aboutsummaryrefslogtreecommitdiffstats
path: root/widgets/misc
diff options
context:
space:
mode:
authorMatthew Barnes <mbarnes@redhat.com>2009-08-30 13:37:36 +0800
committerMatthew Barnes <mbarnes@redhat.com>2009-08-30 13:40:49 +0800
commitcfb9c32b6657165e4d5e11aa7b47804f679a61f8 (patch)
tree1f9c8954df7a357b5dc20a13ac82bf31c1112083 /widgets/misc
parentfefeb30f58447f2fa7bcbee16dbe68a9333ce89d (diff)
parent0f7f4cfe38b3c4cd83efbe9922ae15c5aee00317 (diff)
downloadgsoc2013-evolution-cfb9c32b6657165e4d5e11aa7b47804f679a61f8.tar.gz
gsoc2013-evolution-cfb9c32b6657165e4d5e11aa7b47804f679a61f8.tar.zst
gsoc2013-evolution-cfb9c32b6657165e4d5e11aa7b47804f679a61f8.zip
Merge commit 'origin/kill-bonobo'
Diffstat (limited to 'widgets/misc')
-rw-r--r--widgets/misc/Makefile.am196
-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.c454
-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.c712
-rw-r--r--widgets/misc/e-activity-handler.h101
-rw-r--r--widgets/misc/e-activity-proxy.c346
-rw-r--r--widgets/misc/e-activity-proxy.h68
-rw-r--r--widgets/misc/e-activity.c605
-rw-r--r--widgets/misc/e-activity.h98
-rw-r--r--widgets/misc/e-alert-activity.c258
-rw-r--r--widgets/misc/e-alert-activity.h70
-rw-r--r--widgets/misc/e-attachment-button.c6
-rw-r--r--widgets/misc/e-calendar.c31
-rw-r--r--widgets/misc/e-calendar.h21
-rw-r--r--widgets/misc/e-cell-date-edit.c1005
-rw-r--r--widgets/misc/e-cell-date-edit.h101
-rw-r--r--widgets/misc/e-cell-percent.c151
-rw-r--r--widgets/misc/e-cell-percent.h51
-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-dateedit.c336
-rw-r--r--widgets/misc/e-dropdown-button.c236
-rw-r--r--widgets/misc/e-dropdown-button.h65
-rw-r--r--widgets/misc/e-filter-bar.c1032
-rw-r--r--widgets/misc/e-filter-bar.h138
-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.c418
-rw-r--r--widgets/misc/e-icon-entry.h87
-rw-r--r--widgets/misc/e-image-chooser.c588
-rw-r--r--widgets/misc/e-image-chooser.h65
-rw-r--r--widgets/misc/e-info-label.c246
-rw-r--r--widgets/misc/e-menu-tool-button.c183
-rw-r--r--widgets/misc/e-menu-tool-button.h68
-rw-r--r--widgets/misc/e-multi-config-dialog.c368
-rw-r--r--widgets/misc/e-multi-config-dialog.h71
-rw-r--r--widgets/misc/e-online-button.c32
-rw-r--r--widgets/misc/e-paned.c310
-rw-r--r--widgets/misc/e-paned.h72
-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-reflow-model.c348
-rw-r--r--widgets/misc/e-reflow-model.h108
-rw-r--r--widgets/misc/e-reflow.c1531
-rw-r--r--widgets/misc/e-reflow.h140
-rw-r--r--widgets/misc/e-search-bar.c1683
-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.c509
-rw-r--r--widgets/misc/e-signature-editor.h70
-rw-r--r--widgets/misc/e-signature-manager.c753
-rw-r--r--widgets/misc/e-signature-manager.h100
-rw-r--r--widgets/misc/e-signature-preview.c349
-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.c448
-rw-r--r--widgets/misc/e-signature-tree-view.h78
-rw-r--r--widgets/misc/e-task-bar.c307
-rw-r--r--widgets/misc/e-task-bar.h76
-rw-r--r--widgets/misc/e-task-widget.c290
-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.h111
-rw-r--r--widgets/misc/ea-calendar-cell.c386
-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.h67
-rw-r--r--widgets/misc/ea-cell-table.c202
-rw-r--r--widgets/misc/ea-cell-table.h60
-rw-r--r--widgets/misc/ea-widgets.c (renamed from widgets/misc/e-config-page.c)30
-rw-r--r--widgets/misc/ea-widgets.h (renamed from widgets/misc/e-info-label.h)36
-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
93 files changed, 11750 insertions, 14135 deletions
diff --git a/widgets/misc/Makefile.am b/widgets/misc/Makefile.am
index d6689ef73f..29607758e5 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)"\" \
@@ -13,8 +13,7 @@ AM_CPPFLAGS = \
$(GNOME_PLATFORM_CFLAGS)
privsolib_LTLIBRARIES = \
- libemiscwidgets.la \
- libefilterbar.la
+ libemiscwidgets.la
widgetsincludedir = $(privincludedir)/misc
filterbarincludedir = $(privincludedir)/misc
@@ -32,7 +31,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 \
@@ -44,54 +48,59 @@ 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-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-paned.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-cell-table.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 \
@@ -103,78 +112,62 @@ 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-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-paned.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-cell-table.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
@@ -184,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
@@ -194,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..8d3d2d211b
--- /dev/null
+++ b/widgets/misc/e-account-manager.c
@@ -0,0 +1,454 @@
+/*
+ * 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;
+ 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)
+ gtk_widget_grab_focus (add_button);
+
+ /* XXX EAccountList misuses const */
+ default_account = (EAccount *)
+ e_account_list_get_default (account_list);
+
+ sensitive = (account != NULL);
+ 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 338e4015fb..0000000000
--- a/widgets/misc/e-activity-handler.c
+++ /dev/null
@@ -1,712 +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;
-}
-
-static gboolean
-show_intrusive_errors (void)
-{
- const gchar *intrusive = NULL;
-
- intrusive = g_getenv ("EVO-SHOW-INTRUSIVE-ERRORS");
-
- if (intrusive && g_str_equal (intrusive, "1"))
- return TRUE;
- else
- return FALSE;
-}
-
-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);
-
- if (show_intrusive_errors ()) {
- gtk_widget_show (error);
- return activity_id;
- }
-
- 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 3fd5c64d9a..0000000000
--- a/widgets/misc/e-activity-handler.h
+++ /dev/null
@@ -1,101 +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..10249b1911
--- /dev/null
+++ b/widgets/misc/e-activity-proxy.c
@@ -0,0 +1,346 @@
+/*
+ * 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_button_set_relief (GTK_BUTTON (widget), GTK_RELIEF_NONE);
+ 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..9f8faf75cb
--- /dev/null
+++ b/widgets/misc/e-activity.c
@@ -0,0 +1,605 @@
+/*
+ * 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 allow_cancel : 1;
+ guint cancelled : 1;
+ guint clickable : 1;
+ guint completed : 1;
+};
+
+enum {
+ PROP_0,
+ PROP_ALLOW_CANCEL,
+ 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_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_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_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);
+
+ /* Chain up to parent's finalize() method. */
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+activity_cancelled (EActivity *activity)
+{
+ activity->priv->cancelled = TRUE;
+}
+
+static void
+activity_completed (EActivity *activity)
+{
+ activity->priv->completed = TRUE;
+}
+
+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_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_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_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_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");
+}
diff --git a/widgets/misc/e-activity.h b/widgets/misc/e-activity.h
new file mode 100644
index 0000000000..b396e3a630
--- /dev/null
+++ b/widgets/misc/e-activity.h
@@ -0,0 +1,98 @@
+/*
+ * 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_complete (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_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);
+
+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..1e8f915213
--- /dev/null
+++ b/widgets/misc/e-alert-activity.c
@@ -0,0 +1,258 @@
+/*
+ * 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);
+
+ /* This is a constructor property, so can't do it in init().
+ * XXX What we really want to do is override the property's
+ * default value, but GObject does not support that. */
+ e_activity_set_clickable (E_ACTIVITY (alert_activity), TRUE);
+}
+
+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_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-attachment-button.c b/widgets/misc/e-attachment-button.c
index d64dcafb4a..1cd517d3e2 100644
--- a/widgets/misc/e-attachment-button.c
+++ b/widgets/misc/e-attachment-button.c
@@ -199,7 +199,7 @@ exit:
static void
attachment_button_update_pixbufs (EAttachmentButton *button)
{
- GtkCellView *cell_view;
+ GtkCellLayout *cell_layout;
GtkCellRenderer *renderer;
GtkIconTheme *icon_theme;
GdkPixbuf *pixbuf_expander_open;
@@ -209,8 +209,8 @@ attachment_button_update_pixbufs (EAttachmentButton *button)
icon_theme = gtk_icon_theme_get_default ();
/* Grab the first cell renderer. */
- cell_view = GTK_CELL_VIEW (button->priv->cell_view);
- list = gtk_cell_view_get_cell_renderers (cell_view);
+ cell_layout = GTK_CELL_LAYOUT (button->priv->cell_view);
+ list = gtk_cell_layout_get_cells (cell_layout);
renderer = GTK_CELL_RENDERER (list->data);
g_list_free (list);
diff --git a/widgets/misc/e-calendar.c b/widgets/misc/e-calendar.c
index fd17c67aab..e9aacfa8b9 100644
--- a/widgets/misc/e-calendar.c
+++ b/widgets/misc/e-calendar.c
@@ -241,12 +241,16 @@ e_calendar_destroy (GtkObject *object)
static void
e_calendar_realize (GtkWidget *widget)
{
+ GtkStyle *style;
+ GdkWindow *window;
+
(*GTK_WIDGET_CLASS (e_calendar_parent_class)->realize) (widget);
/* Set the background of the canvas window to the normal color,
or the arrow buttons are not displayed properly. */
- gdk_window_set_background (GTK_LAYOUT (widget)->bin_window,
- &widget->style->bg[GTK_STATE_NORMAL]);
+ style = gtk_widget_get_style (widget);
+ window = gtk_layout_get_bin_window (GTK_LAYOUT (widget));
+ gdk_window_set_background (window, &style->bg[GTK_STATE_NORMAL]);
}
static void
@@ -254,6 +258,7 @@ e_calendar_style_set (GtkWidget *widget,
GtkStyle *previous_style)
{
ECalendar *e_calendar;
+ GtkWidget *parent;
e_calendar = E_CALENDAR(widget);
if (GTK_WIDGET_CLASS (e_calendar_parent_class)->style_set)
@@ -262,9 +267,15 @@ e_calendar_style_set (GtkWidget *widget,
/* Set the background of the canvas window to the normal color,
or the arrow buttons are not displayed properly. */
- if (GTK_WIDGET_REALIZED (widget->parent))
- gdk_window_set_background (GTK_LAYOUT (widget)->bin_window,
- &widget->style->bg[GTK_STATE_NORMAL]);
+ parent = gtk_widget_get_parent (widget);
+ if (GTK_WIDGET_REALIZED (parent)) {
+ GtkStyle *style;
+ GdkWindow *window;
+
+ style = gtk_widget_get_style (widget);
+ window = gtk_layout_get_bin_window (GTK_LAYOUT (widget));
+ gdk_window_set_background (window, &style->bg[GTK_STATE_NORMAL]);
+ }
e_calendar_item_style_set (widget, e_calendar->calitem);
}
@@ -277,7 +288,7 @@ e_calendar_size_request (GtkWidget *widget,
gint col_width, row_height, width, height;
cal = E_CALENDAR (widget);
- style = GTK_WIDGET (cal)->style;
+ style = gtk_widget_get_style (GTK_WIDGET (cal));
g_object_get((cal->calitem),
"row_height", &row_height,
@@ -296,6 +307,7 @@ e_calendar_size_allocate (GtkWidget *widget,
GtkAllocation *allocation)
{
ECalendar *cal;
+ GtkStyle *style;
PangoFontDescription *font_desc;
PangoContext *pango_context;
PangoFontMetrics *font_metrics;
@@ -303,8 +315,9 @@ e_calendar_size_allocate (GtkWidget *widget,
gdouble xthickness, ythickness, arrow_button_size;
cal = E_CALENDAR (widget);
- xthickness = widget->style->xthickness;
- ythickness = widget->style->ythickness;
+ style = gtk_widget_get_style (widget);
+ xthickness = style->xthickness;
+ ythickness = style->ythickness;
(*GTK_WIDGET_CLASS (e_calendar_parent_class)->size_allocate) (widget, allocation);
@@ -412,7 +425,7 @@ e_calendar_get_border_size (ECalendar *cal,
g_return_if_fail (E_IS_CALENDAR (cal));
- style = GTK_WIDGET (cal)->style;
+ style = gtk_widget_get_style (GTK_WIDGET (cal));
if (style) {
*top = style->ythickness;
diff --git a/widgets/misc/e-calendar.h b/widgets/misc/e-calendar.h
index 2ee002807a..d6b50209a7 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;
typedef struct _ECalendarClass ECalendarClass;
diff --git a/widgets/misc/e-cell-date-edit.c b/widgets/misc/e-cell-date-edit.c
deleted file mode 100644
index dfbe183f88..0000000000
--- a/widgets/misc/e-cell-date-edit.c
+++ /dev/null
@@ -1,1005 +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:
- * Damon Chaplin <damon@ximian.com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-/*
- * ECellDateEdit - a subclass of ECellPopup used to show a date with a popup
- * window to edit it.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "e-cell-date-edit.h"
-
-#include <string.h>
-#include <time.h>
-#include <glib.h>
-
-#include <gdk/gdkkeysyms.h>
-#include <gtk/gtk.h>
-
-#include <table/e-table-item.h>
-#include <table/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"
-
-static void e_cell_date_edit_destroy (GtkObject *object);
-static void e_cell_date_edit_get_property (GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec);
-static void e_cell_date_edit_set_property (GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec);
-
-static gint e_cell_date_edit_do_popup (ECellPopup *ecp,
- GdkEvent *event,
- gint row,
- gint view_col);
-static void e_cell_date_edit_set_popup_values (ECellDateEdit *ecde);
-static void e_cell_date_edit_select_matching_time(ECellDateEdit *ecde,
- gchar *time);
-static void e_cell_date_edit_show_popup (ECellDateEdit *ecde,
- gint row,
- gint view_col);
-static void e_cell_date_edit_get_popup_pos (ECellDateEdit *ecde,
- gint row,
- gint view_col,
- gint *x,
- gint *y,
- gint *height,
- gint *width);
-
-static void e_cell_date_edit_rebuild_time_list (ECellDateEdit *ecde);
-
-static gint e_cell_date_edit_key_press (GtkWidget *popup_window,
- GdkEventKey *event,
- ECellDateEdit *ecde);
-static gint e_cell_date_edit_button_press (GtkWidget *popup_window,
- GdkEventButton *event,
- ECellDateEdit *ecde);
-static void e_cell_date_edit_on_ok_clicked (GtkWidget *button,
- ECellDateEdit *ecde);
-static void e_cell_date_edit_show_time_invalid_warning (ECellDateEdit *ecde);
-static void e_cell_date_edit_on_now_clicked (GtkWidget *button,
- ECellDateEdit *ecde);
-static void e_cell_date_edit_on_none_clicked (GtkWidget *button,
- ECellDateEdit *ecde);
-static void e_cell_date_edit_on_today_clicked (GtkWidget *button,
- ECellDateEdit *ecde);
-static void e_cell_date_edit_update_cell (ECellDateEdit *ecde,
- const gchar *text);
-static void e_cell_date_edit_on_time_selected (GtkTreeSelection *selection, ECellDateEdit *ecde);
-static void e_cell_date_edit_hide_popup (ECellDateEdit *ecde);
-
-/* Our arguments. */
-enum {
- PROP_0,
- PROP_SHOW_TIME,
- PROP_SHOW_NOW_BUTTON,
- PROP_SHOW_TODAY_BUTTON,
- PROP_ALLOW_NO_DATE_SET,
- PROP_USE_24_HOUR_FORMAT,
- PROP_LOWER_HOUR,
- PROP_UPPER_HOUR
-};
-
-G_DEFINE_TYPE (ECellDateEdit, e_cell_date_edit, E_CELL_POPUP_TYPE)
-
-static void
-e_cell_date_edit_class_init (ECellDateEditClass *class)
-{
- GObjectClass *object_class;
- GtkObjectClass *gtk_object_class;
- ECellPopupClass *ecpc;
-
- object_class = G_OBJECT_CLASS (class);
- object_class->get_property = e_cell_date_edit_get_property;
- object_class->set_property = e_cell_date_edit_set_property;
-
- gtk_object_class = GTK_OBJECT_CLASS (class);
- gtk_object_class->destroy = e_cell_date_edit_destroy;
-
- ecpc = E_CELL_POPUP_CLASS (class);
- ecpc->popup = e_cell_date_edit_do_popup;
-
- g_object_class_install_property (
- object_class,
- PROP_SHOW_TIME,
- g_param_spec_boolean (
- "show_time",
- NULL,
- NULL,
- TRUE,
- G_PARAM_READWRITE));
-
- g_object_class_install_property (
- object_class,
- PROP_SHOW_NOW_BUTTON,
- g_param_spec_boolean (
- "show_now_button",
- NULL,
- NULL,
- TRUE,
- G_PARAM_READWRITE));
-
- g_object_class_install_property (
- object_class,
- PROP_SHOW_TODAY_BUTTON,
- g_param_spec_boolean (
- "show_today_button",
- NULL,
- NULL,
- TRUE,
- G_PARAM_READWRITE));
-
- g_object_class_install_property (
- object_class,
- PROP_ALLOW_NO_DATE_SET,
- g_param_spec_boolean (
- "allow_no_date_set",
- NULL,
- NULL,
- TRUE,
- G_PARAM_READWRITE));
-
- g_object_class_install_property (
- object_class,
- PROP_USE_24_HOUR_FORMAT,
- g_param_spec_boolean (
- "use_24_hour_format",
- NULL,
- NULL,
- TRUE,
- G_PARAM_READWRITE));
-
- g_object_class_install_property (
- object_class,
- PROP_LOWER_HOUR,
- g_param_spec_int (
- "lower_hour",
- NULL,
- NULL,
- G_MININT,
- G_MAXINT,
- 0,
- G_PARAM_READWRITE));
-
- g_object_class_install_property (
- object_class,
- PROP_UPPER_HOUR,
- g_param_spec_int (
- "upper_hour",
- NULL,
- NULL,
- G_MININT,
- G_MAXINT,
- 24,
- G_PARAM_READWRITE));
-}
-
-static void
-e_cell_date_edit_init (ECellDateEdit *ecde)
-{
- GtkWidget *frame, *vbox, *hbox, *vbox2;
- GtkWidget *scrolled_window, *bbox, *tree_view;
- GtkWidget *now_button, *today_button, *none_button, *ok_button;
- GtkListStore *store;
-
- ecde->lower_hour = 0;
- ecde->upper_hour = 24;
- ecde->use_24_hour_format = TRUE;
- ecde->need_time_list_rebuild = TRUE;
- ecde->freeze_count = 0;
- ecde->time_callback = NULL;
- ecde->time_callback_data = NULL;
- ecde->time_callback_destroy = NULL;
-
- /* We create one popup window for the ECell, since there will only
- ever be one popup in use at a time. */
- ecde->popup_window = gtk_window_new (GTK_WINDOW_POPUP);
-
- gtk_window_set_type_hint (GTK_WINDOW (ecde->popup_window),
- GDK_WINDOW_TYPE_HINT_COMBO);
- gtk_window_set_resizable (GTK_WINDOW (ecde->popup_window), TRUE);
-
- frame = gtk_frame_new (NULL);
- gtk_container_add (GTK_CONTAINER (ecde->popup_window), frame);
- gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT);
- gtk_widget_show (frame);
-
- vbox = gtk_vbox_new (FALSE, 0);
- gtk_container_add (GTK_CONTAINER (frame), vbox);
- gtk_widget_show (vbox);
-
- hbox = gtk_hbox_new (FALSE, 4);
- gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
- gtk_widget_show (hbox);
-
- ecde->calendar = e_calendar_new ();
- gnome_canvas_item_set (GNOME_CANVAS_ITEM (E_CALENDAR (ecde->calendar)->calitem),
- "move_selection_when_moving", FALSE,
- NULL);
- gtk_box_pack_start (GTK_BOX (hbox), ecde->calendar, TRUE, TRUE, 0);
- gtk_widget_show (ecde->calendar);
-
- vbox2 = gtk_vbox_new (FALSE, 2);
- gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 0);
- gtk_widget_show (vbox2);
-
- ecde->time_entry = gtk_entry_new ();
- gtk_widget_set_size_request (ecde->time_entry, 50, -1);
- gtk_box_pack_start (GTK_BOX (vbox2), ecde->time_entry,
- FALSE, FALSE, 0);
- gtk_widget_show (ecde->time_entry);
-
- scrolled_window = gtk_scrolled_window_new (NULL, NULL);
- gtk_box_pack_start (GTK_BOX (vbox2), scrolled_window, TRUE, TRUE, 0);
- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
- GTK_POLICY_NEVER,
- GTK_POLICY_ALWAYS);
- gtk_widget_show (scrolled_window);
-
- store = gtk_list_store_new (1, G_TYPE_STRING);
- tree_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store));
- g_object_unref (store);
-
- gtk_tree_view_append_column (
- GTK_TREE_VIEW (tree_view),
- gtk_tree_view_column_new_with_attributes ("Text", gtk_cell_renderer_text_new (), "text", 0, NULL));
-
- gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (tree_view), FALSE);
-
- gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_window), tree_view);
- gtk_container_set_focus_vadjustment (GTK_CONTAINER (tree_view),
- gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (scrolled_window)));
- gtk_container_set_focus_hadjustment (GTK_CONTAINER (tree_view),
- gtk_scrolled_window_get_hadjustment (GTK_SCROLLED_WINDOW (scrolled_window)));
- gtk_widget_show (tree_view);
- ecde->time_tree_view = tree_view;
- g_signal_connect (gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view)), "changed",
- G_CALLBACK (e_cell_date_edit_on_time_selected),
- ecde);
-
- bbox = gtk_hbutton_box_new ();
- gtk_container_set_border_width (GTK_CONTAINER (bbox), 4);
- gtk_box_set_spacing (GTK_BOX (bbox), 2);
- gtk_box_pack_start (GTK_BOX (vbox), bbox, FALSE, FALSE, 0);
- gtk_widget_show (bbox);
-
- now_button = gtk_button_new_with_label (_("Now"));
- gtk_container_add (GTK_CONTAINER (bbox), now_button);
- gtk_widget_show (now_button);
- g_signal_connect((now_button), "clicked",
- G_CALLBACK (e_cell_date_edit_on_now_clicked),
- ecde);
- ecde->now_button = now_button;
-
- today_button = gtk_button_new_with_label (_("Today"));
- gtk_container_add (GTK_CONTAINER (bbox), today_button);
- gtk_widget_show (today_button);
- g_signal_connect((today_button), "clicked",
- G_CALLBACK (e_cell_date_edit_on_today_clicked),
- ecde);
- ecde->today_button = today_button;
-
- none_button = gtk_button_new_with_label (_("None"));
- gtk_container_add (GTK_CONTAINER (bbox), none_button);
- gtk_widget_show (none_button);
- g_signal_connect((none_button), "clicked",
- G_CALLBACK (e_cell_date_edit_on_none_clicked),
- ecde);
- ecde->none_button = none_button;
-
- ok_button = gtk_button_new_with_label (_("OK"));
- gtk_container_add (GTK_CONTAINER (bbox), ok_button);
- gtk_widget_show (ok_button);
- g_signal_connect((ok_button), "clicked",
- G_CALLBACK (e_cell_date_edit_on_ok_clicked),
- ecde);
-
- g_signal_connect((ecde->popup_window),
- "key_press_event",
- G_CALLBACK (e_cell_date_edit_key_press),
- ecde);
- g_signal_connect((ecde->popup_window),
- "button_press_event",
- G_CALLBACK (e_cell_date_edit_button_press),
- ecde);
-}
-
-/**
- * e_cell_date_edit_new:
- *
- * Creates a new ECellDateEdit renderer.
- *
- * Returns: an ECellDateEdit object.
- */
-ECell *
-e_cell_date_edit_new (void)
-{
- return g_object_new (e_cell_date_edit_get_type (), NULL);
-}
-
-/*
- * GtkObject::destroy method
- */
-static void
-e_cell_date_edit_destroy (GtkObject *object)
-{
- ECellDateEdit *ecde = E_CELL_DATE_EDIT (object);
-
- e_cell_date_edit_set_get_time_callback (ecde, NULL, NULL, NULL);
-
- gtk_widget_destroy (ecde->popup_window);
- ecde->popup_window = NULL;
-
- GTK_OBJECT_CLASS (e_cell_date_edit_parent_class)->destroy (object);
-}
-
-static void
-e_cell_date_edit_get_property (GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
-{
- ECellDateEdit *ecde;
-
- ecde = E_CELL_DATE_EDIT (object);
-
- switch (property_id) {
- case PROP_SHOW_TIME:
- g_value_set_boolean (value, GTK_WIDGET_VISIBLE (ecde->time_entry));
- return;
- case PROP_SHOW_NOW_BUTTON:
- g_value_set_boolean (value, GTK_WIDGET_VISIBLE (ecde->now_button));
- return;
- case PROP_SHOW_TODAY_BUTTON:
- g_value_set_boolean (value, GTK_WIDGET_VISIBLE (ecde->today_button));
- return;
- case PROP_ALLOW_NO_DATE_SET:
- g_value_set_boolean (value, GTK_WIDGET_VISIBLE (ecde->none_button));
- return;
- case PROP_USE_24_HOUR_FORMAT:
- g_value_set_boolean (value, ecde->use_24_hour_format);
- return;
- case PROP_LOWER_HOUR:
- g_value_set_int (value, ecde->lower_hour);
- return;
- case PROP_UPPER_HOUR:
- g_value_set_int (value, ecde->upper_hour);
- return;
- }
-
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
-}
-
-static void
-e_cell_date_edit_set_property (GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- ECellDateEdit *ecde;
- gint ivalue;
- gboolean bvalue;
-
- ecde = E_CELL_DATE_EDIT (object);
-
- switch (property_id) {
- case PROP_SHOW_TIME:
- if (g_value_get_boolean (value)) {
- gtk_widget_show (ecde->time_entry);
- gtk_widget_show (ecde->time_tree_view);
- } else {
- gtk_widget_hide (ecde->time_entry);
- gtk_widget_hide (ecde->time_tree_view);
- }
- return;
- case PROP_SHOW_NOW_BUTTON:
- if (g_value_get_boolean (value)) {
- gtk_widget_show (ecde->now_button);
- } else {
- gtk_widget_hide (ecde->now_button);
- }
- return;
- case PROP_SHOW_TODAY_BUTTON:
- if (g_value_get_boolean (value)) {
- gtk_widget_show (ecde->today_button);
- } else {
- gtk_widget_hide (ecde->today_button);
- }
- return;
- case PROP_ALLOW_NO_DATE_SET:
- if (g_value_get_boolean (value)) {
- gtk_widget_show (ecde->none_button);
- } else {
- /* FIXME: What if we have no date set now. */
- gtk_widget_hide (ecde->none_button);
- }
- return;
- case PROP_USE_24_HOUR_FORMAT:
- bvalue = g_value_get_boolean (value);
- if (ecde->use_24_hour_format != bvalue) {
- ecde->use_24_hour_format = bvalue;
- ecde->need_time_list_rebuild = TRUE;
- }
- return;
- case PROP_LOWER_HOUR:
- ivalue = g_value_get_int (value);
- ivalue = CLAMP (ivalue, 0, 24);
- if (ecde->lower_hour != ivalue) {
- ecde->lower_hour = ivalue;
- ecde->need_time_list_rebuild = TRUE;
- }
- return;
- case PROP_UPPER_HOUR:
- ivalue = g_value_get_int (value);
- ivalue = CLAMP (ivalue, 0, 24);
- if (ecde->upper_hour != ivalue) {
- ecde->upper_hour = ivalue;
- ecde->need_time_list_rebuild = TRUE;
- }
- return;
- }
-
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
-}
-
-static gint
-e_cell_date_edit_do_popup (ECellPopup *ecp,
- GdkEvent *event,
- gint row,
- gint view_col)
-{
- ECellDateEdit *ecde = E_CELL_DATE_EDIT (ecp);
-
- e_cell_date_edit_show_popup (ecde, row, view_col);
- e_cell_date_edit_set_popup_values (ecde);
-
- gtk_grab_add (ecde->popup_window);
-
- /* Set the focus to the first widget. */
- gtk_widget_grab_focus (ecde->time_entry);
- gdk_window_focus (ecde->popup_window->window, GDK_CURRENT_TIME);
-
- return TRUE;
-}
-
-static void
-e_cell_date_edit_set_popup_values (ECellDateEdit *ecde)
-{
- ECellPopup *ecp = E_CELL_POPUP (ecde);
- ECellText *ecell_text = E_CELL_TEXT (ecp->child);
- ECellView *ecv = (ECellView*) ecp->popup_cell_view;
- ETableItem *eti = E_TABLE_ITEM (ecp->popup_cell_view->cell_view.e_table_item_view);
- ETableCol *ecol;
- gchar *cell_text;
- ETimeParseStatus status;
- struct tm date_tm;
- GDate date;
- ECalendarItem *calitem;
- gchar buffer[64];
- gboolean is_date = TRUE;
-
- ecol = e_table_header_get_column (eti->header, ecp->popup_view_col);
- cell_text = e_cell_text_get_text (ecell_text, ecv->e_table_model,
- ecol->col_idx, ecp->popup_row);
-
- /* Try to parse just a date first. If the value is only a date, we
- use a DATE value. */
- status = e_time_parse_date (cell_text, &date_tm);
- if (status == E_TIME_PARSE_INVALID) {
- is_date = FALSE;
- status = e_time_parse_date_and_time (cell_text, &date_tm);
- }
-
- /* If there is no date and time set, or the date is invalid, we clear
- the selections, else we select the appropriate date & time. */
- calitem = E_CALENDAR_ITEM (E_CALENDAR (ecde->calendar)->calitem);
- if (status == E_TIME_PARSE_NONE || status == E_TIME_PARSE_INVALID) {
- gtk_entry_set_text (GTK_ENTRY (ecde->time_entry), "");
- e_calendar_item_set_selection (calitem, NULL, NULL);
- gtk_tree_selection_unselect_all (gtk_tree_view_get_selection (GTK_TREE_VIEW (ecde->time_tree_view)));
- } else {
- if (is_date) {
- buffer[0] = '\0';
- } else {
- e_time_format_time (&date_tm, ecde->use_24_hour_format,
- FALSE, buffer, sizeof (buffer));
- }
- gtk_entry_set_text (GTK_ENTRY (ecde->time_entry), buffer);
-
- g_date_clear (&date, 1);
- g_date_set_dmy (&date, date_tm.tm_mday, date_tm.tm_mon + 1,
- date_tm.tm_year + 1900);
- e_calendar_item_set_selection (calitem, &date, &date);
-
- if (is_date) {
- gtk_tree_selection_unselect_all (gtk_tree_view_get_selection (GTK_TREE_VIEW (ecde->time_tree_view)));
- } else {
- e_cell_date_edit_select_matching_time (ecde, buffer);
- }
- }
-
- e_cell_text_free_text (ecell_text, cell_text);
-}
-
-static void
-e_cell_date_edit_select_matching_time (ECellDateEdit *ecde,
- gchar *time)
-{
- gboolean found = FALSE;
- gboolean valid;
- GtkTreeSelection *selection;
- GtkTreeIter iter;
- GtkTreeModel *model;
-
- model = gtk_tree_view_get_model (GTK_TREE_VIEW (ecde->time_tree_view));
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (ecde->time_tree_view));
-
- for (valid = gtk_tree_model_get_iter_first (model, &iter);
- valid && !found;
- valid = gtk_tree_model_iter_next (model, &iter)) {
- gchar *str = NULL;
-
- gtk_tree_model_get (model, &iter, 0, &str, -1);
-
- if (g_str_equal (str, time)) {
- GtkTreePath *path = gtk_tree_model_get_path (model, &iter);
-
- gtk_tree_view_set_cursor (GTK_TREE_VIEW (ecde->time_tree_view), path, NULL, FALSE);
- gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (ecde->time_tree_view), path, NULL, FALSE, 0.0, 0.0);
- gtk_tree_path_free (path);
-
- found = TRUE;
- }
-
- g_free (str);
- }
-
- if (!found) {
- gtk_tree_selection_unselect_all (selection);
- gtk_tree_view_scroll_to_point (GTK_TREE_VIEW (ecde->time_tree_view), 0, 0);
- }
-}
-
-static void
-e_cell_date_edit_show_popup (ECellDateEdit *ecde,
- gint row,
- gint view_col)
-{
- gint x, y, width, height;
-
- if (ecde->need_time_list_rebuild)
- e_cell_date_edit_rebuild_time_list (ecde);
-
- /* This code is practically copied from GtkCombo. */
-
- e_cell_date_edit_get_popup_pos (ecde, row, view_col, &x, &y, &height, &width);
-
- gtk_window_move (GTK_WINDOW (ecde->popup_window), x, y);
- gtk_widget_set_size_request (ecde->popup_window, width, height);
- gtk_widget_realize (ecde->popup_window);
- gdk_window_resize (ecde->popup_window->window, width, height);
- gtk_widget_show (ecde->popup_window);
-
- e_cell_popup_set_shown (E_CELL_POPUP (ecde), TRUE);
-}
-
-/* Calculates the size and position of the popup window (like GtkCombo). */
-static void
-e_cell_date_edit_get_popup_pos (ECellDateEdit *ecde,
- gint row,
- gint view_col,
- gint *x,
- gint *y,
- gint *height,
- gint *width)
-{
- ECellPopup *ecp = E_CELL_POPUP (ecde);
- ETableItem *eti = E_TABLE_ITEM (ecp->popup_cell_view->cell_view.e_table_item_view);
- GtkWidget *canvas = GTK_WIDGET (GNOME_CANVAS_ITEM (eti)->canvas);
- GtkRequisition popup_requisition;
- gint avail_height, screen_width, column_width, row_height;
- double x1, y1, wx, wy;
-
- gdk_window_get_origin (canvas->window, x, y);
-
- x1 = e_table_header_col_diff (eti->header, 0, view_col + 1);
- y1 = e_table_item_row_diff (eti, 0, row + 1);
- column_width = e_table_header_col_diff (eti->header, view_col,
- view_col + 1);
- row_height = e_table_item_row_diff (eti, row,
- row + 1);
- gnome_canvas_item_i2w (GNOME_CANVAS_ITEM (eti), &x1, &y1);
-
- gnome_canvas_world_to_window (GNOME_CANVAS (canvas),
- x1,
- y1,
- &wx,
- &wy);
-
- x1 = wx;
- y1 = wy;
-
- *x += x1;
- /* The ETable positions don't include the grid lines, I think, so we
- add 1. */
- *y += y1 + 1
- - (gint)((GnomeCanvas *)canvas)->layout.vadjustment->value
- + ((GnomeCanvas *)canvas)->zoom_yofs;
-
- avail_height = gdk_screen_height () - *y;
-
- /* We'll use the entire screen width if needed, but we save space for
- the vertical scrollbar in case we need to show that. */
- screen_width = gdk_screen_width ();
-
- gtk_widget_size_request (ecde->popup_window, &popup_requisition);
-
- /* Calculate the desired width. */
- *width = popup_requisition.width;
-
- /* Use at least the same width as the column. */
- if (*width < column_width)
- *width = column_width;
-
- /* Check if it fits in the available height. */
- if (popup_requisition.height > avail_height) {
- /* It doesn't fit, so we see if we have the minimum space
- needed. */
- if (*y - row_height > avail_height) {
- /* We don't, so we show the popup above the cell
- instead of below it. */
- avail_height = *y - row_height;
- *y -= (popup_requisition.height + row_height);
- if (*y < 0)
- *y = 0;
- }
- }
-
- /* We try to line it up with the right edge of the column, but we don't
- want it to go off the edges of the screen. */
- if (*x > screen_width)
- *x = screen_width;
- *x -= *width;
- if (*x < 0)
- *x = 0;
-
- *height = popup_requisition.height;
-}
-
-/* This handles key press events in the popup window. If the Escape key is
- pressed we hide the popup, and do not change the cell contents. */
-static gint
-e_cell_date_edit_key_press (GtkWidget *popup_window,
- GdkEventKey *event,
- ECellDateEdit *ecde)
-{
- /* If the Escape key is pressed we hide the popup. */
- if (event->keyval != GDK_Escape)
- return FALSE;
-
- e_cell_date_edit_hide_popup (ecde);
-
- return TRUE;
-}
-
-/* This handles button press events in the popup window. If the button is
- pressed outside the popup, we hide it and do not change the cell contents.
-*/
-static gint
-e_cell_date_edit_button_press (GtkWidget *popup_window,
- GdkEventButton *event,
- ECellDateEdit *ecde)
-{
- GtkWidget *event_widget;
-
- event_widget = gtk_get_event_widget ((GdkEvent*) event);
- if (gtk_widget_get_toplevel (event_widget) != popup_window) {
- e_cell_date_edit_hide_popup (ecde);
- }
-
- return TRUE;
-}
-
-/* Clears the time list and rebuilds it using the lower_hour, upper_hour
- and use_24_hour_format settings. */
-static void
-e_cell_date_edit_rebuild_time_list (ECellDateEdit *ecde)
-{
- GtkListStore *store;
- gchar buffer[40];
- struct tm tmp_tm;
- gint hour, min;
-
- store = GTK_LIST_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (ecde->time_tree_view)));
- gtk_list_store_clear (store);
-
- /* Fill the struct tm with some sane values. */
- tmp_tm.tm_year = 2000;
- tmp_tm.tm_mon = 0;
- tmp_tm.tm_mday = 1;
- tmp_tm.tm_sec = 0;
- tmp_tm.tm_isdst = 0;
-
- for (hour = ecde->lower_hour; hour <= ecde->upper_hour; hour++) {
- /* We don't want to display midnight at the end, since that is
- really in the next day. */
- if (hour == 24)
- break;
-
- /* We want to finish on upper_hour, with min == 0. */
- for (min = 0;
- min == 0 || (min < 60 && hour != ecde->upper_hour);
- min += 30) {
- GtkTreeIter iter;
-
- tmp_tm.tm_hour = hour;
- tmp_tm.tm_min = min;
- e_time_format_time (&tmp_tm, ecde->use_24_hour_format,
- FALSE, buffer, sizeof (buffer));
-
- gtk_list_store_append (store, &iter);
- gtk_list_store_set (store, &iter, 0, buffer, -1);
- }
- }
-
- ecde->need_time_list_rebuild = FALSE;
-}
-
-static void
-e_cell_date_edit_on_ok_clicked (GtkWidget *button,
- ECellDateEdit *ecde)
-{
- ECalendarItem *calitem;
- GDate start_date, end_date;
- gboolean day_selected;
- struct tm date_tm;
- gchar buffer[64];
- const gchar *text;
- ETimeParseStatus status;
- gboolean is_date = FALSE;
-
- calitem = E_CALENDAR_ITEM (E_CALENDAR (ecde->calendar)->calitem);
- day_selected = e_calendar_item_get_selection (calitem, &start_date,
- &end_date);
-
- text = gtk_entry_get_text (GTK_ENTRY (ecde->time_entry));
- status = e_time_parse_time (text, &date_tm);
- if (status == E_TIME_PARSE_INVALID) {
- e_cell_date_edit_show_time_invalid_warning (ecde);
- return;
- } else if (status == E_TIME_PARSE_NONE) {
- is_date = TRUE;
- }
-
- if (day_selected) {
- date_tm.tm_year = g_date_get_year (&start_date) - 1900;
- date_tm.tm_mon = g_date_get_month (&start_date) - 1;
- date_tm.tm_mday = g_date_get_day (&start_date);
- /* We need to call this to set the weekday. */
- mktime (&date_tm);
- e_time_format_date_and_time (&date_tm,
- ecde->use_24_hour_format,
- !is_date, FALSE,
- buffer, sizeof (buffer));
- } else {
- buffer[0] = '\0';
- }
-
- e_cell_date_edit_update_cell (ecde, buffer);
- e_cell_date_edit_hide_popup (ecde);
-}
-
-static void
-e_cell_date_edit_show_time_invalid_warning (ECellDateEdit *ecde)
-{
- GtkWidget *dialog;
- struct tm date_tm;
- gchar buffer[64];
-
- /* Create a useful error message showing the correct format. */
- date_tm.tm_year = 100;
- date_tm.tm_mon = 0;
- date_tm.tm_mday = 1;
- date_tm.tm_hour = 1;
- date_tm.tm_min = 30;
- date_tm.tm_sec = 0;
- date_tm.tm_isdst = -1;
- e_time_format_time (&date_tm, ecde->use_24_hour_format, FALSE,
- buffer, sizeof (buffer));
-
- /* FIXME: Fix transient settings - I'm not sure it works with popup
- windows. Maybe we need to use a normal window without decorations.*/
- dialog = gtk_message_dialog_new (
- GTK_WINDOW (ecde->popup_window),
- GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
- _("The time must be in the format: %s"),
- buffer);
- gtk_dialog_run (GTK_DIALOG (dialog));
- gtk_widget_destroy (dialog);
-}
-
-static void
-e_cell_date_edit_on_now_clicked (GtkWidget *button,
- ECellDateEdit *ecde)
-{
- struct tm tmp_tm;
- time_t t;
- gchar buffer[64];
-
- if (ecde->time_callback) {
- tmp_tm = (*ecde->time_callback) (ecde, ecde->time_callback_data);
- } else {
- t = time (NULL);
- tmp_tm = *localtime (&t);
- }
- e_time_format_date_and_time (&tmp_tm,
- ecde->use_24_hour_format,
- TRUE, FALSE,
- buffer, sizeof (buffer));
-
- e_cell_date_edit_update_cell (ecde, buffer);
- e_cell_date_edit_hide_popup (ecde);
-}
-
-static void
-e_cell_date_edit_on_none_clicked (GtkWidget *button,
- ECellDateEdit *ecde)
-{
- e_cell_date_edit_update_cell (ecde, "");
- e_cell_date_edit_hide_popup (ecde);
-}
-
-static void
-e_cell_date_edit_on_today_clicked (GtkWidget *button,
- ECellDateEdit *ecde)
-{
- struct tm tmp_tm;
- time_t t;
- gchar buffer[64];
-
- if (ecde->time_callback) {
- tmp_tm = (*ecde->time_callback) (ecde, ecde->time_callback_data);
- } else {
- t = time (NULL);
- tmp_tm = *localtime (&t);
- }
-
- tmp_tm.tm_hour = 0;
- tmp_tm.tm_min = 0;
- tmp_tm.tm_sec = 0;
- e_time_format_date_and_time (&tmp_tm,
- ecde->use_24_hour_format,
- FALSE, FALSE,
- buffer, sizeof (buffer));
-
- e_cell_date_edit_update_cell (ecde, buffer);
- e_cell_date_edit_hide_popup (ecde);
-}
-
-static void
-e_cell_date_edit_update_cell (ECellDateEdit *ecde,
- const gchar *text)
-{
- ECellPopup *ecp = E_CELL_POPUP (ecde);
- ECellText *ecell_text = E_CELL_TEXT (ecp->child);
- ECellView *ecv = (ECellView*) ecp->popup_cell_view;
- ETableItem *eti = E_TABLE_ITEM (ecv->e_table_item_view);
- ETableCol *ecol;
- gchar *old_text;
-
- /* Compare the new text with the existing cell contents. */
- ecol = e_table_header_get_column (eti->header, ecp->popup_view_col);
-
- old_text = e_cell_text_get_text (ecell_text, ecv->e_table_model,
- ecol->col_idx, ecp->popup_row);
-
- /* If they are different, update the cell contents. */
- if (strcmp (old_text, text)) {
- e_cell_text_set_value (ecell_text, ecv->e_table_model,
- ecol->col_idx, ecp->popup_row, text);
- e_cell_leave_edit (ecv, ecp->popup_view_col, ecol->col_idx, ecp->popup_row, NULL);
- }
-
- e_cell_text_free_text (ecell_text, old_text);
-}
-
-static void
-e_cell_date_edit_on_time_selected (GtkTreeSelection *selection, ECellDateEdit *ecde)
-{
- gchar *list_item_text = NULL;
- GtkTreeIter iter;
- GtkTreeModel *model;
-
- if (!gtk_tree_selection_get_selected (selection, &model, &iter))
- return;
-
- gtk_tree_model_get (model, &iter, 0, &list_item_text, -1);
-
- g_return_if_fail (list_item_text != NULL);
-
- gtk_entry_set_text (GTK_ENTRY (ecde->time_entry), list_item_text);
-
- g_free (list_item_text);
-}
-
-static void
-e_cell_date_edit_hide_popup (ECellDateEdit *ecde)
-{
- gtk_grab_remove (ecde->popup_window);
- gtk_widget_hide (ecde->popup_window);
- e_cell_popup_set_shown (E_CELL_POPUP (ecde), FALSE);
-}
-
-/* These freeze and thaw the rebuilding of the time list. They are useful when
- setting several properties which result in rebuilds of the list, e.g. the
- lower_hour, upper_hour and use_24_hour_format properties. */
-void
-e_cell_date_edit_freeze (ECellDateEdit *ecde)
-{
- g_return_if_fail (E_IS_CELL_DATE_EDIT (ecde));
-
- ecde->freeze_count++;
-}
-
-void
-e_cell_date_edit_thaw (ECellDateEdit *ecde)
-{
- g_return_if_fail (E_IS_CELL_DATE_EDIT (ecde));
-
- if (ecde->freeze_count > 0) {
- ecde->freeze_count--;
-
- if (ecde->freeze_count == 0)
- e_cell_date_edit_rebuild_time_list (ecde);
- }
-}
-
-/* Sets a callback to use to get the current time. This is useful if the
- application needs to use its own timezone data rather than rely on the
- Unix timezone. */
-void
-e_cell_date_edit_set_get_time_callback (ECellDateEdit *ecde,
- ECellDateEditGetTimeCallback cb,
- gpointer data,
- GDestroyNotify destroy)
-{
- g_return_if_fail (E_IS_CELL_DATE_EDIT (ecde));
-
- if (ecde->time_callback_data && ecde->time_callback_destroy)
- (*ecde->time_callback_destroy) (ecde->time_callback_data);
-
- ecde->time_callback = cb;
- ecde->time_callback_data = data;
- ecde->time_callback_destroy = destroy;
-}
diff --git a/widgets/misc/e-cell-date-edit.h b/widgets/misc/e-cell-date-edit.h
deleted file mode 100644
index 72fe952e31..0000000000
--- a/widgets/misc/e-cell-date-edit.h
+++ /dev/null
@@ -1,101 +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:
- * Damon Chaplin <damon@ximian.com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-/*
- * ECellDateEdit - a subclass of ECellPopup used to show a date with a popup
- * window to edit it.
- */
-
-#ifndef _E_CELL_DATE_EDIT_H_
-#define _E_CELL_DATE_EDIT_H_
-
-#include <time.h>
-#include <table/e-cell-popup.h>
-
-#define E_CELL_DATE_EDIT_TYPE (e_cell_date_edit_get_type ())
-#define E_CELL_DATE_EDIT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), E_CELL_DATE_EDIT_TYPE, ECellDateEdit))
-#define E_CELL_DATE_EDIT_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), E_CELL_DATE_EDIT_TYPE, ECellDateEditClass))
-#define E_IS_CELL_DATE_EDIT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), E_CELL_DATE_EDIT_TYPE))
-#define E_IS_CELL_DATE_EDIT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), E_CELL_DATE_EDIT_TYPE))
-
-typedef struct _ECellDateEdit ECellDateEdit;
-typedef struct _ECellDateEditClass ECellDateEditClass;
-
-/* The type of the callback function optionally used to get the current time.
- */
-typedef struct tm (*ECellDateEditGetTimeCallback) (ECellDateEdit *ecde,
- gpointer data);
-
-struct _ECellDateEdit {
- ECellPopup parent;
-
- GtkWidget *popup_window;
- GtkWidget *calendar;
- GtkWidget *time_entry;
- GtkWidget *time_tree_view;
-
- GtkWidget *now_button;
- GtkWidget *today_button;
- GtkWidget *none_button;
-
- /* This is the range of hours we show in the time list. */
- gint lower_hour;
- gint upper_hour;
-
- /* TRUE if we use 24-hour format for the time list and entry. */
- gboolean use_24_hour_format;
-
- /* This is TRUE if we need to rebuild the list of times. */
- gboolean need_time_list_rebuild;
-
- /* The freeze count for rebuilding the time list. We only rebuild when
- this is 0. */
- gint freeze_count;
-
- ECellDateEditGetTimeCallback time_callback;
- gpointer time_callback_data;
- GDestroyNotify time_callback_destroy;
-};
-
-struct _ECellDateEditClass {
- ECellPopupClass parent_class;
-};
-
-GType e_cell_date_edit_get_type (void);
-ECell *e_cell_date_edit_new (void);
-
-/* These freeze and thaw the rebuilding of the time list. They are useful when
- setting several properties which result in rebuilds of the list, e.g. the
- lower_hour, upper_hour and use_24_hour_format properties. */
-void e_cell_date_edit_freeze (ECellDateEdit *ecde);
-void e_cell_date_edit_thaw (ECellDateEdit *ecde);
-
-/* Sets a callback to use to get the current time. This is useful if the
- application needs to use its own timezone data rather than rely on the
- Unix timezone. */
-void e_cell_date_edit_set_get_time_callback(ECellDateEdit *ecde,
- ECellDateEditGetTimeCallback cb,
- gpointer data,
- GDestroyNotify destroy);
-
-#endif /* _E_CELL_DATE_EDIT_H_ */
diff --git a/widgets/misc/e-cell-percent.c b/widgets/misc/e-cell-percent.c
deleted file mode 100644
index 3ed995421b..0000000000
--- a/widgets/misc/e-cell-percent.c
+++ /dev/null
@@ -1,151 +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:
- * Damon Chaplin <damon@ximian.com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-/*
- * ECellPercent - a subclass of ECellText used to show an integer percentage
- * in an ETable.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <ctype.h>
-
-#include <sys/time.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <glib/gi18n.h>
-
-#include "e-cell-percent.h"
-
-G_DEFINE_TYPE (ECellPercent, e_cell_percent, E_CELL_TEXT_TYPE)
-
-static gchar *
-ecp_get_text (ECellText *cell, ETableModel *model, gint col, gint row)
-{
- gint percent;
- static gchar buffer[8];
-
- percent = GPOINTER_TO_INT (e_table_model_value_at (model, col, row));
-
- /* A -ve value means the property is not set. */
- if (percent < 0) {
- buffer[0] = '\0';
- } else {
- g_snprintf (buffer, sizeof (buffer), "%i%%", percent);
- }
-
- return buffer;
-}
-
-static void
-ecp_free_text(ECellText *cell, gchar *text)
-{
- /* Do Nothing. */
-}
-
-/* FIXME: We need to set the "transient_for" property for the dialog. */
-static void
-show_percent_warning (void)
-{
- GtkWidget *dialog;
-
- dialog = gtk_message_dialog_new (
- NULL, 0,
- GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
- "%s", _("The percent value must be between 0 and 100, inclusive"));
- gtk_dialog_run (GTK_DIALOG (dialog));
- gtk_widget_destroy (dialog);
-}
-
-static void
-ecp_set_value (ECellText *cell, ETableModel *model, gint col, gint row,
- const gchar *text)
-{
- gint matched, percent;
- gboolean empty = TRUE;
- const gchar *p;
-
- if (text) {
- p = text;
- while (*p) {
- if (!isspace ((guchar) *p)) {
- empty = FALSE;
- break;
- }
- p++;
- }
- }
-
- if (empty) {
- percent = -1;
- } else {
- matched = sscanf (text, "%i", &percent);
-
- if (matched != 1 || percent < 0 || percent > 100) {
- show_percent_warning ();
- return;
- }
- }
-
- e_table_model_set_value_at (model, col, row,
- GINT_TO_POINTER (percent));
-}
-
-static void
-e_cell_percent_class_init (ECellPercentClass *ecpc)
-{
- ECellTextClass *ectc = (ECellTextClass *) ecpc;
-
- ectc->get_text = ecp_get_text;
- ectc->free_text = ecp_free_text;
- ectc->set_value = ecp_set_value;
-}
-
-static void
-e_cell_percent_init (ECellPercent *ecp)
-{
-}
-
-/**
- * e_cell_percent_new:
- * @fontname: font to be used to render on the screen
- * @justify: Justification of the string in the cell.
- *
- * Creates a new ECell renderer that can be used to render an integer
- * percentage that comes from the model. The value returned from the model is
- * interpreted as being an int.
- *
- * See ECellText for other features.
- *
- * Returns: an ECell object that can be used to render numbers.
- */
-ECell *
-e_cell_percent_new (const gchar *fontname, GtkJustification justify)
-{
- ECellPercent *ecn = g_object_new (E_CELL_PERCENT_TYPE, NULL);
-
- e_cell_text_construct (E_CELL_TEXT(ecn), fontname, justify);
-
- return (ECell *) ecn;
-}
diff --git a/widgets/misc/e-cell-percent.h b/widgets/misc/e-cell-percent.h
deleted file mode 100644
index 3ac15afab7..0000000000
--- a/widgets/misc/e-cell-percent.h
+++ /dev/null
@@ -1,51 +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:
- * Damon Chaplin <damon@ximian.com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-/*
- * ECellPercent - a subclass of ECellText used to show an integer percentage
- * in an ETable.
- */
-
-#ifndef _E_CELL_PERCENT_H_
-#define _E_CELL_PERCENT_H_
-
-#include <table/e-cell-text.h>
-
-#define E_CELL_PERCENT_TYPE (e_cell_percent_get_type ())
-#define E_CELL_PERCENT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), E_CELL_PERCENT_TYPE, ECellPercent))
-#define E_CELL_PERCENT_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), E_CELL_PERCENT_TYPE, ECellPercentClass))
-#define E_IS_CELL_NUMBER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), E_CELL_PERCENT_TYPE))
-#define E_IS_CELL_NUMBER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), E_CELL_PERCENT_TYPE))
-
-typedef struct {
- ECellText base;
-} ECellPercent;
-
-typedef struct {
- ECellTextClass parent_class;
-} ECellPercentClass;
-
-GType e_cell_percent_get_type (void);
-ECell *e_cell_percent_new (const gchar *fontname, GtkJustification justify);
-
-#endif /* _E_CELL_PERCENT_H_ */
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 3caf793611..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-dateedit.c b/widgets/misc/e-dateedit.c
index 775ab3b8a3..07a9fc61c4 100644
--- a/widgets/misc/e-dateedit.c
+++ b/widgets/misc/e-dateedit.c
@@ -42,6 +42,10 @@
#include <e-util/e-util.h>
#include "e-calendar.h"
+#define E_DATE_EDIT_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), E_TYPE_DATE_EDIT, EDateEditPrivate))
+
struct _EDateEditPrivate {
GtkWidget *date_entry;
GtkWidget *date_button;
@@ -108,16 +112,18 @@ struct _EDateEditPrivate {
};
enum {
+ PROP_0,
+ PROP_SHOW_WEEK_NUMBERS,
+ PROP_USE_24_HOUR_FORMAT,
+ PROP_WEEK_START_DAY
+};
+
+enum {
CHANGED,
LAST_SIGNAL
};
-static gint date_edit_signals [LAST_SIGNAL] = { 0 };
-
-static void e_date_edit_class_init (EDateEditClass *class);
-static void e_date_edit_init (EDateEdit *dedit);
static void create_children (EDateEdit *dedit);
-static void e_date_edit_dispose (GObject *object);
static gboolean e_date_edit_mnemonic_activate (GtkWidget *widget,
gboolean group_cycling);
static void e_date_edit_grab_focus (GtkWidget *widget);
@@ -188,87 +194,168 @@ static gboolean e_date_edit_set_time_internal (EDateEdit *dedit,
gint hour,
gint minute);
-static GtkHBoxClass *parent_class;
+static gpointer parent_class;
+static gint signals[LAST_SIGNAL];
-/**
- * e_date_edit_get_type:
- *
- * Returns the GType for the EDateEdit widget
- */
-GType
-e_date_edit_get_type (void)
-{
- static GType date_edit_type = 0;
+static void
+date_edit_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_SHOW_WEEK_NUMBERS:
+ e_date_edit_set_show_week_numbers (
+ E_DATE_EDIT (object),
+ g_value_get_boolean (value));
+ return;
- if (!date_edit_type) {
- static const GTypeInfo date_edit_info = {
- sizeof (EDateEditClass),
- NULL, /* base_init */
- NULL, /* base_finalize */
- (GClassInitFunc) e_date_edit_class_init,
- NULL, /* class_finalize */
- NULL, /* class_data */
- sizeof (EDateEdit),
- 0, /* n_preallocs */
- (GInstanceInitFunc) e_date_edit_init,
- };
+ case PROP_USE_24_HOUR_FORMAT:
+ e_date_edit_set_use_24_hour_format (
+ E_DATE_EDIT (object),
+ g_value_get_boolean (value));
+ return;
+
+ case PROP_WEEK_START_DAY:
+ e_date_edit_set_week_start_day (
+ E_DATE_EDIT (object),
+ g_value_get_int (value));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
- date_edit_type = g_type_register_static (GTK_TYPE_HBOX, "EDateEdit", &date_edit_info, 0);
+static void
+date_edit_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_SHOW_WEEK_NUMBERS:
+ g_value_set_boolean (
+ value, e_date_edit_get_show_week_numbers (
+ E_DATE_EDIT (object)));
+ return;
+
+ case PROP_USE_24_HOUR_FORMAT:
+ g_value_set_boolean (
+ value, e_date_edit_get_use_24_hour_format (
+ E_DATE_EDIT (object)));
+ return;
+
+ case PROP_WEEK_START_DAY:
+ g_value_set_int (
+ value, e_date_edit_get_week_start_day (
+ E_DATE_EDIT (object)));
+ return;
}
- return date_edit_type;
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
static void
-e_date_edit_class_init (EDateEditClass *class)
+date_edit_dispose (GObject *object)
{
- GObjectClass *object_class = (GObjectClass *) class;
- GtkWidgetClass *widget_class = (GtkWidgetClass *) class;
+ EDateEdit *dedit;
- parent_class = g_type_class_ref (GTK_TYPE_HBOX);
+ dedit = E_DATE_EDIT (object);
- date_edit_signals [CHANGED] =
- g_signal_new ("changed",
- G_OBJECT_CLASS_TYPE (object_class),
- G_SIGNAL_RUN_FIRST,
- G_STRUCT_OFFSET (EDateEditClass, changed),
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
+ e_date_edit_set_get_time_callback (dedit, NULL, NULL, NULL);
- object_class->dispose = e_date_edit_dispose;
+ if (dedit->priv->cal_popup != NULL) {
+ gtk_widget_destroy (dedit->priv->cal_popup);
+ dedit->priv->cal_popup = NULL;
+ }
+ /* Chain up to parent's dispose() method. */
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+date_edit_class_init (EDateEditClass *class)
+{
+ GObjectClass *object_class;
+ GtkWidgetClass *widget_class;
+
+ parent_class = g_type_class_peek_parent (class);
+ g_type_class_add_private (class, sizeof (EDateEditPrivate));
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->set_property = date_edit_set_property;
+ object_class->get_property = date_edit_get_property;
+ object_class->dispose = date_edit_dispose;
+
+ widget_class = GTK_WIDGET_CLASS (class);
widget_class->mnemonic_activate = e_date_edit_mnemonic_activate;
widget_class->grab_focus = e_date_edit_grab_focus;
- class->changed = NULL;
+ g_object_class_install_property (
+ object_class,
+ PROP_SHOW_WEEK_NUMBERS,
+ g_param_spec_boolean (
+ "show-week-numbers",
+ "Show Week Numbers",
+ NULL,
+ TRUE,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_USE_24_HOUR_FORMAT,
+ g_param_spec_boolean (
+ "use-24-hour-format",
+ "Use 24-Hour Format",
+ NULL,
+ TRUE,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_WEEK_START_DAY,
+ g_param_spec_int (
+ "week-start-day",
+ "Week Start Day",
+ NULL,
+ 0, /* Monday */
+ 6, /* Sunday */
+ 0,
+ G_PARAM_READWRITE));
+
+ signals[CHANGED] = g_signal_new (
+ "changed",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (EDateEditClass, changed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
}
static void
-e_date_edit_init (EDateEdit *dedit)
+date_edit_init (EDateEdit *dedit)
{
- EDateEditPrivate *priv;
+ dedit->priv = E_DATE_EDIT_GET_PRIVATE (dedit);
- dedit->priv = priv = g_new0 (EDateEditPrivate, 1);
+ dedit->priv->show_date = TRUE;
+ dedit->priv->show_time = TRUE;
+ dedit->priv->use_24_hour_format = TRUE;
- priv->show_date = TRUE;
- priv->show_time = TRUE;
- priv->use_24_hour_format = TRUE;
+ dedit->priv->make_time_insensitive = FALSE;
- priv->make_time_insensitive = FALSE;
+ dedit->priv->lower_hour = 0;
+ dedit->priv->upper_hour = 24;
- priv->lower_hour = 0;
- priv->upper_hour = 24;
+ dedit->priv->date_is_valid = TRUE;
+ dedit->priv->date_set_to_none = TRUE;
+ dedit->priv->time_is_valid = TRUE;
+ dedit->priv->time_set_to_none = TRUE;
+ dedit->priv->time_callback = NULL;
+ dedit->priv->time_callback_data = NULL;
+ dedit->priv->time_callback_destroy = NULL;
- priv->date_is_valid = TRUE;
- priv->date_set_to_none = TRUE;
- priv->time_is_valid = TRUE;
- priv->time_set_to_none = TRUE;
- priv->time_callback = NULL;
- priv->time_callback_data = NULL;
- priv->time_callback_destroy = NULL;
-
- priv->twodigit_year_can_future = TRUE;
+ dedit->priv->twodigit_year_can_future = TRUE;
create_children (dedit);
@@ -276,6 +363,32 @@ e_date_edit_init (EDateEdit *dedit)
e_date_edit_set_time (dedit, 0);
}
+GType
+e_date_edit_get_type (void)
+{
+ static GType type = 0;
+
+ if (G_UNLIKELY (type == 0)) {
+ static const GTypeInfo type_info = {
+ sizeof (EDateEditClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) date_edit_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+ sizeof (EDateEdit),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) date_edit_init,
+ NULL /* value_table */
+ };
+
+ type = g_type_register_static (
+ GTK_TYPE_HBOX, "EDateEdit", &type_info, 0);
+ }
+
+ return type;
+}
+
/**
* e_date_edit_new:
*
@@ -472,29 +585,6 @@ create_children (EDateEdit *dedit)
G_CALLBACK (on_date_popup_none_button_clicked), dedit);
}
-static void
-e_date_edit_dispose (GObject *object)
-{
- EDateEdit *dedit;
-
- g_return_if_fail (E_IS_DATE_EDIT (object));
-
- dedit = E_DATE_EDIT (object);
-
- if (dedit->priv) {
- e_date_edit_set_get_time_callback (dedit, NULL, NULL, NULL);
-
- gtk_widget_destroy (dedit->priv->cal_popup);
- dedit->priv->cal_popup = NULL;
-
- g_free (dedit->priv);
- dedit->priv = NULL;
- }
-
- if (G_OBJECT_CLASS (parent_class)->dispose)
- (* G_OBJECT_CLASS (parent_class)->dispose) (object);
-}
-
/* GtkWidget::mnemonic_activate() handler for the EDateEdit */
static gboolean
e_date_edit_mnemonic_activate (GtkWidget *widget, gboolean group_cycling)
@@ -647,8 +737,7 @@ e_date_edit_set_time (EDateEdit *dedit,
/* Emit the signals if the date and/or time has actually changed. */
if (date_changed || time_changed)
- g_signal_emit (dedit,
- date_edit_signals [CHANGED], 0);
+ g_signal_emit (dedit, signals[CHANGED], 0);
}
/**
@@ -715,8 +804,7 @@ e_date_edit_set_date (EDateEdit *dedit,
/* Emit the signals if the date has actually changed. */
if (date_changed)
- g_signal_emit (dedit,
- date_edit_signals [CHANGED], 0);
+ g_signal_emit (dedit, signals[CHANGED], 0);
}
/**
@@ -792,8 +880,7 @@ e_date_edit_set_time_of_day (EDateEdit *dedit,
e_date_edit_update_time_entry (dedit);
if (time_changed)
- g_signal_emit (dedit,
- date_edit_signals [CHANGED], 0);
+ g_signal_emit (dedit, signals[CHANGED], 0);
}
void
@@ -818,8 +905,7 @@ e_date_edit_set_date_and_time_of_day (EDateEdit *dedit,
e_date_edit_update_time_combo_state (dedit);
if (date_changed || time_changed)
- g_signal_emit (dedit,
- date_edit_signals [CHANGED], 0);
+ g_signal_emit (dedit, signals[CHANGED], 0);
}
/**
@@ -969,21 +1055,21 @@ e_date_edit_set_make_time_insensitive (EDateEdit *dedit,
/**
* e_date_edit_get_week_start_day:
* @dedit: an #EDateEdit widget
- * @Returns: the week start day, from 0 (Sunday) to 6 (Saturday).
+ * @Returns: the week start day, from 0 (Monday) to 6 (Sunday).
*
* Description: Returns the week start day currently used in the calendar
* popup.
*/
gint
-e_date_edit_get_week_start_day (EDateEdit *dedit)
+e_date_edit_get_week_start_day (EDateEdit *dedit)
{
gint week_start_day;
g_return_val_if_fail (E_IS_DATE_EDIT (dedit), 1);
- g_object_get (E_CALENDAR (dedit->priv->calendar)->calitem,
- "week_start_day", &week_start_day,
- NULL);
+ g_object_get (
+ E_CALENDAR (dedit->priv->calendar)->calitem,
+ "week_start_day", &week_start_day, NULL);
return week_start_day;
}
@@ -991,50 +1077,54 @@ e_date_edit_get_week_start_day (EDateEdit *dedit)
/**
* e_date_edit_set_week_start_day:
* @dedit: an #EDateEdit widget
- * @week_start_day: the week start day, from 0 (Sunday) to 6 (Saturday).
+ * @week_start_day: the week start day, from 0 (Monday) to 6 (Sunday).
*
* Description: Sets the week start day to use in the calendar popup.
*/
void
-e_date_edit_set_week_start_day (EDateEdit *dedit,
- gint week_start_day)
+e_date_edit_set_week_start_day (EDateEdit *dedit,
+ gint week_start_day)
{
g_return_if_fail (E_IS_DATE_EDIT (dedit));
- gnome_canvas_item_set (GNOME_CANVAS_ITEM (E_CALENDAR (dedit->priv->calendar)->calitem),
- "week_start_day", week_start_day,
- NULL);
+ gnome_canvas_item_set (
+ GNOME_CANVAS_ITEM (E_CALENDAR (dedit->priv->calendar)->calitem),
+ "week_start_day", week_start_day, NULL);
+
+ g_object_notify (G_OBJECT (dedit), "week-start-day");
}
/* Whether we show week numbers in the date popup. */
gboolean
-e_date_edit_get_show_week_numbers (EDateEdit *dedit)
+e_date_edit_get_show_week_numbers (EDateEdit *dedit)
{
gboolean show_week_numbers;
g_return_val_if_fail (E_IS_DATE_EDIT (dedit), FALSE);
- g_object_get (E_CALENDAR (dedit->priv->calendar)->calitem,
- "show_week_numbers", &show_week_numbers,
- NULL);
+ g_object_get (
+ E_CALENDAR (dedit->priv->calendar)->calitem,
+ "show_week_numbers", &show_week_numbers, NULL);
return show_week_numbers;
}
void
-e_date_edit_set_show_week_numbers (EDateEdit *dedit,
- gboolean show_week_numbers)
+e_date_edit_set_show_week_numbers (EDateEdit *dedit,
+ gboolean show_week_numbers)
{
g_return_if_fail (E_IS_DATE_EDIT (dedit));
- gnome_canvas_item_set (GNOME_CANVAS_ITEM (E_CALENDAR (dedit->priv->calendar)->calitem),
- "show_week_numbers", show_week_numbers,
- NULL);
+ gnome_canvas_item_set (
+ GNOME_CANVAS_ITEM (E_CALENDAR (dedit->priv->calendar)->calitem),
+ "show_week_numbers", show_week_numbers, NULL);
+
+ g_object_notify (G_OBJECT (dedit), "show-week-numbers");
}
/* Whether we use 24 hour format in the time field & popup. */
gboolean
-e_date_edit_get_use_24_hour_format (EDateEdit *dedit)
+e_date_edit_get_use_24_hour_format (EDateEdit *dedit)
{
g_return_val_if_fail (E_IS_DATE_EDIT (dedit), TRUE);
@@ -1042,8 +1132,8 @@ e_date_edit_get_use_24_hour_format (EDateEdit *dedit)
}
void
-e_date_edit_set_use_24_hour_format (EDateEdit *dedit,
- gboolean use_24_hour_format)
+e_date_edit_set_use_24_hour_format (EDateEdit *dedit,
+ gboolean use_24_hour_format)
{
g_return_if_fail (E_IS_DATE_EDIT (dedit));
@@ -1055,6 +1145,8 @@ e_date_edit_set_use_24_hour_format (EDateEdit *dedit,
rebuild_time_popup (dedit);
e_date_edit_update_time_entry (dedit);
+
+ g_object_notify (G_OBJECT (dedit), "use-24-hour-format");
}
/* Whether we allow the date to be set to 'None'. e_date_edit_get_time() will
@@ -1399,8 +1491,8 @@ rebuild_time_popup (EDateEdit *dedit)
/* For 12-hour am/pm format, we want space padding, not zero padding. This
* can be done with strftime's %l, but it's a potentially unportable extension. */
- if (!priv->use_24_hour_format && buffer [0] == '0')
- buffer [0] = ' ';
+ if (!priv->use_24_hour_format && buffer[0] == '0')
+ buffer[0] = ' ';
gtk_combo_box_append_text (combo, buffer);
}
@@ -1736,8 +1828,8 @@ e_date_edit_update_time_entry (EDateEdit *dedit)
/* For 12-hour am/pm format, we want space padding, not zero padding. This
* can be done with strftime's %l, but it's a potentially unportable extension. */
- if (!priv->use_24_hour_format && buffer [0] == '0')
- buffer [0] = ' ';
+ if (!priv->use_24_hour_format && buffer[0] == '0')
+ buffer[0] = ' ';
gtk_entry_set_text (GTK_ENTRY (GTK_BIN (priv->time_combo)->child),
buffer);
@@ -1860,8 +1952,7 @@ e_date_edit_check_date_changed (EDateEdit *dedit)
tmp_tm.tm_mday);
if (date_changed)
- g_signal_emit (dedit,
- date_edit_signals [CHANGED], 0);
+ g_signal_emit (dedit, signals[CHANGED], 0);
}
/* Parses the time, and if it is different from the current settings it
@@ -1891,8 +1982,7 @@ e_date_edit_check_time_changed (EDateEdit *dedit)
if (time_changed) {
e_date_edit_update_time_entry (dedit);
- g_signal_emit (dedit,
- date_edit_signals [CHANGED], 0);
+ g_signal_emit (dedit, signals[CHANGED], 0);
}
}
diff --git a/widgets/misc/e-dropdown-button.c b/widgets/misc/e-dropdown-button.c
deleted file mode 100644
index 0ff0c99fef..0000000000
--- a/widgets/misc/e-dropdown-button.c
+++ /dev/null
@@ -1,236 +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-filter-bar.c b/widgets/misc/e-filter-bar.c
deleted file mode 100644
index 42fc03882f..0000000000
--- a/widgets/misc/e-filter-bar.c
+++ /dev/null
@@ -1,1032 +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 8659f0a638..0000000000
--- a/widgets/misc/e-filter-bar.h
+++ /dev/null
@@ -1,138 +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 87b89f61d5..0000000000
--- a/widgets/misc/e-icon-entry.c
+++ /dev/null
@@ -1,418 +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_create_text (const gchar *text)
-{
- 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_label_new (text);
- gtk_container_add (GTK_CONTAINER (eventbox), image);
- g_object_set_data ((GObject *)eventbox, "lbl", 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_create_separator ()
-{
- GtkWidget *eventbox;
- GtkWidget *image;
-
- eventbox = gtk_event_box_new ();
- gtk_container_set_border_width (GTK_CONTAINER (eventbox), 0);
- gtk_event_box_set_visible_window (GTK_EVENT_BOX (eventbox), FALSE);
-
- image = (GtkWidget *)gtk_separator_tool_item_new ();
- gtk_container_add (GTK_CONTAINER (eventbox), image);
-
- 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 cde735ba6f..0000000000
--- a/widgets/misc/e-icon-entry.h
+++ /dev/null
@@ -1,87 +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);
-GtkWidget * e_icon_entry_create_text (const gchar *text);
-GtkWidget * e_icon_entry_create_separator (void);
-
-G_END_DECLS
-
-#endif
diff --git a/widgets/misc/e-image-chooser.c b/widgets/misc/e-image-chooser.c
index e5a20e5303..32a3f2a899 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,23 +27,20 @@
#include <glib/gi18n.h>
#include "e-image-chooser.h"
-#include "e-util/e-icon-factory.h"
#include "e-util/e-util.h"
-#define d(x)
+#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 {
@@ -52,182 +48,24 @@ enum {
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]);
+static gpointer parent_class;
+static guint signals[LAST_SIGNAL];
-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);
-}
+#define URI_LIST_TYPE "text/uri-list"
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);
@@ -236,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);
-
- d (printf ("new dimensions = (%d,%d)\n", new_width, new_height));
-
- if (chooser->priv->image_height == 0
- && chooser->priv->image_width == 0) {
- d (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 */
- d (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 */
- d (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;
- }
-
- d (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;
- d (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;
@@ -336,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;
}
@@ -376,77 +216,205 @@ 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;
- }
- }
+ if (!handled)
+ g_free (buf);
- if (!handled)
- 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 +422,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 +439,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 ece1419633..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,53 +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-menu-tool-button.c b/widgets/misc/e-menu-tool-button.c
new file mode 100644
index 0000000000..fcf73d6c4e
--- /dev/null
+++ b/widgets/misc/e-menu-tool-button.c
@@ -0,0 +1,183 @@
+/*
+ * 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_activatable_get_related_action (
+ GTK_ACTIVATABLE (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_size_request (GtkWidget *widget,
+ GtkRequisition *requisition)
+{
+ gint minimum_width;
+
+ /* Chain up to parent's size_request() method. */
+ GTK_WIDGET_CLASS (parent_class)->size_request (widget, requisition);
+
+ /* XXX This is a hack. This widget is only used for the New
+ * button in the main window toolbar. The New button is
+ * pretty important, but the word "New" is pretty short
+ * (in English, anyway) and this results in a small screen
+ * target when using a "text below item" toolbar style.
+ *
+ * We can't go hard-coding a width, but we -can- use a
+ * heuristic based on the toolbar button height. */
+ minimum_width = requisition->height * 2;
+ requisition->width = MAX (minimum_width, requisition->width);
+}
+
+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)
+{
+ GtkWidgetClass *widget_class;
+ GtkToolButtonClass *tool_button_class;
+
+ parent_class = g_type_class_peek_parent (class);
+
+ widget_class = GTK_WIDGET_CLASS (class);
+ widget_class->size_request = menu_tool_button_size_request;
+
+ 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 1f31ff8cc4..0000000000
--- a/widgets/misc/e-multi-config-dialog.c
+++ /dev/null
@@ -1,368 +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..444296dcef 100644
--- a/widgets/misc/e-online-button.c
+++ b/widgets/misc/e-online-button.c
@@ -23,6 +23,15 @@
(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.")
+
+#define NETWORK_UNAVAILABLE_TOOLTIP \
+ _("Evolution is currently offline because the network is unavailable.")
+
struct _EOnlineButtonPrivate {
GtkWidget *image;
gboolean online;
@@ -36,6 +45,21 @@ enum {
static gpointer parent_class;
static void
+online_button_update_tooltip (EOnlineButton *button)
+{
+ const gchar *tooltip;
+
+ if (e_online_button_get_online (button))
+ tooltip = ONLINE_TOOLTIP;
+ else if (GTK_WIDGET_SENSITIVE (button))
+ tooltip = OFFLINE_TOOLTIP;
+ else
+ tooltip = NETWORK_UNAVAILABLE_TOOLTIP;
+
+ gtk_widget_set_tooltip_text (GTK_WIDGET (button), tooltip);
+}
+
+static void
online_button_set_property (GObject *object,
guint property_id,
const GValue *value,
@@ -124,6 +148,14 @@ online_button_init (EOnlineButton *button)
gtk_container_add (GTK_CONTAINER (button), widget);
button->priv->image = g_object_ref (widget);
gtk_widget_show (widget);
+
+ g_signal_connect (
+ button, "notify::online",
+ G_CALLBACK (online_button_update_tooltip), NULL);
+
+ g_signal_connect (
+ button, "notify::sensitive",
+ G_CALLBACK (online_button_update_tooltip), NULL);
}
GType
diff --git a/widgets/misc/e-paned.c b/widgets/misc/e-paned.c
new file mode 100644
index 0000000000..51f8dbfa1c
--- /dev/null
+++ b/widgets/misc/e-paned.c
@@ -0,0 +1,310 @@
+/*
+ * e-paned.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-paned.h"
+
+#include <config.h>
+#include <glib/gi18n-lib.h>
+
+#define E_PANED_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), E_TYPE_PANED, EPanedPrivate))
+
+struct _EPanedPrivate {
+ gint hposition;
+ gint vposition;
+
+ guint sync_position : 1;
+};
+
+enum {
+ PROP_0,
+ PROP_HPOSITION,
+ PROP_VPOSITION
+};
+
+static gpointer parent_class;
+
+static void
+paned_notify_orientation_cb (EPaned *paned)
+{
+ /* Ignore the next "notify::position" emission. */
+ paned->priv->sync_position = TRUE;
+ gtk_widget_queue_resize (GTK_WIDGET (paned));
+}
+
+static void
+paned_notify_position_cb (EPaned *paned)
+{
+ GtkAllocation *allocation;
+ GtkOrientable *orientable;
+ GtkOrientation orientation;
+ gint position;
+
+ if (paned->priv->sync_position)
+ return;
+
+ orientable = GTK_ORIENTABLE (paned);
+ orientation = gtk_orientable_get_orientation (orientable);
+
+ allocation = &GTK_WIDGET (paned)->allocation;
+ position = gtk_paned_get_position (GTK_PANED (paned));
+
+ if (orientation == GTK_ORIENTATION_HORIZONTAL) {
+ position = MAX (0, allocation->width - position);
+ e_paned_set_hposition (paned, position);
+ } else {
+ position = MAX (0, allocation->height - position);
+ e_paned_set_vposition (paned, position);
+ }
+}
+
+static void
+paned_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_HPOSITION:
+ e_paned_set_hposition (
+ E_PANED (object),
+ g_value_get_int (value));
+ return;
+
+ case PROP_VPOSITION:
+ e_paned_set_vposition (
+ E_PANED (object),
+ g_value_get_int (value));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+paned_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_HPOSITION:
+ g_value_set_int (
+ value, e_paned_get_hposition (
+ E_PANED (object)));
+ return;
+
+ case PROP_VPOSITION:
+ g_value_set_int (
+ value, e_paned_get_vposition (
+ E_PANED (object)));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+paned_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ EPaned *paned = E_PANED (widget);
+ GtkOrientable *orientable;
+ GtkOrientation orientation;
+ gint allocated;
+ gint position;
+
+ /* Chain up to parent's size_allocate() method. */
+ GTK_WIDGET_CLASS (parent_class)->size_allocate (widget, allocation);
+
+ if (!paned->priv->sync_position)
+ return;
+
+ orientable = GTK_ORIENTABLE (paned);
+ orientation = gtk_orientable_get_orientation (orientable);
+
+ if (orientation == GTK_ORIENTATION_HORIZONTAL) {
+ allocated = allocation->width;
+ position = e_paned_get_hposition (paned);
+ } else {
+ allocated = allocation->height;
+ position = e_paned_get_vposition (paned);
+ }
+
+ position = MAX (0, allocated - position);
+ gtk_paned_set_position (GTK_PANED (paned), position);
+
+ paned->priv->sync_position = FALSE;
+}
+
+static void
+paned_class_init (EPanedClass *class)
+{
+ GObjectClass *object_class;
+ GtkWidgetClass *widget_class;
+
+ parent_class = g_type_class_peek_parent (class);
+ g_type_class_add_private (class, sizeof (EPanedPrivate));
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->set_property = paned_set_property;
+ object_class->get_property = paned_get_property;
+
+ widget_class = GTK_WIDGET_CLASS (class);
+ widget_class->size_allocate = paned_size_allocate;
+
+ g_object_class_install_property (
+ object_class,
+ PROP_HPOSITION,
+ g_param_spec_int (
+ "hposition",
+ _("Horizontal Position"),
+ _("Pane position when oriented horizontally"),
+ G_MININT,
+ G_MAXINT,
+ 0,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_VPOSITION,
+ g_param_spec_int (
+ "vposition",
+ _("Vertical Position"),
+ _("Pane position when oriented vertically"),
+ G_MININT,
+ G_MAXINT,
+ 0,
+ G_PARAM_READWRITE));
+}
+
+static void
+paned_init (EPaned *paned)
+{
+ paned->priv = E_PANED_GET_PRIVATE (paned);
+
+ g_signal_connect (
+ paned, "notify::orientation",
+ G_CALLBACK (paned_notify_orientation_cb), NULL);
+
+ g_signal_connect (
+ paned, "notify::position",
+ G_CALLBACK (paned_notify_position_cb), NULL);
+}
+
+GType
+e_paned_get_type (void)
+{
+ static GType type = 0;
+
+ if (G_UNLIKELY (type == 0)) {
+ static const GTypeInfo type_info = {
+ sizeof (EPanedClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) paned_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+ sizeof (EPaned),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) paned_init,
+ NULL /* value_table */
+ };
+
+ type = g_type_register_static (
+ GTK_TYPE_PANED, "EPaned", &type_info, 0);
+ }
+
+ return type;
+}
+
+GtkWidget *
+e_paned_new (GtkOrientation orientation)
+{
+ return g_object_new (E_TYPE_PANED, "orientation", orientation, NULL);
+}
+
+gint
+e_paned_get_hposition (EPaned *paned)
+{
+ g_return_val_if_fail (E_IS_PANED (paned), 0);
+
+ return paned->priv->hposition;
+}
+
+void
+e_paned_set_hposition (EPaned *paned,
+ gint hposition)
+{
+ GtkOrientable *orientable;
+ GtkOrientation orientation;
+
+ g_return_if_fail (E_IS_PANED (paned));
+
+ if (hposition == paned->priv->hposition)
+ return;
+
+ paned->priv->hposition = hposition;
+
+ g_object_notify (G_OBJECT (paned), "hposition");
+
+ orientable = GTK_ORIENTABLE (paned);
+ orientation = gtk_orientable_get_orientation (orientable);
+
+ if (orientation == GTK_ORIENTATION_HORIZONTAL) {
+ paned->priv->sync_position = TRUE;
+ gtk_widget_queue_resize (GTK_WIDGET (paned));
+ }
+}
+
+gint
+e_paned_get_vposition (EPaned *paned)
+{
+ g_return_val_if_fail (E_IS_PANED (paned), 0);
+
+ return paned->priv->vposition;
+}
+
+void
+e_paned_set_vposition (EPaned *paned,
+ gint vposition)
+{
+ GtkOrientable *orientable;
+ GtkOrientation orientation;
+
+ g_return_if_fail (E_IS_PANED (paned));
+
+ if (vposition == paned->priv->vposition)
+ return;
+
+ paned->priv->vposition = vposition;
+
+ g_object_notify (G_OBJECT (paned), "vposition");
+
+ orientable = GTK_ORIENTABLE (paned);
+ orientation = gtk_orientable_get_orientation (orientable);
+
+ if (orientation == GTK_ORIENTATION_VERTICAL) {
+ paned->priv->sync_position = TRUE;
+ gtk_widget_queue_resize (GTK_WIDGET (paned));
+ }
+}
diff --git a/widgets/misc/e-paned.h b/widgets/misc/e-paned.h
new file mode 100644
index 0000000000..8bd1c22024
--- /dev/null
+++ b/widgets/misc/e-paned.h
@@ -0,0 +1,72 @@
+/*
+ * e-paned.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_PANED_H
+#define E_PANED_H
+
+#include <gtk/gtk.h>
+
+/* Standard GObject macros */
+#define E_TYPE_PANED \
+ (e_paned_get_type ())
+#define E_PANED(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_PANED, EPaned))
+#define E_PANED_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_PANED, EPanedClass))
+#define E_IS_PANED(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_PANED))
+#define E_IS_PANED_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_PANED))
+#define E_PANED_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_PANED, EPanedClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EPaned EPaned;
+typedef struct _EPanedClass EPanedClass;
+typedef struct _EPanedPrivate EPanedPrivate;
+
+struct _EPaned {
+ GtkPaned parent;
+ EPanedPrivate *priv;
+};
+
+struct _EPanedClass {
+ GtkPanedClass parent_class;
+};
+
+GType e_paned_get_type (void);
+GtkWidget * e_paned_new (GtkOrientation orientation);
+gint e_paned_get_hposition (EPaned *paned);
+void e_paned_set_hposition (EPaned *paned,
+ gint hposition);
+gint e_paned_get_vposition (EPaned *paned);
+void e_paned_set_vposition (EPaned *paned,
+ gint vposition);
+
+G_END_DECLS
+
+#endif /* E_PANED_H */
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-reflow-model.c b/widgets/misc/e-reflow-model.c
deleted file mode 100644
index 1eaccdad09..0000000000
--- a/widgets/misc/e-reflow-model.c
+++ /dev/null
@@ -1,348 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- *
- * 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 <config.h>
-
-#include "e-util/e-util.h"
-
-#include "e-reflow-model.h"
-
-G_DEFINE_TYPE (EReflowModel, e_reflow_model, G_TYPE_OBJECT)
-
-#define d(x)
-
-d(static gint depth = 0;)
-
-enum {
- MODEL_CHANGED,
- COMPARISON_CHANGED,
- MODEL_ITEMS_INSERTED,
- MODEL_ITEM_CHANGED,
- MODEL_ITEM_REMOVED,
- LAST_SIGNAL
-};
-
-static guint e_reflow_model_signals [LAST_SIGNAL] = { 0, };
-
-/**
- * e_reflow_model_set_width:
- * @e_reflow_model: The e-reflow-model to operate on
- * @width: The new value for the width of each item.
- */
-void
-e_reflow_model_set_width (EReflowModel *e_reflow_model, gint width)
-{
- g_return_if_fail (e_reflow_model != NULL);
- g_return_if_fail (E_IS_REFLOW_MODEL (e_reflow_model));
-
- E_REFLOW_MODEL_GET_CLASS (e_reflow_model)->set_width (e_reflow_model, width);
-}
-
-/**
- * e_reflow_model_count:
- * @e_reflow_model: The e-reflow-model to operate on
- *
- * Returns: the number of items in the reflow model.
- */
-gint
-e_reflow_model_count (EReflowModel *e_reflow_model)
-{
- g_return_val_if_fail (e_reflow_model != NULL, 0);
- g_return_val_if_fail (E_IS_REFLOW_MODEL (e_reflow_model), 0);
-
- return E_REFLOW_MODEL_GET_CLASS (e_reflow_model)->count (e_reflow_model);
-}
-
-/**
- * e_reflow_model_height:
- * @e_reflow_model: The e-reflow-model to operate on
- * @n: The item number to get the height of.
- * @parent: The parent GnomeCanvasItem.
- *
- * Returns: the height of the nth item.
- */
-gint
-e_reflow_model_height (EReflowModel *e_reflow_model, gint n, GnomeCanvasGroup *parent)
-{
- g_return_val_if_fail (e_reflow_model != NULL, 0);
- g_return_val_if_fail (E_IS_REFLOW_MODEL (e_reflow_model), 0);
-
- return E_REFLOW_MODEL_GET_CLASS (e_reflow_model)->height (e_reflow_model, n, parent);
-}
-
-/**
- * e_reflow_model_incarnate:
- * @e_reflow_model: The e-reflow-model to operate on
- * @n: The item to create.
- * @parent: The parent GnomeCanvasItem to create a child of.
- *
- * Create a GnomeCanvasItem to represent the nth piece of data.
- *
- * Returns: the new GnomeCanvasItem.
- */
-GnomeCanvasItem *
-e_reflow_model_incarnate (EReflowModel *e_reflow_model, gint n, GnomeCanvasGroup *parent)
-{
- g_return_val_if_fail (e_reflow_model != NULL, NULL);
- g_return_val_if_fail (E_IS_REFLOW_MODEL (e_reflow_model), NULL);
-
- return E_REFLOW_MODEL_GET_CLASS (e_reflow_model)->incarnate (e_reflow_model, n, parent);
-}
-
-/**
- * e_reflow_model_compare:
- * @e_reflow_model: The e-reflow-model to operate on
- * @n1: The first item to compare
- * @n2: The second item to compare
- *
- * Compares item n1 and item n2 to see which should come first.
- *
- * Returns: strcmp like semantics for the comparison value.
- */
-gint
-e_reflow_model_compare (EReflowModel *e_reflow_model, gint n1, gint n2)
-{
-#if 0
- g_return_val_if_fail (e_reflow_model != NULL, 0);
- g_return_val_if_fail (E_IS_REFLOW_MODEL (e_reflow_model), 0);
-#endif
-
- return E_REFLOW_MODEL_GET_CLASS (e_reflow_model)->compare (e_reflow_model, n1, n2);
-}
-
-/**
- * e_reflow_model_reincarnate:
- * @e_reflow_model: The e-reflow-model to operate on
- * @n: The item to create.
- * @item: The item to reuse.
- *
- * Update item to represent the nth piece of data.
- */
-void
-e_reflow_model_reincarnate (EReflowModel *e_reflow_model, gint n, GnomeCanvasItem *item)
-{
- g_return_if_fail (e_reflow_model != NULL);
- g_return_if_fail (E_IS_REFLOW_MODEL (e_reflow_model));
-
- E_REFLOW_MODEL_GET_CLASS (e_reflow_model)->reincarnate (e_reflow_model, n, item);
-}
-
-static void
-e_reflow_model_class_init (EReflowModelClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
- e_reflow_model_signals [MODEL_CHANGED] =
- g_signal_new ("model_changed",
- G_OBJECT_CLASS_TYPE (object_class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (EReflowModelClass, model_changed),
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
-
- e_reflow_model_signals [COMPARISON_CHANGED] =
- g_signal_new ("comparison_changed",
- G_OBJECT_CLASS_TYPE (object_class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (EReflowModelClass, comparison_changed),
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
-
- e_reflow_model_signals [MODEL_ITEMS_INSERTED] =
- g_signal_new ("model_items_inserted",
- G_OBJECT_CLASS_TYPE (object_class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (EReflowModelClass, model_items_inserted),
- NULL, NULL,
- e_marshal_NONE__INT_INT,
- G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_INT);
-
- e_reflow_model_signals [MODEL_ITEM_CHANGED] =
- g_signal_new ("model_item_changed",
- G_OBJECT_CLASS_TYPE (object_class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (EReflowModelClass, model_item_changed),
- NULL, NULL,
- g_cclosure_marshal_VOID__INT,
- G_TYPE_NONE, 1, G_TYPE_INT);
-
- e_reflow_model_signals [MODEL_ITEM_REMOVED] =
- g_signal_new ("model_item_removed",
- G_OBJECT_CLASS_TYPE (object_class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (EReflowModelClass, model_item_removed),
- NULL, NULL,
- g_cclosure_marshal_VOID__INT,
- G_TYPE_NONE, 1, G_TYPE_INT);
-
- klass->set_width = NULL;
- klass->count = NULL;
- klass->height = NULL;
- klass->incarnate = NULL;
- klass->reincarnate = NULL;
-
- klass->model_changed = NULL;
- klass->comparison_changed = NULL;
- klass->model_items_inserted = NULL;
- klass->model_item_removed = NULL;
- klass->model_item_changed = NULL;
-}
-
-static void
-e_reflow_model_init (EReflowModel *e_reflow_model)
-{
-}
-
-#if d(!)0
-static void
-print_tabs (void)
-{
- gint i;
- for (i = 0; i < depth; i++)
- g_print("\t");
-}
-#endif
-
-/**
- * e_reflow_model_changed:
- * @e_reflow_model: the reflow model to notify of the change
- *
- * Use this function to notify any views of this reflow model that
- * the contents of the reflow model have changed. This will emit
- * the signal "model_changed" on the @e_reflow_model object.
- *
- * It is preferable to use the e_reflow_model_item_changed() signal to
- * notify of smaller changes than to invalidate the entire model, as
- * the views might have ways of caching the information they render
- * from the model.
- */
-void
-e_reflow_model_changed (EReflowModel *e_reflow_model)
-{
- g_return_if_fail (e_reflow_model != NULL);
- g_return_if_fail (E_IS_REFLOW_MODEL (e_reflow_model));
-
- d(print_tabs());
- d(g_print("Emitting model_changed on model 0x%p.\n", e_reflow_model));
- d(depth++);
- g_signal_emit (e_reflow_model,
- e_reflow_model_signals [MODEL_CHANGED], 0);
- d(depth--);
-}
-
-/**
- * e_reflow_model_comparison_changed:
- * @e_reflow_model: the reflow model to notify of the change
- *
- * Use this function to notify any views of this reflow model that the
- * sorting has changed. The actual contents of the items hasn't, so
- * there's no need to re-query the model for the heights of the
- * individual items.
- */
-void
-e_reflow_model_comparison_changed (EReflowModel *e_reflow_model)
-{
- g_return_if_fail (e_reflow_model != NULL);
- g_return_if_fail (E_IS_REFLOW_MODEL (e_reflow_model));
-
- d(print_tabs());
- d(g_print("Emitting comparison_changed on model 0x%p.\n", e_reflow_model));
- d(depth++);
- g_signal_emit (e_reflow_model,
- e_reflow_model_signals [COMPARISON_CHANGED], 0);
- d(depth--);
-}
-
-/**
- * e_reflow_model_items_inserted:
- * @e_reflow_model: The model changed.
- * @position: The position the items were insert in.
- * @count: The number of items inserted.
- *
- * Use this function to notify any views of the reflow model that a number of items have been inserted.
- **/
-void
-e_reflow_model_items_inserted (EReflowModel *e_reflow_model, gint position, gint count)
-{
- g_return_if_fail (e_reflow_model != NULL);
- g_return_if_fail (E_IS_REFLOW_MODEL (e_reflow_model));
-
- d(print_tabs());
- d(g_print("Emitting items_inserted on model 0x%p, position=%d, count=%d.\n", e_reflow_model, position, count));
- d(depth++);
- g_signal_emit (e_reflow_model,
- e_reflow_model_signals [MODEL_ITEMS_INSERTED], 0,
- position, count);
- d(depth--);
-}
-
-/**
- * e_reflow_model_item_removed:
- * @e_reflow_model: The model changed.
- * @n: The position from which the items were removed.
- *
- * Use this function to notify any views of the reflow model that an
- * item has been removed.
- **/
-void
-e_reflow_model_item_removed (EReflowModel *e_reflow_model,
- gint n)
-{
- g_return_if_fail (e_reflow_model != NULL);
- g_return_if_fail (E_IS_REFLOW_MODEL (e_reflow_model));
-
- d(print_tabs());
- d(g_print("Emitting item_removed on model 0x%p, n=%d.\n", e_reflow_model, n));
- d(depth++);
- g_signal_emit (e_reflow_model,
- e_reflow_model_signals [MODEL_ITEM_REMOVED], 0,
- n);
- d(depth--);
-}
-
-/**
- * e_reflow_model_item_changed:
- * @e_reflow_model: the reflow model to notify of the change
- * @item: the item that was changed in the model.
- *
- * Use this function to notify any views of the reflow model that the
- * contents of item @item have changed in model such that the height
- * has changed or the item needs to be reincarnated. This function
- * will emit the "model_item_changed" signal on the @e_reflow_model
- * object
- */
-void
-e_reflow_model_item_changed (EReflowModel *e_reflow_model, gint n)
-{
- g_return_if_fail (e_reflow_model != NULL);
- g_return_if_fail (E_IS_REFLOW_MODEL (e_reflow_model));
-
- d(print_tabs());
- d(g_print("Emitting item_changed on model 0x%p, n=%d.\n", e_reflow_model, n));
- d(depth++);
- g_signal_emit (e_reflow_model,
- e_reflow_model_signals [MODEL_ITEM_CHANGED], 0,
- n);
- d(depth--);
-}
diff --git a/widgets/misc/e-reflow-model.h b/widgets/misc/e-reflow-model.h
deleted file mode 100644
index ebbf3c1f75..0000000000
--- a/widgets/misc/e-reflow-model.h
+++ /dev/null
@@ -1,108 +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_REFLOW_MODEL_H_
-#define _E_REFLOW_MODEL_H_
-
-#include <glib-object.h>
-#include <libgnomecanvas/gnome-canvas.h>
-
-G_BEGIN_DECLS
-
-#define E_REFLOW_MODEL_TYPE (e_reflow_model_get_type ())
-#define E_REFLOW_MODEL(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), E_REFLOW_MODEL_TYPE, EReflowModel))
-#define E_REFLOW_MODEL_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), E_REFLOW_MODEL_TYPE, EReflowModelClass))
-#define E_IS_REFLOW_MODEL(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), E_REFLOW_MODEL_TYPE))
-#define E_IS_REFLOW_MODEL_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), E_REFLOW_MODEL_TYPE))
-#define E_REFLOW_MODEL_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), E_REFLOW_MODEL_TYPE, EReflowModelClass))
-
-typedef struct {
- GObject base;
-} EReflowModel;
-
-typedef struct {
- GObjectClass parent_class;
-
- /*
- * Virtual methods
- */
- void (*set_width) (EReflowModel *etm, gint width);
-
- gint (*count) (EReflowModel *etm);
- gint (*height) (EReflowModel *etm, gint n, GnomeCanvasGroup *parent);
- GnomeCanvasItem *(*incarnate) (EReflowModel *etm, gint n, GnomeCanvasGroup *parent);
- gint (*compare) (EReflowModel *etm, gint n1, gint n2);
- void (*reincarnate) (EReflowModel *etm, gint n, GnomeCanvasItem *item);
-
- /*
- * Signals
- */
-
- /*
- * These all come after the change has been made.
- * Major structural changes: model_changed
- * Changes to the sorting of elements: comparison_changed
- * Changes only in an item: item_changed
- */
- void (*model_changed) (EReflowModel *etm);
- void (*comparison_changed) (EReflowModel *etm);
- void (*model_items_inserted) (EReflowModel *etm, gint position, gint count);
- void (*model_item_removed) (EReflowModel *etm, gint position);
- void (*model_item_changed) (EReflowModel *etm, gint n);
-} EReflowModelClass;
-
-GType e_reflow_model_get_type (void);
-
-/**/
-void e_reflow_model_set_width (EReflowModel *e_reflow_model,
- gint width);
-gint e_reflow_model_count (EReflowModel *e_reflow_model);
-gint e_reflow_model_height (EReflowModel *e_reflow_model,
- gint n,
- GnomeCanvasGroup *parent);
-GnomeCanvasItem *e_reflow_model_incarnate (EReflowModel *e_reflow_model,
- gint n,
- GnomeCanvasGroup *parent);
-gint e_reflow_model_compare (EReflowModel *e_reflow_model,
- gint n1,
- gint n2);
-void e_reflow_model_reincarnate (EReflowModel *e_reflow_model,
- gint n,
- GnomeCanvasItem *item);
-
-/*
- * Routines for emitting signals on the e_reflow
- */
-void e_reflow_model_changed (EReflowModel *e_reflow_model);
-void e_reflow_model_comparison_changed (EReflowModel *e_reflow_model);
-void e_reflow_model_items_inserted (EReflowModel *e_reflow_model,
- gint position,
- gint count);
-void e_reflow_model_item_removed (EReflowModel *e_reflow_model,
- gint n);
-void e_reflow_model_item_changed (EReflowModel *e_reflow_model,
- gint n);
-
-G_END_DECLS
-
-#endif /* _E_REFLOW_MODEL_H_ */
diff --git a/widgets/misc/e-reflow.c b/widgets/misc/e-reflow.c
deleted file mode 100644
index 794e650ea1..0000000000
--- a/widgets/misc/e-reflow.c
+++ /dev/null
@@ -1,1531 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * 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 <config.h>
-
-#include <math.h>
-#include <string.h>
-
-#include <gdk/gdkkeysyms.h>
-#include <gtk/gtk.h>
-
-#include "text/e-text.h"
-#include <glib/gi18n.h>
-#include "e-util/e-util.h"
-#include "misc/e-unicode.h"
-
-#include "e-canvas.h"
-#include "e-canvas-utils.h"
-#include "e-reflow.h"
-#include "e-selection-model-simple.h"
-
-static gboolean e_reflow_event (GnomeCanvasItem *item, GdkEvent *event);
-static void e_reflow_realize (GnomeCanvasItem *item);
-static void e_reflow_unrealize (GnomeCanvasItem *item);
-static void e_reflow_draw (GnomeCanvasItem *item, GdkDrawable *drawable,
- gint x, gint y, gint width, gint height);
-static void e_reflow_update (GnomeCanvasItem *item, double affine[6], ArtSVP *clip_path, gint flags);
-static double e_reflow_point (GnomeCanvasItem *item, double x, double y, gint cx, gint cy, GnomeCanvasItem **actual_item);
-static void e_reflow_reflow (GnomeCanvasItem *item, gint flags);
-static void set_empty(EReflow *reflow);
-
-static void e_reflow_resize_children (GnomeCanvasItem *item);
-
-#define E_REFLOW_DIVIDER_WIDTH 2
-#define E_REFLOW_BORDER_WIDTH 7
-#define E_REFLOW_FULL_GUTTER (E_REFLOW_DIVIDER_WIDTH + E_REFLOW_BORDER_WIDTH * 2)
-
-G_DEFINE_TYPE (EReflow, e_reflow, GNOME_TYPE_CANVAS_GROUP)
-
-/* The arguments we take */
-enum {
- PROP_0,
- PROP_MINIMUM_WIDTH,
- PROP_WIDTH,
- PROP_HEIGHT,
- PROP_EMPTY_MESSAGE,
- PROP_MODEL,
- PROP_COLUMN_WIDTH
-};
-
-enum {
- SELECTION_EVENT,
- COLUMN_WIDTH_CHANGED,
- LAST_SIGNAL
-};
-
-static guint signals [LAST_SIGNAL] = {0, };
-
-static gint
-er_compare (gint i1, gint i2, gpointer user_data)
-{
- EReflow *reflow = user_data;
- return e_reflow_model_compare (reflow->model, i1, i2);
-}
-
-static gint
-e_reflow_pick_line (EReflow *reflow, double x)
-{
- x += E_REFLOW_BORDER_WIDTH + E_REFLOW_DIVIDER_WIDTH;
- x /= reflow->column_width + E_REFLOW_FULL_GUTTER;
- return x;
-}
-
-static gint
-er_find_item (EReflow *reflow, GnomeCanvasItem *item)
-{
- gint i;
- for (i = 0; i < reflow->count; i++) {
- if (reflow->items[i] == item)
- return i;
- }
- return -1;
-}
-
-static void
-e_reflow_resize_children (GnomeCanvasItem *item)
-{
- EReflow *reflow;
- gint i;
- gint count;
-
- reflow = E_REFLOW (item);
-
- count = reflow->count;
- for (i = 0; i < count; i++) {
- if (reflow->items[i])
- gnome_canvas_item_set(reflow->items[i],
- "width", (double) reflow->column_width,
- NULL);
- }
-}
-
-static inline void
-e_reflow_update_selection_row (EReflow *reflow, gint row)
-{
- if (reflow->items[row]) {
- g_object_set(reflow->items[row],
- "selected", e_selection_model_is_row_selected(E_SELECTION_MODEL(reflow->selection), row),
- NULL);
- } else if (e_selection_model_is_row_selected (E_SELECTION_MODEL (reflow->selection), row)) {
- reflow->items[row] = e_reflow_model_incarnate (reflow->model, row, GNOME_CANVAS_GROUP (reflow));
- g_object_set (reflow->items[row],
- "selected", e_selection_model_is_row_selected(E_SELECTION_MODEL(reflow->selection), row),
- "width", (double) reflow->column_width,
- NULL);
- }
-}
-
-static void
-e_reflow_update_selection (EReflow *reflow)
-{
- gint i;
- gint count;
-
- count = reflow->count;
- for (i = 0; i < count; i++) {
- e_reflow_update_selection_row (reflow, i);
- }
-}
-
-static void
-selection_changed (ESelectionModel *selection, EReflow *reflow)
-{
- e_reflow_update_selection (reflow);
-}
-
-static void
-selection_row_changed (ESelectionModel *selection, gint row, EReflow *reflow)
-{
- e_reflow_update_selection_row (reflow, row);
-}
-
-static gboolean
-do_adjustment (gpointer user_data)
-{
- gint row;
- GtkAdjustment *adj;
- gfloat value, min_value, max_value;
- EReflow *reflow = user_data;
-
- row = reflow->cursor_row;
- if (row == -1)
- return FALSE;
-
- adj = gtk_layout_get_hadjustment (GTK_LAYOUT (GNOME_CANVAS_ITEM (reflow)->canvas));
- value = adj->value;
-
- if ((!reflow->items) || (!reflow->items[row]))
- return TRUE;
- min_value = reflow->items[row]->x2 - adj->page_size;
- max_value = reflow->items[row]->x1;
-
- if (value < min_value)
- value = min_value;
-
- if (value > max_value)
- value = max_value;
-
- if (value != adj->value) {
- adj->value = value;
- gtk_adjustment_value_changed (adj);
- }
-
- reflow->do_adjustment_idle_id = 0;
-
- return FALSE;
-}
-
-static void
-cursor_changed (ESelectionModel *selection, gint row, gint col, EReflow *reflow)
-{
- gint count = reflow->count;
- gint old_cursor = reflow->cursor_row;
-
- if (old_cursor < count && old_cursor >= 0) {
- if (reflow->items[old_cursor]) {
- g_object_set (reflow->items[old_cursor],
- "has_cursor", FALSE,
- NULL);
- }
- }
-
- reflow->cursor_row = row;
-
- if (row < count && row >= 0) {
- if (reflow->items[row]) {
- g_object_set (reflow->items[row],
- "has_cursor", TRUE,
- NULL);
- } else {
- reflow->items[row] = e_reflow_model_incarnate (reflow->model, row, GNOME_CANVAS_GROUP (reflow));
- g_object_set (reflow->items[row],
- "has_cursor", TRUE,
- "width", (double) reflow->column_width,
- NULL);
- }
- }
-
- if (reflow->do_adjustment_idle_id == 0)
- reflow->do_adjustment_idle_id = g_idle_add (do_adjustment, reflow);
-
-}
-
-static void
-incarnate (EReflow *reflow)
-{
- gint column_width;
- gint first_column;
- gint last_column;
- gint first_cell;
- gint last_cell;
- gint i;
- GtkAdjustment *adjustment = gtk_layout_get_hadjustment (GTK_LAYOUT (GNOME_CANVAS_ITEM (reflow)->canvas));
-
- column_width = reflow->column_width;
-
- first_column = adjustment->value - 1 + E_REFLOW_BORDER_WIDTH;
- first_column /= column_width + E_REFLOW_FULL_GUTTER;
-
- last_column = adjustment->value + adjustment->page_size + 1 - E_REFLOW_BORDER_WIDTH - E_REFLOW_DIVIDER_WIDTH;
- last_column /= column_width + E_REFLOW_FULL_GUTTER;
- last_column ++;
-
- if (first_column >= 0 && first_column < reflow->column_count)
- first_cell = reflow->columns[first_column];
- else
- first_cell = 0;
-
- if (last_column >= 0 && last_column < reflow->column_count)
- last_cell = reflow->columns[last_column];
- else
- last_cell = reflow->count;
-
- for (i = first_cell; i < last_cell; i++) {
- gint unsorted = e_sorter_sorted_to_model (E_SORTER (reflow->sorter), i);
- if (reflow->items[unsorted] == NULL) {
- if (reflow->model) {
- reflow->items[unsorted] = e_reflow_model_incarnate (reflow->model, unsorted, GNOME_CANVAS_GROUP (reflow));
- g_object_set (reflow->items[unsorted],
- "selected", e_selection_model_is_row_selected(E_SELECTION_MODEL(reflow->selection), unsorted),
- "width", (double) reflow->column_width,
- NULL);
- }
- }
- }
- reflow->incarnate_idle_id = 0;
-}
-
-static gboolean
-invoke_incarnate (gpointer user_data)
-{
- EReflow *reflow = user_data;
- incarnate (reflow);
- return FALSE;
-}
-
-static void
-queue_incarnate (EReflow *reflow)
-{
- if (reflow->incarnate_idle_id == 0)
- reflow->incarnate_idle_id =
- g_idle_add_full (25, invoke_incarnate, reflow, NULL);
-}
-
-static void
-reflow_columns (EReflow *reflow)
-{
- GSList *list;
- gint count;
- gint start;
- gint i;
- gint column_count, column_start;
- double running_height;
-
- if (reflow->reflow_from_column <= 1) {
- start = 0;
- column_count = 1;
- column_start = 0;
- }
- else {
- /* we start one column before the earliest new entry,
- so we can handle the case where the new entry is
- inserted at the start of the column */
- column_start = reflow->reflow_from_column - 1;
- start = reflow->columns[column_start];
- column_count = column_start + 1;
- }
-
- list = NULL;
-
- running_height = E_REFLOW_BORDER_WIDTH;
-
- count = reflow->count - start;
- for (i = start; i < count; i++) {
- gint unsorted = e_sorter_sorted_to_model (E_SORTER (reflow->sorter), i);
- if (i != 0 && running_height + reflow->heights[unsorted] + E_REFLOW_BORDER_WIDTH > reflow->height) {
- list = g_slist_prepend (list, GINT_TO_POINTER(i));
- column_count ++;
- running_height = E_REFLOW_BORDER_WIDTH * 2 + reflow->heights[unsorted];
- } else
- running_height += reflow->heights[unsorted] + E_REFLOW_BORDER_WIDTH;
- }
-
- reflow->column_count = column_count;
- reflow->columns = g_renew (int, reflow->columns, column_count);
- column_count --;
-
- for (; column_count > column_start; column_count--) {
- GSList *to_free;
- reflow->columns[column_count] = GPOINTER_TO_INT(list->data);
- to_free = list;
- list = list->next;
- g_slist_free_1 (to_free);
- }
- reflow->columns[column_start] = start;
-
- queue_incarnate (reflow);
-
- reflow->need_reflow_columns = FALSE;
- reflow->reflow_from_column = -1;
-}
-
-static void
-item_changed (EReflowModel *model, gint i, EReflow *reflow)
-{
- if (i < 0 || i >= reflow->count)
- return;
-
- reflow->heights[i] = e_reflow_model_height (reflow->model, i, GNOME_CANVAS_GROUP (reflow));
- if (reflow->items[i] != NULL)
- e_reflow_model_reincarnate (model, i, reflow->items[i]);
- e_sorter_array_clean (reflow->sorter);
- reflow->reflow_from_column = -1;
- reflow->need_reflow_columns = TRUE;
- e_canvas_item_request_reflow(GNOME_CANVAS_ITEM (reflow));
-}
-
-static void
-item_removed (EReflowModel *model, gint i, EReflow *reflow)
-{
- gint c;
- gint sorted;
-
- if (i < 0 || i >= reflow->count)
- return;
-
- sorted = e_sorter_model_to_sorted (E_SORTER (reflow->sorter), i);
- for (c = reflow->column_count - 1; c >= 0; c--) {
- gint start_of_column = reflow->columns[c];
-
- if (start_of_column <= sorted) {
- if (reflow->reflow_from_column == -1
- || reflow->reflow_from_column > c) {
- reflow->reflow_from_column = c;
- }
- break;
- }
- }
-
- if (reflow->items[i])
- gtk_object_destroy (GTK_OBJECT (reflow->items[i]));
-
- memmove (reflow->heights + i, reflow->heights + i + 1, (reflow->count - i - 1) * sizeof (gint));
- memmove (reflow->items + i, reflow->items + i + 1, (reflow->count - i - 1) * sizeof (GnomeCanvasItem *));
-
- reflow->count --;
-
- reflow->heights [reflow->count] = 0;
- reflow->items [reflow->count] = NULL;
-
- reflow->need_reflow_columns = TRUE;
- set_empty (reflow);
- e_canvas_item_request_reflow(GNOME_CANVAS_ITEM (reflow));
-
- e_sorter_array_set_count (reflow->sorter, reflow->count);
-
- e_selection_model_simple_delete_rows (E_SELECTION_MODEL_SIMPLE (reflow->selection), i, 1);
-}
-
-static void
-items_inserted (EReflowModel *model, gint position, gint count, EReflow *reflow)
-{
- gint i, oldcount;
-
- if (position < 0 || position > reflow->count)
- return;
-
- oldcount = reflow->count;
-
- reflow->count += count;
-
- if (reflow->count > reflow->allocated_count) {
- while (reflow->count > reflow->allocated_count)
- reflow->allocated_count += 256;
- reflow->heights = g_renew (int, reflow->heights, reflow->allocated_count);
- reflow->items = g_renew (GnomeCanvasItem *, reflow->items, reflow->allocated_count);
- }
- memmove (reflow->heights + position + count, reflow->heights + position, (reflow->count - position - count) * sizeof (gint));
- memmove (reflow->items + position + count, reflow->items + position, (reflow->count - position - count) * sizeof (GnomeCanvasItem *));
- for (i = position; i < position + count; i++) {
- reflow->items[i] = NULL;
- reflow->heights[i] = e_reflow_model_height (reflow->model, i, GNOME_CANVAS_GROUP (reflow));
- }
-
- e_selection_model_simple_set_row_count (E_SELECTION_MODEL_SIMPLE (reflow->selection), reflow->count);
- if (position == oldcount)
- e_sorter_array_append (reflow->sorter, count);
- else
- e_sorter_array_set_count (reflow->sorter, reflow->count);
-
- for (i = position; i < position + count; i ++) {
- gint sorted = e_sorter_model_to_sorted (E_SORTER (reflow->sorter), i);
- gint c;
-
- for (c = reflow->column_count - 1; c >= 0; c--) {
- gint start_of_column = reflow->columns[c];
-
- if (start_of_column <= sorted) {
- if (reflow->reflow_from_column == -1
- || reflow->reflow_from_column > c) {
- reflow->reflow_from_column = c;
- }
- break;
- }
- }
- }
-
- reflow->need_reflow_columns = TRUE;
- set_empty (reflow);
- e_canvas_item_request_reflow(GNOME_CANVAS_ITEM (reflow));
-}
-
-static void
-model_changed (EReflowModel *model, EReflow *reflow)
-{
- gint i;
- gint count;
- gint oldcount;
-
- count = reflow->count;
- oldcount = count;
-
- for (i = 0; i < count; i++) {
- if (reflow->items[i])
- gtk_object_destroy (GTK_OBJECT (reflow->items[i]));
- }
- g_free (reflow->items);
- g_free (reflow->heights);
- reflow->count = e_reflow_model_count (model);
- reflow->allocated_count = reflow->count;
- reflow->items = g_new (GnomeCanvasItem *, reflow->count);
- reflow->heights = g_new (int, reflow->count);
-
- count = reflow->count;
- for (i = 0; i < count; i++) {
- reflow->items[i] = NULL;
- reflow->heights[i] = e_reflow_model_height (reflow->model, i, GNOME_CANVAS_GROUP (reflow));
- }
-
- e_selection_model_simple_set_row_count (E_SELECTION_MODEL_SIMPLE (reflow->selection), count);
- e_sorter_array_set_count (reflow->sorter, reflow->count);
-
- reflow->need_reflow_columns = TRUE;
- if (oldcount > reflow->count)
- reflow_columns (reflow);
- set_empty (reflow);
- e_canvas_item_request_reflow(GNOME_CANVAS_ITEM (reflow));
-}
-
-static void
-comparison_changed (EReflowModel *model, EReflow *reflow)
-{
- e_sorter_array_clean (reflow->sorter);
- reflow->reflow_from_column = -1;
- reflow->need_reflow_columns = TRUE;
- e_canvas_item_request_reflow(GNOME_CANVAS_ITEM (reflow));
-}
-
-static void
-set_empty(EReflow *reflow)
-{
- if (reflow->count == 0) {
- if (reflow->empty_text) {
- if (reflow->empty_message) {
- gnome_canvas_item_set(reflow->empty_text,
- "width", reflow->minimum_width,
- "text", reflow->empty_message,
- NULL);
- e_canvas_item_move_absolute(reflow->empty_text,
- reflow->minimum_width / 2,
- 0);
- } else {
- gtk_object_destroy(GTK_OBJECT(reflow->empty_text));
- reflow->empty_text = NULL;
- }
- } else {
- if (reflow->empty_message) {
- reflow->empty_text =
- gnome_canvas_item_new(GNOME_CANVAS_GROUP(reflow),
- e_text_get_type(),
- "anchor", GTK_ANCHOR_N,
- "width", reflow->minimum_width,
- "clip", TRUE,
- "use_ellipsis", TRUE,
- "justification", GTK_JUSTIFY_CENTER,
- "text", reflow->empty_message,
- "draw_background", FALSE,
- NULL);
- e_canvas_item_move_absolute(reflow->empty_text,
- reflow->minimum_width / 2,
- 0);
- }
- }
- } else {
- if (reflow->empty_text) {
- gtk_object_destroy(GTK_OBJECT(reflow->empty_text));
- reflow->empty_text = NULL;
- }
- }
-}
-
-static void
-disconnect_model (EReflow *reflow)
-{
- if (reflow->model == NULL)
- return;
-
- g_signal_handler_disconnect (reflow->model,
- reflow->model_changed_id);
- g_signal_handler_disconnect (reflow->model,
- reflow->comparison_changed_id);
- g_signal_handler_disconnect (reflow->model,
- reflow->model_items_inserted_id);
- g_signal_handler_disconnect (reflow->model,
- reflow->model_item_removed_id);
- g_signal_handler_disconnect (reflow->model,
- reflow->model_item_changed_id);
- g_object_unref (reflow->model);
-
- reflow->model_changed_id = 0;
- reflow->comparison_changed_id = 0;
- reflow->model_items_inserted_id = 0;
- reflow->model_item_removed_id = 0;
- reflow->model_item_changed_id = 0;
- reflow->model = NULL;
-}
-
-static void
-disconnect_selection (EReflow *reflow)
-{
- if (reflow->selection == NULL)
- return;
-
- g_signal_handler_disconnect (reflow->selection,
- reflow->selection_changed_id);
- g_signal_handler_disconnect (reflow->selection,
- reflow->selection_row_changed_id);
- g_signal_handler_disconnect (reflow->selection,
- reflow->cursor_changed_id);
- g_object_unref (reflow->selection);
-
- reflow->selection_changed_id = 0;
- reflow->selection_row_changed_id = 0;
- reflow->cursor_changed_id = 0;
- reflow->selection = NULL;
-}
-
-static void
-connect_model (EReflow *reflow, EReflowModel *model)
-{
- if (reflow->model != NULL)
- disconnect_model (reflow);
-
- if (model == NULL)
- return;
-
- reflow->model = model;
- g_object_ref (reflow->model);
- reflow->model_changed_id =
- g_signal_connect (reflow->model, "model_changed",
- G_CALLBACK (model_changed), reflow);
- reflow->comparison_changed_id =
- g_signal_connect (reflow->model, "comparison_changed",
- G_CALLBACK (comparison_changed), reflow);
- reflow->model_items_inserted_id =
- g_signal_connect (reflow->model, "model_items_inserted",
- G_CALLBACK (items_inserted), reflow);
- reflow->model_item_removed_id =
- g_signal_connect (reflow->model, "model_item_removed",
- G_CALLBACK (item_removed), reflow);
- reflow->model_item_changed_id =
- g_signal_connect (reflow->model, "model_item_changed",
- G_CALLBACK (item_changed), reflow);
- model_changed (model, reflow);
-}
-
-static void
-adjustment_changed (GtkAdjustment *adjustment, EReflow *reflow)
-{
- queue_incarnate (reflow);
-}
-
-static void
-disconnect_adjustment (EReflow *reflow)
-{
- if (reflow->adjustment == NULL)
- return;
-
- g_signal_handler_disconnect (reflow->adjustment,
- reflow->adjustment_changed_id);
- g_signal_handler_disconnect (reflow->adjustment,
- reflow->adjustment_value_changed_id);
-
- g_object_unref (reflow->adjustment);
-
- reflow->adjustment_changed_id = 0;
- reflow->adjustment_value_changed_id = 0;
- reflow->adjustment = NULL;
-}
-
-static void
-connect_adjustment (EReflow *reflow, GtkAdjustment *adjustment)
-{
- if (reflow->adjustment != NULL)
- disconnect_adjustment (reflow);
-
- if (adjustment == NULL)
- return;
-
- reflow->adjustment = adjustment;
- reflow->adjustment_changed_id =
- g_signal_connect (adjustment, "changed",
- G_CALLBACK (adjustment_changed), reflow);
- reflow->adjustment_value_changed_id =
- g_signal_connect (adjustment, "value_changed",
- G_CALLBACK (adjustment_changed), reflow);
- g_object_ref (adjustment);
-}
-
-#if 0
-static void
-set_scroll_adjustments (GtkLayout *layout, GtkAdjustment *hadj, GtkAdjustment *vadj, EReflow *reflow)
-{
- connect_adjustment (reflow, hadj);
-}
-
-static void
-connect_set_adjustment (EReflow *reflow)
-{
- reflow->set_scroll_adjustments_id =
- g_signal_connect (GNOME_CANVAS_ITEM (reflow)->canvas,
- "set_scroll_adjustments",
- G_CALLBACK (set_scroll_adjustments), reflow);
-}
-#endif
-
-static void
-disconnect_set_adjustment (EReflow *reflow)
-{
- if (reflow->set_scroll_adjustments_id != 0) {
- g_signal_handler_disconnect (GNOME_CANVAS_ITEM (reflow)->canvas,
- reflow->set_scroll_adjustments_id);
- reflow->set_scroll_adjustments_id = 0;
- }
-}
-
-static void
-column_width_changed (EReflow *reflow)
-{
- g_signal_emit (reflow, signals[COLUMN_WIDTH_CHANGED], 0, reflow->column_width);
-}
-
-
-
-/* Virtual functions */
-static void
-e_reflow_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
-{
- GnomeCanvasItem *item;
- EReflow *reflow;
-
- item = GNOME_CANVAS_ITEM (object);
- reflow = E_REFLOW (object);
-
- switch (prop_id) {
- case PROP_HEIGHT:
- reflow->height = g_value_get_double (value);
- reflow->need_reflow_columns = TRUE;
- e_canvas_item_request_reflow(item);
- break;
- case PROP_MINIMUM_WIDTH:
- reflow->minimum_width = g_value_get_double (value);
- if (GNOME_CANVAS_ITEM_REALIZED & GTK_OBJECT_FLAGS(object))
- set_empty(reflow);
- e_canvas_item_request_reflow(item);
- break;
- case PROP_EMPTY_MESSAGE:
- g_free(reflow->empty_message);
- reflow->empty_message = g_strdup(g_value_get_string (value));
- if (GNOME_CANVAS_ITEM_REALIZED & GTK_OBJECT_FLAGS(object))
- set_empty(reflow);
- break;
- case PROP_MODEL:
- connect_model (reflow, (EReflowModel *) g_value_get_object (value));
- break;
- case PROP_COLUMN_WIDTH:
- if (reflow->column_width != g_value_get_double (value)) {
- GtkAdjustment *adjustment = gtk_layout_get_hadjustment(GTK_LAYOUT(item->canvas));
- double old_width = reflow->column_width;
-
- reflow->column_width = g_value_get_double (value);
- adjustment->step_increment = (reflow->column_width + E_REFLOW_FULL_GUTTER) / 2;
- adjustment->page_increment = adjustment->page_size - adjustment->step_increment;
- gtk_adjustment_changed(adjustment);
- e_reflow_resize_children(item);
- e_canvas_item_request_reflow(item);
-
- reflow->need_column_resize = TRUE;
- gnome_canvas_item_request_update(item);
-
- if (old_width != reflow->column_width)
- column_width_changed (reflow);
- }
- break;
- }
-}
-
-static void
-e_reflow_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
-{
- EReflow *reflow;
-
- reflow = E_REFLOW (object);
-
- switch (prop_id) {
- case PROP_MINIMUM_WIDTH:
- g_value_set_double (value, reflow->minimum_width);
- break;
- case PROP_WIDTH:
- g_value_set_double (value, reflow->width);
- break;
- case PROP_HEIGHT:
- g_value_set_double (value, reflow->height);
- break;
- case PROP_EMPTY_MESSAGE:
- g_value_set_string (value, reflow->empty_message);
- break;
- case PROP_MODEL:
- g_value_set_object (value, reflow->model);
- break;
- case PROP_COLUMN_WIDTH:
- g_value_set_double (value, reflow->column_width);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-e_reflow_dispose (GObject *object)
-{
- EReflow *reflow = E_REFLOW(object);
-
- g_free (reflow->items);
- g_free (reflow->heights);
- g_free (reflow->columns);
-
- reflow->items = NULL;
- reflow->heights = NULL;
- reflow->columns = NULL;
- reflow->count = 0;
- reflow->allocated_count = 0;
-
- if (reflow->incarnate_idle_id)
- g_source_remove (reflow->incarnate_idle_id);
- reflow->incarnate_idle_id = 0;
-
- if (reflow->do_adjustment_idle_id)
- g_source_remove (reflow->do_adjustment_idle_id);
- reflow->do_adjustment_idle_id = 0;
-
- disconnect_model (reflow);
- disconnect_selection (reflow);
-
- g_free(reflow->empty_message);
- reflow->empty_message = NULL;
-
- if (reflow->sorter) {
- g_object_unref (reflow->sorter);
- reflow->sorter = NULL;
- }
-
- G_OBJECT_CLASS(e_reflow_parent_class)->dispose (object);
-}
-
-static void
-e_reflow_realize (GnomeCanvasItem *item)
-{
- EReflow *reflow;
- GtkAdjustment *adjustment;
- gint count;
- gint i;
-
- reflow = E_REFLOW (item);
-
- if (GNOME_CANVAS_ITEM_CLASS(e_reflow_parent_class)->realize)
- (* GNOME_CANVAS_ITEM_CLASS(e_reflow_parent_class)->realize) (item);
-
- reflow->arrow_cursor = gdk_cursor_new (GDK_SB_H_DOUBLE_ARROW);
- reflow->default_cursor = gdk_cursor_new (GDK_LEFT_PTR);
-
- count = reflow->count;
- for (i = 0; i < count; i++) {
- if (reflow->items[i])
- gnome_canvas_item_set(reflow->items[i],
- "width", reflow->column_width,
- NULL);
- }
-
- set_empty(reflow);
-
- reflow->need_reflow_columns = TRUE;
- e_canvas_item_request_reflow(item);
-
- adjustment = gtk_layout_get_hadjustment(GTK_LAYOUT(item->canvas));
-
-#if 0
- connect_set_adjustment (reflow);
-#endif
- connect_adjustment (reflow, adjustment);
-
- adjustment->step_increment = (reflow->column_width + E_REFLOW_FULL_GUTTER) / 2;
- adjustment->page_increment = adjustment->page_size - adjustment->step_increment;
- gtk_adjustment_changed(adjustment);
-
- if (!item->canvas->aa) {
- }
-}
-
-static void
-e_reflow_unrealize (GnomeCanvasItem *item)
-{
- EReflow *reflow;
-
- reflow = E_REFLOW (item);
-
- if (!item->canvas->aa) {
- }
-
- gdk_cursor_unref (reflow->arrow_cursor);
- gdk_cursor_unref (reflow->default_cursor);
- reflow->arrow_cursor = NULL;
- reflow->default_cursor = NULL;
-
- g_free (reflow->columns);
- reflow->columns = NULL;
-
- disconnect_set_adjustment (reflow);
- disconnect_adjustment (reflow);
-
- if (GNOME_CANVAS_ITEM_CLASS(e_reflow_parent_class)->unrealize)
- (* GNOME_CANVAS_ITEM_CLASS(e_reflow_parent_class)->unrealize) (item);
-}
-
-static gboolean
-e_reflow_event (GnomeCanvasItem *item, GdkEvent *event)
-{
- EReflow *reflow;
- gint return_val = FALSE;
-
- reflow = E_REFLOW (item);
-
- switch ( event->type )
- {
- case GDK_KEY_PRESS:
- return_val = e_selection_model_key_press(reflow->selection, (GdkEventKey *) event);
- break;
-#if 0
- if (event->key.keyval == GDK_Tab ||
- event->key.keyval == GDK_KP_Tab ||
- event->key.keyval == GDK_ISO_Left_Tab) {
- gint i;
- gint count;
- count = reflow->count;
- for (i = 0; i < count; i++) {
- gint unsorted = e_sorter_sorted_to_model (E_SORTER (reflow->sorter), i);
- GnomeCanvasItem *item = reflow->items[unsorted];
- EFocus has_focus;
- if (item) {
- g_object_get(item,
- "has_focus", &has_focus,
- NULL);
- if (has_focus) {
- if (event->key.state & GDK_SHIFT_MASK) {
- if (i == 0)
- return FALSE;
- i--;
- } else {
- if (i == count - 1)
- return FALSE;
- i++;
- }
-
- unsorted = e_sorter_sorted_to_model (E_SORTER (reflow->sorter), i);
- if (reflow->items[unsorted] == NULL) {
- reflow->items[unsorted] = e_reflow_model_incarnate (reflow->model, unsorted, GNOME_CANVAS_GROUP (reflow));
- }
-
- item = reflow->items[unsorted];
- gnome_canvas_item_set(item,
- "has_focus", (event->key.state & GDK_SHIFT_MASK) ? E_FOCUS_END : E_FOCUS_START,
- NULL);
- return TRUE;
- }
- }
- }
- }
-#endif
- case GDK_BUTTON_PRESS:
- switch (event->button.button)
- {
- case 1:
- {
- GdkEventButton *button = (GdkEventButton *) event;
- double n_x;
- n_x = button->x;
- n_x += E_REFLOW_BORDER_WIDTH + E_REFLOW_DIVIDER_WIDTH;
- n_x = fmod(n_x,(reflow->column_width + E_REFLOW_FULL_GUTTER));
-
- if ( button->y >= E_REFLOW_BORDER_WIDTH && button->y <= reflow->height - E_REFLOW_BORDER_WIDTH && n_x < E_REFLOW_FULL_GUTTER ) {
- /* don't allow to drag the first line*/
- if (e_reflow_pick_line(reflow, button->x) == 0)
- return TRUE;
- reflow->which_column_dragged = e_reflow_pick_line(reflow, button->x);
- reflow->start_x = reflow->which_column_dragged * (reflow->column_width + E_REFLOW_FULL_GUTTER) - E_REFLOW_DIVIDER_WIDTH / 2;
- reflow->temp_column_width = reflow->column_width;
- reflow->column_drag = TRUE;
-
- gnome_canvas_item_grab (item,
- GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK,
- reflow->arrow_cursor,
- button->time);
-
- reflow->previous_temp_column_width = -1;
- reflow->need_column_resize = TRUE;
- gnome_canvas_item_request_update(item);
- return TRUE;
- }
- }
- break;
- case 4:
- {
- GtkAdjustment *adjustment = gtk_layout_get_hadjustment(GTK_LAYOUT(item->canvas));
- gdouble new_value = adjustment->value;
- new_value -= adjustment->step_increment;
- gtk_adjustment_set_value(adjustment, new_value);
- }
- break;
- case 5:
- {
- GtkAdjustment *adjustment = gtk_layout_get_hadjustment(GTK_LAYOUT(item->canvas));
- gdouble new_value = adjustment->value;
- new_value += adjustment->step_increment;
- if ( new_value > adjustment->upper - adjustment->page_size )
- new_value = adjustment->upper - adjustment->page_size;
- gtk_adjustment_set_value(adjustment, new_value);
- }
- break;
- }
- break;
- case GDK_BUTTON_RELEASE:
- if (reflow->column_drag) {
- gdouble old_width = reflow->column_width;
- GdkEventButton *button = (GdkEventButton *) event;
- GtkAdjustment *adjustment = gtk_layout_get_hadjustment(GTK_LAYOUT(item->canvas));
- reflow->temp_column_width = reflow->column_width +
- (button->x - reflow->start_x)/(reflow->which_column_dragged - e_reflow_pick_line(reflow, adjustment->value));
- if ( reflow->temp_column_width < 50 )
- reflow->temp_column_width = 50;
- reflow->column_drag = FALSE;
- if ( old_width != reflow->temp_column_width ) {
- gtk_adjustment_set_value(adjustment, adjustment->value + e_reflow_pick_line(reflow, adjustment->value) * (reflow->temp_column_width - reflow->column_width));
- reflow->column_width = reflow->temp_column_width;
- adjustment->step_increment = (reflow->column_width + E_REFLOW_FULL_GUTTER) / 2;
- adjustment->page_increment = adjustment->page_size - adjustment->step_increment;
- gtk_adjustment_changed(adjustment);
- e_reflow_resize_children(item);
- e_canvas_item_request_reflow(item);
- gnome_canvas_request_redraw(item->canvas, 0, 0, reflow->width, reflow->height);
- column_width_changed (reflow);
- }
- reflow->need_column_resize = TRUE;
- gnome_canvas_item_request_update(item);
- gnome_canvas_item_ungrab (item, button->time);
- return TRUE;
- }
- break;
- case GDK_MOTION_NOTIFY:
- if (reflow->column_drag) {
- double old_width = reflow->temp_column_width;
- GdkEventMotion *motion = (GdkEventMotion *) event;
- GtkAdjustment *adjustment = gtk_layout_get_hadjustment(GTK_LAYOUT(item->canvas));
- reflow->temp_column_width = reflow->column_width +
- (motion->x - reflow->start_x)/(reflow->which_column_dragged - e_reflow_pick_line(reflow, adjustment->value));
- if (reflow->temp_column_width < 50)
- reflow->temp_column_width = 50;
- if (old_width != reflow->temp_column_width) {
- reflow->need_column_resize = TRUE;
- gnome_canvas_item_request_update(item);
- }
- return TRUE;
- } else {
- GdkEventMotion *motion = (GdkEventMotion *) event;
- double n_x;
-
- n_x = motion->x;
- n_x += E_REFLOW_BORDER_WIDTH + E_REFLOW_DIVIDER_WIDTH;
- n_x = fmod(n_x,(reflow->column_width + E_REFLOW_FULL_GUTTER));
-
- if ( motion->y >= E_REFLOW_BORDER_WIDTH && motion->y <= reflow->height - E_REFLOW_BORDER_WIDTH && n_x < E_REFLOW_FULL_GUTTER ) {
- if ( reflow->default_cursor_shown ) {
- gdk_window_set_cursor(GTK_WIDGET(item->canvas)->window, reflow->arrow_cursor);
- reflow->default_cursor_shown = FALSE;
- }
- } else
- if ( ! reflow->default_cursor_shown ) {
- gdk_window_set_cursor(GTK_WIDGET(item->canvas)->window, reflow->default_cursor);
- reflow->default_cursor_shown = TRUE;
- }
-
- }
- break;
- case GDK_ENTER_NOTIFY:
- if (!reflow->column_drag) {
- GdkEventCrossing *crossing = (GdkEventCrossing *) event;
- double n_x;
- n_x = crossing->x;
- n_x += E_REFLOW_BORDER_WIDTH + E_REFLOW_DIVIDER_WIDTH;
- n_x = fmod(n_x,(reflow->column_width + E_REFLOW_FULL_GUTTER));
-
- if ( crossing->y >= E_REFLOW_BORDER_WIDTH && crossing->y <= reflow->height - E_REFLOW_BORDER_WIDTH && n_x < E_REFLOW_FULL_GUTTER ) {
- if ( reflow->default_cursor_shown ) {
- gdk_window_set_cursor(GTK_WIDGET(item->canvas)->window, reflow->arrow_cursor);
- reflow->default_cursor_shown = FALSE;
- }
- }
- }
- break;
- case GDK_LEAVE_NOTIFY:
- if (!reflow->column_drag) {
- GdkEventCrossing *crossing = (GdkEventCrossing *) event;
- double n_x;
- n_x = crossing->x;
- n_x += E_REFLOW_BORDER_WIDTH + E_REFLOW_DIVIDER_WIDTH;
- n_x = fmod(n_x,(reflow->column_width + E_REFLOW_FULL_GUTTER));
- if ( !( crossing->y >= E_REFLOW_BORDER_WIDTH && crossing->y <= reflow->height - E_REFLOW_BORDER_WIDTH && n_x < E_REFLOW_FULL_GUTTER ) ) {
- if ( ! reflow->default_cursor_shown ) {
- gdk_window_set_cursor(GTK_WIDGET(item->canvas)->window, reflow->default_cursor);
- reflow->default_cursor_shown = TRUE;
- }
- }
- }
- break;
- default:
- break;
- }
- if (return_val)
- return return_val;
- else if (GNOME_CANVAS_ITEM_CLASS( e_reflow_parent_class )->event)
- return (* GNOME_CANVAS_ITEM_CLASS( e_reflow_parent_class )->event) (item, event);
- else
- return FALSE;
-}
-
-static void e_reflow_draw (GnomeCanvasItem *item, GdkDrawable *drawable,
- gint x, gint y, gint width, gint height)
-{
- gint x_rect, y_rect, width_rect, height_rect;
- gdouble running_width;
- EReflow *reflow = E_REFLOW(item);
- gint i;
- double column_width;
-
- if (GNOME_CANVAS_ITEM_CLASS(e_reflow_parent_class)->draw)
- GNOME_CANVAS_ITEM_CLASS(e_reflow_parent_class)->draw (item, drawable, x, y, width, height);
- column_width = reflow->column_width;
- running_width = E_REFLOW_BORDER_WIDTH + column_width + E_REFLOW_BORDER_WIDTH;
- x_rect = running_width;
- y_rect = E_REFLOW_BORDER_WIDTH;
- width_rect = E_REFLOW_DIVIDER_WIDTH;
- height_rect = reflow->height - (E_REFLOW_BORDER_WIDTH * 2);
-
- /* Compute first column to draw. */
- i = x;
- i /= column_width + E_REFLOW_FULL_GUTTER;
- running_width += i * (column_width + E_REFLOW_FULL_GUTTER);
-
- for (; i < reflow->column_count; i++) {
- if ( running_width > x + width )
- break;
- x_rect = running_width;
- gtk_paint_flat_box(GTK_WIDGET(item->canvas)->style,
- drawable,
- GTK_STATE_ACTIVE,
- GTK_SHADOW_NONE,
- NULL,
- GTK_WIDGET(item->canvas),
- "reflow",
- x_rect - x,
- y_rect - y,
- width_rect,
- height_rect);
- running_width += E_REFLOW_DIVIDER_WIDTH + E_REFLOW_BORDER_WIDTH + column_width + E_REFLOW_BORDER_WIDTH;
- }
- if (reflow->column_drag) {
- gint start_line = e_reflow_pick_line(reflow,
- gtk_layout_get_hadjustment(GTK_LAYOUT(item->canvas))->value);
- i = x - start_line * (column_width + E_REFLOW_FULL_GUTTER);
- running_width = start_line * (column_width + E_REFLOW_FULL_GUTTER);
- column_width = reflow->temp_column_width;
- running_width -= start_line * (column_width + E_REFLOW_FULL_GUTTER);
- i += start_line * (column_width + E_REFLOW_FULL_GUTTER);
- running_width += E_REFLOW_BORDER_WIDTH + column_width + E_REFLOW_BORDER_WIDTH;
- x_rect = running_width;
- y_rect = E_REFLOW_BORDER_WIDTH;
- width_rect = E_REFLOW_DIVIDER_WIDTH;
- height_rect = reflow->height - (E_REFLOW_BORDER_WIDTH * 2);
-
- /* Compute first column to draw. */
- i /= column_width + E_REFLOW_FULL_GUTTER;
- running_width += i * (column_width + E_REFLOW_FULL_GUTTER);
-
- for (; i < reflow->column_count; i++) {
- if ( running_width > x + width )
- break;
- x_rect = running_width;
- gdk_draw_rectangle(drawable,
- GTK_WIDGET(item->canvas)->style->fg_gc[GTK_STATE_NORMAL],
- TRUE,
- x_rect - x,
- y_rect - y,
- width_rect - 1,
- height_rect - 1);
- running_width += E_REFLOW_DIVIDER_WIDTH + E_REFLOW_BORDER_WIDTH + column_width + E_REFLOW_BORDER_WIDTH;
- }
- }
-}
-
-static void
-e_reflow_update (GnomeCanvasItem *item, double affine[6], ArtSVP *clip_path, gint flags)
-{
- EReflow *reflow;
- double x0, x1, y0, y1;
-
- reflow = E_REFLOW (item);
-
- if (GNOME_CANVAS_ITEM_CLASS(e_reflow_parent_class)->update)
- GNOME_CANVAS_ITEM_CLASS(e_reflow_parent_class)->update (item, affine, clip_path, flags);
-
- x0 = item->x1;
- y0 = item->y1;
- x1 = item->x2;
- y1 = item->y2;
- if ( x1 < x0 + reflow->width )
- x1 = x0 + reflow->width;
- if ( y1 < y0 + reflow->height )
- y1 = y0 + reflow->height;
- item->x2 = x1;
- item->y2 = y1;
-
- if (reflow->need_height_update) {
- x0 = item->x1;
- y0 = item->y1;
- x1 = item->x2;
- y1 = item->y2;
- if ( x0 > 0 )
- x0 = 0;
- if ( y0 > 0 )
- y0 = 0;
- if ( x1 < E_REFLOW(item)->width )
- x1 = E_REFLOW(item)->width;
- if ( x1 < E_REFLOW(item)->height )
- x1 = E_REFLOW(item)->height;
-
- gnome_canvas_request_redraw(item->canvas, x0, y0, x1, y1);
- reflow->need_height_update = FALSE;
- } else if (reflow->need_column_resize) {
- gint x_rect, y_rect, width_rect, height_rect;
- gint start_line = e_reflow_pick_line(reflow,
- gtk_layout_get_hadjustment(GTK_LAYOUT(item->canvas))->value);
- gdouble running_width;
- gint i;
- double column_width;
-
- if ( reflow->previous_temp_column_width != -1 ) {
- running_width = start_line * (reflow->column_width + E_REFLOW_FULL_GUTTER);
- column_width = reflow->previous_temp_column_width;
- running_width -= start_line * (column_width + E_REFLOW_FULL_GUTTER);
- running_width += E_REFLOW_BORDER_WIDTH + column_width + E_REFLOW_BORDER_WIDTH;
- y_rect = E_REFLOW_BORDER_WIDTH;
- width_rect = E_REFLOW_DIVIDER_WIDTH;
- height_rect = reflow->height - (E_REFLOW_BORDER_WIDTH * 2);
-
- for ( i = 0; i < reflow->column_count; i++) {
- x_rect = running_width;
- gnome_canvas_request_redraw(item->canvas, x_rect, y_rect, x_rect + width_rect, y_rect + height_rect);
- running_width += E_REFLOW_DIVIDER_WIDTH + E_REFLOW_BORDER_WIDTH + column_width + E_REFLOW_BORDER_WIDTH;
- }
- }
-
- if ( reflow->temp_column_width != -1 ) {
- running_width = start_line * (reflow->column_width + E_REFLOW_FULL_GUTTER);
- column_width = reflow->temp_column_width;
- running_width -= start_line * (column_width + E_REFLOW_FULL_GUTTER);
- running_width += E_REFLOW_BORDER_WIDTH + column_width + E_REFLOW_BORDER_WIDTH;
- y_rect = E_REFLOW_BORDER_WIDTH;
- width_rect = E_REFLOW_DIVIDER_WIDTH;
- height_rect = reflow->height - (E_REFLOW_BORDER_WIDTH * 2);
-
- for ( i = 0; i < reflow->column_count; i++) {
- x_rect = running_width;
- gnome_canvas_request_redraw(item->canvas, x_rect, y_rect, x_rect + width_rect, y_rect + height_rect);
- running_width += E_REFLOW_DIVIDER_WIDTH + E_REFLOW_BORDER_WIDTH + column_width + E_REFLOW_BORDER_WIDTH;
- }
- }
-
- reflow->previous_temp_column_width = reflow->temp_column_width;
- reflow->need_column_resize = FALSE;
- }
-}
-
-static double
-e_reflow_point (GnomeCanvasItem *item,
- double x, double y, gint cx, gint cy,
- GnomeCanvasItem **actual_item)
-{
- double distance = 1;
-
- *actual_item = NULL;
-
- if (GNOME_CANVAS_ITEM_CLASS(e_reflow_parent_class)->point)
- distance = GNOME_CANVAS_ITEM_CLASS(e_reflow_parent_class)->point (item, x, y, cx, cy, actual_item);
- if ((gint) (distance * item->canvas->pixels_per_unit + 0.5) <= item->canvas->close_enough && *actual_item)
- return distance;
-
- *actual_item = item;
- return 0;
-#if 0
- if (y >= E_REFLOW_BORDER_WIDTH && y <= reflow->height - E_REFLOW_BORDER_WIDTH) {
- gfloat n_x;
- n_x = x;
- n_x += E_REFLOW_BORDER_WIDTH + E_REFLOW_DIVIDER_WIDTH;
- n_x = fmod(n_x, (reflow->column_width + E_REFLOW_FULL_GUTTER));
- if (n_x < E_REFLOW_FULL_GUTTER) {
- *actual_item = item;
- return 0;
- }
- }
- return distance;
-#endif
-}
-
-static void
-e_reflow_reflow( GnomeCanvasItem *item, gint flags )
-{
- EReflow *reflow = E_REFLOW(item);
- gdouble old_width;
- gdouble running_width;
- gdouble running_height;
- gint next_column;
- gint i;
-
- if (! (GTK_OBJECT_FLAGS (reflow) & GNOME_CANVAS_ITEM_REALIZED))
- return;
-
- if (reflow->need_reflow_columns) {
- reflow_columns (reflow);
- }
-
- old_width = reflow->width;
-
- running_width = E_REFLOW_BORDER_WIDTH;
- running_height = E_REFLOW_BORDER_WIDTH;
-
- next_column = 1;
-
- for (i = 0; i < reflow->count; i++) {
- gint unsorted = e_sorter_sorted_to_model (E_SORTER (reflow->sorter), i);
- if (next_column < reflow->column_count && i == reflow->columns[next_column]) {
- running_height = E_REFLOW_BORDER_WIDTH;
- running_width += reflow->column_width + E_REFLOW_FULL_GUTTER;
- next_column ++;
- }
-
- if (unsorted >= 0 && reflow->items[unsorted]) {
- e_canvas_item_move_absolute(GNOME_CANVAS_ITEM(reflow->items[unsorted]),
- (double) running_width,
- (double) running_height);
- running_height += reflow->heights[unsorted] + E_REFLOW_BORDER_WIDTH;
- }
- }
- reflow->width = running_width + reflow->column_width + E_REFLOW_BORDER_WIDTH;
- if ( reflow->width < reflow->minimum_width )
- reflow->width = reflow->minimum_width;
- if (old_width != reflow->width)
- e_canvas_item_request_parent_reflow(item);
-}
-
-static gint
-e_reflow_selection_event_real (EReflow *reflow, GnomeCanvasItem *item, GdkEvent *event)
-{
- gint row;
- gint return_val = TRUE;
- switch (event->type) {
- case GDK_BUTTON_PRESS:
- switch (event->button.button) {
- case 1: /* Fall through. */
- case 2:
- row = er_find_item (reflow, item);
- if (event->button.button == 1) {
- reflow->maybe_did_something =
- e_selection_model_maybe_do_something(reflow->selection, row, 0, event->button.state);
- reflow->maybe_in_drag = TRUE;
- } else {
- e_selection_model_do_something(reflow->selection, row, 0, event->button.state);
- }
- break;
- case 3:
- row = er_find_item (reflow, item);
- e_selection_model_right_click_down(reflow->selection, row, 0, 0);
- break;
- default:
- return_val = FALSE;
- break;
- }
- break;
- case GDK_BUTTON_RELEASE:
- if (event->button.button == 1) {
- if (reflow->maybe_in_drag) {
- reflow->maybe_in_drag = FALSE;
- if (!reflow->maybe_did_something) {
- row = er_find_item (reflow, item);
- e_selection_model_do_something(reflow->selection, row, 0, event->button.state);
- }
- }
- }
- break;
- case GDK_KEY_PRESS:
- return_val = e_selection_model_key_press(reflow->selection, (GdkEventKey *) event);
- break;
- default:
- return_val = FALSE;
- break;
- }
-
- return return_val;
-}
-
-static void
-e_reflow_class_init (EReflowClass *klass)
-{
- GObjectClass *object_class;
- GnomeCanvasItemClass *item_class;
-
- object_class = (GObjectClass*) klass;
- item_class = (GnomeCanvasItemClass *) klass;
-
- object_class->set_property = e_reflow_set_property;
- object_class->get_property = e_reflow_get_property;
- object_class->dispose = e_reflow_dispose;
-
- /* GnomeCanvasItem method overrides */
- item_class->event = e_reflow_event;
- item_class->realize = e_reflow_realize;
- item_class->unrealize = e_reflow_unrealize;
- item_class->draw = e_reflow_draw;
- item_class->update = e_reflow_update;
- item_class->point = e_reflow_point;
-
- klass->selection_event = e_reflow_selection_event_real;
- klass->column_width_changed = NULL;
-
- g_object_class_install_property (object_class, PROP_MINIMUM_WIDTH,
- g_param_spec_double ("minimum_width",
- _( "Minimum width" ),
- _( "Minimum Width" ),
- 0.0, G_MAXDOUBLE, 0.0,
- G_PARAM_READWRITE));
-
- g_object_class_install_property (object_class, PROP_WIDTH,
- g_param_spec_double ("width",
- _( "Width" ),
- _( "Width" ),
- 0.0, G_MAXDOUBLE, 0.0,
- G_PARAM_READABLE));
-
- g_object_class_install_property (object_class, PROP_HEIGHT,
- g_param_spec_double ("height",
- _( "Height" ),
- _( "Height" ),
- 0.0, G_MAXDOUBLE, 0.0,
- G_PARAM_READWRITE));
-
- g_object_class_install_property (object_class, PROP_EMPTY_MESSAGE,
- g_param_spec_string ("empty_message",
- _( "Empty message" ),
- _( "Empty message" ),
- NULL,
- G_PARAM_READWRITE));
-
- g_object_class_install_property (object_class, PROP_MODEL,
- g_param_spec_object ("model",
- _( "Reflow model" ),
- _( "Reflow model" ),
- E_REFLOW_MODEL_TYPE,
- G_PARAM_READWRITE));
-
- g_object_class_install_property (object_class, PROP_COLUMN_WIDTH,
- g_param_spec_double ("column_width",
- _( "Column width" ),
- _( "Column width" ),
- 0.0, G_MAXDOUBLE, 150.0,
- G_PARAM_READWRITE));
-
- signals [SELECTION_EVENT] =
- g_signal_new ("selection_event",
- G_OBJECT_CLASS_TYPE (object_class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (EReflowClass, selection_event),
- NULL, NULL,
- e_marshal_INT__OBJECT_BOXED,
- G_TYPE_INT, 2, G_TYPE_OBJECT,
- GDK_TYPE_EVENT);
-
- signals [COLUMN_WIDTH_CHANGED] =
- g_signal_new ("column_width_changed",
- G_OBJECT_CLASS_TYPE (object_class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (EReflowClass, column_width_changed),
- NULL, NULL,
- g_cclosure_marshal_VOID__DOUBLE,
- G_TYPE_NONE, 1, G_TYPE_DOUBLE);
-}
-
-static void
-e_reflow_init (EReflow *reflow)
-{
- reflow->model = NULL;
- reflow->items = NULL;
- reflow->heights = NULL;
- reflow->count = 0;
-
- reflow->columns = NULL;
- reflow->column_count = 0;
-
- reflow->empty_text = NULL;
- reflow->empty_message = NULL;
-
- reflow->minimum_width = 10;
- reflow->width = 10;
- reflow->height = 10;
-
- reflow->column_width = 150;
-
- reflow->column_drag = FALSE;
-
- reflow->need_height_update = FALSE;
- reflow->need_column_resize = FALSE;
- reflow->need_reflow_columns = FALSE;
-
- reflow->maybe_did_something = FALSE;
- reflow->maybe_in_drag = FALSE;
-
- reflow->default_cursor_shown = TRUE;
- reflow->arrow_cursor = NULL;
- reflow->default_cursor = NULL;
-
- reflow->cursor_row = -1;
-
- reflow->incarnate_idle_id = 0;
- reflow->do_adjustment_idle_id = 0;
- reflow->set_scroll_adjustments_id = 0;
-
- reflow->selection = E_SELECTION_MODEL (e_selection_model_simple_new());
- reflow->sorter = e_sorter_array_new (er_compare, reflow);
-
- g_object_set (reflow->selection,
- "sorter", reflow->sorter,
- NULL);
-
- reflow->selection_changed_id =
- g_signal_connect(reflow->selection, "selection_changed",
- G_CALLBACK (selection_changed), reflow);
- reflow->selection_row_changed_id =
- g_signal_connect(reflow->selection, "selection_row_changed",
- G_CALLBACK (selection_row_changed), reflow);
- reflow->cursor_changed_id =
- g_signal_connect(reflow->selection, "cursor_changed",
- G_CALLBACK (cursor_changed), reflow);
-
- e_canvas_item_set_reflow_callback(GNOME_CANVAS_ITEM(reflow), e_reflow_reflow);
-}
diff --git a/widgets/misc/e-reflow.h b/widgets/misc/e-reflow.h
deleted file mode 100644
index ab27051d40..0000000000
--- a/widgets/misc/e-reflow.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:
- * Chris Lahey <clahey@ximian.com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-#ifndef __E_REFLOW_H__
-#define __E_REFLOW_H__
-
-#include <libgnomecanvas/gnome-canvas.h>
-#include <misc/e-reflow-model.h>
-#include <misc/e-selection-model.h>
-#include <e-util/e-sorter-array.h>
-
-G_BEGIN_DECLS
-
-/* EReflow - A canvas item container.
- *
- * The following arguments are available:
- *
- * name type read/write description
- * --------------------------------------------------------------------------------
- * minimum_width double RW minimum width of the reflow. width >= minimum_width
- * width double R width of the reflow
- * height double RW height of the reflow
- */
-
-#define E_REFLOW_TYPE (e_reflow_get_type ())
-#define E_REFLOW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_REFLOW_TYPE, EReflow))
-#define E_REFLOW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E_REFLOW_TYPE, EReflowClass))
-#define E_IS_REFLOW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_REFLOW_TYPE))
-#define E_IS_REFLOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), E_REFLOW_TYPE))
-
-typedef struct EReflowPriv EReflowPriv;
-
-typedef struct _EReflow EReflow;
-typedef struct _EReflowClass EReflowClass;
-
-struct _EReflow
-{
- GnomeCanvasGroup parent;
-
- /* item specific fields */
- EReflowModel *model;
- guint model_changed_id;
- guint comparison_changed_id;
- guint model_items_inserted_id;
- guint model_item_removed_id;
- guint model_item_changed_id;
-
- ESelectionModel *selection;
- guint selection_changed_id;
- guint selection_row_changed_id;
- guint cursor_changed_id;
- ESorterArray *sorter;
-
- GtkAdjustment *adjustment;
- guint adjustment_changed_id;
- guint adjustment_value_changed_id;
- guint set_scroll_adjustments_id;
-
- gint *heights;
- GnomeCanvasItem **items;
- gint count;
- gint allocated_count;
-
- gint *columns;
- gint column_count; /* Number of columnns */
-
- GnomeCanvasItem *empty_text;
- gchar *empty_message;
-
- double minimum_width;
- double width;
- double height;
-
- double column_width;
-
- gint incarnate_idle_id;
- gint do_adjustment_idle_id;
-
- /* These are all for when the column is being dragged. */
- gdouble start_x;
- gint which_column_dragged;
- double temp_column_width;
- double previous_temp_column_width;
-
- gint cursor_row;
-
- gint reflow_from_column;
-
- guint column_drag : 1;
-
- guint need_height_update : 1;
- guint need_column_resize : 1;
- guint need_reflow_columns : 1;
-
- guint default_cursor_shown : 1;
-
- guint maybe_did_something : 1;
- guint maybe_in_drag : 1;
- GdkCursor *arrow_cursor;
- GdkCursor *default_cursor;
-};
-
-struct _EReflowClass
-{
- GnomeCanvasGroupClass parent_class;
-
- gint (*selection_event) (EReflow *reflow, GnomeCanvasItem *item, GdkEvent *event);
- void (*column_width_changed) (EReflow *reflow, double width);
-};
-
-/*
- * To be added to a reflow, an item must have the argument "width" as
- * a Read/Write argument and "height" as a Read Only argument. It
- * should also do an ECanvas parent reflow request if its size
- * changes.
- */
-GType e_reflow_get_type (void);
-
-G_END_DECLS
-
-#endif /* __E_REFLOW_H__ */
diff --git a/widgets/misc/e-search-bar.c b/widgets/misc/e-search-bar.c
deleted file mode 100644
index 0a778531b7..0000000000
--- a/widgets/misc/e-search-bar.c
+++ /dev/null
@@ -1,1683 +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
-esb_paint_label (GtkWidget *label, gboolean active)
-{
- static gchar *sens = NULL;
- static gchar *insens = NULL;
- gchar *text;
-
- if (!label)
- return;
-
- if (!sens) {
- GtkStyle *default_style = gtk_widget_get_default_style ();
- sens = gdk_color_to_string (&default_style->text[GTK_STATE_SELECTED]);
- insens = gdk_color_to_string (&default_style->text[GTK_STATE_NORMAL]);
- }
- text = g_strdup_printf("<span foreground=\"%s\">%s</span>", active ? sens : insens, _("Search"));
- gtk_label_set_markup ((GtkLabel *)label, text);
- g_free(text);
-}
-
-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]));
- esb_paint_label (esb->label, TRUE);
- 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);
- esb_paint_label (esb->label, FALSE);
- if (!esb->lite)
- gtk_widget_set_sensitive (esb->clear_button, FALSE);
- }
-
- emit_search_activated (esb);
-}
-
-static void
-search_entry_press_cb (GtkWidget *w, GdkEventButton *event, ESearchBar *esb)
-{
- if (event->button == 1)
- entry_activated_cb (w, 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);
- esb_paint_label (esb->label, 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->label = NULL;
- if (search_bar->lite) {
- label = e_icon_entry_create_text (_("Search"));
- g_signal_connect (G_OBJECT (label), "button-press-event", G_CALLBACK(search_entry_press_cb), search_bar);
- e_icon_entry_pack_widget (E_ICON_ENTRY (search_bar->icon_entry), label, FALSE);
- search_bar->label = g_object_get_data ((GObject *)label, "lbl");
- esb_paint_label (search_bar->label, FALSE);
-
- label = e_icon_entry_create_separator ();
- e_icon_entry_pack_widget (E_ICON_ENTRY (search_bar->icon_entry), label, FALSE);
- }
-
- 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 5385ebf66a..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;
- GtkWidget *label;
-
- /* 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 abaa8eafe3..fe4e474729 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..699216784f
--- /dev/null
+++ b/widgets/misc/e-signature-editor.c
@@ -0,0 +1,509 @@
+/*
+ * 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) {
+ gchar *new_filename;
+
+ signature = e_signature_new ();
+ e_signature_set_name (signature, _("Unnamed"));
+ e_signature_set_is_script (signature, FALSE);
+ e_signature_set_is_html (signature, html);
+
+ /* FIXME Pass a GError and deal with it. */
+ new_filename = e_create_signature_file (NULL);
+ e_signature_set_filename (signature, new_filename);
+ g_free (new_filename);
+ } else {
+ signature = g_object_ref (editor->priv->signature);
+ e_signature_set_is_html (signature, html);
+ }
+
+ filename = e_signature_get_filename (signature);
+ 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 && !e_signature_is_equal (signature, same_name)) {
+ e_error_run (
+ GTK_WINDOW (editor),
+ "mail:signature-already-exists",
+ signature_name, NULL);
+ gtk_widget_grab_focus (entry);
+ g_free (signature_name);
+ return;
+ }
+
+ e_signature_set_name (signature, signature_name);
+ g_free (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;
+ gboolean is_html;
+ 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 = e_signature_get_filename (signature);
+ is_html = e_signature_get_is_html (signature);
+
+ if (is_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), is_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 = e_signature_get_name (signature);
+ 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..7e29f75cef
--- /dev/null
+++ b/widgets/misc/e-signature-manager.c
@@ -0,0 +1,753 @@
+/*
+ * 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 *name;
+ const gchar *filename;
+ const gchar *script_name;
+ gboolean success = FALSE;
+ gpointer parent;
+ gchar *path;
+
+ 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);
+
+ name = e_signature_get_name (signature);
+ filename = e_signature_get_filename (signature);
+
+ if (filename != NULL && name != NULL) {
+
+ script_file = g_file_new_for_path (filename);
+ script_name = 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));
+
+ path = g_file_get_path (script_file);
+ e_signature_set_name (signature, script_name);
+ e_signature_set_filename (signature, path);
+ g_free (path);
+
+ 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 ();
+ e_signature_set_is_script (signature, TRUE);
+ e_signature_set_is_html (signature, 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;
+ const 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 (e_signature_get_is_script (signature))
+ goto script;
+
+ filename = e_signature_get_filename (signature);
+ if (filename == NULL || *filename == '\0')
+ e_signature_set_filename (signature, _("Unnamed"));
+
+ 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;
+ const gchar *filename;
+ gboolean is_script;
+
+ 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;
+
+ filename = e_signature_get_filename (signature);
+ is_script = e_signature_get_is_script (signature);
+
+ if (filename != NULL && !is_script)
+ g_unlink (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..bbef65f39c
--- /dev/null
+++ b/widgets/misc/e-signature-preview.c
@@ -0,0 +1,349 @@
+/*
+ * 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;
+ const gchar *filename;
+ gboolean is_script;
+ 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;
+
+ filename = e_signature_get_filename (signature);
+ is_script = e_signature_get_is_script (signature);
+
+ if (is_script && !preview->priv->allow_scripts)
+ goto clear;
+
+ if (is_script)
+ content = e_run_signature_script (filename);
+ else
+ content = e_read_signature_file (signature, FALSE, NULL);
+
+ if (content == NULL || *content == '\0')
+ goto clear;
+
+ length = strlen (content);
+
+ if (e_signature_get_is_html (signature))
+ 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..5c931c8d93
--- /dev/null
+++ b/widgets/misc/e-signature-tree-view.c
@@ -0,0 +1,448 @@
+/*
+ * 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;
+ const gchar *name;
+
+ signature = iter->data;
+
+ /* Skip autogenerated signatures. */
+ if (e_signature_get_autogenerated (signature))
+ continue;
+
+ name = e_signature_get_name (signature);
+
+ gtk_list_store_append (store, &tree_iter);
+ gtk_list_store_set (
+ store, &tree_iter,
+ COLUMN_STRING, 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 e7fc15fe00..0000000000
--- a/widgets/misc/e-task-bar.c
+++ /dev/null
@@ -1,307 +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);
-}
-
-gint
-e_task_bar_get_num_children (ETaskBar *task_bar)
-{
- return g_list_length (GTK_BOX (task_bar->priv->hbox)->children);
-}
diff --git a/widgets/misc/e-task-bar.h b/widgets/misc/e-task-bar.h
deleted file mode 100644
index 19ed37a2e8..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);
-gint e_task_bar_get_num_children (ETaskBar *task_bar);
-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 7d583c3ffa..0000000000
--- a/widgets/misc/e-task-widget.c
+++ /dev/null
@@ -1,290 +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 737c5088eb..0000000000
--- a/widgets/misc/e-unicode.h
+++ /dev/null
@@ -1,111 +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..05d0dcce6b
--- /dev/null
+++ b/widgets/misc/ea-calendar-cell.c
@@ -0,0 +1,386 @@
+/*
+ *
+ * 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..9dcb83449c
--- /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 "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..b5271a9f8b
--- /dev/null
+++ b/widgets/misc/ea-calendar-item.h
@@ -0,0 +1,67 @@
+/*
+ * 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/ea-cell-table.c b/widgets/misc/ea-cell-table.c
new file mode 100644
index 0000000000..95ae59dea4
--- /dev/null
+++ b/widgets/misc/ea-cell-table.c
@@ -0,0 +1,202 @@
+/*
+ * 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 "ea-cell-table.h"
+
+EaCellTable *
+ea_cell_table_create (gint rows, gint columns, gboolean column_first)
+{
+ EaCellTable * cell_data;
+ gint index;
+
+ g_return_val_if_fail (((columns > 0) && (rows > 0)), NULL);
+
+ cell_data = g_new0 (EaCellTable, 1);
+
+ cell_data->column_first = column_first;
+ cell_data->columns = columns;
+ cell_data->rows = rows;
+
+ cell_data->column_labels = g_new0 (gchar *, columns);
+ for (index = columns -1; index >= 0; --index)
+ cell_data->column_labels [index] = NULL;
+
+ cell_data->row_labels = g_new0 (gchar *, rows);
+ for (index = rows -1; index >= 0; --index)
+ cell_data->row_labels [index] = NULL;
+
+ cell_data->cells = g_new0(gpointer, (columns * rows));
+ for (index = (columns * rows) -1; index >= 0; --index)
+ cell_data->cells [index] = NULL;
+ return cell_data;
+}
+
+void
+ea_cell_table_destroy (EaCellTable * cell_data)
+{
+ gint index;
+ g_return_if_fail (cell_data);
+
+ for (index = 0; index < cell_data->columns; ++index)
+ if (cell_data->column_labels [index])
+ g_free (cell_data->column_labels [index]);
+ g_free (cell_data->column_labels);
+
+ for (index = 0; index < cell_data->rows; ++index)
+ if (cell_data->row_labels [index])
+ g_free (cell_data->row_labels [index]);
+ g_free (cell_data->row_labels);
+
+ for (index = (cell_data->columns * cell_data->rows) -1;
+ index >= 0; --index)
+ if (cell_data->cells[index] &&
+ G_IS_OBJECT (cell_data->cells[index]))
+ g_object_unref (cell_data->cells[index]);
+
+ g_free (cell_data->cells);
+}
+
+gpointer
+ea_cell_table_get_cell (EaCellTable * cell_data,
+ gint row, gint column)
+{
+ gint index;
+
+ g_return_val_if_fail (cell_data, NULL);
+
+ index = ea_cell_table_get_index (cell_data, column, row);
+ if (index == -1)
+ return NULL;
+
+ return cell_data->cells[index];
+}
+
+gboolean
+ea_cell_table_set_cell (EaCellTable * cell_data,
+ gint row, gint column, gpointer cell)
+{
+ gint index;
+
+ g_return_val_if_fail (cell_data, FALSE);
+
+ index = ea_cell_table_get_index (cell_data, column, row);
+ if (index == -1)
+ return FALSE;
+
+ if (cell && G_IS_OBJECT(cell))
+ g_object_ref (cell);
+ if (cell_data->cells[index] &&
+ G_IS_OBJECT (cell_data->cells[index]))
+ g_object_unref (cell_data->cells[index]);
+ cell_data->cells[index] = cell;
+
+ return TRUE;
+}
+
+gpointer
+ea_cell_table_get_cell_at_index (EaCellTable * cell_data,
+ gint index)
+{
+ g_return_val_if_fail (cell_data, NULL);
+
+ if (index >=0 && index < (cell_data->columns * cell_data->rows))
+ return cell_data->cells [index];
+ return NULL;
+}
+
+gboolean
+ea_cell_table_set_cell_at_index (EaCellTable * cell_data,
+ gint index, gpointer cell)
+{
+ g_return_val_if_fail (cell_data, FALSE);
+
+ if (index < 0 || index >=cell_data->columns * cell_data->rows)
+ return FALSE;
+
+ if (cell && G_IS_OBJECT(cell))
+ g_object_ref (cell);
+ if (cell_data->cells[index] &&
+ G_IS_OBJECT (cell_data->cells[index]))
+ g_object_unref (cell_data->cells[index]);
+ cell_data->cells[index] = cell;
+
+ return TRUE;
+}
+
+G_CONST_RETURN gchar *
+ea_cell_table_get_column_label (EaCellTable * cell_data,
+ gint column)
+{
+ g_return_val_if_fail (cell_data, NULL);
+ g_return_val_if_fail ((column >= 0 && column < cell_data->columns), NULL);
+
+ return cell_data->column_labels[column];
+}
+
+void
+ea_cell_table_set_column_label (EaCellTable * cell_data,
+ gint column, const gchar *label)
+{
+ g_return_if_fail (cell_data);
+ g_return_if_fail ((column >= 0 && column < cell_data->columns));
+
+ if (cell_data->column_labels[column])
+ g_free (cell_data->column_labels[column]);
+ cell_data->column_labels[column] = g_strdup(label);
+}
+
+G_CONST_RETURN gchar *
+ea_cell_table_get_row_label (EaCellTable * cell_data,
+ gint row)
+{
+ g_return_val_if_fail (cell_data, NULL);
+ g_return_val_if_fail ((row >= 0 && row < cell_data->rows), NULL);
+
+ return cell_data->row_labels[row];
+}
+
+void
+ea_cell_table_set_row_label (EaCellTable * cell_data,
+ gint row, const gchar *label)
+{
+ g_return_if_fail (cell_data);
+ g_return_if_fail ((row >= 0 && row < cell_data->rows));
+
+ if (cell_data->row_labels[row])
+ g_free (cell_data->row_labels[row]);
+ cell_data->row_labels[row] = g_strdup(label);
+}
+
+gint
+ea_cell_table_get_index (EaCellTable *cell_data,
+ gint row, gint column)
+{
+ g_return_val_if_fail (cell_data, -1);
+ if (row < 0 || row >= cell_data->rows ||
+ column < 0 || column >= cell_data->columns)
+ return -1;
+
+ if (cell_data->column_first)
+ return column * cell_data->rows + row;
+ else
+ return row * cell_data->columns + column;
+}
diff --git a/widgets/misc/ea-cell-table.h b/widgets/misc/ea-cell-table.h
new file mode 100644
index 0000000000..353bbd0634
--- /dev/null
+++ b/widgets/misc/ea-cell-table.h
@@ -0,0 +1,60 @@
+/*
+ * 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)
+ *
+ */
+
+/* EaCellTable */
+
+#include <glib.h>
+#include <glib-object.h>
+
+struct _EaCellTable {
+ gint columns;
+ gint rows;
+ gboolean column_first; /* index order */
+ gchar **column_labels;
+ gchar **row_labels;
+ gpointer *cells;
+};
+
+typedef struct _EaCellTable EaCellTable;
+
+EaCellTable * ea_cell_table_create (gint rows, gint columns,
+ gboolean column_first);
+void ea_cell_table_destroy (EaCellTable * cell_data);
+gpointer ea_cell_table_get_cell (EaCellTable * cell_data,
+ gint row, gint column);
+gboolean ea_cell_table_set_cell (EaCellTable * cell_data,
+ gint row, gint column, gpointer cell);
+gpointer ea_cell_table_get_cell_at_index (EaCellTable * cell_data,
+ gint index);
+gboolean ea_cell_table_set_cell_at_index (EaCellTable * cell_data,
+ gint index, gpointer cell);
+
+G_CONST_RETURN gchar *
+ea_cell_table_get_column_label (EaCellTable * cell_data, gint column);
+void ea_cell_table_set_column_label (EaCellTable * cell_data,
+ gint column, const gchar *label);
+G_CONST_RETURN gchar *
+ea_cell_table_get_row_label (EaCellTable * cell_data, gint row);
+void ea_cell_table_set_row_label (EaCellTable * cell_data,
+ gint row, const gchar *label);
+gint ea_cell_table_get_index (EaCellTable *cell_data,
+ gint row, gint column);
diff --git a/widgets/misc/e-config-page.c b/widgets/misc/ea-widgets.c
index 922a26960c..9deede235e 100644
--- a/widgets/misc/e-config-page.c
+++ b/widgets/misc/ea-widgets.c
@@ -14,35 +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/misc/e-info-label.h b/widgets/misc/ea-widgets.h
index 977cc6ac4f..495222ae05 100644
--- a/widgets/misc/e-info-label.h
+++ b/widgets/misc/ea-widgets.h
@@ -15,40 +15,18 @@
*
*
* Authors:
- * Michael Zucchi <notzed@ximian.com>
+ * Bolian Yin <bolian.yin@sun.com>
*
* Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
*
*/
-#ifndef _E_INFO_LABEL_H
-#define _E_INFO_LABEL_H
+/* Evolution Accessibility
+*/
-#include <gtk/gtk.h>
+#ifndef _EA_WIDGETS_H__
+#define _EA_WIDGETS_H__
-G_BEGIN_DECLS
+void e_calendar_item_a11y_init (void);
-#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 */
+#endif /* _EA_WIDGETS_H__ */
diff --git a/widgets/misc/test-calendar.c b/widgets/misc/test-calendar.c
index c9cc8e7891..458d60f90a 100644
--- a/widgets/misc/test-calendar.c
+++ b/widgets/misc/test-calendar.c
@@ -114,7 +114,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 ();