aboutsummaryrefslogtreecommitdiffstats
path: root/widgets
diff options
context:
space:
mode:
Diffstat (limited to 'widgets')
-rw-r--r--widgets/Makefile.am4
-rw-r--r--widgets/menus/Makefile.am4
-rw-r--r--widgets/menus/gal-view-collection.c2
-rw-r--r--widgets/menus/gal-view-instance.c143
-rw-r--r--widgets/menus/gal-view-instance.h5
-rw-r--r--widgets/menus/gal-view-menus.c544
-rw-r--r--widgets/menus/gal-view-menus.h63
-rw-r--r--widgets/menus/gal-view-new-dialog.c2
-rw-r--r--widgets/misc/Makefile.am194
-rw-r--r--widgets/misc/e-account-combo-box.c1
-rw-r--r--widgets/misc/e-account-combo-box.h1
-rw-r--r--widgets/misc/e-account-manager.c461
-rw-r--r--widgets/misc/e-account-manager.h82
-rw-r--r--widgets/misc/e-account-tree-view.c632
-rw-r--r--widgets/misc/e-account-tree-view.h84
-rw-r--r--widgets/misc/e-action-combo-box.c582
-rw-r--r--widgets/misc/e-action-combo-box.h85
-rw-r--r--widgets/misc/e-activity-handler.c700
-rw-r--r--widgets/misc/e-activity-handler.h103
-rw-r--r--widgets/misc/e-activity-proxy.c345
-rw-r--r--widgets/misc/e-activity-proxy.h68
-rw-r--r--widgets/misc/e-activity.c764
-rw-r--r--widgets/misc/e-activity.h107
-rw-r--r--widgets/misc/e-alert-activity.c254
-rw-r--r--widgets/misc/e-alert-activity.h70
-rw-r--r--widgets/misc/e-calendar.h21
-rw-r--r--widgets/misc/e-charset-combo-box.c428
-rw-r--r--widgets/misc/e-charset-combo-box.h69
-rw-r--r--widgets/misc/e-charset-picker.c715
-rw-r--r--widgets/misc/e-charset-picker.h50
-rw-r--r--widgets/misc/e-combo-button.c625
-rw-r--r--widgets/misc/e-combo-button.h78
-rw-r--r--widgets/misc/e-config-page.h62
-rw-r--r--widgets/misc/e-dropdown-button.c237
-rw-r--r--widgets/misc/e-dropdown-button.h65
-rw-r--r--widgets/misc/e-file-activity.c365
-rw-r--r--widgets/misc/e-file-activity.h83
-rw-r--r--widgets/misc/e-filter-bar.c1039
-rw-r--r--widgets/misc/e-filter-bar.h140
-rw-r--r--widgets/misc/e-hinted-entry.c298
-rw-r--r--widgets/misc/e-hinted-entry.h73
-rw-r--r--widgets/misc/e-icon-entry.c384
-rw-r--r--widgets/misc/e-icon-entry.h85
-rw-r--r--widgets/misc/e-image-chooser.c587
-rw-r--r--widgets/misc/e-image-chooser.h66
-rw-r--r--widgets/misc/e-info-label.c246
-rw-r--r--widgets/misc/e-info-label.h54
-rw-r--r--widgets/misc/e-menu-tool-button.c157
-rw-r--r--widgets/misc/e-menu-tool-button.h68
-rw-r--r--widgets/misc/e-multi-config-dialog.c374
-rw-r--r--widgets/misc/e-multi-config-dialog.h71
-rw-r--r--widgets/misc/e-online-button.c10
-rw-r--r--widgets/misc/e-popup-action.c285
-rw-r--r--widgets/misc/e-popup-action.h95
-rw-r--r--widgets/misc/e-preferences-window.c393
-rw-r--r--widgets/misc/e-preferences-window.h74
-rw-r--r--widgets/misc/e-search-bar.c1644
-rw-r--r--widgets/misc/e-search-bar.h194
-rw-r--r--widgets/misc/e-signature-combo-box.c1
-rw-r--r--widgets/misc/e-signature-combo-box.h1
-rw-r--r--widgets/misc/e-signature-editor.c503
-rw-r--r--widgets/misc/e-signature-editor.h70
-rw-r--r--widgets/misc/e-signature-manager.c746
-rw-r--r--widgets/misc/e-signature-manager.h100
-rw-r--r--widgets/misc/e-signature-preview.c344
-rw-r--r--widgets/misc/e-signature-preview.h81
-rw-r--r--widgets/misc/e-signature-script-dialog.c463
-rw-r--r--widgets/misc/e-signature-script-dialog.h76
-rw-r--r--widgets/misc/e-signature-tree-view.c445
-rw-r--r--widgets/misc/e-signature-tree-view.h78
-rw-r--r--widgets/misc/e-task-bar.c302
-rw-r--r--widgets/misc/e-task-bar.h76
-rw-r--r--widgets/misc/e-task-widget.c291
-rw-r--r--widgets/misc/e-task-widget.h77
-rw-r--r--widgets/misc/e-timeout-activity.c198
-rw-r--r--widgets/misc/e-timeout-activity.h73
-rw-r--r--widgets/misc/e-unicode.c2052
-rw-r--r--widgets/misc/e-unicode.h112
-rw-r--r--widgets/misc/ea-calendar-cell.c387
-rw-r--r--widgets/misc/ea-calendar-cell.h86
-rw-r--r--widgets/misc/ea-calendar-item.c1314
-rw-r--r--widgets/misc/ea-calendar-item.h68
-rw-r--r--widgets/misc/ea-widgets.c (renamed from widgets/misc/e-config-page.c)31
-rw-r--r--widgets/misc/ea-widgets.h (renamed from widgets/table/table-test.h)15
-rw-r--r--widgets/misc/test-calendar.c2
-rw-r--r--widgets/misc/test-dropdown-button.c99
-rw-r--r--widgets/misc/test-error.c61
-rw-r--r--widgets/misc/test-info-label.c75
-rw-r--r--widgets/misc/test-preferences-window.c (renamed from widgets/misc/test-multi-config-dialog.c)49
-rw-r--r--widgets/table/Makefile.am58
-rw-r--r--widgets/table/e-cell-combo.c2
-rw-r--r--widgets/table/e-cell-date-edit.c (renamed from widgets/misc/e-cell-date-edit.c)6
-rw-r--r--widgets/table/e-cell-date-edit.h (renamed from widgets/misc/e-cell-date-edit.h)0
-rw-r--r--widgets/table/e-cell-date.c2
-rw-r--r--widgets/table/e-cell-hbox.c4
-rw-r--r--widgets/table/e-cell-percent.c (renamed from widgets/misc/e-cell-percent.c)0
-rw-r--r--widgets/table/e-cell-percent.h (renamed from widgets/misc/e-cell-percent.h)0
-rw-r--r--widgets/table/e-cell-popup.c4
-rw-r--r--widgets/table/e-cell-text.c6
-rw-r--r--widgets/table/e-cell-toggle.c4
-rw-r--r--widgets/table/e-cell-tree.c4
-rw-r--r--widgets/table/e-cell-vbox.c4
-rw-r--r--widgets/table/e-table-click-to-add.c2
-rw-r--r--widgets/table/e-table-config.c2
-rw-r--r--widgets/table/e-table-example-1.c305
-rw-r--r--widgets/table/e-table-group-container.c2
-rw-r--r--widgets/table/e-table-header-item.c5
-rw-r--r--widgets/table/e-table-header-utils.c2
-rw-r--r--widgets/table/e-table-item.c4
-rw-r--r--widgets/table/e-table-tree.h48
-rw-r--r--widgets/table/e-table-utils.c2
-rw-r--r--widgets/table/e-table.c4
-rw-r--r--widgets/table/e-tree.c2
-rw-r--r--widgets/table/gal-a11y-e-cell-popup.c144
-rw-r--r--widgets/table/gal-a11y-e-cell-popup.h62
-rw-r--r--widgets/table/gal-a11y-e-cell-registry.c149
-rw-r--r--widgets/table/gal-a11y-e-cell-registry.h72
-rw-r--r--widgets/table/gal-a11y-e-cell-text.c737
-rw-r--r--widgets/table/gal-a11y-e-cell-text.h64
-rw-r--r--widgets/table/gal-a11y-e-cell-toggle.c191
-rw-r--r--widgets/table/gal-a11y-e-cell-toggle.h64
-rw-r--r--widgets/table/gal-a11y-e-cell-tree.c260
-rw-r--r--widgets/table/gal-a11y-e-cell-tree.h64
-rw-r--r--widgets/table/gal-a11y-e-cell-vbox.c225
-rw-r--r--widgets/table/gal-a11y-e-cell-vbox.h63
-rw-r--r--widgets/table/gal-a11y-e-cell.c644
-rw-r--r--widgets/table/gal-a11y-e-cell.h113
-rw-r--r--widgets/table/gal-a11y-e-table-click-to-add-factory.c106
-rw-r--r--widgets/table/gal-a11y-e-table-click-to-add-factory.h50
-rw-r--r--widgets/table/gal-a11y-e-table-click-to-add.c344
-rw-r--r--widgets/table/gal-a11y-e-table-click-to-add.h55
-rw-r--r--widgets/table/gal-a11y-e-table-column-header.c229
-rw-r--r--widgets/table/gal-a11y-e-table-column-header.h55
-rw-r--r--widgets/table/gal-a11y-e-table-factory.c99
-rw-r--r--widgets/table/gal-a11y-e-table-factory.h51
-rw-r--r--widgets/table/gal-a11y-e-table-item-factory.c105
-rw-r--r--widgets/table/gal-a11y-e-table-item-factory.h50
-rw-r--r--widgets/table/gal-a11y-e-table-item.c1327
-rw-r--r--widgets/table/gal-a11y-e-table-item.h59
-rw-r--r--widgets/table/gal-a11y-e-table.c308
-rw-r--r--widgets/table/gal-a11y-e-table.h59
-rw-r--r--widgets/table/gal-a11y-e-tree-factory.c98
-rw-r--r--widgets/table/gal-a11y-e-tree-factory.h50
-rw-r--r--widgets/table/gal-a11y-e-tree.c191
-rw-r--r--widgets/table/gal-a11y-e-tree.h58
-rw-r--r--widgets/text/Makefile.am17
-rw-r--r--widgets/text/e-reflow-model.c (renamed from widgets/misc/e-reflow-model.c)0
-rw-r--r--widgets/text/e-reflow-model.h (renamed from widgets/misc/e-reflow-model.h)0
-rw-r--r--widgets/text/e-reflow.c (renamed from widgets/misc/e-reflow.c)8
-rw-r--r--widgets/text/e-reflow.h (renamed from widgets/misc/e-reflow.h)2
-rw-r--r--widgets/text/e-text.c4
-rw-r--r--widgets/text/gal-a11y-e-text-factory.c101
-rw-r--r--widgets/text/gal-a11y-e-text-factory.h50
-rw-r--r--widgets/text/gal-a11y-e-text.c1134
-rw-r--r--widgets/text/gal-a11y-e-text.h57
155 files changed, 19010 insertions, 11692 deletions
diff --git a/widgets/Makefile.am b/widgets/Makefile.am
index 347c0f7c66..99305b844e 100644
--- a/widgets/Makefile.am
+++ b/widgets/Makefile.am
@@ -1,9 +1,9 @@
SUBDIRS = \
- table \
- text \
misc \
+ text \
e-timezone-dialog \
+ table \
menus
EXTRA_DIST = \
diff --git a/widgets/menus/Makefile.am b/widgets/menus/Makefile.am
index f67a07370c..f07ae41d14 100644
--- a/widgets/menus/Makefile.am
+++ b/widgets/menus/Makefile.am
@@ -8,7 +8,6 @@ AM_CPPFLAGS = \
$(E_UTIL_CFLAGS)
libmenus_la_SOURCES = \
- gal-view-menus.c \
gal-define-views-dialog.c \
gal-define-views-model.c \
gal-view-collection.c \
@@ -18,8 +17,7 @@ libmenus_la_SOURCES = \
gal-view-instance-save-as-dialog.c \
gal-view-instance.c \
gal-view-new-dialog.c \
- gal-view.c \
- gal-view-menus.h
+ gal-view.c
glade_DATA = \
gal-define-views.glade \
diff --git a/widgets/menus/gal-view-collection.c b/widgets/menus/gal-view-collection.c
index 958759326a..a854d4bffa 100644
--- a/widgets/menus/gal-view-collection.c
+++ b/widgets/menus/gal-view-collection.c
@@ -33,7 +33,7 @@
#include <glib/gi18n.h>
#include "e-util/e-util.h"
#include "e-util/e-xml-utils.h"
-#include "misc/e-unicode.h"
+#include "e-util/e-unicode.h"
#include "gal-view-collection.h"
diff --git a/widgets/menus/gal-view-instance.c b/widgets/menus/gal-view-instance.c
index 6ed7f9a604..bd93b64034 100644
--- a/widgets/menus/gal-view-instance.c
+++ b/widgets/menus/gal-view-instance.c
@@ -38,7 +38,7 @@
#include <glib/gi18n.h>
#include "e-util/e-util.h"
#include "e-util/e-xml-utils.h"
-#include "misc/e-unicode.h"
+#include "e-util/e-unicode.h"
#include "gal-define-views-dialog.h"
#include "gal-view-instance.h"
@@ -46,10 +46,6 @@
G_DEFINE_TYPE (GalViewInstance, gal_view_instance, G_TYPE_OBJECT)
-static const EPopupMenu separator = E_POPUP_SEPARATOR;
-static const EPopupMenu terminator = E_POPUP_TERMINATOR;
-
-
#define d(x)
enum {
@@ -467,140 +463,3 @@ gal_view_instance_exists (GalViewInstance *instance)
return FALSE;
}
-
-typedef struct {
- GalViewInstance *instance;
- gchar *id;
-} ListenerClosure;
-
-static void
-view_item_cb (GtkWidget *widget,
- gpointer user_data)
-{
- ListenerClosure *closure = user_data;
-
- if (GTK_CHECK_MENU_ITEM (widget)->active) {
- gal_view_instance_set_current_view_id (closure->instance, closure->id);
- }
-}
-
-static void
-add_popup_radio_item (EPopupMenu *menu_item,
- const gchar *title,
- GCallback fn,
- gpointer closure,
- gboolean value)
-{
- EPopupMenu menu_item_struct =
- E_POPUP_RADIO_ITEM_CC (title,
- fn,
- closure,
- 0,
- 0);
- menu_item_struct.is_active = value;
-
- e_popup_menu_copy_1 (menu_item, &menu_item_struct);
-}
-
-static void
-add_popup_menu_item (EPopupMenu *menu_item,
- const gchar *title,
- GCallback fn,
- gpointer closure)
-{
- EPopupMenu menu_item_struct =
- E_POPUP_ITEM_CC (title,
- fn,
- closure,
- 0);
-
- e_popup_menu_copy_1 (menu_item, &menu_item_struct);
-}
-
-static void
-define_views_dialog_response(GtkWidget *dialog, gint id, GalViewInstance *instance)
-{
- if (id == GTK_RESPONSE_OK) {
- gal_view_collection_save(instance->collection);
- }
- gtk_widget_destroy (dialog);
-}
-
-static void
-define_views_cb(GtkWidget *widget,
- GalViewInstance *instance)
-{
- GtkWidget *dialog = gal_define_views_dialog_new(instance->collection);
- g_signal_connect(dialog, "response",
- G_CALLBACK(define_views_dialog_response), instance);
- gtk_widget_show(dialog);
-}
-
-static void
-save_current_view_cb(GtkWidget *widget,
- GalViewInstance *instance)
-{
- gal_view_instance_save_as (instance);
-}
-
-EPopupMenu *
-gal_view_instance_get_popup_menu (GalViewInstance *instance)
-{
- EPopupMenu *ret_val;
- gint length;
- gint i;
- gboolean found = FALSE;
- gchar *id;
-
- length = gal_view_collection_get_count(instance->collection);
- id = gal_view_instance_get_current_view_id (instance);
-
- ret_val = g_new (EPopupMenu, length + 6);
-
- for (i = 0; i < length; i++) {
- gboolean value = FALSE;
- GalViewCollectionItem *item = gal_view_collection_get_view_item(instance->collection, i);
- ListenerClosure *closure;
-
- closure = g_new (ListenerClosure, 1);
- closure->instance = instance;
- closure->id = item->id;
- g_object_ref (closure->instance);
-
- if (!found && id && !strcmp (id, item->id)) {
- found = TRUE;
- value = TRUE;
- }
-
- add_popup_radio_item (ret_val + i, item->title, G_CALLBACK (view_item_cb), closure, value);
- }
-
- if (!found) {
- e_popup_menu_copy_1 (ret_val + i++, &separator);
-
- add_popup_radio_item (ret_val + i++, N_("Custom View"), NULL, NULL, TRUE);
- add_popup_menu_item (ret_val + i++, N_("Save Custom View"), G_CALLBACK (save_current_view_cb), instance);
- }
-
- e_popup_menu_copy_1 (ret_val + i++, &separator);
- add_popup_menu_item (ret_val + i++, N_("Define Views..."), G_CALLBACK (define_views_cb), instance);
- e_popup_menu_copy_1 (ret_val + i++, &terminator);
-
- if (id)
- g_free (id);
-
- return ret_val;
-}
-
-void
-gal_view_instance_free_popup_menu (GalViewInstance *instance, EPopupMenu *menu)
-{
- gint i;
- /* This depends on the first non-custom closure to be a separator or a terminator. */
- for (i = 0; menu[i].name && *(menu[i].name); i++) {
- g_object_unref (((ListenerClosure *)(menu[i].closure))->instance);
- g_free (menu[i].closure);
- }
-
- e_popup_menu_free (menu);
-}
diff --git a/widgets/menus/gal-view-instance.h b/widgets/menus/gal-view-instance.h
index a7ce2778c9..960bf940c6 100644
--- a/widgets/menus/gal-view-instance.h
+++ b/widgets/menus/gal-view-instance.h
@@ -26,7 +26,6 @@
#include <glib-object.h>
#include <widgets/menus/gal-view-collection.h>
-#include <misc/e-popup-menu.h>
G_BEGIN_DECLS
@@ -107,10 +106,6 @@ const gchar *gal_view_instance_get_default_view (GalViewInstance *ins
void gal_view_instance_set_default_view (GalViewInstance *instance,
const gchar *id);
-EPopupMenu *gal_view_instance_get_popup_menu (GalViewInstance *instance);
-void gal_view_instance_free_popup_menu (GalViewInstance *instance,
- EPopupMenu *menu);
-
G_END_DECLS
#endif /* _GAL_VIEW_INSTANCE_H_ */
diff --git a/widgets/menus/gal-view-menus.c b/widgets/menus/gal-view-menus.c
deleted file mode 100644
index c1b75aee4b..0000000000
--- a/widgets/menus/gal-view-menus.c
+++ /dev/null
@@ -1,544 +0,0 @@
-/*
- * gal-view-menus.c: Deploy a GalViewCollection in the menus.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) version 3.
- *
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- *
- * Authors:
- * Chris Lahey <clahey@ximian.com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "gal-view-menus.h"
-
-#include <stdlib.h>
-#include <string.h>
-#include <gtk/gtk.h>
-#include <libxml/parser.h>
-#include <libxml/xmlmemory.h>
-#include <glib/gi18n.h>
-#include <bonobo/bonobo-ui-util.h>
-#include <e-util/e-util.h>
-#include <e-util/e-xml-utils.h>
-#include <widgets/menus/gal-define-views-dialog.h>
-#include <bonobo/bonobo-ui-util.h>
-#include <libedataserver/e-list.h>
-
-struct _GalViewMenusPrivate {
- GalViewInstance *instance;
- gint collection_changed_id;
- gint instance_changed_id;
- BonoboUIComponent *component;
- EList *listenerClosures;
- GtkWidget *define_views_dialog;
-
- guint show_define_views : 1;
-};
-
-typedef struct {
- GalViewInstance *instance;
- gchar *id;
- gint ref_count;
-} ListenerClosure;
-
-static void collection_changed (GalViewCollection *collection,
- GalViewMenus *gvm);
-static void instance_changed (GalViewInstance *instance,
- GalViewMenus *gvm);
-
-#define d(x)
-#define CURRENT_VIEW_PATH "/menu/View/ViewBegin/CurrentView"
-
-G_DEFINE_TYPE(GalViewMenus, gal_view_menus, G_TYPE_OBJECT)
-
-static void
-closure_free (gpointer data, gpointer user_data)
-{
- ListenerClosure *closure = data;
- GalViewMenus *gvm = user_data;
-
- closure->ref_count --;
- if (closure->ref_count == 0) {
- g_object_unref (closure->instance);
-
- bonobo_ui_component_remove_listener (gvm->priv->component, closure->id);
- g_free (closure);
- }
-}
-
-static gpointer
-closure_copy (gconstpointer data, gpointer user_data)
-{
- ListenerClosure *closure = (gpointer) data;
-
- closure->ref_count ++;
- return closure;
-}
-
-static void
-remove_listeners (GalViewMenus *gvm)
-{
- if (gvm->priv->listenerClosures)
- g_object_unref (gvm->priv->listenerClosures);
-
- gvm->priv->listenerClosures = NULL;
-}
-
-static void
-remove_xml (GalViewMenus *gvm)
-{
-}
-
-static void
-remove_instance (GalViewMenus *gvm)
-{
- if (gvm->priv->instance) {
- if (gvm->priv->instance_changed_id != 0)
- g_signal_handler_disconnect (gvm->priv->instance, gvm->priv->instance_changed_id);
-
- if (gvm->priv->instance->collection && gvm->priv->collection_changed_id != 0)
- g_signal_handler_disconnect (gvm->priv->instance->collection, gvm->priv->collection_changed_id);
- }
-
- gvm->priv->instance_changed_id = 0;
- gvm->priv->collection_changed_id = 0;
-
- if (gvm->priv->instance) {
- g_object_unref (gvm->priv->instance);
- gvm->priv->instance = NULL;
- }
-
- remove_listeners(gvm);
- remove_xml(gvm);
-}
-
-static void
-add_instance (GalViewMenus *gvm,
- GalViewInstance *instance)
-{
- g_object_ref (instance);
-
- if (gvm->priv->instance != NULL)
- remove_instance (gvm);
-
- gvm->priv->instance = instance;
-
- gal_view_instance_load (gvm->priv->instance);
-
- gvm->priv->instance_changed_id = g_signal_connect (instance, "changed",
- G_CALLBACK (instance_changed), gvm);
- gvm->priv->collection_changed_id = g_signal_connect (instance->collection, "changed",
- G_CALLBACK (collection_changed), gvm);
-}
-
-static void
-clear_define_views_dialog (gpointer data,
- GObject *where_the_object_was)
-{
- GalViewMenus *gvm = GAL_VIEW_MENUS (data);
- gvm->priv->define_views_dialog = NULL;
-}
-
-static void
-gal_view_menus_finalize (GObject *object)
-{
- GalViewMenus *gvm = GAL_VIEW_MENUS (object);
-
- remove_instance (gvm);
-
- gal_view_menus_unmerge (gvm, NULL);
-
- if (gvm->priv->component)
- bonobo_object_unref (gvm->priv->component);
-
- if (gvm->priv->define_views_dialog)
- g_object_weak_unref (G_OBJECT (gvm->priv->define_views_dialog), clear_define_views_dialog, gvm);
-
- g_free(gvm->priv);
-
- (* G_OBJECT_CLASS (gal_view_menus_parent_class)->finalize) (object);
-}
-
-static void
-gal_view_menus_class_init (GalViewMenusClass *gvm_class)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (gvm_class);
-
- object_class->finalize = gal_view_menus_finalize;
-}
-
-static void
-gal_view_menus_init (GalViewMenus *gvm)
-{
- gvm->priv = g_new(GalViewMenusPrivate, 1);
- gvm->priv->instance = NULL;
- gvm->priv->collection_changed_id = 0;
- gvm->priv->instance_changed_id = 0;
- gvm->priv->component = NULL;
- gvm->priv->listenerClosures = NULL;
- gvm->priv->define_views_dialog = NULL;
- gvm->priv->show_define_views = TRUE;
-}
-
-GalViewMenus *
-gal_view_menus_new (GalViewInstance *instance)
-{
- GalViewMenus *gvm;
-
- g_return_val_if_fail (instance != NULL, NULL);
- g_return_val_if_fail (GAL_IS_VIEW_INSTANCE (instance), NULL);
-
- gvm = g_object_new (GAL_VIEW_MENUS_TYPE, NULL);
- gal_view_menus_construct(gvm, instance);
-
- return gvm;
-}
-
-GalViewMenus *
-gal_view_menus_construct (GalViewMenus *gvm,
- GalViewInstance *instance)
-{
- g_return_val_if_fail (gvm != NULL, NULL);
- g_return_val_if_fail (GAL_IS_VIEW_MENUS (gvm), NULL);
- g_return_val_if_fail (instance != NULL, NULL);
- g_return_val_if_fail (GAL_IS_VIEW_INSTANCE (instance), NULL);
-
- add_instance (gvm, instance);
-
- return gvm;
-}
-
-static void
-dialog_response(GtkWidget *dialog, gint id, GalViewMenus *menus)
-{
- if (id == GTK_RESPONSE_OK) {
- gal_view_collection_save(menus->priv->instance->collection);
- }
- gtk_widget_destroy(dialog);
-}
-
-static void
-define_views(BonoboUIComponent *component,
- GalViewMenus *menus,
- gchar *cname)
-{
- if (menus->priv->define_views_dialog) {
- gdk_window_raise (menus->priv->define_views_dialog->window);
- } else {
- GtkWidget *dialog = gal_define_views_dialog_new(menus->priv->instance->collection);
-
- g_signal_connect (dialog, "response", G_CALLBACK (dialog_response), menus);
- menus->priv->define_views_dialog = dialog;
- g_object_weak_ref (G_OBJECT (dialog), clear_define_views_dialog, menus);
- gtk_widget_show(dialog);
- }
-}
-
-static void
-save_current_view(BonoboUIComponent *component,
- GalViewMenus *menus,
- gchar *cname)
-{
- gal_view_instance_save_as (menus->priv->instance);
-}
-
-static void
-toggled_cb (BonoboUIComponent *component,
- const gchar *path,
- Bonobo_UIComponent_EventType type,
- const gchar *state,
- gpointer user_data)
-{
- ListenerClosure *closure = user_data;
-
- /* do nothing on state change to untoggled */
- if (!strcmp (state, "0"))
- return;
-
- g_print ("%s\n", path);
-
- gal_view_instance_set_current_view_id (closure->instance, closure->id);
-}
-
-static gchar *
-build_menus(GalViewMenus *menus)
-{
- BonoboUINode *root, *menu, *submenu, *place, *menuitem, *commands, *command;
- gchar *xml;
- gint length;
- gint i;
- GalViewInstance *instance = menus->priv->instance;
- GalViewCollection *collection = instance->collection;
- gchar *id;
- gboolean found = FALSE;
-
- root = bonobo_ui_node_new("Root");
- menu = bonobo_ui_node_new_child(root, "menu");
- commands = bonobo_ui_node_new_child (root, "commands");
-
- submenu = bonobo_ui_node_new_child(menu, "submenu");
- bonobo_ui_node_set_attr(submenu, "name", "View");
-
- place = bonobo_ui_node_new_child(submenu, "placeholder");
- bonobo_ui_node_set_attr(place, "name", "ViewBegin");
-
- submenu = bonobo_ui_node_new_child(place, "submenu");
- bonobo_ui_node_set_attr(submenu, "name", "CurrentView");
- bonobo_ui_node_set_attr(submenu, "_label", N_("C_urrent View"));
-
- id = gal_view_instance_get_current_view_id (instance);
-
-
- length = gal_view_collection_get_count(collection);
-
- menus->priv->listenerClosures = e_list_new (closure_copy, closure_free, menus);
-
- for (i = 0; i < length; i++) {
- GalViewCollectionItem *item = gal_view_collection_get_view_item(collection, i);
- ListenerClosure *closure;
- gchar *label;
- gchar *tip;
-
- menuitem = bonobo_ui_node_new_child(submenu, "menuitem");
- bonobo_ui_node_set_attr(menuitem, "name", item->id);
- bonobo_ui_node_set_attr(menuitem, "id", item->id);
- bonobo_ui_node_set_attr(menuitem, "group", "GalViewMenus");
- bonobo_ui_node_set_attr(menuitem, "type", "radio");
-
- command = bonobo_ui_node_new_child (commands, "cmd");
- bonobo_ui_node_set_attr(command, "name", item->id);
- bonobo_ui_node_set_attr(command, "group", "GalViewMenus");
- tip = g_strdup_printf (_("Select View: %s"), item->id);
- bonobo_ui_node_set_attr(command, "_tip", tip);
- g_free (tip);
-
- label = bonobo_ui_util_encode_str (item->title);
- bonobo_ui_node_set_attr(menuitem, "label", label);
- g_free (label);
-
- closure = g_new (ListenerClosure, 1);
- closure->instance = instance;
- closure->id = item->id;
- closure->ref_count = 1;
-
- if (!found && id && !strcmp (item->id, id)) {
- found = TRUE;
- }
-
- g_object_ref (closure->instance);
-
- bonobo_ui_component_add_listener (menus->priv->component, item->id, toggled_cb, closure);
- e_list_append (menus->priv->listenerClosures, closure);
-
- closure_free (closure, menus);
- }
-
- if (menus->priv->show_define_views) {
- if (!found) {
-
- menuitem = bonobo_ui_node_new_child(submenu, "separator");
- bonobo_ui_node_set_attr(menuitem, "name", "GalView:first_sep");
- bonobo_ui_node_set_attr(menuitem, "f", "");
-
-
- menuitem = bonobo_ui_node_new_child(submenu, "menuitem");
- bonobo_ui_node_set_attr(menuitem, "name", "custom_view");
- bonobo_ui_node_set_attr(menuitem, "id", "custom_view");
- bonobo_ui_node_set_attr(menuitem, "group", "GalViewMenus");
- bonobo_ui_node_set_attr(menuitem, "type", "radio");
- /* bonobo displays this string so it must be in locale */
- bonobo_ui_node_set_attr(menuitem, "_label", N_("Custom View"));
-
- command = bonobo_ui_node_new_child (commands, "cmd");
- bonobo_ui_node_set_attr(command, "name", "custom_view");
- bonobo_ui_node_set_attr(command, "group", "GalViewMenus");
- bonobo_ui_node_set_attr(command, "_tip", N_("Current view is a customized view"));
-
-
- menuitem = bonobo_ui_node_new_child(submenu, "menuitem");
- bonobo_ui_node_set_attr(menuitem, "name", "SaveCurrentView");
- bonobo_ui_node_set_attr(menuitem, "_label", N_("Save Custom View..."));
- bonobo_ui_node_set_attr(menuitem, "verb", "");
-
- command = bonobo_ui_node_new_child(commands, "cmd");
- bonobo_ui_node_set_attr(command, "name", "SaveCurrentView");
- bonobo_ui_node_set_attr(command, "_tip", N_("Save current custom view"));
- }
-
- menuitem = bonobo_ui_node_new_child(submenu, "separator");
- bonobo_ui_node_set_attr(menuitem, "name", "GalView:second_sep");
- bonobo_ui_node_set_attr(menuitem, "f", "");
-
- menuitem = bonobo_ui_node_new_child(submenu, "menuitem");
- bonobo_ui_node_set_attr(menuitem, "name", "DefineViews");
- bonobo_ui_node_set_attr(menuitem, "_label", N_("Define Views..."));
- bonobo_ui_node_set_attr(menuitem, "verb", "");
-
- command = bonobo_ui_node_new_child(commands, "cmd");
- bonobo_ui_node_set_attr(command, "name", "DefineViews");
- bonobo_ui_node_set_attr(command, "_tip", N_("Create or edit views"));
- }
-
- xml = bonobo_ui_node_to_string(root, TRUE);
-
- bonobo_ui_node_free(root);
-
- g_free (id);
-
- /* d(g_print (xml));*/
-
- return xml;
-}
-
-static BonoboUIVerb verbs [] = {
- BONOBO_UI_UNSAFE_VERB ("DefineViews", define_views),
- BONOBO_UI_UNSAFE_VERB ("SaveCurrentView", save_current_view),
- BONOBO_UI_VERB_END
-};
-
-static void
-set_state (GalViewMenus *gvm, const gchar *path, CORBA_Environment *ev)
-{
- gchar *full_path = g_strdup_printf ("/commands/%s", path);
-
- bonobo_ui_component_set_prop (gvm->priv->component, full_path, "state", "1", ev);
- g_free (full_path);
-}
-
-static void
-set_radio (GalViewMenus *gvm,
- CORBA_Environment *ev)
-{
- gchar *id;
-
- id = gal_view_instance_get_current_view_id (gvm->priv->instance);
-
- if (id) {
- set_state (gvm, id, ev);
- } else {
- set_state (gvm, "custom_view", ev);
- }
- g_free (id);
-}
-
-static void
-build_stuff (GalViewMenus *gvm,
- CORBA_Environment *ev)
-{
- gchar *xml;
-
- g_object_ref (gvm);
-
- gal_view_menus_unmerge (gvm, ev);
-
- remove_listeners(gvm);
- remove_xml(gvm);
- xml = build_menus(gvm);
- bonobo_ui_component_set_translate(gvm->priv->component, "/", xml, ev);
- g_free(xml);
-
- bonobo_ui_component_add_verb_list_with_data(gvm->priv->component, verbs, gvm);
-
- set_radio (gvm, ev);
-
- g_object_unref (gvm);
-}
-
-void
-gal_view_menus_set_show_define_views (GalViewMenus *gvm,
- gboolean show_define_views)
-{
- if (gvm->priv->show_define_views == show_define_views)
- return;
-
- gvm->priv->show_define_views = show_define_views;
-
- if (gvm->priv->component) {
- CORBA_Environment ev;
-
- CORBA_exception_init (&ev);
- build_stuff(gvm, &ev);
- CORBA_exception_free (&ev);
- }
-}
-
-void
-gal_view_menus_apply (GalViewMenus *gvm,
- BonoboUIComponent *component,
- CORBA_Environment *opt_ev)
-{
- if (gvm->priv == NULL)
- return;
-
- if (component != gvm->priv->component) {
- if (component)
- bonobo_object_ref (BONOBO_OBJECT (component));
-
- if (gvm->priv->component)
- bonobo_object_unref (BONOBO_OBJECT (gvm->priv->component));
- }
-
- gvm->priv->component = component;
-
- build_stuff (gvm, opt_ev);
-}
-
-void
-gal_view_menus_unmerge (GalViewMenus *gvm,
- CORBA_Environment *opt_ev)
-{
- d(g_print ("%s:\n", G_STRFUNC));
- if (bonobo_ui_component_get_container (gvm->priv->component) != NULL
- && bonobo_ui_component_path_exists (gvm->priv->component, CURRENT_VIEW_PATH, opt_ev)) {
- d(g_print ("%s: Removing path\n", G_STRFUNC));
- bonobo_ui_component_rm (gvm->priv->component, CURRENT_VIEW_PATH, opt_ev);
- }
-}
-
-static void
-collection_changed (GalViewCollection *collection,
- GalViewMenus *gvm)
-{
- CORBA_Environment ev;
-
- CORBA_exception_init (&ev);
- build_stuff(gvm, &ev);
- CORBA_exception_free (&ev);
-}
-
-static void
-instance_changed (GalViewInstance *instance,
- GalViewMenus *gvm)
-{
- CORBA_Environment ev;
-
- CORBA_exception_init (&ev);
- build_stuff(gvm, &ev);
- CORBA_exception_free (&ev);
-}
-
-void
-gal_view_menus_set_instance (GalViewMenus *gvm,
- GalViewInstance *instance)
-{
- remove_instance (gvm);
- add_instance (gvm, instance);
- instance_changed (instance, gvm);
-}
diff --git a/widgets/menus/gal-view-menus.h b/widgets/menus/gal-view-menus.h
deleted file mode 100644
index f565d07613..0000000000
--- a/widgets/menus/gal-view-menus.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) version 3.
- *
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-#ifndef _GAL_VIEW_MENUS_H_
-#define _GAL_VIEW_MENUS_H_
-
-#include <libxml/tree.h>
-#include <bonobo/bonobo-ui-component.h>
-#include <widgets/menus/gal-view-instance.h>
-
-#include <glib-object.h>
-
-#define GAL_VIEW_MENUS_TYPE (gal_view_menus_get_type ())
-#define GAL_VIEW_MENUS(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GAL_VIEW_MENUS_TYPE, GalViewMenus))
-#define GAL_VIEW_MENUS_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GAL_VIEW_MENUS_TYPE, GalViewMenusClass))
-#define GAL_IS_VIEW_MENUS(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GAL_VIEW_MENUS_TYPE))
-#define GAL_IS_VIEW_MENUS_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GAL_VIEW_MENUS_TYPE))
-
-typedef struct _GalViewMenusPrivate GalViewMenusPrivate;
-
-typedef struct {
- GObject base;
- GalViewMenusPrivate *priv;
-} GalViewMenus;
-
-typedef struct {
- GObjectClass parent_class;
-} GalViewMenusClass;
-
-GType gal_view_menus_get_type (void);
-GalViewMenus *gal_view_menus_new (GalViewInstance *instance);
-GalViewMenus *gal_view_menus_construct (GalViewMenus *menus,
- GalViewInstance *instance);
-
-void gal_view_menus_set_show_define_views (GalViewMenus *menus,
- gboolean show_define_views);
-
-void gal_view_menus_apply (GalViewMenus *menus,
- BonoboUIComponent *component,
- CORBA_Environment *opt_ev);
-void gal_view_menus_unmerge (GalViewMenus *gvm,
- CORBA_Environment *opt_ev);
-void gal_view_menus_set_instance (GalViewMenus *gvm,
- GalViewInstance *instance);
-
-#endif /* _GAL_VIEW_MENUS_H_ */
diff --git a/widgets/menus/gal-view-new-dialog.c b/widgets/menus/gal-view-new-dialog.c
index ab819a484c..e3a24726c5 100644
--- a/widgets/menus/gal-view-new-dialog.c
+++ b/widgets/menus/gal-view-new-dialog.c
@@ -27,7 +27,7 @@
#include <glib/gi18n.h>
#include "e-util/e-util.h"
#include "e-util/e-util-private.h"
-#include "misc/e-unicode.h"
+#include "e-util/e-unicode.h"
#include "gal-define-views-model.h"
#include "gal-view-new-dialog.h"
diff --git a/widgets/misc/Makefile.am b/widgets/misc/Makefile.am
index 303efa878b..d893247818 100644
--- a/widgets/misc/Makefile.am
+++ b/widgets/misc/Makefile.am
@@ -4,7 +4,7 @@ endif
AM_CPPFLAGS = \
-I$(top_srcdir) \
- -I$(top_srcdir)/a11y/widgets \
+ -I$(top_srcdir)/filter \
-I$(top_srcdir)/widgets \
-DEVOLUTION_IMAGES=\""$(imagesdir)"\" \
-DEVOLUTION_GLADEDIR=\""$(gladedir)"\" \
@@ -15,8 +15,7 @@ AM_CPPFLAGS = \
privsolib_LTLIBRARIES = \
- libemiscwidgets.la \
- libefilterbar.la
+ libemiscwidgets.la
widgetsincludedir = $(privincludedir)/misc
filterbarincludedir = $(privincludedir)/misc
@@ -34,7 +33,12 @@ glade_DATA = e-send-options.glade
widgetsinclude_HEADERS = \
$(pilot_headers) \
e-account-combo-box.h \
- e-activity-handler.h \
+ e-account-manager.h \
+ e-account-tree-view.h \
+ e-action-combo-box.h \
+ e-activity.h \
+ e-activity-proxy.h \
+ e-alert-activity.h \
e-attachment.h \
e-attachment-button.h \
e-attachment-dialog.h \
@@ -46,54 +50,58 @@ widgetsinclude_HEADERS = \
e-attachment-store.h \
e-attachment-tree-view.h \
e-attachment-view.h \
- e-spinner.c \
- e-spinner.h \
e-calendar.h \
e-calendar-item.h \
- e-cell-date-edit.h \
- e-cell-percent.h \
- e-cell-renderer-combo.h \
- e-charset-picker.h \
- e-combo-cell-editable.h \
- e-config-page.h \
- e-combo-button.h \
- e-dateedit.h \
- e-dropdown-button.h \
- e-icon-entry.h \
- e-image-chooser.h \
- e-info-label.h \
- e-map.h \
- e-multi-config-dialog.h \
- e-online-button.h \
- e-search-bar.h \
- e-task-bar.h \
- e-task-widget.h \
- e-send-options.h \
- e-url-entry.h \
+ e-canvas.h \
e-canvas-background.h \
e-canvas-utils.h \
e-canvas-vbox.h \
- e-canvas.h \
+ e-cell-renderer-combo.h \
+ e-charset-combo-box.h \
+ e-colors.h \
+ e-combo-cell-editable.h \
e-cursors.h \
+ e-dateedit.h \
+ e-file-activity.h \
e-gui-utils.h \
+ e-hinted-entry.h \
e-hsv-utils.h \
+ e-image-chooser.h \
+ e-map.h \
+ e-menu-tool-button.h \
+ e-online-button.h \
+ e-popup-action.h \
e-popup-menu.h \
+ e-preferences-window.h \
e-printable.h \
- e-reflow-model.h \
- e-reflow.h \
+ e-selection-model.h \
e-selection-model-array.h \
e-selection-model-simple.h \
- e-selection-model.h \
+ e-send-options.h \
e-signature-combo-box.h \
- e-unicode.h \
- e-colors.h
+ e-signature-editor.h \
+ e-signature-manager.h \
+ e-signature-preview.h \
+ e-signature-script-dialog.h \
+ e-signature-tree-view.h \
+ e-spinner.c \
+ e-spinner.h \
+ e-timeout-activity.h \
+ e-url-entry.h \
+ ea-calendar-cell.h \
+ ea-calendar-item.h \
+ ea-widgets.h
libemiscwidgets_la_SOURCES = \
$(widgetsinclude_HEADERS) \
$(pilot_sources) \
e-account-combo-box.c \
- e-activity-handler.c \
- e-calendar.c \
+ e-account-manager.c \
+ e-account-tree-view.c \
+ e-action-combo-box.c \
+ e-activity.c \
+ e-activity-proxy.c \
+ e-alert-activity.c \
e-attachment.c \
e-attachment-button.c \
e-attachment-dialog.c \
@@ -105,78 +113,61 @@ libemiscwidgets_la_SOURCES = \
e-attachment-store.c \
e-attachment-tree-view.c \
e-attachment-view.c \
+ e-calendar.c \
e-calendar-item.c \
- e-cell-date-edit.c \
- e-cell-percent.c \
- e-cell-renderer-combo.c \
- e-charset-picker.c \
- e-combo-cell-editable.c \
- e-config-page.c \
- e-combo-button.c \
- e-dateedit.c \
- e-dropdown-button.c \
- e-icon-entry.c \
- e-image-chooser.c \
- e-info-label.c \
- e-map.c \
- e-multi-config-dialog.c \
- e-online-button.c \
- e-search-bar.c \
- e-task-bar.c \
- e-task-widget.c \
- e-send-options.c \
- e-url-entry.c \
+ e-canvas.c \
e-canvas-background.c \
e-canvas-utils.c \
e-canvas-vbox.c \
- e-canvas.c \
+ e-cell-renderer-combo.c \
+ e-charset-combo-box.c \
+ e-colors.c \
+ e-combo-cell-editable.c \
e-cursors.c \
+ e-dateedit.c \
+ e-file-activity.c \
e-gui-utils.c \
+ e-hinted-entry.c \
e-hsv-utils.c \
+ e-image-chooser.c \
+ e-map.c \
+ e-menu-tool-button.c \
+ e-online-button.c \
+ e-popup-action.c \
e-popup-menu.c \
+ e-preferences-window.c \
e-printable.c \
- e-reflow-model.c \
- e-reflow.c \
+ e-selection-model.c \
e-selection-model-array.c \
e-selection-model-simple.c \
- e-selection-model.c \
+ e-send-options.c \
e-signature-combo-box.c \
- e-unicode.c \
- e-colors.c
-
+ e-signature-editor.c \
+ e-signature-manager.c \
+ e-signature-preview.c \
+ e-signature-script-dialog.c \
+ e-signature-tree-view.c \
+ e-timeout-activity.c \
+ e-url-entry.c \
+ ea-calendar-cell.c \
+ ea-calendar-item.c \
+ ea-widgets.c
libemiscwidgets_la_LDFLAGS = $(NO_UNDEFINED)
-libemiscwidgets_la_LIBADD = $(top_builddir)/e-util/libeutil.la \
- $(top_builddir)/e-util/libeutil.la \
- $(top_builddir)/widgets/table/libetable.la \
- $(top_builddir)/widgets/text/libetext.la \
- $(top_builddir)/a11y/widgets/libevolution-widgets-a11y.la \
- $(top_builddir)/a11y/libevolution-a11y.la \
- $(EVOLUTION_MAIL_LIBS) \
- $(GNOME_PLATFORM_LIBS) \
- $(EVOLUTON_MAIL_LIBS) \
+libemiscwidgets_la_LIBADD = \
+ $(top_builddir)/e-util/libeutil.la \
+ $(top_builddir)/filter/libfilter.la \
+ $(top_builddir)/a11y/libevolution-a11y.la \
+ $(EVOLUTION_MAIL_LIBS) \
+ $(GNOME_PLATFORM_LIBS) \
+ $(MATH_LIB) \
$(ICONV_LIBS)
-filterbarinclude_HEADERS = e-filter-bar.h
-
-libefilterbar_la_SOURCES = \
- e-filter-bar.c \
- $(filterbarinclude_HEADERS)
-
-libefilterbar_la_LDFLAGS = $(NO_UNDEFINED)
-
-libefilterbar_la_LIBADD = \
- $(WIN32_BOOTSTRAP_LIBS) \
- libemiscwidgets.la \
- $(E_WIDGETS_LIBS)
-
noinst_PROGRAMS = \
test-calendar \
test-dateedit \
- test-dropdown-button \
- test-multi-config-dialog \
- test-info-label
+ test-preferences-window
# test-calendar
@@ -186,6 +177,7 @@ test_calendar_SOURCES = \
test_calendar_LDADD = \
libemiscwidgets.la \
$(top_builddir)/e-util/libeutil.la \
+ $(top_builddir)/filter/libfilter.la \
$(E_WIDGETS_LIBS)
# test-dateedit
@@ -196,36 +188,18 @@ test_dateedit_SOURCES = \
test_dateedit_LDADD = \
libemiscwidgets.la \
$(top_builddir)/e-util/libeutil.la \
+ $(top_builddir)/filter/libfilter.la \
$(E_WIDGETS_LIBS)
-# test-dropdown-button
-
-test_dropdown_button_SOURCES = \
- test-dropdown-button.c
-
-test_dropdown_button_LDADD = \
- libemiscwidgets.la \
- $(top_builddir)/e-util/libeutil.la \
- $(E_WIDGETS_LIBS)
-
-# test-multi-config-dialog
-
-test_multi_config_dialog_SOURCES = \
- test-multi-config-dialog.c
-
-test_multi_config_dialog_LDADD = \
- libemiscwidgets.la \
- $(top_builddir)/e-util/libeutil.la \
- $(E_WIDGETS_LIBS)
-
-# test-info-label
+# test-preferences-window
-test_info_label_SOURCES = \
- test-info-label.c
+test_preferences_window_SOURCES = \
+ test-preferences-window.c
-test_info_label_LDADD = \
+test_preferences_window_LDADD = \
libemiscwidgets.la \
$(top_builddir)/e-util/libeutil.la \
+ $(top_builddir)/filter/libfilter.la \
$(E_WIDGETS_LIBS)
diff --git a/widgets/misc/e-account-combo-box.c b/widgets/misc/e-account-combo-box.c
index a0d02bcd80..0ded393e72 100644
--- a/widgets/misc/e-account-combo-box.c
+++ b/widgets/misc/e-account-combo-box.c
@@ -1,4 +1,5 @@
/*
+ * e-account-combo-box.c
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
diff --git a/widgets/misc/e-account-combo-box.h b/widgets/misc/e-account-combo-box.h
index b163278dcd..12d4be6c72 100644
--- a/widgets/misc/e-account-combo-box.h
+++ b/widgets/misc/e-account-combo-box.h
@@ -1,4 +1,5 @@
/*
+ * e-account-combo-box.h
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
diff --git a/widgets/misc/e-account-manager.c b/widgets/misc/e-account-manager.c
new file mode 100644
index 0000000000..24b579dee9
--- /dev/null
+++ b/widgets/misc/e-account-manager.c
@@ -0,0 +1,461 @@
+/*
+ * e-account-manager.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#include "e-account-manager.h"
+
+#include <glib/gi18n.h>
+#include <gdk/gdkkeysyms.h>
+#include "e-util/e-binding.h"
+#include "e-account-tree-view.h"
+
+#define E_ACCOUNT_MANAGER_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), E_TYPE_ACCOUNT_MANAGER, EAccountManagerPrivate))
+
+struct _EAccountManagerPrivate {
+ EAccountList *account_list;
+
+ GtkWidget *tree_view;
+ GtkWidget *add_button;
+ GtkWidget *edit_button;
+ GtkWidget *delete_button;
+ GtkWidget *default_button;
+};
+
+enum {
+ PROP_0,
+ PROP_ACCOUNT_LIST
+};
+
+enum {
+ ADD_ACCOUNT,
+ EDIT_ACCOUNT,
+ DELETE_ACCOUNT,
+ LAST_SIGNAL
+};
+
+static gpointer parent_class;
+static guint signals[LAST_SIGNAL];
+
+static void
+account_manager_default_clicked_cb (EAccountManager *manager)
+{
+ EAccountTreeView *tree_view;
+ EAccountList *account_list;
+ EAccount *account;
+
+ tree_view = e_account_manager_get_tree_view (manager);
+ account_list = e_account_manager_get_account_list (manager);
+ account = e_account_tree_view_get_selected (tree_view);
+ g_return_if_fail (account != NULL);
+
+ e_account_list_set_default (account_list, account);
+
+ /* This signals the tree view to refresh. */
+ e_account_list_change (account_list, account);
+}
+
+static gboolean
+account_manager_key_press_event_cb (EAccountManager *manager,
+ GdkEventKey *event)
+{
+ if (event->keyval == GDK_Delete) {
+ e_account_manager_delete_account (manager);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
+account_manager_selection_changed_cb (EAccountManager *manager,
+ GtkTreeSelection *selection)
+{
+ EAccountTreeView *tree_view;
+ EAccountList *account_list;
+ EAccount *default_account;
+ EAccount *account;
+ GtkWidget *add_button;
+ GtkWidget *edit_button;
+ GtkWidget *delete_button;
+ GtkWidget *default_button;
+ const gchar *url = NULL;
+ gboolean has_proxies;
+ gboolean sensitive;
+
+ add_button = manager->priv->add_button;
+ edit_button = manager->priv->edit_button;
+ delete_button = manager->priv->delete_button;
+ default_button = manager->priv->default_button;
+
+ tree_view = e_account_manager_get_tree_view (manager);
+ account = e_account_tree_view_get_selected (tree_view);
+ account_list = e_account_tree_view_get_account_list (tree_view);
+
+ if (account != NULL)
+ url = e_account_get_string (account, E_ACCOUNT_SOURCE_URL);
+ else
+ gtk_widget_grab_focus (add_button);
+
+ has_proxies = (url != NULL) &&
+ e_account_list_account_has_proxies (account_list, account);
+
+ /* XXX EAccountList misuses const */
+ default_account = (EAccount *)
+ e_account_list_get_default (account_list);
+
+ sensitive = (account != NULL) && !has_proxies;
+ gtk_widget_set_sensitive (edit_button, sensitive);
+
+ sensitive = (account != NULL);
+ gtk_widget_set_sensitive (delete_button, sensitive);
+
+ sensitive = (account != NULL && account != default_account);
+ gtk_widget_set_sensitive (default_button, sensitive);
+}
+
+static void
+account_manager_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_ACCOUNT_LIST:
+ e_account_manager_set_account_list (
+ E_ACCOUNT_MANAGER (object),
+ g_value_get_object (value));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+account_manager_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_ACCOUNT_LIST:
+ g_value_set_object (
+ value,
+ e_account_manager_get_account_list (
+ E_ACCOUNT_MANAGER (object)));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+account_manager_dispose (GObject *object)
+{
+ EAccountManagerPrivate *priv;
+
+ priv = E_ACCOUNT_MANAGER_GET_PRIVATE (object);
+
+ if (priv->account_list != NULL) {
+ g_object_unref (priv->account_list);
+ priv->account_list = NULL;
+ }
+
+ if (priv->tree_view != NULL) {
+ g_object_unref (priv->tree_view);
+ priv->tree_view = NULL;
+ }
+
+ if (priv->add_button != NULL) {
+ g_object_unref (priv->add_button);
+ priv->add_button = NULL;
+ }
+
+ if (priv->edit_button != NULL) {
+ g_object_unref (priv->edit_button);
+ priv->edit_button = NULL;
+ }
+
+ if (priv->delete_button != NULL) {
+ g_object_unref (priv->delete_button);
+ priv->delete_button = NULL;
+ }
+
+ /* Chain up to parent's dispose() method. */
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+account_manager_class_init (EAccountManagerClass *class)
+{
+ GObjectClass *object_class;
+
+ parent_class = g_type_class_peek_parent (class);
+ g_type_class_add_private (class, sizeof (EAccountManagerPrivate));
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->set_property = account_manager_set_property;
+ object_class->get_property = account_manager_get_property;
+ object_class->dispose = account_manager_dispose;
+
+ /* XXX If we moved the account editor to /widgets/misc we
+ * could handle adding and editing accounts directly. */
+
+ g_object_class_install_property (
+ object_class,
+ PROP_ACCOUNT_LIST,
+ g_param_spec_object (
+ "account-list",
+ "Account List",
+ NULL,
+ E_TYPE_ACCOUNT_LIST,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT));
+
+ signals[ADD_ACCOUNT] = g_signal_new (
+ "add-account",
+ G_OBJECT_CLASS_TYPE (class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (EAccountManagerClass, add_account),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ signals[EDIT_ACCOUNT] = g_signal_new (
+ "edit-account",
+ G_OBJECT_CLASS_TYPE (class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (EAccountManagerClass, edit_account),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ signals[DELETE_ACCOUNT] = g_signal_new (
+ "delete-account",
+ G_OBJECT_CLASS_TYPE (class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (EAccountManagerClass, delete_account),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+}
+
+static void
+account_manager_init (EAccountManager *manager)
+{
+ GtkTreeSelection *selection;
+ GtkWidget *container;
+ GtkWidget *widget;
+
+ manager->priv = E_ACCOUNT_MANAGER_GET_PRIVATE (manager);
+
+ gtk_table_resize (GTK_TABLE (manager), 1, 2);
+ gtk_table_set_col_spacings (GTK_TABLE (manager), 6);
+ gtk_table_set_row_spacings (GTK_TABLE (manager), 12);
+
+ container = GTK_WIDGET (manager);
+
+ widget = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (
+ GTK_SCROLLED_WINDOW (widget),
+ GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+ gtk_scrolled_window_set_shadow_type (
+ GTK_SCROLLED_WINDOW (widget), GTK_SHADOW_IN);
+ gtk_table_attach (
+ GTK_TABLE (container), widget, 0, 1, 0, 1,
+ GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
+ gtk_widget_show (widget);
+
+ container = widget;
+
+ widget = e_account_tree_view_new ();
+ gtk_container_add (GTK_CONTAINER (container), widget);
+ manager->priv->tree_view = g_object_ref (widget);
+ gtk_widget_show (widget);
+
+ e_mutual_binding_new (
+ G_OBJECT (manager), "account-list",
+ G_OBJECT (widget), "account-list");
+
+ g_signal_connect_swapped (
+ widget, "key-press-event",
+ G_CALLBACK (account_manager_key_press_event_cb),
+ manager);
+
+ g_signal_connect_swapped (
+ widget, "row-activated",
+ G_CALLBACK (e_account_manager_edit_account),
+ manager);
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
+
+ g_signal_connect_swapped (
+ selection, "changed",
+ G_CALLBACK (account_manager_selection_changed_cb),
+ manager);
+
+ container = GTK_WIDGET (manager);
+
+ widget = gtk_vbutton_box_new ();
+ gtk_button_box_set_layout (
+ GTK_BUTTON_BOX (widget), GTK_BUTTONBOX_START);
+ gtk_box_set_spacing (GTK_BOX (widget), 6);
+ gtk_table_attach (
+ GTK_TABLE (container), widget,
+ 1, 2, 0, 2, 0, GTK_FILL, 0, 0);
+ gtk_widget_show (widget);
+
+ container = widget;
+
+ widget = gtk_button_new_from_stock (GTK_STOCK_ADD);
+ gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
+ manager->priv->add_button = g_object_ref (widget);
+ gtk_widget_show (widget);
+
+ g_signal_connect_swapped (
+ widget, "clicked",
+ G_CALLBACK (e_account_manager_add_account), manager);
+
+ widget = gtk_button_new_from_stock (GTK_STOCK_EDIT);
+ gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
+ manager->priv->edit_button = g_object_ref (widget);
+ gtk_widget_show (widget);
+
+ g_signal_connect_swapped (
+ widget, "clicked",
+ G_CALLBACK (e_account_manager_edit_account), manager);
+
+ widget = gtk_button_new_from_stock (GTK_STOCK_DELETE);
+ gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
+ manager->priv->delete_button = g_object_ref (widget);
+ gtk_widget_show (widget);
+
+ g_signal_connect_swapped (
+ widget, "clicked",
+ G_CALLBACK (e_account_manager_delete_account), manager);
+
+ widget = gtk_button_new_with_mnemonic (_("De_fault"));
+ gtk_button_set_image (
+ GTK_BUTTON (widget), gtk_image_new_from_icon_name (
+ "emblem-default", GTK_ICON_SIZE_BUTTON));
+ gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
+ manager->priv->default_button = g_object_ref (widget);
+ gtk_widget_show (widget);
+
+ g_signal_connect_swapped (
+ widget, "clicked",
+ G_CALLBACK (account_manager_default_clicked_cb), manager);
+}
+
+GType
+e_account_manager_get_type (void)
+{
+ static GType type = 0;
+
+ if (G_UNLIKELY (type == 0)) {
+ static const GTypeInfo type_info = {
+ sizeof (EAccountManagerClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) account_manager_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_init */
+ sizeof (EAccountManager),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) account_manager_init,
+ NULL /* value_table */
+ };
+
+ type = g_type_register_static (
+ GTK_TYPE_TABLE, "EAccountManager", &type_info, 0);
+ }
+
+ return type;
+}
+
+GtkWidget *
+e_account_manager_new (EAccountList *account_list)
+{
+ g_return_val_if_fail (E_IS_ACCOUNT_LIST (account_list), NULL);
+
+ return g_object_new (
+ E_TYPE_ACCOUNT_MANAGER,
+ "account-list", account_list, NULL);
+}
+
+void
+e_account_manager_add_account (EAccountManager *manager)
+{
+ g_return_if_fail (E_IS_ACCOUNT_MANAGER (manager));
+
+ g_signal_emit (manager, signals[ADD_ACCOUNT], 0);
+}
+
+void
+e_account_manager_edit_account (EAccountManager *manager)
+{
+ g_return_if_fail (E_IS_ACCOUNT_MANAGER (manager));
+
+ g_signal_emit (manager, signals[EDIT_ACCOUNT], 0);
+}
+
+void
+e_account_manager_delete_account (EAccountManager *manager)
+{
+ g_return_if_fail (E_IS_ACCOUNT_MANAGER (manager));
+
+ g_signal_emit (manager, signals[DELETE_ACCOUNT], 0);
+}
+
+EAccountList *
+e_account_manager_get_account_list (EAccountManager *manager)
+{
+ g_return_val_if_fail (E_IS_ACCOUNT_MANAGER (manager), NULL);
+
+ return manager->priv->account_list;
+}
+
+void
+e_account_manager_set_account_list (EAccountManager *manager,
+ EAccountList *account_list)
+{
+ g_return_if_fail (E_IS_ACCOUNT_MANAGER (manager));
+
+ if (account_list != NULL) {
+ g_return_if_fail (E_IS_ACCOUNT_LIST (account_list));
+ g_object_ref (account_list);
+ }
+
+ if (manager->priv->account_list != NULL)
+ g_object_unref (manager->priv->account_list);
+
+ manager->priv->account_list = account_list;
+
+ g_object_notify (G_OBJECT (manager), "account-list");
+}
+
+EAccountTreeView *
+e_account_manager_get_tree_view (EAccountManager *manager)
+{
+ g_return_val_if_fail (E_IS_ACCOUNT_MANAGER (manager), NULL);
+
+ return E_ACCOUNT_TREE_VIEW (manager->priv->tree_view);
+}
diff --git a/widgets/misc/e-account-manager.h b/widgets/misc/e-account-manager.h
new file mode 100644
index 0000000000..dab8b2832f
--- /dev/null
+++ b/widgets/misc/e-account-manager.h
@@ -0,0 +1,82 @@
+/*
+ * e-account-manager.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef E_ACCOUNT_MANAGER_H
+#define E_ACCOUNT_MANAGER_H
+
+#include <gtk/gtk.h>
+#include <libedataserver/e-account-list.h>
+#include <misc/e-account-tree-view.h>
+
+/* Standard GObject macros */
+#define E_TYPE_ACCOUNT_MANAGER \
+ (e_account_manager_get_type ())
+#define E_ACCOUNT_MANAGER(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_ACCOUNT_MANAGER, EAccountManager))
+#define E_ACCOUNT_MANAGER_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_ACCOUNT_MANAGER, EAccountManagerClass))
+#define E_IS_ACCOUNT_MANAGER(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_ACCOUNT_MANAGER))
+#define E_IS_ACCOUNT_MANAGER_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_ACCOUNT_MANAGER))
+#define E_ACCOUNT_MANAGER_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_ACCOUNT_MANAGER, EAccountManagerClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EAccountManager EAccountManager;
+typedef struct _EAccountManagerClass EAccountManagerClass;
+typedef struct _EAccountManagerPrivate EAccountManagerPrivate;
+
+struct _EAccountManager {
+ GtkTable parent;
+ EAccountManagerPrivate *priv;
+};
+
+struct _EAccountManagerClass {
+ GtkTableClass parent_class;
+
+ void (*add_account) (EAccountManager *manager);
+ void (*edit_account) (EAccountManager *manager);
+ void (*delete_account) (EAccountManager *manager);
+};
+
+GType e_account_manager_get_type (void);
+GtkWidget * e_account_manager_new (EAccountList *account_list);
+void e_account_manager_add_account (EAccountManager *manager);
+void e_account_manager_edit_account (EAccountManager *manager);
+void e_account_manager_delete_account(EAccountManager *manager);
+EAccountList * e_account_manager_get_account_list
+ (EAccountManager *manager);
+void e_account_manager_set_account_list
+ (EAccountManager *manager,
+ EAccountList *account_list);
+EAccountTreeView *
+ e_account_manager_get_tree_view (EAccountManager *manager);
+
+G_END_DECLS
+
+#endif /* E_ACCOUNT_MANAGER_H */
diff --git a/widgets/misc/e-account-tree-view.c b/widgets/misc/e-account-tree-view.c
new file mode 100644
index 0000000000..8e57dfcf66
--- /dev/null
+++ b/widgets/misc/e-account-tree-view.c
@@ -0,0 +1,632 @@
+/*
+ * e-account-tree-view.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#include "e-account-tree-view.h"
+
+#include <glib/gi18n.h>
+#include <camel/camel-url.h>
+
+#define E_ACCOUNT_TREE_VIEW_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), E_TYPE_ACCOUNT_TREE_VIEW, EAccountTreeViewPrivate))
+
+enum {
+ COLUMN_ACCOUNT,
+ COLUMN_DEFAULT,
+ COLUMN_ENABLED,
+ COLUMN_NAME,
+ COLUMN_PROTOCOL
+};
+
+enum {
+ PROP_0,
+ PROP_ACCOUNT_LIST,
+ PROP_SELECTED
+};
+
+enum {
+ ENABLE_ACCOUNT,
+ DISABLE_ACCOUNT,
+ REFRESHED,
+ LAST_SIGNAL
+};
+
+struct _EAccountTreeViewPrivate {
+ EAccountList *account_list;
+ GHashTable *index;
+};
+
+static gpointer parent_class;
+static guint signals[LAST_SIGNAL];
+
+static void
+account_tree_view_refresh_cb (EAccountList *account_list,
+ EAccount *account,
+ EAccountTreeView *tree_view)
+{
+ GtkListStore *store;
+ GtkTreeModel *model;
+ GtkTreeIter tree_iter;
+ EIterator *account_iter;
+ EAccount *default_account;
+ GHashTable *index;
+ GList *list = NULL;
+ GList *iter;
+
+ store = gtk_list_store_new (
+ 5, E_TYPE_ACCOUNT, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
+ G_TYPE_STRING, G_TYPE_STRING);
+ model = GTK_TREE_MODEL (store);
+ index = tree_view->priv->index;
+
+ g_hash_table_remove_all (index);
+
+ if (account_list == NULL)
+ goto skip;
+
+ /* XXX EAccountList misuses const. */
+ default_account = (EAccount *)
+ e_account_list_get_default (account_list);
+
+ /* Build a list of EAccounts to display. */
+ account_iter = e_list_get_iterator (E_LIST (account_list));
+ while (e_iterator_is_valid (account_iter)) {
+
+ /* XXX EIterator misuses const. */
+ account = (EAccount *) e_iterator_get (account_iter);
+ list = g_list_prepend (list, account);
+ e_iterator_next (account_iter);
+ }
+ g_object_unref (account_iter);
+
+ list = g_list_reverse (list);
+
+ /* Populate the list store and index. */
+ for (iter = list; iter != NULL; iter = iter->next) {
+ GtkTreeRowReference *reference;
+ GtkTreePath *path;
+ CamelURL *url = NULL;
+ gboolean is_default;
+ const gchar *protocol;
+
+ account = iter->data;
+
+ /* Skip proxy accounts. */
+ if (account->parent_uid != NULL)
+ continue;
+
+ is_default = (account == default_account);
+
+ if (account->source != NULL && account->source->url != NULL)
+ url = camel_url_new (account->source->url, NULL);
+
+ if (url != NULL && url->protocol != NULL)
+ protocol = url->protocol;
+ else
+ protocol = _("None");
+
+ gtk_list_store_append (store, &tree_iter);
+ gtk_list_store_set (
+ store, &tree_iter,
+ COLUMN_ACCOUNT, account,
+ COLUMN_DEFAULT, is_default,
+ COLUMN_ENABLED, account->enabled,
+ COLUMN_NAME, account->name,
+ COLUMN_PROTOCOL, protocol, -1);
+
+ path = gtk_tree_model_get_path (model, &tree_iter);
+ reference = gtk_tree_row_reference_new (model, path);
+ g_hash_table_insert (index, account, reference);
+ gtk_tree_path_free (path);
+
+ if (url != NULL)
+ camel_url_free (url);
+ }
+
+skip:
+ /* Restore the previously selected account. */
+ account = e_account_tree_view_get_selected (tree_view);
+ if (account != NULL)
+ g_object_ref (account);
+ gtk_tree_view_set_model (GTK_TREE_VIEW (tree_view), model);
+ e_account_tree_view_set_selected (tree_view, account);
+ if (account != NULL)
+ g_object_unref (account);
+
+ g_signal_emit (tree_view, signals[REFRESHED], 0);
+}
+
+static void
+account_tree_view_enabled_toggled_cb (EAccountTreeView *tree_view,
+ gchar *path_string,
+ GtkCellRendererToggle *renderer)
+{
+ GtkTreeSelection *selection;
+ GtkTreePath *path;
+
+ /* Change the selection first so we enable or disable the
+ * correct account. */
+ path = gtk_tree_path_new_from_string (path_string);
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view));
+ gtk_tree_selection_select_path (selection, path);
+ gtk_tree_path_free (path);
+
+ if (gtk_cell_renderer_toggle_get_active (renderer))
+ e_account_tree_view_disable_account (tree_view);
+ else
+ e_account_tree_view_enable_account (tree_view);
+}
+
+static void
+account_tree_view_selection_changed_cb (EAccountTreeView *tree_view)
+{
+ g_object_notify (G_OBJECT (tree_view), "selected");
+}
+
+static GObject *
+account_tree_view_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_properties)
+{
+ GObject *object;
+ GtkTreeView *tree_view;
+ GtkTreeViewColumn *column;
+ GtkCellRenderer *renderer;
+
+ /* Chain up to parent's constructor() method. */
+ object = G_OBJECT_CLASS (parent_class)->constructor (
+ type, n_construct_properties, construct_properties);
+
+ tree_view = GTK_TREE_VIEW (object);
+ gtk_tree_view_set_headers_visible (tree_view, TRUE);
+
+ /* Column: Enabled */
+
+ column = gtk_tree_view_column_new ();
+ gtk_tree_view_column_set_expand (column, FALSE);
+ gtk_tree_view_column_set_title (column, _("Enabled"));
+
+ renderer = gtk_cell_renderer_toggle_new ();
+ gtk_tree_view_column_pack_start (column, renderer, TRUE);
+
+ g_signal_connect_swapped (
+ renderer, "toggled",
+ G_CALLBACK (account_tree_view_enabled_toggled_cb),
+ tree_view);
+
+ gtk_tree_view_column_add_attribute (
+ column, renderer, "active", COLUMN_ENABLED);
+
+ gtk_tree_view_append_column (tree_view, column);
+
+ /* Column: Account Name */
+
+ column = gtk_tree_view_column_new ();
+ gtk_tree_view_column_set_expand (column, TRUE);
+ gtk_tree_view_column_set_title (column, _("Account Name"));
+
+ renderer = gtk_cell_renderer_text_new ();
+ g_object_set (renderer, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
+ gtk_tree_view_column_pack_start (column, renderer, TRUE);
+
+ gtk_tree_view_column_add_attribute (
+ column, renderer, "text", COLUMN_NAME);
+
+ renderer = gtk_cell_renderer_text_new ();
+ g_object_set (renderer, "text", _("Default"), NULL);
+ gtk_tree_view_column_pack_end (column, renderer, FALSE);
+
+ gtk_tree_view_column_add_attribute (
+ column, renderer, "visible", COLUMN_DEFAULT);
+
+ renderer = gtk_cell_renderer_pixbuf_new ();
+ g_object_set (
+ renderer, "icon-name", "emblem-default",
+ "stock-size", GTK_ICON_SIZE_MENU, NULL);
+ gtk_tree_view_column_pack_end (column, renderer, FALSE);
+
+ gtk_tree_view_column_add_attribute (
+ column, renderer, "visible", COLUMN_DEFAULT);
+
+ gtk_tree_view_append_column (tree_view, column);
+
+ /* Column: Protocol */
+
+ column = gtk_tree_view_column_new ();
+ gtk_tree_view_column_set_expand (column, FALSE);
+ gtk_tree_view_column_set_title (column, _("Protocol"));
+
+ renderer = gtk_cell_renderer_text_new ();
+ gtk_tree_view_column_pack_start (column, renderer, TRUE);
+
+ gtk_tree_view_column_add_attribute (
+ column, renderer, "text", COLUMN_PROTOCOL);
+
+ gtk_tree_view_append_column (tree_view, column);
+
+ return object;
+}
+
+static void
+account_tree_view_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_ACCOUNT_LIST:
+ e_account_tree_view_set_account_list (
+ E_ACCOUNT_TREE_VIEW (object),
+ g_value_get_object (value));
+ return;
+
+ case PROP_SELECTED:
+ e_account_tree_view_set_selected (
+ E_ACCOUNT_TREE_VIEW (object),
+ g_value_get_object (value));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+account_tree_view_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_ACCOUNT_LIST:
+ g_value_set_object (
+ value,
+ e_account_tree_view_get_account_list (
+ E_ACCOUNT_TREE_VIEW (object)));
+ return;
+
+ case PROP_SELECTED:
+ g_value_set_object (
+ value,
+ e_account_tree_view_get_selected (
+ E_ACCOUNT_TREE_VIEW (object)));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+account_tree_view_dispose (GObject *object)
+{
+ EAccountTreeViewPrivate *priv;
+
+ priv = E_ACCOUNT_TREE_VIEW_GET_PRIVATE (object);
+
+ if (priv->account_list != NULL) {
+ g_signal_handlers_disconnect_by_func (
+ priv->account_list,
+ account_tree_view_refresh_cb, object);
+ g_object_unref (priv->account_list);
+ priv->account_list = NULL;
+ }
+
+ g_hash_table_remove_all (priv->index);
+
+ /* Chain up to parent's dispose() method. */
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+account_tree_view_finalize (GObject *object)
+{
+ EAccountTreeViewPrivate *priv;
+
+ priv = E_ACCOUNT_TREE_VIEW_GET_PRIVATE (object);
+
+ g_hash_table_destroy (priv->index);
+
+ /* Chain up to parent's finalize() method. */
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+account_tree_view_enable_account (EAccountTreeView *tree_view)
+{
+ EAccountList *account_list;
+ EAccount *account;
+
+ account = e_account_tree_view_get_selected (tree_view);
+ if (account == NULL || account->enabled)
+ return;
+
+ account_list = e_account_tree_view_get_account_list (tree_view);
+ g_return_if_fail (account_list != NULL);
+
+ account->enabled = TRUE;
+ e_account_list_change (account_list, account);
+
+ e_account_list_save (account_list);
+}
+
+static void
+account_tree_view_disable_account (EAccountTreeView *tree_view)
+{
+ EAccountList *account_list;
+ EAccount *account;
+
+ account = e_account_tree_view_get_selected (tree_view);
+ if (account == NULL || !account->enabled)
+ return;
+
+ account_list = e_account_tree_view_get_account_list (tree_view);
+ g_return_if_fail (account_list != NULL);
+
+ account->enabled = FALSE;
+ e_account_list_change (account_list, account);
+
+ e_account_list_save (account_list);
+}
+
+static void
+account_tree_view_class_init (EAccountTreeViewClass *class)
+{
+ GObjectClass *object_class;
+
+ parent_class = g_type_class_peek_parent (class);
+ g_type_class_add_private (class, sizeof (EAccountTreeViewPrivate));
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->constructor = account_tree_view_constructor;
+ object_class->set_property = account_tree_view_set_property;
+ object_class->get_property = account_tree_view_get_property;
+ object_class->dispose = account_tree_view_dispose;
+ object_class->finalize = account_tree_view_finalize;
+
+ class->enable_account = account_tree_view_enable_account;
+ class->disable_account = account_tree_view_disable_account;
+
+ g_object_class_install_property (
+ object_class,
+ PROP_SELECTED,
+ g_param_spec_object (
+ "selected",
+ "Selected Account",
+ NULL,
+ E_TYPE_ACCOUNT,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_ACCOUNT_LIST,
+ g_param_spec_object (
+ "account-list",
+ "Account List",
+ NULL,
+ E_TYPE_ACCOUNT_LIST,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT));
+
+ signals[ENABLE_ACCOUNT] = g_signal_new (
+ "enable-account",
+ G_TYPE_FROM_CLASS (class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EAccountTreeViewClass, enable_account),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ signals[DISABLE_ACCOUNT] = g_signal_new (
+ "disable-account",
+ G_TYPE_FROM_CLASS (class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EAccountTreeViewClass, disable_account),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ signals[REFRESHED] = g_signal_new (
+ "refreshed",
+ G_TYPE_FROM_CLASS (class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EAccountTreeViewClass, refreshed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+}
+
+static void
+account_tree_view_init (EAccountTreeView *tree_view)
+{
+ GHashTable *index;
+ GtkTreeSelection *selection;
+
+ /* Reverse-lookup index */
+ index = g_hash_table_new_full (
+ g_direct_hash, g_direct_equal,
+ (GDestroyNotify) g_object_unref,
+ (GDestroyNotify) gtk_tree_row_reference_free);
+
+ tree_view->priv = E_ACCOUNT_TREE_VIEW_GET_PRIVATE (tree_view);
+ tree_view->priv->index = index;
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view));
+
+ g_signal_connect_swapped (
+ selection, "changed",
+ G_CALLBACK (account_tree_view_selection_changed_cb),
+ tree_view);
+}
+
+GType
+e_account_tree_view_get_type (void)
+{
+ static GType type = 0;
+
+ if (G_UNLIKELY (type == 0)) {
+ static const GTypeInfo type_info = {
+ sizeof (EAccountTreeViewClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) account_tree_view_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+ sizeof (EAccountTreeView),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) account_tree_view_init,
+ NULL /* value_table */
+ };
+
+ type = g_type_register_static (
+ GTK_TYPE_TREE_VIEW, "EAccountTreeView",
+ &type_info, 0);
+ }
+
+ return type;
+}
+
+GtkWidget *
+e_account_tree_view_new (void)
+{
+ return g_object_new (E_TYPE_ACCOUNT_TREE_VIEW, NULL);
+}
+
+void
+e_account_tree_view_enable_account (EAccountTreeView *tree_view)
+{
+ g_return_if_fail (E_IS_ACCOUNT_TREE_VIEW (tree_view));
+
+ g_signal_emit (tree_view, signals[ENABLE_ACCOUNT], 0);
+}
+
+void
+e_account_tree_view_disable_account (EAccountTreeView *tree_view)
+{
+ g_return_if_fail (E_IS_ACCOUNT_TREE_VIEW (tree_view));
+
+ g_signal_emit (tree_view, signals[DISABLE_ACCOUNT], 0);
+}
+
+EAccountList *
+e_account_tree_view_get_account_list (EAccountTreeView *tree_view)
+{
+ g_return_val_if_fail (E_IS_ACCOUNT_TREE_VIEW (tree_view), NULL);
+
+ return tree_view->priv->account_list;
+}
+
+void
+e_account_tree_view_set_account_list (EAccountTreeView *tree_view,
+ EAccountList *account_list)
+{
+ EAccountTreeViewPrivate *priv;
+
+ g_return_if_fail (E_IS_ACCOUNT_TREE_VIEW (tree_view));
+
+ if (account_list != NULL)
+ g_return_if_fail (E_IS_ACCOUNT_LIST (account_list));
+
+ priv = E_ACCOUNT_TREE_VIEW_GET_PRIVATE (tree_view);
+
+ if (priv->account_list != NULL) {
+ g_signal_handlers_disconnect_by_func (
+ priv->account_list,
+ account_tree_view_refresh_cb, tree_view);
+ g_object_unref (priv->account_list);
+ priv->account_list = NULL;
+ }
+
+ if (account_list != NULL) {
+ priv->account_list = g_object_ref (account_list);
+
+ /* Listen for changes to the account list. */
+ g_signal_connect (
+ priv->account_list, "account-added",
+ G_CALLBACK (account_tree_view_refresh_cb),
+ tree_view);
+ g_signal_connect (
+ priv->account_list, "account-changed",
+ G_CALLBACK (account_tree_view_refresh_cb),
+ tree_view);
+ g_signal_connect (
+ priv->account_list, "account-removed",
+ G_CALLBACK (account_tree_view_refresh_cb),
+ tree_view);
+ }
+
+ account_tree_view_refresh_cb (account_list, NULL, tree_view);
+
+ g_object_notify (G_OBJECT (tree_view), "account-list");
+}
+
+EAccount *
+e_account_tree_view_get_selected (EAccountTreeView *tree_view)
+{
+ EAccount *account;
+ GtkTreeSelection *selection;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+
+ g_return_val_if_fail (E_IS_ACCOUNT_TREE_VIEW (tree_view), NULL);
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view));
+ if (!gtk_tree_selection_get_selected (selection, &model, &iter))
+ return NULL;
+
+ gtk_tree_model_get (model, &iter, COLUMN_ACCOUNT, &account, -1);
+
+ return account;
+}
+
+gboolean
+e_account_tree_view_set_selected (EAccountTreeView *tree_view,
+ EAccount *account)
+{
+ GtkTreeRowReference *reference;
+ GtkTreeSelection *selection;
+ GtkTreePath *path;
+
+ g_return_val_if_fail (E_IS_ACCOUNT_TREE_VIEW (tree_view), FALSE);
+
+ if (account != NULL)
+ g_return_val_if_fail (E_IS_ACCOUNT (account), FALSE);
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view));
+
+ /* NULL means clear the selection. */
+ if (account == NULL) {
+ gtk_tree_selection_unselect_all (selection);
+ return TRUE;
+ }
+
+ /* Lookup the tree row reference for the account. */
+ reference = g_hash_table_lookup (tree_view->priv->index, account);
+ if (reference == NULL)
+ return FALSE;
+
+ /* Select the referenced path. */
+ path = gtk_tree_row_reference_get_path (reference);
+ gtk_tree_selection_select_path (selection, path);
+ gtk_tree_path_free (path);
+
+ g_object_notify (G_OBJECT (tree_view), "selected");
+
+ return TRUE;
+}
diff --git a/widgets/misc/e-account-tree-view.h b/widgets/misc/e-account-tree-view.h
new file mode 100644
index 0000000000..ea13dc3902
--- /dev/null
+++ b/widgets/misc/e-account-tree-view.h
@@ -0,0 +1,84 @@
+/*
+ * e-account-tree-view.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef E_ACCOUNT_TREE_VIEW_H
+#define E_ACCOUNT_TREE_VIEW_H
+
+#include <gtk/gtk.h>
+#include <libedataserver/e-account.h>
+#include <libedataserver/e-account-list.h>
+
+/* Standard GObject macros */
+#define E_TYPE_ACCOUNT_TREE_VIEW \
+ (e_account_tree_view_get_type ())
+#define E_ACCOUNT_TREE_VIEW(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_ACCOUNT_TREE_VIEW, EAccountTreeView))
+#define E_ACCOUNT_TREE_VIEW_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_ACCOUNT_TREE_VIEW, EAccountTreeViewClass))
+#define E_IS_ACCOUNT_TREE_VIEW(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_ACCOUNT_TREE_VIEW))
+#define E_IS_ACCOUNT_TREE_VIEW_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_ACCOUNT_TREE_VIEW))
+#define E_ACCOUNT_TREE_VIEW_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_ACCOUNT_TREE_VIEW, EAccountTreeViewClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EAccountTreeView EAccountTreeView;
+typedef struct _EAccountTreeViewClass EAccountTreeViewClass;
+typedef struct _EAccountTreeViewPrivate EAccountTreeViewPrivate;
+
+struct _EAccountTreeView {
+ GtkTreeView parent;
+ EAccountTreeViewPrivate *priv;
+};
+
+struct _EAccountTreeViewClass {
+ GtkTreeViewClass parent_class;
+
+ void (*enable_account) (EAccountTreeView *tree_view);
+ void (*disable_account) (EAccountTreeView *tree_view);
+ void (*refreshed) (EAccountTreeView *tree_view);
+};
+
+GType e_account_tree_view_get_type (void);
+GtkWidget * e_account_tree_view_new (void);
+void e_account_tree_view_enable_account
+ (EAccountTreeView *tree_view);
+void e_account_tree_view_disable_account
+ (EAccountTreeView *tree_view);
+EAccountList * e_account_tree_view_get_account_list
+ (EAccountTreeView *tree_view);
+void e_account_tree_view_set_account_list
+ (EAccountTreeView *tree_view,
+ EAccountList *account_list);
+EAccount * e_account_tree_view_get_selected(EAccountTreeView *tree_view);
+gboolean e_account_tree_view_set_selected(EAccountTreeView *tree_view,
+ EAccount *account);
+
+G_END_DECLS
+
+#endif /* E_ACCOUNT_TREE_VIEW_H */
diff --git a/widgets/misc/e-action-combo-box.c b/widgets/misc/e-action-combo-box.c
new file mode 100644
index 0000000000..e8a9be51ed
--- /dev/null
+++ b/widgets/misc/e-action-combo-box.c
@@ -0,0 +1,582 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* e-action-combo-box.c
+ *
+ * Copyright (C) 2008 Novell, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * 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 Lesser 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.
+ */
+
+#include "e-action-combo-box.h"
+
+#include <glib/gi18n.h>
+
+#define E_ACTION_COMBO_BOX_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), E_TYPE_ACTION_COMBO_BOX, EActionComboBoxPrivate))
+
+enum {
+ COLUMN_ACTION,
+ COLUMN_SORT
+};
+
+enum {
+ PROP_0,
+ PROP_ACTION
+};
+
+struct _EActionComboBoxPrivate {
+ GtkRadioAction *action;
+ GtkActionGroup *action_group;
+ GHashTable *index;
+ guint changed_handler_id; /* action::changed */
+ guint group_sensitive_handler_id; /* action-group::sensitive */
+ guint group_visible_handler_id; /* action-group::visible */
+ gboolean group_has_icons : 1;
+};
+
+static gpointer parent_class;
+
+static void
+action_combo_box_action_changed_cb (GtkRadioAction *action,
+ GtkRadioAction *current,
+ EActionComboBox *combo_box)
+{
+ GtkTreeRowReference *reference;
+ GtkTreeModel *model;
+ GtkTreePath *path;
+ GtkTreeIter iter;
+ gboolean valid;
+
+ reference = g_hash_table_lookup (
+ combo_box->priv->index, GINT_TO_POINTER (
+ gtk_radio_action_get_current_value (current)));
+ g_return_if_fail (reference != NULL);
+
+ model = gtk_tree_row_reference_get_model (reference);
+ path = gtk_tree_row_reference_get_path (reference);
+ valid = gtk_tree_model_get_iter (model, &iter, path);
+ gtk_tree_path_free (path);
+ g_return_if_fail (valid);
+
+ gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combo_box), &iter);
+}
+
+static void
+action_combo_box_action_group_notify_cb (GtkActionGroup *action_group,
+ GParamSpec *pspec,
+ EActionComboBox *combo_box)
+{
+ g_object_set (
+ combo_box, "sensitive",
+ gtk_action_group_get_sensitive (action_group), "visible",
+ gtk_action_group_get_visible (action_group), NULL);
+}
+
+static void
+action_combo_box_render_pixbuf (GtkCellLayout *layout,
+ GtkCellRenderer *renderer,
+ GtkTreeModel *model,
+ GtkTreeIter *iter,
+ EActionComboBox *combo_box)
+{
+ GtkRadioAction *action;
+ gchar *icon_name;
+ gchar *stock_id;
+ gboolean sensitive;
+ gboolean visible;
+ gint width;
+
+ gtk_tree_model_get (model, iter, COLUMN_ACTION, &action, -1);
+
+ /* Do any of the actions have an icon? */
+ if (!combo_box->priv->group_has_icons)
+ return;
+
+ /* A NULL action means the row is a separator. */
+ if (action == NULL)
+ return;
+
+ g_object_get (
+ G_OBJECT (action),
+ "icon-name", &icon_name,
+ "sensitive", &sensitive,
+ "stock-id", &stock_id,
+ "visible", &visible,
+ NULL);
+
+ /* Keep the pixbuf renderer a fixed size for proper alignment. */
+ gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &width, NULL);
+
+ /* We can't set both "icon-name" and "stock-id" because setting
+ * one unsets the other. So pick the one that has a non-NULL
+ * value. If both are non-NULL, "stock-id" wins. */
+
+ if (stock_id != NULL)
+ g_object_set (
+ G_OBJECT (renderer),
+ "sensitive", sensitive,
+ "stock-id", stock_id,
+ "stock-size", GTK_ICON_SIZE_MENU,
+ "visible", visible,
+ "width", width,
+ NULL);
+ else
+ g_object_set (
+ G_OBJECT (renderer),
+ "icon-name", icon_name,
+ "sensitive", sensitive,
+ "stock-size", GTK_ICON_SIZE_MENU,
+ "visible", visible,
+ "width", width,
+ NULL);
+
+ g_free (icon_name);
+ g_free (stock_id);
+}
+
+static void
+action_combo_box_render_text (GtkCellLayout *layout,
+ GtkCellRenderer *renderer,
+ GtkTreeModel *model,
+ GtkTreeIter *iter,
+ EActionComboBox *combo_box)
+{
+ GtkRadioAction *action;
+ gchar **strv;
+ gchar *label;
+ gboolean sensitive;
+ gboolean visible;
+ gint xpad;
+
+ gtk_tree_model_get (model, iter, COLUMN_ACTION, &action, -1);
+
+ /* A NULL action means the row is a separator. */
+ if (action == NULL)
+ return;
+
+ g_object_get (
+ G_OBJECT (action),
+ "label", &label,
+ "sensitive", &sensitive,
+ "visible", &visible,
+ NULL);
+
+ /* Strip out underscores. */
+ strv = g_strsplit (label, "_", -1);
+ g_free (label);
+ label = g_strjoinv (NULL, strv);
+ g_strfreev (strv);
+
+ xpad = combo_box->priv->group_has_icons ? 3 : 0;
+
+ g_object_set (
+ G_OBJECT (renderer),
+ "sensitive", sensitive,
+ "text", label,
+ "visible", visible,
+ "xpad", xpad,
+ NULL);
+
+ g_free (label);
+}
+
+static gboolean
+action_combo_box_is_row_separator (GtkTreeModel *model,
+ GtkTreeIter *iter)
+{
+ GtkAction *action;
+ gboolean separator;
+
+ /* NULL actions are rendered as separators. */
+ gtk_tree_model_get (model, iter, COLUMN_ACTION, &action, -1);
+ separator = (action == NULL);
+ if (action != NULL)
+ g_object_unref (action);
+
+ return separator;
+}
+
+static void
+action_combo_box_update_model (EActionComboBox *combo_box)
+{
+ GtkListStore *list_store;
+ GSList *list;
+
+ g_hash_table_remove_all (combo_box->priv->index);
+
+ if (combo_box->priv->action == NULL) {
+ gtk_combo_box_set_model (GTK_COMBO_BOX (combo_box), NULL);
+ return;
+ }
+
+ /* We store values in the sort column as floats so that we can
+ * insert separators in between consecutive integer values and
+ * still maintain the proper ordering. */
+ list_store = gtk_list_store_new (
+ 2, GTK_TYPE_RADIO_ACTION, G_TYPE_FLOAT);
+
+ list = gtk_radio_action_get_group (combo_box->priv->action);
+ combo_box->priv->group_has_icons = FALSE;
+
+ while (list != NULL) {
+ GtkTreeRowReference *reference;
+ GtkRadioAction *action = list->data;
+ GtkTreePath *path;
+ GtkTreeIter iter;
+ gchar *icon_name;
+ gchar *stock_id;
+ gint value;
+
+ g_object_get (
+ action, "icon-name", &icon_name,
+ "stock-id", &stock_id, NULL);
+ combo_box->priv->group_has_icons |=
+ (icon_name != NULL || stock_id != NULL);
+ g_free (icon_name);
+ g_free (stock_id);
+
+ gtk_list_store_append (list_store, &iter);
+ g_object_get (G_OBJECT (action), "value", &value, NULL);
+ gtk_list_store_set (
+ list_store, &iter, COLUMN_ACTION,
+ list->data, COLUMN_SORT, (gfloat) value, -1);
+
+ path = gtk_tree_model_get_path (
+ GTK_TREE_MODEL (list_store), &iter);
+ reference = gtk_tree_row_reference_new (
+ GTK_TREE_MODEL (list_store), path);
+ g_hash_table_insert (
+ combo_box->priv->index,
+ GINT_TO_POINTER (value), reference);
+ gtk_tree_path_free (path);
+
+ list = g_slist_next (list);
+ }
+
+ gtk_tree_sortable_set_sort_column_id (
+ GTK_TREE_SORTABLE (list_store),
+ COLUMN_SORT, GTK_SORT_ASCENDING);
+ gtk_combo_box_set_model (
+ GTK_COMBO_BOX (combo_box), GTK_TREE_MODEL (list_store));
+
+ action_combo_box_action_changed_cb (
+ combo_box->priv->action,
+ combo_box->priv->action,
+ combo_box);
+}
+
+static void
+action_combo_box_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_ACTION:
+ e_action_combo_box_set_action (
+ E_ACTION_COMBO_BOX (object),
+ g_value_get_object (value));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+action_combo_box_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_ACTION:
+ g_value_set_object (
+ value, e_action_combo_box_get_action (
+ E_ACTION_COMBO_BOX (object)));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+action_combo_box_dispose (GObject *object)
+{
+ EActionComboBoxPrivate *priv = E_ACTION_COMBO_BOX_GET_PRIVATE (object);
+
+ if (priv->action != NULL) {
+ g_object_unref (priv->action);
+ priv->action = NULL;
+ }
+
+ if (priv->action_group != NULL) {
+ g_object_unref (priv->action_group);
+ priv->action_group = NULL;
+ }
+
+ g_hash_table_remove_all (priv->index);
+
+ /* Chain up to parent's dispose() method. */
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+action_combo_box_finalize (GObject *object)
+{
+ EActionComboBoxPrivate *priv = E_ACTION_COMBO_BOX_GET_PRIVATE (object);
+
+ g_hash_table_destroy (priv->index);
+
+ /* Chain up to parent's finalize() method. */
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+action_combo_box_changed (GtkComboBox *combo_box)
+{
+ GtkRadioAction *action;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ gint value;
+
+ /* This method is virtual, so no need to chain up. */
+
+ if (!gtk_combo_box_get_active_iter (combo_box, &iter))
+ return;
+
+ model = gtk_combo_box_get_model (combo_box);
+ gtk_tree_model_get (model, &iter, COLUMN_ACTION, &action, -1);
+ g_object_get (G_OBJECT (action), "value", &value, NULL);
+ gtk_radio_action_set_current_value (action, value);
+}
+
+static void
+action_combo_box_class_init (EActionComboBoxClass *class)
+{
+ GObjectClass *object_class;
+ GtkComboBoxClass *combo_box_class;
+
+ parent_class = g_type_class_peek_parent (class);
+ g_type_class_add_private (class, sizeof (EActionComboBoxPrivate));
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->set_property = action_combo_box_set_property;
+ object_class->get_property = action_combo_box_get_property;
+ object_class->dispose = action_combo_box_dispose;
+ object_class->finalize = action_combo_box_finalize;
+
+ combo_box_class = GTK_COMBO_BOX_CLASS (class);
+ combo_box_class->changed = action_combo_box_changed;
+
+ g_object_class_install_property (
+ object_class,
+ PROP_ACTION,
+ g_param_spec_object (
+ "action",
+ _("Action"),
+ _("A GtkRadioAction"),
+ GTK_TYPE_RADIO_ACTION,
+ G_PARAM_READWRITE));
+}
+
+static void
+action_combo_box_init (EActionComboBox *combo_box)
+{
+ GtkCellRenderer *renderer;
+
+ combo_box->priv = E_ACTION_COMBO_BOX_GET_PRIVATE (combo_box);
+
+ renderer = gtk_cell_renderer_pixbuf_new ();
+ gtk_cell_layout_pack_start (
+ GTK_CELL_LAYOUT (combo_box), renderer, FALSE);
+ gtk_cell_layout_set_cell_data_func (
+ GTK_CELL_LAYOUT (combo_box), renderer,
+ (GtkCellLayoutDataFunc) action_combo_box_render_pixbuf,
+ combo_box, NULL);
+
+ renderer = gtk_cell_renderer_text_new ();
+ gtk_cell_layout_pack_start (
+ GTK_CELL_LAYOUT (combo_box), renderer, TRUE);
+ gtk_cell_layout_set_cell_data_func (
+ GTK_CELL_LAYOUT (combo_box), renderer,
+ (GtkCellLayoutDataFunc) action_combo_box_render_text,
+ combo_box, NULL);
+
+ gtk_combo_box_set_row_separator_func (
+ GTK_COMBO_BOX (combo_box), (GtkTreeViewRowSeparatorFunc)
+ action_combo_box_is_row_separator, NULL, NULL);
+
+ combo_box->priv->index = g_hash_table_new_full (
+ g_direct_hash, g_direct_equal,
+ (GDestroyNotify) NULL,
+ (GDestroyNotify) gtk_tree_row_reference_free);
+}
+
+GType
+e_action_combo_box_get_type (void)
+{
+ static GType type = 0;
+
+ if (G_UNLIKELY (type == 0)) {
+ static const GTypeInfo type_info = {
+ sizeof (EActionComboBoxClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) action_combo_box_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+ sizeof (EActionComboBox),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) action_combo_box_init,
+ NULL /* value_table */
+ };
+
+ type = g_type_register_static (
+ GTK_TYPE_COMBO_BOX, "EActionComboBox",
+ &type_info, 0);
+ }
+
+ return type;
+}
+
+GtkWidget *
+e_action_combo_box_new (void)
+{
+ return e_action_combo_box_new_with_action (NULL);
+}
+
+GtkWidget *
+e_action_combo_box_new_with_action (GtkRadioAction *action)
+{
+ return g_object_new (E_TYPE_ACTION_COMBO_BOX, "action", action, NULL);
+}
+
+GtkRadioAction *
+e_action_combo_box_get_action (EActionComboBox *combo_box)
+{
+ g_return_val_if_fail (E_ACTION_IS_COMBO_BOX (combo_box), NULL);
+
+ return combo_box->priv->action;
+}
+
+void
+e_action_combo_box_set_action (EActionComboBox *combo_box,
+ GtkRadioAction *action)
+{
+ g_return_if_fail (E_ACTION_IS_COMBO_BOX (combo_box));
+
+ if (action != NULL)
+ g_return_if_fail (GTK_IS_RADIO_ACTION (action));
+
+ if (combo_box->priv->action != NULL) {
+ g_signal_handler_disconnect (
+ combo_box->priv->action,
+ combo_box->priv->changed_handler_id);
+ g_object_unref (combo_box->priv->action);
+ }
+
+ if (combo_box->priv->action_group != NULL) {
+ g_signal_handler_disconnect (
+ combo_box->priv->action_group,
+ combo_box->priv->group_sensitive_handler_id);
+ g_signal_handler_disconnect (
+ combo_box->priv->action_group,
+ combo_box->priv->group_visible_handler_id);
+ g_object_unref (combo_box->priv->action_group);
+ combo_box->priv->action_group = NULL;
+ }
+
+ if (action != NULL)
+ g_object_get (
+ g_object_ref (action), "action-group",
+ &combo_box->priv->action_group, NULL);
+ combo_box->priv->action = action;
+ action_combo_box_update_model (combo_box);
+
+ if (combo_box->priv->action != NULL)
+ combo_box->priv->changed_handler_id = g_signal_connect (
+ combo_box->priv->action, "changed",
+ G_CALLBACK (action_combo_box_action_changed_cb),
+ combo_box);
+
+ if (combo_box->priv->action_group != NULL) {
+ combo_box->priv->group_sensitive_handler_id =
+ g_signal_connect (
+ combo_box->priv->action_group,
+ "notify::sensitive", G_CALLBACK (
+ action_combo_box_action_group_notify_cb),
+ combo_box);
+ combo_box->priv->group_visible_handler_id =
+ g_signal_connect (
+ combo_box->priv->action_group,
+ "notify::visible", G_CALLBACK (
+ action_combo_box_action_group_notify_cb),
+ combo_box);
+ }
+}
+
+gint
+e_action_combo_box_get_current_value (EActionComboBox *combo_box)
+{
+ g_return_val_if_fail (E_ACTION_IS_COMBO_BOX (combo_box), 0);
+ g_return_val_if_fail (combo_box->priv->action != NULL, 0);
+
+ return gtk_radio_action_get_current_value (combo_box->priv->action);
+}
+
+void
+e_action_combo_box_set_current_value (EActionComboBox *combo_box,
+ gint current_value)
+{
+ g_return_if_fail (E_ACTION_IS_COMBO_BOX (combo_box));
+ g_return_if_fail (combo_box->priv->action != NULL);
+
+ gtk_radio_action_set_current_value (
+ combo_box->priv->action, current_value);
+}
+
+void
+e_action_combo_box_add_separator_before (EActionComboBox *combo_box,
+ gint action_value)
+{
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+
+ g_return_if_fail (E_ACTION_IS_COMBO_BOX (combo_box));
+
+ /* NULL actions are rendered as separators. */
+ model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo_box));
+ gtk_list_store_append (GTK_LIST_STORE (model), &iter);
+ gtk_list_store_set (
+ GTK_LIST_STORE (model), &iter, COLUMN_ACTION,
+ NULL, COLUMN_SORT, (gfloat) action_value - 0.5, -1);
+}
+
+void
+e_action_combo_box_add_separator_after (EActionComboBox *combo_box,
+ gint action_value)
+{
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+
+ g_return_if_fail (E_ACTION_IS_COMBO_BOX (combo_box));
+
+ /* NULL actions are rendered as separators. */
+ model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo_box));
+ gtk_list_store_append (GTK_LIST_STORE (model), &iter);
+ gtk_list_store_set (
+ GTK_LIST_STORE (model), &iter, COLUMN_ACTION,
+ NULL, COLUMN_SORT, (gfloat) action_value + 0.5, -1);
+}
diff --git a/widgets/misc/e-action-combo-box.h b/widgets/misc/e-action-combo-box.h
new file mode 100644
index 0000000000..300338639a
--- /dev/null
+++ b/widgets/misc/e-action-combo-box.h
@@ -0,0 +1,85 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* e-action-combo-box.h
+ *
+ * Copyright (C) 2008 Novell, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * 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 Lesser 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.
+ */
+
+#ifndef E_ACTION_COMBO_BOX_H
+#define E_ACTION_COMBO_BOX_H
+
+/* This is a GtkComboBox that is driven by a group of GtkRadioActions.
+ * Just plug in a GtkRadioAction and the widget will handle the rest.
+ * (Based on GtkhtmlComboBox.) */
+
+#include <gtk/gtk.h>
+
+/* Standard GObject macros */
+#define E_TYPE_ACTION_COMBO_BOX \
+ (e_action_combo_box_get_type ())
+#define E_ACTION_COMBO_BOX(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_ACTION_COMBO_BOX, EActionComboBox))
+#define E_ACTION_COMBO_BOX_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_ACTION_COMBO_BOX, EActionComboBoxClass))
+#define E_ACTION_IS_COMBO_BOX(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_ACTION_COMBO_BOX))
+#define E_ACTION_IS_COMBO_BOX_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_ACTION_COMBO_BOX))
+#define E_ACTION_COMBO_BOX_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_ACTION_COMBO_BOX, EActionComboBoxClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EActionComboBox EActionComboBox;
+typedef struct _EActionComboBoxClass EActionComboBoxClass;
+typedef struct _EActionComboBoxPrivate EActionComboBoxPrivate;
+
+struct _EActionComboBox {
+ GtkComboBox parent;
+ EActionComboBoxPrivate *priv;
+};
+
+struct _EActionComboBoxClass {
+ GtkComboBoxClass parent_class;
+};
+
+GType e_action_combo_box_get_type (void);
+GtkWidget * e_action_combo_box_new (void);
+GtkWidget * e_action_combo_box_new_with_action
+ (GtkRadioAction *action);
+GtkRadioAction *e_action_combo_box_get_action (EActionComboBox *combo_box);
+void e_action_combo_box_set_action (EActionComboBox *combo_box,
+ GtkRadioAction *action);
+gint e_action_combo_box_get_current_value
+ (EActionComboBox *combo_box);
+void e_action_combo_box_set_current_value
+ (EActionComboBox *combo_box,
+ gint current_value);
+void e_action_combo_box_add_separator_before
+ (EActionComboBox *combo_box,
+ gint action_value);
+void e_action_combo_box_add_separator_after
+ (EActionComboBox *combo_box,
+ gint action_value);
+
+G_END_DECLS
+
+#endif /* E_ACTION_COMBO_BOX_H */
diff --git a/widgets/misc/e-activity-handler.c b/widgets/misc/e-activity-handler.c
deleted file mode 100644
index d397f142dd..0000000000
--- a/widgets/misc/e-activity-handler.c
+++ /dev/null
@@ -1,700 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) version 3.
- *
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- *
- * Authors:
- * Ettore Perazzoli <ettore@ximian.com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "e-activity-handler.h"
-
-#include <gtk/gtk.h>
-#include <glib/gi18n.h>
-#include <gdk-pixbuf/gdk-pixbuf.h>
-
-#include <misc/e-popup-menu.h>
-
-#define ICON_SIZE 16
-
-
-struct _ActivityInfo {
- gchar *component_id;
- gint error_type;
- guint id;
- gchar *information;
- gboolean cancellable;
- double progress;
- GtkWidget *menu;
- void (*cancel_func) (gpointer data);
- gpointer data;
- gpointer error;
- time_t error_time;
-};
-typedef struct _ActivityInfo ActivityInfo;
-
-struct _EActivityHandlerPrivate {
- guint next_activity_id;
- GList *activity_infos;
- GSList *task_bars;
- ELogger *logger;
- guint error_timer;
- guint error_flush_interval;
-
-};
-
-/* In the status bar, we show only errors and info. Errors are pictured as warnings. */
-const gchar *icon_data [] = {"dialog-warning", "dialog-information"};
-
-G_DEFINE_TYPE (EActivityHandler, e_activity_handler, G_TYPE_OBJECT)
-
-/* Utility functions. */
-
-static void handle_error (ETaskWidget *task);
-
-static guint
-get_new_activity_id (EActivityHandler *activity_handler)
-{
- EActivityHandlerPrivate *priv;
-
- priv = activity_handler->priv;
-
- return priv->next_activity_id ++;
-}
-
-static GList *
-lookup_activity (GList *list,
- guint activity_id,
- gint *order_number_return)
-{
- GList *p;
- gint 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;
-}
-
-
-/* ETaskWidget actions. */
-
-static gint
-task_widget_button_press_event_callback (GtkWidget *widget,
- GdkEventButton *button_event,
- gpointer data)
-{
- ActivityInfo *activity_info;
-
- activity_info = (ActivityInfo *) data;
-
- if (button_event->button == 3)
- return activity_info->cancellable;
-
- if (button_event->button != 1)
- return FALSE;
-
- return TRUE;
-}
-
-
-/* Creating and destroying ActivityInfos. */
-
-static ActivityInfo *
-activity_info_new (const gchar *component_id,
- guint id,
- const gchar *information,
- gboolean cancellable)
-{
- ActivityInfo *info;
-
- info = g_new (ActivityInfo, 1);
- info->component_id = g_strdup (component_id);
- info->id = id;
- info->information = g_strdup (information);
- info->cancellable = cancellable;
- info->progress = -1.0; /* (Unknown) */
- info->menu = NULL;
- info->error = NULL;
- info->cancel_func = NULL;
-
- return info;
-}
-
-static void
-activity_info_free (ActivityInfo *info)
-{
- g_free (info->component_id);
- g_free (info->information);
-
- if (info->menu != NULL)
- gtk_widget_destroy (info->menu);
-
- g_free (info);
-}
-
-static ETaskWidget *
-task_widget_new_from_activity_info (ActivityInfo *activity_info)
-{
- GtkWidget *widget;
- ETaskWidget *etw;
-
- widget = e_task_widget_new_with_cancel (
- activity_info->component_id,
- activity_info->information,
- activity_info->cancel_func,
- activity_info->data);
- etw = (ETaskWidget *) widget;
- etw->id = activity_info->id;
- gtk_widget_show (widget);
-
- g_signal_connect (widget, "button_press_event",
- G_CALLBACK (task_widget_button_press_event_callback),
- activity_info);
-
- 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) {
- ActivityInfo *info = p->data;
- ETaskWidget *task_widget = task_widget_new_from_activity_info (info);
- task_widget->id = info->id;
- e_task_bar_prepend_task (task_bar, task_widget);
- if (info->error) {
- /* Prepare to handle existing errors*/
- GtkWidget *tool;
- const gchar *stock;
-
- stock = info->error_type ? icon_data [1] : icon_data[0];
- tool = e_task_widget_update_image (task_widget, (gchar *)stock, info->information);
- g_object_set_data ((GObject *) task_widget, "tool", tool);
- g_object_set_data ((GObject *) task_widget, "error", info->error);
- g_object_set_data ((GObject *) task_widget, "activity-handler", activity_handler);
- g_object_set_data ((GObject *) task_widget, "activity", GINT_TO_POINTER(info->id));
- g_object_set_data ((GObject *) task_widget, "error-type", GINT_TO_POINTER(info->error_type));
- g_signal_connect_swapped (tool, "clicked", G_CALLBACK(handle_error), task_widget);
- }
- }
-}
-
-static void
-task_bar_destroy_notify (gpointer data,
- GObject *task_bar_instance)
-{
- EActivityHandler *activity_handler;
- EActivityHandlerPrivate *priv;
-
- activity_handler = E_ACTIVITY_HANDLER (data);
- priv = activity_handler->priv;
-
- priv->task_bars = g_slist_remove (priv->task_bars, task_bar_instance);
-}
-
-
-/* GObject methods. */
-
-static void
-impl_dispose (GObject *object)
-{
- EActivityHandler *handler;
- EActivityHandlerPrivate *priv;
- GList *p;
- GSList *sp;
-
- 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_list_free (priv->activity_infos);
- priv->activity_infos = NULL;
-
- for (sp = priv->task_bars; sp != NULL; sp = sp->next)
- g_object_weak_unref (G_OBJECT (sp->data), task_bar_destroy_notify, handler);
- priv->task_bars = NULL;
-
- (* G_OBJECT_CLASS (e_activity_handler_parent_class)->dispose) (object);
-}
-
-static void
-impl_finalize (GObject *object)
-{
- EActivityHandler *handler;
- EActivityHandlerPrivate *priv;
-
- handler = E_ACTIVITY_HANDLER (object);
- priv = handler->priv;
-
- g_free (priv);
-
- (* G_OBJECT_CLASS (e_activity_handler_parent_class)->finalize) (object);
-}
-
-static void
-e_activity_handler_class_init (EActivityHandlerClass *activity_handler_class)
-{
- GObjectClass *object_class = (GObjectClass *) activity_handler_class;
-
- object_class->dispose = impl_dispose;
- object_class->finalize = impl_finalize;
-}
-
-static void
-e_activity_handler_init (EActivityHandler *activity_handler)
-{
- EActivityHandlerPrivate *priv;
-
- priv = g_new (EActivityHandlerPrivate, 1);
- priv->next_activity_id = 1;
- priv->activity_infos = NULL;
- priv->task_bars = NULL;
- priv->logger = NULL;
- priv->error_timer = 0;
- priv->error_flush_interval = 0;
- activity_handler->priv = priv;
-}
-
-
-EActivityHandler *
-e_activity_handler_new (void)
-{
- return g_object_new (e_activity_handler_get_type (), NULL);
-}
-
-void
-e_activity_handler_set_error_flush_time (EActivityHandler *handler, gint time)
-{
- handler->priv->error_flush_interval = time;
-}
-void
-e_activity_handler_set_logger (EActivityHandler *handler, ELogger *logger)
-{
- handler->priv->logger = logger;
-}
-
-void
-e_activity_handler_set_message (EActivityHandler *activity_handler,
- const gchar *message)
-{
- EActivityHandlerPrivate *priv;
- GSList *i;
-
- priv = activity_handler->priv;
-
- for (i = priv->task_bars; i; i = i->next)
- e_task_bar_set_message (E_TASK_BAR (i->data), message);
-}
-
-void
-e_activity_handler_unset_message (EActivityHandler *activity_handler)
-{
- EActivityHandlerPrivate *priv;
- GSList *i;
-
- priv = activity_handler->priv;
-
- for (i = priv->task_bars; i; i = i->next)
- e_task_bar_unset_message (E_TASK_BAR (i->data));
-}
-
-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;
-
- g_object_weak_ref (G_OBJECT (task_bar), task_bar_destroy_notify, activity_handler);
-
- priv->task_bars = g_slist_prepend (priv->task_bars, task_bar);
-
- setup_task_bar (activity_handler, task_bar);
-}
-
-struct _cancel_wdata {
- EActivityHandler *handler;
- ActivityInfo *info;
- guint id;
- void (*cancel)(gpointer);
- gpointer data;
-};
-
-static void
-cancel_wrapper (gpointer pdata)
-{
- struct _cancel_wdata *data = (struct _cancel_wdata *) pdata;
- /* This can be invoked in two scenario. Either to cancel or to hide error */
- if (data->info->error) {
- /* Hide the error */
- EActivityHandler *handler = data->handler;
- ActivityInfo *info;
- gint order, len;
- GSList *sp;
- GList *p = lookup_activity (handler->priv->activity_infos, data->id, &order);
- e_logger_log (handler->priv->logger, E_LOG_ERROR, g_object_get_data (data->info->error, "primary"),
- g_object_get_data (data->info->error, "secondary"));
- gtk_widget_destroy (data->info->error);
- data->info->error = NULL;
- info = data->info;
- for (sp = handler->priv->task_bars; sp != NULL; sp = sp->next) {
- ETaskBar *task_bar;
-
- task_bar = E_TASK_BAR (sp->data);
- e_task_bar_remove_task_from_id (task_bar, info->id);
- }
- activity_info_free (info);
- len = g_list_length (handler->priv->activity_infos);
- handler->priv->activity_infos = g_list_remove_link (handler->priv->activity_infos, p);
- if (len == 1)
- handler->priv->activity_infos = NULL;
- } else {
- /* Cancel the operation */
- data->cancel (data->data);
- }
- /* No need to free the data. It will be freed as part of the task widget destroy */
-}
-
-/* CORBA methods. */
-guint e_activity_handler_cancelable_operation_started (EActivityHandler *activity_handler,
- const gchar *component_id,
- const gchar *information,
- gboolean cancellable,
- void (*cancel_func)(gpointer),
- gpointer user_data)
-{
- EActivityHandlerPrivate *priv;
- ActivityInfo *activity_info;
- guint activity_id;
- GSList *p;
- struct _cancel_wdata *data;
- gboolean bfree = FALSE;
- priv = activity_handler->priv;
-
- activity_id = get_new_activity_id (activity_handler);
- activity_info = activity_info_new (component_id, activity_id, information, cancellable);
-
- data = g_new(struct _cancel_wdata, 1);
- data->handler = activity_handler;
- data->id = activity_id;
- data->info = activity_info;
- data->cancel = cancel_func;
- data->data = user_data;
-
- activity_info->cancel_func = cancel_wrapper;
- activity_info->data = data;
- for (p = priv->task_bars; p != NULL; p = p->next) {
- ETaskWidget *tw = task_widget_new_from_activity_info (activity_info);
- tw->id = activity_id;
- if (!bfree) {
- /* The data will be freed part of the widget destroy */
- g_object_set_data_full ((GObject *) tw, "free-data", data, g_free);
- bfree = TRUE;
- }
- e_task_bar_prepend_task (E_TASK_BAR (p->data), tw);
- }
-
- priv->activity_infos = g_list_prepend (priv->activity_infos, activity_info);
-
- return activity_id;
-
-}
-
-guint
-e_activity_handler_operation_started (EActivityHandler *activity_handler,
- const gchar *component_id,
- const gchar *information,
- gboolean cancellable)
-{
- EActivityHandlerPrivate *priv;
- ActivityInfo *activity_info;
- guint activity_id;
- GSList *p;
-
- priv = activity_handler->priv;
-
- activity_id = get_new_activity_id (activity_handler);
-
- activity_info = activity_info_new (component_id, activity_id, information, cancellable);
-
- for (p = priv->task_bars; p != NULL; p = p->next) {
- ETaskWidget *tw = task_widget_new_from_activity_info (activity_info);
- tw->id = activity_id;
- e_task_bar_prepend_task (E_TASK_BAR (p->data), tw);
- }
-
- priv->activity_infos = g_list_prepend (priv->activity_infos, activity_info);
-
- return activity_id;
-}
-
-static void
-handle_error (ETaskWidget *task)
-{
- GtkWidget *tool, *error;
- EActivityHandler *activity_handler;
- guint id;
- gint error_type = GPOINTER_TO_INT((g_object_get_data ((GObject *) task, "error-type")));
- tool = g_object_get_data ((GObject *) task, "tool");
- error = g_object_get_data ((GObject *) task, "error");
- activity_handler = g_object_get_data ((GObject *) task, "activity-handler");
- id = GPOINTER_TO_UINT (g_object_get_data ((GObject *) task, "activity"));
- e_activity_handler_operation_finished (activity_handler, id);
- gtk_widget_show (error);
- e_logger_log (activity_handler->priv->logger, error_type,
- g_object_get_data ((GObject *) error, "primary"),
- g_object_get_data ((GObject *) error, "secondary"));
-}
-
-static gboolean
-error_cleanup (EActivityHandler *activity_handler)
-{
- EActivityHandlerPrivate *priv = activity_handler->priv;
- GList *p, *node;
- GSList *sp;
- gint i;
- time_t now = time (NULL);
- gboolean berror = FALSE;
-
- for (p = priv->activity_infos, i = 0; p != NULL; i++) {
- ActivityInfo *info;
-
- info = (ActivityInfo *) p->data;
- if (info->error)
- berror = TRUE;
- if (info->error && info->error_time && (now - info->error_time) > 5 ) {
- /* Error older than wanted time. So cleanup */
- e_logger_log (priv->logger, info->error_type, g_object_get_data (info->error, "primary"),
- g_object_get_data (info->error, "secondary"));
-
- if (GTK_IS_DIALOG (info->error))
- gtk_dialog_response (GTK_DIALOG (info->error), GTK_RESPONSE_CLOSE);
- else
- gtk_widget_destroy (info->error);
-
- node = p;
- p = p->next;
-
- 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_from_id (task_bar, info->id);
- }
- activity_info_free (info);
- priv->activity_infos = g_list_remove_link (priv->activity_infos, node);
-
- } else
- p = p->next;
- }
- if (!berror)
- priv->error_timer = 0;
- return berror;
-}
-
-guint
-e_activity_handler_make_error (EActivityHandler *activity_handler,
- const gchar *component_id,
- gint error_type,
- GtkWidget *error)
-{
- EActivityHandlerPrivate *priv;
- ActivityInfo *activity_info;
- guint activity_id;
- GSList *p;
- gchar *information = g_object_get_data((GObject *) error, "primary");
- const gchar *img;
-
- priv = activity_handler->priv;
- activity_id = get_new_activity_id (activity_handler);
-
- activity_info = activity_info_new (component_id, activity_id, information, TRUE);
- activity_info->error = error;
- activity_info->error_time = time (NULL);
- activity_info->error_type = error_type;
-
- img = error_type ? icon_data[1] : icon_data[0];
- for (p = priv->task_bars; p != NULL; p = p->next) {
- ETaskBar *task_bar;
- ETaskWidget *task_widget;
- GtkWidget *tool;
-
- task_bar = E_TASK_BAR (p->data);
- task_widget = task_widget_new_from_activity_info (activity_info);
- task_widget->id = activity_id;
- e_task_bar_prepend_task (E_TASK_BAR (p->data), task_widget);
-
- tool = e_task_widget_update_image (task_widget, (gchar *)img, information);
- g_object_set_data ((GObject *) task_widget, "tool", tool);
- g_object_set_data ((GObject *) task_widget, "error", error);
- g_object_set_data ((GObject *) task_widget, "activity-handler", activity_handler);
- g_object_set_data ((GObject *) task_widget, "activity", GINT_TO_POINTER(activity_id));
- g_object_set_data ((GObject *) task_widget, "error-type", GINT_TO_POINTER(error_type));
- g_signal_connect_swapped (tool, "clicked", G_CALLBACK(handle_error), task_widget);
- }
-
- priv->activity_infos = g_list_prepend (priv->activity_infos, activity_info);
-
- if (!activity_handler->priv->error_timer)
- activity_handler->priv->error_timer = g_timeout_add (activity_handler->priv->error_flush_interval, (GSourceFunc)error_cleanup, activity_handler);
-
- return activity_id;
-}
-
-void
-e_activity_handler_operation_set_error(EActivityHandler *activity_handler,
- guint activity_id,
- GtkWidget *error)
-{
- EActivityHandlerPrivate *priv = activity_handler->priv;
- ActivityInfo *activity_info;
- GList *p;
- GSList *sp;
- gint order_number;
-
- p = lookup_activity (priv->activity_infos, activity_id, &order_number);
- if (p == NULL) {
- g_warning ("EActivityHandler: unknown operation %d", activity_id);
- return;
- }
-
- activity_info = (ActivityInfo *) p->data;
- activity_info->error = error;
- activity_info->error_time = time (NULL);
- activity_info->error_type = E_LOG_ERROR;
- g_free (activity_info->information);
- activity_info->information = g_strdup (g_object_get_data ((GObject *) error, "primary"));
- for (sp = priv->task_bars; sp != NULL; sp = sp->next) {
- ETaskBar *task_bar;
- ETaskWidget *task_widget;
- GtkWidget *tool;
-
- task_bar = E_TASK_BAR (sp->data);
- task_widget = e_task_bar_get_task_widget_from_id (task_bar, activity_info->id);
- if (!task_widget)
- continue;
-
- tool = e_task_widget_update_image (task_widget, (gchar *)icon_data[0], g_object_get_data ((GObject *) error, "primary"));
- g_object_set_data ((GObject *) task_widget, "tool", tool);
- g_object_set_data ((GObject *) task_widget, "error", error);
- g_object_set_data ((GObject *) task_widget, "activity-handler", activity_handler);
- g_object_set_data ((GObject *) task_widget, "activity", GINT_TO_POINTER(activity_id));
- g_object_set_data ((GObject *) task_widget, "error-type", GINT_TO_POINTER(E_LOG_ERROR));
- g_signal_connect_swapped (tool, "clicked", G_CALLBACK(handle_error), task_widget);
- }
-
- if (!activity_handler->priv->error_timer)
- activity_handler->priv->error_timer = g_timeout_add (activity_handler->priv->error_flush_interval, (GSourceFunc) error_cleanup, activity_handler);
-}
-
-void
-e_activity_handler_operation_progressing (EActivityHandler *activity_handler,
- guint activity_id,
- const gchar *information,
- double progress)
-{
- EActivityHandlerPrivate *priv = activity_handler->priv;
- ActivityInfo *activity_info;
- GList *p;
- GSList *sp;
- gint order_number;
-
- p = lookup_activity (priv->activity_infos, activity_id, &order_number);
- if (p == NULL) {
- g_warning ("EActivityHandler: unknown operation %d", activity_id);
- return;
- }
-
- activity_info = (ActivityInfo *) p->data;
-
- g_free (activity_info->information);
- activity_info->information = g_strdup (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_from_id (task_bar, activity_info->id);
- if (!task_widget)
- continue;
-
- e_task_widget_update (task_widget, information, progress);
- }
-}
-
-void
-e_activity_handler_operation_finished (EActivityHandler *activity_handler,
- guint activity_id)
-{
- EActivityHandlerPrivate *priv = activity_handler->priv;
- GList *p;
- GSList *sp;
- gint order_number;
-
- p = lookup_activity (priv->activity_infos, activity_id, &order_number);
- if (p == NULL) {
- g_warning ("e_activity_handler_operation_finished: Unknown activity %d\n", activity_id);
- return;
- }
-
- 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_from_id (task_bar, activity_id);
- }
-}
-
diff --git a/widgets/misc/e-activity-handler.h b/widgets/misc/e-activity-handler.h
deleted file mode 100644
index 880972867e..0000000000
--- a/widgets/misc/e-activity-handler.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) version 3.
- *
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- *
- * Authors:
- * Ettore Perazzoli <ettore@ximian.com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-#ifndef _E_ACTIVITY_HANDLER_H_
-#define _E_ACTIVITY_HANDLER_H_
-
-#include "e-task-bar.h"
-#include "e-util/e-logger.h"
-#include <glib-object.h>
-
-G_BEGIN_DECLS
-
-#define E_TYPE_ACTIVITY_HANDLER (e_activity_handler_get_type ())
-#define E_ACTIVITY_HANDLER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_ACTIVITY_HANDLER, EActivityHandler))
-#define E_ACTIVITY_HANDLER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E_TYPE_ACTIVITY_HANDLER, EActivityHandlerClass))
-#define E_IS_ACTIVITY_HANDLER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_TYPE_ACTIVITY_HANDLER))
-#define E_IS_ACTIVITY_HANDLER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), E_TYPE_ACTIVITY_HANDLER))
-
-
-typedef struct _EActivityHandler EActivityHandler;
-typedef struct _EActivityHandlerPrivate EActivityHandlerPrivate;
-typedef struct _EActivityHandlerClass EActivityHandlerClass;
-
-#define EAH_ICON_INFO "stock_dialog-info"
-#define EAH_ICON_ERROR "stock_dialog-warning"
-
-struct _EActivityHandler {
- GObject parent;
-
- EActivityHandlerPrivate *priv;
-};
-
-struct _EActivityHandlerClass {
- GObjectClass parent_class;
-};
-
-
-GType e_activity_handler_get_type (void);
-
-EActivityHandler *e_activity_handler_new (void);
-
-void e_activity_handler_attach_task_bar (EActivityHandler *activity_hanlder,
- ETaskBar *task_bar);
-
-void e_activity_handler_set_message (EActivityHandler *activity_handler,
- const gchar *message);
-
-void e_activity_handler_unset_message (EActivityHandler *activity_handler);
-
-guint e_activity_handler_operation_started (EActivityHandler *activity_handler,
- const gchar *component_id,
- const gchar *information,
- gboolean cancellable);
-guint e_activity_handler_cancelable_operation_started (EActivityHandler *activity_handler,
- const gchar *component_id,
- const gchar *information,
- gboolean cancellable,
- void (*cancel_func)(gpointer),
- gpointer user_data);
-
-void e_activity_handler_operation_progressing (EActivityHandler *activity_handler,
- guint activity_id,
- const gchar *information,
- double progress);
-
-void e_activity_handler_operation_finished (EActivityHandler *activity_handler,
- guint activity_id);
-
-void e_activity_handler_set_logger (EActivityHandler *handler, ELogger *logger);
-guint e_activity_handler_make_error (EActivityHandler *activity_handler,
- const gchar *component_id,
- gint error_type,
- GtkWidget *error);
-void
-e_activity_handler_operation_set_error (EActivityHandler *activity_handler,
- guint activity_id,
- GtkWidget *error);
-
-void
-e_activity_handler_set_error_flush_time (EActivityHandler *handler, gint time);
-
-G_END_DECLS
-
-#endif /* _E_ACTIVITY_HANDLER_H_ */
diff --git a/widgets/misc/e-activity-proxy.c b/widgets/misc/e-activity-proxy.c
new file mode 100644
index 0000000000..b045394442
--- /dev/null
+++ b/widgets/misc/e-activity-proxy.c
@@ -0,0 +1,345 @@
+/*
+ * e-activity-proxy.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#include "e-activity-proxy.h"
+
+#include <glib/gi18n.h>
+#include <e-spinner.h>
+
+#define E_ACTIVITY_PROXY_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), E_TYPE_ACTIVITY_PROXY, EActivityProxyPrivate))
+
+struct _EActivityProxyPrivate {
+ EActivity *activity;
+ GtkWidget *button;
+ GtkWidget *image;
+ GtkWidget *label;
+ GtkWidget *cancel;
+ GtkWidget *spinner;
+};
+
+enum {
+ PROP_0,
+ PROP_ACTIVITY
+};
+
+static gpointer parent_class;
+
+static void
+activity_proxy_update (EActivityProxy *proxy)
+{
+ EActivity *activity = proxy->priv->activity;
+ const gchar *icon_name;
+ gboolean allow_cancel;
+ gboolean cancelled;
+ gboolean clickable;
+ gboolean completed;
+ gboolean sensitive;
+ gchar *description;
+
+ allow_cancel = e_activity_get_allow_cancel (activity);
+ cancelled = e_activity_is_cancelled (activity);
+ clickable = e_activity_get_clickable (activity);
+ completed = e_activity_is_completed (activity);
+ icon_name = e_activity_get_icon_name (activity);
+
+ description = e_activity_describe (activity);
+ gtk_widget_set_tooltip_text (GTK_WIDGET (proxy), description);
+ gtk_label_set_text (GTK_LABEL (proxy->priv->label), description);
+ g_free (description);
+
+ /* Note, an activity requires an icon name in order to
+ * be clickable. We don't support spinner buttons. */
+ if (icon_name != NULL) {
+ gtk_image_set_from_icon_name (
+ GTK_IMAGE (proxy->priv->image),
+ icon_name, GTK_ICON_SIZE_MENU);
+ gtk_button_set_image (
+ GTK_BUTTON (proxy->priv->button),
+ gtk_image_new_from_icon_name (
+ icon_name, GTK_ICON_SIZE_MENU));
+ gtk_widget_hide (proxy->priv->spinner);
+ if (clickable) {
+ gtk_widget_show (proxy->priv->button);
+ gtk_widget_hide (proxy->priv->image);
+ } else {
+ gtk_widget_hide (proxy->priv->button);
+ gtk_widget_show (proxy->priv->image);
+ }
+ } else {
+ gtk_widget_show (proxy->priv->spinner);
+ gtk_widget_hide (proxy->priv->button);
+ gtk_widget_hide (proxy->priv->image);
+ }
+
+ if (allow_cancel)
+ gtk_widget_show (proxy->priv->cancel);
+ else
+ gtk_widget_hide (proxy->priv->cancel);
+
+ sensitive = !(cancelled || completed);
+ gtk_widget_set_sensitive (proxy->priv->cancel, sensitive);
+}
+
+static void
+activity_proxy_set_activity (EActivityProxy *proxy,
+ EActivity *activity)
+{
+ g_return_if_fail (proxy->priv->activity == NULL);
+
+ proxy->priv->activity = g_object_ref (activity);
+}
+
+static void
+activity_proxy_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_ACTIVITY:
+ activity_proxy_set_activity (
+ E_ACTIVITY_PROXY (object),
+ g_value_get_object (value));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+activity_proxy_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_ACTIVITY:
+ g_value_set_object (
+ value, e_activity_proxy_get_activity (
+ E_ACTIVITY_PROXY (object)));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+activity_proxy_dispose (GObject *object)
+{
+ EActivityProxyPrivate *priv;
+
+ priv = E_ACTIVITY_PROXY_GET_PRIVATE (object);
+
+ if (priv->activity != NULL) {
+ g_signal_handlers_disconnect_matched (
+ priv->activity, G_SIGNAL_MATCH_FUNC, 0, 0,
+ NULL, activity_proxy_update, NULL);
+ g_object_unref (priv->activity);
+ priv->activity = NULL;
+ }
+
+ if (priv->button != NULL) {
+ g_object_unref (priv->button);
+ priv->button = NULL;
+ }
+
+ if (priv->image != NULL) {
+ g_object_unref (priv->image);
+ priv->image = NULL;
+ }
+
+ if (priv->label != NULL) {
+ g_object_unref (priv->label);
+ priv->label = NULL;
+ }
+
+ if (priv->cancel != NULL) {
+ g_object_unref (priv->cancel);
+ priv->cancel = NULL;
+ }
+
+ if (priv->spinner != NULL) {
+ g_object_unref (priv->spinner);
+ priv->spinner = NULL;
+ }
+
+ /* Chain up to parent's dispose() method. */
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+activity_proxy_constructed (GObject *object)
+{
+ EActivityProxy *proxy;
+
+ proxy = E_ACTIVITY_PROXY (object);
+
+ g_signal_connect_swapped (
+ proxy->priv->button, "clicked",
+ G_CALLBACK (e_activity_clicked), proxy->priv->activity);
+
+ g_signal_connect_swapped (
+ proxy->priv->cancel, "clicked",
+ G_CALLBACK (e_activity_cancel), proxy->priv->activity);
+
+ g_signal_connect_swapped (
+ proxy->priv->activity, "cancelled",
+ G_CALLBACK (activity_proxy_update), proxy);
+
+ g_signal_connect_swapped (
+ proxy->priv->activity, "completed",
+ G_CALLBACK (activity_proxy_update), proxy);
+
+ g_signal_connect_swapped (
+ proxy->priv->activity, "notify",
+ G_CALLBACK (activity_proxy_update), proxy);
+
+ activity_proxy_update (proxy);
+}
+
+static void
+activity_proxy_class_init (EActivityProxyClass *class)
+{
+ GObjectClass *object_class;
+
+ parent_class = g_type_class_peek_parent (class);
+ g_type_class_add_private (class, sizeof (EActivityProxyPrivate));
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->set_property = activity_proxy_set_property;
+ object_class->get_property = activity_proxy_get_property;
+ object_class->dispose = activity_proxy_dispose;
+ object_class->constructed = activity_proxy_constructed;
+
+ g_object_class_install_property (
+ object_class,
+ PROP_ACTIVITY,
+ g_param_spec_object (
+ "activity",
+ NULL,
+ NULL,
+ E_TYPE_ACTIVITY,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY));
+}
+
+static void
+activity_proxy_init (EActivityProxy *proxy)
+{
+ GtkWidget *container;
+ GtkWidget *widget;
+
+ proxy->priv = E_ACTIVITY_PROXY_GET_PRIVATE (proxy);
+
+ container = GTK_WIDGET (proxy);
+
+ widget = gtk_frame_new (NULL);
+ gtk_frame_set_shadow_type (GTK_FRAME (widget), GTK_SHADOW_IN);
+ gtk_container_add (GTK_CONTAINER (container), widget);
+ gtk_widget_show (widget);
+
+ container = widget;
+
+ widget = gtk_hbox_new (FALSE, 3);
+ gtk_container_add (GTK_CONTAINER (container), widget);
+ gtk_widget_show (widget);
+
+ container = widget;
+
+ widget = gtk_image_new ();
+ gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
+ proxy->priv->image = g_object_ref (widget);
+ gtk_widget_hide (widget);
+
+ widget = gtk_button_new ();
+ gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
+ proxy->priv->button = g_object_ref (widget);
+ gtk_widget_hide (widget);
+
+ /* XXX What's the rationale for killing the old spinner API? */
+ widget = e_spinner_new_spinning_small_shown ();
+ gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
+ proxy->priv->spinner = g_object_ref (widget);
+ gtk_widget_show (widget);
+
+ widget = gtk_label_new (NULL);
+ gtk_label_set_ellipsize (GTK_LABEL (widget), PANGO_ELLIPSIZE_END);
+ gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
+ gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
+ proxy->priv->label = g_object_ref (widget);
+ gtk_widget_show (widget);
+
+ widget = gtk_button_new ();
+ gtk_button_set_image (
+ GTK_BUTTON (widget), gtk_image_new_from_stock (
+ GTK_STOCK_STOP, GTK_ICON_SIZE_MENU));
+ gtk_button_set_relief (GTK_BUTTON (widget), GTK_RELIEF_NONE);
+ gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
+ gtk_widget_set_tooltip_text (widget, _("Cancel"));
+ proxy->priv->cancel = g_object_ref (widget);
+ gtk_widget_show (widget);
+}
+
+GType
+e_activity_proxy_get_type (void)
+{
+ static GType type = 0;
+
+ if (G_UNLIKELY (type == 0)) {
+ static const GTypeInfo type_info = {
+ sizeof (EActivityProxyClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) activity_proxy_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+ sizeof (EActivityProxy),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) activity_proxy_init,
+ NULL /* value_table */
+ };
+
+ type = g_type_register_static (
+ GTK_TYPE_EVENT_BOX, "EActivityProxy", &type_info, 0);
+ }
+
+ return type;
+}
+
+GtkWidget *
+e_activity_proxy_new (EActivity *activity)
+{
+ g_return_val_if_fail (E_IS_ACTIVITY (activity), NULL);
+
+ return g_object_new (
+ E_TYPE_ACTIVITY_PROXY,
+ "activity", activity, NULL);
+}
+
+EActivity *
+e_activity_proxy_get_activity (EActivityProxy *proxy)
+{
+ g_return_val_if_fail (E_IS_ACTIVITY_PROXY (proxy), NULL);
+
+ return proxy->priv->activity;
+}
diff --git a/widgets/misc/e-activity-proxy.h b/widgets/misc/e-activity-proxy.h
new file mode 100644
index 0000000000..714dc63e0f
--- /dev/null
+++ b/widgets/misc/e-activity-proxy.h
@@ -0,0 +1,68 @@
+/*
+ * e-activity-proxy.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef E_ACTIVITY_PROXY_H
+#define E_ACTIVITY_PROXY_H
+
+#include <gtk/gtk.h>
+#include <e-activity.h>
+
+/* Standard GObject macros */
+#define E_TYPE_ACTIVITY_PROXY \
+ (e_activity_proxy_get_type ())
+#define E_ACTIVITY_PROXY(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_ACTIVITY_PROXY, EActivityProxy))
+#define E_ACTIVITY_PROXY_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_ACTIVITY_PROXY, EActivityProxyClass))
+#define E_IS_ACTIVITY_PROXY(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_ACTIVITY_PROXY))
+#define E_IS_ACTIVITY_PROXY_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_ACTIVITY_PROXY))
+#define E_ACTIVITY_PROXY_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_ACTIVITY_PROXY, EActivityProxyClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EActivityProxy EActivityProxy;
+typedef struct _EActivityProxyClass EActivityProxyClass;
+typedef struct _EActivityProxyPrivate EActivityProxyPrivate;
+
+struct _EActivityProxy {
+ GtkEventBox parent;
+ EActivityProxyPrivate *priv;
+};
+
+struct _EActivityProxyClass {
+ GtkEventBoxClass parent_class;
+};
+
+GType e_activity_proxy_get_type (void);
+GtkWidget * e_activity_proxy_new (EActivity *activity);
+EActivity * e_activity_proxy_get_activity (EActivityProxy *proxy);
+
+G_END_DECLS
+
+#endif /* E_ACTIVITY_PROXY_H */
diff --git a/widgets/misc/e-activity.c b/widgets/misc/e-activity.c
new file mode 100644
index 0000000000..ac9a3d7e8a
--- /dev/null
+++ b/widgets/misc/e-activity.c
@@ -0,0 +1,764 @@
+/*
+ * e-activity.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#include "e-activity.h"
+
+#include <stdarg.h>
+#include <glib/gi18n.h>
+
+#include "e-util/e-util.h"
+
+#define E_ACTIVITY_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), E_TYPE_ACTIVITY, EActivityPrivate))
+
+struct _EActivityPrivate {
+ gchar *icon_name;
+ gchar *primary_text;
+ gchar *secondary_text;
+ gdouble percent;
+ guint idle_id;
+ GError *error;
+
+ guint allow_cancel : 1;
+ guint blocking : 1;
+ guint cancelled : 1;
+ guint clickable : 1;
+ guint completed : 1;
+};
+
+enum {
+ PROP_0,
+ PROP_ALLOW_CANCEL,
+ PROP_BLOCKING,
+ PROP_CLICKABLE,
+ PROP_ICON_NAME,
+ PROP_PERCENT,
+ PROP_PRIMARY_TEXT,
+ PROP_SECONDARY_TEXT
+};
+
+enum {
+ CANCELLED,
+ CLICKED,
+ COMPLETED,
+ DESCRIBE,
+ LAST_SIGNAL
+};
+
+static gpointer parent_class;
+static gulong signals[LAST_SIGNAL];
+
+static gboolean
+activity_idle_cancel_cb (EActivity *activity)
+{
+ activity->priv->idle_id = 0;
+ e_activity_cancel (activity);
+ g_object_unref (activity);
+
+ return FALSE;
+}
+
+static gboolean
+activity_idle_complete_cb (EActivity *activity)
+{
+ activity->priv->idle_id = 0;
+ e_activity_complete (activity);
+ g_object_unref (activity);
+
+ return FALSE;
+}
+
+static gboolean
+activity_describe_accumulator (GSignalInvocationHint *ihint,
+ GValue *return_accu,
+ const GValue *handler_return,
+ gpointer accu_data)
+{
+ const gchar *string;
+
+ string = g_value_get_string (handler_return);
+ g_value_set_string (return_accu, string);
+
+ return (string == NULL);
+}
+
+static void
+activity_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_ALLOW_CANCEL:
+ e_activity_set_allow_cancel (
+ E_ACTIVITY (object),
+ g_value_get_boolean (value));
+ return;
+
+ case PROP_BLOCKING:
+ e_activity_set_blocking (
+ E_ACTIVITY (object),
+ g_value_get_boolean (value));
+ return;
+
+ case PROP_CLICKABLE:
+ e_activity_set_clickable (
+ E_ACTIVITY (object),
+ g_value_get_boolean (value));
+ return;
+
+ case PROP_ICON_NAME:
+ e_activity_set_icon_name (
+ E_ACTIVITY (object),
+ g_value_get_string (value));
+ return;
+
+ case PROP_PERCENT:
+ e_activity_set_percent (
+ E_ACTIVITY (object),
+ g_value_get_double (value));
+ return;
+
+ case PROP_PRIMARY_TEXT:
+ e_activity_set_primary_text (
+ E_ACTIVITY (object),
+ g_value_get_string (value));
+ return;
+
+ case PROP_SECONDARY_TEXT:
+ e_activity_set_secondary_text (
+ E_ACTIVITY (object),
+ g_value_get_string (value));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+activity_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_ALLOW_CANCEL:
+ g_value_set_boolean (
+ value, e_activity_get_allow_cancel (
+ E_ACTIVITY (object)));
+ return;
+
+ case PROP_BLOCKING:
+ g_value_set_boolean (
+ value, e_activity_get_blocking (
+ E_ACTIVITY (object)));
+ return;
+
+ case PROP_CLICKABLE:
+ g_value_set_boolean (
+ value, e_activity_get_clickable (
+ E_ACTIVITY (object)));
+ return;
+
+ case PROP_ICON_NAME:
+ g_value_set_string (
+ value, e_activity_get_icon_name (
+ E_ACTIVITY (object)));
+ return;
+
+ case PROP_PERCENT:
+ g_value_set_double (
+ value, e_activity_get_percent (
+ E_ACTIVITY (object)));
+ return;
+
+ case PROP_PRIMARY_TEXT:
+ g_value_set_string (
+ value, e_activity_get_primary_text (
+ E_ACTIVITY (object)));
+ return;
+
+ case PROP_SECONDARY_TEXT:
+ g_value_set_string (
+ value, e_activity_get_secondary_text (
+ E_ACTIVITY (object)));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+activity_finalize (GObject *object)
+{
+ EActivityPrivate *priv;
+
+ priv = E_ACTIVITY_GET_PRIVATE (object);
+
+ g_free (priv->icon_name);
+ g_free (priv->primary_text);
+ g_free (priv->secondary_text);
+
+ if (priv->idle_id > 0)
+ g_source_remove (priv->idle_id);
+
+ if (priv->error != NULL)
+ g_error_free (priv->error);
+
+ /* Chain up to parent's finalize() method. */
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+activity_cancelled (EActivity *activity)
+{
+ activity->priv->cancelled = TRUE;
+
+ if (activity->priv->idle_id > 0) {
+ g_source_remove (activity->priv->idle_id);
+ activity->priv->idle_id = 0;
+ }
+}
+
+static void
+activity_completed (EActivity *activity)
+{
+ activity->priv->completed = TRUE;
+
+ if (activity->priv->idle_id > 0) {
+ g_source_remove (activity->priv->idle_id);
+ activity->priv->idle_id = 0;
+ }
+}
+
+static void
+activity_clicked (EActivity *activity)
+{
+ /* Allow subclasses to safely chain up. */
+}
+
+static gchar *
+activity_describe (EActivity *activity)
+{
+ GString *string;
+ const gchar *text;
+ gboolean cancelled;
+ gboolean completed;
+ gdouble percent;
+
+ string = g_string_sized_new (256);
+ text = e_activity_get_primary_text (activity);
+ cancelled = e_activity_is_cancelled (activity);
+ completed = e_activity_is_completed (activity);
+ percent = e_activity_get_percent (activity);
+
+ if (cancelled) {
+ /* Translators: This is a cancelled activity. */
+ g_string_printf (string, _("%s (cancelled)"), text);
+ } else if (completed) {
+ /* Translators: This is a completed activity. */
+ g_string_printf (string, _("%s (completed)"), text);
+ } else if (percent < 0.0) {
+ /* Translators: This is an activity whose percent
+ * complete is unknown. */
+ g_string_printf (string, _("%s..."), text);
+ } else {
+ /* Translators: This is an activity whose percent
+ * complete is known. */
+ g_string_printf (
+ string, _("%s (%d%% complete)"), text,
+ (gint) (percent * 100.0 + 0.5));
+ }
+
+ return g_string_free (string, FALSE);
+}
+
+static void
+activity_class_init (EActivityClass *class)
+{
+ GObjectClass *object_class;
+
+ parent_class = g_type_class_peek_parent (class);
+ g_type_class_add_private (class, sizeof (EActivityPrivate));
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->set_property = activity_set_property;
+ object_class->get_property = activity_get_property;
+ object_class->finalize = activity_finalize;
+
+ class->cancelled = activity_cancelled;
+ class->completed = activity_completed;
+ class->clicked = activity_clicked;
+ class->describe = activity_describe;
+
+ g_object_class_install_property (
+ object_class,
+ PROP_ALLOW_CANCEL,
+ g_param_spec_boolean (
+ "allow-cancel",
+ NULL,
+ NULL,
+ FALSE,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_BLOCKING,
+ g_param_spec_boolean (
+ "blocking",
+ NULL,
+ NULL,
+ TRUE,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_CLICKABLE,
+ g_param_spec_boolean (
+ "clickable",
+ NULL,
+ NULL,
+ FALSE,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_ICON_NAME,
+ g_param_spec_string (
+ "icon-name",
+ NULL,
+ NULL,
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_PERCENT,
+ g_param_spec_double (
+ "percent",
+ NULL,
+ NULL,
+ -G_MAXDOUBLE,
+ G_MAXDOUBLE,
+ -1.0,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_PRIMARY_TEXT,
+ g_param_spec_string (
+ "primary-text",
+ NULL,
+ NULL,
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_SECONDARY_TEXT,
+ g_param_spec_string (
+ "secondary-text",
+ NULL,
+ NULL,
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT));
+
+ signals[CANCELLED] = g_signal_new (
+ "cancelled",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (EActivityClass, cancelled),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ signals[CLICKED] = g_signal_new (
+ "clicked",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (EActivityClass, clicked),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ signals[COMPLETED] = g_signal_new (
+ "completed",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (EActivityClass, completed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ signals[DESCRIBE] = g_signal_new (
+ "describe",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (EActivityClass, describe),
+ activity_describe_accumulator, NULL,
+ e_marshal_STRING__VOID,
+ G_TYPE_STRING, 0);
+}
+
+static void
+activity_init (EActivity *activity)
+{
+ activity->priv = E_ACTIVITY_GET_PRIVATE (activity);
+}
+
+GType
+e_activity_get_type (void)
+{
+ static GType type = 0;
+
+ if (G_UNLIKELY (type == 0)) {
+ static const GTypeInfo type_info = {
+ sizeof (EActivityClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) activity_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+ sizeof (EActivity),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) activity_init,
+ NULL /* value_table */
+ };
+
+ type = g_type_register_static (
+ G_TYPE_OBJECT, "EActivity", &type_info, 0);
+ }
+
+ return type;
+}
+
+EActivity *
+e_activity_new (const gchar *primary_text)
+{
+ return g_object_new (
+ E_TYPE_ACTIVITY,
+ "primary-text", primary_text, NULL);
+}
+
+EActivity *
+e_activity_newv (const gchar *format, ...)
+{
+ EActivity *activity;
+ gchar *primary_text;
+ va_list args;
+
+ va_start (args, format);
+ primary_text = g_strdup_vprintf (format, args);
+ activity = e_activity_new (primary_text);
+ g_free (primary_text);
+ va_end (args);
+
+ return activity;
+}
+
+void
+e_activity_cancel (EActivity *activity)
+{
+ g_return_if_fail (E_IS_ACTIVITY (activity));
+
+ if (!activity->priv->allow_cancel)
+ return;
+
+ if (activity->priv->cancelled)
+ return;
+
+ if (activity->priv->completed)
+ return;
+
+ g_signal_emit (activity, signals[CANCELLED], 0);
+}
+
+void
+e_activity_cancel_in_idle (EActivity *activity)
+{
+ guint old_idle_id;
+
+ g_return_if_fail (E_IS_ACTIVITY (activity));
+
+ /* Be careful not to finalize the activity. Decrement the
+ * reference count only after incrementing it, in case this
+ * is the last reference. */
+
+ old_idle_id = activity->priv->idle_id;
+
+ activity->priv->idle_id = g_idle_add (
+ (GSourceFunc) activity_idle_cancel_cb,
+ g_object_ref (activity));
+
+ if (old_idle_id > 0) {
+ g_source_remove (old_idle_id);
+ g_object_unref (activity);
+ }
+}
+
+void
+e_activity_complete (EActivity *activity)
+{
+ g_return_if_fail (E_IS_ACTIVITY (activity));
+
+ if (activity->priv->cancelled)
+ return;
+
+ if (activity->priv->completed)
+ return;
+
+ g_signal_emit (activity, signals[COMPLETED], 0);
+}
+
+void
+e_activity_complete_in_idle (EActivity *activity)
+{
+ guint old_idle_id;
+
+ g_return_if_fail (E_IS_ACTIVITY (activity));
+
+ /* Be careful not to finalize the activity. Decrement the
+ * reference count only after incrementing it, in case this
+ * is the last reference. */
+
+ old_idle_id = activity->priv->idle_id;
+
+ activity->priv->idle_id = g_idle_add (
+ (GSourceFunc) activity_idle_complete_cb,
+ g_object_ref (activity));
+
+ if (old_idle_id > 0) {
+ g_source_remove (old_idle_id);
+ g_object_unref (activity);
+ }
+}
+
+void
+e_activity_clicked (EActivity *activity)
+{
+ g_return_if_fail (E_IS_ACTIVITY (activity));
+
+ g_signal_emit (activity, signals[CLICKED], 0);
+}
+
+gchar *
+e_activity_describe (EActivity *activity)
+{
+ EActivityClass *class;
+
+ g_return_val_if_fail (E_IS_ACTIVITY (activity), NULL);
+
+ class = E_ACTIVITY_GET_CLASS (activity);
+ g_return_val_if_fail (class->describe != NULL, NULL);
+
+ return class->describe (activity);
+}
+
+gboolean
+e_activity_is_cancelled (EActivity *activity)
+{
+ g_return_val_if_fail (E_IS_ACTIVITY (activity), FALSE);
+
+ return activity->priv->cancelled;
+}
+
+gboolean
+e_activity_is_completed (EActivity *activity)
+{
+ g_return_val_if_fail (E_IS_ACTIVITY (activity), FALSE);
+
+ return activity->priv->completed;
+}
+
+gboolean
+e_activity_get_allow_cancel (EActivity *activity)
+{
+ g_return_val_if_fail (E_IS_ACTIVITY (activity), FALSE);
+
+ return activity->priv->allow_cancel;
+}
+
+void
+e_activity_set_allow_cancel (EActivity *activity,
+ gboolean allow_cancel)
+{
+ g_return_if_fail (E_IS_ACTIVITY (activity));
+
+ activity->priv->allow_cancel = allow_cancel;
+
+ g_object_notify (G_OBJECT (activity), "allow-cancel");
+}
+
+gboolean
+e_activity_get_blocking (EActivity *activity)
+{
+ g_return_val_if_fail (E_IS_ACTIVITY (activity), FALSE);
+
+ return activity->priv->blocking;
+}
+
+void
+e_activity_set_blocking (EActivity *activity,
+ gboolean blocking)
+{
+ g_return_if_fail (E_IS_ACTIVITY (activity));
+
+ activity->priv->blocking = blocking;
+
+ g_object_notify (G_OBJECT (activity), "blocking");
+}
+
+gboolean
+e_activity_get_clickable (EActivity *activity)
+{
+ g_return_val_if_fail (E_IS_ACTIVITY (activity), FALSE);
+
+ return activity->priv->clickable;
+}
+
+void
+e_activity_set_clickable (EActivity *activity,
+ gboolean clickable)
+{
+ g_return_if_fail (E_IS_ACTIVITY (activity));
+
+ activity->priv->clickable = clickable;
+
+ g_object_notify (G_OBJECT (activity), "clickable");
+}
+
+const gchar *
+e_activity_get_icon_name (EActivity *activity)
+{
+ g_return_val_if_fail (E_IS_ACTIVITY (activity), NULL);
+
+ return activity->priv->icon_name;
+}
+
+void
+e_activity_set_icon_name (EActivity *activity,
+ const gchar *icon_name)
+{
+ g_return_if_fail (E_IS_ACTIVITY (activity));
+
+ g_free (activity->priv->icon_name);
+ activity->priv->icon_name = g_strdup (icon_name);
+
+ g_object_notify (G_OBJECT (activity), "icon-name");
+}
+
+gdouble
+e_activity_get_percent (EActivity *activity)
+{
+ g_return_val_if_fail (E_IS_ACTIVITY (activity), -1.0);
+
+ return activity->priv->percent;
+}
+
+void
+e_activity_set_percent (EActivity *activity,
+ gdouble percent)
+{
+ g_return_if_fail (E_IS_ACTIVITY (activity));
+
+ activity->priv->percent = percent;
+
+ g_object_notify (G_OBJECT (activity), "percent");
+}
+
+const gchar *
+e_activity_get_primary_text (EActivity *activity)
+{
+ g_return_val_if_fail (E_IS_ACTIVITY (activity), NULL);
+
+ return activity->priv->primary_text;
+}
+
+void
+e_activity_set_primary_text (EActivity *activity,
+ const gchar *primary_text)
+{
+ g_return_if_fail (E_IS_ACTIVITY (activity));
+
+ g_free (activity->priv->primary_text);
+ activity->priv->primary_text = g_strdup (primary_text);
+
+ g_object_notify (G_OBJECT (activity), "primary-text");
+}
+
+const gchar *
+e_activity_get_secondary_text (EActivity *activity)
+{
+ g_return_val_if_fail (E_IS_ACTIVITY (activity), NULL);
+
+ return activity->priv->secondary_text;
+}
+
+void
+e_activity_set_secondary_text (EActivity *activity,
+ const gchar *secondary_text)
+{
+ g_return_if_fail (E_IS_ACTIVITY (activity));
+
+ g_free (activity->priv->secondary_text);
+ activity->priv->secondary_text = g_strdup (secondary_text);
+
+ g_object_notify (G_OBJECT (activity), "secondary-text");
+}
+
+void
+e_activity_set_error (EActivity *activity,
+ const GError *error)
+{
+ g_return_if_fail (E_IS_ACTIVITY (activity));
+
+ if (activity->priv->error != NULL) {
+ g_error_free (activity->priv->error);
+ activity->priv->error = NULL;
+ }
+
+ if (error != NULL)
+ activity->priv->error = g_error_copy (error);
+}
+
+gboolean
+e_activity_propagate_error (EActivity *activity,
+ GError **destination)
+{
+ gboolean propagated;
+
+ g_return_val_if_fail (E_IS_ACTIVITY (activity), FALSE);
+
+ if ((propagated = (activity->priv->error != NULL))) {
+ g_propagate_error (destination, activity->priv->error);
+ activity->priv->error = NULL;
+ }
+
+ return propagated;
+}
diff --git a/widgets/misc/e-activity.h b/widgets/misc/e-activity.h
new file mode 100644
index 0000000000..aca262172c
--- /dev/null
+++ b/widgets/misc/e-activity.h
@@ -0,0 +1,107 @@
+/*
+ * e-activity.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef E_ACTIVITY_H
+#define E_ACTIVITY_H
+
+#include <gtk/gtk.h>
+
+/* Standard GObject macros */
+#define E_TYPE_ACTIVITY \
+ (e_activity_get_type ())
+#define E_ACTIVITY(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_ACTIVITY, EActivity))
+#define E_ACTIVITY_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_ACTIVITY, EActivityClass))
+#define E_IS_ACTIVITY(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_ACTIVITY))
+#define E_IS_ACTIVITY_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_ACTIVITY))
+#define E_ACTIVITY_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_ACTIVITY, EActivityClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EActivity EActivity;
+typedef struct _EActivityClass EActivityClass;
+typedef struct _EActivityPrivate EActivityPrivate;
+
+struct _EActivity {
+ GObject parent;
+ EActivityPrivate *priv;
+};
+
+struct _EActivityClass {
+ GObjectClass parent_class;
+
+ /* Signals */
+ void (*cancelled) (EActivity *activity);
+ void (*completed) (EActivity *activity);
+ void (*clicked) (EActivity *activity);
+ gchar * (*describe) (EActivity *activity);
+};
+
+GType e_activity_get_type (void);
+EActivity * e_activity_new (const gchar *primary_text);
+EActivity * e_activity_newv (const gchar *format,
+ ...) G_GNUC_PRINTF (1, 2);
+void e_activity_cancel (EActivity *activity);
+void e_activity_cancel_in_idle (EActivity *activity);
+void e_activity_complete (EActivity *activity);
+void e_activity_complete_in_idle (EActivity *activity);
+void e_activity_clicked (EActivity *activity);
+gchar * e_activity_describe (EActivity *activity);
+gboolean e_activity_is_cancelled (EActivity *activity);
+gboolean e_activity_is_completed (EActivity *activity);
+gboolean e_activity_get_allow_cancel (EActivity *activity);
+void e_activity_set_allow_cancel (EActivity *activity,
+ gboolean allow_cancel);
+gboolean e_activity_get_blocking (EActivity *activity);
+void e_activity_set_blocking (EActivity *activity,
+ gboolean blocking);
+gboolean e_activity_get_clickable (EActivity *activity);
+void e_activity_set_clickable (EActivity *activity,
+ gboolean clickable);
+const gchar * e_activity_get_icon_name (EActivity *activity);
+void e_activity_set_icon_name (EActivity *activity,
+ const gchar *icon_name);
+gdouble e_activity_get_percent (EActivity *activity);
+void e_activity_set_percent (EActivity *activity,
+ gdouble percent);
+const gchar * e_activity_get_primary_text (EActivity *activity);
+void e_activity_set_primary_text (EActivity *activity,
+ const gchar *primary_text);
+const gchar * e_activity_get_secondary_text (EActivity *activity);
+void e_activity_set_secondary_text (EActivity *activity,
+ const gchar *secondary_text);
+void e_activity_set_error (EActivity *activity,
+ const GError *error);
+gboolean e_activity_propagate_error (EActivity *activity,
+ GError **destination);
+
+G_END_DECLS
+
+#endif /* E_ACTIVITY_H */
diff --git a/widgets/misc/e-alert-activity.c b/widgets/misc/e-alert-activity.c
new file mode 100644
index 0000000000..860b129ef9
--- /dev/null
+++ b/widgets/misc/e-alert-activity.c
@@ -0,0 +1,254 @@
+/*
+ * e-alert-activity.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#include "e-alert-activity.h"
+
+#define E_ALERT_ACTIVITY_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), E_TYPE_ALERT_ACTIVITY, EAlertActivityPrivate))
+
+struct _EAlertActivityPrivate {
+ GtkWidget *message_dialog;
+};
+
+enum {
+ PROP_0,
+ PROP_MESSAGE_DIALOG
+};
+
+static gpointer parent_class;
+
+static void
+alert_activity_set_message_dialog (EAlertActivity *alert_activity,
+ GtkWidget *message_dialog)
+{
+ g_return_if_fail (alert_activity->priv->message_dialog == NULL);
+
+ alert_activity->priv->message_dialog = g_object_ref (message_dialog);
+}
+
+static void
+alert_activity_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_MESSAGE_DIALOG:
+ alert_activity_set_message_dialog (
+ E_ALERT_ACTIVITY (object),
+ g_value_get_object (value));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+alert_activity_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_MESSAGE_DIALOG:
+ g_value_set_object (
+ value, e_alert_activity_get_message_dialog (
+ E_ALERT_ACTIVITY (object)));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+alert_activity_dispose (GObject *object)
+{
+ EAlertActivityPrivate *priv;
+
+ priv = E_ALERT_ACTIVITY_GET_PRIVATE (object);
+
+ if (priv->message_dialog != NULL) {
+ g_object_unref (priv->message_dialog);
+ priv->message_dialog = NULL;
+ }
+
+ /* Chain up to parent's dispose() method. */
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+alert_activity_constructed (GObject *object)
+{
+ EActivity *activity;
+ EAlertActivity *alert_activity;
+ GtkWidget *message_dialog;
+ const gchar *primary_text;
+ const gchar *secondary_text;
+
+ alert_activity = E_ALERT_ACTIVITY (object);
+ message_dialog = e_alert_activity_get_message_dialog (alert_activity);
+
+ object = G_OBJECT (message_dialog);
+ primary_text = g_object_get_data (object, "primary");
+ secondary_text = g_object_get_data (object, "secondary");
+
+ activity = E_ACTIVITY (alert_activity);
+ e_activity_set_primary_text (activity, primary_text);
+ e_activity_set_secondary_text (activity, secondary_text);
+}
+
+static void
+alert_activity_clicked (EActivity *activity)
+{
+ EAlertActivity *alert_activity;
+ GtkWidget *message_dialog;
+
+ e_activity_complete (activity);
+
+ alert_activity = E_ALERT_ACTIVITY (activity);
+ message_dialog = e_alert_activity_get_message_dialog (alert_activity);
+ gtk_dialog_run (GTK_DIALOG (message_dialog));
+ gtk_widget_hide (message_dialog);
+
+ /* Chain up to parent's clicked() method. */
+ E_ACTIVITY_CLASS (parent_class)->clicked (activity);
+}
+
+static void
+alert_activity_timeout (ETimeoutActivity *activity)
+{
+ e_activity_complete (E_ACTIVITY (activity));
+
+ /* Chain up to parent's timeout() method. */
+ E_TIMEOUT_ACTIVITY_CLASS (parent_class)->timeout (activity);
+}
+
+static void
+alert_activity_class_init (EAlertActivityClass *class)
+{
+ GObjectClass *object_class;
+ EActivityClass *activity_class;
+ ETimeoutActivityClass *timeout_activity_class;
+
+ parent_class = g_type_class_peek_parent (class);
+ g_type_class_add_private (class, sizeof (EAlertActivityPrivate));
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->set_property = alert_activity_set_property;
+ object_class->get_property = alert_activity_get_property;
+ object_class->dispose = alert_activity_dispose;
+ object_class->constructed = alert_activity_constructed;
+
+ activity_class = E_ACTIVITY_CLASS (class);
+ activity_class->clicked = alert_activity_clicked;
+
+ timeout_activity_class = E_TIMEOUT_ACTIVITY_CLASS (class);
+ timeout_activity_class->timeout = alert_activity_timeout;
+
+ g_object_class_install_property (
+ object_class,
+ PROP_MESSAGE_DIALOG,
+ g_param_spec_object (
+ "message-dialog",
+ NULL,
+ NULL,
+ GTK_TYPE_DIALOG,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY));
+}
+
+static void
+alert_activity_init (EAlertActivity *alert_activity)
+{
+ alert_activity->priv = E_ALERT_ACTIVITY_GET_PRIVATE (alert_activity);
+
+ e_activity_set_clickable (E_ACTIVITY (alert_activity), TRUE);
+ e_timeout_activity_set_timeout (E_TIMEOUT_ACTIVITY (alert_activity), 60);
+}
+
+GType
+e_alert_activity_get_type (void)
+{
+ static GType type = 0;
+
+ if (G_UNLIKELY (type == 0)) {
+ static const GTypeInfo type_info = {
+ sizeof (EAlertActivityClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) alert_activity_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+ sizeof (EAlertActivity),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) alert_activity_init,
+ NULL /* value_table */
+ };
+
+ type = g_type_register_static (
+ E_TYPE_TIMEOUT_ACTIVITY, "EAlertActivity",
+ &type_info, 0);
+ }
+
+ return type;
+}
+
+EActivity *
+e_alert_activity_new_info (GtkWidget *message_dialog)
+{
+ g_return_val_if_fail (GTK_IS_DIALOG (message_dialog), NULL);
+
+ return g_object_new (
+ E_TYPE_ALERT_ACTIVITY,
+ "icon-name", "dialog-information",
+ "message-dialog", message_dialog, NULL);
+}
+
+EActivity *
+e_alert_activity_new_error (GtkWidget *message_dialog)
+{
+ g_return_val_if_fail (GTK_IS_DIALOG (message_dialog), NULL);
+
+ return g_object_new (
+ E_TYPE_ALERT_ACTIVITY,
+ "icon-name", "dialog-error",
+ "message-dialog", message_dialog, NULL);
+}
+
+EActivity *
+e_alert_activity_new_warning (GtkWidget *message_dialog)
+{
+ g_return_val_if_fail (GTK_IS_DIALOG (message_dialog), NULL);
+
+ return g_object_new (
+ E_TYPE_ALERT_ACTIVITY,
+ "icon-name", "dialog-warning",
+ "message-dialog", message_dialog, NULL);
+}
+
+GtkWidget *
+e_alert_activity_get_message_dialog (EAlertActivity *alert_activity)
+{
+ g_return_val_if_fail (E_IS_ALERT_ACTIVITY (alert_activity), NULL);
+
+ return alert_activity->priv->message_dialog;
+}
diff --git a/widgets/misc/e-alert-activity.h b/widgets/misc/e-alert-activity.h
new file mode 100644
index 0000000000..5557094dda
--- /dev/null
+++ b/widgets/misc/e-alert-activity.h
@@ -0,0 +1,70 @@
+/*
+ * e-alert-activity.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef E_ALERT_ACTIVITY_H
+#define E_ALERT_ACTIVITY_H
+
+#include <e-timeout-activity.h>
+
+/* Standard GObject macros */
+#define E_TYPE_ALERT_ACTIVITY \
+ (e_alert_activity_get_type ())
+#define E_ALERT_ACTIVITY(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_ALERT_ACTIVITY, EAlertActivity))
+#define E_ALERT_ACTIVITY_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_ALERT_ACTIVITY, EAlertActivityClass))
+#define E_IS_ALERT_ACTIVITY(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_ALERT_ACTIVITY))
+#define E_IS_ALERT_ACTIVITY_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_ALERT_ACTIVITY))
+#define E_ALERT_ACTIVITY_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_ALERT_ACTIVITY, EAlertActivityClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EAlertActivity EAlertActivity;
+typedef struct _EAlertActivityClass EAlertActivityClass;
+typedef struct _EAlertActivityPrivate EAlertActivityPrivate;
+
+struct _EAlertActivity {
+ ETimeoutActivity parent;
+ EAlertActivityPrivate *priv;
+};
+
+struct _EAlertActivityClass {
+ ETimeoutActivityClass parent_class;
+};
+
+GType e_alert_activity_get_type (void);
+EActivity * e_alert_activity_new_info (GtkWidget *message_dialog);
+EActivity * e_alert_activity_new_error (GtkWidget *message_dialog);
+EActivity * e_alert_activity_new_warning (GtkWidget *message_dialog);
+GtkWidget * e_alert_activity_get_message_dialog
+ (EAlertActivity *alert_activity);
+
+G_END_DECLS
+
+#endif /* E_ALERT_ACTIVITY_H */
diff --git a/widgets/misc/e-calendar.h b/widgets/misc/e-calendar.h
index 911e9ee22a..c281e7436b 100644
--- a/widgets/misc/e-calendar.h
+++ b/widgets/misc/e-calendar.h
@@ -37,9 +37,24 @@ G_BEGIN_DECLS
* to got to the current day.
*/
-#define E_CALENDAR(obj) G_TYPE_CHECK_INSTANCE_CAST (obj, e_calendar_get_type (), ECalendar)
-#define E_CALENDAR_CLASS(klass) G_TYPE_CHECK_CLASS_CAST (klass, e_calendar_get_type (), ECalendarClass)
-#define E_IS_CALENDAR(obj) G_TYPE_CHECK_INSTANCE_TYPE (obj, e_calendar_get_type ())
+/* Standard GObject macros */
+#define E_TYPE_CALENDAR \
+ (e_calendar_get_type ())
+#define E_CALENDAR(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_CALENDAR, ECalendar))
+#define E_CALENDAR_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_CALENDAR, ECalendarClass))
+#define E_IS_CALENDAR(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_CALENDAR))
+#define E_IS_CALENDAR_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_CALENDAR))
+#define E_CALENDAR_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_CALENDAR, ECalendarClass))
typedef struct _ECalendar ECalendar;
diff --git a/widgets/misc/e-charset-combo-box.c b/widgets/misc/e-charset-combo-box.c
new file mode 100644
index 0000000000..9c992ce1f7
--- /dev/null
+++ b/widgets/misc/e-charset-combo-box.c
@@ -0,0 +1,428 @@
+/*
+ * e-charset-combo-box.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#include "e-charset-combo-box.h"
+
+#include <glib/gi18n.h>
+
+#include "e-util/e-charset.h"
+#include "e-util/e-util.h"
+
+#define E_CHARSET_COMBO_BOX_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), E_TYPE_CHARSET_COMBO_BOX, ECharsetComboBoxPrivate))
+
+#define DEFAULT_CHARSET "UTF-8"
+#define OTHER_VALUE G_MAXINT
+
+struct _ECharsetComboBoxPrivate {
+ GtkActionGroup *action_group;
+ GtkRadioAction *other_action;
+ GHashTable *charset_index;
+
+ /* Used when the user clicks Cancel in the character set
+ * dialog. Reverts to the previous combo box setting. */
+ gint previous_index;
+
+ /* When setting the character set programmatically, this
+ * prevents the custom character set dialog from running. */
+ guint block_dialog : 1;
+};
+
+enum {
+ PROP_0,
+ PROP_CHARSET
+};
+
+static gpointer parent_class;
+
+static void
+charset_combo_box_entry_changed_cb (GtkEntry *entry,
+ GtkDialog *dialog)
+{
+ const gchar *text;
+ gboolean sensitive;
+
+ text = gtk_entry_get_text (entry);
+ sensitive = (text != NULL && *text != '\0');
+ gtk_dialog_set_response_sensitive (dialog, GTK_RESPONSE_OK, sensitive);
+}
+
+static void
+charset_combo_box_run_dialog (ECharsetComboBox *combo_box)
+{
+ GtkDialog *dialog;
+ GtkEntry *entry;
+ GtkWidget *container;
+ GtkWidget *widget;
+ GObject *object;
+ gpointer parent;
+ const gchar *charset;
+
+ /* FIXME Using a dialog for this is lame. Selecting "Other..."
+ * should unlock an entry directly in the Preferences tab.
+ * Unfortunately space in Preferences is at a premium right
+ * now, but we should revisit this when the space issue is
+ * finally resolved. */
+
+ parent = gtk_widget_get_toplevel (GTK_WIDGET (combo_box));
+ parent = GTK_WIDGET_TOPLEVEL (parent) ? parent : NULL;
+
+ object = G_OBJECT (combo_box->priv->other_action);
+ charset = g_object_get_data (object, "charset");
+
+ widget = gtk_dialog_new_with_buttons (
+ _("Character Encoding"), parent,
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ GTK_STOCK_OK, GTK_RESPONSE_OK, NULL);
+
+ /* Load the broken border width defaults so we can override them. */
+ gtk_widget_ensure_style (widget);
+
+ dialog = GTK_DIALOG (widget);
+
+ gtk_dialog_set_has_separator (dialog, FALSE);
+ gtk_dialog_set_default_response (dialog, GTK_RESPONSE_OK);
+
+ gtk_container_set_border_width (GTK_CONTAINER (dialog), 12);
+
+ widget = gtk_dialog_get_action_area (dialog);
+ gtk_container_set_border_width (GTK_CONTAINER (widget), 0);
+
+ widget = gtk_dialog_get_content_area (dialog);
+ gtk_box_set_spacing (GTK_BOX (widget), 12);
+ gtk_container_set_border_width (GTK_CONTAINER (widget), 0);
+
+ container = widget;
+
+ widget = gtk_label_new (_("Enter the character set to use"));
+ gtk_label_set_line_wrap (GTK_LABEL (widget), TRUE);
+ gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
+ gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
+ gtk_widget_show (widget);
+
+ widget = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
+ gtk_alignment_set_padding (GTK_ALIGNMENT (widget), 0, 0, 12, 0);
+ gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
+ gtk_widget_show (widget);
+
+ container = widget;
+
+ widget = gtk_entry_new ();
+ entry = GTK_ENTRY (widget);
+ gtk_entry_set_activates_default (entry, TRUE);
+ gtk_container_add (GTK_CONTAINER (container), widget);
+ gtk_widget_show (widget);
+
+ g_signal_connect (
+ entry, "changed",
+ G_CALLBACK (charset_combo_box_entry_changed_cb), dialog);
+
+ /* Set the default text -after- connecting the signal handler.
+ * This will initialize the "OK" button to the proper state. */
+ gtk_entry_set_text (entry, charset);
+
+ if (gtk_dialog_run (dialog) != GTK_RESPONSE_OK) {
+ gint active;
+
+ /* Revert to the previously selected character set. */
+ combo_box->priv->block_dialog = TRUE;
+ active = combo_box->priv->previous_index;
+ gtk_combo_box_set_active (GTK_COMBO_BOX (combo_box), active);
+ combo_box->priv->block_dialog = FALSE;
+
+ goto exit;
+ }
+
+ charset = gtk_entry_get_text (entry);
+ g_return_if_fail (charset != NULL && charset != '\0');
+
+ g_object_set_data_full (
+ object, "charset", g_strdup (charset),
+ (GDestroyNotify) g_free);
+
+exit:
+ gtk_widget_destroy (GTK_WIDGET (dialog));
+}
+
+static void
+charset_combo_box_notify_charset_cb (ECharsetComboBox *combo_box)
+{
+ GtkToggleAction *action;
+
+ action = GTK_TOGGLE_ACTION (combo_box->priv->other_action);
+ if (!gtk_toggle_action_get_active (action))
+ return;
+
+ if (combo_box->priv->block_dialog)
+ return;
+
+ /* "Other" action was selected by user. */
+ charset_combo_box_run_dialog (combo_box);
+}
+
+static void
+charset_combo_box_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_CHARSET:
+ e_charset_combo_box_set_charset (
+ E_CHARSET_COMBO_BOX (object),
+ g_value_get_string (value));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+charset_combo_box_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_CHARSET:
+ g_value_set_string (
+ value, e_charset_combo_box_get_charset (
+ E_CHARSET_COMBO_BOX (object)));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+charset_combo_box_dispose (GObject *object)
+{
+ ECharsetComboBoxPrivate *priv;
+
+ priv = E_CHARSET_COMBO_BOX_GET_PRIVATE (object);
+
+ if (priv->action_group != NULL) {
+ g_object_unref (priv->action_group);
+ priv->action_group = NULL;
+ }
+
+ if (priv->other_action != NULL) {
+ g_object_unref (priv->other_action);
+ priv->other_action = NULL;
+ }
+
+ g_hash_table_remove_all (priv->charset_index);
+
+ /* Chain up to parent's dispose() method. */
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+charset_combo_box_finalize (GObject *object)
+{
+ ECharsetComboBoxPrivate *priv;
+
+ priv = E_CHARSET_COMBO_BOX_GET_PRIVATE (object);
+
+ g_hash_table_destroy (priv->charset_index);
+
+ /* Chain up to parent's finalize() method. */
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+charset_combo_box_changed (GtkComboBox *combo_box)
+{
+ ECharsetComboBoxPrivate *priv;
+
+ priv = E_CHARSET_COMBO_BOX_GET_PRIVATE (combo_box);
+
+ /* Chain up to parent's changed() method. */
+ GTK_COMBO_BOX_CLASS (parent_class)->changed (combo_box);
+
+ /* Notify -before- updating previous index. */
+ g_object_notify (G_OBJECT (combo_box), "charset");
+ priv->previous_index = gtk_combo_box_get_active (combo_box);
+}
+
+static void
+charset_combo_box_class_init (ECharsetComboBoxClass *class)
+{
+ GObjectClass *object_class;
+ GtkComboBoxClass *combo_box_class;
+
+ parent_class = g_type_class_peek_parent (class);
+ g_type_class_add_private (class, sizeof (ECharsetComboBoxPrivate));
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->set_property = charset_combo_box_set_property;
+ object_class->get_property = charset_combo_box_get_property;
+ object_class->dispose = charset_combo_box_dispose;
+ object_class->finalize = charset_combo_box_finalize;
+
+ combo_box_class = GTK_COMBO_BOX_CLASS (class);
+ combo_box_class->changed = charset_combo_box_changed;
+
+ g_object_class_install_property (
+ object_class,
+ PROP_CHARSET,
+ g_param_spec_string (
+ "charset",
+ "Charset",
+ "The selected character set",
+ "UTF-8",
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT));
+}
+
+static void
+charset_combo_box_init (ECharsetComboBox *combo_box)
+{
+ GtkActionGroup *action_group;
+ GtkRadioAction *radio_action;
+ GHashTable *charset_index;
+ GSList *group, *iter;
+
+ action_group = gtk_action_group_new ("charset-combo-box-internal");
+
+ charset_index = g_hash_table_new_full (
+ g_str_hash, g_str_equal,
+ (GDestroyNotify) g_free,
+ (GDestroyNotify) g_object_unref);
+
+ combo_box->priv = E_CHARSET_COMBO_BOX_GET_PRIVATE (combo_box);
+ combo_box->priv->action_group = action_group;
+ combo_box->priv->charset_index = charset_index;
+
+ group = e_charset_add_radio_actions (
+ action_group, "charset-", NULL, NULL, NULL);
+
+ /* Populate the character set index. */
+ for (iter = group; iter != NULL; iter = iter->next) {
+ GObject *object = iter->data;
+ const gchar *charset;
+
+ charset = g_object_get_data (object, "charset");
+ g_return_if_fail (charset != NULL);
+
+ g_hash_table_insert (
+ charset_index, g_strdup (charset),
+ g_object_ref (object));
+ }
+
+ /* Note the "other" action is not included in the index. */
+
+ radio_action = gtk_radio_action_new (
+ "charset-other", _("Other..."), NULL, NULL, OTHER_VALUE);
+
+ g_object_set_data (G_OBJECT (radio_action), "charset", (gpointer) "");
+
+ gtk_radio_action_set_group (radio_action, group);
+ group = gtk_radio_action_get_group (radio_action);
+
+ e_action_combo_box_set_action (
+ E_ACTION_COMBO_BOX (combo_box), radio_action);
+
+ e_action_combo_box_add_separator_after (
+ E_ACTION_COMBO_BOX (combo_box), g_slist_length (group));
+
+ g_signal_connect (
+ combo_box, "notify::charset",
+ G_CALLBACK (charset_combo_box_notify_charset_cb), NULL);
+
+ combo_box->priv->other_action = radio_action;
+}
+
+GType
+e_charset_combo_box_get_type (void)
+{
+ static GType type = 0;
+
+ if (G_UNLIKELY (type == 0)) {
+ static const GTypeInfo type_info = {
+ sizeof (ECharsetComboBoxClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) charset_combo_box_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+ sizeof (ECharsetComboBox),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) charset_combo_box_init,
+ NULL /* value_table */
+ };
+
+ type = g_type_register_static (
+ E_TYPE_ACTION_COMBO_BOX, "ECharsetComboBox",
+ &type_info, 0);
+ }
+
+ return type;
+}
+
+GtkWidget *
+e_charset_combo_box_new (void)
+{
+ return g_object_new (E_TYPE_CHARSET_COMBO_BOX, NULL);
+}
+
+const gchar *
+e_charset_combo_box_get_charset (ECharsetComboBox *combo_box)
+{
+ GtkRadioAction *radio_action;
+
+ g_return_val_if_fail (E_IS_CHARSET_COMBO_BOX (combo_box), NULL);
+
+ radio_action = combo_box->priv->other_action;
+ radio_action = e_radio_action_get_current_action (radio_action);
+
+ return g_object_get_data (G_OBJECT (radio_action), "charset");
+}
+
+void
+e_charset_combo_box_set_charset (ECharsetComboBox *combo_box,
+ const gchar *charset)
+{
+ GHashTable *charset_index;
+ GtkRadioAction *radio_action;
+
+ g_return_if_fail (E_IS_CHARSET_COMBO_BOX (combo_box));
+
+ if (charset == NULL || *charset == '\0')
+ charset = "UTF-8";
+
+ charset_index = combo_box->priv->charset_index;
+ radio_action = g_hash_table_lookup (charset_index, charset);
+
+ if (radio_action == NULL) {
+ radio_action = combo_box->priv->other_action;
+ g_object_set_data_full (
+ G_OBJECT (radio_action),
+ "charset", g_strdup (charset),
+ (GDestroyNotify) g_free);
+ }
+
+ combo_box->priv->block_dialog = TRUE;
+ gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (radio_action), TRUE);
+ combo_box->priv->block_dialog = FALSE;
+}
diff --git a/widgets/misc/e-charset-combo-box.h b/widgets/misc/e-charset-combo-box.h
new file mode 100644
index 0000000000..471dfa6a54
--- /dev/null
+++ b/widgets/misc/e-charset-combo-box.h
@@ -0,0 +1,69 @@
+/*
+ * e-charset-combo-box.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef E_CHARSET_COMBO_BOX_H
+#define E_CHARSET_COMBO_BOX_H
+
+#include <misc/e-action-combo-box.h>
+
+/* Standard GObject macros */
+#define E_TYPE_CHARSET_COMBO_BOX \
+ (e_charset_combo_box_get_type ())
+#define E_CHARSET_COMBO_BOX(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_CHARSET_COMBO_BOX, ECharsetComboBox))
+#define E_CHARSET_COMBO_BOX_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_CHARSET_COMBO_BOX, ECharsetComboBoxClass))
+#define E_IS_CHARSET_COMBO_BOX(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_CHARSET_COMBO_BOX))
+#define E_IS_CHARSET_COMBO_BOX_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_CHARSET_COMBO_BOX))
+#define E_CHARSET_COMBO_BOX_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_CHARSET_COMBO_BOX, ECharsetComboBoxClass))
+
+G_BEGIN_DECLS
+
+typedef struct _ECharsetComboBox ECharsetComboBox;
+typedef struct _ECharsetComboBoxClass ECharsetComboBoxClass;
+typedef struct _ECharsetComboBoxPrivate ECharsetComboBoxPrivate;
+
+struct _ECharsetComboBox {
+ EActionComboBox parent;
+ ECharsetComboBoxPrivate *priv;
+};
+
+struct _ECharsetComboBoxClass {
+ EActionComboBoxClass parent_class;
+};
+
+GType e_charset_combo_box_get_type (void);
+GtkWidget * e_charset_combo_box_new (void);
+const gchar * e_charset_combo_box_get_charset (ECharsetComboBox *combo_box);
+void e_charset_combo_box_set_charset (ECharsetComboBox *combo_box,
+ const gchar *charset);
+
+G_END_DECLS
+
+#endif /* E_CHARSET_COMBO_BOX_H */
diff --git a/widgets/misc/e-charset-picker.c b/widgets/misc/e-charset-picker.c
deleted file mode 100644
index 53beaa9c11..0000000000
--- a/widgets/misc/e-charset-picker.c
+++ /dev/null
@@ -1,715 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) version 3.
- *
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- *
- * Authors:
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "e-charset-picker.h"
-#include "e-util/e-dialog-utils.h"
-
-#include <string.h>
-#include <iconv.h>
-
-#include <glib/gi18n-lib.h>
-
-#include <bonobo/bonobo-ui-node.h>
-#include <bonobo/bonobo-ui-util.h>
-
-typedef enum {
- E_CHARSET_UNKNOWN,
- E_CHARSET_ARABIC,
- E_CHARSET_BALTIC,
- E_CHARSET_CENTRAL_EUROPEAN,
- E_CHARSET_CHINESE,
- E_CHARSET_CYRILLIC,
- E_CHARSET_GREEK,
- E_CHARSET_HEBREW,
- E_CHARSET_JAPANESE,
- E_CHARSET_KOREAN,
- E_CHARSET_THAI,
- E_CHARSET_TURKISH,
- E_CHARSET_UNICODE,
- E_CHARSET_WESTERN_EUROPEAN,
- E_CHARSET_WESTERN_EUROPEAN_NEW
-} ECharsetClass;
-
-static const gchar *classnames[] = {
- N_("Unknown"),
- N_("Arabic"),
- N_("Baltic"),
- N_("Central European"),
- N_("Chinese"),
- N_("Cyrillic"),
- N_("Greek"),
- N_("Hebrew"),
- N_("Japanese"),
- N_("Korean"),
- N_("Thai"),
- N_("Turkish"),
- N_("Unicode"),
- N_("Western European"),
- N_("Western European, New"),
-};
-
-typedef struct {
- const gchar *name;
- ECharsetClass class;
- const gchar *subclass;
-} ECharset;
-
-/* This list is based on what other mailers/browsers support. There's
- * not a lot of point in using, say, ISO-8859-3, if anything that can
- * read that can read UTF8 too.
- */
-/* To Translators: Character set "Logical Hebrew" */
-static ECharset charsets[] = {
- { "ISO-8859-6", E_CHARSET_ARABIC, NULL },
- { "ISO-8859-13", E_CHARSET_BALTIC, NULL },
- { "ISO-8859-4", E_CHARSET_BALTIC, NULL },
- { "ISO-8859-2", E_CHARSET_CENTRAL_EUROPEAN, NULL },
- { "Big5", E_CHARSET_CHINESE, N_("Traditional") },
- { "BIG5HKSCS", E_CHARSET_CHINESE, N_("Traditional") },
- { "EUC-TW", E_CHARSET_CHINESE, N_("Traditional") },
- { "GB18030", E_CHARSET_CHINESE, N_("Simplified") },
- { "GB2312", E_CHARSET_CHINESE, N_("Simplified") },
- { "HZ", E_CHARSET_CHINESE, N_("Simplified") },
- { "ISO-2022-CN", E_CHARSET_CHINESE, N_("Simplified") },
- { "KOI8-R", E_CHARSET_CYRILLIC, NULL },
- { "Windows-1251", E_CHARSET_CYRILLIC, NULL },
- { "KOI8-U", E_CHARSET_CYRILLIC, N_("Ukrainian") },
- { "ISO-8859-5", E_CHARSET_CYRILLIC, NULL },
- { "ISO-8859-7", E_CHARSET_GREEK, NULL },
- { "ISO-8859-8", E_CHARSET_HEBREW, N_("Visual") },
- { "ISO-2022-JP", E_CHARSET_JAPANESE, NULL },
- { "EUC-JP", E_CHARSET_JAPANESE, NULL },
- { "Shift_JIS", E_CHARSET_JAPANESE, NULL },
- { "EUC-KR", E_CHARSET_KOREAN, NULL },
- { "TIS-620", E_CHARSET_THAI, NULL },
- { "ISO-8859-9", E_CHARSET_TURKISH, NULL },
- { "UTF-8", E_CHARSET_UNICODE, NULL },
- { "UTF-7", E_CHARSET_UNICODE, NULL },
- { "ISO-8859-1", E_CHARSET_WESTERN_EUROPEAN, NULL },
- { "ISO-8859-15", E_CHARSET_WESTERN_EUROPEAN_NEW, NULL },
-};
-static const gint num_charsets = sizeof (charsets) / sizeof (charsets[0]);
-
-static void
-select_item (GtkMenuShell *menu_shell, GtkWidget *item)
-{
- gtk_menu_shell_select_item (menu_shell, item);
- gtk_menu_shell_deactivate (menu_shell);
-}
-
-static void
-activate (GtkWidget *item, gpointer menu)
-{
- g_object_set_data ((GObject *) menu, "activated_item", item);
-}
-
-static GtkWidget *
-add_charset (GtkWidget *menu, ECharset *charset, gboolean free_name)
-{
- GtkWidget *item;
- gchar *label;
-
- if (charset->subclass) {
- label = g_strdup_printf ("%s, %s (%s)",
- _(classnames[charset->class]),
- _(charset->subclass),
- charset->name);
- } else if (charset->class) {
- label = g_strdup_printf ("%s (%s)",
- _(classnames[charset->class]),
- charset->name);
- } else {
- label = g_strdup (charset->name);
- }
-
- item = gtk_menu_item_new_with_label (label);
- g_object_set_data_full ((GObject *) item, "charset",
- (gpointer) charset->name, free_name ? g_free : NULL);
- g_free (label);
-
- gtk_widget_show (item);
- gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
- g_signal_connect (item, "activate", G_CALLBACK (activate), menu);
-
- return item;
-}
-
-static gboolean
-add_other_charset (GtkWidget *menu, GtkWidget *other, const gchar *new_charset)
-{
- ECharset charset = { NULL, E_CHARSET_UNKNOWN, NULL };
- GtkWidget *item;
- iconv_t ic;
-
- ic = iconv_open ("UTF-8", new_charset);
- if (ic == (iconv_t)-1) {
- GtkWidget *window = gtk_widget_get_ancestor (other, GTK_TYPE_WINDOW);
- e_notice (window, GTK_MESSAGE_ERROR,
- _("Unknown character set: %s"), new_charset);
- return FALSE;
- }
- iconv_close (ic);
-
- /* Temporarily remove the "Other..." item */
- g_object_ref (other);
- gtk_container_remove (GTK_CONTAINER (menu), other);
-
- /* Create new menu item */
- charset.name = g_strdup (new_charset);
- item = add_charset (menu, &charset, TRUE);
-
- /* And re-add "Other..." */
- gtk_menu_shell_append (GTK_MENU_SHELL (menu), other);
- g_object_unref (other);
-
- g_object_set_data_full ((GObject *) menu, "other_charset",
- g_strdup (new_charset), g_free);
-
- g_object_set_data ((GObject *) menu, "activated_item", item);
- select_item (GTK_MENU_SHELL (menu), item);
-
- return TRUE;
-}
-
-static void
-activate_entry (GtkWidget *entry, GtkDialog *dialog)
-{
- gtk_dialog_response (dialog, GTK_RESPONSE_OK);
-}
-
-static void
-activate_other (GtkWidget *item, gpointer menu)
-{
- GtkWidget *window, *entry, *label, *vbox, *hbox;
- gchar *old_charset, *new_charset;
- GtkDialog *dialog;
-
- window = gtk_widget_get_toplevel (menu);
- if (!GTK_WIDGET_TOPLEVEL (window))
- window = gtk_widget_get_ancestor (item, GTK_TYPE_WINDOW);
-
- old_charset = g_object_get_data(menu, "other_charset");
-
- dialog = GTK_DIALOG (gtk_dialog_new_with_buttons (_("Character Encoding"),
- GTK_WINDOW (window),
- GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
- GTK_STOCK_OK, GTK_RESPONSE_OK,
- NULL));
-
- gtk_dialog_set_has_separator (dialog, FALSE);
- gtk_dialog_set_default_response (dialog, GTK_RESPONSE_OK);
-
- vbox = gtk_vbox_new (FALSE, 6);
- gtk_container_set_border_width (GTK_CONTAINER (vbox), 12);
- gtk_box_pack_start (GTK_BOX (dialog->vbox), vbox, TRUE, TRUE, 0);
- gtk_widget_show (vbox);
-
- label = gtk_label_new (_("Enter the character set to use"));
- gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
- gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
- gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
- gtk_widget_show (label);
-
- hbox = gtk_hbox_new (FALSE, 12);
- gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
- gtk_widget_show (hbox);
-
- label = gtk_label_new ("");
- gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
- gtk_widget_show (label);
-
- entry = gtk_entry_new ();
- gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0);
- gtk_widget_show (entry);
-
- if (old_charset)
- gtk_entry_set_text (GTK_ENTRY (entry), old_charset);
- g_signal_connect (entry, "activate",
- G_CALLBACK (activate_entry), dialog);
-
- gtk_container_set_border_width (GTK_CONTAINER (dialog->vbox), 0);
- gtk_container_set_border_width (GTK_CONTAINER (dialog->action_area), 12);
-
- gtk_widget_show_all (GTK_WIDGET (dialog));
-
- g_object_ref (dialog);
- if (gtk_dialog_run (dialog) == GTK_RESPONSE_OK) {
- new_charset = (gchar *)gtk_entry_get_text (GTK_ENTRY (entry));
-
- if (*new_charset) {
- if (add_other_charset (menu, item, new_charset)) {
- gtk_widget_destroy (GTK_WIDGET (dialog));
- g_object_unref (dialog);
- return;
- }
- }
- }
- gtk_widget_destroy (GTK_WIDGET (dialog));
- g_object_unref (dialog);
-
- /* Revert to previous selection */
- select_item (GTK_MENU_SHELL (menu), g_object_get_data(G_OBJECT(menu), "activated_item"));
-}
-
-/**
- * e_charset_picker_new:
- * @default_charset: the default character set, or %NULL to use the
- * locale character set.
- *
- * This creates an option menu widget and fills it in with a selection
- * of available character sets. The @default_charset (or locale character
- * set if @default_charset is %NULL) will be listed first, and selected
- * by default (except that iso-8859-1 will always be used instead of
- * US-ASCII). Any other character sets of the same language class as
- * the default will be listed next, followed by the remaining character
- * sets, a separator, and an "Other..." menu item, which can be used to
- * select other charsets.
- *
- * Return value: an option menu widget, filled in and with signals
- * attached.
- */
-GtkWidget *
-e_charset_picker_new (const gchar *default_charset)
-{
- GtkWidget *menu, *item;
- gint def, i;
- const gchar *locale_charset;
-
- g_get_charset (&locale_charset);
- if (!g_ascii_strcasecmp (locale_charset, "US-ASCII"))
- locale_charset = "iso-8859-1";
-
- if (!default_charset)
- default_charset = locale_charset;
- for (def = 0; def < num_charsets; def++) {
- if (!g_ascii_strcasecmp (charsets[def].name, default_charset))
- break;
- }
-
- menu = gtk_menu_new ();
- for (i = 0; i < num_charsets; i++) {
- item = add_charset (menu, &charsets[i], FALSE);
- if (i == def) {
- activate (item, menu);
- select_item (GTK_MENU_SHELL (menu), item);
- }
- }
-
- /* do the Unknown/Other section */
- gtk_menu_shell_append (GTK_MENU_SHELL (menu), gtk_menu_item_new ());
-
- if (def == num_charsets) {
- ECharset other = { NULL, E_CHARSET_UNKNOWN, NULL };
-
- /* Add an entry for @default_charset */
- other.name = g_strdup (default_charset);
- item = add_charset (menu, &other, TRUE);
- activate (item, menu);
- select_item (GTK_MENU_SHELL (menu), item);
- g_object_set_data_full ((GObject *) menu, "other_charset",
- g_strdup (default_charset), g_free);
- def++;
- }
-
- item = gtk_menu_item_new_with_label (_("Other..."));
- g_signal_connect (item, "activate", G_CALLBACK (activate_other), menu);
- gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
-
- gtk_widget_show_all (menu);
-
- return menu;
-}
-
-/**
- * e_charset_picker_get_charset:
- * @menu: a character set menu from e_charset_picker_new()
- *
- * Return value: the currently-selected character set in @picker,
- * which must be freed with g_free().
- **/
-gchar *
-e_charset_picker_get_charset (GtkWidget *menu)
-{
- GtkWidget *item;
- gchar *charset;
-
- g_return_val_if_fail (GTK_IS_MENU (menu), NULL);
-
- item = gtk_menu_get_active (GTK_MENU (menu));
- charset = g_object_get_data ((GObject *) item, "charset");
-
- return g_strdup (charset);
-}
-
-/**
- * e_charset_picker_dialog:
- * @title: title for the dialog box
- * @prompt: prompt string for the dialog box
- * @default_charset: as for e_charset_picker_new()
- * @parent: a parent window for the dialog box, or %NULL
- *
- * This creates a new dialog box with the given @title and @prompt and
- * a character set picker menu. It then runs the dialog and returns
- * the selected character set, or %NULL if the user clicked "Cancel".
- *
- * Return value: the selected character set (which must be freed with
- * g_free()), or %NULL.
- **/
-gchar *
-e_charset_picker_dialog (const gchar *title, const gchar *prompt,
- const gchar *default_charset, GtkWindow *parent)
-{
- GtkDialog *dialog;
- GtkWidget *label, *omenu, *picker, *vbox, *hbox;
- gchar *charset = NULL;
-
- dialog = GTK_DIALOG (gtk_dialog_new_with_buttons (title,
- parent,
- GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
- GTK_STOCK_OK, GTK_RESPONSE_OK,
- NULL));
-
- gtk_dialog_set_has_separator (dialog, FALSE);
- gtk_dialog_set_default_response (dialog, GTK_RESPONSE_OK);
-
- vbox = gtk_vbox_new (FALSE, 6);
- gtk_container_set_border_width (GTK_CONTAINER (vbox), 12);
- gtk_box_pack_start (GTK_BOX (dialog->vbox), vbox, FALSE, FALSE, 0);
- gtk_widget_show (vbox);
-
- label = gtk_label_new (prompt);
- gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
- gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
- gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
- gtk_widget_show (label);
-
- hbox = gtk_hbox_new (FALSE, 12);
- gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
- gtk_widget_show (hbox);
-
- label = gtk_label_new ("");
- gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
- gtk_widget_show (label);
-
- picker = e_charset_picker_new (default_charset);
- omenu = gtk_option_menu_new ();
- gtk_option_menu_set_menu (GTK_OPTION_MENU (omenu), picker);
- gtk_box_pack_start (GTK_BOX (hbox), omenu, TRUE, TRUE, 0);
- gtk_widget_show (omenu);
-
- gtk_container_set_border_width (GTK_CONTAINER (dialog->vbox), 0);
- gtk_container_set_border_width (GTK_CONTAINER (dialog->action_area), 12);
-
- gtk_widget_show_all (GTK_WIDGET (dialog));
-
- g_object_ref (dialog);
-
- if (gtk_dialog_run (dialog) == GTK_RESPONSE_OK)
- charset = e_charset_picker_get_charset (picker);
-
- gtk_widget_destroy (GTK_WIDGET (dialog));
- g_object_unref (dialog);
-
- return charset;
-}
-
-/**
- * e_charset_add_radio_actions:
- * @action_group: a #GtkActionGroup
- * @default_charset: the default character set, or %NULL to use the
- * locale character set
- * @callback: a callback function for actions in the group, or %NULL
- * @user_data: user data to be passed to @callback, or %NULL
- *
- * Adds a set of #GtkRadioActions for available character sets to
- * @action_group. The @default_charset (or locale character set if
- * @default_charset is %NULL) will be added first, and selected by
- * default (except that iso-8859-1 will always be used instead of
- * US-ASCII). Any other character sets of the same language class as
- * the default will be added next, followed by the remaining character
- * sets.
- **/
-void
-e_charset_add_radio_actions (GtkActionGroup *action_group,
- const gchar *default_charset,
- GCallback callback,
- gpointer user_data)
-{
- GtkRadioAction *action = NULL;
- GSList *group = NULL;
- const gchar *locale_charset;
- gint def, ii;
-
- g_return_if_fail (GTK_IS_ACTION_GROUP (action_group));
-
- /* XXX I could try to factor out code common to this
- * function and e_charset_picker_bonobo_ui_populate()
- * instead of duplicating it, but I expect the latter
- * function to be obsolete in the foreseeable future. */
-
- g_get_charset (&locale_charset);
- if (!g_ascii_strcasecmp (locale_charset, "US-ASCII"))
- locale_charset = "iso-8859-1";
-
- if (default_charset == NULL)
- default_charset = locale_charset;
- for (def = 0; def < G_N_ELEMENTS (charsets); def++)
- if (!g_ascii_strcasecmp (charsets[def].name, default_charset))
- break;
-
- for (ii = 0; ii < G_N_ELEMENTS (charsets); ii++) {
- gchar *escaped_name;
- gchar *charset_label;
- gchar **str_array;
-
- /* Escape underlines in the character set name so
- * they're not treated as GtkLabel mnemonics. */
- str_array = g_strsplit (charsets[ii].name, "_", -1);
- escaped_name = g_strjoinv ("__", str_array);
- g_strfreev (str_array);
-
- if (charsets[ii].subclass != NULL)
- charset_label = g_strdup_printf (
- "%s, %s (%s)",
- gettext (classnames[charsets[ii].class]),
- gettext (charsets[ii].subclass),
- escaped_name);
- else if (charsets[ii].class != E_CHARSET_UNKNOWN)
- charset_label = g_strdup_printf (
- "%s (%s)",
- gettext (classnames[charsets[ii].class]),
- escaped_name);
- else
- charset_label = g_strdup (escaped_name);
-
- action = gtk_radio_action_new (
- charsets[ii].name, charset_label, NULL, NULL, ii);
-
- gtk_radio_action_set_group (action, group);
- group = gtk_radio_action_get_group (action);
-
- if (callback != NULL)
- g_signal_connect (
- action, "changed", callback, user_data);
-
- gtk_action_group_add_action (
- action_group, GTK_ACTION (action));
-
- g_object_unref (action);
-
- g_free (escaped_name);
- g_free (charset_label);
- }
-
- if (def == G_N_ELEMENTS (charsets)) {
- gchar *charset_label;
- gchar **str_array;
-
- /* Escape underlines in the character set name so
- * they're not treated as GtkLabel mnemonics. */
- str_array = g_strsplit (default_charset, "_", -1);
- charset_label = g_strjoinv ("__", str_array);
- g_strfreev (str_array);
-
- action = gtk_radio_action_new (
- default_charset, charset_label, NULL, NULL, def);
-
- gtk_radio_action_set_group (action, group);
- group = gtk_radio_action_get_group (action);
-
- if (callback != NULL)
- g_signal_connect (
- action, "changed", callback, user_data);
-
- gtk_action_group_add_action (
- action_group, GTK_ACTION (action));
-
- g_object_unref (action);
-
- g_free (charset_label);
- }
-
- /* Any of the actions in the action group will do. */
- if (action != NULL)
- gtk_radio_action_set_current_value (action, def);
-}
-
-/**
- * e_charset_picker_bonobo_ui_populate:
- * @uic: Bonobo UI Component
- * @path: menu path
- * @default_charset: the default character set, or %NULL to use the
- * locale character set.
- * @cb: Callback function
- * @user_data: data to be passed to the callback.
- *
- * This creates a Bonobo UI menu and fills it in with a selection
- * of available character sets. The @default_charset (or locale character
- * set if @default_charset is %NULL) will be listed first, and selected
- * by default (except that iso-8859-1 will always be used instead of
- * US-ASCII). Any other character sets of the same language class as
- * the default will be listed next, followed by the remaining character
- * sets.
- **/
-void
-e_charset_picker_bonobo_ui_populate (BonoboUIComponent *uic, const gchar *path,
- const gchar *default_charset,
- BonoboUIListenerFn cb, gpointer user_data)
-{
- gchar *encoded_label, *label;
- const gchar *locale_charset;
- GString *menuitems;
- gint def, i;
-
- g_get_charset (&locale_charset);
- if (!g_ascii_strcasecmp (locale_charset, "US-ASCII"))
- locale_charset = "iso-8859-1";
-
- if (!default_charset)
- default_charset = locale_charset;
- for (def = 0; def < num_charsets; def++) {
- if (!g_ascii_strcasecmp (charsets[def].name, default_charset))
- break;
- }
-
- label = g_strdup (_("Ch_aracter Encoding"));
- encoded_label = bonobo_ui_util_encode_str (label);
- menuitems = g_string_new ("");
- g_string_append_printf (menuitems, "<submenu name=\"ECharsetPicker\" label=\"%s\">\n",
- encoded_label);
- g_free (encoded_label);
- g_free (label);
-
- for (i = 0; i < num_charsets; i++) {
- gchar *charset_name;
- gchar *command, *u;
-
- /* escape _'s in the charset name so that it doesn't become an underline in a GtkLabel */
- if ((u = strchr (charsets[i].name, '_'))) {
- gint extra = 1;
- const gchar *s;
- gchar *d;
-
- while ((u = strchr (u + 1, '_')))
- extra++;
-
- d = charset_name = g_alloca (strlen (charsets[i].name) + extra + 1);
- s = charsets[i].name;
- while (*s != '\0') {
- if (*s == '_')
- *d++ = '_';
- *d++ = *s++;
- }
- *d = '\0';
- } else {
- charset_name = (gchar *) charsets[i].name;
- }
-
- if (charsets[i].subclass) {
- label = g_strdup_printf ("%s, %s (%s)",
- _(classnames[charsets[i].class]),
- _(charsets[i].subclass),
- charset_name);
- } else if (charsets[i].class) {
- label = g_strdup_printf ("%s (%s)",
- _(classnames[charsets[i].class]),
- charset_name);
- } else {
- label = g_strdup (charset_name);
- }
-
- encoded_label = bonobo_ui_util_encode_str (label);
- g_free (label);
-
- command = g_strdup_printf ("<cmd name=\"Charset-%s\" label=\"%s\" type=\"radio\""
- " group=\"charset_picker\" state=\"%d\"/>\n",
- charsets[i].name, encoded_label, i == def);
-
- bonobo_ui_component_set (uic, "/commands", command, NULL);
- g_free (command);
-
- g_string_append_printf (menuitems, " <menuitem name=\"Charset-%s\" verb=\"\"/>\n",
- charsets[i].name);
-
- g_free (encoded_label);
-
- label = g_strdup_printf ("Charset-%s", charsets[i].name);
- bonobo_ui_component_add_listener (uic, label, cb, user_data);
- g_free (label);
- }
-
- if (def == num_charsets) {
- gchar *command;
- gchar *charset_name, *u;
-
- /* escape _'s in the charset name so that it doesn't become an underline in a GtkLabel */
- if ((u = strchr (default_charset, '_'))) {
- gint extra = 1;
- gchar *s, *d;
-
- while ((u = strchr (u + 1, '_')))
- extra++;
-
- d = charset_name = g_alloca (strlen (default_charset) + extra + 1);
- s = (gchar *) default_charset;
- while (*s != '\0') {
- if (*s == '_')
- *d++ = '_';
- *d++ = *s++;
- }
- *d = '\0';
- } else {
- charset_name = (gchar *) default_charset;
- }
-
- label = g_strdup (charset_name);
- encoded_label = bonobo_ui_util_encode_str (label);
- g_free (label);
-
- command = g_strdup_printf ("<cmd name=\"Charset-%s\" label=\"%s\" type=\"radio\""
- " group=\"charset_picker\" state=\"1\"/>\n",
- default_charset, encoded_label);
-
- bonobo_ui_component_set (uic, "/commands", command, NULL);
- g_free (command);
-
- g_string_append (menuitems, " <separator/>\n");
- g_string_append_printf (menuitems, " <menuitem name=\"Charset-%s\" verb=\"\"/>\n",
- default_charset);
-
- g_free (encoded_label);
-
- label = g_strdup_printf ("Charset-%s", default_charset);
- bonobo_ui_component_add_listener (uic, label, cb, user_data);
- g_free (label);
- }
-
- g_string_append (menuitems, "</submenu>\n");
-
- bonobo_ui_component_set (uic, path, menuitems->str, NULL);
- g_string_free (menuitems, TRUE);
-}
diff --git a/widgets/misc/e-charset-picker.h b/widgets/misc/e-charset-picker.h
deleted file mode 100644
index 04c013bd88..0000000000
--- a/widgets/misc/e-charset-picker.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) version 3.
- *
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-#ifndef E_CHARSETPICKER_H
-#define E_CHARSETPICKER_H
-
-#include <gtk/gtk.h>
-#include <bonobo/bonobo-ui-component.h>
-
-G_BEGIN_DECLS
-
-GtkWidget * e_charset_picker_new (const gchar *default_charset);
-gchar * e_charset_picker_get_charset (GtkWidget *picker);
-gchar * e_charset_picker_dialog (const gchar *title,
- const gchar *prompt,
- const gchar *default_charset,
- GtkWindow *parent);
-
-void e_charset_add_radio_actions (GtkActionGroup *action_group,
- const gchar *default_charset,
- GCallback callback,
- gpointer user_data);
-
-void e_charset_picker_bonobo_ui_populate
- (BonoboUIComponent *uic,
- const gchar *path,
- const gchar *default_charset,
- BonoboUIListenerFn cb,
- gpointer user_data);
-
-G_END_DECLS
-
-#endif /* E_CHARSETPICKER_H */
diff --git a/widgets/misc/e-combo-button.c b/widgets/misc/e-combo-button.c
deleted file mode 100644
index f482f06094..0000000000
--- a/widgets/misc/e-combo-button.c
+++ /dev/null
@@ -1,625 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) version 3.
- *
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- *
- * Authors:
- * Ettore Perazzoli <ettore@ximian.com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "e-combo-button.h"
-#include "ea-widgets.h"
-
-struct _EComboButtonPrivate {
- GdkPixbuf *icon;
-
- GtkWidget *icon_image;
- GtkWidget *label;
- GtkWidget *arrow_image;
- GtkWidget *hbox;
- GtkWidget *vbox;
-
- GtkMenu *menu;
-
- gboolean menu_popped_up;
- gboolean is_already_packed;
-};
-
-#define SPACING 2
-
-enum {
- ACTIVATE_DEFAULT,
- LAST_SIGNAL
-};
-
-static guint signals[LAST_SIGNAL] = { 0 };
-
-G_DEFINE_TYPE (EComboButton, e_combo_button, GTK_TYPE_BUTTON)
-
-/* Utility functions. */
-
-static void
-set_icon (EComboButton *combo_button,
- GdkPixbuf *pixbuf)
-{
- EComboButtonPrivate *priv;
-
- priv = combo_button->priv;
-
- if (priv->icon != NULL)
- g_object_unref (priv->icon);
-
- if (pixbuf == NULL) {
- priv->icon = NULL;
- gtk_widget_hide (priv->icon_image);
- return;
- }
-
- priv->icon = g_object_ref (pixbuf);
-
- gtk_image_set_from_pixbuf (GTK_IMAGE (priv->icon_image), priv->icon);
-
- gtk_widget_show (priv->icon_image);
-}
-
-
-/* Paint the borders. */
-
-static void
-paint (EComboButton *combo_button,
- GdkRectangle *area)
-{
- EComboButtonPrivate *priv = combo_button->priv;
- GtkWidget *widget = GTK_WIDGET (combo_button);
- GtkButton *button = GTK_BUTTON (combo_button);
- GtkShadowType shadow_type;
- gboolean interior_focus;
- gint separator_x;
- gint focus_width, focus_pad;
- gint x, y, width, height;
- gint border_width;
-
- if (GTK_BUTTON (widget)->depressed || priv->menu_popped_up) {
- shadow_type = GTK_SHADOW_IN;
- gtk_widget_set_state (widget, GTK_STATE_ACTIVE);
- } else if (GTK_BUTTON (widget)->relief == GTK_RELIEF_NONE &&
- (GTK_WIDGET_STATE (widget) == GTK_STATE_NORMAL ||
- GTK_WIDGET_STATE (widget) == GTK_STATE_INSENSITIVE))
- shadow_type = GTK_SHADOW_NONE;
- else
- shadow_type = GTK_SHADOW_OUT;
-
- border_width = GTK_CONTAINER (widget)->border_width;
-
- x = widget->allocation.x + border_width;
- y = widget->allocation.y + border_width;
- width = widget->allocation.width - border_width * 2;
- height = widget->allocation.height - border_width * 2;
-
- separator_x = (priv->label->allocation.width
- + priv->label->allocation.x
- + priv->arrow_image->allocation.x) / 2;
-
- gtk_widget_style_get (GTK_WIDGET (widget),
- "focus-line-width", &focus_width,
- "focus-padding", &focus_pad,
- "interior-focus", &interior_focus,
- NULL);
-
- if (GTK_WIDGET_HAS_DEFAULT (widget)
- && GTK_BUTTON (widget)->relief == GTK_RELIEF_NORMAL)
- gtk_paint_box (widget->style, widget->window,
- GTK_STATE_NORMAL, GTK_SHADOW_IN,
- area, widget, "buttondefault",
- x, y, width, height);
-
- if (!interior_focus && GTK_WIDGET_HAS_FOCUS (widget)) {
- x += focus_width + focus_pad;
- y += focus_width + focus_pad;
- width -= 2 * (focus_width + focus_pad);
- height -= 2 * (focus_width + focus_pad);
- }
-
- if (button->relief != GTK_RELIEF_NONE || button->depressed ||
- priv->menu_popped_up ||
- GTK_WIDGET_STATE (widget) == GTK_STATE_PRELIGHT) {
-
- gtk_paint_box (widget->style, widget->window,
- GTK_WIDGET_STATE (widget), shadow_type,
- area, widget, "button",
- x, y, separator_x, height);
-
- if (width - separator_x > 0)
- gtk_paint_box (widget->style, widget->window,
- GTK_WIDGET_STATE (widget), shadow_type,
- area, widget, "button",
- separator_x, y, width - separator_x, height);
- }
-
- if (GTK_WIDGET_HAS_FOCUS (widget)) {
- if (interior_focus) {
- x += widget->style->xthickness + focus_pad;
- y += widget->style->ythickness + focus_pad;
- width -= 2 * (widget->style->xthickness + focus_pad);
- height -= 2 * (widget->style->xthickness + focus_pad);
- } else {
- x -= focus_width + focus_pad;
- y -= focus_width + focus_pad;
- width += 2 * (focus_width + focus_pad);
- height += 2 * (focus_width + focus_pad);
- }
-
- gtk_paint_focus (widget->style, widget->window,
- GTK_WIDGET_STATE (widget),
- area, widget, "button",
- x, y, width, height);
- }
-}
-
-
-/* Callbacks for the associated menu. */
-
-static void
-menu_detacher (GtkWidget *widget,
- GtkMenu *menu)
-{
- EComboButton *combo_button;
- EComboButtonPrivate *priv;
-
- combo_button = E_COMBO_BUTTON (widget);
- priv = combo_button->priv;
- g_signal_handlers_disconnect_matched (menu,
- G_SIGNAL_MATCH_DATA,
- 0, 0, NULL, NULL,
- combo_button);
- priv->menu = NULL;
-}
-
-static void
-menu_deactivate_callback (GtkMenuShell *menu_shell,
- gpointer data)
-{
- EComboButton *combo_button;
- EComboButtonPrivate *priv;
-
- combo_button = E_COMBO_BUTTON (data);
- priv = combo_button->priv;
-
- priv->menu_popped_up = FALSE;
-
- GTK_BUTTON (combo_button)->button_down = FALSE;
- GTK_BUTTON (combo_button)->in_button = FALSE;
- gtk_button_leave (GTK_BUTTON (combo_button));
- gtk_button_clicked (GTK_BUTTON (combo_button));
-}
-
-static void
-menu_position_func (GtkMenu *menu,
- gint *x_return,
- gint *y_return,
- gboolean *push_in,
- gpointer data)
-{
- EComboButton *combo_button;
- GtkAllocation *allocation;
-
- combo_button = E_COMBO_BUTTON (data);
- allocation = & (GTK_WIDGET (combo_button)->allocation);
-
- gdk_window_get_origin (GTK_WIDGET (combo_button)->window, x_return, y_return);
-
- *y_return += allocation->height;
-}
-
-
-/* GtkObject methods. */
-
-static void
-impl_destroy (GtkObject *object)
-{
- EComboButton *combo_button;
- EComboButtonPrivate *priv;
-
- combo_button = E_COMBO_BUTTON (object);
- priv = combo_button->priv;
-
- if (priv) {
- if (priv->arrow_image != NULL) {
- gtk_widget_destroy (priv->arrow_image);
- priv->arrow_image = NULL;
- }
-
- if (priv->icon != NULL) {
- g_object_unref (priv->icon);
- priv->icon = NULL;
- }
-
- g_free (priv);
- combo_button->priv = NULL;
- }
-
- (* GTK_OBJECT_CLASS (e_combo_button_parent_class)->destroy) (object);
-}
-
-
-
-static gboolean
-e_combo_button_popup (EComboButton *combo_button, GdkEventButton *event)
-{
- EComboButtonPrivate *priv;
-
- g_return_val_if_fail (combo_button != NULL, FALSE);
- g_return_val_if_fail (E_IS_COMBO_BUTTON (combo_button), FALSE);
-
- priv = combo_button->priv;
-
- priv->menu_popped_up = TRUE;
-
- if (event)
- gtk_menu_popup (GTK_MENU (priv->menu), NULL, NULL,
- menu_position_func, combo_button,
- event->button, event->time);
- else
- gtk_menu_popup (GTK_MENU (priv->menu), NULL, NULL,
- menu_position_func, combo_button,
- 0, gtk_get_current_event_time());
-
- return TRUE;
-}
-/* GtkWidget methods. */
-
-static gint
-impl_button_press_event (GtkWidget *widget,
- GdkEventButton *event)
-{
- EComboButton *combo_button;
- EComboButtonPrivate *priv;
-
- combo_button = E_COMBO_BUTTON (widget);
- priv = combo_button->priv;
-
- if (event->type == GDK_BUTTON_PRESS &&
- (event->button == 1 || event->button == 3)) {
- GTK_BUTTON (widget)->button_down = TRUE;
-
- if (event->button == 3 ||
- event->x >= priv->arrow_image->allocation.x) {
- /* User clicked on the right side: pop up the menu. */
- gtk_button_pressed (GTK_BUTTON (widget));
-
- e_combo_button_popup (combo_button, event);
- } else {
- /* User clicked on the left side: just behave like a
- normal button (i.e. not a toggle). */
- gtk_button_pressed (GTK_BUTTON (widget));
- }
- }
-
- return TRUE;
-}
-
-static gint
-impl_leave_notify_event (GtkWidget *widget,
- GdkEventCrossing *event)
-{
- EComboButton *combo_button;
- EComboButtonPrivate *priv;
-
- combo_button = E_COMBO_BUTTON (widget);
- priv = combo_button->priv;
-
- /* This is to override the standard behavior of deactivating the button
- when the pointer gets out of the widget, in the case in which we
- have just popped up the menu. Otherwise, the button would look as
- inactive when the menu is popped up. */
- if (! priv->menu_popped_up)
- return (* GTK_WIDGET_CLASS (e_combo_button_parent_class)->leave_notify_event) (widget, event);
-
- return FALSE;
-}
-
-static gint
-impl_expose_event (GtkWidget *widget,
- GdkEventExpose *event)
-{
- GtkBin *bin;
- GdkEventExpose child_event;
-
- if (! GTK_WIDGET_DRAWABLE (widget))
- return FALSE;
-
- bin = GTK_BIN (widget);
-
- paint (E_COMBO_BUTTON (widget), &event->area);
-
- child_event = *event;
- if (bin->child && GTK_WIDGET_NO_WINDOW (bin->child) &&
- gtk_widget_intersect (bin->child, &event->area, &child_event.area))
- gtk_container_propagate_expose (GTK_CONTAINER (widget), bin->child, &child_event);
-
- return FALSE;
-}
-
-
-/* GtkButton methods. */
-
-static void
-impl_released (GtkButton *button)
-{
- EComboButton *combo_button;
- EComboButtonPrivate *priv;
-
- combo_button = E_COMBO_BUTTON (button);
- priv = combo_button->priv;
-
- /* Massive cut & paste from GtkButton here... The only change in
- behavior here is that we want to emit ::activate_default when not
- the menu hasn't been popped up. */
-
- if (button->button_down) {
- gint new_state;
-
- button->button_down = FALSE;
-
- if (button->in_button) {
- gtk_button_clicked (button);
-
- if (! priv->menu_popped_up)
- g_signal_emit (button, signals[ACTIVATE_DEFAULT], 0);
- }
-
- new_state = (button->in_button ? GTK_STATE_PRELIGHT : GTK_STATE_NORMAL);
-
- if (GTK_WIDGET_STATE (button) != new_state) {
- gtk_widget_set_state (GTK_WIDGET (button), new_state);
-
- /* We _draw () instead of queue_draw so that if the
- operation blocks, the label doesn't vanish. */
- /* XXX gtk_widget_draw() is deprecated.
- * Replace it with GTK's implementation. */
- gtk_widget_queue_draw (GTK_WIDGET (button));
- gdk_window_process_updates (
- GTK_WIDGET (button)->window, TRUE);
- }
- }
-}
-
-
-static void
-e_combo_button_class_init (EComboButtonClass *combo_button_class)
-{
- GtkObjectClass *object_class;
- GtkWidgetClass *widget_class;
- GtkButtonClass *button_class;
-
- object_class = GTK_OBJECT_CLASS (combo_button_class);
- object_class->destroy = impl_destroy;
-
- widget_class = GTK_WIDGET_CLASS (object_class);
- widget_class->button_press_event = impl_button_press_event;
- widget_class->leave_notify_event = impl_leave_notify_event;
- widget_class->expose_event = impl_expose_event;
-
- button_class = GTK_BUTTON_CLASS (object_class);
- button_class->released = impl_released;
-
- signals[ACTIVATE_DEFAULT] = g_signal_new ("activate_default",
- G_TYPE_FROM_CLASS (object_class),
- G_SIGNAL_RUN_FIRST,
- G_STRUCT_OFFSET (EComboButtonClass, activate_default),
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
-
- e_combo_button_a11y_init ();
-}
-
-static void
-e_combo_button_init (EComboButton *combo_button)
-{
- EComboButtonPrivate *priv;
-
- priv = g_new (EComboButtonPrivate, 1);
- combo_button->priv = priv;
-
- priv->icon = NULL;
- priv->menu = NULL;
- priv->menu_popped_up = FALSE;
- priv->is_already_packed = FALSE;
-}
-
-void
-e_combo_button_pack_hbox (EComboButton *combo_button)
-{
- EComboButtonPrivate *priv;
-
- priv = combo_button->priv;
-
- if(priv->is_already_packed){
- gtk_widget_destroy (priv->hbox);
- }
-
- priv->hbox = gtk_hbox_new (FALSE, SPACING);
- gtk_container_add (GTK_CONTAINER (combo_button), priv->hbox);
- gtk_widget_show (priv->hbox);
-
- priv->icon_image = gtk_image_new_from_stock (
- GTK_STOCK_MISSING_IMAGE, GTK_ICON_SIZE_MENU);
- gtk_box_pack_start (GTK_BOX (priv->hbox), priv->icon_image, TRUE, TRUE, 0);
- gtk_widget_show (priv->icon_image);
-
- priv->label = gtk_label_new ("");
- gtk_box_pack_start (GTK_BOX (priv->hbox), priv->label, TRUE, TRUE,
- 0);
- gtk_widget_show (priv->label);
-
- priv->arrow_image = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
- gtk_box_pack_end (GTK_BOX (priv->hbox), priv->arrow_image, TRUE, TRUE,
- GTK_WIDGET (combo_button)->style->xthickness);
- gtk_widget_show (priv->arrow_image);
-
- gtk_widget_show (priv->hbox);
-
- priv->is_already_packed = TRUE;
-}
-
-void
-e_combo_button_pack_vbox (EComboButton *combo_button)
-{
- EComboButtonPrivate *priv;
-
- priv = combo_button->priv;
-
- if(priv->is_already_packed){
- gtk_widget_destroy (priv->hbox);
- }
-
- priv->hbox = gtk_hbox_new (FALSE, SPACING);
- gtk_container_add (GTK_CONTAINER (combo_button), priv->hbox);
- gtk_widget_show (priv->hbox);
-
- priv->vbox = gtk_vbox_new (FALSE, 0);
- gtk_widget_show (priv->vbox);
-
- priv->icon_image = gtk_image_new_from_stock (
- GTK_STOCK_MISSING_IMAGE, GTK_ICON_SIZE_MENU);
- gtk_box_pack_start (GTK_BOX (priv->vbox), priv->icon_image, TRUE, TRUE, 0);
- gtk_widget_show (priv->icon_image);
-
- priv->label = gtk_label_new ("");
- gtk_box_pack_start (GTK_BOX (priv->vbox), priv->label, TRUE, TRUE,
- 0);
- gtk_widget_show (priv->label);
-
- gtk_box_pack_start (GTK_BOX(priv->hbox),priv->vbox, TRUE, TRUE, 0);
-
- priv->arrow_image = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
- gtk_box_pack_end (GTK_BOX (priv->hbox), priv->arrow_image, TRUE, TRUE,
- GTK_WIDGET (combo_button)->style->xthickness);
- gtk_widget_show (priv->arrow_image);
-
- gtk_widget_show (priv->hbox);
-
- priv->is_already_packed = TRUE;
-}
-
-
-void
-e_combo_button_construct (EComboButton *combo_button)
-{
- EComboButtonPrivate *priv;
-
- g_return_if_fail (combo_button != NULL);
- g_return_if_fail (E_IS_COMBO_BUTTON (combo_button));
-
- priv = combo_button->priv;
- g_return_if_fail (priv->menu == NULL);
-
- GTK_WIDGET_UNSET_FLAGS (combo_button, GTK_CAN_FOCUS);
-
- gtk_button_set_relief (GTK_BUTTON (combo_button), GTK_RELIEF_NONE);
-}
-
-GtkWidget *
-e_combo_button_new (void)
-{
- EComboButton *new;
-
- new = g_object_new (e_combo_button_get_type (), NULL);
- e_combo_button_construct (new);
-
- return GTK_WIDGET (new);
-}
-
-
-void
-e_combo_button_set_icon (EComboButton *combo_button,
- GdkPixbuf *pixbuf)
-{
- g_return_if_fail (combo_button != NULL);
- g_return_if_fail (E_IS_COMBO_BUTTON (combo_button));
-
- set_icon (combo_button, pixbuf);
-}
-
-void
-e_combo_button_set_label (EComboButton *combo_button,
- const gchar *label)
-{
- EComboButtonPrivate *priv;
-
- g_return_if_fail (combo_button != NULL);
- g_return_if_fail (E_IS_COMBO_BUTTON (combo_button));
-
- priv = combo_button->priv;
-
- if (label == NULL)
- label = "";
-
- gtk_label_set_label (GTK_LABEL (priv->label), label);
- gtk_label_set_use_markup (GTK_LABEL (priv->label), FALSE);
- gtk_label_set_use_underline (GTK_LABEL (priv->label), TRUE);
-}
-
-void
-e_combo_button_set_menu (EComboButton *combo_button,
- GtkMenu *menu)
-{
- EComboButtonPrivate *priv;
-
- g_return_if_fail (combo_button != NULL);
- g_return_if_fail (E_IS_COMBO_BUTTON (combo_button));
- g_return_if_fail (menu != NULL);
- g_return_if_fail (GTK_IS_MENU (menu));
-
- priv = combo_button->priv;
-
- if (priv->menu != NULL)
- gtk_menu_detach (priv->menu);
-
- priv->menu = menu;
- if (menu == NULL)
- return;
-
- gtk_menu_attach_to_widget (menu, GTK_WIDGET (combo_button), menu_detacher);
-
- g_signal_connect((menu), "deactivate",
- G_CALLBACK (menu_deactivate_callback),
- combo_button);
-}
-
-GtkWidget *
-e_combo_button_get_label (EComboButton *combo_button)
-{
- EComboButtonPrivate *priv;
-
- g_return_val_if_fail (combo_button != NULL, NULL);
- g_return_val_if_fail (E_IS_COMBO_BUTTON (combo_button), NULL);
-
- priv = combo_button->priv;
-
- return priv->label;
-}
-
-gboolean
-e_combo_button_popup_menu (EComboButton *combo_button)
-{
- return e_combo_button_popup (combo_button, NULL);
-}
diff --git a/widgets/misc/e-combo-button.h b/widgets/misc/e-combo-button.h
deleted file mode 100644
index 29d4b2efe7..0000000000
--- a/widgets/misc/e-combo-button.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) version 3.
- *
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- *
- * Authors:
- * Ettore Perazzoli <ettore@ximian.com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-#ifndef _E_COMBO_BUTTON_H_
-#define _E_COMBO_BUTTON_H_
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <gtk/gtk.h>
-
-G_BEGIN_DECLS
-
-#define E_TYPE_COMBO_BUTTON (e_combo_button_get_type ())
-#define E_COMBO_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_COMBO_BUTTON, EComboButton))
-#define E_COMBO_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E_TYPE_COMBO_BUTTON, EComboButtonClass))
-#define E_IS_COMBO_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_TYPE_COMBO_BUTTON))
-#define E_IS_COMBO_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), E_TYPE_COMBO_BUTTON))
-
-
-typedef struct _EComboButton EComboButton;
-typedef struct _EComboButtonPrivate EComboButtonPrivate;
-typedef struct _EComboButtonClass EComboButtonClass;
-
-struct _EComboButton {
- GtkButton parent;
-
- EComboButtonPrivate *priv;
-};
-
-struct _EComboButtonClass {
- GtkButtonClass parent_class;
-
- /* Signals. */
- void (* activate_default) (EComboButton *combo_button);
-};
-
-
-GType e_combo_button_get_type (void);
-void e_combo_button_construct (EComboButton *combo_button);
-GtkWidget *e_combo_button_new (void);
-
-void e_combo_button_set_icon (EComboButton *combo_button,
- GdkPixbuf *pixbuf);
-void e_combo_button_set_label (EComboButton *combo_button,
- const gchar *label);
-void e_combo_button_set_menu (EComboButton *combo_button,
- GtkMenu *menu);
-void e_combo_button_pack_vbox (EComboButton *combo_button);
-void e_combo_button_pack_hbox (EComboButton *combo_button);
-
-GtkWidget *e_combo_button_get_label (EComboButton *combo_button);
-
-gboolean e_combo_button_popup_menu (EComboButton *combo_button);
-
-G_END_DECLS
-
-#endif /* _E_COMBO_BUTTON_H_ */
diff --git a/widgets/misc/e-config-page.h b/widgets/misc/e-config-page.h
deleted file mode 100644
index 1de9591397..0000000000
--- a/widgets/misc/e-config-page.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) version 3.
- *
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- *
- * Authors:
- * Ettore Perazzoli <ettore@ximian.com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-#ifndef _E_CONFIG_PAGE_H_
-#define _E_CONFIG_PAGE_H_
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <gtk/gtk.h>
-
-G_BEGIN_DECLS
-
-#define E_TYPE_CONFIG_PAGE (e_config_page_get_type ())
-#define E_CONFIG_PAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_CONFIG_PAGE, EConfigPage))
-#define E_CONFIG_PAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E_TYPE_CONFIG_PAGE, EConfigPageClass))
-#define E_IS_CONFIG_PAGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_TYPE_CONFIG_PAGE))
-#define E_IS_CONFIG_PAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), E_TYPE_CONFIG_PAGE))
-
-
-typedef struct _EConfigPage EConfigPage;
-typedef struct _EConfigPagePrivate EConfigPagePrivate;
-typedef struct _EConfigPageClass EConfigPageClass;
-
-struct _EConfigPage {
- GtkEventBox parent;
-
- EConfigPagePrivate *priv;
-};
-
-struct _EConfigPageClass {
- GtkEventBoxClass parent_class;
-
-};
-
-
-GType e_config_page_get_type (void);
-GtkWidget *e_config_page_new (void);
-
-G_END_DECLS
-
-#endif /* _E_CONFIG_PAGE_H_ */
diff --git a/widgets/misc/e-dropdown-button.c b/widgets/misc/e-dropdown-button.c
deleted file mode 100644
index 98c64f4ea7..0000000000
--- a/widgets/misc/e-dropdown-button.c
+++ /dev/null
@@ -1,237 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) version 3.
- *
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- *
- * Authors:
- * Ettore Perazzoli <ettore@ximian.com>
- * Damon Chaplin <damon@ximian.com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "e-dropdown-button.h"
-
-#include <stdio.h>
-
-struct _EDropdownButtonPrivate {
- GtkAccelGroup *accel_group;
- GtkWidget *menu;
-};
-
-G_DEFINE_TYPE (EDropdownButton, e_dropdown_button, GTK_TYPE_TOGGLE_BUTTON)
-
-/* Callback to position the pop-up menu. */
-
-static void
-menu_position_cb (GtkMenu *menu,
- gint *x,
- gint *y,
- gboolean *push_in,
- gpointer data)
-{
- EDropdownButton *dropdown_button;
- EDropdownButtonPrivate *priv;
- GtkRequisition menu_requisition;
- gint max_x, max_y;
-
- dropdown_button = E_DROPDOWN_BUTTON (data);
- priv = dropdown_button->priv;
-
- /* Calculate our preferred position. */
- gdk_window_get_origin (GTK_WIDGET (dropdown_button)->window, x, y);
- *y += GTK_WIDGET (dropdown_button)->allocation.height;
-
- /* Now make sure we are on the screen. */
- gtk_widget_size_request (GTK_WIDGET (priv->menu), &menu_requisition);
- max_x = MAX (0, gdk_screen_width () - menu_requisition.width);
- max_y = MAX (0, gdk_screen_height () - menu_requisition.height);
-
- *x = CLAMP (*x, 0, max_x);
- *y = CLAMP (*y, 0, max_y);
-}
-
-/* Callback for the "deactivate" signal on the pop-up menu. This is used so
- that we unset the state of the toggle button when the pop-up menu
- disappears. */
-
-static gint
-menu_deactivate_cb (GtkMenuShell *menu_shell,
- gpointer data)
-{
- EDropdownButton *dropdown_button;
-
- dropdown_button = E_DROPDOWN_BUTTON (data);
-
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dropdown_button), FALSE);
- return TRUE;
-}
-
-
-/* GtkObject methods. */
-
-static void
-impl_destroy (GtkObject *object)
-{
- EDropdownButton *dropdown_button;
- EDropdownButtonPrivate *priv;
-
- dropdown_button = E_DROPDOWN_BUTTON (object);
- priv = dropdown_button->priv;
-
- g_object_unref (priv->accel_group);
- gtk_widget_destroy (priv->menu);
-
- g_free (priv);
-
- if (GTK_OBJECT_CLASS (e_dropdown_button_parent_class)->destroy)
- (* GTK_OBJECT_CLASS (e_dropdown_button_parent_class)->destroy) (object);
-}
-
-
-/* GtkWidget methods. */
-
-static void
-impl_toggled (GtkToggleButton *toggle_button)
-{
- EDropdownButton *dropdown_button;
- EDropdownButtonPrivate *priv;
-
- if (GTK_TOGGLE_BUTTON_CLASS (e_dropdown_button_parent_class)->toggled)
- GTK_TOGGLE_BUTTON_CLASS (e_dropdown_button_parent_class)->toggled (toggle_button);
-
- dropdown_button = E_DROPDOWN_BUTTON (toggle_button);
- priv = dropdown_button->priv;
-
- if (toggle_button->active) {
- gtk_menu_popup (GTK_MENU (priv->menu), NULL, NULL,
- menu_position_cb, dropdown_button,
- 1, GDK_CURRENT_TIME);
- } else {
- gtk_menu_popdown (GTK_MENU (priv->menu));
- }
-}
-
-
-static void
-e_dropdown_button_class_init (EDropdownButtonClass *klass)
-{
- GtkObjectClass *object_class;
- GtkToggleButtonClass *toggle_class;
-
- object_class = GTK_OBJECT_CLASS (klass);
- toggle_class = GTK_TOGGLE_BUTTON_CLASS (klass);
-
- object_class->destroy = impl_destroy;
- toggle_class->toggled = impl_toggled;
-}
-
-
-static void
-e_dropdown_button_init (EDropdownButton *dropdown_button)
-{
- EDropdownButtonPrivate *priv;
-
- priv = g_new (EDropdownButtonPrivate, 1);
- priv->accel_group = gtk_accel_group_new ();
- priv->menu = NULL;
-
- dropdown_button->priv = priv;
-}
-
-
-/**
- * e_dropdown_button_construct:
- * @dropdown_button: A pointer to an %EDropdownButton object
- * @label_text: Text to display in the button
- * @menu: The menu to pop up when the button is pressed
- *
- * Construct the @dropdown_button with the specified @label_text and the
- * associated @menu.
- **/
-void
-e_dropdown_button_construct (EDropdownButton *dropdown_button,
- const gchar *label_text,
- GtkMenu *menu)
-{
- EDropdownButtonPrivate *priv;
- GtkWidget *hbox;
- GtkWidget *arrow;
- GtkWidget *label;
- guint accel_key;
-
- g_return_if_fail (dropdown_button != NULL);
- g_return_if_fail (E_IS_DROPDOWN_BUTTON (dropdown_button));
- g_return_if_fail (label_text != NULL);
- g_return_if_fail (menu != NULL);
- g_return_if_fail (GTK_IS_MENU (menu));
-
- priv = dropdown_button->priv;
-
- hbox = gtk_hbox_new (FALSE, 2);
- gtk_container_add (GTK_CONTAINER (dropdown_button), hbox);
- gtk_widget_show (hbox);
-
- label = gtk_label_new ("");
- gtk_label_set_label (GTK_LABEL (label), label_text);
- gtk_label_set_use_markup (GTK_LABEL (label), FALSE);
- gtk_label_set_use_underline (GTK_LABEL (label), TRUE);
-
- accel_key = gtk_label_get_mnemonic_keyval (GTK_LABEL (label));
- gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 0);
- gtk_widget_show (label);
- gtk_widget_add_accelerator (GTK_WIDGET (dropdown_button), "clicked",
- priv->accel_group, accel_key, GDK_MOD1_MASK, 0);
-
- arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
- gtk_box_pack_start (GTK_BOX (hbox), arrow, FALSE, FALSE, 2);
- gtk_widget_show (arrow);
-
- priv->menu = GTK_WIDGET (menu);
-
- g_signal_connect_object (priv->menu, "deactivate",
- G_CALLBACK (menu_deactivate_cb),
- dropdown_button, 0);
-}
-
-/**
- * e_dropdown_button_new:
- * @label_text: Text to display in the button
- * @menu: The menu to pop up when the button is pressed
- *
- * Create a new dropdown button. When the button is clicked, the specified
- * @menu will be popped up.
- *
- * Return value: A pointer to the newly created %EDropdownButton.
- **/
-GtkWidget *
-e_dropdown_button_new (const gchar *label_text,
- GtkMenu *menu)
-{
- GtkWidget *widget;
-
- g_return_val_if_fail (label_text != NULL, NULL);
- g_return_val_if_fail (menu != NULL, NULL);
- g_return_val_if_fail (GTK_IS_MENU (menu), NULL);
-
- widget = g_object_new (e_dropdown_button_get_type (), NULL);
-
- e_dropdown_button_construct (E_DROPDOWN_BUTTON (widget), label_text, menu);
- return widget;
-}
-
diff --git a/widgets/misc/e-dropdown-button.h b/widgets/misc/e-dropdown-button.h
deleted file mode 100644
index f58cd73085..0000000000
--- a/widgets/misc/e-dropdown-button.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) version 3.
- *
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- *
- * Authors:
- * Ettore Perazzoli <ettore@ximian.com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-#ifndef _E_DROPDOWN_BUTTON_H_
-#define _E_DROPDOWN_BUTTON_H_
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <gtk/gtk.h>
-
-G_BEGIN_DECLS
-
-#define E_TYPE_DROPDOWN_BUTTON (e_dropdown_button_get_type ())
-#define E_DROPDOWN_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_DROPDOWN_BUTTON, EDropdownButton))
-#define E_DROPDOWN_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E_TYPE_DROPDOWN_BUTTON, EDropdownButtonClass))
-#define E_IS_DROPDOWN_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_TYPE_DROPDOWN_BUTTON))
-#define E_IS_DROPDOWN_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), E_TYPE_DROPDOWN_BUTTON))
-
-
-typedef struct _EDropdownButton EDropdownButton;
-typedef struct _EDropdownButtonPrivate EDropdownButtonPrivate;
-typedef struct _EDropdownButtonClass EDropdownButtonClass;
-
-struct _EDropdownButton {
- GtkToggleButton parent;
-
- EDropdownButtonPrivate *priv;
-};
-
-struct _EDropdownButtonClass {
- GtkToggleButtonClass parent_class;
-};
-
-
-GType e_dropdown_button_get_type (void);
-void e_dropdown_button_construct (EDropdownButton *dropdown_button,
- const gchar *label_text,
- GtkMenu *menu);
-GtkWidget *e_dropdown_button_new (const gchar *label_text,
- GtkMenu *menu);
-
-G_END_DECLS
-
-#endif /* _E_DROPDOWN_BUTTON_H_ */
diff --git a/widgets/misc/e-file-activity.c b/widgets/misc/e-file-activity.c
new file mode 100644
index 0000000000..e35ab4955c
--- /dev/null
+++ b/widgets/misc/e-file-activity.c
@@ -0,0 +1,365 @@
+/*
+ * e-file-activity.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#include "e-file-activity.h"
+
+#include <stdarg.h>
+
+#define E_FILE_ACTIVITY_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), E_TYPE_FILE_ACTIVITY, EFileActivityPrivate))
+
+struct _EFileActivityPrivate {
+ GCancellable *cancellable;
+ GAsyncResult *result;
+ GFile *file;
+
+ gulong handler_id;
+};
+
+enum {
+ PROP_0,
+ PROP_CANCELLABLE,
+ PROP_FILE,
+ PROP_RESULT
+};
+
+static gpointer parent_class;
+
+static void
+file_activity_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_CANCELLABLE:
+ e_file_activity_set_cancellable (
+ E_FILE_ACTIVITY (object),
+ g_value_get_object (value));
+ return;
+
+ case PROP_FILE:
+ e_file_activity_set_file (
+ E_FILE_ACTIVITY (object),
+ g_value_get_object (value));
+ return;
+
+ case PROP_RESULT:
+ e_file_activity_set_result (
+ E_FILE_ACTIVITY (object),
+ g_value_get_object (value));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+file_activity_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_CANCELLABLE:
+ g_value_set_object (
+ value, e_file_activity_get_cancellable (
+ E_FILE_ACTIVITY (object)));
+ return;
+
+ case PROP_FILE:
+ g_value_set_object (
+ value, e_file_activity_get_file (
+ E_FILE_ACTIVITY (object)));
+ return;
+
+ case PROP_RESULT:
+ g_value_set_object (
+ value, e_file_activity_get_result (
+ E_FILE_ACTIVITY (object)));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+file_activity_dispose (GObject *object)
+{
+ EFileActivityPrivate *priv;
+
+ priv = E_FILE_ACTIVITY_GET_PRIVATE (object);
+
+ if (priv->cancellable != NULL) {
+ g_signal_handler_disconnect (
+ priv->cancellable, priv->handler_id);
+ g_object_unref (priv->cancellable);
+ priv->cancellable = NULL;
+ }
+
+ if (priv->result != NULL) {
+ g_object_unref (priv->result);
+ priv->result = NULL;
+ }
+
+ if (priv->file != NULL) {
+ g_object_unref (priv->file);
+ priv->file = NULL;
+ }
+
+ /* Chain up to parent's dispose() method. */
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+file_activity_cancelled (EActivity *activity)
+{
+ EFileActivity *file_activity;
+ GCancellable *cancellable;
+
+ file_activity = E_FILE_ACTIVITY (activity);
+ cancellable = e_file_activity_get_cancellable (file_activity);
+ g_cancellable_cancel (cancellable);
+
+ /* Chain up to parent's cancelled() method. */
+ E_ACTIVITY_CLASS (parent_class)->cancelled (activity);
+}
+
+static void
+file_activity_class_init (EFileActivityClass *class)
+{
+ GObjectClass *object_class;
+ EActivityClass *activity_class;
+
+ parent_class = g_type_class_peek_parent (class);
+ g_type_class_add_private (class, sizeof (EFileActivityPrivate));
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->set_property = file_activity_set_property;
+ object_class->get_property = file_activity_get_property;
+ object_class->dispose = file_activity_dispose;
+
+ activity_class = E_ACTIVITY_CLASS (class);
+ activity_class->cancelled = file_activity_cancelled;
+
+ g_object_class_install_property (
+ object_class,
+ PROP_CANCELLABLE,
+ g_param_spec_object (
+ "cancellable",
+ "Cancellable",
+ NULL,
+ G_TYPE_CANCELLABLE,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_FILE,
+ g_param_spec_object (
+ "file",
+ "File",
+ NULL,
+ G_TYPE_FILE,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_RESULT,
+ g_param_spec_object (
+ "result",
+ "Result",
+ NULL,
+ G_TYPE_ASYNC_RESULT,
+ G_PARAM_READWRITE));
+}
+
+static void
+file_activity_init (EFileActivity *file_activity)
+{
+ GCancellable *cancellable;
+
+ file_activity->priv = E_FILE_ACTIVITY_GET_PRIVATE (file_activity);
+
+ e_activity_set_allow_cancel (E_ACTIVITY (file_activity), TRUE);
+
+ cancellable = g_cancellable_new ();
+ e_file_activity_set_cancellable (file_activity, cancellable);
+ g_object_unref (cancellable);
+}
+
+GType
+e_file_activity_get_type (void)
+{
+ static GType type = 0;
+
+ if (G_UNLIKELY (type == 0)) {
+ static const GTypeInfo type_info = {
+ sizeof (EFileActivityClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) file_activity_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+ sizeof (EFileActivity),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) file_activity_init,
+ NULL /* value_table */
+ };
+
+ type = g_type_register_static (
+ E_TYPE_ACTIVITY, "EFileActivity", &type_info, 0);
+ }
+
+ return type;
+}
+
+EActivity *
+e_file_activity_new (const gchar *primary_text)
+{
+ return g_object_new (
+ E_TYPE_FILE_ACTIVITY,
+ "primary-text", primary_text, NULL);
+}
+
+EActivity *
+e_file_activity_newv (const gchar *format, ...)
+{
+ EActivity *activity;
+ gchar *primary_text;
+ va_list args;
+
+ va_start (args, format);
+ primary_text = g_strdup_vprintf (format, args);
+ activity = e_file_activity_new (primary_text);
+ g_free (primary_text);
+ va_end (args);
+
+ return activity;
+}
+
+GCancellable *
+e_file_activity_get_cancellable (EFileActivity *file_activity)
+{
+ g_return_val_if_fail (E_IS_FILE_ACTIVITY (file_activity), NULL);
+
+ return file_activity->priv->cancellable;
+}
+
+void
+e_file_activity_set_cancellable (EFileActivity *file_activity,
+ GCancellable *cancellable)
+{
+ g_return_if_fail (E_IS_FILE_ACTIVITY (file_activity));
+
+ if (cancellable != NULL) {
+ g_return_if_fail (G_IS_CANCELLABLE (cancellable));
+ g_object_ref (cancellable);
+ }
+
+ if (file_activity->priv->cancellable != NULL) {
+ g_signal_handler_disconnect (
+ file_activity->priv->cancellable,
+ file_activity->priv->handler_id);
+ g_object_unref (file_activity->priv->cancellable);
+ file_activity->priv->handler_id = 0;
+ }
+
+ file_activity->priv->cancellable = cancellable;
+
+ if (cancellable != NULL)
+ file_activity->priv->handler_id =
+ g_signal_connect_swapped (
+ cancellable, "cancelled",
+ G_CALLBACK (e_activity_cancel),
+ file_activity);
+
+ g_object_notify (G_OBJECT (file_activity), "cancellable");
+}
+
+GFile *
+e_file_activity_get_file (EFileActivity *file_activity)
+{
+ g_return_val_if_fail (E_IS_FILE_ACTIVITY (file_activity), NULL);
+
+ return file_activity->priv->file;
+}
+
+void
+e_file_activity_set_file (EFileActivity *file_activity,
+ GFile *file)
+{
+ g_return_if_fail (E_IS_FILE_ACTIVITY (file_activity));
+
+ if (file != NULL) {
+ g_return_if_fail (G_IS_FILE (file));
+ g_object_ref (file);
+ }
+
+ if (file_activity->priv->file != NULL)
+ g_object_unref (file_activity->priv->file);
+
+ file_activity->priv->file = file;
+
+ g_object_notify (G_OBJECT (file_activity), "file");
+}
+
+GAsyncResult *
+e_file_activity_get_result (EFileActivity *file_activity)
+{
+ g_return_val_if_fail (E_IS_FILE_ACTIVITY (file_activity), NULL);
+
+ return file_activity->priv->result;
+}
+
+void
+e_file_activity_set_result (EFileActivity *file_activity,
+ GAsyncResult *result)
+{
+ g_return_if_fail (E_IS_FILE_ACTIVITY (file_activity));
+
+ if (result != NULL) {
+ g_return_if_fail (G_IS_ASYNC_RESULT (result));
+ g_object_ref (result);
+ }
+
+ if (file_activity->priv->result != NULL)
+ g_object_unref (file_activity->priv->result);
+
+ file_activity->priv->result = result;
+
+ g_object_notify (G_OBJECT (file_activity), "result");
+}
+
+void
+e_file_activity_progress (goffset current_num_bytes,
+ goffset total_num_bytes,
+ gpointer activity)
+{
+ gdouble percent = -1.0;
+
+ g_return_if_fail (E_IS_ACTIVITY (activity));
+
+ if (current_num_bytes > 0 && total_num_bytes > 0)
+ percent = (gdouble) current_num_bytes / total_num_bytes;
+
+ e_activity_set_percent (activity, percent);
+}
diff --git a/widgets/misc/e-file-activity.h b/widgets/misc/e-file-activity.h
new file mode 100644
index 0000000000..b4a5433c21
--- /dev/null
+++ b/widgets/misc/e-file-activity.h
@@ -0,0 +1,83 @@
+/*
+ * e-file-activity.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef E_FILE_ACTIVITY_H
+#define E_FILE_ACTIVITY_H
+
+#include <gio/gio.h>
+#include <widgets/misc/e-activity.h>
+
+/* Standard GObject macros */
+#define E_TYPE_FILE_ACTIVITY \
+ (e_file_activity_get_type ())
+#define E_FILE_ACTIVITY(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_FILE_ACTIVITY, EFileActivity))
+#define E_FILE_ACTIVITY_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_FILE_ACTIVITY, EFileActivityClass))
+#define E_IS_FILE_ACTIVITY(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_FILE_ACTIVITY))
+#define E_IS_FILE_ACTIVITY_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_FILE_ACTIVITY))
+#define E_FILE_ACTIVITY_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_FILE_ACTIVITY, EFileActivityClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EFileActivity EFileActivity;
+typedef struct _EFileActivityClass EFileActivityClass;
+typedef struct _EFileActivityPrivate EFileActivityPrivate;
+
+struct _EFileActivity {
+ EActivity parent;
+ EFileActivityPrivate *priv;
+};
+
+struct _EFileActivityClass {
+ EActivityClass parent_class;
+};
+
+GType e_file_activity_get_type (void);
+EActivity * e_file_activity_new (const gchar *primary_text);
+EActivity * e_file_activity_newv (const gchar *format,
+ ...) G_GNUC_PRINTF (1, 2);
+GCancellable * e_file_activity_get_cancellable (EFileActivity *file_activity);
+void e_file_activity_set_cancellable (EFileActivity *file_activity,
+ GCancellable *cancellable);
+GFile * e_file_activity_get_file (EFileActivity *file_activity);
+void e_file_activity_set_file (EFileActivity *file_activity,
+ GFile *file);
+GAsyncResult * e_file_activity_get_result (EFileActivity *file_activity);
+void e_file_activity_set_result (EFileActivity *file_activity,
+ GAsyncResult *result);
+
+/* This can be used as a GFileProgressCallback. */
+void e_file_activity_progress (goffset current_num_bytes,
+ goffset total_num_bytes,
+ gpointer activity);
+
+G_END_DECLS
+
+#endif /* E_FILE_ACTIVITY_H */
diff --git a/widgets/misc/e-filter-bar.c b/widgets/misc/e-filter-bar.c
deleted file mode 100644
index 87725cd498..0000000000
--- a/widgets/misc/e-filter-bar.c
+++ /dev/null
@@ -1,1039 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) version 3.
- *
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- *
- * Authors:
- * Michael Zucchi <notzed@ximian.com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <string.h>
-
-#include <libxml/tree.h>
-#include <libxml/parser.h>
-
-#include <glib/gi18n.h>
-
-#include "e-dropdown-button.h"
-#include "e-filter-bar.h"
-#include "filter/rule-editor.h"
-
-#define d(x)
-
-enum {
- LAST_SIGNAL
-};
-
-/*static gint esb_signals [LAST_SIGNAL] = { 0, };*/
-
-static ESearchBarClass *parent_class = NULL;
-
-/* The arguments we take */
-enum {
- PROP_0,
- PROP_QUERY,
- PROP_STATE
-};
-
-
-/* Callbacks. */
-
-static void rule_changed (FilterRule *rule, gpointer user_data);
-
-
-/* rule editor thingy */
-static void
-rule_editor_destroyed (EFilterBar *efb, GObject *deadbeef)
-{
- efb->save_dialog = NULL;
- e_search_bar_set_menu_sensitive (E_SEARCH_BAR (efb), E_FILTERBAR_SAVE_ID, TRUE);
-}
-
-/* FIXME: need to update the popup menu to match any edited rules, sigh */
-static void
-full_rule_editor_response (GtkWidget *dialog, gint response, gpointer data)
-{
- EFilterBar *efb = data;
-
- if (response == GTK_RESPONSE_OK)
- rule_context_save (efb->context, efb->userrules);
-
- gtk_widget_destroy (dialog);
-}
-
-static void
-rule_editor_response (GtkWidget *dialog, gint response, gpointer data)
-{
- EFilterBar *efb = data;
- FilterRule *rule;
-
- if (response == GTK_RESPONSE_OK) {
- rule = g_object_get_data (G_OBJECT (dialog), "rule");
- if (rule) {
- if (!filter_rule_validate (rule))
- return;
-
- rule_context_add_rule (efb->context, rule);
- /* FIXME: check return */
- rule_context_save (efb->context, efb->userrules);
- }
- }
-
- gtk_widget_destroy (dialog);
-}
-
-static void
-rule_advanced_response (GtkWidget *dialog, gint response, gpointer data)
-{
- EFilterBar *efb = data;
- /* the below generates a compiler warning about incompatible pointer types */
- ESearchBar *esb = (ESearchBar *)efb;
- FilterRule *rule;
-
- if (response == GTK_RESPONSE_OK || response == GTK_RESPONSE_APPLY) {
- rule = g_object_get_data ((GObject *) dialog, "rule");
- if (rule) {
- GtkStyle *style = gtk_widget_get_default_style ();
-
- if (!filter_rule_validate (rule))
- return;
-
- efb->current_query = rule;
- g_object_ref (rule);
-
- gtk_widget_modify_base (esb->entry, GTK_STATE_NORMAL, &(style->base[GTK_STATE_SELECTED]));
- gtk_widget_modify_text (esb->entry, GTK_STATE_NORMAL, &(style->text[GTK_STATE_SELECTED]));
- gtk_widget_modify_base (esb->icon_entry, GTK_STATE_NORMAL, &(style->base[GTK_STATE_SELECTED]));
- gtk_widget_modify_base (esb->viewoption, GTK_STATE_NORMAL, &(style->base[GTK_STATE_SELECTED]));
- e_search_bar_set_text (esb,_("Advanced Search"));
- gtk_widget_set_sensitive (esb->clear_button, TRUE);
-
- g_signal_emit_by_name (efb, "search_activated");
-
- if (response == GTK_RESPONSE_APPLY) {
- if (!rule_context_find_rule (efb->context, rule->name, rule->source))
- rule_context_add_rule (efb->context, rule);
- /* FIXME: check return */
- rule_context_save (efb->context, efb->userrules);
- }
- }
- } else {
- e_search_bar_set_item_id (esb, esb->last_search_option);
- }
-
- if (response != GTK_RESPONSE_APPLY)
- gtk_widget_destroy (dialog);
-}
-
-static void
-dialog_rule_changed (FilterRule *fr, GtkWidget *dialog)
-{
- gboolean sensitive;
-
- g_return_if_fail (dialog != NULL);
-
- sensitive = fr && fr->parts;
- gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, sensitive);
- gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_APPLY, sensitive);
-}
-
-static void
-do_advanced (ESearchBar *esb)
-{
- EFilterBar *efb = (EFilterBar *)esb;
-
- d(printf("Advanced search!\n"));
-
- if (!efb->save_dialog && !efb->setquery) {
- GtkWidget *dialog, *w;
- FilterRule *rule;
-
- if (efb->current_query)
- rule = filter_rule_clone (efb->current_query);
- else {
- rule = filter_rule_new ();
- efb->current_query = rule;
- }
-
- w = filter_rule_get_widget (rule, efb->context);
- filter_rule_set_source (rule, FILTER_SOURCE_INCOMING);
- gtk_container_set_border_width (GTK_CONTAINER (w), 12);
-
- /* FIXME: get the toplevel window... */
- dialog = gtk_dialog_new_with_buttons (_("Advanced Search"), NULL, GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_STOCK_SAVE, GTK_RESPONSE_APPLY,
- GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
- GTK_STOCK_OK, GTK_RESPONSE_OK, NULL);
-
- efb->save_dialog = dialog;
- gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
-
- gtk_window_set_resizable (GTK_WINDOW (dialog), TRUE);
- gtk_window_set_default_size (GTK_WINDOW (dialog), 600, 300);
- gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), 0);
- gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (dialog)->action_area), 12);
-
- gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), w, TRUE, TRUE, 0);
-
- g_object_ref (rule);
- g_object_set_data_full ((GObject *) dialog, "rule", rule, (GDestroyNotify) g_object_unref);
-
- g_signal_connect (rule, "changed", G_CALLBACK (dialog_rule_changed), dialog);
- dialog_rule_changed (rule, dialog);
-
- g_signal_connect (dialog, "response", G_CALLBACK (rule_advanced_response), efb);
- g_object_weak_ref ((GObject *) dialog, (GWeakNotify) rule_editor_destroyed, efb);
-
- e_search_bar_set_menu_sensitive (esb, E_FILTERBAR_SAVE_ID, FALSE);
-
- gtk_widget_show (dialog);
- }
-}
-
-static void
-save_search_dialog (ESearchBar *esb)
-{
- FilterRule *rule;
- gchar *name, *text;
- GtkWidget *dialog, *w;
-
- EFilterBar *efb = (EFilterBar *)esb;
-
- rule = filter_rule_clone (efb->current_query);
- text = e_search_bar_get_text (esb);
- name = g_strdup_printf ("%s %s", rule->name, text && text[0] ? text : "''");
- filter_rule_set_name (rule, name);
- g_free (text);
- g_free (name);
-
- w = filter_rule_get_widget (rule, efb->context);
- filter_rule_set_source (rule, FILTER_SOURCE_INCOMING);
- gtk_container_set_border_width (GTK_CONTAINER (w), 12);
-
- /* FIXME: get the toplevel window... */
- dialog = gtk_dialog_new_with_buttons (_("Save Search"), NULL, GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
- GTK_STOCK_OK, GTK_RESPONSE_OK, NULL);
- efb->save_dialog = dialog;
- gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
- gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), 0);
- gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (dialog)->action_area), 12);
-
- gtk_window_set_default_size (GTK_WINDOW (dialog), 500, 300);
-
- gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), w, TRUE, TRUE, 0);
-
- g_object_ref (rule);
- g_object_set_data_full ((GObject *) dialog, "rule", rule, (GDestroyNotify) g_object_unref);
- g_signal_connect (dialog, "response", G_CALLBACK (rule_editor_response), efb);
- g_object_weak_ref ((GObject *) dialog, (GWeakNotify) rule_editor_destroyed, efb);
-
- g_signal_connect (rule, "changed", G_CALLBACK (dialog_rule_changed), dialog);
- dialog_rule_changed (rule, dialog);
-
- e_search_bar_set_menu_sensitive (esb, E_FILTERBAR_SAVE_ID, FALSE);
-
- gtk_widget_show (dialog);
-}
-
-static void
-menubar_activated (ESearchBar *esb, gint id, gpointer data)
-{
- EFilterBar *efb = (EFilterBar *)esb;
- GtkWidget *dialog;
- GtkStyle *style;
-
- d(printf ("menubar activated!\n"));
-
- switch (id) {
- case E_FILTERBAR_EDIT_ID:
- if (!efb->save_dialog) {
- efb->save_dialog = dialog = (GtkWidget *) rule_editor_new (efb->context, FILTER_SOURCE_INCOMING, _("_Searches"));
-
- gtk_window_set_title (GTK_WINDOW (dialog), _("Searches"));
- g_signal_connect (dialog, "response", G_CALLBACK (full_rule_editor_response), efb);
- g_object_weak_ref ((GObject *) dialog, (GWeakNotify) rule_editor_destroyed, efb);
- gtk_widget_show (dialog);
- }
- break;
- case E_FILTERBAR_SAVE_ID:
- if (efb->current_query && !efb->save_dialog)
- save_search_dialog (esb);
-
- d(printf("Save menu\n"));
- break;
- case E_FILTERBAR_ADVANCED_ID:
- e_search_bar_set_item_id (esb, E_FILTERBAR_ADVANCED_ID);
- break;
- default:
- if (id >= efb->menu_base && id < efb->menu_base + efb->menu_rules->len) {
-#if d(!)0
- GString *out = g_string_new ("");
-
- printf("Selected rule: %s\n", ((FilterRule *)efb->menu_rules->pdata[id - efb->menu_base])->name);
- filter_rule_build_code (efb->menu_rules->pdata[id - efb->menu_base], out);
- printf("query: '%s'\n", out->str);
- g_string_free (out, TRUE);
-#endif
- efb->current_query = (FilterRule *)efb->menu_rules->pdata[id - efb->menu_base];
-
- efb->setquery = TRUE;
- e_search_bar_set_item_id (esb, E_FILTERBAR_ADVANCED_ID);
- efb->setquery = FALSE;
-
- /* saved searches activated */
- style = gtk_widget_get_default_style ();
- efb->setquery = TRUE;
- gtk_widget_modify_base (esb->entry , GTK_STATE_NORMAL, &(style->base[GTK_STATE_SELECTED] ));
- gtk_widget_modify_text (esb->entry, GTK_STATE_NORMAL, &(style->text [GTK_STATE_SELECTED] ));
- gtk_widget_modify_base (esb->icon_entry, GTK_STATE_NORMAL, &(style->base [GTK_STATE_SELECTED] ));
- gtk_widget_modify_base (esb->viewoption, GTK_STATE_NORMAL, &(style->base [GTK_STATE_SELECTED] ));
- e_search_bar_set_text (esb,_("Advanced Search"));
- g_signal_emit_by_name (efb, "search_activated", NULL);
- efb->setquery = FALSE;
- } else {
- return;
- }
- }
-
- g_signal_stop_emission_by_name (esb, "menu_activated");
-}
-
-static void
-option_changed (ESearchBar *esb, gpointer data)
-{
- EFilterBar *efb = (EFilterBar *)esb;
- gint id = e_search_bar_get_item_id (esb);
- gchar *query;
-
- d(printf("option changed, id = %d, setquery = %s %d\n", id, efb->setquery ? "true" : "false", esb->block_search));
-
- if (efb->setquery)
- return;
-
- switch (id) {
- case E_FILTERBAR_SAVE_ID:
- /* Fixme */
- /* save_search_dialog (esb); */
- break;
- case E_FILTERBAR_ADVANCED_ID:
- d(printf ("do_advanced\n"));
- if (!esb->block_search)
- do_advanced (esb);
- break;
- default:
- if (id >= efb->option_base && id < efb->option_base + efb->option_rules->len) {
- efb->current_query = (FilterRule *)efb->option_rules->pdata[id - efb->option_base];
- if (efb->config && efb->current_query) {
- query = e_search_bar_get_text (esb);
- efb->config (efb, efb->current_query, id, query, efb->config_data);
- g_free (query);
- }
- } else {
- gtk_widget_modify_base (esb->entry, GTK_STATE_NORMAL, NULL);
- gtk_widget_modify_text (esb->entry, GTK_STATE_NORMAL, NULL);
- gtk_widget_modify_base (esb->icon_entry, GTK_STATE_NORMAL, NULL);
- efb->current_query = NULL;
- gtk_entry_set_text ((GtkEntry *)esb->entry, "");
- }
- }
-}
-
-static void
-dup_item_no_subitems (ESearchBarItem *dest,
- const ESearchBarItem *src)
-{
- dest->id = src->id;
- dest->text = g_strdup (src->text);
- dest->type = src->type;
-}
-
-static GArray *
-build_items (ESearchBar *esb, ESearchBarItem *items, gint type, gint *start, GPtrArray *rules)
-{
- FilterRule *rule = NULL;
- EFilterBar *efb = (EFilterBar *)esb;
- gint id = 0, i;
- GArray *menu = g_array_new (FALSE, FALSE, sizeof (ESearchBarItem));
- ESearchBarItem item = { NULL, -1, 2 };
- const gchar *source;
- GSList *gtksux = NULL;
- gint num;
-
- for (i=0;i<rules->len;i++)
- gtksux = g_slist_prepend(gtksux, rules->pdata[i]);
-
- g_ptr_array_set_size(rules, 0);
-
- /* find a unique starting point for the id's of our items */
- for (i = 0; items[i].id != -1; i++) {
- ESearchBarItem dup_item = { NULL, -1, 2 };
-
- if (items[i].id >= id)
- id = items[i].id + 1;
-
- dup_item_no_subitems (&dup_item, items + i);
- g_array_append_vals (menu, &dup_item, 1);
- }
-
- *start = id;
-
- if (type == 0) {
- source = FILTER_SOURCE_INCOMING;
-
- /* Add a separator if there is at least one custom rule. */
- if (rule_context_next_rule (efb->context, rule, source) != NULL) {
- item.id = 0;
- item.text = NULL;
- item.type = 0;
- g_array_append_vals (menu, &item, 1);
- }
- } else {
- source = FILTER_SOURCE_DEMAND;
- }
-
- num = 1;
- while ((rule = rule_context_next_rule (efb->context, rule, source))) {
- item.id = id++;
-
- if (type == 0 && num <= 10) {
- item.text = g_strdup_printf ("_%d. %s", num % 10, rule->name);
- num ++;
- } else {
- item.text = g_strdup (rule->name);
- }
- g_array_append_vals (menu, &item, 1);
-
- if (g_slist_find(gtksux, rule) == NULL) {
- g_object_ref (rule);
- g_signal_connect (rule, "changed", G_CALLBACK (rule_changed), efb);
- } else {
- gtksux = g_slist_remove(gtksux, rule);
- }
- g_ptr_array_add (rules, rule);
- }
-
- /* anything elft in gtksux has gone away, and we need to unref/disconnect from it */
- while (gtksux) {
- GSList *next;
-
- next = gtksux->next;
- rule = gtksux->data;
-
- g_signal_handlers_disconnect_by_func (rule, G_CALLBACK (rule_changed), efb);
- g_object_unref (rule);
-
- g_slist_free_1(gtksux);
- gtksux = next;
- }
-
- /* always add on the advanced menu */
- if (type == 1) {
- ESearchBarItem sb_items[2] = { E_FILTERBAR_SEPARATOR, E_FILTERBAR_ADVANCED,
- /* E_FILTERBAR_SEPARATOR, E_FILTERBAR_SAVE */ };
- ESearchBarItem dup_items[2];
-
- dup_item_no_subitems (&dup_items[0], &sb_items[0]);
- dup_item_no_subitems (&dup_items[1], &sb_items[1]);
- /* dup_item_no_subitems (&dup_items[2], &sb_items[2]); */
- /* dup_item_no_subitems (&dup_items[3], &sb_items[3]); */
- g_array_append_vals (menu, &dup_items, 2);
- }
-
- item.id = -1;
- item.text = NULL;
- g_array_append_vals (menu, &item, 1);
-
- return menu;
-}
-
-static void
-free_built_items (GArray *menu)
-{
- gint i;
-
- for (i = 0; i < menu->len; i ++) {
- ESearchBarItem *item;
-
- item = & g_array_index (menu, ESearchBarItem, i);
- g_free (item->text);
- }
-
- g_array_free (menu, TRUE);
-}
-
-static void
-generate_menu (ESearchBar *esb, ESearchBarItem *items)
-{
- EFilterBar *efb = (EFilterBar *)esb;
- GArray *menu;
-
- menu = build_items (esb, items, 0, &efb->menu_base, efb->menu_rules);
- ((ESearchBarClass *)parent_class)->set_menu (esb, (ESearchBarItem *)menu->data);
- free_built_items (menu);
-}
-
-static void
-free_items (ESearchBarItem *items)
-{
- gint i;
-
- for (i = 0; items[i].id != -1; i++)
- g_free (items[i].text);
-
-
- g_free (items);
-}
-
-/* Virtual methods */
-static void
-set_menu (ESearchBar *esb, ESearchBarItem *items)
-{
- EFilterBar *efb = E_FILTER_BAR (esb);
- ESearchBarItem *default_items;
- gint i, num;
-
- if (efb->default_items)
- free_items (efb->default_items);
-
- for (num = 0; items[num].id != -1; num++)
- ;
-
- default_items = g_new (ESearchBarItem, num + 1);
- for (i = 0; i < num + 1; i++) {
- default_items[i].text = g_strdup (items[i].text);
- default_items[i].id = items[i].id;
- default_items[i].type = items[i].type;
- }
-
- efb->default_items = default_items;
-
- generate_menu (esb, default_items);
-}
-
-static void
-set_option (ESearchBar *esb, ESearchBarItem *items)
-{
- GArray *menu;
- EFilterBar *efb = (EFilterBar *)esb;
-
- menu = build_items (esb, items, 1, &efb->option_base, efb->option_rules);
- ((ESearchBarClass *)parent_class)->set_option (esb, (ESearchBarItem *)menu->data);
- free_built_items (menu);
-
- e_search_bar_set_item_id (esb, efb->option_base);
-}
-
-static void
-context_changed (RuleContext *context, gpointer user_data)
-{
- EFilterBar *efb = E_FILTER_BAR (user_data);
- ESearchBar *esb = E_SEARCH_BAR (user_data);
-
- /* just generate whole menu again */
- generate_menu (esb, efb->default_items);
-}
-
-static void
-context_rule_removed (RuleContext *context, FilterRule *rule, gpointer user_data)
-{
- EFilterBar *efb = E_FILTER_BAR (user_data);
- ESearchBar *esb = E_SEARCH_BAR (user_data);
-
- /* just generate whole menu again */
- generate_menu (esb, efb->default_items);
-}
-
-static void
-rule_changed (FilterRule *rule, gpointer user_data)
-{
- EFilterBar *efb = E_FILTER_BAR (user_data);
- ESearchBar *esb = E_SEARCH_BAR (user_data);
-
- /* just generate whole menu again */
- generate_menu (esb, efb->default_items);
-}
-
-
-/* GtkObject methods. */
-
-static void
-get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
-{
- EFilterBar *efb = (EFilterBar *) object;
- ESearchBar *esb = E_SEARCH_BAR (object);
-
- switch (property_id) {
- case PROP_QUERY: {
- gchar *text = e_search_bar_get_text (E_SEARCH_BAR (efb));
-
- /* empty search text means searching turned off */
- if (efb->current_query && text && *text) {
- GString *out = g_string_new ("");
-
- filter_rule_build_code (efb->current_query, out);
- g_value_take_string (value, out->str);
- g_string_free (out, FALSE);
- } else {
- g_value_set_string (value, NULL);
- }
-
- g_free (text);
- break; }
- case PROP_STATE: {
- /* FIXME: we should have ESearchBar save its own state to the xmlDocPtr */
- xmlChar *xmlbuf;
- gchar *text, buf[12];
- gint searchscope, item_id, n, view_id;
- xmlNodePtr root, node;
- xmlDocPtr doc;
-
- item_id = e_search_bar_get_item_id ((ESearchBar *) efb);
-
- doc = xmlNewDoc ((const guchar *)"1.0");
- root = xmlNewDocNode (doc, NULL, (const guchar *)"state", NULL);
- xmlDocSetRootElement (doc, root);
- searchscope = e_search_bar_get_search_scope ((ESearchBar *) efb);
- view_id = e_search_bar_get_viewitem_id ((ESearchBar *) efb);
-
- if (searchscope < E_FILTERBAR_CURRENT_FOLDER_ID)
- item_id = esb->last_search_option;
-
- if (item_id == E_FILTERBAR_ADVANCED_ID) {
- /* advanced query, save the filterbar state */
- node = xmlNewChild (root, NULL, (const guchar *)"filter-bar", NULL);
-
- sprintf (buf, "%d", esb->last_search_option);
- xmlSetProp (node, (const guchar *)"item_id", (guchar *)buf);
- sprintf (buf, "%d", searchscope);
- xmlSetProp (node, (const guchar *)"searchscope", (guchar *)buf);
- sprintf (buf, "%d", view_id);
- xmlSetProp (node, (const guchar *)"view_id", (guchar *)buf);
-
- xmlAddChild (node, filter_rule_xml_encode (efb->current_query));
- } else {
- /* simple query, save the searchbar state */
- text = e_search_bar_get_text ((ESearchBar *) efb);
-
- node = xmlNewChild (root, NULL, (const guchar *)"search-bar", NULL);
- xmlSetProp (node, (const guchar *)"text", (guchar *)(text ? text : ""));
- sprintf (buf, "%d", item_id);
- xmlSetProp (node, (const guchar *)"item_id", (guchar *)buf);
- sprintf (buf, "%d", searchscope);
- xmlSetProp (node, (const guchar *)"searchscope", (guchar *)buf);
- sprintf (buf, "%d", view_id);
- xmlSetProp (node, (const guchar *)"view_id", (guchar *)buf);
- g_free (text);
- }
-
- xmlDocDumpMemory (doc, &xmlbuf, &n);
- xmlFreeDoc (doc);
-
- /* remap to glib memory */
- text = g_malloc (n + 1);
- memcpy (text, (gchar *)xmlbuf, n);
- text[n] = '\0';
- xmlFree (xmlbuf);
-
- g_value_take_string (value, text);
-
- break; }
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-static gint
-xml_get_prop_int (xmlNodePtr node, const gchar *prop)
-{
- gchar *buf;
- gint ret;
-
- if ((buf = (gchar *)xmlGetProp (node, (guchar *)prop))) {
- ret = strtol (buf, NULL, 10);
- xmlFree (buf);
- } else {
- ret = -1;
- }
-
- return ret;
-}
-
-static void
-set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
-{
- EFilterBar *efb = (EFilterBar *) object;
- ESearchBar *esb = E_SEARCH_BAR (object);
- xmlNodePtr root, node;
- const gchar *state;
- xmlDocPtr doc;
- gboolean rule_set = FALSE, is_cur_folder=FALSE;
- gint view_id, scope, item_id;
-
- switch (property_id) {
- case PROP_STATE:
- if ((state = g_value_get_string (value))) {
- if (!(doc = xmlParseDoc ((guchar *) state)))
- return;
-
- root = doc->children;
- if (strcmp ((gchar *)root->name, "state") != 0) {
- xmlFreeDoc (doc);
- return;
- }
-
- node = root->children;
- while (node != NULL) {
- if (!strcmp ((gchar *)node->name, "filter-bar")) {
- FilterRule *rule = NULL;
-
-
- view_id = xml_get_prop_int (node, "view_id");
- scope = xml_get_prop_int (node, "searchscope");
- item_id = xml_get_prop_int (node, "item_id");
- if (item_id == -1)
- item_id = 0;
-
- if (scope == E_FILTERBAR_CURRENT_FOLDER_ID)
- is_cur_folder = TRUE;
-
- if ((node = node->children)) {
- GtkStyle *style = gtk_widget_get_default_style ();
-
- rule = filter_rule_new ();
- if (filter_rule_xml_decode (rule, node, efb->context) != 0) {
- gtk_widget_modify_base (E_SEARCH_BAR (efb)->entry, GTK_STATE_NORMAL, NULL);
- gtk_widget_modify_text (((ESearchBar *)efb)->entry, GTK_STATE_NORMAL, NULL);
- gtk_widget_modify_base (((ESearchBar *)efb)->icon_entry, GTK_STATE_NORMAL, NULL);
- g_object_unref (rule);
- rule = NULL;
- } else {
- rule_set = TRUE;
- gtk_widget_set_sensitive (esb->clear_button, TRUE);
- gtk_widget_modify_base (((ESearchBar *)efb)->entry, GTK_STATE_NORMAL, &(style->base[GTK_STATE_SELECTED]));
- gtk_widget_modify_text (((ESearchBar *)efb)->entry, GTK_STATE_NORMAL, &(style->text[GTK_STATE_SELECTED]));
- gtk_widget_modify_base (((ESearchBar *)efb)->icon_entry, GTK_STATE_NORMAL, &(style->base[GTK_STATE_SELECTED]));
- gtk_widget_modify_base (((ESearchBar *)efb)->viewoption, GTK_STATE_NORMAL, &(style->base[GTK_STATE_SELECTED]));
- g_object_set_data_full (object, "rule", rule, (GDestroyNotify) g_object_unref);
- }
- }
-
-
- if (rule_set) {
- esb->block_search = TRUE;
- e_search_bar_set_text (esb, _("Advanced Search"));
- e_search_bar_set_item_menu ((ESearchBar *) efb, item_id);
- e_search_bar_set_search_scope ((ESearchBar *) efb, scope);
- esb->block_search = FALSE;
- efb->current_query = (FilterRule *)efb->option_rules->pdata[item_id - efb->option_base];
- if (efb->config && efb->current_query) {
- gchar *query = e_search_bar_get_text (esb);
- efb->config (efb, efb->current_query, item_id, query, efb->config_data);
- g_free (query);
-
- }
- }
- e_search_bar_set_viewitem_id ((ESearchBar *) efb, view_id);
- efb->current_query = rule;
- efb->setquery = TRUE;
- e_search_bar_set_item_id ((ESearchBar *) efb, E_FILTERBAR_ADVANCED_ID);
- efb->setquery = FALSE;
-
- break;
- } else if (!strcmp ((gchar *)node->name, "search-bar")) {
- gint subitem_id, item_id, scope, view_id;
- gchar *text;
- GtkStyle *style = gtk_widget_get_default_style ();
-
- /* set the text first (it doesn't emit a signal) */
-
-
- /* now set the item_id and subitem_id */
- item_id = xml_get_prop_int (node, "item_id");
- subitem_id = xml_get_prop_int (node, "subitem_id");
-
- esb->block_search = TRUE;
- if (subitem_id >= 0)
- e_search_bar_set_ids (E_SEARCH_BAR (efb), item_id, subitem_id);
- else
- e_search_bar_set_item_menu (E_SEARCH_BAR (efb), item_id);
- esb->block_search = FALSE;
- view_id = xml_get_prop_int (node, "view_id");
- e_search_bar_set_viewitem_id (E_SEARCH_BAR (efb), view_id);
- scope = xml_get_prop_int (node, "searchscope");
- e_search_bar_set_search_scope (E_SEARCH_BAR (efb), scope);
-
- text = (gchar *)xmlGetProp (node, (const guchar *)"text");
- e_search_bar_set_text (E_SEARCH_BAR (efb), text);
- if (text && *text) {
- efb->current_query = (FilterRule *)efb->option_rules->pdata[item_id - efb->option_base];
- if (efb->config && efb->current_query)
- efb->config (efb, efb->current_query, item_id, text, efb->config_data);
- gtk_widget_set_sensitive (esb->clear_button, TRUE);
- gtk_widget_modify_base (((ESearchBar *)efb)->entry, GTK_STATE_NORMAL, &(style->base[GTK_STATE_SELECTED]));
- gtk_widget_modify_text (((ESearchBar *)efb)->entry, GTK_STATE_NORMAL, &(style->text[GTK_STATE_SELECTED]));
- gtk_widget_modify_base (((ESearchBar *)efb)->icon_entry, GTK_STATE_NORMAL, &(style->base[GTK_STATE_SELECTED]));
- gtk_widget_modify_base (((ESearchBar *)efb)->viewoption, GTK_STATE_NORMAL, &(style->base[GTK_STATE_SELECTED]));
- } else {
- gtk_widget_modify_base (((ESearchBar *)efb)->entry, GTK_STATE_NORMAL, NULL);
- gtk_widget_modify_text (((ESearchBar *)efb)->entry, GTK_STATE_NORMAL, NULL);
- gtk_widget_modify_base (((ESearchBar *)efb)->icon_entry, GTK_STATE_NORMAL, NULL);
- e_search_bar_paint (esb);
- efb->current_query = (FilterRule *)efb->option_rules->pdata[item_id - efb->option_base];
- if (efb->config && efb->current_query)
- efb->config (efb, efb->current_query, item_id, "", efb->config_data);
- }
-
- xmlFree (text);
-
-
- break;
- }
-
- node = node->next;
- }
-
- xmlFreeDoc (doc);
- } else {
- /* set default state */
- e_search_bar_set_item_id ((ESearchBar *) efb, 0);
- e_search_bar_set_viewitem_id ((ESearchBar *) efb, 0);
- e_search_bar_set_search_scope ((ESearchBar *) efb, E_FILTERBAR_CURRENT_FOLDER_ID);
- }
-
- /* we don't want to run option_changed */
- efb->setquery = TRUE;
- g_signal_emit_by_name (efb, "search_activated", NULL);
- efb->setquery = FALSE;
-
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-static void clear_rules(EFilterBar *efb, GPtrArray *rules)
-{
- gint i;
- FilterRule *rule;
-
- /* clear out any data on old rules */
- for (i=0;i<rules->len;i++) {
- rule = rules->pdata[i];
- g_signal_handlers_disconnect_by_func (rule, G_CALLBACK (rule_changed), efb);
- g_object_unref(rule);
- }
- g_ptr_array_set_size (rules, 0);
-}
-
-static void
-dispose (GObject *object)
-{
- EFilterBar *bar;
-
- g_return_if_fail (object != NULL);
- g_return_if_fail (E_IS_FILTER_BAR (object));
-
- bar = E_FILTER_BAR (object);
-
- if (bar->context != NULL && bar->userrules != NULL)
- rule_context_save (bar->context, bar->userrules);
-
- if (bar->menu_rules != NULL) {
- clear_rules(bar, bar->menu_rules);
- clear_rules(bar, bar->option_rules);
-
- g_ptr_array_free (bar->menu_rules, TRUE);
- g_ptr_array_free (bar->option_rules, TRUE);
-
- g_free (bar->systemrules);
- g_free (bar->userrules);
-
- bar->menu_rules = NULL;
- bar->option_rules = NULL;
- bar->systemrules = NULL;
- bar->userrules = NULL;
- }
-
- if (bar->context != NULL) {
- g_signal_handlers_disconnect_by_func (bar->context, G_CALLBACK (context_changed), bar);
- g_signal_handlers_disconnect_by_func (bar->context, G_CALLBACK (context_rule_removed), bar);
-
- g_object_unref (bar->context);
- bar->context = NULL;
- }
-
- if (bar->default_items) {
- free_items (bar->default_items);
- bar->default_items = NULL;
- }
-
- (* G_OBJECT_CLASS (parent_class)->dispose) (object);
-}
-
-
-static void
-class_init (EFilterBarClass *klass)
-{
- GObjectClass *object_class = (GObjectClass *) klass;
- ESearchBarClass *esb_class = (ESearchBarClass *) klass;
- GParamSpec *pspec;
-
- parent_class = g_type_class_ref (e_search_bar_get_type ());
-
- object_class->dispose = dispose;
- object_class->get_property = get_property;
- object_class->set_property = set_property;
-
- esb_class->set_menu = set_menu;
- esb_class->set_option = set_option;
-
- pspec = g_param_spec_string ("query", NULL, NULL, NULL, G_PARAM_READABLE);
- g_object_class_install_property (object_class, PROP_QUERY, pspec);
-
- pspec = g_param_spec_string ("state", NULL, NULL, NULL, G_PARAM_READWRITE);
- g_object_class_install_property (object_class, PROP_STATE, pspec);
-
- /*gtk_object_add_arg_type ("EFilterBar::query", G_TYPE_STRING, GTK_ARG_READABLE, ARG_QUERY);*/
-
-#if 0
- esb_signals [QUERY_CHANGED] =
- g_signal_new ("query_changed",
- G_SIGNAL_RUN_LAST,
- object_class->type,
- G_STRUCT_OFFSET (EFilterBarClass, query_changed),
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
-
- esb_signals [MENU_ACTIVATED] =
- g_signal_new ("menu_activated",
- G_SIGNAL_RUN_LAST,
- object_class->type,
- G_STRUCT_OFFSET (EFilterBarClass, menu_activated),
- g_cclosure_marshal_VOID__INT,
- G_TYPE_NONE, 1, G_TYPE_INT);
-
- gtk_object_class_add_signals (object_class, esb_signals, LAST_SIGNAL);
-#endif
-}
-
-static void
-init (EFilterBar *efb)
-{
- g_signal_connect (efb, "menu_activated", G_CALLBACK (menubar_activated), NULL);
- g_signal_connect (efb, "query_changed", G_CALLBACK (option_changed), NULL);
- g_signal_connect (efb, "search_activated", G_CALLBACK (option_changed), NULL);
-
- efb->menu_rules = g_ptr_array_new ();
- efb->option_rules = g_ptr_array_new ();
-}
-
-
-/* Object construction. */
-
-EFilterBar *
-e_filter_bar_new (RuleContext *context,
- const gchar *systemrules,
- const gchar *userrules,
- EFilterBarConfigRule config,
- gpointer data)
-{
- EFilterBar *bar;
-
- bar = g_object_new (e_filter_bar_get_type (), NULL);
- ((ESearchBar *)bar)->lite = FALSE;
-
- e_filter_bar_new_construct (context, systemrules, userrules, config, data, bar);
-
- return bar;
-}
-
-EFilterBar *
-e_filter_bar_lite_new (RuleContext *context,
- const gchar *systemrules,
- const gchar *userrules,
- EFilterBarConfigRule config,
- gpointer data)
-{
- EFilterBar *bar;
-
- bar = g_object_new (e_filter_bar_get_type (), NULL);
- ((ESearchBar *)bar)->lite = TRUE;
- e_filter_bar_new_construct (context, systemrules, userrules, config, data, bar);
-
- return bar;
-}
-
-void
-e_filter_bar_new_construct (RuleContext *context,
- const gchar *systemrules,
- const gchar *userrules,
- EFilterBarConfigRule config,
- gpointer data ,EFilterBar *bar )
-{
- ESearchBarItem item = { NULL, -1, 0 };
-
- bar->context = context;
- g_object_ref (context);
-
- bar->config = config;
- bar->config_data = data;
-
- bar->systemrules = g_strdup (systemrules);
- bar->userrules = g_strdup (userrules);
-
- bar->all_account_search_vf = NULL;
- bar->account_search_vf = NULL;
- bar->account_search_cancel = NULL;
-
- e_search_bar_construct ((ESearchBar *)bar, &item, &item);
-
- g_signal_connect (context, "changed", G_CALLBACK (context_changed), bar);
- g_signal_connect (context, "rule_removed", G_CALLBACK (context_rule_removed), bar);
-
-}
-
-GType
-e_filter_bar_get_type (void)
-{
- static GType type = 0;
-
- if (G_UNLIKELY (type == 0)) {
- static const GTypeInfo type_info = {
- sizeof (EFilterBarClass),
- (GBaseInitFunc) NULL,
- (GBaseFinalizeFunc) NULL,
- (GClassInitFunc) class_init,
- (GClassFinalizeFunc) NULL,
- NULL, /* class_data */
- sizeof (EFilterBar),
- 0, /* n_preallocs */
- (GInstanceInitFunc) init,
- NULL /* value_table */
- };
-
- type = g_type_register_static (
- e_search_bar_get_type (), "EFilterBar", &type_info, 0);
- }
-
- return type;
-}
diff --git a/widgets/misc/e-filter-bar.h b/widgets/misc/e-filter-bar.h
deleted file mode 100644
index f25a66fa73..0000000000
--- a/widgets/misc/e-filter-bar.h
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) version 3.
- *
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- *
- * Authors:
- * Michael Zucchi <notzed@ximian.com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-#ifndef __E_FILTER_BAR_H__
-#define __E_FILTER_BAR_H__
-
-#include <gtk/gtk.h>
-#include <camel/camel-vee-folder.h>
-#include <camel/camel-operation.h>
-
-#include "e-search-bar.h"
-
-#include "filter/rule-context.h"
-#include "filter/filter-rule.h"
-
-G_BEGIN_DECLS
-
-/* EFilterBar - A filter rule driven search bar.
- *
- * The following arguments are available:
- *
- * name type read/write description
- * ---------------------------------------------------------------------------------
- * query string R String representing query.
- * state string RW XML string representing the state.
- */
-
-#define E_FILTER_BAR_TYPE (e_filter_bar_get_type ())
-#define E_FILTER_BAR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_FILTER_BAR_TYPE, EFilterBar))
-#define E_FILTER_BAR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E_FILTER_BAR_TYPE, EFilterBarClass))
-#define E_IS_FILTER_BAR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_FILTER_BAR_TYPE))
-#define E_IS_FILTER_BAR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), E_FILTER_BAR_TYPE))
-
-typedef struct _EFilterBar EFilterBar;
-typedef struct _EFilterBarClass EFilterBarClass;
-
-typedef void (*EFilterBarConfigRule)(EFilterBar *, FilterRule *rule, gint id, const gchar *query, gpointer data);
-
-struct _EFilterBar {
- ESearchBar parent;
- gint menu_base, option_base;
- GPtrArray *menu_rules, *option_rules;
-
- ESearchBarItem *default_items;
-
- GtkWidget *save_dialog; /* current save dialogue (so we dont pop up multiple ones) */
-
- FilterRule *current_query; /* as it says */
- gint setquery; /* true when we're setting a query directly to advanced, so dont popup the dialog */
-
- RuleContext *context;
- gchar *systemrules;
- gchar *userrules;
-
- EFilterBarConfigRule config;
- gpointer config_data;
-
- CamelVeeFolder *all_account_search_vf;
- CamelVeeFolder *account_search_vf;
- CamelOperation *account_search_cancel;
-};
-
-struct _EFilterBarClass
-{
- ESearchBarClass parent_class;
-};
-
-/* "preset" items */
-enum {
- /* preset menu options */
- E_FILTERBAR_SAVE_ID = -3,
- E_FILTERBAR_EDIT_ID = -4,
-
- /* preset option options */
- E_FILTERBAR_ADVANCED_ID = -5,
- E_FILTERBAR_CURRENT_FOLDER_ID = -7,
- E_FILTERBAR_CURRENT_ACCOUNT_ID = -8,
- E_FILTERBAR_ALL_ACCOUNTS_ID = -9
-};
-
-#define E_FILTERBAR_SAVE { (gchar *) N_("_Save Search..."), E_FILTERBAR_SAVE_ID, 0 }
-#define E_FILTERBAR_EDIT { (gchar *) N_("_Edit Saved Searches..."), E_FILTERBAR_EDIT_ID, 0 }
-#define E_FILTERBAR_ADVANCED { (gchar *) N_("_Advanced Search..."), E_FILTERBAR_ADVANCED_ID, 0 }
-#define E_FILTERBAR_ALL_ACCOUNTS { (gchar *) N_("All Accounts"), E_FILTERBAR_ALL_ACCOUNTS_ID, ESB_ITEMTYPE_RADIO }
-#define E_FILTERBAR_CURRENT_ACCOUNT { (gchar *) N_("Current Account"), E_FILTERBAR_CURRENT_ACCOUNT_ID, ESB_ITEMTYPE_RADIO }
-#define E_FILTERBAR_CURRENT_FOLDER { (gchar *) N_("Current Folder"), E_FILTERBAR_CURRENT_FOLDER_ID, ESB_ITEMTYPE_RADIO }
-#define E_FILTERBAR_SEPARATOR { NULL, 0, 0 }
-
-#ifdef JUST_FOR_TRANSLATORS
-const gchar * strings[] = {
- N_("_Save Search..."),
- N_("_Edit Saved Searches..."),
- N_("_Advanced Search...")
-};
-#endif
-
-
-GType e_filter_bar_get_type (void);
-
-EFilterBar *e_filter_bar_new (RuleContext *context,
- const gchar *systemrules,
- const gchar *userrules,
- EFilterBarConfigRule config,
- gpointer data);
-EFilterBar *e_filter_bar_lite_new (RuleContext *context,
- const gchar *systemrules,
- const gchar *userrules,
- EFilterBarConfigRule config,
- gpointer data);
-
-void
-e_filter_bar_new_construct (RuleContext *context,
- const gchar *systemrules,
- const gchar *userrules,
- EFilterBarConfigRule config,
- gpointer data ,EFilterBar *bar );
-
-G_END_DECLS
-
-
-#endif /* __E_FILTER_BAR_H__ */
diff --git a/widgets/misc/e-hinted-entry.c b/widgets/misc/e-hinted-entry.c
new file mode 100644
index 0000000000..ca75e85297
--- /dev/null
+++ b/widgets/misc/e-hinted-entry.c
@@ -0,0 +1,298 @@
+/*
+ * e-hinted-entry.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#include "e-hinted-entry.h"
+
+#define E_HINTED_ENTRY_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), E_TYPE_HINTED_ENTRY, EHintedEntryPrivate))
+
+struct _EHintedEntryPrivate {
+ gchar *hint;
+ guint hint_shown : 1;
+};
+
+enum {
+ PROP_0,
+ PROP_HINT,
+ PROP_HINT_SHOWN
+};
+
+static gpointer parent_class;
+
+static void
+hinted_entry_hide_hint (EHintedEntry *entry)
+{
+ gtk_entry_set_text (GTK_ENTRY (entry), "");
+
+ gtk_widget_modify_text (GTK_WIDGET (entry), GTK_STATE_NORMAL, NULL);
+
+ entry->priv->hint_shown = FALSE;
+
+ g_object_notify (G_OBJECT (entry), "hint-shown");
+}
+
+static void
+hinted_entry_show_hint (EHintedEntry *entry)
+{
+ GtkStyle *style;
+ const GdkColor *color;
+ const gchar *hint;
+
+ hint = e_hinted_entry_get_hint (entry);
+ gtk_entry_set_text (GTK_ENTRY (entry), hint);
+
+ style = gtk_widget_get_style (GTK_WIDGET (entry));
+ color = &style->text[GTK_STATE_INSENSITIVE];
+ gtk_widget_modify_text (GTK_WIDGET (entry), GTK_STATE_NORMAL, color);
+
+ entry->priv->hint_shown = TRUE;
+
+ g_object_notify (G_OBJECT (entry), "hint-shown");
+}
+
+static void
+hinted_entry_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_HINT:
+ e_hinted_entry_set_hint (
+ E_HINTED_ENTRY (object),
+ g_value_get_string (value));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+hinted_entry_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_HINT:
+ g_value_set_string (
+ value, e_hinted_entry_get_hint (
+ E_HINTED_ENTRY (object)));
+ return;
+
+ case PROP_HINT_SHOWN:
+ g_value_set_boolean (
+ value, e_hinted_entry_get_hint_shown (
+ E_HINTED_ENTRY (object)));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+hinted_entry_finalize (GObject *object)
+{
+ EHintedEntryPrivate *priv;
+
+ priv = E_HINTED_ENTRY_GET_PRIVATE (object);
+
+ g_free (priv->hint);
+
+ /* Chain up to parent's finalize() method. */
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static gboolean
+hinted_entry_focus_in_event (GtkWidget *widget,
+ GdkEventFocus *event)
+{
+ EHintedEntry *entry = E_HINTED_ENTRY (widget);
+
+ if (e_hinted_entry_get_hint_shown (entry))
+ hinted_entry_hide_hint (entry);
+
+ /* Chain up to parent's focus_in_event() method. */
+ return GTK_WIDGET_CLASS (parent_class)->
+ focus_in_event (widget, event);
+}
+
+static gboolean
+hinted_entry_focus_out_event (GtkWidget *widget,
+ GdkEventFocus *event)
+{
+ EHintedEntry *entry = E_HINTED_ENTRY (widget);
+ const gchar *text;
+
+ text = e_hinted_entry_get_text (entry);
+
+ if (text == NULL || *text == '\0')
+ hinted_entry_show_hint (E_HINTED_ENTRY (widget));
+
+ /* Chain up to parent's focus_out_event() method. */
+ return GTK_WIDGET_CLASS (parent_class)->
+ focus_out_event (widget, event);
+}
+
+static void
+hinted_entry_class_init (EHintedEntryClass *class)
+{
+ GObjectClass *object_class;
+ GtkWidgetClass *widget_class;
+
+ parent_class = g_type_class_peek_parent (class);
+ g_type_class_add_private (class, sizeof (EHintedEntryPrivate));
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->set_property = hinted_entry_set_property;
+ object_class->get_property = hinted_entry_get_property;
+ object_class->finalize = hinted_entry_finalize;
+
+ widget_class = GTK_WIDGET_CLASS (class);
+ widget_class->focus_in_event = hinted_entry_focus_in_event;
+ widget_class->focus_out_event = hinted_entry_focus_out_event;
+
+ g_object_class_install_property (
+ object_class,
+ PROP_HINT,
+ g_param_spec_string (
+ "hint",
+ "Hint",
+ NULL,
+ NULL,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_HINT_SHOWN,
+ g_param_spec_boolean (
+ "hint-shown",
+ "Hint Shown",
+ NULL,
+ FALSE,
+ G_PARAM_READABLE));
+}
+
+static void
+hinted_entry_init (EHintedEntry *entry)
+{
+ entry->priv = E_HINTED_ENTRY_GET_PRIVATE (entry);
+ entry->priv->hint = g_strdup (""); /* hint must never be NULL */
+}
+
+GType
+e_hinted_entry_get_type (void)
+{
+ static GType type = 0;
+
+ if (G_UNLIKELY (type == 0)) {
+ static const GTypeInfo type_info = {
+ sizeof (EHintedEntryClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) hinted_entry_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+ sizeof (EHintedEntry),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) hinted_entry_init,
+ NULL /* value_table */
+ };
+
+ type = g_type_register_static (
+ GTK_TYPE_ENTRY, "EHintedEntry", &type_info, 0);
+ }
+
+ return type;
+}
+
+GtkWidget *
+e_hinted_entry_new (void)
+{
+ return g_object_new (E_TYPE_HINTED_ENTRY, NULL);
+}
+
+const gchar *
+e_hinted_entry_get_hint (EHintedEntry *entry)
+{
+ g_return_val_if_fail (E_IS_HINTED_ENTRY (entry), NULL);
+
+ return entry->priv->hint;
+}
+
+void
+e_hinted_entry_set_hint (EHintedEntry *entry,
+ const gchar *hint)
+{
+ g_return_if_fail (E_IS_HINTED_ENTRY (entry));
+
+ if (hint == NULL)
+ hint = "";
+
+ g_free (entry->priv->hint);
+ entry->priv->hint = g_strdup (hint);
+
+ if (e_hinted_entry_get_hint_shown (entry))
+ gtk_entry_set_text (GTK_ENTRY (entry), hint);
+
+ g_object_notify (G_OBJECT (entry), "hint");
+}
+
+gboolean
+e_hinted_entry_get_hint_shown (EHintedEntry *entry)
+{
+ g_return_val_if_fail (E_IS_HINTED_ENTRY (entry), FALSE);
+
+ return entry->priv->hint_shown;
+}
+
+const gchar *
+e_hinted_entry_get_text (EHintedEntry *entry)
+{
+ /* XXX This clumsily overrides gtk_entry_get_text(). */
+
+ g_return_val_if_fail (E_IS_HINTED_ENTRY (entry), NULL);
+
+ if (e_hinted_entry_get_hint_shown (entry))
+ return "";
+
+ return gtk_entry_get_text (GTK_ENTRY (entry));
+}
+
+void
+e_hinted_entry_set_text (EHintedEntry *entry,
+ const gchar *text)
+{
+ /* XXX This clumsily overrides gtk_entry_set_text(). */
+
+ g_return_if_fail (E_IS_HINTED_ENTRY (entry));
+
+ if (text == NULL)
+ text = "";
+
+ if (*text == '\0' && !GTK_WIDGET_HAS_FOCUS (entry))
+ hinted_entry_show_hint (entry);
+ else {
+ hinted_entry_hide_hint (entry);
+ gtk_entry_set_text (GTK_ENTRY (entry), text);
+ }
+}
diff --git a/widgets/misc/e-hinted-entry.h b/widgets/misc/e-hinted-entry.h
new file mode 100644
index 0000000000..02379d4ad7
--- /dev/null
+++ b/widgets/misc/e-hinted-entry.h
@@ -0,0 +1,73 @@
+/*
+ * e-hinted-entry.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef E_HINTED_ENTRY_H
+#define E_HINTED_ENTRY_H
+
+#include <gtk/gtk.h>
+
+/* Standard GObject macros */
+#define E_TYPE_HINTED_ENTRY \
+ (e_hinted_entry_get_type ())
+#define E_HINTED_ENTRY(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_HINTED_ENTRY, EHintedEntry))
+#define E_HINTED_ENTRY_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_HINTED_ENTRY, EHintedEntryClass))
+#define E_IS_HINTED_ENTRY(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_HINTED_ENTRY))
+#define E_IS_HINTED_ENTRY_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_HINTED_ENTRY))
+#define E_HINTED_ENTRY_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_HINTED_ENTRY, EHintedEntryClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EHintedEntry EHintedEntry;
+typedef struct _EHintedEntryClass EHintedEntryClass;
+typedef struct _EHintedEntryPrivate EHintedEntryPrivate;
+
+struct _EHintedEntry {
+ GtkEntry parent;
+ EHintedEntryPrivate *priv;
+};
+
+struct _EHintedEntryClass {
+ GtkEntryClass parent_class;
+};
+
+GType e_hinted_entry_get_type (void);
+GtkWidget * e_hinted_entry_new (void);
+const gchar * e_hinted_entry_get_hint (EHintedEntry *entry);
+void e_hinted_entry_set_hint (EHintedEntry *entry,
+ const gchar *hint);
+gboolean e_hinted_entry_get_hint_shown (EHintedEntry *entry);
+const gchar * e_hinted_entry_get_text (EHintedEntry *entry);
+void e_hinted_entry_set_text (EHintedEntry *entry,
+ const gchar *text);
+
+G_END_DECLS
+
+#endif /* E_HINTED_ENTRY_H */
diff --git a/widgets/misc/e-icon-entry.c b/widgets/misc/e-icon-entry.c
deleted file mode 100644
index 0fb4540161..0000000000
--- a/widgets/misc/e-icon-entry.c
+++ /dev/null
@@ -1,384 +0,0 @@
-/*
- * e-icon-entry.c
- *
- * Author: Johnny Jacob <jjohnny@novell.com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- * Copyright (C) 2003, 2004, 2005 Christian Persch
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- * Adapted and modified from gtk+ code:
- *
- * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
- * Modified by the GTK+ Team and others 1997-2005. See the AUTHORS
- * file in the gtk+ distribution for a list of people on the GTK+ Team.
- * See the ChangeLog in the gtk+ distribution files for a list of changes.
- * These files are distributed with GTK+ at ftp://ftp.gtk.org/pub/gtk/.
- *
- */
-
-#include "config.h"
-
-#include "e-icon-entry.h"
-
-#define E_ICON_ENTRY_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), E_TYPE_ICON_ENTRY, EIconEntryPrivate))
-
-struct _EIconEntryPrivate
-{
- GtkWidget *hbox;
-};
-
-static GtkWidgetClass *parent_class = NULL;
-
-/* private helper functions */
-
-static gboolean
-entry_focus_change_cb (GtkWidget *widget,
- GdkEventFocus *event,
- GtkWidget *entry)
-{
- gtk_widget_queue_draw (entry);
-
- return FALSE;
-}
-
-static void
-e_icon_entry_get_borders (GtkWidget *widget,
- GtkWidget *entry,
- gint *xborder,
- gint *yborder)
-{
- gint focus_width;
- gboolean interior_focus;
-
- g_return_if_fail (entry->style != NULL);
-
- gtk_widget_style_get (entry,
- "focus-line-width", &focus_width,
- "interior-focus", &interior_focus,
- NULL);
-
- *xborder = entry->style->xthickness;
- *yborder = entry->style->ythickness;
-
- if (!interior_focus)
- {
- *xborder += focus_width;
- *yborder += focus_width;
- }
-}
-
-static void
-e_icon_entry_paint (GtkWidget *widget,
- GdkEventExpose *event)
-{
- EIconEntry *entry = E_ICON_ENTRY (widget);
- GtkWidget *entry_widget = entry->entry;
- gint x = 0, y = 0, width, height, focus_width;
- gboolean interior_focus;
-
- gtk_widget_style_get (entry_widget,
- "interior-focus", &interior_focus,
- "focus-line-width", &focus_width,
- NULL);
-
- gdk_drawable_get_size (widget->window, &width, &height);
-
- if (GTK_WIDGET_HAS_FOCUS (entry_widget) && !interior_focus)
- {
- x += focus_width;
- y += focus_width;
- width -= 2 * focus_width;
- height -= 2 * focus_width;
- }
-
- gtk_paint_flat_box (entry_widget->style, widget->window,
- GTK_WIDGET_STATE (entry_widget), GTK_SHADOW_NONE,
- NULL, entry_widget, "entry_bg",
- /* FIXME: was 0, 0 in gtk_entry_expose, but I think this is correct: */
- x, y, width, height);
-
- gtk_paint_shadow (entry_widget->style, widget->window,
- GTK_STATE_NORMAL, GTK_SHADOW_IN,
- NULL, entry_widget, "entry",
- x, y, width, height);
-
- if (GTK_WIDGET_HAS_FOCUS (entry_widget) && !interior_focus)
- {
- x -= focus_width;
- y -= focus_width;
- width += 2 * focus_width;
- height += 2 * focus_width;
-
- gtk_paint_focus (entry_widget->style, widget->window,
- GTK_WIDGET_STATE (entry_widget),
- NULL, entry_widget, "entry",
- /* FIXME: was 0, 0 in gtk_entry_draw_frame, but I think this is correct: */
- x, y, width, height);
- }
-}
-
-/* Class implementation */
-
-static void
-e_icon_entry_init (EIconEntry *entry)
-{
- EIconEntryPrivate *priv;
- GtkWidget *widget = (GtkWidget *) entry;
-
- priv = entry->priv = E_ICON_ENTRY_GET_PRIVATE (entry);
-
- GTK_WIDGET_UNSET_FLAGS (widget, GTK_NO_WINDOW);
-
- priv->hbox = gtk_hbox_new (FALSE, /* FIXME */ 0);
- gtk_container_add (GTK_CONTAINER (entry), priv->hbox);
-
- entry->entry = gtk_entry_new ();
- gtk_entry_set_has_frame (GTK_ENTRY (entry->entry), FALSE);
- gtk_box_pack_start (GTK_BOX (priv->hbox), entry->entry, TRUE, TRUE, /* FIXME */ 0);
-
- /* We need to queue a redraw when focus changes, to comply with themes
- * (like Clearlooks) which draw focused and unfocused entries differently.
- */
- g_signal_connect_after (entry->entry, "focus-in-event",
- G_CALLBACK (entry_focus_change_cb), entry);
- g_signal_connect_after (entry->entry, "focus-out-event",
- G_CALLBACK (entry_focus_change_cb), entry);
-}
-
-static void
-e_icon_entry_realize (GtkWidget *widget)
-{
- GdkWindowAttr attributes;
- gint attributes_mask;
- gint border_width;
-
- GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
-
- border_width = GTK_CONTAINER (widget)->border_width;
-
- attributes.x = widget->allocation.x + border_width;
- attributes.y = widget->allocation.y + border_width;
- attributes.width = widget->allocation.width - 2 * border_width;
- attributes.height = widget->allocation.height - 2 * border_width;
- attributes.window_type = GDK_WINDOW_CHILD;
- attributes.event_mask = gtk_widget_get_events (widget)
- | GDK_EXPOSURE_MASK;
-
- attributes.visual = gtk_widget_get_visual (widget);
- attributes.colormap = gtk_widget_get_colormap (widget);
- attributes.wclass = GDK_INPUT_OUTPUT;
- attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
-
- widget->window = gdk_window_new (gtk_widget_get_parent_window (widget),
- &attributes, attributes_mask);
- gdk_window_set_user_data (widget->window, widget);
-
- widget->style = gtk_style_attach (widget->style, widget->window);
-
- gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
-}
-
-static void
-e_icon_entry_size_request (GtkWidget *widget,
- GtkRequisition *requisition)
-{
- EIconEntry *entry = E_ICON_ENTRY (widget);
- GtkContainer *container = GTK_CONTAINER (widget);
- GtkBin *bin = GTK_BIN (widget);
- gint xborder, yborder;
-
- requisition->width = requisition->height = container->border_width * 2;
-
- gtk_widget_ensure_style (entry->entry);
- e_icon_entry_get_borders (widget, entry->entry, &xborder, &yborder);
-
- if (GTK_WIDGET_VISIBLE (bin->child))
- {
- GtkRequisition child_requisition;
-
- gtk_widget_size_request (bin->child, &child_requisition);
- requisition->width += child_requisition.width;
- requisition->height += child_requisition.height;
- }
-
- requisition->width += 2 * xborder;
- requisition->height += 2 * yborder;
-}
-
-static void
-e_icon_entry_size_allocate (GtkWidget *widget,
- GtkAllocation *allocation)
-{
- EIconEntry *entry = E_ICON_ENTRY (widget);
- GtkContainer *container = GTK_CONTAINER (widget);
- GtkBin *bin = GTK_BIN (widget);
- GtkAllocation child_allocation;
- gint xborder, yborder;
-
- widget->allocation = *allocation;
-
- e_icon_entry_get_borders (widget, entry->entry, &xborder, &yborder);
-
- if (GTK_WIDGET_REALIZED (widget))
- {
- child_allocation.x = container->border_width;
- child_allocation.y = container->border_width;
- child_allocation.width = MAX (allocation->width - container->border_width * 2, 0);
- child_allocation.height = MAX (allocation->height - container->border_width * 2, 0);
-
- gdk_window_move_resize (widget->window,
- allocation->x + child_allocation.x,
- allocation->y + child_allocation.y,
- child_allocation.width,
- child_allocation.height);
- }
-
- child_allocation.x = container->border_width + xborder;
- child_allocation.y = container->border_width + yborder;
- child_allocation.width = MAX (allocation->width - (container->border_width + xborder) * 2, 0);
- child_allocation.height = MAX (allocation->height - (container->border_width + yborder) * 2, 0);
-
- gtk_widget_size_allocate (bin->child, &child_allocation);
-}
-
-static gboolean
-e_icon_entry_expose (GtkWidget *widget,
- GdkEventExpose *event)
-{
- if (GTK_WIDGET_DRAWABLE (widget) &&
- event->window == widget->window)
- {
- e_icon_entry_paint (widget, event);
- }
-
- return parent_class->expose_event (widget, event);
-}
-
-static void
-e_icon_entry_class_init (EIconEntryClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
- GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
-
- parent_class = GTK_WIDGET_CLASS (g_type_class_peek_parent (klass));
-
- widget_class->realize = e_icon_entry_realize;
- widget_class->size_request = e_icon_entry_size_request;
- widget_class->size_allocate = e_icon_entry_size_allocate;
- widget_class->expose_event = e_icon_entry_expose;
-
- g_type_class_add_private (object_class, sizeof (EIconEntryPrivate));
-}
-
-GType
-e_icon_entry_get_type (void)
-{
- static GType type = 0;
-
- if (G_UNLIKELY (type == 0))
- {
- static const GTypeInfo our_info =
- {
- sizeof (EIconEntryClass),
- NULL,
- NULL,
- (GClassInitFunc) e_icon_entry_class_init,
- NULL,
- NULL,
- sizeof (EIconEntry),
- 0,
- (GInstanceInitFunc) e_icon_entry_init
- };
-
- type = g_type_register_static (GTK_TYPE_BIN,
- "EIconEntry",
- &our_info, 0);
- }
-
- return type;
-}
-
-/* public functions */
-
-GtkWidget *
-e_icon_entry_new (void)
-{
- return GTK_WIDGET (g_object_new (E_TYPE_ICON_ENTRY, NULL));
-}
-
-void
-e_icon_entry_pack_widget (EIconEntry *entry,
- GtkWidget *widget,
- gboolean start)
-{
- EIconEntryPrivate *priv;
-
- g_return_if_fail (E_IS_ICON_ENTRY (entry));
-
- priv = entry->priv;
-
- if (start)
- {
- gtk_box_pack_start (GTK_BOX (priv->hbox), widget, FALSE, FALSE, /* FIXME */ 2);
- gtk_box_reorder_child (GTK_BOX (priv->hbox), widget, 0);
- }
- else
- {
- gtk_box_pack_end (GTK_BOX (priv->hbox), widget, FALSE, FALSE, /* FIXME */ 2);
- }
-}
-
-static void
-set_cursor (GtkWidget *widget, GdkEventCrossing *event, gpointer dummy)
-{
-
- if (event->type == GDK_ENTER_NOTIFY)
- gdk_window_set_cursor (widget->window, gdk_cursor_new (GDK_HAND1));
- else
- gdk_window_set_cursor (widget->window, gdk_cursor_new (GDK_LEFT_PTR));
-
-
-}
-
-GtkWidget *
-e_icon_entry_create_button (const gchar *stock)
-{
- GtkWidget *eventbox;
- GtkWidget *image;
-
- eventbox = gtk_event_box_new ();
- gtk_container_set_border_width (GTK_CONTAINER (eventbox), 2);
- gtk_event_box_set_visible_window (GTK_EVENT_BOX (eventbox), FALSE);
-
- image = gtk_image_new_from_stock (stock, GTK_ICON_SIZE_MENU);
- gtk_container_add (GTK_CONTAINER (eventbox), image);
-
- g_signal_connect_after (eventbox, "enter-notify-event", (GCallback) set_cursor, NULL);
- g_signal_connect_after (eventbox, "leave-notify-event", (GCallback) set_cursor, NULL);
-
- return eventbox;
-}
-
-GtkWidget *
-e_icon_entry_get_entry (EIconEntry *entry)
-{
- g_return_val_if_fail (E_IS_ICON_ENTRY (entry), NULL);
-
- return entry->entry;
-}
diff --git a/widgets/misc/e-icon-entry.h b/widgets/misc/e-icon-entry.h
deleted file mode 100644
index f8e4740d36..0000000000
--- a/widgets/misc/e-icon-entry.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * e-icon-entry.h
- *
- * Authors: Johnny Jacob <jjohnny@novell.com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- * Adapted and modified from Epiphany.
- *
- * Copyright (C) 2003, 2004, 2005 Christian Persch
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- * Adapted and modified from gtk+ code:
- *
- * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
- * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
- * file in the gtk+ distribution for a list of people on the GTK+ Team.
- * See the ChangeLog in the gtk+ distribution files for a list of changes.
- * These files are distributed with GTK+ at ftp://ftp.gtk.org/pub/gtk/.
- *
- */
-
-#ifndef E_ICON_ENTRY_H
-#define E_ICON_ENTRY_H
-
-#include <gtk/gtk.h>
-
-G_BEGIN_DECLS
-
-#define E_TYPE_ICON_ENTRY (e_icon_entry_get_type())
-#define E_ICON_ENTRY(object) (G_TYPE_CHECK_INSTANCE_CAST((object), E_TYPE_ICON_ENTRY, EIconEntry))
-#define E_ICON_ENTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), E_TYPE_ICON_ENTRY, EIconEntryClass))
-#define E_IS_ICON_ENTRY(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), E_TYPE_ICON_ENTRY))
-#define E_IS_ICON_ENTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), E_TYPE_ICON_ENTRY))
-#define E_ICON_ENTRY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), E_TYPE_ICON_ENTRY, EIconEntryClass))
-
-typedef struct _EIconEntryClass EIconEntryClass;
-typedef struct _EIconEntry EIconEntry;
-typedef struct _EIconEntryPrivate EIconEntryPrivate;
-
-struct _EIconEntryClass
-{
- GtkBinClass parent_class;
-};
-
-struct _EIconEntry
-{
- GtkBin parent_object;
-
- /*< public >*/
- GtkWidget *entry;
-
- /*< private >*/
- EIconEntryPrivate *priv;
-};
-
-GType e_icon_entry_get_type (void);
-
-GtkWidget *e_icon_entry_new (void);
-
-void e_icon_entry_pack_widget (EIconEntry *entry,
- GtkWidget *widget,
- gboolean start);
-
-GtkWidget *e_icon_entry_get_entry (EIconEntry *entry);
-
-GtkWidget *e_icon_entry_create_button (const gchar *stock);
-
-G_END_DECLS
-
-#endif
diff --git a/widgets/misc/e-image-chooser.c b/widgets/misc/e-image-chooser.c
index 3c83cb1048..2f451543e3 100644
--- a/widgets/misc/e-image-chooser.c
+++ b/widgets/misc/e-image-chooser.c
@@ -1,4 +1,6 @@
/*
+ * e-image-chooser.c
+ *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
@@ -13,9 +15,6 @@
* License along with the program; if not, see <http://www.gnu.org/licenses/>
*
*
- * Authors:
- * Chris Toshok <toshok@ximian.com>
- *
* Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
*
*/
@@ -28,21 +27,20 @@
#include <glib/gi18n.h>
#include "e-image-chooser.h"
-#include "e-util/e-icon-factory.h"
#include "e-util/e-util.h"
-struct _EImageChooserPrivate {
+#define E_IMAGE_CHOOSER_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), E_TYPE_IMAGE_CHOOSER, EImageChooserPrivate))
+struct _EImageChooserPrivate {
GtkWidget *frame;
GtkWidget *image;
- GtkWidget *browse_button;
gchar *image_buf;
- gint image_buf_size;
- gint image_width;
- gint image_height;
-
- gboolean editable;
+ gint image_buf_size;
+ gint image_width;
+ gint image_height;
};
enum {
@@ -50,185 +48,24 @@ enum {
LAST_SIGNAL
};
+static gpointer parent_class;
+static guint signals[LAST_SIGNAL];
-static gint image_chooser_signals [LAST_SIGNAL] = { 0 };
-
-static void e_image_chooser_init (EImageChooser *chooser);
-static void e_image_chooser_class_init (EImageChooserClass *klass);
-#if 0
-static void e_image_chooser_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
-static void e_image_chooser_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
-#endif
-static void e_image_chooser_dispose (GObject *object);
-
-static gboolean image_drag_motion_cb (GtkWidget *widget,
- GdkDragContext *context,
- gint x, gint y, guint time, EImageChooser *chooser);
-static void image_drag_leave_cb (GtkWidget *widget,
- GdkDragContext *context,
- guint time, EImageChooser *chooser);
-static gboolean image_drag_drop_cb (GtkWidget *widget,
- GdkDragContext *context,
- gint x, gint y, guint time, EImageChooser *chooser);
-static void image_drag_data_received_cb (GtkWidget *widget,
- GdkDragContext *context,
- gint x, gint y,
- GtkSelectionData *selection_data,
- guint info, guint time, EImageChooser *chooser);
-
-static GtkObjectClass *parent_class = NULL;
-#define PARENT_TYPE GTK_TYPE_VBOX
-
-enum DndTargetType {
- DND_TARGET_TYPE_URI_LIST
-};
#define URI_LIST_TYPE "text/uri-list"
-static GtkTargetEntry image_drag_types[] = {
- { (gchar *) URI_LIST_TYPE, 0, DND_TARGET_TYPE_URI_LIST },
-};
-static const gint num_image_drag_types = sizeof (image_drag_types) / sizeof (image_drag_types[0]);
-
-GtkWidget *
-e_image_chooser_new (void)
-{
- return g_object_new (E_TYPE_IMAGE_CHOOSER, NULL);
-}
-
-GType
-e_image_chooser_get_type (void)
-{
- static GType eic_type = 0;
-
- if (!eic_type) {
- static const GTypeInfo eic_info = {
- sizeof (EImageChooserClass),
- NULL, /* base_init */
- NULL, /* base_finalize */
- (GClassInitFunc) e_image_chooser_class_init,
- NULL, /* class_finalize */
- NULL, /* class_data */
- sizeof (EImageChooser),
- 0, /* n_preallocs */
- (GInstanceInitFunc) e_image_chooser_init,
- };
-
- eic_type = g_type_register_static (PARENT_TYPE, "EImageChooser", &eic_info, 0);
- }
-
- return eic_type;
-}
-
-
-static void
-e_image_chooser_class_init (EImageChooserClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
- parent_class = g_type_class_ref (PARENT_TYPE);
-
- image_chooser_signals [CHANGED] =
- g_signal_new ("changed",
- G_OBJECT_CLASS_TYPE (object_class),
- G_SIGNAL_RUN_FIRST,
- G_STRUCT_OFFSET (EImageChooserClass, changed),
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
-
- /*
- object_class->set_property = e_image_chooser_set_property;
- object_class->get_property = e_image_chooser_get_property;
- */
- object_class->dispose = e_image_chooser_dispose;
-}
-
-#ifdef UI_CHANGE_OK
-static void
-browse_for_image_cb (GtkWidget *button, gpointer data)
-{
-}
-#endif
-
-static void
-e_image_chooser_init (EImageChooser *chooser)
-{
- EImageChooserPrivate *priv;
- GtkWidget *alignment;
-
- priv = chooser->priv = g_new0 (EImageChooserPrivate, 1);
-
- alignment = gtk_alignment_new (0, 0, 0, 0);
- priv->frame = gtk_frame_new ("");
- priv->image = gtk_image_new ();
-
- gtk_container_add (GTK_CONTAINER (alignment), priv->image);
-
-#ifdef UI_CHANGE_OK
- priv->browse_button = gtk_button_new_with_label (_("Choose Image"));
-#endif
-
- gtk_frame_set_shadow_type (GTK_FRAME (priv->frame), GTK_SHADOW_NONE);
-
- gtk_container_add (GTK_CONTAINER (priv->frame), alignment);
- gtk_box_set_homogeneous (GTK_BOX (chooser), FALSE);
- gtk_box_pack_start (GTK_BOX (chooser), priv->frame, TRUE, TRUE, 0);
-#ifdef UI_CHANGE_OK
- gtk_box_pack_start (GTK_BOX (chooser), priv->browse_button, FALSE, FALSE, 0);
-
- g_signal_connect (priv->browse_button, "clicked", G_CALLBACK (browse_for_image_cb), NULL);
-#endif
-
- gtk_drag_dest_set (priv->image, 0, image_drag_types, num_image_drag_types, GDK_ACTION_COPY);
- g_signal_connect (priv->image,
- "drag_motion", G_CALLBACK (image_drag_motion_cb), chooser);
- g_signal_connect (priv->image,
- "drag_leave", G_CALLBACK (image_drag_leave_cb), chooser);
- g_signal_connect (priv->image,
- "drag_drop", G_CALLBACK (image_drag_drop_cb), chooser);
- g_signal_connect (priv->image,
- "drag_data_received", G_CALLBACK (image_drag_data_received_cb), chooser);
-
- gtk_widget_show_all (priv->frame);
-#ifdef UI_CHANGE_OK
- gtk_widget_show (priv->browse_button);
-#endif
-
- /* we default to being editable */
- priv->editable = TRUE;
-}
-
-static void
-e_image_chooser_dispose (GObject *object)
-{
- EImageChooser *eic = E_IMAGE_CHOOSER (object);
-
- if (eic->priv) {
- EImageChooserPrivate *priv = eic->priv;
-
- if (priv->image_buf) {
- g_free (priv->image_buf);
- priv->image_buf = NULL;
- }
-
- g_free (eic->priv);
- eic->priv = NULL;
- }
-
- if (G_OBJECT_CLASS (parent_class)->dispose)
- (* G_OBJECT_CLASS (parent_class)->dispose) (object);
-}
-
-
static gboolean
set_image_from_data (EImageChooser *chooser,
- gchar *data, gint length)
+ gchar *data,
+ gint length)
{
- gboolean rv = FALSE;
- GdkPixbufLoader *loader = gdk_pixbuf_loader_new ();
+ GdkPixbufLoader *loader;
GdkPixbuf *pixbuf;
+ gfloat scale;
+ gint new_height;
+ gint new_width;
- gdk_pixbuf_loader_write (loader, (guchar *)data, length, NULL);
+ loader = gdk_pixbuf_loader_new ();
+ gdk_pixbuf_loader_write (loader, (guchar *) data, length, NULL);
gdk_pixbuf_loader_close (loader, NULL);
pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
@@ -237,98 +74,92 @@ set_image_from_data (EImageChooser *chooser,
g_object_unref (loader);
- if (pixbuf) {
- GdkPixbuf *scaled;
- GdkPixbuf *composite;
-
- gfloat scale;
- gint new_height, new_width;
-
- new_height = gdk_pixbuf_get_height (pixbuf);
- new_width = gdk_pixbuf_get_width (pixbuf);
-
- printf ("new dimensions = (%d,%d)\n", new_width, new_height);
-
- if (chooser->priv->image_height == 0
- && chooser->priv->image_width == 0) {
- printf ("initial setting of an image. no scaling\n");
- scale = 1.0;
- }
- else if (chooser->priv->image_height < new_height
- || chooser->priv->image_width < new_width) {
- /* we need to scale down */
- printf ("we need to scale down\n");
- if (new_height > new_width)
- scale = (gfloat)chooser->priv->image_height / new_height;
- else
- scale = (gfloat)chooser->priv->image_width / new_width;
- }
- else {
- /* we need to scale up */
- printf ("we need to scale up\n");
- if (new_height > new_width)
- scale = (gfloat)new_height / chooser->priv->image_height;
- else
- scale = (gfloat)new_width / chooser->priv->image_width;
- }
-
- printf ("scale = %g\n", scale);
+ if (pixbuf == NULL)
+ return FALSE;
- if (scale == 1.0) {
- gtk_image_set_from_pixbuf (GTK_IMAGE (chooser->priv->image), pixbuf);
+ new_height = gdk_pixbuf_get_height (pixbuf);
+ new_width = gdk_pixbuf_get_width (pixbuf);
+
+ if (chooser->priv->image_height == 0
+ && chooser->priv->image_width == 0) {
+ scale = 1.0;
+ } else if (chooser->priv->image_height < new_height
+ || chooser->priv->image_width < new_width) {
+ /* we need to scale down */
+ if (new_height > new_width)
+ scale = (gfloat)chooser->priv->image_height / new_height;
+ else
+ scale = (gfloat)chooser->priv->image_width / new_width;
+ } else {
+ /* we need to scale up */
+ if (new_height > new_width)
+ scale = (gfloat)new_height / chooser->priv->image_height;
+ else
+ scale = (gfloat)new_width / chooser->priv->image_width;
+ }
- chooser->priv->image_width = new_width;
- chooser->priv->image_height = new_height;
- }
- else {
- new_width *= scale;
- new_height *= scale;
- new_width = MIN (new_width, chooser->priv->image_width);
- new_height = MIN (new_height, chooser->priv->image_height);
+ if (scale == 1.0) {
+ gtk_image_set_from_pixbuf (
+ GTK_IMAGE (chooser->priv->image), pixbuf);
+ chooser->priv->image_width = new_width;
+ chooser->priv->image_height = new_height;
+ } else {
+ GdkPixbuf *scaled;
+ GdkPixbuf *composite;
- printf ("new scaled dimensions = (%d,%d)\n", new_width, new_height);
+ new_width *= scale;
+ new_height *= scale;
+ new_width = MIN (new_width, chooser->priv->image_width);
+ new_height = MIN (new_height, chooser->priv->image_height);
- scaled = e_icon_factory_pixbuf_scale (pixbuf, new_width, new_height);
+ scaled = gdk_pixbuf_scale_simple (
+ pixbuf, new_width, new_height,
+ GDK_INTERP_BILINEAR);
- composite = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, gdk_pixbuf_get_bits_per_sample (pixbuf),
- chooser->priv->image_width, chooser->priv->image_height);
+ composite = gdk_pixbuf_new (
+ GDK_COLORSPACE_RGB, TRUE,
+ gdk_pixbuf_get_bits_per_sample (pixbuf),
+ chooser->priv->image_width,
+ chooser->priv->image_height);
- gdk_pixbuf_fill (composite, 0x00000000);
+ gdk_pixbuf_fill (composite, 0x00000000);
- gdk_pixbuf_copy_area (scaled, 0, 0, new_width, new_height,
- composite,
- chooser->priv->image_width / 2 - new_width / 2,
- chooser->priv->image_height / 2 - new_height / 2);
+ gdk_pixbuf_copy_area (
+ scaled, 0, 0, new_width, new_height,
+ composite,
+ chooser->priv->image_width / 2 - new_width / 2,
+ chooser->priv->image_height / 2 - new_height / 2);
- gtk_image_set_from_pixbuf (GTK_IMAGE (chooser->priv->image), composite);
- g_object_unref (scaled);
- g_object_unref (composite);
- }
+ gtk_image_set_from_pixbuf (
+ GTK_IMAGE (chooser->priv->image), composite);
- g_object_unref (pixbuf);
+ g_object_unref (scaled);
+ g_object_unref (composite);
+ }
- g_free (chooser->priv->image_buf);
- chooser->priv->image_buf = data;
- chooser->priv->image_buf_size = length;
+ g_object_unref (pixbuf);
- g_signal_emit (chooser,
- image_chooser_signals [CHANGED], 0);
+ g_free (chooser->priv->image_buf);
+ chooser->priv->image_buf = data;
+ chooser->priv->image_buf_size = length;
- rv = TRUE;
- }
+ g_signal_emit (chooser, signals[CHANGED], 0);
- return rv;
+ return TRUE;
}
static gboolean
image_drag_motion_cb (GtkWidget *widget,
- GdkDragContext *context,
- gint x, gint y, guint time, EImageChooser *chooser)
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ guint time,
+ EImageChooser *chooser)
{
+ GtkFrame *frame;
GList *p;
- if (!chooser->priv->editable)
- return FALSE;
+ frame = GTK_FRAME (chooser->priv->frame);
for (p = context->targets; p != NULL; p = p->next) {
gchar *possible_type;
@@ -337,37 +168,45 @@ image_drag_motion_cb (GtkWidget *widget,
if (!strcmp (possible_type, URI_LIST_TYPE)) {
g_free (possible_type);
gdk_drag_status (context, GDK_ACTION_COPY, time);
- gtk_frame_set_shadow_type (GTK_FRAME (chooser->priv->frame), GTK_SHADOW_IN);
+ gtk_frame_set_shadow_type (frame, GTK_SHADOW_IN);
return TRUE;
}
g_free (possible_type);
}
- gtk_frame_set_shadow_type (GTK_FRAME (chooser->priv->frame), GTK_SHADOW_NONE);
+ gtk_frame_set_shadow_type (frame, GTK_SHADOW_NONE);
+
return FALSE;
}
static void
image_drag_leave_cb (GtkWidget *widget,
- GdkDragContext *context,
- guint time, EImageChooser *chooser)
+ GdkDragContext *context,
+ guint time,
+ EImageChooser *chooser)
{
- gtk_frame_set_shadow_type (GTK_FRAME (chooser->priv->frame), GTK_SHADOW_NONE);
+ GtkFrame *frame;
+
+ frame = GTK_FRAME (chooser->priv->frame);
+ gtk_frame_set_shadow_type (frame, GTK_SHADOW_NONE);
}
static gboolean
image_drag_drop_cb (GtkWidget *widget,
- GdkDragContext *context,
- gint x, gint y, guint time, EImageChooser *chooser)
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ guint time,
+ EImageChooser *chooser)
{
+ GtkFrame *frame;
GList *p;
- if (!chooser->priv->editable)
- return FALSE;
+ frame = GTK_FRAME (chooser->priv->frame);
if (context->targets == NULL) {
- gtk_frame_set_shadow_type (GTK_FRAME (chooser->priv->frame), GTK_SHADOW_NONE);
+ gtk_frame_set_shadow_type (frame, GTK_SHADOW_NONE);
return FALSE;
}
@@ -377,76 +216,204 @@ image_drag_drop_cb (GtkWidget *widget,
possible_type = gdk_atom_name (GDK_POINTER_TO_ATOM (p->data));
if (!strcmp (possible_type, URI_LIST_TYPE)) {
g_free (possible_type);
- gtk_drag_get_data (widget, context,
- GDK_POINTER_TO_ATOM (p->data),
- time);
- gtk_frame_set_shadow_type (GTK_FRAME (chooser->priv->frame), GTK_SHADOW_NONE);
+ gtk_drag_get_data (
+ widget, context,
+ GDK_POINTER_TO_ATOM (p->data), time);
+ gtk_frame_set_shadow_type (frame, GTK_SHADOW_NONE);
return TRUE;
}
g_free (possible_type);
}
- gtk_frame_set_shadow_type (GTK_FRAME (chooser->priv->frame), GTK_SHADOW_NONE);
+ gtk_frame_set_shadow_type (frame, GTK_SHADOW_NONE);
+
return FALSE;
}
static void
image_drag_data_received_cb (GtkWidget *widget,
- GdkDragContext *context,
- gint x, gint y,
- GtkSelectionData *selection_data,
- guint info, guint time, EImageChooser *chooser)
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ GtkSelectionData *selection_data,
+ guint info,
+ guint time,
+ EImageChooser *chooser)
{
- gchar *target_type;
gboolean handled = FALSE;
+ gchar **uris;
+ gchar *buf = NULL;
+ gsize read = 0;
+ GError *error = NULL;
- target_type = gdk_atom_name (selection_data->target);
+ uris = gtk_selection_data_get_uris (selection_data);
- if (!strcmp (target_type, URI_LIST_TYPE)) {
- GError *error = NULL;
- gchar *uri;
- gchar *nl = strstr ((gchar *)selection_data->data, "\r\n");
- gchar *buf = NULL;
- gsize read = 0;
+ if (uris == NULL)
+ goto exit;
- if (nl)
- uri = g_strndup ((gchar *)selection_data->data, nl - (gchar *)selection_data->data);
- else
- uri = g_strdup ((gchar *)selection_data->data);
+ if (e_util_read_file (uris[0], TRUE, &buf, &read, &error) && read > 0 && buf)
+ handled = set_image_from_data (chooser, buf, read);
- if (e_util_read_file (uri, TRUE, &buf, &read, &error) && read > 0 && buf) {
- if (set_image_from_data (chooser, buf, read)) {
- handled = TRUE;
- }
- }
+ g_free (buf);
- g_free (buf);
- g_free (uri);
+ g_strfreev (uris);
- if (error) {
- g_warning ("%s", error->message);
- g_error_free (error);
- }
+ if (error) {
+ g_warning ("%s", error->message);
+ g_error_free (error);
}
+exit:
gtk_drag_finish (context, handled, FALSE, time);
}
-
+static void
+image_chooser_dispose (GObject *object)
+{
+ EImageChooserPrivate *priv;
+
+ priv = E_IMAGE_CHOOSER_GET_PRIVATE (object);
+
+ if (priv->frame != NULL) {
+ g_object_unref (priv->frame);
+ priv->frame = NULL;
+ }
+
+ if (priv->image != NULL) {
+ g_object_unref (priv->image);
+ priv->image = NULL;
+ }
+
+ /* Chain up to parent's dispose() method. */
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+image_chooser_finalize (GObject *object)
+{
+ EImageChooserPrivate *priv;
+
+ priv = E_IMAGE_CHOOSER_GET_PRIVATE (object);
+
+ g_free (priv->image_buf);
+
+ /* Chain up to parent's finalize() method. */
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+e_image_chooser_class_init (EImageChooserClass *class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+
+ parent_class = g_type_class_peek_parent (class);
+ g_type_class_add_private (class, sizeof (EImageChooserPrivate));
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->dispose = image_chooser_dispose;
+ object_class->finalize = image_chooser_finalize;
+
+ signals[CHANGED] = g_signal_new (
+ "changed",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (EImageChooserClass, changed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+}
+
+static void
+e_image_chooser_init (EImageChooser *chooser)
+{
+ GtkWidget *container;
+ GtkWidget *widget;
+
+ chooser->priv = E_IMAGE_CHOOSER_GET_PRIVATE (chooser);
+
+ container = GTK_WIDGET (chooser);
+
+ widget = gtk_frame_new ("");
+ gtk_frame_set_shadow_type (GTK_FRAME (widget), GTK_SHADOW_NONE);
+ gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
+ chooser->priv->frame = g_object_ref (widget);
+ gtk_widget_show (widget);
+
+ container = widget;
+
+ widget = gtk_alignment_new (0, 0, 0, 0);
+ gtk_container_add (GTK_CONTAINER (container), widget);
+ gtk_widget_show (widget);
+
+ container = widget;
+
+ widget = gtk_image_new ();
+ gtk_container_add (GTK_CONTAINER (container), widget);
+ chooser->priv->image = g_object_ref (widget);
+ gtk_widget_show (widget);
+
+ gtk_drag_dest_set (widget, 0, NULL, 0, GDK_ACTION_COPY);
+ gtk_drag_dest_add_uri_targets (widget);
+
+ g_signal_connect (
+ widget, "drag-motion",
+ G_CALLBACK (image_drag_motion_cb), chooser);
+ g_signal_connect (
+ widget, "drag-leave",
+ G_CALLBACK (image_drag_leave_cb), chooser);
+ g_signal_connect (
+ widget, "drag-drop",
+ G_CALLBACK (image_drag_drop_cb), chooser);
+ g_signal_connect (
+ widget, "drag-data-received",
+ G_CALLBACK (image_drag_data_received_cb), chooser);
+}
+
+GType
+e_image_chooser_get_type (void)
+{
+ static GType type = 0;
+
+ if (G_UNLIKELY (type == 0)) {
+ static const GTypeInfo type_info = {
+ sizeof (EImageChooserClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) e_image_chooser_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+ sizeof (EImageChooser),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) e_image_chooser_init,
+ NULL /* value_table */
+ };
+
+ type = g_type_register_static (
+ GTK_TYPE_VBOX, "EImageChooser", &type_info, 0);
+ }
+
+ return type;
+}
+
+GtkWidget *
+e_image_chooser_new (void)
+{
+ return g_object_new (E_TYPE_IMAGE_CHOOSER, NULL);
+}
gboolean
-e_image_chooser_set_from_file (EImageChooser *chooser, const gchar *filename)
+e_image_chooser_set_from_file (EImageChooser *chooser,
+ const gchar *filename)
{
gchar *data;
gsize data_length;
g_return_val_if_fail (E_IS_IMAGE_CHOOSER (chooser), FALSE);
- g_return_val_if_fail (filename, FALSE);
+ g_return_val_if_fail (filename != NULL, FALSE);
- if (!g_file_get_contents (filename, &data, &data_length, NULL)) {
+ if (!g_file_get_contents (filename, &data, &data_length, NULL))
return FALSE;
- }
if (!set_image_from_data (chooser, data, data_length))
g_free (data);
@@ -454,18 +421,10 @@ e_image_chooser_set_from_file (EImageChooser *chooser, const gchar *filename)
return TRUE;
}
-void
-e_image_chooser_set_editable (EImageChooser *chooser, gboolean editable)
-{
- g_return_if_fail (E_IS_IMAGE_CHOOSER (chooser));
-
- chooser->priv->editable = editable;
-
- gtk_widget_set_sensitive (chooser->priv->browse_button, editable);
-}
-
gboolean
-e_image_chooser_get_image_data (EImageChooser *chooser, gchar **data, gsize *data_length)
+e_image_chooser_get_image_data (EImageChooser *chooser,
+ gchar **data,
+ gsize *data_length)
{
g_return_val_if_fail (E_IS_IMAGE_CHOOSER (chooser), FALSE);
g_return_val_if_fail (data != NULL, FALSE);
@@ -479,7 +438,9 @@ e_image_chooser_get_image_data (EImageChooser *chooser, gchar **data, gsize *dat
}
gboolean
-e_image_chooser_set_image_data (EImageChooser *chooser, gchar *data, gsize data_length)
+e_image_chooser_set_image_data (EImageChooser *chooser,
+ gchar *data,
+ gsize data_length)
{
gchar *buf;
diff --git a/widgets/misc/e-image-chooser.h b/widgets/misc/e-image-chooser.h
index be2d427291..7116500dc4 100644
--- a/widgets/misc/e-image-chooser.h
+++ b/widgets/misc/e-image-chooser.h
@@ -1,4 +1,5 @@
/*
+ * e-image-chooser.h
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -14,54 +15,61 @@
* License along with the program; if not, see <http://www.gnu.org/licenses/>
*
*
- * Authors:
- * Chris Toshok <toshok@ximian.com>
- *
* Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
*
*/
-#ifndef _E_IMAGE_CHOOSER_H_
-#define _E_IMAGE_CHOOSER_H_
+#ifndef E_IMAGE_CHOOSER_H
+#define E_IMAGE_CHOOSER_H
#include <gtk/gtk.h>
-G_BEGIN_DECLS
+/* Standard GObject macros */
+#define E_TYPE_IMAGE_CHOOSER \
+ (e_image_chooser_get_type ())
+#define E_IMAGE_CHOOSER(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_IMAGE_CHOOSER, EImageChooser))
+#define E_IMAGE_CHOOSER_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_IMAGE_CHOOSER, EImageChooserClass))
+#define E_IS_IMAGE_CHOOSER(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_IMAGE_CHOOSER))
+#define E_IS_IMAGE_CHOOSER_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_IMAGE_CHOOSER))
+#define E_IMAGE_CHOOSER_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_IMAGE_CHOOSER, EImageChooserClass))
-#define E_TYPE_IMAGE_CHOOSER (e_image_chooser_get_type ())
-#define E_IMAGE_CHOOSER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_IMAGE_CHOOSER, EImageChooser))
-#define E_IMAGE_CHOOSER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E_TYPE_IMAGE_CHOOSER, EImageChooserClass))
-#define E_IS_IMAGE_CHOOSER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_TYPE_IMAGE_CHOOSER))
-#define E_IS_IMAGE_CHOOSER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), E_TYPE_IMAGE_CHOOSER))
+G_BEGIN_DECLS
-typedef struct _EImageChooser EImageChooser;
-typedef struct _EImageChooserClass EImageChooserClass;
+typedef struct _EImageChooser EImageChooser;
+typedef struct _EImageChooserClass EImageChooserClass;
typedef struct _EImageChooserPrivate EImageChooserPrivate;
-struct _EImageChooser
-{
+struct _EImageChooser {
GtkVBox parent;
-
EImageChooserPrivate *priv;
};
-struct _EImageChooserClass
-{
+struct _EImageChooserClass {
GtkVBoxClass parent_class;
/* signals */
void (*changed) (EImageChooser *chooser);
-
-
};
-GtkWidget *e_image_chooser_new (void);
-GType e_image_chooser_get_type (void);
-
-gboolean e_image_chooser_set_from_file (EImageChooser *chooser, const gchar *filename);
-gboolean e_image_chooser_set_image_data (EImageChooser *chooser, gchar *data, gsize data_length);
-void e_image_chooser_set_editable (EImageChooser *chooser, gboolean editable);
-
-gboolean e_image_chooser_get_image_data (EImageChooser *chooser, gchar **data, gsize *data_length);
+GType e_image_chooser_get_type (void);
+GtkWidget * e_image_chooser_new (void);
+gboolean e_image_chooser_set_from_file (EImageChooser *chooser,
+ const gchar *filename);
+gboolean e_image_chooser_set_image_data (EImageChooser *chooser,
+ gchar *data,
+ gsize data_length);
+gboolean e_image_chooser_get_image_data (EImageChooser *chooser,
+ gchar **data,
+ gsize *data_length);
-#endif /* _E_IMAGE_CHOOSER_H_ */
+#endif /* E_IMAGE_CHOOSER_H */
diff --git a/widgets/misc/e-info-label.c b/widgets/misc/e-info-label.c
deleted file mode 100644
index 3333d47202..0000000000
--- a/widgets/misc/e-info-label.c
+++ /dev/null
@@ -1,246 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) version 3.
- *
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- *
- * Authors:
- * Michael Zucchi <notzed@ximian.com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <string.h>
-
-#include "e-info-label.h"
-
-static GtkHBoxClass *el_parent;
-
-static void
-el_init(GObject *o)
-{
- /*EInfoLabel *el = (EInfoLabel *)o;*/
-}
-
-static void
-el_finalise(GObject *o)
-{
- ((GObjectClass *)el_parent)->finalize(o);
-}
-
-static void
-el_destroy (GtkObject *o)
-{
- ((EInfoLabel *)o)->location = NULL;
- ((EInfoLabel *)o)->info = NULL;
-
- ((GtkObjectClass *)el_parent)->destroy(o);
-}
-
-static gint
-el_expose_event(GtkWidget *w, GdkEventExpose *event)
-{
- gint x = ((GtkContainer *)w)->border_width;
-
- /* This seems a hack to me, but playing with styles wouldn't affect the background */
- gtk_paint_flat_box(w->style, w->window,
- GTK_STATE_ACTIVE, GTK_SHADOW_NONE,
- &event->area, w, "EInfoLabel",
- w->allocation.x+x, w->allocation.y+x,
- w->allocation.width-x*2, w->allocation.height-x*2);
-
- return ((GtkWidgetClass *)el_parent)->expose_event(w, event);
-}
-
-static gint
-get_text_full_width (GtkWidget *label)
-{
- PangoLayout *layout;
- PangoRectangle rect;
- gint width;
-
- g_return_val_if_fail (GTK_IS_LABEL (label), 0);
-
- layout = gtk_label_get_layout (GTK_LABEL (label));
-
- if (!layout)
- return 0;
-
- width = pango_layout_get_width (layout);
- pango_layout_set_width (layout, -1);
- pango_layout_get_extents (layout, NULL, &rect);
- pango_layout_set_width (layout, width);
-
- return PANGO_PIXELS (rect.width);
-}
-
-static void
-el_size_allocate (GtkWidget *widget, GtkAllocation *pallocation)
-{
- EInfoLabel *el;
- GtkAllocation allocation;
- gint full_loc, full_nfo;
- gint diff;
-
- /* let calculate parent class first, and then just make it not divide evenly */
- ((GtkWidgetClass *)el_parent)->size_allocate (widget, pallocation);
-
- g_return_if_fail (widget!= NULL);
-
- el = (EInfoLabel*) widget;
-
- if (!el->location)
- return;
-
- full_loc = get_text_full_width (el->location) + 1;
- full_nfo = get_text_full_width (el->info) + 1;
-
- /* do not know the width of text, thus return */
- if (full_loc == 1 && full_nfo == 1)
- return;
-
- if (el->location->allocation.width + el->info->allocation.width >= full_loc + full_nfo) {
- /* allocate for location only as many pixels as it requires to not ellipsize
- and keep rest for the info part */
- diff = el->location->allocation.width - full_loc;
- } else {
- /* make both shorter, but based on the ratio of its full widths */
- gint total_have = el->location->allocation.width + el->info->allocation.width;
- gint total_full = full_loc + full_nfo;
-
- diff = el->location->allocation.width - full_loc * total_have / total_full;
- }
-
- if (!diff)
- return;
-
- allocation = el->location->allocation;
- allocation.width -= diff;
- gtk_widget_size_allocate (el->location, &allocation);
-
- allocation = el->info->allocation;
- allocation.x -= diff;
- allocation.width += diff;
- gtk_widget_size_allocate (el->info, &allocation);
-}
-
-static void
-el_class_init(GObjectClass *klass)
-{
- klass->finalize = el_finalise;
-
- ((GtkObjectClass *)klass)->destroy = el_destroy;
- ((GtkWidgetClass *)klass)->expose_event = el_expose_event;
- ((GtkWidgetClass *)klass)->size_allocate = el_size_allocate;
-}
-
-GType
-e_info_label_get_type(void)
-{
- static GType type = 0;
-
- if (type == 0) {
- static const GTypeInfo info = {
- sizeof(EInfoLabelClass),
- NULL, NULL,
- (GClassInitFunc)el_class_init,
- NULL, NULL,
- sizeof(EInfoLabel), 0,
- (GInstanceInitFunc)el_init
- };
- el_parent = g_type_class_ref(gtk_hbox_get_type());
- type = g_type_register_static(gtk_hbox_get_type(), "EInfoLabel", &info, 0);
- }
-
- return type;
-}
-
-/**
- * e_info_label_new:
- * @icon:
- *
- * Create a new info label widget. @icon is the name of the icon
- * (from the icon theme) to use for the icon image.
- *
- * Return value:
- **/
-GtkWidget *
-e_info_label_new(const gchar *icon)
-{
- EInfoLabel *el = g_object_new(e_info_label_get_type(), NULL);
- GtkWidget *image;
-
- image = gtk_image_new_from_icon_name (icon, GTK_ICON_SIZE_MENU);
- gtk_misc_set_padding((GtkMisc *)image, 6, 6);
- gtk_box_pack_start((GtkBox *)el, image, FALSE, TRUE, 0);
- gtk_widget_show(image);
-
- gtk_container_set_border_width((GtkContainer *)el, 3);
-
- return (GtkWidget *)el;
-}
-
-/**
- * e_info_label_set_info:
- * @el:
- * @location:
- * @info:
- *
- * Set the information to show on the label. @location is some
- * context about the current view. e.g. the folder name. If the
- * label is too wide, this will be truncated.
- *
- * @info is some info about this location.
- **/
-void
-e_info_label_set_info(EInfoLabel *el, const gchar *location, const gchar *info)
-{
- gchar *markup;
-
- if (el->location == NULL) {
- el->location = gtk_label_new (NULL);
- el->info = gtk_label_new (NULL);
-
- gtk_label_set_ellipsize (GTK_LABEL (el->location), PANGO_ELLIPSIZE_END);
- gtk_misc_set_alignment (GTK_MISC (el->location), 0.0, 0.5);
- gtk_misc_set_padding (GTK_MISC (el->location), 0, 6);
-
- gtk_label_set_ellipsize (GTK_LABEL (el->info), PANGO_ELLIPSIZE_MIDDLE);
- gtk_misc_set_alignment (GTK_MISC (el->info), 1.0, 0.5);
- gtk_misc_set_padding (GTK_MISC (el->info), 0, 6);
-
- gtk_widget_show (el->location);
- gtk_widget_show (el->info);
-
- gtk_box_pack_start (
- GTK_BOX (el), GTK_WIDGET (el->location),
- TRUE, TRUE, 0);
- gtk_box_pack_end (
- GTK_BOX (el), GTK_WIDGET (el->info),
- TRUE, TRUE, 6);
- gtk_widget_set_state (GTK_WIDGET (el), GTK_STATE_ACTIVE);
- }
-
- markup = g_markup_printf_escaped ("<b>%s</b>", location);
- gtk_label_set_markup (GTK_LABEL (el->location), markup);
- g_free (markup);
-
- markup = g_markup_printf_escaped ("<small>%s</small>", info);
- gtk_label_set_markup (GTK_LABEL (el->info), markup);
- g_free (markup);
-}
-
diff --git a/widgets/misc/e-info-label.h b/widgets/misc/e-info-label.h
deleted file mode 100644
index 977cc6ac4f..0000000000
--- a/widgets/misc/e-info-label.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) version 3.
- *
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- *
- * Authors:
- * Michael Zucchi <notzed@ximian.com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-#ifndef _E_INFO_LABEL_H
-#define _E_INFO_LABEL_H
-
-#include <gtk/gtk.h>
-
-G_BEGIN_DECLS
-
-#define E_INFO_LABEL_GET_CLASS(emfv) ((EInfoLabelClass *) G_OBJECT_GET_CLASS (emfv))
-
-typedef struct _EInfoLabel EInfoLabel;
-typedef struct _EInfoLabelClass EInfoLabelClass;
-
-struct _EInfoLabel {
- GtkHBox parent;
-
- GtkWidget *location;
- GtkWidget *info;
-};
-
-struct _EInfoLabelClass {
- GtkHBoxClass parent_class;
-};
-
-GType e_info_label_get_type(void);
-
-GtkWidget *e_info_label_new(const gchar *icon);
-void e_info_label_set_info(EInfoLabel *, const gchar *loc, const gchar *info);
-
-G_END_DECLS
-
-#endif /* ! _E_INFO_LABEL_H */
diff --git a/widgets/misc/e-menu-tool-button.c b/widgets/misc/e-menu-tool-button.c
new file mode 100644
index 0000000000..53778e6678
--- /dev/null
+++ b/widgets/misc/e-menu-tool-button.c
@@ -0,0 +1,157 @@
+/*
+ * e-menu-tool-button.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#include "e-menu-tool-button.h"
+
+static gpointer parent_class;
+
+static GtkWidget *
+menu_tool_button_clone_image (GtkWidget *source)
+{
+ GtkIconSize size;
+ GtkImageType image_type;
+ const gchar *icon_name;
+
+ /* XXX This isn't general purpose because it requires that the
+ * source image be using a named icon. Somewhat surprised
+ * GTK+ doesn't offer something like this. */
+ image_type = gtk_image_get_storage_type (GTK_IMAGE (source));
+ g_return_val_if_fail (image_type == GTK_IMAGE_ICON_NAME, NULL);
+ gtk_image_get_icon_name (GTK_IMAGE (source), &icon_name, &size);
+
+ return gtk_image_new_from_icon_name (icon_name, size);
+}
+
+static GtkMenuItem *
+menu_tool_button_get_first_menu_item (GtkMenuToolButton *menu_tool_button)
+{
+ GtkWidget *menu;
+ GList *children;
+
+ menu = gtk_menu_tool_button_get_menu (menu_tool_button);
+ if (!GTK_IS_MENU (menu))
+ return NULL;
+
+ /* XXX GTK+ 2.12 provides no accessor function. */
+ children = GTK_MENU_SHELL (menu)->children;
+ if (children == NULL)
+ return NULL;
+
+ return GTK_MENU_ITEM (children->data);
+}
+
+static void
+menu_tool_button_update_button (GtkToolButton *tool_button)
+{
+ GtkMenuItem *menu_item;
+ GtkMenuToolButton *menu_tool_button;
+ GtkImageMenuItem *image_menu_item;
+ GtkAction *action;
+ GtkWidget *image;
+ gchar *tooltip = NULL;
+
+ menu_tool_button = GTK_MENU_TOOL_BUTTON (tool_button);
+ menu_item = menu_tool_button_get_first_menu_item (menu_tool_button);
+ if (!GTK_IS_IMAGE_MENU_ITEM (menu_item))
+ return;
+
+ image_menu_item = GTK_IMAGE_MENU_ITEM (menu_item);
+ image = gtk_image_menu_item_get_image (image_menu_item);
+ if (!GTK_IS_IMAGE (image))
+ return;
+
+ image = menu_tool_button_clone_image (image);
+ gtk_tool_button_set_icon_widget (tool_button, image);
+ gtk_widget_show (image);
+
+ /* If the menu item is a proxy for a GtkAction, extract
+ * the action's tooltip and use it as our own tooltip. */
+ action = gtk_widget_get_action (GTK_WIDGET (menu_item));
+ if (action != NULL)
+ g_object_get (action, "tooltip", &tooltip, NULL);
+ gtk_widget_set_tooltip_text (GTK_WIDGET (tool_button), tooltip);
+ g_free (tooltip);
+}
+
+static void
+menu_tool_button_clicked (GtkToolButton *tool_button)
+{
+ GtkMenuItem *menu_item;
+ GtkMenuToolButton *menu_tool_button;
+
+ menu_tool_button = GTK_MENU_TOOL_BUTTON (tool_button);
+ menu_item = menu_tool_button_get_first_menu_item (menu_tool_button);
+
+ if (GTK_IS_MENU_ITEM (menu_item))
+ gtk_menu_item_activate (menu_item);
+}
+
+static void
+menu_tool_button_class_init (EMenuToolButtonClass *class)
+{
+ GtkToolButtonClass *tool_button_class;
+
+ parent_class = g_type_class_peek_parent (class);
+
+ tool_button_class = GTK_TOOL_BUTTON_CLASS (class);
+ tool_button_class->clicked = menu_tool_button_clicked;
+}
+
+static void
+menu_tool_button_init (EMenuToolButton *button)
+{
+ g_signal_connect (
+ button, "notify::menu",
+ G_CALLBACK (menu_tool_button_update_button), NULL);
+}
+
+GType
+e_menu_tool_button_get_type (void)
+{
+ static GType type = 0;
+
+ if (G_UNLIKELY (type == 0)) {
+ const GTypeInfo type_info = {
+ sizeof (EMenuToolButtonClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) menu_tool_button_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+ sizeof (EMenuToolButton),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) menu_tool_button_init,
+ NULL /* value_table */
+ };
+
+ type = g_type_register_static (
+ GTK_TYPE_MENU_TOOL_BUTTON, "EMenuToolButton",
+ &type_info, 0);
+ }
+
+ return type;
+}
+
+GtkToolItem *
+e_menu_tool_button_new (const gchar *label)
+{
+ return g_object_new (E_TYPE_MENU_TOOL_BUTTON, "label", label, NULL);
+}
diff --git a/widgets/misc/e-menu-tool-button.h b/widgets/misc/e-menu-tool-button.h
new file mode 100644
index 0000000000..214f5ab217
--- /dev/null
+++ b/widgets/misc/e-menu-tool-button.h
@@ -0,0 +1,68 @@
+/*
+ * e-menu-tool-button.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+/* EMenuToolButton is a variation of GtkMenuToolButton where the
+ * button icon always reflects the first menu item, and clicking
+ * the button activates the first menu item. */
+
+#ifndef E_MENU_TOOL_BUTTON_H
+#define E_MENU_TOOL_BUTTON_H
+
+#include <gtk/gtk.h>
+
+/* Standard GObject macros */
+#define E_TYPE_MENU_TOOL_BUTTON \
+ (e_menu_tool_button_get_type ())
+#define E_MENU_TOOL_BUTTON(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_MENU_TOOL_BUTTON, EMenuToolButton))
+#define E_MENU_TOOL_BUTTON_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_MENU_TOOL_BUTTON, EMenuToolButtonClass))
+#define E_IS_MENU_TOOL_BUTTON(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_MENU_TOOL_BUTTON))
+#define E_IS_MENU_TOOL_BUTTON_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_MENU_TOOL_BUTTON))
+#define E_MENU_TOOL_BUTTON_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_MENU_TOOL_BUTTON, EMenuToolButtonClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EMenuToolButton EMenuToolButton;
+typedef struct _EMenuToolButtonClass EMenuToolButtonClass;
+
+struct _EMenuToolButton {
+ GtkMenuToolButton parent;
+};
+
+struct _EMenuToolButtonClass {
+ GtkMenuToolButtonClass parent_class;
+};
+
+GType e_menu_tool_button_get_type (void);
+GtkToolItem * e_menu_tool_button_new (const gchar *label);
+
+G_END_DECLS
+
+#endif /* E_MENU_TOOL_BUTTON_H */
diff --git a/widgets/misc/e-multi-config-dialog.c b/widgets/misc/e-multi-config-dialog.c
deleted file mode 100644
index eaf843dfb2..0000000000
--- a/widgets/misc/e-multi-config-dialog.c
+++ /dev/null
@@ -1,374 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) version 3.
- *
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- *
- * Authors:
- * Ettore Perazzoli <ettore@ximian.com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "e-multi-config-dialog.h"
-
-#include <e-util/e-util.h>
-#include <table/e-table-scrolled.h>
-#include <table/e-table-memory-store.h>
-#include <table/e-cell-pixbuf.h>
-#include <table/e-cell-vbox.h>
-#include <table/e-cell-text.h>
-
-#define SWITCH_PAGE_INTERVAL 250
-
-struct _EMultiConfigDialogPrivate {
- GSList *pages;
-
- GtkWidget *list_e_table;
- ETableModel *list_e_table_model;
-
- GtkWidget *notebook;
-
- gint set_page_timeout_id;
- gint set_page_timeout_page;
-};
-
-G_DEFINE_TYPE (EMultiConfigDialog, e_multi_config_dialog, GTK_TYPE_DIALOG)
-
-
-/* ETable stuff. */
-
-static const gchar *list_e_table_spec =
- "<ETableSpecification cursor-mode=\"line\""
- " selection-mode=\"browse\""
- " no-headers=\"true\""
- " alternating-row-colors=\"false\""
- " horizontal-resize=\"true\""
- ">"
- " <ETableColumn model_col=\"0\""
- " expansion=\"1.0\""
- " cell=\"vbox\""
- " minimum_width=\"32\""
- " resizable=\"true\""
- " _title=\"Category\""
- " compare=\"string\"/>"
- " <ETableState>"
- " <column source=\"0\"/>"
- " <grouping>"
- " </grouping>"
- " </ETableState>"
- "</ETableSpecification>";
-
-/* Page handling. */
-
-static GtkWidget *
-create_page_container (const gchar *description,
- GtkWidget *widget)
-{
- GtkWidget *vbox;
-
- vbox = gtk_vbox_new (FALSE, 0);
-
- gtk_box_pack_start (GTK_BOX (vbox), widget, TRUE, TRUE, 0);
-
- gtk_widget_show (widget);
- gtk_widget_show (vbox);
-
- return vbox;
-}
-
-/* Timeout for switching pages (so it's more comfortable navigating with the
- keyboard). */
-
-static gint
-set_page_timeout_callback (gpointer data)
-{
- EMultiConfigDialog *multi_config_dialog;
- EMultiConfigDialogPrivate *priv;
-
- multi_config_dialog = E_MULTI_CONFIG_DIALOG (data);
- priv = multi_config_dialog->priv;
-
- gtk_notebook_set_current_page (
- GTK_NOTEBOOK (priv->notebook), priv->set_page_timeout_page);
-
- priv->set_page_timeout_id = 0;
- gtk_widget_grab_focus(priv->list_e_table);
- return FALSE;
-}
-
-
-/* Button handling. */
-
-static void
-do_close (EMultiConfigDialog *dialog)
-{
- gtk_widget_destroy (GTK_WIDGET (dialog));
-}
-
-
-/* ETable signals. */
-
-static void
-table_cursor_change_callback (ETable *etable,
- gint row,
- gpointer data)
-{
- EMultiConfigDialog *dialog;
- EMultiConfigDialogPrivate *priv;
-
- dialog = E_MULTI_CONFIG_DIALOG (data);
- priv = dialog->priv;
-
- if (priv->set_page_timeout_id == 0)
- priv->set_page_timeout_id = g_timeout_add (SWITCH_PAGE_INTERVAL,
- set_page_timeout_callback,
- dialog);
-
- priv->set_page_timeout_page = row;
-}
-
-
-/* GObject methods. */
-
-static void
-impl_finalize (GObject *object)
-{
- EMultiConfigDialog *dialog;
- EMultiConfigDialogPrivate *priv;
-
- dialog = E_MULTI_CONFIG_DIALOG (object);
- priv = dialog->priv;
-
- if (priv->set_page_timeout_id != 0)
- g_source_remove (priv->set_page_timeout_id);
-
- g_slist_free (priv->pages);
-
- g_free (priv);
-
- (* G_OBJECT_CLASS (e_multi_config_dialog_parent_class)->finalize) (object);
-}
-
-
-/* GtkDialog methods. */
-
-static void
-impl_response (GtkDialog *dialog, gint response_id)
-{
- EMultiConfigDialog *multi_config_dialog;
-
- multi_config_dialog = E_MULTI_CONFIG_DIALOG (dialog);
-
- switch (response_id) {
- case GTK_RESPONSE_HELP:
- e_display_help (GTK_WINDOW (dialog), "config-prefs");
- break;
- case GTK_RESPONSE_CLOSE:
- default:
- do_close (multi_config_dialog);
- break;
- }
-}
-
-
-/* GObject ctors. */
-
-static void
-e_multi_config_dialog_class_init (EMultiConfigDialogClass *class)
-{
- GObjectClass *object_class;
- GtkDialogClass *dialog_class;
-
- object_class = G_OBJECT_CLASS (class);
- object_class->finalize = impl_finalize;
-
- dialog_class = GTK_DIALOG_CLASS (class);
- dialog_class->response = impl_response;
-}
-
-#define RGB_COLOR(color) (((color).red & 0xff00) << 8 | \
- ((color).green & 0xff00) | \
- ((color).blue & 0xff00) >> 8)
-
-static void
-canvas_realize (GtkWidget *widget, EMultiConfigDialog *dialog)
-{
-}
-
-
-static ETableMemoryStoreColumnInfo columns[] = {
- E_TABLE_MEMORY_STORE_STRING,
- E_TABLE_MEMORY_STORE_PIXBUF,
- E_TABLE_MEMORY_STORE_PIXBUF,
- E_TABLE_MEMORY_STORE_PIXBUF,
- E_TABLE_MEMORY_STORE_PIXBUF,
- E_TABLE_MEMORY_STORE_TERMINATOR
-};
-
-static void
-e_multi_config_dialog_init (EMultiConfigDialog *multi_config_dialog)
-{
- EMultiConfigDialogPrivate *priv;
- ETableModel *list_e_table_model;
- GtkWidget *dialog_vbox;
- GtkWidget *hbox;
- GtkWidget *notebook;
- GtkWidget *list_e_table;
- ETableExtras *extras;
- ECell *pixbuf;
- ECell *text;
- ECell *vbox;
-
- gtk_dialog_set_has_separator (GTK_DIALOG (multi_config_dialog), FALSE);
- gtk_widget_realize (GTK_WIDGET (multi_config_dialog));
- gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (multi_config_dialog)->vbox), 0);
- gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (multi_config_dialog)->action_area), 12);
-
- hbox = gtk_hbox_new (FALSE, 6);
- gtk_container_set_border_width (GTK_CONTAINER (hbox), 12);
- dialog_vbox = GTK_DIALOG (multi_config_dialog)->vbox;
-
- gtk_container_add (GTK_CONTAINER (dialog_vbox), hbox);
-
- list_e_table_model = e_table_memory_store_new (columns);
-
- vbox = e_cell_vbox_new ();
-
- pixbuf = e_cell_pixbuf_new();
- g_object_set (G_OBJECT (pixbuf),
- "focused_column", 2,
- "selected_column", 3,
- "unselected_column", 4,
- NULL);
- e_cell_vbox_append (E_CELL_VBOX (vbox), pixbuf, 1);
- g_object_unref (pixbuf);
-
- text = e_cell_text_new (NULL, GTK_JUSTIFY_CENTER);
- e_cell_vbox_append (E_CELL_VBOX (vbox), text, 0);
- g_object_unref (text);
-
- extras = e_table_extras_new ();
- e_table_extras_add_cell (extras, "vbox", vbox);
-
- list_e_table = e_table_scrolled_new (list_e_table_model, extras, list_e_table_spec, NULL);
- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (list_e_table), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
- g_signal_connect (e_table_scrolled_get_table (E_TABLE_SCROLLED (list_e_table)),
- "cursor_change", G_CALLBACK (table_cursor_change_callback), multi_config_dialog);
-
- g_signal_connect (e_table_scrolled_get_table (E_TABLE_SCROLLED (list_e_table))->table_canvas,
- "realize", G_CALLBACK (canvas_realize), multi_config_dialog);
-
- g_object_unref (extras);
-
- gtk_box_pack_start (GTK_BOX (hbox), list_e_table, FALSE, TRUE, 0);
-
- notebook = gtk_notebook_new ();
- gtk_notebook_set_show_tabs (GTK_NOTEBOOK (notebook), FALSE);
- gtk_notebook_set_show_border (GTK_NOTEBOOK (notebook), FALSE);
- gtk_box_pack_start (GTK_BOX (hbox), notebook, TRUE, TRUE, 0);
-
- gtk_widget_show (hbox);
- gtk_widget_show (notebook);
- gtk_widget_show (list_e_table);
-
- gtk_dialog_add_buttons (GTK_DIALOG (multi_config_dialog),
- GTK_STOCK_HELP, GTK_RESPONSE_HELP,
- GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
- NULL);
- gtk_dialog_set_default_response (GTK_DIALOG (multi_config_dialog), GTK_RESPONSE_OK);
-
- gtk_window_set_resizable (GTK_WINDOW (multi_config_dialog), TRUE);
-
- priv = g_new (EMultiConfigDialogPrivate, 1);
- priv->pages = NULL;
- priv->list_e_table = list_e_table;
- priv->list_e_table_model = list_e_table_model;
- priv->notebook = notebook;
- priv->set_page_timeout_id = 0;
- priv->set_page_timeout_page = 0;
-
- multi_config_dialog->priv = priv;
-}
-
-
-GtkWidget *
-e_multi_config_dialog_new (void)
-{
- return g_object_new (e_multi_config_dialog_get_type (), NULL);
-}
-
-
-void
-e_multi_config_dialog_add_page (EMultiConfigDialog *dialog,
- const gchar *title,
- const gchar *description,
- GdkPixbuf *icon,
- EConfigPage *page_widget)
-{
- EMultiConfigDialogPrivate *priv;
- AtkObject *a11y;
- AtkObject *a11yPage;
- gint page_no;
-
- g_return_if_fail (E_IS_MULTI_CONFIG_DIALOG (dialog));
- g_return_if_fail (title != NULL);
- g_return_if_fail (description != NULL);
- g_return_if_fail (E_IS_CONFIG_PAGE (page_widget));
-
- priv = dialog->priv;
-
- priv->pages = g_slist_append (priv->pages, page_widget);
-
- e_table_memory_store_insert (E_TABLE_MEMORY_STORE (priv->list_e_table_model), -1, NULL, title, icon, NULL, NULL, NULL);
-
- page_no = gtk_notebook_append_page (GTK_NOTEBOOK (priv->notebook),
- create_page_container (description, GTK_WIDGET (page_widget)),
- NULL);
-
- a11y = gtk_widget_get_accessible (GTK_WIDGET(priv->notebook));
- a11yPage = atk_object_ref_accessible_child (a11y, page_no);
- if (a11yPage != NULL) {
- if (atk_object_get_role (a11yPage) == ATK_ROLE_PAGE_TAB)
- atk_object_set_name (a11yPage, title);
- g_object_unref (a11yPage);
- }
- if (priv->pages->next == NULL) {
- ETable *table;
-
- /* FIXME: This is supposed to select the first entry by default
- but it doesn't seem to work at all. */
- table = e_table_scrolled_get_table (E_TABLE_SCROLLED (priv->list_e_table));
- e_table_set_cursor_row (table, 0);
- e_selection_model_select_all (e_table_get_selection_model (table));
- }
-}
-
-void
-e_multi_config_dialog_show_page (EMultiConfigDialog *dialog, gint page)
-{
- EMultiConfigDialogPrivate *priv;
-
- g_return_if_fail (dialog != NULL);
- g_return_if_fail (E_IS_MULTI_CONFIG_DIALOG (dialog));
-
- priv = dialog->priv;
-
- e_table_set_cursor_row (e_table_scrolled_get_table (E_TABLE_SCROLLED (priv->list_e_table)), page);
- gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook), page);
-}
-
diff --git a/widgets/misc/e-multi-config-dialog.h b/widgets/misc/e-multi-config-dialog.h
deleted file mode 100644
index 1bc310b888..0000000000
--- a/widgets/misc/e-multi-config-dialog.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) version 3.
- *
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- *
- * Authors:
- * Ettore Perazzoli <ettore@ximian.com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-#ifndef _E_MULTI_CONFIG_DIALOG_H_
-#define _E_MULTI_CONFIG_DIALOG_H_
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "e-config-page.h"
-
-#include <gtk/gtk.h>
-
-G_BEGIN_DECLS
-
-#define E_TYPE_MULTI_CONFIG_DIALOG (e_multi_config_dialog_get_type ())
-#define E_MULTI_CONFIG_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_MULTI_CONFIG_DIALOG, EMultiConfigDialog))
-#define E_MULTI_CONFIG_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E_TYPE_MULTI_CONFIG_DIALOG, EMultiConfigDialogClass))
-#define E_IS_MULTI_CONFIG_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_TYPE_MULTI_CONFIG_DIALOG))
-#define E_IS_MULTI_CONFIG_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), E_TYPE_MULTI_CONFIG_DIALOG))
-
-
-typedef struct _EMultiConfigDialog EMultiConfigDialog;
-typedef struct _EMultiConfigDialogPrivate EMultiConfigDialogPrivate;
-typedef struct _EMultiConfigDialogClass EMultiConfigDialogClass;
-
-struct _EMultiConfigDialog {
- GtkDialog parent;
-
- EMultiConfigDialogPrivate *priv;
-};
-
-struct _EMultiConfigDialogClass {
- GtkDialogClass parent_class;
-};
-
-
-GType e_multi_config_dialog_get_type (void);
-GtkWidget *e_multi_config_dialog_new (void);
-
-void e_multi_config_dialog_add_page (EMultiConfigDialog *dialog,
- const gchar *title,
- const gchar *description,
- GdkPixbuf *icon,
- EConfigPage *page);
-void e_multi_config_dialog_show_page (EMultiConfigDialog *dialog,
- gint page);
-
-G_END_DECLS
-
-#endif /* _E_MULTI_CONFIG_DIALOG_H_ */
diff --git a/widgets/misc/e-online-button.c b/widgets/misc/e-online-button.c
index 114d76ac32..c14114b9c3 100644
--- a/widgets/misc/e-online-button.c
+++ b/widgets/misc/e-online-button.c
@@ -23,6 +23,12 @@
(G_TYPE_INSTANCE_GET_PRIVATE \
((obj), E_TYPE_ONLINE_BUTTON, EOnlineButtonPrivate))
+#define ONLINE_TOOLTIP \
+ "Evolution is currently online. Click this button to work offline."
+
+#define OFFLINE_TOOLTIP \
+ "Evolution is currently offline. Click this button to work online."
+
struct _EOnlineButtonPrivate {
GtkWidget *image;
gboolean online;
@@ -175,6 +181,7 @@ e_online_button_set_online (EOnlineButton *button,
GtkIconTheme *icon_theme;
const gchar *filename;
const gchar *icon_name;
+ const gchar *tooltip;
g_return_if_fail (E_IS_ONLINE_BUTTON (button));
@@ -191,5 +198,8 @@ e_online_button_set_online (EOnlineButton *button,
gtk_image_set_from_file (image, filename);
gtk_icon_info_free (icon_info);
+ tooltip = _(online ? ONLINE_TOOLTIP : OFFLINE_TOOLTIP);
+ gtk_widget_set_tooltip_text (GTK_WIDGET (button), tooltip);
+
g_object_notify (G_OBJECT (button), "online");
}
diff --git a/widgets/misc/e-popup-action.c b/widgets/misc/e-popup-action.c
new file mode 100644
index 0000000000..e856a1fc24
--- /dev/null
+++ b/widgets/misc/e-popup-action.c
@@ -0,0 +1,285 @@
+/*
+ * e-popup-action.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#include "e-popup-action.h"
+
+#include <glib/gi18n.h>
+#include "e-util/e-binding.h"
+
+#define E_POPUP_ACTION_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), E_TYPE_POPUP_ACTION, EPopupActionPrivate))
+
+enum {
+ PROP_0,
+ PROP_SOURCE
+};
+
+struct _EPopupActionPrivate {
+ GtkAction *source;
+};
+
+static gpointer parent_class;
+
+static void
+popup_action_set_source (EPopupAction *popup_action,
+ GtkAction *source)
+{
+ g_return_if_fail (popup_action->priv->source == NULL);
+ g_return_if_fail (GTK_IS_ACTION (source));
+
+ popup_action->priv->source = g_object_ref (source);
+}
+
+static void
+popup_action_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_SOURCE:
+ popup_action_set_source (
+ E_POPUP_ACTION (object),
+ g_value_get_object (value));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+popup_action_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_SOURCE:
+ g_value_set_object (
+ value, e_popup_action_get_source (
+ E_POPUP_ACTION (object)));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+popup_action_dispose (GObject *object)
+{
+ EPopupActionPrivate *priv;
+
+ priv = E_POPUP_ACTION_GET_PRIVATE (object);
+
+ if (priv->source != NULL) {
+ g_object_unref (priv->source);
+ priv->source = NULL;
+ }
+
+ /* Chain up to parent's dispose() method. */
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+popup_action_constructed (GObject *object)
+{
+ EPopupActionPrivate *priv;
+ GObject *source;
+ gchar *icon_name;
+ gchar *label;
+ gchar *stock_id;
+ gchar *tooltip;
+
+ priv = E_POPUP_ACTION_GET_PRIVATE (object);
+
+ source = G_OBJECT (priv->source);
+
+ g_object_get (
+ object, "icon-name", &icon_name, "label", &label,
+ "stock-id", &stock_id, "tooltip", &tooltip, NULL);
+
+ if (label == NULL)
+ e_binding_new (source, "label", object, "label");
+
+ if (tooltip == NULL)
+ e_binding_new (source, "tooltip", object, "tooltip");
+
+ if (icon_name == NULL && stock_id == NULL) {
+ g_free (icon_name);
+ g_free (stock_id);
+
+ g_object_get (
+ source, "icon-name", &icon_name,
+ "stock-id", &stock_id, NULL);
+
+ if (icon_name == NULL) {
+ e_binding_new (
+ source, "icon-name", object, "icon-name");
+ e_binding_new (
+ source, "stock-id", object, "stock-id");
+ } else {
+ e_binding_new (
+ source, "stock-id", object, "stock-id");
+ e_binding_new (
+ source, "icon-name", object, "icon-name");
+ }
+ }
+
+ e_binding_new (source, "sensitive", object, "visible");
+
+ g_free (icon_name);
+ g_free (label);
+ g_free (stock_id);
+ g_free (tooltip);
+}
+
+static void
+popup_action_class_init (EPopupActionClass *class)
+{
+ GObjectClass *object_class;
+
+ parent_class = g_type_class_peek_parent (class);
+ g_type_class_add_private (class, sizeof (EPopupActionPrivate));
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->set_property = popup_action_set_property;
+ object_class->get_property = popup_action_get_property;
+ object_class->dispose = popup_action_dispose;
+
+ g_object_class_install_property (
+ object_class,
+ PROP_SOURCE,
+ g_param_spec_object (
+ "source",
+ _("Source Action"),
+ _("The source action to proxy"),
+ GTK_TYPE_ACTION,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY));
+}
+
+static void
+popup_action_init (EPopupAction *popup_action)
+{
+ popup_action->priv = E_POPUP_ACTION_GET_PRIVATE (popup_action);
+}
+
+GType
+e_popup_action_get_type (void)
+{
+ static GType type = 0;
+
+ if (G_UNLIKELY (type == 0)) {
+ static const GTypeInfo type_info = {
+ sizeof (EPopupActionClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) popup_action_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+ sizeof (EPopupAction),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) popup_action_init,
+ NULL /* value_table */
+ };
+
+ type = g_type_register_static (
+ GTK_TYPE_ACTION, "EPopupAction", &type_info, 0);
+ }
+
+ return type;
+}
+
+EPopupAction *
+e_popup_action_new (const gchar *name,
+ const gchar *label,
+ GtkAction *source)
+{
+ EPopupAction *popup_action;
+
+ g_return_val_if_fail (name != NULL, NULL);
+ g_return_val_if_fail (GTK_IS_ACTION (source), NULL);
+
+ popup_action = g_object_new (
+ E_TYPE_POPUP_ACTION, "name", name,
+ "label", label, "source", source, NULL);
+
+ /* XXX This is a hack to work around the fact that GtkAction's
+ * "label" and "tooltip" properties are not constructor
+ * properties, even though they're supplied upfront.
+ *
+ * See: http://bugzilla.gnome.org/show_bug.cgi?id=568334 */
+ popup_action_constructed (G_OBJECT (popup_action));
+
+ return popup_action;
+}
+
+GtkAction *
+e_popup_action_get_source (EPopupAction *popup_action)
+{
+ g_return_val_if_fail (E_IS_POPUP_ACTION (popup_action), NULL);
+
+ return popup_action->priv->source;
+}
+
+void
+e_action_group_add_popup_actions (GtkActionGroup *action_group,
+ const EPopupActionEntry *entries,
+ guint n_entries)
+{
+ guint ii;
+
+ g_return_if_fail (GTK_IS_ACTION_GROUP (action_group));
+
+ for (ii = 0; ii < n_entries; ii++) {
+ EPopupAction *popup_action;
+ GtkAction *source;
+ const gchar *label;
+
+ label = gtk_action_group_translate_string (
+ action_group, entries[ii].label);
+
+ source = gtk_action_group_get_action (
+ action_group, entries[ii].source);
+
+ if (source == NULL) {
+ g_warning (
+ "Source action '%s' not found in "
+ "action group '%s'", entries[ii].source,
+ gtk_action_group_get_name (action_group));
+ continue;
+ }
+
+ popup_action = e_popup_action_new (
+ entries[ii].name, label, source);
+
+ g_signal_connect_swapped (
+ popup_action, "activate",
+ G_CALLBACK (gtk_action_activate),
+ popup_action->priv->source);
+
+ gtk_action_group_add_action (
+ action_group, GTK_ACTION (popup_action));
+
+ g_object_unref (popup_action);
+ }
+}
diff --git a/widgets/misc/e-popup-action.h b/widgets/misc/e-popup-action.h
new file mode 100644
index 0000000000..d19971f303
--- /dev/null
+++ b/widgets/misc/e-popup-action.h
@@ -0,0 +1,95 @@
+/*
+ * e-popup-action.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+/* A popup action is an action that lives in a popup menu. It proxies an
+ * equivalent action in the main menu, with two differences:
+ *
+ * 1) If the main menu action is insensitive, the popup action is invisible.
+ * 2) The popup action may have a different label than the main menu action.
+ *
+ * To use:
+ *
+ * Create an array of EPopupActionEntry structs. Add the main menu actions
+ * that serve as "sources" for the popup actions to an action group first.
+ * Then pass the same action group and the EPopupActionEntry array to
+ * e_action_group_add_popup_actions() to add popup actions.
+ */
+
+#ifndef E_POPUP_ACTION_H
+#define E_POPUP_ACTION_H
+
+#include <gtk/gtk.h>
+
+/* Standard GObject macros */
+#define E_TYPE_POPUP_ACTION \
+ (e_popup_action_get_type ())
+#define E_POPUP_ACTION(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_POPUP_ACTION, EPopupAction))
+#define E_POPUP_ACTION_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_POPUP_ACTION, EPopupActionClass))
+#define E_IS_POPUP_ACTION(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_POPUP_ACTION))
+#define E_IS_POPUP_ACTION_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_POPUP_ACTION))
+#define E_POPUP_ACTION_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_POPUP_ACTION, EPopupActionClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EPopupAction EPopupAction;
+typedef struct _EPopupActionClass EPopupActionClass;
+typedef struct _EPopupActionPrivate EPopupActionPrivate;
+typedef struct _EPopupActionEntry EPopupActionEntry;
+
+struct _EPopupAction {
+ GtkAction parent;
+ EPopupActionPrivate *priv;
+};
+
+struct _EPopupActionClass {
+ GtkActionClass parent_class;
+};
+
+struct _EPopupActionEntry {
+ const gchar *name;
+ const gchar *label; /* optional: overrides the source action */
+ const gchar *source; /* name of the source action */
+};
+
+GType e_popup_action_get_type (void);
+EPopupAction * e_popup_action_new (const gchar *name,
+ const gchar *label,
+ GtkAction *source);
+GtkAction * e_popup_action_get_source (EPopupAction *popup_action);
+
+void e_action_group_add_popup_actions
+ (GtkActionGroup *action_group,
+ const EPopupActionEntry *entries,
+ guint n_entries);
+
+G_END_DECLS
+
+#endif /* E_POPUP_ACTION_H */
diff --git a/widgets/misc/e-preferences-window.c b/widgets/misc/e-preferences-window.c
new file mode 100644
index 0000000000..af2d07d871
--- /dev/null
+++ b/widgets/misc/e-preferences-window.c
@@ -0,0 +1,393 @@
+/*
+ * e-preferences-window.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#include "e-preferences-window.h"
+
+#include <glib/gi18n.h>
+#include <e-util/e-util.h>
+
+#define SWITCH_PAGE_INTERVAL 250
+
+#define E_PREFERENCES_WINDOW_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), E_TYPE_PREFERENCES_WINDOW, EPreferencesWindowPrivate))
+
+struct _EPreferencesWindowPrivate {
+ GtkWidget *icon_view;
+ GtkWidget *notebook;
+ GHashTable *index;
+};
+
+enum {
+ COLUMN_TEXT, /* G_TYPE_STRING */
+ COLUMN_PIXBUF, /* GDK_TYPE_PIXBUF */
+ COLUMN_PAGE, /* G_TYPE_INT */
+ COLUMN_SORT /* G_TYPE_INT */
+};
+
+static gpointer parent_class;
+
+static GdkPixbuf *
+preferences_window_load_pixbuf (const gchar *icon_name)
+{
+ GtkIconTheme *icon_theme;
+ GtkIconInfo *icon_info;
+ GdkPixbuf *pixbuf;
+ const gchar *filename;
+ gint size;
+ GError *error = NULL;
+
+ icon_theme = gtk_icon_theme_get_default ();
+
+ if (!gtk_icon_size_lookup (GTK_ICON_SIZE_DIALOG, &size, 0))
+ return NULL;
+
+ icon_info = gtk_icon_theme_lookup_icon (
+ icon_theme, icon_name, size, 0);
+
+ if (icon_info == NULL)
+ return NULL;
+
+ filename = gtk_icon_info_get_filename (icon_info);
+
+ pixbuf = gdk_pixbuf_new_from_file (filename, &error);
+
+ gtk_icon_info_free (icon_info);
+
+ if (error != NULL) {
+ g_warning ("%s", error->message);
+ g_error_free (error);
+ }
+
+ return pixbuf;
+}
+
+static void
+preferences_window_help_clicked_cb (GtkWindow *window)
+{
+ e_display_help (window, "config-prefs");
+}
+
+static void
+preferences_window_selection_changed_cb (EPreferencesWindow *window)
+{
+ GtkIconView *icon_view;
+ GtkNotebook *notebook;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ GList *list;
+ gint page;
+
+ icon_view = GTK_ICON_VIEW (window->priv->icon_view);
+ list = gtk_icon_view_get_selected_items (icon_view);
+ if (list == NULL)
+ return;
+
+ model = gtk_icon_view_get_model (icon_view);
+ gtk_tree_model_get_iter (model, &iter, list->data);
+ gtk_tree_model_get (model, &iter, COLUMN_PAGE, &page, -1);
+
+ notebook = GTK_NOTEBOOK (window->priv->notebook);
+ gtk_notebook_set_current_page (notebook, page);
+
+ g_list_foreach (list, (GFunc) gtk_tree_path_free, NULL);
+ g_list_free (list);
+
+ gtk_widget_grab_focus (GTK_WIDGET (icon_view));
+}
+
+static void
+preferences_window_dispose (GObject *object)
+{
+ EPreferencesWindowPrivate *priv;
+
+ priv = E_PREFERENCES_WINDOW_GET_PRIVATE (object);
+
+ if (priv->icon_view != NULL) {
+ g_object_unref (priv->icon_view);
+ priv->icon_view = NULL;
+ }
+
+ if (priv->notebook != NULL) {
+ g_object_unref (priv->notebook);
+ priv->notebook = NULL;
+ }
+
+ g_hash_table_remove_all (priv->index);
+
+ /* Chain up to parent's dispose() method. */
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+preferences_window_finalize (GObject *object)
+{
+ EPreferencesWindowPrivate *priv;
+
+ priv = E_PREFERENCES_WINDOW_GET_PRIVATE (object);
+
+ g_hash_table_destroy (priv->index);
+
+ /* Chain up to parent's finalize() method. */
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+preferences_window_show (GtkWidget *widget)
+{
+ EPreferencesWindowPrivate *priv;
+ GtkIconView *icon_view;
+ GtkTreePath *path;
+
+ priv = E_PREFERENCES_WINDOW_GET_PRIVATE (widget);
+
+ icon_view = GTK_ICON_VIEW (priv->icon_view);
+
+ path = gtk_tree_path_new_first ();
+ gtk_icon_view_select_path (icon_view, path);
+ gtk_icon_view_scroll_to_path (icon_view, path, FALSE, 0.0, 0.0);
+ gtk_tree_path_free (path);
+
+ gtk_widget_grab_focus (priv->icon_view);
+
+ /* Chain up to parent's show() method. */
+ GTK_WIDGET_CLASS (parent_class)->show (widget);
+}
+
+static void
+preferences_window_class_init (EPreferencesWindowClass *class)
+{
+ GObjectClass *object_class;
+ GtkWidgetClass *widget_class;
+
+ parent_class = g_type_class_peek_parent (class);
+ g_type_class_add_private (class, sizeof (EPreferencesWindowPrivate));
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->dispose = preferences_window_dispose;
+ object_class->finalize = preferences_window_finalize;
+
+ widget_class = GTK_WIDGET_CLASS (class);
+ widget_class->show = preferences_window_show;
+}
+
+static void
+preferences_window_init (EPreferencesWindow *window)
+{
+ GtkListStore *store;
+ GtkWidget *container;
+ GtkWidget *hbox;
+ GtkWidget *vbox;
+ GtkWidget *widget;
+ GHashTable *index;
+ const gchar *title;
+
+ index = g_hash_table_new_full (
+ g_str_hash, g_str_equal,
+ (GDestroyNotify) g_free,
+ (GDestroyNotify) gtk_tree_row_reference_free);
+
+ window->priv = E_PREFERENCES_WINDOW_GET_PRIVATE (window);
+ window->priv->index = index;
+
+ store = gtk_list_store_new (
+ 4, G_TYPE_STRING, GDK_TYPE_PIXBUF, G_TYPE_INT, G_TYPE_INT);
+ gtk_tree_sortable_set_sort_column_id (
+ GTK_TREE_SORTABLE (store), COLUMN_SORT, GTK_SORT_ASCENDING);
+
+ title = _("Evolution Preferences");
+ gtk_window_set_title (GTK_WINDOW (window), title);
+ gtk_window_set_resizable (GTK_WINDOW (window), TRUE);
+ gtk_container_set_border_width (GTK_CONTAINER (window), 12);
+
+ g_signal_connect (
+ window, "delete-event",
+ G_CALLBACK (gtk_widget_hide_on_delete), NULL);
+
+ widget = gtk_vbox_new (FALSE, 12);
+ gtk_container_add (GTK_CONTAINER (window), widget);
+ gtk_widget_show (widget);
+
+ vbox = widget;
+
+ widget = gtk_hbox_new (FALSE, 12);
+ gtk_box_pack_start (GTK_BOX (vbox), widget, TRUE, TRUE, 0);
+ gtk_widget_show (widget);
+
+ hbox = widget;
+
+ widget = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (
+ GTK_SCROLLED_WINDOW (widget),
+ GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+ gtk_scrolled_window_set_shadow_type (
+ GTK_SCROLLED_WINDOW (widget), GTK_SHADOW_IN);
+ gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, TRUE, 0);
+ gtk_widget_show (widget);
+
+ container = widget;
+
+ widget = gtk_icon_view_new_with_model (GTK_TREE_MODEL (store));
+ gtk_icon_view_set_columns (GTK_ICON_VIEW (widget), 1);
+ gtk_icon_view_set_text_column (GTK_ICON_VIEW (widget), COLUMN_TEXT);
+ gtk_icon_view_set_pixbuf_column (GTK_ICON_VIEW (widget), COLUMN_PIXBUF);
+ g_signal_connect_swapped (
+ widget, "selection-changed",
+ G_CALLBACK (preferences_window_selection_changed_cb), window);
+ gtk_container_add (GTK_CONTAINER (container), widget);
+ window->priv->icon_view = g_object_ref (widget);
+ gtk_widget_show (widget);
+ g_object_unref (store);
+
+ widget = gtk_notebook_new ();
+ gtk_notebook_set_show_tabs (GTK_NOTEBOOK (widget), FALSE);
+ gtk_notebook_set_show_border (GTK_NOTEBOOK (widget), FALSE);
+ gtk_box_pack_start (GTK_BOX (hbox), widget, TRUE, TRUE, 0);
+ window->priv->notebook = g_object_ref (widget);
+ gtk_widget_show (widget);
+
+ widget = gtk_hbutton_box_new ();
+ gtk_button_box_set_layout (
+ GTK_BUTTON_BOX (widget), GTK_BUTTONBOX_END);
+ gtk_box_pack_start (GTK_BOX (vbox), widget, FALSE, FALSE, 0);
+ gtk_widget_show (widget);
+
+ container = widget;
+
+ widget = gtk_button_new_from_stock (GTK_STOCK_HELP);
+ g_signal_connect_swapped (
+ widget, "clicked",
+ G_CALLBACK (preferences_window_help_clicked_cb), window);
+ gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
+ gtk_button_box_set_child_secondary (
+ GTK_BUTTON_BOX (container), widget, TRUE);
+ gtk_widget_show (widget);
+
+ widget = gtk_button_new_from_stock (GTK_STOCK_CLOSE);
+ g_signal_connect_swapped (
+ widget, "clicked",
+ G_CALLBACK (gtk_widget_hide), window);
+ GTK_WIDGET_SET_FLAGS (widget, GTK_CAN_DEFAULT);
+ gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
+ gtk_widget_grab_default (widget);
+ gtk_widget_show (widget);
+}
+
+GType
+e_preferences_window_get_type (void)
+{
+ static GType type = 0;
+
+ if (G_UNLIKELY (type == 0)) {
+ const GTypeInfo type_info = {
+ sizeof (EPreferencesWindowClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) preferences_window_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+ sizeof (EPreferencesWindow),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) preferences_window_init,
+ NULL /* value_table */
+ };
+
+ type = g_type_register_static (
+ GTK_TYPE_WINDOW, "EPreferencesWindow", &type_info, 0);
+ }
+
+ return type;
+}
+
+GtkWidget *
+e_preferences_window_new (void)
+{
+ return g_object_new (E_TYPE_PREFERENCES_WINDOW, NULL);
+}
+
+void
+e_preferences_window_add_page (EPreferencesWindow *window,
+ const gchar *page_name,
+ const gchar *icon_name,
+ const gchar *caption,
+ GtkWidget *widget,
+ gint sort_order)
+{
+ GtkTreeRowReference *reference;
+ GtkIconView *icon_view;
+ GtkNotebook *notebook;
+ GtkTreeModel *model;
+ GtkTreePath *path;
+ GHashTable *index;
+ GdkPixbuf *pixbuf;
+ GtkTreeIter iter;
+ gint page;
+
+ g_return_if_fail (E_IS_PREFERENCES_WINDOW (window));
+ g_return_if_fail (page_name != NULL);
+ g_return_if_fail (icon_name != NULL);
+ g_return_if_fail (caption != NULL);
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+
+ icon_view = GTK_ICON_VIEW (window->priv->icon_view);
+ notebook = GTK_NOTEBOOK (window->priv->notebook);
+
+ page = gtk_notebook_get_n_pages (notebook);
+ model = gtk_icon_view_get_model (icon_view);
+ pixbuf = preferences_window_load_pixbuf (icon_name);
+
+ gtk_list_store_append (GTK_LIST_STORE (model), &iter);
+
+ gtk_list_store_set (
+ GTK_LIST_STORE (model), &iter,
+ COLUMN_TEXT, caption, COLUMN_PIXBUF, pixbuf,
+ COLUMN_PAGE, page, COLUMN_SORT, sort_order, -1);
+
+ index = window->priv->index;
+ path = gtk_tree_model_get_path (model, &iter);
+ reference = gtk_tree_row_reference_new (model, path);
+ g_hash_table_insert (index, g_strdup (page_name), reference);
+ gtk_tree_path_free (path);
+
+ gtk_widget_show (widget);
+ gtk_notebook_append_page (notebook, widget, NULL);
+}
+
+void
+e_preferences_window_show_page (EPreferencesWindow *window,
+ const gchar *page_name)
+{
+ GtkTreeRowReference *reference;
+ GtkIconView *icon_view;
+ GtkTreePath *path;
+
+ g_return_if_fail (E_IS_PREFERENCES_WINDOW (window));
+ g_return_if_fail (page_name != NULL);
+
+ icon_view = GTK_ICON_VIEW (window->priv->icon_view);
+ reference = g_hash_table_lookup (window->priv->index, page_name);
+ g_return_if_fail (reference != NULL);
+
+ path = gtk_tree_row_reference_get_path (reference);
+ gtk_icon_view_select_path (icon_view, path);
+ gtk_icon_view_scroll_to_path (icon_view, path, FALSE, 0.0, 0.0);
+ gtk_tree_path_free (path);
+}
diff --git a/widgets/misc/e-preferences-window.h b/widgets/misc/e-preferences-window.h
new file mode 100644
index 0000000000..4944a89e58
--- /dev/null
+++ b/widgets/misc/e-preferences-window.h
@@ -0,0 +1,74 @@
+/*
+ * e-preferences-window.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef E_PREFERENCES_WINDOW_H
+#define E_PREFERENCES_WINDOW_H
+
+#include <gtk/gtk.h>
+
+/* Standard GObject macros */
+#define E_TYPE_PREFERENCES_WINDOW \
+ (e_preferences_window_get_type ())
+#define E_PREFERENCES_WINDOW(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_PREFERENCES_WINDOW, EPreferencesWindow))
+#define E_PREFERENCES_WINDOW_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_PREFERENCES_WINDOW, EPreferencesWindowClass))
+#define E_IS_PREFERENCES_WINDOW(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_PREFERENCES_WINDOW))
+#define E_IS_PREFERENCES_WINDOW_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((obj), E_TYPE_PREFERENCES_WINDOW))
+#define E_PREFERENCES_WINDOW_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_TYPE \
+ ((obj), E_TYPE_PREFERENCES_WINDOW, EPreferencesWindowClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EPreferencesWindow EPreferencesWindow;
+typedef struct _EPreferencesWindowClass EPreferencesWindowClass;
+typedef struct _EPreferencesWindowPrivate EPreferencesWindowPrivate;
+
+struct _EPreferencesWindow {
+ GtkWindow parent;
+ EPreferencesWindowPrivate *priv;
+};
+
+struct _EPreferencesWindowClass {
+ GtkWindowClass parent_class;
+};
+
+GType e_preferences_window_get_type (void);
+GtkWidget * e_preferences_window_new (void);
+void e_preferences_window_add_page (EPreferencesWindow *window,
+ const gchar *page_name,
+ const gchar *icon_name,
+ const gchar *caption,
+ GtkWidget *widget,
+ gint sort_order);
+void e_preferences_window_show_page (EPreferencesWindow *window,
+ const gchar *page_name);
+
+G_END_DECLS
+
+#endif /* E_PREFERENCES_WINDOW_H */
diff --git a/widgets/misc/e-search-bar.c b/widgets/misc/e-search-bar.c
deleted file mode 100644
index b2f1a314e2..0000000000
--- a/widgets/misc/e-search-bar.c
+++ /dev/null
@@ -1,1644 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) version 3.
- *
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- *
- * Authors:
- * Chris Lahey <clahey@ximian.com>
- * Ettore Perazzoli <ettore@ximian.com>
- * Jon Trowbridge <trow@ximian.com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <gdk/gdkkeysyms.h>
-
-#include <misc/e-unicode.h>
-#include <misc/e-gui-utils.h>
-
-#include <glib/gi18n.h>
-
-#include <bonobo/bonobo-ui-util.h>
-
-#include <stdlib.h>
-#include <string.h>
-
-#include "e-icon-entry.h"
-#include "e-search-bar.h"
-#include "e-util/e-util.h"
-
-
-enum {
- QUERY_CHANGED,
- MENU_ACTIVATED,
- SEARCH_ACTIVATED,
- SEARCH_CLEARED,
- LAST_SIGNAL
-};
-
-static gint esb_signals [LAST_SIGNAL] = { 0, };
-
-static GtkHBoxClass *parent_class = NULL;
-
-/* The arguments we take */
-enum {
- PROP_0,
- PROP_ITEM_ID,
- PROP_SUBITEM_ID,
- PROP_TEXT
-};
-
-
-/* Forward decls. */
-
-static gint find_id (GtkWidget *menu, gint idin, const gchar *type, GtkWidget **widget);
-
-static void emit_search_activated (ESearchBar *esb);
-static void emit_query_changed (ESearchBar *esb);
-
-
-/* Utility functions. */
-
-static void
-set_find_now_sensitive (ESearchBar *search_bar,
- gboolean sensitive)
-{
- if (search_bar->ui_component != NULL)
- bonobo_ui_component_set_prop (search_bar->ui_component,
- "/commands/ESearchBar:FindNow",
- "sensitive", sensitive ? "1" : "0", NULL);
-}
-
-static void
-update_clear_menuitem_sensitive (ESearchBar *search_bar)
-{
- if (search_bar->ui_component != NULL) {
- gboolean sensitive = GTK_WIDGET_SENSITIVE (search_bar->clear_button) || search_bar->viewitem_id != 0;
-
- bonobo_ui_component_set_prop (search_bar->ui_component,
- "/commands/ESearchBar:Clear",
- "sensitive", sensitive ? "1" : "0", NULL);
- }
-}
-
-static void
-clear_button_state_changed (GtkWidget *clear_button, GtkStateType state, ESearchBar *search_bar)
-{
- g_return_if_fail (clear_button != NULL && search_bar != NULL);
-
- if (!search_bar->lite)
- update_clear_menuitem_sensitive (search_bar);
-}
-
-static gchar *
-verb_name_from_id (gint id)
-{
- return g_strdup_printf ("ESearchBar:Activate:%d", id);
-}
-
-/* This implements the "clear" action, i.e. clears the text and then emits
- * ::search_activated. */
-
-static void
-clear_search (ESearchBar *esb)
-{
- e_search_bar_set_text (esb, "");
- esb->block_search = TRUE;
- if (esb->item_id < 0)
- e_search_bar_set_item_id (esb, esb->last_search_option);
- e_search_bar_set_viewitem_id (esb, 0);
- esb->block_search = FALSE;
- emit_search_activated (esb);
-}
-
-static void
-free_menu_items (ESearchBar *esb)
-{
- GSList *p;
-
- if (esb->menu_items == NULL)
- return;
-
- for (p = esb->menu_items; p != NULL; p = p->next) {
- ESearchBarItem *item;
-
- item = (ESearchBarItem *) p->data;
-
- /* (No submitems for the menu_items, so no need to free that
- member.) */
-
- g_free (item->text);
- g_free (item);
- }
-
- g_slist_free (esb->menu_items);
- esb->menu_items = NULL;
-}
-
-
-/* Signals. */
-
-static void
-emit_query_changed (ESearchBar *esb)
-{
- g_signal_emit (esb, esb_signals [QUERY_CHANGED], 0);
- if (!esb->lite)
- update_clear_menuitem_sensitive (esb);
-}
-
-static void
-emit_search_activated(ESearchBar *esb)
-{
- if (esb->pending_activate) {
- g_source_remove (esb->pending_activate);
- esb->pending_activate = 0;
- }
-
- g_signal_emit (esb, esb_signals [SEARCH_ACTIVATED], 0);
-
- if (!esb->lite) {
- set_find_now_sensitive (esb, FALSE);
- update_clear_menuitem_sensitive (esb);
- }
-}
-
-static void
-emit_menu_activated (ESearchBar *esb, gint item)
-{
- g_signal_emit (esb,
- esb_signals [MENU_ACTIVATED], 0,
- item);
-}
-
-
-/* Callbacks -- Standard verbs. */
-
-static void
-search_now_verb_cb (BonoboUIComponent *ui_component,
- gpointer data,
- const gchar *verb_name)
-{
- ESearchBar *esb;
- GtkStyle *style = gtk_widget_get_default_style ();
- gchar *text;
-
- esb = E_SEARCH_BAR (data);
- text = e_search_bar_get_text (esb);
-
- if (text && *text) {
- gtk_widget_modify_base (esb->entry, GTK_STATE_NORMAL, &(style->base[GTK_STATE_SELECTED]));
- gtk_widget_modify_text (esb->entry, GTK_STATE_NORMAL, &(style->text[GTK_STATE_SELECTED]));
- gtk_widget_modify_base (esb->icon_entry, GTK_STATE_NORMAL, &(style->base[GTK_STATE_SELECTED]));
- gtk_widget_modify_base (esb->viewoption, GTK_STATE_NORMAL, &(style->base[GTK_STATE_SELECTED]));
- } else {
- gtk_widget_modify_base (esb->entry, GTK_STATE_NORMAL, NULL);
- gtk_widget_modify_text (esb->entry, GTK_STATE_NORMAL, NULL);
- gtk_widget_modify_base (esb->icon_entry, GTK_STATE_NORMAL, NULL);
- gtk_widget_set_sensitive (esb->clear_button, FALSE);
- }
-
- g_free (text);
- emit_search_activated (esb);
-}
-
-static void
-clear_verb_cb (BonoboUIComponent *ui_component,
- gpointer data,
- const gchar *verb_name)
-{
- ESearchBar *esb;
- esb = E_SEARCH_BAR (data);
-
- gtk_widget_modify_base (esb->entry, GTK_STATE_NORMAL, NULL);
- gtk_widget_modify_text (esb->entry, GTK_STATE_NORMAL, NULL);
- gtk_widget_modify_base (esb->icon_entry, GTK_STATE_NORMAL, NULL);
- gtk_widget_set_sensitive (esb->clear_button, FALSE);
-
- clear_search (esb);
- gtk_entry_set_text (GTK_ENTRY (esb->entry), "");
- gtk_widget_grab_focus (esb->entry);
-}
-
-static void
-setup_standard_verbs (ESearchBar *search_bar)
-{
- bonobo_ui_component_add_verb (search_bar->ui_component, "ESearchBar:Clear",
- clear_verb_cb, search_bar);
- bonobo_ui_component_add_verb (search_bar->ui_component, "ESearchBar:FindNow",
- search_now_verb_cb, search_bar);
-
- bonobo_ui_component_set (search_bar->ui_component, "/",
- ("<commands>"
- " <cmd name=\"ESearchBar:Clear\"/>"
- " <cmd name=\"ESearchBar:FindNow\"/>"
- "</commands>"),
- NULL);
-
- /* Make sure the entries are created with the correct sensitivity. */
- set_find_now_sensitive (search_bar, FALSE);
- update_clear_menuitem_sensitive (search_bar);
-}
-
-/* Callbacks -- The verbs for all the definable items. */
-
-static void
-search_verb_cb (BonoboUIComponent *ui_component,
- gpointer data,
- const gchar *verb_name)
-{
- ESearchBar *esb;
- const gchar *p;
- gint id;
-
- esb = E_SEARCH_BAR (data);
-
- p = strrchr (verb_name, ':');
- g_return_if_fail (p != NULL);
-
- id = atoi (p + 1);
-
- emit_menu_activated (esb, id);
-}
-
-/* Get the selected menu item's label */
-static const gchar *
-get_selected_item_label (GtkWidget *menu)
-{
- GtkWidget *label, *item;
- const gchar *text = NULL;
-
- item = gtk_menu_get_active ((GtkMenu *)menu);
- label = gtk_bin_get_child ((GtkBin *)item);
-
- if (GTK_IS_LABEL (label))
- text = gtk_label_get_text ((GtkLabel *)label);
-
- return text;
-}
-
-static gboolean
-entry_focus_in_cb (GtkWidget *widget,
- GdkEventFocus *event,
- ESearchBar *esb)
-{
- GtkStyle *entry_style, *default_style;
-
- entry_style = gtk_widget_get_style (esb->entry);
- default_style = gtk_widget_get_default_style ();
-
- if (gdk_color_equal (&(entry_style->text[GTK_STATE_NORMAL]), &(default_style->text[GTK_STATE_INSENSITIVE]))) {
- gtk_entry_set_text (GTK_ENTRY (esb->entry), "");
- gtk_widget_modify_text (esb->entry, GTK_STATE_NORMAL, NULL);
- }
-
- return FALSE;
-}
-
-static gboolean
-paint_search_text (GtkWidget *widget, ESearchBar *esb)
-{
- GtkStyle *style = gtk_widget_get_default_style ();
- const gchar *text = NULL;
- GtkWidget *menu_widget = esb->option_menu;
-
- text = gtk_entry_get_text (GTK_ENTRY (widget));
- if (text && *text)
- return FALSE;
-
- if (!GTK_WIDGET_SENSITIVE (esb->option_button)) {
- menu_widget = esb->scopeoption_menu;
- text = g_object_get_data (G_OBJECT(gtk_menu_get_active ( GTK_MENU (esb->scopeoption_menu))),"string");
- } else if (!GTK_IS_RADIO_MENU_ITEM (gtk_menu_get_active ( GTK_MENU (esb->option_menu))))
- return FALSE;
- else /* no query in search entry .. so set the current option */
- text = get_selected_item_label (menu_widget);
-
-
- if (text && *text) {
- gchar *t;
-
- if (!GTK_WIDGET_HAS_FOCUS(esb->entry)) {
- gtk_entry_set_text (GTK_ENTRY (esb->entry), text);
- gtk_widget_modify_text (esb->entry, GTK_STATE_NORMAL, &(style->text[GTK_STATE_INSENSITIVE]));
- }
-
- t = g_strdup_printf ("%s: %s\n%s", _("Search"), text, _("Click here to change the search type"));
- gtk_widget_set_tooltip_text (esb->option_button, t);
- g_free (t);
-
- gtk_widget_set_sensitive (esb->clear_button, FALSE);
- }
-
- return FALSE;
-}
-
-void
-e_search_bar_paint (ESearchBar *search_bar)
-{
- paint_search_text (search_bar->entry, search_bar);
-}
-
-static gboolean
-entry_focus_out_cb (GtkWidget *widget,
- GdkEventFocus *event,
- ESearchBar *esb)
-{
- return paint_search_text (widget, esb);
-}
-
-static void
-entry_activated_cb (GtkWidget *widget,
- ESearchBar *esb)
-{
- const gchar *text = gtk_entry_get_text (GTK_ENTRY (esb->entry));
- GtkStyle *style = gtk_widget_get_default_style ();
-
- if (text && *text) {
- gtk_widget_modify_base (esb->entry, GTK_STATE_NORMAL, &(style->base[GTK_STATE_SELECTED]));
- gtk_widget_modify_text (esb->entry, GTK_STATE_NORMAL, &(style->text[GTK_STATE_SELECTED]));
- gtk_widget_modify_base (esb->icon_entry, GTK_STATE_NORMAL, &(style->base[GTK_STATE_SELECTED]));
- if (!esb->lite)
- gtk_widget_modify_base (esb->viewoption, GTK_STATE_NORMAL, &(style->base[GTK_STATE_SELECTED]));
- } else {
- gtk_widget_modify_base (esb->entry, GTK_STATE_NORMAL, NULL);
- gtk_widget_modify_text (esb->entry, GTK_STATE_NORMAL, NULL);
- gtk_widget_modify_base (esb->icon_entry, GTK_STATE_NORMAL, NULL);
- if (!esb->lite)
- gtk_widget_set_sensitive (esb->clear_button, FALSE);
- }
-
- emit_search_activated (esb);
-}
-
-static void
-entry_changed_cb (GtkWidget *widget,
- ESearchBar *esb)
-{
- const gchar *text = gtk_entry_get_text (GTK_ENTRY (esb->entry));
- GtkStyle *entry_style, *default_style;
-
- entry_style = gtk_widget_get_style (esb->entry);
- default_style = gtk_widget_get_default_style ();
-
- if (text && *text) {
- if (gdk_color_equal (&(entry_style->text[GTK_STATE_NORMAL]), &(default_style->text[GTK_STATE_INSENSITIVE])))
- gtk_widget_set_sensitive (esb->clear_button, FALSE);
- else
- gtk_widget_set_sensitive (esb->clear_button, TRUE);
- } else {
- /* selected color means some search text is active */
- gtk_widget_set_sensitive (esb->clear_button, gdk_color_equal (&(entry_style->base[GTK_STATE_NORMAL]), &(default_style->base[GTK_STATE_SELECTED])));
- }
-}
-
-static void
-viewitem_activated_cb(GtkWidget *widget, ESearchBar *esb)
-{
- gint viewid;
- GtkStyle *entry_style, *default_style;
-
- widget = gtk_menu_get_active (GTK_MENU (esb->viewoption_menu));
-
- viewid = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget), "EsbItemId"));
- esb->viewitem_id = viewid;
-
- entry_style = gtk_widget_get_style (esb->entry);
- default_style = gtk_widget_get_default_style ();
-
- /* If the text is grayed, Its not the query string */
- if (gdk_color_equal (&(entry_style->text[GTK_STATE_NORMAL]), &(default_style->text[GTK_STATE_INSENSITIVE]))) {
- gtk_entry_set_text (GTK_ENTRY (esb->entry), "");
- gtk_widget_modify_text (esb->entry, GTK_STATE_NORMAL, NULL);
- }
-
- esb->block_search = TRUE;
- emit_search_activated (esb);
- esb->block_search = FALSE;
-}
-
-static void
-scopeitem_activated_cb(GtkWidget *widget, ESearchBar *esb)
-{
- gint scopeid;
- GtkStyle *entry_style, *default_style;
-
- widget = gtk_menu_get_active (GTK_MENU (esb->scopeoption_menu));
-
- scopeid = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget), "EsbItemId"));
- esb->scopeitem_id = scopeid;
-
- entry_style = gtk_widget_get_style (esb->entry);
- default_style = gtk_widget_get_default_style ();
-
- /* If the text is grayed, Its not the query string */
- if (gdk_color_equal (&(entry_style->text[GTK_STATE_NORMAL]), &(default_style->text[GTK_STATE_INSENSITIVE]))) {
- gtk_widget_grab_focus (esb->entry);
- gtk_entry_set_text (GTK_ENTRY (esb->entry), "");
- gtk_widget_modify_text (esb->entry, GTK_STATE_NORMAL, NULL);
- }
-
- esb->block_search = TRUE;
- emit_search_activated (esb);
- esb->block_search = FALSE;
-}
-
-static void
-option_activated_cb (GtkWidget *widget,
- ESearchBar *esb)
-{
- gint id;
- const gchar *text;
-
- id = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget), "EsbItemId"));
-
- e_search_bar_set_item_id (esb, id);
-
- if (GTK_IS_RADIO_MENU_ITEM (gtk_menu_get_active ( GTK_MENU (esb->option_menu)))) {
- gchar *t;
- text = get_selected_item_label (esb->option_menu);
- if (text && *text)
- t = g_strdup_printf ("%s: %s\n%s", _("Search"), text, _("Click here to change the search type"));
- else
- t = g_strdup_printf ("%s: %s", _("Search"), _("Click here to change the search type"));
-
- gtk_widget_set_tooltip_text (esb->option_button, t);
- g_free (t);
- }
-
- if (!esb->block_search) {
- emit_query_changed (esb);
- }
- if (!esb->block_search && id > 0) {
- emit_search_activated (esb);
- }
-}
-
-static void
-option_button_clicked_cb (GtkWidget *widget, GdkEventButton *event,
- ESearchBar *esb)
-{
- gtk_menu_popup (GTK_MENU (esb->option_menu), NULL, NULL, NULL, NULL,1,gtk_get_current_event_time());
-
- gtk_widget_grab_focus (esb->entry);
-}
-
-static void
-clear_button_clicked_cb (GtkWidget *widget, GdkEventButton *event,
- ESearchBar *esb)
-{
- gtk_widget_modify_base (esb->entry, GTK_STATE_NORMAL, NULL);
- gtk_widget_modify_text (esb->entry, GTK_STATE_NORMAL, NULL);
- gtk_widget_modify_base (esb->icon_entry, GTK_STATE_NORMAL, NULL);
- gtk_widget_set_sensitive (esb->clear_button, FALSE);
-
- clear_search (esb);
- gtk_entry_set_text (GTK_ENTRY (esb->entry), "");
- gtk_widget_grab_focus (esb->entry);
-}
-
-static gboolean
-entry_key_press_cb (GtkWidget *widget,
- GdkEventKey *key_event,
- ESearchBar *esb)
-{
- if (((key_event->state & gtk_accelerator_get_default_mod_mask ()) ==
- GDK_MOD1_MASK) && (key_event->keyval == GDK_Down)) {
- option_button_clicked_cb (NULL, NULL, esb);
- return TRUE;
- }
-
- return FALSE;
-}
-
-#if 0
-static void
-scopeoption_changed_cb (GtkWidget *option_menu, ESearchBar *search_bar)
-{
- gchar *text = NULL;
-
- text = e_search_bar_get_text (search_bar);
- if (!(text && *text))
- gtk_widget_grab_focus (search_bar->entry);
-
- if(!search_bar->block_search)
- emit_query_changed (search_bar);
-
- g_free (text);
-}
-#endif
-
-/* Widgetry creation. */
-
-#if 0
-/* This function exists to fix the irreparable GtkOptionMenu stupidity. In
- fact, this lame-ass widget adds a 1-pixel-wide empty border around the
- button for no reason. So we have add a 1-pixel-wide border around the the
- buttons we have in the search bar to make things look right. This is done
- through an event box. */
-static GtkWidget *
-put_in_spacer_widget (GtkWidget *widget)
-{
- GtkWidget *holder;
-
- holder = gtk_event_box_new ();
- gtk_container_set_border_width (GTK_CONTAINER (holder), 1);
- gtk_container_add (GTK_CONTAINER (holder), widget);
-
- return holder;
-}
-#endif
-
-static void
-append_xml_menu_item (GString *xml,
- const gchar *name,
- const gchar *label,
- const gchar *stock,
- const gchar *verb,
- const gchar *accelerator)
-{
- gchar *encoded_label;
-
- encoded_label = bonobo_ui_util_encode_str (label);
- g_string_append_printf (xml, "<menuitem name=\"%s\" verb=\"%s\" label=\"%s\"",
- name, verb, encoded_label);
- g_free (encoded_label);
-
- if (accelerator != NULL)
- g_string_append_printf (xml, " accel=\"%s\"", accelerator);
- if (stock != NULL)
- g_string_append_printf (xml, " pixtype=\"stock\" pixname=\"%s\"", stock);
-
- g_string_append (xml, "/>");
-}
-
-static void
-remove_bonobo_menus (ESearchBar *esb)
-{
- if (bonobo_ui_component_get_container (esb->ui_component) == CORBA_OBJECT_NIL)
- return;
-
- bonobo_ui_component_rm (esb->ui_component, "/menu/SearchPlaceholder", NULL);
-}
-
-static void
-setup_bonobo_menus (ESearchBar *esb)
-{
- GString *xml;
- GSList *p;
- gchar *verb_name;
- gchar *encoded_title;
-
- xml = g_string_new ("");
-
- encoded_title = bonobo_ui_util_encode_str (_("_Search"));
- g_string_append_printf (xml, "<submenu name=\"Search\" label=\"%s\">", encoded_title);
- g_free (encoded_title);
-
- g_string_append (xml, "<placeholder name=\"SearchBar\">");
-
- append_xml_menu_item (xml, "FindNow", _("_Find Now"), "gtk-find", "ESearchBar:FindNow", NULL);
- append_xml_menu_item (xml, "Clear", _("_Clear"), "gtk-clear", "ESearchBar:Clear", "*Control**Shift*q");
-
- for (p = esb->menu_items; p != NULL; p = p->next) {
- const ESearchBarItem *item;
-
- item = (const ESearchBarItem *) p->data;
-
- verb_name = verb_name_from_id (item->id);
- bonobo_ui_component_add_verb (esb->ui_component, verb_name, search_verb_cb, esb);
-
- if (item->text == NULL)
- g_string_append (xml, "<separator/>");
- else
- append_xml_menu_item (xml, verb_name, item->text, NULL, verb_name, NULL);
-
- g_free (verb_name);
- }
-
- g_string_append (xml, "</placeholder>");
- g_string_append (xml, "</submenu>");
-
- remove_bonobo_menus (esb);
- bonobo_ui_component_set (esb->ui_component, "/menu/SearchPlaceholder", xml->str, NULL);
-
- g_string_free (xml, TRUE);
-
- if (esb->clear_button) {
- g_signal_connect (esb->clear_button, "state-changed", G_CALLBACK (clear_button_state_changed), esb);
- }
-}
-
-static void
-update_bonobo_menus (ESearchBar *esb)
-{
- setup_bonobo_menus (esb);
-}
-
-static void
-set_menu (ESearchBar *esb,
- ESearchBarItem *items)
-{
- gint i;
-
- free_menu_items (esb);
-
- if (items == NULL)
- return;
-
- for (i = 0; items[i].id != -1; i++) {
- ESearchBarItem *new_item;
-
- new_item = g_new (ESearchBarItem, 1);
- new_item->text = items[i].text ? g_strdup (_(items[i].text)) : NULL;
- new_item->id = items[i].id;
- new_item->type = items[i].type;
-
- esb->menu_items = g_slist_append (esb->menu_items, new_item);
- }
-
- if (!esb->lite && esb->ui_component != NULL)
- update_bonobo_menus (esb);
-}
-
-/* /\* Callback used when an option item is destroyed. We have to destroy its */
-/* * suboption items. */
-/* *\/ */
-/* static gpointer */
-/* option_item_destroy_cb (GtkObject *object, gpointer data) */
-/* { */
-/* /\* ESearchBarSubitem *subitems; *\/ */
-
-/* /\* subitems = data; *\/ */
-
-/* /\* g_assert (subitems != NULL); *\/ */
-/* /\* free_subitems (subitems); *\/ */
-/* /\* g_object_set_data (G_OBJECT (object), "EsbChoiceSubitems", NULL); *\/ */
-/* } */
-
-static void
-set_option (ESearchBar *esb, ESearchBarItem *items)
-{
- GtkWidget *menu;
- GSList *group = NULL;
- gint i;
-
- if (esb->option_menu)
- gtk_widget_destroy (esb->option_menu);
-
- esb->option_menu = menu = gtk_menu_new ();
- for (i = 0; items[i].id != -1; i++) {
- GtkWidget *item;
-
- /* Create a new group */
- if (items[i].id == 0)
- group = NULL;
-
- if (items[i].text) {
- gchar *str;
- str = e_str_without_underscores (_(items[i].text));
- switch (items[i].type) {
- case ESB_ITEMTYPE_NORMAL:
- item = gtk_menu_item_new_with_label (str);
- break;
- case ESB_ITEMTYPE_CHECK:
- item = gtk_check_menu_item_new_with_label (str);
- break;
- case ESB_ITEMTYPE_RADIO:
- item = gtk_radio_menu_item_new_with_label (group, str);
- group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM (item));
- break;
- default:
- /* Fixme : this should be a normal item */
- item = gtk_radio_menu_item_new_with_label (group, str);
- group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM (item));
- break;
- }
- g_free (str);
- } else {
- item = gtk_menu_item_new ();
- gtk_widget_set_sensitive (item, FALSE);
- }
-
- gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
-
- g_object_set_data (G_OBJECT (item), "EsbItemId", GINT_TO_POINTER(items[i].id));
-
- g_signal_connect (item, "activate",
- G_CALLBACK (option_activated_cb),
- esb);
- }
-
- gtk_widget_show_all (menu);
- g_object_set_data (G_OBJECT(esb->option_menu), "group", group);
- entry_focus_out_cb (esb->entry, NULL, esb);
-}
-
-static gint
-find_id (GtkWidget *menu, gint idin, const gchar *type, GtkWidget **widget)
-{
- GList *l = GTK_MENU_SHELL (menu)->children;
- gint row = -1, i = 0, id;
-
- if (widget)
- *widget = NULL;
- while (l) {
- id = GPOINTER_TO_INT (g_object_get_data (l->data, type));
- if (id == idin) {
- row = i;
- if (widget)
- *widget = l->data;
- break;
- }
- i++;
- l = l->next;
- }
- return row;
-}
-
-
-/* GtkObject methods. */
-
-static void
-impl_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
-{
- ESearchBar *esb = E_SEARCH_BAR (object);
-
- switch (prop_id) {
- case PROP_ITEM_ID:
- g_value_set_int (value, e_search_bar_get_item_id (esb));
- break;
-
- case PROP_TEXT:
- g_value_take_string (value, e_search_bar_get_text (esb));
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-impl_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
-{
- ESearchBar *esb = E_SEARCH_BAR(object);
-
- switch (prop_id) {
- case PROP_ITEM_ID:
- e_search_bar_set_item_id (esb, g_value_get_int (value));
- break;
-
- case PROP_TEXT:
- e_search_bar_set_text (esb, g_value_get_string (value));
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-impl_dispose (GObject *object)
-{
- ESearchBar *esb = E_SEARCH_BAR (object);
-
- g_return_if_fail (object != NULL);
- g_return_if_fail (E_IS_SEARCH_BAR (object));
-
- /* These three we do need to unref, because we explicitly hold
- references to them. */
-
- if (!esb->lite && esb->ui_component != NULL) {
- bonobo_object_unref (BONOBO_OBJECT (esb->ui_component));
- esb->ui_component = NULL;
- }
-/* if (esb->entry) { */
-/* g_object_unref (esb->entry); */
-/* esb->entry = NULL; */
-/* } */
- if (esb->suboption) {
- g_object_unref (esb->suboption);
- esb->suboption = NULL;
- }
-
- if (esb->pending_activate) {
- g_source_remove (esb->pending_activate);
- esb->pending_activate = 0;
- }
-
- free_menu_items (esb);
-
- if (G_OBJECT_CLASS (parent_class)->dispose)
- G_OBJECT_CLASS (parent_class)->dispose (object);
-}
-
-
-static void
-class_init (ESearchBarClass *klass)
-{
- GObjectClass *object_class;
-
- object_class = G_OBJECT_CLASS (klass);
-
- parent_class = g_type_class_ref (gtk_hbox_get_type ());
-
- object_class->set_property = impl_set_property;
- object_class->get_property = impl_get_property;
- object_class->dispose = impl_dispose;
-
- klass->set_menu = set_menu;
- klass->set_option = set_option;
-
- g_object_class_install_property (object_class, PROP_ITEM_ID,
- g_param_spec_int ("item_id",
- _("Item ID"),
- /*_( */"XXX blurb" /*)*/,
- 0, 0, 0,
- G_PARAM_READWRITE | G_PARAM_LAX_VALIDATION));
-
- g_object_class_install_property (object_class, PROP_TEXT,
- g_param_spec_string ("text",
- _("Text"),
- /*_( */"XXX blurb" /*)*/,
- NULL,
- G_PARAM_READWRITE));
-
- esb_signals [QUERY_CHANGED] =
- g_signal_new ("query_changed",
- G_OBJECT_CLASS_TYPE (object_class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (ESearchBarClass, query_changed),
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
-
- esb_signals [MENU_ACTIVATED] =
- g_signal_new ("menu_activated",
- G_OBJECT_CLASS_TYPE (object_class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (ESearchBarClass, menu_activated),
- NULL, NULL,
- g_cclosure_marshal_VOID__INT,
- G_TYPE_NONE, 1, G_TYPE_INT);
-
- esb_signals [SEARCH_ACTIVATED] =
- g_signal_new ("search_activated",
- G_OBJECT_CLASS_TYPE (object_class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (ESearchBarClass, search_activated),
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
-
- esb_signals [SEARCH_CLEARED] =
- g_signal_new ("search_cleared",
- G_OBJECT_CLASS_TYPE (object_class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (ESearchBarClass, search_cleared),
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
-}
-
-static void
-init (ESearchBar *esb)
-{
- esb->ui_component = NULL;
- esb->menu_items = NULL;
-
- esb->option = NULL;
- esb->entry = NULL;
- esb->suboption = NULL;
-
- esb->option_menu = NULL;
- esb->suboption_menu = NULL;
- esb->option_button = NULL;
- esb->clear_button = NULL;
- esb->entry_box = NULL;
-
- esb->scopeoption_menu = NULL;
- esb->scopeoption = NULL;
- esb->scopeoption_box = NULL;
-
- esb->pending_activate = 0;
-
- esb->item_id = 0;
- esb->scopeitem_id = 0;
- esb->last_search_option = 0;
- esb->block_search = FALSE;
-}
-
-
-/* Object construction. */
-
-static gint
-idle_activate_hack (gpointer ptr)
-{
- ESearchBar *esb = E_SEARCH_BAR (ptr);
- esb->pending_activate = 0;
- emit_search_activated (esb);
- return FALSE;
-}
-
-void
-e_search_bar_construct (ESearchBar *search_bar,
- ESearchBarItem *menu_items,
- ESearchBarItem *option_items)
-{
- GtkWidget *label, *hbox, *bighbox;
-
- g_return_if_fail (search_bar != NULL);
- g_return_if_fail (E_IS_SEARCH_BAR (search_bar));
- g_return_if_fail (option_items != NULL);
-
- gtk_box_set_spacing (GTK_BOX (search_bar), 3);
-
- gtk_box_set_homogeneous (GTK_BOX (search_bar), FALSE);
-
- bighbox = gtk_hbox_new (FALSE, 0);
- search_bar->entry_box = gtk_hbox_new (0, FALSE);
- search_bar->icon_entry = e_icon_entry_new ();
- search_bar->entry = e_icon_entry_get_entry (E_ICON_ENTRY (search_bar->icon_entry));
-
- g_signal_connect (search_bar->entry, "changed",
- G_CALLBACK (entry_changed_cb), search_bar);
- g_signal_connect (search_bar->entry, "activate",
- G_CALLBACK (entry_activated_cb), search_bar);
- g_signal_connect (search_bar->entry, "focus-in-event",
- G_CALLBACK (entry_focus_in_cb), search_bar);
- g_signal_connect (search_bar->entry, "focus-out-event",
- G_CALLBACK (entry_focus_out_cb), search_bar);
- g_signal_connect (search_bar->entry, "key-press-event",
- G_CALLBACK (entry_key_press_cb), search_bar);
-
- search_bar->clear_button = e_icon_entry_create_button ("gtk-clear");
- g_signal_connect (G_OBJECT (search_bar->clear_button), "button-press-event", G_CALLBACK(clear_button_clicked_cb), search_bar);
- e_icon_entry_pack_widget (E_ICON_ENTRY (search_bar->icon_entry), search_bar->clear_button, FALSE);
-
- search_bar->option_button = e_icon_entry_create_button ("gtk-find");
- g_signal_connect (G_OBJECT (search_bar->option_button), "button-press-event", G_CALLBACK(option_button_clicked_cb), search_bar);
- e_icon_entry_pack_widget (E_ICON_ENTRY (search_bar->icon_entry), search_bar->option_button, TRUE);
-
- if (!search_bar->lite)
- gtk_box_pack_start (GTK_BOX(search_bar->entry_box), search_bar->icon_entry, FALSE, FALSE, 0);
- else
- gtk_box_pack_start (GTK_BOX(search_bar->entry_box), search_bar->icon_entry, TRUE, TRUE, 0);
-
-
- gtk_widget_show_all (search_bar->entry_box);
- gtk_widget_set_sensitive (search_bar->clear_button, FALSE);
-
- if (!search_bar->lite) {
- /* Current View filter */
- search_bar->viewoption_box = gtk_hbox_new (0, FALSE);
-
- /* To Translators: The "Show: " label is followed by the Quick Search Dropdown Menu where you can choose
- to display "All Messages", "Unread Messages", "Message with 'Important' Label" and so on... */
- label = gtk_label_new_with_mnemonic (_("Sho_w: "));
- gtk_widget_show (label);
- gtk_box_pack_start (GTK_BOX(search_bar->viewoption_box), label, FALSE, FALSE, 0);
-
- search_bar->viewoption = gtk_option_menu_new ();
- gtk_label_set_mnemonic_widget ((GtkLabel *)label, search_bar->viewoption);
- gtk_box_pack_start (GTK_BOX(search_bar->viewoption_box), search_bar->viewoption, FALSE, TRUE, 0);
- gtk_widget_show_all (search_bar->viewoption_box);
- gtk_box_pack_start (GTK_BOX(search_bar), search_bar->viewoption_box, FALSE, FALSE, 0);
-
- hbox = gtk_hbox_new (FALSE, 0);
- gtk_box_pack_start (GTK_BOX(search_bar), hbox, FALSE, FALSE, 0);
- }
-
- /* Search entry */
- hbox = gtk_hbox_new (FALSE, 0);
- /* To Translators: The "Show: " label is followed by the Quick Search Text input field where one enters
- the term to search for */
- if (!search_bar->lite) {
- label = gtk_label_new_with_mnemonic (_("Sear_ch: "));
- gtk_widget_show (label);
- gtk_box_pack_start (GTK_BOX(hbox), label, FALSE, FALSE, 0);
- gtk_box_pack_start (GTK_BOX(hbox), search_bar->entry_box, FALSE, FALSE, 0);
- gtk_label_set_mnemonic_widget ((GtkLabel *)label, search_bar->entry);
- } else {
- gtk_box_pack_start (GTK_BOX(hbox), search_bar->entry_box, TRUE, TRUE, 0);
- }
- gtk_widget_show (search_bar->entry_box);
-
- if (!search_bar->lite) {
- /* Search Scope Widgets */
- search_bar->scopeoption_box = gtk_hbox_new (0, FALSE);
- gtk_box_set_spacing (GTK_BOX (search_bar->scopeoption_box), 3);
- /* To Translators: The " in " label is part of the Quick Search Bar, example:
- Search: | <user's_search_term> | in | Current Folder/All Accounts/Current Account */
- label = gtk_label_new_with_mnemonic (_(" i_n "));
- gtk_widget_show (label);
- gtk_box_pack_start (GTK_BOX(search_bar->scopeoption_box), label, FALSE, FALSE, 0);
-
- search_bar->scopeoption = gtk_option_menu_new ();
- /* g_signal_connect (GTK_OPTION_MENU (search_bar->scopeoption), "changed", scopeoption_changed_cb, search_bar); */
- gtk_box_pack_start (GTK_BOX(search_bar->scopeoption_box), search_bar->scopeoption, FALSE, FALSE, 0);
- gtk_widget_show_all (search_bar->scopeoption_box);
- gtk_widget_hide (hbox);
- gtk_label_set_mnemonic_widget ((GtkLabel *)label, search_bar->scopeoption);
-
- gtk_box_pack_end (GTK_BOX(hbox), search_bar->scopeoption_box, FALSE, FALSE, 0);
- gtk_widget_hide (search_bar->scopeoption_box);
-
- }
- if (!search_bar->lite)
- gtk_box_pack_end (GTK_BOX(search_bar), hbox, FALSE, FALSE, 0);
- else
- gtk_box_pack_end (GTK_BOX(search_bar), hbox, TRUE, TRUE, 0);
-
- gtk_widget_show (hbox);
-
- /* Set the menu */
- e_search_bar_set_menu (search_bar, menu_items);
- e_search_bar_set_option (search_bar, option_items);
-
- /*
- * If the default choice for the option menu has subitems, then we need to
- * activate the search immediately. However, the developer won't have
- * connected to the activated signal until after the object is constructed,
- * so we can't emit here. Thus we launch a one-shot idle function that will
- * emit the changed signal, so that the proper callback will get invoked.
- */
- if (!search_bar->lite)
- search_bar->pending_activate = g_idle_add (idle_activate_hack, search_bar);
-}
-
-void
-e_search_bar_set_menu (ESearchBar *search_bar, ESearchBarItem *menu_items)
-{
- g_return_if_fail (search_bar != NULL);
- g_return_if_fail (E_IS_SEARCH_BAR (search_bar));
-
- ((ESearchBarClass *) GTK_OBJECT_GET_CLASS (search_bar))->set_menu (search_bar, menu_items);
-}
-
-void
-e_search_bar_add_menu (ESearchBar *search_bar, ESearchBarItem *menu_item)
-{
- g_return_if_fail (search_bar != NULL);
- g_return_if_fail (E_IS_SEARCH_BAR (search_bar));
-
- set_menu (search_bar, menu_item);
-}
-
-void
-e_search_bar_set_option (ESearchBar *search_bar, ESearchBarItem *option_items)
-{
- g_return_if_fail (search_bar != NULL);
- g_return_if_fail (E_IS_SEARCH_BAR (search_bar));
- g_return_if_fail (option_items != NULL);
-
- ((ESearchBarClass *) GTK_OBJECT_GET_CLASS (search_bar))->set_option (search_bar, option_items);
-}
-
-void
-e_search_bar_set_viewoption_menufunc (ESearchBar *search_bar, ESearchBarMenuFunc *menu_gen_func, gpointer data)
-{
- g_signal_connect (search_bar->viewoption, "button_press_event", G_CALLBACK (menu_gen_func), data);
-}
-
-/**
- * e_search_bar_set_viewoption_menu:
- * @search_bar: A search bar.
- * @option_id: Identifier of the main option menu item under which the subitems
- * are to be set.
- * @subitems: Array of subitem information.
- *
- * Sets the items for the secondary option menu of a search bar.
- **/
-void
-e_search_bar_set_viewoption_menu (ESearchBar *search_bar, GtkWidget *menu)
-{
-
- if (search_bar->viewoption_menu != NULL)
- gtk_option_menu_remove_menu (GTK_OPTION_MENU (search_bar->viewoption));
-
- search_bar->viewoption_menu = menu;
- gtk_option_menu_set_menu (GTK_OPTION_MENU (search_bar->viewoption), search_bar->viewoption_menu);
-
- g_signal_connect (search_bar->viewoption_menu,
- "selection-done",
- G_CALLBACK (viewitem_activated_cb),
- search_bar);
-}
-
-GtkWidget *
-e_search_bar_get_selected_viewitem (ESearchBar *search_bar)
-{
- GtkWidget *widget = NULL;
-
- widget = gtk_menu_get_active (GTK_MENU (search_bar->viewoption_menu));
-
- return widget;
-}
-
-/**
- * e_search_bar_set_viewoption:
- * @search_bar: A search bar.
- * @option_id: Identifier of the main option menu item under which the subitems
- * are to be set.
- * @subitems: Array of subitem information.
- *
- * Sets the items for the secondary option menu of a search bar.
- **/
-void
-e_search_bar_set_viewoption (ESearchBar *search_bar, gint option_id, ESearchBarItem *subitems)
-{
- GtkWidget *menu;
- GtkWidget *menu_item;
- gint i;
-
- /* Create the menu if it is not there. right scenario ????*/
-
- if (search_bar->viewoption_menu == NULL) {
- search_bar->viewoption_menu = menu = gtk_menu_new ();
- } else {
- gtk_option_menu_remove_menu (GTK_OPTION_MENU (search_bar->viewoption));
- search_bar->viewoption_menu = menu = gtk_menu_new ();
- }
-
- /* Create the items */
-
- for (i = 0; subitems[i].id != -1; ++i) {
- if (subitems[i].text) {
- gchar *str = NULL;
- str = e_str_without_underscores (subitems[i].text);
- menu_item = gtk_menu_item_new_with_label (str);
- g_free (str);
- } else {
- menu_item = gtk_menu_item_new ();
- gtk_widget_set_sensitive (menu_item, FALSE);
- }
-
- g_object_set_data (G_OBJECT (menu_item), "EsbItemId",
- GINT_TO_POINTER (subitems[i].id));
-
- g_signal_connect (menu_item,
- "activate",
- G_CALLBACK (viewitem_activated_cb),
- search_bar);
-
- gtk_widget_show (menu_item);
- gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
- }
- gtk_option_menu_set_menu (GTK_OPTION_MENU (search_bar->viewoption), menu);
-
-}
-
-/**
- * e_search_bar_set_scopeoption:
- * @search_bar: A search bar.
- * are to be set.
- * @scopeitems: Array of scope information.
- *
- * Sets the items for the search scope option menu of a search bar.
- **/
-void
-e_search_bar_set_scopeoption (ESearchBar *search_bar, ESearchBarItem *scopeitems)
-{
- GtkWidget *menu;
- GtkWidget *menu_item;
- gint i;
-
- gtk_widget_show (search_bar->scopeoption_box);
- if (search_bar->scopeoption_menu != NULL) {
- gtk_option_menu_remove_menu (GTK_OPTION_MENU (search_bar->scopeoption));
- }
-
- search_bar->scopeoption_menu = menu = gtk_menu_new ();
-
- /* Generate items */
- for (i = 0; scopeitems[i].id != -1; ++i) {
- if (scopeitems[i].text) {
- gchar *str;
- str = e_str_without_underscores (_(scopeitems[i].text));
- menu_item = gtk_menu_item_new_with_label (str);
- g_object_set_data_full (G_OBJECT (menu_item), "string",str, g_free);
- } else {
- menu_item = gtk_menu_item_new ();
- gtk_widget_set_sensitive (menu_item, FALSE);
- }
-
- g_object_set_data (G_OBJECT (menu_item), "EsbItemId",
- GINT_TO_POINTER (scopeitems[i].id));
-
- g_signal_connect (menu_item,
- "activate",
- G_CALLBACK (scopeitem_activated_cb),
- search_bar);
-
- gtk_widget_show (menu_item);
- gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
- }
- gtk_option_menu_set_menu (GTK_OPTION_MENU (search_bar->scopeoption), menu);
-}
-
-/**
- * e_search_bar_set_scopeoption_menu:
- * @search_bar: A search bar.
- * @menu: the scope option menu
- *
- * Sets the items for the secondary option menu of a search bar.
- **/
-void
-e_search_bar_set_scopeoption_menu (ESearchBar *search_bar, GtkMenu *menu)
-{
-
- if (search_bar->scopeoption_menu != NULL)
- gtk_option_menu_remove_menu (GTK_OPTION_MENU (search_bar->scopeoption));
-
- search_bar->scopeoption_menu = GTK_WIDGET (menu);
- gtk_option_menu_set_menu (GTK_OPTION_MENU (search_bar->scopeoption), search_bar->scopeoption_menu);
-
- g_signal_connect (search_bar->scopeoption_menu,
- "selection-done",
- G_CALLBACK (scopeitem_activated_cb),
- search_bar);
-}
-
-GtkWidget *
-e_search_bar_new (ESearchBarItem *menu_items,
- ESearchBarItem *option_items)
-{
- GtkWidget *widget;
-
- g_return_val_if_fail (option_items != NULL, NULL);
-
- widget = g_object_new (e_search_bar_get_type (), NULL);
-
- e_search_bar_construct (E_SEARCH_BAR (widget), menu_items, option_items);
-
- return widget;
-}
-
-GtkWidget *
-e_search_bar_lite_new (ESearchBarItem *menu_items,
- ESearchBarItem *option_items)
-{
- GtkWidget *widget;
-
- g_return_val_if_fail (option_items != NULL, NULL);
-
- widget = g_object_new (e_search_bar_get_type (), NULL);
- E_SEARCH_BAR(widget)->lite = TRUE;
-
- e_search_bar_construct (E_SEARCH_BAR (widget), menu_items, option_items);
-
- return widget;
-}
-
-void
-e_search_bar_set_ui_component (ESearchBar *search_bar,
- BonoboUIComponent *ui_component)
-{
- g_return_if_fail (E_IS_SEARCH_BAR (search_bar));
-
- if (search_bar->lite)
- return;
-
- if (search_bar->ui_component != NULL) {
- remove_bonobo_menus (search_bar);
- bonobo_object_unref (BONOBO_OBJECT (search_bar->ui_component));
- }
-
- search_bar->ui_component = ui_component;
- if (ui_component != NULL) {
- bonobo_object_ref (BONOBO_OBJECT (ui_component));
- setup_standard_verbs (search_bar);
- setup_bonobo_menus (search_bar);
- }
-}
-
-void
-e_search_bar_set_menu_sensitive (ESearchBar *search_bar, gint id, gboolean state)
-{
- gchar *verb_name;
- gchar *path;
-
- if (search_bar->lite)
- return;
-
- verb_name = verb_name_from_id (id);
- path = g_strconcat ("/commands/", verb_name, NULL);
- g_free (verb_name);
-
- bonobo_ui_component_set_prop (search_bar->ui_component, path,
- "sensitive", state ? "1" : "0",
- NULL);
-
- g_free (path);
-}
-
-GType
-e_search_bar_get_type (void)
-{
- static GType type = 0;
-
- if (!type) {
- static const GTypeInfo info = {
- sizeof (ESearchBarClass),
- NULL, /* base_init */
- NULL, /* base_finalize */
- (GClassInitFunc) class_init,
- NULL, /* class_finalize */
- NULL, /* class_data */
- sizeof (ESearchBar),
- 0, /* n_preallocs */
- (GInstanceInitFunc) init,
- };
-
- type = g_type_register_static (gtk_hbox_get_type (), "ESearchBar", &info, 0);
- }
-
- return type;
-}
-
-void
-e_search_bar_set_viewitem_id (ESearchBar *search_bar, gint id)
-{
- gint row;
-
- g_return_if_fail (E_IS_SEARCH_BAR (search_bar));
- if (!search_bar->viewoption_menu)
- return;
-
- row = find_id (search_bar->viewoption_menu, id, "EsbItemId", NULL);
- if (row == -1)
- return;
- search_bar->viewitem_id = id;
- gtk_option_menu_set_history (GTK_OPTION_MENU (search_bar->viewoption), row);
-
- emit_query_changed (search_bar);
-}
-
-/**
- * e_search_bar_set_item_id:
- * @search_bar: A search bar.
- * @id: Identifier of the item to set.
- *
- * Sets the active item in the options menu of a search bar.
- **/
-void
-e_search_bar_set_item_id (ESearchBar *search_bar, gint id)
-{
- gint row;
-
- g_return_if_fail (E_IS_SEARCH_BAR (search_bar));
-
- if (!search_bar->option_menu)
- return;
- row = find_id (search_bar->option_menu, id, "EsbItemId", NULL);
- if (row == -1)
- return;
-
- if (id>=0)
- search_bar->last_search_option = id;
- search_bar->item_id = id;
- gtk_menu_set_active ((GtkMenu *)search_bar->option_menu, row);
-
- if (!search_bar->block_search)
- emit_query_changed (search_bar);
-
- if (!search_bar->lite)
- update_clear_menuitem_sensitive (search_bar);
-}
-
-void
-e_search_bar_set_item_menu (ESearchBar *search_bar, gint id)
-{
- gint row;
- GtkWidget *item;
- g_return_if_fail (E_IS_SEARCH_BAR (search_bar));
-
- row = find_id (search_bar->option_menu, id, "EsbItemId", &item);
- if (row == -1)
- return;
-
- gtk_menu_set_active ((GtkMenu *)search_bar->option_menu, row);
- if (id>=0)
- gtk_check_menu_item_set_active ((GtkCheckMenuItem *)item, TRUE);
-}
-
-/**
- * e_search_bar_set_search_scope:
- * @search_bar: A search bar.
- * @id: Identifier of the item to set.
- *
- * Sets the active item in the options menu of a search bar.
- **/
-void
-e_search_bar_set_search_scope (ESearchBar *search_bar, gint id)
-{
- gint row;
-
- g_return_if_fail (E_IS_SEARCH_BAR (search_bar));
-
- if (!search_bar->scopeoption_menu)
- return;
- row = find_id (search_bar->scopeoption_menu, id, "EsbItemId", NULL);
- if (row == -1)
- return;
-
- search_bar->scopeitem_id = id;
- gtk_option_menu_set_history (GTK_OPTION_MENU (search_bar->scopeoption), row);
-
- if (!search_bar->block_search)
- emit_query_changed (search_bar);
-}
-
-
-/**
- * e_search_bar_get_item_id:
- * @search_bar: A search bar.
- *
- * Queries the currently selected item in the options menu of a search bar.
- *
- * Return value: Identifier of the selected item in the options menu.
- **/
-gint
-e_search_bar_get_item_id (ESearchBar *search_bar)
-{
- GtkWidget *menu_item;
- gint item_id;
-
- g_return_val_if_fail (search_bar != NULL, -1);
- g_return_val_if_fail (E_IS_SEARCH_BAR (search_bar), -1);
-
- menu_item = gtk_menu_get_active (GTK_MENU (search_bar->option_menu));
- item_id = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (menu_item), "EsbItemId"));
- search_bar->item_id = item_id;
-
- return search_bar->item_id;
-}
-
-/**
- * e_search_bar_get_search_scope:
- * @search_bar: A search bar.
- *
- * Queries the currently selected search type in the options menu of a search bar.
- *
- * Return value: Identifier of the selected item in the options menu.
- **/
-gint
-e_search_bar_get_search_scope (ESearchBar *search_bar)
-{
- GtkWidget *menu_item;
- gint scopeitem_id;
-
- g_return_val_if_fail (search_bar != NULL, -1);
- g_return_val_if_fail (E_IS_SEARCH_BAR (search_bar), -1);
-
- if (!search_bar->scopeoption_menu)
- return -7 /*Current folder hack */;
-
- menu_item = gtk_menu_get_active (GTK_MENU (search_bar->scopeoption_menu));
- scopeitem_id = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (menu_item), "EsbItemId"));
-
- search_bar->scopeitem_id = scopeitem_id;
-
- return search_bar->scopeitem_id;
-}
-
-/**
- * e_search_bar_get_viewitem_id:
- * @search_bar: A search bar.
- *
- * Queries the currently selected item in the viewoptions menu of a search bar.
- *
- * Return value: Identifier of the selected item in the viewoptions menu.
- * If the search bar currently contains an entry rather than a a viewoption menu,
- * a value less than zero is returned.
- **/
-gint
-e_search_bar_get_viewitem_id (ESearchBar *search_bar)
-{
- GtkWidget *menu_item;
- gint viewitem_id;
-
- g_return_val_if_fail (search_bar != NULL, -1);
- g_return_val_if_fail (E_IS_SEARCH_BAR (search_bar), -1);
-
- if (!search_bar->viewoption_menu)
- return -1;
-
- menu_item = gtk_menu_get_active (GTK_MENU (search_bar->viewoption_menu));
- viewitem_id = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (menu_item), "EsbItemId"));
-
- search_bar->viewitem_id = viewitem_id;
-
- return search_bar->viewitem_id;
-}
-
-/**
- * e_search_bar_set_ids:
- * @search_bar: A search bar.
- * @item_id: Identifier of the item to set.
- * @subitem_id: Identifier of the subitem to set.
- *
- * Sets the item and subitem ids for a search bar. This is intended to switch
- * to an item that has subitems.
- **/
-void
-e_search_bar_set_ids (ESearchBar *search_bar, gint item_id, gint subitem_id)
-{
- gint item_row;
- GtkWidget *item_widget;
-
- g_return_if_fail (search_bar != NULL);
- g_return_if_fail (E_IS_SEARCH_BAR (search_bar));
-
- item_row = find_id (search_bar->option_menu, item_id, "EsbChoiceId", &item_widget);
- if (item_row == -1 || !item_widget)
- return;
-
- search_bar->item_id = item_id;
- gtk_option_menu_set_history (GTK_OPTION_MENU (search_bar->option), item_row);
-
-}
-
-/**
- * e_search_bar_set_text:
- * @search_bar: A search bar.
- * @text: Text to set in the search bar's entry line.
- *
- * Sets the text string inside the entry line of a search bar.
- **/
-void
-e_search_bar_set_text (ESearchBar *search_bar, const gchar *text)
-{
- g_return_if_fail (E_IS_SEARCH_BAR (search_bar));
- gtk_entry_set_text (GTK_ENTRY (search_bar->entry), text);
-}
-
-/**
- * e_search_bar_get_text:
- * @search_bar: A search bar.
- *
- * Queries the text of the entry line in a search bar.
- *
- * Return value: The text string that is in the entry line of the search bar.
- * This must be freed using g_free(). If a suboption menu is active instead
- * of an entry, NULL is returned.
- **/
-gchar *
-e_search_bar_get_text (ESearchBar *search_bar)
-{
- GtkStyle *entry_style, *default_style;
-
- g_return_val_if_fail (search_bar != NULL, NULL);
- g_return_val_if_fail (E_IS_SEARCH_BAR (search_bar), NULL);
-
- entry_style = gtk_widget_get_style (search_bar->entry);
- default_style = gtk_widget_get_default_style ();
-
- if (gdk_color_equal (&(entry_style->text[GTK_STATE_NORMAL]), &(default_style->text[GTK_STATE_INSENSITIVE])))
- return g_strdup ("");
-
- return g_strdup (gtk_entry_get_text (GTK_ENTRY (search_bar->entry)));
-}
-
-void e_search_bar_scope_enable (ESearchBar *esb, gint did, gboolean state)
-{
- GtkWidget *widget=NULL;
- GList *l;
- gint id;
- gpointer *pointer;
-
- g_return_if_fail (esb != NULL);
- g_return_if_fail (E_IS_SEARCH_BAR (esb));
-
- l = GTK_MENU_SHELL (esb->scopeoption_menu)->children;
- while (l) {
- pointer = g_object_get_data (l->data, "EsbItemId");
- if (pointer) {
- id = GPOINTER_TO_INT (pointer);
- if (id == did) {
- widget = l->data;
- break;
- }
- }
- l = l->next;
- }
-
- if (widget)
- gtk_widget_set_sensitive (widget, state);
-}
diff --git a/widgets/misc/e-search-bar.h b/widgets/misc/e-search-bar.h
deleted file mode 100644
index 336c27608d..0000000000
--- a/widgets/misc/e-search-bar.h
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) version 3.
- *
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- *
- * Authors:
- * Chris Lahey <clahey@ximian.com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-#ifndef __E_SEARCH_BAR_H__
-#define __E_SEARCH_BAR_H__
-
-#include <gtk/gtk.h>
-
-#include <bonobo/bonobo-ui-component.h>
-
-G_BEGIN_DECLS
-
-/* ESearchBar - A card displaying information about a contact.
- *
- * The following arguments are available:
- *
- * name type read/write description
- * ---------------------------------------------------------------------------------
- * item_id gint RW Which option item is currently selected.
- * subitem_id gint RW Which option subitem is currently selected.
- * text string RW Text in the entry box.
- */
-
-#define E_SEARCH_BAR_TYPE (e_search_bar_get_type ())
-#define E_SEARCH_BAR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_SEARCH_BAR_TYPE, ESearchBar))
-#define E_SEARCH_BAR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E_SEARCH_BAR_TYPE, ESearchBarClass))
-#define E_IS_SEARCH_BAR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_SEARCH_BAR_TYPE))
-#define E_IS_SEARCH_BAR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), E_SEARCH_BAR_TYPE))
-
-enum _ESearchBarItemType {
- ESB_ITEMTYPE_NORMAL,
- ESB_ITEMTYPE_CHECK,
- ESB_ITEMTYPE_RADIO
-};
-typedef enum _ESearchBarItemType ESearchBarItemType;
-
-typedef struct {
- gchar *text;
- gint id;
- gint type;
-} ESearchBarItem;
-
-typedef struct _ESearchBar ESearchBar;
-typedef struct _ESearchBarClass ESearchBarClass;
-
-typedef void (*ESearchBarMenuFunc)(ESearchBar *esb, ESearchBarItem *menu_items);
-
-struct _ESearchBar
-{
- GtkHBox parent;
-
- BonoboUIComponent *ui_component;
-
- GSList *menu_items;
-
- /* item specific fields */
- GtkWidget *option;
- GtkWidget *entry;
- GtkWidget *suboption; /* an option menu for the choices associated with some options */
-
- /* PRIVATE */
- GtkWidget *dropdown_holder; /* holds the dropdown */
- GtkWidget *option_menu;
- GtkWidget *suboption_menu;
- GtkWidget *option_button;
- GtkWidget *clear_button;
- GtkWidget *entry_box;
- GtkWidget *icon_entry;
-
- /* show option widgets */
- GtkWidget *viewoption_box;
- GtkWidget *viewoption; /* an option menu for the choices associated with some search options */
- GtkWidget *viewoption_menu;
-
- /* search scope widgets */
- GtkWidget *scopeoption_box;
- GtkWidget *scopeoption; /* an option menu for the choices associated with scope search */
- GtkWidget *scopeoption_menu;
-
- guint pending_activate;
-
- /* The currently-selected item & subitem */
- gint item_id;
- gint viewitem_id; /* Current View Id */
- gint scopeitem_id; /* Scope of search */
- gint last_search_option;
-
- gboolean block_search;
- gboolean lite;
-};
-
-struct _ESearchBarClass
-{
- GtkHBoxClass parent_class;
-
- void (*set_menu) (ESearchBar *, ESearchBarItem *);
- void (*set_option) (ESearchBar *, ESearchBarItem *);
-
- /* signals */
- void (*search_activated) (ESearchBar *search);
- void (*search_cleared) (ESearchBar *search);
- void (*query_changed) (ESearchBar *search);
- void (*menu_activated) (ESearchBar *search, gint item);
-};
-
-enum {
- E_SEARCHBAR_FIND_NOW_ID = -1,
- E_SEARCHBAR_CLEAR_ID = -2
-};
-
-
-GType e_search_bar_get_type (void);
-void e_search_bar_construct (ESearchBar *search_bar,
- ESearchBarItem *menu_items,
- ESearchBarItem *option_items);
-GtkWidget *e_search_bar_new (ESearchBarItem *menu_items,
- ESearchBarItem *option_items);
-GtkWidget *e_search_bar_lite_new (ESearchBarItem *menu_items,
- ESearchBarItem *option_items);
-
-void e_search_bar_set_ui_component (ESearchBar *search_bar,
- BonoboUIComponent *ui_component);
-
-void e_search_bar_set_menu (ESearchBar *search_bar,
- ESearchBarItem *menu_items);
-void e_search_bar_add_menu (ESearchBar *search_bar,
- ESearchBarItem *menu_item);
-
-void e_search_bar_set_option (ESearchBar *search_bar,
- ESearchBarItem *option_items);
-void e_search_bar_paint (ESearchBar *search_bar);
-void e_search_bar_set_viewoption (ESearchBar *search_bar,
- gint option_id,
- ESearchBarItem *subitems);
-
-void e_search_bar_set_menu_sensitive (ESearchBar *search_bar,
- gint id,
- gboolean state);
-
-void e_search_bar_set_item_id (ESearchBar *search_bar,
- gint id);
-void e_search_bar_set_item_menu (ESearchBar *search_bar,
- gint id);
-gint e_search_bar_get_item_id (ESearchBar *search_bar);
-
-gint e_search_bar_get_viewitem_id (ESearchBar *search_bar);
-
-void e_search_bar_set_viewitem_id (ESearchBar *search_bar, gint id);
-
-void e_search_bar_set_ids (ESearchBar *search_bar,
- gint item_id,
- gint subitem_id);
-
-void e_search_bar_set_scopeoption (ESearchBar *search_bar, ESearchBarItem *scopeitems);
-
-void e_search_bar_set_scopeoption_menu (ESearchBar *search_bar, GtkMenu *menu);
-
-void e_search_bar_set_search_scope (ESearchBar *search_bar, gint id);
-
-void e_search_bar_set_viewoption_menu (ESearchBar *search_bar, GtkWidget *menu);
-
-void e_search_bar_set_viewoption_menufunc (ESearchBar *search_bar, ESearchBarMenuFunc *menu_gen_func, gpointer data);
-
-GtkWidget *e_search_bar_get_selected_viewitem (ESearchBar *search_bar);
-
-gint e_search_bar_get_search_scope (ESearchBar *search_bar);
-
-void e_search_bar_set_text (ESearchBar *search_bar,
- const gchar *text);
-gchar *e_search_bar_get_text (ESearchBar *search_bar);
-void e_search_bar_scope_enable (ESearchBar *search_bar, gint did, gboolean state);
-G_END_DECLS
-
-
-#endif /* __E_SEARCH_BAR_H__ */
diff --git a/widgets/misc/e-signature-combo-box.c b/widgets/misc/e-signature-combo-box.c
index cb11ba632f..d447cccb8e 100644
--- a/widgets/misc/e-signature-combo-box.c
+++ b/widgets/misc/e-signature-combo-box.c
@@ -1,4 +1,5 @@
/*
+ * e-signature-combo-box.c
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
diff --git a/widgets/misc/e-signature-combo-box.h b/widgets/misc/e-signature-combo-box.h
index fac47518e1..dd81eb55c3 100644
--- a/widgets/misc/e-signature-combo-box.h
+++ b/widgets/misc/e-signature-combo-box.h
@@ -1,4 +1,5 @@
/*
+ * e-signature-combo-box.h
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
diff --git a/widgets/misc/e-signature-editor.c b/widgets/misc/e-signature-editor.c
new file mode 100644
index 0000000000..53cb34906b
--- /dev/null
+++ b/widgets/misc/e-signature-editor.c
@@ -0,0 +1,503 @@
+/*
+ * e-signature-editor.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#include "e-signature-editor.h"
+
+#include <string.h>
+#include <glib/gi18n.h>
+
+#include <e-util/e-error.h>
+#include <e-util/e-signature-utils.h>
+
+#define E_SIGNATURE_EDITOR_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), E_TYPE_SIGNATURE_EDITOR, ESignatureEditorPrivate))
+
+enum {
+ PROP_0,
+ PROP_SIGNATURE
+};
+
+struct _ESignatureEditorPrivate {
+ GtkActionGroup *action_group;
+ ESignature *signature;
+ GtkWidget *entry;
+ gchar *original_name;
+};
+
+static const gchar *ui =
+"<ui>\n"
+" <menubar name='main-menu'>\n"
+" <placeholder name='pre-edit-menu'>\n"
+" <menu action='file-menu'>\n"
+" <menuitem action='save-and-close'/>\n"
+" <separator/>"
+" <menuitem action='close'/>\n"
+" </menu>\n"
+" </placeholder>\n"
+" </menubar>\n"
+" <toolbar name='main-toolbar'>\n"
+" <placeholder name='pre-main-toolbar'>\n"
+" <toolitem action='save-and-close'/>\n"
+" </placeholder>\n"
+" </toolbar>\n"
+"</ui>";
+
+static gpointer parent_class = NULL;
+
+static void
+handle_error (GError **error)
+{
+ if (*error != NULL) {
+ g_warning ("%s", (*error)->message);
+ g_clear_error (error);
+ }
+}
+
+static void
+action_close_cb (GtkAction *action,
+ ESignatureEditor *editor)
+{
+ gboolean something_changed = FALSE;
+ const gchar *original_name;
+ const gchar *signature_name;
+
+ original_name = editor->priv->original_name;
+ signature_name = gtk_entry_get_text (GTK_ENTRY (editor->priv->entry));
+
+ something_changed |= gtkhtml_editor_has_undo (GTKHTML_EDITOR (editor));
+ something_changed |= (strcmp (signature_name, original_name) != 0);
+
+ if (something_changed) {
+ gint response;
+
+ response = e_error_run (
+ GTK_WINDOW (editor),
+ "mail:ask-signature-changed", NULL);
+ if (response == GTK_RESPONSE_YES) {
+ GtkActionGroup *action_group;
+
+ action_group = editor->priv->action_group;
+ action = gtk_action_group_get_action (
+ action_group, "save-and-close");
+ gtk_action_activate (action);
+ return;
+ } else if (response == GTK_RESPONSE_CANCEL)
+ return;
+ }
+
+ gtk_widget_destroy (GTK_WIDGET (editor));
+}
+
+static void
+action_save_and_close_cb (GtkAction *action,
+ ESignatureEditor *editor)
+{
+ GtkWidget *entry;
+ ESignatureList *signature_list;
+ ESignature *signature;
+ ESignature *same_name;
+ const gchar *filename;
+ gchar *signature_name;
+ gboolean html;
+ GError *error = NULL;
+
+ entry = editor->priv->entry;
+ html = gtkhtml_editor_get_html_mode (GTKHTML_EDITOR (editor));
+
+ if (editor->priv->signature == NULL) {
+ signature = e_signature_new ();
+ signature->name = g_strdup (_("Unnamed"));
+ signature->script = FALSE;
+ signature->html = html;
+
+ /* FIXME Pass a GError and deal with it. */
+ signature->filename = e_create_signature_file (NULL);
+ } else {
+ signature = g_object_ref (editor->priv->signature);
+ signature->html = html;
+ }
+
+ filename = signature->filename;
+ gtkhtml_editor_save (GTKHTML_EDITOR (editor), filename, html, &error);
+
+ if (error != NULL) {
+ e_error_run (
+ GTK_WINDOW (editor),
+ "mail:no-save-signature",
+ error->message, NULL);
+ g_clear_error (&error);
+ return;
+ }
+
+ signature_list = e_get_signature_list ();
+
+ signature_name = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
+ g_strstrip (signature_name);
+
+ /* Make sure the signature name is not blank. */
+ if (*signature_name == '\0') {
+ e_error_run (
+ GTK_WINDOW (editor),
+ "mail:blank-signature", NULL);
+ gtk_widget_grab_focus (entry);
+ g_free (signature_name);
+ return;
+ }
+
+ /* Don't overwrite an existing signature of the same name.
+ * XXX ESignatureList misuses const. */
+ same_name = (ESignature *) e_signature_list_find (
+ signature_list, E_SIGNATURE_FIND_NAME, signature_name);
+ if (same_name != NULL && strcmp (signature->uid, same_name->uid) != 0) {
+ e_error_run (
+ GTK_WINDOW (editor),
+ "mail:signature-already-exists",
+ signature_name, NULL);
+ gtk_widget_grab_focus (entry);
+ g_free (signature_name);
+ return;
+ }
+
+ g_free (signature->name);
+ signature->name = signature_name;
+
+ if (editor->priv->signature != NULL)
+ e_signature_list_change (signature_list, signature);
+ else
+ e_signature_list_add (signature_list, signature);
+ e_signature_list_save (signature_list);
+
+ gtk_widget_destroy (GTK_WIDGET (editor));
+}
+
+static GtkActionEntry entries[] = {
+
+ { "close",
+ GTK_STOCK_CLOSE,
+ N_("_Close"),
+ "<Control>w",
+ NULL,
+ G_CALLBACK (action_close_cb) },
+
+ { "save-and-close",
+ GTK_STOCK_SAVE,
+ N_("_Save and Close"),
+ "<Control>Return",
+ NULL,
+ G_CALLBACK (action_save_and_close_cb) },
+
+ { "file-menu",
+ NULL,
+ N_("_File"),
+ NULL,
+ NULL,
+ NULL }
+};
+
+static gboolean
+signature_editor_delete_event_cb (ESignatureEditor *editor,
+ GdkEvent *event)
+{
+ GtkActionGroup *action_group;
+ GtkAction *action;
+
+ action_group = editor->priv->action_group;
+ action = gtk_action_group_get_action (action_group, "close");
+ gtk_action_activate (action);
+
+ return TRUE;
+}
+
+static void
+signature_editor_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_SIGNATURE:
+ e_signature_editor_set_signature (
+ E_SIGNATURE_EDITOR (object),
+ g_value_get_object (value));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+signature_editor_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_SIGNATURE:
+ g_value_set_object (
+ value, e_signature_editor_get_signature (
+ E_SIGNATURE_EDITOR (object)));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+signature_editor_dispose (GObject *object)
+{
+ ESignatureEditorPrivate *priv;
+
+ priv = E_SIGNATURE_EDITOR_GET_PRIVATE (object);
+
+ if (priv->action_group != NULL) {
+ g_object_unref (priv->action_group);
+ priv->action_group = NULL;
+ }
+
+ if (priv->signature != NULL) {
+ g_object_unref (priv->signature);
+ priv->signature = NULL;
+ }
+
+ if (priv->entry != NULL) {
+ g_object_unref (priv->entry);
+ priv->entry = NULL;
+ }
+
+ /* Chain up to parent's dispose() method. */
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+signature_editor_finalize (GObject *object)
+{
+ ESignatureEditorPrivate *priv;
+
+ priv = E_SIGNATURE_EDITOR_GET_PRIVATE (object);
+
+ g_free (priv->original_name);
+
+ /* Chain up to parent's finalize() method. */
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+signature_editor_class_init (ESignatureEditorClass *class)
+{
+ GObjectClass *object_class;
+
+ parent_class = g_type_class_peek_parent (class);
+ g_type_class_add_private (class, sizeof (ESignatureEditorPrivate));
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->set_property = signature_editor_set_property;
+ object_class->get_property = signature_editor_get_property;
+ object_class->dispose = signature_editor_dispose;
+ object_class->finalize = signature_editor_finalize;
+
+ g_object_class_install_property (
+ object_class,
+ PROP_SIGNATURE,
+ g_param_spec_object (
+ "signature",
+ NULL,
+ NULL,
+ E_TYPE_SIGNATURE,
+ G_PARAM_READWRITE));
+}
+
+static void
+signature_editor_init (ESignatureEditor *editor)
+{
+ GtkActionGroup *action_group;
+ GtkUIManager *ui_manager;
+ GtkWidget *container;
+ GtkWidget *widget;
+ GtkWidget *vbox;
+ GError *error = NULL;
+
+ editor->priv = E_SIGNATURE_EDITOR_GET_PRIVATE (editor);
+ vbox = GTKHTML_EDITOR (editor)->vbox;
+
+ ui_manager = gtkhtml_editor_get_ui_manager (GTKHTML_EDITOR (editor));
+
+ gtk_ui_manager_add_ui_from_string (ui_manager, ui, -1, &error);
+ handle_error (&error);
+
+ action_group = gtk_action_group_new ("signature");
+ gtk_action_group_set_translation_domain (
+ action_group, GETTEXT_PACKAGE);
+ gtk_action_group_add_actions (
+ action_group, entries,
+ G_N_ELEMENTS (entries), editor);
+ gtk_ui_manager_insert_action_group (ui_manager, action_group, 0);
+ editor->priv->action_group = g_object_ref (action_group);
+
+ gtk_ui_manager_ensure_update (ui_manager);
+
+ gtk_window_set_title (GTK_WINDOW (editor), _("Edit Signature"));
+
+ widget = gtk_hbox_new (FALSE, 6);
+ gtk_container_set_border_width (GTK_CONTAINER (widget), 6);
+ gtk_box_pack_start (GTK_BOX (vbox), widget, FALSE, FALSE, 0);
+ /* Position 2 should be between the main and style toolbars. */
+ gtk_box_reorder_child (GTK_BOX (vbox), widget, 2);
+ gtk_widget_show (widget);
+ container = widget;
+
+ widget = gtk_entry_new ();
+ gtk_box_pack_end (GTK_BOX (container), widget, TRUE, TRUE, 0);
+ editor->priv->entry = g_object_ref_sink (widget);
+ gtk_widget_show (widget);
+
+ widget = gtk_label_new_with_mnemonic (_("_Signature Name:"));
+ gtk_label_set_mnemonic_widget (GTK_LABEL (widget), editor->priv->entry);
+ gtk_box_pack_end (GTK_BOX (container), widget, FALSE, FALSE, 0);
+ gtk_widget_show (widget);
+
+ g_signal_connect (
+ editor, "delete-event",
+ G_CALLBACK (signature_editor_delete_event_cb), NULL);
+
+ e_signature_editor_set_signature (editor, NULL);
+}
+
+GType
+e_signature_editor_get_type (void)
+{
+ static GType type = 0;
+
+ if (G_UNLIKELY (type == 0)) {
+ static const GTypeInfo type_info = {
+ sizeof (ESignatureEditorClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) signature_editor_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+ sizeof (ESignatureEditor),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) signature_editor_init,
+ NULL /* value_table */
+ };
+
+ type = g_type_register_static (
+ GTKHTML_TYPE_EDITOR, "ESignatureEditor",
+ &type_info, 0);
+ }
+
+ return type;
+}
+
+GtkWidget *
+e_signature_editor_new (void)
+{
+ return g_object_new (E_TYPE_SIGNATURE_EDITOR, NULL);
+}
+
+ESignature *
+e_signature_editor_get_signature (ESignatureEditor *editor)
+{
+ g_return_val_if_fail (E_IS_SIGNATURE_EDITOR (editor), NULL);
+
+ return editor->priv->signature;
+}
+
+void
+e_signature_editor_set_signature (ESignatureEditor *editor,
+ ESignature *signature)
+{
+ const gchar *filename;
+ const gchar *signature_name;
+ gchar *contents;
+ gsize length;
+ GError *error = NULL;
+
+ g_return_if_fail (E_IS_SIGNATURE_EDITOR (editor));
+
+ if (signature != NULL)
+ g_return_if_fail (E_SIGNATURE (signature));
+
+ if (editor->priv->signature != NULL) {
+ g_object_unref (editor->priv->signature);
+ editor->priv->signature = NULL;
+ }
+
+ if (signature == NULL)
+ goto exit;
+
+ editor->priv->signature = g_object_ref (signature);
+
+ /* Load signature content. */
+
+ filename = signature->filename;
+
+ if (signature->html)
+ g_file_get_contents (filename, &contents, &length, &error);
+ else {
+ gchar *data;
+
+ data = e_read_signature_file (signature, FALSE, &error);
+ if (data != NULL)
+ contents = g_strdup_printf ("<PRE>\n%s", data);
+ else
+ contents = NULL;
+ length = -1;
+ g_free (data);
+ }
+
+ if (error == NULL) {
+ gtkhtml_editor_set_html_mode (
+ GTKHTML_EDITOR (editor), signature->html);
+ gtkhtml_editor_set_text_html (
+ GTKHTML_EDITOR (editor), contents, length);
+ g_free (contents);
+ } else {
+ g_warning ("%s", error->message);
+ g_error_free (error);
+ }
+
+exit:
+ if (signature != NULL)
+ signature_name = signature->name;
+ else
+ signature_name = _("Unnamed");
+
+ /* Set the entry text before we grab focus. */
+ g_free (editor->priv->original_name);
+ editor->priv->original_name = g_strdup (signature_name);
+ gtk_entry_set_text (GTK_ENTRY (editor->priv->entry), signature_name);
+
+ /* Set the focus appropriately. If this is a new signature, draw
+ * the user's attention to the signature name entry. Otherwise go
+ * straight to the editing area. */
+ if (signature == NULL)
+ gtk_widget_grab_focus (editor->priv->entry);
+ else {
+ GtkHTML *html;
+
+ html = gtkhtml_editor_get_html (GTKHTML_EDITOR (editor));
+ gtk_widget_grab_focus (GTK_WIDGET (html));
+ }
+
+ g_object_notify (G_OBJECT (editor), "signature");
+}
diff --git a/widgets/misc/e-signature-editor.h b/widgets/misc/e-signature-editor.h
new file mode 100644
index 0000000000..1e8b88a909
--- /dev/null
+++ b/widgets/misc/e-signature-editor.h
@@ -0,0 +1,70 @@
+/*
+ * e-signature-editor.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef E_SIGNATURE_EDITOR_H
+#define E_SIGNATURE_EDITOR_H
+
+#include <gtkhtml-editor.h>
+#include <e-util/e-signature.h>
+
+/* Standard GObject macros */
+#define E_TYPE_SIGNATURE_EDITOR \
+ (e_signature_editor_get_type ())
+#define E_SIGNATURE_EDITOR(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_SIGNATURE_EDITOR, ESignatureEditor))
+#define E_SIGNATURE_EDITOR_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_SIGNATURE_EDITOR, ESignatureEditorClass))
+#define E_IS_SIGNATURE_EDITOR(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_SIGNATURE_EDITOR))
+#define E_IS_SIGNATURE_EDITOR_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_SIGNATURE_EDITOR))
+#define E_SIGNATURE_EDITOR_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_SIGNATURE_EDITOR, ESignatureEditorClass))
+
+G_BEGIN_DECLS
+
+typedef struct _ESignatureEditor ESignatureEditor;
+typedef struct _ESignatureEditorClass ESignatureEditorClass;
+typedef struct _ESignatureEditorPrivate ESignatureEditorPrivate;
+
+struct _ESignatureEditor {
+ GtkhtmlEditor parent;
+ ESignatureEditorPrivate *priv;
+};
+
+struct _ESignatureEditorClass {
+ GtkhtmlEditorClass parent_class;
+};
+
+GType e_signature_editor_get_type (void);
+GtkWidget * e_signature_editor_new (void);
+ESignature * e_signature_editor_get_signature (ESignatureEditor *editor);
+void e_signature_editor_set_signature (ESignatureEditor *editor,
+ ESignature *signature);
+
+G_END_DECLS
+
+#endif /* E_SIGNATURE_EDITOR_H */
diff --git a/widgets/misc/e-signature-manager.c b/widgets/misc/e-signature-manager.c
new file mode 100644
index 0000000000..a70bc1dc60
--- /dev/null
+++ b/widgets/misc/e-signature-manager.c
@@ -0,0 +1,746 @@
+/*
+ * e-signature-manager.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#include "e-signature-manager.h"
+
+#include <glib/gi18n.h>
+#include <glib/gstdio.h>
+#include <gdk/gdkkeysyms.h>
+#include "e-util/e-binding.h"
+#include "e-signature-tree-view.h"
+#include "e-signature-script-dialog.h"
+
+#define E_SIGNATURE_MANAGER_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), E_TYPE_SIGNATURE_MANAGER, ESignatureManagerPrivate))
+
+struct _ESignatureManagerPrivate {
+ ESignatureList *signature_list;
+
+ GtkWidget *tree_view;
+ GtkWidget *add_button;
+ GtkWidget *add_script_button;
+ GtkWidget *edit_button;
+ GtkWidget *remove_button;
+
+ guint allow_scripts : 1;
+ guint prefer_html : 1;
+};
+
+enum {
+ PROP_0,
+ PROP_ALLOW_SCRIPTS,
+ PROP_PREFER_HTML,
+ PROP_SIGNATURE_LIST
+};
+
+enum {
+ ADD_SIGNATURE,
+ ADD_SIGNATURE_SCRIPT,
+ EDITOR_CREATED,
+ EDIT_SIGNATURE,
+ REMOVE_SIGNATURE,
+ LAST_SIGNAL
+};
+
+static gpointer parent_class;
+static guint signals[LAST_SIGNAL];
+
+static void
+signature_manager_emit_editor_created (ESignatureManager *manager,
+ GtkWidget *editor)
+{
+ g_return_if_fail (E_IS_SIGNATURE_EDITOR (editor));
+
+ g_signal_emit (manager, signals[EDITOR_CREATED], 0, editor);
+}
+
+static gboolean
+signature_manager_key_press_event_cb (ESignatureManager *manager,
+ GdkEventKey *event)
+{
+ if (event->keyval == GDK_Delete) {
+ e_signature_manager_remove_signature (manager);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gboolean
+signature_manager_run_script_dialog (ESignatureManager *manager,
+ ESignature *signature,
+ const gchar *title)
+{
+ GtkWidget *dialog;
+ GFile *script_file;
+ const gchar *script_name;
+ gboolean success = FALSE;
+ gpointer parent;
+
+ parent = gtk_widget_get_toplevel (GTK_WIDGET (manager));
+ parent = GTK_WIDGET_TOPLEVEL (parent) ? parent : NULL;
+
+ dialog = e_signature_script_dialog_new (parent);
+ gtk_window_set_title (GTK_WINDOW (dialog), title);
+
+ if (signature->filename != NULL && signature->name != NULL) {
+
+ script_file = g_file_new_for_path (signature->filename);
+ script_name = signature->name;
+
+ e_signature_script_dialog_set_script_file (
+ E_SIGNATURE_SCRIPT_DIALOG (dialog), script_file);
+ e_signature_script_dialog_set_script_name (
+ E_SIGNATURE_SCRIPT_DIALOG (dialog), script_name);
+
+ g_object_unref (script_file);
+ }
+
+ if (gtk_dialog_run (GTK_DIALOG (dialog)) != GTK_RESPONSE_OK)
+ goto exit;
+
+ script_file = e_signature_script_dialog_get_script_file (
+ E_SIGNATURE_SCRIPT_DIALOG (dialog));
+ script_name = e_signature_script_dialog_get_script_name (
+ E_SIGNATURE_SCRIPT_DIALOG (dialog));
+
+ g_free (signature->filename);
+ signature->filename = g_file_get_path (script_file);
+
+ g_free (signature->name);
+ signature->name = g_strdup (script_name);
+
+ g_object_unref (script_file);
+
+ success = TRUE;
+
+exit:
+ gtk_widget_destroy (dialog);
+
+ return success;
+}
+
+static void
+signature_manager_selection_changed_cb (ESignatureManager *manager,
+ GtkTreeSelection *selection)
+{
+ ESignatureTreeView *tree_view;
+ ESignature *signature;
+ GtkWidget *edit_button;
+ GtkWidget *remove_button;
+ gboolean sensitive;
+
+ edit_button = manager->priv->edit_button;
+ remove_button = manager->priv->remove_button;
+
+ tree_view = e_signature_manager_get_tree_view (manager);
+ signature = e_signature_tree_view_get_selected (tree_view);
+ sensitive = (signature != NULL);
+
+ gtk_widget_set_sensitive (edit_button, sensitive);
+ gtk_widget_set_sensitive (remove_button, sensitive);
+}
+
+static void
+signature_manager_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_ALLOW_SCRIPTS:
+ e_signature_manager_set_allow_scripts (
+ E_SIGNATURE_MANAGER (object),
+ g_value_get_boolean (value));
+ return;
+
+ case PROP_PREFER_HTML:
+ e_signature_manager_set_prefer_html (
+ E_SIGNATURE_MANAGER (object),
+ g_value_get_boolean (value));
+ return;
+
+ case PROP_SIGNATURE_LIST:
+ e_signature_manager_set_signature_list (
+ E_SIGNATURE_MANAGER (object),
+ g_value_get_object (value));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+signature_manager_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_ALLOW_SCRIPTS:
+ g_value_set_boolean (
+ value,
+ e_signature_manager_get_allow_scripts (
+ E_SIGNATURE_MANAGER (object)));
+ return;
+
+ case PROP_PREFER_HTML:
+ g_value_set_boolean (
+ value,
+ e_signature_manager_get_prefer_html (
+ E_SIGNATURE_MANAGER (object)));
+ return;
+
+ case PROP_SIGNATURE_LIST:
+ g_value_set_object (
+ value,
+ e_signature_manager_get_signature_list (
+ E_SIGNATURE_MANAGER (object)));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+signature_manager_dispose (GObject *object)
+{
+ ESignatureManagerPrivate *priv;
+
+ priv = E_SIGNATURE_MANAGER_GET_PRIVATE (object);
+
+ if (priv->signature_list != NULL) {
+ g_object_unref (priv->signature_list);
+ priv->signature_list = NULL;
+ }
+
+ if (priv->tree_view != NULL) {
+ g_object_unref (priv->tree_view);
+ priv->tree_view = NULL;
+ }
+
+ if (priv->add_button != NULL) {
+ g_object_unref (priv->add_button);
+ priv->add_button = NULL;
+ }
+
+ if (priv->add_script_button != NULL) {
+ g_object_unref (priv->add_script_button);
+ priv->add_script_button = NULL;
+ }
+
+ if (priv->edit_button != NULL) {
+ g_object_unref (priv->edit_button);
+ priv->edit_button = NULL;
+ }
+
+ if (priv->remove_button != NULL) {
+ g_object_unref (priv->remove_button);
+ priv->remove_button = NULL;
+ }
+
+ /* Chain up to parent's dispose() method. */
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+signature_manager_add_signature (ESignatureManager *manager)
+{
+ ESignatureTreeView *tree_view;
+ GtkWidget *editor;
+
+ tree_view = e_signature_manager_get_tree_view (manager);
+
+ editor = e_signature_editor_new ();
+ gtkhtml_editor_set_html_mode (
+ GTKHTML_EDITOR (editor), manager->priv->prefer_html);
+ signature_manager_emit_editor_created (manager, editor);
+
+ gtk_widget_grab_focus (GTK_WIDGET (tree_view));
+}
+
+static void
+signature_manager_add_signature_script (ESignatureManager *manager)
+{
+ ESignatureTreeView *tree_view;
+ ESignatureList *signature_list;
+ ESignature *signature;
+ const gchar *title;
+
+ title = _("Add Signature Script");
+ tree_view = e_signature_manager_get_tree_view (manager);
+ signature_list = e_signature_manager_get_signature_list (manager);
+
+ signature = e_signature_new ();
+ signature->script = TRUE;
+ signature->html = TRUE;
+
+ if (signature_manager_run_script_dialog (manager, signature, title))
+ e_signature_list_add (signature_list, signature);
+
+ e_signature_list_save (signature_list);
+ g_object_unref (signature);
+
+ gtk_widget_grab_focus (GTK_WIDGET (tree_view));
+}
+
+static void
+signature_manager_editor_created (ESignatureManager *manager,
+ ESignatureEditor *editor)
+{
+ GtkWindowPosition position;
+ gpointer parent;
+
+ position = GTK_WIN_POS_CENTER_ON_PARENT;
+ parent = gtk_widget_get_toplevel (GTK_WIDGET (manager));
+ parent = GTK_WIDGET_TOPLEVEL (parent) ? parent : NULL;
+
+ gtk_window_set_transient_for (GTK_WINDOW (editor), parent);
+ gtk_window_set_position (GTK_WINDOW (editor), position);
+ gtk_widget_show (GTK_WIDGET (editor));
+}
+
+static void
+signature_manager_edit_signature (ESignatureManager *manager)
+{
+ ESignatureTreeView *tree_view;
+ ESignatureList *signature_list;
+ ESignature *signature;
+ GtkWidget *editor;
+ const gchar *title;
+ gchar *filename;
+
+ tree_view = e_signature_manager_get_tree_view (manager);
+ signature = e_signature_tree_view_get_selected (tree_view);
+ signature_list = e_signature_manager_get_signature_list (manager);
+
+ if (signature == NULL)
+ return;
+
+ if (signature->script)
+ goto script;
+
+ filename = signature->filename;
+ if (filename == NULL || *filename == '\0') {
+ g_free (filename);
+ filename = g_strdup (_("Unnamed"));
+ signature->filename = filename;
+ }
+
+ editor = e_signature_editor_new ();
+ e_signature_editor_set_signature (
+ E_SIGNATURE_EDITOR (editor), signature);
+ signature_manager_emit_editor_created (manager, editor);
+
+ goto exit;
+
+script:
+ title = _("Edit Signature Script");
+
+ if (signature_manager_run_script_dialog (manager, signature, title))
+ e_signature_list_change (signature_list, signature);
+
+ e_signature_list_save (signature_list);
+
+exit:
+ gtk_widget_grab_focus (GTK_WIDGET (tree_view));
+
+ g_object_unref (signature);
+}
+
+static void
+signature_manager_remove_signature (ESignatureManager *manager)
+{
+ ESignatureTreeView *tree_view;
+ ESignatureList *signature_list;
+ ESignature *signature;
+
+ tree_view = e_signature_manager_get_tree_view (manager);
+ signature = e_signature_tree_view_get_selected (tree_view);
+ signature_list = e_signature_tree_view_get_signature_list (tree_view);
+
+ if (signature == NULL)
+ return;
+
+ if (signature->filename != NULL && !signature->script)
+ g_unlink (signature->filename);
+
+ e_signature_list_remove (signature_list, signature);
+ e_signature_list_save (signature_list);
+
+ gtk_widget_grab_focus (GTK_WIDGET (tree_view));
+}
+
+static void
+signature_manager_class_init (ESignatureManagerClass *class)
+{
+ GObjectClass *object_class;
+
+ parent_class = g_type_class_peek_parent (class);
+ g_type_class_add_private (class, sizeof (ESignatureManagerPrivate));
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->set_property = signature_manager_set_property;
+ object_class->get_property = signature_manager_get_property;
+ object_class->dispose = signature_manager_dispose;
+
+ class->add_signature = signature_manager_add_signature;
+ class->add_signature_script = signature_manager_add_signature_script;
+ class->editor_created = signature_manager_editor_created;
+ class->edit_signature = signature_manager_edit_signature;
+ class->remove_signature = signature_manager_remove_signature;
+
+ g_object_class_install_property (
+ object_class,
+ PROP_ALLOW_SCRIPTS,
+ g_param_spec_boolean (
+ "allow-scripts",
+ "Allow Scripts",
+ NULL,
+ TRUE,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_PREFER_HTML,
+ g_param_spec_boolean (
+ "prefer-html",
+ "Prefer HTML",
+ NULL,
+ TRUE,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_SIGNATURE_LIST,
+ g_param_spec_object (
+ "signature-list",
+ "Signature List",
+ NULL,
+ E_TYPE_SIGNATURE_LIST,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT));
+
+ signals[ADD_SIGNATURE] = g_signal_new (
+ "add-signature",
+ G_OBJECT_CLASS_TYPE (class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (ESignatureManagerClass, add_signature),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ signals[ADD_SIGNATURE_SCRIPT] = g_signal_new (
+ "add-signature-script",
+ G_OBJECT_CLASS_TYPE (class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (ESignatureManagerClass, add_signature_script),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ signals[EDITOR_CREATED] = g_signal_new (
+ "editor-created",
+ G_OBJECT_CLASS_TYPE (class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (ESignatureManagerClass, editor_created),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1,
+ E_TYPE_SIGNATURE_EDITOR);
+
+ signals[EDIT_SIGNATURE] = g_signal_new (
+ "edit-signature",
+ G_OBJECT_CLASS_TYPE (class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (ESignatureManagerClass, edit_signature),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ signals[REMOVE_SIGNATURE] = g_signal_new (
+ "remove-signature",
+ G_OBJECT_CLASS_TYPE (class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (ESignatureManagerClass, remove_signature),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+}
+
+static void
+signature_manager_init (ESignatureManager *manager)
+{
+ GtkTreeSelection *selection;
+ GtkWidget *container;
+ GtkWidget *widget;
+
+ manager->priv = E_SIGNATURE_MANAGER_GET_PRIVATE (manager);
+
+ gtk_table_resize (GTK_TABLE (manager), 1, 2);
+ gtk_table_set_col_spacings (GTK_TABLE (manager), 6);
+ gtk_table_set_row_spacings (GTK_TABLE (manager), 12);
+
+ container = GTK_WIDGET (manager);
+
+ widget = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (
+ GTK_SCROLLED_WINDOW (widget),
+ GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+ gtk_scrolled_window_set_shadow_type (
+ GTK_SCROLLED_WINDOW (widget), GTK_SHADOW_IN);
+ gtk_table_attach (
+ GTK_TABLE (container), widget, 0, 1, 0, 1,
+ GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
+ gtk_widget_show (widget);
+
+ container = widget;
+
+ widget = e_signature_tree_view_new ();
+ gtk_container_add (GTK_CONTAINER (container), widget);
+ manager->priv->tree_view = g_object_ref (widget);
+ gtk_widget_show (widget);
+
+ e_mutual_binding_new (
+ G_OBJECT (manager), "signature-list",
+ G_OBJECT (widget), "signature-list");
+
+ g_signal_connect_swapped (
+ widget, "key-press-event",
+ G_CALLBACK (signature_manager_key_press_event_cb),
+ manager);
+
+ g_signal_connect_swapped (
+ widget, "row-activated",
+ G_CALLBACK (e_signature_manager_edit_signature),
+ manager);
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
+
+ g_signal_connect_swapped (
+ selection, "changed",
+ G_CALLBACK (signature_manager_selection_changed_cb),
+ manager);
+
+ container = GTK_WIDGET (manager);
+
+ widget = gtk_vbutton_box_new ();
+ gtk_button_box_set_layout (
+ GTK_BUTTON_BOX (widget), GTK_BUTTONBOX_START);
+ gtk_box_set_spacing (GTK_BOX (widget), 6);
+ gtk_table_attach (
+ GTK_TABLE (container), widget,
+ 1, 2, 0, 2, 0, GTK_FILL, 0, 0);
+ gtk_widget_show (widget);
+
+ container = widget;
+
+ widget = gtk_button_new_from_stock (GTK_STOCK_ADD);
+ gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
+ manager->priv->add_button = g_object_ref (widget);
+ gtk_widget_show (widget);
+
+ g_signal_connect_swapped (
+ widget, "clicked",
+ G_CALLBACK (e_signature_manager_add_signature),
+ manager);
+
+ widget = gtk_button_new_with_mnemonic (_("Add _Script"));
+ gtk_button_set_image (
+ GTK_BUTTON (widget), gtk_image_new_from_stock (
+ GTK_STOCK_EXECUTE, GTK_ICON_SIZE_BUTTON));
+ gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
+ manager->priv->add_script_button = g_object_ref (widget);
+ gtk_widget_show (widget);
+
+ e_binding_new (
+ G_OBJECT (manager), "allow-scripts",
+ G_OBJECT (widget), "sensitive");
+
+ g_signal_connect_swapped (
+ widget, "clicked",
+ G_CALLBACK (e_signature_manager_add_signature_script),
+ manager);
+
+ widget = gtk_button_new_from_stock (GTK_STOCK_EDIT);
+ gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
+ manager->priv->edit_button = g_object_ref (widget);
+ gtk_widget_show (widget);
+
+ g_signal_connect_swapped (
+ widget, "clicked",
+ G_CALLBACK (e_signature_manager_edit_signature),
+ manager);
+
+ widget = gtk_button_new_from_stock (GTK_STOCK_REMOVE);
+ gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
+ manager->priv->remove_button = g_object_ref (widget);
+ gtk_widget_show (widget);
+
+ g_signal_connect_swapped (
+ widget, "clicked",
+ G_CALLBACK (e_signature_manager_remove_signature),
+ manager);
+}
+
+GType
+e_signature_manager_get_type (void)
+{
+ static GType type = 0;
+
+ if (G_UNLIKELY (type == 0)) {
+ static const GTypeInfo type_info = {
+ sizeof (ESignatureManagerClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) signature_manager_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_init */
+ sizeof (ESignatureManager),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) signature_manager_init,
+ NULL /* value_table */
+ };
+
+ type = g_type_register_static (
+ GTK_TYPE_TABLE, "ESignatureManager", &type_info, 0);
+ }
+
+ return type;
+}
+
+GtkWidget *
+e_signature_manager_new (ESignatureList *signature_list)
+{
+ g_return_val_if_fail (E_IS_SIGNATURE_LIST (signature_list), NULL);
+
+ return g_object_new (
+ E_TYPE_SIGNATURE_MANAGER,
+ "signature-list", signature_list, NULL);
+}
+
+void
+e_signature_manager_add_signature (ESignatureManager *manager)
+{
+ g_return_if_fail (E_IS_SIGNATURE_MANAGER (manager));
+
+ g_signal_emit (manager, signals[ADD_SIGNATURE], 0);
+}
+
+void
+e_signature_manager_add_signature_script (ESignatureManager *manager)
+{
+ g_return_if_fail (E_IS_SIGNATURE_MANAGER (manager));
+
+ g_signal_emit (manager, signals[ADD_SIGNATURE_SCRIPT], 0);
+}
+
+void
+e_signature_manager_edit_signature (ESignatureManager *manager)
+{
+ g_return_if_fail (E_IS_SIGNATURE_MANAGER (manager));
+
+ g_signal_emit (manager, signals[EDIT_SIGNATURE], 0);
+}
+
+void
+e_signature_manager_remove_signature (ESignatureManager *manager)
+{
+ g_return_if_fail (E_IS_SIGNATURE_MANAGER (manager));
+
+ g_signal_emit (manager, signals[REMOVE_SIGNATURE], 0);
+}
+
+gboolean
+e_signature_manager_get_allow_scripts (ESignatureManager *manager)
+{
+ g_return_val_if_fail (E_IS_SIGNATURE_MANAGER (manager), FALSE);
+
+ return manager->priv->allow_scripts;
+}
+
+void
+e_signature_manager_set_allow_scripts (ESignatureManager *manager,
+ gboolean allow_scripts)
+{
+ g_return_if_fail (E_IS_SIGNATURE_MANAGER (manager));
+
+ manager->priv->allow_scripts = allow_scripts;
+
+ g_object_notify (G_OBJECT (manager), "allow-scripts");
+}
+
+gboolean
+e_signature_manager_get_prefer_html (ESignatureManager *manager)
+{
+ g_return_val_if_fail (E_IS_SIGNATURE_MANAGER (manager), FALSE);
+
+ return manager->priv->prefer_html;
+}
+
+void
+e_signature_manager_set_prefer_html (ESignatureManager *manager,
+ gboolean prefer_html)
+{
+ g_return_if_fail (E_IS_SIGNATURE_MANAGER (manager));
+
+ manager->priv->prefer_html = prefer_html;
+
+ g_object_notify (G_OBJECT (manager), "prefer-html");
+}
+
+ESignatureList *
+e_signature_manager_get_signature_list (ESignatureManager *manager)
+{
+ g_return_val_if_fail (E_IS_SIGNATURE_MANAGER (manager), NULL);
+
+ return manager->priv->signature_list;
+}
+
+void
+e_signature_manager_set_signature_list (ESignatureManager *manager,
+ ESignatureList *signature_list)
+{
+ g_return_if_fail (E_IS_SIGNATURE_MANAGER (manager));
+
+ if (signature_list != NULL) {
+ g_return_if_fail (E_IS_SIGNATURE_LIST (signature_list));
+ g_object_ref (signature_list);
+ }
+
+ if (manager->priv->signature_list != NULL)
+ g_object_unref (manager->priv->signature_list);
+
+ manager->priv->signature_list = signature_list;
+
+ g_object_notify (G_OBJECT (manager), "signature-list");
+}
+
+ESignatureTreeView *
+e_signature_manager_get_tree_view (ESignatureManager *manager)
+{
+ g_return_val_if_fail (E_IS_SIGNATURE_MANAGER (manager), NULL);
+
+ return E_SIGNATURE_TREE_VIEW (manager->priv->tree_view);
+}
diff --git a/widgets/misc/e-signature-manager.h b/widgets/misc/e-signature-manager.h
new file mode 100644
index 0000000000..662836e4ef
--- /dev/null
+++ b/widgets/misc/e-signature-manager.h
@@ -0,0 +1,100 @@
+/*
+ * e-signature-manager.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef E_SIGNATURE_MANAGER_H
+#define E_SIGNATURE_MANAGER_H
+
+#include <gtk/gtk.h>
+#include <e-util/e-signature-list.h>
+#include <misc/e-signature-editor.h>
+#include <misc/e-signature-tree-view.h>
+
+/* Standard GObject macros */
+#define E_TYPE_SIGNATURE_MANAGER \
+ (e_signature_manager_get_type ())
+#define E_SIGNATURE_MANAGER(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_SIGNATURE_MANAGER, ESignatureManager))
+#define E_SIGNATURE_MANAGER_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_SIGNATURE_MANAGER, ESignatureManagerClass))
+#define E_IS_SIGNATURE_MANAGER(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_SIGNATURE_MANAGER))
+#define E_IS_SIGNATURE_MANAGER_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_SIGNATURE_MANAGER))
+#define E_SIGNATURE_MANAGER_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_SIGNATURE_MANAGER, ESignatureManagerClass))
+
+G_BEGIN_DECLS
+
+typedef struct _ESignatureManager ESignatureManager;
+typedef struct _ESignatureManagerClass ESignatureManagerClass;
+typedef struct _ESignatureManagerPrivate ESignatureManagerPrivate;
+
+struct _ESignatureManager {
+ GtkTable parent;
+ ESignatureManagerPrivate *priv;
+};
+
+struct _ESignatureManagerClass {
+ GtkTableClass parent_class;
+
+ void (*add_signature) (ESignatureManager *manager);
+ void (*add_signature_script) (ESignatureManager *manager);
+ void (*editor_created) (ESignatureManager *manager,
+ ESignatureEditor *editor);
+ void (*edit_signature) (ESignatureManager *manager);
+ void (*remove_signature) (ESignatureManager *manager);
+};
+
+GType e_signature_manager_get_type (void);
+GtkWidget * e_signature_manager_new (ESignatureList *signature_list);
+void e_signature_manager_add_signature
+ (ESignatureManager *manager);
+void e_signature_manager_add_signature_script
+ (ESignatureManager *manager);
+void e_signature_manager_edit_signature
+ (ESignatureManager *manager);
+void e_signature_manager_remove_signature
+ (ESignatureManager *manager);
+gboolean e_signature_manager_get_allow_scripts
+ (ESignatureManager *manager);
+void e_signature_manager_set_allow_scripts
+ (ESignatureManager *manager,
+ gboolean allow_scripts);
+gboolean e_signature_manager_get_prefer_html
+ (ESignatureManager *manager);
+void e_signature_manager_set_prefer_html
+ (ESignatureManager *manager,
+ gboolean prefer_html);
+ESignatureList *e_signature_manager_get_signature_list
+ (ESignatureManager *manager);
+void e_signature_manager_set_signature_list
+ (ESignatureManager *manager,
+ ESignatureList *signature_list);
+ESignatureTreeView *
+ e_signature_manager_get_tree_view
+ (ESignatureManager *manager);
+
+#endif /* E_SIGNATURE_MANAGER_H */
diff --git a/widgets/misc/e-signature-preview.c b/widgets/misc/e-signature-preview.c
new file mode 100644
index 0000000000..f8e168cd5a
--- /dev/null
+++ b/widgets/misc/e-signature-preview.c
@@ -0,0 +1,344 @@
+/*
+ * e-signature-preview.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#include "e-signature-preview.h"
+
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+#include <glib/gstdio.h>
+#include "e-util/e-signature-utils.h"
+
+#define E_SIGNATURE_PREVIEW_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), E_TYPE_SIGNATURE_PREVIEW, ESignaturePreviewPrivate))
+
+enum {
+ PROP_0,
+ PROP_ALLOW_SCRIPTS,
+ PROP_SIGNATURE
+};
+
+enum {
+ REFRESH,
+ LAST_SIGNAL
+};
+
+struct _ESignaturePreviewPrivate {
+ ESignature *signature;
+ guint allow_scripts : 1;
+};
+
+static gpointer parent_class;
+static guint signals[LAST_SIGNAL];
+
+static void
+signature_preview_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_ALLOW_SCRIPTS:
+ e_signature_preview_set_allow_scripts (
+ E_SIGNATURE_PREVIEW (object),
+ g_value_get_boolean (value));
+ return;
+
+ case PROP_SIGNATURE:
+ e_signature_preview_set_signature (
+ E_SIGNATURE_PREVIEW (object),
+ g_value_get_object (value));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+signature_preview_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_ALLOW_SCRIPTS:
+ g_value_set_boolean (
+ value, e_signature_preview_get_allow_scripts (
+ E_SIGNATURE_PREVIEW (object)));
+ return;
+
+ case PROP_SIGNATURE:
+ g_value_set_object (
+ value, e_signature_preview_get_signature (
+ E_SIGNATURE_PREVIEW (object)));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+signature_preview_dispose (GObject *object)
+{
+ ESignaturePreviewPrivate *priv;
+
+ priv = E_SIGNATURE_PREVIEW_GET_PRIVATE (object);
+
+ if (priv->signature != NULL) {
+ g_object_unref (priv->signature);
+ priv->signature = NULL;
+ }
+
+ /* Chain up to parent's dispose() method. */
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+signature_preview_url_requested (GtkHTML *html,
+ const gchar *url,
+ GtkHTMLStream *handle)
+{
+ GtkHTMLStreamStatus status;
+ gchar buffer[128];
+ gchar *filename;
+ gssize size;
+ gint fd;
+
+ /* FIXME Use GInputStream for this. */
+
+ if (g_str_has_prefix (url, "file:"))
+ filename = g_filename_from_uri (url, NULL, NULL);
+ else
+ filename = g_strdup (url);
+ fd = g_open (filename, O_RDONLY, 0);
+ g_free (filename);
+
+ status = GTK_HTML_STREAM_OK;
+ if (fd != -1) {
+ while ((size = read (fd, buffer, sizeof (buffer)))) {
+ if (size == -1) {
+ status = GTK_HTML_STREAM_ERROR;
+ break;
+ } else
+ gtk_html_write (html, handle, buffer, size);
+ }
+ } else
+ status = GTK_HTML_STREAM_ERROR;
+
+ gtk_html_end (html, handle, status);
+
+ if (fd > 0)
+ close (fd);
+}
+
+static void
+signature_preview_refresh (ESignaturePreview *preview)
+{
+ GtkHTML *html;
+ ESignature *signature;
+ gchar *content = NULL;
+ gsize length;
+
+ /* XXX We should show error messages in the preview. */
+
+ html = GTK_HTML (preview);
+ signature = e_signature_preview_get_signature (preview);
+
+ if (signature == NULL)
+ goto clear;
+
+ if (signature->script && !preview->priv->allow_scripts)
+ goto clear;
+
+ if (signature->script)
+ content = e_run_signature_script (signature->filename);
+ else
+ content = e_read_signature_file (signature, FALSE, NULL);
+
+ if (content == NULL || *content == '\0')
+ goto clear;
+
+ length = strlen (content);
+
+ if (signature->html)
+ gtk_html_load_from_string (html, content, length);
+ else {
+ GtkHTMLStream *stream;
+
+ stream = gtk_html_begin_content (
+ html, "text/html; charset=utf-8");
+ gtk_html_write (html, stream, "<PRE>", 5);
+ if (length > 0)
+ gtk_html_write (html, stream, content, length);
+ gtk_html_write (html, stream, "</PRE>", 6);
+ gtk_html_end (html, stream, GTK_HTML_STREAM_OK);
+ }
+
+ g_free (content);
+ return;
+
+clear:
+ gtk_html_load_from_string (html, " ", 1);
+ g_free (content);
+}
+
+static void
+signature_preview_class_init (ESignaturePreviewClass *class)
+{
+ GObjectClass *object_class;
+ GtkHTMLClass *html_class;
+
+ parent_class = g_type_class_peek_parent (class);
+ g_type_class_add_private (class, sizeof (ESignaturePreviewPrivate));
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->set_property = signature_preview_set_property;
+ object_class->get_property = signature_preview_get_property;
+ object_class->dispose = signature_preview_dispose;
+
+ html_class = GTK_HTML_CLASS (class);
+ html_class->url_requested = signature_preview_url_requested;
+
+ class->refresh = signature_preview_refresh;
+
+ g_object_class_install_property (
+ object_class,
+ PROP_ALLOW_SCRIPTS,
+ g_param_spec_boolean (
+ "allow-scripts",
+ "Allow Scripts",
+ NULL,
+ TRUE,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_SIGNATURE,
+ g_param_spec_object (
+ "signature",
+ "Signature",
+ NULL,
+ E_TYPE_SIGNATURE,
+ G_PARAM_READWRITE));
+
+ signals[REFRESH] = g_signal_new (
+ "refresh",
+ G_TYPE_FROM_CLASS (class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (ESignaturePreviewClass, refresh),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+}
+
+static void
+signature_preview_init (ESignaturePreview *preview)
+{
+ preview->priv = E_SIGNATURE_PREVIEW_GET_PRIVATE (preview);
+}
+
+GType
+e_signature_preview_get_type (void)
+{
+ static GType type = 0;
+
+ if (G_UNLIKELY (type == 0)) {
+ static const GTypeInfo type_info = {
+ sizeof (ESignaturePreviewClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) signature_preview_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+ sizeof (ESignaturePreview),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) signature_preview_init,
+ NULL /* value_table */
+ };
+
+ type = g_type_register_static (
+ GTK_TYPE_HTML, "ESignaturePreview", &type_info, 0);
+ }
+
+ return type;
+}
+
+GtkWidget *
+e_signature_preview_new (void)
+{
+ return g_object_new (E_TYPE_SIGNATURE_PREVIEW, NULL);
+}
+
+void
+e_signature_preview_refresh (ESignaturePreview *preview)
+{
+ g_return_if_fail (E_IS_SIGNATURE_PREVIEW (preview));
+
+ g_signal_emit (preview, signals[REFRESH], 0);
+}
+
+gboolean
+e_signature_preview_get_allow_scripts (ESignaturePreview *preview)
+{
+ g_return_val_if_fail (E_IS_SIGNATURE_PREVIEW (preview), FALSE);
+
+ return preview->priv->allow_scripts;
+}
+
+void
+e_signature_preview_set_allow_scripts (ESignaturePreview *preview,
+ gboolean allow_scripts)
+{
+ g_return_if_fail (E_IS_SIGNATURE_PREVIEW (preview));
+
+ preview->priv->allow_scripts = allow_scripts;
+ g_object_notify (G_OBJECT (preview), "allow-scripts");
+}
+
+ESignature *
+e_signature_preview_get_signature (ESignaturePreview *preview)
+{
+ g_return_val_if_fail (E_IS_SIGNATURE_PREVIEW (preview), NULL);
+
+ return preview->priv->signature;
+}
+
+void
+e_signature_preview_set_signature (ESignaturePreview *preview,
+ ESignature *signature)
+{
+ g_return_if_fail (E_IS_SIGNATURE_PREVIEW (preview));
+
+ if (signature != NULL) {
+ g_return_if_fail (E_IS_SIGNATURE (signature));
+ g_object_ref (signature);
+ }
+
+ if (preview->priv->signature != NULL)
+ g_object_unref (preview->priv->signature);
+
+ preview->priv->signature = signature;
+ g_object_notify (G_OBJECT (preview), "signature");
+
+ e_signature_preview_refresh (preview);
+}
diff --git a/widgets/misc/e-signature-preview.h b/widgets/misc/e-signature-preview.h
new file mode 100644
index 0000000000..a4221832c2
--- /dev/null
+++ b/widgets/misc/e-signature-preview.h
@@ -0,0 +1,81 @@
+/*
+ * e-signature-preview.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef E_SIGNATURE_PREVIEW_H
+#define E_SIGNATURE_PREVIEW_H
+
+#include <gtkhtml/gtkhtml.h>
+#include <e-util/e-signature.h>
+
+/* Standard GObject macros */
+#define E_TYPE_SIGNATURE_PREVIEW \
+ (e_signature_preview_get_type ())
+#define E_SIGNATURE_PREVIEW(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_SIGNATURE_PREVIEW, ESignaturePreview))
+#define E_SIGNATURE_PREVIEW_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_SIGNATURE_PREVIEW, ESignaturePreviewClass))
+#define E_IS_SIGNATURE_PREVIEW(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_SIGNATURE_PREVIEW))
+#define E_IS_SIGNATURE_PREVIEW_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_SIGNATURE_PREVIEW))
+#define E_SIGNATURE_PREVIEW_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_SIGNATURE_PREVIEW, ESignaturePreview))
+
+G_BEGIN_DECLS
+
+typedef struct _ESignaturePreview ESignaturePreview;
+typedef struct _ESignaturePreviewClass ESignaturePreviewClass;
+typedef struct _ESignaturePreviewPrivate ESignaturePreviewPrivate;
+
+struct _ESignaturePreview {
+ GtkHTML parent;
+ ESignaturePreviewPrivate *priv;
+};
+
+struct _ESignaturePreviewClass {
+ GtkHTMLClass parent_class;
+
+ /* Signals */
+ void (*refresh) (ESignaturePreview *preview);
+};
+
+GType e_signature_preview_get_type (void);
+GtkWidget * e_signature_preview_new (void);
+void e_signature_preview_refresh (ESignaturePreview *preview);
+gboolean e_signature_preview_get_allow_scripts
+ (ESignaturePreview *preview);
+void e_signature_preview_set_allow_scripts
+ (ESignaturePreview *preview,
+ gboolean allow_scripts);
+ESignature * e_signature_preview_get_signature
+ (ESignaturePreview *preview);
+void e_signature_preview_set_signature
+ (ESignaturePreview *preview,
+ ESignature *signature);
+
+G_END_DECLS
+
+#endif /* E_SIGNATURE_PREVIEW_H */
diff --git a/widgets/misc/e-signature-script-dialog.c b/widgets/misc/e-signature-script-dialog.c
new file mode 100644
index 0000000000..777d064f09
--- /dev/null
+++ b/widgets/misc/e-signature-script-dialog.c
@@ -0,0 +1,463 @@
+/*
+ * e-signature-script-dialog.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#include "e-signature-script-dialog.h"
+
+#include <glib/gi18n.h>
+#include "e-util/e-binding.h"
+
+#define E_SIGNATURE_SCRIPT_DIALOG_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), E_TYPE_SIGNATURE_SCRIPT_DIALOG, ESignatureScriptDialogPrivate))
+
+struct _ESignatureScriptDialogPrivate {
+ GtkWidget *entry;
+ GtkWidget *file_chooser;
+ GtkWidget *alert;
+};
+
+enum {
+ PROP_0,
+ PROP_SCRIPT_FILE,
+ PROP_SCRIPT_NAME
+};
+
+static gpointer parent_class;
+
+static gboolean
+signature_script_dialog_filter_cb (const GtkFileFilterInfo *filter_info)
+{
+ const gchar *filename = filter_info->filename;
+
+ return g_file_test (filename, G_FILE_TEST_IS_EXECUTABLE);
+}
+
+static void
+signature_script_dialog_update_status (ESignatureScriptDialog *dialog)
+{
+ GFile *script_file;
+ const gchar *script_name;
+ gboolean show_alert;
+ gboolean sensitive;
+
+ script_file = e_signature_script_dialog_get_script_file (dialog);
+ script_name = e_signature_script_dialog_get_script_name (dialog);
+
+ sensitive = (script_name != NULL && *script_name != '\0');
+
+ if (script_file != NULL) {
+ gboolean executable;
+ gchar *filename;
+
+ filename = g_file_get_path (script_file);
+ executable = g_file_test (filename, G_FILE_TEST_IS_EXECUTABLE);
+ g_free (filename);
+
+ show_alert = !executable;
+ sensitive &= executable;
+
+ g_object_unref (script_file);
+ } else {
+ sensitive = FALSE;
+ show_alert = FALSE;
+ }
+
+ if (show_alert)
+ gtk_widget_show (dialog->priv->alert);
+ else
+ gtk_widget_hide (dialog->priv->alert);
+
+ gtk_dialog_set_response_sensitive (
+ GTK_DIALOG (dialog), GTK_RESPONSE_OK, sensitive);
+}
+
+static void
+signature_script_dialog_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_SCRIPT_FILE:
+ e_signature_script_dialog_set_script_file (
+ E_SIGNATURE_SCRIPT_DIALOG (object),
+ g_value_get_object (value));
+ return;
+
+ case PROP_SCRIPT_NAME:
+ e_signature_script_dialog_set_script_name (
+ E_SIGNATURE_SCRIPT_DIALOG (object),
+ g_value_get_string (value));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+signature_script_dialog_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_SCRIPT_FILE:
+ g_value_set_object (
+ value,
+ e_signature_script_dialog_get_script_file (
+ E_SIGNATURE_SCRIPT_DIALOG (object)));
+ return;
+
+ case PROP_SCRIPT_NAME:
+ g_value_set_string (
+ value,
+ e_signature_script_dialog_get_script_name (
+ E_SIGNATURE_SCRIPT_DIALOG (object)));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+signature_script_dialog_dispose (GObject *object)
+{
+ ESignatureScriptDialogPrivate *priv;
+
+ priv = E_SIGNATURE_SCRIPT_DIALOG_GET_PRIVATE (object);
+
+ if (priv->entry != NULL) {
+ g_object_unref (priv->entry);
+ priv->entry = NULL;
+ }
+
+ if (priv->file_chooser != NULL) {
+ g_object_unref (priv->file_chooser);
+ priv->file_chooser = NULL;
+ }
+
+ if (priv->alert != NULL) {
+ g_object_unref (priv->alert);
+ priv->alert = NULL;
+ }
+
+ /* Chain up to parent's dispose() method. */
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+signature_script_dialog_map (GtkWidget *widget)
+{
+ GtkWidget *action_area;
+ GtkWidget *content_area;
+
+ /* Chain up to parent's map() method. */
+ GTK_WIDGET_CLASS (parent_class)->map (widget);
+
+ /* XXX Override GtkDialog's broken style property defaults. */
+ action_area = gtk_dialog_get_action_area (GTK_DIALOG (widget));
+ content_area = gtk_dialog_get_content_area (GTK_DIALOG (widget));
+
+ gtk_box_set_spacing (GTK_BOX (content_area), 12);
+ gtk_container_set_border_width (GTK_CONTAINER (action_area), 0);
+ gtk_container_set_border_width (GTK_CONTAINER (content_area), 12);
+}
+
+static void
+signature_script_dialog_class_init (ESignatureScriptDialogClass *class)
+{
+ GObjectClass *object_class;
+ GtkWidgetClass *widget_class;
+
+ parent_class = g_type_class_peek_parent (class);
+ g_type_class_add_private (class, sizeof (ESignatureScriptDialogPrivate));
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->set_property = signature_script_dialog_set_property;
+ object_class->get_property = signature_script_dialog_get_property;
+ object_class->dispose = signature_script_dialog_dispose;
+
+ widget_class = GTK_WIDGET_CLASS (class);
+ widget_class->map = signature_script_dialog_map;
+
+ g_object_class_install_property (
+ object_class,
+ PROP_SCRIPT_FILE,
+ g_param_spec_object (
+ "script-file",
+ "Script File",
+ NULL,
+ G_TYPE_FILE,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_SCRIPT_NAME,
+ g_param_spec_string (
+ "script-name",
+ "Script Name",
+ NULL,
+ _("Unnamed"),
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT));
+}
+
+static void
+signature_script_dialog_init (ESignatureScriptDialog *dialog)
+{
+ GtkFileFilter *filter;
+ GtkWidget *content_area;
+ GtkWidget *container;
+ GtkWidget *widget;
+ gchar *markup;
+
+ dialog->priv = E_SIGNATURE_SCRIPT_DIALOG_GET_PRIVATE (dialog);
+
+ content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
+
+ gtk_dialog_add_button (
+ GTK_DIALOG (dialog),
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
+
+ gtk_dialog_add_button (
+ GTK_DIALOG (dialog),
+ GTK_STOCK_SAVE, GTK_RESPONSE_OK);
+
+ gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
+
+ container = content_area;
+
+ widget = gtk_table_new (4, 2, FALSE);
+ gtk_table_set_col_spacings (GTK_TABLE (widget), 6);
+ gtk_table_set_row_spacings (GTK_TABLE (widget), 6);
+ gtk_table_set_row_spacing (GTK_TABLE (widget), 0, 12);
+ gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
+ gtk_widget_show (widget);
+
+ container = widget;
+
+ widget = gtk_image_new_from_stock (
+ GTK_STOCK_DIALOG_INFO, GTK_ICON_SIZE_DIALOG);
+ gtk_table_attach (
+ GTK_TABLE (container), widget,
+ 0, 1, 0, 1, 0, 0, 0, 0);
+ gtk_widget_show (widget);
+
+ widget = gtk_label_new (_(
+ "The output of this script will be used as your\n"
+ "signature. The name you specify will be used\n"
+ "for display purposes only."));
+ gtk_table_attach (
+ GTK_TABLE (container), widget,
+ 1, 2, 0, 1, GTK_FILL | GTK_EXPAND, 0, 0, 0);
+ gtk_widget_show (widget);
+
+ widget = gtk_entry_new ();
+ gtk_entry_set_activates_default (GTK_ENTRY (widget), TRUE);
+ gtk_table_attach (
+ GTK_TABLE (container), widget,
+ 1, 2, 1, 2, GTK_FILL | GTK_EXPAND, 0, 0, 0);
+ dialog->priv->entry = g_object_ref (widget);
+ gtk_widget_show (widget);
+
+ widget = gtk_label_new_with_mnemonic (_("_Name:"));
+ gtk_label_set_mnemonic_widget (
+ GTK_LABEL (widget), dialog->priv->entry);
+ gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.5);
+ gtk_table_attach (
+ GTK_TABLE (container), widget,
+ 0, 1, 1, 2, GTK_FILL, 0, 0, 0);
+ gtk_widget_show (widget);
+
+ widget = gtk_file_chooser_button_new (
+ NULL, GTK_FILE_CHOOSER_ACTION_OPEN);
+ gtk_table_attach (
+ GTK_TABLE (container), widget,
+ 1, 2, 2, 3, GTK_FILL | GTK_EXPAND, 0, 0, 0);
+ dialog->priv->file_chooser = g_object_ref (widget);
+ gtk_widget_show (widget);
+
+ /* Restrict file selection to executable files. */
+ filter = gtk_file_filter_new ();
+ gtk_file_filter_add_custom (
+ filter, GTK_FILE_FILTER_FILENAME,
+ (GtkFileFilterFunc) signature_script_dialog_filter_cb,
+ NULL, NULL);
+ gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (widget), filter);
+
+ /* XXX ESignature stores a filename instead of a URI,
+ * so we have to restrict it to local files only. */
+ gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (widget), TRUE);
+
+ widget = gtk_label_new_with_mnemonic (_("S_cript:"));
+ gtk_label_set_mnemonic_widget (
+ GTK_LABEL (widget), dialog->priv->file_chooser);
+ gtk_table_attach (
+ GTK_TABLE (container), widget,
+ 0, 1, 2, 3, GTK_FILL, 0, 0, 0);
+ gtk_widget_show (widget);
+
+ /* This is just a placeholder. */
+ widget = gtk_label_new (NULL);
+ gtk_table_attach (
+ GTK_TABLE (container), widget,
+ 0, 1, 3, 4, GTK_FILL, 0, 0, 0);
+ gtk_widget_show (widget);
+
+ widget = gtk_hbox_new (FALSE, 6);
+ gtk_table_attach (
+ GTK_TABLE (container), widget,
+ 1, 2, 3, 4, 0, 0, 0, 0);
+ dialog->priv->alert = g_object_ref (widget);
+ gtk_widget_show (widget);
+
+ container = widget;
+
+ widget = gtk_image_new_from_stock (
+ GTK_STOCK_DIALOG_WARNING, GTK_ICON_SIZE_MENU);
+ gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
+ gtk_widget_show (widget);
+
+ markup = g_markup_printf_escaped (
+ "<small>%s</small>",
+ _("Script file must be executable."));
+ widget = gtk_label_new (markup);
+ gtk_label_set_use_markup (GTK_LABEL (widget), TRUE);
+ gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
+ gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
+ gtk_widget_show (widget);
+ g_free (markup);
+
+ g_signal_connect (
+ dialog, "notify::script-file",
+ G_CALLBACK (signature_script_dialog_update_status), NULL);
+
+ g_signal_connect (
+ dialog, "notify::script-name",
+ G_CALLBACK (signature_script_dialog_update_status), NULL);
+
+ g_signal_connect_swapped (
+ dialog->priv->entry, "changed",
+ G_CALLBACK (signature_script_dialog_update_status), dialog);
+
+ g_signal_connect_swapped (
+ dialog->priv->file_chooser, "file-set",
+ G_CALLBACK (signature_script_dialog_update_status), dialog);
+
+ signature_script_dialog_update_status (dialog);
+}
+
+GType
+e_signature_script_dialog_get_type (void)
+{
+ static GType type = 0;
+
+ if (G_UNLIKELY (type == 0)) {
+ static const GTypeInfo type_info = {
+ sizeof (ESignatureScriptDialogClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) signature_script_dialog_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+ sizeof (ESignatureScriptDialog),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) signature_script_dialog_init,
+ NULL /* value_table */
+ };
+
+ type = g_type_register_static (
+ GTK_TYPE_DIALOG, "ESignatureScriptDialog",
+ &type_info, 0);
+ }
+
+ return type;
+}
+
+GtkWidget *
+e_signature_script_dialog_new (GtkWindow *parent)
+{
+ return g_object_new (
+ E_TYPE_SIGNATURE_SCRIPT_DIALOG,
+ "transient-for", parent, NULL);
+}
+
+GFile *
+e_signature_script_dialog_get_script_file (ESignatureScriptDialog *dialog)
+{
+ GtkFileChooser *file_chooser;
+
+ g_return_val_if_fail (E_IS_SIGNATURE_SCRIPT_DIALOG (dialog), NULL);
+
+ file_chooser = GTK_FILE_CHOOSER (dialog->priv->file_chooser);
+
+ return gtk_file_chooser_get_file (file_chooser);
+}
+
+void
+e_signature_script_dialog_set_script_file (ESignatureScriptDialog *dialog,
+ GFile *script_file)
+{
+ GtkFileChooser *file_chooser;
+ GError *error = NULL;
+
+ g_return_if_fail (E_IS_SIGNATURE_SCRIPT_DIALOG (dialog));
+ g_return_if_fail (G_IS_FILE (script_file));
+
+ file_chooser = GTK_FILE_CHOOSER (dialog->priv->file_chooser);
+
+ if (gtk_file_chooser_set_file (file_chooser, script_file, &error))
+ g_object_notify (G_OBJECT (dialog), "script-file");
+ else {
+ g_warning ("%s", error->message);
+ g_error_free (error);
+ }
+}
+
+const gchar *
+e_signature_script_dialog_get_script_name (ESignatureScriptDialog *dialog)
+{
+ GtkEntry *entry;
+
+ g_return_val_if_fail (E_IS_SIGNATURE_SCRIPT_DIALOG (dialog), NULL);
+
+ entry = GTK_ENTRY (dialog->priv->entry);
+
+ return gtk_entry_get_text (entry);
+}
+
+void
+e_signature_script_dialog_set_script_name (ESignatureScriptDialog *dialog,
+ const gchar *script_name)
+{
+ GtkEntry *entry;
+
+ g_return_if_fail (E_IS_SIGNATURE_SCRIPT_DIALOG (dialog));
+
+ if (script_name == NULL)
+ script_name = "";
+
+ entry = GTK_ENTRY (dialog->priv->entry);
+ gtk_entry_set_text (entry, script_name);
+
+ g_object_notify (G_OBJECT (dialog), "script-name");
+}
diff --git a/widgets/misc/e-signature-script-dialog.h b/widgets/misc/e-signature-script-dialog.h
new file mode 100644
index 0000000000..3967ae60c3
--- /dev/null
+++ b/widgets/misc/e-signature-script-dialog.h
@@ -0,0 +1,76 @@
+/*
+ * e-signature-script-dialog.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef E_SIGNATURE_SCRIPT_DIALOG_H
+#define E_SIGNATURE_SCRIPT_DIALOG_H
+
+#include <gtk/gtk.h>
+
+/* Standard GObject macros */
+#define E_TYPE_SIGNATURE_SCRIPT_DIALOG \
+ (e_signature_script_dialog_get_type ())
+#define E_SIGNATURE_SCRIPT_DIALOG(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_SIGNATURE_SCRIPT_DIALOG, ESignatureScriptDialog))
+#define E_SIGNATURE_SCRIPT_DIALOG_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_SIGNATURE_SCRIPT_DIALOG, ESignatureScriptDialogClass))
+#define E_IS_SIGNATURE_SCRIPT_DIALOG(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_SIGNATURE_SCRIPT_DIALOG))
+#define E_IS_SIGNATURE_SCRIPT_DIALOG_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_SIGNATURE_SCRIPT_DIALOG))
+#define E_SIGNATURE_SCRIPT_DIALOG_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_SIGNATURE_SCRIPT_DIALOG, ESignatureScriptDialogClass))
+
+G_BEGIN_DECLS
+
+typedef struct _ESignatureScriptDialog ESignatureScriptDialog;
+typedef struct _ESignatureScriptDialogClass ESignatureScriptDialogClass;
+typedef struct _ESignatureScriptDialogPrivate ESignatureScriptDialogPrivate;
+
+struct _ESignatureScriptDialog {
+ GtkDialog parent;
+ ESignatureScriptDialogPrivate *priv;
+};
+
+struct _ESignatureScriptDialogClass {
+ GtkDialogClass parent_class;
+};
+
+GType e_signature_script_dialog_get_type (void);
+GtkWidget * e_signature_script_dialog_new (GtkWindow *parent);
+GFile * e_signature_script_dialog_get_script_file
+ (ESignatureScriptDialog *dialog);
+void e_signature_script_dialog_set_script_file
+ (ESignatureScriptDialog *dialog,
+ GFile *script_file);
+const gchar * e_signature_script_dialog_get_script_name
+ (ESignatureScriptDialog *dialog);
+void e_signature_script_dialog_set_script_name
+ (ESignatureScriptDialog *dialog,
+ const gchar *script_name);
+
+G_END_DECLS
+
+#endif /* E_SIGNATURE_SCRIPT_DIALOG_H */
diff --git a/widgets/misc/e-signature-tree-view.c b/widgets/misc/e-signature-tree-view.c
new file mode 100644
index 0000000000..b2cc9d6f66
--- /dev/null
+++ b/widgets/misc/e-signature-tree-view.c
@@ -0,0 +1,445 @@
+/*
+ * e-signature-tree-view.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#include "e-signature-tree-view.h"
+
+#define E_SIGNATURE_TREE_VIEW_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), E_TYPE_SIGNATURE_TREE_VIEW, ESignatureTreeViewPrivate))
+
+enum {
+ COLUMN_STRING,
+ COLUMN_SIGNATURE
+};
+
+enum {
+ PROP_0,
+ PROP_SELECTED,
+ PROP_SIGNATURE_LIST
+};
+
+enum {
+ REFRESHED,
+ LAST_SIGNAL
+};
+
+struct _ESignatureTreeViewPrivate {
+ ESignatureList *signature_list;
+ GHashTable *index;
+};
+
+static gpointer parent_class;
+static guint signals[LAST_SIGNAL];
+
+static void
+signature_tree_view_refresh_cb (ESignatureList *signature_list,
+ ESignature *unused,
+ ESignatureTreeView *tree_view)
+{
+ GtkListStore *store;
+ GtkTreeModel *model;
+ GtkTreeIter tree_iter;
+ EIterator *signature_iter;
+ ESignature *signature;
+ GHashTable *index;
+ GList *list = NULL;
+ GList *iter;
+
+ store = gtk_list_store_new (2, G_TYPE_STRING, E_TYPE_SIGNATURE);
+ model = GTK_TREE_MODEL (store);
+ index = tree_view->priv->index;
+
+ g_hash_table_remove_all (index);
+
+ if (signature_list == NULL)
+ goto skip;
+
+ /* Build a list of ESignatures to display. */
+ signature_iter = e_list_get_iterator (E_LIST (signature_list));
+ while (e_iterator_is_valid (signature_iter)) {
+
+ /* XXX EIterator misuses const. */
+ signature = (ESignature *) e_iterator_get (signature_iter);
+ list = g_list_prepend (list, signature);
+ e_iterator_next (signature_iter);
+ }
+ g_object_unref (signature_iter);
+
+ list = g_list_reverse (list);
+
+ /* Populate the list store and index. */
+ for (iter = list; iter != NULL; iter = iter->next) {
+ GtkTreeRowReference *reference;
+ GtkTreePath *path;
+
+ signature = iter->data;
+
+ /* Skip autogenerated signatures. */
+ if (signature->autogen)
+ continue;
+
+ gtk_list_store_append (store, &tree_iter);
+ gtk_list_store_set (
+ store, &tree_iter,
+ COLUMN_STRING, signature->name,
+ COLUMN_SIGNATURE, signature, -1);
+
+ path = gtk_tree_model_get_path (model, &tree_iter);
+ reference = gtk_tree_row_reference_new (model, path);
+ g_hash_table_insert (index, signature, reference);
+ gtk_tree_path_free (path);
+ }
+
+skip:
+ /* Restore the previously selected signature. */
+ signature = e_signature_tree_view_get_selected (tree_view);
+ if (signature != NULL)
+ g_object_ref (signature);
+ gtk_tree_view_set_model (GTK_TREE_VIEW (tree_view), model);
+ e_signature_tree_view_set_selected (tree_view, signature);
+ if (signature != NULL)
+ g_object_unref (signature);
+
+ g_signal_emit (tree_view, signals[REFRESHED], 0);
+}
+
+static void
+signature_tree_view_selection_changed_cb (ESignatureTreeView *tree_view)
+{
+ g_object_notify (G_OBJECT (tree_view), "selected");
+}
+
+static GObject *
+signature_tree_view_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_properties)
+{
+ GObject *object;
+ GtkTreeView *tree_view;
+ GtkTreeViewColumn *column;
+ GtkCellRenderer *renderer;
+
+ /* Chain up to parent's constructor() method. */
+ object = G_OBJECT_CLASS (parent_class)->constructor (
+ type, n_construct_properties, construct_properties);
+
+ tree_view = GTK_TREE_VIEW (object);
+ gtk_tree_view_set_headers_visible (tree_view, FALSE);
+
+ column = gtk_tree_view_column_new ();
+ renderer = gtk_cell_renderer_text_new ();
+ gtk_tree_view_column_pack_start (column, renderer, TRUE);
+ gtk_tree_view_column_add_attribute (
+ column, renderer, "text", COLUMN_STRING);
+ gtk_tree_view_append_column (tree_view, column);
+
+ return object;
+}
+
+static void
+signature_tree_view_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_SELECTED:
+ e_signature_tree_view_set_selected (
+ E_SIGNATURE_TREE_VIEW (object),
+ g_value_get_object (value));
+ return;
+
+ case PROP_SIGNATURE_LIST:
+ e_signature_tree_view_set_signature_list (
+ E_SIGNATURE_TREE_VIEW (object),
+ g_value_get_object (value));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+signature_tree_view_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_SELECTED:
+ g_value_set_object (
+ value,
+ e_signature_tree_view_get_selected (
+ E_SIGNATURE_TREE_VIEW (object)));
+ return;
+
+ case PROP_SIGNATURE_LIST:
+ g_value_set_object (
+ value,
+ e_signature_tree_view_get_signature_list (
+ E_SIGNATURE_TREE_VIEW (object)));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+signature_tree_view_dispose (GObject *object)
+{
+ ESignatureTreeViewPrivate *priv;
+
+ priv = E_SIGNATURE_TREE_VIEW_GET_PRIVATE (object);
+
+ if (priv->signature_list != NULL) {
+ g_signal_handlers_disconnect_by_func (
+ priv->signature_list,
+ signature_tree_view_refresh_cb, object);
+ g_object_unref (priv->signature_list);
+ priv->signature_list = NULL;
+ }
+
+ g_hash_table_remove_all (priv->index);
+
+ /* Chain up to parent's dispose() method. */
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+signature_tree_view_finalize (GObject *object)
+{
+ ESignatureTreeViewPrivate *priv;
+
+ priv = E_SIGNATURE_TREE_VIEW_GET_PRIVATE (object);
+
+ g_hash_table_destroy (priv->index);
+
+ /* Chain up to parent's finalize() method. */
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+signature_tree_view_class_init (ESignatureTreeViewClass *class)
+{
+ GObjectClass *object_class;
+
+ parent_class = g_type_class_peek_parent (class);
+ g_type_class_add_private (class, sizeof (ESignatureTreeViewPrivate));
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->constructor = signature_tree_view_constructor;
+ object_class->set_property = signature_tree_view_set_property;
+ object_class->get_property = signature_tree_view_get_property;
+ object_class->dispose = signature_tree_view_dispose;
+ object_class->finalize = signature_tree_view_finalize;
+
+ g_object_class_install_property (
+ object_class,
+ PROP_SELECTED,
+ g_param_spec_object (
+ "selected",
+ "Selected Signature",
+ NULL,
+ E_TYPE_SIGNATURE,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_SIGNATURE_LIST,
+ g_param_spec_object (
+ "signature-list",
+ "Signature List",
+ NULL,
+ E_TYPE_SIGNATURE_LIST,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT));
+
+ signals[REFRESHED] = g_signal_new (
+ "refreshed",
+ G_TYPE_FROM_CLASS (class),
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+}
+
+static void
+signature_tree_view_init (ESignatureTreeView *tree_view)
+{
+ GHashTable *index;
+ GtkTreeSelection *selection;
+
+ /* Reverse-lookup index */
+ index = g_hash_table_new_full (
+ g_direct_hash, g_direct_equal,
+ (GDestroyNotify) g_object_unref,
+ (GDestroyNotify) gtk_tree_row_reference_free);
+
+ tree_view->priv = E_SIGNATURE_TREE_VIEW_GET_PRIVATE (tree_view);
+ tree_view->priv->index = index;
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view));
+
+ g_signal_connect_swapped (
+ selection, "changed",
+ G_CALLBACK (signature_tree_view_selection_changed_cb),
+ tree_view);
+}
+
+GType
+e_signature_tree_view_get_type (void)
+{
+ static GType type = 0;
+
+ if (G_UNLIKELY (type == 0)) {
+ static const GTypeInfo type_info = {
+ sizeof (ESignatureTreeViewClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) signature_tree_view_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+ sizeof (ESignatureTreeView),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) signature_tree_view_init,
+ NULL /* value_table */
+ };
+
+ type = g_type_register_static (
+ GTK_TYPE_TREE_VIEW, "ESignatureTreeView",
+ &type_info, 0);
+ }
+
+ return type;
+}
+
+GtkWidget *
+e_signature_tree_view_new (void)
+{
+ return g_object_new (E_TYPE_SIGNATURE_TREE_VIEW, NULL);
+}
+
+ESignatureList *
+e_signature_tree_view_get_signature_list (ESignatureTreeView *tree_view)
+{
+ g_return_val_if_fail (E_IS_SIGNATURE_TREE_VIEW (tree_view), NULL);
+
+ return tree_view->priv->signature_list;
+}
+
+void
+e_signature_tree_view_set_signature_list (ESignatureTreeView *tree_view,
+ ESignatureList *signature_list)
+{
+ ESignatureTreeViewPrivate *priv;
+
+ g_return_if_fail (E_IS_SIGNATURE_TREE_VIEW (tree_view));
+
+ if (signature_list != NULL)
+ g_return_if_fail (E_IS_SIGNATURE_LIST (signature_list));
+
+ priv = E_SIGNATURE_TREE_VIEW_GET_PRIVATE (tree_view);
+
+ if (priv->signature_list != NULL) {
+ g_signal_handlers_disconnect_by_func (
+ priv->signature_list,
+ signature_tree_view_refresh_cb, tree_view);
+ g_object_unref (priv->signature_list);
+ priv->signature_list = NULL;
+ }
+
+ if (signature_list != NULL) {
+ priv->signature_list = g_object_ref (signature_list);
+
+ /* Listen for changes to the signature list. */
+ g_signal_connect (
+ priv->signature_list, "signature-added",
+ G_CALLBACK (signature_tree_view_refresh_cb),
+ tree_view);
+ g_signal_connect (
+ priv->signature_list, "signature-changed",
+ G_CALLBACK (signature_tree_view_refresh_cb),
+ tree_view);
+ g_signal_connect (
+ priv->signature_list, "signature-removed",
+ G_CALLBACK (signature_tree_view_refresh_cb),
+ tree_view);
+ }
+
+ signature_tree_view_refresh_cb (signature_list, NULL, tree_view);
+
+ g_object_notify (G_OBJECT (tree_view), "signature-list");
+}
+
+ESignature *
+e_signature_tree_view_get_selected (ESignatureTreeView *tree_view)
+{
+ ESignature *signature;
+ GtkTreeSelection *selection;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+
+ g_return_val_if_fail (E_IS_SIGNATURE_TREE_VIEW (tree_view), NULL);
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view));
+ if (!gtk_tree_selection_get_selected (selection, &model, &iter))
+ return NULL;
+
+ gtk_tree_model_get (model, &iter, COLUMN_SIGNATURE, &signature, -1);
+
+ return signature;
+}
+
+gboolean
+e_signature_tree_view_set_selected (ESignatureTreeView *tree_view,
+ ESignature *signature)
+{
+ GtkTreeRowReference *reference;
+ GtkTreeSelection *selection;
+ GtkTreePath *path;
+
+ g_return_val_if_fail (E_IS_SIGNATURE_TREE_VIEW (tree_view), FALSE);
+
+ if (signature != NULL)
+ g_return_val_if_fail (E_IS_SIGNATURE (signature), FALSE);
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view));
+
+ /* NULL means clear the selection. */
+ if (signature == NULL) {
+ gtk_tree_selection_unselect_all (selection);
+ return TRUE;
+ }
+
+ /* Lookup the tree row reference for the signature. */
+ reference = g_hash_table_lookup (tree_view->priv->index, signature);
+ if (reference == NULL)
+ return FALSE;
+
+ /* Select the referenced path. */
+ path = gtk_tree_row_reference_get_path (reference);
+ gtk_tree_selection_select_path (selection, path);
+ gtk_tree_path_free (path);
+
+ g_object_notify (G_OBJECT (tree_view), "selected");
+
+ return TRUE;
+}
diff --git a/widgets/misc/e-signature-tree-view.h b/widgets/misc/e-signature-tree-view.h
new file mode 100644
index 0000000000..50d1e11905
--- /dev/null
+++ b/widgets/misc/e-signature-tree-view.h
@@ -0,0 +1,78 @@
+/*
+ * e-signature-tree-view.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef E_SIGNATURE_TREE_VIEW_H
+#define E_SIGNATURE_TREE_VIEW_H
+
+#include <gtk/gtk.h>
+#include <e-util/e-signature.h>
+#include <e-util/e-signature-list.h>
+
+/* Standard GObject macros */
+#define E_TYPE_SIGNATURE_TREE_VIEW \
+ (e_signature_tree_view_get_type ())
+#define E_SIGNATURE_TREE_VIEW(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_SIGNATURE_TREE_VIEW, ESignatureTreeView))
+#define E_SIGNATURE_TREE_VIEW_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_SIGNATURE_TREE_VIEW, ESignatureTreeViewClass))
+#define E_IS_SIGNATURE_TREE_VIEW(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_SIGNATURE_TREE_VIEW))
+#define E_IS_SIGNATURE_TREE_VIEW_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_SIGNATURE_TREE_VIEW))
+#define E_SIGNATURE_TREE_VIEW_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_SIGNATURE_TREE_VIEW, ESignatureTreeViewClass))
+
+G_BEGIN_DECLS
+
+typedef struct _ESignatureTreeView ESignatureTreeView;
+typedef struct _ESignatureTreeViewClass ESignatureTreeViewClass;
+typedef struct _ESignatureTreeViewPrivate ESignatureTreeViewPrivate;
+
+struct _ESignatureTreeView {
+ GtkTreeView parent;
+ ESignatureTreeViewPrivate *priv;
+};
+
+struct _ESignatureTreeViewClass {
+ GtkTreeViewClass parent_class;
+};
+
+GType e_signature_tree_view_get_type (void);
+GtkWidget * e_signature_tree_view_new (void);
+ESignatureList *e_signature_tree_view_get_signature_list
+ (ESignatureTreeView *tree_view);
+void e_signature_tree_view_set_signature_list
+ (ESignatureTreeView *tree_view,
+ ESignatureList *signature_list);
+ESignature * e_signature_tree_view_get_selected
+ (ESignatureTreeView *tree_view);
+gboolean e_signature_tree_view_set_selected
+ (ESignatureTreeView *tree_view,
+ ESignature *signature);
+
+G_END_DECLS
+
+#endif /* E_SIGNATURE_TREE_VIEW_H */
diff --git a/widgets/misc/e-task-bar.c b/widgets/misc/e-task-bar.c
deleted file mode 100644
index e0bdc762a3..0000000000
--- a/widgets/misc/e-task-bar.c
+++ /dev/null
@@ -1,302 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) version 3.
- *
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- *
- * Authors:
- * Ettore Perazzoli <ettore@ximian.com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "e-task-bar.h"
-
-struct _ETaskBarPrivate
-{
- GtkWidget *message_label;
- GtkHBox *hbox;
-};
-
-/* WARNING: Ugly hack starts here. */
-#define MAX_ACTIVITIES_PER_COMPONENT 2
-
-G_DEFINE_TYPE (ETaskBar, e_task_bar, GTK_TYPE_HBOX)
-
-#if 0
-static void
-reduce_displayed_activities_per_component (ETaskBar *task_bar)
-{
- GHashTable *component_ids_hash;
- GtkBox *box;
- GList *p;
-
- component_ids_hash = g_hash_table_new (g_str_hash, g_str_equal);
-
- box = GTK_BOX (task_bar->priv->hbox);
-
- for (p = box->children; p != NULL; p = p->next) {
- GtkBoxChild *child;
- const gchar *component_id;
- gpointer hash_item;
-
- child = (GtkBoxChild *) p->data;
- component_id = e_task_widget_get_component_id (E_TASK_WIDGET (child->widget));
-
- hash_item = g_hash_table_lookup (component_ids_hash, component_id);
-
- if (hash_item == NULL) {
- gtk_widget_show (child->widget);
- g_hash_table_insert (component_ids_hash, (gpointer) component_id, GINT_TO_POINTER (1));
- } else {
- gint num_items;
-
- num_items = GPOINTER_TO_INT (hash_item);
- g_return_if_fail (num_items <= MAX_ACTIVITIES_PER_COMPONENT);
-
- if (num_items == MAX_ACTIVITIES_PER_COMPONENT) {
- gtk_widget_hide (child->widget);
- } else {
- num_items ++;
- gtk_widget_show (child->widget);
- g_hash_table_insert (component_ids_hash, (gpointer) component_id, GINT_TO_POINTER (num_items));
- }
- }
- }
-
- g_hash_table_destroy (component_ids_hash);
-}
-#endif
-
-
-static void impl_finalize (GObject *object);
-
-static void
-e_task_bar_class_init (ETaskBarClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
- object_class->finalize = impl_finalize;
-}
-
-static void
-e_task_bar_init (ETaskBar *task_bar)
-{
- GtkWidget *label, *hbox;
- gint height;
-
- task_bar->priv = g_new (ETaskBarPrivate, 1);
-
- gtk_box_set_spacing (GTK_BOX (task_bar), 10);
-
- label = gtk_label_new (NULL);
- gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_END);
- gtk_box_pack_start (GTK_BOX (task_bar), label, TRUE, TRUE, 0);
- gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
- task_bar->priv->message_label = label;
-
- hbox = gtk_hbox_new (FALSE, 0);
- gtk_container_add (GTK_CONTAINER (task_bar), hbox);
- task_bar->priv->hbox = GTK_HBOX (hbox);
-
- /* Make the task bar large enough to accomodate a small icon.
- * XXX The "* 2" is a fudge factor to allow for some padding.
- * The true value is probably buried in a style property. */
- gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, NULL, &height);
- gtk_widget_set_size_request (GTK_WIDGET (task_bar), -1, height * 2);
-}
-
-static void
-impl_finalize (GObject *object)
-{
- ETaskBar *task_bar;
- ETaskBarPrivate *priv;
-
- task_bar = E_TASK_BAR (object);
- priv = task_bar->priv;
-
- g_free (priv);
-
- (* G_OBJECT_CLASS (e_task_bar_parent_class)->finalize) (object);
-}
-
-
-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 = g_object_new (e_task_bar_get_type (), NULL);
- e_task_bar_construct (task_bar);
-
- return GTK_WIDGET (task_bar);
-}
-
-void
-e_task_bar_set_message (ETaskBar *task_bar,
- const gchar *message)
-{
- if (message) {
- gtk_label_set_text (
- GTK_LABEL (task_bar->priv->message_label), message);
- gtk_widget_show (task_bar->priv->message_label);
- } else {
- e_task_bar_unset_message (task_bar);
- }
-}
-
-void
-e_task_bar_unset_message (ETaskBar *task_bar)
-{
- gtk_widget_hide (task_bar->priv->message_label);
-}
-
-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->priv->hbox);
-
- box->children = g_list_prepend (box->children, child_info);
-
- gtk_widget_set_parent (GTK_WIDGET (task_widget), GTK_WIDGET (task_bar->priv->hbox));
-
- 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));
- }
-
- /* We don't restrict */
- /* reduce_displayed_activities_per_component (task_bar);*/
-
- gtk_widget_show (GTK_WIDGET (task_bar->priv->hbox));
-}
-
-void
-e_task_bar_remove_task_from_id (ETaskBar *task_bar,
- guint id)
-{
- ETaskWidget *task_widget;
-
- g_return_if_fail (task_bar != NULL);
- g_return_if_fail (E_IS_TASK_BAR (task_bar));
-
- task_widget = e_task_bar_get_task_widget_from_id (task_bar, id);
- if (!task_widget) {
- printf("Failed...\n");
- return;
- }
-
- gtk_widget_destroy (GTK_WIDGET (task_widget));
-
- /* We don't restrict here on */
- /* reduce_displayed_activities_per_component (task_bar); */
-
- if (g_list_length (GTK_BOX (task_bar->priv->hbox)->children) == 0)
- gtk_widget_hide (GTK_WIDGET (task_bar->priv->hbox));
-}
-
-void
-e_task_bar_remove_task (ETaskBar *task_bar,
- gint 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_widget_destroy (GTK_WIDGET (task_widget));
-
- /* We don't restrict here on */
- /* reduce_displayed_activities_per_component (task_bar); */
-
- if (g_list_length (GTK_BOX (task_bar->priv->hbox)->children) == 0)
- gtk_widget_hide (GTK_WIDGET (task_bar->priv->hbox));
-}
-
-ETaskWidget *
-e_task_bar_get_task_widget_from_id (ETaskBar *task_bar,
- guint id)
-{
- GtkBoxChild *child_info;
- ETaskWidget *w = NULL;
- GList *list;
-
- g_return_val_if_fail (task_bar != NULL, NULL);
- g_return_val_if_fail (E_IS_TASK_BAR (task_bar), NULL);
-
- list = GTK_BOX (task_bar->priv->hbox)->children;
- while (list) {
- child_info = list->data;
- w = (ETaskWidget *) child_info->widget;
- if (w && w->id == id)
- break;
-
- w = NULL;
- list = list->next;
- }
-
- return w;
-}
-
-ETaskWidget *
-
-e_task_bar_get_task_widget (ETaskBar *task_bar,
- gint 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->priv->hbox)->children, n)->data;
-
- return E_TASK_WIDGET (child_info->widget);
-}
-
diff --git a/widgets/misc/e-task-bar.h b/widgets/misc/e-task-bar.h
deleted file mode 100644
index d88c0697dd..0000000000
--- a/widgets/misc/e-task-bar.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) version 3.
- *
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- *
- * Authors:
- * Ettore Perazzoli <ettore@ximian.com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-#ifndef _E_TASK_BAR_H_
-#define _E_TASK_BAR_H_
-
-#include "e-task-widget.h"
-
-#include <gtk/gtk.h>
-
-G_BEGIN_DECLS
-
-#define E_TYPE_TASK_BAR (e_task_bar_get_type ())
-#define E_TASK_BAR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_TASK_BAR, ETaskBar))
-#define E_TASK_BAR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E_TYPE_TASK_BAR, ETaskBarClass))
-#define E_IS_TASK_BAR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_TYPE_TASK_BAR))
-#define E_IS_TASK_BAR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), E_TYPE_TASK_BAR))
-
-
-typedef struct _ETaskBar ETaskBar;
-typedef struct _ETaskBarPrivate ETaskBarPrivate;
-typedef struct _ETaskBarClass ETaskBarClass;
-
-struct _ETaskBar {
- GtkHBox parent;
-
- ETaskBarPrivate *priv;
-};
-
-struct _ETaskBarClass {
- GtkHBoxClass parent_class;
-};
-
-
-GType e_task_bar_get_type (void);
-void e_task_bar_construct (ETaskBar *task_bar);
-GtkWidget *e_task_bar_new (void);
-
-void e_task_bar_set_message (ETaskBar *task_bar,
- const gchar *message);
-void e_task_bar_unset_message (ETaskBar *task_bar);
-
-void e_task_bar_prepend_task (ETaskBar *task_bar,
- ETaskWidget *task_widget);
-void e_task_bar_remove_task (ETaskBar *task_bar,
- gint n);
-ETaskWidget * e_task_bar_get_task_widget_from_id (ETaskBar *task_bar,
- guint id);
-
-void e_task_bar_remove_task_from_id (ETaskBar *task_bar,
- guint id);
-ETaskWidget *e_task_bar_get_task_widget (ETaskBar *task_bar,
- gint n);
-
-G_END_DECLS
-
-#endif /* _E_TASK_BAR_H_ */
diff --git a/widgets/misc/e-task-widget.c b/widgets/misc/e-task-widget.c
deleted file mode 100644
index bf3cefcf24..0000000000
--- a/widgets/misc/e-task-widget.c
+++ /dev/null
@@ -1,291 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) version 3.
- *
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- *
- * Authors:
- * Ettore Perazzoli <ettore@ximian.com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "e-task-widget.h"
-#include "e-spinner.h"
-
-#include <glib/gi18n.h>
-
-
-#define SPACING 2
-
-struct _ETaskWidgetPrivate {
- gchar *component_id;
-
- GtkWidget *label;
- GtkWidget *box;
- GtkWidget *image;
-
- void (*cancel_func) (gpointer data);
- gpointer data;
-};
-
-G_DEFINE_TYPE (ETaskWidget, e_task_widget, GTK_TYPE_EVENT_BOX)
-
-/* GObject methods. */
-
-static void
-impl_finalize (GObject *object)
-{
- ETaskWidget *task_widget;
- ETaskWidgetPrivate *priv;
-
- task_widget = E_TASK_WIDGET (object);
- priv = task_widget->priv;
-
- g_free (priv->component_id);
- g_free (priv);
-
- (* G_OBJECT_CLASS (e_task_widget_parent_class)->finalize) (object);
-}
-
-
-static void
-e_task_widget_class_init (ETaskWidgetClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
- object_class->finalize = impl_finalize;
-}
-
-static void
-e_task_widget_init (ETaskWidget *task_widget)
-{
- ETaskWidgetPrivate *priv;
-
- priv = g_new (ETaskWidgetPrivate, 1);
-
- priv->component_id = NULL;
- priv->label = NULL;
- priv->image = NULL;
- priv->box = NULL;
-
- task_widget->priv = priv;
- task_widget->id = 0;
-}
-
-static gboolean
-button_press_event_cb (GtkWidget *w, gpointer data)
-{
- ETaskWidget *tw = (ETaskWidget *) data;
- ETaskWidgetPrivate *priv = tw->priv;
-
- priv->cancel_func (priv->data);
-
- return TRUE;
-}
-
-static gboolean
-prepare_popup (ETaskWidget *widget, GdkEventButton *event)
-{
- if (event->type != GDK_BUTTON_PRESS)
- return FALSE;
-
- if (event->button != 3)
- return FALSE;
-
- /* FIXME: Implement Cancel */
-
- return TRUE;
-}
-
-
-void
-e_task_widget_construct (ETaskWidget *task_widget,
- const gchar *component_id,
- const gchar *information,
- void (*cancel_func) (gpointer data),
- gpointer data)
-{
- ETaskWidgetPrivate *priv;
- GtkWidget *box;
- GtkWidget *frame;
-
- g_return_if_fail (task_widget != NULL);
- g_return_if_fail (E_IS_TASK_WIDGET (task_widget));
- g_return_if_fail (component_id != NULL);
- g_return_if_fail (information != NULL);
-
- priv = task_widget->priv;
-
- priv->component_id = g_strdup (component_id);
-
- frame = gtk_frame_new (NULL);
- gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
- gtk_container_add (GTK_CONTAINER (task_widget), frame);
- gtk_widget_show (frame);
-
- box = gtk_hbox_new (FALSE, 0);
- gtk_container_add (GTK_CONTAINER (frame), box);
- gtk_widget_show (box);
-
- gtk_widget_set_size_request (box, 1, -1);
-
- priv->box = gtk_hbox_new (FALSE, 0);
- priv->image = e_spinner_new_spinning_small_shown ();
- gtk_widget_show (priv->box);
- gtk_box_pack_start (GTK_BOX (priv->box), priv->image, FALSE, TRUE, 0);
- gtk_box_pack_start (GTK_BOX (box), priv->box, 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);
- if (cancel_func) {
- GdkPixbuf *pixbuf;
- GtkWidget *image;
- GtkWidget *tool;
-
- pixbuf = gtk_icon_theme_load_icon (
- gtk_icon_theme_get_default (),
- "gtk-stop", 16, 0, NULL);
- image = gtk_image_new_from_pixbuf (pixbuf);
- g_object_unref (pixbuf);
-
- tool = (GtkWidget *) gtk_tool_button_new (image, NULL);
- gtk_box_pack_end (GTK_BOX (box), tool, FALSE, TRUE, 0);
- gtk_widget_show_all (tool);
-
- gtk_widget_set_sensitive (tool, cancel_func != NULL);
- priv->cancel_func = cancel_func;
- priv->data = data;
- g_signal_connect (tool, "clicked", G_CALLBACK (button_press_event_cb), task_widget);
- g_signal_connect (task_widget, "button-press-event", G_CALLBACK (prepare_popup), task_widget);
-
- }
-
- e_task_widget_update (task_widget, information, -1.0);
-}
-
-GtkWidget *
-e_task_widget_new_with_cancel (const gchar *component_id,
- const gchar *information,
- void (*cancel_func) (gpointer data),
- gpointer data)
-{
- ETaskWidget *task_widget;
-
- g_return_val_if_fail (information != NULL, NULL);
-
- task_widget = g_object_new (e_task_widget_get_type (), NULL);
- e_task_widget_construct (task_widget, component_id, information, cancel_func, data);
-
- return GTK_WIDGET (task_widget);
-}
-
-GtkWidget *
-e_task_widget_new (const gchar *component_id,
- const gchar *information)
-{
- ETaskWidget *task_widget;
-
- g_return_val_if_fail (information != NULL, NULL);
-
- task_widget = g_object_new (e_task_widget_get_type (), NULL);
- e_task_widget_construct (task_widget, component_id, information, NULL, NULL);
-
- return GTK_WIDGET (task_widget);
-}
-
-GtkWidget *
-e_task_widget_update_image (ETaskWidget *task_widget,
- const gchar *stock, const gchar *text)
-{
- GtkWidget *image, *tool;
- GdkPixbuf *pixbuf;
-
- pixbuf = gtk_icon_theme_load_icon (
- gtk_icon_theme_get_default (),
- stock, 16, 0, NULL);
- image = gtk_image_new_from_pixbuf (pixbuf);
- g_object_unref (pixbuf);
-
- tool = (GtkWidget *) gtk_tool_button_new (image, NULL);
- gtk_box_pack_start (GTK_BOX(task_widget->priv->box), tool, FALSE, TRUE, 0);
- gtk_widget_show_all (task_widget->priv->box);
- gtk_widget_hide (task_widget->priv->image);
- task_widget->priv->image = image;
- gtk_label_set_text (GTK_LABEL (task_widget->priv->label), text);
-
- return tool;
-}
-
-
-void
-e_task_widget_update (ETaskWidget *task_widget,
- const gchar *information,
- double completion)
-{
- ETaskWidgetPrivate *priv;
- gchar *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) {
- /* For Translator only: %s is status message that is displayed (eg "moving items", "updating objects") */
- text = g_strdup_printf (_("%s (...)"), information);
- } else {
- gint percent_complete;
- percent_complete = (gint) (completion * 100.0 + .5);
- /* For Translator only: %s is status message that is displayed (eg "moving items", "updating objects");
- %d is a number between 0 and 100, describing the percentage of operation complete */
- text = g_strdup_printf (_("%s (%d%% complete)"), information, percent_complete);
- }
-
- gtk_label_set_text (GTK_LABEL (priv->label), text);
-
- gtk_widget_set_tooltip_text (GTK_WIDGET (task_widget), 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));
-}
-
-
-const gchar *
-e_task_widget_get_component_id (ETaskWidget *task_widget)
-{
- g_return_val_if_fail (task_widget != NULL, NULL);
- g_return_val_if_fail (E_IS_TASK_WIDGET (task_widget), NULL);
-
- return task_widget->priv->component_id;
-}
-
diff --git a/widgets/misc/e-task-widget.h b/widgets/misc/e-task-widget.h
deleted file mode 100644
index b650bd8ac5..0000000000
--- a/widgets/misc/e-task-widget.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) version 3.
- *
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- *
- * Authors:
- * Ettore Perazzoli <ettore@ximian.com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-#ifndef _E_TASK_WIDGET_H_
-#define _E_TASK_WIDGET_H_
-
-#include <gtk/gtk.h>
-
-G_BEGIN_DECLS
-
-#define E_TYPE_TASK_WIDGET (e_task_widget_get_type ())
-#define E_TASK_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_TASK_WIDGET, ETaskWidget))
-#define E_TASK_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E_TYPE_TASK_WIDGET, ETaskWidgetClass))
-#define E_IS_TASK_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_TYPE_TASK_WIDGET))
-#define E_IS_TASK_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), E_TYPE_TASK_WIDGET))
-
-
-typedef struct _ETaskWidget ETaskWidget;
-typedef struct _ETaskWidgetPrivate ETaskWidgetPrivate;
-typedef struct _ETaskWidgetClass ETaskWidgetClass;
-
-struct _ETaskWidget {
- GtkEventBox parent;
-
- ETaskWidgetPrivate *priv;
- guint id;
-};
-
-struct _ETaskWidgetClass {
- GtkEventBoxClass parent_class;
-};
-
-
-GType e_task_widget_get_type (void);
-void e_task_widget_construct (ETaskWidget *task_widget,
- const gchar *component_id,
- const gchar *information,
- void (*cancel_func) (gpointer data),
- gpointer data);
-GtkWidget * e_task_widget_new (const gchar *component_id,
- const gchar *information);
-GtkWidget * e_task_widget_new_with_cancel (const gchar *component_id,
- const gchar *information,
- void (*cancel_func) (gpointer data),
- gpointer data);
-void e_task_widget_update (ETaskWidget *task_widget,
- const gchar *information,
- double completion);
-GtkWidget * e_task_widget_update_image (ETaskWidget *task_widget,
- const gchar *stock,
- const gchar *text);
-void e_task_wiget_alert (ETaskWidget *task_widget);
-void e_task_wiget_unalert (ETaskWidget *task_widget);
-const gchar * e_task_widget_get_component_id (ETaskWidget *task_widget);
-
-G_END_DECLS
-
-#endif /* _E_TASK_WIDGET_H_ */
diff --git a/widgets/misc/e-timeout-activity.c b/widgets/misc/e-timeout-activity.c
new file mode 100644
index 0000000000..aa57960fe0
--- /dev/null
+++ b/widgets/misc/e-timeout-activity.c
@@ -0,0 +1,198 @@
+/*
+ * e-timeout-activity.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#include "e-timeout-activity.h"
+
+#include <stdarg.h>
+
+#define E_TIMEOUT_ACTIVITY_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), E_TYPE_TIMEOUT_ACTIVITY, ETimeoutActivityPrivate))
+
+struct _ETimeoutActivityPrivate {
+ guint timeout_id;
+};
+
+enum {
+ TIMEOUT,
+ LAST_SIGNAL
+};
+
+static gpointer parent_class;
+static gulong signals[LAST_SIGNAL];
+
+static gboolean
+timeout_activity_cb (ETimeoutActivity *timeout_activity)
+{
+ g_signal_emit (timeout_activity, signals[TIMEOUT], 0);
+
+ return FALSE;
+}
+
+static void
+timeout_activity_finalize (GObject *object)
+{
+ ETimeoutActivityPrivate *priv;
+
+ priv = E_TIMEOUT_ACTIVITY_GET_PRIVATE (object);
+
+ if (priv->timeout_id > 0)
+ g_source_remove (priv->timeout_id);
+
+ /* Chain up to parent's finalize() method. */
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+timeout_activity_cancelled (EActivity *activity)
+{
+ ETimeoutActivityPrivate *priv;
+
+ priv = E_TIMEOUT_ACTIVITY_GET_PRIVATE (activity);
+
+ if (priv->timeout_id > 0) {
+ g_source_remove (priv->timeout_id);
+ priv->timeout_id = 0;
+ }
+
+ /* Chain up to parent's cancelled() method. */
+ E_ACTIVITY_CLASS (parent_class)->cancelled (activity);
+}
+
+static void
+timeout_activity_completed (EActivity *activity)
+{
+ ETimeoutActivityPrivate *priv;
+
+ priv = E_TIMEOUT_ACTIVITY_GET_PRIVATE (activity);
+
+ if (priv->timeout_id > 0) {
+ g_source_remove (priv->timeout_id);
+ priv->timeout_id = 0;
+ }
+
+ /* Chain up to parent's completed() method. */
+ E_ACTIVITY_CLASS (parent_class)->completed (activity);
+}
+
+static void
+timeout_activity_timeout (ETimeoutActivity *timeout_activity)
+{
+ /* Allow subclasses to safely chain up. */
+}
+
+static void
+timeout_activity_class_init (ETimeoutActivityClass *class)
+{
+ GObjectClass *object_class;
+ EActivityClass *activity_class;
+
+ parent_class = g_type_class_peek_parent (class);
+ g_type_class_add_private (class, sizeof (ETimeoutActivityPrivate));
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->finalize = timeout_activity_finalize;
+
+ activity_class = E_ACTIVITY_CLASS (class);
+ activity_class->cancelled = timeout_activity_cancelled;
+ activity_class->completed = timeout_activity_completed;
+
+ class->timeout = timeout_activity_timeout;
+
+ signals[TIMEOUT] = g_signal_new (
+ "timeout",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (ETimeoutActivityClass, timeout),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+}
+
+static void
+timeout_activity_init (ETimeoutActivity *timeout_activity)
+{
+ timeout_activity->priv =
+ E_TIMEOUT_ACTIVITY_GET_PRIVATE (timeout_activity);
+}
+
+GType
+e_timeout_activity_get_type (void)
+{
+ static GType type = 0;
+
+ if (G_UNLIKELY (type == 0)) {
+ static const GTypeInfo type_info = {
+ sizeof (ETimeoutActivityClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) timeout_activity_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+ sizeof (ETimeoutActivity),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) timeout_activity_init,
+ NULL /* value_table */
+ };
+
+ type = g_type_register_static (
+ E_TYPE_ACTIVITY, "ETimeoutActivity", &type_info, 0);
+ }
+
+ return type;
+}
+
+EActivity *
+e_timeout_activity_new (const gchar *primary_text)
+{
+ return g_object_new (
+ E_TYPE_TIMEOUT_ACTIVITY,
+ "primary-text", primary_text, NULL);
+}
+
+EActivity *
+e_timeout_activity_newv (const gchar *format, ...)
+{
+ EActivity *activity;
+ gchar *primary_text;
+ va_list args;
+
+ va_start (args, format);
+ primary_text = g_strdup_vprintf (format, args);
+ activity = e_timeout_activity_new (primary_text);
+ g_free (primary_text);
+ va_end (args);
+
+ return activity;
+}
+
+void
+e_timeout_activity_set_timeout (ETimeoutActivity *timeout_activity,
+ guint seconds)
+{
+ g_return_if_fail (E_IS_TIMEOUT_ACTIVITY (timeout_activity));
+
+ if (timeout_activity->priv->timeout_id > 0)
+ e_activity_cancel (E_ACTIVITY (timeout_activity));
+
+ timeout_activity->priv->timeout_id = g_timeout_add_seconds (
+ seconds, (GSourceFunc) timeout_activity_cb, timeout_activity);
+}
diff --git a/widgets/misc/e-timeout-activity.h b/widgets/misc/e-timeout-activity.h
new file mode 100644
index 0000000000..82dd1138c2
--- /dev/null
+++ b/widgets/misc/e-timeout-activity.h
@@ -0,0 +1,73 @@
+/*
+ * e-timeout-activity.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef E_TIMEOUT_ACTIVITY_H
+#define E_TIMEOUT_ACTIVITY_H
+
+#include <e-activity.h>
+
+/* Standard GObject macros */
+#define E_TYPE_TIMEOUT_ACTIVITY \
+ (e_timeout_activity_get_type ())
+#define E_TIMEOUT_ACTIVITY(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_TIMEOUT_ACTIVITY, ETimeoutActivity))
+#define E_TIMEOUT_ACTIVITY_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_TIMEOUT_ACTIVITY, ETimeoutActivityClass))
+#define E_IS_TIMEOUT_ACTIVITY(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_TIMEOUT_ACTIVITY))
+#define E_IS_TIMEOUT_ACTIVITY_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_TIMEOUT_ACTIVITY))
+#define E_TIMEOUT_ACTIVITY_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_TIMEOUT_ACTIVITY, ETimeoutActivityClass))
+
+G_BEGIN_DECLS
+
+typedef struct _ETimeoutActivity ETimeoutActivity;
+typedef struct _ETimeoutActivityClass ETimeoutActivityClass;
+typedef struct _ETimeoutActivityPrivate ETimeoutActivityPrivate;
+
+struct _ETimeoutActivity {
+ EActivity parent;
+ ETimeoutActivityPrivate *priv;
+};
+
+struct _ETimeoutActivityClass {
+ EActivityClass parent_class;
+
+ /* Signals */
+ void (*timeout) (ETimeoutActivity *timeout_activity);
+};
+
+GType e_timeout_activity_get_type (void);
+EActivity * e_timeout_activity_new (const gchar *primary_text);
+EActivity * e_timeout_activity_newv (const gchar *format,
+ ...) G_GNUC_PRINTF (1, 2);
+void e_timeout_activity_set_timeout (ETimeoutActivity *timeout_activity,
+ guint seconds);
+
+G_END_DECLS
+
+#endif /* E_TIMEOUT_ACTIVITY_H */
diff --git a/widgets/misc/e-unicode.c b/widgets/misc/e-unicode.c
deleted file mode 100644
index fb815ff94f..0000000000
--- a/widgets/misc/e-unicode.c
+++ /dev/null
@@ -1,2052 +0,0 @@
-/*
- * e-unicode.c - utf-8 support functions for gal
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) version 3.
- *
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- *
- * Authors:
- * Lauris Kaplinski <lauris@ximian.com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-/*
- * TODO: Break simple ligatures in e_utf8_strstrcasedecomp
- */
-
-#include <config.h>
-
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-#include <ctype.h>
-#include <iconv.h>
-#ifdef HAVE_ALLOCA_H
-#include <alloca.h>
-#endif
-
-#include <gdk/gdkkeysyms.h>
-#include <gtk/gtk.h>
-#include <libxml/xmlmemory.h>
-
-#include <camel/camel-iconv.h>
-
-#include <glib/gi18n.h>
-#include "e-unicode.h"
-
-#define d(x)
-
-#define FONT_TESTING
-#define MAX_DECOMP 8
-
-static gint e_canonical_decomposition (gunichar ch, gunichar * buf);
-static gunichar e_stripped_char (gunichar ch);
-
-/* FIXME: this has not been ported fully yet - non ASCII people beware. */
-
-/*
- * This my favourite
- *
- * strstr doing case insensitive, decomposing search
- *
- * Lauris
- */
-
-const gchar *
-e_utf8_strstrcasedecomp (const gchar *haystack, const gchar *needle)
-{
- gunichar *nuni;
- gunichar unival;
- gint nlen;
- const gchar *o, *p;
-
- if (haystack == NULL) return NULL;
- if (needle == NULL) return NULL;
- if (strlen (needle) == 0) return haystack;
- if (strlen (haystack) == 0) return NULL;
-
- nuni = alloca (sizeof (gunichar) * strlen (needle));
-
- nlen = 0;
- for (p = e_unicode_get_utf8 (needle, &unival); p && unival; p = e_unicode_get_utf8 (p, &unival)) {
- gint sc;
- sc = e_stripped_char (unival);
- if (sc) {
- nuni[nlen++] = sc;
- }
- }
- /* NULL means there was illegal utf-8 sequence */
- if (!p) return NULL;
- /* If everything is correct, we have decomposed, lowercase, stripped needle */
- if (nlen < 1) return haystack;
-
- o = haystack;
- for (p = e_unicode_get_utf8 (o, &unival); p && unival; p = e_unicode_get_utf8 (p, &unival)) {
- gint sc;
- sc = e_stripped_char (unival);
- if (sc) {
- /* We have valid stripped gchar */
- if (sc == nuni[0]) {
- const gchar *q = p;
- gint npos = 1;
- while (npos < nlen) {
- q = e_unicode_get_utf8 (q, &unival);
- if (!q || !unival) return NULL;
- sc = e_stripped_char (unival);
- if ((!sc) || (sc != nuni[npos])) break;
- npos++;
- }
- if (npos == nlen) {
- return o;
- }
- }
- }
- o = p;
- }
-
- return NULL;
-}
-
-const gchar *
-e_utf8_strstrcase (const gchar *haystack, const gchar *needle)
-{
- gunichar *nuni;
- gunichar unival;
- gint nlen;
- const gchar *o, *p;
-
- if (haystack == NULL) return NULL;
- if (needle == NULL) return NULL;
- if (strlen (needle) == 0) return haystack;
- if (strlen (haystack) == 0) return NULL;
-
- nuni = alloca (sizeof (gunichar) * strlen (needle));
-
- nlen = 0;
- for (p = e_unicode_get_utf8 (needle, &unival); p && unival; p = e_unicode_get_utf8 (p, &unival)) {
- nuni[nlen++] = g_unichar_tolower (unival);
- }
- /* NULL means there was illegal utf-8 sequence */
- if (!p) return NULL;
-
- o = haystack;
- for (p = e_unicode_get_utf8 (o, &unival); p && unival; p = e_unicode_get_utf8 (p, &unival)) {
- gint sc;
- sc = g_unichar_tolower (unival);
- /* We have valid stripped gchar */
- if (sc == nuni[0]) {
- const gchar *q = p;
- gint npos = 1;
- while (npos < nlen) {
- q = e_unicode_get_utf8 (q, &unival);
- if (!q || !unival) return NULL;
- sc = g_unichar_tolower (unival);
- if (sc != nuni[npos]) break;
- npos++;
- }
- if (npos == nlen) {
- return o;
- }
- }
- o = p;
- }
-
- return NULL;
-}
-
-#if 0
-const gchar *
-e_utf8_strstrcase (const gchar *haystack, const gchar *needle)
-{
- gchar *p;
- gunichar *huni, *nuni;
- gunichar unival;
- gint hlen, nlen, hp, np;
-
- if (haystack == NULL) return NULL;
- if (needle == NULL) return NULL;
- if (strlen (needle) == 0) return haystack;
-
- huni = alloca (sizeof (gunichar) * strlen (haystack));
-
- for (hlen = 0, p = e_unicode_get_utf8 (haystack, &unival); p && unival; hlen++, p = e_unicode_get_utf8 (p, &unival)) {
- huni[hlen] = g_unichar_tolower (unival);
- }
-
- if (!p) return NULL;
- if (hlen == 0) return NULL;
-
- nuni = alloca (sizeof (gunichar) * strlen (needle));
-
- for (nlen = 0, p = e_unicode_get_utf8 (needle, &unival); p && unival; nlen++, p = e_unicode_get_utf8 (p, &unival)) {
- nuni[nlen] = g_unichar_tolower (unival);
- }
-
- if (!p) return NULL;
- if (nlen == 0) return NULL;
-
- if (hlen < nlen) return NULL;
-
- for (hp = 0; hp <= hlen - nlen; hp++) {
- for (np = 0; np < nlen; np++) {
- if (huni[hp + np] != nuni[np]) break;
- }
- if (np == nlen) return haystack + unicode_offset_to_index (haystack, hp);
- }
-
- return NULL;
-}
-#endif
-
-gchar *
-e_utf8_from_gtk_event_key (GtkWidget *widget, guint keyval, const gchar *string)
-{
- gint unival;
- gchar *utf;
- gint unilen;
-
- if (keyval == GDK_VoidSymbol) {
- utf = e_utf8_from_locale_string (string);
- } else {
- unival = gdk_keyval_to_unicode (keyval);
-
- if (unival < ' ') return NULL;
-
- utf = g_new (gchar, 7);
-
- unilen = e_unichar_to_utf8 (unival, utf);
-
- utf[unilen] = '\0';
- }
-
- return utf;
-}
-
-gchar *
-e_utf8_from_iconv_string_sized (iconv_t ic, const gchar *string, gint bytes)
-{
- gchar *new, *ob;
- const gchar *ib;
- gsize ibl, obl;
-
- if (!string) return NULL;
-
- if (ic == (iconv_t) -1) {
- gint i;
- /* iso-8859-1 */
- ib = (gchar *) string;
- new = ob = (gchar *)g_new (unsigned char, bytes * 2 + 1);
- for (i = 0; i < (bytes); i ++) {
- ob += e_unichar_to_utf8 (ib[i], ob);
- }
- *ob = '\0';
- return new;
- }
-
- ib = string;
- ibl = bytes;
- new = ob = g_new (gchar, ibl * 6 + 1);
- obl = ibl * 6;
-
- while (ibl > 0) {
- camel_iconv (ic, &ib, &ibl, &ob, &obl);
- if (ibl > 0) {
- gint len;
- if ((*ib & 0x80) == 0x00) len = 1;
- else if ((*ib &0xe0) == 0xc0) len = 2;
- else if ((*ib &0xf0) == 0xe0) len = 3;
- else if ((*ib &0xf8) == 0xf0) len = 4;
- else {
- g_warning ("Invalid UTF-8 sequence");
- break;
- }
- ib += len;
- ibl = bytes - (ib - string);
- if (ibl > bytes) ibl = 0;
- *ob++ = '_';
- obl--;
- }
- }
-
- *ob = '\0';
-
- return new;
-}
-
-gchar *
-e_utf8_from_iconv_string (iconv_t ic, const gchar *string)
-{
- if (!string) return NULL;
- return e_utf8_from_iconv_string_sized (ic, string, strlen (string));
-}
-
-gchar *
-e_utf8_to_iconv_string_sized (iconv_t ic, const gchar *string, gint bytes)
-{
- gchar *new, *ob;
- const gchar *ib;
- gsize ibl, obl;
-
- if (!string) return NULL;
-
- if (ic == (iconv_t) -1) {
- gint len;
- const gchar *u;
- gunichar uc;
-
- new = (gchar *)g_new (unsigned char, bytes * 4 + 1);
- u = string;
- len = 0;
-
- while ((u) && (u - string < bytes)) {
- u = e_unicode_get_utf8 (u, &uc);
- new[len++] = uc & 0xff;
- }
- new[len] = '\0';
- return new;
- }
-
- ib = string;
- ibl = bytes;
- new = ob = g_new (char, ibl * 4 + 4);
- obl = ibl * 4;
-
- while (ibl > 0) {
- camel_iconv (ic, &ib, &ibl, &ob, &obl);
- if (ibl > 0) {
- gint len;
- if ((*ib & 0x80) == 0x00) len = 1;
- else if ((*ib &0xe0) == 0xc0) len = 2;
- else if ((*ib &0xf0) == 0xe0) len = 3;
- else if ((*ib &0xf8) == 0xf0) len = 4;
- else {
- g_warning ("Invalid UTF-8 sequence");
- break;
- }
- ib += len;
- ibl = bytes - (ib - string);
- if (ibl > bytes) ibl = 0;
-
- /* FIXME: this is wrong... what if the destination charset is 16 or 32 bit? */
- *ob++ = '_';
- obl--;
- }
- }
-
- /* Make sure to terminate with plenty of padding */
- memset (ob, 0, 4);
-
- return new;
-}
-
-gchar *
-e_utf8_to_iconv_string (iconv_t ic, const gchar *string)
-{
- if (!string) return NULL;
- return e_utf8_to_iconv_string_sized (ic, string, strlen (string));
-}
-
-gchar *
-e_utf8_from_charset_string_sized (const gchar *charset, const gchar *string, gint bytes)
-{
- iconv_t ic;
- gchar *ret;
-
- if (!string) return NULL;
-
- ic = camel_iconv_open("utf-8", charset);
- ret = e_utf8_from_iconv_string_sized (ic, string, bytes);
- camel_iconv_close(ic);
-
- return ret;
-}
-
-gchar *
-e_utf8_from_charset_string (const gchar *charset, const gchar *string)
-{
- if (!string) return NULL;
- return e_utf8_from_charset_string_sized (charset, string, strlen (string));
-}
-
-gchar *
-e_utf8_to_charset_string_sized (const gchar *charset, const gchar *string, gint bytes)
-{
- iconv_t ic;
- gchar *ret;
-
- if (!string) return NULL;
-
- ic = camel_iconv_open(charset, "utf-8");
- ret = e_utf8_to_iconv_string_sized (ic, string, bytes);
- camel_iconv_close(ic);
-
- return ret;
-}
-
-gchar *
-e_utf8_to_charset_string (const gchar *charset, const gchar *string)
-{
- if (!string) return NULL;
- return e_utf8_to_charset_string_sized (charset, string, strlen (string));
-}
-
-gchar *
-e_utf8_from_locale_string_sized (const gchar *string, gint bytes)
-{
- iconv_t ic;
- gchar *ret;
-
- if (!string) return NULL;
-
- ic = camel_iconv_open("utf-8", camel_iconv_locale_charset());
- ret = e_utf8_from_iconv_string_sized (ic, string, bytes);
- camel_iconv_close(ic);
-
- return ret;
-}
-
-gchar *
-e_utf8_from_locale_string (const gchar *string)
-{
- if (!string) return NULL;
- return e_utf8_from_locale_string_sized (string, strlen (string));
-}
-
-gchar *
-e_utf8_to_locale_string_sized (const gchar *string, gint bytes)
-{
- iconv_t ic;
- gchar *ret;
-
- if (!string) return NULL;
-
- ic = camel_iconv_open(camel_iconv_locale_charset(), "utf-8");
- ret = e_utf8_to_iconv_string_sized (ic, string, bytes);
- camel_iconv_close(ic);
-
- return ret;
-}
-
-gchar *
-e_utf8_to_locale_string (const gchar *string)
-{
- if (!string) return NULL;
- return e_utf8_to_locale_string_sized (string, strlen (string));
-}
-
-gboolean
-e_utf8_is_ascii (const gchar *string)
-{
- gchar c;
-
- g_return_val_if_fail (string != NULL, FALSE);
-
- for (; (c = *string); string++) {
- if (c & 0x80)
- return FALSE;
- }
-
- return TRUE;
-}
-
-gchar *
-e_utf8_gtk_entry_get_text (GtkEntry *entry)
-{
- return g_strdup (gtk_entry_get_text (entry));
-}
-
-gchar *
-e_utf8_gtk_editable_get_text (GtkEditable *editable)
-{
- return gtk_editable_get_chars (editable, 0, -1);
-}
-
-gchar *
-e_utf8_gtk_editable_get_chars (GtkEditable *editable, gint start, gint end)
-{
- return gtk_editable_get_chars (editable, start, end);
-}
-
-void
-e_utf8_gtk_editable_insert_text (GtkEditable *editable, const gchar *text, gint length, gint *position)
-{
- gtk_editable_insert_text (editable, text, length, position);
-}
-
-void
-e_utf8_gtk_editable_set_text (GtkEditable *editable, const gchar *text)
-{
- gint position;
-
- gtk_editable_delete_text(editable, 0, -1);
- gtk_editable_insert_text (editable, text, strlen (text), &position);
-}
-
-void
-e_utf8_gtk_entry_set_text (GtkEntry *entry, const gchar *text)
-{
- if (!text)
- gtk_entry_set_text(entry, "");
- else
- gtk_entry_set_text (entry, text);
-}
-
-/*
- * Translate \U+XXXX\ sequences to utf8 chars
- */
-
-gchar *
-e_utf8_xml1_decode (const gchar *text)
-{
- const guchar *c;
- gchar *u, *d;
- gint len, s;
-
- g_return_val_if_fail (text != NULL, NULL);
-
- len = strlen (text)+1;
- /* len * 2 is absolute maximum */
- u = d = g_malloc (len * 2);
-
- c = (guchar *)text;
- s = 0;
- while (s < len) {
- if ((s <= (len - 8)) &&
- (c[s ] == '\\') &&
- (c[s + 1] == 'U' ) &&
- (c[s + 2] == '+' ) &&
- isxdigit (c[s + 3]) &&
- isxdigit (c[s + 4]) &&
- isxdigit (c[s + 5]) &&
- isxdigit (c[s + 6]) &&
- (c[s + 7] == '\\')) {
- /* Valid \U+XXXX\ sequence */
- gint unival;
- unival = strtol ((gchar *)(c + s + 3), NULL, 16);
- d += e_unichar_to_utf8 (unival, d);
- s += 8;
- } else if (c[s] > 127) {
- /* fixme: We assume iso-8859-1 currently */
- d += e_unichar_to_utf8 (c[s], d);
- s += 1;
- } else {
- *d++ = c[s++];
- }
- }
- *d++ = '\0';
- u = g_realloc (u, (d - u));
-
- return u;
-}
-
-gchar *
-e_utf8_xml1_encode (const gchar *text)
-{
- gchar *u, *d, *c;
- guint unival;
- gint len;
-
- g_return_val_if_fail (text != NULL, NULL);
-
- len = 0;
- for (u = e_unicode_get_utf8 (text, &unival); u && unival; u = e_unicode_get_utf8 (u, &unival)) {
- if ((unival >= 0x80) || (unival == '\\')) {
- len += 8;
- } else {
- len += 1;
- }
- }
- d = c = (gchar *)g_new (guchar, len + 1);
-
- for (u = e_unicode_get_utf8 (text, &unival); u && unival; u = e_unicode_get_utf8 (u, &unival)) {
- if ((unival >= 0x80) || (unival == '\\')) {
- *c++ = '\\';
- *c++ = 'U';
- *c++ = '+';
- c += sprintf (c, "%04x", unival);
- *c++ = '\\';
- } else {
- *c++ = unival;
- }
- }
- *c = '\0';
-
- return d;
-}
-
-/**
- * e_unichar_to_utf8:
- * @c: a ISO10646 character code
- * @outbuf: output buffer, must have at least 6 bytes of space.
- * If %NULL, the length will be computed and returned
- * and nothing will be written to @out.
- *
- * Convert a single character to utf8
- *
- * Return value: number of bytes written
- **/
-
-gint
-e_unichar_to_utf8 (gint c, gchar *outbuf)
-{
- gsize len = 0;
- gint first;
- gint i;
-
- if (c < 0x80)
- {
- first = 0;
- len = 1;
- }
- else if (c < 0x800)
- {
- first = 0xc0;
- len = 2;
- }
- else if (c < 0x10000)
- {
- first = 0xe0;
- len = 3;
- }
- else if (c < 0x200000)
- {
- first = 0xf0;
- len = 4;
- }
- else if (c < 0x4000000)
- {
- first = 0xf8;
- len = 5;
- }
- else
- {
- first = 0xfc;
- len = 6;
- }
-
- if (outbuf)
- {
- for (i = len - 1; i > 0; --i)
- {
- outbuf[i] = (c & 0x3f) | 0x80;
- c >>= 6;
- }
- outbuf[0] = c | first;
- }
-
- return len;
-}
-
-gchar *
-e_unicode_get_utf8 (const gchar *text, gunichar *out)
-{
- *out = g_utf8_get_char (text);
- return (*out == (gunichar)-1) ? NULL : g_utf8_next_char (text);
-}
-
-/*
- * Canonical decomposition
- *
- * It is copied here from libunicode, because we do not want malloc
- *
- */
-
-typedef struct
-{
- gushort ch;
- const gchar *expansion;
-} e_decomposition;
-
-static e_decomposition e_decomp_table[] =
-{
- { 0x00c0, "\x00\x41\x03\x00\0" },
- { 0x00c1, "\x00\x41\x03\x01\0" },
- { 0x00c2, "\x00\x41\x03\x02\0" },
- { 0x00c3, "\x00\x41\x03\x03\0" },
- { 0x00c4, "\x00\x41\x03\x08\0" },
- { 0x00c5, "\x00\x41\x03\x0a\0" },
- { 0x00c7, "\x00\x43\x03\x27\0" },
- { 0x00c8, "\x00\x45\x03\x00\0" },
- { 0x00c9, "\x00\x45\x03\x01\0" },
- { 0x00ca, "\x00\x45\x03\x02\0" },
- { 0x00cb, "\x00\x45\x03\x08\0" },
- { 0x00cc, "\x00\x49\x03\x00\0" },
- { 0x00cd, "\x00\x49\x03\x01\0" },
- { 0x00ce, "\x00\x49\x03\x02\0" },
- { 0x00cf, "\x00\x49\x03\x08\0" },
- { 0x00d1, "\x00\x4e\x03\x03\0" },
- { 0x00d2, "\x00\x4f\x03\x00\0" },
- { 0x00d3, "\x00\x4f\x03\x01\0" },
- { 0x00d4, "\x00\x4f\x03\x02\0" },
- { 0x00d5, "\x00\x4f\x03\x03\0" },
- { 0x00d6, "\x00\x4f\x03\x08\0" },
- { 0x00d9, "\x00\x55\x03\x00\0" },
- { 0x00da, "\x00\x55\x03\x01\0" },
- { 0x00db, "\x00\x55\x03\x02\0" },
- { 0x00dc, "\x00\x55\x03\x08\0" },
- { 0x00dd, "\x00\x59\x03\x01\0" },
- { 0x00e0, "\x00\x61\x03\x00\0" },
- { 0x00e1, "\x00\x61\x03\x01\0" },
- { 0x00e2, "\x00\x61\x03\x02\0" },
- { 0x00e3, "\x00\x61\x03\x03\0" },
- { 0x00e4, "\x00\x61\x03\x08\0" },
- { 0x00e5, "\x00\x61\x03\x0a\0" },
- { 0x00e7, "\x00\x63\x03\x27\0" },
- { 0x00e8, "\x00\x65\x03\x00\0" },
- { 0x00e9, "\x00\x65\x03\x01\0" },
- { 0x00ea, "\x00\x65\x03\x02\0" },
- { 0x00eb, "\x00\x65\x03\x08\0" },
- { 0x00ec, "\x00\x69\x03\x00\0" },
- { 0x00ed, "\x00\x69\x03\x01\0" },
- { 0x00ee, "\x00\x69\x03\x02\0" },
- { 0x00ef, "\x00\x69\x03\x08\0" },
- { 0x00f1, "\x00\x6e\x03\x03\0" },
- { 0x00f2, "\x00\x6f\x03\x00\0" },
- { 0x00f3, "\x00\x6f\x03\x01\0" },
- { 0x00f4, "\x00\x6f\x03\x02\0" },
- { 0x00f5, "\x00\x6f\x03\x03\0" },
- { 0x00f6, "\x00\x6f\x03\x08\0" },
- { 0x00f9, "\x00\x75\x03\x00\0" },
- { 0x00fa, "\x00\x75\x03\x01\0" },
- { 0x00fb, "\x00\x75\x03\x02\0" },
- { 0x00fc, "\x00\x75\x03\x08\0" },
- { 0x00fd, "\x00\x79\x03\x01\0" },
- { 0x00ff, "\x00\x79\x03\x08\0" },
- { 0x0100, "\x00\x41\x03\x04\0" },
- { 0x0101, "\x00\x61\x03\x04\0" },
- { 0x0102, "\x00\x41\x03\x06\0" },
- { 0x0103, "\x00\x61\x03\x06\0" },
- { 0x0104, "\x00\x41\x03\x28\0" },
- { 0x0105, "\x00\x61\x03\x28\0" },
- { 0x0106, "\x00\x43\x03\x01\0" },
- { 0x0107, "\x00\x63\x03\x01\0" },
- { 0x0108, "\x00\x43\x03\x02\0" },
- { 0x0109, "\x00\x63\x03\x02\0" },
- { 0x010a, "\x00\x43\x03\x07\0" },
- { 0x010b, "\x00\x63\x03\x07\0" },
- { 0x010c, "\x00\x43\x03\x0c\0" },
- { 0x010d, "\x00\x63\x03\x0c\0" },
- { 0x010e, "\x00\x44\x03\x0c\0" },
- { 0x010f, "\x00\x64\x03\x0c\0" },
- { 0x0112, "\x00\x45\x03\x04\0" },
- { 0x0113, "\x00\x65\x03\x04\0" },
- { 0x0114, "\x00\x45\x03\x06\0" },
- { 0x0115, "\x00\x65\x03\x06\0" },
- { 0x0116, "\x00\x45\x03\x07\0" },
- { 0x0117, "\x00\x65\x03\x07\0" },
- { 0x0118, "\x00\x45\x03\x28\0" },
- { 0x0119, "\x00\x65\x03\x28\0" },
- { 0x011a, "\x00\x45\x03\x0c\0" },
- { 0x011b, "\x00\x65\x03\x0c\0" },
- { 0x011c, "\x00\x47\x03\x02\0" },
- { 0x011d, "\x00\x67\x03\x02\0" },
- { 0x011e, "\x00\x47\x03\x06\0" },
- { 0x011f, "\x00\x67\x03\x06\0" },
- { 0x0120, "\x00\x47\x03\x07\0" },
- { 0x0121, "\x00\x67\x03\x07\0" },
- { 0x0122, "\x00\x47\x03\x27\0" },
- { 0x0123, "\x00\x67\x03\x27\0" },
- { 0x0124, "\x00\x48\x03\x02\0" },
- { 0x0125, "\x00\x68\x03\x02\0" },
- { 0x0128, "\x00\x49\x03\x03\0" },
- { 0x0129, "\x00\x69\x03\x03\0" },
- { 0x012a, "\x00\x49\x03\x04\0" },
- { 0x012b, "\x00\x69\x03\x04\0" },
- { 0x012c, "\x00\x49\x03\x06\0" },
- { 0x012d, "\x00\x69\x03\x06\0" },
- { 0x012e, "\x00\x49\x03\x28\0" },
- { 0x012f, "\x00\x69\x03\x28\0" },
- { 0x0130, "\x00\x49\x03\x07\0" },
- { 0x0134, "\x00\x4a\x03\x02\0" },
- { 0x0135, "\x00\x6a\x03\x02\0" },
- { 0x0136, "\x00\x4b\x03\x27\0" },
- { 0x0137, "\x00\x6b\x03\x27\0" },
- { 0x0139, "\x00\x4c\x03\x01\0" },
- { 0x013a, "\x00\x6c\x03\x01\0" },
- { 0x013b, "\x00\x4c\x03\x27\0" },
- { 0x013c, "\x00\x6c\x03\x27\0" },
- { 0x013d, "\x00\x4c\x03\x0c\0" },
- { 0x013e, "\x00\x6c\x03\x0c\0" },
- { 0x0143, "\x00\x4e\x03\x01\0" },
- { 0x0144, "\x00\x6e\x03\x01\0" },
- { 0x0145, "\x00\x4e\x03\x27\0" },
- { 0x0146, "\x00\x6e\x03\x27\0" },
- { 0x0147, "\x00\x4e\x03\x0c\0" },
- { 0x0148, "\x00\x6e\x03\x0c\0" },
- { 0x014c, "\x00\x4f\x03\x04\0" },
- { 0x014d, "\x00\x6f\x03\x04\0" },
- { 0x014e, "\x00\x4f\x03\x06\0" },
- { 0x014f, "\x00\x6f\x03\x06\0" },
- { 0x0150, "\x00\x4f\x03\x0b\0" },
- { 0x0151, "\x00\x6f\x03\x0b\0" },
- { 0x0154, "\x00\x52\x03\x01\0" },
- { 0x0155, "\x00\x72\x03\x01\0" },
- { 0x0156, "\x00\x52\x03\x27\0" },
- { 0x0157, "\x00\x72\x03\x27\0" },
- { 0x0158, "\x00\x52\x03\x0c\0" },
- { 0x0159, "\x00\x72\x03\x0c\0" },
- { 0x015a, "\x00\x53\x03\x01\0" },
- { 0x015b, "\x00\x73\x03\x01\0" },
- { 0x015c, "\x00\x53\x03\x02\0" },
- { 0x015d, "\x00\x73\x03\x02\0" },
- { 0x015e, "\x00\x53\x03\x27\0" },
- { 0x015f, "\x00\x73\x03\x27\0" },
- { 0x0160, "\x00\x53\x03\x0c\0" },
- { 0x0161, "\x00\x73\x03\x0c\0" },
- { 0x0162, "\x00\x54\x03\x27\0" },
- { 0x0163, "\x00\x74\x03\x27\0" },
- { 0x0164, "\x00\x54\x03\x0c\0" },
- { 0x0165, "\x00\x74\x03\x0c\0" },
- { 0x0168, "\x00\x55\x03\x03\0" },
- { 0x0169, "\x00\x75\x03\x03\0" },
- { 0x016a, "\x00\x55\x03\x04\0" },
- { 0x016b, "\x00\x75\x03\x04\0" },
- { 0x016c, "\x00\x55\x03\x06\0" },
- { 0x016d, "\x00\x75\x03\x06\0" },
- { 0x016e, "\x00\x55\x03\x0a\0" },
- { 0x016f, "\x00\x75\x03\x0a\0" },
- { 0x0170, "\x00\x55\x03\x0b\0" },
- { 0x0171, "\x00\x75\x03\x0b\0" },
- { 0x0172, "\x00\x55\x03\x28\0" },
- { 0x0173, "\x00\x75\x03\x28\0" },
- { 0x0174, "\x00\x57\x03\x02\0" },
- { 0x0175, "\x00\x77\x03\x02\0" },
- { 0x0176, "\x00\x59\x03\x02\0" },
- { 0x0177, "\x00\x79\x03\x02\0" },
- { 0x0178, "\x00\x59\x03\x08\0" },
- { 0x0179, "\x00\x5a\x03\x01\0" },
- { 0x017a, "\x00\x7a\x03\x01\0" },
- { 0x017b, "\x00\x5a\x03\x07\0" },
- { 0x017c, "\x00\x7a\x03\x07\0" },
- { 0x017d, "\x00\x5a\x03\x0c\0" },
- { 0x017e, "\x00\x7a\x03\x0c\0" },
- { 0x01a0, "\x00\x4f\x03\x1b\0" },
- { 0x01a1, "\x00\x6f\x03\x1b\0" },
- { 0x01af, "\x00\x55\x03\x1b\0" },
- { 0x01b0, "\x00\x75\x03\x1b\0" },
- { 0x01cd, "\x00\x41\x03\x0c\0" },
- { 0x01ce, "\x00\x61\x03\x0c\0" },
- { 0x01cf, "\x00\x49\x03\x0c\0" },
- { 0x01d0, "\x00\x69\x03\x0c\0" },
- { 0x01d1, "\x00\x4f\x03\x0c\0" },
- { 0x01d2, "\x00\x6f\x03\x0c\0" },
- { 0x01d3, "\x00\x55\x03\x0c\0" },
- { 0x01d4, "\x00\x75\x03\x0c\0" },
- { 0x01d5, "\x00\x55\x03\x08\x03\x04\0" },
- { 0x01d6, "\x00\x75\x03\x08\x03\x04\0" },
- { 0x01d7, "\x00\x55\x03\x08\x03\x01\0" },
- { 0x01d8, "\x00\x75\x03\x08\x03\x01\0" },
- { 0x01d9, "\x00\x55\x03\x08\x03\x0c\0" },
- { 0x01da, "\x00\x75\x03\x08\x03\x0c\0" },
- { 0x01db, "\x00\x55\x03\x08\x03\x00\0" },
- { 0x01dc, "\x00\x75\x03\x08\x03\x00\0" },
- { 0x01de, "\x00\x41\x03\x08\x03\x04\0" },
- { 0x01df, "\x00\x61\x03\x08\x03\x04\0" },
- { 0x01e0, "\x00\x41\x03\x07\x03\x04\0" },
- { 0x01e1, "\x00\x61\x03\x07\x03\x04\0" },
- { 0x01e2, "\x00\xc6\x03\x04\0" },
- { 0x01e3, "\x00\xe6\x03\x04\0" },
- { 0x01e6, "\x00\x47\x03\x0c\0" },
- { 0x01e7, "\x00\x67\x03\x0c\0" },
- { 0x01e8, "\x00\x4b\x03\x0c\0" },
- { 0x01e9, "\x00\x6b\x03\x0c\0" },
- { 0x01ea, "\x00\x4f\x03\x28\0" },
- { 0x01eb, "\x00\x6f\x03\x28\0" },
- { 0x01ec, "\x00\x4f\x03\x28\x03\x04\0" },
- { 0x01ed, "\x00\x6f\x03\x28\x03\x04\0" },
- { 0x01ee, "\x01\xb7\x03\x0c\0" },
- { 0x01ef, "\x02\x92\x03\x0c\0" },
- { 0x01f0, "\x00\x6a\x03\x0c\0" },
- { 0x01f4, "\x00\x47\x03\x01\0" },
- { 0x01f5, "\x00\x67\x03\x01\0" },
- { 0x01fa, "\x00\x41\x03\x0a\x03\x01\0" },
- { 0x01fb, "\x00\x61\x03\x0a\x03\x01\0" },
- { 0x01fc, "\x00\xc6\x03\x01\0" },
- { 0x01fd, "\x00\xe6\x03\x01\0" },
- { 0x01fe, "\x00\xd8\x03\x01\0" },
- { 0x01ff, "\x00\xf8\x03\x01\0" },
- { 0x0200, "\x00\x41\x03\x0f\0" },
- { 0x0201, "\x00\x61\x03\x0f\0" },
- { 0x0202, "\x00\x41\x03\x11\0" },
- { 0x0203, "\x00\x61\x03\x11\0" },
- { 0x0204, "\x00\x45\x03\x0f\0" },
- { 0x0205, "\x00\x65\x03\x0f\0" },
- { 0x0206, "\x00\x45\x03\x11\0" },
- { 0x0207, "\x00\x65\x03\x11\0" },
- { 0x0208, "\x00\x49\x03\x0f\0" },
- { 0x0209, "\x00\x69\x03\x0f\0" },
- { 0x020a, "\x00\x49\x03\x11\0" },
- { 0x020b, "\x00\x69\x03\x11\0" },
- { 0x020c, "\x00\x4f\x03\x0f\0" },
- { 0x020d, "\x00\x6f\x03\x0f\0" },
- { 0x020e, "\x00\x4f\x03\x11\0" },
- { 0x020f, "\x00\x6f\x03\x11\0" },
- { 0x0210, "\x00\x52\x03\x0f\0" },
- { 0x0211, "\x00\x72\x03\x0f\0" },
- { 0x0212, "\x00\x52\x03\x11\0" },
- { 0x0213, "\x00\x72\x03\x11\0" },
- { 0x0214, "\x00\x55\x03\x0f\0" },
- { 0x0215, "\x00\x75\x03\x0f\0" },
- { 0x0216, "\x00\x55\x03\x11\0" },
- { 0x0217, "\x00\x75\x03\x11\0" },
- { 0x0340, "\x03\x00\0" },
- { 0x0341, "\x03\x01\0" },
- { 0x0343, "\x03\x13\0" },
- { 0x0344, "\x03\x08\x03\x01\0" },
- { 0x0374, "\x02\xb9\0" },
- { 0x037e, "\x00\x3b\0" },
- { 0x0385, "\x00\xa8\x03\x01\0" },
- { 0x0386, "\x03\x91\x03\x01\0" },
- { 0x0387, "\x00\xb7\0" },
- { 0x0388, "\x03\x95\x03\x01\0" },
- { 0x0389, "\x03\x97\x03\x01\0" },
- { 0x038a, "\x03\x99\x03\x01\0" },
- { 0x038c, "\x03\x9f\x03\x01\0" },
- { 0x038e, "\x03\xa5\x03\x01\0" },
- { 0x038f, "\x03\xa9\x03\x01\0" },
- { 0x0390, "\x03\xb9\x03\x08\x03\x01\0" },
- { 0x03aa, "\x03\x99\x03\x08\0" },
- { 0x03ab, "\x03\xa5\x03\x08\0" },
- { 0x03ac, "\x03\xb1\x03\x01\0" },
- { 0x03ad, "\x03\xb5\x03\x01\0" },
- { 0x03ae, "\x03\xb7\x03\x01\0" },
- { 0x03af, "\x03\xb9\x03\x01\0" },
- { 0x03b0, "\x03\xc5\x03\x08\x03\x01\0" },
- { 0x03ca, "\x03\xb9\x03\x08\0" },
- { 0x03cb, "\x03\xc5\x03\x08\0" },
- { 0x03cc, "\x03\xbf\x03\x01\0" },
- { 0x03cd, "\x03\xc5\x03\x01\0" },
- { 0x03ce, "\x03\xc9\x03\x01\0" },
- { 0x03d3, "\x03\xd2\x03\x01\0" },
- { 0x03d4, "\x03\xd2\x03\x08\0" },
- { 0x0401, "\x04\x15\x03\x08\0" },
- { 0x0403, "\x04\x13\x03\x01\0" },
- { 0x0407, "\x04\x06\x03\x08\0" },
- { 0x040c, "\x04\x1a\x03\x01\0" },
- { 0x040e, "\x04\x23\x03\x06\0" },
- { 0x0419, "\x04\x18\x03\x06\0" },
- { 0x0439, "\x04\x38\x03\x06\0" },
- { 0x0451, "\x04\x35\x03\x08\0" },
- { 0x0453, "\x04\x33\x03\x01\0" },
- { 0x0457, "\x04\x56\x03\x08\0" },
- { 0x045c, "\x04\x3a\x03\x01\0" },
- { 0x045e, "\x04\x43\x03\x06\0" },
- { 0x0476, "\x04\x74\x03\x0f\0" },
- { 0x0477, "\x04\x75\x03\x0f\0" },
- { 0x04c1, "\x04\x16\x03\x06\0" },
- { 0x04c2, "\x04\x36\x03\x06\0" },
- { 0x04d0, "\x04\x10\x03\x06\0" },
- { 0x04d1, "\x04\x30\x03\x06\0" },
- { 0x04d2, "\x04\x10\x03\x08\0" },
- { 0x04d3, "\x04\x30\x03\x08\0" },
- { 0x04d6, "\x04\x15\x03\x06\0" },
- { 0x04d7, "\x04\x35\x03\x06\0" },
- { 0x04da, "\x04\xd8\x03\x08\0" },
- { 0x04db, "\x04\xd9\x03\x08\0" },
- { 0x04dc, "\x04\x16\x03\x08\0" },
- { 0x04dd, "\x04\x36\x03\x08\0" },
- { 0x04de, "\x04\x17\x03\x08\0" },
- { 0x04df, "\x04\x37\x03\x08\0" },
- { 0x04e2, "\x04\x18\x03\x04\0" },
- { 0x04e3, "\x04\x38\x03\x04\0" },
- { 0x04e4, "\x04\x18\x03\x08\0" },
- { 0x04e5, "\x04\x38\x03\x08\0" },
- { 0x04e6, "\x04\x1e\x03\x08\0" },
- { 0x04e7, "\x04\x3e\x03\x08\0" },
- { 0x04ea, "\x04\xe8\x03\x08\0" },
- { 0x04eb, "\x04\xe9\x03\x08\0" },
- { 0x04ee, "\x04\x23\x03\x04\0" },
- { 0x04ef, "\x04\x43\x03\x04\0" },
- { 0x04f0, "\x04\x23\x03\x08\0" },
- { 0x04f1, "\x04\x43\x03\x08\0" },
- { 0x04f2, "\x04\x23\x03\x0b\0" },
- { 0x04f3, "\x04\x43\x03\x0b\0" },
- { 0x04f4, "\x04\x27\x03\x08\0" },
- { 0x04f5, "\x04\x47\x03\x08\0" },
- { 0x04f8, "\x04\x2b\x03\x08\0" },
- { 0x04f9, "\x04\x4b\x03\x08\0" },
- { 0x0929, "\x09\x28\x09\x3c\0" },
- { 0x0931, "\x09\x30\x09\x3c\0" },
- { 0x0934, "\x09\x33\x09\x3c\0" },
- { 0x0958, "\x09\x15\x09\x3c\0" },
- { 0x0959, "\x09\x16\x09\x3c\0" },
- { 0x095a, "\x09\x17\x09\x3c\0" },
- { 0x095b, "\x09\x1c\x09\x3c\0" },
- { 0x095c, "\x09\x21\x09\x3c\0" },
- { 0x095d, "\x09\x22\x09\x3c\0" },
- { 0x095e, "\x09\x2b\x09\x3c\0" },
- { 0x095f, "\x09\x2f\x09\x3c\0" },
- { 0x09b0, "\x09\xac\x09\xbc\0" },
- { 0x09cb, "\x09\xc7\x09\xbe\0" },
- { 0x09cc, "\x09\xc7\x09\xd7\0" },
- { 0x09dc, "\x09\xa1\x09\xbc\0" },
- { 0x09dd, "\x09\xa2\x09\xbc\0" },
- { 0x09df, "\x09\xaf\x09\xbc\0" },
- { 0x0a59, "\x0a\x16\x0a\x3c\0" },
- { 0x0a5a, "\x0a\x17\x0a\x3c\0" },
- { 0x0a5b, "\x0a\x1c\x0a\x3c\0" },
- { 0x0a5c, "\x0a\x21\x0a\x3c\0" },
- { 0x0a5e, "\x0a\x2b\x0a\x3c\0" },
- { 0x0b48, "\x0b\x47\x0b\x56\0" },
- { 0x0b4b, "\x0b\x47\x0b\x3e\0" },
- { 0x0b4c, "\x0b\x47\x0b\x57\0" },
- { 0x0b5c, "\x0b\x21\x0b\x3c\0" },
- { 0x0b5d, "\x0b\x22\x0b\x3c\0" },
- { 0x0b5f, "\x0b\x2f\x0b\x3c\0" },
- { 0x0b94, "\x0b\x92\x0b\xd7\0" },
- { 0x0bca, "\x0b\xc6\x0b\xbe\0" },
- { 0x0bcb, "\x0b\xc7\x0b\xbe\0" },
- { 0x0bcc, "\x0b\xc6\x0b\xd7\0" },
- { 0x0c48, "\x0c\x46\x0c\x56\0" },
- { 0x0cc0, "\x0c\xbf\x0c\xd5\0" },
- { 0x0cc7, "\x0c\xc6\x0c\xd5\0" },
- { 0x0cc8, "\x0c\xc6\x0c\xd6\0" },
- { 0x0cca, "\x0c\xc6\x0c\xc2\0" },
- { 0x0ccb, "\x0c\xc6\x0c\xc2\x0c\xd5\0" },
- { 0x0d4a, "\x0d\x46\x0d\x3e\0" },
- { 0x0d4b, "\x0d\x47\x0d\x3e\0" },
- { 0x0d4c, "\x0d\x46\x0d\x57\0" },
- { 0x0e33, "\x0e\x4d\x0e\x32\0" },
- { 0x0eb3, "\x0e\xcd\x0e\xb2\0" },
- { 0x0f43, "\x0f\x42\x0f\xb7\0" },
- { 0x0f4d, "\x0f\x4c\x0f\xb7\0" },
- { 0x0f52, "\x0f\x51\x0f\xb7\0" },
- { 0x0f57, "\x0f\x56\x0f\xb7\0" },
- { 0x0f5c, "\x0f\x5b\x0f\xb7\0" },
- { 0x0f69, "\x0f\x40\x0f\xb5\0" },
- { 0x0f73, "\x0f\x71\x0f\x72\0" },
- { 0x0f75, "\x0f\x71\x0f\x74\0" },
- { 0x0f76, "\x0f\xb2\x0f\x80\0" },
- { 0x0f78, "\x0f\xb3\x0f\x80\0" },
- { 0x0f81, "\x0f\x71\x0f\x80\0" },
- { 0x0f93, "\x0f\x92\x0f\xb7\0" },
- { 0x0f9d, "\x0f\x9c\x0f\xb7\0" },
- { 0x0fa2, "\x0f\xa1\x0f\xb7\0" },
- { 0x0fa7, "\x0f\xa6\x0f\xb7\0" },
- { 0x0fac, "\x0f\xab\x0f\xb7\0" },
- { 0x0fb9, "\x0f\x90\x0f\xb5\0" },
- { 0x1e00, "\x00\x41\x03\x25\0" },
- { 0x1e01, "\x00\x61\x03\x25\0" },
- { 0x1e02, "\x00\x42\x03\x07\0" },
- { 0x1e03, "\x00\x62\x03\x07\0" },
- { 0x1e04, "\x00\x42\x03\x23\0" },
- { 0x1e05, "\x00\x62\x03\x23\0" },
- { 0x1e06, "\x00\x42\x03\x31\0" },
- { 0x1e07, "\x00\x62\x03\x31\0" },
- { 0x1e08, "\x00\x43\x03\x27\x03\x01\0" },
- { 0x1e09, "\x00\x63\x03\x27\x03\x01\0" },
- { 0x1e0a, "\x00\x44\x03\x07\0" },
- { 0x1e0b, "\x00\x64\x03\x07\0" },
- { 0x1e0c, "\x00\x44\x03\x23\0" },
- { 0x1e0d, "\x00\x64\x03\x23\0" },
- { 0x1e0e, "\x00\x44\x03\x31\0" },
- { 0x1e0f, "\x00\x64\x03\x31\0" },
- { 0x1e10, "\x00\x44\x03\x27\0" },
- { 0x1e11, "\x00\x64\x03\x27\0" },
- { 0x1e12, "\x00\x44\x03\x2d\0" },
- { 0x1e13, "\x00\x64\x03\x2d\0" },
- { 0x1e14, "\x00\x45\x03\x04\x03\x00\0" },
- { 0x1e15, "\x00\x65\x03\x04\x03\x00\0" },
- { 0x1e16, "\x00\x45\x03\x04\x03\x01\0" },
- { 0x1e17, "\x00\x65\x03\x04\x03\x01\0" },
- { 0x1e18, "\x00\x45\x03\x2d\0" },
- { 0x1e19, "\x00\x65\x03\x2d\0" },
- { 0x1e1a, "\x00\x45\x03\x30\0" },
- { 0x1e1b, "\x00\x65\x03\x30\0" },
- { 0x1e1c, "\x00\x45\x03\x27\x03\x06\0" },
- { 0x1e1d, "\x00\x65\x03\x27\x03\x06\0" },
- { 0x1e1e, "\x00\x46\x03\x07\0" },
- { 0x1e1f, "\x00\x66\x03\x07\0" },
- { 0x1e20, "\x00\x47\x03\x04\0" },
- { 0x1e21, "\x00\x67\x03\x04\0" },
- { 0x1e22, "\x00\x48\x03\x07\0" },
- { 0x1e23, "\x00\x68\x03\x07\0" },
- { 0x1e24, "\x00\x48\x03\x23\0" },
- { 0x1e25, "\x00\x68\x03\x23\0" },
- { 0x1e26, "\x00\x48\x03\x08\0" },
- { 0x1e27, "\x00\x68\x03\x08\0" },
- { 0x1e28, "\x00\x48\x03\x27\0" },
- { 0x1e29, "\x00\x68\x03\x27\0" },
- { 0x1e2a, "\x00\x48\x03\x2e\0" },
- { 0x1e2b, "\x00\x68\x03\x2e\0" },
- { 0x1e2c, "\x00\x49\x03\x30\0" },
- { 0x1e2d, "\x00\x69\x03\x30\0" },
- { 0x1e2e, "\x00\x49\x03\x08\x03\x01\0" },
- { 0x1e2f, "\x00\x69\x03\x08\x03\x01\0" },
- { 0x1e30, "\x00\x4b\x03\x01\0" },
- { 0x1e31, "\x00\x6b\x03\x01\0" },
- { 0x1e32, "\x00\x4b\x03\x23\0" },
- { 0x1e33, "\x00\x6b\x03\x23\0" },
- { 0x1e34, "\x00\x4b\x03\x31\0" },
- { 0x1e35, "\x00\x6b\x03\x31\0" },
- { 0x1e36, "\x00\x4c\x03\x23\0" },
- { 0x1e37, "\x00\x6c\x03\x23\0" },
- { 0x1e38, "\x00\x4c\x03\x23\x03\x04\0" },
- { 0x1e39, "\x00\x6c\x03\x23\x03\x04\0" },
- { 0x1e3a, "\x00\x4c\x03\x31\0" },
- { 0x1e3b, "\x00\x6c\x03\x31\0" },
- { 0x1e3c, "\x00\x4c\x03\x2d\0" },
- { 0x1e3d, "\x00\x6c\x03\x2d\0" },
- { 0x1e3e, "\x00\x4d\x03\x01\0" },
- { 0x1e3f, "\x00\x6d\x03\x01\0" },
- { 0x1e40, "\x00\x4d\x03\x07\0" },
- { 0x1e41, "\x00\x6d\x03\x07\0" },
- { 0x1e42, "\x00\x4d\x03\x23\0" },
- { 0x1e43, "\x00\x6d\x03\x23\0" },
- { 0x1e44, "\x00\x4e\x03\x07\0" },
- { 0x1e45, "\x00\x6e\x03\x07\0" },
- { 0x1e46, "\x00\x4e\x03\x23\0" },
- { 0x1e47, "\x00\x6e\x03\x23\0" },
- { 0x1e48, "\x00\x4e\x03\x31\0" },
- { 0x1e49, "\x00\x6e\x03\x31\0" },
- { 0x1e4a, "\x00\x4e\x03\x2d\0" },
- { 0x1e4b, "\x00\x6e\x03\x2d\0" },
- { 0x1e4c, "\x00\x4f\x03\x03\x03\x01\0" },
- { 0x1e4d, "\x00\x6f\x03\x03\x03\x01\0" },
- { 0x1e4e, "\x00\x4f\x03\x03\x03\x08\0" },
- { 0x1e4f, "\x00\x6f\x03\x03\x03\x08\0" },
- { 0x1e50, "\x00\x4f\x03\x04\x03\x00\0" },
- { 0x1e51, "\x00\x6f\x03\x04\x03\x00\0" },
- { 0x1e52, "\x00\x4f\x03\x04\x03\x01\0" },
- { 0x1e53, "\x00\x6f\x03\x04\x03\x01\0" },
- { 0x1e54, "\x00\x50\x03\x01\0" },
- { 0x1e55, "\x00\x70\x03\x01\0" },
- { 0x1e56, "\x00\x50\x03\x07\0" },
- { 0x1e57, "\x00\x70\x03\x07\0" },
- { 0x1e58, "\x00\x52\x03\x07\0" },
- { 0x1e59, "\x00\x72\x03\x07\0" },
- { 0x1e5a, "\x00\x52\x03\x23\0" },
- { 0x1e5b, "\x00\x72\x03\x23\0" },
- { 0x1e5c, "\x00\x52\x03\x23\x03\x04\0" },
- { 0x1e5d, "\x00\x72\x03\x23\x03\x04\0" },
- { 0x1e5e, "\x00\x52\x03\x31\0" },
- { 0x1e5f, "\x00\x72\x03\x31\0" },
- { 0x1e60, "\x00\x53\x03\x07\0" },
- { 0x1e61, "\x00\x73\x03\x07\0" },
- { 0x1e62, "\x00\x53\x03\x23\0" },
- { 0x1e63, "\x00\x73\x03\x23\0" },
- { 0x1e64, "\x00\x53\x03\x01\x03\x07\0" },
- { 0x1e65, "\x00\x73\x03\x01\x03\x07\0" },
- { 0x1e66, "\x00\x53\x03\x0c\x03\x07\0" },
- { 0x1e67, "\x00\x73\x03\x0c\x03\x07\0" },
- { 0x1e68, "\x00\x53\x03\x23\x03\x07\0" },
- { 0x1e69, "\x00\x73\x03\x23\x03\x07\0" },
- { 0x1e6a, "\x00\x54\x03\x07\0" },
- { 0x1e6b, "\x00\x74\x03\x07\0" },
- { 0x1e6c, "\x00\x54\x03\x23\0" },
- { 0x1e6d, "\x00\x74\x03\x23\0" },
- { 0x1e6e, "\x00\x54\x03\x31\0" },
- { 0x1e6f, "\x00\x74\x03\x31\0" },
- { 0x1e70, "\x00\x54\x03\x2d\0" },
- { 0x1e71, "\x00\x74\x03\x2d\0" },
- { 0x1e72, "\x00\x55\x03\x24\0" },
- { 0x1e73, "\x00\x75\x03\x24\0" },
- { 0x1e74, "\x00\x55\x03\x30\0" },
- { 0x1e75, "\x00\x75\x03\x30\0" },
- { 0x1e76, "\x00\x55\x03\x2d\0" },
- { 0x1e77, "\x00\x75\x03\x2d\0" },
- { 0x1e78, "\x00\x55\x03\x03\x03\x01\0" },
- { 0x1e79, "\x00\x75\x03\x03\x03\x01\0" },
- { 0x1e7a, "\x00\x55\x03\x04\x03\x08\0" },
- { 0x1e7b, "\x00\x75\x03\x04\x03\x08\0" },
- { 0x1e7c, "\x00\x56\x03\x03\0" },
- { 0x1e7d, "\x00\x76\x03\x03\0" },
- { 0x1e7e, "\x00\x56\x03\x23\0" },
- { 0x1e7f, "\x00\x76\x03\x23\0" },
- { 0x1e80, "\x00\x57\x03\x00\0" },
- { 0x1e81, "\x00\x77\x03\x00\0" },
- { 0x1e82, "\x00\x57\x03\x01\0" },
- { 0x1e83, "\x00\x77\x03\x01\0" },
- { 0x1e84, "\x00\x57\x03\x08\0" },
- { 0x1e85, "\x00\x77\x03\x08\0" },
- { 0x1e86, "\x00\x57\x03\x07\0" },
- { 0x1e87, "\x00\x77\x03\x07\0" },
- { 0x1e88, "\x00\x57\x03\x23\0" },
- { 0x1e89, "\x00\x77\x03\x23\0" },
- { 0x1e8a, "\x00\x58\x03\x07\0" },
- { 0x1e8b, "\x00\x78\x03\x07\0" },
- { 0x1e8c, "\x00\x58\x03\x08\0" },
- { 0x1e8d, "\x00\x78\x03\x08\0" },
- { 0x1e8e, "\x00\x59\x03\x07\0" },
- { 0x1e8f, "\x00\x79\x03\x07\0" },
- { 0x1e90, "\x00\x5a\x03\x02\0" },
- { 0x1e91, "\x00\x7a\x03\x02\0" },
- { 0x1e92, "\x00\x5a\x03\x23\0" },
- { 0x1e93, "\x00\x7a\x03\x23\0" },
- { 0x1e94, "\x00\x5a\x03\x31\0" },
- { 0x1e95, "\x00\x7a\x03\x31\0" },
- { 0x1e96, "\x00\x68\x03\x31\0" },
- { 0x1e97, "\x00\x74\x03\x08\0" },
- { 0x1e98, "\x00\x77\x03\x0a\0" },
- { 0x1e99, "\x00\x79\x03\x0a\0" },
- { 0x1e9b, "\x01\x7f\x03\x07\0" },
- { 0x1ea0, "\x00\x41\x03\x23\0" },
- { 0x1ea1, "\x00\x61\x03\x23\0" },
- { 0x1ea2, "\x00\x41\x03\x09\0" },
- { 0x1ea3, "\x00\x61\x03\x09\0" },
- { 0x1ea4, "\x00\x41\x03\x02\x03\x01\0" },
- { 0x1ea5, "\x00\x61\x03\x02\x03\x01\0" },
- { 0x1ea6, "\x00\x41\x03\x02\x03\x00\0" },
- { 0x1ea7, "\x00\x61\x03\x02\x03\x00\0" },
- { 0x1ea8, "\x00\x41\x03\x02\x03\x09\0" },
- { 0x1ea9, "\x00\x61\x03\x02\x03\x09\0" },
- { 0x1eaa, "\x00\x41\x03\x02\x03\x03\0" },
- { 0x1eab, "\x00\x61\x03\x02\x03\x03\0" },
- { 0x1eac, "\x00\x41\x03\x23\x03\x02\0" },
- { 0x1ead, "\x00\x61\x03\x23\x03\x02\0" },
- { 0x1eae, "\x00\x41\x03\x06\x03\x01\0" },
- { 0x1eaf, "\x00\x61\x03\x06\x03\x01\0" },
- { 0x1eb0, "\x00\x41\x03\x06\x03\x00\0" },
- { 0x1eb1, "\x00\x61\x03\x06\x03\x00\0" },
- { 0x1eb2, "\x00\x41\x03\x06\x03\x09\0" },
- { 0x1eb3, "\x00\x61\x03\x06\x03\x09\0" },
- { 0x1eb4, "\x00\x41\x03\x06\x03\x03\0" },
- { 0x1eb5, "\x00\x61\x03\x06\x03\x03\0" },
- { 0x1eb6, "\x00\x41\x03\x23\x03\x06\0" },
- { 0x1eb7, "\x00\x61\x03\x23\x03\x06\0" },
- { 0x1eb8, "\x00\x45\x03\x23\0" },
- { 0x1eb9, "\x00\x65\x03\x23\0" },
- { 0x1eba, "\x00\x45\x03\x09\0" },
- { 0x1ebb, "\x00\x65\x03\x09\0" },
- { 0x1ebc, "\x00\x45\x03\x03\0" },
- { 0x1ebd, "\x00\x65\x03\x03\0" },
- { 0x1ebe, "\x00\x45\x03\x02\x03\x01\0" },
- { 0x1ebf, "\x00\x65\x03\x02\x03\x01\0" },
- { 0x1ec0, "\x00\x45\x03\x02\x03\x00\0" },
- { 0x1ec1, "\x00\x65\x03\x02\x03\x00\0" },
- { 0x1ec2, "\x00\x45\x03\x02\x03\x09\0" },
- { 0x1ec3, "\x00\x65\x03\x02\x03\x09\0" },
- { 0x1ec4, "\x00\x45\x03\x02\x03\x03\0" },
- { 0x1ec5, "\x00\x65\x03\x02\x03\x03\0" },
- { 0x1ec6, "\x00\x45\x03\x23\x03\x02\0" },
- { 0x1ec7, "\x00\x65\x03\x23\x03\x02\0" },
- { 0x1ec8, "\x00\x49\x03\x09\0" },
- { 0x1ec9, "\x00\x69\x03\x09\0" },
- { 0x1eca, "\x00\x49\x03\x23\0" },
- { 0x1ecb, "\x00\x69\x03\x23\0" },
- { 0x1ecc, "\x00\x4f\x03\x23\0" },
- { 0x1ecd, "\x00\x6f\x03\x23\0" },
- { 0x1ece, "\x00\x4f\x03\x09\0" },
- { 0x1ecf, "\x00\x6f\x03\x09\0" },
- { 0x1ed0, "\x00\x4f\x03\x02\x03\x01\0" },
- { 0x1ed1, "\x00\x6f\x03\x02\x03\x01\0" },
- { 0x1ed2, "\x00\x4f\x03\x02\x03\x00\0" },
- { 0x1ed3, "\x00\x6f\x03\x02\x03\x00\0" },
- { 0x1ed4, "\x00\x4f\x03\x02\x03\x09\0" },
- { 0x1ed5, "\x00\x6f\x03\x02\x03\x09\0" },
- { 0x1ed6, "\x00\x4f\x03\x02\x03\x03\0" },
- { 0x1ed7, "\x00\x6f\x03\x02\x03\x03\0" },
- { 0x1ed8, "\x00\x4f\x03\x23\x03\x02\0" },
- { 0x1ed9, "\x00\x6f\x03\x23\x03\x02\0" },
- { 0x1eda, "\x00\x4f\x03\x1b\x03\x01\0" },
- { 0x1edb, "\x00\x6f\x03\x1b\x03\x01\0" },
- { 0x1edc, "\x00\x4f\x03\x1b\x03\x00\0" },
- { 0x1edd, "\x00\x6f\x03\x1b\x03\x00\0" },
- { 0x1ede, "\x00\x4f\x03\x1b\x03\x09\0" },
- { 0x1edf, "\x00\x6f\x03\x1b\x03\x09\0" },
- { 0x1ee0, "\x00\x4f\x03\x1b\x03\x03\0" },
- { 0x1ee1, "\x00\x6f\x03\x1b\x03\x03\0" },
- { 0x1ee2, "\x00\x4f\x03\x1b\x03\x23\0" },
- { 0x1ee3, "\x00\x6f\x03\x1b\x03\x23\0" },
- { 0x1ee4, "\x00\x55\x03\x23\0" },
- { 0x1ee5, "\x00\x75\x03\x23\0" },
- { 0x1ee6, "\x00\x55\x03\x09\0" },
- { 0x1ee7, "\x00\x75\x03\x09\0" },
- { 0x1ee8, "\x00\x55\x03\x1b\x03\x01\0" },
- { 0x1ee9, "\x00\x75\x03\x1b\x03\x01\0" },
- { 0x1eea, "\x00\x55\x03\x1b\x03\x00\0" },
- { 0x1eeb, "\x00\x75\x03\x1b\x03\x00\0" },
- { 0x1eec, "\x00\x55\x03\x1b\x03\x09\0" },
- { 0x1eed, "\x00\x75\x03\x1b\x03\x09\0" },
- { 0x1eee, "\x00\x55\x03\x1b\x03\x03\0" },
- { 0x1eef, "\x00\x75\x03\x1b\x03\x03\0" },
- { 0x1ef0, "\x00\x55\x03\x1b\x03\x23\0" },
- { 0x1ef1, "\x00\x75\x03\x1b\x03\x23\0" },
- { 0x1ef2, "\x00\x59\x03\x00\0" },
- { 0x1ef3, "\x00\x79\x03\x00\0" },
- { 0x1ef4, "\x00\x59\x03\x23\0" },
- { 0x1ef5, "\x00\x79\x03\x23\0" },
- { 0x1ef6, "\x00\x59\x03\x09\0" },
- { 0x1ef7, "\x00\x79\x03\x09\0" },
- { 0x1ef8, "\x00\x59\x03\x03\0" },
- { 0x1ef9, "\x00\x79\x03\x03\0" },
- { 0x1f00, "\x03\xb1\x03\x13\0" },
- { 0x1f01, "\x03\xb1\x03\x14\0" },
- { 0x1f02, "\x03\xb1\x03\x13\x03\x00\0" },
- { 0x1f03, "\x03\xb1\x03\x14\x03\x00\0" },
- { 0x1f04, "\x03\xb1\x03\x13\x03\x01\0" },
- { 0x1f05, "\x03\xb1\x03\x14\x03\x01\0" },
- { 0x1f06, "\x03\xb1\x03\x13\x03\x42\0" },
- { 0x1f07, "\x03\xb1\x03\x14\x03\x42\0" },
- { 0x1f08, "\x03\x91\x03\x13\0" },
- { 0x1f09, "\x03\x91\x03\x14\0" },
- { 0x1f0a, "\x03\x91\x03\x13\x03\x00\0" },
- { 0x1f0b, "\x03\x91\x03\x14\x03\x00\0" },
- { 0x1f0c, "\x03\x91\x03\x13\x03\x01\0" },
- { 0x1f0d, "\x03\x91\x03\x14\x03\x01\0" },
- { 0x1f0e, "\x03\x91\x03\x13\x03\x42\0" },
- { 0x1f0f, "\x03\x91\x03\x14\x03\x42\0" },
- { 0x1f10, "\x03\xb5\x03\x13\0" },
- { 0x1f11, "\x03\xb5\x03\x14\0" },
- { 0x1f12, "\x03\xb5\x03\x13\x03\x00\0" },
- { 0x1f13, "\x03\xb5\x03\x14\x03\x00\0" },
- { 0x1f14, "\x03\xb5\x03\x13\x03\x01\0" },
- { 0x1f15, "\x03\xb5\x03\x14\x03\x01\0" },
- { 0x1f18, "\x03\x95\x03\x13\0" },
- { 0x1f19, "\x03\x95\x03\x14\0" },
- { 0x1f1a, "\x03\x95\x03\x13\x03\x00\0" },
- { 0x1f1b, "\x03\x95\x03\x14\x03\x00\0" },
- { 0x1f1c, "\x03\x95\x03\x13\x03\x01\0" },
- { 0x1f1d, "\x03\x95\x03\x14\x03\x01\0" },
- { 0x1f20, "\x03\xb7\x03\x13\0" },
- { 0x1f21, "\x03\xb7\x03\x14\0" },
- { 0x1f22, "\x03\xb7\x03\x13\x03\x00\0" },
- { 0x1f23, "\x03\xb7\x03\x14\x03\x00\0" },
- { 0x1f24, "\x03\xb7\x03\x13\x03\x01\0" },
- { 0x1f25, "\x03\xb7\x03\x14\x03\x01\0" },
- { 0x1f26, "\x03\xb7\x03\x13\x03\x42\0" },
- { 0x1f27, "\x03\xb7\x03\x14\x03\x42\0" },
- { 0x1f28, "\x03\x97\x03\x13\0" },
- { 0x1f29, "\x03\x97\x03\x14\0" },
- { 0x1f2a, "\x03\x97\x03\x13\x03\x00\0" },
- { 0x1f2b, "\x03\x97\x03\x14\x03\x00\0" },
- { 0x1f2c, "\x03\x97\x03\x13\x03\x01\0" },
- { 0x1f2d, "\x03\x97\x03\x14\x03\x01\0" },
- { 0x1f2e, "\x03\x97\x03\x13\x03\x42\0" },
- { 0x1f2f, "\x03\x97\x03\x14\x03\x42\0" },
- { 0x1f30, "\x03\xb9\x03\x13\0" },
- { 0x1f31, "\x03\xb9\x03\x14\0" },
- { 0x1f32, "\x03\xb9\x03\x13\x03\x00\0" },
- { 0x1f33, "\x03\xb9\x03\x14\x03\x00\0" },
- { 0x1f34, "\x03\xb9\x03\x13\x03\x01\0" },
- { 0x1f35, "\x03\xb9\x03\x14\x03\x01\0" },
- { 0x1f36, "\x03\xb9\x03\x13\x03\x42\0" },
- { 0x1f37, "\x03\xb9\x03\x14\x03\x42\0" },
- { 0x1f38, "\x03\x99\x03\x13\0" },
- { 0x1f39, "\x03\x99\x03\x14\0" },
- { 0x1f3a, "\x03\x99\x03\x13\x03\x00\0" },
- { 0x1f3b, "\x03\x99\x03\x14\x03\x00\0" },
- { 0x1f3c, "\x03\x99\x03\x13\x03\x01\0" },
- { 0x1f3d, "\x03\x99\x03\x14\x03\x01\0" },
- { 0x1f3e, "\x03\x99\x03\x13\x03\x42\0" },
- { 0x1f3f, "\x03\x99\x03\x14\x03\x42\0" },
- { 0x1f40, "\x03\xbf\x03\x13\0" },
- { 0x1f41, "\x03\xbf\x03\x14\0" },
- { 0x1f42, "\x03\xbf\x03\x13\x03\x00\0" },
- { 0x1f43, "\x03\xbf\x03\x14\x03\x00\0" },
- { 0x1f44, "\x03\xbf\x03\x13\x03\x01\0" },
- { 0x1f45, "\x03\xbf\x03\x14\x03\x01\0" },
- { 0x1f48, "\x03\x9f\x03\x13\0" },
- { 0x1f49, "\x03\x9f\x03\x14\0" },
- { 0x1f4a, "\x03\x9f\x03\x13\x03\x00\0" },
- { 0x1f4b, "\x03\x9f\x03\x14\x03\x00\0" },
- { 0x1f4c, "\x03\x9f\x03\x13\x03\x01\0" },
- { 0x1f4d, "\x03\x9f\x03\x14\x03\x01\0" },
- { 0x1f50, "\x03\xc5\x03\x13\0" },
- { 0x1f51, "\x03\xc5\x03\x14\0" },
- { 0x1f52, "\x03\xc5\x03\x13\x03\x00\0" },
- { 0x1f53, "\x03\xc5\x03\x14\x03\x00\0" },
- { 0x1f54, "\x03\xc5\x03\x13\x03\x01\0" },
- { 0x1f55, "\x03\xc5\x03\x14\x03\x01\0" },
- { 0x1f56, "\x03\xc5\x03\x13\x03\x42\0" },
- { 0x1f57, "\x03\xc5\x03\x14\x03\x42\0" },
- { 0x1f59, "\x03\xa5\x03\x14\0" },
- { 0x1f5b, "\x03\xa5\x03\x14\x03\x00\0" },
- { 0x1f5d, "\x03\xa5\x03\x14\x03\x01\0" },
- { 0x1f5f, "\x03\xa5\x03\x14\x03\x42\0" },
- { 0x1f60, "\x03\xc9\x03\x13\0" },
- { 0x1f61, "\x03\xc9\x03\x14\0" },
- { 0x1f62, "\x03\xc9\x03\x13\x03\x00\0" },
- { 0x1f63, "\x03\xc9\x03\x14\x03\x00\0" },
- { 0x1f64, "\x03\xc9\x03\x13\x03\x01\0" },
- { 0x1f65, "\x03\xc9\x03\x14\x03\x01\0" },
- { 0x1f66, "\x03\xc9\x03\x13\x03\x42\0" },
- { 0x1f67, "\x03\xc9\x03\x14\x03\x42\0" },
- { 0x1f68, "\x03\xa9\x03\x13\0" },
- { 0x1f69, "\x03\xa9\x03\x14\0" },
- { 0x1f6a, "\x03\xa9\x03\x13\x03\x00\0" },
- { 0x1f6b, "\x03\xa9\x03\x14\x03\x00\0" },
- { 0x1f6c, "\x03\xa9\x03\x13\x03\x01\0" },
- { 0x1f6d, "\x03\xa9\x03\x14\x03\x01\0" },
- { 0x1f6e, "\x03\xa9\x03\x13\x03\x42\0" },
- { 0x1f6f, "\x03\xa9\x03\x14\x03\x42\0" },
- { 0x1f70, "\x03\xb1\x03\x00\0" },
- { 0x1f71, "\x03\xb1\x03\x01\0" },
- { 0x1f72, "\x03\xb5\x03\x00\0" },
- { 0x1f73, "\x03\xb5\x03\x01\0" },
- { 0x1f74, "\x03\xb7\x03\x00\0" },
- { 0x1f75, "\x03\xb7\x03\x01\0" },
- { 0x1f76, "\x03\xb9\x03\x00\0" },
- { 0x1f77, "\x03\xb9\x03\x01\0" },
- { 0x1f78, "\x03\xbf\x03\x00\0" },
- { 0x1f79, "\x03\xbf\x03\x01\0" },
- { 0x1f7a, "\x03\xc5\x03\x00\0" },
- { 0x1f7b, "\x03\xc5\x03\x01\0" },
- { 0x1f7c, "\x03\xc9\x03\x00\0" },
- { 0x1f7d, "\x03\xc9\x03\x01\0" },
- { 0x1f80, "\x03\xb1\x03\x13\x03\x45\0" },
- { 0x1f81, "\x03\xb1\x03\x14\x03\x45\0" },
- { 0x1f82, "\x03\xb1\x03\x13\x03\x00\x03\x45\0" },
- { 0x1f83, "\x03\xb1\x03\x14\x03\x00\x03\x45\0" },
- { 0x1f84, "\x03\xb1\x03\x13\x03\x01\x03\x45\0" },
- { 0x1f85, "\x03\xb1\x03\x14\x03\x01\x03\x45\0" },
- { 0x1f86, "\x03\xb1\x03\x13\x03\x42\x03\x45\0" },
- { 0x1f87, "\x03\xb1\x03\x14\x03\x42\x03\x45\0" },
- { 0x1f88, "\x03\x91\x03\x13\x03\x45\0" },
- { 0x1f89, "\x03\x91\x03\x14\x03\x45\0" },
- { 0x1f8a, "\x03\x91\x03\x13\x03\x00\x03\x45\0" },
- { 0x1f8b, "\x03\x91\x03\x14\x03\x00\x03\x45\0" },
- { 0x1f8c, "\x03\x91\x03\x13\x03\x01\x03\x45\0" },
- { 0x1f8d, "\x03\x91\x03\x14\x03\x01\x03\x45\0" },
- { 0x1f8e, "\x03\x91\x03\x13\x03\x42\x03\x45\0" },
- { 0x1f8f, "\x03\x91\x03\x14\x03\x42\x03\x45\0" },
- { 0x1f90, "\x03\xb7\x03\x13\x03\x45\0" },
- { 0x1f91, "\x03\xb7\x03\x14\x03\x45\0" },
- { 0x1f92, "\x03\xb7\x03\x13\x03\x00\x03\x45\0" },
- { 0x1f93, "\x03\xb7\x03\x14\x03\x00\x03\x45\0" },
- { 0x1f94, "\x03\xb7\x03\x13\x03\x01\x03\x45\0" },
- { 0x1f95, "\x03\xb7\x03\x14\x03\x01\x03\x45\0" },
- { 0x1f96, "\x03\xb7\x03\x13\x03\x42\x03\x45\0" },
- { 0x1f97, "\x03\xb7\x03\x14\x03\x42\x03\x45\0" },
- { 0x1f98, "\x03\x97\x03\x13\x03\x45\0" },
- { 0x1f99, "\x03\x97\x03\x14\x03\x45\0" },
- { 0x1f9a, "\x03\x97\x03\x13\x03\x00\x03\x45\0" },
- { 0x1f9b, "\x03\x97\x03\x14\x03\x00\x03\x45\0" },
- { 0x1f9c, "\x03\x97\x03\x13\x03\x01\x03\x45\0" },
- { 0x1f9d, "\x03\x97\x03\x14\x03\x01\x03\x45\0" },
- { 0x1f9e, "\x03\x97\x03\x13\x03\x42\x03\x45\0" },
- { 0x1f9f, "\x03\x97\x03\x14\x03\x42\x03\x45\0" },
- { 0x1fa0, "\x03\xc9\x03\x13\x03\x45\0" },
- { 0x1fa1, "\x03\xc9\x03\x14\x03\x45\0" },
- { 0x1fa2, "\x03\xc9\x03\x13\x03\x00\x03\x45\0" },
- { 0x1fa3, "\x03\xc9\x03\x14\x03\x00\x03\x45\0" },
- { 0x1fa4, "\x03\xc9\x03\x13\x03\x01\x03\x45\0" },
- { 0x1fa5, "\x03\xc9\x03\x14\x03\x01\x03\x45\0" },
- { 0x1fa6, "\x03\xc9\x03\x13\x03\x42\x03\x45\0" },
- { 0x1fa7, "\x03\xc9\x03\x14\x03\x42\x03\x45\0" },
- { 0x1fa8, "\x03\xa9\x03\x13\x03\x45\0" },
- { 0x1fa9, "\x03\xa9\x03\x14\x03\x45\0" },
- { 0x1faa, "\x03\xa9\x03\x13\x03\x00\x03\x45\0" },
- { 0x1fab, "\x03\xa9\x03\x14\x03\x00\x03\x45\0" },
- { 0x1fac, "\x03\xa9\x03\x13\x03\x01\x03\x45\0" },
- { 0x1fad, "\x03\xa9\x03\x14\x03\x01\x03\x45\0" },
- { 0x1fae, "\x03\xa9\x03\x13\x03\x42\x03\x45\0" },
- { 0x1faf, "\x03\xa9\x03\x14\x03\x42\x03\x45\0" },
- { 0x1fb0, "\x03\xb1\x03\x06\0" },
- { 0x1fb1, "\x03\xb1\x03\x04\0" },
- { 0x1fb2, "\x03\xb1\x03\x00\x03\x45\0" },
- { 0x1fb3, "\x03\xb1\x03\x45\0" },
- { 0x1fb4, "\x03\xb1\x03\x01\x03\x45\0" },
- { 0x1fb6, "\x03\xb1\x03\x42\0" },
- { 0x1fb7, "\x03\xb1\x03\x42\x03\x45\0" },
- { 0x1fb8, "\x03\x91\x03\x06\0" },
- { 0x1fb9, "\x03\x91\x03\x04\0" },
- { 0x1fba, "\x03\x91\x03\x00\0" },
- { 0x1fbb, "\x03\x91\x03\x01\0" },
- { 0x1fbc, "\x03\x91\x03\x45\0" },
- { 0x1fbe, "\x03\xb9\0" },
- { 0x1fc1, "\x00\xa8\x03\x42\0" },
- { 0x1fc2, "\x03\xb7\x03\x00\x03\x45\0" },
- { 0x1fc3, "\x03\xb7\x03\x45\0" },
- { 0x1fc4, "\x03\xb7\x03\x01\x03\x45\0" },
- { 0x1fc6, "\x03\xb7\x03\x42\0" },
- { 0x1fc7, "\x03\xb7\x03\x42\x03\x45\0" },
- { 0x1fc8, "\x03\x95\x03\x00\0" },
- { 0x1fc9, "\x03\x95\x03\x01\0" },
- { 0x1fca, "\x03\x97\x03\x00\0" },
- { 0x1fcb, "\x03\x97\x03\x01\0" },
- { 0x1fcc, "\x03\x97\x03\x45\0" },
- { 0x1fcd, "\x1f\xbf\x03\x00\0" },
- { 0x1fce, "\x1f\xbf\x03\x01\0" },
- { 0x1fcf, "\x1f\xbf\x03\x42\0" },
- { 0x1fd0, "\x03\xb9\x03\x06\0" },
- { 0x1fd1, "\x03\xb9\x03\x04\0" },
- { 0x1fd2, "\x03\xb9\x03\x08\x03\x00\0" },
- { 0x1fd3, "\x03\xb9\x03\x08\x03\x01\0" },
- { 0x1fd6, "\x03\xb9\x03\x42\0" },
- { 0x1fd7, "\x03\xb9\x03\x08\x03\x42\0" },
- { 0x1fd8, "\x03\x99\x03\x06\0" },
- { 0x1fd9, "\x03\x99\x03\x04\0" },
- { 0x1fda, "\x03\x99\x03\x00\0" },
- { 0x1fdb, "\x03\x99\x03\x01\0" },
- { 0x1fdd, "\x1f\xfe\x03\x00\0" },
- { 0x1fde, "\x1f\xfe\x03\x01\0" },
- { 0x1fdf, "\x1f\xfe\x03\x42\0" },
- { 0x1fe0, "\x03\xc5\x03\x06\0" },
- { 0x1fe1, "\x03\xc5\x03\x04\0" },
- { 0x1fe2, "\x03\xc5\x03\x08\x03\x00\0" },
- { 0x1fe3, "\x03\xc5\x03\x08\x03\x01\0" },
- { 0x1fe4, "\x03\xc1\x03\x13\0" },
- { 0x1fe5, "\x03\xc1\x03\x14\0" },
- { 0x1fe6, "\x03\xc5\x03\x42\0" },
- { 0x1fe7, "\x03\xc5\x03\x08\x03\x42\0" },
- { 0x1fe8, "\x03\xa5\x03\x06\0" },
- { 0x1fe9, "\x03\xa5\x03\x04\0" },
- { 0x1fea, "\x03\xa5\x03\x00\0" },
- { 0x1feb, "\x03\xa5\x03\x01\0" },
- { 0x1fec, "\x03\xa1\x03\x14\0" },
- { 0x1fed, "\x00\xa8\x03\x00\0" },
- { 0x1fee, "\x00\xa8\x03\x01\0" },
- { 0x1fef, "\x00\x60\0" },
- { 0x1ff2, "\x03\xc9\x03\x00\x03\x45\0" },
- { 0x1ff3, "\x03\xc9\x03\x45\0" },
- { 0x1ff4, "\x03\xc9\x03\x01\x03\x45\0" },
- { 0x1ff6, "\x03\xc9\x03\x42\0" },
- { 0x1ff7, "\x03\xc9\x03\x42\x03\x45\0" },
- { 0x1ff8, "\x03\x9f\x03\x00\0" },
- { 0x1ff9, "\x03\x9f\x03\x01\0" },
- { 0x1ffa, "\x03\xa9\x03\x00\0" },
- { 0x1ffb, "\x03\xa9\x03\x01\0" },
- { 0x1ffc, "\x03\xa9\x03\x45\0" },
- { 0x1ffd, "\x00\xb4\0" },
- { 0x2000, "\x20\x02\0" },
- { 0x2001, "\x20\x03\0" },
- { 0x2126, "\x03\xa9\0" },
- { 0x212a, "\x00\x4b\0" },
- { 0x212b, "\x00\x41\x03\x0a\0" },
- { 0x2204, "\x22\x03\x03\x38\0" },
- { 0x2209, "\x22\x08\x03\x38\0" },
- { 0x220c, "\x22\x0b\x03\x38\0" },
- { 0x2224, "\x22\x23\x03\x38\0" },
- { 0x2226, "\x22\x25\x03\x38\0" },
- { 0x2241, "\x00\x7e\x03\x38\0" },
- { 0x2244, "\x22\x43\x03\x38\0" },
- { 0x2247, "\x22\x45\x03\x38\0" },
- { 0x2249, "\x22\x48\x03\x38\0" },
- { 0x2260, "\x00\x3d\x03\x38\0" },
- { 0x2262, "\x22\x61\x03\x38\0" },
- { 0x226d, "\x22\x4d\x03\x38\0" },
- { 0x226e, "\x00\x3c\x03\x38\0" },
- { 0x226f, "\x00\x3e\x03\x38\0" },
- { 0x2270, "\x22\x64\x03\x38\0" },
- { 0x2271, "\x22\x65\x03\x38\0" },
- { 0x2274, "\x22\x72\x03\x38\0" },
- { 0x2275, "\x22\x73\x03\x38\0" },
- { 0x2278, "\x22\x76\x03\x38\0" },
- { 0x2279, "\x22\x77\x03\x38\0" },
- { 0x2280, "\x22\x7a\x03\x38\0" },
- { 0x2281, "\x22\x7b\x03\x38\0" },
- { 0x2284, "\x22\x82\x03\x38\0" },
- { 0x2285, "\x22\x83\x03\x38\0" },
- { 0x2288, "\x22\x86\x03\x38\0" },
- { 0x2289, "\x22\x87\x03\x38\0" },
- { 0x22ac, "\x22\xa2\x03\x38\0" },
- { 0x22ad, "\x22\xa8\x03\x38\0" },
- { 0x22ae, "\x22\xa9\x03\x38\0" },
- { 0x22af, "\x22\xab\x03\x38\0" },
- { 0x22e0, "\x22\x7c\x03\x38\0" },
- { 0x22e1, "\x22\x7d\x03\x38\0" },
- { 0x22e2, "\x22\x91\x03\x38\0" },
- { 0x22e3, "\x22\x92\x03\x38\0" },
- { 0x22ea, "\x22\xb2\x03\x38\0" },
- { 0x22eb, "\x22\xb3\x03\x38\0" },
- { 0x22ec, "\x22\xb4\x03\x38\0" },
- { 0x22ed, "\x22\xb5\x03\x38\0" },
- { 0x2329, "\x30\x08\0" },
- { 0x232a, "\x30\x09\0" },
- { 0x304c, "\x30\x4b\x30\x99\0" },
- { 0x304e, "\x30\x4d\x30\x99\0" },
- { 0x3050, "\x30\x4f\x30\x99\0" },
- { 0x3052, "\x30\x51\x30\x99\0" },
- { 0x3054, "\x30\x53\x30\x99\0" },
- { 0x3056, "\x30\x55\x30\x99\0" },
- { 0x3058, "\x30\x57\x30\x99\0" },
- { 0x305a, "\x30\x59\x30\x99\0" },
- { 0x305c, "\x30\x5b\x30\x99\0" },
- { 0x305e, "\x30\x5d\x30\x99\0" },
- { 0x3060, "\x30\x5f\x30\x99\0" },
- { 0x3062, "\x30\x61\x30\x99\0" },
- { 0x3065, "\x30\x64\x30\x99\0" },
- { 0x3067, "\x30\x66\x30\x99\0" },
- { 0x3069, "\x30\x68\x30\x99\0" },
- { 0x3070, "\x30\x6f\x30\x99\0" },
- { 0x3071, "\x30\x6f\x30\x9a\0" },
- { 0x3073, "\x30\x72\x30\x99\0" },
- { 0x3074, "\x30\x72\x30\x9a\0" },
- { 0x3076, "\x30\x75\x30\x99\0" },
- { 0x3077, "\x30\x75\x30\x9a\0" },
- { 0x3079, "\x30\x78\x30\x99\0" },
- { 0x307a, "\x30\x78\x30\x9a\0" },
- { 0x307c, "\x30\x7b\x30\x99\0" },
- { 0x307d, "\x30\x7b\x30\x9a\0" },
- { 0x3094, "\x30\x46\x30\x99\0" },
- { 0x309e, "\x30\x9d\x30\x99\0" },
- { 0x30ac, "\x30\xab\x30\x99\0" },
- { 0x30ae, "\x30\xad\x30\x99\0" },
- { 0x30b0, "\x30\xaf\x30\x99\0" },
- { 0x30b2, "\x30\xb1\x30\x99\0" },
- { 0x30b4, "\x30\xb3\x30\x99\0" },
- { 0x30b6, "\x30\xb5\x30\x99\0" },
- { 0x30b8, "\x30\xb7\x30\x99\0" },
- { 0x30ba, "\x30\xb9\x30\x99\0" },
- { 0x30bc, "\x30\xbb\x30\x99\0" },
- { 0x30be, "\x30\xbd\x30\x99\0" },
- { 0x30c0, "\x30\xbf\x30\x99\0" },
- { 0x30c2, "\x30\xc1\x30\x99\0" },
- { 0x30c5, "\x30\xc4\x30\x99\0" },
- { 0x30c7, "\x30\xc6\x30\x99\0" },
- { 0x30c9, "\x30\xc8\x30\x99\0" },
- { 0x30d0, "\x30\xcf\x30\x99\0" },
- { 0x30d1, "\x30\xcf\x30\x9a\0" },
- { 0x30d3, "\x30\xd2\x30\x99\0" },
- { 0x30d4, "\x30\xd2\x30\x9a\0" },
- { 0x30d6, "\x30\xd5\x30\x99\0" },
- { 0x30d7, "\x30\xd5\x30\x9a\0" },
- { 0x30d9, "\x30\xd8\x30\x99\0" },
- { 0x30da, "\x30\xd8\x30\x9a\0" },
- { 0x30dc, "\x30\xdb\x30\x99\0" },
- { 0x30dd, "\x30\xdb\x30\x9a\0" },
- { 0x30f4, "\x30\xa6\x30\x99\0" },
- { 0x30f7, "\x30\xef\x30\x99\0" },
- { 0x30f8, "\x30\xf0\x30\x99\0" },
- { 0x30f9, "\x30\xf1\x30\x99\0" },
- { 0x30fa, "\x30\xf2\x30\x99\0" },
- { 0x30fe, "\x30\xfd\x30\x99\0" },
- { 0xf900, "\x8c\x48\0" },
- { 0xf901, "\x66\xf4\0" },
- { 0xf902, "\x8e\xca\0" },
- { 0xf903, "\x8c\xc8\0" },
- { 0xf904, "\x6e\xd1\0" },
- { 0xf905, "\x4e\x32\0" },
- { 0xf906, "\x53\xe5\0" },
- { 0xf907, "\x9f\x9c\0" },
- { 0xf908, "\x9f\x9c\0" },
- { 0xf909, "\x59\x51\0" },
- { 0xf90a, "\x91\xd1\0" },
- { 0xf90b, "\x55\x87\0" },
- { 0xf90c, "\x59\x48\0" },
- { 0xf90d, "\x61\xf6\0" },
- { 0xf90e, "\x76\x69\0" },
- { 0xf90f, "\x7f\x85\0" },
- { 0xf910, "\x86\x3f\0" },
- { 0xf911, "\x87\xba\0" },
- { 0xf912, "\x88\xf8\0" },
- { 0xf913, "\x90\x8f\0" },
- { 0xf914, "\x6a\x02\0" },
- { 0xf915, "\x6d\x1b\0" },
- { 0xf916, "\x70\xd9\0" },
- { 0xf917, "\x73\xde\0" },
- { 0xf918, "\x84\x3d\0" },
- { 0xf919, "\x91\x6a\0" },
- { 0xf91a, "\x99\xf1\0" },
- { 0xf91b, "\x4e\x82\0" },
- { 0xf91c, "\x53\x75\0" },
- { 0xf91d, "\x6b\x04\0" },
- { 0xf91e, "\x72\x1b\0" },
- { 0xf91f, "\x86\x2d\0" },
- { 0xf920, "\x9e\x1e\0" },
- { 0xf921, "\x5d\x50\0" },
- { 0xf922, "\x6f\xeb\0" },
- { 0xf923, "\x85\xcd\0" },
- { 0xf924, "\x89\x64\0" },
- { 0xf925, "\x62\xc9\0" },
- { 0xf926, "\x81\xd8\0" },
- { 0xf927, "\x88\x1f\0" },
- { 0xf928, "\x5e\xca\0" },
- { 0xf929, "\x67\x17\0" },
- { 0xf92a, "\x6d\x6a\0" },
- { 0xf92b, "\x72\xfc\0" },
- { 0xf92c, "\x90\xce\0" },
- { 0xf92d, "\x4f\x86\0" },
- { 0xf92e, "\x51\xb7\0" },
- { 0xf92f, "\x52\xde\0" },
- { 0xf930, "\x64\xc4\0" },
- { 0xf931, "\x6a\xd3\0" },
- { 0xf932, "\x72\x10\0" },
- { 0xf933, "\x76\xe7\0" },
- { 0xf934, "\x80\x01\0" },
- { 0xf935, "\x86\x06\0" },
- { 0xf936, "\x86\x5c\0" },
- { 0xf937, "\x8d\xef\0" },
- { 0xf938, "\x97\x32\0" },
- { 0xf939, "\x9b\x6f\0" },
- { 0xf93a, "\x9d\xfa\0" },
- { 0xf93b, "\x78\x8c\0" },
- { 0xf93c, "\x79\x7f\0" },
- { 0xf93d, "\x7d\xa0\0" },
- { 0xf93e, "\x83\xc9\0" },
- { 0xf93f, "\x93\x04\0" },
- { 0xf940, "\x9e\x7f\0" },
- { 0xf941, "\x8a\xd6\0" },
- { 0xf942, "\x58\xdf\0" },
- { 0xf943, "\x5f\x04\0" },
- { 0xf944, "\x7c\x60\0" },
- { 0xf945, "\x80\x7e\0" },
- { 0xf946, "\x72\x62\0" },
- { 0xf947, "\x78\xca\0" },
- { 0xf948, "\x8c\xc2\0" },
- { 0xf949, "\x96\xf7\0" },
- { 0xf94a, "\x58\xd8\0" },
- { 0xf94b, "\x5c\x62\0" },
- { 0xf94c, "\x6a\x13\0" },
- { 0xf94d, "\x6d\xda\0" },
- { 0xf94e, "\x6f\x0f\0" },
- { 0xf94f, "\x7d\x2f\0" },
- { 0xf950, "\x7e\x37\0" },
- { 0xf951, "\x96\xfb\0" },
- { 0xf952, "\x52\xd2\0" },
- { 0xf953, "\x80\x8b\0" },
- { 0xf954, "\x51\xdc\0" },
- { 0xf955, "\x51\xcc\0" },
- { 0xf956, "\x7a\x1c\0" },
- { 0xf957, "\x7d\xbe\0" },
- { 0xf958, "\x83\xf1\0" },
- { 0xf959, "\x96\x75\0" },
- { 0xf95a, "\x8b\x80\0" },
- { 0xf95b, "\x62\xcf\0" },
- { 0xf95c, "\x6a\x02\0" },
- { 0xf95d, "\x8a\xfe\0" },
- { 0xf95e, "\x4e\x39\0" },
- { 0xf95f, "\x5b\xe7\0" },
- { 0xf960, "\x60\x12\0" },
- { 0xf961, "\x73\x87\0" },
- { 0xf962, "\x75\x70\0" },
- { 0xf963, "\x53\x17\0" },
- { 0xf964, "\x78\xfb\0" },
- { 0xf965, "\x4f\xbf\0" },
- { 0xf966, "\x5f\xa9\0" },
- { 0xf967, "\x4e\x0d\0" },
- { 0xf968, "\x6c\xcc\0" },
- { 0xf969, "\x65\x78\0" },
- { 0xf96a, "\x7d\x22\0" },
- { 0xf96b, "\x53\xc3\0" },
- { 0xf96c, "\x58\x5e\0" },
- { 0xf96d, "\x77\x01\0" },
- { 0xf96e, "\x84\x49\0" },
- { 0xf96f, "\x8a\xaa\0" },
- { 0xf970, "\x6b\xba\0" },
- { 0xf971, "\x8f\xb0\0" },
- { 0xf972, "\x6c\x88\0" },
- { 0xf973, "\x62\xfe\0" },
- { 0xf974, "\x82\xe5\0" },
- { 0xf975, "\x63\xa0\0" },
- { 0xf976, "\x75\x65\0" },
- { 0xf977, "\x4e\xae\0" },
- { 0xf978, "\x51\x69\0" },
- { 0xf979, "\x51\xc9\0" },
- { 0xf97a, "\x68\x81\0" },
- { 0xf97b, "\x7c\xe7\0" },
- { 0xf97c, "\x82\x6f\0" },
- { 0xf97d, "\x8a\xd2\0" },
- { 0xf97e, "\x91\xcf\0" },
- { 0xf97f, "\x52\xf5\0" },
- { 0xf980, "\x54\x42\0" },
- { 0xf981, "\x59\x73\0" },
- { 0xf982, "\x5e\xec\0" },
- { 0xf983, "\x65\xc5\0" },
- { 0xf984, "\x6f\xfe\0" },
- { 0xf985, "\x79\x2a\0" },
- { 0xf986, "\x95\xad\0" },
- { 0xf987, "\x9a\x6a\0" },
- { 0xf988, "\x9e\x97\0" },
- { 0xf989, "\x9e\xce\0" },
- { 0xf98a, "\x52\x9b\0" },
- { 0xf98b, "\x66\xc6\0" },
- { 0xf98c, "\x6b\x77\0" },
- { 0xf98d, "\x8f\x62\0" },
- { 0xf98e, "\x5e\x74\0" },
- { 0xf98f, "\x61\x90\0" },
- { 0xf990, "\x62\x00\0" },
- { 0xf991, "\x64\x9a\0" },
- { 0xf992, "\x6f\x23\0" },
- { 0xf993, "\x71\x49\0" },
- { 0xf994, "\x74\x89\0" },
- { 0xf995, "\x79\xca\0" },
- { 0xf996, "\x7d\xf4\0" },
- { 0xf997, "\x80\x6f\0" },
- { 0xf998, "\x8f\x26\0" },
- { 0xf999, "\x84\xee\0" },
- { 0xf99a, "\x90\x23\0" },
- { 0xf99b, "\x93\x4a\0" },
- { 0xf99c, "\x52\x17\0" },
- { 0xf99d, "\x52\xa3\0" },
- { 0xf99e, "\x54\xbd\0" },
- { 0xf99f, "\x70\xc8\0" },
- { 0xf9a0, "\x88\xc2\0" },
- { 0xf9a1, "\x8a\xaa\0" },
- { 0xf9a2, "\x5e\xc9\0" },
- { 0xf9a3, "\x5f\xf5\0" },
- { 0xf9a4, "\x63\x7b\0" },
- { 0xf9a5, "\x6b\xae\0" },
- { 0xf9a6, "\x7c\x3e\0" },
- { 0xf9a7, "\x73\x75\0" },
- { 0xf9a8, "\x4e\xe4\0" },
- { 0xf9a9, "\x56\xf9\0" },
- { 0xf9aa, "\x5b\xe7\0" },
- { 0xf9ab, "\x5d\xba\0" },
- { 0xf9ac, "\x60\x1c\0" },
- { 0xf9ad, "\x73\xb2\0" },
- { 0xf9ae, "\x74\x69\0" },
- { 0xf9af, "\x7f\x9a\0" },
- { 0xf9b0, "\x80\x46\0" },
- { 0xf9b1, "\x92\x34\0" },
- { 0xf9b2, "\x96\xf6\0" },
- { 0xf9b3, "\x97\x48\0" },
- { 0xf9b4, "\x98\x18\0" },
- { 0xf9b5, "\x4f\x8b\0" },
- { 0xf9b6, "\x79\xae\0" },
- { 0xf9b7, "\x91\xb4\0" },
- { 0xf9b8, "\x96\xb8\0" },
- { 0xf9b9, "\x60\xe1\0" },
- { 0xf9ba, "\x4e\x86\0" },
- { 0xf9bb, "\x50\xda\0" },
- { 0xf9bc, "\x5b\xee\0" },
- { 0xf9bd, "\x5c\x3f\0" },
- { 0xf9be, "\x65\x99\0" },
- { 0xf9bf, "\x6a\x02\0" },
- { 0xf9c0, "\x71\xce\0" },
- { 0xf9c1, "\x76\x42\0" },
- { 0xf9c2, "\x84\xfc\0" },
- { 0xf9c3, "\x90\x7c\0" },
- { 0xf9c4, "\x9f\x8d\0" },
- { 0xf9c5, "\x66\x88\0" },
- { 0xf9c6, "\x96\x2e\0" },
- { 0xf9c7, "\x52\x89\0" },
- { 0xf9c8, "\x67\x7b\0" },
- { 0xf9c9, "\x67\xf3\0" },
- { 0xf9ca, "\x6d\x41\0" },
- { 0xf9cb, "\x6e\x9c\0" },
- { 0xf9cc, "\x74\x09\0" },
- { 0xf9cd, "\x75\x59\0" },
- { 0xf9ce, "\x78\x6b\0" },
- { 0xf9cf, "\x7d\x10\0" },
- { 0xf9d0, "\x98\x5e\0" },
- { 0xf9d1, "\x51\x6d\0" },
- { 0xf9d2, "\x62\x2e\0" },
- { 0xf9d3, "\x96\x78\0" },
- { 0xf9d4, "\x50\x2b\0" },
- { 0xf9d5, "\x5d\x19\0" },
- { 0xf9d6, "\x6d\xea\0" },
- { 0xf9d7, "\x8f\x2a\0" },
- { 0xf9d8, "\x5f\x8b\0" },
- { 0xf9d9, "\x61\x44\0" },
- { 0xf9da, "\x68\x17\0" },
- { 0xf9db, "\x73\x87\0" },
- { 0xf9dc, "\x96\x86\0" },
- { 0xf9dd, "\x52\x29\0" },
- { 0xf9de, "\x54\x0f\0" },
- { 0xf9df, "\x5c\x65\0" },
- { 0xf9e0, "\x66\x13\0" },
- { 0xf9e1, "\x67\x4e\0" },
- { 0xf9e2, "\x68\xa8\0" },
- { 0xf9e3, "\x6c\xe5\0" },
- { 0xf9e4, "\x74\x06\0" },
- { 0xf9e5, "\x75\xe2\0" },
- { 0xf9e6, "\x7f\x79\0" },
- { 0xf9e7, "\x88\xcf\0" },
- { 0xf9e8, "\x88\xe1\0" },
- { 0xf9e9, "\x91\xcc\0" },
- { 0xf9ea, "\x96\xe2\0" },
- { 0xf9eb, "\x53\x3f\0" },
- { 0xf9ec, "\x6e\xba\0" },
- { 0xf9ed, "\x54\x1d\0" },
- { 0xf9ee, "\x71\xd0\0" },
- { 0xf9ef, "\x74\x98\0" },
- { 0xf9f0, "\x85\xfa\0" },
- { 0xf9f1, "\x96\xa3\0" },
- { 0xf9f2, "\x9c\x57\0" },
- { 0xf9f3, "\x9e\x9f\0" },
- { 0xf9f4, "\x67\x97\0" },
- { 0xf9f5, "\x6d\xcb\0" },
- { 0xf9f6, "\x81\xe8\0" },
- { 0xf9f7, "\x7a\xcb\0" },
- { 0xf9f8, "\x7b\x20\0" },
- { 0xf9f9, "\x7c\x92\0" },
- { 0xf9fa, "\x72\xc0\0" },
- { 0xf9fb, "\x70\x99\0" },
- { 0xf9fc, "\x8b\x58\0" },
- { 0xf9fd, "\x4e\xc0\0" },
- { 0xf9fe, "\x83\x36\0" },
- { 0xf9ff, "\x52\x3a\0" },
- { 0xfa00, "\x52\x07\0" },
- { 0xfa01, "\x5e\xa6\0" },
- { 0xfa02, "\x62\xd3\0" },
- { 0xfa03, "\x7c\xd6\0" },
- { 0xfa04, "\x5b\x85\0" },
- { 0xfa05, "\x6d\x1e\0" },
- { 0xfa06, "\x66\xb4\0" },
- { 0xfa07, "\x8f\x3b\0" },
- { 0xfa08, "\x88\x4c\0" },
- { 0xfa09, "\x96\x4d\0" },
- { 0xfa0a, "\x89\x8b\0" },
- { 0xfa0b, "\x5e\xd3\0" },
- { 0xfa0c, "\x51\x40\0" },
- { 0xfa0d, "\x55\xc0\0" },
- { 0xfa10, "\x58\x5a\0" },
- { 0xfa12, "\x66\x74\0" },
- { 0xfa15, "\x51\xde\0" },
- { 0xfa16, "\x73\x2a\0" },
- { 0xfa17, "\x76\xca\0" },
- { 0xfa18, "\x79\x3c\0" },
- { 0xfa19, "\x79\x5e\0" },
- { 0xfa1a, "\x79\x65\0" },
- { 0xfa1b, "\x79\x8f\0" },
- { 0xfa1c, "\x97\x56\0" },
- { 0xfa1d, "\x7c\xbe\0" },
- { 0xfa1e, "\x7f\xbd\0" },
- { 0xfa20, "\x86\x12\0" },
- { 0xfa22, "\x8a\xf8\0" },
- { 0xfa25, "\x90\x38\0" },
- { 0xfa26, "\x90\xfd\0" },
- { 0xfa2a, "\x98\xef\0" },
- { 0xfa2b, "\x98\xfc\0" },
- { 0xfa2c, "\x99\x28\0" },
- { 0xfa2d, "\x9d\xb4\0" },
- { 0xfb1f, "\x05\xf2\x05\xb7\0" },
- { 0xfb2a, "\x05\xe9\x05\xc1\0" },
- { 0xfb2b, "\x05\xe9\x05\xc2\0" },
- { 0xfb2c, "\x05\xe9\x05\xbc\x05\xc1\0" },
- { 0xfb2d, "\x05\xe9\x05\xbc\x05\xc2\0" },
- { 0xfb2e, "\x05\xd0\x05\xb7\0" },
- { 0xfb2f, "\x05\xd0\x05\xb8\0" },
- { 0xfb30, "\x05\xd0\x05\xbc\0" },
- { 0xfb31, "\x05\xd1\x05\xbc\0" },
- { 0xfb32, "\x05\xd2\x05\xbc\0" },
- { 0xfb33, "\x05\xd3\x05\xbc\0" },
- { 0xfb34, "\x05\xd4\x05\xbc\0" },
- { 0xfb35, "\x05\xd5\x05\xbc\0" },
- { 0xfb36, "\x05\xd6\x05\xbc\0" },
- { 0xfb38, "\x05\xd8\x05\xbc\0" },
- { 0xfb39, "\x05\xd9\x05\xbc\0" },
- { 0xfb3a, "\x05\xda\x05\xbc\0" },
- { 0xfb3b, "\x05\xdb\x05\xbc\0" },
- { 0xfb3c, "\x05\xdc\x05\xbc\0" },
- { 0xfb3e, "\x05\xde\x05\xbc\0" },
- { 0xfb40, "\x05\xe0\x05\xbc\0" },
- { 0xfb41, "\x05\xe1\x05\xbc\0" },
- { 0xfb43, "\x05\xe3\x05\xbc\0" },
- { 0xfb44, "\x05\xe4\x05\xbc\0" },
- { 0xfb46, "\x05\xe6\x05\xbc\0" },
- { 0xfb47, "\x05\xe7\x05\xbc\0" },
- { 0xfb48, "\x05\xe8\x05\xbc\0" },
- { 0xfb49, "\x05\xe9\x05\xbc\0" },
- { 0xfb4a, "\x05\xea\x05\xbc\0" },
- { 0xfb4b, "\x05\xd5\x05\xb9\0" },
- { 0xfb4c, "\x05\xd1\x05\xbf\0" },
- { 0xfb4d, "\x05\xdb\x05\xbf\0" },
- { 0xfb4e, "\x05\xe4\x05\xbf\0" }
-};
-
-/*
- * WARNING!
- *
- * NO BUFFER CHECKING AHEAD!
- *
- */
-
-static gint
-e_canonical_decomposition (gunichar ch, gunichar * buf)
-{
- gint len = 0;
-
- if (ch <= 0xffff)
- {
- gint start = 0;
- gint end = sizeof (e_decomp_table) / sizeof (e_decomp_table[0]);
- while (start != end)
- {
- gint half = (start + end) / 2;
- if (ch == e_decomp_table[half].ch) {
- /* Found it. */
- gint i;
- /* We store as a double-nul terminated string. */
- for (len = 0; (e_decomp_table[half].expansion[len] || e_decomp_table[half].expansion[len + 1]); len += 2);
-
- /* We've counted twice as many bytes as there are
- characters. */
- len /= 2;
-
- for (i = 0; i < len; i ++) {
- buf[i] = (e_decomp_table[half].expansion[2 * i] << 8) | e_decomp_table[half].expansion[2 * i + 1];
- }
- break;
- } else if (ch > e_decomp_table[half].ch) {
- if (start == half) break;
- start = half;
- } else {
- if (end == half) break;
- end = half;
- }
- }
- }
-
- if (len == 0)
- {
- /* Not in our table. */
- *buf = ch;
- len = 1;
- }
-
- /* Supposedly following the Unicode 2.1.9 table means that the
- decompositions come out in canonical order. I haven't tested
- this, but we rely on it here. */
- return len;
-}
-
-static gunichar
-e_stripped_char (gunichar ch)
-{
- gunichar decomp[MAX_DECOMP];
- GUnicodeType utype;
- gint dlen;
-
- utype = g_unichar_type (ch);
-
- switch (utype) {
- case G_UNICODE_CONTROL:
- case G_UNICODE_FORMAT:
- case G_UNICODE_UNASSIGNED:
- case G_UNICODE_COMBINING_MARK:
- /* Ignore those */
- return 0;
- default:
- /* Convert to lowercase, fall through */
- ch = g_unichar_tolower (ch);
- case G_UNICODE_LOWERCASE_LETTER:
- dlen = e_canonical_decomposition (ch, decomp);
- if (dlen > 0) return *decomp;
- break;
- }
-
- return 0;
-}
-
-gchar *
-e_xml_get_translated_utf8_string_prop_by_name (const xmlNode *parent, const xmlChar *prop_name)
-{
- xmlChar *prop;
- gchar *ret_val = NULL;
- gchar *combined_name;
-
- g_return_val_if_fail (parent != NULL, NULL);
- g_return_val_if_fail (prop_name != NULL, NULL);
-
- prop = xmlGetProp ((xmlNode *) parent, prop_name);
- if (prop != NULL) {
- ret_val = g_strdup ((gchar *)prop);
- xmlFree (prop);
- return ret_val;
- }
-
- combined_name = g_strdup_printf("_%s", prop_name);
- prop = xmlGetProp ((xmlNode *) parent, (guchar *)combined_name);
- if (prop != NULL) {
- ret_val = g_strdup (gettext ((gchar *)prop));
- xmlFree (prop);
- }
- g_free(combined_name);
-
- return ret_val;
-}
diff --git a/widgets/misc/e-unicode.h b/widgets/misc/e-unicode.h
deleted file mode 100644
index 77d1a351cb..0000000000
--- a/widgets/misc/e-unicode.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * e-unicode.h - utf-8 support functions for gal
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) version 3.
- *
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- *
- * Authors:
- * Lauris Kaplinski <lauris@ximian.com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-#ifndef _E_UNICODE_H_
-#define _E_UNICODE_H_
-
-#include <sys/types.h>
-#include <glib.h>
-#include <gtk/gtk.h>
-#include <libxml/tree.h>
-#include <iconv.h>
-
-G_BEGIN_DECLS
-
-#define G_UTF8_IN_GAL
-
-/*
- * UTF-8 searching implementations
- *
- * e_utf8_strstrcase - case insensitive search
- * e_utf8_strstrcasedecomp - case insensitive and decompositing search (i.e. accented
- * letters are treated equal to their base letters, explicit accent marks (unicode
- * not ascii/iso ones) are ignored).
- */
-
-const gchar *e_utf8_strstrcase (const gchar *haystack,
- const gchar *needle);
-const gchar *e_utf8_strstrcasedecomp (const gchar *haystack,
- const gchar *needle);
-gchar *e_utf8_from_gtk_event_key (GtkWidget *widget,
- guint keyval,
- const gchar *string);
-gchar *e_utf8_from_iconv_string (iconv_t ic,
- const gchar *string);
-gchar *e_utf8_from_iconv_string_sized (iconv_t ic,
- const gchar *string,
- gint bytes);
-gchar *e_utf8_to_iconv_string (iconv_t ic,
- const gchar *string);
-gchar *e_utf8_to_iconv_string_sized (iconv_t ic,
- const gchar *string,
- gint bytes);
-gchar *e_utf8_from_charset_string (const gchar *charset,
- const gchar *string);
-gchar *e_utf8_from_charset_string_sized (const gchar *charset,
- const gchar *string,
- gint bytes);
-gchar *e_utf8_to_charset_string (const gchar *charset,
- const gchar *string);
-gchar *e_utf8_to_charset_string_sized (const gchar *charset,
- const gchar *string,
- gint bytes);
-gchar *e_utf8_from_locale_string (const gchar *string);
-gchar *e_utf8_from_locale_string_sized (const gchar *string,
- gint bytes);
-gchar *e_utf8_to_locale_string (const gchar *string);
-gchar *e_utf8_to_locale_string_sized (const gchar *string,
- gint bytes);
-gboolean e_utf8_is_ascii (const gchar *string);
-/*
- * These are simple wrappers that save us some typing
- */
-
-/* NB! This return newly allocated string, not const as gtk+ one */
-gchar *e_utf8_gtk_entry_get_text (GtkEntry *entry);
-void e_utf8_gtk_entry_set_text (GtkEntry *entry,
- const gchar *text);
-gchar *e_utf8_gtk_editable_get_text (GtkEditable *editable);
-void e_utf8_gtk_editable_set_text (GtkEditable *editable,
- const gchar *text);
-gchar *e_utf8_gtk_editable_get_chars (GtkEditable *editable,
- gint start,
- gint end);
-void e_utf8_gtk_editable_insert_text (GtkEditable *editable,
- const gchar *text,
- gint length,
- gint *position);
-gchar *e_utf8_xml1_decode (const gchar *text);
-gchar *e_utf8_xml1_encode (const gchar *text);
-gint e_unichar_to_utf8 (gint c,
- gchar *outbuf);
-gchar *e_unicode_get_utf8 (const gchar *text,
- gunichar *out);
-gchar *e_xml_get_translated_utf8_string_prop_by_name (const xmlNode *parent,
- const xmlChar *prop_name);
-
-G_END_DECLS
-
-#endif
-
-
diff --git a/widgets/misc/ea-calendar-cell.c b/widgets/misc/ea-calendar-cell.c
new file mode 100644
index 0000000000..af9471c5af
--- /dev/null
+++ b/widgets/misc/ea-calendar-cell.c
@@ -0,0 +1,387 @@
+/*
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ * Bolian Yin <bolian.yin@sun.com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#include <gtk/gtk.h>
+#include <e-util/e-util.h>
+#include "ea-calendar-cell.h"
+#include "ea-calendar-item.h"
+#include "a11y/ea-factory.h"
+
+/* ECalendarCell */
+
+static void e_calendar_cell_class_init (ECalendarCellClass *class);
+
+EA_FACTORY_GOBJECT (EA_TYPE_CALENDAR_CELL, ea_calendar_cell, ea_calendar_cell_new)
+
+GType
+e_calendar_cell_get_type (void)
+{
+ static GType type = 0;
+
+ if (!type) {
+ static GTypeInfo tinfo = {
+ sizeof (ECalendarCellClass),
+ (GBaseInitFunc) NULL, /* base init */
+ (GBaseFinalizeFunc) NULL, /* base finalize */
+ (GClassInitFunc) e_calendar_cell_class_init, /* class init */
+ (GClassFinalizeFunc) NULL, /* class finalize */
+ NULL, /* class data */
+ sizeof (ECalendarCell), /* instance size */
+ 0, /* nb preallocs */
+ (GInstanceInitFunc) NULL, /* instance init */
+ NULL /* value table */
+ };
+
+ type = g_type_register_static (G_TYPE_OBJECT,
+ "ECalendarCell", &tinfo, 0);
+ }
+
+ return type;
+}
+
+static void
+e_calendar_cell_class_init (ECalendarCellClass *class)
+{
+ EA_SET_FACTORY (e_calendar_cell_get_type (), ea_calendar_cell);
+}
+
+ECalendarCell *
+e_calendar_cell_new (ECalendarItem *calitem, gint row, gint column)
+{
+ GObject *object;
+ ECalendarCell *cell;
+
+ g_return_val_if_fail (E_IS_CALENDAR_ITEM (calitem), NULL);
+
+ object = g_object_new (E_TYPE_CALENDAR_CELL, NULL);
+ cell = E_CALENDAR_CELL (object);
+ cell->calitem = calitem;
+ cell->row = row;
+ cell->column = column;
+
+#ifdef ACC_DEBUG
+ g_print ("EvoAcc: e_calendar_cell created %p\n", (gpointer)cell);
+#endif
+
+ return cell;
+}
+
+/* EaCalendarCell */
+
+static void ea_calendar_cell_class_init (EaCalendarCellClass *klass);
+static void ea_calendar_cell_init (EaCalendarCell *a11y);
+
+static G_CONST_RETURN gchar * ea_calendar_cell_get_name (AtkObject *accessible);
+static G_CONST_RETURN gchar * ea_calendar_cell_get_description (AtkObject *accessible);
+static AtkObject * ea_calendar_cell_get_parent (AtkObject *accessible);
+static gint ea_calendar_cell_get_index_in_parent (AtkObject *accessible);
+static AtkStateSet *ea_calendar_cell_ref_state_set (AtkObject *accessible);
+
+/* component interface */
+static void atk_component_interface_init (AtkComponentIface *iface);
+static void component_interface_get_extents (AtkComponent *component,
+ gint *x, gint *y,
+ gint *width, gint *height,
+ AtkCoordType coord_type);
+static gboolean component_interface_grab_focus (AtkComponent *component);
+
+static gpointer parent_class = NULL;
+
+#ifdef ACC_DEBUG
+static gint n_ea_calendar_cell_created = 0, n_ea_calendar_cell_destroyed = 0;
+static void ea_calendar_cell_finalize (GObject *object);
+#endif
+
+GType
+ea_calendar_cell_get_type (void)
+{
+ static GType type = 0;
+
+ if (!type) {
+ static GTypeInfo tinfo = {
+ sizeof (EaCalendarCellClass),
+ (GBaseInitFunc) NULL, /* base init */
+ (GBaseFinalizeFunc) NULL, /* base finalize */
+ (GClassInitFunc) ea_calendar_cell_class_init, /* class init */
+ (GClassFinalizeFunc) NULL, /* class finalize */
+ NULL, /* class data */
+ sizeof (EaCalendarCell), /* instance size */
+ 0, /* nb preallocs */
+ (GInstanceInitFunc) ea_calendar_cell_init, /* instance init */
+ NULL /* value table */
+ };
+
+ static const GInterfaceInfo atk_component_info = {
+ (GInterfaceInitFunc) atk_component_interface_init,
+ (GInterfaceFinalizeFunc) NULL,
+ NULL
+ };
+
+ type = g_type_register_static (ATK_TYPE_GOBJECT_ACCESSIBLE,
+ "EaCalendarCell", &tinfo, 0);
+ g_type_add_interface_static (type, ATK_TYPE_COMPONENT,
+ &atk_component_info);
+ }
+
+ return type;
+}
+
+static void
+ea_calendar_cell_class_init (EaCalendarCellClass *klass)
+{
+ AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
+
+#ifdef ACC_DEBUG
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ gobject_class->finalize = ea_calendar_cell_finalize;
+#endif
+
+ parent_class = g_type_class_peek_parent (klass);
+
+ class->get_name = ea_calendar_cell_get_name;
+ class->get_description = ea_calendar_cell_get_description;
+
+ class->get_parent = ea_calendar_cell_get_parent;
+ class->get_index_in_parent = ea_calendar_cell_get_index_in_parent;
+ class->ref_state_set = ea_calendar_cell_ref_state_set;
+}
+
+static void
+ea_calendar_cell_init (EaCalendarCell *a11y)
+{
+ a11y->state_set = atk_state_set_new ();
+ atk_state_set_add_state (a11y->state_set, ATK_STATE_TRANSIENT);
+ atk_state_set_add_state (a11y->state_set, ATK_STATE_ENABLED);
+ atk_state_set_add_state (a11y->state_set, ATK_STATE_SENSITIVE);
+ atk_state_set_add_state (a11y->state_set, ATK_STATE_SELECTABLE);
+ atk_state_set_add_state (a11y->state_set, ATK_STATE_SHOWING);
+ atk_state_set_add_state (a11y->state_set, ATK_STATE_FOCUSABLE);
+}
+
+AtkObject*
+ea_calendar_cell_new (GObject *obj)
+{
+ gpointer object;
+ AtkObject *atk_object;
+
+ g_return_val_if_fail (E_IS_CALENDAR_CELL (obj), NULL);
+ object = g_object_new (EA_TYPE_CALENDAR_CELL, NULL);
+ atk_object = ATK_OBJECT (object);
+ atk_object_initialize (atk_object, obj);
+ atk_object->role = ATK_ROLE_TABLE_CELL;
+
+#ifdef ACC_DEBUG
+ ++n_ea_calendar_cell_created;
+ g_print ("ACC_DEBUG: n_ea_calendar_cell_created = %d\n",
+ n_ea_calendar_cell_created);
+#endif
+ return atk_object;
+}
+
+#ifdef ACC_DEBUG
+static void ea_calendar_cell_finalize (GObject *object)
+{
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+
+ ++n_ea_calendar_cell_destroyed;
+ g_print ("ACC_DEBUG: n_ea_calendar_cell_destroyed = %d\n",
+ n_ea_calendar_cell_destroyed);
+}
+#endif
+
+static G_CONST_RETURN gchar *
+ea_calendar_cell_get_name (AtkObject *accessible)
+{
+ GObject *g_obj;
+
+ g_return_val_if_fail (EA_IS_CALENDAR_CELL (accessible), NULL);
+
+ g_obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE(accessible));
+ if (!g_obj)
+ /* defunct object*/
+ return NULL;
+
+ if (!accessible->name) {
+ AtkObject *atk_obj;
+ EaCalendarItem *ea_calitem;
+ ECalendarCell *cell;
+ gint day_index;
+ gint year, month, day;
+ gchar buffer[128];
+
+ cell = E_CALENDAR_CELL (g_obj);
+ atk_obj = ea_calendar_cell_get_parent (accessible);
+ ea_calitem = EA_CALENDAR_ITEM (atk_obj);
+ day_index = atk_table_get_index_at (ATK_TABLE (ea_calitem),
+ cell->row, cell->column);
+ e_calendar_item_get_date_for_offset (cell->calitem, day_index,
+ &year, &month, &day);
+
+ g_snprintf (buffer, 128, "%d-%d-%d", year, month + 1, day);
+ ATK_OBJECT_CLASS (parent_class)->set_name (accessible, buffer);
+ }
+ return accessible->name;
+}
+
+static G_CONST_RETURN gchar *
+ea_calendar_cell_get_description (AtkObject *accessible)
+{
+ return ea_calendar_cell_get_name (accessible);
+}
+
+static AtkObject *
+ea_calendar_cell_get_parent (AtkObject *accessible)
+{
+ GObject *g_obj;
+ ECalendarCell *cell;
+ ECalendarItem *calitem;
+
+ g_return_val_if_fail (EA_IS_CALENDAR_CELL (accessible), NULL);
+
+ g_obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE(accessible));
+ if (!g_obj)
+ /* defunct object*/
+ return NULL;
+
+ cell = E_CALENDAR_CELL (g_obj);
+ calitem = cell->calitem;
+ return atk_gobject_accessible_for_object (G_OBJECT (calitem));
+}
+
+static gint
+ea_calendar_cell_get_index_in_parent (AtkObject *accessible)
+{
+ GObject *g_obj;
+ ECalendarCell *cell;
+ AtkObject *parent;
+
+ g_return_val_if_fail (EA_IS_CALENDAR_CELL (accessible), -1);
+
+ g_obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE(accessible));
+ if (!g_obj)
+ return -1;
+ cell = E_CALENDAR_CELL (g_obj);
+ parent = atk_object_get_parent (accessible);
+ return atk_table_get_index_at (ATK_TABLE (parent),
+ cell->row, cell->column);
+}
+
+static AtkStateSet *
+ea_calendar_cell_ref_state_set (AtkObject *accessible)
+{
+ EaCalendarCell *atk_cell = EA_CALENDAR_CELL (accessible);
+
+ g_return_val_if_fail (atk_cell->state_set, NULL);
+
+ g_object_ref(atk_cell->state_set);
+
+ return atk_cell->state_set;
+
+}
+
+/* Atk Component Interface */
+
+static void
+atk_component_interface_init (AtkComponentIface *iface)
+{
+ g_return_if_fail (iface != NULL);
+
+ iface->get_extents = component_interface_get_extents;
+ iface->grab_focus = component_interface_grab_focus;
+}
+
+static void
+component_interface_get_extents (AtkComponent *component,
+ gint *x, gint *y, gint *width, gint *height,
+ AtkCoordType coord_type)
+{
+ GObject *g_obj;
+ AtkObject *atk_obj, *atk_canvas;
+ ECalendarCell *cell;
+ ECalendarItem *calitem;
+ EaCalendarItem *ea_calitem;
+ gint day_index;
+ gint year, month, day;
+ gint canvas_x, canvas_y, canvas_width, canvas_height;
+
+ *x = *y = *width = *height = 0;
+
+ g_return_if_fail (EA_IS_CALENDAR_CELL (component));
+
+
+ g_obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE(component));
+ if (!g_obj)
+ /* defunct object*/
+ return;
+
+ cell = E_CALENDAR_CELL (g_obj);
+ calitem = cell->calitem;
+ atk_obj = atk_gobject_accessible_for_object (G_OBJECT (calitem));
+ ea_calitem = EA_CALENDAR_ITEM (atk_obj);
+ day_index = atk_table_get_index_at (ATK_TABLE (ea_calitem),
+ cell->row, cell->column);
+ e_calendar_item_get_date_for_offset (calitem, day_index,
+ &year, &month, &day);
+
+ if (!e_calendar_item_get_day_extents (calitem,
+ year, month, day,
+ x, y, width, height))
+ return;
+ atk_canvas = atk_object_get_parent (ATK_OBJECT (ea_calitem));
+ atk_component_get_extents (ATK_COMPONENT (atk_canvas),
+ &canvas_x, &canvas_y,
+ &canvas_width, &canvas_height,
+ coord_type);
+ *x += canvas_x;
+ *y += canvas_y;
+}
+
+static gboolean
+component_interface_grab_focus (AtkComponent *component)
+{
+ GObject *g_obj;
+ GtkWidget *toplevel;
+ AtkObject *ea_calitem;
+ ECalendarItem *calitem;
+ EaCalendarCell *a11y;
+ gint index;
+
+ a11y = EA_CALENDAR_CELL (component);
+ ea_calitem = ea_calendar_cell_get_parent (ATK_OBJECT (a11y));
+
+ g_obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE(ea_calitem));
+ calitem = E_CALENDAR_ITEM (g_obj);
+
+ index = atk_object_get_index_in_parent (ATK_OBJECT (a11y));
+
+ atk_selection_clear_selection (ATK_SELECTION (ea_calitem));
+ atk_selection_add_selection (ATK_SELECTION (ea_calitem), index);
+
+ gtk_widget_grab_focus (GTK_WIDGET (GNOME_CANVAS_ITEM (calitem)->canvas));
+ toplevel = gtk_widget_get_toplevel (GTK_WIDGET (GNOME_CANVAS_ITEM (calitem)->canvas));
+ if (toplevel && GTK_WIDGET_TOPLEVEL (toplevel))
+ gtk_window_present (GTK_WINDOW (toplevel));
+
+ return TRUE;
+
+}
diff --git a/widgets/misc/ea-calendar-cell.h b/widgets/misc/ea-calendar-cell.h
new file mode 100644
index 0000000000..fa68fdca55
--- /dev/null
+++ b/widgets/misc/ea-calendar-cell.h
@@ -0,0 +1,86 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ * Bolian Yin <bolian.yin@sun.com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef __EA_CALENDAR_CELL_H__
+#define __EA_CALENDAR_CELL_H__
+
+#include <atk/atkgobjectaccessible.h>
+#include "misc/e-calendar-item.h"
+
+G_BEGIN_DECLS
+
+#define E_TYPE_CALENDAR_CELL (e_calendar_cell_get_type ())
+#define E_CALENDAR_CELL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_CALENDAR_CELL, ECalendarCell))
+#define E_CALENDAR_CELL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E_TYPE_CALENDAR_CELL, ECalendarCellClass))
+#define E_IS_CALENDAR_CELL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_TYPE_CALENDAR_CELL))
+#define E_IS_CALENDAR_CELL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), E_TYPE_CALENDAR_CELL))
+#define E_CALENDAR_CELL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), E_TYPE_CALENDAR_CELL, ECalendarCellClass))
+
+typedef struct _ECalendarCell ECalendarCell;
+typedef struct _ECalendarCellClass ECalendarCellClass;
+
+struct _ECalendarCell
+{
+ GObject parent;
+ ECalendarItem *calitem;
+ gint row;
+ gint column;
+};
+
+GType e_calendar_cell_get_type (void);
+
+struct _ECalendarCellClass
+{
+ GObjectClass parent_class;
+};
+
+ECalendarCell * e_calendar_cell_new (ECalendarItem *calitem,
+ gint row, gint column);
+
+#define EA_TYPE_CALENDAR_CELL (ea_calendar_cell_get_type ())
+#define EA_CALENDAR_CELL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EA_TYPE_CALENDAR_CELL, EaCalendarCell))
+#define EA_CALENDAR_CELL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EA_TYPE_CALENDAR_CELL, EaCalendarCellClass))
+#define EA_IS_CALENDAR_CELL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EA_TYPE_CALENDAR_CELL))
+#define EA_IS_CALENDAR_CELL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EA_TYPE_CALENDAR_CELL))
+#define EA_CALENDAR_CELL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EA_TYPE_CALENDAR_CELL, EaCalendarCellClass))
+
+typedef struct _EaCalendarCell EaCalendarCell;
+typedef struct _EaCalendarCellClass EaCalendarCellClass;
+
+struct _EaCalendarCell
+{
+ AtkGObjectAccessible parent;
+ AtkStateSet *state_set;
+};
+
+GType ea_calendar_cell_get_type (void);
+
+struct _EaCalendarCellClass
+{
+ AtkGObjectAccessibleClass parent_class;
+};
+
+AtkObject* ea_calendar_cell_new (GObject *gobj);
+
+G_END_DECLS
+
+#endif /* __EA_CALENDAR_CELL_H__ */
diff --git a/widgets/misc/ea-calendar-item.c b/widgets/misc/ea-calendar-item.c
new file mode 100644
index 0000000000..56a01b510b
--- /dev/null
+++ b/widgets/misc/ea-calendar-item.c
@@ -0,0 +1,1314 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ * Bolian Yin <bolian.yin@sun.com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#include <stdio.h>
+#include <time.h>
+#include <string.h>
+#include <libgnomecanvas/gnome-canvas.h>
+#include <glib.h>
+#include <e-util/e-util.h>
+#include <glib/gi18n.h>
+#include <libedataserver/e-data-server-util.h>
+#include "ea-calendar-item.h"
+#include "ea-calendar-cell.h"
+#include "a11y/ea-cell-table.h"
+
+#define EA_CALENDAR_COLUMN_NUM E_CALENDAR_COLS_PER_MONTH
+
+/* EaCalendarItem */
+static void ea_calendar_item_class_init (EaCalendarItemClass *klass);
+static void ea_calendar_item_finalize (GObject *object);
+
+static G_CONST_RETURN gchar * ea_calendar_item_get_name (AtkObject *accessible);
+static G_CONST_RETURN gchar * ea_calendar_item_get_description (AtkObject *accessible);
+static gint ea_calendar_item_get_n_children (AtkObject *accessible);
+static AtkObject *ea_calendar_item_ref_child (AtkObject *accessible, gint index);
+static AtkStateSet* ea_calendar_item_ref_state_set (AtkObject *accessible);
+
+/* atk table interface */
+static void atk_table_interface_init (AtkTableIface *iface);
+static gint table_interface_get_index_at (AtkTable *table,
+ gint row,
+ gint column);
+static gint table_interface_get_column_at_index (AtkTable *table,
+ gint index);
+static gint table_interface_get_row_at_index (AtkTable *table,
+ gint index);
+static AtkObject* table_interface_ref_at (AtkTable *table,
+ gint row,
+ gint column);
+static gint table_interface_get_n_rows (AtkTable *table);
+static gint table_interface_get_n_columns (AtkTable *table);
+static gint table_interface_get_column_extent_at (AtkTable *table,
+ gint row,
+ gint column);
+static gint table_interface_get_row_extent_at (AtkTable *table,
+ gint row,
+ gint column);
+
+static gboolean table_interface_is_row_selected (AtkTable *table,
+ gint row);
+static gboolean table_interface_is_column_selected (AtkTable *table,
+ gint row);
+static gboolean table_interface_is_selected (AtkTable *table,
+ gint row,
+ gint column);
+static gint table_interface_get_selected_rows (AtkTable *table,
+ gint **rows_selected);
+static gint table_interface_get_selected_columns (AtkTable *table,
+ gint **columns_selected);
+static gboolean table_interface_add_row_selection (AtkTable *table, gint row);
+static gboolean table_interface_remove_row_selection (AtkTable *table,
+ gint row);
+static gboolean table_interface_add_column_selection (AtkTable *table,
+ gint column);
+static gboolean table_interface_remove_column_selection (AtkTable *table,
+ gint column);
+static AtkObject* table_interface_get_row_header (AtkTable *table, gint row);
+static AtkObject* table_interface_get_column_header (AtkTable *table,
+ gint in_col);
+static AtkObject* table_interface_get_caption (AtkTable *table);
+
+static G_CONST_RETURN gchar *
+table_interface_get_column_description (AtkTable *table, gint in_col);
+
+static G_CONST_RETURN gchar *
+table_interface_get_row_description (AtkTable *table, gint row);
+
+static AtkObject* table_interface_get_summary (AtkTable *table);
+
+/* atk selection interface */
+static void atk_selection_interface_init (AtkSelectionIface *iface);
+static gboolean selection_interface_add_selection (AtkSelection *selection,
+ gint i);
+static gboolean selection_interface_clear_selection (AtkSelection *selection);
+static AtkObject* selection_interface_ref_selection (AtkSelection *selection,
+ gint i);
+static gint selection_interface_get_selection_count (AtkSelection *selection);
+static gboolean selection_interface_is_child_selected (AtkSelection *selection,
+ gint i);
+
+/* callbacks */
+static void selection_preview_change_cb (ECalendarItem *calitem);
+static void date_range_changed_cb (ECalendarItem *calitem);
+
+/* helpers */
+static EaCellTable *ea_calendar_item_get_cell_data (EaCalendarItem *ea_calitem);
+static void ea_calendar_item_destory_cell_data (EaCalendarItem *ea_calitem);
+static gboolean ea_calendar_item_get_column_label (EaCalendarItem *ea_calitem,
+ gint column,
+ gchar *buffer,
+ gint buffer_size);
+static gboolean ea_calendar_item_get_row_label (EaCalendarItem *ea_calitem,
+ gint row,
+ gchar *buffer,
+ gint buffer_size);
+static gboolean e_calendar_item_get_offset_for_date (ECalendarItem *calitem,
+ gint year, gint month, gint day,
+ gint *offset);
+static void ea_calendar_set_focus_object (EaCalendarItem *ea_calitem,
+ AtkObject *item_cell);
+
+#ifdef ACC_DEBUG
+static gint n_ea_calendar_item_created = 0;
+static gint n_ea_calendar_item_destroyed = 0;
+#endif
+
+static gpointer parent_class = NULL;
+
+GType
+ea_calendar_item_get_type (void)
+{
+ static GType type = 0;
+ AtkObjectFactory *factory;
+ GTypeQuery query;
+ GType derived_atk_type;
+
+ if (!type) {
+ static GTypeInfo tinfo = {
+ sizeof (EaCalendarItemClass),
+ (GBaseInitFunc) NULL, /* base init */
+ (GBaseFinalizeFunc) NULL, /* base finalize */
+ (GClassInitFunc) ea_calendar_item_class_init, /* class init */
+ (GClassFinalizeFunc) NULL, /* class finalize */
+ NULL, /* class data */
+ sizeof (EaCalendarItem), /* instance size */
+ 0, /* nb preallocs */
+ (GInstanceInitFunc) NULL, /* instance init */
+ NULL /* value table */
+ };
+
+ static const GInterfaceInfo atk_table_info = {
+ (GInterfaceInitFunc) atk_table_interface_init,
+ (GInterfaceFinalizeFunc) NULL,
+ NULL
+ };
+ static const GInterfaceInfo atk_selection_info = {
+ (GInterfaceInitFunc) atk_selection_interface_init,
+ (GInterfaceFinalizeFunc) NULL,
+ NULL
+ };
+
+ /*
+ * Figure out the size of the class and instance
+ * we are run-time deriving from (GailCanvasItem, in this case)
+ */
+
+ factory = atk_registry_get_factory (atk_get_default_registry (),
+ GNOME_TYPE_CANVAS_ITEM);
+ derived_atk_type = atk_object_factory_get_accessible_type (factory);
+ g_type_query (derived_atk_type, &query);
+
+ tinfo.class_size = query.class_size;
+ tinfo.instance_size = query.instance_size;
+
+ type = g_type_register_static (derived_atk_type,
+ "EaCalendarItem", &tinfo, 0);
+ g_type_add_interface_static (type, ATK_TYPE_TABLE,
+ &atk_table_info);
+ g_type_add_interface_static (type, ATK_TYPE_SELECTION,
+ &atk_selection_info);
+ }
+
+ return type;
+}
+
+static void
+ea_calendar_item_class_init (EaCalendarItemClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
+
+ gobject_class->finalize = ea_calendar_item_finalize;
+ parent_class = g_type_class_peek_parent (klass);
+
+ class->get_name = ea_calendar_item_get_name;
+ class->get_description = ea_calendar_item_get_description;
+ class->ref_state_set = ea_calendar_item_ref_state_set;
+
+ class->get_n_children = ea_calendar_item_get_n_children;
+ class->ref_child = ea_calendar_item_ref_child;
+}
+
+AtkObject*
+ea_calendar_item_new (GObject *obj)
+{
+ gpointer object;
+ AtkObject *atk_object;
+ AtkObject *item_cell;
+
+ g_return_val_if_fail (E_IS_CALENDAR_ITEM (obj), NULL);
+ object = g_object_new (EA_TYPE_CALENDAR_ITEM, NULL);
+ atk_object = ATK_OBJECT (object);
+ atk_object_initialize (atk_object, obj);
+ atk_object->role = ATK_ROLE_CALENDAR;
+
+ item_cell = atk_selection_ref_selection (ATK_SELECTION (atk_object),
+ 0);
+ if (item_cell)
+ ea_calendar_set_focus_object (EA_CALENDAR_ITEM (atk_object), item_cell);
+
+#ifdef ACC_DEBUG
+ ++n_ea_calendar_item_created;
+ g_print ("ACC_DEBUG: n_ea_calendar_item_created = %d\n",
+ n_ea_calendar_item_created);
+#endif
+ /* connect signal handlers */
+ g_signal_connect (obj, "selection_preview_changed",
+ G_CALLBACK (selection_preview_change_cb),
+ atk_object);
+ g_signal_connect (obj, "date_range_changed",
+ G_CALLBACK (date_range_changed_cb),
+ atk_object);
+
+ return atk_object;
+}
+
+static void
+ea_calendar_item_finalize (GObject *object)
+{
+ EaCalendarItem *ea_calitem;
+
+ g_return_if_fail (EA_IS_CALENDAR_ITEM (object));
+
+ ea_calitem = EA_CALENDAR_ITEM (object);
+
+ /* Free the allocated cell data */
+ ea_calendar_item_destory_cell_data (ea_calitem);
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+#ifdef ACC_DEBUG
+ ++n_ea_calendar_item_destroyed;
+ printf ("ACC_DEBUG: n_ea_calendar_item_destroyed = %d\n",
+ n_ea_calendar_item_destroyed);
+#endif
+}
+
+static G_CONST_RETURN gchar *
+ea_calendar_item_get_name (AtkObject *accessible)
+{
+ GObject *g_obj;
+ ECalendarItem *calitem;
+ gint start_year, start_month, start_day;
+ gint end_year, end_month, end_day;
+ gchar *name_str = NULL;
+ gchar buffer_start[128] = "";
+ gchar buffer_end[128] = "";
+ struct tm day_start = { 0 };
+ struct tm day_end = { 0 };
+
+ g_return_val_if_fail (EA_IS_CALENDAR_ITEM (accessible), NULL);
+
+ g_obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE(accessible));
+ if (!g_obj)
+ return NULL;
+ g_return_val_if_fail (E_IS_CALENDAR_ITEM (g_obj), NULL);
+
+ calitem = E_CALENDAR_ITEM (g_obj);
+ if (e_calendar_item_get_date_range (calitem,
+ &start_year, &start_month, &start_day,
+ &end_year, &end_month, &end_day)) {
+
+ day_start.tm_year = start_year - 1900;
+ day_start.tm_mon = start_month;
+ day_start.tm_mday = start_day;
+ day_start.tm_isdst = -1;
+ e_utf8_strftime (buffer_start, sizeof (buffer_start), _("%d %B %Y"), &day_start);
+
+ day_end.tm_year = end_year - 1900;
+ day_end.tm_mon = end_month;
+ day_end.tm_mday = end_day;
+ day_end.tm_isdst = -1;
+ e_utf8_strftime (buffer_end, sizeof (buffer_end), _("%d %B %Y"), &day_end);
+
+ name_str = g_strdup_printf (_("Calendar: from %s to %s"), buffer_start, buffer_end);
+ }
+
+#if 0
+ if (e_calendar_item_get_selection (calitem, &select_start, &select_end)) {
+ GDate select_start, select_end;
+ gint year1, year2, month1, month2, day1, day2;
+
+ year1 = g_date_get_year (&select_start);
+ month1 = g_date_get_month (&select_start);
+ day1 = g_date_get_day (&select_start);
+
+ year2 = g_date_get_year (&select_end);
+ month2 = g_date_get_month (&select_end);
+ day2 = g_date_get_day (&select_end);
+
+ sprintf (new_name + strlen (new_name),
+ " : current selection: from %d-%d-%d to %d-%d-%d.",
+ year1, month1, day1,
+ year2, month2, day2);
+ }
+#endif
+
+ ATK_OBJECT_CLASS (parent_class)->set_name (accessible, name_str);
+ g_free (name_str);
+
+ return accessible->name;
+}
+
+static G_CONST_RETURN gchar *
+ea_calendar_item_get_description (AtkObject *accessible)
+{
+ if (accessible->description)
+ return accessible->description;
+
+ return _("evolution calendar item");
+}
+
+static AtkStateSet*
+ea_calendar_item_ref_state_set (AtkObject *accessible)
+{
+ AtkStateSet *state_set;
+ GObject *g_obj;
+
+ state_set = ATK_OBJECT_CLASS (parent_class)->ref_state_set (accessible);
+ g_obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE(accessible));
+ if (!g_obj)
+ return state_set;
+
+ atk_state_set_add_state (state_set, ATK_STATE_ENABLED);
+ atk_state_set_add_state (state_set, ATK_STATE_SENSITIVE);
+
+ return state_set;
+}
+
+static gint
+ea_calendar_item_get_n_children (AtkObject *accessible)
+{
+ AtkGObjectAccessible *atk_gobj;
+ GObject *g_obj;
+ ECalendarItem *calitem;
+ gint n_children = 0;
+ gint start_year, start_month, start_day;
+ gint end_year, end_month, end_day;
+ GDate *start_date, *end_date;
+
+ g_return_val_if_fail (EA_IS_CALENDAR_ITEM (accessible), -1);
+
+ atk_gobj = ATK_GOBJECT_ACCESSIBLE (accessible);
+ g_obj = atk_gobject_accessible_get_object (atk_gobj);
+ if (!g_obj)
+ return -1;
+
+ calitem = E_CALENDAR_ITEM (g_obj);
+ if (!e_calendar_item_get_date_range (calitem, &start_year,
+ &start_month, &start_day,
+ &end_year, &end_month,
+ &end_day))
+ return 0;
+
+ start_date = g_date_new_dmy (start_day, start_month + 1, start_year);
+ end_date = g_date_new_dmy (end_day, end_month + 1, end_year);
+
+ n_children = g_date_days_between (start_date, end_date) + 1;
+ g_free (start_date);
+ g_free (end_date);
+ return n_children;
+}
+
+static AtkObject *
+ea_calendar_item_ref_child (AtkObject *accessible, gint index)
+{
+ AtkGObjectAccessible *atk_gobj;
+ GObject *g_obj;
+ ECalendarItem *calitem;
+ gint n_children;
+ ECalendarCell *cell;
+ EaCellTable *cell_data;
+ EaCalendarItem *ea_calitem;
+
+ g_return_val_if_fail (EA_IS_CALENDAR_ITEM (accessible), NULL);
+
+ atk_gobj = ATK_GOBJECT_ACCESSIBLE (accessible);
+ g_obj = atk_gobject_accessible_get_object (atk_gobj);
+ if (!g_obj)
+ return NULL;
+
+ calitem = E_CALENDAR_ITEM (g_obj);
+
+ n_children = ea_calendar_item_get_n_children (accessible);
+ if (index < 0 || index >= n_children)
+ return NULL;
+
+ ea_calitem = EA_CALENDAR_ITEM (accessible);
+ cell_data = ea_calendar_item_get_cell_data (ea_calitem);
+ if (!cell_data)
+ return NULL;
+
+ cell = ea_cell_table_get_cell_at_index (cell_data, index);
+ if (!cell) {
+ cell = e_calendar_cell_new (calitem,
+ index / EA_CALENDAR_COLUMN_NUM,
+ index % EA_CALENDAR_COLUMN_NUM);
+ ea_cell_table_set_cell_at_index (cell_data, index, cell);
+ g_object_unref (cell);
+ }
+
+#ifdef ACC_DEBUG
+ g_print ("AccDebug: ea_calendar_item children[%d]=%p\n", index,
+ (gpointer)cell);
+#endif
+ return g_object_ref (atk_gobject_accessible_for_object (G_OBJECT(cell)));
+}
+
+/* atk table interface */
+
+static void
+atk_table_interface_init (AtkTableIface *iface)
+{
+ g_return_if_fail (iface != NULL);
+
+ iface->ref_at = table_interface_ref_at;
+
+ iface->get_n_rows = table_interface_get_n_rows;
+ iface->get_n_columns = table_interface_get_n_columns;
+ iface->get_index_at = table_interface_get_index_at;
+ iface->get_column_at_index = table_interface_get_column_at_index;
+ iface->get_row_at_index = table_interface_get_row_at_index;
+ iface->get_column_extent_at = table_interface_get_column_extent_at;
+ iface->get_row_extent_at = table_interface_get_row_extent_at;
+
+ iface->is_selected = table_interface_is_selected;
+ iface->get_selected_rows = table_interface_get_selected_rows;
+ iface->get_selected_columns = table_interface_get_selected_columns;
+ iface->is_row_selected = table_interface_is_row_selected;
+ iface->is_column_selected = table_interface_is_column_selected;
+ iface->add_row_selection = table_interface_add_row_selection;
+ iface->remove_row_selection = table_interface_remove_row_selection;
+ iface->add_column_selection = table_interface_add_column_selection;
+ iface->remove_column_selection = table_interface_remove_column_selection;
+
+ iface->get_row_header = table_interface_get_row_header;
+ iface->get_column_header = table_interface_get_column_header;
+ iface->get_caption = table_interface_get_caption;
+ iface->get_summary = table_interface_get_summary;
+ iface->get_row_description = table_interface_get_row_description;
+ iface->get_column_description = table_interface_get_column_description;
+}
+
+static AtkObject*
+table_interface_ref_at (AtkTable *table,
+ gint row,
+ gint column)
+{
+ gint index;
+
+ EaCalendarItem* ea_calitem = EA_CALENDAR_ITEM (table);
+ index = EA_CALENDAR_COLUMN_NUM * row + column;
+ return ea_calendar_item_ref_child (ATK_OBJECT (ea_calitem), index);
+}
+
+static gint
+table_interface_get_n_rows (AtkTable *table)
+{
+ AtkGObjectAccessible *atk_gobj;
+ GObject *g_obj;
+ EaCalendarItem* ea_calitem = EA_CALENDAR_ITEM (table);
+ gint n_children;
+
+ atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem);
+ g_obj = atk_gobject_accessible_get_object (atk_gobj);
+ if (!g_obj)
+ return -1;
+
+ n_children = ea_calendar_item_get_n_children (ATK_OBJECT (ea_calitem));
+ return (n_children - 1) / EA_CALENDAR_COLUMN_NUM + 1;
+}
+
+static gint
+table_interface_get_n_columns (AtkTable *table)
+{
+ AtkGObjectAccessible *atk_gobj;
+ GObject *g_obj;
+ EaCalendarItem* ea_calitem = EA_CALENDAR_ITEM (table);
+
+ atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem);
+ g_obj = atk_gobject_accessible_get_object (atk_gobj);
+ if (!g_obj)
+ return -1;
+
+ return EA_CALENDAR_COLUMN_NUM;
+}
+
+static gint
+table_interface_get_index_at (AtkTable *table,
+ gint row,
+ gint column)
+{
+ AtkGObjectAccessible *atk_gobj;
+ GObject *g_obj;
+ EaCalendarItem* ea_calitem = EA_CALENDAR_ITEM (table);
+
+ atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem);
+ g_obj = atk_gobject_accessible_get_object (atk_gobj);
+ if (!g_obj)
+ return -1;
+
+ return row * EA_CALENDAR_COLUMN_NUM + column;
+}
+
+static gint
+table_interface_get_column_at_index (AtkTable *table,
+ gint index)
+{
+ AtkGObjectAccessible *atk_gobj;
+ GObject *g_obj;
+ EaCalendarItem* ea_calitem = EA_CALENDAR_ITEM (table);
+ gint n_children;
+
+ atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem);
+ g_obj = atk_gobject_accessible_get_object (atk_gobj);
+ if (!g_obj)
+ return -1;
+
+ n_children = ea_calendar_item_get_n_children (ATK_OBJECT (ea_calitem));
+ if (index >= 0 && index < n_children)
+ return index % EA_CALENDAR_COLUMN_NUM;
+ return -1;
+}
+
+static gint
+table_interface_get_row_at_index (AtkTable *table,
+ gint index)
+{
+ AtkGObjectAccessible *atk_gobj;
+ GObject *g_obj;
+ EaCalendarItem* ea_calitem = EA_CALENDAR_ITEM (table);
+ gint n_children;
+
+ atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem);
+ g_obj = atk_gobject_accessible_get_object (atk_gobj);
+ if (!g_obj)
+ return -1;
+
+ n_children = ea_calendar_item_get_n_children (ATK_OBJECT (ea_calitem));
+ if (index >= 0 && index < n_children)
+ return index / EA_CALENDAR_COLUMN_NUM;
+ return -1;
+}
+
+static gint
+table_interface_get_column_extent_at (AtkTable *table,
+ gint row,
+ gint column)
+{
+ AtkGObjectAccessible *atk_gobj;
+ GObject *g_obj;
+ ECalendarItem *calitem;
+ EaCalendarItem* ea_calitem = EA_CALENDAR_ITEM (table);
+
+ atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem);
+ g_obj = atk_gobject_accessible_get_object (atk_gobj);
+ if (!g_obj)
+ return FALSE;
+
+ calitem = E_CALENDAR_ITEM (g_obj);
+ return calitem->cell_width;
+}
+
+static gint
+table_interface_get_row_extent_at (AtkTable *table,
+ gint row, gint column)
+{
+ AtkGObjectAccessible *atk_gobj;
+ GObject *g_obj;
+ ECalendarItem *calitem;
+ EaCalendarItem* ea_calitem = EA_CALENDAR_ITEM (table);
+
+ atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem);
+ g_obj = atk_gobject_accessible_get_object (atk_gobj);
+ if (!g_obj)
+ return FALSE;
+
+ calitem = E_CALENDAR_ITEM (g_obj);
+ return calitem->cell_height;
+}
+
+/* any day in the row is selected, the row is selected */
+static gboolean
+table_interface_is_row_selected (AtkTable *table,
+ gint row)
+{
+ AtkGObjectAccessible *atk_gobj;
+ GObject *g_obj;
+ gint n_rows;
+ ECalendarItem *calitem;
+ gint row_index_start, row_index_end;
+ gint sel_index_start, sel_index_end;
+
+ GDate start_date, end_date;
+
+ g_return_val_if_fail (EA_IS_CALENDAR_ITEM (table), FALSE);
+
+ atk_gobj = ATK_GOBJECT_ACCESSIBLE (table);
+ g_obj = atk_gobject_accessible_get_object (atk_gobj);
+ if (!g_obj)
+ return FALSE;
+
+ n_rows = table_interface_get_n_rows (table);
+ if (row < 0 || row >= n_rows)
+ return FALSE;
+
+ row_index_start = row * EA_CALENDAR_COLUMN_NUM;
+ row_index_end = row_index_start + EA_CALENDAR_COLUMN_NUM - 1;
+
+ calitem = E_CALENDAR_ITEM (g_obj);
+ if (!e_calendar_item_get_selection (calitem, &start_date, &end_date))
+ return FALSE;
+
+ e_calendar_item_get_offset_for_date (calitem,
+ g_date_get_year (&start_date),
+ g_date_get_month (&start_date),
+ g_date_get_day (&start_date),
+ &sel_index_start);
+ e_calendar_item_get_offset_for_date (calitem,
+ g_date_get_year (&end_date),
+ g_date_get_month (&end_date),
+ g_date_get_day (&end_date),
+ &sel_index_end);
+
+ if ((sel_index_start < row_index_start &&
+ sel_index_end >= row_index_start) ||
+ (sel_index_start >= row_index_start &&
+ sel_index_start <= row_index_end))
+ return TRUE;
+ return FALSE;
+}
+
+static gboolean
+table_interface_is_selected (AtkTable *table,
+ gint row,
+ gint column)
+{
+ AtkGObjectAccessible *atk_gobj;
+ GObject *g_obj;
+ gint n_rows, n_columns;
+ ECalendarItem *calitem;
+ gint index;
+ gint sel_index_start, sel_index_end;
+
+ GDate start_date, end_date;
+
+ g_return_val_if_fail (EA_IS_CALENDAR_ITEM (table), FALSE);
+
+ atk_gobj = ATK_GOBJECT_ACCESSIBLE (table);
+ g_obj = atk_gobject_accessible_get_object (atk_gobj);
+ if (!g_obj)
+ return FALSE;
+
+ n_rows = table_interface_get_n_rows (table);
+ if (row < 0 || row >= n_rows)
+ return FALSE;
+ n_columns = table_interface_get_n_columns (table);
+ if (column < 0 || column >= n_columns)
+ return FALSE;
+
+ index = table_interface_get_index_at (table, row, column);
+
+ calitem = E_CALENDAR_ITEM (g_obj);
+ if (!e_calendar_item_get_selection (calitem, &start_date, &end_date))
+ return FALSE;
+
+ e_calendar_item_get_offset_for_date (calitem,
+ g_date_get_year (&start_date),
+ g_date_get_month (&start_date),
+ g_date_get_day (&start_date),
+ &sel_index_start);
+ e_calendar_item_get_offset_for_date (calitem,
+ g_date_get_year (&end_date),
+ g_date_get_month (&end_date),
+ g_date_get_day (&end_date), &sel_index_end);
+
+ if (sel_index_start <= index && sel_index_end >= index)
+ return TRUE;
+ return FALSE;
+}
+
+static gboolean
+table_interface_is_column_selected (AtkTable *table,
+ gint column)
+{
+ return FALSE;
+}
+
+static gint
+table_interface_get_selected_rows (AtkTable *table,
+ gint **rows_selected)
+{
+ *rows_selected = NULL;
+ return -1;
+}
+
+static gint
+table_interface_get_selected_columns (AtkTable *table,
+ gint **columns_selected)
+{
+ *columns_selected = NULL;
+ return -1;
+}
+
+static gboolean
+table_interface_add_row_selection (AtkTable *table,
+ gint row)
+{
+ return FALSE;
+}
+
+static gboolean
+table_interface_remove_row_selection (AtkTable *table,
+ gint row)
+{
+ return FALSE;
+}
+
+static gboolean
+table_interface_add_column_selection (AtkTable *table,
+ gint column)
+{
+ return FALSE;
+}
+
+static gboolean
+table_interface_remove_column_selection (AtkTable *table,
+ gint column)
+{
+ /* FIXME: NOT IMPLEMENTED */
+ return FALSE;
+}
+
+static AtkObject*
+table_interface_get_row_header (AtkTable *table,
+ gint row)
+{
+ /* FIXME: NOT IMPLEMENTED */
+ return NULL;
+}
+
+static AtkObject*
+table_interface_get_column_header (AtkTable *table,
+ gint in_col)
+{
+ /* FIXME: NOT IMPLEMENTED */
+ return NULL;
+}
+
+static AtkObject*
+table_interface_get_caption (AtkTable *table)
+{
+ /* FIXME: NOT IMPLEMENTED */
+ return NULL;
+}
+
+static G_CONST_RETURN gchar *
+table_interface_get_column_description (AtkTable *table, gint in_col)
+{
+ AtkGObjectAccessible *atk_gobj;
+ GObject *g_obj;
+ EaCalendarItem* ea_calitem = EA_CALENDAR_ITEM (table);
+ const gchar *description = NULL;
+ EaCellTable *cell_data;
+ gint n_columns;
+
+ atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem);
+ g_obj = atk_gobject_accessible_get_object (atk_gobj);
+ if (!g_obj)
+ return NULL;
+
+ n_columns = table_interface_get_n_columns (table);
+ if (in_col < 0 || in_col >= n_columns)
+ return NULL;
+ cell_data = ea_calendar_item_get_cell_data (ea_calitem);
+ if (!cell_data)
+ return NULL;
+
+ description = ea_cell_table_get_column_label (cell_data, in_col);
+ if (!description) {
+ gchar buffer[128] = "column description";
+ ea_calendar_item_get_column_label (ea_calitem, in_col,
+ buffer, sizeof (buffer));
+ ea_cell_table_set_column_label (cell_data, in_col, buffer);
+ description = ea_cell_table_get_column_label (cell_data,
+ in_col);
+ }
+ return description;
+}
+
+static G_CONST_RETURN gchar *
+table_interface_get_row_description (AtkTable *table, gint row)
+{
+ AtkGObjectAccessible *atk_gobj;
+ GObject *g_obj;
+ EaCalendarItem* ea_calitem = EA_CALENDAR_ITEM (table);
+ const gchar *description = NULL;
+ EaCellTable *cell_data;
+ gint n_rows;
+
+ atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem);
+ g_obj = atk_gobject_accessible_get_object (atk_gobj);
+ if (!g_obj)
+ return NULL;
+
+ n_rows = table_interface_get_n_rows (table);
+ if (row < 0 || row >= n_rows)
+ return NULL;
+ cell_data = ea_calendar_item_get_cell_data (ea_calitem);
+ if (!cell_data)
+ return NULL;
+
+ description = ea_cell_table_get_row_label (cell_data, row);
+ if (!description) {
+ gchar buffer[128] = "row description";
+ ea_calendar_item_get_row_label (ea_calitem, row,
+ buffer, sizeof (buffer));
+ ea_cell_table_set_row_label (cell_data, row, buffer);
+ description = ea_cell_table_get_row_label (cell_data,
+ row);
+ }
+ return description;
+}
+
+static AtkObject*
+table_interface_get_summary (AtkTable *table)
+{
+ /* FIXME: NOT IMPLEMENTED */
+ return NULL;
+}
+
+/* atkselection interface */
+
+static void
+atk_selection_interface_init (AtkSelectionIface *iface)
+{
+ g_return_if_fail (iface != NULL);
+
+ iface->add_selection = selection_interface_add_selection;
+ iface->clear_selection = selection_interface_clear_selection;
+ iface->ref_selection = selection_interface_ref_selection;
+ iface->get_selection_count = selection_interface_get_selection_count;
+ iface->is_child_selected = selection_interface_is_child_selected;
+}
+
+static gboolean
+selection_interface_add_selection (AtkSelection *selection, gint index)
+{
+ AtkGObjectAccessible *atk_gobj;
+ GObject *g_obj;
+ ECalendarItem *calitem;
+ EaCalendarItem* ea_calitem = EA_CALENDAR_ITEM (selection);
+ gint year, month, day;
+ GDate start_date, end_date;
+
+ atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem);
+ g_obj = atk_gobject_accessible_get_object (atk_gobj);
+ if (!g_obj)
+ return FALSE;
+
+ calitem = E_CALENDAR_ITEM (g_obj);
+ if (!e_calendar_item_get_date_for_offset (calitem, index,
+ &year, &month, &day))
+ return FALSE;
+
+ /* FIXME: not support mulit-selection */
+ g_date_set_dmy (&start_date, day, month + 1, year);
+ end_date = start_date;
+ e_calendar_item_set_selection (calitem, &start_date, &end_date);
+ return TRUE;
+}
+
+static gboolean
+selection_interface_clear_selection (AtkSelection *selection)
+{
+ AtkGObjectAccessible *atk_gobj;
+ GObject *g_obj;
+ ECalendarItem *calitem;
+ EaCalendarItem* ea_calitem = EA_CALENDAR_ITEM (selection);
+
+ atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem);
+ g_obj = atk_gobject_accessible_get_object (atk_gobj);
+ if (!g_obj)
+ return FALSE;
+
+ calitem = E_CALENDAR_ITEM (g_obj);
+ e_calendar_item_set_selection (calitem, NULL, NULL);
+
+ return TRUE;
+}
+
+static AtkObject*
+selection_interface_ref_selection (AtkSelection *selection, gint i)
+{
+ GObject *g_obj;
+ ECalendarItem *calitem;
+ EaCalendarItem* ea_calitem = EA_CALENDAR_ITEM (selection);
+ gint count, sel_offset;
+ GDate start_date, end_date;
+
+ count = selection_interface_get_selection_count (selection);
+ if (i < 0 || i >= count)
+ return NULL;
+
+ g_obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (ea_calitem));
+
+ calitem = E_CALENDAR_ITEM (g_obj);
+ if (!e_calendar_item_get_selection (calitem, &start_date, &end_date))
+ return NULL;
+ if (!e_calendar_item_get_offset_for_date (calitem,
+ g_date_get_year (&start_date),
+ g_date_get_month (&start_date) - 1,
+ g_date_get_day (&start_date),
+ &sel_offset))
+ return NULL;
+
+ return ea_calendar_item_ref_child (ATK_OBJECT (selection), sel_offset + i);
+}
+
+static gint
+selection_interface_get_selection_count (AtkSelection *selection)
+{
+ AtkGObjectAccessible *atk_gobj;
+ GObject *g_obj;
+ ECalendarItem *calitem;
+ EaCalendarItem* ea_calitem = EA_CALENDAR_ITEM (selection);
+ GDate start_date, end_date;
+
+ atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem);
+ g_obj = atk_gobject_accessible_get_object (atk_gobj);
+ if (!g_obj)
+ return 0;
+
+ calitem = E_CALENDAR_ITEM (g_obj);
+ if (e_calendar_item_get_selection (calitem, &start_date, &end_date))
+ return g_date_days_between (&start_date, &end_date) + 1;
+ else
+ return 0;
+}
+
+static gboolean
+selection_interface_is_child_selected (AtkSelection *selection, gint index)
+{
+ AtkGObjectAccessible *atk_gobj;
+ GObject *g_obj;
+ EaCalendarItem* ea_calitem = EA_CALENDAR_ITEM (selection);
+ gint row, column, n_children;
+
+ atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem);
+ g_obj = atk_gobject_accessible_get_object (atk_gobj);
+ if (!g_obj)
+ return FALSE;
+
+ n_children = atk_object_get_n_accessible_children (ATK_OBJECT (selection));
+ if (index < 0 || index >= n_children)
+ return FALSE;
+
+ row = index / EA_CALENDAR_COLUMN_NUM;
+ column = index % EA_CALENDAR_COLUMN_NUM;
+
+ return table_interface_is_selected (ATK_TABLE (selection), row, column);
+}
+
+/* callbacks */
+
+static void
+selection_preview_change_cb (ECalendarItem *calitem)
+{
+ AtkObject *atk_obj;
+ AtkObject *item_cell;
+
+ g_return_if_fail (E_IS_CALENDAR_ITEM (calitem));
+ atk_obj = atk_gobject_accessible_for_object (G_OBJECT (calitem));
+ ea_calendar_item_destory_cell_data (EA_CALENDAR_ITEM (atk_obj));
+
+ /* only deal with the first selected child, for now */
+ item_cell = atk_selection_ref_selection (ATK_SELECTION (atk_obj),
+ 0);
+
+ if (item_cell)
+ ea_calendar_set_focus_object (EA_CALENDAR_ITEM (atk_obj), item_cell);
+
+ g_signal_emit_by_name (atk_obj,
+ "active-descendant-changed",
+ item_cell);
+ g_signal_emit_by_name (atk_obj, "selection_changed");
+}
+
+static void
+date_range_changed_cb (ECalendarItem *calitem)
+{
+ AtkObject *atk_obj;
+ AtkObject *item_cell;
+
+ g_return_if_fail (E_IS_CALENDAR_ITEM (calitem));
+ atk_obj = atk_gobject_accessible_for_object (G_OBJECT (calitem));
+ ea_calendar_item_destory_cell_data (EA_CALENDAR_ITEM (atk_obj));
+
+ item_cell = atk_selection_ref_selection (ATK_SELECTION (atk_obj),
+ 0);
+ if (item_cell)
+ ea_calendar_set_focus_object (EA_CALENDAR_ITEM (atk_obj), item_cell);
+
+ g_signal_emit_by_name (atk_obj, "model_changed");
+}
+
+/* helpers */
+
+static EaCellTable *
+ea_calendar_item_get_cell_data (EaCalendarItem *ea_calitem)
+{
+ AtkGObjectAccessible *atk_gobj;
+ GObject *g_obj;
+ EaCellTable *cell_data;
+
+ g_return_val_if_fail (ea_calitem, NULL);
+
+ atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem);
+ g_obj = atk_gobject_accessible_get_object (atk_gobj);
+ if (!g_obj)
+ return NULL;
+
+ cell_data = g_object_get_data (G_OBJECT(ea_calitem),
+ "ea-calendar-cell-table");
+
+ if (!cell_data) {
+ gint n_cells = ea_calendar_item_get_n_children (ATK_OBJECT(ea_calitem));
+ cell_data = ea_cell_table_create (n_cells/EA_CALENDAR_COLUMN_NUM,
+ EA_CALENDAR_COLUMN_NUM,
+ FALSE);
+ g_object_set_data (G_OBJECT(ea_calitem),
+ "ea-calendar-cell-table", cell_data);
+ }
+ return cell_data;
+}
+
+static void
+ea_calendar_item_destory_cell_data (EaCalendarItem *ea_calitem)
+{
+ EaCellTable *cell_data;
+
+ g_return_if_fail (ea_calitem);
+
+ cell_data = g_object_get_data (G_OBJECT(ea_calitem),
+ "ea-calendar-cell-table");
+ if (cell_data) {
+ g_object_set_data (G_OBJECT(ea_calitem),
+ "ea-calendar-cell-table", NULL);
+ ea_cell_table_destroy (cell_data);
+ }
+}
+
+static gboolean
+ea_calendar_item_get_row_label (EaCalendarItem *ea_calitem, gint row,
+ gchar *buffer, gint buffer_size)
+{
+ AtkGObjectAccessible *atk_gobj;
+ GObject *g_obj;
+ ECalendarItem *calitem;
+ gint index, week_num;
+ gint year, month, day;
+
+ g_return_val_if_fail (ea_calitem, FALSE);
+
+ atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem);
+ g_obj = atk_gobject_accessible_get_object (atk_gobj);
+ if (!g_obj)
+ return FALSE;
+
+ calitem = E_CALENDAR_ITEM (g_obj);
+
+ index = atk_table_get_index_at (ATK_TABLE (ea_calitem), row, 0);
+ if (!e_calendar_item_get_date_for_offset (calitem, index,
+ &year, &month, &day))
+ return FALSE;
+
+ week_num = e_calendar_item_get_week_number (calitem,
+ day, month, year);
+
+ g_snprintf (buffer, buffer_size, "week number : %d", week_num);
+ return TRUE;
+}
+
+static gboolean
+ea_calendar_item_get_column_label (EaCalendarItem *ea_calitem, gint column,
+ gchar *buffer, gint buffer_size)
+{
+ AtkGObjectAccessible *atk_gobj;
+ GObject *g_obj;
+ ECalendarItem *calitem;
+ const gchar *abbr_name;
+
+ g_return_val_if_fail (ea_calitem, FALSE);
+
+ atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem);
+ g_obj = atk_gobject_accessible_get_object (atk_gobj);
+ if (!g_obj)
+ return FALSE;
+
+ /* Columns are 0 = Monday ... 6 = Sunday */
+ calitem = E_CALENDAR_ITEM (g_obj);
+ abbr_name = e_get_weekday_name (column + 1, TRUE);
+ g_strlcpy (buffer, abbr_name, buffer_size);
+
+ return TRUE;
+}
+
+/* the coordinate the e-calendar canvas coord */
+gboolean
+e_calendar_item_get_day_extents (ECalendarItem *calitem,
+ gint year, gint month, gint date,
+ gint *x, gint *y,
+ gint *width, gint *height)
+{
+ GnomeCanvasItem *item;
+ GtkWidget *widget;
+ GtkStyle *style;
+ PangoFontDescription *font_desc;
+ PangoContext *pango_context;
+ PangoFontMetrics *font_metrics;
+ gint char_height, xthickness, ythickness, text_y;
+ gint new_year, new_month, num_months, months_offset;
+ gint month_x, month_y, month_cell_x, month_cell_y;
+ gint month_row, month_col;
+ gint day_row, day_col;
+ gint days_from_week_start;
+
+ g_return_val_if_fail (E_IS_CALENDAR_ITEM (calitem), FALSE);
+
+ item = GNOME_CANVAS_ITEM (calitem);
+ widget = GTK_WIDGET (item->canvas);
+ style = widget->style;
+
+ /* Set up Pango prerequisites */
+ font_desc = calitem->font_desc;
+ if (!font_desc)
+ font_desc = style->font_desc;
+ pango_context = gtk_widget_get_pango_context (widget);
+ font_metrics = pango_context_get_metrics (pango_context, font_desc,
+ pango_context_get_language (pango_context));
+
+ char_height =
+ PANGO_PIXELS (pango_font_metrics_get_ascent (font_metrics)) +
+ PANGO_PIXELS (pango_font_metrics_get_descent (font_metrics));
+
+ xthickness = style->xthickness;
+ ythickness = style->ythickness;
+
+ new_year = year;
+ new_month = month;
+ e_calendar_item_normalize_date (calitem, &new_year, &new_month);
+ num_months = calitem->rows * calitem->cols;
+ months_offset = (new_year - calitem->year) * 12
+ + new_month - calitem->month;
+
+ if (months_offset > num_months || months_offset < 0)
+ return FALSE;
+
+ month_row = months_offset / calitem->cols;
+ month_col = months_offset % calitem->cols;
+
+ month_x = item->x1 + xthickness + calitem->x_offset
+ + month_col * calitem->month_width;
+ month_y = item->y1 + ythickness + month_row * calitem->month_height;
+
+ month_cell_x = month_x + E_CALENDAR_ITEM_XPAD_BEFORE_WEEK_NUMBERS
+ + calitem->month_lpad + E_CALENDAR_ITEM_XPAD_BEFORE_CELLS;
+ text_y = month_y + ythickness * 2
+ + E_CALENDAR_ITEM_YPAD_ABOVE_MONTH_NAME
+ + char_height + E_CALENDAR_ITEM_YPAD_BELOW_MONTH_NAME
+ + E_CALENDAR_ITEM_YPAD_ABOVE_DAY_LETTERS + calitem->month_tpad;
+
+ month_cell_y = text_y + char_height
+ + E_CALENDAR_ITEM_YPAD_BELOW_DAY_LETTERS + 1
+ + E_CALENDAR_ITEM_YPAD_ABOVE_CELLS;
+
+ days_from_week_start =
+ e_calendar_item_get_n_days_from_week_start (calitem, new_year,
+ new_month);
+ day_row = (date + days_from_week_start - 1) / EA_CALENDAR_COLUMN_NUM;
+ day_col = (date + days_from_week_start - 1) % EA_CALENDAR_COLUMN_NUM;
+
+ *x = month_cell_x + day_col * calitem->cell_width;
+ *y = month_cell_y + day_row * calitem->cell_height;
+ *width = calitem->cell_width;
+ *height = calitem->cell_height;
+
+ return TRUE;
+}
+
+/* month is from 0 to 11 */
+gboolean
+e_calendar_item_get_date_for_offset (ECalendarItem *calitem, gint day_offset,
+ gint *year, gint *month, gint *day)
+{
+ gint start_year, start_month, start_day;
+ gint end_year, end_month, end_day;
+ GDate *start_date;
+
+ g_return_val_if_fail (E_IS_CALENDAR_ITEM (calitem), FALSE);
+
+ if (!e_calendar_item_get_date_range (calitem, &start_year,
+ &start_month, &start_day,
+ &end_year, &end_month,
+ &end_day))
+ return FALSE;
+
+ start_date = g_date_new_dmy (start_day, start_month + 1, start_year);
+
+ g_date_add_days (start_date, day_offset);
+
+ *year = g_date_get_year (start_date);
+ *month = g_date_get_month (start_date) - 1;
+ *day = g_date_get_day (start_date);
+
+ return TRUE;
+}
+
+/* the arg month is from 0 to 11 */
+static gboolean
+e_calendar_item_get_offset_for_date (ECalendarItem *calitem,
+ gint year, gint month, gint day,
+ gint *offset)
+{
+ gint start_year, start_month, start_day;
+ gint end_year, end_month, end_day;
+ GDate *start_date, *end_date;
+
+ *offset = 0;
+ g_return_val_if_fail (E_IS_CALENDAR_ITEM (calitem), FALSE);
+
+ if (!e_calendar_item_get_date_range (calitem, &start_year,
+ &start_month, &start_day,
+ &end_year, &end_month,
+ &end_day))
+ return FALSE;
+
+ start_date = g_date_new_dmy (start_day, start_month + 1, start_year);
+ end_date = g_date_new_dmy (day, month + 1, year);
+
+ *offset = g_date_days_between (start_date, end_date);
+ g_free (start_date);
+ g_free (end_date);
+
+ return TRUE;
+}
+
+gint
+e_calendar_item_get_n_days_from_week_start (ECalendarItem *calitem,
+ gint year, gint month)
+{
+ struct tm tmp_tm;
+ gint start_weekday, days_from_week_start;
+
+ memset (&tmp_tm, 0, sizeof (tmp_tm));
+ tmp_tm.tm_year = year - 1900;
+ tmp_tm.tm_mon = month;
+ tmp_tm.tm_mday = 1;
+ tmp_tm.tm_isdst = -1;
+ mktime (&tmp_tm);
+ start_weekday = (tmp_tm.tm_wday + 6) % 7; /* 0 to 6 */
+ days_from_week_start = (start_weekday + 7 - calitem->week_start_day)
+ % 7;
+ return days_from_week_start;
+}
+
+static void
+ea_calendar_set_focus_object (EaCalendarItem *ea_calitem, AtkObject *item_cell)
+{
+ AtkStateSet *state_set, *old_state_set;
+ AtkObject *old_cell;
+
+ old_cell = (AtkObject *)g_object_get_data (G_OBJECT(ea_calitem), "gail-focus-object");
+ if (old_cell && EA_IS_CALENDAR_CELL (old_cell)) {
+ old_state_set = atk_object_ref_state_set (old_cell);
+ atk_state_set_remove_state (old_state_set, ATK_STATE_FOCUSED);
+ g_object_unref (old_state_set);
+ }
+ if (old_cell)
+ g_object_unref (old_cell);
+
+ state_set = atk_object_ref_state_set (item_cell);
+ atk_state_set_add_state (state_set, ATK_STATE_FOCUSED);
+ g_object_set_data (G_OBJECT(ea_calitem), "gail-focus-object", item_cell);
+ g_object_unref (state_set);
+}
diff --git a/widgets/misc/ea-calendar-item.h b/widgets/misc/ea-calendar-item.h
new file mode 100644
index 0000000000..36cc671a3b
--- /dev/null
+++ b/widgets/misc/ea-calendar-item.h
@@ -0,0 +1,68 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ * Bolian Yin <bolian.yin@sun.com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef __EA_CALENDAR_ITEM_H__
+#define __EA_CALENDAR_ITEM_H__
+
+#include <atk/atkgobjectaccessible.h>
+#include <misc/e-calendar-item.h>
+
+G_BEGIN_DECLS
+
+#define EA_TYPE_CALENDAR_ITEM (ea_calendar_item_get_type ())
+#define EA_CALENDAR_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EA_TYPE_CALENDAR_ITEM, EaCalendarItem))
+#define EA_CALENDAR_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EA_TYPE_CALENDAR_ITEM, EaCalendarItemClass))
+#define EA_IS_CALENDAR_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EA_TYPE_CALENDAR_ITEM))
+#define EA_IS_CALENDAR_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EA_TYPE_CALENDAR_ITEM))
+#define EA_CALENDAR_ITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EA_TYPE_CALENDAR_ITEM, EaCalendarItemClass))
+
+typedef struct _EaCalendarItem EaCalendarItem;
+typedef struct _EaCalendarItemClass EaCalendarItemClass;
+
+struct _EaCalendarItem
+{
+ AtkGObjectAccessible parent;
+};
+
+GType ea_calendar_item_get_type (void);
+
+struct _EaCalendarItemClass
+{
+ AtkGObjectAccessibleClass parent_class;
+};
+
+AtkObject *ea_calendar_item_new (GObject *obj);
+gboolean e_calendar_item_get_day_extents (ECalendarItem *calitem,
+ gint year, gint month, gint date,
+ gint *x, gint *y,
+ gint *width, gint *height);
+gboolean e_calendar_item_get_date_for_offset (ECalendarItem *calitem,
+ gint day_offset,
+ gint *year, gint *month,
+ gint *day);
+gint e_calendar_item_get_n_days_from_week_start (ECalendarItem *calitem,
+ gint year, gint month);
+
+G_END_DECLS
+
+
+#endif /* __EA_CALENDAR_ITEM_H__ */
diff --git a/widgets/misc/e-config-page.c b/widgets/misc/ea-widgets.c
index 00fb991578..9deede235e 100644
--- a/widgets/misc/e-config-page.c
+++ b/widgets/misc/ea-widgets.c
@@ -14,36 +14,19 @@
*
*
* Authors:
- * Ettore Perazzoli <ettore@ximian.com>
+ * Bolian Yin <bolian.yin@sun.com>
*
* Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
*
*/
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
+#include "a11y/ea-factory.h"
+#include "ea-calendar-item.h"
+#include "ea-widgets.h"
-#include "e-config-page.h"
+EA_FACTORY_GOBJECT (EA_TYPE_CALENDAR_ITEM, ea_calendar_item, ea_calendar_item_new)
-G_DEFINE_TYPE (EConfigPage, e_config_page, GTK_TYPE_EVENT_BOX)
-
-/* GObject methods. */
-
-static void
-e_config_page_class_init (EConfigPageClass *class)
-{
-}
-
-static void
-e_config_page_init (EConfigPage *page)
+void e_calendar_item_a11y_init (void)
{
+ EA_SET_FACTORY (e_calendar_item_get_type (), ea_calendar_item);
}
-
-GtkWidget *
-e_config_page_new (void)
-{
- return g_object_new (e_config_page_get_type (), NULL);
-}
-
-
diff --git a/widgets/table/table-test.h b/widgets/misc/ea-widgets.h
index 8b179bafdf..495222ae05 100644
--- a/widgets/table/table-test.h
+++ b/widgets/misc/ea-widgets.h
@@ -15,13 +15,18 @@
*
*
* Authors:
- * Miguel de Icaza (miguel@gnu.org)
+ * Bolian Yin <bolian.yin@sun.com>
*
* Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
*
*/
-void table_browser_test (void);
-void multi_cols_test (void);
-void check_test (void);
-void e_table_test (void);
+/* Evolution Accessibility
+*/
+
+#ifndef _EA_WIDGETS_H__
+#define _EA_WIDGETS_H__
+
+void e_calendar_item_a11y_init (void);
+
+#endif /* _EA_WIDGETS_H__ */
diff --git a/widgets/misc/test-calendar.c b/widgets/misc/test-calendar.c
index 20b8773c34..ed670a817c 100644
--- a/widgets/misc/test-calendar.c
+++ b/widgets/misc/test-calendar.c
@@ -118,7 +118,7 @@ on_date_range_changed (ECalendarItem *calitem)
start_day, start_month + 1, start_year,
end_day, end_month + 1, end_year);
- /* These days should appear bold. Remember month is 0 to 11. */
+ /* These days should windowear bold. Remember month is 0 to 11. */
e_calendar_item_mark_day (calitem, 2000, 7, 26, /* 26th Aug 2000. */
E_CALENDAR_ITEM_MARK_BOLD, FALSE);
e_calendar_item_mark_day (calitem, 2000, 8, 13, /* 13th Sep 2000. */
diff --git a/widgets/misc/test-dropdown-button.c b/widgets/misc/test-dropdown-button.c
deleted file mode 100644
index 7320fb9bac..0000000000
--- a/widgets/misc/test-dropdown-button.c
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) version 3.
- *
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- *
- * Authors:
- * Ettore Perazzoli <ettore@ximian.com>
- * Damon Chaplin <damon@ximian.com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdio.h>
-#include <gtk/gtk.h>
-
-#include <libgnomeui/gnome-app.h>
-#include <libgnomeui/gnome-app-helper.h>
-#include <libgnomeui/gnome-ui-init.h>
-
-#include "e-dropdown-button.h"
-
-
-/* (The following is shameless stolen from `testgnome.c'. */
-
-static void
-item_activated (GtkWidget *widget,
- gpointer data)
-{
- printf ("%s activated.\n", (gchar *) data);
-}
-
-static GnomeUIInfo ui_info[] = {
- { GNOME_APP_UI_ITEM, "_New", "Create a new file", item_activated, (gpointer) "file/new", NULL,
- GNOME_APP_PIXMAP_STOCK, GTK_STOCK_NEW, 'n', GDK_CONTROL_MASK, NULL },
- { GNOME_APP_UI_ITEM, "_Open...", "Open an existing file", item_activated, (gpointer) "file/open", NULL,
- GNOME_APP_PIXMAP_STOCK, GTK_STOCK_OPEN, 'o', GDK_CONTROL_MASK, NULL },
- { GNOME_APP_UI_ITEM, "_Save", "Save the current file", item_activated, (gpointer) "file/save", NULL,
- GNOME_APP_PIXMAP_STOCK, GTK_STOCK_SAVE, 's', GDK_CONTROL_MASK, NULL },
- { GNOME_APP_UI_ITEM, "Save _as...", "Save the current file with a new name", item_activated, (gpointer) "file/save as", NULL,
- GNOME_APP_PIXMAP_STOCK, GTK_STOCK_SAVE_AS, 0, 0, NULL },
-
- GNOMEUIINFO_SEPARATOR,
-
- { GNOME_APP_UI_ITEM, "_Print...", "Print the current file", item_activated, (gpointer) "file/print", NULL,
- GNOME_APP_PIXMAP_STOCK, GTK_STOCK_PRINT, 'p', GDK_CONTROL_MASK, NULL },
-
- GNOMEUIINFO_SEPARATOR,
-
- { GNOME_APP_UI_ITEM, "_Close", "Close the current file", item_activated, (gpointer) "file/close", NULL,
- GNOME_APP_PIXMAP_STOCK, GTK_STOCK_CLOSE, 0, 0, NULL },
- { GNOME_APP_UI_ITEM, "E_xit", "Exit the program", item_activated, (gpointer) "file/exit", NULL,
- GNOME_APP_PIXMAP_STOCK, GTK_STOCK_QUIT, 'q', GDK_CONTROL_MASK, NULL },
- GNOMEUIINFO_END
-};
-
-
-gint
-main (gint argc, gchar **argv)
-{
- GtkWidget *window;
- GtkWidget *menu;
- GtkWidget *dropdown_button;
-
- gnome_program_init (
- "test-dropdown-button", "0.0", LIBGNOMEUI_MODULE,
- argc, argv, GNOME_PARAM_NONE);
-
- window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
- gtk_window_set_default_size (GTK_WINDOW (window), 1, 1);
-
- menu = gtk_menu_new ();
-
- gnome_app_fill_menu (GTK_MENU_SHELL (menu), ui_info, NULL, TRUE, 0);
-
- dropdown_button = e_dropdown_button_new ("Me_nu", GTK_MENU (menu));
- gtk_container_add (GTK_CONTAINER (window), dropdown_button);
-
- gtk_widget_show (window);
- gtk_widget_show (dropdown_button);
-
- gtk_main ();
-
- return 0;
-}
diff --git a/widgets/misc/test-error.c b/widgets/misc/test-error.c
deleted file mode 100644
index a7d584bf6c..0000000000
--- a/widgets/misc/test-error.c
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) version 3.
- *
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- *
- * Authors:
- * Michael Zucchi <notzed@ximian.com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "e-error.h"
-
-gint
-main (gint argc, gchar **argv)
-{
- gtk_init (&argc, &argv);
-
- argc--;
- switch (argc) {
- case 1:
- e_error_run(NULL, argv[1], NULL);
- break;
- case 2:
- e_error_run(NULL, argv[1], argv[2], NULL);
- break;
- case 3:
- e_error_run(NULL, argv[1], argv[2], argv[3], NULL);
- break;
- case 4:
- e_error_run(NULL, argv[1], argv[2], argv[3], argv[4], NULL);
- break;
- case 5:
- e_error_run(NULL, argv[1], argv[2], argv[3], argv[4], argv[5], NULL);
- break;
- case 6:
- e_error_run(NULL, argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], NULL);
- break;
- default:
- printf("Error: too many or too few arguments\n");
- printf("Usage:\n %s domain:error-id [ args ... ]\n", argv[0]);
- }
-
- return 0;
-}
diff --git a/widgets/misc/test-info-label.c b/widgets/misc/test-info-label.c
deleted file mode 100644
index 0f292a0487..0000000000
--- a/widgets/misc/test-info-label.c
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) version 3.
- *
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- *
- * Authors:
- * Ettore Perazzoli <ettore@ximian.com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <gtk/gtk.h>
-#include "e-info-label.h"
-
-static void
-delete_event_cb (GtkWidget *widget,
- GdkEventAny *event,
- gpointer data)
-{
- gtk_main_quit ();
-}
-
-gint
-main (gint argc, gchar **argv)
-{
- GtkWidget *window;
- GtkWidget *info_label;
- GtkWidget *label;
- GtkWidget *vbox;
-
- gtk_init (&argc, &argv);
-
- window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
- gtk_window_set_title (GTK_WINDOW (window), "EInfoLabel Test");
- gtk_window_set_default_size (GTK_WINDOW (window), 400, 400);
- gtk_window_set_resizable (GTK_WINDOW (window), TRUE);
-
- g_signal_connect (window, "delete_event",
- G_CALLBACK (delete_event_cb), NULL);
-
- info_label = e_info_label_new ("stock_default-folder");
- e_info_label_set_info ((EInfoLabel *) info_label, "Component Name", "An annoyingly long component message");
- gtk_widget_show (info_label);
-
- label = gtk_label_new ("boo");
- gtk_widget_show (label);
-
- vbox = gtk_vbox_new (FALSE, 0);
- gtk_box_pack_start (GTK_BOX (vbox), info_label, FALSE, TRUE, 0);
- gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
- gtk_widget_show (vbox);
-
- gtk_container_add (GTK_CONTAINER (window), vbox);
- gtk_widget_show (window);
-
- gtk_main ();
-
- return 0;
-}
diff --git a/widgets/misc/test-multi-config-dialog.c b/widgets/misc/test-preferences-window.c
index 14327cd6ae..c5291cf755 100644
--- a/widgets/misc/test-multi-config-dialog.c
+++ b/widgets/misc/test-preferences-window.c
@@ -1,4 +1,6 @@
/*
+ * test-preferences-window.c
+ *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
@@ -13,49 +15,38 @@
* License along with the program; if not, see <http://www.gnu.org/licenses/>
*
*
- * Authors:
- * Ettore Perazzoli <ettore@ximian.com>
- *
* Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
*
*/
-#include "e-multi-config-dialog.c"
+#include "e-preferences-window.c"
#include <gtk/gtk.h>
-
#define NUM_PAGES 10
-
static void
-add_pages (EMultiConfigDialog *multi_config_dialog)
+add_pages (EPreferencesWindow *preferences_window)
{
gint i;
for (i = 0; i < NUM_PAGES; i ++) {
GtkWidget *widget;
- GtkWidget *page;
- gchar *string;
- gchar *title;
- gchar *description;
+ gchar *caption;
+ gchar *page_name;
- string = g_strdup_printf ("This is page %d", i);
- description = g_strdup_printf ("Description of page %d", i);
- title = g_strdup_printf ("Title of page %d", i);
+ caption = g_strdup_printf ("Title of page %d", i);
+ page_name = g_strdup_printf ("page-%d", i);
- widget = gtk_label_new (string);
+ widget = gtk_label_new (caption);
gtk_widget_show (widget);
- page = e_config_page_new ();
- gtk_container_add (GTK_CONTAINER (page), widget);
-
- e_multi_config_dialog_add_page (multi_config_dialog, title, description, NULL,
- E_CONFIG_PAGE (page));
+ e_preferences_window_add_page (
+ preferences_window, page_name,
+ "gtk-properties", caption, widget, i);
- g_free (string);
- g_free (title);
- g_free (description);
+ g_free (caption);
+ g_free (page_name);
}
}
@@ -69,23 +60,23 @@ delete_event_callback (GtkWidget *widget,
return TRUE;
}
-
gint
main (gint argc, gchar **argv)
{
- GtkWidget *dialog;
+ GtkWidget *window;
gtk_init (&argc, &argv);
- dialog = e_multi_config_dialog_new ();
+ window = e_preferences_window_new ();
+ gtk_window_set_default_size (GTK_WINDOW (window), 400, 300);
g_signal_connect(
- dialog, "delete-event",
+ window, "delete-event",
G_CALLBACK (delete_event_callback), NULL);
- add_pages (E_MULTI_CONFIG_DIALOG (dialog));
+ add_pages (E_PREFERENCES_WINDOW (window));
- gtk_widget_show (dialog);
+ gtk_widget_show (window);
gtk_main ();
diff --git a/widgets/table/Makefile.am b/widgets/table/Makefile.am
index 4ae0861027..7a8a5c7fab 100644
--- a/widgets/table/Makefile.am
+++ b/widgets/table/Makefile.am
@@ -1,16 +1,11 @@
-if OS_WIN32
-WIN32_BOOTSTRAP_LIBS = \
- $(top_builddir)/win32/libemiscwidgets.la \
- $(top_builddir)/win32/libetext.la
-endif
-
glade_DATA = \
e-table-config.glade \
e-table-field-chooser.glade
AM_CPPFLAGS = \
- -I$(top_srcdir) \
- -I$(top_srcdir)/widgets \
+ -I$(top_srcdir) \
+ -I$(top_srcdir)/widgets \
+ $(E_UTIL_CFLAGS) \
$(E_WIDGETS_CFLAGS) \
$(GNOME_PLATFORM_CFLAGS) \
-DEVOLUTION_GLADEDIR=\"$(gladedir)\" \
@@ -23,7 +18,9 @@ libetable_la_SOURCES = \
e-cell-checkbox.c \
e-cell-combo.c \
e-cell-date.c \
+ e-cell-date-edit.c \
e-cell-number.c \
+ e-cell-percent.c \
e-cell-pixbuf.c \
e-cell-popup.c \
e-cell-size.c \
@@ -75,7 +72,23 @@ libetable_la_SOURCES = \
e-tree-selection-model.c \
e-tree-sorted.c \
e-tree-table-adapter.c \
- e-tree.c
+ e-tree.c \
+ gal-a11y-e-cell.c \
+ gal-a11y-e-cell-popup.c \
+ gal-a11y-e-cell-registry.c \
+ gal-a11y-e-cell-text.c \
+ gal-a11y-e-cell-toggle.c \
+ gal-a11y-e-cell-tree.c \
+ gal-a11y-e-cell-vbox.c \
+ gal-a11y-e-table.c \
+ gal-a11y-e-table-click-to-add.c \
+ gal-a11y-e-table-click-to-add-factory.c \
+ gal-a11y-e-table-column-header.c \
+ gal-a11y-e-table-factory.c \
+ gal-a11y-e-table-item.c \
+ gal-a11y-e-table-item-factory.c \
+ gal-a11y-e-tree.c \
+ gal-a11y-e-tree-factory.c
libetableincludedir = $(privincludedir)/table
@@ -84,7 +97,9 @@ libetableinclude_HEADERS = \
e-cell-checkbox.h \
e-cell-combo.h \
e-cell-date.h \
+ e-cell-date-edit.h \
e-cell-number.h \
+ e-cell-percent.h \
e-cell-pixbuf.h \
e-cell-popup.h \
e-cell-size.h \
@@ -139,15 +154,34 @@ libetableinclude_HEADERS = \
e-tree-selection-model.h \
e-tree-sorted.h \
e-tree-table-adapter.h \
- e-tree.h
+ e-tree.h \
+ gal-a11y-e-cell.h \
+ gal-a11y-e-cell-popup.h \
+ gal-a11y-e-cell-registry.h \
+ gal-a11y-e-cell-text.h \
+ gal-a11y-e-cell-toggle.h \
+ gal-a11y-e-cell-tree.h \
+ gal-a11y-e-cell-vbox.h \
+ gal-a11y-e-table.h \
+ gal-a11y-e-table-click-to-add.h \
+ gal-a11y-e-table-click-to-add-factory.h \
+ gal-a11y-e-table-column-header.h \
+ gal-a11y-e-table-factory.h \
+ gal-a11y-e-table-item.h \
+ gal-a11y-e-table-item-factory.h \
+ gal-a11y-e-tree.h \
+ gal-a11y-e-tree-factory.h
libetable_la_LDFLAGS = $(NO_UNDEFINED)
libetable_la_LIBADD = \
- $(WIN32_BOOTSTRAP_LIBS) \
- $(top_builddir)/e-util/libeutil.la \
$(top_builddir)/a11y/libevolution-a11y.la \
+ $(top_builddir)/e-util/libeutil.la \
+ $(top_builddir)/widgets/misc/libemiscwidgets.la \
+ $(top_builddir)/widgets/text/libetext.la \
+ $(E_UTIL_LIBS) \
$(E_WIDGETS_LIBS) \
+ $(MATH_LIB) \
$(GNOME_PLATFORM_LIBS)
icons = \
diff --git a/widgets/table/e-cell-combo.c b/widgets/table/e-cell-combo.c
index ef1bb5bc42..9fd01f9874 100644
--- a/widgets/table/e-cell-combo.c
+++ b/widgets/table/e-cell-combo.c
@@ -62,7 +62,7 @@
#include <glib/gi18n.h>
#include "e-util/e-util.h"
-#include "misc/e-unicode.h"
+#include "e-util/e-unicode.h"
#include "e-table-item.h"
#include "e-cell-combo.h"
diff --git a/widgets/misc/e-cell-date-edit.c b/widgets/table/e-cell-date-edit.c
index 38aaf590c6..9207437cb3 100644
--- a/widgets/misc/e-cell-date-edit.c
+++ b/widgets/table/e-cell-date-edit.c
@@ -39,15 +39,15 @@
#include <gdk/gdkkeysyms.h>
#include <gtk/gtk.h>
-#include <table/e-table-item.h>
-#include <table/e-cell-text.h>
+#include "e-table-item.h"
+#include "e-cell-text.h"
#include <glib/gi18n.h>
#include <libedataserver/e-time-utils.h>
/* This depends on ECalendar which is why I didn't put it in gal. */
-#include "e-calendar.h"
+#include <misc/e-calendar.h>
static void e_cell_date_edit_destroy (GtkObject *object);
static void e_cell_date_edit_get_property (GObject *object,
diff --git a/widgets/misc/e-cell-date-edit.h b/widgets/table/e-cell-date-edit.h
index 2e125fece3..2e125fece3 100644
--- a/widgets/misc/e-cell-date-edit.h
+++ b/widgets/table/e-cell-date-edit.h
diff --git a/widgets/table/e-cell-date.c b/widgets/table/e-cell-date.c
index 6e95a1f5ea..d9dcbbea3b 100644
--- a/widgets/table/e-cell-date.c
+++ b/widgets/table/e-cell-date.c
@@ -29,7 +29,7 @@
#include <glib/gi18n.h>
#include "e-util/e-util.h"
-#include "misc/e-unicode.h"
+#include "e-util/e-unicode.h"
#include "e-cell-date.h"
diff --git a/widgets/table/e-cell-hbox.c b/widgets/table/e-cell-hbox.c
index 8fd82a9504..53d1b79934 100644
--- a/widgets/table/e-cell-hbox.c
+++ b/widgets/table/e-cell-hbox.c
@@ -32,8 +32,8 @@
#include <gtk/gtk.h>
-/* #include "a11y/e-table/gal-a11y-e-cell-registry.h" */
-/* #include "a11y/e-table/gal-a11y-e-cell-vbox.h" */
+/* #include "a11y/gal-a11y-e-cell-registry.h" */
+/* #include "a11y/gal-a11y-e-cell-vbox.h" */
#include "e-util/e-util.h"
#include "e-cell-hbox.h"
diff --git a/widgets/misc/e-cell-percent.c b/widgets/table/e-cell-percent.c
index 35dbb611ed..35dbb611ed 100644
--- a/widgets/misc/e-cell-percent.c
+++ b/widgets/table/e-cell-percent.c
diff --git a/widgets/misc/e-cell-percent.h b/widgets/table/e-cell-percent.h
index 3ac15afab7..3ac15afab7 100644
--- a/widgets/misc/e-cell-percent.h
+++ b/widgets/table/e-cell-percent.h
diff --git a/widgets/table/e-cell-popup.c b/widgets/table/e-cell-popup.c
index 8dff44914a..298f67db82 100644
--- a/widgets/table/e-cell-popup.c
+++ b/widgets/table/e-cell-popup.c
@@ -33,8 +33,8 @@
#include <gdk/gdkkeysyms.h>
-#include "a11y/e-table/gal-a11y-e-cell-popup.h"
-#include "a11y/e-table/gal-a11y-e-cell-registry.h"
+#include "gal-a11y-e-cell-popup.h"
+#include "gal-a11y-e-cell-registry.h"
#include "e-util/e-util.h"
#include "e-cell-popup.h"
diff --git a/widgets/table/e-cell-text.c b/widgets/table/e-cell-text.c
index c62e2d52c5..78065025f3 100644
--- a/widgets/table/e-cell-text.c
+++ b/widgets/table/e-cell-text.c
@@ -45,15 +45,15 @@
#include <libgnomecanvas/gnome-canvas.h>
#include <libgnomecanvas/gnome-canvas-rect-ellipse.h>
-#include "a11y/e-table/gal-a11y-e-cell-registry.h"
-#include "a11y/e-table/gal-a11y-e-cell-text.h"
+#include "gal-a11y-e-cell-registry.h"
+#include "gal-a11y-e-cell-text.h"
#include "text/e-text.h"
#include <glib/gi18n.h>
#include "e-util/e-text-event-processor.h"
#include "e-util/e-text-event-processor-emacs-like.h"
#include "e-util/e-util.h"
#include "misc/e-canvas.h"
-#include "misc/e-unicode.h"
+#include "e-util/e-unicode.h"
#include "e-cell-text.h"
#include "e-table-item.h"
diff --git a/widgets/table/e-cell-toggle.c b/widgets/table/e-cell-toggle.c
index 4057c06440..02a7425e41 100644
--- a/widgets/table/e-cell-toggle.c
+++ b/widgets/table/e-cell-toggle.c
@@ -28,8 +28,8 @@
#include <gtk/gtk.h>
#include <libgnomecanvas/gnome-canvas.h>
-#include "a11y/e-table/gal-a11y-e-cell-toggle.h"
-#include "a11y/e-table/gal-a11y-e-cell-registry.h"
+#include "gal-a11y-e-cell-toggle.h"
+#include "gal-a11y-e-cell-registry.h"
#include "e-util/e-util.h"
#include "misc/e-hsv-utils.h"
diff --git a/widgets/table/e-cell-tree.c b/widgets/table/e-cell-tree.c
index 7e7325684d..2156aa9917 100644
--- a/widgets/table/e-cell-tree.c
+++ b/widgets/table/e-cell-tree.c
@@ -38,8 +38,8 @@
#include <gtk/gtk.h>
#include <libgnomecanvas/gnome-canvas.h>
-#include "a11y/e-table/gal-a11y-e-cell-registry.h"
-#include "a11y/e-table/gal-a11y-e-cell-tree.h"
+#include "gal-a11y-e-cell-registry.h"
+#include "gal-a11y-e-cell-tree.h"
#include "e-util/e-util.h"
#include "e-cell-tree.h"
diff --git a/widgets/table/e-cell-vbox.c b/widgets/table/e-cell-vbox.c
index 3d18894530..210cc84139 100644
--- a/widgets/table/e-cell-vbox.c
+++ b/widgets/table/e-cell-vbox.c
@@ -29,8 +29,8 @@
#include <gtk/gtk.h>
-#include "a11y/e-table/gal-a11y-e-cell-registry.h"
-#include "a11y/e-table/gal-a11y-e-cell-vbox.h"
+#include "gal-a11y-e-cell-registry.h"
+#include "gal-a11y-e-cell-vbox.h"
#include "e-util/e-util.h"
#include "e-cell-vbox.h"
diff --git a/widgets/table/e-table-click-to-add.c b/widgets/table/e-table-click-to-add.c
index eceae68bc8..d2d1534611 100644
--- a/widgets/table/e-table-click-to-add.c
+++ b/widgets/table/e-table-click-to-add.c
@@ -29,7 +29,7 @@
#include <libgnomecanvas/gnome-canvas-util.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
-#include "a11y/e-table/gal-a11y-e-table-click-to-add.h"
+#include "gal-a11y-e-table-click-to-add.h"
#include "text/e-text.h"
#include <glib/gi18n.h>
#include "e-util/e-util.h"
diff --git a/widgets/table/e-table-config.c b/widgets/table/e-table-config.c
index 3a0ee849e8..cc61d1eb46 100644
--- a/widgets/table/e-table-config.c
+++ b/widgets/table/e-table-config.c
@@ -38,7 +38,7 @@
#include <glib/gi18n.h>
#include "e-util/e-util-private.h"
#include "e-util/e-util.h"
-#include "misc/e-unicode.h"
+#include "e-util/e-unicode.h"
#include "e-table-config.h"
#include "e-table-memory-store.h"
diff --git a/widgets/table/e-table-example-1.c b/widgets/table/e-table-example-1.c
deleted file mode 100644
index 39d9719b03..0000000000
--- a/widgets/table/e-table-example-1.c
+++ /dev/null
@@ -1,305 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) version 3.
- *
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- *
- * Authors:
- * Chris Lahey <clahey@ximian.com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <gdk-pixbuf/gdk-pixbuf.h>
-
-#include "gal/e-util/e-cursors.h"
-#include "e-table-simple.h"
-#include "e-table-header.h"
-#include "e-table-header-item.h"
-#include "e-table-item.h"
-#include "e-cell-text.h"
-#include "e-cell-checkbox.h"
-#include "e-table.h"
-
-#include "table-test.h"
-
-/*
- * One way in which we make it simpler to build an ETableModel is through
- * the ETableSimple class. Instead of creating your own ETableModel
- * class, you simply create a new object of the ETableSimple class. You
- * give it a bunch of functions that act as callbacks.
- *
- * You also get to pass a gpointer to ETableSimple and it gets passed to
- * your callbacks. This would be for having multiple models of the same
- * type. This is just an example though, so we statically define all the
- * data and ignore the gpointer data parameter.
- *
- * In our example we will be creating a table model with 6 columns and 10
- * rows. This corresponds to having 6 different types of information and
- * 10 different sets of data in our database.
- *
- * The headers will be hard coded, as will be the example data.
- *
- */
-
-/*
- * There are two different meanings to the word "column". The first is
- * the model column. A model column corresponds to a specific type of
- * data. This is very much like the usage in a database table where a
- * column is a field in the database.
- *
- * The second type of column is a view column. A view column
- * corresponds to a visually displayed column. Each view column
- * corresponds to a specific model column, though a model column may
- * have any number of view columns associated with it, from zero to
- * greater than one.
- *
- * Also, a view column doesn't necessarily depend on only one model
- * column. In some cases, the view column renderer can be given a
- * reference to another column to get extra information about its
- * display.
-*/
-
-#define ROWS 10
-#define COLS 4
-
-#define IMPORTANCE_COLUMN 4
-#define COLOR_COLUMN 5
-
-/*
- * Here we define the initial layout of the table. This is an xml
- * format that allows you to change the initial ordering of the
- * columns or to do sorting or grouping initially. This specification
- * shows all 5 columns, but moves the importance column nearer to the
- * front. It also sorts by the "Full Name" column (ascending.)
- * Sorting and grouping take the model column as their arguments
- * (sorting is specified by the "column" argument to the leaf elemnt.
- */
-
-#define INITIAL_SPEC "<ETableSpecification> \
- <columns-shown> \
- <column> 0 </column> \
- <column> 4 </column> \
- <column> 1 </column> \
- <column> 2 </column> \
- <column> 3 </column> \
- </columns-shown> \
- <grouping> <leaf column=\"1\" ascending=\"true\"/> </grouping> \
-</ETableSpecification>"
-
-gchar *headers [COLS] = {
- "Email",
- "Full Name",
- "Address",
- "Phone"
-};
-
-/*
- * Virtual Column list:
- * 0 Email
- * 1 Full Name
- * 2 Address
- * 3 Phone
- */
-
-gchar *table_data [ROWS] [COLS];
-
-/*
- * ETableSimple callbacks
- * These are the callbacks that define the behavior of our custom model.
- */
-
-/*
- * Since our model is a constant size, we can just return its size in
- * the column and row count fields.
- */
-
-/* This function returns the number of columns in our ETableModel. */
-static gint
-my_col_count (ETableModel *etc, gpointer data)
-{
- return COLS;
-}
-
-/* This function returns the number of rows in our ETableModel. */
-static gint
-my_row_count (ETableModel *etc, gpointer data)
-{
- return ROWS;
-}
-
-/* This function returns the value at a particular point in our ETableModel. */
-static gpointer
-my_value_at (ETableModel *etc, gint col, gint row, gpointer data)
-{
- return (gpointer) table_data [row] [col];
-}
-
-/* This function sets the value at a particular point in our ETableModel. */
-static void
-my_set_value_at (ETableModel *etc, gint col, gint row, gconstpointer val, gpointer data)
-{
- g_free (table_data [row] [col]);
- table_data [row] [col] = g_strdup (val);
-}
-
-/* This function returns whether a particular cell is editable. */
-static gboolean
-my_is_cell_editable (ETableModel *etc, gint col, gint row, gpointer data)
-{
- return TRUE;
-}
-
-/* This function duplicates the value passed to it. */
-static gpointer
-my_duplicate_value (ETableModel *etc, gint col, gconstpointer value, gpointer data)
-{
- return g_strdup (value);
-}
-
-/* This function frees the value passed to it. */
-static void
-my_free_value (ETableModel *etc, gint col, gpointer value, gpointer data)
-{
- g_free (value);
-}
-
-/* This function creates an empty value. */
-static gpointer
-my_initialize_value (ETableModel *etc, gint col, gpointer data)
-{
- return g_strdup ("");
-}
-
-/* This function reports if a value is empty. */
-static gboolean
-my_value_is_empty (ETableModel *etc, gint col, gconstpointer value, gpointer data)
-{
- return !(value && *(gchar *)value);
-}
-
-/* This function reports if a value is empty. */
-static gchar *
-my_value_to_string (ETableModel *etc, gint col, gconstpointer value, gpointer data)
-{
- return g_strdup(value);
-}
-
-/* We create a window containing our new table. */
-static void
-create_table (void)
-{
- GtkWidget *e_table, *window, *frame;
- ECell *cell_left_just;
- ETableHeader *e_table_header;
- gint i, j;
- ETableModel *e_table_model = NULL;
-
- /* First we fill in the simple data. */
- for (i = 0; i < ROWS; i++){
- for (j = 0; j < COLS; j++)
- table_data [i] [j] = g_strdup ("");
- }
- /* Next we create our model. This uses the functions we defined
- earlier. */
- e_table_model = e_table_simple_new (
- my_col_count, my_row_count, my_value_at,
- my_set_value_at, my_is_cell_editable,
- my_duplicate_value, my_free_value,
- my_initialize_value, my_value_is_empty,
- my_value_to_string,
- NULL);
- /*
- * Next we create a header. The ETableHeader is used in two
- * different way. The first is the full_header. This is the
- * list of possible columns in the view. The second use is
- * completely internal. Many of the ETableHeader functions are
- * for that purpose. The only functions we really need are
- * e_table_header_new and e_table_header_add_col.
- *
- * First we create the header.
- */
- e_table_header = e_table_header_new ();
-
- /*
- * Next we have to build renderers for all of the columns.
- * Since all our columns are text columns, we can simply use
- * the same renderer over and over again. If we had different
- * types of columns, we could use a different renderer for
- * each column.
- */
- cell_left_just = e_cell_text_new (e_table_model, NULL, GTK_JUSTIFY_LEFT);
-
- /*
- * Next we create a column object for each view column and add
- * them to the header. We don't create a column object for
- * the importance column since it will not be shown.
- */
- for (i = 0; i < COLS; i++) {
- /* Create the column. */
- ETableCol *ecol = e_table_col_new (
- i, headers [i],
- 1.0, 20, cell_left_just,
- g_str_compare, TRUE);
- /* Add it to the header. */
- e_table_header_add_column (e_table_header, ecol, i);
- }
-
- /*
- * Here we create a window for our new table. This window
- * will get shown and the person will be able to test their
- * item.
- */
- window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
-
- /* This frame is simply to get a bevel around our table. */
- frame = gtk_frame_new (NULL);
-
- /*
- * Here we create the table. We give it the three pieces of
- * the table we've created, the header, the model, and the
- * initial layout. It does the rest.
- */
- e_table = e_table_new (e_table_header, e_table_model, INITIAL_SPEC);
-
- /* Build the gtk widget hierarchy. */
- gtk_container_add (GTK_CONTAINER (frame), e_table);
- gtk_container_add (GTK_CONTAINER (window), frame);
-
- /* Size the initial window. */
- gtk_widget_set_size_request (window, 200, 200);
-
- /* Show it all. */
- gtk_widget_show_all (window);
-}
-
-/* This is the main function which just initializes gnome and call our create_table function */
-
-gint
-main (gint argc, gchar *argv [])
-{
- gnome_init ("TableExample", "TableExample", argc, argv);
- e_cursors_init ();
-
- gtk_widget_push_colormap (gdk_rgb_get_colormap ());
-
- create_table ();
-
- gtk_main ();
-
- e_cursors_shutdown ();
- return 0;
-}
-
diff --git a/widgets/table/e-table-group-container.c b/widgets/table/e-table-group-container.c
index 1ba845e2c3..29cd2b94d7 100644
--- a/widgets/table/e-table-group-container.c
+++ b/widgets/table/e-table-group-container.c
@@ -31,7 +31,7 @@
#include "e-util/e-util.h"
#include "misc/e-canvas-utils.h"
#include "misc/e-canvas.h"
-#include "misc/e-unicode.h"
+#include "e-util/e-unicode.h"
#include "e-table-defines.h"
#include "e-table-group-container.h"
diff --git a/widgets/table/e-table-header-item.c b/widgets/table/e-table-header-item.c
index 67695e87b3..190fccb846 100644
--- a/widgets/table/e-table-header-item.c
+++ b/widgets/table/e-table-header-item.c
@@ -913,7 +913,10 @@ ethi_unrealize (GnomeCanvasItem *item)
{
ETableHeaderItem *ethi = E_TABLE_HEADER_ITEM (item);
- pango_font_description_free (ethi->font_desc);
+ if (ethi->font_desc != NULL) {
+ pango_font_description_free (ethi->font_desc);
+ ethi->font_desc = NULL;
+ }
g_signal_handler_disconnect (item->canvas, ethi->drag_motion_id);
g_signal_handler_disconnect (item->canvas, ethi->drag_leave_id);
diff --git a/widgets/table/e-table-header-utils.c b/widgets/table/e-table-header-utils.c
index bfc6768817..5d6ed5cb36 100644
--- a/widgets/table/e-table-header-utils.c
+++ b/widgets/table/e-table-header-utils.c
@@ -29,7 +29,7 @@
#include <gtk/gtk.h>
-#include "misc/e-unicode.h"
+#include "e-util/e-unicode.h"
#include "e-table-defines.h"
#include "e-table-header-utils.h"
diff --git a/widgets/table/e-table-item.c b/widgets/table/e-table-item.c
index e5eb2f2d11..7448a355f7 100644
--- a/widgets/table/e-table-item.c
+++ b/widgets/table/e-table-item.c
@@ -36,8 +36,8 @@
#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>
-#include "a11y/e-table/gal-a11y-e-table-item-factory.h"
-#include "a11y/e-table/gal-a11y-e-table-item.h"
+#include "gal-a11y-e-table-item-factory.h"
+#include "gal-a11y-e-table-item.h"
#include <glib/gi18n.h>
#include "e-util/e-util.h"
#include "misc/e-canvas.h"
diff --git a/widgets/table/e-table-tree.h b/widgets/table/e-table-tree.h
deleted file mode 100644
index 178c2a3ba2..0000000000
--- a/widgets/table/e-table-tree.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) version 3.
- *
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- *
- * Authors:
- * Chris Lahey <clahey@ximian.com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-#ifndef _E_TABLE_TREE_H_
-#define _E_TABLE_TREE_H_
-
-#include <table/e-table-model.h>
-
-G_BEGIN_DECLS
-
-typedef struct {
- gchar *title;
-
- union {
- ETableModel *table;
- GList *children;
- } u;
-
- guint expanded :1;
- guint is_leaf :1;
-} ETableGroup;
-
-ETableGroup *e_table_group_new (const gchar *title, ETableModel *table);
-ETableGroup *e_table_group_new_leaf (const gchar *title);
-
-G_END_DECLS
-
-#endif /* _E_TABLE_TREE_H_ */
diff --git a/widgets/table/e-table-utils.c b/widgets/table/e-table-utils.c
index 784f1f5b66..03c8e17a33 100644
--- a/widgets/table/e-table-utils.c
+++ b/widgets/table/e-table-utils.c
@@ -27,7 +27,7 @@
#include <string.h>
#include "e-util/e-util.h"
-#include "misc/e-unicode.h"
+#include "e-util/e-unicode.h"
#include "e-table-utils.h"
#include "e-table-header-utils.h"
diff --git a/widgets/table/e-table.c b/widgets/table/e-table.c
index 703f645527..bf18fbb224 100644
--- a/widgets/table/e-table.c
+++ b/widgets/table/e-table.c
@@ -36,13 +36,13 @@
#include <libgnomecanvas/gnome-canvas.h>
#include <libgnomecanvas/gnome-canvas-rect-ellipse.h>
-#include "a11y/e-table/gal-a11y-e-table.h"
+#include "gal-a11y-e-table.h"
#include <glib/gi18n.h>
#include "e-util/e-util.h"
#include "misc/e-canvas.h"
#include "misc/e-canvas-background.h"
#include "misc/e-canvas-vbox.h"
-#include "misc/e-unicode.h"
+#include "e-util/e-unicode.h"
#include "e-table.h"
#include "e-table-click-to-add.h"
diff --git a/widgets/table/e-tree.c b/widgets/table/e-tree.c
index 92b79fefd3..dd07b2b536 100644
--- a/widgets/table/e-tree.c
+++ b/widgets/table/e-tree.c
@@ -30,7 +30,7 @@
#include <gtk/gtk.h>
#include <libgnomecanvas/gnome-canvas-rect-ellipse.h>
-#include "a11y/e-table/gal-a11y-e-tree.h"
+#include "gal-a11y-e-tree.h"
#include <glib/gi18n.h>
#include "e-util/e-util.h"
#include "misc/e-canvas.h"
diff --git a/widgets/table/gal-a11y-e-cell-popup.c b/widgets/table/gal-a11y-e-cell-popup.c
new file mode 100644
index 0000000000..141ce172a4
--- /dev/null
+++ b/widgets/table/gal-a11y-e-cell-popup.c
@@ -0,0 +1,144 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ * Yang Wu <yang.wu@sun.com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#include <config.h>
+
+#include <gdk/gdkkeysyms.h>
+#include <gtk/gtk.h>
+
+#include "a11y/gal-a11y-util.h"
+#include "table/e-cell-popup.h"
+#include <glib/gi18n.h>
+
+#include "gal-a11y-e-cell-popup.h"
+#include "gal-a11y-e-cell-registry.h"
+
+static AtkObjectClass *parent_class = NULL;
+#define PARENT_TYPE (gal_a11y_e_cell_get_type ())
+
+static void gal_a11y_e_cell_popup_class_init (GalA11yECellPopupClass *klass);
+static void popup_cell_action (GalA11yECell *cell);
+
+/**
+ * gal_a11y_e_cell_popup_get_type:
+ * @void:
+ *
+ * Registers the &GalA11yECellPopup class if necessary, and returns the type ID
+ * associated to it.
+ *
+ * Return value: The type ID of the &GalA11yECellPopup class.
+ **/
+GType
+gal_a11y_e_cell_popup_get_type (void)
+{
+ static GType type = 0;
+
+ if (!type) {
+ GTypeInfo info = {
+ sizeof (GalA11yECellPopupClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) gal_a11y_e_cell_popup_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+ sizeof (GalA11yECellPopup),
+ 0,
+ (GInstanceInitFunc) NULL,
+ NULL /* value_cell_popup */
+ };
+
+ type = g_type_register_static (PARENT_TYPE, "GalA11yECellPopup", &info, 0);
+ gal_a11y_e_cell_type_add_action_interface (type);
+ }
+
+ return type;
+}
+
+static void
+gal_a11y_e_cell_popup_class_init (GalA11yECellPopupClass *klass)
+{
+ parent_class = g_type_class_ref (PARENT_TYPE);
+}
+
+AtkObject *
+gal_a11y_e_cell_popup_new (ETableItem *item,
+ ECellView *cell_view,
+ AtkObject *parent,
+ gint model_col,
+ gint view_col,
+ gint row)
+{
+ AtkObject *a11y;
+ GalA11yECell *cell;
+ ECellPopup *popupcell;
+ ECellView* child_view = NULL;
+
+ popupcell= E_CELL_POPUP(cell_view->ecell);
+
+ if (popupcell && popupcell->popup_cell_view)
+ child_view = popupcell->popup_cell_view->child_view;
+
+ if (child_view && child_view->ecell) {
+ a11y = gal_a11y_e_cell_registry_get_object (NULL,
+ item,
+ child_view,
+ parent,
+ model_col,
+ view_col,
+ row);
+ } else {
+ a11y = g_object_new (GAL_A11Y_TYPE_E_CELL_POPUP, NULL);
+ gal_a11y_e_cell_construct (a11y,
+ item,
+ cell_view,
+ parent,
+ model_col,
+ view_col,
+ row);
+ }
+ g_return_val_if_fail (a11y != NULL, NULL);
+ cell = GAL_A11Y_E_CELL(a11y);
+ gal_a11y_e_cell_add_action (cell,
+ _("popup"), /* action name*/
+ _("popup a child"), /* action description */
+ "<Alt>Down", /* action keybinding */
+ popup_cell_action);
+
+ a11y->role = ATK_ROLE_TABLE_CELL;
+ return a11y;
+}
+
+static void
+popup_cell_action (GalA11yECell *cell)
+{
+ gint finished;
+ GdkEvent event;
+
+ event.key.type = GDK_KEY_PRESS;
+ event.key.window = GTK_LAYOUT(GNOME_CANVAS_ITEM(cell->item)->canvas)->bin_window;;
+ event.key.send_event = TRUE;
+ event.key.time = GDK_CURRENT_TIME;
+ event.key.state = GDK_MOD1_MASK;
+ event.key.keyval = GDK_Down;
+
+ g_signal_emit_by_name (cell->item, "event", &event, &finished);
+}
diff --git a/widgets/table/gal-a11y-e-cell-popup.h b/widgets/table/gal-a11y-e-cell-popup.h
new file mode 100644
index 0000000000..641d345308
--- /dev/null
+++ b/widgets/table/gal-a11y-e-cell-popup.h
@@ -0,0 +1,62 @@
+/*
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ * Yang Wu <yang.wu@sun.com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef __GAL_A11Y_E_CELL_POPUP_H__
+#define __GAL_A11Y_E_CELL_POPUP_H__
+
+#include <glib-object.h>
+#include <table/e-table-item.h>
+#include <table/gal-a11y-e-cell.h>
+#include <atk/atkgobjectaccessible.h>
+
+#define GAL_A11Y_TYPE_E_CELL_POPUP (gal_a11y_e_cell_popup_get_type ())
+#define GAL_A11Y_E_CELL_POPUP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAL_A11Y_TYPE_E_CELL_POPUP, GalA11yECellPopup))
+#define GAL_A11Y_E_CELL_POPUP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAL_A11Y_TYPE_E_CELL_POPUP, GalA11yECellPopupClass))
+#define GAL_A11Y_IS_E_CELL_POPUP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAL_A11Y_TYPE_E_CELL_POPUP))
+#define GAL_A11Y_IS_E_CELL_POPUP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAL_A11Y_TYPE_E_CELL_POPUP))
+
+typedef struct _GalA11yECellPopup GalA11yECellPopup;
+typedef struct _GalA11yECellPopupClass GalA11yECellPopupClass;
+
+/* This struct should actually be larger as this isn't what we derive from.
+ * The GalA11yECellPopupPrivate comes right after the parent class structure.
+ **/
+struct _GalA11yECellPopup {
+ GalA11yECell object;
+};
+
+struct _GalA11yECellPopupClass {
+ GalA11yECellClass parent_class;
+};
+
+
+/* Standard Glib function */
+GType gal_a11y_e_cell_popup_get_type (void);
+AtkObject *gal_a11y_e_cell_popup_new (ETableItem *item,
+ ECellView *cell_view,
+ AtkObject *parent,
+ gint model_col,
+ gint view_col,
+ gint row);
+
+#endif /* ! __GAL_A11Y_E_CELL_POPUP_H__ */
diff --git a/widgets/table/gal-a11y-e-cell-registry.c b/widgets/table/gal-a11y-e-cell-registry.c
new file mode 100644
index 0000000000..9dc9598608
--- /dev/null
+++ b/widgets/table/gal-a11y-e-cell-registry.c
@@ -0,0 +1,149 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ * Christopher James Lahey <clahey@ximian.com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#include <config.h>
+
+#include "gal-a11y-e-cell.h"
+#include "gal-a11y-e-cell-registry.h"
+
+static GObjectClass *parent_class;
+static GalA11yECellRegistry *default_registry;
+#define PARENT_TYPE (G_TYPE_OBJECT)
+
+struct _GalA11yECellRegistryPrivate {
+ GHashTable *table;
+};
+
+/* Static functions */
+
+static void
+gal_a11y_e_cell_registry_finalize (GObject *obj)
+{
+ GalA11yECellRegistry *registry = GAL_A11Y_E_CELL_REGISTRY (obj);
+
+ g_hash_table_destroy (registry->priv->table);
+ g_free (registry->priv);
+
+ G_OBJECT_CLASS (parent_class)->finalize (obj);
+}
+
+static void
+gal_a11y_e_cell_registry_class_init (GalA11yECellRegistryClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ parent_class = g_type_class_ref (PARENT_TYPE);
+
+ object_class->finalize = gal_a11y_e_cell_registry_finalize;
+}
+
+static void
+gal_a11y_e_cell_registry_init (GalA11yECellRegistry *registry)
+{
+ registry->priv = g_new (GalA11yECellRegistryPrivate, 1);
+ registry->priv->table = g_hash_table_new (NULL, NULL);
+}
+
+/**
+ * gal_a11y_e_cell_registry_get_type:
+ * @void:
+ *
+ * Registers the &GalA11yECellRegistry class if necessary, and returns the type ID
+ * associated to it.
+ *
+ * Return value: The type ID of the &GalA11yECellRegistry class.
+ **/
+GType
+gal_a11y_e_cell_registry_get_type (void)
+{
+ static GType type = 0;
+
+ if (!type) {
+ GTypeInfo info = {
+ sizeof (GalA11yECellRegistryClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) gal_a11y_e_cell_registry_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+ sizeof (GalA11yECellRegistry),
+ 0,
+ (GInstanceInitFunc) gal_a11y_e_cell_registry_init,
+ NULL /* value_cell */
+ };
+
+ type = g_type_register_static (PARENT_TYPE, "GalA11yECellRegistry", &info, 0);
+ }
+
+ return type;
+}
+
+static void
+init_default_registry (void)
+{
+ if (default_registry == NULL) {
+ default_registry = g_object_new (gal_a11y_e_cell_registry_get_type(), NULL);
+ }
+}
+
+
+AtkObject *
+gal_a11y_e_cell_registry_get_object (GalA11yECellRegistry *registry,
+ ETableItem *item,
+ ECellView *cell_view,
+ AtkObject *parent,
+ gint model_col,
+ gint view_col,
+ gint row)
+{
+ GalA11yECellRegistryFunc func = NULL;
+ GType type;
+
+ if (registry == NULL) {
+ init_default_registry ();
+ registry = default_registry;
+ }
+
+ type = GTK_OBJECT_TYPE (cell_view->ecell);
+ while (func == NULL && type != 0) {
+ func = g_hash_table_lookup (registry->priv->table, GINT_TO_POINTER (type));
+ type = g_type_parent (type);
+ }
+
+ if (func)
+ return func (item, cell_view, parent, model_col, view_col, row);
+ else
+ return gal_a11y_e_cell_new (item, cell_view, parent, model_col, view_col, row);
+}
+
+void
+gal_a11y_e_cell_registry_add_cell_type (GalA11yECellRegistry *registry,
+ GType type,
+ GalA11yECellRegistryFunc func)
+{
+ if (registry == NULL) {
+ init_default_registry ();
+ registry = default_registry;
+ }
+
+ g_hash_table_insert (registry->priv->table, GINT_TO_POINTER (type), func);
+}
diff --git a/widgets/table/gal-a11y-e-cell-registry.h b/widgets/table/gal-a11y-e-cell-registry.h
new file mode 100644
index 0000000000..0620fd1b9c
--- /dev/null
+++ b/widgets/table/gal-a11y-e-cell-registry.h
@@ -0,0 +1,72 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ * Christopher James Lahey <clahey@ximian.com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef __GAL_A11Y_E_CELL_REGISTRY_H__
+#define __GAL_A11Y_E_CELL_REGISTRY_H__
+
+#include <glib-object.h>
+#include <atk/atkobject.h>
+#include <table/e-table-item.h>
+#include <table/e-cell.h>
+
+#define GAL_A11Y_TYPE_E_CELL_REGISTRY (gal_a11y_e_cell_registry_get_type ())
+#define GAL_A11Y_E_CELL_REGISTRY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAL_A11Y_TYPE_E_CELL_REGISTRY, GalA11yECellRegistry))
+#define GAL_A11Y_E_CELL_REGISTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAL_A11Y_TYPE_E_CELL_REGISTRY, GalA11yECellRegistryClass))
+#define GAL_A11Y_IS_E_CELL_REGISTRY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAL_A11Y_TYPE_E_CELL_REGISTRY))
+#define GAL_A11Y_IS_E_CELL_REGISTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAL_A11Y_TYPE_E_CELL_REGISTRY))
+
+typedef struct _GalA11yECellRegistry GalA11yECellRegistry;
+typedef struct _GalA11yECellRegistryClass GalA11yECellRegistryClass;
+typedef struct _GalA11yECellRegistryPrivate GalA11yECellRegistryPrivate;
+
+typedef AtkObject *(*GalA11yECellRegistryFunc) (ETableItem *item,
+ ECellView *cell_view,
+ AtkObject *parent,
+ gint model_col,
+ gint view_col,
+ gint row);
+
+struct _GalA11yECellRegistry {
+ GObject object;
+
+ GalA11yECellRegistryPrivate *priv;
+};
+
+struct _GalA11yECellRegistryClass {
+ GObjectClass parent_class;
+};
+
+
+/* Standard Glib function */
+GType gal_a11y_e_cell_registry_get_type (void);
+AtkObject *gal_a11y_e_cell_registry_get_object (GalA11yECellRegistry *registry,
+ ETableItem *item,
+ ECellView *cell_view,
+ AtkObject *parent,
+ gint model_col,
+ gint view_col,
+ gint row);
+void gal_a11y_e_cell_registry_add_cell_type (GalA11yECellRegistry *registry,
+ GType type,
+ GalA11yECellRegistryFunc func);
+
+#endif /* ! __GAL_A11Y_E_CELL_REGISTRY_H__ */
diff --git a/widgets/table/gal-a11y-e-cell-text.c b/widgets/table/gal-a11y-e-cell-text.c
new file mode 100644
index 0000000000..77823b0a7c
--- /dev/null
+++ b/widgets/table/gal-a11y-e-cell-text.c
@@ -0,0 +1,737 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ * Christopher James Lahey <clahey@ximian.com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#include <config.h>
+
+#include <string.h>
+
+#include <atk/atk.h>
+
+#include "a11y/gal-a11y-util.h"
+#include "table/e-cell-text.h"
+#include <glib/gi18n.h>
+
+#include "gal-a11y-e-cell-text.h"
+
+#define CS_CLASS(a11y) (G_TYPE_INSTANCE_GET_CLASS ((a11y), C_TYPE_STREAM, GalA11yECellTextClass))
+static AtkObjectClass *parent_class;
+#define PARENT_TYPE (gal_a11y_e_cell_get_type ())
+
+/* Static functions */
+static void
+ect_dispose (GObject *object)
+{
+ GObjectClass *g_class;
+ GalA11yECell *gaec = GAL_A11Y_E_CELL (object);
+ GalA11yECellText *gaet = GAL_A11Y_E_CELL_TEXT (object);
+
+ if (gaet->inserted_id != 0) {
+ ECellText *ect = E_CELL_TEXT (gaec->cell_view->ecell);
+
+ if (ect) {
+ g_signal_handler_disconnect (ect, gaet->inserted_id);
+ g_signal_handler_disconnect (ect, gaet->deleted_id);
+ }
+
+ gaet->inserted_id = 0;
+ gaet->deleted_id = 0;
+ }
+
+ g_class = (GObjectClass *)parent_class;
+ if (g_class->dispose)
+ g_class->dispose (object);
+
+}
+
+static gboolean
+ect_check (gpointer a11y)
+{
+ GalA11yECell *gaec = GAL_A11Y_E_CELL (a11y);
+ ETableItem *item = gaec->item;
+
+ g_return_val_if_fail ((gaec->item != NULL), FALSE);
+ g_return_val_if_fail ((gaec->cell_view != NULL), FALSE);
+ g_return_val_if_fail ((gaec->cell_view->ecell != NULL), FALSE);
+
+ if (atk_state_set_contains_state (gaec->state_set, ATK_STATE_DEFUNCT))
+ return FALSE;
+
+ if (gaec->row < 0 || gaec->row >= item->rows
+ || gaec->view_col <0 || gaec->view_col >= item->cols
+ || gaec->model_col <0 || gaec->model_col >= e_table_model_column_count (item->table_model))
+ return FALSE;
+
+ if (!E_IS_CELL_TEXT (gaec->cell_view->ecell))
+ return FALSE;
+
+ return TRUE;
+}
+
+static G_CONST_RETURN gchar *
+ect_get_name (AtkObject * a11y)
+{
+ GalA11yECell *gaec;
+ gchar *name;
+
+ if (!ect_check (a11y))
+ return NULL;
+
+ gaec = GAL_A11Y_E_CELL (a11y);
+ name = e_cell_text_get_text_by_view (gaec->cell_view, gaec->model_col, gaec->row);
+ if (name != NULL) {
+ ATK_OBJECT_CLASS (parent_class)->set_name (a11y, name);
+ g_free (name);
+ }
+
+ if (a11y->name != NULL && strcmp (a11y->name, "")) {
+ return a11y->name;
+ } else {
+ return parent_class->get_name (a11y);
+ }
+}
+
+static gchar *
+ect_get_text (AtkText *text,
+ gint start_offset,
+ gint end_offset)
+{
+ GalA11yECell *gaec = GAL_A11Y_E_CELL (text);
+ gchar *full_text;
+ gchar *ret_val;
+
+ if (!ect_check (text))
+ return NULL;
+
+ full_text = e_cell_text_get_text_by_view (gaec->cell_view, gaec->model_col, gaec->row);
+
+ if (end_offset == -1)
+ end_offset = strlen (full_text);
+ else
+ end_offset = g_utf8_offset_to_pointer (full_text, end_offset) - full_text;
+
+ start_offset = g_utf8_offset_to_pointer (full_text, start_offset) - full_text;
+
+ ret_val = g_strndup (full_text + start_offset, end_offset - start_offset);
+
+ g_free (full_text);
+
+ return ret_val;
+}
+
+static gchar *
+ect_get_text_after_offset (AtkText *text,
+ gint offset,
+ AtkTextBoundary boundary_type,
+ gint *start_offset,
+ gint *end_offset)
+{
+ /* Unimplemented */
+ return NULL;
+}
+
+static gchar *
+ect_get_text_at_offset (AtkText *text,
+ gint offset,
+ AtkTextBoundary boundary_type,
+ gint *start_offset,
+ gint *end_offset)
+{
+ /* Unimplemented */
+ return NULL;
+}
+
+static gunichar
+ect_get_character_at_offset (AtkText *text,
+ gint offset)
+{
+ GalA11yECell *gaec = GAL_A11Y_E_CELL (text);
+ gunichar ret_val;
+ gchar *at_offset;
+ gchar *full_text;
+
+ if (!ect_check (text))
+ return -1;
+
+ full_text = e_cell_text_get_text_by_view (gaec->cell_view, gaec->model_col, gaec->row);
+ at_offset = g_utf8_offset_to_pointer (full_text, offset);
+ ret_val = g_utf8_get_char_validated (at_offset, -1);
+ g_free (full_text);
+
+ return ret_val;
+}
+
+
+static gchar *
+ect_get_text_before_offset (AtkText *text,
+ gint offset,
+ AtkTextBoundary boundary_type,
+ gint *start_offset,
+ gint *end_offset)
+{
+ /* Unimplemented */
+ return NULL;
+}
+
+
+static gint
+ect_get_caret_offset (AtkText *text)
+{
+ GalA11yECell *gaec = GAL_A11Y_E_CELL (text);
+ gint start, end;
+
+ if (!ect_check (text))
+ return -1;
+
+ if (e_cell_text_get_selection (gaec->cell_view,
+ gaec->view_col, gaec->row,
+ &start, &end)) {
+ gchar *full_text = e_cell_text_get_text_by_view (gaec->cell_view, gaec->model_col, gaec->row);
+ end = g_utf8_pointer_to_offset (full_text, full_text + end);
+ g_free (full_text);
+
+ return end;
+ }
+ else
+ return -1;
+}
+
+static AtkAttributeSet*
+ect_get_run_attributes (AtkText *text,
+ gint offset,
+ gint *start_offset,
+ gint *end_offset)
+{
+ /* Unimplemented */
+ return NULL;
+}
+
+
+static AtkAttributeSet*
+ect_get_default_attributes (AtkText *text)
+{
+ /* Unimplemented */
+ return NULL;
+}
+
+
+static void
+ect_get_character_extents (AtkText *text,
+ gint offset,
+ gint *x,
+ gint *y,
+ gint *width,
+ gint *height,
+ AtkCoordType coords)
+{
+ /* Unimplemented */
+}
+
+
+static gint
+ect_get_character_count (AtkText *text)
+{
+ GalA11yECell *gaec = GAL_A11Y_E_CELL (text);
+ gint ret_val;
+ gchar *full_text;
+
+ if (!ect_check (text))
+ return -1;
+
+ full_text = e_cell_text_get_text_by_view (gaec->cell_view, gaec->model_col, gaec->row);
+
+ ret_val = g_utf8_strlen (full_text, -1);
+ g_free (full_text);
+ return ret_val;
+}
+
+
+static gint
+ect_get_offset_at_point (AtkText *text,
+ gint x,
+ gint y,
+ AtkCoordType coords)
+{
+ /* Unimplemented */
+ return 0;
+}
+
+
+static gint
+ect_get_n_selections (AtkText *text)
+{
+ GalA11yECell *gaec = GAL_A11Y_E_CELL (text);
+ gint selection_start, selection_end;
+
+ if (!ect_check (text))
+ return 0;
+
+ if (e_cell_text_get_selection (gaec->cell_view,
+ gaec->view_col, gaec->row,
+ &selection_start,
+ &selection_end)
+ && selection_start != selection_end)
+ return 1;
+ return 0;
+}
+
+
+static gchar *
+ect_get_selection (AtkText *text,
+ gint selection_num,
+ gint *start_offset,
+ gint *end_offset)
+{
+ GalA11yECell *gaec = GAL_A11Y_E_CELL (text);
+ gchar *ret_val;
+ gint selection_start, selection_end;
+
+ if (selection_num == 0
+ && e_cell_text_get_selection (gaec->cell_view,
+ gaec->view_col, gaec->row,
+ &selection_start,
+ &selection_end)
+ && selection_start != selection_end) {
+ gint real_start, real_end, len;
+ gchar *full_text = e_cell_text_get_text_by_view (gaec->cell_view, gaec->model_col, gaec->row);
+ len = strlen (full_text);
+ real_start = MIN (selection_start, selection_end);
+ real_end = MAX (selection_start, selection_end);
+ real_start = MIN (MAX (0, real_start), len);
+ real_end = MIN (MAX (0, real_end), len);
+
+ ret_val = g_strndup (full_text + real_start, real_end - real_start);
+
+ real_start = g_utf8_pointer_to_offset (full_text, full_text + real_start);
+ real_end = g_utf8_pointer_to_offset (full_text, full_text + real_end);
+
+ if (start_offset)
+ *start_offset = real_start;
+ if (end_offset)
+ *end_offset = real_end;
+ g_free (full_text);
+ } else {
+ if (start_offset)
+ *start_offset = 0;
+ if (end_offset)
+ *end_offset = 0;
+ ret_val = NULL;
+ }
+
+ return ret_val;
+}
+
+
+static gboolean
+ect_add_selection (AtkText *text,
+ gint start_offset,
+ gint end_offset)
+{
+ GalA11yECell *gaec = GAL_A11Y_E_CELL (text);
+
+ if (start_offset != end_offset) {
+ gint real_start, real_end, len;
+ gchar *full_text =
+ e_cell_text_get_text_by_view (gaec->cell_view, gaec->model_col, gaec->row);
+
+ len = g_utf8_strlen (full_text, -1);
+ if (end_offset == -1)
+ end_offset = len;
+
+ real_start = MIN (start_offset, end_offset);
+ real_end = MAX (start_offset, end_offset);
+
+ real_start = MIN (MAX (0, real_start), len);
+ real_end = MIN (MAX (0, real_end), len);
+
+ real_start = g_utf8_offset_to_pointer (full_text, real_start) - full_text;
+ real_end = g_utf8_offset_to_pointer (full_text, real_end) - full_text;
+ g_free (full_text);
+
+ if (e_cell_text_set_selection (gaec->cell_view,
+ gaec->view_col, gaec->row,
+ real_start, real_end)) {
+ g_signal_emit_by_name (ATK_OBJECT(text), "text_selection_changed");
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+
+static gboolean
+ect_remove_selection (AtkText *text,
+ gint selection_num)
+{
+ GalA11yECell *gaec = GAL_A11Y_E_CELL (text);
+ gint selection_start, selection_end;
+
+ if (selection_num == 0
+ && e_cell_text_get_selection (gaec->cell_view,
+ gaec->view_col, gaec->row,
+ &selection_start,
+ &selection_end)
+ && selection_start != selection_end
+ && e_cell_text_set_selection (gaec->cell_view,
+ gaec->view_col, gaec->row,
+ selection_end, selection_end)) {
+ g_signal_emit_by_name (ATK_OBJECT(text), "text_selection_changed");
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+
+static gboolean
+ect_set_selection (AtkText *text,
+ gint selection_num,
+ gint start_offset,
+ gint end_offset)
+{
+ if (selection_num == 0) {
+ atk_text_add_selection (text, start_offset, end_offset);
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+
+static gboolean
+ect_set_caret_offset (AtkText *text,
+ gint offset)
+{
+ GalA11yECell *gaec = GAL_A11Y_E_CELL (text);
+ gchar *full_text;
+ gint len;
+
+ full_text = e_cell_text_get_text_by_view (gaec->cell_view, gaec->model_col, gaec->row);
+
+ len = g_utf8_strlen (full_text, -1);
+ if (offset == -1)
+ offset = len;
+ else
+ offset = MIN (MAX (0, offset), len);
+
+ offset = g_utf8_offset_to_pointer (full_text, offset) - full_text;
+
+ g_free (full_text);
+
+ return e_cell_text_set_selection (gaec->cell_view,
+ gaec->view_col, gaec->row,
+ offset, offset);
+}
+
+static gboolean
+ect_set_run_attributes (AtkEditableText *text,
+ AtkAttributeSet *attrib_set,
+ gint start_offset,
+ gint end_offset)
+{
+ /* Unimplemented */
+ return FALSE;
+}
+
+static void
+ect_set_text_contents (AtkEditableText *text,
+ const gchar *string)
+{
+ GalA11yECell *gaec = GAL_A11Y_E_CELL (text);
+ ECellText *ect = E_CELL_TEXT (gaec->cell_view->ecell);
+
+ e_cell_text_set_value (ect, gaec->item->table_model, gaec->model_col, gaec->row, string);
+ e_table_item_enter_edit (gaec->item, gaec->view_col, gaec->row);
+}
+
+static void
+ect_insert_text (AtkEditableText *text,
+ const gchar *string,
+ gint length,
+ gint *position)
+{
+ /* Utf8 unimplemented */
+ GalA11yECell *gaec = GAL_A11Y_E_CELL (text);
+ ECellText *ect = E_CELL_TEXT (gaec->cell_view->ecell);
+
+ gchar *full_text = e_cell_text_get_text_by_view (gaec->cell_view, gaec->model_col, gaec->row);
+ gchar *result = g_strdup_printf ("%.*s%.*s%s", *position, full_text, length, string, full_text + *position);
+
+ e_cell_text_set_value (ect, gaec->item->table_model, gaec->model_col, gaec->row, result);
+
+ *position += length;
+
+ g_free (result);
+ g_free (full_text);
+}
+
+static void
+ect_copy_text (AtkEditableText *text,
+ gint start_pos,
+ gint end_pos)
+{
+ GalA11yECell *gaec = GAL_A11Y_E_CELL (text);
+ if (start_pos != end_pos
+ && atk_text_set_selection (ATK_TEXT (text), 0, start_pos, end_pos))
+ e_cell_text_copy_clipboard (gaec->cell_view,
+ gaec->view_col, gaec->row);
+}
+
+static void
+ect_delete_text (AtkEditableText *text,
+ gint start_pos,
+ gint end_pos)
+{
+ GalA11yECell *gaec = GAL_A11Y_E_CELL (text);
+ if (start_pos != end_pos
+ && atk_text_set_selection (ATK_TEXT (text), 0, start_pos, end_pos))
+ e_cell_text_delete_selection (gaec->cell_view,
+ gaec->view_col, gaec->row);
+}
+
+static void
+ect_cut_text (AtkEditableText *text,
+ gint start_pos,
+ gint end_pos)
+{
+ ect_copy_text (text, start_pos, end_pos);
+ ect_delete_text (text, start_pos, end_pos);
+}
+
+static void
+ect_paste_text (AtkEditableText *text,
+ gint position)
+{
+ GalA11yECell *gaec = GAL_A11Y_E_CELL (text);
+
+ e_table_item_enter_edit (gaec->item, gaec->view_col, gaec->row);
+
+ if (atk_text_set_caret_offset (ATK_TEXT (text), position))
+ e_cell_text_paste_clipboard (gaec->cell_view,
+ gaec->view_col, gaec->row);
+}
+
+static void
+ect_do_action_edit (AtkAction *action)
+{
+ GalA11yECell *a11y = GAL_A11Y_E_CELL (action);
+ ETableModel *e_table_model = a11y->item->table_model;
+
+ if (e_table_model_is_cell_editable(e_table_model, a11y->model_col, a11y->row)) {
+ e_table_item_enter_edit (a11y->item, a11y->view_col, a11y->row);
+ }
+}
+
+/* text signal handlers */
+static void
+ect_text_inserted_cb (ECellText *text, ECellView *cell_view, gint pos, gint len, gint row, gint model_col, gpointer data)
+{
+ GalA11yECellText *gaet;
+ GalA11yECell *gaec;
+
+ if (!ect_check (data))
+ return;
+ gaet = GAL_A11Y_E_CELL_TEXT (data);
+ gaec = GAL_A11Y_E_CELL (data);
+
+ if (cell_view == gaec->cell_view && row == gaec->row && model_col == gaec->model_col) {
+ g_signal_emit_by_name (gaet, "text_changed::insert", pos, len);
+
+ }
+}
+
+static void
+ect_text_deleted_cb (ECellText *text, ECellView *cell_view, gint pos, gint len, gint row, gint model_col, gpointer data)
+{
+ GalA11yECellText *gaet;
+ GalA11yECell *gaec;
+ if (!ect_check (data))
+ return;
+ gaet = GAL_A11Y_E_CELL_TEXT (data);
+ gaec = GAL_A11Y_E_CELL (data);
+ if (cell_view == gaec->cell_view && row == gaec->row && model_col == gaec->model_col) {
+ g_signal_emit_by_name (gaet, "text_changed::delete", pos, len);
+ }
+}
+
+static void
+ect_atk_text_iface_init (AtkTextIface *iface)
+{
+ iface->get_text = ect_get_text;
+ iface->get_text_after_offset = ect_get_text_after_offset;
+ iface->get_text_at_offset = ect_get_text_at_offset;
+ iface->get_character_at_offset = ect_get_character_at_offset;
+ iface->get_text_before_offset = ect_get_text_before_offset;
+ iface->get_caret_offset = ect_get_caret_offset;
+ iface->get_run_attributes = ect_get_run_attributes;
+ iface->get_default_attributes = ect_get_default_attributes;
+ iface->get_character_extents = ect_get_character_extents;
+ iface->get_character_count = ect_get_character_count;
+ iface->get_offset_at_point = ect_get_offset_at_point;
+ iface->get_n_selections = ect_get_n_selections;
+ iface->get_selection = ect_get_selection;
+ iface->add_selection = ect_add_selection;
+ iface->remove_selection = ect_remove_selection;
+ iface->set_selection = ect_set_selection;
+ iface->set_caret_offset = ect_set_caret_offset;
+}
+
+static void
+ect_atk_editable_text_iface_init (AtkEditableTextIface *iface)
+{
+ iface->set_run_attributes = ect_set_run_attributes;
+ iface->set_text_contents = ect_set_text_contents;
+ iface->insert_text = ect_insert_text;
+ iface->copy_text = ect_copy_text;
+ iface->cut_text = ect_cut_text;
+ iface->delete_text = ect_delete_text;
+ iface->paste_text = ect_paste_text;
+}
+
+static void
+ect_class_init (GalA11yECellTextClass *klass)
+{
+ AtkObjectClass *a11y = ATK_OBJECT_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ parent_class = g_type_class_ref (PARENT_TYPE);
+ a11y->get_name = ect_get_name;
+ object_class->dispose = ect_dispose;
+}
+
+static void
+ect_action_init (GalA11yECellText *a11y)
+{
+ GalA11yECell *gaec = GAL_A11Y_E_CELL (a11y);
+ ECellText *ect = E_CELL_TEXT (gaec->cell_view->ecell);
+ if (ect->editable && e_table_model_is_cell_editable (gaec->cell_view->e_table_model, gaec->model_col, gaec->row))
+ gal_a11y_e_cell_add_action (gaec,
+ _("edit"),
+ _("begin editing this cell"),
+ NULL,
+ (ACTION_FUNC) ect_do_action_edit);
+}
+
+/**
+ * gal_a11y_e_cell_text_get_type:
+ * @void:
+ *
+ * Registers the &GalA11yECellText class if necessary, and returns the type ID
+ * associated to it.
+ *
+ * Return value: The type ID of the &GalA11yECellText class.
+ **/
+GType
+gal_a11y_e_cell_text_get_type (void)
+{
+ static GType type = 0;
+
+ if (!type) {
+ GTypeInfo info = {
+ sizeof (GalA11yECellTextClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) ect_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+ sizeof (GalA11yECellText),
+ 0,
+ (GInstanceInitFunc) NULL,
+ NULL /* value_cell_text */
+ };
+
+ static const GInterfaceInfo atk_text_info = {
+ (GInterfaceInitFunc) ect_atk_text_iface_init,
+ (GInterfaceFinalizeFunc) NULL,
+ NULL
+ };
+
+ static const GInterfaceInfo atk_editable_text_info = {
+ (GInterfaceInitFunc) ect_atk_editable_text_iface_init,
+ (GInterfaceFinalizeFunc) NULL,
+ NULL
+ };
+
+ type = g_type_register_static (PARENT_TYPE, "GalA11yECellText", &info, 0);
+ g_type_add_interface_static (type, ATK_TYPE_TEXT, &atk_text_info);
+ g_type_add_interface_static (type, ATK_TYPE_EDITABLE_TEXT, &atk_editable_text_info);
+ gal_a11y_e_cell_type_add_action_interface (type);
+ }
+
+ return type;
+}
+
+static void
+cell_text_destroyed (gpointer data)
+{
+ g_return_if_fail (GAL_A11Y_IS_E_CELL_TEXT (data));
+
+ g_object_unref (data);
+}
+
+AtkObject *
+gal_a11y_e_cell_text_new (ETableItem *item,
+ ECellView *cell_view,
+ AtkObject *parent,
+ gint model_col,
+ gint view_col,
+ gint row)
+{
+ AtkObject *a11y;
+ GalA11yECell *gaec;
+ GalA11yECellText *gaet;
+ ECellText *ect;
+
+ a11y = g_object_new (gal_a11y_e_cell_text_get_type (), NULL);
+
+ gal_a11y_e_cell_construct (a11y,
+ item,
+ cell_view,
+ parent,
+ model_col,
+ view_col,
+ row);
+ gaet = GAL_A11Y_E_CELL_TEXT (a11y);
+
+ /* will be unrefed in cell_text_destroyed */
+ g_object_ref (a11y);
+
+ gaet->inserted_id = g_signal_connect (E_CELL_TEXT (((ECellView *)cell_view)->ecell),
+ "text_inserted", G_CALLBACK (ect_text_inserted_cb), a11y);
+ gaet->deleted_id = g_signal_connect (E_CELL_TEXT (((ECellView *)cell_view)->ecell),
+ "text_deleted", G_CALLBACK (ect_text_deleted_cb), a11y);
+
+ g_object_weak_ref (G_OBJECT (((ECellView *)cell_view)->ecell),
+ (GWeakNotify) cell_text_destroyed,
+ a11y);
+
+ ect_action_init (gaet);
+
+ ect = E_CELL_TEXT (cell_view->ecell);
+ gaec = GAL_A11Y_E_CELL (a11y);
+ if (ect->editable && e_table_model_is_cell_editable (gaec->cell_view->e_table_model, gaec->model_col, gaec->row))
+ gal_a11y_e_cell_add_state (gaec, ATK_STATE_EDITABLE, FALSE);
+ else
+ gal_a11y_e_cell_remove_state (gaec, ATK_STATE_EDITABLE, FALSE);
+
+ return a11y;
+}
diff --git a/widgets/table/gal-a11y-e-cell-text.h b/widgets/table/gal-a11y-e-cell-text.h
new file mode 100644
index 0000000000..bb400b38e3
--- /dev/null
+++ b/widgets/table/gal-a11y-e-cell-text.h
@@ -0,0 +1,64 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ * Christopher James Lahey <clahey@ximian.com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef __GAL_A11Y_E_CELL_TEXT_H__
+#define __GAL_A11Y_E_CELL_TEXT_H__
+
+#include <glib-object.h>
+#include <table/e-table-item.h>
+#include <table/e-cell-text.h>
+#include <table/gal-a11y-e-cell.h>
+
+#define GAL_A11Y_TYPE_E_CELL_TEXT (gal_a11y_e_cell_text_get_type ())
+#define GAL_A11Y_E_CELL_TEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAL_A11Y_TYPE_E_CELL_TEXT, GalA11yECellText))
+#define GAL_A11Y_E_CELL_TEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAL_A11Y_TYPE_E_CELL_TEXT, GalA11yECellTextClass))
+#define GAL_A11Y_IS_E_CELL_TEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAL_A11Y_TYPE_E_CELL_TEXT))
+#define GAL_A11Y_IS_E_CELL_TEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAL_A11Y_TYPE_E_CELL_TEXT))
+
+typedef struct _GalA11yECellText GalA11yECellText;
+typedef struct _GalA11yECellTextClass GalA11yECellTextClass;
+typedef struct _GalA11yECellTextPrivate GalA11yECellTextPrivate;
+
+/* This struct should actually be larger as this isn't what we derive from.
+ * The GalA11yECellTextPrivate comes right after the parent class structure.
+ **/
+struct _GalA11yECellText {
+ GalA11yECell object;
+ gint inserted_id;
+ gint deleted_id;
+};
+
+struct _GalA11yECellTextClass {
+ GalA11yECellClass parent_class;
+};
+
+
+/* Standard Glib function */
+GType gal_a11y_e_cell_text_get_type (void);
+AtkObject *gal_a11y_e_cell_text_new (ETableItem *item,
+ ECellView *cell_view,
+ AtkObject *parent,
+ gint model_col,
+ gint view_col,
+ gint row);
+
+#endif /* ! __GAL_A11Y_E_CELL_TEXT_H__ */
diff --git a/widgets/table/gal-a11y-e-cell-toggle.c b/widgets/table/gal-a11y-e-cell-toggle.c
new file mode 100644
index 0000000000..df687f4005
--- /dev/null
+++ b/widgets/table/gal-a11y-e-cell-toggle.c
@@ -0,0 +1,191 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#include <gtk/gtk.h>
+
+#include "table/e-cell-toggle.h"
+#include "table/e-table-model.h"
+#include <glib/gi18n.h>
+
+#include "gal-a11y-e-cell-toggle.h"
+
+#define PARENT_TYPE (gal_a11y_e_cell_get_type ())
+static GObjectClass *parent_class;
+
+static void gal_a11y_e_cell_toggle_class_init (GalA11yECellToggleClass *klass);
+
+static void
+gal_a11y_e_cell_toggle_dispose (GObject *object)
+{
+ GalA11yECellToggle *a11y = GAL_A11Y_E_CELL_TOGGLE (object);
+
+ ETableModel *e_table_model = GAL_A11Y_E_CELL (a11y)->item->table_model;
+
+ if (e_table_model && a11y->model_id > 0) {
+ g_signal_handler_disconnect (e_table_model, a11y->model_id);
+ a11y->model_id = 0;
+ }
+
+ if (parent_class->dispose)
+ parent_class->dispose (object);
+}
+
+GType
+gal_a11y_e_cell_toggle_get_type (void)
+{
+ static GType type = 0;
+
+ if (!type)
+ {
+ static const GTypeInfo tinfo =
+ {
+ sizeof (GalA11yECellToggleClass),
+ (GBaseInitFunc) NULL, /* base init */
+ (GBaseFinalizeFunc) NULL, /* base finalize */
+ (GClassInitFunc) gal_a11y_e_cell_toggle_class_init, /* class init */
+ (GClassFinalizeFunc) NULL, /* class finalize */
+ NULL, /* class data */
+ sizeof (GalA11yECellToggle), /* instance size */
+ 0, /* nb preallocs */
+ NULL, /* instance init */
+ NULL /* value table */
+ };
+
+
+ type = g_type_register_static (GAL_A11Y_TYPE_E_CELL,
+ "GalA11yECellToggle", &tinfo, 0);
+ gal_a11y_e_cell_type_add_action_interface (type);
+
+ }
+ return type;
+}
+
+
+static void
+gal_a11y_e_cell_toggle_class_init (GalA11yECellToggleClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->dispose = gal_a11y_e_cell_toggle_dispose;
+ parent_class = g_type_class_ref (PARENT_TYPE);
+}
+
+static void
+toggle_cell_action (GalA11yECell *cell)
+{
+ gint finished;
+ GdkEventButton event;
+ gint x, y, width, height;
+ gint row, col;
+
+ row = cell->row;
+ col = cell->view_col;
+
+ e_table_item_get_cell_geometry (cell->item, &row, &col,
+ &x, &y, &width, &height);
+
+ event.x = x + width / 2 + (gint)(GNOME_CANVAS_ITEM (cell->item)->x1);
+ event.y = y + height / 2 + (gint)(GNOME_CANVAS_ITEM (cell->item)->y1);
+
+ event.type = GDK_BUTTON_PRESS;
+ event.window = GTK_LAYOUT(GNOME_CANVAS_ITEM(cell->item)->canvas)->bin_window;
+ event.button = 1;
+ event.send_event = TRUE;
+ event.time = GDK_CURRENT_TIME;
+ event.axes = NULL;
+
+ g_signal_emit_by_name (cell->item, "event", &event, &finished);
+}
+
+static void
+model_change_cb (ETableModel *etm,
+ gint col,
+ gint row,
+ GalA11yECell *cell)
+{
+ gint value;
+
+ if (col == cell->model_col && row == cell->row) {
+
+ value = GPOINTER_TO_INT (
+ e_table_model_value_at (cell->cell_view->e_table_model,
+ cell->model_col, cell->row));
+ /* Cheat gnopernicus, or it will ignore the state change signal */
+ atk_focus_tracker_notify (ATK_OBJECT (cell));
+
+ if (value)
+ gal_a11y_e_cell_add_state (cell, ATK_STATE_CHECKED, TRUE);
+ else
+ gal_a11y_e_cell_remove_state (cell, ATK_STATE_CHECKED, TRUE);
+ }
+}
+
+
+AtkObject*
+gal_a11y_e_cell_toggle_new (ETableItem *item,
+ ECellView *cell_view,
+ AtkObject *parent,
+ gint model_col,
+ gint view_col,
+ gint row)
+{
+ AtkObject *a11y;
+ GalA11yECell *cell;
+ GalA11yECellToggle *toggle_cell;
+ gint value;
+
+ a11y = ATK_OBJECT(g_object_new (GAL_A11Y_TYPE_E_CELL_TOGGLE, NULL));
+
+ g_return_val_if_fail (a11y != NULL, NULL);
+
+ cell = GAL_A11Y_E_CELL(a11y);
+ toggle_cell = GAL_A11Y_E_CELL_TOGGLE(a11y);
+ a11y->role = ATK_ROLE_TABLE_CELL;
+
+ gal_a11y_e_cell_construct (a11y,
+ item,
+ cell_view,
+ parent,
+ model_col,
+ view_col,
+ row);
+
+ gal_a11y_e_cell_add_action (cell,
+ _("toggle"), /* action name*/
+ _("toggle the cell"), /* action description */
+ NULL, /* action keybinding */
+ toggle_cell_action);
+
+ toggle_cell->model_id = g_signal_connect (item->table_model,
+ "model_cell_changed",
+ (GCallback) model_change_cb,
+ a11y);
+
+ value = GPOINTER_TO_INT (
+ e_table_model_value_at (cell->cell_view->e_table_model,
+ cell->model_col, cell->row));
+ if (value)
+ gal_a11y_e_cell_add_state (cell, ATK_STATE_CHECKED, FALSE);
+ else
+ gal_a11y_e_cell_remove_state (cell, ATK_STATE_CHECKED, FALSE);
+
+ return a11y;
+}
diff --git a/widgets/table/gal-a11y-e-cell-toggle.h b/widgets/table/gal-a11y-e-cell-toggle.h
new file mode 100644
index 0000000000..8e9b4def08
--- /dev/null
+++ b/widgets/table/gal-a11y-e-cell-toggle.h
@@ -0,0 +1,64 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef __GAL_A11Y_E_CELL_TOGGLE_H__
+#define __GAL_A11Y_E_CELL_TOGGLE_H__
+
+#include <atk/atk.h>
+#include "gal-a11y-e-cell.h"
+#include "gal-a11y-e-cell-toggle.h"
+
+G_BEGIN_DECLS
+
+#define GAL_A11Y_TYPE_E_CELL_TOGGLE (gal_a11y_e_cell_toggle_get_type ())
+#define GAL_A11Y_E_CELL_TOGGLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAL_A11Y_TYPE_E_CELL_TOGGLE, GalA11yECellToggle))
+#define GAL_A11Y_E_CELL_TOGGLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAL_A11Y_E_CELL_TOGGLE, GalA11yECellToggleClass))
+#define GAL_A11Y_IS_E_CELL_TOGGLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAL_A11Y_TYPE_E_CELL_TOGGLE))
+#define GAL_A11Y_IS_E_CELL_TOGGLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAL_A11Y_TYPE_E_CELL_TOGGLE))
+#define GAL_A11Y_E_CELL_TOGGLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GAL_A11Y_TYPE_E_CELL_TOGGLE, GalA11yECellToggleClass))
+
+typedef struct _GalA11yECellToggle GalA11yECellToggle;
+typedef struct _GalA11yECellToggleClass GalA11yECellToggleClass;
+
+struct _GalA11yECellToggle
+{
+ GalA11yECell parent;
+ gint model_id;
+};
+
+GType gal_a11y_e_cell_toggle_get_type (void);
+
+struct _GalA11yECellToggleClass
+{
+ GalA11yECellClass parent_class;
+};
+
+AtkObject *gal_a11y_e_cell_toggle_new (ETableItem *item,
+ ECellView *cell_view,
+ AtkObject *parent,
+ gint model_col,
+ gint view_col,
+ gint row);
+
+G_END_DECLS
+
+
+#endif /* __GAL_A11Y_E_CELL_TOGGLE_H__ */
diff --git a/widgets/table/gal-a11y-e-cell-tree.c b/widgets/table/gal-a11y-e-cell-tree.c
new file mode 100644
index 0000000000..aaf490c726
--- /dev/null
+++ b/widgets/table/gal-a11y-e-cell-tree.c
@@ -0,0 +1,260 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ * Tim Wo <tim.wo@sun.com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#include <config.h>
+
+#include <atk/atk.h>
+
+#include "a11y/gal-a11y-util.h"
+#include "table/e-cell-tree.h"
+#include "table/e-table.h"
+#include "table/e-tree-table-adapter.h"
+#include <glib/gi18n.h>
+
+#include "gal-a11y-e-cell-tree.h"
+#include "gal-a11y-e-cell-registry.h"
+
+#define CS_CLASS(a11y) (G_TYPE_INSTANCE_GET_CLASS ((a11y), C_TYPE_STREAM, GalA11yECellTreeClass))
+static AtkObjectClass *a11y_parent_class;
+#define A11Y_PARENT_TYPE (gal_a11y_e_cell_get_type ())
+
+#define d(x)
+
+static void
+ectr_model_row_changed_cb (ETableModel *etm,
+ gint row,
+ GalA11yECell *a11y)
+{
+ ETreePath node;
+ ETreeModel *tree_model;
+ ETreeTableAdapter *tree_table_adapter;
+
+ g_return_if_fail (a11y);
+ if (a11y->row != row)
+ return;
+
+ node = e_table_model_value_at (etm, -1, a11y->row);
+ tree_model = e_table_model_value_at (etm, -2, a11y->row);
+ tree_table_adapter = e_table_model_value_at (etm, -3, a11y->row);
+
+ if (e_tree_model_node_is_expandable (tree_model, node)) {
+ gboolean is_exp = e_tree_table_adapter_node_is_expanded (tree_table_adapter, node);
+ if (is_exp)
+ gal_a11y_e_cell_add_state (a11y, ATK_STATE_EXPANDED, TRUE);
+ else
+ gal_a11y_e_cell_remove_state (a11y, ATK_STATE_EXPANDED, TRUE);
+ }
+}
+
+static void
+kill_view_cb(ECellView *subcell_view,
+ gpointer psubcell_a11ies)
+{
+ GList *node;
+ GList *subcell_a11ies = (GList *) psubcell_a11ies;
+ GalA11yECell *subcell;
+
+ for (node = subcell_a11ies; node != NULL; node = g_list_next (node))
+ {
+ subcell = GAL_A11Y_E_CELL(node->data);
+ if (subcell && subcell->cell_view == subcell_view)
+ {
+ d(fprintf(stderr, "subcell_view %p deleted before the a11y object %p\n", subcell_view, subcell));
+ subcell->cell_view = NULL;
+ }
+ }
+}
+
+static void
+ectr_subcell_weak_ref (GalA11yECellTree *a11y,
+ GalA11yECell *subcell_a11y)
+{
+ ECellView *subcell_view = subcell_a11y ? subcell_a11y->cell_view : NULL;
+ if (subcell_a11y && subcell_view && subcell_view->kill_view_cb_data)
+ subcell_view->kill_view_cb_data = g_list_remove(subcell_view->kill_view_cb_data, subcell_a11y);
+
+ g_signal_handler_disconnect (GAL_A11Y_E_CELL (a11y)->item->table_model,
+ a11y->model_row_changed_id);
+ g_object_unref (a11y);
+}
+
+static void
+ectr_do_action_expand (AtkAction *action)
+{
+ GalA11yECell *a11y;
+ ETableModel *table_model;
+ ETreePath node;
+ ETreeModel *tree_model;
+ ETreeTableAdapter *tree_table_adapter;
+
+ a11y = GAL_A11Y_E_CELL (action);
+ table_model = a11y->item->table_model;
+ node = e_table_model_value_at (table_model, -1, a11y->row);
+ tree_model = e_table_model_value_at (table_model, -2, a11y->row);
+ tree_table_adapter = e_table_model_value_at (table_model, -3, a11y->row);
+
+ if (e_tree_model_node_is_expandable (tree_model, node)) {
+ e_tree_table_adapter_node_set_expanded (tree_table_adapter,
+ node,
+ TRUE);
+ gal_a11y_e_cell_add_state (a11y, ATK_STATE_EXPANDED, TRUE);
+ }
+}
+
+static void
+ectr_do_action_collapse (AtkAction *action)
+{
+ GalA11yECell *a11y;
+ ETableModel *table_model;
+ ETreePath node;
+ ETreeModel *tree_model;
+ ETreeTableAdapter *tree_table_adapter;
+
+ a11y = GAL_A11Y_E_CELL (action);
+ table_model = a11y->item->table_model;
+ node = e_table_model_value_at (table_model, -1, a11y->row);
+ tree_model = e_table_model_value_at (table_model, -2, a11y->row);
+ tree_table_adapter = e_table_model_value_at (table_model, -3, a11y->row);
+
+ if (e_tree_model_node_is_expandable (tree_model, node)) {
+ e_tree_table_adapter_node_set_expanded (tree_table_adapter,
+ node,
+ FALSE);
+ gal_a11y_e_cell_remove_state (a11y, ATK_STATE_EXPANDED, TRUE);
+ }
+}
+
+static void
+ectr_class_init (GalA11yECellTreeClass *klass)
+{
+ a11y_parent_class = g_type_class_ref (A11Y_PARENT_TYPE);
+}
+
+static void
+ectr_init (GalA11yECellTree *a11y)
+{
+}
+
+GType
+gal_a11y_e_cell_tree_get_type (void)
+{
+ static GType type = 0;
+
+ if (!type) {
+ GTypeInfo info = {
+ sizeof (GalA11yECellTreeClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) ectr_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+ sizeof (GalA11yECellTree),
+ 0,
+ (GInstanceInitFunc) ectr_init,
+ NULL /* value_cell_text */
+ };
+
+ type = g_type_register_static (A11Y_PARENT_TYPE, "GalA11yECellTree", &info, 0);
+ gal_a11y_e_cell_type_add_action_interface (type);
+ }
+
+ return type;
+}
+
+AtkObject *
+gal_a11y_e_cell_tree_new (ETableItem *item,
+ ECellView *cell_view,
+ AtkObject *parent,
+ gint model_col,
+ gint view_col,
+ gint row)
+{
+ AtkObject *subcell_a11y;
+ GalA11yECellTree *a11y;
+
+ ETreePath node;
+ ETreeModel *tree_model;
+ ETreeTableAdapter *tree_table_adapter;
+
+ ECellView *subcell_view;
+ subcell_view = e_cell_tree_view_get_subcell_view (cell_view);
+
+ if (subcell_view->ecell) {
+ subcell_a11y = gal_a11y_e_cell_registry_get_object (NULL,
+ item,
+ subcell_view,
+ parent,
+ model_col,
+ view_col,
+ row);
+ gal_a11y_e_cell_add_action (GAL_A11Y_E_CELL (subcell_a11y),
+ _("expand"),
+ _("expands the row in the ETree containing this cell"),
+ NULL,
+ (ACTION_FUNC)ectr_do_action_expand);
+
+ gal_a11y_e_cell_add_action (GAL_A11Y_E_CELL (subcell_a11y),
+ _("collapse"),
+ _("collapses the row in the ETree containing this cell"),
+ NULL,
+ (ACTION_FUNC)ectr_do_action_collapse);
+
+ /* init AtkStates for the cell's a11y object */
+ node = e_table_model_value_at (item->table_model, -1, row);
+ tree_model = e_table_model_value_at (item->table_model, -2, row);
+ tree_table_adapter = e_table_model_value_at (item->table_model, -3, row);
+ if (e_tree_model_node_is_expandable (tree_model, node)) {
+ gal_a11y_e_cell_add_state (GAL_A11Y_E_CELL (subcell_a11y), ATK_STATE_EXPANDABLE, FALSE);
+ if (e_tree_table_adapter_node_is_expanded (tree_table_adapter, node))
+ gal_a11y_e_cell_add_state (GAL_A11Y_E_CELL (subcell_a11y), ATK_STATE_EXPANDED, FALSE);
+ }
+ }
+ else
+ subcell_a11y = NULL;
+
+ /* create a companion a11y object, this object has type GalA11yECellTree
+ and it connects to some signals to determine whether a tree cell is
+ expanded or collapsed */
+ a11y = g_object_new (gal_a11y_e_cell_tree_get_type (), NULL);
+ gal_a11y_e_cell_construct (ATK_OBJECT (a11y),
+ item,
+ cell_view,
+ parent,
+ model_col,
+ view_col,
+ row);
+ a11y->model_row_changed_id =
+ g_signal_connect (item->table_model, "model_row_changed",
+ G_CALLBACK (ectr_model_row_changed_cb),
+ subcell_a11y);
+
+ if (subcell_a11y && subcell_view)
+ {
+ subcell_view->kill_view_cb = kill_view_cb;
+ if (!g_list_find(subcell_view->kill_view_cb_data, subcell_a11y))
+ subcell_view->kill_view_cb_data = g_list_append(subcell_view->kill_view_cb_data, subcell_a11y);
+ }
+
+ g_object_weak_ref (G_OBJECT (subcell_a11y), (GWeakNotify) ectr_subcell_weak_ref, a11y);
+
+ return subcell_a11y;
+}
diff --git a/widgets/table/gal-a11y-e-cell-tree.h b/widgets/table/gal-a11y-e-cell-tree.h
new file mode 100644
index 0000000000..497590b351
--- /dev/null
+++ b/widgets/table/gal-a11y-e-cell-tree.h
@@ -0,0 +1,64 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ * Tim Wo <tim.wo@sun.com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef __GAL_A11Y_E_CELL_TREE_H__
+#define __GAL_A11Y_E_CELL_TREE_H__
+
+#include <glib-object.h>
+#include <table/e-table-item.h>
+#include <table/e-cell-tree.h>
+#include "gal-a11y-e-cell.h"
+
+#define GAL_A11Y_TYPE_E_CELL_TREE (gal_a11y_e_cell_tree_get_type ())
+#define GAL_A11Y_E_CELL_TREE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAL_A11Y_TYPE_E_CELL_TREE, GalA11yECellTree))
+#define GAL_A11Y_E_CELL_TREE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAL_A11Y_TYPE_E_CELL_TREE, GalA11yECellTreeClass))
+#define GAL_A11Y_IS_E_CELL_TREE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAL_A11Y_TYPE_E_CELL_TREE))
+#define GAL_A11Y_IS_E_CELL_TREE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAL_A11Y_TYPE_E_CELL_TREE))
+
+typedef struct _GalA11yECellTree GalA11yECellTree;
+typedef struct _GalA11yECellTreeClass GalA11yECellTreeClass;
+typedef struct _GalA11yECellTreePrivate GalA11yECellTreePrivate;
+
+/* This struct should actually be larger as this isn't what we derive from.
+ * The GalA11yECellTreePrivate comes right after the parent class structure.
+ **/
+struct _GalA11yECellTree {
+ GalA11yECell object;
+
+ gint model_row_changed_id;
+};
+
+struct _GalA11yECellTreeClass {
+ GalA11yECellClass parent_class;
+};
+
+
+/* Standard Glib function */
+GType gal_a11y_e_cell_tree_get_type (void);
+AtkObject *gal_a11y_e_cell_tree_new (ETableItem *item,
+ ECellView *cell_view,
+ AtkObject *parent,
+ gint model_col,
+ gint view_col,
+ gint row);
+
+#endif /* ! __GAL_A11Y_E_CELL_TREE_H__ */
diff --git a/widgets/table/gal-a11y-e-cell-vbox.c b/widgets/table/gal-a11y-e-cell-vbox.c
new file mode 100644
index 0000000000..b3f92a695a
--- /dev/null
+++ b/widgets/table/gal-a11y-e-cell-vbox.c
@@ -0,0 +1,225 @@
+/*
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ * Eric Zhao <eric.zhao@sun.com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * Copyright (C) 2004 Sun Microsystem, Inc.
+ *
+ */
+
+#include <config.h>
+
+#include <atk/atk.h>
+
+#include "table/e-cell-vbox.h"
+
+#include "gal-a11y-e-cell-registry.h"
+#include "gal-a11y-e-cell-vbox.h"
+
+static GObjectClass *parent_class;
+static AtkComponentIface *component_parent_iface;
+#define PARENT_TYPE (gal_a11y_e_cell_get_type ())
+
+static gint
+ecv_get_n_children (AtkObject *a11y)
+{
+ g_return_val_if_fail (GAL_A11Y_IS_E_CELL_VBOX (a11y), 0);
+
+ return GAL_A11Y_E_CELL_VBOX (a11y)->a11y_subcell_count;
+}
+
+static void
+subcell_destroyed (gpointer data)
+{
+ GalA11yECell *cell;
+ AtkObject *parent;
+ GalA11yECellVbox *gaev;
+
+ g_return_if_fail (GAL_A11Y_IS_E_CELL (data));
+ cell = GAL_A11Y_E_CELL (data);
+
+ parent = atk_object_get_parent (ATK_OBJECT (cell));
+ g_return_if_fail (GAL_A11Y_IS_E_CELL_VBOX (parent));
+ gaev = GAL_A11Y_E_CELL_VBOX (parent);
+
+ if (cell->view_col < gaev->a11y_subcell_count)
+ gaev->a11y_subcells[cell->view_col] = NULL;
+}
+
+static AtkObject*
+ecv_ref_child (AtkObject *a11y, gint i)
+{
+ GalA11yECellVbox *gaev = GAL_A11Y_E_CELL_VBOX (a11y);
+ GalA11yECell *gaec = GAL_A11Y_E_CELL (a11y);
+ ECellVboxView *ecvv = (ECellVboxView *) (gaec->cell_view);
+ AtkObject *ret;
+ if (i < gaev->a11y_subcell_count) {
+ if (gaev->a11y_subcells[i] == NULL) {
+ ECellView *subcell_view;
+ gint model_col, row;
+ row = gaec->row;
+ model_col = ecvv->model_cols[i];
+ subcell_view = ecvv->subcell_views[i];
+ ret = gal_a11y_e_cell_registry_get_object (NULL,
+ gaec->item,
+ subcell_view,
+ a11y,
+ model_col,
+ gaec->view_col, /* FIXME should the view column use a fake one or the same as its parent? */
+ row);
+ gaev->a11y_subcells[i] = ret;
+ g_object_ref (ret);
+ g_object_weak_ref (G_OBJECT (ret),
+ (GWeakNotify) subcell_destroyed,
+ ret);
+ } else {
+ ret = (AtkObject *) gaev->a11y_subcells[i];
+ if (ATK_IS_OBJECT (ret))
+ g_object_ref (ret);
+ else
+ ret = NULL;
+ }
+ } else {
+ ret = NULL;
+ }
+
+ return ret;
+}
+
+static void
+ecv_dispose (GObject *object)
+{
+ GalA11yECellVbox *gaev = GAL_A11Y_E_CELL_VBOX (object);
+ if (gaev->a11y_subcells)
+ g_free (gaev->a11y_subcells);
+
+ if (parent_class->dispose)
+ parent_class->dispose (object);
+}
+
+/* AtkComponet interface */
+static AtkObject*
+ecv_ref_accessible_at_point (AtkComponent *component,
+ gint x,
+ gint y,
+ AtkCoordType coord_type)
+{
+ gint x0, y0, width, height;
+ gint subcell_height, i;
+
+ GalA11yECell *gaec = GAL_A11Y_E_CELL (component);
+ ECellVboxView *ecvv = (ECellVboxView *) (gaec->cell_view);
+
+ atk_component_get_extents (component, &x0, &y0, &width, &height, coord_type);
+ x -= x0;
+ y -= y0;
+ if (x < 0 || x > width || y < 0 || y > height)
+ return NULL;
+
+ for (i = 0; i < ecvv->subcell_view_count; i++) {
+ subcell_height = e_cell_height (ecvv->subcell_views[i], ecvv->model_cols[i], gaec->view_col, gaec->row);
+ if ( 0 <= y && y <= subcell_height) {
+ return ecv_ref_child ((AtkObject *)component, i);
+ } else
+ y -= subcell_height;
+ }
+
+ return NULL;
+}
+
+static void
+ecv_class_init (GalA11yECellVboxClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ AtkObjectClass *a11y_class = ATK_OBJECT_CLASS (klass);
+ parent_class = g_type_class_ref (PARENT_TYPE);
+
+ object_class->dispose = ecv_dispose;
+
+ a11y_class->get_n_children = ecv_get_n_children;
+ a11y_class->ref_child = ecv_ref_child;
+}
+
+static void
+ecv_init (GalA11yECellVbox *a11y)
+{
+}
+
+static void
+ecv_atk_component_iface_init (AtkComponentIface *iface)
+{
+ component_parent_iface = g_type_interface_peek_parent (iface);
+
+ iface->ref_accessible_at_point = ecv_ref_accessible_at_point;
+}
+
+GType
+gal_a11y_e_cell_vbox_get_type (void)
+{
+ static GType type = 0;
+ if (!type) {
+ GTypeInfo info = {
+ sizeof (GalA11yECellVboxClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) ecv_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+ sizeof (GalA11yECellVbox),
+ 0,
+ (GInstanceInitFunc) ecv_init,
+ NULL /* value_cell */
+ };
+
+ static const GInterfaceInfo atk_component_info = {
+ (GInterfaceInitFunc) ecv_atk_component_iface_init,
+ (GInterfaceFinalizeFunc) NULL,
+ NULL
+ };
+
+ type = g_type_register_static (PARENT_TYPE, "GalA11yECellVbox", &info, 0);
+ gal_a11y_e_cell_type_add_action_interface (type);
+ g_type_add_interface_static (type, ATK_TYPE_COMPONENT, &atk_component_info);
+ }
+
+ return type;
+}
+
+AtkObject *gal_a11y_e_cell_vbox_new (ETableItem *item,
+ ECellView *cell_view,
+ AtkObject *parent,
+ gint model_col,
+ gint view_col,
+ gint row)
+{
+ AtkObject *a11y;
+ GalA11yECell *gaec;
+ GalA11yECellVbox *gaev;
+ ECellVboxView *ecvv;
+
+ a11y = g_object_new (gal_a11y_e_cell_vbox_get_type (), NULL);
+
+ gal_a11y_e_cell_construct (a11y, item, cell_view, parent, model_col, view_col, row);
+
+ gaec = GAL_A11Y_E_CELL (a11y);
+ gaev = GAL_A11Y_E_CELL_VBOX (a11y);
+ ecvv = (ECellVboxView *) (gaec->cell_view);
+ gaev->a11y_subcell_count = ecvv->subcell_view_count;
+ gaev->a11y_subcells = g_malloc0 (sizeof(AtkObject *)*gaev->a11y_subcell_count);
+ return a11y;
+}
diff --git a/widgets/table/gal-a11y-e-cell-vbox.h b/widgets/table/gal-a11y-e-cell-vbox.h
new file mode 100644
index 0000000000..657cb5d9a5
--- /dev/null
+++ b/widgets/table/gal-a11y-e-cell-vbox.h
@@ -0,0 +1,63 @@
+/*
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ * Eric Zhao <eric.zhao@sun.com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * Copyright (C) 2004 Sun Microsystem, Inc.
+ *
+ */
+
+#ifndef __GAL_A11Y_E_CELL_VBOX_H__
+#define __GAL_A11Y_E_CELL_VBOX_H__
+
+#include "gal-a11y-e-cell.h"
+
+G_BEGIN_DECLS
+
+#define GAL_A11Y_TYPE_E_CELL_VBOX (gal_a11y_e_cell_vbox_get_type ())
+#define GAL_A11Y_E_CELL_VBOX(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAL_A11Y_TYPE_E_CELL_VBOX, GalA11yECellVbox))
+#define GAL_A11Y_E_CELL_VBOX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAL_A11Y_E_CELL_VBOX, GalA11yECellVboxClass))
+#define GAL_A11Y_IS_E_CELL_VBOX(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAL_A11Y_TYPE_E_CELL_VBOX))
+#define GAL_A11Y_IS_E_CELL_VBOX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAL_A11Y_TYPE_E_CELL_VBOX))
+#define GAL_A11Y_E_CELL_VBOX_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GAL_A11Y_TYPE_E_CELL_VBOX, GalA11yECellVboxClass))
+
+typedef struct _GalA11yECellVbox GalA11yECellVbox;
+typedef struct _GalA11yECellVboxClass GalA11yECellVboxClass;
+
+struct _GalA11yECellVbox
+{
+ GalA11yECell object;
+ gint a11y_subcell_count;
+ gpointer *a11y_subcells;
+};
+
+struct _GalA11yECellVboxClass
+{
+ GalA11yECellClass parent_class;
+};
+
+GType gal_a11y_e_cell_vbox_get_type (void);
+AtkObject *gal_a11y_e_cell_vbox_new (ETableItem *item,
+ ECellView *cell_view,
+ AtkObject *parent,
+ gint model_col,
+ gint view_col,
+ gint row);
+
+G_END_DECLS
+#endif /* __GAL_A11Y_E_CELL_VBOX_H__ */
diff --git a/widgets/table/gal-a11y-e-cell.c b/widgets/table/gal-a11y-e-cell.c
new file mode 100644
index 0000000000..e09b5456d9
--- /dev/null
+++ b/widgets/table/gal-a11y-e-cell.c
@@ -0,0 +1,644 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ * Christopher James Lahey <clahey@ximian.com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#include <config.h>
+
+#include <string.h>
+
+#include <gtk/gtk.h>
+
+#include "a11y/gal-a11y-util.h"
+#include "table/e-table.h"
+#include "table/e-tree.h"
+#include <glib/gi18n.h>
+
+#include "gal-a11y-e-cell.h"
+#include "gal-a11y-e-cell-vbox.h"
+#include "gal-a11y-e-table-item.h"
+
+#define CS_CLASS(a11y) (G_TYPE_INSTANCE_GET_CLASS ((a11y), C_TYPE_STREAM, GalA11yECellClass))
+static GObjectClass *parent_class;
+#define PARENT_TYPE (atk_object_get_type ())
+
+
+#if 0
+static void
+unref_item (gpointer user_data, GObject *obj_loc)
+{
+ GalA11yECell *a11y = GAL_A11Y_E_CELL (user_data);
+ a11y->item = NULL;
+ g_object_unref (a11y);
+}
+
+static void
+unref_cell (gpointer user_data, GObject *obj_loc)
+{
+ GalA11yECell *a11y = GAL_A11Y_E_CELL (user_data);
+ a11y->cell_view = NULL;
+ g_object_unref (a11y);
+}
+#endif
+
+static gboolean
+is_valid (AtkObject *cell)
+{
+ GalA11yECell *a11y = GAL_A11Y_E_CELL (cell);
+ GalA11yETableItem *a11yItem = GAL_A11Y_E_TABLE_ITEM (a11y->parent);
+ AtkStateSet *item_ss;
+ gboolean ret = TRUE;
+
+ item_ss = atk_object_ref_state_set (ATK_OBJECT (a11yItem));
+ if (atk_state_set_contains_state (item_ss, ATK_STATE_DEFUNCT))
+ ret = FALSE;
+
+ g_object_unref (item_ss);
+
+ if (ret && atk_state_set_contains_state (a11y->state_set, ATK_STATE_DEFUNCT))
+ ret = FALSE;
+
+ return ret;
+}
+
+static void
+gal_a11y_e_cell_dispose (GObject *object)
+{
+ GalA11yECell *a11y = GAL_A11Y_E_CELL (object);
+
+#if 0
+ if (a11y->item)
+ g_object_unref (G_OBJECT (a11y->item)); /*, unref_item, a11y); */
+ if (a11y->cell_view)
+ g_object_unref (G_OBJECT (a11y->cell_view)); /*, unref_cell, a11y); */
+ if (a11y->parent)
+ g_object_unref (a11y->parent);
+#endif
+
+ if (a11y->state_set) {
+ g_object_unref (a11y->state_set);
+ a11y->state_set = NULL;
+ }
+
+ if (parent_class->dispose)
+ parent_class->dispose (object);
+
+}
+
+/* Static functions */
+static G_CONST_RETURN gchar *
+gal_a11y_e_cell_get_name (AtkObject * a11y)
+{
+ GalA11yECell *cell = GAL_A11Y_E_CELL (a11y);
+ ETableCol *ecol;
+
+ if (a11y->name != NULL && strcmp (a11y->name, ""))
+ return a11y->name;
+
+ if (cell->item != NULL) {
+ ecol = e_table_header_get_column (cell->item->header, cell->view_col);
+ if (ecol != NULL)
+ return ecol->text;
+ }
+
+ return _("Table Cell");
+}
+
+static AtkStateSet *
+gal_a11y_e_cell_ref_state_set (AtkObject *accessible)
+{
+ GalA11yECell *cell = GAL_A11Y_E_CELL (accessible);
+
+ g_return_val_if_fail (cell->state_set, NULL);
+
+ g_object_ref(cell->state_set);
+
+ return cell->state_set;
+}
+
+static AtkObject*
+gal_a11y_e_cell_get_parent (AtkObject *accessible)
+{
+ GalA11yECell *a11y = GAL_A11Y_E_CELL (accessible);
+ return a11y->parent;
+}
+
+static gint
+gal_a11y_e_cell_get_index_in_parent (AtkObject *accessible)
+{
+ GalA11yECell *a11y = GAL_A11Y_E_CELL (accessible);
+
+ if (!is_valid (accessible))
+ return -1;
+
+ return (a11y->row + 1) * a11y->item->cols + a11y->view_col;
+}
+
+
+/* Component IFace */
+static void
+gal_a11y_e_cell_get_extents (AtkComponent *component,
+ gint *x,
+ gint *y,
+ gint *width,
+ gint *height,
+ AtkCoordType coord_type)
+{
+ GalA11yECell *a11y = GAL_A11Y_E_CELL (component);
+ GtkWidget *tableOrTree;
+ gint row;
+ gint col;
+ gint xval;
+ gint yval;
+
+ row = a11y->row;
+ col = a11y->view_col;
+
+ tableOrTree = gtk_widget_get_parent (GTK_WIDGET (a11y->item->parent.canvas));
+ if (E_IS_TREE (tableOrTree)) {
+ e_tree_get_cell_geometry (E_TREE (tableOrTree),
+ row, col, &xval, &yval,
+ width, height);
+ } else {
+ e_table_get_cell_geometry (E_TABLE (tableOrTree),
+ row, col, &xval, &yval,
+ width, height);
+ }
+
+ atk_component_get_position (ATK_COMPONENT (a11y->parent),
+ x, y, coord_type);
+ if (x && *x != G_MININT)
+ *x += xval;
+ if (y && *y != G_MININT)
+ *y += yval;
+}
+
+static gboolean
+gal_a11y_e_cell_grab_focus (AtkComponent *component)
+{
+ GalA11yECell *a11y;
+ gint index;
+ GtkWidget *toplevel;
+ GalA11yETableItem *a11yTableItem;
+
+ a11y = GAL_A11Y_E_CELL (component);
+
+ /* for e_cell_vbox's children, we just grab the e_cell_vbox */
+ if (GAL_A11Y_IS_E_CELL_VBOX (a11y->parent)) {
+ return atk_component_grab_focus (ATK_COMPONENT (a11y->parent));
+ }
+
+ a11yTableItem = GAL_A11Y_E_TABLE_ITEM (a11y->parent);
+ index = atk_object_get_index_in_parent (ATK_OBJECT (a11y));
+
+ atk_selection_clear_selection (ATK_SELECTION (a11yTableItem));
+ atk_selection_add_selection (ATK_SELECTION (a11yTableItem), index);
+
+ gtk_widget_grab_focus (GTK_WIDGET (GNOME_CANVAS_ITEM (a11y->item)->canvas));
+ toplevel = gtk_widget_get_toplevel (GTK_WIDGET (GNOME_CANVAS_ITEM (a11y->item)->canvas));
+ if (toplevel && GTK_WIDGET_TOPLEVEL (toplevel))
+ gtk_window_present (GTK_WINDOW (toplevel));
+
+ return TRUE;
+}
+
+/* Table IFace */
+
+static void
+gal_a11y_e_cell_atk_component_iface_init (AtkComponentIface *iface)
+{
+ iface->get_extents = gal_a11y_e_cell_get_extents;
+ iface->grab_focus = gal_a11y_e_cell_grab_focus;
+}
+
+static void
+gal_a11y_e_cell_class_init (GalA11yECellClass *klass)
+{
+ AtkObjectClass *atk_object_class = ATK_OBJECT_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ parent_class = g_type_class_ref (PARENT_TYPE);
+
+ object_class->dispose = gal_a11y_e_cell_dispose;
+
+ atk_object_class->get_parent = gal_a11y_e_cell_get_parent;
+ atk_object_class->get_index_in_parent = gal_a11y_e_cell_get_index_in_parent;
+ atk_object_class->ref_state_set = gal_a11y_e_cell_ref_state_set;
+ atk_object_class->get_name = gal_a11y_e_cell_get_name;
+}
+
+static void
+gal_a11y_e_cell_init (GalA11yECell *a11y)
+{
+ a11y->item = NULL;
+ a11y->cell_view = NULL;
+ a11y->parent = NULL;
+ a11y->model_col = -1;
+ a11y->view_col = -1;
+ a11y->row = -1;
+
+ a11y->state_set = atk_state_set_new ();
+ atk_state_set_add_state (a11y->state_set, ATK_STATE_TRANSIENT);
+ atk_state_set_add_state (a11y->state_set, ATK_STATE_ENABLED);
+ atk_state_set_add_state (a11y->state_set, ATK_STATE_SENSITIVE);
+ atk_state_set_add_state (a11y->state_set, ATK_STATE_SELECTABLE);
+ atk_state_set_add_state (a11y->state_set, ATK_STATE_SHOWING);
+ atk_state_set_add_state (a11y->state_set, ATK_STATE_FOCUSABLE);
+ atk_state_set_add_state (a11y->state_set, ATK_STATE_VISIBLE);
+}
+
+
+static ActionInfo *
+_gal_a11y_e_cell_get_action_info (GalA11yECell *cell,
+ gint index)
+{
+ GList *list_node;
+
+ g_return_val_if_fail (GAL_A11Y_IS_E_CELL (cell), NULL);
+ if (cell->action_list == NULL)
+ return NULL;
+ list_node = g_list_nth (cell->action_list, index);
+ if (!list_node)
+ return NULL;
+ return (ActionInfo *) (list_node->data);
+}
+
+static void
+_gal_a11y_e_cell_destroy_action_info (gpointer action_info,
+ gpointer user_data)
+{
+ ActionInfo *info = (ActionInfo *)action_info;
+
+ g_return_if_fail (info != NULL);
+ g_free (info->name);
+ g_free (info->description);
+ g_free (info->keybinding);
+ g_free (info);
+}
+
+
+gboolean
+gal_a11y_e_cell_add_action ( GalA11yECell * cell,
+ const gchar *action_name,
+ const gchar *action_description,
+ const gchar *action_keybinding,
+ ACTION_FUNC action_func)
+{
+ ActionInfo *info;
+ g_return_val_if_fail (GAL_A11Y_IS_E_CELL (cell), FALSE);
+ info = g_new (ActionInfo, 1);
+
+ if (action_name != NULL)
+ info->name = g_strdup (action_name);
+ else
+ info->name = NULL;
+
+ if (action_description != NULL)
+ info->description = g_strdup (action_description);
+ else
+ info->description = NULL;
+ if (action_keybinding != NULL)
+ info->keybinding = g_strdup (action_keybinding);
+ else
+ info->keybinding = NULL;
+ info->do_action_func = action_func;
+
+ cell->action_list = g_list_append (cell->action_list, (gpointer) info);
+ return TRUE;
+}
+
+gboolean
+gal_a11y_e_cell_remove_action (GalA11yECell *cell,
+ gint action_index)
+{
+ GList *list_node;
+
+ g_return_val_if_fail (GAL_A11Y_IS_E_CELL (cell), FALSE);
+ list_node = g_list_nth (cell->action_list, action_index);
+ if (!list_node)
+ return FALSE;
+ g_return_val_if_fail (list_node->data != NULL, FALSE);
+ _gal_a11y_e_cell_destroy_action_info (list_node->data, NULL);
+ cell->action_list = g_list_remove_link (cell->action_list, list_node);
+
+ return TRUE;
+}
+
+gboolean
+gal_a11y_e_cell_remove_action_by_name (GalA11yECell *cell,
+ const gchar *action_name)
+{
+ GList *list_node;
+ gboolean action_found= FALSE;
+
+ g_return_val_if_fail (GAL_A11Y_IS_E_CELL (cell), FALSE);
+ for (list_node = cell->action_list; list_node && !action_found;
+ list_node = list_node->next) {
+ if (!g_ascii_strcasecmp (((ActionInfo *)(list_node->data))->name, action_name)) {
+ action_found = TRUE;
+ break;
+ }
+ }
+
+ g_return_val_if_fail (action_found, FALSE);
+ _gal_a11y_e_cell_destroy_action_info (list_node->data, NULL);
+ cell->action_list = g_list_remove_link (cell->action_list, list_node);
+
+ return TRUE;
+}
+
+static gint
+gal_a11y_e_cell_action_get_n_actions (AtkAction *action)
+{
+ GalA11yECell *cell = GAL_A11Y_E_CELL(action);
+ if (cell->action_list != NULL)
+ return g_list_length (cell->action_list);
+ else
+ return 0;
+}
+
+static G_CONST_RETURN gchar *
+gal_a11y_e_cell_action_get_name (AtkAction *action,
+ gint index)
+{
+ GalA11yECell *cell = GAL_A11Y_E_CELL(action);
+ ActionInfo *info = _gal_a11y_e_cell_get_action_info (cell, index);
+
+ if (info == NULL)
+ return NULL;
+ return info->name;
+}
+
+static G_CONST_RETURN gchar *
+gal_a11y_e_cell_action_get_description (AtkAction *action,
+ gint index)
+{
+ GalA11yECell *cell = GAL_A11Y_E_CELL(action);
+ ActionInfo *info = _gal_a11y_e_cell_get_action_info (cell, index);
+
+ if (info == NULL)
+ return NULL;
+ return info->description;
+}
+
+static gboolean
+gal_a11y_e_cell_action_set_description (AtkAction *action,
+ gint index,
+ const gchar *desc)
+{
+ GalA11yECell *cell = GAL_A11Y_E_CELL(action);
+ ActionInfo *info = _gal_a11y_e_cell_get_action_info (cell, index);
+
+ if (info == NULL)
+ return FALSE;
+ g_free (info->description);
+ info->description = g_strdup (desc);
+ return TRUE;
+}
+
+static G_CONST_RETURN gchar *
+gal_a11y_e_cell_action_get_keybinding (AtkAction *action,
+ gint index)
+{
+ GalA11yECell *cell = GAL_A11Y_E_CELL(action);
+ ActionInfo *info = _gal_a11y_e_cell_get_action_info (cell, index);
+ if (info == NULL)
+ return NULL;
+
+ return info->keybinding;
+}
+
+static gboolean
+idle_do_action (gpointer data)
+{
+ GalA11yECell *cell;
+
+ cell = GAL_A11Y_E_CELL (data);
+
+ if (!is_valid (ATK_OBJECT (cell)))
+ return FALSE;
+
+ cell->action_idle_handler = 0;
+ cell->action_func (cell);
+ g_object_unref (cell);
+
+ return FALSE;
+}
+
+static gboolean
+gal_a11y_e_cell_action_do_action (AtkAction *action,
+ gint index)
+{
+ GalA11yECell *cell = GAL_A11Y_E_CELL(action);
+ ActionInfo *info = _gal_a11y_e_cell_get_action_info (cell, index);
+
+ if (!is_valid (ATK_OBJECT (action)))
+ return FALSE;
+
+ if (info == NULL)
+ return FALSE;
+ g_return_val_if_fail (info->do_action_func, FALSE);
+ if (cell->action_idle_handler)
+ return FALSE;
+ cell->action_func = info->do_action_func;
+ g_object_ref (cell);
+ cell->action_idle_handler = g_idle_add (idle_do_action, cell);
+
+ return TRUE;
+}
+
+static void
+gal_a11y_e_cell_atk_action_interface_init (AtkActionIface *iface)
+{
+ g_return_if_fail (iface != NULL);
+
+ iface->get_n_actions = gal_a11y_e_cell_action_get_n_actions;
+ iface->do_action = gal_a11y_e_cell_action_do_action;
+ iface->get_name = gal_a11y_e_cell_action_get_name;
+ iface->get_description = gal_a11y_e_cell_action_get_description;
+ iface->set_description = gal_a11y_e_cell_action_set_description;
+ iface->get_keybinding = gal_a11y_e_cell_action_get_keybinding;
+}
+
+void
+gal_a11y_e_cell_type_add_action_interface (GType type)
+{
+ static const GInterfaceInfo atk_action_info =
+ {
+ (GInterfaceInitFunc) gal_a11y_e_cell_atk_action_interface_init,
+ (GInterfaceFinalizeFunc) NULL,
+ NULL
+ };
+
+ g_type_add_interface_static (type, ATK_TYPE_ACTION,
+ &atk_action_info);
+}
+
+gboolean
+gal_a11y_e_cell_add_state (GalA11yECell *cell,
+ AtkStateType state_type,
+ gboolean emit_signal)
+{
+ if (!atk_state_set_contains_state (cell->state_set, state_type)) {
+ gboolean rc;
+
+ rc = atk_state_set_add_state (cell->state_set, state_type);
+ /*
+ * The signal should only be generated if the value changed,
+ * not when the cell is set up. So states that are set
+ * initially should pass FALSE as the emit_signal argument.
+ */
+
+ if (emit_signal) {
+ atk_object_notify_state_change (ATK_OBJECT (cell), state_type, TRUE);
+ /* If state_type is ATK_STATE_VISIBLE, additional
+ notification */
+ if (state_type == ATK_STATE_VISIBLE)
+ g_signal_emit_by_name (cell, "visible_data_changed");
+ }
+
+ return rc;
+ }
+ else
+ return FALSE;
+}
+
+gboolean
+gal_a11y_e_cell_remove_state (GalA11yECell *cell,
+ AtkStateType state_type,
+ gboolean emit_signal)
+{
+ if (atk_state_set_contains_state (cell->state_set, state_type)) {
+ gboolean rc;
+
+ rc = atk_state_set_remove_state (cell->state_set, state_type);
+ /*
+ * The signal should only be generated if the value changed,
+ * not when the cell is set up. So states that are set
+ * initially should pass FALSE as the emit_signal argument.
+ */
+
+ if (emit_signal) {
+ atk_object_notify_state_change (ATK_OBJECT (cell), state_type, FALSE);
+ /* If state_type is ATK_STATE_VISIBLE, additional notification */
+ if (state_type == ATK_STATE_VISIBLE)
+ g_signal_emit_by_name (cell, "visible_data_changed");
+ }
+
+ return rc;
+ }
+ else
+ return FALSE;
+}
+
+/**
+ * gal_a11y_e_cell_get_type:
+ * @void:
+ *
+ * Registers the &GalA11yECell class if necessary, and returns the type ID
+ * associated to it.
+ *
+ * Return value: The type ID of the &GalA11yECell class.
+ **/
+GType
+gal_a11y_e_cell_get_type (void)
+{
+ static GType type = 0;
+
+ if (!type) {
+ GTypeInfo info = {
+ sizeof (GalA11yECellClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) gal_a11y_e_cell_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+ sizeof (GalA11yECell),
+ 0,
+ (GInstanceInitFunc) gal_a11y_e_cell_init,
+ NULL /* value_cell */
+ };
+
+ static const GInterfaceInfo atk_component_info = {
+ (GInterfaceInitFunc) gal_a11y_e_cell_atk_component_iface_init,
+ (GInterfaceFinalizeFunc) NULL,
+ NULL
+ };
+
+ type = g_type_register_static (PARENT_TYPE, "GalA11yECell", &info, 0);
+ g_type_add_interface_static (type, ATK_TYPE_COMPONENT, &atk_component_info);
+ }
+
+ return type;
+}
+
+AtkObject *
+gal_a11y_e_cell_new (ETableItem *item,
+ ECellView *cell_view,
+ AtkObject *parent,
+ gint model_col,
+ gint view_col,
+ gint row)
+{
+ AtkObject *a11y;
+
+ a11y = g_object_new (gal_a11y_e_cell_get_type (), NULL);
+
+ gal_a11y_e_cell_construct (a11y,
+ item,
+ cell_view,
+ parent,
+ model_col,
+ view_col,
+ row);
+ return a11y;
+}
+
+void
+gal_a11y_e_cell_construct (AtkObject *object,
+ ETableItem *item,
+ ECellView *cell_view,
+ AtkObject *parent,
+ gint model_col,
+ gint view_col,
+ gint row)
+{
+ GalA11yECell *a11y = GAL_A11Y_E_CELL (object);
+ a11y->item = item;
+ a11y->cell_view = cell_view;
+ a11y->parent = parent;
+ a11y->model_col = model_col;
+ a11y->view_col = view_col;
+ a11y->row = row;
+ ATK_OBJECT (a11y) ->role = ATK_ROLE_TABLE_CELL;
+
+ if (item)
+ g_object_ref (G_OBJECT (item));
+
+#if 0
+ if (parent)
+ g_object_ref (parent);
+
+ if (cell_view)
+ g_object_ref (G_OBJECT (cell_view));
+
+
+#endif
+}
diff --git a/widgets/table/gal-a11y-e-cell.h b/widgets/table/gal-a11y-e-cell.h
new file mode 100644
index 0000000000..c61e5e2d22
--- /dev/null
+++ b/widgets/table/gal-a11y-e-cell.h
@@ -0,0 +1,113 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ * Christopher James Lahey <clahey@ximian.com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef __GAL_A11Y_E_CELL_H__
+#define __GAL_A11Y_E_CELL_H__
+
+#include <glib-object.h>
+#include <table/e-table-item.h>
+#include <table/e-cell.h>
+
+#define GAL_A11Y_TYPE_E_CELL (gal_a11y_e_cell_get_type ())
+#define GAL_A11Y_E_CELL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAL_A11Y_TYPE_E_CELL, GalA11yECell))
+#define GAL_A11Y_E_CELL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAL_A11Y_TYPE_E_CELL, GalA11yECellClass))
+#define GAL_A11Y_IS_E_CELL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAL_A11Y_TYPE_E_CELL))
+#define GAL_A11Y_IS_E_CELL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAL_A11Y_TYPE_E_CELL))
+
+typedef struct _GalA11yECell GalA11yECell;
+typedef struct _GalA11yECellClass GalA11yECellClass;
+typedef struct _GalA11yECellPrivate GalA11yECellPrivate;
+typedef struct _ActionInfo ActionInfo;
+typedef void (*ACTION_FUNC) (GalA11yECell *cell);
+
+
+/* This struct should actually be larger as this isn't what we derive from.
+ * The GalA11yECellPrivate comes right after the parent class structure.
+ **/
+struct _GalA11yECell {
+ AtkObject object;
+
+ ETableItem *item;
+ ECellView *cell_view;
+ AtkObject *parent;
+ gint model_col;
+ gint view_col;
+ gint row;
+ AtkStateSet *state_set;
+ GList *action_list;
+ gint action_idle_handler;
+ ACTION_FUNC action_func;
+};
+
+struct _GalA11yECellClass {
+ AtkObjectClass parent_class;
+};
+
+struct _ActionInfo {
+ gchar *name;
+ gchar *description;
+ gchar *keybinding;
+ ACTION_FUNC do_action_func;
+};
+
+
+
+/* Standard Glib function */
+GType gal_a11y_e_cell_get_type (void);
+AtkObject *gal_a11y_e_cell_new (ETableItem *item,
+ ECellView *cell_view,
+ AtkObject *parent,
+ gint model_col,
+ gint view_col,
+ gint row);
+void gal_a11y_e_cell_construct (AtkObject *object,
+ ETableItem *item,
+ ECellView *cell_view,
+ AtkObject *parent,
+ gint model_col,
+ gint view_col,
+ gint row);
+
+void gal_a11y_e_cell_type_add_action_interface (GType type);
+
+gboolean gal_a11y_e_cell_add_action (GalA11yECell *cell,
+ const gchar *action_name,
+ const gchar *action_description,
+ const gchar *action_keybinding,
+ ACTION_FUNC action_func);
+
+gboolean gal_a11y_e_cell_remove_action (GalA11yECell *cell,
+ gint action_id);
+
+gboolean gal_a11y_e_cell_remove_action_by_name (GalA11yECell *cell,
+ const gchar *action_name);
+
+gboolean gal_a11y_e_cell_add_state (GalA11yECell *cell,
+ AtkStateType state_type,
+ gboolean emit_signal);
+
+gboolean gal_a11y_e_cell_remove_state (GalA11yECell *cell,
+ AtkStateType state_type,
+ gboolean emit_signal);
+
+
+#endif /* ! __GAL_A11Y_E_CELL_H__ */
diff --git a/widgets/table/gal-a11y-e-table-click-to-add-factory.c b/widgets/table/gal-a11y-e-table-click-to-add-factory.c
new file mode 100644
index 0000000000..0ebb3c4621
--- /dev/null
+++ b/widgets/table/gal-a11y-e-table-click-to-add-factory.c
@@ -0,0 +1,106 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ * Yuedong Du <yuedong.du@sun.com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#include <config.h>
+
+#include <atk/atk.h>
+
+#include "table/e-table.h"
+#include "table/e-table-click-to-add.h"
+
+#include "gal-a11y-e-table.h"
+#include "gal-a11y-e-table-click-to-add.h"
+#include "gal-a11y-e-table-click-to-add-factory.h"
+
+#define CS_CLASS(factory) (G_TYPE_INSTANCE_GET_CLASS ((factory), C_TYPE_STREAM, GalA11yETableClickToAddFactoryClass))
+static AtkObjectFactoryClass *parent_class;
+#define PARENT_TYPE (ATK_TYPE_OBJECT_FACTORY)
+
+/* Static functions */
+
+static GType
+gal_a11y_e_table_click_to_add_factory_get_accessible_type (void)
+{
+ return GAL_A11Y_TYPE_E_TABLE_CLICK_TO_ADD;
+}
+
+static AtkObject*
+gal_a11y_e_table_click_to_add_factory_create_accessible (GObject *obj)
+{
+ AtkObject * atk_object;
+
+ g_return_val_if_fail (E_IS_TABLE_CLICK_TO_ADD(obj), NULL);
+
+ atk_object = gal_a11y_e_table_click_to_add_new (obj);
+
+ return atk_object;
+}
+
+static void
+gal_a11y_e_table_click_to_add_factory_class_init (GalA11yETableClickToAddFactoryClass *klass)
+{
+ AtkObjectFactoryClass *factory_class = ATK_OBJECT_FACTORY_CLASS (klass);
+
+ parent_class = g_type_class_ref (PARENT_TYPE);
+
+ factory_class->create_accessible = gal_a11y_e_table_click_to_add_factory_create_accessible;
+ factory_class->get_accessible_type = gal_a11y_e_table_click_to_add_factory_get_accessible_type;
+}
+
+static void
+gal_a11y_e_table_click_to_add_factory_init (GalA11yETableClickToAddFactory *factory)
+{
+}
+
+/**
+ * gal_a11y_e_table_factory_get_type:
+ * @void:
+ *
+ * Registers the &GalA11yETableFactory class if necessary, and returns the type ID
+ * associated to it.
+ *
+ * Return value: The type ID of the &GalA11yETableFactory class.
+ **/
+GType
+gal_a11y_e_table_click_to_add_factory_get_type (void)
+{
+ static GType type = 0;
+
+ if (!type) {
+ GTypeInfo info = {
+ sizeof (GalA11yETableClickToAddFactoryClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) gal_a11y_e_table_click_to_add_factory_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+ sizeof (GalA11yETableClickToAddFactory),
+ 0,
+ (GInstanceInitFunc) gal_a11y_e_table_click_to_add_factory_init,
+ NULL /* value_table */
+ };
+
+ type = g_type_register_static (PARENT_TYPE, "GalA11yETableClickToAddFactory", &info, 0);
+ }
+
+ return type;
+}
diff --git a/widgets/table/gal-a11y-e-table-click-to-add-factory.h b/widgets/table/gal-a11y-e-table-click-to-add-factory.h
new file mode 100644
index 0000000000..9f249f0178
--- /dev/null
+++ b/widgets/table/gal-a11y-e-table-click-to-add-factory.h
@@ -0,0 +1,50 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ * Yuedong Du <yuedong.du@sun.com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef __GAL_A11Y_E_TABLE_CLICK_TO_ADD_FACTORY_H__
+#define __GAL_A11Y_E_TABLE_CLICK_TO_ADD_FACTORY_H__
+
+#include <glib-object.h>
+#include <atk/atkobjectfactory.h>
+
+#define GAL_A11Y_TYPE_E_TABLE_CLICK_TO_ADD_FACTORY (gal_a11y_e_table_item_factory_get_type ())
+#define GAL_A11Y_E_TABLE_CLICK_TO_ADD_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAL_A11Y_TYPE_E_TABLE_CLICK_TO_ADD_FACTORY, GalA11yETableClickToAddFactory))
+#define GAL_A11Y_E_TABLE_CLICK_TO_ADD_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAL_A11Y_TYPE_E_TABLE_CLICK_TO_ADD_FACTORY, GalA11yETableClickToAddFactoryClass))
+#define GAL_A11Y_IS_E_TABLE_CLICK_TO_ADD_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAL_A11Y_TYPE_E_TABLE_CLICK_TO_ADD_FACTORY))
+#define GAL_A11Y_IS_E_TABLE_CLICK_TO_ADD_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAL_A11Y_TYPE_E_TABLE_CLICK_TO_ADD_FACTORY))
+
+typedef struct _GalA11yETableClickToAddFactory GalA11yETableClickToAddFactory;
+typedef struct _GalA11yETableClickToAddFactoryClass GalA11yETableClickToAddFactoryClass;
+
+struct _GalA11yETableClickToAddFactory {
+ AtkObject object;
+};
+
+struct _GalA11yETableClickToAddFactoryClass {
+ AtkObjectClass parent_class;
+};
+
+
+/* Standard Glib function */
+GType gal_a11y_e_table_click_to_add_factory_get_type (void);
+
+#endif
diff --git a/widgets/table/gal-a11y-e-table-click-to-add.c b/widgets/table/gal-a11y-e-table-click-to-add.c
new file mode 100644
index 0000000000..8a8fe56796
--- /dev/null
+++ b/widgets/table/gal-a11y-e-table-click-to-add.c
@@ -0,0 +1,344 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ * Yuedong Du <yuedong.du@sun.com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#include <config.h>
+
+#include <atk/atk.h>
+
+#include "a11y/gal-a11y-util.h"
+#include "table/e-table-click-to-add.h"
+#include "table/e-table-group.h"
+#include "table/e-table-group-leaf.h"
+#include <glib/gi18n.h>
+
+#include "gal-a11y-e-table-click-to-add.h"
+#include "gal-a11y-e-table-click-to-add-factory.h"
+
+static AtkObjectClass *parent_class;
+static GType parent_type;
+static gint priv_offset;
+#define GET_PRIVATE(object) ((GalA11yETableClickToAddPrivate *) (((gchar *) object) + priv_offset))
+#define PARENT_TYPE (parent_type)
+
+struct _GalA11yETableClickToAddPrivate {
+ gpointer rect;
+ gpointer row;
+};
+
+
+static gint
+etcta_get_n_actions (AtkAction *action)
+{
+ return 1;
+}
+
+static G_CONST_RETURN gchar *
+etcta_get_description (AtkAction *action,
+ gint i)
+{
+ if (i == 0)
+ return _("click to add");
+
+ return NULL;
+}
+
+static G_CONST_RETURN gchar *
+etcta_action_get_name (AtkAction *action, gint i)
+{
+ if (i == 0)
+ return _("click");
+
+ return NULL;
+}
+
+
+static gboolean
+idle_do_action (gpointer data)
+{
+ GdkEventButton event;
+ ETableClickToAdd * etcta;
+ gint finished;
+
+ g_return_val_if_fail ( data!= NULL, FALSE);
+
+ etcta = E_TABLE_CLICK_TO_ADD (atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (data)));
+ g_return_val_if_fail (etcta, FALSE);
+
+ event.x = 0;
+ event.y = 0;
+
+ event.type = GDK_BUTTON_PRESS;
+ event.window = GTK_LAYOUT(GNOME_CANVAS_ITEM(etcta)->canvas)->bin_window;
+ event.button = 1;
+ event.send_event = TRUE;
+ event.time = GDK_CURRENT_TIME;
+ event.axes = NULL;
+
+ g_signal_emit_by_name (etcta, "event", &event, &finished);
+
+ return FALSE;
+}
+
+static gboolean
+etcta_do_action (AtkAction * action, gint i)
+{
+ g_return_val_if_fail (i == 0, FALSE);
+
+ g_idle_add (idle_do_action, action);
+
+ return TRUE;
+}
+
+static void
+atk_action_interface_init (AtkActionIface *iface)
+{
+ g_return_if_fail (iface != NULL);
+
+ iface->do_action = etcta_do_action;
+ iface->get_n_actions = etcta_get_n_actions;
+ iface->get_description = etcta_get_description;
+ iface->get_name = etcta_action_get_name;
+}
+
+
+static G_CONST_RETURN gchar *
+etcta_get_name (AtkObject *obj)
+{
+ ETableClickToAdd * etcta;
+
+ g_return_val_if_fail (GAL_A11Y_IS_E_TABLE_CLICK_TO_ADD (obj), NULL);
+
+ etcta = E_TABLE_CLICK_TO_ADD (atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE(obj)));
+ if (etcta && etcta->message != NULL)
+ return etcta->message;
+
+ return _("click to add");
+}
+
+static gint
+etcta_get_n_children (AtkObject *accessible)
+{
+ return 1;
+}
+
+static AtkObject*
+etcta_ref_child (AtkObject *accessible,
+ gint i)
+{
+ AtkObject * atk_obj = NULL;
+ ETableClickToAdd * etcta;
+
+ if ( i != 0 )
+ return NULL;
+
+ etcta = E_TABLE_CLICK_TO_ADD(atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (accessible)));
+
+ g_return_val_if_fail (etcta, NULL);
+
+ if (etcta->rect) {
+ atk_obj = atk_gobject_accessible_for_object (G_OBJECT(etcta->rect));
+ } else if (etcta->row) {
+ atk_obj = atk_gobject_accessible_for_object (G_OBJECT(etcta->row));
+ }
+
+ g_object_ref (atk_obj);
+
+ return atk_obj;
+}
+
+static AtkStateSet *
+etcta_ref_state_set (AtkObject *accessible)
+{
+ AtkStateSet * state_set = NULL;
+
+ state_set = ATK_OBJECT_CLASS (parent_class)->ref_state_set (accessible);
+ if (state_set != NULL) {
+ atk_state_set_add_state (state_set, ATK_STATE_SENSITIVE);
+ atk_state_set_add_state (state_set, ATK_STATE_SHOWING);
+ }
+
+ return state_set;
+}
+
+static void
+etcta_class_init (GalA11yETableClickToAddClass *klass)
+{
+ AtkObjectClass *atk_object_class = ATK_OBJECT_CLASS (klass);
+
+ parent_class = g_type_class_ref (PARENT_TYPE);
+
+ atk_object_class->get_name = etcta_get_name;
+ atk_object_class->get_n_children = etcta_get_n_children;
+ atk_object_class->ref_child = etcta_ref_child;
+ atk_object_class->ref_state_set = etcta_ref_state_set;
+}
+
+static void
+etcta_init (GalA11yETableClickToAdd *a11y)
+{
+}
+
+/**
+ * gal_a11y_e_table_click_to_add_get_type:
+ * @void:
+ *
+ * Registers the &GalA11yETableClickToAdd class if necessary, and returns the type ID
+ * associated to it.
+ *
+ * Return value: The type ID of the &GalA11yETableClickToAdd class.
+ **/
+GType
+gal_a11y_e_table_click_to_add_get_type (void)
+{
+ static GType type = 0;
+
+ if (!type) {
+ AtkObjectFactory *factory;
+
+ GTypeInfo info = {
+ sizeof (GalA11yETableClickToAddClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) etcta_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+ sizeof (GalA11yETableClickToAdd),
+ 0,
+ (GInstanceInitFunc) etcta_init,
+ NULL /* value_table */
+ };
+
+ static const GInterfaceInfo atk_action_info = {
+ (GInterfaceInitFunc) atk_action_interface_init,
+ (GInterfaceFinalizeFunc) NULL,
+ NULL
+ };
+
+ factory = atk_registry_get_factory (atk_get_default_registry (), GNOME_TYPE_CANVAS_ITEM);
+
+ parent_type = atk_object_factory_get_accessible_type (factory);
+ type = gal_a11y_type_register_static_with_private (PARENT_TYPE,
+ "GalA11yETableClickToAdd", &info, 0,
+ sizeof(GalA11yETableClickToAddPrivate), &priv_offset);
+
+ g_type_add_interface_static (type, ATK_TYPE_ACTION, &atk_action_info);
+
+ }
+
+ return type;
+}
+
+static gboolean
+etcta_event (GnomeCanvasItem *item, GdkEvent *e, gpointer data)
+{
+ ETableClickToAdd *etcta = E_TABLE_CLICK_TO_ADD (item);
+ GalA11yETableClickToAdd *a11y;
+ GalA11yETableClickToAddPrivate *priv;
+
+ g_return_val_if_fail (item, TRUE);
+
+ g_return_val_if_fail (GAL_A11Y_IS_E_TABLE_CLICK_TO_ADD(data), FALSE);
+ a11y = GAL_A11Y_E_TABLE_CLICK_TO_ADD (data);
+
+ priv = GET_PRIVATE (a11y);
+
+ /* rect replaced by row. */
+ if (etcta->rect == NULL && priv->rect != NULL) {
+ g_signal_emit_by_name (a11y, "children_changed::remove", 0, NULL, NULL);
+
+ }
+ /* row inserted, and/or replaced by a new row. */
+ if (etcta->row != NULL && priv->row == NULL) {
+ g_signal_emit_by_name (a11y, "children_changed::add", 0, NULL, NULL);
+ } else if (etcta->row != NULL && priv->row != NULL && etcta->row != priv->row) {
+ g_signal_emit_by_name (a11y, "children_changed::remove", 0, NULL, NULL);
+ g_signal_emit_by_name (a11y, "children_changed::add", 0, NULL, NULL);
+ }
+
+
+ priv->rect = etcta->rect;
+ priv->row = etcta->row;
+
+ return FALSE;
+}
+
+static void
+etcta_selection_cursor_changed (ESelectionModel *esm, gint row, gint col,
+ GalA11yETableClickToAdd *a11y)
+{
+ ETableClickToAdd *etcta;
+ AtkObject *row_a11y;
+
+ etcta = E_TABLE_CLICK_TO_ADD (atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE(a11y)));
+
+ if (etcta == NULL || etcta->row == NULL)
+ return;
+
+ row_a11y = atk_gobject_accessible_for_object (G_OBJECT(etcta->row));
+ if (row_a11y) {
+ AtkObject *cell_a11y = g_object_get_data (G_OBJECT(row_a11y), "gail-focus-object");
+ if (cell_a11y) {
+ atk_focus_tracker_notify (cell_a11y);
+ }
+ }
+}
+
+AtkObject *
+gal_a11y_e_table_click_to_add_new (GObject *widget)
+{
+ GalA11yETableClickToAdd *a11y;
+ ETableClickToAdd * etcta;
+ GalA11yETableClickToAddPrivate *priv;
+
+ g_return_val_if_fail (widget != NULL, NULL);
+
+ a11y = g_object_new (gal_a11y_e_table_click_to_add_get_type (), NULL);
+ priv = GET_PRIVATE (a11y);
+
+ etcta = E_TABLE_CLICK_TO_ADD(widget);
+
+
+ atk_object_initialize (ATK_OBJECT (a11y), etcta);
+
+ priv->rect = etcta->rect;
+ priv->row = etcta->row;
+
+
+ g_signal_connect_after (G_OBJECT(widget), "event",
+ G_CALLBACK (etcta_event), a11y);
+
+ g_signal_connect (etcta->selection, "cursor_changed",
+ G_CALLBACK (etcta_selection_cursor_changed), a11y);
+
+ return ATK_OBJECT (a11y);
+}
+
+void
+gal_a11y_e_table_click_to_add_init (void)
+{
+ if (atk_get_root ())
+ atk_registry_set_factory_type (atk_get_default_registry (),
+ E_TABLE_CLICK_TO_ADD_TYPE,
+ gal_a11y_e_table_click_to_add_factory_get_type ());
+
+}
+
diff --git a/widgets/table/gal-a11y-e-table-click-to-add.h b/widgets/table/gal-a11y-e-table-click-to-add.h
new file mode 100644
index 0000000000..17d6940d08
--- /dev/null
+++ b/widgets/table/gal-a11y-e-table-click-to-add.h
@@ -0,0 +1,55 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef __GAL_A11Y_E_TABLE_CLICK_TO_ADD_H__
+#define __GAL_A11Y_E_TABLE_CLICK_TO_ADD_H__
+
+#include <glib-object.h>
+#include <table/e-table-item.h>
+#include <atk/atkgobjectaccessible.h>
+
+#define GAL_A11Y_TYPE_E_TABLE_CLICK_TO_ADD (gal_a11y_e_table_click_to_add_get_type ())
+#define GAL_A11Y_E_TABLE_CLICK_TO_ADD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAL_A11Y_TYPE_E_TABLE_CLICK_TO_ADD, GalA11yETableClickToAdd))
+#define GAL_A11Y_E_TABLE_CLICK_TO_ADD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAL_A11Y_TYPE_E_TABLE_CLICK_TO_ADD, GalA11yETableClickToAddClass))
+#define GAL_A11Y_IS_E_TABLE_CLICK_TO_ADD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAL_A11Y_TYPE_E_TABLE_CLICK_TO_ADD))
+#define GAL_A11Y_IS_E_TABLE_CLICK_TO_ADD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAL_A11Y_TYPE_E_TABLE_CLICK_TO_ADD))
+
+typedef struct _GalA11yETableClickToAdd GalA11yETableClickToAdd;
+typedef struct _GalA11yETableClickToAddClass GalA11yETableClickToAddClass;
+typedef struct _GalA11yETableClickToAddPrivate GalA11yETableClickToAddPrivate;
+
+/* This struct should actually be larger as this isn't what we derive from.
+ * The GalA11yETableClickToAddPrivate comes right after the parent class structure.
+ **/
+struct _GalA11yETableClickToAdd {
+ AtkGObjectAccessible parent;
+};
+
+struct _GalA11yETableClickToAddClass {
+ AtkGObjectAccessibleClass parent_class;
+};
+
+/* Standard Glib function */
+GType gal_a11y_e_table_click_to_add_get_type (void);
+AtkObject *gal_a11y_e_table_click_to_add_new (GObject *widget);
+
+void gal_a11y_e_table_click_to_add_init (void);
+#endif /* ! __GAL_A11Y_E_TABLE_CLICK_TO_ADD_H__ */
diff --git a/widgets/table/gal-a11y-e-table-column-header.c b/widgets/table/gal-a11y-e-table-column-header.c
new file mode 100644
index 0000000000..41e6ab0fca
--- /dev/null
+++ b/widgets/table/gal-a11y-e-table-column-header.c
@@ -0,0 +1,229 @@
+/*
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ * Li Yuan <li.yuan@sun.com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#include <config.h>
+#include <glib/gi18n.h>
+#include <atk/atkobject.h>
+#include <atk/atkregistry.h>
+#include "table/e-table-header-item.h"
+#include "a11y/gal-a11y-util.h"
+#include "gal-a11y-e-table-column-header.h"
+
+static GObjectClass *parent_class;
+static gint priv_offset;
+
+#define GET_PRIVATE(object) ((GalA11yETableColumnHeaderPrivate *) (((gchar *) object) + priv_offset))
+#define PARENT_TYPE (atk_gobject_accessible_get_type ())
+
+struct _GalA11yETableColumnHeaderPrivate {
+ ETableItem *item;
+ AtkObject *parent;
+ AtkStateSet *state_set;
+};
+
+static void
+etch_init (GalA11yETableColumnHeader *a11y)
+{
+ GET_PRIVATE (a11y)->item = NULL;
+ GET_PRIVATE (a11y)->parent = NULL;
+ GET_PRIVATE (a11y)->state_set = NULL;
+}
+
+static AtkStateSet *
+gal_a11y_e_table_column_header_ref_state_set (AtkObject *accessible)
+{
+ GalA11yETableColumnHeaderPrivate *priv = GET_PRIVATE (accessible);
+
+ g_return_val_if_fail (priv->state_set, NULL);
+
+ g_object_ref(priv->state_set);
+
+ return priv->state_set;
+}
+
+static void
+gal_a11y_e_table_column_header_real_initialize (AtkObject *obj, gpointer data)
+{
+ ATK_OBJECT_CLASS (parent_class)->initialize (obj, data);
+}
+
+static void
+gal_a11y_e_table_column_header_dispose (GObject *object)
+{
+ GalA11yETableColumnHeader *a11y = GAL_A11Y_E_TABLE_COLUMN_HEADER (object);
+ GalA11yETableColumnHeaderPrivate *priv = GET_PRIVATE (a11y);
+
+ if (priv->state_set) {
+ g_object_unref (priv->state_set);
+ priv->state_set = NULL;
+ }
+
+ if (parent_class->dispose)
+ parent_class->dispose (object);
+
+}
+
+static void
+etch_class_init (GalA11yETableColumnHeaderClass *klass)
+{
+ AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ parent_class = g_type_class_ref (PARENT_TYPE);
+
+ object_class->dispose = gal_a11y_e_table_column_header_dispose;
+
+ class->ref_state_set = gal_a11y_e_table_column_header_ref_state_set;
+ class->initialize = gal_a11y_e_table_column_header_real_initialize;
+}
+
+inline static GObject *
+etch_a11y_get_gobject (AtkGObjectAccessible *accessible)
+{
+ return atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (accessible));
+}
+
+static gboolean
+gal_a11y_e_table_column_header_do_action (AtkAction *action,
+ gint i)
+{
+ gboolean return_value = TRUE;
+ GtkWidget *widget;
+ GalA11yETableColumnHeader *a11y;
+ ETableHeaderItem *ethi;
+ ETableItem *item;
+ ETableCol *col;
+
+ switch (i) {
+ case 0:
+ a11y = GAL_A11Y_E_TABLE_COLUMN_HEADER (action);
+ col = E_TABLE_COL (etch_a11y_get_gobject (ATK_GOBJECT_ACCESSIBLE (a11y)));
+ item = GET_PRIVATE (a11y)->item;
+ widget = gtk_widget_get_parent (GTK_WIDGET (item->parent.canvas));
+ if (E_IS_TREE (widget)) {
+ ethi = E_TABLE_HEADER_ITEM (e_tree_get_header_item (E_TREE (widget)));
+ }
+ else if (E_IS_TABLE (widget))
+ ethi = E_TABLE_HEADER_ITEM (E_TABLE (widget)->header_item);
+ else
+ break;
+ ethi_change_sort_state (ethi, col);
+ default:
+ return_value = FALSE;
+ break;
+ }
+ return return_value;
+}
+
+static gint
+gal_a11y_e_table_column_header_get_n_actions (AtkAction *action)
+{
+ return 1;
+}
+
+static G_CONST_RETURN gchar *
+gal_a11y_e_table_column_header_action_get_name (AtkAction *action,
+ gint i)
+{
+ G_CONST_RETURN gchar *return_value;
+
+ switch (i) {
+ case 0:
+ return_value = _("sort");
+ break;
+ default:
+ return_value = NULL;
+ break;
+ }
+ return return_value;
+}
+
+static void
+atk_action_interface_init (AtkActionIface *iface)
+{
+ g_return_if_fail (iface != NULL);
+
+ iface->do_action = gal_a11y_e_table_column_header_do_action;
+ iface->get_n_actions = gal_a11y_e_table_column_header_get_n_actions;
+ iface->get_name = gal_a11y_e_table_column_header_action_get_name;
+}
+
+GType
+gal_a11y_e_table_column_header_get_type (void)
+{
+ static GType type = 0;
+
+ if (!type) {
+ GTypeInfo info = {
+ sizeof (GalA11yETableColumnHeaderClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) etch_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL,
+ sizeof (GalA11yETableColumnHeader),
+ 0,
+ (GInstanceInitFunc) etch_init,
+ NULL
+ };
+ static const GInterfaceInfo atk_action_info = {
+ (GInterfaceInitFunc) atk_action_interface_init,
+ (GInterfaceFinalizeFunc) NULL,
+ NULL
+ };
+
+ type = gal_a11y_type_register_static_with_private (PARENT_TYPE, "GalA11yETableColumnHeader", &info, 0,
+ sizeof (GalA11yETableColumnHeaderPrivate), &priv_offset);
+
+ g_type_add_interface_static (type, ATK_TYPE_ACTION, &atk_action_info);
+ }
+
+ return type;
+}
+
+AtkObject *
+gal_a11y_e_table_column_header_new (ETableCol *ecol, ETableItem *item)
+{
+ GalA11yETableColumnHeader *a11y;
+ AtkObject *accessible;
+
+ g_return_val_if_fail (E_IS_TABLE_COL (ecol), NULL);
+
+ a11y = g_object_new (gal_a11y_e_table_column_header_get_type(), NULL);
+ accessible = ATK_OBJECT (a11y);
+ atk_object_initialize (accessible, ecol);
+
+ GET_PRIVATE (a11y)->item = item;
+ GET_PRIVATE (a11y)->state_set = atk_state_set_new ();
+
+ atk_state_set_add_state (GET_PRIVATE(a11y)->state_set, ATK_STATE_VISIBLE);
+ atk_state_set_add_state (GET_PRIVATE(a11y)->state_set, ATK_STATE_SHOWING);
+ atk_state_set_add_state (GET_PRIVATE(a11y)->state_set, ATK_STATE_SENSITIVE);
+ atk_state_set_add_state (GET_PRIVATE(a11y)->state_set, ATK_STATE_ENABLED);
+
+ if (ecol->text)
+ atk_object_set_name (accessible, ecol->text);
+ atk_object_set_role (accessible, ATK_ROLE_TABLE_COLUMN_HEADER);
+
+ return ATK_OBJECT (a11y);
+}
diff --git a/widgets/table/gal-a11y-e-table-column-header.h b/widgets/table/gal-a11y-e-table-column-header.h
new file mode 100644
index 0000000000..d0b1ff5aeb
--- /dev/null
+++ b/widgets/table/gal-a11y-e-table-column-header.h
@@ -0,0 +1,55 @@
+/*
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ * Li Yuan <li.yuan@sun.com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+
+#ifndef __GAL_A11Y_E_TABLE_COLUMN_HEADER_H__
+#define __GAL_A11Y_E_TABLE_COLUMN_HEADER_H__
+
+#include <glib-object.h>
+#include <atk/atkgobjectaccessible.h>
+
+#define GAL_A11Y_TYPE_E_TABLE_COLUMN_HEADER (gal_a11y_e_table_column_header_get_type ())
+#define GAL_A11Y_E_TABLE_COLUMN_HEADER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAL_A11Y_TYPE_E_TABLE_COLUMN_HEADER, GalA11yETableColumnHeader))
+#define GAL_A11Y_E_TABLE_COLUMN_HEADER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAL_A11Y_TYPE_E_TABLE_COLUMN_HEADER, GalA11yETableColumnHeaderClass))
+#define GAL_A11Y_IS_E_TABLE_COLUMN_HEADER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAL_A11Y_TYPE_E_TABLE_COLUMN_HEADER))
+#define GAL_A11Y_IS_E_TABLE_COLUMN_HEADER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAL_A11Y_TYPE_E_TABLE_COLUMN_HEADER))
+
+typedef struct _GalA11yETableColumnHeader GalA11yETableColumnHeader;
+typedef struct _GalA11yETableColumnHeaderClass GalA11yETableColumnHeaderClass;
+typedef struct _GalA11yETableColumnHeaderPrivate GalA11yETableColumnHeaderPrivate;
+
+struct _GalA11yETableColumnHeader {
+ AtkGObjectAccessible parent;
+};
+
+struct _GalA11yETableColumnHeaderClass {
+ AtkGObjectAccessibleClass parent_class;
+};
+
+
+/* Standard Glib function */
+GType gal_a11y_e_table_column_header_get_type (void);
+AtkObject *gal_a11y_e_table_column_header_new (ETableCol *etc, ETableItem *item);
+void gal_a11y_e_table_column_header_init (void);
+
+#endif /* ! __GAL_A11Y_E_TABLE_COLUMN_HEADER_H__ */
diff --git a/widgets/table/gal-a11y-e-table-factory.c b/widgets/table/gal-a11y-e-table-factory.c
new file mode 100644
index 0000000000..f459f3b67c
--- /dev/null
+++ b/widgets/table/gal-a11y-e-table-factory.c
@@ -0,0 +1,99 @@
+/*
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ * Christopher James Lahey <clahey@ximian.com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#include <config.h>
+
+#include "gal-a11y-e-table.h"
+#include "gal-a11y-e-table-factory.h"
+
+#define CS_CLASS(factory) (G_TYPE_INSTANCE_GET_CLASS ((factory), C_TYPE_STREAM, GalA11yETableFactoryClass))
+static AtkObjectFactoryClass *parent_class;
+#define PARENT_TYPE (ATK_TYPE_OBJECT_FACTORY)
+
+/* Static functions */
+
+static GType
+gal_a11y_e_table_factory_get_accessible_type (void)
+{
+ return GAL_A11Y_TYPE_E_TABLE;
+}
+
+static AtkObject*
+gal_a11y_e_table_factory_create_accessible (GObject *obj)
+{
+ AtkObject *accessible;
+
+ accessible = gal_a11y_e_table_new (obj);
+
+ return accessible;
+}
+
+static void
+gal_a11y_e_table_factory_class_init (GalA11yETableFactoryClass *klass)
+{
+ AtkObjectFactoryClass *factory_class = ATK_OBJECT_FACTORY_CLASS (klass);
+
+ parent_class = g_type_class_ref (PARENT_TYPE);
+
+ factory_class->create_accessible = gal_a11y_e_table_factory_create_accessible;
+ factory_class->get_accessible_type = gal_a11y_e_table_factory_get_accessible_type;
+}
+
+static void
+gal_a11y_e_table_factory_init (GalA11yETableFactory *factory)
+{
+}
+
+/**
+ * gal_a11y_e_table_factory_get_type:
+ * @void:
+ *
+ * Registers the &GalA11yETableFactory class if necessary, and returns the type ID
+ * associated to it.
+ *
+ * Return value: The type ID of the &GalA11yETableFactory class.
+ **/
+GType
+gal_a11y_e_table_factory_get_type (void)
+{
+ static GType type = 0;
+
+ if (!type) {
+ GTypeInfo info = {
+ sizeof (GalA11yETableFactoryClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) gal_a11y_e_table_factory_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+ sizeof (GalA11yETableFactory),
+ 0,
+ (GInstanceInitFunc) gal_a11y_e_table_factory_init,
+ NULL /* value_table */
+ };
+
+ type = g_type_register_static (PARENT_TYPE, "GalA11yETableFactory", &info, 0);
+ }
+
+ return type;
+}
diff --git a/widgets/table/gal-a11y-e-table-factory.h b/widgets/table/gal-a11y-e-table-factory.h
new file mode 100644
index 0000000000..3439cf0bdc
--- /dev/null
+++ b/widgets/table/gal-a11y-e-table-factory.h
@@ -0,0 +1,51 @@
+/*
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ * Christopher James Lahey <clahey@ximian.com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef __GAL_A11Y_E_TABLE_FACTORY_H__
+#define __GAL_A11Y_E_TABLE_FACTORY_H__
+
+#include <glib-object.h>
+#include <atk/atkobjectfactory.h>
+
+#define GAL_A11Y_TYPE_E_TABLE_FACTORY (gal_a11y_e_table_factory_get_type ())
+#define GAL_A11Y_E_TABLE_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAL_A11Y_TYPE_E_TABLE_FACTORY, GalA11yETableFactory))
+#define GAL_A11Y_E_TABLE_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAL_A11Y_TYPE_E_TABLE_FACTORY, GalA11yETableFactoryClass))
+#define GAL_A11Y_IS_E_TABLE_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAL_A11Y_TYPE_E_TABLE_FACTORY))
+#define GAL_A11Y_IS_E_TABLE_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAL_A11Y_TYPE_E_TABLE_FACTORY))
+
+typedef struct _GalA11yETableFactory GalA11yETableFactory;
+typedef struct _GalA11yETableFactoryClass GalA11yETableFactoryClass;
+
+struct _GalA11yETableFactory {
+ AtkObject object;
+};
+
+struct _GalA11yETableFactoryClass {
+ AtkObjectClass parent_class;
+};
+
+
+/* Standard Glib function */
+GType gal_a11y_e_table_factory_get_type (void);
+
+#endif /* ! __GAL_A11Y_E_TABLE_FACTORY_H__ */
diff --git a/widgets/table/gal-a11y-e-table-item-factory.c b/widgets/table/gal-a11y-e-table-item-factory.c
new file mode 100644
index 0000000000..fa14652788
--- /dev/null
+++ b/widgets/table/gal-a11y-e-table-item-factory.c
@@ -0,0 +1,105 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ * Yuedong Du <yuedong.du@sun.com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#include <config.h>
+
+#include <atk/atk.h>
+
+#include "table/e-table.h"
+#include "table/e-tree.h"
+
+#include "gal-a11y-e-table.h"
+#include "gal-a11y-e-table-item.h"
+#include "gal-a11y-e-table-item-factory.h"
+
+#define CS_CLASS(factory) (G_TYPE_INSTANCE_GET_CLASS ((factory), C_TYPE_STREAM, GalA11yETableItemFactoryClass))
+static AtkObjectFactoryClass *parent_class;
+#define PARENT_TYPE (ATK_TYPE_OBJECT_FACTORY)
+
+/* Static functions */
+
+static GType
+gal_a11y_e_table_item_factory_get_accessible_type (void)
+{
+ return GAL_A11Y_TYPE_E_TABLE_ITEM;
+}
+
+static AtkObject*
+gal_a11y_e_table_item_factory_create_accessible (GObject *obj)
+{
+ AtkObject *accessible;
+
+ g_return_val_if_fail (E_IS_TABLE_ITEM(obj), NULL);
+ accessible = gal_a11y_e_table_item_new (E_TABLE_ITEM (obj));
+
+ return accessible;
+}
+
+static void
+gal_a11y_e_table_item_factory_class_init (GalA11yETableItemFactoryClass *klass)
+{
+ AtkObjectFactoryClass *factory_class = ATK_OBJECT_FACTORY_CLASS (klass);
+
+ parent_class = g_type_class_ref (PARENT_TYPE);
+
+ factory_class->create_accessible = gal_a11y_e_table_item_factory_create_accessible;
+ factory_class->get_accessible_type = gal_a11y_e_table_item_factory_get_accessible_type;
+}
+
+static void
+gal_a11y_e_table_item_factory_init (GalA11yETableItemFactory *factory)
+{
+}
+
+/**
+ * gal_a11y_e_table_factory_get_type:
+ * @void:
+ *
+ * Registers the &GalA11yETableFactory class if necessary, and returns the type ID
+ * associated to it.
+ *
+ * Return value: The type ID of the &GalA11yETableFactory class.
+ **/
+GType
+gal_a11y_e_table_item_factory_get_type (void)
+{
+ static GType type = 0;
+
+ if (!type) {
+ GTypeInfo info = {
+ sizeof (GalA11yETableItemFactoryClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) gal_a11y_e_table_item_factory_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+ sizeof (GalA11yETableItemFactory),
+ 0,
+ (GInstanceInitFunc) gal_a11y_e_table_item_factory_init,
+ NULL /* value_table */
+ };
+
+ type = g_type_register_static (PARENT_TYPE, "GalA11yETableItemFactory", &info, 0);
+ }
+
+ return type;
+}
diff --git a/widgets/table/gal-a11y-e-table-item-factory.h b/widgets/table/gal-a11y-e-table-item-factory.h
new file mode 100644
index 0000000000..f27c491a4d
--- /dev/null
+++ b/widgets/table/gal-a11y-e-table-item-factory.h
@@ -0,0 +1,50 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ * Yuedong Du <yuedong.du@sun.com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef __GAL_A11Y_E_TABLE_ITEM_FACTORY_H__
+#define __GAL_A11Y_E_TABLE_ITEM_FACTORY_H__
+
+#include <glib-object.h>
+#include <atk/atkobjectfactory.h>
+
+#define GAL_A11Y_TYPE_E_TABLE_ITEM_FACTORY (gal_a11y_e_table_item_factory_get_type ())
+#define GAL_A11Y_E_TABLE_ITEM_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAL_A11Y_TYPE_E_TABLE_ITEM_FACTORY, GalA11yETableItemFactory))
+#define GAL_A11Y_E_TABLE_ITEM_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAL_A11Y_TYPE_E_TABLE_ITEM_FACTORY, GalA11yETableItemFactoryClass))
+#define GAL_A11Y_IS_E_TABLE_ITEM_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAL_A11Y_TYPE_E_TABLE_ITEM_FACTORY))
+#define GAL_A11Y_IS_E_TABLE_ITEM_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAL_A11Y_TYPE_E_TABLE_ITEM_FACTORY))
+
+typedef struct _GalA11yETableItemFactory GalA11yETableItemFactory;
+typedef struct _GalA11yETableItemFactoryClass GalA11yETableItemFactoryClass;
+
+struct _GalA11yETableItemFactory {
+ AtkObject object;
+};
+
+struct _GalA11yETableItemFactoryClass {
+ AtkObjectClass parent_class;
+};
+
+
+/* Standard Glib function */
+GType gal_a11y_e_table_item_factory_get_type (void);
+
+#endif /* ! __GAL_A11Y_E_TABLE_FACTORY_H__ */
diff --git a/widgets/table/gal-a11y-e-table-item.c b/widgets/table/gal-a11y-e-table-item.c
new file mode 100644
index 0000000000..561b9a84d6
--- /dev/null
+++ b/widgets/table/gal-a11y-e-table-item.c
@@ -0,0 +1,1327 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ * Christopher James Lahey <clahey@ximian.com>
+ * Bolian Yin <bolian.yin@sun.com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#include <config.h>
+
+#include <string.h>
+
+#include <atk/atk.h>
+
+#include "a11y/gal-a11y-util.h"
+#include "table/e-table-click-to-add.h"
+#include "table/e-table-subset.h"
+#include "table/e-table.h"
+#include "table/e-tree.h"
+#include "misc/e-canvas.h"
+#include "misc/e-selection-model.h"
+
+#include "gal-a11y-e-table-item.h"
+#include "gal-a11y-e-table-item-factory.h"
+#include "gal-a11y-e-table-click-to-add.h"
+#include "gal-a11y-e-cell-registry.h"
+#include "gal-a11y-e-cell.h"
+#include "gal-a11y-e-table-column-header.h"
+
+#define CS_CLASS(a11y) (G_TYPE_INSTANCE_GET_CLASS ((a11y), C_TYPE_STREAM, GalA11yETableItemClass))
+static GObjectClass *parent_class;
+static AtkComponentIface *component_parent_iface;
+static GType parent_type;
+static gint priv_offset;
+static GQuark quark_accessible_object = 0;
+#define GET_PRIVATE(object) ((GalA11yETableItemPrivate *) (((gchar *) object) + priv_offset))
+#define PARENT_TYPE (parent_type)
+
+struct _GalA11yETableItemPrivate {
+ gint cols;
+ gint rows;
+ gint selection_change_id;
+ gint cursor_change_id;
+ ETableCol ** columns;
+ ESelectionModel *selection;
+ AtkStateSet *state_set;
+ GtkWidget *widget;
+};
+
+static gboolean gal_a11y_e_table_item_ref_selection (GalA11yETableItem *a11y,
+ ESelectionModel *selection);
+static gboolean gal_a11y_e_table_item_unref_selection (GalA11yETableItem *a11y);
+
+static AtkObject* eti_ref_at (AtkTable *table, gint row, gint column);
+
+static void
+item_destroyed (GtkObject *item, gpointer user_data)
+{
+ GalA11yETableItem *a11y = GAL_A11Y_E_TABLE_ITEM (user_data);
+ GalA11yETableItemPrivate *priv = GET_PRIVATE (a11y);
+
+ atk_state_set_add_state (priv->state_set, ATK_STATE_DEFUNCT);
+ atk_object_notify_state_change (ATK_OBJECT (a11y), ATK_STATE_DEFUNCT, TRUE);
+
+ if (priv->selection)
+ gal_a11y_e_table_item_unref_selection (a11y);
+
+}
+
+static AtkStateSet *
+eti_ref_state_set (AtkObject *accessible)
+{
+ GalA11yETableItemPrivate *priv = GET_PRIVATE (accessible);
+
+ g_object_ref(priv->state_set);
+
+ return priv->state_set;
+}
+
+inline static gint
+view_to_model_row(ETableItem *eti, gint row)
+{
+ if (eti->uses_source_model) {
+ ETableSubset *etss = E_TABLE_SUBSET(eti->table_model);
+ if (row >= 0 && row < etss->n_map) {
+ eti->row_guess = row;
+ return etss->map_table[row];
+ } else
+ return -1;
+ } else
+ return row;
+}
+
+inline static gint
+view_to_model_col(ETableItem *eti, gint col)
+{
+ ETableCol *ecol = e_table_header_get_column (eti->header, col);
+ return ecol ? ecol->col_idx : -1;
+}
+
+inline static gint
+model_to_view_row(ETableItem *eti, gint row)
+{
+ gint i;
+ if (row == -1)
+ return -1;
+ if (eti->uses_source_model) {
+ ETableSubset *etss = E_TABLE_SUBSET(eti->table_model);
+ if (eti->row_guess >= 0 && eti->row_guess < etss->n_map) {
+ if (etss->map_table[eti->row_guess] == row) {
+ return eti->row_guess;
+ }
+ }
+ for (i = 0; i < etss->n_map; i++) {
+ if (etss->map_table[i] == row)
+ return i;
+ }
+ return -1;
+ } else
+ return row;
+}
+
+inline static gint
+model_to_view_col(ETableItem *eti, gint col)
+{
+ gint i;
+ if (col == -1)
+ return -1;
+ for (i = 0; i < eti->cols; i++) {
+ ETableCol *ecol = e_table_header_get_column (eti->header, i);
+ if (ecol->col_idx == col)
+ return i;
+ }
+ return -1;
+}
+
+inline static GObject *
+eti_a11y_get_gobject (AtkObject *accessible)
+{
+ return atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (accessible));
+}
+
+static void
+eti_a11y_reset_focus_object (GalA11yETableItem *a11y, ETableItem *item, gboolean notify)
+{
+ ESelectionModel * esm;
+ gint cursor_row, cursor_col, view_row, view_col;
+ AtkObject *cell, *old_cell;
+
+ esm = item->selection;
+ g_return_if_fail (esm);
+
+ cursor_row = e_selection_model_cursor_row (esm);
+ cursor_col = e_selection_model_cursor_col (esm);
+
+ view_row = model_to_view_row (item, cursor_row);
+ view_col = model_to_view_col (item, cursor_col);
+
+ if (view_row == -1)
+ view_row = 0;
+ if (view_col == -1)
+ view_col = 0;
+
+ old_cell = (AtkObject *)g_object_get_data (G_OBJECT (a11y), "gail-focus-object");
+ if (old_cell && GAL_A11Y_IS_E_CELL (old_cell))
+ gal_a11y_e_cell_remove_state (GAL_A11Y_E_CELL (old_cell), ATK_STATE_FOCUSED, FALSE);
+ if (old_cell)
+ g_object_unref (old_cell);
+
+ cell = eti_ref_at (ATK_TABLE (a11y), view_row, view_col);
+
+ if (cell != NULL) {
+ g_object_set_data (G_OBJECT (a11y), "gail-focus-object", cell);
+ gal_a11y_e_cell_add_state (GAL_A11Y_E_CELL (cell), ATK_STATE_FOCUSED, FALSE);
+ } else
+ g_object_set_data (G_OBJECT (a11y), "gail-focus-object", NULL);
+
+ if (notify && cell)
+ atk_focus_tracker_notify (cell);
+}
+
+static void
+eti_dispose (GObject *object)
+{
+ GalA11yETableItem *a11y = GAL_A11Y_E_TABLE_ITEM (object);
+ GalA11yETableItemPrivate *priv = GET_PRIVATE (a11y);
+
+ if (priv->columns) {
+ g_free(priv->columns);
+ priv->columns = NULL;
+ }
+
+ if (parent_class->dispose)
+ parent_class->dispose (object);
+}
+
+/* Static functions */
+static gint
+eti_get_n_children (AtkObject *accessible)
+{
+ g_return_val_if_fail (GAL_A11Y_IS_E_TABLE_ITEM (accessible), 0);
+ if (!eti_a11y_get_gobject (accessible))
+ return 0;
+
+ return atk_table_get_n_columns (ATK_TABLE (accessible)) *
+ (atk_table_get_n_rows (ATK_TABLE (accessible)) + 1);
+}
+
+static AtkObject*
+eti_ref_child (AtkObject *accessible, gint index)
+{
+ ETableItem *item;
+ gint col, row;
+
+ g_return_val_if_fail (GAL_A11Y_IS_E_TABLE_ITEM (accessible), NULL);
+ item = E_TABLE_ITEM (eti_a11y_get_gobject (accessible));
+ if (!item)
+ return NULL;
+
+ if (index < item->cols) {
+ ETableCol *ecol;
+ AtkObject *child;
+
+ ecol = e_table_header_get_column (item->header, index);
+ child = gal_a11y_e_table_column_header_new (ecol, item);
+ return child;
+ }
+ index -= item->cols;
+
+ col = index % item->cols;
+ row = index / item->cols;
+
+ return eti_ref_at (ATK_TABLE (accessible), row, col);
+}
+
+static void
+eti_get_extents (AtkComponent *component,
+ gint *x,
+ gint *y,
+ gint *width,
+ gint *height,
+ AtkCoordType coord_type)
+{
+ ETableItem *item;
+ AtkObject *parent;
+
+ item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (component)));
+ if (!item)
+ return;
+
+ parent = ATK_OBJECT (component)->accessible_parent;
+ if (parent && ATK_IS_COMPONENT (parent))
+ atk_component_get_extents (ATK_COMPONENT (parent), x, y,
+ width, height,
+ coord_type);
+
+ if (parent && GAL_A11Y_IS_E_TABLE_CLICK_TO_ADD (parent)) {
+ ETableClickToAdd *etcta = E_TABLE_CLICK_TO_ADD (atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (parent)));
+ if (etcta) {
+ *width = etcta->width;
+ *height = etcta->height;
+ }
+ }
+}
+
+static AtkObject*
+eti_ref_accessible_at_point (AtkComponent *component,
+ gint x,
+ gint y,
+ AtkCoordType coord_type)
+{
+ gint row = -1;
+ gint col = -1;
+ gint x_origin, y_origin;
+ ETableItem *item;
+ GtkWidget *tableOrTree;
+
+ item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (component)));
+ if (!item)
+ return NULL;
+
+ atk_component_get_position (component,
+ &x_origin,
+ &y_origin,
+ coord_type);
+ x -= x_origin;
+ y -= y_origin;
+
+ tableOrTree = gtk_widget_get_parent (GTK_WIDGET (item->parent.canvas));
+
+ if (E_IS_TREE(tableOrTree))
+ e_tree_get_cell_at (E_TREE (tableOrTree), x, y, &row, &col);
+ else
+ e_table_get_cell_at (E_TABLE (tableOrTree), x, y, &row, &col);
+
+ if (row != -1 && col != -1) {
+ return eti_ref_at (ATK_TABLE (component), row, col);
+ } else {
+ return NULL;
+ }
+}
+
+
+static void
+cell_destroyed (gpointer data)
+{
+ GalA11yECell * cell;
+
+ g_return_if_fail (GAL_A11Y_IS_E_CELL (data));
+ cell = GAL_A11Y_E_CELL (data);
+
+ g_return_if_fail (cell->item && G_IS_OBJECT (cell->item));
+
+ if (cell->item) {
+ g_object_unref (cell->item);
+ cell->item = NULL;
+ }
+
+}
+
+/* atk table */
+static AtkObject*
+eti_ref_at (AtkTable *table, gint row, gint column)
+{
+ ETableItem *item;
+ AtkObject* ret;
+ GalA11yETableItemPrivate *priv = GET_PRIVATE (table);
+
+ if (atk_state_set_contains_state (priv->state_set, ATK_STATE_DEFUNCT))
+ return NULL;
+
+
+ item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (table)));
+ if (!item)
+ return NULL;
+
+ if (column >= 0 &&
+ column < item->cols &&
+ row >= 0 &&
+ row < item->rows &&
+ item->cell_views_realized) {
+ ECellView *cell_view = item->cell_views[column];
+ ETableCol *ecol = e_table_header_get_column (item->header, column);
+ ret = gal_a11y_e_cell_registry_get_object (NULL,
+ item,
+ cell_view,
+ ATK_OBJECT (table),
+ ecol->col_idx,
+ column,
+ row);
+ if (ATK_IS_OBJECT (ret)) {
+ g_object_weak_ref (G_OBJECT (ret),
+ (GWeakNotify) cell_destroyed,
+ ret);
+ /* if current cell is focused, add FOCUSED state */
+ if (e_selection_model_cursor_row (item->selection) == GAL_A11Y_E_CELL (ret)->row &&
+ e_selection_model_cursor_col (item->selection) == GAL_A11Y_E_CELL (ret)->model_col)
+ gal_a11y_e_cell_add_state (GAL_A11Y_E_CELL (ret), ATK_STATE_FOCUSED, FALSE);
+ } else
+ ret = NULL;
+
+ return ret;
+ }
+
+ return NULL;
+}
+
+static gint
+eti_get_index_at (AtkTable *table, gint row, gint column)
+{
+ ETableItem *item;
+
+ item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (table)));
+ if (!item)
+ return -1;
+
+ return column + (row + 1) * item->cols;
+}
+
+static gint
+eti_get_column_at_index (AtkTable *table, gint index)
+{
+ ETableItem *item;
+
+ item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (table)));
+ if (!item)
+ return -1;
+
+ return index % item->cols;
+}
+
+static gint
+eti_get_row_at_index (AtkTable *table, gint index)
+{
+ ETableItem *item;
+
+ item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (table)));
+ if (!item)
+ return -1;
+
+ return index / item->cols - 1;
+}
+
+static gint
+eti_get_n_columns (AtkTable *table)
+{
+ ETableItem *item;
+
+ item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (table)));
+ if (!item)
+ return -1;
+
+ return item->cols;
+}
+
+static gint
+eti_get_n_rows (AtkTable *table)
+{
+ ETableItem *item;
+
+ item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (table)));
+ if (!item)
+ return -1;
+
+ return item->rows;
+}
+
+static gint
+eti_get_column_extent_at (AtkTable *table,
+ gint row,
+ gint column)
+{
+ ETableItem *item;
+ gint width;
+
+ item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (table)));
+ if (!item)
+ return -1;
+
+ e_table_item_get_cell_geometry (item,
+ &row,
+ &column,
+ NULL,
+ NULL,
+ &width,
+ NULL);
+
+ return width;
+}
+
+static gint
+eti_get_row_extent_at (AtkTable *table,
+ gint row,
+ gint column)
+{
+ ETableItem *item;
+ gint height;
+
+ item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (table)));
+ if (!item)
+ return -1;
+
+ e_table_item_get_cell_geometry (item,
+ &row,
+ &column,
+ NULL,
+ NULL,
+ NULL,
+ &height);
+
+ return height;
+}
+
+static AtkObject *
+eti_get_caption (AtkTable *table)
+{
+ /* Unimplemented */
+ return NULL;
+}
+
+static G_CONST_RETURN gchar *
+eti_get_column_description (AtkTable *table,
+ gint column)
+{
+ ETableItem *item;
+ ETableCol *ecol;
+
+ item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (table)));
+ if (!item)
+ return NULL;
+
+ ecol = e_table_header_get_column (item->header, column);
+
+ return ecol->text;
+}
+
+static AtkObject *
+eti_get_column_header (AtkTable *table, gint column)
+{
+ ETableItem *item;
+ ETableCol *ecol;
+ AtkObject *atk_obj = NULL;
+
+ item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (table)));
+ if (!item)
+ return NULL;
+
+ ecol = e_table_header_get_column (item->header, column);
+ if (ecol) {
+ atk_obj = gal_a11y_e_table_column_header_new (ecol, item);
+ }
+
+ return atk_obj;
+}
+
+static G_CONST_RETURN gchar *
+eti_get_row_description (AtkTable *table,
+ gint row)
+{
+ /* Unimplemented */
+ return NULL;
+}
+
+static AtkObject *
+eti_get_row_header (AtkTable *table,
+ gint row)
+{
+ /* Unimplemented */
+ return NULL;
+}
+
+static AtkObject *
+eti_get_summary (AtkTable *table)
+{
+ /* Unimplemented */
+ return NULL;
+}
+
+static gboolean
+table_is_row_selected (AtkTable *table, gint row)
+{
+ ETableItem *item;
+ GalA11yETableItemPrivate *priv = GET_PRIVATE (table);
+
+ if (row < 0)
+ return FALSE;
+
+ if (atk_state_set_contains_state (priv->state_set, ATK_STATE_DEFUNCT))
+ return FALSE;
+
+ item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (table)));
+ if (!item)
+ return FALSE;
+
+ return e_selection_model_is_row_selected(item->selection, view_to_model_row (item, row));
+}
+
+static gboolean
+table_is_selected (AtkTable *table, gint row, gint column)
+{
+ return table_is_row_selected (table, row);
+}
+
+static gint
+table_get_selected_rows (AtkTable *table, gint **rows_selected)
+{
+ ETableItem *item;
+ gint n_selected, row, index_selected;
+ GalA11yETableItemPrivate *priv = GET_PRIVATE (table);
+
+ if (atk_state_set_contains_state (priv->state_set, ATK_STATE_DEFUNCT))
+ return 0;
+
+ item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (table)));
+ if (!item)
+ return 0;
+
+ n_selected = e_selection_model_selected_count (item->selection);
+ if (rows_selected) {
+ *rows_selected = (gint *) g_malloc (n_selected * sizeof (gint));
+
+ index_selected = 0;
+ for (row = 0; row < item->rows && index_selected < n_selected; ++row) {
+ if (atk_table_is_row_selected (table, row)) {
+ (*rows_selected)[index_selected] = row;
+ ++index_selected;
+ }
+ }
+ }
+ return n_selected;
+}
+
+static gboolean
+table_add_row_selection (AtkTable *table, gint row)
+{
+ ETableItem *item;
+
+ item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (table)));
+ if (!item)
+ return FALSE;
+
+ if (table_is_row_selected (table, row))
+ return TRUE;
+ e_selection_model_toggle_single_row (item->selection,
+ view_to_model_row (item, row));
+
+ return TRUE;
+}
+
+static gboolean
+table_remove_row_selection (AtkTable *table, gint row)
+{
+ ETableItem *item;
+ GalA11yETableItemPrivate *priv = GET_PRIVATE (table);
+
+ if (atk_state_set_contains_state (priv->state_set, ATK_STATE_DEFUNCT))
+ return FALSE;
+
+ item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (table)));
+ if (!item)
+ return FALSE;
+
+ if (!atk_table_is_row_selected (table, row))
+ return TRUE;
+ e_selection_model_toggle_single_row (item->selection, view_to_model_row (item, row));
+ return TRUE;
+}
+
+static void
+eti_atk_table_iface_init (AtkTableIface *iface)
+{
+ iface->ref_at = eti_ref_at;
+ iface->get_index_at = eti_get_index_at;
+ iface->get_column_at_index = eti_get_column_at_index;
+ iface->get_row_at_index = eti_get_row_at_index;
+ iface->get_n_columns = eti_get_n_columns;
+ iface->get_n_rows = eti_get_n_rows;
+ iface->get_column_extent_at = eti_get_column_extent_at;
+ iface->get_row_extent_at = eti_get_row_extent_at;
+ iface->get_caption = eti_get_caption;
+ iface->get_column_description = eti_get_column_description;
+ iface->get_column_header = eti_get_column_header;
+ iface->get_row_description = eti_get_row_description;
+ iface->get_row_header = eti_get_row_header;
+ iface->get_summary = eti_get_summary;
+
+ iface->is_row_selected = table_is_row_selected;
+ iface->is_selected = table_is_selected;
+ iface->get_selected_rows = table_get_selected_rows;
+ iface->add_row_selection = table_add_row_selection;
+ iface->remove_row_selection = table_remove_row_selection;
+}
+
+static void
+eti_atk_component_iface_init (AtkComponentIface *iface)
+{
+ component_parent_iface = g_type_interface_peek_parent (iface);
+
+ iface->ref_accessible_at_point = eti_ref_accessible_at_point;
+ iface->get_extents = eti_get_extents;
+}
+
+static void
+eti_rows_inserted (ETableModel * model, gint row, gint count,
+ AtkObject * table_item)
+{
+ gint n_cols,n_rows,i,j;
+ GalA11yETableItem * item_a11y;
+ gint old_nrows;
+
+ g_return_if_fail (table_item);
+ item_a11y = GAL_A11Y_E_TABLE_ITEM (table_item);
+
+ n_cols = atk_table_get_n_columns (ATK_TABLE(table_item));
+ n_rows = atk_table_get_n_rows (ATK_TABLE(table_item));
+
+ old_nrows = GET_PRIVATE(item_a11y)->rows;
+
+ g_return_if_fail (n_cols > 0 && n_rows > 0);
+ g_return_if_fail (old_nrows == n_rows - count);
+
+ GET_PRIVATE(table_item)->rows = n_rows;
+
+ g_signal_emit_by_name (table_item, "row-inserted", row,
+ count, NULL);
+
+ for (i = row; i < (row + count); i ++) {
+ for (j = 0; j < n_cols; j ++) {
+ g_signal_emit_by_name (table_item,
+ "children_changed::add",
+ ( ((i + 1)*n_cols) + j), NULL, NULL);
+ }
+ }
+
+ g_signal_emit_by_name (table_item, "visible-data-changed");
+}
+
+static void
+eti_rows_deleted (ETableModel * model, gint row, gint count,
+ AtkObject * table_item)
+{
+ gint i,j, n_rows, n_cols, old_nrows;
+ ETableItem *item = E_TABLE_ITEM (atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (table_item)));
+
+ n_rows = atk_table_get_n_rows (ATK_TABLE(table_item));
+ n_cols = atk_table_get_n_columns (ATK_TABLE(table_item));
+
+ old_nrows = GET_PRIVATE(table_item)->rows;
+
+ g_return_if_fail ( row+count <= old_nrows);
+ g_return_if_fail (old_nrows == n_rows + count);
+ GET_PRIVATE(table_item)->rows = n_rows;
+
+ g_signal_emit_by_name (table_item, "row-deleted", row,
+ count, NULL);
+
+ for (i = row; i < (row + count); i ++) {
+ for (j = 0; j < n_cols; j ++) {
+ g_signal_emit_by_name (table_item,
+ "children_changed::remove",
+ ( ((i + 1)*n_cols) + j), NULL, NULL);
+ }
+ }
+ g_signal_emit_by_name (table_item, "visible-data-changed");
+ eti_a11y_reset_focus_object ((GalA11yETableItem *)table_item, item, TRUE);
+}
+
+static void
+eti_tree_model_node_changed_cb (ETreeModel *model, ETreePath node, ETableItem *eti)
+{
+ AtkObject *atk_obj;
+ GalA11yETableItem *a11y;
+
+ g_return_if_fail (E_IS_TABLE_ITEM (eti));
+
+ atk_obj = atk_gobject_accessible_for_object (G_OBJECT (eti));
+ a11y = GAL_A11Y_E_TABLE_ITEM (atk_obj);
+
+ /* we can't figure out which rows are changed, so just send out a signal ... */
+ if (GET_PRIVATE (a11y)->rows > 0)
+ g_signal_emit_by_name (a11y, "visible-data-changed");
+}
+
+enum {
+ ETI_HEADER_UNCHANGED = 0,
+ ETI_HEADER_REORDERED,
+ ETI_HEADER_NEW_ADDED,
+ ETI_HEADER_REMOVED
+};
+
+/*
+ * 1. Check what actually happened: column reorder, remove or add
+ * 2. Update cache
+ * 3. Emit signals
+ */
+static void
+eti_header_structure_changed (ETableHeader *eth, AtkObject *a11y)
+{
+
+ gboolean reorder_found=FALSE, added_found=FALSE, removed_found=FALSE;
+ GalA11yETableItem * a11y_item;
+ ETableCol ** cols, **prev_cols;
+ GalA11yETableItemPrivate *priv;
+ gint *state = NULL, *prev_state = NULL, *reorder = NULL;
+ gint i,j,n_rows,n_cols, prev_n_cols;
+
+ a11y_item = GAL_A11Y_E_TABLE_ITEM (a11y);
+ priv = GET_PRIVATE (a11y_item);
+
+ /* Assume rows do not changed. */
+ n_rows = priv->rows;
+
+ prev_n_cols = priv->cols;
+ prev_cols = priv->columns;
+
+ cols = e_table_header_get_columns (eth);
+ n_cols = eth->col_count;
+
+ g_return_if_fail (cols && prev_cols && n_cols > 0);
+
+ /* Init to ETI_HEADER_UNCHANGED. */
+ state = g_malloc0 (sizeof (gint) * n_cols);
+ prev_state = g_malloc0 (sizeof (gint) * prev_n_cols);
+ reorder = g_malloc0 (sizeof (gint) * n_cols);
+
+ /* Compare with previously saved column headers. */
+ for ( i = 0; i < n_cols && cols[i]; i ++ ) {
+ for ( j = 0; j < prev_n_cols && prev_cols[j]; j ++ ) {
+ if ( prev_cols [j] == cols[i] && i != j ) {
+
+ reorder_found = TRUE;
+ state [i] = ETI_HEADER_REORDERED;
+ reorder [i] = j;
+
+ break;
+ } else if (prev_cols[j] == cols[i]) {
+ /* OK, this column is not changed. */
+ break;
+ }
+ }
+
+ /* cols[i] is new added column. */
+ if ( j == prev_n_cols ) {
+ added_found = TRUE;
+ state[i] = ETI_HEADER_NEW_ADDED;
+ }
+ }
+
+ /* Now try to find if there are removed columns. */
+ for (i = 0; i < prev_n_cols && prev_cols[i]; i ++) {
+ for (j = 0; j < n_cols && cols[j]; j ++)
+ if ( prev_cols [j] == cols[i] )
+ break;
+
+ /* Removed columns found. */
+ if ( j == n_cols ) {
+ removed_found = TRUE;
+ prev_state[j] = ETI_HEADER_REMOVED;
+ }
+ }
+
+ /* If nothing interesting just return. */
+ if (!reorder_found && !added_found && !removed_found)
+ return;
+
+ /* Emit signals */
+ if (reorder_found)
+ g_signal_emit_by_name (G_OBJECT(a11y_item), "column_reordered");
+
+
+ if (removed_found) {
+ for (i = 0; i < prev_n_cols; i ++ ) {
+ if (prev_state[i] == ETI_HEADER_REMOVED) {
+ g_signal_emit_by_name (G_OBJECT(a11y_item), "column-deleted", i, 1);
+ for (j = 0; j < n_rows; j ++)
+ g_signal_emit_by_name (G_OBJECT(a11y_item), "children_changed::remove", ((j+1)*prev_n_cols+i), NULL, NULL);
+ }
+ }
+ }
+
+ if (added_found) {
+ for ( i = 0; i < n_cols; i ++ ) {
+ if (state[i] == ETI_HEADER_NEW_ADDED) {
+ g_signal_emit_by_name (G_OBJECT(a11y_item), "column-inserted", i, 1);
+ for (j = 0; j < n_rows; j ++)
+ g_signal_emit_by_name (G_OBJECT(a11y_item), "children_changed::add", ((j+1)*n_cols+i), NULL, NULL);
+ }
+ }
+ }
+
+ priv->cols = n_cols;
+
+ g_free (state);
+ g_free (reorder);
+ g_free (prev_state);
+
+ g_free (priv->columns);
+ priv->columns = cols;
+}
+
+
+static void
+eti_real_initialize (AtkObject *obj,
+ gpointer data)
+{
+ ETableItem * eti;
+ ETableModel * model;
+
+ ATK_OBJECT_CLASS (parent_class)->initialize (obj, data);
+ eti = E_TABLE_ITEM (data);
+
+ model = eti->table_model;
+
+ g_signal_connect (model, "model-rows-inserted",
+ G_CALLBACK (eti_rows_inserted),
+ obj);
+ g_signal_connect (model, "model-rows-deleted",
+ G_CALLBACK (eti_rows_deleted),
+ obj);
+ g_signal_connect (G_OBJECT (eti->header), "structure_change",
+ G_CALLBACK (eti_header_structure_changed), obj);
+
+}
+
+static void
+eti_class_init (GalA11yETableItemClass *klass)
+{
+ AtkObjectClass *atk_object_class = ATK_OBJECT_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ quark_accessible_object = g_quark_from_static_string ("gtk-accessible-object");
+
+ parent_class = g_type_class_ref (PARENT_TYPE);
+
+ object_class->dispose = eti_dispose;
+
+ atk_object_class->get_n_children = eti_get_n_children;
+ atk_object_class->ref_child = eti_ref_child;
+ atk_object_class->initialize = eti_real_initialize;
+ atk_object_class->ref_state_set = eti_ref_state_set;
+}
+
+static void
+eti_init (GalA11yETableItem *a11y)
+{
+ GalA11yETableItemPrivate *priv;
+
+ priv = GET_PRIVATE (a11y);
+
+ priv->selection_change_id = 0;
+ priv->cursor_change_id = 0;
+ priv->selection = NULL;
+}
+
+/* atk selection */
+
+static void atk_selection_interface_init (AtkSelectionIface *iface);
+static gboolean selection_add_selection (AtkSelection *selection,
+ gint i);
+static gboolean selection_clear_selection (AtkSelection *selection);
+static AtkObject* selection_ref_selection (AtkSelection *selection,
+ gint i);
+static gint selection_get_selection_count (AtkSelection *selection);
+static gboolean selection_is_child_selected (AtkSelection *selection,
+ gint i);
+
+/* callbacks */
+static void eti_a11y_selection_model_removed_cb (ETableItem *eti,
+ ESelectionModel *selection,
+ gpointer data);
+static void eti_a11y_selection_model_added_cb (ETableItem *eti,
+ ESelectionModel *selection,
+ gpointer data);
+static void eti_a11y_selection_changed_cb (ESelectionModel *selection,
+ GalA11yETableItem *a11y);
+static void eti_a11y_cursor_changed_cb (ESelectionModel *selection,
+ gint row, gint col,
+ GalA11yETableItem *a11y);
+
+/**
+ * gal_a11y_e_table_item_get_type:
+ * @void:
+ *
+ * Registers the &GalA11yETableItem class if necessary, and returns the type ID
+ * associated to it.
+ *
+ * Return value: The type ID of the &GalA11yETableItem class.
+ **/
+GType
+gal_a11y_e_table_item_get_type (void)
+{
+ static GType type = 0;
+
+ if (!type) {
+ AtkObjectFactory *factory;
+
+ GTypeInfo info = {
+ sizeof (GalA11yETableItemClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) eti_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+ sizeof (GalA11yETableItem),
+ 0,
+ (GInstanceInitFunc) eti_init,
+ NULL /* value_table_item */
+ };
+
+ static const GInterfaceInfo atk_component_info = {
+ (GInterfaceInitFunc) eti_atk_component_iface_init,
+ (GInterfaceFinalizeFunc) NULL,
+ NULL
+ };
+ static const GInterfaceInfo atk_table_info = {
+ (GInterfaceInitFunc) eti_atk_table_iface_init,
+ (GInterfaceFinalizeFunc) NULL,
+ NULL
+ };
+
+ static const GInterfaceInfo atk_selection_info = {
+ (GInterfaceInitFunc) atk_selection_interface_init,
+ (GInterfaceFinalizeFunc) NULL,
+ NULL
+ };
+
+
+ factory = atk_registry_get_factory (atk_get_default_registry (), GNOME_TYPE_CANVAS_ITEM);
+ parent_type = atk_object_factory_get_accessible_type (factory);
+
+ type = gal_a11y_type_register_static_with_private (PARENT_TYPE, "GalA11yETableItem", &info, 0,
+ sizeof (GalA11yETableItemPrivate), &priv_offset);
+
+ g_type_add_interface_static (type, ATK_TYPE_COMPONENT, &atk_component_info);
+ g_type_add_interface_static (type, ATK_TYPE_TABLE, &atk_table_info);
+ g_type_add_interface_static (type, ATK_TYPE_SELECTION, &atk_selection_info);
+ }
+
+ return type;
+}
+
+AtkObject *
+gal_a11y_e_table_item_new (ETableItem *item)
+{
+ GalA11yETableItem *a11y;
+ AtkObject *accessible;
+ ESelectionModel * esm;
+ AtkObject *parent;
+ const gchar *name;
+
+ g_return_val_if_fail (item && item->cols >= 0 && item->rows >= 0, NULL);
+ a11y = g_object_new (gal_a11y_e_table_item_get_type (), NULL);
+
+ atk_object_initialize (ATK_OBJECT (a11y), item);
+
+ GET_PRIVATE (a11y)->state_set = atk_state_set_new ();
+
+ atk_state_set_add_state (GET_PRIVATE(a11y)->state_set, ATK_STATE_TRANSIENT);
+ atk_state_set_add_state (GET_PRIVATE(a11y)->state_set, ATK_STATE_ENABLED);
+ atk_state_set_add_state (GET_PRIVATE(a11y)->state_set, ATK_STATE_SENSITIVE);
+ atk_state_set_add_state (GET_PRIVATE(a11y)->state_set, ATK_STATE_SHOWING);
+ atk_state_set_add_state (GET_PRIVATE(a11y)->state_set, ATK_STATE_VISIBLE);
+
+
+ accessible = ATK_OBJECT(a11y);
+
+ /* Initialize cell data. */
+ GET_PRIVATE (a11y)->cols = item->cols;
+ GET_PRIVATE (a11y)->rows = item->rows;
+
+ GET_PRIVATE (a11y)->columns = e_table_header_get_columns (item->header);
+ if ( GET_PRIVATE (a11y)->columns == NULL)
+ return NULL;
+
+ if (item) {
+ g_signal_connect (G_OBJECT(item), "selection_model_removed",
+ G_CALLBACK (eti_a11y_selection_model_removed_cb), NULL);
+ g_signal_connect (G_OBJECT(item), "selection_model_added",
+ G_CALLBACK (eti_a11y_selection_model_added_cb), NULL);
+ if (item->selection)
+ gal_a11y_e_table_item_ref_selection (a11y,
+ item->selection);
+
+ /* find the TableItem's parent: table or tree */
+ GET_PRIVATE (a11y)->widget = gtk_widget_get_parent (GTK_WIDGET (item->parent.canvas));
+ parent = gtk_widget_get_accessible (GET_PRIVATE (a11y)->widget);
+ name = atk_object_get_name (parent);
+ if (name)
+ atk_object_set_name (accessible, name);
+ atk_object_set_parent (accessible, parent);
+
+ if (E_IS_TREE (GET_PRIVATE (a11y)->widget)) {
+ ETreeModel *model;
+ model = e_tree_get_model (E_TREE (GET_PRIVATE (a11y)->widget));
+ g_signal_connect (G_OBJECT(model), "node_changed",
+ G_CALLBACK (eti_tree_model_node_changed_cb), item);
+ accessible->role = ATK_ROLE_TREE_TABLE;
+ } else if (E_IS_TABLE (GET_PRIVATE (a11y)->widget)) {
+ accessible->role = ATK_ROLE_TABLE;
+ }
+ }
+
+ if (item)
+ g_signal_connect (G_OBJECT (item), "destroy",
+ G_CALLBACK (item_destroyed),
+ a11y);
+ esm = item->selection;
+
+ if (esm != NULL) {
+ eti_a11y_reset_focus_object (a11y, item, FALSE);
+ }
+
+ return ATK_OBJECT (a11y);
+}
+
+static gboolean
+gal_a11y_e_table_item_ref_selection (GalA11yETableItem *a11y,
+ ESelectionModel *selection)
+{
+ GalA11yETableItemPrivate *priv;
+
+ g_return_val_if_fail (a11y && selection, FALSE);
+
+ priv = GET_PRIVATE (a11y);
+ priv->selection_change_id = g_signal_connect (
+ G_OBJECT(selection), "selection_changed",
+ G_CALLBACK (eti_a11y_selection_changed_cb), a11y);
+ priv->cursor_change_id = g_signal_connect (
+ G_OBJECT(selection), "cursor_changed",
+ G_CALLBACK (eti_a11y_cursor_changed_cb), a11y);
+
+ priv->selection = selection;
+ g_object_ref (selection);
+
+ return TRUE;
+}
+
+static gboolean
+gal_a11y_e_table_item_unref_selection (GalA11yETableItem *a11y)
+{
+ GalA11yETableItemPrivate *priv;
+
+ g_return_val_if_fail (a11y, FALSE);
+
+ priv = GET_PRIVATE (a11y);
+
+ g_return_val_if_fail (priv->selection_change_id != 0, FALSE);
+ g_return_val_if_fail (priv->cursor_change_id != 0, FALSE);
+
+
+ g_signal_handler_disconnect (priv->selection,
+ priv->selection_change_id);
+ g_signal_handler_disconnect (priv->selection,
+ priv->cursor_change_id);
+ priv->cursor_change_id = 0;
+ priv->selection_change_id = 0;
+
+ g_object_unref (priv->selection);
+ priv->selection = NULL;
+
+ return TRUE;
+}
+
+/* callbacks */
+
+static void
+eti_a11y_selection_model_removed_cb (ETableItem *eti, ESelectionModel *selection,
+ gpointer data)
+{
+ AtkObject *atk_obj;
+ GalA11yETableItem *a11y;
+
+ g_return_if_fail (E_IS_TABLE_ITEM (eti));
+ g_return_if_fail (E_IS_SELECTION_MODEL (selection));
+
+ atk_obj = atk_gobject_accessible_for_object (G_OBJECT (eti));
+ a11y = GAL_A11Y_E_TABLE_ITEM (atk_obj);
+
+ if (selection == GET_PRIVATE (a11y)->selection)
+ gal_a11y_e_table_item_unref_selection (a11y);
+}
+
+static void
+eti_a11y_selection_model_added_cb (ETableItem *eti, ESelectionModel *selection,
+ gpointer data)
+{
+ AtkObject *atk_obj;
+ GalA11yETableItem *a11y;
+
+ g_return_if_fail (E_IS_TABLE_ITEM (eti));
+ g_return_if_fail (E_IS_SELECTION_MODEL (selection));
+
+ atk_obj = atk_gobject_accessible_for_object (G_OBJECT (eti));
+ a11y = GAL_A11Y_E_TABLE_ITEM (atk_obj);
+
+ if (GET_PRIVATE (a11y)->selection)
+ gal_a11y_e_table_item_unref_selection (a11y);
+ gal_a11y_e_table_item_ref_selection (a11y, selection);
+}
+
+static void
+eti_a11y_selection_changed_cb (ESelectionModel *selection, GalA11yETableItem *a11y)
+{
+ GalA11yETableItemPrivate *priv = GET_PRIVATE (a11y);
+
+ if (atk_state_set_contains_state (priv->state_set, ATK_STATE_DEFUNCT))
+ return;
+
+ g_return_if_fail (GAL_A11Y_IS_E_TABLE_ITEM (a11y));
+
+ g_signal_emit_by_name (a11y, "selection_changed");
+}
+
+static void
+eti_a11y_cursor_changed_cb (ESelectionModel *selection,
+ gint row, gint col, GalA11yETableItem *a11y)
+{
+ ETableItem *item;
+ GalA11yETableItemPrivate *priv = GET_PRIVATE (a11y);
+
+ g_return_if_fail (GAL_A11Y_IS_E_TABLE_ITEM (a11y));
+
+ if (atk_state_set_contains_state (priv->state_set, ATK_STATE_DEFUNCT))
+ return;
+
+ item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (a11y)));
+
+ g_return_if_fail (item);
+
+ if (row == -1 && col == -1)
+ return;
+ eti_a11y_reset_focus_object (a11y, item, TRUE);
+}
+
+/* atk selection */
+
+static void atk_selection_interface_init (AtkSelectionIface *iface)
+{
+ g_return_if_fail (iface != NULL);
+ iface->add_selection = selection_add_selection;
+ iface->clear_selection = selection_clear_selection;
+ iface->ref_selection = selection_ref_selection;
+ iface->get_selection_count = selection_get_selection_count;
+ iface->is_child_selected = selection_is_child_selected;
+}
+
+static gboolean
+selection_add_selection (AtkSelection *selection, gint index)
+{
+ AtkTable *table;
+ gint row, col, cursor_row, cursor_col, model_row, model_col;
+ ETableItem *item;
+
+ item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (selection)));
+ if (!item)
+ return FALSE;
+
+ table = ATK_TABLE (selection);
+
+ row = atk_table_get_row_at_index (table, index);
+ col = atk_table_get_column_at_index (table, index);
+
+ model_row = view_to_model_row (item, row);
+ model_col = view_to_model_col (item, col);
+
+ cursor_row = e_selection_model_cursor_row (item->selection);
+ cursor_col = e_selection_model_cursor_col (item->selection);
+
+ /* check whether is selected already */
+ if (model_row == cursor_row && model_col == cursor_col)
+ return TRUE;
+
+ if (model_row != cursor_row) {
+ /* we need to make the item get focus */
+ e_canvas_item_grab_focus (GNOME_CANVAS_ITEM (item), TRUE);
+
+ /* FIXME, currently we only support single row selection */
+ atk_selection_clear_selection (selection);
+ atk_table_add_row_selection (table, row);
+ }
+
+ e_selection_model_change_cursor (item->selection,
+ model_row,
+ model_col);
+ e_selection_model_cursor_changed (item->selection,
+ model_row,
+ model_col);
+ e_selection_model_cursor_activated (item->selection,
+ model_row,
+ model_col);
+ return TRUE;
+}
+
+static gboolean
+selection_clear_selection (AtkSelection *selection)
+{
+ ETableItem *item;
+
+ item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (selection)));
+ if (!item)
+ return FALSE;
+
+ e_selection_model_clear (item->selection);
+ return TRUE;
+}
+
+static AtkObject *
+selection_ref_selection (AtkSelection *selection, gint index)
+{
+ AtkTable *table;
+ gint row, col;
+
+ table = ATK_TABLE (selection);
+ row = atk_table_get_row_at_index (table, index);
+ col = atk_table_get_column_at_index (table, index);
+ if (!atk_table_is_row_selected (table, row))
+ return NULL;
+
+ return eti_ref_at (table, row, col);
+}
+
+static gint
+selection_get_selection_count (AtkSelection *selection)
+{
+ AtkTable *table;
+ gint n_selected;
+
+ table = ATK_TABLE (selection);
+ n_selected = atk_table_get_selected_rows (table, NULL);
+ if (n_selected > 0)
+ n_selected *= atk_table_get_n_columns (table);
+ return n_selected;
+}
+
+static gboolean
+selection_is_child_selected (AtkSelection *selection, gint i)
+{
+ gint row;
+
+ row = atk_table_get_row_at_index (ATK_TABLE (selection), i);
+ return atk_table_is_row_selected (ATK_TABLE (selection), row);
+}
+
+void
+gal_a11y_e_table_item_init (void)
+{
+ if (atk_get_root ())
+ atk_registry_set_factory_type (atk_get_default_registry (),
+ E_TABLE_ITEM_TYPE,
+ gal_a11y_e_table_item_factory_get_type ());
+}
+
diff --git a/widgets/table/gal-a11y-e-table-item.h b/widgets/table/gal-a11y-e-table-item.h
new file mode 100644
index 0000000000..27d6a8244b
--- /dev/null
+++ b/widgets/table/gal-a11y-e-table-item.h
@@ -0,0 +1,59 @@
+/*
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ * Christopher James Lahey <clahey@ximian.com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef __GAL_A11Y_E_TABLE_ITEM_H__
+#define __GAL_A11Y_E_TABLE_ITEM_H__
+
+#include <glib-object.h>
+#include <table/e-table-item.h>
+#include <atk/atkgobjectaccessible.h>
+
+#define GAL_A11Y_TYPE_E_TABLE_ITEM (gal_a11y_e_table_item_get_type ())
+#define GAL_A11Y_E_TABLE_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAL_A11Y_TYPE_E_TABLE_ITEM, GalA11yETableItem))
+#define GAL_A11Y_E_TABLE_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAL_A11Y_TYPE_E_TABLE_ITEM, GalA11yETableItemClass))
+#define GAL_A11Y_IS_E_TABLE_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAL_A11Y_TYPE_E_TABLE_ITEM))
+#define GAL_A11Y_IS_E_TABLE_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAL_A11Y_TYPE_E_TABLE_ITEM))
+
+typedef struct _GalA11yETableItem GalA11yETableItem;
+typedef struct _GalA11yETableItemClass GalA11yETableItemClass;
+typedef struct _GalA11yETableItemPrivate GalA11yETableItemPrivate;
+
+/* This struct should actually be larger as this isn't what we derive from.
+ * The GalA11yETableItemPrivate comes right after the parent class structure.
+ **/
+struct _GalA11yETableItem {
+ AtkGObjectAccessible parent;
+};
+
+struct _GalA11yETableItemClass {
+ AtkGObjectAccessibleClass parent_class;
+};
+
+
+/* Standard Glib function */
+GType gal_a11y_e_table_item_get_type (void);
+AtkObject *gal_a11y_e_table_item_new (ETableItem *item);
+
+void gal_a11y_e_table_item_init (void);
+
+#endif /* ! __GAL_A11Y_E_TABLE_ITEM_H__ */
diff --git a/widgets/table/gal-a11y-e-table.c b/widgets/table/gal-a11y-e-table.c
new file mode 100644
index 0000000000..bf75227af4
--- /dev/null
+++ b/widgets/table/gal-a11y-e-table.c
@@ -0,0 +1,308 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ * Christopher James Lahey <clahey@ximian.com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#include <config.h>
+
+#include "a11y/gal-a11y-util.h"
+#include "table/e-table.h"
+#include "table/e-table-click-to-add.h"
+#include "table/e-table-group.h"
+#include "table/e-table-group-container.h"
+#include "table/e-table-group-leaf.h"
+
+#include "gal-a11y-e-table.h"
+#include "gal-a11y-e-table-factory.h"
+#include "gal-a11y-e-table-item.h"
+
+#define CS_CLASS(a11y) (G_TYPE_INSTANCE_GET_CLASS ((a11y), C_TYPE_STREAM, GalA11yETableClass))
+static AtkObjectClass *parent_class;
+static GType parent_type;
+static gint priv_offset;
+#define GET_PRIVATE(object) ((GalA11yETablePrivate *) (((gchar *) object) + priv_offset))
+#define PARENT_TYPE (parent_type)
+
+struct _GalA11yETablePrivate {
+ AtkObject *child_item;
+};
+
+/* Static functions */
+static ETableItem *
+find_first_table_item (ETableGroup *group)
+{
+ GnomeCanvasGroup *cgroup;
+ GList *l;
+
+ cgroup = GNOME_CANVAS_GROUP (group);
+
+ for (l = cgroup->item_list; l; l = l->next) {
+ GnomeCanvasItem *i;
+
+ i = GNOME_CANVAS_ITEM (l->data);
+
+ if (E_IS_TABLE_GROUP (i))
+ return find_first_table_item (E_TABLE_GROUP (i));
+ else if (E_IS_TABLE_ITEM (i)) {
+ return E_TABLE_ITEM (i);
+ }
+ }
+
+ return NULL;
+}
+
+static AtkObject*
+eti_get_accessible (ETableItem *eti, AtkObject *parent)
+{
+ AtkObject *a11y = NULL;
+
+ g_return_val_if_fail (eti, NULL);
+
+ a11y = atk_gobject_accessible_for_object (G_OBJECT (eti));
+ g_return_val_if_fail (a11y, NULL);
+
+ return a11y;
+}
+
+static gboolean
+init_child_item (GalA11yETable *a11y)
+{
+ ETable *table;
+
+ if (!a11y || !GTK_IS_ACCESSIBLE (a11y))
+ return FALSE;
+
+ table = E_TABLE (GTK_ACCESSIBLE (a11y)->widget);
+ if (table && GTK_WIDGET_MAPPED (GTK_WIDGET (table)) && table->group && E_IS_TABLE_GROUP_CONTAINER(table->group)) {
+ ETableGroupContainer *etgc = (ETableGroupContainer *)table->group;
+ GList *list;
+
+ for (list = etgc->children; list; list = g_list_next (list)) {
+ ETableGroupContainerChildNode *child_node = list->data;
+ ETableGroup *child = child_node->child;
+ ETableItem *eti = find_first_table_item (child);
+
+ eti_get_accessible (eti, ATK_OBJECT (a11y));
+ }
+ }
+ g_object_unref (a11y);
+ g_object_unref (table);
+
+ return FALSE;
+}
+
+static AtkObject*
+et_ref_accessible_at_point (AtkComponent *component,
+ gint x,
+ gint y,
+ AtkCoordType coord_type)
+{
+ GalA11yETable *a11y = GAL_A11Y_E_TABLE (component);
+ if (GET_PRIVATE (a11y)->child_item)
+ g_object_ref (GET_PRIVATE (a11y)->child_item);
+ return GET_PRIVATE (a11y)->child_item;
+}
+
+static gint
+et_get_n_children (AtkObject *accessible)
+{
+ GalA11yETable *a11y = GAL_A11Y_E_TABLE (accessible);
+ ETable * et;
+ gint n = 0;
+
+ et = E_TABLE(GTK_ACCESSIBLE (a11y)->widget);
+
+ if (et->group) {
+ if (E_IS_TABLE_GROUP_LEAF (et->group))
+ n = 1;
+ else if (E_IS_TABLE_GROUP_CONTAINER (et->group)) {
+ ETableGroupContainer *etgc = (ETableGroupContainer *)et->group;
+ n = g_list_length (etgc->children);
+ }
+ }
+
+ if (et && et->use_click_to_add && et->click_to_add) {
+ n++;
+ }
+ return n;
+}
+
+static AtkObject*
+et_ref_child (AtkObject *accessible,
+ gint i)
+{
+ GalA11yETable *a11y = GAL_A11Y_E_TABLE (accessible);
+ ETable * et;
+ gint child_no;
+
+ et = E_TABLE(GTK_ACCESSIBLE (a11y)->widget);
+
+ child_no = et_get_n_children (accessible);
+ if (i == 0 || i < child_no - 1) {
+ if (E_IS_TABLE_GROUP_LEAF (et->group)) {
+ ETableItem *eti = find_first_table_item (et->group);
+ AtkObject *aeti = eti_get_accessible (eti, accessible);
+ if (aeti)
+ g_object_ref (aeti);
+ return aeti;
+
+ } else if (E_IS_TABLE_GROUP_CONTAINER (et->group)) {
+ ETableGroupContainer *etgc = (ETableGroupContainer *) et->group;
+ ETableGroupContainerChildNode *child_node = g_list_nth_data (etgc->children, i);
+ if (child_node) {
+ ETableGroup *child = child_node->child;
+ ETableItem * eti = find_first_table_item (child);
+ AtkObject *aeti = eti_get_accessible (eti, accessible);
+ if (aeti)
+ g_object_ref (aeti);
+ return aeti;
+ }
+ }
+ } else if (i == child_no -1) {
+ ETableClickToAdd * etcta;
+
+ if (et && et->use_click_to_add && et->click_to_add) {
+ etcta = E_TABLE_CLICK_TO_ADD(et->click_to_add);
+ accessible = atk_gobject_accessible_for_object (G_OBJECT(etcta));
+ if (accessible)
+ g_object_ref (accessible);
+ return accessible;
+ }
+ }
+
+ return NULL;
+}
+
+static AtkLayer
+et_get_layer (AtkComponent *component)
+{
+ return ATK_LAYER_WIDGET;
+}
+
+static void
+et_class_init (GalA11yETableClass *klass)
+{
+ AtkObjectClass *atk_object_class = ATK_OBJECT_CLASS (klass);
+
+ parent_class = g_type_class_ref (PARENT_TYPE);
+
+ atk_object_class->get_n_children = et_get_n_children;
+ atk_object_class->ref_child = et_ref_child;
+}
+
+static void
+et_atk_component_iface_init (AtkComponentIface *iface)
+{
+ iface->ref_accessible_at_point = et_ref_accessible_at_point;
+ iface->get_layer = et_get_layer;
+}
+
+static void
+et_init (GalA11yETable *a11y)
+{
+ GalA11yETablePrivate *priv;
+
+ priv = GET_PRIVATE (a11y);
+
+ priv->child_item = NULL;
+}
+
+/**
+ * gal_a11y_e_table_get_type:
+ * @void:
+ *
+ * Registers the &GalA11yETable class if necessary, and returns the type ID
+ * associated to it.
+ *
+ * Return value: The type ID of the &GalA11yETable class.
+ **/
+GType
+gal_a11y_e_table_get_type (void)
+{
+ static GType type = 0;
+
+ if (!type) {
+ AtkObjectFactory *factory;
+
+ GTypeInfo info = {
+ sizeof (GalA11yETableClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) et_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+ sizeof (GalA11yETable),
+ 0,
+ (GInstanceInitFunc) et_init,
+ NULL /* value_table */
+ };
+
+ static const GInterfaceInfo atk_component_info = {
+ (GInterfaceInitFunc) et_atk_component_iface_init,
+ (GInterfaceFinalizeFunc) NULL,
+ NULL
+ };
+
+ factory = atk_registry_get_factory (atk_get_default_registry (), GTK_TYPE_WIDGET);
+ parent_type = atk_object_factory_get_accessible_type (factory);
+
+ type = gal_a11y_type_register_static_with_private (PARENT_TYPE, "GalA11yETable", &info, 0,
+ sizeof (GalA11yETablePrivate), &priv_offset);
+ g_type_add_interface_static (type, ATK_TYPE_COMPONENT, &atk_component_info);
+ }
+
+ return type;
+}
+
+AtkObject *
+gal_a11y_e_table_new (GObject *widget)
+{
+ GalA11yETable *a11y;
+ ETable *table;
+
+ table = E_TABLE (widget);
+
+ a11y = g_object_new (gal_a11y_e_table_get_type (), NULL);
+
+ GTK_ACCESSIBLE (a11y)->widget = GTK_WIDGET (widget);
+
+ /* we need to init all the children for multiple table items */
+ if (table && GTK_WIDGET_MAPPED (GTK_WIDGET (table)) && table->group && E_IS_TABLE_GROUP_CONTAINER (table->group)) {
+ /* Ref it here so that it is still valid in the idle function */
+ /* It will be unrefed in the idle function */
+ g_object_ref (a11y);
+ g_object_ref (widget);
+
+ g_idle_add ((GSourceFunc)init_child_item, a11y);
+ }
+
+ return ATK_OBJECT (a11y);
+}
+
+void
+gal_a11y_e_table_init (void)
+{
+ if (atk_get_root ())
+ atk_registry_set_factory_type (atk_get_default_registry (),
+ E_TABLE_TYPE,
+ gal_a11y_e_table_factory_get_type ());
+
+}
+
diff --git a/widgets/table/gal-a11y-e-table.h b/widgets/table/gal-a11y-e-table.h
new file mode 100644
index 0000000000..d8f972df81
--- /dev/null
+++ b/widgets/table/gal-a11y-e-table.h
@@ -0,0 +1,59 @@
+/*
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ * Christopher James Lahey <clahey@ximian.com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef __GAL_A11Y_E_TABLE_H__
+#define __GAL_A11Y_E_TABLE_H__
+
+#include <gtk/gtk.h>
+#include <atk/atkobject.h>
+#include <atk/atkcomponent.h>
+
+#define GAL_A11Y_TYPE_E_TABLE (gal_a11y_e_table_get_type ())
+#define GAL_A11Y_E_TABLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAL_A11Y_TYPE_E_TABLE, GalA11yETable))
+#define GAL_A11Y_E_TABLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAL_A11Y_TYPE_E_TABLE, GalA11yETableClass))
+#define GAL_A11Y_IS_E_TABLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAL_A11Y_TYPE_E_TABLE))
+#define GAL_A11Y_IS_E_TABLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAL_A11Y_TYPE_E_TABLE))
+
+typedef struct _GalA11yETable GalA11yETable;
+typedef struct _GalA11yETableClass GalA11yETableClass;
+typedef struct _GalA11yETablePrivate GalA11yETablePrivate;
+
+/* This struct should actually be larger as this isn't what we derive from.
+ * The GalA11yETablePrivate comes right after the parent class structure.
+ **/
+struct _GalA11yETable {
+ GtkAccessible object;
+};
+
+struct _GalA11yETableClass {
+ GtkAccessibleClass parent_class;
+};
+
+
+/* Standard Glib function */
+GType gal_a11y_e_table_get_type (void);
+AtkObject *gal_a11y_e_table_new (GObject *table);
+
+void gal_a11y_e_table_init (void);
+
+#endif /* ! __GAL_A11Y_E_TABLE_H__ */
diff --git a/widgets/table/gal-a11y-e-tree-factory.c b/widgets/table/gal-a11y-e-tree-factory.c
new file mode 100644
index 0000000000..8dc06e2936
--- /dev/null
+++ b/widgets/table/gal-a11y-e-tree-factory.c
@@ -0,0 +1,98 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ * Yuedong Du <yuedong.du@sun.com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#include <config.h>
+
+#include "gal-a11y-e-tree.h"
+#include "gal-a11y-e-tree-factory.h"
+
+#define CS_CLASS(factory) (G_TYPE_INSTANCE_GET_CLASS ((factory), C_TYPE_STREAM, GalA11yETreeFactoryClass))
+static AtkObjectFactoryClass *parent_class;
+#define PARENT_TYPE (ATK_TYPE_OBJECT_FACTORY)
+
+/* Static functions */
+
+static GType
+gal_a11y_e_tree_factory_get_accessible_type (void)
+{
+ return GAL_A11Y_TYPE_E_TREE;
+}
+
+static AtkObject*
+gal_a11y_e_tree_factory_create_accessible (GObject *obj)
+{
+ AtkObject *accessible;
+
+ accessible = gal_a11y_e_tree_new (obj);
+
+ return accessible;
+}
+
+static void
+gal_a11y_e_tree_factory_class_init (GalA11yETreeFactoryClass *klass)
+{
+ AtkObjectFactoryClass *factory_class = ATK_OBJECT_FACTORY_CLASS (klass);
+
+ parent_class = g_type_class_ref (PARENT_TYPE);
+
+ factory_class->create_accessible = gal_a11y_e_tree_factory_create_accessible;
+ factory_class->get_accessible_type = gal_a11y_e_tree_factory_get_accessible_type;
+}
+
+static void
+gal_a11y_e_tree_factory_init (GalA11yETreeFactory *factory)
+{
+}
+
+/**
+ * gal_a11y_e_tree_factory_get_type:
+ * @void:
+ *
+ * Registers the &GalA11yETreeFactory class if necessary, and returns the type ID
+ * associated to it.
+ *
+ * Return value: The type ID of the &GalA11yETreeFactory class.
+ **/
+GType
+gal_a11y_e_tree_factory_get_type (void)
+{
+ static GType type = 0;
+
+ if (!type) {
+ GTypeInfo info = {
+ sizeof (GalA11yETreeFactoryClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) gal_a11y_e_tree_factory_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+ sizeof (GalA11yETreeFactory),
+ 0,
+ (GInstanceInitFunc) gal_a11y_e_tree_factory_init,
+ NULL /* value_tree */
+ };
+
+ type = g_type_register_static (PARENT_TYPE, "GalA11yETreeFactory", &info, 0);
+ }
+
+ return type;
+}
diff --git a/widgets/table/gal-a11y-e-tree-factory.h b/widgets/table/gal-a11y-e-tree-factory.h
new file mode 100644
index 0000000000..3d97c7a3b1
--- /dev/null
+++ b/widgets/table/gal-a11y-e-tree-factory.h
@@ -0,0 +1,50 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ * Yuedong Du <yuedong.du@ximian.com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef __GAL_A11Y_E_TREE_FACTORY_H__
+#define __GAL_A11Y_E_TREE_FACTORY_H__
+
+#include <glib-object.h>
+#include <atk/atkobjectfactory.h>
+
+#define GAL_A11Y_TYPE_E_TREE_FACTORY (gal_a11y_e_table_factory_get_type ())
+#define GAL_A11Y_E_TREE_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAL_A11Y_TYPE_E_TREE_FACTORY, GalA11yETreeFactory))
+#define GAL_A11Y_E_TREE_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAL_A11Y_TYPE_E_TREE_FACTORY, GalA11yETreeFactoryClass))
+#define GAL_A11Y_IS_E_TREE_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAL_A11Y_TYPE_E_TREE_FACTORY))
+#define GAL_A11Y_IS_E_TREE_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAL_A11Y_TYPE_E_TREE_FACTORY))
+
+typedef struct _GalA11yETreeFactory GalA11yETreeFactory;
+typedef struct _GalA11yETreeFactoryClass GalA11yETreeFactoryClass;
+
+struct _GalA11yETreeFactory {
+ AtkObject object;
+};
+
+struct _GalA11yETreeFactoryClass {
+ AtkObjectClass parent_class;
+};
+
+
+/* Standard Glib function */
+GType gal_a11y_e_tree_factory_get_type (void);
+
+#endif /* ! __GAL_A11Y_E_TREE_FACTORY_H__ */
diff --git a/widgets/table/gal-a11y-e-tree.c b/widgets/table/gal-a11y-e-tree.c
new file mode 100644
index 0000000000..879b517aab
--- /dev/null
+++ b/widgets/table/gal-a11y-e-tree.c
@@ -0,0 +1,191 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ * Yuedong Du <yuedong.du@sun.com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#include <config.h>
+
+#include "a11y/gal-a11y-util.h"
+#include "table/e-table-item.h"
+#include "table/e-tree.h"
+
+#include "gal-a11y-e-table-item.h"
+#include "gal-a11y-e-tree.h"
+#include "gal-a11y-e-tree-factory.h"
+
+#define CS_CLASS(a11y) (G_TYPE_INSTANCE_GET_CLASS ((a11y), C_TYPE_STREAM, GalA11yETreeClass))
+static AtkObjectClass *parent_class;
+static GType parent_type;
+static gint priv_offset;
+#define GET_PRIVATE(object) ((GalA11yETreePrivate *) (((gchar *) object) + priv_offset))
+#define PARENT_TYPE (parent_type)
+
+struct _GalA11yETreePrivate {
+ AtkObject *child_item;
+};
+
+/* Static functions */
+
+static void
+init_child_item (GalA11yETree *a11y)
+{
+ GalA11yETreePrivate *priv = GET_PRIVATE (a11y);
+ ETree *tree = E_TREE (GTK_ACCESSIBLE (a11y)->widget);
+ ETableItem * eti;
+
+ g_return_if_fail (tree);
+ eti = e_tree_get_item (tree);
+ if (priv->child_item == NULL) {
+ priv->child_item = atk_gobject_accessible_for_object (G_OBJECT (eti));
+ }
+}
+
+static AtkObject*
+et_ref_accessible_at_point (AtkComponent *component,
+ gint x,
+ gint y,
+ AtkCoordType coord_type)
+{
+ GalA11yETree *a11y = GAL_A11Y_E_TREE (component);
+ init_child_item (a11y);
+ return GET_PRIVATE (a11y)->child_item;
+}
+
+static gint
+et_get_n_children (AtkObject *accessible)
+{
+ return 1;
+}
+
+static AtkObject*
+et_ref_child (AtkObject *accessible,
+ gint i)
+{
+ GalA11yETree *a11y = GAL_A11Y_E_TREE (accessible);
+ if (i != 0)
+ return NULL;
+ init_child_item (a11y);
+ g_object_ref (GET_PRIVATE (a11y)->child_item);
+ return GET_PRIVATE (a11y)->child_item;
+}
+
+static AtkLayer
+et_get_layer (AtkComponent *component)
+{
+ return ATK_LAYER_WIDGET;
+}
+
+static void
+et_class_init (GalA11yETreeClass *klass)
+{
+ AtkObjectClass *atk_object_class = ATK_OBJECT_CLASS (klass);
+
+ parent_class = g_type_class_ref (PARENT_TYPE);
+
+ atk_object_class->get_n_children = et_get_n_children;
+ atk_object_class->ref_child = et_ref_child;
+}
+
+static void
+et_atk_component_iface_init (AtkComponentIface *iface)
+{
+ iface->ref_accessible_at_point = et_ref_accessible_at_point;
+ iface->get_layer = et_get_layer;
+}
+
+static void
+et_init (GalA11yETree *a11y)
+{
+ GalA11yETreePrivate *priv;
+
+ priv = GET_PRIVATE (a11y);
+
+ priv->child_item = NULL;
+}
+
+/**
+ * gal_a11y_e_tree_get_type:
+ * @void:
+ *
+ * Registers the &GalA11yETree class if necessary, and returns the type ID
+ * associated to it.
+ *
+ * Return value: The type ID of the &GalA11yETree class.
+ **/
+GType
+gal_a11y_e_tree_get_type (void)
+{
+ static GType type = 0;
+
+ if (!type) {
+ AtkObjectFactory *factory;
+
+ GTypeInfo info = {
+ sizeof (GalA11yETreeClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) et_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+ sizeof (GalA11yETree),
+ 0,
+ (GInstanceInitFunc) et_init,
+ NULL /* value_tree */
+ };
+
+ static const GInterfaceInfo atk_component_info = {
+ (GInterfaceInitFunc) et_atk_component_iface_init,
+ (GInterfaceFinalizeFunc) NULL,
+ NULL
+ };
+
+ factory = atk_registry_get_factory (atk_get_default_registry (), GTK_TYPE_WIDGET);
+ parent_type = atk_object_factory_get_accessible_type (factory);
+
+ type = gal_a11y_type_register_static_with_private (PARENT_TYPE, "GalA11yETree", &info, 0,
+ sizeof (GalA11yETreePrivate), &priv_offset);
+ g_type_add_interface_static (type, ATK_TYPE_COMPONENT, &atk_component_info);
+ }
+
+ return type;
+}
+
+AtkObject *
+gal_a11y_e_tree_new (GObject *widget)
+{
+ GalA11yETree *a11y;
+
+ a11y = g_object_new (gal_a11y_e_tree_get_type (), NULL);
+
+ GTK_ACCESSIBLE (a11y)->widget = GTK_WIDGET (widget);
+
+ return ATK_OBJECT (a11y);
+}
+
+void
+gal_a11y_e_tree_init (void)
+{
+ if (atk_get_root ())
+ atk_registry_set_factory_type (atk_get_default_registry (),
+ E_TREE_TYPE,
+ gal_a11y_e_tree_factory_get_type ());
+
+}
+
diff --git a/widgets/table/gal-a11y-e-tree.h b/widgets/table/gal-a11y-e-tree.h
new file mode 100644
index 0000000000..d2aa8a0d2a
--- /dev/null
+++ b/widgets/table/gal-a11y-e-tree.h
@@ -0,0 +1,58 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ * Yuedong Du <yuedong.du@sun.com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef __GAL_A11Y_E_TREE_H__
+#define __GAL_A11Y_E_TREE_H__
+
+#include <gtk/gtk.h>
+#include <atk/atkobject.h>
+#include <atk/atkcomponent.h>
+
+#define GAL_A11Y_TYPE_E_TREE (gal_a11y_e_tree_get_type ())
+#define GAL_A11Y_E_TREE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAL_A11Y_TYPE_E_TREE, GalA11yETree))
+#define GAL_A11Y_E_TREE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAL_A11Y_TYPE_E_TREE, GalA11yETreeClass))
+#define GAL_A11Y_IS_E_TREE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAL_A11Y_TYPE_E_TREE))
+#define GAL_A11Y_IS_E_TREE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAL_A11Y_TYPE_E_TREE))
+
+typedef struct _GalA11yETree GalA11yETree;
+typedef struct _GalA11yETreeClass GalA11yETreeClass;
+typedef struct _GalA11yETreePrivate GalA11yETreePrivate;
+
+/* This struct should actually be larger as this isn't what we derive from.
+ * The GalA11yETablePrivate comes right after the parent class structure.
+ **/
+struct _GalA11yETree {
+ GtkAccessible object;
+};
+
+struct _GalA11yETreeClass {
+ GtkAccessibleClass parent_class;
+};
+
+
+/* Standard Glib function */
+GType gal_a11y_e_tree_get_type (void);
+AtkObject *gal_a11y_e_tree_new (GObject *tree);
+
+void gal_a11y_e_tree_init (void);
+
+#endif /* ! __GAL_A11Y_E_TREE_H__ */
diff --git a/widgets/text/Makefile.am b/widgets/text/Makefile.am
index ad106158d9..ee426f4791 100644
--- a/widgets/text/Makefile.am
+++ b/widgets/text/Makefile.am
@@ -15,22 +15,29 @@ privsolib_LTLIBRARIES = libetext.la
libetext_la_SOURCES = \
e-text-model-repos.c \
e-text-model.c \
- e-text.c
+ e-text.c \
+ e-reflow.c \
+ e-reflow-model.c \
+ gal-a11y-e-text-factory.c \
+ gal-a11y-e-text.c
libetextincludedir = $(privincludedir)/text
libetextinclude_HEADERS = \
e-text-model-repos.h \
e-text-model.h \
- e-text.h
+ e-text.h \
+ e-reflow.h \
+ e-reflow-model.h \
+ gal-a11y-e-text-factory.h \
+ gal-a11y-e-text.h
libetext_la_LDFLAGS = $(NO_UNDEFINED)
libetext_la_LIBADD = \
- $(WIN32_BOOTSTRAP_LIBS) \
- $(top_builddir)/e-util/libeutil.la \
$(top_builddir)/a11y/libevolution-a11y.la \
- $(top_builddir)/widgets/table/libetable.la \
+ $(top_builddir)/e-util/libeutil.la \
+ $(top_builddir)/widgets/misc/libemiscwidgets.la \
$(E_UTIL_LIBS) \
$(GNOME_PLATFORM_LIBS) \
$(REGEX_LIBS)
diff --git a/widgets/misc/e-reflow-model.c b/widgets/text/e-reflow-model.c
index 2bf5e4990d..2bf5e4990d 100644
--- a/widgets/misc/e-reflow-model.c
+++ b/widgets/text/e-reflow-model.c
diff --git a/widgets/misc/e-reflow-model.h b/widgets/text/e-reflow-model.h
index ebbf3c1f75..ebbf3c1f75 100644
--- a/widgets/misc/e-reflow-model.h
+++ b/widgets/text/e-reflow-model.h
diff --git a/widgets/misc/e-reflow.c b/widgets/text/e-reflow.c
index c20edfc5e4..441102ac0f 100644
--- a/widgets/misc/e-reflow.c
+++ b/widgets/text/e-reflow.c
@@ -30,12 +30,12 @@
#include "text/e-text.h"
#include <glib/gi18n.h>
#include "e-util/e-util.h"
-#include "misc/e-unicode.h"
+#include "e-util/e-unicode.h"
-#include "e-canvas.h"
-#include "e-canvas-utils.h"
+#include "misc/e-canvas.h"
+#include "misc/e-canvas-utils.h"
#include "e-reflow.h"
-#include "e-selection-model-simple.h"
+#include "misc/e-selection-model-simple.h"
static gboolean e_reflow_event (GnomeCanvasItem *item, GdkEvent *event);
static void e_reflow_realize (GnomeCanvasItem *item);
diff --git a/widgets/misc/e-reflow.h b/widgets/text/e-reflow.h
index 19e6d4a709..234dbc16a2 100644
--- a/widgets/misc/e-reflow.h
+++ b/widgets/text/e-reflow.h
@@ -24,7 +24,7 @@
#define __E_REFLOW_H__
#include <libgnomecanvas/gnome-canvas.h>
-#include <misc/e-reflow-model.h>
+#include <text/e-reflow-model.h>
#include <misc/e-selection-model.h>
#include <e-util/e-sorter-array.h>
diff --git a/widgets/text/e-text.c b/widgets/text/e-text.c
index 0b2f84cf8e..7c542d8f5f 100644
--- a/widgets/text/e-text.c
+++ b/widgets/text/e-text.c
@@ -46,10 +46,10 @@
#include <gtk/gtk.h>
#include <libgnomecanvas/gnome-canvas-rect-ellipse.h>
-#include "a11y/e-text/gal-a11y-e-text.h"
+#include "gal-a11y-e-text.h"
#include "misc/e-canvas.h"
#include "misc/e-canvas-utils.h"
-#include "misc/e-unicode.h"
+#include "e-util/e-unicode.h"
#include <glib/gi18n.h>
#include "e-util/e-text-event-processor-emacs-like.h"
#include "e-util/e-util.h"
diff --git a/widgets/text/gal-a11y-e-text-factory.c b/widgets/text/gal-a11y-e-text-factory.c
new file mode 100644
index 0000000000..2df9241014
--- /dev/null
+++ b/widgets/text/gal-a11y-e-text-factory.c
@@ -0,0 +1,101 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ * Christopher James Lahey <clahey@ximian.com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#include <config.h>
+#include "text/e-text.h"
+#include "gal-a11y-e-text-factory.h"
+#include "gal-a11y-e-text.h"
+
+#define CS_CLASS(factory) (G_TYPE_INSTANCE_GET_CLASS ((factory), C_TYPE_STREAM, GalA11yETextFactoryClass))
+static AtkObjectFactoryClass *parent_class;
+#define PARENT_TYPE (ATK_TYPE_OBJECT_FACTORY)
+
+/* Static functions */
+
+static GType
+gal_a11y_e_text_factory_get_accessible_type (void)
+{
+ return GAL_A11Y_TYPE_E_TEXT;
+}
+
+static AtkObject*
+gal_a11y_e_text_factory_create_accessible (GObject *obj)
+{
+ AtkObject *atk_object;
+
+ g_return_val_if_fail (E_IS_TEXT (obj), NULL);
+
+ atk_object = g_object_new (GAL_A11Y_TYPE_E_TEXT, NULL);
+ atk_object_initialize (atk_object, obj);
+
+ return atk_object;
+}
+
+static void
+gal_a11y_e_text_factory_class_init (GalA11yETextFactoryClass *klass)
+{
+ AtkObjectFactoryClass *factory_class = ATK_OBJECT_FACTORY_CLASS (klass);
+
+ parent_class = g_type_class_ref (PARENT_TYPE);
+
+ factory_class->create_accessible = gal_a11y_e_text_factory_create_accessible;
+ factory_class->get_accessible_type = gal_a11y_e_text_factory_get_accessible_type;
+}
+
+static void
+gal_a11y_e_text_factory_init (GalA11yETextFactory *factory)
+{
+}
+
+/**
+ * gal_a11y_e_text_factory_get_type:
+ * @void:
+ *
+ * Registers the &GalA11yETextFactory class if necessary, and returns the type ID
+ * associated to it.
+ *
+ * Return value: The type ID of the &GalA11yETextFactory class.
+ **/
+GType
+gal_a11y_e_text_factory_get_type (void)
+{
+ static GType type = 0;
+
+ if (!type) {
+ GTypeInfo info = {
+ sizeof (GalA11yETextFactoryClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) gal_a11y_e_text_factory_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+ sizeof (GalA11yETextFactory),
+ 0,
+ (GInstanceInitFunc) gal_a11y_e_text_factory_init,
+ NULL /* value_text */
+ };
+
+ type = g_type_register_static (PARENT_TYPE, "GalA11yETextFactory", &info, 0);
+ }
+
+ return type;
+}
diff --git a/widgets/text/gal-a11y-e-text-factory.h b/widgets/text/gal-a11y-e-text-factory.h
new file mode 100644
index 0000000000..df7638f64f
--- /dev/null
+++ b/widgets/text/gal-a11y-e-text-factory.h
@@ -0,0 +1,50 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ * Christopher James Lahey <clahey@ximian.com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef __GAL_A11Y_E_TEXT_FACTORY_H__
+#define __GAL_A11Y_E_TEXT_FACTORY_H__
+
+#include <glib-object.h>
+#include <atk/atkobjectfactory.h>
+
+#define GAL_A11Y_TYPE_E_TEXT_FACTORY (gal_a11y_e_text_factory_get_type ())
+#define GAL_A11Y_E_TEXT_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAL_A11Y_TYPE_E_TEXT_FACTORY, GalA11yETextFactory))
+#define GAL_A11Y_E_TEXT_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAL_A11Y_TYPE_E_TEXT_FACTORY, GalA11yETextFactoryClass))
+#define GAL_A11Y_IS_E_TEXT_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAL_A11Y_TYPE_E_TEXT_FACTORY))
+#define GAL_A11Y_IS_E_TEXT_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAL_A11Y_TYPE_E_TEXT_FACTORY))
+
+typedef struct _GalA11yETextFactory GalA11yETextFactory;
+typedef struct _GalA11yETextFactoryClass GalA11yETextFactoryClass;
+
+struct _GalA11yETextFactory {
+ AtkObjectFactory object;
+};
+
+struct _GalA11yETextFactoryClass {
+ AtkObjectFactoryClass parent_class;
+};
+
+
+/* Standard Glib function */
+GType gal_a11y_e_text_factory_get_type (void);
+
+#endif /* ! __GAL_A11Y_E_TEXT_FACTORY_H__ */
diff --git a/widgets/text/gal-a11y-e-text.c b/widgets/text/gal-a11y-e-text.c
new file mode 100644
index 0000000000..99fb4e8a94
--- /dev/null
+++ b/widgets/text/gal-a11y-e-text.c
@@ -0,0 +1,1134 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ * Christopher James Lahey <clahey@ximian.com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#include <config.h>
+
+#include <string.h>
+
+#include <gtk/gtk.h>
+
+#include "a11y/gal-a11y-util.h"
+#include "text/e-text.h"
+#include "text/e-text-model-repos.h"
+
+#include "gal-a11y-e-text.h"
+#include "gal-a11y-e-text-factory.h"
+
+#define CS_CLASS(a11y) (G_TYPE_INSTANCE_GET_CLASS ((a11y), C_TYPE_STREAM, GalA11yETextClass))
+static GObjectClass *parent_class;
+static AtkComponentIface *component_parent_iface;
+static GType parent_type;
+static gint priv_offset;
+static GQuark quark_accessible_object = 0;
+#define GET_PRIVATE(object) ((GalA11yETextPrivate *) (((gchar *) object) + priv_offset))
+#define PARENT_TYPE (parent_type)
+
+struct _GalA11yETextPrivate {
+ gint dummy;
+};
+
+static void
+et_dispose (GObject *object)
+{
+ if (parent_class->dispose)
+ parent_class->dispose (object);
+}
+
+/* Static functions */
+
+static void
+et_get_extents (AtkComponent *component,
+ gint *x,
+ gint *y,
+ gint *width,
+ gint *height,
+ AtkCoordType coord_type)
+{
+ EText *item = E_TEXT (atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (component)));
+ double real_width;
+ double real_height;
+ gint fake_width;
+ gint fake_height;
+
+ if (component_parent_iface &&
+ component_parent_iface->get_extents)
+ component_parent_iface->get_extents (component,
+ x,
+ y,
+ &fake_width,
+ &fake_height,
+ coord_type);
+
+ g_object_get (item,
+ "text_width", &real_width,
+ "text_height", &real_height,
+ NULL);
+
+ if (width)
+ *width = real_width;
+ if (height)
+ *height = real_height;
+}
+
+static const gchar *
+et_get_full_text (AtkText *text)
+{
+ EText *etext = E_TEXT (atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (text)));
+ ETextModel *model;
+ const gchar *full_text;
+
+ g_object_get (etext, "model", &model, NULL);
+
+ full_text = e_text_model_get_text (model);
+
+ return full_text;
+}
+
+static void
+et_set_full_text (AtkEditableText *text,
+ const gchar *full_text)
+{
+ EText *etext = E_TEXT (atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (text)));
+ ETextModel *model;
+
+ g_object_get (etext, "model", &model, NULL);
+
+ e_text_model_set_text (model, full_text);
+}
+
+static gchar *
+et_get_text (AtkText *text,
+ gint start_offset,
+ gint end_offset)
+{
+ gint start, end, real_start, real_end, len;
+ const gchar *full_text = et_get_full_text (text);
+ if (full_text == NULL)
+ return NULL;
+ len = g_utf8_strlen (full_text, -1);
+
+ start = MIN (MAX (0, start_offset), len);
+ end = MIN (MAX (-1, end_offset), len);
+
+ if (end_offset == -1)
+ end = strlen (full_text);
+ else
+ end = g_utf8_offset_to_pointer (full_text, end) - full_text;
+
+ start = g_utf8_offset_to_pointer (full_text, start) - full_text;
+
+ real_start = MIN (start, end);
+ real_end = MAX (start, end);
+
+ return g_strndup (full_text + real_start, real_end - real_start);
+}
+
+static gboolean
+is_a_seperator (gunichar c)
+{
+ return g_unichar_ispunct(c) || g_unichar_isspace(c);
+}
+
+static gint
+find_word_start (const gchar *text,
+ gint begin_offset,
+ gint step)
+{
+ gint offset;
+ gchar *at_offset;
+ gunichar current, previous;
+ gint len;
+
+ offset = begin_offset;
+ len = g_utf8_strlen (text, -1);
+
+ while (offset > 0 && offset < len) {
+ at_offset = g_utf8_offset_to_pointer (text, offset);
+ current = g_utf8_get_char_validated (at_offset, -1);
+ at_offset = g_utf8_offset_to_pointer (text, offset-1);
+ previous = g_utf8_get_char_validated (at_offset, -1);
+ if ((! is_a_seperator (current)) && is_a_seperator (previous))
+ break;
+ offset += step;
+ }
+
+ return offset;
+}
+
+static gint
+find_word_end (const gchar *text,
+ gint begin_offset,
+ gint step)
+{
+ gint offset;
+ gchar *at_offset;
+ gunichar current, previous;
+ gint len;
+
+ offset = begin_offset;
+ len = g_utf8_strlen (text, -1);
+
+ while (offset > 0 && offset < len) {
+ at_offset = g_utf8_offset_to_pointer (text, offset);
+ current = g_utf8_get_char_validated (at_offset, -1);
+ at_offset = g_utf8_offset_to_pointer (text, offset-1);
+ previous = g_utf8_get_char_validated (at_offset, -1);
+ if (is_a_seperator (current) && (! is_a_seperator (previous)))
+ break;
+ offset += step;
+ }
+
+ return offset;
+}
+
+static gint
+find_sentence_start (const gchar *text,
+ gint begin_offset,
+ gint step)
+{
+ gint offset, last_word_end, len;
+ gchar *at_offset;
+ gunichar ch;
+ gint i;
+
+ offset = find_word_start (text, begin_offset, step);
+ len = g_utf8_strlen (text, -1);
+
+ while (offset>0 && offset <len) {
+ last_word_end = find_word_end (text, offset - 1, -1);
+ if (last_word_end == 0)
+ break;
+ for (i = last_word_end; i < offset; i++) {
+ at_offset = g_utf8_offset_to_pointer (text, i);
+ ch = g_utf8_get_char_validated (at_offset, -1);
+ if (ch == '.' || ch == '!' || ch == '?')
+ return offset;
+ }
+
+ offset = find_word_start (text, offset + step, step);
+ }
+
+ return offset;
+}
+
+static gint
+find_sentence_end (const gchar *text,
+ gint begin_offset,
+ gint step)
+{
+ gint offset;
+ gchar *at_offset;
+ gunichar previous;
+ gint len;
+
+ offset = begin_offset;
+ len = g_utf8_strlen (text, -1);
+
+ while (offset > 0 && offset < len) {
+ at_offset = g_utf8_offset_to_pointer (text, offset - 1);
+ previous = g_utf8_get_char_validated (at_offset, -1);
+ if (previous == '.' || previous == '!' || previous == '?')
+ break;
+ offset += step;
+ }
+
+ return offset;
+}
+
+static gint
+find_line_start (const gchar *text,
+ gint begin_offset,
+ gint step)
+{
+ gint offset;
+ gchar *at_offset;
+ gunichar previous;
+ gint len;
+
+ offset = begin_offset;
+ len = g_utf8_strlen (text, -1);
+
+ while (offset > 0 && offset < len) {
+ at_offset = g_utf8_offset_to_pointer (text, offset - 1);
+ previous = g_utf8_get_char_validated (at_offset, -1);
+ if (previous == '\n' || previous == '\r')
+ break;
+ offset += step;
+ }
+
+ return offset;
+}
+
+static gint
+find_line_end (const gchar *text,
+ gint begin_offset,
+ gint step)
+{
+ gint offset;
+ gchar *at_offset;
+ gunichar current;
+ gint len;
+
+ offset = begin_offset;
+ len = g_utf8_strlen (text, -1);
+
+ while (offset >= 0 && offset < len) {
+ at_offset = g_utf8_offset_to_pointer (text, offset);
+ current = g_utf8_get_char_validated (at_offset, -1);
+ if (current == '\n' || current == '\r')
+ break;
+ offset += step;
+ }
+
+ return offset;
+}
+
+static gchar *
+et_get_text_after_offset (AtkText *text,
+ gint offset,
+ AtkTextBoundary boundary_type,
+ gint *start_offset,
+ gint *end_offset)
+{
+ gint start, end, len;
+ const gchar *full_text = et_get_full_text (text);
+ g_return_val_if_fail (full_text, NULL);
+
+ switch (boundary_type)
+ {
+ case ATK_TEXT_BOUNDARY_CHAR:
+ start = offset + 1;
+ end = offset + 2;
+ break;
+ case ATK_TEXT_BOUNDARY_WORD_START:
+ start = find_word_start (full_text, offset + 1, 1);
+ end = find_word_start (full_text, start + 1, 1);
+ break;
+ case ATK_TEXT_BOUNDARY_WORD_END:
+ start = find_word_end (full_text, offset + 1, 1);
+ end = find_word_end (full_text, start + 1, 1);
+ break;
+ case ATK_TEXT_BOUNDARY_SENTENCE_START:
+ start = find_sentence_start (full_text, offset + 1, 1);
+ end = find_sentence_start (full_text, start + 1, 1);
+ break;
+ case ATK_TEXT_BOUNDARY_SENTENCE_END:
+ start = find_sentence_end (full_text, offset + 1, 1);
+ end = find_sentence_end (full_text, start + 1, 1);
+ break;
+ case ATK_TEXT_BOUNDARY_LINE_START:
+ start = find_line_start (full_text, offset + 1, 1);
+ end = find_line_start (full_text, start + 1, 1);
+ break;
+ case ATK_TEXT_BOUNDARY_LINE_END:
+ start = find_line_end (full_text, offset + 1, 1);
+ end = find_line_end (full_text, start + 1, 1);
+ break;
+ default:
+ return NULL;
+ }
+
+ len = g_utf8_strlen (full_text, -1);
+ if (start_offset)
+ *start_offset = MIN (MAX (0, start), len);
+ if (end_offset)
+ *end_offset = MIN (MAX (0, end), len);
+ return et_get_text (text, start, end);
+}
+
+static gchar *
+et_get_text_at_offset (AtkText *text,
+ gint offset,
+ AtkTextBoundary boundary_type,
+ gint *start_offset,
+ gint *end_offset)
+{
+ gint start, end, len;
+ const gchar *full_text = et_get_full_text (text);
+ g_return_val_if_fail (full_text, NULL);
+
+ switch (boundary_type)
+ {
+ case ATK_TEXT_BOUNDARY_CHAR:
+ start = offset;
+ end = offset + 1;
+ break;
+ case ATK_TEXT_BOUNDARY_WORD_START:
+ start = find_word_start (full_text, offset - 1, -1);
+ end = find_word_start (full_text, offset, 1);
+ break;
+ case ATK_TEXT_BOUNDARY_WORD_END:
+ start = find_word_end (full_text, offset, -1);
+ end = find_word_end (full_text, offset + 1, 1);
+ break;
+ case ATK_TEXT_BOUNDARY_SENTENCE_START:
+ start = find_sentence_start (full_text, offset - 1, -1);
+ end = find_sentence_start (full_text, offset, 1);
+ break;
+ case ATK_TEXT_BOUNDARY_SENTENCE_END:
+ start = find_sentence_end (full_text, offset, -1);
+ end = find_sentence_end (full_text, offset + 1, 1);
+ break;
+ case ATK_TEXT_BOUNDARY_LINE_START:
+ start = find_line_start (full_text, offset - 1, -1);
+ end = find_line_start (full_text, offset, 1);
+ break;
+ case ATK_TEXT_BOUNDARY_LINE_END:
+ start = find_line_end (full_text, offset, -1);
+ end = find_line_end (full_text, offset + 1, 1);
+ break;
+ default:
+ return NULL;
+ }
+
+ len = g_utf8_strlen (full_text, -1);
+ if (start_offset)
+ *start_offset = MIN (MAX (0, start), len);
+ if (end_offset)
+ *end_offset = MIN (MAX (0, end), len);
+ return et_get_text (text, start, end);
+}
+
+static gunichar
+et_get_character_at_offset (AtkText *text,
+ gint offset)
+{
+ const gchar *full_text = et_get_full_text (text);
+ gchar *at_offset;
+
+ at_offset = g_utf8_offset_to_pointer (full_text, offset);
+ return g_utf8_get_char_validated (at_offset, -1);
+}
+
+
+static gchar *
+et_get_text_before_offset (AtkText *text,
+ gint offset,
+ AtkTextBoundary boundary_type,
+ gint *start_offset,
+ gint *end_offset)
+{
+ gint start, end, len;
+ const gchar *full_text = et_get_full_text (text);
+ g_return_val_if_fail (full_text, NULL);
+
+ switch (boundary_type)
+ {
+ case ATK_TEXT_BOUNDARY_CHAR:
+ start = offset - 1;
+ end = offset;
+ break;
+ case ATK_TEXT_BOUNDARY_WORD_START:
+ end = find_word_start (full_text, offset - 1, -1);
+ start = find_word_start (full_text, end - 1, -1);
+ break;
+ case ATK_TEXT_BOUNDARY_WORD_END:
+ end = find_word_end (full_text, offset, -1);
+ start = find_word_end (full_text, end - 1, -1);
+ break;
+ case ATK_TEXT_BOUNDARY_SENTENCE_START:
+ end = find_sentence_start (full_text, offset, -1);
+ start = find_sentence_start (full_text, end - 1, -1);
+ break;
+ case ATK_TEXT_BOUNDARY_SENTENCE_END:
+ end = find_sentence_end (full_text, offset, -1);
+ start = find_sentence_end (full_text, end - 1, -1);
+ break;
+ case ATK_TEXT_BOUNDARY_LINE_START:
+ end = find_line_start (full_text, offset, -1);
+ start = find_line_start (full_text, end - 1, -1);
+ break;
+ case ATK_TEXT_BOUNDARY_LINE_END:
+ end = find_line_end (full_text, offset, -1);
+ start = find_line_end (full_text, end - 1, -1);
+ break;
+ default:
+ return NULL;
+ }
+
+ len = g_utf8_strlen (full_text, -1);
+ if (start_offset)
+ *start_offset = MIN (MAX (0, start), len);
+ if (end_offset)
+ *end_offset = MIN (MAX (0, end), len);
+ return et_get_text (text, start, end);
+}
+
+static gint
+et_get_caret_offset (AtkText *text)
+{
+ GObject *obj;
+ EText *etext;
+ gint offset;
+
+ g_return_val_if_fail (ATK_IS_GOBJECT_ACCESSIBLE(text), -1);
+ obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (text));
+ if (obj == NULL)
+ return -1;
+
+ g_return_val_if_fail (E_IS_TEXT (obj), -1);
+ etext = E_TEXT (obj);
+
+ g_object_get (etext, "cursor_pos", &offset, NULL);
+ return offset;
+}
+
+
+static AtkAttributeSet*
+et_get_run_attributes (AtkText *text,
+ gint offset,
+ gint *start_offset,
+ gint *end_offset)
+{
+ /* Unimplemented */
+ return NULL;
+}
+
+
+static AtkAttributeSet*
+et_get_default_attributes (AtkText *text)
+{
+ /* Unimplemented */
+ return NULL;
+}
+
+
+static void
+et_get_character_extents (AtkText *text,
+ gint offset,
+ gint *x,
+ gint *y,
+ gint *width,
+ gint *height,
+ AtkCoordType coords)
+{
+ GObject *obj;
+ EText *etext;
+ GnomeCanvas *canvas;
+ gint x_widget, y_widget, x_window, y_window;
+ GdkWindow *window;
+ GtkWidget *widget;
+ PangoRectangle pango_pos;
+
+ g_return_if_fail (ATK_IS_GOBJECT_ACCESSIBLE(text));
+ obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (text));
+ if (obj == NULL)
+ return;
+ g_return_if_fail (E_IS_TEXT (obj));
+ etext = E_TEXT(obj);
+ canvas = GNOME_CANVAS_ITEM(etext)->canvas;
+ widget = GTK_WIDGET(canvas);
+ window = widget->window;
+ gdk_window_get_origin (window, &x_widget, &y_widget);
+
+ pango_layout_index_to_pos (etext->layout, offset, &pango_pos);
+ pango_pos.x = PANGO_PIXELS (pango_pos.x);
+ pango_pos.y = PANGO_PIXELS (pango_pos.y);
+ pango_pos.width = (pango_pos.width + PANGO_SCALE / 2) / PANGO_SCALE;
+ pango_pos.height = (pango_pos.height + PANGO_SCALE / 2) / PANGO_SCALE;
+
+ *x = pango_pos.x + x_widget;
+ *y = pango_pos.y + y_widget;
+
+ *width = pango_pos.width;
+ *height = pango_pos.height;
+
+ if (etext->draw_borders) {
+ *x += 3; /*BORDER_INDENT;*/
+ *y += 3; /*BORDER_INDENT;*/
+ }
+
+ *x += etext->xofs;
+ *y += etext->yofs;
+
+ if (etext->editing) {
+ *x -= etext->xofs_edit;
+ *y -= etext->yofs_edit;
+ }
+
+ *x += etext->cx;
+ *y += etext->cy;
+
+ if (coords == ATK_XY_WINDOW) {
+ window = gdk_window_get_toplevel (window);
+ gdk_window_get_origin (window, &x_window, &y_window);
+ *x -= x_window;
+ *y -= y_window;
+ }
+ else if (coords == ATK_XY_SCREEN) {
+ }
+ else {
+ *x = 0;
+ *y = 0;
+ *height = 0;
+ *width = 0;
+ }
+}
+
+
+static gint
+et_get_character_count (AtkText *text)
+{
+ const gchar *full_text = et_get_full_text (text);
+
+ return g_utf8_strlen (full_text, -1);
+}
+
+
+static gint
+et_get_offset_at_point (AtkText *text,
+ gint x,
+ gint y,
+ AtkCoordType coords)
+{
+ GObject *obj;
+ EText *etext;
+ GnomeCanvas *canvas;
+ gint x_widget, y_widget, x_window, y_window;
+ GdkWindow *window;
+ GtkWidget *widget;
+ gint index;
+ gint trailing;
+
+ g_return_val_if_fail (ATK_IS_GOBJECT_ACCESSIBLE(text), -1);
+ obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (text));
+ if (obj == NULL)
+ return -1;
+ g_return_val_if_fail (E_IS_TEXT (obj), -1);
+ etext = E_TEXT(obj);
+ canvas = GNOME_CANVAS_ITEM(etext)->canvas;
+ widget = GTK_WIDGET(canvas);
+ window = widget->window;
+ gdk_window_get_origin (window, &x_widget, &y_widget);
+
+ if (coords == ATK_XY_SCREEN) {
+ x = x - x_widget;
+ y = y - y_widget;
+ }
+ else if (coords == ATK_XY_WINDOW) {
+ window = gdk_window_get_toplevel (window);
+ gdk_window_get_origin (window, &x_window, &y_window);
+ x = x - x_widget + x_window;
+ y = y - y_widget + y_window;
+ }
+ else
+ return -1;
+
+ if (etext->draw_borders) {
+ x -= 3; /*BORDER_INDENT;*/
+ y -= 3; /*BORDER_INDENT;*/
+ }
+
+ x -= etext->xofs;
+ y -= etext->yofs;
+
+ if (etext->editing) {
+ x += etext->xofs_edit;
+ y += etext->yofs_edit;
+ }
+
+ x -= etext->cx;
+ y -= etext->cy;
+
+ pango_layout_xy_to_index (etext->layout,
+ x * PANGO_SCALE - PANGO_SCALE / 2,
+ y * PANGO_SCALE - PANGO_SCALE / 2,
+ &index,
+ &trailing);
+
+ return g_utf8_pointer_to_offset (etext->text, etext->text + index + trailing);
+}
+
+
+static gint
+et_get_n_selections (AtkText *text)
+{
+ EText *etext = E_TEXT (atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (text)));
+ if (etext->selection_start !=
+ etext->selection_end)
+ return 1;
+ return 0;
+}
+
+
+static gchar *
+et_get_selection (AtkText *text,
+ gint selection_num,
+ gint *start_offset,
+ gint *end_offset)
+{
+ gint start, end, real_start, real_end, len;
+ EText *etext;
+ if (selection_num == 0) {
+ const gchar *full_text = et_get_full_text (text);
+ if (full_text == NULL)
+ return NULL;
+ len = g_utf8_strlen (full_text, -1);
+ etext = E_TEXT (atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (text)));
+ start = MIN (etext->selection_start, etext->selection_end);
+ end = MAX (etext->selection_start, etext->selection_end);
+ start = MIN (MAX (0, start), len);
+ end = MIN (MAX (0, end), len);
+ if (start != end) {
+ if (start_offset)
+ *start_offset = start;
+ if (end_offset)
+ *end_offset = end;
+ real_start = g_utf8_offset_to_pointer (full_text, start) - full_text;
+ real_end = g_utf8_offset_to_pointer (full_text, end) - full_text;
+ return g_strndup (full_text + real_start, real_end - real_start);
+ }
+ }
+
+ return NULL;
+}
+
+
+static gboolean
+et_add_selection (AtkText *text,
+ gint start_offset,
+ gint end_offset)
+{
+ GObject *obj;
+ EText *etext;
+
+ g_return_val_if_fail (ATK_IS_GOBJECT_ACCESSIBLE (text), FALSE);
+ obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (text));
+ if (obj == NULL)
+ return FALSE;
+ g_return_val_if_fail (E_IS_TEXT (obj), FALSE);
+ etext = E_TEXT (obj);
+
+ g_return_val_if_fail (start_offset >= 0, FALSE);
+ g_return_val_if_fail (start_offset >= -1, FALSE);
+ if (end_offset == -1)
+ end_offset = et_get_character_count (text);
+
+ if (start_offset != end_offset) {
+ gint real_start, real_end;
+ real_start = MIN (start_offset, end_offset);
+ real_end = MAX (start_offset, end_offset);
+ etext->selection_start = real_start;
+ etext->selection_end = real_end;
+
+ gnome_canvas_item_grab_focus (GNOME_CANVAS_ITEM (etext));
+ gnome_canvas_item_request_update (GNOME_CANVAS_ITEM (etext));
+
+ g_signal_emit_by_name (ATK_OBJECT (text), "text_selection_changed");
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+static gboolean
+et_remove_selection (AtkText *text,
+ gint selection_num)
+{
+ GObject *obj;
+ EText *etext;
+
+ g_return_val_if_fail (ATK_IS_GOBJECT_ACCESSIBLE (text), FALSE);
+ obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (text));
+ if (obj == NULL)
+ return FALSE;
+ g_return_val_if_fail (E_IS_TEXT (obj), FALSE);
+ etext = E_TEXT (obj);
+
+ if (selection_num == 0
+ && etext->selection_start != etext->selection_end) {
+ etext->selection_end = etext->selection_start;
+ g_signal_emit_by_name (ATK_OBJECT(text), "text_selection_changed");
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+static gboolean
+et_set_selection (AtkText *text,
+ gint selection_num,
+ gint start_offset,
+ gint end_offset)
+{
+ GObject *obj;
+
+ g_return_val_if_fail (ATK_IS_GOBJECT_ACCESSIBLE (text), FALSE);
+ obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (text));
+ if (obj == NULL)
+ return FALSE;
+ g_return_val_if_fail (E_IS_TEXT (obj), FALSE);
+ if (selection_num == 0)
+ return et_add_selection (text, start_offset, end_offset);
+ return FALSE;
+}
+
+
+static gboolean
+et_set_caret_offset (AtkText *text,
+ gint offset)
+{
+ GObject *obj;
+ EText *etext;
+
+ g_return_val_if_fail (ATK_IS_GOBJECT_ACCESSIBLE (text), FALSE);
+ obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (text));
+ if (obj == NULL)
+ return FALSE;
+
+ g_return_val_if_fail (E_IS_TEXT (obj), FALSE);
+ etext = E_TEXT (obj);
+
+ if (offset < -1)
+ return FALSE;
+ else {
+ ETextEventProcessorCommand command;
+
+ if (offset == -1)
+ offset = et_get_character_count (text);
+
+ command.action = E_TEP_MOVE;
+ command.position = E_TEP_VALUE;
+ command.value = offset;
+ command.time = GDK_CURRENT_TIME;
+ g_signal_emit_by_name (etext->tep, "command", &command);
+ return TRUE;
+ }
+}
+
+static gboolean
+et_set_run_attributes (AtkEditableText *text,
+ AtkAttributeSet *attrib_set,
+ gint start_offset,
+ gint end_offset)
+{
+ /* Unimplemented */
+ return FALSE;
+}
+
+static void
+et_set_text_contents (AtkEditableText *text,
+ const gchar *string)
+{
+ et_set_full_text (text, string);
+}
+
+static void
+et_insert_text (AtkEditableText *text,
+ const gchar *string,
+ gint length,
+ gint *position)
+{
+ /* Utf8 unimplemented */
+ gchar *result;
+
+ const gchar *full_text = et_get_full_text (ATK_TEXT (text));
+ if (full_text == NULL)
+ return;
+
+ result = g_strdup_printf ("%.*s%.*s%s", *position, full_text, length, string, full_text + *position);
+
+ et_set_full_text (text, result);
+
+ *position += length;
+
+ g_free (result);
+}
+
+static void
+et_copy_text (AtkEditableText *text,
+ gint start_pos,
+ gint end_pos)
+{
+ GObject *obj;
+ EText *etext;
+
+ g_return_if_fail (ATK_IS_GOBJECT_ACCESSIBLE (text));
+ obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (text));
+ if (obj == NULL)
+ return;
+
+ g_return_if_fail (E_IS_TEXT (obj));
+ etext = E_TEXT (obj);
+
+ if (start_pos != end_pos) {
+ etext->selection_start = start_pos;
+ etext->selection_end = end_pos;
+ e_text_copy_clipboard (etext);
+ }
+}
+
+static void
+et_delete_text (AtkEditableText *text,
+ gint start_pos,
+ gint end_pos)
+{
+ GObject *obj;
+ EText *etext;
+
+ g_return_if_fail (ATK_IS_GOBJECT_ACCESSIBLE(text));
+ obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (text));
+ if (obj == NULL)
+ return;
+
+ g_return_if_fail (E_IS_TEXT (obj));
+ etext = E_TEXT (obj);
+
+ etext->selection_start = start_pos;
+ etext->selection_end = end_pos;
+
+ e_text_delete_selection (etext);
+}
+
+static void
+et_cut_text (AtkEditableText *text,
+ gint start_pos,
+ gint end_pos)
+{
+ et_copy_text (text, start_pos, end_pos);
+ et_delete_text (text, start_pos, end_pos);
+}
+
+static void
+et_paste_text (AtkEditableText *text,
+ gint position)
+{
+ GObject *obj;
+ EText *etext;
+
+ g_return_if_fail (ATK_IS_GOBJECT_ACCESSIBLE (text));
+ obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (text));
+ if (obj == NULL)
+ return;
+
+ g_return_if_fail (E_IS_TEXT (obj));
+ etext = E_TEXT (obj);
+
+ g_object_set (etext, "cursor_pos", position, NULL);
+ e_text_paste_clipboard (etext);
+}
+
+static void
+et_atk_component_iface_init (AtkComponentIface *iface)
+{
+ iface->get_extents = et_get_extents;
+}
+
+static void
+et_atk_text_iface_init (AtkTextIface *iface)
+{
+ iface->get_text = et_get_text;
+ iface->get_text_after_offset = et_get_text_after_offset;
+ iface->get_text_at_offset = et_get_text_at_offset;
+ iface->get_character_at_offset = et_get_character_at_offset;
+ iface->get_text_before_offset = et_get_text_before_offset;
+ iface->get_caret_offset = et_get_caret_offset;
+ iface->get_run_attributes = et_get_run_attributes;
+ iface->get_default_attributes = et_get_default_attributes;
+ iface->get_character_extents = et_get_character_extents;
+ iface->get_character_count = et_get_character_count;
+ iface->get_offset_at_point = et_get_offset_at_point;
+ iface->get_n_selections = et_get_n_selections;
+ iface->get_selection = et_get_selection;
+ iface->add_selection = et_add_selection;
+ iface->remove_selection = et_remove_selection;
+ iface->set_selection = et_set_selection;
+ iface->set_caret_offset = et_set_caret_offset;
+}
+
+static void
+et_atk_editable_text_iface_init (AtkEditableTextIface *iface)
+{
+ iface->set_run_attributes = et_set_run_attributes;
+ iface->set_text_contents = et_set_text_contents;
+ iface->insert_text = et_insert_text;
+ iface->copy_text = et_copy_text;
+ iface->cut_text = et_cut_text;
+ iface->delete_text = et_delete_text;
+ iface->paste_text = et_paste_text;
+}
+
+static void
+_et_reposition_cb (ETextModel *model,
+ ETextModelReposFn fn,
+ gpointer repos_data,
+ gpointer user_data)
+{
+ AtkObject *accessible;
+ AtkText *text;
+
+ accessible = ATK_OBJECT (user_data);
+ text = ATK_TEXT (accessible);
+
+ if (fn == e_repos_delete_shift) {
+ EReposDeleteShift *info = (EReposDeleteShift *) repos_data;
+ g_signal_emit_by_name (text, "text-changed::delete", info->pos, info->len);
+ }
+ else if (fn == e_repos_insert_shift) {
+ EReposInsertShift *info = (EReposInsertShift *) repos_data;
+ g_signal_emit_by_name (text, "text-changed::insert", info->pos, info->len);
+ }
+}
+
+static void
+_et_command_cb (ETextEventProcessor *tep,
+ ETextEventProcessorCommand *command,
+ gpointer user_data)
+{
+ AtkObject *accessible;
+ AtkText *text;
+
+ accessible = ATK_OBJECT (user_data);
+ text = ATK_TEXT (accessible);
+
+ switch (command->action) {
+ case E_TEP_MOVE:
+ g_signal_emit_by_name (text, "text-caret-moved", et_get_caret_offset (text));
+ break;
+ case E_TEP_SELECT:
+ g_signal_emit_by_name (text, "text-selection-changed");
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+et_real_initialize (AtkObject *obj,
+ gpointer data)
+{
+ EText *etext;
+
+ ATK_OBJECT_CLASS (parent_class)->initialize (obj, data);
+
+ g_return_if_fail (GAL_A11Y_IS_E_TEXT (obj));
+ g_return_if_fail (E_IS_TEXT (data));
+
+ etext = E_TEXT (data);
+
+ /* Set up signal callbacks */
+ g_signal_connect (etext->model, "reposition",
+ G_CALLBACK (_et_reposition_cb), obj);
+
+ if (etext->tep)
+ g_signal_connect_after (etext->tep, "command",
+ (GCallback) _et_command_cb, obj);
+
+ obj->role = ATK_ROLE_TEXT;
+}
+
+static void
+et_class_init (GalA11yETextClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ AtkObjectClass *atk_class = ATK_OBJECT_CLASS (klass);
+
+ quark_accessible_object = g_quark_from_static_string ("gtk-accessible-object");
+ parent_class = g_type_class_ref (PARENT_TYPE);
+ component_parent_iface = g_type_interface_peek(parent_class, ATK_TYPE_COMPONENT);
+ object_class->dispose = et_dispose;
+ atk_class->initialize = et_real_initialize;
+}
+
+static void
+et_init (GalA11yEText *a11y)
+{
+#if 0
+ GalA11yETextPrivate *priv;
+
+ priv = GET_PRIVATE (a11y);
+#endif
+}
+
+/**
+ * gal_a11y_e_text_get_type:
+ * @void:
+ *
+ * Registers the &GalA11yEText class if necessary, and returns the type ID
+ * associated to it.
+ *
+ * Return value: The type ID of the &GalA11yEText class.
+ **/
+GType
+gal_a11y_e_text_get_type (void)
+{
+ static GType type = 0;
+
+ if (!type) {
+ AtkObjectFactory *factory;
+
+ GTypeInfo info = {
+ sizeof (GalA11yETextClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) et_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+ sizeof (GalA11yEText),
+ 0,
+ (GInstanceInitFunc) et_init,
+ NULL /* value_text */
+ };
+
+ static const GInterfaceInfo atk_component_info = {
+ (GInterfaceInitFunc) et_atk_component_iface_init,
+ (GInterfaceFinalizeFunc) NULL,
+ NULL
+ };
+ static const GInterfaceInfo atk_text_info = {
+ (GInterfaceInitFunc) et_atk_text_iface_init,
+ (GInterfaceFinalizeFunc) NULL,
+ NULL
+ };
+ static const GInterfaceInfo atk_editable_text_info = {
+ (GInterfaceInitFunc) et_atk_editable_text_iface_init,
+ (GInterfaceFinalizeFunc) NULL,
+ NULL
+ };
+
+ factory = atk_registry_get_factory (atk_get_default_registry (), GNOME_TYPE_CANVAS_ITEM);
+ parent_type = atk_object_factory_get_accessible_type (factory);
+
+ type = gal_a11y_type_register_static_with_private (PARENT_TYPE, "GalA11yEText", &info, 0,
+ sizeof (GalA11yETextPrivate), &priv_offset);
+
+ g_type_add_interface_static (type, ATK_TYPE_COMPONENT, &atk_component_info);
+ g_type_add_interface_static (type, ATK_TYPE_TEXT, &atk_text_info);
+ g_type_add_interface_static (type, ATK_TYPE_EDITABLE_TEXT, &atk_editable_text_info);
+ }
+
+ return type;
+}
+
+void
+gal_a11y_e_text_init (void)
+{
+ if (atk_get_root ())
+ atk_registry_set_factory_type (atk_get_default_registry (),
+ E_TYPE_TEXT,
+ gal_a11y_e_text_factory_get_type ());
+
+}
+
diff --git a/widgets/text/gal-a11y-e-text.h b/widgets/text/gal-a11y-e-text.h
new file mode 100644
index 0000000000..6a5bb80de0
--- /dev/null
+++ b/widgets/text/gal-a11y-e-text.h
@@ -0,0 +1,57 @@
+/*
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ * Christopher James Lahey <clahey@ximian.com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef __GAL_A11Y_E_TEXT_H__
+#define __GAL_A11Y_E_TEXT_H__
+
+#include <glib-object.h>
+#include <table/e-table-item.h>
+
+#define GAL_A11Y_TYPE_E_TEXT (gal_a11y_e_text_get_type ())
+#define GAL_A11Y_E_TEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAL_A11Y_TYPE_E_TEXT, GalA11yEText))
+#define GAL_A11Y_E_TEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAL_A11Y_TYPE_E_TEXT, GalA11yETextClass))
+#define GAL_A11Y_IS_E_TEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAL_A11Y_TYPE_E_TEXT))
+#define GAL_A11Y_IS_E_TEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAL_A11Y_TYPE_E_TEXT))
+
+typedef struct _GalA11yEText GalA11yEText;
+typedef struct _GalA11yETextClass GalA11yETextClass;
+typedef struct _GalA11yETextPrivate GalA11yETextPrivate;
+
+/* This struct should actually be larger as this isn't what we derive from.
+ * The GalA11yETextPrivate comes right after the parent class structure.
+ **/
+struct _GalA11yEText {
+ AtkObject object;
+};
+
+struct _GalA11yETextClass {
+ AtkObject parent_class;
+};
+
+
+/* Standard Glib function */
+GType gal_a11y_e_text_get_type (void);
+
+void gal_a11y_e_text_init (void);
+
+#endif /* ! __GAL_A11Y_E_TEXT_H__ */