diff options
Diffstat (limited to 'widgets/misc')
62 files changed, 8778 insertions, 6053 deletions
diff --git a/widgets/misc/Makefile.am b/widgets/misc/Makefile.am index 124c736d26..35d9289536 100644 --- a/widgets/misc/Makefile.am +++ b/widgets/misc/Makefile.am @@ -5,6 +5,7 @@ endif INCLUDES = \ -I$(top_srcdir) \ -I$(top_srcdir)/a11y/widgets \ + -I$(top_srcdir)/filter \ -I$(top_srcdir)/widgets \ -DEVOLUTION_IMAGES=\""$(imagesdir)"\" \ -DEVOLUTION_GLADEDIR=\""$(gladedir)"\" \ @@ -15,8 +16,7 @@ INCLUDES = \ privsolib_LTLIBRARIES = \ - libemiscwidgets.la \ - libefilterbar.la + libemiscwidgets.la widgetsincludedir = $(privincludedir)/misc @@ -33,7 +33,10 @@ glade_DATA = e-send-options.glade widgetsinclude_HEADERS = \ $(pilot_headers) \ e-account-combo-box.h \ - e-activity-handler.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 +47,60 @@ 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-camel-activity.h \ + e-canvas.h \ + e-canvas-background.h \ + e-canvas-utils.h \ + e-canvas-vbox.h \ e-cell-date-edit.h \ e-cell-percent.h \ e-cell-renderer-combo.h \ e-charset-picker.h \ + e-colors.h \ e-combo-cell-editable.h \ - e-config-page.h \ - e-combo-button.h \ + e-cursors.h \ e-dateedit.h \ - e-dropdown-button.h \ + e-file-activity.h \ + e-gui-utils.h \ + e-hsv-utils.h \ e-icon-entry.h \ e-image-chooser.h \ - e-info-label.h \ e-map.h \ - e-multi-config-dialog.h \ + e-menu-tool-button.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-background.h \ - e-canvas-utils.h \ - e-canvas-vbox.h \ - e-canvas.h \ - e-cursors.h \ - e-gui-utils.h \ - e-hsv-utils.h \ + e-popup-action.h \ e-popup-menu.h \ + e-preferences-window.h \ e-printable.h \ - e-reflow-model.h \ e-reflow.h \ + e-reflow-model.h \ + e-search-bar.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-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-unicode.h \ - e-colors.h + e-url-entry.h libemiscwidgets_la_SOURCES = \ $(widgetsinclude_HEADERS) \ $(pilot_sources) \ e-account-combo-box.c \ - e-activity-handler.c \ - e-calendar.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 \ @@ -102,76 +111,67 @@ libemiscwidgets_la_SOURCES = \ e-attachment-store.c \ e-attachment-tree-view.c \ e-attachment-view.c \ + e-calendar.c \ e-calendar-item.c \ + e-camel-activity.c \ + e-canvas.c \ + e-canvas-background.c \ + e-canvas-utils.c \ + e-canvas-vbox.c \ e-cell-date-edit.c \ e-cell-percent.c \ e-cell-renderer-combo.c \ e-charset-picker.c \ + e-colors.c \ e-combo-cell-editable.c \ - e-config-page.c \ - e-combo-button.c \ + e-cursors.c \ e-dateedit.c \ - e-dropdown-button.c \ + e-file-activity.c \ + e-gui-utils.c \ + e-hsv-utils.c \ e-icon-entry.c \ e-image-chooser.c \ - e-info-label.c \ e-map.c \ - e-multi-config-dialog.c \ + e-menu-tool-button.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-background.c \ - e-canvas-utils.c \ - e-canvas-vbox.c \ - e-canvas.c \ - e-cursors.c \ - e-gui-utils.c \ - e-hsv-utils.c \ + e-popup-action.c \ e-popup-menu.c \ + e-preferences-window.c \ e-printable.c \ e-reflow-model.c \ e-reflow.c \ + e-search-bar.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-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-unicode.c \ - e-colors.c - + e-url-entry.c libemiscwidgets_la_LDFLAGS = $(NO_UNDEFINED) -libemiscwidgets_la_LIBADD = $(top_builddir)/e-util/libeutil.la \ +libemiscwidgets_la_LIBADD = \ $(top_builddir)/e-util/libeutil.la \ + $(top_builddir)/filter/libfilter.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) \ $(ICONV_LIBS) -libefilterbar_la_SOURCES = \ - e-filter-bar.c \ - e-filter-bar.h - -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 @@ -181,6 +181,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 @@ -191,36 +192,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-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 e464353665..0000000000 --- a/widgets/misc/e-activity-handler.c +++ /dev/null @@ -1,700 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see <http://www.gnu.org/licenses/> - * - * - * Authors: - * Ettore Perazzoli <ettore@ximian.com> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "e-activity-handler.h" - -#include <gtk/gtk.h> -#include <glib/gi18n.h> -#include <gdk-pixbuf/gdk-pixbuf.h> - -#include <misc/e-popup-menu.h> - -#define ICON_SIZE 16 - - -struct _ActivityInfo { - char *component_id; - int error_type; - guint id; - char *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 char *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 unsigned int -get_new_activity_id (EActivityHandler *activity_handler) -{ - EActivityHandlerPrivate *priv; - - priv = activity_handler->priv; - - return priv->next_activity_id ++; -} - -static GList * -lookup_activity (GList *list, - guint activity_id, - int *order_number_return) -{ - GList *p; - int i; - - for (p = list, i = 0; p != NULL; p = p->next, i ++) { - ActivityInfo *activity_info; - - activity_info = (ActivityInfo *) p->data; - if (activity_info->id == activity_id) { - *order_number_return = i; - return p; - } - } - - *order_number_return = -1; - return NULL; -} - - -/* ETaskWidget actions. */ - -static int -task_widget_button_press_event_callback (GtkWidget *widget, - GdkEventButton *button_event, - void *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 char *component_id, - guint id, - const char *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 char *stock; - - stock = info->error_type ? icon_data [1] : icon_data[0]; - tool = e_task_widget_update_image (task_widget, (char *)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 (void *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, int 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 char *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; - int 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 char *component_id, - const char *information, - gboolean cancellable, - void (*cancel_func)(gpointer), - gpointer user_data) -{ - EActivityHandlerPrivate *priv; - ActivityInfo *activity_info; - unsigned int 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 char *component_id, - const char *information, - gboolean cancellable) -{ - EActivityHandlerPrivate *priv; - ActivityInfo *activity_info; - unsigned int 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; - int 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; - int i; - time_t now = time (NULL); - gboolean berror = FALSE; - - for (p = priv->activity_infos, i = 0; p != NULL; i++) { - ActivityInfo *info; - - info = (ActivityInfo *) p->data; - if (info->error) - berror = TRUE; - if (info->error && info->error_time && (now - info->error_time) > 5 ) { - /* Error older than wanted time. So cleanup */ - e_logger_log (priv->logger, info->error_type, g_object_get_data (info->error, "primary"), - g_object_get_data (info->error, "secondary")); - - if (GTK_IS_DIALOG (info->error)) - gtk_dialog_response (GTK_DIALOG (info->error), GTK_RESPONSE_CLOSE); - else - gtk_widget_destroy (info->error); - - node = p; - p = p->next; - - for (sp = priv->task_bars; sp != NULL; sp = sp->next) { - ETaskBar *task_bar; - - task_bar = E_TASK_BAR (sp->data); - e_task_bar_remove_task_from_id (task_bar, info->id); - } - activity_info_free (info); - priv->activity_infos = g_list_remove_link (priv->activity_infos, node); - - } else - p = p->next; - } - if (!berror) - priv->error_timer = 0; - return berror; -} - -guint -e_activity_handler_make_error (EActivityHandler *activity_handler, - const char *component_id, - int error_type, - GtkWidget *error) -{ - EActivityHandlerPrivate *priv; - ActivityInfo *activity_info; - unsigned int activity_id; - GSList *p; - char *information = g_object_get_data((GObject *) error, "primary"); - const char *img; - - priv = activity_handler->priv; - activity_id = get_new_activity_id (activity_handler); - - activity_info = activity_info_new (component_id, activity_id, information, TRUE); - activity_info->error = error; - activity_info->error_time = time (NULL); - activity_info->error_type = error_type; - - img = error_type ? icon_data[1] : icon_data[0]; - for (p = priv->task_bars; p != NULL; p = p->next) { - ETaskBar *task_bar; - ETaskWidget *task_widget; - GtkWidget *tool; - - task_bar = E_TASK_BAR (p->data); - task_widget = task_widget_new_from_activity_info (activity_info); - task_widget->id = activity_id; - e_task_bar_prepend_task (E_TASK_BAR (p->data), task_widget); - - tool = e_task_widget_update_image (task_widget, (char *)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; - int 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, (char *)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 char *information, - double progress) -{ - EActivityHandlerPrivate *priv = activity_handler->priv; - ActivityInfo *activity_info; - GList *p; - GSList *sp; - int 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; - int 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 5dc1820dd0..0000000000 --- a/widgets/misc/e-activity-handler.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: - * 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> - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#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 char *message); - -void e_activity_handler_unset_message (EActivityHandler *activity_handler); - -guint e_activity_handler_operation_started (EActivityHandler *activity_handler, - const char *component_id, - const char *information, - gboolean cancellable); -guint e_activity_handler_cancelable_operation_started (EActivityHandler *activity_handler, - const char *component_id, - const char *information, - gboolean cancellable, - void (*cancel_func)(gpointer), - gpointer user_data); - -void e_activity_handler_operation_progressing (EActivityHandler *activity_handler, - guint activity_id, - const char *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 char *component_id, - int 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, int time); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#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..bddcc124f3 --- /dev/null +++ b/widgets/misc/e-activity-proxy.c @@ -0,0 +1,345 @@ +/* + * e-activity-proxy.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-activity-proxy.h" + +#include <glib/gi18n.h> +#include <e-spinner.h> + +#define E_ACTIVITY_PROXY_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_ACTIVITY_PROXY, EActivityProxyPrivate)) + +struct _EActivityProxyPrivate { + EActivity *activity; + GtkWidget *button; + GtkWidget *image; + GtkWidget *label; + GtkWidget *cancel; + GtkWidget *spinner; +}; + +enum { + PROP_0, + PROP_ACTIVITY +}; + +static gpointer parent_class; + +static void +activity_proxy_update (EActivityProxy *proxy) +{ + EActivity *activity = proxy->priv->activity; + const gchar *icon_name; + gboolean allow_cancel; + gboolean cancelled; + gboolean clickable; + gboolean completed; + gboolean sensitive; + gchar *description; + + allow_cancel = e_activity_get_allow_cancel (activity); + cancelled = e_activity_is_cancelled (activity); + clickable = e_activity_get_clickable (activity); + completed = e_activity_is_completed (activity); + icon_name = e_activity_get_icon_name (activity); + + description = e_activity_describe (activity); + gtk_widget_set_tooltip_text (GTK_WIDGET (proxy), description); + gtk_label_set_text (GTK_LABEL (proxy->priv->label), description); + g_free (description); + + /* Note, an activity requires an icon name in order to + * be clickable. We don't support spinner buttons. */ + if (icon_name != NULL) { + gtk_image_set_from_icon_name ( + GTK_IMAGE (proxy->priv->image), + icon_name, GTK_ICON_SIZE_MENU); + gtk_button_set_image ( + GTK_BUTTON (proxy->priv->button), + gtk_image_new_from_icon_name ( + icon_name, GTK_ICON_SIZE_MENU)); + gtk_widget_hide (proxy->priv->spinner); + if (clickable) { + gtk_widget_show (proxy->priv->button); + gtk_widget_hide (proxy->priv->image); + } else { + gtk_widget_hide (proxy->priv->button); + gtk_widget_show (proxy->priv->image); + } + } else { + gtk_widget_show (proxy->priv->spinner); + gtk_widget_hide (proxy->priv->button); + gtk_widget_hide (proxy->priv->image); + } + + if (allow_cancel) + gtk_widget_show (proxy->priv->cancel); + else + gtk_widget_hide (proxy->priv->cancel); + + sensitive = !(cancelled || completed); + gtk_widget_set_sensitive (proxy->priv->cancel, sensitive); +} + +static void +activity_proxy_set_activity (EActivityProxy *proxy, + EActivity *activity) +{ + g_return_if_fail (proxy->priv->activity == NULL); + + proxy->priv->activity = g_object_ref (activity); +} + +static void +activity_proxy_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_ACTIVITY: + activity_proxy_set_activity ( + E_ACTIVITY_PROXY (object), + g_value_get_object (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +activity_proxy_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_ACTIVITY: + g_value_set_object ( + value, e_activity_proxy_get_activity ( + E_ACTIVITY_PROXY (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +activity_proxy_dispose (GObject *object) +{ + EActivityProxyPrivate *priv; + + priv = E_ACTIVITY_PROXY_GET_PRIVATE (object); + + if (priv->activity != NULL) { + g_signal_handlers_disconnect_matched ( + priv->activity, G_SIGNAL_MATCH_FUNC, 0, 0, + NULL, activity_proxy_update, NULL); + g_object_unref (priv->activity); + priv->activity = NULL; + } + + if (priv->button != NULL) { + g_object_unref (priv->button); + priv->button = NULL; + } + + if (priv->image != NULL) { + g_object_unref (priv->image); + priv->image = NULL; + } + + if (priv->label != NULL) { + g_object_unref (priv->label); + priv->label = NULL; + } + + if (priv->cancel != NULL) { + g_object_unref (priv->cancel); + priv->cancel = NULL; + } + + if (priv->spinner != NULL) { + g_object_unref (priv->spinner); + priv->spinner = NULL; + } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +activity_proxy_constructed (GObject *object) +{ + EActivityProxy *proxy; + + proxy = E_ACTIVITY_PROXY (object); + + g_signal_connect_swapped ( + proxy->priv->button, "clicked", + G_CALLBACK (e_activity_clicked), proxy->priv->activity); + + g_signal_connect_swapped ( + proxy->priv->cancel, "clicked", + G_CALLBACK (e_activity_cancel), proxy->priv->activity); + + g_signal_connect_swapped ( + proxy->priv->activity, "cancelled", + G_CALLBACK (activity_proxy_update), proxy); + + g_signal_connect_swapped ( + proxy->priv->activity, "completed", + G_CALLBACK (activity_proxy_update), proxy); + + g_signal_connect_swapped ( + proxy->priv->activity, "notify", + G_CALLBACK (activity_proxy_update), proxy); + + activity_proxy_update (proxy); +} + +static void +activity_proxy_class_init (EActivityProxyClass *class) +{ + GObjectClass *object_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EActivityProxyPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = activity_proxy_set_property; + object_class->get_property = activity_proxy_get_property; + object_class->dispose = activity_proxy_dispose; + object_class->constructed = activity_proxy_constructed; + + g_object_class_install_property ( + object_class, + PROP_ACTIVITY, + g_param_spec_object ( + "activity", + NULL, + NULL, + E_TYPE_ACTIVITY, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY)); +} + +static void +activity_proxy_init (EActivityProxy *proxy) +{ + GtkWidget *container; + GtkWidget *widget; + + proxy->priv = E_ACTIVITY_PROXY_GET_PRIVATE (proxy); + + container = GTK_WIDGET (proxy); + + widget = gtk_frame_new (NULL); + gtk_frame_set_shadow_type (GTK_FRAME (widget), GTK_SHADOW_IN); + gtk_container_add (GTK_CONTAINER (container), widget); + gtk_widget_show (widget); + + container = widget; + + widget = gtk_hbox_new (FALSE, 3); + gtk_container_add (GTK_CONTAINER (container), widget); + gtk_widget_show (widget); + + container = widget; + + widget = gtk_image_new (); + gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); + proxy->priv->image = g_object_ref (widget); + gtk_widget_hide (widget); + + widget = gtk_button_new (); + gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); + proxy->priv->button = g_object_ref (widget); + gtk_widget_hide (widget); + + /* XXX What's the rationale for killing the old spinner API? */ + widget = e_spinner_new_spinning_small_shown (); + gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); + proxy->priv->spinner = g_object_ref (widget); + gtk_widget_show (widget); + + widget = gtk_label_new (NULL); + gtk_label_set_ellipsize (GTK_LABEL (widget), PANGO_ELLIPSIZE_END); + gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5); + gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0); + proxy->priv->label = g_object_ref (widget); + gtk_widget_show (widget); + + widget = gtk_button_new (); + gtk_button_set_image ( + GTK_BUTTON (widget), gtk_image_new_from_stock ( + GTK_STOCK_STOP, GTK_ICON_SIZE_MENU)); + gtk_button_set_relief (GTK_BUTTON (widget), GTK_RELIEF_NONE); + gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); + gtk_widget_set_tooltip_text (widget, _("Cancel")); + proxy->priv->cancel = g_object_ref (widget); + gtk_widget_show (widget); +} + +GType +e_activity_proxy_get_type (void) +{ + static GType type = 0; + + if (G_UNLIKELY (type == 0)) { + static const GTypeInfo type_info = { + sizeof (EActivityProxyClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) activity_proxy_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EActivityProxy), + 0, /* n_preallocs */ + (GInstanceInitFunc) activity_proxy_init, + NULL /* value_table */ + }; + + type = g_type_register_static ( + GTK_TYPE_EVENT_BOX, "EActivityProxy", &type_info, 0); + } + + return type; +} + +GtkWidget * +e_activity_proxy_new (EActivity *activity) +{ + g_return_val_if_fail (E_IS_ACTIVITY (activity), NULL); + + return g_object_new ( + E_TYPE_ACTIVITY_PROXY, + "activity", activity, NULL); +} + +EActivity * +e_activity_proxy_get_activity (EActivityProxy *proxy) +{ + g_return_val_if_fail (E_IS_ACTIVITY_PROXY (proxy), NULL); + + return proxy->priv->activity; +} diff --git a/widgets/misc/e-activity-proxy.h b/widgets/misc/e-activity-proxy.h new file mode 100644 index 0000000000..af305be4fe --- /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..7cd89a7c47 --- /dev/null +++ b/widgets/misc/e-activity.c @@ -0,0 +1,764 @@ +/* + * e-activity.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-activity.h" + +#include <stdarg.h> +#include <glib/gi18n.h> + +#include "e-util/e-util.h" + +#define E_ACTIVITY_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_ACTIVITY, EActivityPrivate)) + +struct _EActivityPrivate { + gchar *icon_name; + gchar *primary_text; + gchar *secondary_text; + gdouble percent; + guint idle_id; + GError *error; + + guint allow_cancel : 1; + guint blocking : 1; + guint cancelled : 1; + guint clickable : 1; + guint completed : 1; +}; + +enum { + PROP_0, + PROP_ALLOW_CANCEL, + PROP_BLOCKING, + PROP_CLICKABLE, + PROP_ICON_NAME, + PROP_PERCENT, + PROP_PRIMARY_TEXT, + PROP_SECONDARY_TEXT +}; + +enum { + CANCELLED, + CLICKED, + COMPLETED, + DESCRIBE, + LAST_SIGNAL +}; + +static gpointer parent_class; +static gulong signals[LAST_SIGNAL]; + +static gboolean +activity_idle_cancel_cb (EActivity *activity) +{ + activity->priv->idle_id = 0; + e_activity_cancel (activity); + g_object_unref (activity); + + return FALSE; +} + +static gboolean +activity_idle_complete_cb (EActivity *activity) +{ + activity->priv->idle_id = 0; + e_activity_complete (activity); + g_object_unref (activity); + + return FALSE; +} + +static gboolean +activity_describe_accumulator (GSignalInvocationHint *ihint, + GValue *return_accu, + const GValue *handler_return, + gpointer accu_data) +{ + const gchar *string; + + string = g_value_get_string (handler_return); + g_value_set_string (return_accu, string); + + return (string == NULL); +} + +static void +activity_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_ALLOW_CANCEL: + e_activity_set_allow_cancel ( + E_ACTIVITY (object), + g_value_get_boolean (value)); + return; + + case PROP_BLOCKING: + e_activity_set_blocking ( + E_ACTIVITY (object), + g_value_get_boolean (value)); + return; + + case PROP_CLICKABLE: + e_activity_set_clickable ( + E_ACTIVITY (object), + g_value_get_boolean (value)); + return; + + case PROP_ICON_NAME: + e_activity_set_icon_name ( + E_ACTIVITY (object), + g_value_get_string (value)); + return; + + case PROP_PERCENT: + e_activity_set_percent ( + E_ACTIVITY (object), + g_value_get_double (value)); + return; + + case PROP_PRIMARY_TEXT: + e_activity_set_primary_text ( + E_ACTIVITY (object), + g_value_get_string (value)); + return; + + case PROP_SECONDARY_TEXT: + e_activity_set_secondary_text ( + E_ACTIVITY (object), + g_value_get_string (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +activity_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_ALLOW_CANCEL: + g_value_set_boolean ( + value, e_activity_get_allow_cancel ( + E_ACTIVITY (object))); + return; + + case PROP_BLOCKING: + g_value_set_boolean ( + value, e_activity_get_blocking ( + E_ACTIVITY (object))); + return; + + case PROP_CLICKABLE: + g_value_set_boolean ( + value, e_activity_get_clickable ( + E_ACTIVITY (object))); + return; + + case PROP_ICON_NAME: + g_value_set_string ( + value, e_activity_get_icon_name ( + E_ACTIVITY (object))); + return; + + case PROP_PERCENT: + g_value_set_double ( + value, e_activity_get_percent ( + E_ACTIVITY (object))); + return; + + case PROP_PRIMARY_TEXT: + g_value_set_string ( + value, e_activity_get_primary_text ( + E_ACTIVITY (object))); + return; + + case PROP_SECONDARY_TEXT: + g_value_set_string ( + value, e_activity_get_secondary_text ( + E_ACTIVITY (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +activity_finalize (GObject *object) +{ + EActivityPrivate *priv; + + priv = E_ACTIVITY_GET_PRIVATE (object); + + g_free (priv->icon_name); + g_free (priv->primary_text); + g_free (priv->secondary_text); + + if (priv->idle_id > 0) + g_source_remove (priv->idle_id); + + if (priv->error != NULL) + g_error_free (priv->error); + + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +activity_cancelled (EActivity *activity) +{ + activity->priv->cancelled = TRUE; + + if (activity->priv->idle_id > 0) { + g_source_remove (activity->priv->idle_id); + activity->priv->idle_id = 0; + } +} + +static void +activity_completed (EActivity *activity) +{ + activity->priv->completed = TRUE; + + if (activity->priv->idle_id > 0) { + g_source_remove (activity->priv->idle_id); + activity->priv->idle_id = 0; + } +} + +static void +activity_clicked (EActivity *activity) +{ + /* Allow subclasses to safely chain up. */ +} + +static gchar * +activity_describe (EActivity *activity) +{ + GString *string; + const gchar *text; + gboolean cancelled; + gboolean completed; + gdouble percent; + + string = g_string_sized_new (256); + text = e_activity_get_primary_text (activity); + cancelled = e_activity_is_cancelled (activity); + completed = e_activity_is_completed (activity); + percent = e_activity_get_percent (activity); + + if (cancelled) { + /* Translators: This is a cancelled activity. */ + g_string_printf (string, _("%s (cancelled)"), text); + } else if (completed) { + /* Translators: This is a completed activity. */ + g_string_printf (string, _("%s (completed)"), text); + } else if (percent < 0.0) { + /* Translators: This is an activity whose percent + * complete is unknown. */ + g_string_printf (string, _("%s..."), text); + } else { + /* Translators: This is an activity whose percent + * complete is known. */ + g_string_printf ( + string, _("%s (%d%% complete)"), text, + (gint) (percent * 100.0 + 0.5)); + } + + return g_string_free (string, FALSE); +} + +static void +activity_class_init (EActivityClass *class) +{ + GObjectClass *object_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EActivityPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = activity_set_property; + object_class->get_property = activity_get_property; + object_class->finalize = activity_finalize; + + class->cancelled = activity_cancelled; + class->completed = activity_completed; + class->clicked = activity_clicked; + class->describe = activity_describe; + + g_object_class_install_property ( + object_class, + PROP_ALLOW_CANCEL, + g_param_spec_boolean ( + "allow-cancel", + NULL, + NULL, + FALSE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + g_object_class_install_property ( + object_class, + PROP_BLOCKING, + g_param_spec_boolean ( + "blocking", + NULL, + NULL, + TRUE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + g_object_class_install_property ( + object_class, + PROP_CLICKABLE, + g_param_spec_boolean ( + "clickable", + NULL, + NULL, + FALSE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + g_object_class_install_property ( + object_class, + PROP_ICON_NAME, + g_param_spec_string ( + "icon-name", + NULL, + NULL, + NULL, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + g_object_class_install_property ( + object_class, + PROP_PERCENT, + g_param_spec_double ( + "percent", + NULL, + NULL, + -G_MAXDOUBLE, + G_MAXDOUBLE, + -1.0, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + g_object_class_install_property ( + object_class, + PROP_PRIMARY_TEXT, + g_param_spec_string ( + "primary-text", + NULL, + NULL, + NULL, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + g_object_class_install_property ( + object_class, + PROP_SECONDARY_TEXT, + g_param_spec_string ( + "secondary-text", + NULL, + NULL, + NULL, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + signals[CANCELLED] = g_signal_new ( + "cancelled", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (EActivityClass, cancelled), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + signals[CLICKED] = g_signal_new ( + "clicked", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (EActivityClass, clicked), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + signals[COMPLETED] = g_signal_new ( + "completed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (EActivityClass, completed), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + signals[DESCRIBE] = g_signal_new ( + "describe", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (EActivityClass, describe), + activity_describe_accumulator, NULL, + e_marshal_STRING__VOID, + G_TYPE_STRING, 0); +} + +static void +activity_init (EActivity *activity) +{ + activity->priv = E_ACTIVITY_GET_PRIVATE (activity); +} + +GType +e_activity_get_type (void) +{ + static GType type = 0; + + if (G_UNLIKELY (type == 0)) { + static const GTypeInfo type_info = { + sizeof (EActivityClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) activity_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EActivity), + 0, /* n_preallocs */ + (GInstanceInitFunc) activity_init, + NULL /* value_table */ + }; + + type = g_type_register_static ( + G_TYPE_OBJECT, "EActivity", &type_info, 0); + } + + return type; +} + +EActivity * +e_activity_new (const gchar *primary_text) +{ + return g_object_new ( + E_TYPE_ACTIVITY, + "primary-text", primary_text, NULL); +} + +EActivity * +e_activity_newv (const gchar *format, ...) +{ + EActivity *activity; + gchar *primary_text; + va_list args; + + va_start (args, format); + primary_text = g_strdup_vprintf (format, args); + activity = e_activity_new (primary_text); + g_free (primary_text); + va_end (args); + + return activity; +} + +void +e_activity_cancel (EActivity *activity) +{ + g_return_if_fail (E_IS_ACTIVITY (activity)); + + if (!activity->priv->allow_cancel); + return; + + if (activity->priv->cancelled) + return; + + if (activity->priv->completed) + return; + + g_signal_emit (activity, signals[CANCELLED], 0); +} + +void +e_activity_cancel_in_idle (EActivity *activity) +{ + guint old_idle_id; + + g_return_if_fail (E_IS_ACTIVITY (activity)); + + /* Be careful not to finalize the activity. Decrement the + * reference count only after incrementing it, in case this + * is the last reference. */ + + old_idle_id = activity->priv->idle_id; + + activity->priv->idle_id = g_idle_add ( + (GSourceFunc) activity_idle_cancel_cb, + g_object_ref (activity)); + + if (old_idle_id > 0) { + g_source_remove (old_idle_id); + g_object_unref (activity); + } +} + +void +e_activity_complete (EActivity *activity) +{ + g_return_if_fail (E_IS_ACTIVITY (activity)); + + if (activity->priv->cancelled) + return; + + if (activity->priv->completed) + return; + + g_signal_emit (activity, signals[COMPLETED], 0); +} + +void +e_activity_complete_in_idle (EActivity *activity) +{ + guint old_idle_id; + + g_return_if_fail (E_IS_ACTIVITY (activity)); + + /* Be careful not to finalize the activity. Decrement the + * reference count only after incrementing it, in case this + * is the last reference. */ + + old_idle_id = activity->priv->idle_id; + + activity->priv->idle_id = g_idle_add ( + (GSourceFunc) activity_idle_complete_cb, + g_object_ref (activity)); + + if (old_idle_id > 0) { + g_source_remove (old_idle_id); + g_object_unref (activity); + } +} + +void +e_activity_clicked (EActivity *activity) +{ + g_return_if_fail (E_IS_ACTIVITY (activity)); + + g_signal_emit (activity, signals[CLICKED], 0); +} + +gchar * +e_activity_describe (EActivity *activity) +{ + EActivityClass *class; + + g_return_val_if_fail (E_IS_ACTIVITY (activity), NULL); + + class = E_ACTIVITY_GET_CLASS (activity); + g_return_val_if_fail (class->describe != NULL, NULL); + + return class->describe (activity); +} + +gboolean +e_activity_is_cancelled (EActivity *activity) +{ + g_return_val_if_fail (E_IS_ACTIVITY (activity), FALSE); + + return activity->priv->cancelled; +} + +gboolean +e_activity_is_completed (EActivity *activity) +{ + g_return_val_if_fail (E_IS_ACTIVITY (activity), FALSE); + + return activity->priv->completed; +} + +gboolean +e_activity_get_allow_cancel (EActivity *activity) +{ + g_return_val_if_fail (E_IS_ACTIVITY (activity), FALSE); + + return activity->priv->allow_cancel; +} + +void +e_activity_set_allow_cancel (EActivity *activity, + gboolean allow_cancel) +{ + g_return_if_fail (E_IS_ACTIVITY (activity)); + + activity->priv->allow_cancel = allow_cancel; + + g_object_notify (G_OBJECT (activity), "allow-cancel"); +} + +gboolean +e_activity_get_blocking (EActivity *activity) +{ + g_return_val_if_fail (E_IS_ACTIVITY (activity), FALSE); + + return activity->priv->blocking; +} + +void +e_activity_set_blocking (EActivity *activity, + gboolean blocking) +{ + g_return_if_fail (E_IS_ACTIVITY (activity)); + + activity->priv->blocking = blocking; + + g_object_notify (G_OBJECT (activity), "blocking"); +} + +gboolean +e_activity_get_clickable (EActivity *activity) +{ + g_return_val_if_fail (E_IS_ACTIVITY (activity), FALSE); + + return activity->priv->clickable; +} + +void +e_activity_set_clickable (EActivity *activity, + gboolean clickable) +{ + g_return_if_fail (E_IS_ACTIVITY (activity)); + + activity->priv->clickable = clickable; + + g_object_notify (G_OBJECT (activity), "clickable"); +} + +const gchar * +e_activity_get_icon_name (EActivity *activity) +{ + g_return_val_if_fail (E_IS_ACTIVITY (activity), NULL); + + return activity->priv->icon_name; +} + +void +e_activity_set_icon_name (EActivity *activity, + const gchar *icon_name) +{ + g_return_if_fail (E_IS_ACTIVITY (activity)); + + g_free (activity->priv->icon_name); + activity->priv->icon_name = g_strdup (icon_name); + + g_object_notify (G_OBJECT (activity), "icon-name"); +} + +gdouble +e_activity_get_percent (EActivity *activity) +{ + g_return_val_if_fail (E_IS_ACTIVITY (activity), -1.0); + + return activity->priv->percent; +} + +void +e_activity_set_percent (EActivity *activity, + gdouble percent) +{ + g_return_if_fail (E_IS_ACTIVITY (activity)); + + activity->priv->percent = percent; + + g_object_notify (G_OBJECT (activity), "percent"); +} + +const gchar * +e_activity_get_primary_text (EActivity *activity) +{ + g_return_val_if_fail (E_IS_ACTIVITY (activity), NULL); + + return activity->priv->primary_text; +} + +void +e_activity_set_primary_text (EActivity *activity, + const gchar *primary_text) +{ + g_return_if_fail (E_IS_ACTIVITY (activity)); + + g_free (activity->priv->primary_text); + activity->priv->primary_text = g_strdup (primary_text); + + g_object_notify (G_OBJECT (activity), "primary-text"); +} + +const gchar * +e_activity_get_secondary_text (EActivity *activity) +{ + g_return_val_if_fail (E_IS_ACTIVITY (activity), NULL); + + return activity->priv->secondary_text; +} + +void +e_activity_set_secondary_text (EActivity *activity, + const gchar *secondary_text) +{ + g_return_if_fail (E_IS_ACTIVITY (activity)); + + g_free (activity->priv->secondary_text); + activity->priv->secondary_text = g_strdup (secondary_text); + + g_object_notify (G_OBJECT (activity), "secondary-text"); +} + +void +e_activity_set_error (EActivity *activity, + const GError *error) +{ + g_return_if_fail (E_IS_ACTIVITY (activity)); + + if (activity->priv->error != NULL) { + g_error_free (activity->priv->error); + activity->priv->error = NULL; + } + + if (error != NULL) + activity->priv->error = g_error_copy (error); +} + +gboolean +e_activity_propagate_error (EActivity *activity, + GError **destination) +{ + gboolean propagated; + + g_return_val_if_fail (E_IS_ACTIVITY (activity), FALSE); + + if ((propagated = (activity->priv->error != NULL))) { + g_propagate_error (destination, activity->priv->error); + activity->priv->error = NULL; + } + + return propagated; +} diff --git a/widgets/misc/e-activity.h b/widgets/misc/e-activity.h new file mode 100644 index 0000000000..34974dd415 --- /dev/null +++ b/widgets/misc/e-activity.h @@ -0,0 +1,107 @@ +/* + * e-activity.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_ACTIVITY_H +#define E_ACTIVITY_H + +#include <gtk/gtk.h> + +/* Standard GObject macros */ +#define E_TYPE_ACTIVITY \ + (e_activity_get_type ()) +#define E_ACTIVITY(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_ACTIVITY, EActivity)) +#define E_ACTIVITY_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_ACTIVITY, EActivityClass)) +#define E_IS_ACTIVITY(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_ACTIVITY)) +#define E_IS_ACTIVITY_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_ACTIVITY)) +#define E_ACTIVITY_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_ACTIVITY, EActivityClass)) + +G_BEGIN_DECLS + +typedef struct _EActivity EActivity; +typedef struct _EActivityClass EActivityClass; +typedef struct _EActivityPrivate EActivityPrivate; + +struct _EActivity { + GObject parent; + EActivityPrivate *priv; +}; + +struct _EActivityClass { + GObjectClass parent_class; + + /* Signals */ + void (*cancelled) (EActivity *activity); + void (*completed) (EActivity *activity); + void (*clicked) (EActivity *activity); + gchar * (*describe) (EActivity *activity); +}; + +GType e_activity_get_type (void); +EActivity * e_activity_new (const gchar *primary_text); +EActivity * e_activity_newv (const gchar *format, + ...) G_GNUC_PRINTF (1, 2); +void e_activity_cancel (EActivity *activity); +void e_activity_cancel_in_idle (EActivity *activity); +void e_activity_complete (EActivity *activity); +void e_activity_complete_in_idle (EActivity *activity); +void e_activity_clicked (EActivity *activity); +gchar * e_activity_describe (EActivity *activity); +gboolean e_activity_is_cancelled (EActivity *activity); +gboolean e_activity_is_completed (EActivity *activity); +gboolean e_activity_get_allow_cancel (EActivity *activity); +void e_activity_set_allow_cancel (EActivity *activity, + gboolean allow_cancel); +gboolean e_activity_get_blocking (EActivity *activity); +void e_activity_set_blocking (EActivity *activity, + gboolean blocking); +gboolean e_activity_get_clickable (EActivity *activity); +void e_activity_set_clickable (EActivity *activity, + gboolean clickable); +const gchar * e_activity_get_icon_name (EActivity *activity); +void e_activity_set_icon_name (EActivity *activity, + const gchar *icon_name); +gdouble e_activity_get_percent (EActivity *activity); +void e_activity_set_percent (EActivity *activity, + gdouble percent); +const gchar * e_activity_get_primary_text (EActivity *activity); +void e_activity_set_primary_text (EActivity *activity, + const gchar *primary_text); +const gchar * e_activity_get_secondary_text (EActivity *activity); +void e_activity_set_secondary_text (EActivity *activity, + const gchar *secondary_text); +void e_activity_set_error (EActivity *activity, + const GError *error); +gboolean e_activity_propagate_error (EActivity *activity, + GError **destination); + +G_END_DECLS + +#endif /* E_ACTIVITY_H */ diff --git a/widgets/misc/e-alert-activity.c b/widgets/misc/e-alert-activity.c new file mode 100644 index 0000000000..d8b9d6f3f3 --- /dev/null +++ b/widgets/misc/e-alert-activity.c @@ -0,0 +1,254 @@ +/* + * e-alert-activity.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-alert-activity.h" + +#define E_ALERT_ACTIVITY_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_ALERT_ACTIVITY, EAlertActivityPrivate)) + +struct _EAlertActivityPrivate { + GtkWidget *message_dialog; +}; + +enum { + PROP_0, + PROP_MESSAGE_DIALOG +}; + +static gpointer parent_class; + +static void +alert_activity_set_message_dialog (EAlertActivity *alert_activity, + GtkWidget *message_dialog) +{ + g_return_if_fail (alert_activity->priv->message_dialog == NULL); + + alert_activity->priv->message_dialog = g_object_ref (message_dialog); +} + +static void +alert_activity_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_MESSAGE_DIALOG: + alert_activity_set_message_dialog ( + E_ALERT_ACTIVITY (object), + g_value_get_object (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +alert_activity_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_MESSAGE_DIALOG: + g_value_set_object ( + value, e_alert_activity_get_message_dialog ( + E_ALERT_ACTIVITY (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +alert_activity_dispose (GObject *object) +{ + EAlertActivityPrivate *priv; + + priv = E_ALERT_ACTIVITY_GET_PRIVATE (object); + + if (priv->message_dialog != NULL) { + g_object_unref (priv->message_dialog); + priv->message_dialog = NULL; + } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +alert_activity_constructed (GObject *object) +{ + EActivity *activity; + EAlertActivity *alert_activity; + GtkWidget *message_dialog; + const gchar *primary_text; + const gchar *secondary_text; + + alert_activity = E_ALERT_ACTIVITY (object); + message_dialog = e_alert_activity_get_message_dialog (alert_activity); + + object = G_OBJECT (message_dialog); + primary_text = g_object_get_data (object, "primary"); + secondary_text = g_object_get_data (object, "secondary"); + + activity = E_ACTIVITY (alert_activity); + e_activity_set_primary_text (activity, primary_text); + e_activity_set_secondary_text (activity, secondary_text); +} + +static void +alert_activity_clicked (EActivity *activity) +{ + EAlertActivity *alert_activity; + GtkWidget *message_dialog; + + e_activity_complete (activity); + + alert_activity = E_ALERT_ACTIVITY (activity); + message_dialog = e_alert_activity_get_message_dialog (alert_activity); + gtk_dialog_run (GTK_DIALOG (message_dialog)); + gtk_widget_hide (message_dialog); + + /* Chain up to parent's clicked() method. */ + E_ACTIVITY_CLASS (parent_class)->clicked (activity); +} + +static void +alert_activity_timeout (ETimeoutActivity *activity) +{ + e_activity_complete (E_ACTIVITY (activity)); + + /* Chain up to parent's timeout() method. */ + E_TIMEOUT_ACTIVITY_CLASS (parent_class)->timeout (activity); +} + +static void +alert_activity_class_init (EAlertActivityClass *class) +{ + GObjectClass *object_class; + EActivityClass *activity_class; + ETimeoutActivityClass *timeout_activity_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EAlertActivityPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = alert_activity_set_property; + object_class->get_property = alert_activity_get_property; + object_class->dispose = alert_activity_dispose; + object_class->constructed = alert_activity_constructed; + + activity_class = E_ACTIVITY_CLASS (class); + activity_class->clicked = alert_activity_clicked; + + timeout_activity_class = E_TIMEOUT_ACTIVITY_CLASS (class); + timeout_activity_class->timeout = alert_activity_timeout; + + g_object_class_install_property ( + object_class, + PROP_MESSAGE_DIALOG, + g_param_spec_object ( + "message-dialog", + NULL, + NULL, + GTK_TYPE_DIALOG, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY)); +} + +static void +alert_activity_init (EAlertActivity *alert_activity) +{ + alert_activity->priv = E_ALERT_ACTIVITY_GET_PRIVATE (alert_activity); + + e_activity_set_clickable (E_ACTIVITY (alert_activity), TRUE); + e_timeout_activity_set_timeout (E_TIMEOUT_ACTIVITY (alert_activity), 60); +} + +GType +e_alert_activity_get_type (void) +{ + static GType type = 0; + + if (G_UNLIKELY (type == 0)) { + static const GTypeInfo type_info = { + sizeof (EAlertActivityClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) alert_activity_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EAlertActivity), + 0, /* n_preallocs */ + (GInstanceInitFunc) alert_activity_init, + NULL /* value_table */ + }; + + type = g_type_register_static ( + E_TYPE_TIMEOUT_ACTIVITY, "EAlertActivity", + &type_info, 0); + } + + return type; +} + +EActivity * +e_alert_activity_new_info (GtkWidget *message_dialog) +{ + g_return_val_if_fail (GTK_IS_DIALOG (message_dialog), NULL); + + return g_object_new ( + E_TYPE_ALERT_ACTIVITY, + "icon-name", "dialog-information", + "message-dialog", message_dialog, NULL); +} + +EActivity * +e_alert_activity_new_error (GtkWidget *message_dialog) +{ + g_return_val_if_fail (GTK_IS_DIALOG (message_dialog), NULL); + + return g_object_new ( + E_TYPE_ALERT_ACTIVITY, + "icon-name", "dialog-error", + "message-dialog", message_dialog, NULL); +} + +EActivity * +e_alert_activity_new_warning (GtkWidget *message_dialog) +{ + g_return_val_if_fail (GTK_IS_DIALOG (message_dialog), NULL); + + return g_object_new ( + E_TYPE_ALERT_ACTIVITY, + "icon-name", "dialog-warning", + "message-dialog", message_dialog, NULL); +} + +GtkWidget * +e_alert_activity_get_message_dialog (EAlertActivity *alert_activity) +{ + g_return_val_if_fail (E_IS_ALERT_ACTIVITY (alert_activity), NULL); + + return alert_activity->priv->message_dialog; +} diff --git a/widgets/misc/e-alert-activity.h b/widgets/misc/e-alert-activity.h new file mode 100644 index 0000000000..4c5547d7fa --- /dev/null +++ b/widgets/misc/e-alert-activity.h @@ -0,0 +1,70 @@ +/* + * e-alert-activity.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_ALERT_ACTIVITY_H +#define E_ALERT_ACTIVITY_H + +#include <e-timeout-activity.h> + +/* Standard GObject macros */ +#define E_TYPE_ALERT_ACTIVITY \ + (e_alert_activity_get_type ()) +#define E_ALERT_ACTIVITY(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_ALERT_ACTIVITY, EAlertActivity)) +#define E_ALERT_ACTIVITY_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_ALERT_ACTIVITY, EAlertActivityClass)) +#define E_IS_ALERT_ACTIVITY(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_ALERT_ACTIVITY)) +#define E_IS_ALERT_ACTIVITY_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_ALERT_ACTIVITY)) +#define E_ALERT_ACTIVITY_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_ALERT_ACTIVITY, EAlertActivityClass)) + +G_BEGIN_DECLS + +typedef struct _EAlertActivity EAlertActivity; +typedef struct _EAlertActivityClass EAlertActivityClass; +typedef struct _EAlertActivityPrivate EAlertActivityPrivate; + +struct _EAlertActivity { + ETimeoutActivity parent; + EAlertActivityPrivate *priv; +}; + +struct _EAlertActivityClass { + ETimeoutActivityClass parent_class; +}; + +GType e_alert_activity_get_type (void); +EActivity * e_alert_activity_new_info (GtkWidget *message_dialog); +EActivity * e_alert_activity_new_error (GtkWidget *message_dialog); +EActivity * e_alert_activity_new_warning (GtkWidget *message_dialog); +GtkWidget * e_alert_activity_get_message_dialog + (EAlertActivity *alert_activity); + +G_END_DECLS + +#endif /* E_ALERT_ACTIVITY_H */ diff --git a/widgets/misc/e-calendar.h b/widgets/misc/e-calendar.h index aebc615cfc..1330eb4cf3 100644 --- a/widgets/misc/e-calendar.h +++ b/widgets/misc/e-calendar.h @@ -39,9 +39,24 @@ extern "C" { * to got to the current day. */ -#define E_CALENDAR(obj) G_TYPE_CHECK_INSTANCE_CAST (obj, e_calendar_get_type (), ECalendar) -#define E_CALENDAR_CLASS(klass) G_TYPE_CHECK_CLASS_CAST (klass, e_calendar_get_type (), ECalendarClass) -#define E_IS_CALENDAR(obj) G_TYPE_CHECK_INSTANCE_TYPE (obj, e_calendar_get_type ()) +/* Standard GObject macros */ +#define E_TYPE_CALENDAR \ + (e_calendar_get_type ()) +#define E_CALENDAR(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_CALENDAR, ECalendar)) +#define E_CALENDAR_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_CALENDAR, ECalendarClass)) +#define E_IS_CALENDAR(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_CALENDAR)) +#define E_IS_CALENDAR_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_CALENDAR)) +#define E_CALENDAR_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_CALENDAR, ECalendarClass)) typedef struct _ECalendar ECalendar; diff --git a/widgets/misc/e-charset-picker.c b/widgets/misc/e-charset-picker.c index cf3f758ce7..6b30b3b11c 100644 --- a/widgets/misc/e-charset-picker.c +++ b/widgets/misc/e-charset-picker.c @@ -31,9 +31,6 @@ #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, @@ -440,6 +437,7 @@ e_charset_picker_dialog (const char *title, const char *prompt, /** * e_charset_add_radio_actions: * @action_group: a #GtkActionGroup + * @action_prefix: a prefix for action names, or %NULL * @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 @@ -453,8 +451,9 @@ e_charset_picker_dialog (const char *title, const char *prompt, * the default will be added next, followed by the remaining character * sets. **/ -void +GSList * e_charset_add_radio_actions (GtkActionGroup *action_group, + const gchar *action_prefix, const gchar *default_charset, GCallback callback, gpointer user_data) @@ -464,12 +463,10 @@ e_charset_add_radio_actions (GtkActionGroup *action_group, const gchar *locale_charset; gint def, ii; - g_return_if_fail (GTK_IS_ACTION_GROUP (action_group)); + g_return_val_if_fail (GTK_IS_ACTION_GROUP (action_group), NULL); - /* 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. */ + if (action_prefix == NULL) + action_prefix = ""; g_get_charset (&locale_charset); if (!g_ascii_strcasecmp (locale_charset, "US-ASCII")) @@ -482,13 +479,18 @@ e_charset_add_radio_actions (GtkActionGroup *action_group, break; for (ii = 0; ii < G_N_ELEMENTS (charsets); ii++) { + const gchar *charset_name; + gchar *action_name; gchar *escaped_name; gchar *charset_label; gchar **str_array; + charset_name = charsets[ii].name; + action_name = g_strconcat (action_prefix, charset_name, NULL); + /* Escape underlines in the character set name so * they're not treated as GtkLabel mnemonics. */ - str_array = g_strsplit (charsets[ii].name, "_", -1); + str_array = g_strsplit (charset_name, "_", -1); escaped_name = g_strjoinv ("__", str_array); g_strfreev (str_array); @@ -506,8 +508,14 @@ e_charset_add_radio_actions (GtkActionGroup *action_group, else charset_label = g_strdup (escaped_name); + /* XXX Add a tooltip! */ action = gtk_radio_action_new ( - charsets[ii].name, charset_label, NULL, NULL, ii); + action_name, charset_label, NULL, NULL, ii); + + /* Character set name is static so no need to free it. */ + g_object_set_data ( + G_OBJECT (action), "charset", + (gpointer) charset_name); gtk_radio_action_set_group (action, group); group = gtk_radio_action_get_group (action); @@ -521,22 +529,34 @@ e_charset_add_radio_actions (GtkActionGroup *action_group, g_object_unref (action); + g_free (action_name); g_free (escaped_name); g_free (charset_label); } if (def == G_N_ELEMENTS (charsets)) { + const gchar *charset_name; + gchar *action_name; gchar *charset_label; gchar **str_array; + charset_name = default_charset; + action_name = g_strconcat (action_prefix, charset_name, NULL); + /* Escape underlines in the character set name so * they're not treated as GtkLabel mnemonics. */ - str_array = g_strsplit (default_charset, "_", -1); + str_array = g_strsplit (charset_name, "_", -1); charset_label = g_strjoinv ("__", str_array); g_strfreev (str_array); + /* XXX Add a tooltip! */ action = gtk_radio_action_new ( - default_charset, charset_label, NULL, NULL, def); + action_name, charset_label, NULL, NULL, def); + + /* Character set name is static so no need to free it. */ + g_object_set_data ( + G_OBJECT (action), "charset", + (gpointer) charset_name); gtk_radio_action_set_group (action, group); group = gtk_radio_action_get_group (action); @@ -550,165 +570,13 @@ e_charset_add_radio_actions (GtkActionGroup *action_group, g_object_unref (action); + g_free (action_name); 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 char *path, - const char *default_charset, - BonoboUIListenerFn cb, gpointer user_data) -{ - char *encoded_label, *label; - const char *locale_charset; - GString *menuitems; - int 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++) { - char *command; - char *charset_name, *u; - - /* escape _'s in the charset name so that it doesn't become an underline in a GtkLabel */ - if ((u = strchr (charsets[i].name, '_'))) { - int extra = 1; - char *s, *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 = 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) { - char *command; - char *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, '_'))) { - int extra = 1; - char *s, *d; - - while ((u = strchr (u + 1, '_'))) - extra++; - - d = charset_name = g_alloca (strlen (default_charset) + extra + 1); - s = (char *) default_charset; - while (*s != '\0') { - if (*s == '_') - *d++ = '_'; - *d++ = *s++; - } - *d = '\0'; - } else { - charset_name = (char *) 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); + return group; } diff --git a/widgets/misc/e-charset-picker.h b/widgets/misc/e-charset-picker.h index 7250b10dfb..1521a2dbb0 100644 --- a/widgets/misc/e-charset-picker.h +++ b/widgets/misc/e-charset-picker.h @@ -22,7 +22,6 @@ #define E_CHARSETPICKER_H #include <gtk/gtk.h> -#include <bonobo/bonobo-ui-component.h> G_BEGIN_DECLS @@ -33,18 +32,12 @@ char * e_charset_picker_dialog (const char *title, const char *default_charset, GtkWindow *parent); -void e_charset_add_radio_actions (GtkActionGroup *action_group, +GSList * e_charset_add_radio_actions (GtkActionGroup *action_group, + const gchar *action_prefix, const gchar *default_charset, GCallback callback, gpointer user_data); -void e_charset_picker_bonobo_ui_populate - (BonoboUIComponent *uic, - const char *path, - const char *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 aabb7073f1..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; - int separator_x; - int focus_width, focus_pad; - int x, y, width, height; - int 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, - void *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, - void *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 int -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 int -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 int -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) { - int 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 char *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 0abe347a93..0000000000 --- a/widgets/misc/e-combo-button.h +++ /dev/null @@ -1,83 +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> - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#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 char *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); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* _E_COMBO_BUTTON_H_ */ diff --git a/widgets/misc/e-config-page.c b/widgets/misc/e-config-page.c deleted file mode 100644 index c9823a29e8..0000000000 --- a/widgets/misc/e-config-page.c +++ /dev/null @@ -1,49 +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-config-page.h" - -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) -{ -} - -GtkWidget * -e_config_page_new (void) -{ - return g_object_new (e_config_page_get_type (), NULL); -} - - diff --git a/widgets/misc/e-config-page.h b/widgets/misc/e-config-page.h deleted file mode 100644 index 24317d3f9d..0000000000 --- a/widgets/misc/e-config-page.h +++ /dev/null @@ -1,67 +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> - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#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); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* _E_CONFIG_PAGE_H_ */ diff --git a/widgets/misc/e-dropdown-button.c b/widgets/misc/e-dropdown-button.c deleted file mode 100644 index 6008f64ad9..0000000000 --- a/widgets/misc/e-dropdown-button.c +++ /dev/null @@ -1,237 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see <http://www.gnu.org/licenses/> - * - * - * Authors: - * Ettore Perazzoli <ettore@ximian.com> - * Damon Chaplin <damon@ximian.com> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "e-dropdown-button.h" - -#include <stdio.h> - -struct _EDropdownButtonPrivate { - GtkAccelGroup *accel_group; - GtkWidget *menu; -}; - -G_DEFINE_TYPE (EDropdownButton, e_dropdown_button, GTK_TYPE_TOGGLE_BUTTON) - -/* Callback to position the pop-up menu. */ - -static void -menu_position_cb (GtkMenu *menu, - int *x, - int *y, - gboolean *push_in, - void *data) -{ - EDropdownButton *dropdown_button; - EDropdownButtonPrivate *priv; - GtkRequisition menu_requisition; - int 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 int -menu_deactivate_cb (GtkMenuShell *menu_shell, - void *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 char *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 char *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 b10fd9a670..0000000000 --- a/widgets/misc/e-dropdown-button.h +++ /dev/null @@ -1,70 +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> - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#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 char *label_text, - GtkMenu *menu); -GtkWidget *e_dropdown_button_new (const char *label_text, - GtkMenu *menu); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* _E_DROPDOWN_BUTTON_H_ */ diff --git a/widgets/misc/e-file-activity.c b/widgets/misc/e-file-activity.c new file mode 100644 index 0000000000..1957c20282 --- /dev/null +++ b/widgets/misc/e-file-activity.c @@ -0,0 +1,365 @@ +/* + * e-file-activity.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-file-activity.h" + +#include <stdarg.h> + +#define E_FILE_ACTIVITY_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_FILE_ACTIVITY, EFileActivityPrivate)) + +struct _EFileActivityPrivate { + GCancellable *cancellable; + GAsyncResult *result; + GFile *file; + + gulong handler_id; +}; + +enum { + PROP_0, + PROP_CANCELLABLE, + PROP_FILE, + PROP_RESULT +}; + +static gpointer parent_class; + +static void +file_activity_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_CANCELLABLE: + e_file_activity_set_cancellable ( + E_FILE_ACTIVITY (object), + g_value_get_object (value)); + return; + + case PROP_FILE: + e_file_activity_set_file ( + E_FILE_ACTIVITY (object), + g_value_get_object (value)); + return; + + case PROP_RESULT: + e_file_activity_set_result ( + E_FILE_ACTIVITY (object), + g_value_get_object (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +file_activity_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_CANCELLABLE: + g_value_set_object ( + value, e_file_activity_get_cancellable ( + E_FILE_ACTIVITY (object))); + return; + + case PROP_FILE: + g_value_set_object ( + value, e_file_activity_get_file ( + E_FILE_ACTIVITY (object))); + return; + + case PROP_RESULT: + g_value_set_object ( + value, e_file_activity_get_result ( + E_FILE_ACTIVITY (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +file_activity_dispose (GObject *object) +{ + EFileActivityPrivate *priv; + + priv = E_FILE_ACTIVITY_GET_PRIVATE (object); + + if (priv->cancellable != NULL) { + g_signal_handler_disconnect ( + priv->cancellable, priv->handler_id); + g_object_unref (priv->cancellable); + priv->cancellable = NULL; + } + + if (priv->result != NULL) { + g_object_unref (priv->result); + priv->result = NULL; + } + + if (priv->file != NULL) { + g_object_unref (priv->file); + priv->file = NULL; + } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +file_activity_cancelled (EActivity *activity) +{ + EFileActivity *file_activity; + GCancellable *cancellable; + + file_activity = E_FILE_ACTIVITY (activity); + cancellable = e_file_activity_get_cancellable (file_activity); + g_cancellable_cancel (cancellable); + + /* Chain up to parent's cancelled() method. */ + E_ACTIVITY_CLASS (parent_class)->cancelled (activity); +} + +static void +file_activity_class_init (EFileActivityClass *class) +{ + GObjectClass *object_class; + EActivityClass *activity_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EFileActivityPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = file_activity_set_property; + object_class->get_property = file_activity_get_property; + object_class->dispose = file_activity_dispose; + + activity_class = E_ACTIVITY_CLASS (class); + activity_class->cancelled = file_activity_cancelled; + + g_object_class_install_property ( + object_class, + PROP_CANCELLABLE, + g_param_spec_object ( + "cancellable", + "Cancellable", + NULL, + G_TYPE_CANCELLABLE, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_FILE, + g_param_spec_object ( + "file", + "File", + NULL, + G_TYPE_FILE, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_RESULT, + g_param_spec_object ( + "result", + "Result", + NULL, + G_TYPE_ASYNC_RESULT, + G_PARAM_READWRITE)); +} + +static void +file_activity_init (EFileActivity *file_activity) +{ + GCancellable *cancellable; + + file_activity->priv = E_FILE_ACTIVITY_GET_PRIVATE (file_activity); + + e_activity_set_allow_cancel (E_ACTIVITY (file_activity), TRUE); + + cancellable = g_cancellable_new (); + e_file_activity_set_cancellable (file_activity, cancellable); + g_object_unref (cancellable); +} + +GType +e_file_activity_get_type (void) +{ + static GType type = 0; + + if (G_UNLIKELY (type == 0)) { + static const GTypeInfo type_info = { + sizeof (EFileActivityClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) file_activity_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EFileActivity), + 0, /* n_preallocs */ + (GInstanceInitFunc) file_activity_init, + NULL /* value_table */ + }; + + type = g_type_register_static ( + E_TYPE_ACTIVITY, "EFileActivity", &type_info, 0); + } + + return type; +} + +EActivity * +e_file_activity_new (const gchar *primary_text) +{ + return g_object_new ( + E_TYPE_FILE_ACTIVITY, + "primary-text", primary_text, NULL); +} + +EActivity * +e_file_activity_newv (const gchar *format, ...) +{ + EActivity *activity; + gchar *primary_text; + va_list args; + + va_start (args, format); + primary_text = g_strdup_vprintf (format, args); + activity = e_file_activity_new (primary_text); + g_free (primary_text); + va_end (args); + + return activity; +} + +GCancellable * +e_file_activity_get_cancellable (EFileActivity *file_activity) +{ + g_return_val_if_fail (E_IS_FILE_ACTIVITY (file_activity), NULL); + + return file_activity->priv->cancellable; +} + +void +e_file_activity_set_cancellable (EFileActivity *file_activity, + GCancellable *cancellable) +{ + g_return_if_fail (E_IS_FILE_ACTIVITY (file_activity)); + + if (cancellable != NULL) { + g_return_if_fail (G_IS_CANCELLABLE (cancellable)); + g_object_ref (cancellable); + } + + if (file_activity->priv->cancellable != NULL) { + g_signal_handler_disconnect ( + file_activity->priv->cancellable, + file_activity->priv->handler_id); + g_object_unref (file_activity->priv->cancellable); + file_activity->priv->handler_id = 0; + } + + file_activity->priv->cancellable = cancellable; + + if (cancellable != NULL) + file_activity->priv->handler_id = + g_signal_connect_swapped ( + cancellable, "cancelled", + G_CALLBACK (e_activity_cancel), + file_activity); + + g_object_notify (G_OBJECT (file_activity), "cancellable"); +} + +GFile * +e_file_activity_get_file (EFileActivity *file_activity) +{ + g_return_val_if_fail (E_IS_FILE_ACTIVITY (file_activity), NULL); + + return file_activity->priv->file; +} + +void +e_file_activity_set_file (EFileActivity *file_activity, + GFile *file) +{ + g_return_if_fail (E_IS_FILE_ACTIVITY (file_activity)); + + if (file != NULL) { + g_return_if_fail (G_IS_FILE (file)); + g_object_ref (file); + } + + if (file_activity->priv->file != NULL) + g_object_unref (file_activity->priv->file); + + file_activity->priv->file = file; + + g_object_notify (G_OBJECT (file_activity), "file"); +} + +GAsyncResult * +e_file_activity_get_result (EFileActivity *file_activity) +{ + g_return_val_if_fail (E_IS_FILE_ACTIVITY (file_activity), NULL); + + return file_activity->priv->result; +} + +void +e_file_activity_set_result (EFileActivity *file_activity, + GAsyncResult *result) +{ + g_return_if_fail (E_IS_FILE_ACTIVITY (file_activity)); + + if (result != NULL) { + g_return_if_fail (G_IS_ASYNC_RESULT (result)); + g_object_ref (result); + } + + if (file_activity->priv->result != NULL) + g_object_unref (file_activity->priv->result); + + file_activity->priv->result = result; + + g_object_notify (G_OBJECT (file_activity), "result"); +} + +void +e_file_activity_progress (goffset current_num_bytes, + goffset total_num_bytes, + gpointer activity) +{ + gdouble percent = -1.0; + + g_return_if_fail (E_IS_ACTIVITY (activity)); + + if (current_num_bytes > 0 && total_num_bytes > 0) + percent = (gdouble) current_num_bytes / total_num_bytes; + + e_activity_set_percent (activity, percent); +} diff --git a/widgets/misc/e-file-activity.h b/widgets/misc/e-file-activity.h new file mode 100644 index 0000000000..acd144dec0 --- /dev/null +++ b/widgets/misc/e-file-activity.h @@ -0,0 +1,83 @@ +/* + * e-file-activity.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_FILE_ACTIVITY_H +#define E_FILE_ACTIVITY_H + +#include <gio/gio.h> +#include <widgets/misc/e-activity.h> + +/* Standard GObject macros */ +#define E_TYPE_FILE_ACTIVITY \ + (e_file_activity_get_type ()) +#define E_FILE_ACTIVITY(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_FILE_ACTIVITY, EFileActivity)) +#define E_FILE_ACTIVITY_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_FILE_ACTIVITY, EFileActivityClass)) +#define E_IS_FILE_ACTIVITY(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_FILE_ACTIVITY)) +#define E_IS_FILE_ACTIVITY_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_FILE_ACTIVITY)) +#define E_FILE_ACTIVITY_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_FILE_ACTIVITY, EFileActivityClass)) + +G_BEGIN_DECLS + +typedef struct _EFileActivity EFileActivity; +typedef struct _EFileActivityClass EFileActivityClass; +typedef struct _EFileActivityPrivate EFileActivityPrivate; + +struct _EFileActivity { + EActivity parent; + EFileActivityPrivate *priv; +}; + +struct _EFileActivityClass { + EActivityClass parent_class; +}; + +GType e_file_activity_get_type (void); +EActivity * e_file_activity_new (const gchar *primary_text); +EActivity * e_file_activity_newv (const gchar *format, + ...) G_GNUC_PRINTF (1, 2); +GCancellable * e_file_activity_get_cancellable (EFileActivity *file_activity); +void e_file_activity_set_cancellable (EFileActivity *file_activity, + GCancellable *cancellable); +GFile * e_file_activity_get_file (EFileActivity *file_activity); +void e_file_activity_set_file (EFileActivity *file_activity, + GFile *file); +GAsyncResult * e_file_activity_get_result (EFileActivity *file_activity); +void e_file_activity_set_result (EFileActivity *file_activity, + GAsyncResult *result); + +/* This can be used as a GFileProgressCallback. */ +void e_file_activity_progress (goffset current_num_bytes, + goffset total_num_bytes, + gpointer activity); + +G_END_DECLS + +#endif /* E_FILE_ACTIVITY_H */ diff --git a/widgets/misc/e-filter-bar.c b/widgets/misc/e-filter-bar.c index a52756943c..2125bdf30d 100644 --- a/widgets/misc/e-filter-bar.c +++ b/widgets/misc/e-filter-bar.c @@ -25,26 +25,14 @@ #endif #include <string.h> +#include <glib/gi18n.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, @@ -52,59 +40,26 @@ enum { PROP_STATE, }; +static gpointer parent_class; /* 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, int response, void *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, int response, void *data) +rule_editor_destroyed (EFilterBar *filter_bar, GObject *deadbeef) { - 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); + filter_bar->save_dialog = NULL; + e_search_bar_set_menu_sensitive (E_SEARCH_BAR (filter_bar), E_FILTERBAR_SAVE_ID, TRUE); } static void rule_advanced_response (GtkWidget *dialog, int response, void *data) { - EFilterBar *efb = data; + EFilterBar *filter_bar = data; /* the below generates a compiler warning about incompatible pointer types */ - ESearchBar *esb = (ESearchBar *)efb; + ESearchBar *search_bar = (ESearchBar *)filter_bar; FilterRule *rule; if (response == GTK_RESPONSE_OK || response == GTK_RESPONSE_APPLY) { @@ -115,27 +70,29 @@ rule_advanced_response (GtkWidget *dialog, int response, void *data) if (!filter_rule_validate (rule)) return; - efb->current_query = rule; + filter_bar->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); + gtk_widget_modify_base (search_bar->entry, GTK_STATE_NORMAL, &(style->base[GTK_STATE_SELECTED])); + gtk_widget_modify_text (search_bar->entry, GTK_STATE_NORMAL, &(style->text[GTK_STATE_SELECTED])); + gtk_widget_modify_base (search_bar->icon_entry, GTK_STATE_NORMAL, &(style->base[GTK_STATE_SELECTED])); + gtk_widget_modify_base (search_bar->viewoption, GTK_STATE_NORMAL, &(style->base[GTK_STATE_SELECTED])); + e_search_bar_set_text (search_bar,_("Advanced Search")); + gtk_widget_set_sensitive (search_bar->clear_button, TRUE); + + g_signal_emit_by_name (efb, "search_activated"); 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); + if (!rule_context_find_rule (filter_bar->context, rule->name, rule->source)) + rule_context_add_rule (filter_bar->context, rule); /* FIXME: check return */ - rule_context_save (efb->context, efb->userrules); + rule_context_save (filter_bar->context, filter_bar->userrules); } } } else { - e_search_bar_set_item_id (esb, esb->last_search_option); + e_search_bar_set_item_id (search_bar, search_bar->last_search_option); } if (response != GTK_RESPONSE_APPLY) @@ -145,34 +102,26 @@ rule_advanced_response (GtkWidget *dialog, int response, void *data) 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); + /* mbarnes: converted */ } static void -do_advanced (ESearchBar *esb) +do_advanced (ESearchBar *search_bar) { - EFilterBar *efb = (EFilterBar *)esb; - - d(printf("Advanced search!\n")); + EFilterBar *filter_bar = (EFilterBar *)search_bar; - if (!efb->save_dialog && !efb->setquery) { + if (!filter_bar->save_dialog && !filter_bar->setquery) { GtkWidget *dialog, *w; FilterRule *rule; - if (efb->current_query) - rule = filter_rule_clone (efb->current_query); + if (filter_bar->current_query) + rule = filter_rule_clone (filter_bar->current_query); else { rule = filter_rule_new (); - efb->current_query = rule; + filter_bar->current_query = rule; } - w = filter_rule_get_widget (rule, efb->context); + w = filter_rule_get_widget (rule, filter_bar->context); filter_rule_set_source (rule, FILTER_SOURCE_INCOMING); gtk_container_set_border_width (GTK_CONTAINER (w), 12); @@ -182,7 +131,7 @@ do_advanced (ESearchBar *esb) GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OK, GTK_RESPONSE_OK, NULL); - efb->save_dialog = dialog; + filter_bar->save_dialog = dialog; gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE); gtk_window_set_resizable (GTK_WINDOW (dialog), TRUE); @@ -198,166 +147,105 @@ do_advanced (ESearchBar *esb) 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); + g_signal_connect (dialog, "response", G_CALLBACK (rule_advanced_response), filter_bar); + g_object_weak_ref ((GObject *) dialog, (GWeakNotify) rule_editor_destroyed, filter_bar); - e_search_bar_set_menu_sensitive (esb, E_FILTERBAR_SAVE_ID, FALSE); + e_search_bar_set_menu_sensitive (search_bar, E_FILTERBAR_SAVE_ID, FALSE); gtk_widget_show (dialog); } } static void -save_search_dialog (ESearchBar *esb) +save_search_dialog (ESearchBar *search_bar) { - FilterRule *rule; - char *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); + /* mbarnes: converted */ } static void -menubar_activated (ESearchBar *esb, int id, void *data) +menubar_activated (ESearchBar *search_bar, int id, void *data) { - EFilterBar *efb = (EFilterBar *)esb; + EFilterBar *filter_bar = (EFilterBar *)search_bar; 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); - } + /* mbarnes: converted */ break; case E_FILTERBAR_SAVE_ID: - if (efb->current_query && !efb->save_dialog) - save_search_dialog (esb); + if (filter_bar->current_query && !filter_bar->save_dialog) + save_search_dialog (search_bar); - d(printf("Save menu\n")); break; case E_FILTERBAR_ADVANCED_ID: - e_search_bar_set_item_id (esb, E_FILTERBAR_ADVANCED_ID); + e_search_bar_set_item_id (search_bar, 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 (""); + if (id >= filter_bar->menu_base && id < filter_bar->menu_base + filter_bar->menu_rules->len) { + filter_bar->current_query = (FilterRule *)filter_bar->menu_rules->pdata[id - filter_bar->menu_base]; - 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; + filter_bar->setquery = TRUE; + e_search_bar_set_item_id (search_bar, E_FILTERBAR_ADVANCED_ID); + filter_bar->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; + filter_bar->setquery = TRUE; + gtk_widget_modify_base (search_bar->entry , GTK_STATE_NORMAL, &(style->base[GTK_STATE_SELECTED] )); + gtk_widget_modify_text (search_bar->entry, GTK_STATE_NORMAL, &(style->text [GTK_STATE_SELECTED] )); + gtk_widget_modify_base (search_bar->icon_entry, GTK_STATE_NORMAL, &(style->base [GTK_STATE_SELECTED] )); + gtk_widget_modify_base (search_bar->viewoption, GTK_STATE_NORMAL, &(style->base [GTK_STATE_SELECTED] )); + e_search_bar_set_text (search_bar,_("Advanced Search")); + g_signal_emit_by_name (filter_bar, "search_activated", NULL); + filter_bar->setquery = FALSE; } else { return; } } - g_signal_stop_emission_by_name (esb, "menu_activated"); + g_signal_stop_emission_by_name (search_bar, "menu_activated"); } static void -option_changed (ESearchBar *esb, void *data) +option_changed (ESearchBar *search_bar, void *data) { - EFilterBar *efb = (EFilterBar *)esb; - int id = e_search_bar_get_item_id (esb); + EFilterBar *filter_bar = (EFilterBar *)search_bar; + int id = e_search_bar_get_item_id (search_bar); char *query; - d(printf("option changed, id = %d, setquery = %s %d\n", id, efb->setquery ? "true" : "false", esb->block_search)); - - if (esb->scopeitem_id == E_FILTERBAR_CURRENT_MESSAGE_ID) { - gtk_widget_set_sensitive (esb->option_button, FALSE); + if (search_bar->scopeitem_id == E_FILTERBAR_CURRENT_MESSAGE_ID) { + gtk_widget_set_sensitive (search_bar->option_button, FALSE); } else { - gtk_widget_set_sensitive (esb->option_button, TRUE); + gtk_widget_set_sensitive (search_bar->option_button, TRUE); } - if (efb->setquery) + if (filter_bar->setquery) return; switch (id) { case E_FILTERBAR_SAVE_ID: /* Fixme */ - /* save_search_dialog (esb); */ + /* save_search_dialog (search_bar); */ break; case E_FILTERBAR_ADVANCED_ID: - d(printf ("do_advanced\n")); - if (!esb->block_search) - do_advanced (esb); + if (!search_bar->block_search) + do_advanced (search_bar); 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); + if (id >= filter_bar->option_base && id < filter_bar->option_base + filter_bar->option_rules->len) { + filter_bar->current_query = (FilterRule *)filter_bar->option_rules->pdata[id - filter_bar->option_base]; + if (filter_bar->config && filter_bar->current_query) { + query = e_search_bar_get_text (search_bar); + filter_bar->config (filter_bar, filter_bar->current_query, id, query, filter_bar->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, ""); + gtk_widget_modify_base (search_bar->entry, GTK_STATE_NORMAL, NULL); + gtk_widget_modify_text (search_bar->entry, GTK_STATE_NORMAL, NULL); + gtk_widget_modify_base (search_bar->icon_entry, GTK_STATE_NORMAL, NULL); + filter_bar->current_query = NULL; + gtk_entry_set_text ((GtkEntry *)search_bar->entry, ""); } } } @@ -372,10 +260,10 @@ dup_item_no_subitems (ESearchBarItem *dest, } static GArray * -build_items (ESearchBar *esb, ESearchBarItem *items, int type, int *start, GPtrArray *rules) +build_items (ESearchBar *search_bar, ESearchBarItem *items, int type, int *start, GPtrArray *rules) { FilterRule *rule = NULL; - EFilterBar *efb = (EFilterBar *)esb; + EFilterBar *filter_bar = (EFilterBar *)search_bar; int id = 0, i; GArray *menu = g_array_new (FALSE, FALSE, sizeof (ESearchBarItem)); ESearchBarItem item = { NULL, -1, 2 }; @@ -405,7 +293,7 @@ build_items (ESearchBar *esb, ESearchBarItem *items, int type, int *start, GPtrA 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) { + if (rule_context_next_rule (filter_bar->context, rule, source) != NULL) { item.id = 0; item.text = NULL; item.type = 0; @@ -416,7 +304,7 @@ build_items (ESearchBar *esb, ESearchBarItem *items, int type, int *start, GPtrA } num = 1; - while ((rule = rule_context_next_rule (efb->context, rule, source))) { + while ((rule = rule_context_next_rule (filter_bar->context, rule, source))) { item.id = id++; if (type == 0 && num <= 10) { @@ -429,7 +317,7 @@ build_items (ESearchBar *esb, ESearchBarItem *items, int type, int *start, GPtrA if (g_slist_find(gtksux, rule) == NULL) { g_object_ref (rule); - g_signal_connect (rule, "changed", G_CALLBACK (rule_changed), efb); + g_signal_connect (rule, "changed", G_CALLBACK (rule_changed), filter_bar); } else { gtksux = g_slist_remove(gtksux, rule); } @@ -443,7 +331,7 @@ build_items (ESearchBar *esb, ESearchBarItem *items, int type, int *start, GPtrA next = gtksux->next; rule = gtksux->data; - g_signal_handlers_disconnect_by_func (rule, G_CALLBACK (rule_changed), efb); + g_signal_handlers_disconnect_by_func (rule, G_CALLBACK (rule_changed), filter_bar); g_object_unref (rule); g_slist_free_1(gtksux); @@ -486,13 +374,13 @@ free_built_items (GArray *menu) } static void -generate_menu (ESearchBar *esb, ESearchBarItem *items) +generate_menu (ESearchBar *search_bar, ESearchBarItem *items) { - EFilterBar *efb = (EFilterBar *)esb; + EFilterBar *filter_bar = (EFilterBar *)search_bar; GArray *menu; - menu = build_items (esb, items, 0, &efb->menu_base, efb->menu_rules); - ((ESearchBarClass *)parent_class)->set_menu (esb, (ESearchBarItem *)menu->data); + menu = build_items (search_bar, items, 0, &filter_bar->menu_base, filter_bar->menu_rules); + ((ESearchBarClass *)parent_class)->set_menu (search_bar, (ESearchBarItem *)menu->data); free_built_items (menu); } @@ -510,14 +398,14 @@ free_items (ESearchBarItem *items) /* Virtual methods */ static void -set_menu (ESearchBar *esb, ESearchBarItem *items) +set_menu (ESearchBar *search_bar, ESearchBarItem *items) { - EFilterBar *efb = E_FILTER_BAR (esb); + EFilterBar *filter_bar = E_FILTER_BAR (search_bar); ESearchBarItem *default_items; int i, num; - if (efb->default_items) - free_items (efb->default_items); + if (filter_bar->default_items) + free_items (filter_bar->default_items); for (num = 0; items[num].id != -1; num++) ; @@ -529,72 +417,72 @@ set_menu (ESearchBar *esb, ESearchBarItem *items) default_items[i].type = items[i].type; } - efb->default_items = default_items; + filter_bar->default_items = default_items; - generate_menu (esb, default_items); + generate_menu (search_bar, default_items); } static void -set_option (ESearchBar *esb, ESearchBarItem *items) +set_option (ESearchBar *search_bar, ESearchBarItem *items) { GArray *menu; - EFilterBar *efb = (EFilterBar *)esb; + EFilterBar *filter_bar = (EFilterBar *)search_bar; - menu = build_items (esb, items, 1, &efb->option_base, efb->option_rules); - ((ESearchBarClass *)parent_class)->set_option (esb, (ESearchBarItem *)menu->data); + menu = build_items (search_bar, items, 1, &filter_bar->option_base, filter_bar->option_rules); + ((ESearchBarClass *)parent_class)->set_option (search_bar, (ESearchBarItem *)menu->data); free_built_items (menu); - e_search_bar_set_item_id (esb, efb->option_base); + e_search_bar_set_item_id (search_bar, filter_bar->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); + EFilterBar *filter_bar = E_FILTER_BAR (user_data); + ESearchBar *search_bar = E_SEARCH_BAR (user_data); /* just generate whole menu again */ - generate_menu (esb, efb->default_items); + generate_menu (search_bar, filter_bar->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); + EFilterBar *filter_bar = E_FILTER_BAR (user_data); + ESearchBar *search_bar = E_SEARCH_BAR (user_data); /* just generate whole menu again */ - generate_menu (esb, efb->default_items); + generate_menu (search_bar, filter_bar->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); + EFilterBar *filter_bar = E_FILTER_BAR (user_data); + ESearchBar *search_bar = E_SEARCH_BAR (user_data); /* just generate whole menu again */ - generate_menu (esb, efb->default_items); + generate_menu (search_bar, filter_bar->default_items); } - -/* GtkObject methods. */ - static void -get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) +filter_bar_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) { - EFilterBar *efb = (EFilterBar *) object; - ESearchBar *esb = E_SEARCH_BAR (object); + EFilterBar *filter_bar = (EFilterBar *) object; + ESearchBar *search_bar = E_SEARCH_BAR (object); switch (property_id) { case PROP_QUERY: { - char *text = e_search_bar_get_text (E_SEARCH_BAR (efb)); + char *text = e_search_bar_get_text (E_SEARCH_BAR (filter_bar)); /* empty search text means searching turned off */ - if (efb->current_query && text && *text) { + if (filter_bar->current_query && text && *text) { GString *out = g_string_new (""); - filter_rule_build_code (efb->current_query, out); + filter_rule_build_code (filter_bar->current_query, out); g_value_take_string (value, out->str); g_string_free (out, FALSE); } else { @@ -611,32 +499,32 @@ get_property (GObject *object, guint property_id, GValue *value, GParamSpec *psp xmlNodePtr root, node; xmlDocPtr doc; - item_id = e_search_bar_get_item_id ((ESearchBar *) efb); + item_id = e_search_bar_get_item_id ((ESearchBar *) filter_bar); doc = xmlNewDoc ((const unsigned char *)"1.0"); root = xmlNewDocNode (doc, NULL, (const unsigned char *)"state", NULL); xmlDocSetRootElement (doc, root); - searchscope = e_search_bar_get_search_scope ((ESearchBar *) efb); - view_id = e_search_bar_get_viewitem_id ((ESearchBar *) efb); + searchscope = e_search_bar_get_search_scope ((ESearchBar *) filter_bar); + view_id = e_search_bar_get_viewitem_id ((ESearchBar *) filter_bar); if (searchscope < E_FILTERBAR_CURRENT_FOLDER_ID) - item_id = esb->last_search_option; + item_id = search_bar->last_search_option; if (item_id == E_FILTERBAR_ADVANCED_ID) { /* advanced query, save the filterbar state */ node = xmlNewChild (root, NULL, (const unsigned char *)"filter-bar", NULL); - sprintf (buf, "%d", esb->last_search_option); + sprintf (buf, "%d", search_bar->last_search_option); xmlSetProp (node, (const unsigned char *)"item_id", (unsigned char *)buf); sprintf (buf, "%d", searchscope); xmlSetProp (node, (const unsigned char *)"searchscope", (unsigned char *)buf); sprintf (buf, "%d", view_id); xmlSetProp (node, (const unsigned char *)"view_id", (unsigned char *)buf); - xmlAddChild (node, filter_rule_xml_encode (efb->current_query)); + xmlAddChild (node, filter_rule_xml_encode (filter_bar->current_query)); } else { /* simple query, save the searchbar state */ - text = e_search_bar_get_text ((ESearchBar *) efb); + text = e_search_bar_get_text ((ESearchBar *) filter_bar); node = xmlNewChild (root, NULL, (const unsigned char *)"search-bar", NULL); xmlSetProp (node, (const unsigned char *)"text", (unsigned char *)(text ? text : "")); @@ -684,10 +572,13 @@ xml_get_prop_int (xmlNodePtr node, const char *prop) } static void -set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) +filter_bar_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) { - EFilterBar *efb = (EFilterBar *) object; - ESearchBar *esb = E_SEARCH_BAR (object); + EFilterBar *filter_bar = (EFilterBar *) object; + ESearchBar *search_bar = E_SEARCH_BAR (object); xmlNodePtr root, node; const char *state; xmlDocPtr doc; @@ -725,43 +616,43 @@ set_property (GObject *object, guint property_id, const GValue *value, GParamSpe 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); + if (filter_rule_xml_decode (rule, node, filter_bar->context) != 0) { + gtk_widget_modify_base (E_SEARCH_BAR (filter_bar)->entry, GTK_STATE_NORMAL, NULL); + gtk_widget_modify_text (((ESearchBar *)filter_bar)->entry, GTK_STATE_NORMAL, NULL); + gtk_widget_modify_base (((ESearchBar *)filter_bar)->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])); + gtk_widget_set_sensitive (search_bar->clear_button, TRUE); + gtk_widget_modify_base (((ESearchBar *)filter_bar)->entry, GTK_STATE_NORMAL, &(style->base[GTK_STATE_SELECTED])); + gtk_widget_modify_text (((ESearchBar *)filter_bar)->entry, GTK_STATE_NORMAL, &(style->text[GTK_STATE_SELECTED])); + gtk_widget_modify_base (((ESearchBar *)filter_bar)->icon_entry, GTK_STATE_NORMAL, &(style->base[GTK_STATE_SELECTED])); + gtk_widget_modify_base (((ESearchBar *)filter_bar)->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) { - char *query = e_search_bar_get_text (esb); - efb->config (efb, efb->current_query, item_id, query, efb->config_data); + search_bar->block_search = TRUE; + e_search_bar_set_text (search_bar, _("Advanced Search")); + e_search_bar_set_item_menu ((ESearchBar *) filter_bar, item_id); + e_search_bar_set_search_scope ((ESearchBar *) filter_bar, scope); + search_bar->block_search = FALSE; + filter_bar->current_query = (FilterRule *)filter_bar->option_rules->pdata[item_id - filter_bar->option_base]; + if (filter_bar->config && filter_bar->current_query) { + char *query = e_search_bar_get_text (search_bar); + filter_bar->config (filter_bar, filter_bar->current_query, item_id, query, filter_bar->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; + e_search_bar_set_viewitem_id ((ESearchBar *) filter_bar, view_id); + filter_bar->current_query = rule; + filter_bar->setquery = TRUE; + e_search_bar_set_item_id ((ESearchBar *) filter_bar, E_FILTERBAR_ADVANCED_ID); + filter_bar->setquery = FALSE; break; } else if (!strcmp ((char *)node->name, "search-bar")) { @@ -776,36 +667,36 @@ set_property (GObject *object, guint property_id, const GValue *value, GParamSpe item_id = xml_get_prop_int (node, "item_id"); subitem_id = xml_get_prop_int (node, "subitem_id"); - esb->block_search = TRUE; + search_bar->block_search = TRUE; if (subitem_id >= 0) - e_search_bar_set_ids (E_SEARCH_BAR (efb), item_id, subitem_id); + e_search_bar_set_ids (E_SEARCH_BAR (filter_bar), item_id, subitem_id); else - e_search_bar_set_item_menu (E_SEARCH_BAR (efb), item_id); - esb->block_search = FALSE; + e_search_bar_set_item_menu (E_SEARCH_BAR (filter_bar), item_id); + search_bar->block_search = FALSE; view_id = xml_get_prop_int (node, "view_id"); - e_search_bar_set_viewitem_id (E_SEARCH_BAR (efb), view_id); + e_search_bar_set_viewitem_id (E_SEARCH_BAR (filter_bar), view_id); scope = xml_get_prop_int (node, "searchscope"); - e_search_bar_set_search_scope (E_SEARCH_BAR (efb), scope); + e_search_bar_set_search_scope (E_SEARCH_BAR (filter_bar), scope); text = (char *)xmlGetProp (node, (const unsigned char *)"text"); - e_search_bar_set_text (E_SEARCH_BAR (efb), text); + e_search_bar_set_text (E_SEARCH_BAR (filter_bar), 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])); + filter_bar->current_query = (FilterRule *)filter_bar->option_rules->pdata[item_id - filter_bar->option_base]; + if (filter_bar->config && filter_bar->current_query) + filter_bar->config (filter_bar, filter_bar->current_query, item_id, text, filter_bar->config_data); + gtk_widget_set_sensitive (search_bar->clear_button, TRUE); + gtk_widget_modify_base (((ESearchBar *)filter_bar)->entry, GTK_STATE_NORMAL, &(style->base[GTK_STATE_SELECTED])); + gtk_widget_modify_text (((ESearchBar *)filter_bar)->entry, GTK_STATE_NORMAL, &(style->text[GTK_STATE_SELECTED])); + gtk_widget_modify_base (((ESearchBar *)filter_bar)->icon_entry, GTK_STATE_NORMAL, &(style->base[GTK_STATE_SELECTED])); + gtk_widget_modify_base (((ESearchBar *)filter_bar)->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); + gtk_widget_modify_base (((ESearchBar *)filter_bar)->entry, GTK_STATE_NORMAL, NULL); + gtk_widget_modify_text (((ESearchBar *)filter_bar)->entry, GTK_STATE_NORMAL, NULL); + gtk_widget_modify_base (((ESearchBar *)filter_bar)->icon_entry, GTK_STATE_NORMAL, NULL); + e_search_bar_paint (search_bar); + filter_bar->current_query = (FilterRule *)filter_bar->option_rules->pdata[item_id - filter_bar->option_base]; + if (filter_bar->config && filter_bar->current_query) + filter_bar->config (filter_bar, filter_bar->current_query, item_id, "", filter_bar->config_data); } xmlFree (text); @@ -820,15 +711,15 @@ set_property (GObject *object, guint property_id, const GValue *value, GParamSpe 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); + e_search_bar_set_item_id ((ESearchBar *) filter_bar, 0); + e_search_bar_set_viewitem_id ((ESearchBar *) filter_bar, 0); + e_search_bar_set_search_scope ((ESearchBar *) filter_bar, 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; + filter_bar->setquery = TRUE; + g_signal_emit_by_name (filter_bar, "search_activated", NULL); + filter_bar->setquery = FALSE; break; default: @@ -837,22 +728,27 @@ set_property (GObject *object, guint property_id, const GValue *value, GParamSpe } } -static void clear_rules(EFilterBar *efb, GPtrArray *rules) +static void +filter_bar_clear_rules (EFilterBar *filter_bar, + GPtrArray *rules) { - int i; FilterRule *rule; + gint ii; - /* 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); + /* Clear out any data on old rules. */ + for (ii = 0; ii < rules->len; ii++) { + FilterRule *rule = rules->pdata[ii]; + + g_signal_handlers_disconnect_by_func ( + rule, G_CALLBACK (rule_changed), filter_bar); g_object_unref(rule); } + g_ptr_array_set_size (rules, 0); } static void -dispose (GObject *object) +filter_bar_dispose (GObject *object) { EFilterBar *bar; @@ -865,8 +761,8 @@ dispose (GObject *object) rule_context_save (bar->context, bar->userrules); if (bar->menu_rules != NULL) { - clear_rules(bar, bar->menu_rules); - clear_rules(bar, bar->option_rules); + filter_bar_clear_rules (bar, bar->menu_rules); + filter_bar_clear_rules (bar, bar->option_rules); g_ptr_array_free (bar->menu_rules, TRUE); g_ptr_array_free (bar->option_rules, TRUE); @@ -893,97 +789,97 @@ dispose (GObject *object) bar->default_items = NULL; } - (* G_OBJECT_CLASS (parent_class)->dispose) (object); + G_OBJECT_CLASS (parent_class)->dispose (object); } - static void -class_init (EFilterBarClass *klass) +class_init (EFilterBarClass *class) { - GObjectClass *object_class = (GObjectClass *) klass; - ESearchBarClass *esb_class = (ESearchBarClass *) klass; + GObjectClass *object_class; + ESearchBarClass *search_bar_class; 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 + parent_class = g_type_class_peek_parent (class); + + object_class = G_OBJECT_CLASS (object_class); + object_class->set_property = filter_bar_set_property; + object_class->get_property = filter_bar_get_property; + object_class->dispose = filter_bar_dispose; + + search_bar_class = E_SEARCH_BAR_CLASS (class); + search_bar_class->set_menu = set_menu; + search_bar_class->set_option = set_option; + + g_object_class_install_property ( + object_class, + PROP_QUERY, + g_param_spec_string ( + "query", + NULL, + NULL, + NULL, + G_PARAM_READABLE)); + + g_object_class_install_property ( + object_class, + PROP_STATE, + g_param_spec_string ( + "state", + NULL, + NULL, + NULL, + G_PARAM_READWRITE)); } static void -init (EFilterBar *efb) +filter_bar_init (EFilterBar *filter_bar) { - 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); + g_signal_connect (filter_bar, "menu_activated", G_CALLBACK (menubar_activated), NULL); + g_signal_connect (filter_bar, "query_changed", G_CALLBACK (option_changed), NULL); + g_signal_connect (filter_bar, "search_activated", G_CALLBACK (option_changed), NULL); - efb->menu_rules = g_ptr_array_new (); - efb->option_rules = g_ptr_array_new (); + filter_bar->menu_rules = g_ptr_array_new (); + filter_bar->option_rules = g_ptr_array_new (); } - -/* Object construction. */ - -EFilterBar * -e_filter_bar_new (RuleContext *context, - const char *systemrules, - const char *userrules, - EFilterBarConfigRule config, - void *data) +GType +e_filter_bar_get_type (void) { - EFilterBar *bar; + static GType type = 0; - bar = g_object_new (e_filter_bar_get_type (), NULL); + if (G_UNLIKELY (type == 0)) { + static const GTypeInfo type_info = { + sizeof (EFilterBarClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) filter_bar_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EFilterBar), + 0, /* n_preallocs */ + (GInstanceInitFunc) filter_bar_init, + NULL /* value_table */ + }; - e_filter_bar_new_construct (context, systemrules, userrules, config, data, bar); + type = g_type_register_static ( + E_TYPE_SEARCH_BAR, "EFilterBar", &type_info, 0); + } - return bar; + return type; } - -void -e_filter_bar_new_construct (RuleContext *context, - const char *systemrules, - const char *userrules, +EFilterBar * +e_filter_bar_new (RuleContext *context, + const gchar *systemrules, + const gchar *userrules, EFilterBarConfigRule config, - void *data ,EFilterBar *bar ) + gpointer data) { - ESearchBarItem item = { NULL, -1, 0 }; + EFilterBar *bar; + + bar = g_object_new (E_TYPE_FILTER_BAR, NULL); - bar->context = context; - g_object_ref (context); + bar->context = g_object_ref (context); bar->config = config; bar->config_data = data; @@ -995,35 +891,8 @@ e_filter_bar_new_construct (RuleContext *context, 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; + return bar; } diff --git a/widgets/misc/e-filter-bar.h b/widgets/misc/e-filter-bar.h index e1d4fc7def..edc20e2fec 100644 --- a/widgets/misc/e-filter-bar.h +++ b/widgets/misc/e-filter-bar.h @@ -20,8 +20,8 @@ * */ -#ifndef __E_FILTER_BAR_H__ -#define __E_FILTER_BAR_H__ +#ifndef E_FILTER_BAR_H +#define E_FILTER_BAR_H #include <gtk/gtk.h> #include <camel/camel-vee-folder.h> @@ -32,11 +32,6 @@ #include "filter/rule-context.h" #include "filter/filter-rule.h" -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - /* EFilterBar - A filter rule driven search bar. * * The following arguments are available: @@ -47,14 +42,29 @@ extern "C" { * 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; +/* Standard GObject macros */ +#define E_TYPE_FILTER_BAR \ + (e_filter_bar_get_type ()) +#define E_FILTER_BAR(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_FILTER_BAR, EFilterBar)) +#define E_FILTER_BAR_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_FILTER_BAR, EFilterBarClass)) +#define E_IS_FILTER_BAR(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_FILTER_BAR)) +#define E_IS_FILTER_BAR_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((obj), E_TYPE_FILTER_BAR)) +#define E_FILTER_BAR_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_FILTER_BAR, EFilterBarClass)) + +G_BEGIN_DECLS + +typedef struct _EFilterBar EFilterBar; +typedef struct _EFilterBarClass EFilterBarClass; typedef void (*EFilterBarConfigRule)(EFilterBar *, FilterRule *rule, int id, const char *query, void *data); @@ -82,8 +92,7 @@ struct _EFilterBar { CamelOperation *account_search_cancel; }; -struct _EFilterBarClass -{ +struct _EFilterBarClass { ESearchBarClass parent_class; }; @@ -104,10 +113,10 @@ enum { #define E_FILTERBAR_SAVE { N_("_Save Search..."), E_FILTERBAR_SAVE_ID, 0 } #define E_FILTERBAR_EDIT { N_("_Edit Saved Searches..."), E_FILTERBAR_EDIT_ID, 0 } #define E_FILTERBAR_ADVANCED { N_("_Advanced Search..."), E_FILTERBAR_ADVANCED_ID, 0 } -#define E_FILTERBAR_ALL_ACCOUNTS { N_("All Accounts"), E_FILTERBAR_ALL_ACCOUNTS_ID, ESB_ITEMTYPE_RADIO } -#define E_FILTERBAR_CURRENT_ACCOUNT { N_("Current Account"), E_FILTERBAR_CURRENT_ACCOUNT_ID, ESB_ITEMTYPE_RADIO } -#define E_FILTERBAR_CURRENT_FOLDER { N_("Current Folder"), E_FILTERBAR_CURRENT_FOLDER_ID, ESB_ITEMTYPE_RADIO } -#define E_FILTERBAR_CURRENT_MESSAGE { N_("Current Message"), E_FILTERBAR_CURRENT_MESSAGE_ID, ESB_ITEMTYPE_RADIO } +#define E_FILTERBAR_ALL_ACCOUNTS { N_("All Accounts"), E_FILTERBAR_ALL_ACCOUNTS_ID } +#define E_FILTERBAR_CURRENT_ACCOUNT { N_("Current Account"), E_FILTERBAR_CURRENT_ACCOUNT_ID } +#define E_FILTERBAR_CURRENT_FOLDER { N_("Current Folder"), E_FILTERBAR_CURRENT_FOLDER_ID } +#define E_FILTERBAR_CURRENT_MESSAGE { N_("Current Message"), E_FILTERBAR_CURRENT_MESSAGE_ID } #define E_FILTERBAR_SEPARATOR { NULL, 0, 0 } #ifdef JUST_FOR_TRANSLATORS @@ -119,23 +128,13 @@ const char * strings[] = { #endif -GType e_filter_bar_get_type (void); - -EFilterBar *e_filter_bar_new (RuleContext *context, - const char *systemrules, - const char *userrules, - EFilterBarConfigRule config, - void *data); -void -e_filter_bar_new_construct (RuleContext *context, - const char *systemrules, - const char *userrules, - EFilterBarConfigRule config, - void *data ,EFilterBar *bar ); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ +GType e_filter_bar_get_type (void); +EFilterBar * e_filter_bar_new (RuleContext *context, + const gchar *systemrules, + const gchar *userrules, + EFilterBarConfigRule config, + gpointer data); +G_END_DECLS -#endif /* __E_FILTER_BAR_H__ */ +#endif /* E_FILTER_BAR_H */ diff --git a/widgets/misc/e-icon-entry.c b/widgets/misc/e-icon-entry.c index 7f0dbaaaee..cfcce8f8c5 100644 --- a/widgets/misc/e-icon-entry.c +++ b/widgets/misc/e-icon-entry.c @@ -32,25 +32,75 @@ * */ -#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)) +#define E_ICON_ENTRY_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_ICON_ENTRY, EIconEntryPrivate)) -struct _EIconEntryPrivate -{ +struct _EIconEntryPrivate { + GtkStateType visual_state; + GtkWidget *entry; GtkWidget *hbox; }; -static GtkWidgetClass *parent_class = NULL; +enum { + PROP_0, + PROP_VISUAL_STATE +}; -/* private helper functions */ +static gpointer parent_class; + +static void +icon_entry_proxy_set_cursor (GtkWidget *widget, + GdkEventCrossing *event) +{ + if (event->type == GDK_ENTER_NOTIFY) { + GdkCursor *cursor; + + cursor = gdk_cursor_new (GDK_HAND1); + gdk_window_set_cursor (widget->window, cursor); + gdk_cursor_unref (cursor); + } else + gdk_window_set_cursor (widget->window, NULL); +} +static GtkWidget * +icon_entry_create_proxy (GtkAction *action) +{ + GtkWidget *proxy; + GtkWidget *widget; + gchar *tooltip; + + proxy = gtk_event_box_new (); + gtk_event_box_set_visible_window (GTK_EVENT_BOX (proxy), FALSE); + gtk_container_set_border_width (GTK_CONTAINER (proxy), 2); + gtk_widget_show (proxy); + + widget = gtk_action_create_icon (action, GTK_ICON_SIZE_MENU); + gtk_container_add (GTK_CONTAINER (proxy), widget); + gtk_widget_show (widget); + + g_object_get (action, "tooltip", &tooltip, NULL); + gtk_widget_set_tooltip_text (proxy, tooltip); + g_free (tooltip); + + g_signal_connect_swapped ( + proxy, "button-press-event", + G_CALLBACK (gtk_action_activate), action); + g_signal_connect_after ( + proxy, "enter-notify-event", + G_CALLBACK (icon_entry_proxy_set_cursor), NULL); + g_signal_connect_after ( + proxy, "leave-notify-event", + G_CALLBACK (icon_entry_proxy_set_cursor), NULL); + + return proxy; +} static gboolean -entry_focus_change_cb (GtkWidget *widget, - GdkEventFocus *event, - GtkWidget *entry) +icon_entry_focus_change_cb (GtkWidget *widget, + GdkEventFocus *event, + GtkWidget *entry) { gtk_widget_queue_draw (entry); @@ -58,111 +108,137 @@ entry_focus_change_cb (GtkWidget *widget, } static void -e_icon_entry_get_borders (GtkWidget *widget, - GtkWidget *entry, - int *xborder, - int *yborder) +icon_entry_get_borders (GtkWidget *widget, + GtkWidget *entry, + gint *xborder, + gint *yborder) { - int focus_width; + 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); + 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) - { + if (!interior_focus) { *xborder += focus_width; *yborder += focus_width; } } static void -e_icon_entry_paint (GtkWidget *widget, - GdkEventExpose *event) +icon_entry_paint (GtkWidget *widget, + GdkEventExpose *event) { EIconEntry *entry = E_ICON_ENTRY (widget); - GtkWidget *entry_widget = entry->entry; + GtkWidget *entry_widget = entry->priv->entry; int 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); + 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) - { + 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_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); + 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) - { + 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); + 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 +icon_entry_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_VISUAL_STATE: + e_icon_entry_set_visual_state ( + E_ICON_ENTRY (object), + g_value_get_enum (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} static void -e_icon_entry_init (EIconEntry *entry) +icon_entry_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) { - EIconEntryPrivate *priv; - GtkWidget *widget = (GtkWidget *) entry; + switch (property_id) { + case PROP_VISUAL_STATE: + g_value_set_enum ( + value, e_icon_entry_get_visual_state ( + E_ICON_ENTRY (object))); + return; + } - priv = entry->priv = E_ICON_ENTRY_GET_PRIVATE (entry); + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} - GTK_WIDGET_UNSET_FLAGS (widget, GTK_NO_WINDOW); +static void +icon_entry_dispose (GObject *object) +{ + EIconEntryPrivate *priv; - priv->hbox = gtk_hbox_new (FALSE, /* FIXME */ 0); - gtk_container_add (GTK_CONTAINER (entry), priv->hbox); + priv = E_ICON_ENTRY_GET_PRIVATE (object); - 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); + if (priv->entry != NULL) { + g_object_unref (priv->entry); + priv->entry = NULL; + } - /* 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); + if (priv->hbox != NULL) { + g_object_unref (priv->hbox); + priv->hbox = NULL; + } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); } static void -e_icon_entry_realize (GtkWidget *widget) +icon_entry_realize (GtkWidget *widget) { GdkWindowAttr attributes; gint attributes_mask; @@ -185,34 +261,41 @@ e_icon_entry_realize (GtkWidget *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); + 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); + gtk_style_set_background ( + widget->style, widget->window, GTK_STATE_NORMAL); } static void -e_icon_entry_size_request (GtkWidget *widget, - GtkRequisition *requisition) +icon_entry_size_request (GtkWidget *widget, + GtkRequisition *requisition) { - EIconEntry *entry = E_ICON_ENTRY (widget); - GtkContainer *container = GTK_CONTAINER (widget); - GtkBin *bin = GTK_BIN (widget); - int xborder, yborder; + EIconEntryPrivate *priv; + GtkContainer *container; + GtkWidget *child; + gint xborder, yborder; - requisition->width = requisition->height = container->border_width * 2; + priv = E_ICON_ENTRY_GET_PRIVATE (widget); + container = GTK_CONTAINER (widget); - gtk_widget_ensure_style (entry->entry); - e_icon_entry_get_borders (widget, entry->entry, &xborder, &yborder); + requisition->width = container->border_width * 2; + requisition->height = container->border_width * 2; - if (GTK_WIDGET_VISIBLE (bin->child)) - { + gtk_widget_ensure_style (priv->entry); + icon_entry_get_borders (widget, priv->entry, &xborder, &yborder); + + child = GTK_BIN (widget)->child; + if (GTK_WIDGET_VISIBLE (child)) { GtkRequisition child_requisition; - gtk_widget_size_request (bin->child, &child_requisition); + gtk_widget_size_request (child, &child_requisition); requisition->width += child_requisition.width; requisition->height += child_requisition.height; } @@ -222,68 +305,126 @@ e_icon_entry_size_request (GtkWidget *widget, } static void -e_icon_entry_size_allocate (GtkWidget *widget, - GtkAllocation *allocation) +icon_entry_size_allocate (GtkWidget *widget, + GtkAllocation *allocation) { - EIconEntry *entry = E_ICON_ENTRY (widget); - GtkContainer *container = GTK_CONTAINER (widget); - GtkBin *bin = GTK_BIN (widget); + EIconEntryPrivate *priv; + GtkContainer *container; GtkAllocation child_allocation; - int xborder, yborder; + gint xborder, yborder; + gint width, height; + + priv = E_ICON_ENTRY_GET_PRIVATE (widget); + container = GTK_CONTAINER (widget); widget->allocation = *allocation; - e_icon_entry_get_borders (widget, entry->entry, &xborder, &yborder); + icon_entry_get_borders (widget, priv->entry, &xborder, &yborder); + + if (GTK_WIDGET_REALIZED (widget)) { + width = allocation->width - container->border_width * 2; + height = allocation->height - container->border_width * 2; - 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.width = MAX (width, 0); + child_allocation.height = MAX (height, 0); + + gdk_window_move_resize ( + widget->window, + allocation->x + child_allocation.x, + allocation->y + child_allocation.y, + child_allocation.width, + child_allocation.height); } + width = allocation->width - (container->border_width + xborder) * 2; + height = allocation->height - (container->border_width + yborder) * 2; + 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); + child_allocation.width = MAX (width, 0); + child_allocation.height = MAX (height, 0); - gtk_widget_size_allocate (bin->child, &child_allocation); + gtk_widget_size_allocate (GTK_BIN (widget)->child, &child_allocation); } static gboolean -e_icon_entry_expose (GtkWidget *widget, - GdkEventExpose *event) +icon_entry_expose (GtkWidget *widget, + GdkEventExpose *event) { - if (GTK_WIDGET_DRAWABLE (widget) && - event->window == widget->window) - { - e_icon_entry_paint (widget, event); - } + if (GTK_WIDGET_DRAWABLE (widget) && event->window == widget->window) + icon_entry_paint (widget, event); - return parent_class->expose_event (widget, event); + /* Chain up to parent's expose() method. */ + return GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event); } static void -e_icon_entry_class_init (EIconEntryClass *klass) +icon_entry_class_init (EIconEntryClass *class) { - 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; + GObjectClass *object_class; + GtkWidgetClass *widget_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EIconEntryPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = icon_entry_set_property; + object_class->get_property = icon_entry_get_property; + object_class->dispose = icon_entry_dispose; + + widget_class = GTK_WIDGET_CLASS (class); + widget_class->realize = icon_entry_realize; + widget_class->size_request = icon_entry_size_request; + widget_class->size_allocate = icon_entry_size_allocate; + widget_class->expose_event = icon_entry_expose; + + g_object_class_install_property ( + object_class, + PROP_VISUAL_STATE, + g_param_spec_enum ( + "visual-state", + NULL, + NULL, + GTK_TYPE_STATE_TYPE, + GTK_STATE_NORMAL, + G_PARAM_READWRITE)); +} - g_type_class_add_private (object_class, sizeof (EIconEntryPrivate)); +static void +icon_entry_init (EIconEntry *icon_entry) +{ + GtkWidget *widget; + GtkWidget *container; + + icon_entry->priv = E_ICON_ENTRY_GET_PRIVATE (icon_entry); + icon_entry->priv->visual_state = GTK_STATE_NORMAL; + + GTK_WIDGET_UNSET_FLAGS (icon_entry, GTK_NO_WINDOW); + + widget = gtk_hbox_new (FALSE, 0); + gtk_container_add (GTK_CONTAINER (icon_entry), widget); + icon_entry->priv->hbox = g_object_ref (widget); + gtk_widget_show (widget); + + container = widget; + + widget = gtk_entry_new (); + gtk_entry_set_has_frame (GTK_ENTRY (widget), FALSE); + gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0); + icon_entry->priv->entry = g_object_ref (widget); + gtk_widget_show (widget); + + /* 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 ( + widget, "focus-in-event", + G_CALLBACK (icon_entry_focus_change_cb), icon_entry); + g_signal_connect_after ( + widget, "focus-out-event", + G_CALLBACK (icon_entry_focus_change_cb), icon_entry); } GType @@ -293,92 +434,110 @@ e_icon_entry_get_type (void) if (G_UNLIKELY (type == 0)) { - static const GTypeInfo our_info = - { + static const GTypeInfo type_info = { sizeof (EIconEntryClass), - NULL, - NULL, - (GClassInitFunc) e_icon_entry_class_init, - NULL, - NULL, + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) icon_entry_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ sizeof (EIconEntry), - 0, - (GInstanceInitFunc) e_icon_entry_init + 0, /* n_preallocs */ + (GInstanceInitFunc) icon_entry_init, + NULL /* value_table */ }; - type = g_type_register_static (GTK_TYPE_BIN, - "EIconEntry", - &our_info, 0); + type = g_type_register_static ( + GTK_TYPE_BIN, "EIconEntry", &type_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) +GtkWidget * +e_icon_entry_get_entry (EIconEntry *icon_entry) { - EIconEntryPrivate *priv; + g_return_val_if_fail (E_IS_ICON_ENTRY (icon_entry), NULL); - g_return_if_fail (E_IS_ICON_ENTRY (entry)); + return icon_entry->priv->entry; +} - priv = entry->priv; +void +e_icon_entry_add_action_start (EIconEntry *icon_entry, + GtkAction *action) +{ + GtkWidget *proxy; + GtkBox *box; - 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); - } + g_return_if_fail (E_IS_ICON_ENTRY (icon_entry)); + g_return_if_fail (GTK_IS_ACTION (action)); + + box = GTK_BOX (icon_entry->priv->hbox); + proxy = icon_entry_create_proxy (action); + gtk_box_pack_start (box, proxy, FALSE, FALSE, 2); + gtk_box_reorder_child (box, proxy, 0); } -static void -set_cursor (GtkWidget *widget, GdkEventCrossing *event, gpointer dummy) +void +e_icon_entry_add_action_end (EIconEntry *icon_entry, + GtkAction *action) { + GtkWidget *proxy; + GtkBox *box; + + g_return_if_fail (E_IS_ICON_ENTRY (icon_entry)); + g_return_if_fail (GTK_IS_ACTION (action)); - 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)); + box = GTK_BOX (icon_entry->priv->hbox); + proxy = icon_entry_create_proxy (action); + gtk_box_pack_end (box, proxy, FALSE, FALSE, 2); +} +GtkStateType +e_icon_entry_get_visual_state (EIconEntry *icon_entry) +{ + g_return_val_if_fail (E_IS_ICON_ENTRY (icon_entry), GTK_STATE_NORMAL); + return icon_entry->priv->visual_state; } -GtkWidget * -e_icon_entry_create_button (const char *stock) +void +e_icon_entry_set_visual_state (EIconEntry *icon_entry, + GtkStateType visual_state) { - GtkWidget *eventbox; - GtkWidget *image; + GtkWidget *widget; + const GdkColor *base_color; + const GdkColor *text_color; - 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); + g_return_if_fail (E_IS_ICON_ENTRY (icon_entry)); - image = gtk_image_new_from_stock (stock, GTK_ICON_SIZE_MENU); - gtk_container_add (GTK_CONTAINER (eventbox), image); + if (visual_state == GTK_STATE_NORMAL) { + base_color = NULL; + text_color = NULL; + } else { + GtkStyle *style; - g_signal_connect_after (eventbox, "enter-notify-event", (GCallback) set_cursor, NULL); - g_signal_connect_after (eventbox, "leave-notify-event", (GCallback) set_cursor, NULL); + style = gtk_widget_get_default_style (); + base_color = &style->base[visual_state]; + text_color = &style->text[visual_state]; + } - return eventbox; -} + widget = GTK_WIDGET (icon_entry); + gtk_widget_modify_base (widget, GTK_STATE_NORMAL, base_color); -GtkWidget * -e_icon_entry_get_entry (EIconEntry *entry) -{ - g_return_val_if_fail (E_IS_ICON_ENTRY (entry), NULL); + widget = icon_entry->priv->entry; + gtk_widget_modify_base (widget, GTK_STATE_NORMAL, base_color); + gtk_widget_modify_text (widget, GTK_STATE_NORMAL, text_color); + + widget = icon_entry->priv->hbox; + gtk_widget_modify_base (widget, GTK_STATE_NORMAL, base_color); - return entry->entry; + icon_entry->priv->visual_state = visual_state; + g_object_notify (G_OBJECT (icon_entry), "visual-state"); } diff --git a/widgets/misc/e-icon-entry.h b/widgets/misc/e-icon-entry.h index 894cb16c4f..65aff61978 100644 --- a/widgets/misc/e-icon-entry.h +++ b/widgets/misc/e-icon-entry.h @@ -41,44 +41,50 @@ 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)) - +/* Standard GObject macros */ +#define E_TYPE_ICON_ENTRY \ + (e_icon_entry_get_type()) +#define E_ICON_ENTRY(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_ICON_ENTRY, EIconEntry)) +#define E_ICON_ENTRY_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_ICON_ENTRY, EIconEntryClass)) +#define E_IS_ICON_ENTRY(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_ICON_ENTRY)) +#define E_IS_ICON_ENTRY_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_ICON_ENTRY)) +#define E_ICON_ENTRY_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_ICON_ENTRY, EIconEntryClass)) + +typedef struct _EIconEntry EIconEntry; typedef struct _EIconEntryClass EIconEntryClass; -typedef struct _EIconEntry EIconEntry; -typedef struct _EIconEntryPrivate EIconEntryPrivate; - -struct _EIconEntryClass -{ - GtkBinClass parent_class; -}; - +typedef struct _EIconEntryPrivate EIconEntryPrivate; + struct _EIconEntry { - GtkBin parent_object; - - /*< public >*/ - GtkWidget *entry; - - /*< private >*/ + GtkBin parent; 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); +struct _EIconEntryClass +{ + GtkBinClass parent_class; +}; -GtkWidget *e_icon_entry_create_button (const char *stock); +GType e_icon_entry_get_type (void); +GtkWidget * e_icon_entry_new (void); +GtkWidget * e_icon_entry_get_entry (EIconEntry *entry); +void e_icon_entry_add_action_start (EIconEntry *entry, + GtkAction *action); +void e_icon_entry_add_action_end (EIconEntry *entry, + GtkAction *action); +GtkStateType e_icon_entry_get_visual_state (EIconEntry *entry); +void e_icon_entry_set_visual_state (EIconEntry *entry, + GtkStateType visual_state); G_END_DECLS diff --git a/widgets/misc/e-info-label.c b/widgets/misc/e-info-label.c deleted file mode 100644 index e1959607fb..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 int -el_expose_event(GtkWidget *w, GdkEventExpose *event) -{ - int 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 int -get_text_full_width (GtkWidget *label) -{ - PangoLayout *layout; - PangoRectangle rect; - int 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; - int 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 char *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 char *location, const char *info) -{ - gchar *markup; - - if (el->location == NULL) { - el->location = gtk_label_new (NULL); - el->info = gtk_label_new (NULL); - - gtk_label_set_ellipsize (GTK_LABEL (el->location), PANGO_ELLIPSIZE_END); - gtk_misc_set_alignment (GTK_MISC (el->location), 0.0, 0.5); - gtk_misc_set_padding (GTK_MISC (el->location), 0, 6); - - gtk_label_set_ellipsize (GTK_LABEL (el->info), PANGO_ELLIPSIZE_MIDDLE); - gtk_misc_set_alignment (GTK_MISC (el->info), 1.0, 0.5); - gtk_misc_set_padding (GTK_MISC (el->info), 0, 6); - - gtk_widget_show (el->location); - gtk_widget_show (el->info); - - gtk_box_pack_start ( - GTK_BOX (el), GTK_WIDGET (el->location), - TRUE, TRUE, 0); - gtk_box_pack_end ( - GTK_BOX (el), GTK_WIDGET (el->info), - TRUE, TRUE, 6); - gtk_widget_set_state (GTK_WIDGET (el), GTK_STATE_ACTIVE); - } - - markup = g_markup_printf_escaped ("<b>%s</b>", location); - gtk_label_set_markup (GTK_LABEL (el->location), markup); - g_free (markup); - - markup = g_markup_printf_escaped ("<small>%s</small>", info); - gtk_label_set_markup (GTK_LABEL (el->info), markup); - g_free (markup); -} - diff --git a/widgets/misc/e-info-label.h b/widgets/misc/e-info-label.h deleted file mode 100644 index 905a39b0ca..0000000000 --- a/widgets/misc/e-info-label.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see <http://www.gnu.org/licenses/> - * - * - * Authors: - * Michael Zucchi <notzed@ximian.com> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef _E_INFO_LABEL_H -#define _E_INFO_LABEL_H - -#include <gtk/gtk.h> - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#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; - - struct _GtkWidget *location; - struct _GtkWidget *info; -}; - -struct _EInfoLabelClass { - GtkHBoxClass parent_class; -}; - -GType e_info_label_get_type(void); - -GtkWidget *e_info_label_new(const char *icon); -void e_info_label_set_info(EInfoLabel *, const char *loc, const char *info); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* ! _E_INFO_LABEL_H */ diff --git a/widgets/misc/e-menu-tool-button.c b/widgets/misc/e-menu-tool-button.c new file mode 100644 index 0000000000..5e87de8175 --- /dev/null +++ b/widgets/misc/e-menu-tool-button.c @@ -0,0 +1,157 @@ +/* + * e-menu-tool-button.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-menu-tool-button.h" + +static gpointer parent_class; + +static GtkWidget * +menu_tool_button_clone_image (GtkWidget *source) +{ + GtkIconSize size; + GtkImageType image_type; + const gchar *icon_name; + + /* XXX This isn't general purpose because it requires that the + * source image be using a named icon. Somewhat surprised + * GTK+ doesn't offer something like this. */ + image_type = gtk_image_get_storage_type (GTK_IMAGE (source)); + g_return_val_if_fail (image_type == GTK_IMAGE_ICON_NAME, NULL); + gtk_image_get_icon_name (GTK_IMAGE (source), &icon_name, &size); + + return gtk_image_new_from_icon_name (icon_name, size); +} + +static GtkMenuItem * +menu_tool_button_get_first_menu_item (GtkMenuToolButton *menu_tool_button) +{ + GtkWidget *menu; + GList *children; + + menu = gtk_menu_tool_button_get_menu (menu_tool_button); + if (!GTK_IS_MENU (menu)) + return NULL; + + /* XXX GTK+ 2.12 provides no accessor function. */ + children = GTK_MENU_SHELL (menu)->children; + if (children == NULL) + return NULL; + + return GTK_MENU_ITEM (children->data); +} + +static void +menu_tool_button_update_button (GtkToolButton *tool_button) +{ + GtkMenuItem *menu_item; + GtkMenuToolButton *menu_tool_button; + GtkImageMenuItem *image_menu_item; + GtkAction *action; + GtkWidget *image; + gchar *tooltip = NULL; + + menu_tool_button = GTK_MENU_TOOL_BUTTON (tool_button); + menu_item = menu_tool_button_get_first_menu_item (menu_tool_button); + if (!GTK_IS_IMAGE_MENU_ITEM (menu_item)) + return; + + image_menu_item = GTK_IMAGE_MENU_ITEM (menu_item); + image = gtk_image_menu_item_get_image (image_menu_item); + if (!GTK_IS_IMAGE (image)) + return; + + image = menu_tool_button_clone_image (image); + gtk_tool_button_set_icon_widget (tool_button, image); + gtk_widget_show (image); + + /* If the menu item is a proxy for a GtkAction, extract + * the action's tooltip and use it as our own tooltip. */ + action = gtk_widget_get_action (GTK_WIDGET (menu_item)); + if (action != NULL) + g_object_get (action, "tooltip", &tooltip, NULL); + gtk_widget_set_tooltip_text (GTK_WIDGET (tool_button), tooltip); + g_free (tooltip); +} + +static void +menu_tool_button_clicked (GtkToolButton *tool_button) +{ + GtkMenuItem *menu_item; + GtkMenuToolButton *menu_tool_button; + + menu_tool_button = GTK_MENU_TOOL_BUTTON (tool_button); + menu_item = menu_tool_button_get_first_menu_item (menu_tool_button); + + if (GTK_IS_MENU_ITEM (menu_item)) + gtk_menu_item_activate (menu_item); +} + +static void +menu_tool_button_class_init (EMenuToolButtonClass *class) +{ + GtkToolButtonClass *tool_button_class; + + parent_class = g_type_class_peek_parent (class); + + tool_button_class = GTK_TOOL_BUTTON_CLASS (class); + tool_button_class->clicked = menu_tool_button_clicked; +} + +static void +menu_tool_button_init (EMenuToolButton *button) +{ + g_signal_connect ( + button, "notify::menu", + G_CALLBACK (menu_tool_button_update_button), NULL); +} + +GType +e_menu_tool_button_get_type (void) +{ + static GType type = 0; + + if (G_UNLIKELY (type == 0)) { + const GTypeInfo type_info = { + sizeof (EMenuToolButtonClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) menu_tool_button_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EMenuToolButton), + 0, /* n_preallocs */ + (GInstanceInitFunc) menu_tool_button_init, + NULL /* value_table */ + }; + + type = g_type_register_static ( + GTK_TYPE_MENU_TOOL_BUTTON, "EMenuToolButton", + &type_info, 0); + } + + return type; +} + +GtkToolItem * +e_menu_tool_button_new (const gchar *label) +{ + return g_object_new (E_TYPE_MENU_TOOL_BUTTON, "label", label, NULL); +} diff --git a/widgets/misc/e-menu-tool-button.h b/widgets/misc/e-menu-tool-button.h new file mode 100644 index 0000000000..b10cf3a62f --- /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 0d5594cf66..0000000000 --- a/widgets/misc/e-multi-config-dialog.c +++ /dev/null @@ -1,374 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see <http://www.gnu.org/licenses/> - * - * - * Authors: - * Ettore Perazzoli <ettore@ximian.com> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "e-multi-config-dialog.h" - -#include <e-util/e-util.h> -#include <table/e-table-scrolled.h> -#include <table/e-table-memory-store.h> -#include <table/e-cell-pixbuf.h> -#include <table/e-cell-vbox.h> -#include <table/e-cell-text.h> - -#define SWITCH_PAGE_INTERVAL 250 - -struct _EMultiConfigDialogPrivate { - GSList *pages; - - GtkWidget *list_e_table; - ETableModel *list_e_table_model; - - GtkWidget *notebook; - - int set_page_timeout_id; - int set_page_timeout_page; -}; - -G_DEFINE_TYPE (EMultiConfigDialog, e_multi_config_dialog, GTK_TYPE_DIALOG) - - -/* ETable stuff. */ - -static char *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 char *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 int -set_page_timeout_callback (void *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, - int row, - void *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, int 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 char *title, - const char *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, int 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 462d593c81..0000000000 --- a/widgets/misc/e-multi-config-dialog.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_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> - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#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 char *title, - const char *description, - GdkPixbuf *icon, - EConfigPage *page); -void e_multi_config_dialog_show_page (EMultiConfigDialog *dialog, - int page); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* _E_MULTI_CONFIG_DIALOG_H_ */ diff --git a/widgets/misc/e-online-button.c b/widgets/misc/e-online-button.c index dec24a6587..fbfb850272 100644 --- a/widgets/misc/e-online-button.c +++ b/widgets/misc/e-online-button.c @@ -23,6 +23,12 @@ (G_TYPE_INSTANCE_GET_PRIVATE \ ((obj), E_TYPE_ONLINE_BUTTON, EOnlineButtonPrivate)) +#define ONLINE_TOOLTIP \ + "Evolution is currently online. Click this button to work offline." + +#define OFFLINE_TOOLTIP \ + "Evolution is currently offline. Click this button to work online." + struct _EOnlineButtonPrivate { GtkWidget *image; gboolean online; @@ -175,6 +181,7 @@ e_online_button_set_online (EOnlineButton *button, GtkIconTheme *icon_theme; const gchar *filename; const gchar *icon_name; + const gchar *tooltip; g_return_if_fail (E_IS_ONLINE_BUTTON (button)); @@ -191,5 +198,8 @@ e_online_button_set_online (EOnlineButton *button, gtk_image_set_from_file (image, filename); gtk_icon_info_free (icon_info); + tooltip = _(online ? ONLINE_TOOLTIP : OFFLINE_TOOLTIP); + gtk_widget_set_tooltip_text (GTK_WIDGET (button), tooltip); + g_object_notify (G_OBJECT (button), "online"); } diff --git a/widgets/misc/e-popup-action.c b/widgets/misc/e-popup-action.c new file mode 100644 index 0000000000..51abc01338 --- /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..6000b5a6ec --- /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..ecdbee1402 --- /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..39f2b82b89 --- /dev/null +++ b/widgets/misc/e-preferences-window.h @@ -0,0 +1,74 @@ +/* + * e-preferences-window.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_PREFERENCES_WINDOW_H +#define E_PREFERENCES_WINDOW_H + +#include <gtk/gtk.h> + +/* Standard GObject macros */ +#define E_TYPE_PREFERENCES_WINDOW \ + (e_preferences_window_get_type ()) +#define E_PREFERENCES_WINDOW(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_PREFERENCES_WINDOW, EPreferencesWindow)) +#define E_PREFERENCES_WINDOW_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_PREFERENCES_WINDOW, EPreferencesWindowClass)) +#define E_IS_PREFERENCES_WINDOW(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_PREFERENCES_WINDOW)) +#define E_IS_PREFERENCES_WINDOW_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((obj), E_TYPE_PREFERENCES_WINDOW)) +#define E_PREFERENCES_WINDOW_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_TYPE \ + ((obj), E_TYPE_PREFERENCES_WINDOW, EPreferencesWindowClass)) + +G_BEGIN_DECLS + +typedef struct _EPreferencesWindow EPreferencesWindow; +typedef struct _EPreferencesWindowClass EPreferencesWindowClass; +typedef struct _EPreferencesWindowPrivate EPreferencesWindowPrivate; + +struct _EPreferencesWindow { + GtkWindow parent; + EPreferencesWindowPrivate *priv; +}; + +struct _EPreferencesWindowClass { + GtkWindowClass parent_class; +}; + +GType e_preferences_window_get_type (void); +GtkWidget * e_preferences_window_new (void); +void e_preferences_window_add_page (EPreferencesWindow *window, + const gchar *page_name, + const gchar *icon_name, + const gchar *caption, + GtkWidget *widget, + gint sort_order); +void e_preferences_window_show_page (EPreferencesWindow *window, + const gchar *page_name); + +G_END_DECLS + +#endif /* E_PREFERENCES_WINDOW_H */ diff --git a/widgets/misc/e-search-bar.c b/widgets/misc/e-search-bar.c index 30cba7f074..050f840fa8 100644 --- a/widgets/misc/e-search-bar.c +++ b/widgets/misc/e-search-bar.c @@ -22,304 +22,176 @@ * */ -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <gdk/gdkkeysyms.h> +#include "e-search-bar.h" -#include <misc/e-unicode.h> -#include <misc/e-gui-utils.h> +#include "config.h" +#include <stdlib.h> +#include <string.h> #include <glib/gi18n.h> +#include <gdk/gdkkeysyms.h> +#include <e-util/e-util.h> -#include <bonobo/bonobo-ui-util.h> +#include <e-action-combo-box.h> +#include <e-gui-utils.h> +#include <e-icon-entry.h> +#include <e-unicode.h> -#include <stdlib.h> -#include <string.h> +#define E_SEARCH_BAR_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_SEARCH_BAR, ESearchBarPrivate)) -#include "e-icon-entry.h" -#include "e-search-bar.h" -#include "e-util/e-util.h" +struct _ESearchBarPrivate { + RuleContext *context; + FilterRule *current_query; - -enum { - QUERY_CHANGED, - MENU_ACTIVATED, - SEARCH_ACTIVATED, - SEARCH_CLEARED, - LAST_SIGNAL -}; + GtkWidget *filter_label; + GtkWidget *filter_combo_box; + GtkWidget *search_label; + GtkWidget *search_entry; + GtkWidget *scope_label; + GtkWidget *scope_combo_box; -static gint esb_signals [LAST_SIGNAL] = { 0, }; + GtkRadioAction *search_action; + GtkWidget *search_popup_menu; -static GtkHBoxClass *parent_class = NULL; + GtkActionGroup *action_group; +}; -/* The arguments we take */ enum { PROP_0, - PROP_ITEM_ID, - PROP_SUBITEM_ID, - PROP_TEXT, + PROP_CONTEXT, + PROP_FILTER_ACTION, + PROP_FILTER_VALUE, + PROP_FILTER_VISIBLE, + PROP_SEARCH_ACTION, + PROP_SEARCH_TEXT, + PROP_SEARCH_VALUE, + PROP_SEARCH_VISIBLE, + PROP_SCOPE_ACTION, + PROP_SCOPE_VALUE, + PROP_SCOPE_VISIBLE }; - -/* Forward decls. */ - -static int find_id (GtkWidget *menu, int idin, const char *type, GtkWidget **widget); - -static void emit_search_activated (ESearchBar *esb); -static void emit_query_changed (ESearchBar *esb); - - -/* Utility functions. */ +static gpointer parent_class; static void -set_find_now_sensitive (ESearchBar *search_bar, - gboolean sensitive) +action_search_clear_cb (GtkAction *action, + ESearchBar *search_bar) { - if (search_bar->ui_component != NULL) - bonobo_ui_component_set_prop (search_bar->ui_component, - "/commands/ESearchBar:FindNow", - "sensitive", sensitive ? "1" : "0", NULL); + e_search_bar_set_search_text (search_bar, ""); + gtk_action_set_sensitive (action, FALSE); } static void -update_clear_menuitem_sensitive (ESearchBar *search_bar) +action_search_find_cb (GtkAction *action, + 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); - } + gtk_action_set_sensitive (action, FALSE); } static void -clear_button_state_changed (GtkWidget *clear_button, GtkStateType state, ESearchBar *search_bar) -{ - g_return_if_fail (clear_button != NULL && search_bar != NULL); - - update_clear_menuitem_sensitive (search_bar); -} - -static char * -verb_name_from_id (int 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); - update_clear_menuitem_sensitive (esb); -} +action_search_type_cb (GtkAction *action, + ESearchBar *search_bar) +{ + gtk_menu_popup ( + GTK_MENU (search_bar->priv->search_popup_menu), + NULL, NULL, NULL, NULL, 0, gtk_get_current_event_time ()); +} + +static GtkActionEntry search_entries[] = { + + { "search-clear", + GTK_STOCK_CLEAR, + NULL, + "<Shift><Control>q", + N_("Clear the most recent search"), + G_CALLBACK (action_search_clear_cb) }, + + { "search-find", + GTK_STOCK_FIND, + N_("_Find Now"), + NULL, + N_("Execute the search"), + G_CALLBACK (action_search_find_cb) }, + + { "search-type", + GTK_STOCK_FIND, + NULL, + NULL, + NULL, + G_CALLBACK (action_search_type_cb) } +}; static void -emit_search_activated(ESearchBar *esb) +search_bar_rule_changed (FilterRule *rule, + GtkDialog *dialog) { - if (esb->pending_activate) { - g_source_remove (esb->pending_activate); - esb->pending_activate = 0; - } + gboolean sensitive; - g_signal_emit (esb, esb_signals [SEARCH_ACTIVATED], 0); + sensitive = (rule != NULL && rule->parts != NULL); - set_find_now_sensitive (esb, FALSE); - update_clear_menuitem_sensitive (esb); + gtk_dialog_set_response_sensitive ( + dialog, GTK_RESPONSE_OK, sensitive); + gtk_dialog_set_response_sensitive ( + dialog, GTK_RESPONSE_APPLY, sensitive); } static void -emit_menu_activated (ESearchBar *esb, int item) +search_bar_update_search_popup (ESearchBar *search_bar) { - g_signal_emit (esb, - esb_signals [MENU_ACTIVATED], 0, - item); -} + GtkAction *action; + GtkMenuShell *menu_shell; + GSList *list, *iter; - -/* Callbacks -- Standard verbs. */ + action = gtk_action_group_get_action ( + search_bar->priv->action_group, "search-type"); -static void -search_now_verb_cb (BonoboUIComponent *ui_component, - void *data, - const char *verb_name) -{ - ESearchBar *esb; - GtkStyle *style = gtk_widget_get_default_style (); - char *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); + if (search_bar->priv->search_popup_menu != NULL) { + g_object_unref (search_bar->priv->search_popup_menu); + search_bar->priv->search_popup_menu = NULL; } - g_free (text); - emit_search_activated (esb); -} - -static void -clear_verb_cb (BonoboUIComponent *ui_component, - void *data, - const char *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, - void *data, - const char *verb_name) -{ - ESearchBar *esb; - const char *p; - int 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 (search_bar->priv->search_action == NULL) { + gtk_action_set_sensitive (action, FALSE); + return; + } - if (GTK_IS_LABEL (label)) - text = gtk_label_get_text ((GtkLabel *)label); + search_bar->priv->search_popup_menu = gtk_menu_new (); + menu_shell = GTK_MENU_SHELL (search_bar->priv->search_popup_menu); + list = gtk_radio_action_get_group (search_bar->priv->search_action); - return text; -} + for (iter = list; iter != NULL; iter = iter->next) { + GtkAction *action = iter->data; + GtkWidget *widget; -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); + widget = gtk_action_create_menu_item (action); + gtk_menu_shell_append (menu_shell, widget); + gtk_widget_show (widget); } - return FALSE; + gtk_action_set_sensitive (action, TRUE); } static gboolean -paint_search_text (GtkWidget *widget, ESearchBar *esb) +paint_search_text (GtkWidget *widget, + ESearchBar *search_bar) { +#if 0 GtkStyle *style = gtk_widget_get_default_style (); - const gchar *text = NULL; - GtkWidget *menu_widget = esb->option_menu; + const gchar *text; + GtkWidget *menu_widget = search_bar->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)))) + style = gtk_widget_get_default_style (); + + if (!GTK_WIDGET_SENSITIVE (search_bar->option_button)) { + menu_widget = search_bar->scopeoption_menu; + text = g_object_get_data (G_OBJECT(gtk_menu_get_active ( GTK_MENU (search_bar->scopeoption_menu))),"string"); + } else if (!GTK_IS_RADIO_MENU_ITEM (gtk_menu_get_active ( GTK_MENU (search_bar->option_menu)))) return FALSE; else /* no query in search entry .. so set the current option */ text = get_selected_item_label (menu_widget); @@ -328,1263 +200,1018 @@ paint_search_text (GtkWidget *widget, ESearchBar *esb) 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])); + if (!GTK_WIDGET_HAS_FOCUS(search_bar->entry)) { + gtk_entry_set_text (GTK_ENTRY (search_bar->entry), text); + gtk_widget_modify_text (search_bar->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); + gtk_widget_set_tooltip_text (search_bar->option_button, t); g_free (t); - gtk_widget_set_sensitive (esb->clear_button, FALSE); + gtk_widget_set_sensitive (search_bar->clear_button, FALSE); } return FALSE; +#endif + + 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 char *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])); - 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); - } + EIconEntry *icon_entry; + GtkWidget *entry; - emit_search_activated (esb); + icon_entry = E_ICON_ENTRY (search_bar->priv->search_entry); + entry = e_icon_entry_get_entry (icon_entry); + paint_search_text (entry, search_bar); } static void -entry_changed_cb (GtkWidget *widget, - ESearchBar *esb) +search_bar_entry_activated_cb (ESearchBar *search_bar, + GtkWidget *entry) { - const char *text = gtk_entry_get_text (GTK_ENTRY (esb->entry)); - GtkStyle *entry_style, *default_style; + GtkStyle *style; + GtkAction *action; + GtkActionGroup *action_group; + gboolean sensitive; + const gchar *text; - entry_style = gtk_widget_get_style (esb->entry); - default_style = gtk_widget_get_default_style (); + style = gtk_widget_get_default_style (); + text = gtk_entry_get_text (GTK_ENTRY (entry)); + action_group = e_search_bar_get_action_group (search_bar); 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); + gtk_widget_modify_base ( + entry, GTK_STATE_NORMAL, + &(style->base[GTK_STATE_SELECTED])); + gtk_widget_modify_text ( + entry, GTK_STATE_NORMAL, + &(style->text[GTK_STATE_SELECTED])); + gtk_widget_modify_base ( + search_bar->priv->search_entry, + GTK_STATE_NORMAL, + &(style->base[GTK_STATE_SELECTED])); + gtk_widget_modify_base ( + search_bar->priv->filter_combo_box, + GTK_STATE_NORMAL, + &(style->base[GTK_STATE_SELECTED])); + sensitive = 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]))); + gtk_widget_modify_base ( + entry, GTK_STATE_NORMAL, NULL); + gtk_widget_modify_text ( + entry, GTK_STATE_NORMAL, NULL); + gtk_widget_modify_base ( + search_bar->priv->search_entry, + GTK_STATE_NORMAL, NULL); + sensitive = FALSE; } -} - -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 (); + action = gtk_action_group_get_action ( + action_group, E_SEARCH_BAR_ACTION_CLEAR); + gtk_action_set_sensitive (action, sensitive); - /* 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; + action = gtk_action_group_get_action ( + action_group, E_SEARCH_BAR_ACTION_FIND); + gtk_action_activate (action); } 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); +search_bar_entry_changed_cb (ESearchBar *search_bar, + GtkWidget *entry) +{ + GtkActionGroup *action_group; + GtkAction *action; + GtkStyle *style1; + GtkStyle *style2; + GdkColor *color1; + GdkColor *color2; + gboolean sensitive; + const gchar *text; + + style1 = gtk_widget_get_style (entry); + style2 = gtk_widget_get_default_style (); + + text = gtk_entry_get_text (GTK_ENTRY (entry)); + + if (text != NULL && *text != '\0') { + color1 = &style1->text[GTK_STATE_NORMAL]; + color2 = &style2->text[GTK_STATE_INSENSITIVE]; + sensitive = !gdk_color_equal (color1, color2); + } else { + color1 = &style1->text[GTK_STATE_NORMAL]; + color2 = &style2->text[GTK_STATE_SELECTED]; + sensitive = gdk_color_equal (color1, color2); } - esb->block_search = TRUE; - emit_search_activated (esb); - esb->block_search = FALSE; + action_group = search_bar->priv->action_group; + action = gtk_action_group_get_action ( + action_group, E_SEARCH_BAR_ACTION_CLEAR); + gtk_action_set_sensitive (action, sensitive); } -static void -option_activated_cb (GtkWidget *widget, - ESearchBar *esb) +static gboolean +search_bar_entry_focus_in_cb (ESearchBar *search_bar, + GdkEventFocus *event, + GtkWidget *entry) { - int id; - const char *text; - - id = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget), "EsbItemId")); + GtkStyle *style1; + GtkStyle *style2; + GdkColor *color1; + GdkColor *color2; - e_search_bar_set_item_id (esb, id); + style1 = gtk_widget_get_style (entry); + style2 = gtk_widget_get_default_style (); - 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); - } + color1 = &style1->text[GTK_STATE_NORMAL]; + color2 = &style2->text[GTK_STATE_INSENSITIVE]; - if (!esb->block_search) { - emit_query_changed (esb); - } - if (!esb->block_search && id > 0) { - emit_search_activated (esb); + if (gdk_color_equal (color1, color2)) { + gtk_entry_set_text (GTK_ENTRY (entry), ""); + gtk_widget_modify_text (entry, GTK_STATE_NORMAL, NULL); } -} - -static void -option_button_clicked_cb (GtkWidget *widget, GdkEventButton *event, - ESearchBar *esb) -{ - gtk_menu_popup (GTK_MENU (esb->option_menu), NULL, NULL, NULL, NULL,1,gtk_get_current_event_time()); - - gtk_widget_grab_focus (esb->entry); -} -static void -clear_button_clicked_cb (GtkWidget *widget, GdkEventButton *event, - ESearchBar *esb) -{ - gtk_widget_modify_base (esb->entry, GTK_STATE_NORMAL, NULL); - gtk_widget_modify_text (esb->entry, GTK_STATE_NORMAL, NULL); - gtk_widget_modify_base (esb->icon_entry, GTK_STATE_NORMAL, NULL); - gtk_widget_set_sensitive (esb->clear_button, FALSE); - - clear_search (esb); - gtk_entry_set_text (GTK_ENTRY (esb->entry), ""); - gtk_widget_grab_focus (esb->entry); + return FALSE; } static gboolean -entry_key_press_cb (GtkWidget *widget, - GdkEventKey *key_event, - ESearchBar *esb) +search_bar_entry_focus_out_cb (ESearchBar *search_bar, + GdkEventFocus *event, + GtkWidget *entry) { - 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; + return paint_search_text (entry, search_bar); } -#if 0 -static void -scopeoption_changed_cb (GtkWidget *option_menu, ESearchBar *search_bar) +static gboolean +search_bar_entry_key_press_cb (ESearchBar *search_bar, + GdkEventKey *key_event, + GtkWidget *entry) { - char *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); + guint state; - g_free (text); -} +#if 0 /* FIXME */ + state = key_event->state & gtk_accelerator_get_default_mod_mask (); + if (state == GDK_MOD1_MASK && key_event->keyval == GDK_Down) { + search_bar_option_clicked_cb (search_bar, NULL, NULL); + return TRUE; + } #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; + return FALSE; } -#endif static void -append_xml_menu_item (GString *xml, - const char *name, - const char *label, - const char *stock, - const char *verb, - const char *accelerator) -{ - char *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); +search_bar_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_CONTEXT: + e_search_bar_set_context ( + E_SEARCH_BAR (object), + g_value_get_object (value)); + return; + + case PROP_FILTER_ACTION: + e_search_bar_set_filter_action ( + E_SEARCH_BAR (object), + g_value_get_object (value)); + return; + + case PROP_FILTER_VALUE: + e_search_bar_set_filter_value ( + E_SEARCH_BAR (object), + g_value_get_int (value)); + return; + + case PROP_FILTER_VISIBLE: + e_search_bar_set_filter_visible ( + E_SEARCH_BAR (object), + g_value_get_boolean (value)); + return; + + case PROP_SEARCH_ACTION: + e_search_bar_set_search_action ( + E_SEARCH_BAR (object), + g_value_get_object (value)); + return; + + case PROP_SEARCH_TEXT: + e_search_bar_set_search_text ( + E_SEARCH_BAR (object), + g_value_get_string (value)); + return; + + case PROP_SEARCH_VALUE: + e_search_bar_set_search_value ( + E_SEARCH_BAR (object), + g_value_get_int (value)); + return; + + case PROP_SEARCH_VISIBLE: + e_search_bar_set_search_visible ( + E_SEARCH_BAR (object), + g_value_get_boolean (value)); + return; + + case PROP_SCOPE_ACTION: + e_search_bar_set_scope_action ( + E_SEARCH_BAR (object), + g_value_get_object (value)); + return; + + case PROP_SCOPE_VALUE: + e_search_bar_set_scope_value ( + E_SEARCH_BAR (object), + g_value_get_int (value)); + return; + + case PROP_SCOPE_VISIBLE: + e_search_bar_set_scope_visible ( + E_SEARCH_BAR (object), + g_value_get_boolean (value)); + return; + } - g_string_append (xml, "/>"); + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } static void -remove_bonobo_menus (ESearchBar *esb) -{ - if (bonobo_ui_component_get_container (esb->ui_component) == CORBA_OBJECT_NIL) - return; +search_bar_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_CONTEXT: + g_value_set_object ( + value, e_search_bar_get_context ( + E_SEARCH_BAR (object))); + return; + + case PROP_FILTER_ACTION: + g_value_set_object ( + value, e_search_bar_get_filter_action ( + E_SEARCH_BAR (object))); + return; + + case PROP_FILTER_VALUE: + g_value_set_int ( + value, e_search_bar_get_filter_value ( + E_SEARCH_BAR (object))); + return; + + case PROP_FILTER_VISIBLE: + g_value_set_boolean ( + value, e_search_bar_get_filter_visible ( + E_SEARCH_BAR (object))); + return; + + case PROP_SEARCH_ACTION: + g_value_set_object ( + value, e_search_bar_get_search_action ( + E_SEARCH_BAR (object))); + return; + + case PROP_SEARCH_TEXT: + g_value_set_string ( + value, e_search_bar_get_search_text ( + E_SEARCH_BAR (object))); + return; + + case PROP_SEARCH_VALUE: + g_value_set_int ( + value, e_search_bar_get_search_value ( + E_SEARCH_BAR (object))); + return; + + case PROP_SEARCH_VISIBLE: + g_value_set_boolean ( + value, e_search_bar_get_search_visible ( + E_SEARCH_BAR (object))); + return; + + case PROP_SCOPE_ACTION: + g_value_set_object ( + value, e_search_bar_get_scope_action ( + E_SEARCH_BAR (object))); + return; + + case PROP_SCOPE_VALUE: + g_value_set_int ( + value, e_search_bar_get_scope_value ( + E_SEARCH_BAR (object))); + return; + + case PROP_SCOPE_VISIBLE: + g_value_set_boolean ( + value, e_search_bar_get_scope_visible ( + E_SEARCH_BAR (object))); + return; + } - bonobo_ui_component_rm (esb->ui_component, "/menu/SearchPlaceholder", NULL); + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } static void -setup_bonobo_menus (ESearchBar *esb) +search_bar_dispose (GObject *object) { - GString *xml; - GSList *p; - char *verb_name; - char *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); + ESearchBarPrivate *priv; - if (item->text == NULL) - g_string_append (xml, "<separator/>"); - else - append_xml_menu_item (xml, verb_name, item->text, NULL, verb_name, NULL); + priv = E_SEARCH_BAR_GET_PRIVATE (object); - g_free (verb_name); + if (priv->context != NULL) { + g_object_unref (priv->context); + priv->context = NULL; } - 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); + if (priv->filter_label != NULL) { + g_object_unref (priv->filter_label); + priv->filter_label = NULL; } -} - -static void -update_bonobo_menus (ESearchBar *esb) -{ - setup_bonobo_menus (esb); -} - -static void -set_menu (ESearchBar *esb, - ESearchBarItem *items) -{ - int 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 (priv->filter_combo_box != NULL) { + g_object_unref (priv->filter_combo_box); + priv->filter_combo_box = NULL; } - if (esb->ui_component != NULL) - update_bonobo_menus (esb); -} - -/* /\* Callback used when an option item is destroyed. We have to destroy its */ -/* * suboption items. */ -/* *\/ */ -/* static void */ -/* 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; - int 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) { - char *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); - } + if (priv->search_label != NULL) { + g_object_unref (priv->search_label); + priv->search_label = NULL; + } - gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); + if (priv->search_entry != NULL) { + g_object_unref (priv->search_entry); + priv->search_entry = NULL; + } - g_object_set_data (G_OBJECT (item), "EsbItemId", GINT_TO_POINTER(items[i].id)); + if (priv->scope_label != NULL) { + g_object_unref (priv->scope_label); + priv->scope_label = NULL; + } - g_signal_connect (item, "activate", - G_CALLBACK (option_activated_cb), - esb); + if (priv->scope_combo_box != NULL) { + g_object_unref (priv->scope_combo_box); + priv->scope_combo_box = NULL; } - gtk_widget_show_all (menu); - g_object_set_data (G_OBJECT(esb->option_menu), "group", group); - entry_focus_out_cb (esb->entry, NULL, esb); -} + if (priv->search_action != NULL) { + g_object_unref (priv->search_action); + priv->search_action = NULL; + } -static int -find_id (GtkWidget *menu, int idin, const char *type, GtkWidget **widget) -{ - GList *l = GTK_MENU_SHELL (menu)->children; - int 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; + if (priv->action_group != NULL) { + g_object_unref (priv->action_group); + priv->action_group = NULL; } - return row; -} - -/* GtkObject methods. */ + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); +} static void -impl_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +search_bar_class_init (ESearchBarClass *class) { - 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; + GObjectClass *object_class; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (ESearchBarPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = search_bar_set_property; + object_class->get_property = search_bar_get_property; + object_class->dispose = search_bar_dispose; + + g_object_class_install_property ( + object_class, + PROP_CONTEXT, + g_param_spec_object ( + "context", + NULL, + NULL, + RULE_TYPE_CONTEXT, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_FILTER_ACTION, + g_param_spec_object ( + "filter-action", + NULL, + NULL, + GTK_TYPE_RADIO_ACTION, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_FILTER_VALUE, + g_param_spec_int ( + "filter-value", + NULL, + NULL, + G_MININT, + G_MAXINT, + 0, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_FILTER_VISIBLE, + g_param_spec_boolean ( + "filter-visible", + NULL, + NULL, + TRUE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + g_object_class_install_property ( + object_class, + PROP_SEARCH_ACTION, + g_param_spec_object ( + "search-action", + NULL, + NULL, + GTK_TYPE_RADIO_ACTION, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_SEARCH_TEXT, + g_param_spec_string ( + "search-text", + NULL, + NULL, + NULL, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_SEARCH_VALUE, + g_param_spec_int ( + "search-value", + NULL, + NULL, + G_MININT, + G_MAXINT, + 0, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_SEARCH_VISIBLE, + g_param_spec_boolean ( + "search-visible", + NULL, + NULL, + TRUE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + g_object_class_install_property ( + object_class, + PROP_SCOPE_ACTION, + g_param_spec_object ( + "scope-action", + NULL, + NULL, + GTK_TYPE_RADIO_ACTION, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_SCOPE_VALUE, + g_param_spec_int ( + "scope-value", + NULL, + NULL, + G_MININT, + G_MAXINT, + 0, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_SCOPE_VISIBLE, + g_param_spec_boolean ( + "scope-visible", + NULL, + NULL, + FALSE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); } static void -impl_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +search_bar_init (ESearchBar *search_bar) { - ESearchBar *esb = E_SEARCH_BAR(object); + EIconEntry *icon_entry; + GtkActionGroup *action_group; + GtkAction *action; + GtkLabel *label; + GtkWidget *mnemonic; + GtkWidget *widget; - switch (prop_id) { - case PROP_ITEM_ID: - e_search_bar_set_item_id (esb, g_value_get_int (value)); - break; + search_bar->priv = E_SEARCH_BAR_GET_PRIVATE (search_bar); - case PROP_TEXT: - e_search_bar_set_text (esb, g_value_get_string (value)); - break; + gtk_box_set_spacing (GTK_BOX (search_bar), 3); + gtk_box_set_homogeneous (GTK_BOX (search_bar), FALSE); - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } + /*** Filter Widgets ***/ + + /* 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... */ + widget = gtk_label_new_with_mnemonic (_("Sho_w: ")); + gtk_box_pack_start (GTK_BOX (search_bar), widget, FALSE, FALSE, 0); + search_bar->priv->filter_label = g_object_ref (widget); + gtk_widget_show (widget); + + label = GTK_LABEL (widget); + + widget = e_action_combo_box_new (); + gtk_label_set_mnemonic_widget (label, widget); + gtk_box_pack_start (GTK_BOX (search_bar), widget, FALSE, TRUE, 0); + search_bar->priv->filter_combo_box = g_object_ref (widget); + gtk_widget_show (widget); + + /*** Scope Widgets ***/ + + widget = e_action_combo_box_new (); + gtk_box_pack_end (GTK_BOX (search_bar), widget, FALSE, FALSE, 0); + search_bar->priv->scope_combo_box = g_object_ref (widget); + gtk_widget_show (widget); + + mnemonic = widget; + + /* Translators: The " in " label is part of the Quick Search Bar, + * example: Search: [_________________] in [ Current Folder ] */ + widget = gtk_label_new_with_mnemonic (_(" i_n ")); + gtk_label_set_mnemonic_widget (GTK_LABEL (widget), mnemonic); + gtk_box_pack_end (GTK_BOX (search_bar), widget, FALSE, FALSE, 0); + search_bar->priv->scope_label = g_object_ref (widget); + gtk_widget_show (widget); + + /*** Search Widgets ***/ + + widget = e_icon_entry_new (); + gtk_box_pack_end (GTK_BOX (search_bar), widget, FALSE, FALSE, 0); + search_bar->priv->search_entry = g_object_ref (widget); + gtk_widget_show (widget); + + icon_entry = E_ICON_ENTRY (widget); + + /* Translators: The "Search: " label is followed by the Quick Search + * Text input field where one enters the term to search for. */ + widget = gtk_label_new_with_mnemonic (_("Sear_ch: ")); + gtk_box_pack_end (GTK_BOX (search_bar), widget, FALSE, FALSE, 0); + search_bar->priv->search_label = g_object_ref (widget); + gtk_widget_show (widget); + + label = GTK_LABEL (widget); + + widget = e_icon_entry_get_entry (icon_entry); + gtk_label_set_mnemonic_widget (label, widget); + g_signal_connect_swapped ( + widget, "activate", + G_CALLBACK (search_bar_entry_activated_cb), search_bar); + g_signal_connect_swapped ( + widget, "changed", + G_CALLBACK (search_bar_entry_changed_cb), search_bar); + g_signal_connect_swapped ( + widget, "focus-in-event", + G_CALLBACK (search_bar_entry_focus_in_cb), search_bar); + g_signal_connect_swapped ( + widget, "focus-out-event", + G_CALLBACK (search_bar_entry_focus_out_cb), search_bar); + g_signal_connect_swapped ( + widget, "key-press-event", + G_CALLBACK (search_bar_entry_key_press_cb), search_bar); + + action_group = gtk_action_group_new ("search"); + gtk_action_group_set_translation_domain ( + action_group, GETTEXT_PACKAGE); + gtk_action_group_add_actions ( + action_group, search_entries, + G_N_ELEMENTS (search_entries), search_bar); + search_bar->priv->action_group = action_group; + + action = gtk_action_group_get_action ( + action_group, E_SEARCH_BAR_ACTION_TYPE); + e_icon_entry_add_action_start (icon_entry, action); + gtk_action_set_sensitive (action, FALSE); + + action = gtk_action_group_get_action ( + action_group, E_SEARCH_BAR_ACTION_CLEAR); + e_icon_entry_add_action_end (icon_entry, action); + gtk_action_set_sensitive (action, FALSE); } -static void -impl_dispose (GObject *object) +GType +e_search_bar_get_type (void) { - 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. */ + static GType type = 0; - if (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 (G_UNLIKELY (type == 0)) { + static const GTypeInfo type_info = { + sizeof (ESearchBarClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) search_bar_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (ESearchBar), + 0, /* n_preallocs */ + (GInstanceInitFunc) search_bar_init, + NULL /* value_table */ + }; - if (esb->pending_activate) { - g_source_remove (esb->pending_activate); - esb->pending_activate = 0; + type = g_type_register_static ( + GTK_TYPE_HBOX, "ESearchBar", &type_info, 0); } - free_menu_items (esb); - - if (G_OBJECT_CLASS (parent_class)->dispose) - G_OBJECT_CLASS (parent_class)->dispose (object); + return type; } - -static void -class_init (ESearchBarClass *klass) +GtkWidget * +e_search_bar_new (void) { - 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); + return g_object_new (E_TYPE_SEARCH_BAR, NULL); } -static void -init (ESearchBar *esb) +GtkActionGroup * +e_search_bar_get_action_group (ESearchBar *search_bar) { - 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; + g_return_val_if_fail (E_IS_SEARCH_BAR (search_bar), NULL); - esb->item_id = 0; - esb->scopeitem_id = 0; - esb->last_search_option = 0; - esb->block_search = FALSE; + return search_bar->priv->action_group; } - -/* Object construction. */ - -static gint -idle_activate_hack (gpointer ptr) +RuleContext * +e_search_bar_get_context (ESearchBar *search_bar) { - ESearchBar *esb = E_SEARCH_BAR (ptr); - esb->pending_activate = 0; - emit_search_activated (esb); - return FALSE; + g_return_val_if_fail (E_IS_SEARCH_BAR (search_bar), NULL); + + return search_bar->priv->context; } void -e_search_bar_construct (ESearchBar *search_bar, - ESearchBarItem *menu_items, - ESearchBarItem *option_items) +e_search_bar_set_context (ESearchBar *search_bar, + RuleContext *context) { - 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); + g_return_if_fail (IS_RULE_CONTEXT (context)); - gtk_box_set_spacing (GTK_BOX (search_bar), 3); - - gtk_box_set_homogeneous (GTK_BOX (search_bar), FALSE); + if (search_bar->priv->context != NULL) + g_object_unref (search_bar->priv->context); - bighbox = gtk_hbox_new (FALSE, 0); - search_bar->entry_box = gtk_hbox_new (0, FALSE); - search_bar->icon_entry = e_icon_entry_new (); - search_bar->entry = e_icon_entry_get_entry (E_ICON_ENTRY (search_bar->icon_entry)); - - g_signal_connect (search_bar->entry, "changed", - G_CALLBACK (entry_changed_cb), search_bar); - g_signal_connect (search_bar->entry, "activate", - G_CALLBACK (entry_activated_cb), search_bar); - g_signal_connect (search_bar->entry, "focus-in-event", - G_CALLBACK (entry_focus_in_cb), search_bar); - g_signal_connect (search_bar->entry, "focus-out-event", - G_CALLBACK (entry_focus_out_cb), search_bar); - g_signal_connect (search_bar->entry, "key-press-event", - G_CALLBACK (entry_key_press_cb), search_bar); - - search_bar->clear_button = e_icon_entry_create_button ("gtk-clear"); - g_signal_connect (G_OBJECT (search_bar->clear_button), "button-press-event", G_CALLBACK(clear_button_clicked_cb), search_bar); - e_icon_entry_pack_widget (E_ICON_ENTRY (search_bar->icon_entry), search_bar->clear_button, FALSE); - - search_bar->option_button = e_icon_entry_create_button ("gtk-find"); - g_signal_connect (G_OBJECT (search_bar->option_button), "button-press-event", G_CALLBACK(option_button_clicked_cb), search_bar); - e_icon_entry_pack_widget (E_ICON_ENTRY (search_bar->icon_entry), search_bar->option_button, TRUE); - - gtk_box_pack_start (GTK_BOX(search_bar->entry_box), search_bar->icon_entry, FALSE, FALSE, 0); - - gtk_widget_show_all (search_bar->entry_box); - gtk_widget_set_sensitive (search_bar->clear_button, FALSE); - - /* 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 */ - 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_widget_show (search_bar->entry_box); - gtk_label_set_mnemonic_widget ((GtkLabel *)label, search_bar->entry); - - /* 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); - - gtk_box_pack_end (GTK_BOX(search_bar), hbox, FALSE, FALSE, 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. - */ - - search_bar->pending_activate = g_idle_add (idle_activate_hack, search_bar); + search_bar->priv->context = g_object_ref (context); + g_object_notify (G_OBJECT (search_bar), "context"); } -void -e_search_bar_set_menu (ESearchBar *search_bar, ESearchBarItem *menu_items) +GtkRadioAction * +e_search_bar_get_filter_action (ESearchBar *search_bar) { - g_return_if_fail (search_bar != NULL); - g_return_if_fail (E_IS_SEARCH_BAR (search_bar)); + EActionComboBox *combo_box; - ((ESearchBarClass *) GTK_OBJECT_GET_CLASS (search_bar))->set_menu (search_bar, menu_items); -} + g_return_val_if_fail (E_IS_SEARCH_BAR (search_bar), NULL); -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)); + combo_box = E_ACTION_COMBO_BOX (search_bar->priv->filter_combo_box); - set_menu (search_bar, menu_item); + return e_action_combo_box_get_action (combo_box); } void -e_search_bar_set_option (ESearchBar *search_bar, ESearchBarItem *option_items) +e_search_bar_set_filter_action (ESearchBar *search_bar, + GtkRadioAction *action) { - g_return_if_fail (search_bar != NULL); + EActionComboBox *combo_box; + 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); + combo_box = E_ACTION_COMBO_BOX (search_bar->priv->filter_combo_box); + + e_action_combo_box_set_action (combo_box, action); + g_object_notify (G_OBJECT (search_bar), "filter-action"); } -void -e_search_bar_set_viewoption_menufunc (ESearchBar *search_bar, ESearchBarMenuFunc *menu_gen_func, void *data) +gint +e_search_bar_get_filter_value (ESearchBar *search_bar) { - g_signal_connect (search_bar->viewoption, "button_press_event", G_CALLBACK (menu_gen_func), data); + EActionComboBox *combo_box; + + g_return_val_if_fail (E_IS_SEARCH_BAR (search_bar), 0); + + combo_box = E_ACTION_COMBO_BOX (search_bar->priv->filter_combo_box); + + return e_action_combo_box_get_current_value (combo_box); } -/** - * 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) +e_search_bar_set_filter_value (ESearchBar *search_bar, + gint value) { + EActionComboBox *combo_box; - if (search_bar->viewoption_menu != NULL) - gtk_option_menu_remove_menu (GTK_OPTION_MENU (search_bar->viewoption)); + g_return_if_fail (E_IS_SEARCH_BAR (search_bar)); - search_bar->viewoption_menu = menu; - gtk_option_menu_set_menu (GTK_OPTION_MENU (search_bar->viewoption), search_bar->viewoption_menu); + combo_box = E_ACTION_COMBO_BOX (search_bar->priv->filter_combo_box); - g_signal_connect (search_bar->viewoption_menu, - "selection-done", - G_CALLBACK (viewitem_activated_cb), - search_bar); + e_action_combo_box_set_current_value (combo_box, value); + g_object_notify (G_OBJECT (search_bar), "filter-value"); } -GtkWidget * -e_search_bar_get_selected_viewitem (ESearchBar *search_bar) +gboolean +e_search_bar_get_filter_visible (ESearchBar *search_bar) { - GtkWidget *widget = NULL; + g_return_val_if_fail (E_IS_SEARCH_BAR (search_bar), FALSE); - widget = gtk_menu_get_active (GTK_MENU (search_bar->viewoption_menu)); - - return widget; + return GTK_WIDGET_VISIBLE (search_bar->priv->filter_combo_box); } -/** - * 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, int option_id, ESearchBarItem *subitems) +e_search_bar_set_filter_visible (ESearchBar *search_bar, + gboolean visible) { - GtkWidget *menu; - GtkWidget *menu_item; - gint i; - - /* Create the menu if it is not there. right scenario ????*/ + g_return_if_fail (E_IS_SEARCH_BAR (search_bar)); - if (search_bar->viewoption_menu == NULL) { - search_bar->viewoption_menu = menu = gtk_menu_new (); + if (visible) { + gtk_widget_show (search_bar->priv->filter_label); + gtk_widget_show (search_bar->priv->filter_combo_box); } else { - gtk_option_menu_remove_menu (GTK_OPTION_MENU (search_bar->viewoption)); - search_bar->viewoption_menu = menu = gtk_menu_new (); + gtk_widget_hide (search_bar->priv->filter_label); + gtk_widget_hide (search_bar->priv->filter_combo_box); } - /* Create the items */ - - for (i = 0; subitems[i].id != -1; ++i) { - if (subitems[i].text) { - char *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); - + g_object_notify (G_OBJECT (search_bar), "filter-visible"); } -/** - * 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) +GtkRadioAction * +e_search_bar_get_search_action (ESearchBar *search_bar) { - 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) { - char *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); + g_return_val_if_fail (E_IS_SEARCH_BAR (search_bar), NULL); - 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); + return search_bar->priv->search_action; } -/** - * 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) +e_search_bar_set_search_action (ESearchBar *search_bar, + GtkRadioAction *action) { + g_return_if_fail (E_IS_SEARCH_BAR (search_bar)); - if (search_bar->scopeoption_menu != NULL) - gtk_option_menu_remove_menu (GTK_OPTION_MENU (search_bar->scopeoption)); + if (action != NULL) { + g_return_if_fail (GTK_IS_RADIO_ACTION (action)); + g_object_ref (action); + } - search_bar->scopeoption_menu = GTK_WIDGET (menu); - gtk_option_menu_set_menu (GTK_OPTION_MENU (search_bar->scopeoption), search_bar->scopeoption_menu); + search_bar->priv->search_action = action; + search_bar_update_search_popup (search_bar); - g_signal_connect (search_bar->scopeoption_menu, - "selection-done", - G_CALLBACK (scopeitem_activated_cb), - search_bar); + g_object_notify (G_OBJECT (search_bar), "search-action"); } -GtkWidget * -e_search_bar_new (ESearchBarItem *menu_items, - ESearchBarItem *option_items) +const gchar * +e_search_bar_get_search_text (ESearchBar *search_bar) { - GtkWidget *widget; + EIconEntry *icon_entry; + GtkWidget *entry; + GtkStyle *style1; + GtkStyle *style2; + GdkColor *color1; + GdkColor *color2; - g_return_val_if_fail (option_items != NULL, NULL); + g_return_val_if_fail (E_IS_SEARCH_BAR (search_bar), NULL); - widget = g_object_new (e_search_bar_get_type (), NULL); + icon_entry = E_ICON_ENTRY (search_bar->priv->search_entry); + entry = e_icon_entry_get_entry (icon_entry); - e_search_bar_construct (E_SEARCH_BAR (widget), menu_items, option_items); + style1 = gtk_widget_get_style (entry); + style2 = gtk_widget_get_default_style (); - return widget; -} + color1 = &style1->text[GTK_STATE_NORMAL]; + color2 = &style2->text[GTK_STATE_INSENSITIVE]; -void -e_search_bar_set_ui_component (ESearchBar *search_bar, - BonoboUIComponent *ui_component) -{ - g_return_if_fail (E_IS_SEARCH_BAR (search_bar)); + if (gdk_color_equal (color1, color2)) + 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); - } + return gtk_entry_get_text (GTK_ENTRY (entry)); } void -e_search_bar_set_menu_sensitive (ESearchBar *search_bar, int id, gboolean state) +e_search_bar_set_search_text (ESearchBar *search_bar, + const gchar *text) { - char *verb_name; - char *path; + EIconEntry *icon_entry; + GtkWidget *entry; - verb_name = verb_name_from_id (id); - path = g_strconcat ("/commands/", verb_name, NULL); - g_free (verb_name); + g_return_if_fail (E_IS_SEARCH_BAR (search_bar)); - bonobo_ui_component_set_prop (search_bar->ui_component, path, - "sensitive", state ? "1" : "0", - NULL); + icon_entry = E_ICON_ENTRY (search_bar->priv->search_entry); + entry = e_icon_entry_get_entry (icon_entry); - g_free (path); + text = (text != NULL) ? text : ""; + gtk_entry_set_text (GTK_ENTRY (entry), text); + g_object_notify (G_OBJECT (search_bar), "search-text"); } -GType -e_search_bar_get_type (void) +gint +e_search_bar_get_search_value (ESearchBar *search_bar) { - static GType type = 0; + g_return_val_if_fail (E_IS_SEARCH_BAR (search_bar), 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; + /* FIXME */ + return 0; } void -e_search_bar_set_viewitem_id (ESearchBar *search_bar, int id) +e_search_bar_set_search_value (ESearchBar *search_bar, + gint value) { - int row; - g_return_if_fail (E_IS_SEARCH_BAR (search_bar)); - 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); + /* FIXME */ - emit_query_changed (search_bar); + g_object_notify (G_OBJECT (search_bar), "search-value"); } -/** - * 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, int id) +gboolean +e_search_bar_get_search_visible (ESearchBar *search_bar) { - int row; - - g_return_if_fail (E_IS_SEARCH_BAR (search_bar)); + g_return_val_if_fail (E_IS_SEARCH_BAR (search_bar), FALSE); - 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); - - update_clear_menuitem_sensitive (search_bar); + return GTK_WIDGET_VISIBLE (search_bar->priv->search_entry); } void -e_search_bar_set_item_menu (ESearchBar *search_bar, int id) +e_search_bar_set_search_visible (ESearchBar *search_bar, + gboolean visible) { - int 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; + if (visible) { + gtk_widget_show (search_bar->priv->search_label); + gtk_widget_show (search_bar->priv->search_entry); + } else { + gtk_widget_hide (search_bar->priv->search_label); + gtk_widget_hide (search_bar->priv->search_entry); + } - gtk_menu_set_active ((GtkMenu *)search_bar->option_menu, row); - if (id>=0) - gtk_check_menu_item_set_active ((GtkCheckMenuItem *)item, TRUE); + g_object_notify (G_OBJECT (search_bar), "search-visible"); } -/** - * 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, int id) +GtkRadioAction * +e_search_bar_get_scope_action (ESearchBar *search_bar) { - int row; - - g_return_if_fail (E_IS_SEARCH_BAR (search_bar)); + EActionComboBox *combo_box; - row = find_id (search_bar->scopeoption_menu, id, "EsbItemId", NULL); - if (row == -1) - return; + g_return_val_if_fail (E_IS_SEARCH_BAR (search_bar), NULL); - search_bar->scopeitem_id = id; - gtk_option_menu_set_history (GTK_OPTION_MENU (search_bar->scopeoption), row); + combo_box = E_ACTION_COMBO_BOX (search_bar->priv->scope_combo_box); - if (!search_bar->block_search) - emit_query_changed (search_bar); + return e_action_combo_box_get_action (combo_box); } - -/** - * 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. - **/ -int -e_search_bar_get_item_id (ESearchBar *search_bar) +void +e_search_bar_set_scope_action (ESearchBar *search_bar, + GtkRadioAction *action) { - GtkWidget *menu_item; - gint item_id; + EActionComboBox *combo_box; - g_return_val_if_fail (search_bar != NULL, -1); - g_return_val_if_fail (E_IS_SEARCH_BAR (search_bar), -1); + g_return_if_fail (E_IS_SEARCH_BAR (search_bar)); + g_return_if_fail (GTK_IS_RADIO_ACTION (action)); - 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; + combo_box = E_ACTION_COMBO_BOX (search_bar->priv->scope_combo_box); - return search_bar->item_id; + e_action_combo_box_set_action (combo_box, action); + g_object_notify (G_OBJECT (search_bar), "scope-action"); } -/** - * 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. - **/ -int -e_search_bar_get_search_scope (ESearchBar *search_bar) +gint +e_search_bar_get_scope_value (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); + EActionComboBox *combo_box; - 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")); + g_return_val_if_fail (E_IS_SEARCH_BAR (search_bar), 0); - search_bar->scopeitem_id = scopeitem_id; + combo_box = E_ACTION_COMBO_BOX (search_bar->priv->scope_combo_box); - return search_bar->scopeitem_id; + return e_action_combo_box_get_current_value (combo_box); } -/** - * 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. - **/ -int -e_search_bar_get_viewitem_id (ESearchBar *search_bar) +void +e_search_bar_set_scope_value (ESearchBar *search_bar, + gint value) { - GtkWidget *menu_item; - gint viewitem_id; + EActionComboBox *combo_box; - g_return_val_if_fail (search_bar != NULL, -1); - g_return_val_if_fail (E_IS_SEARCH_BAR (search_bar), -1); + g_return_if_fail (E_IS_SEARCH_BAR (search_bar)); - if (!search_bar->viewoption_menu) - return -1; + combo_box = E_ACTION_COMBO_BOX (search_bar->priv->scope_combo_box); - 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")); + e_action_combo_box_set_current_value (combo_box, value); + g_object_notify (G_OBJECT (search_bar), "scope-value"); +} - search_bar->viewitem_id = viewitem_id; +gboolean +e_search_bar_get_scope_visible (ESearchBar *search_bar) +{ + g_return_val_if_fail (E_IS_SEARCH_BAR (search_bar), FALSE); - return search_bar->viewitem_id; + return GTK_WIDGET_VISIBLE (search_bar->priv->scope_combo_box); } -/** - * 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, int item_id, int subitem_id) +e_search_bar_set_scope_visible (ESearchBar *search_bar, + gboolean visible) { - int 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); + if (visible) { + gtk_widget_show (search_bar->priv->scope_label); + gtk_widget_show (search_bar->priv->scope_combo_box); + } else { + gtk_widget_hide (search_bar->priv->scope_label); + gtk_widget_hide (search_bar->priv->scope_combo_box); + } + g_object_notify (G_OBJECT (search_bar), "scope-visible"); } -/** - * 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 char *text) +static void +search_bar_rule_changed_cb (FilterRule *rule, + GtkDialog *dialog) { - g_return_if_fail (E_IS_SEARCH_BAR (search_bar)); - gtk_entry_set_text (GTK_ENTRY (search_bar->entry), text); + /* FIXME Think this does something with sensitivity. */ } -/** - * 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. - **/ -char * -e_search_bar_get_text (ESearchBar *search_bar) +void +e_search_bar_save_search_dialog (ESearchBar *search_bar, + const gchar *filename) { - 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))); -} + RuleContext *context; + FilterRule *rule; + GtkWidget *dialog; + GtkWidget *parent; + GtkWidget *widget; + const gchar *search_text; + gchar *rule_name; -void e_search_bar_scope_enable (ESearchBar *esb, int did, gboolean state) -{ - GtkWidget *widget=NULL; - GList *l ; - int 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; - } + g_return_if_fail (E_IS_SEARCH_BAR (search_bar)); + g_return_if_fail (filename != NULL); + + g_return_if_fail (search_bar->priv->current_query != NULL); + + rule = filter_rule_clone (search_bar->priv->current_query); + search_text = e_search_bar_get_search_text (search_bar); + if (search_text == NULL || *search_text == '\0') + search_text = "''"; + + rule_name = g_strdup_printf ("%s %s", rule->name, search_text); + filter_rule_set_name (rule, rule_name); + g_free (rule_name); + + parent = gtk_widget_get_toplevel (GTK_WIDGET (search_bar)); + + dialog = gtk_dialog_new_with_buttons ( + _("Save Search"), GTK_WINDOW (parent), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_OK, GTK_RESPONSE_OK, + NULL); + + gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE); + gtk_window_set_default_size (GTK_WINDOW (dialog), 500, 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); + + context = search_bar->priv->context; + widget = filter_rule_get_widget (rule, context); + filter_rule_set_source (rule, FILTER_SOURCE_INCOMING); + gtk_container_set_border_width (GTK_CONTAINER (widget), 12); + gtk_box_pack_start ( + GTK_BOX (GTK_DIALOG (dialog)->vbox), + widget, TRUE, TRUE, 0); + + g_signal_connect ( + rule, "changed", + G_CALLBACK (search_bar_rule_changed_cb), + dialog); + + search_bar_rule_changed_cb (rule, GTK_DIALOG (dialog)); + + if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) { + if (filter_rule_validate (rule)) { + rule_context_add_rule (context, rule); + rule_context_save (context, filename); } - l = l->next; } - if (widget) - gtk_widget_set_sensitive (widget, state); + gtk_widget_destroy (dialog); } diff --git a/widgets/misc/e-search-bar.h b/widgets/misc/e-search-bar.h index 1f7072d988..333cbabc82 100644 --- a/widgets/misc/e-search-bar.h +++ b/widgets/misc/e-search-bar.h @@ -1,191 +1,107 @@ -/* - * 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. +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* e-search-bar.h + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * Author: Chris Lahey <clahey@ximian.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU 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 - * 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) + * General Public License for more details. * + * You should have received a copy of the GNU 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. */ -#ifndef __E_SEARCH_BAR_H__ -#define __E_SEARCH_BAR_H__ +#ifndef E_SEARCH_BAR_H +#define E_SEARCH_BAR_H #include <gtk/gtk.h> - -#include <bonobo/bonobo-ui-component.h> +#include <filter/rule-context.h> + +/* Standard GObject macros */ +#define E_TYPE_SEARCH_BAR \ + (e_search_bar_get_type ()) +#define E_SEARCH_BAR(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_SEARCH_BAR, ESearchBar)) +#define E_SEARCH_BAR_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_SEARCH_BAR, ESearchBarClass)) +#define E_IS_SEARCH_BAR(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_SEARCH_BAR)) +#define E_IS_SEARCH_BAR_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_SEARCH_BAR)) +#define E_SEARCH_BAR_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_SEARCH_BAR, ESearchBarClass)) + +/* Action Names */ +#define E_SEARCH_BAR_ACTION_CLEAR "search-clear" +#define E_SEARCH_BAR_ACTION_FIND "search-find" +#define E_SEARCH_BAR_ACTION_TYPE "search-type" G_BEGIN_DECLS -/* ESearchBar - A card displaying information about a contact. - * - * The following arguments are available: - * - * name type read/write description - * --------------------------------------------------------------------------------- - * item_id int RW Which option item is currently selected. - * subitem_id int 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)) +typedef struct _ESearchBar ESearchBar; +typedef struct _ESearchBarClass ESearchBarClass; +typedef struct _ESearchBarPrivate ESearchBarPrivate; -enum _ESearchBarItemType { - ESB_ITEMTYPE_NORMAL, - ESB_ITEMTYPE_CHECK, - ESB_ITEMTYPE_RADIO, -}; -typedef enum _ESearchBarItemType ESearchBarItemType; - -typedef struct { - char *text; - int id; - int type; -} ESearchBarItem; - -typedef struct _ESearchBar ESearchBar; -typedef struct _ESearchBarClass ESearchBarClass; - -typedef void (*ESearchBarMenuFunc)(ESearchBar *esb, ESearchBarItem *menu_items); - -struct _ESearchBar -{ +struct _ESearchBar { GtkHBox parent; - - BonoboUIComponent *ui_component; - - GSList *menu_items; - - /* item specific fields */ - GtkWidget *option; - GtkWidget *entry; - GtkWidget *suboption; /* an option menu for the choices associated with some options */ - - /* PRIVATE */ - GtkWidget *dropdown_holder; /* holds the dropdown */ - GtkWidget *option_menu; - GtkWidget *suboption_menu; - GtkWidget *option_button; - GtkWidget *clear_button; - GtkWidget *entry_box; - GtkWidget *icon_entry; - - /* show option widgets */ - GtkWidget *viewoption_box; - GtkWidget *viewoption; /* an option menu for the choices associated with some search options */ - GtkWidget *viewoption_menu; - - /* search scope widgets */ - GtkWidget *scopeoption_box; - GtkWidget *scopeoption; /* an option menu for the choices associated with scope search */ - GtkWidget *scopeoption_menu; - - guint pending_activate; - - /* The currently-selected item & subitem */ - int item_id; - int viewitem_id; /* Current View Id */ - int scopeitem_id; /* Scope of search */ - int last_search_option; - - gboolean block_search; + ESearchBarPrivate *priv; }; -struct _ESearchBarClass -{ +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, int 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); - -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, - int option_id, - ESearchBarItem *subitems); - -void e_search_bar_set_menu_sensitive (ESearchBar *search_bar, - int id, - gboolean state); - -void e_search_bar_set_item_id (ESearchBar *search_bar, - int id); -void e_search_bar_set_item_menu (ESearchBar *search_bar, - int id); -int e_search_bar_get_item_id (ESearchBar *search_bar); +GType e_search_bar_get_type (void); +GtkWidget * e_search_bar_new (void); +GtkActionGroup *e_search_bar_get_action_group (ESearchBar *search_bar); +RuleContext * e_search_bar_get_context (ESearchBar *search_bar); +void e_search_bar_set_context (ESearchBar *search_bar, + RuleContext *context); +GtkRadioAction *e_search_bar_get_filter_action (ESearchBar *search_bar); +void e_search_bar_set_filter_action (ESearchBar *search_bar, + GtkRadioAction *action); +gint e_search_bar_get_filter_value (ESearchBar *search_bar); +void e_search_bar_set_filter_value (ESearchBar *search_bar, + gint value); +gboolean e_search_bar_get_filter_visible (ESearchBar *search_bar); +void e_search_bar_set_filter_visible (ESearchBar *search_bar, + gboolean visible); +GtkRadioAction *e_search_bar_get_search_action (ESearchBar *search_bar); +void e_search_bar_set_search_action (ESearchBar *search_bar, + GtkRadioAction *action); +const gchar * e_search_bar_get_search_text (ESearchBar *search_bar); +void e_search_bar_set_search_text (ESearchBar *search_bar, + const gchar *text); +gint e_search_bar_get_search_value (ESearchBar *search_bar); +void e_search_bar_set_search_value (ESearchBar *search_bar, + gint value); +gboolean e_search_bar_get_search_visible (ESearchBar *search_bar); +void e_search_bar_set_search_visible (ESearchBar *search_bar, + gboolean visible); +GtkRadioAction *e_search_bar_get_scope_action (ESearchBar *search_bar); +void e_search_bar_set_scope_action (ESearchBar *search_bar, + GtkRadioAction *action); +gint e_search_bar_get_scope_value (ESearchBar *search_bar); +void e_search_bar_set_scope_value (ESearchBar *search_bar, + gint value); +gboolean e_search_bar_get_scope_visible (ESearchBar *search_bar); +void e_search_bar_set_scope_visible (ESearchBar *search_bar, + gboolean visible); +void e_search_bar_save_search_dialog (ESearchBar *search_bar, + const gchar *filename); -int e_search_bar_get_viewitem_id (ESearchBar *search_bar); - -void e_search_bar_set_viewitem_id (ESearchBar *search_bar, int id); - -void e_search_bar_set_ids (ESearchBar *search_bar, - int item_id, - int 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, int 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, void *data); - -GtkWidget *e_search_bar_get_selected_viewitem (ESearchBar *search_bar); - -int e_search_bar_get_search_scope (ESearchBar *search_bar); - -void e_search_bar_set_text (ESearchBar *search_bar, - const char *text); -char *e_search_bar_get_text (ESearchBar *search_bar); -void e_search_bar_scope_enable (ESearchBar *search_bar, int did, gboolean state); G_END_DECLS - -#endif /* __E_SEARCH_BAR_H__ */ +#endif /* E_SEARCH_BAR_H */ diff --git a/widgets/misc/e-signature-combo-box.c b/widgets/misc/e-signature-combo-box.c index 9ebd20a0b2..40a93b7d25 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 ec05c2b5d7..5cdd224e6b 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..cc1e9f6c18 --- /dev/null +++ b/widgets/misc/e-signature-editor.c @@ -0,0 +1,503 @@ +/* + * e-signature-editor.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-signature-editor.h" + +#include <string.h> +#include <glib/gi18n.h> + +#include <e-util/e-error.h> +#include <e-util/e-signature-utils.h> + +#define E_SIGNATURE_EDITOR_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_SIGNATURE_EDITOR, ESignatureEditorPrivate)) + +enum { + PROP_0, + PROP_SIGNATURE +}; + +struct _ESignatureEditorPrivate { + GtkActionGroup *action_group; + ESignature *signature; + GtkWidget *entry; + gchar *original_name; +}; + +static const gchar *ui = +"<ui>\n" +" <menubar name='main-menu'>\n" +" <placeholder name='pre-edit-menu'>\n" +" <menu action='file-menu'>\n" +" <menuitem action='save-and-close'/>\n" +" <separator/>" +" <menuitem action='close'/>\n" +" </menu>\n" +" </placeholder>\n" +" </menubar>\n" +" <toolbar name='main-toolbar'>\n" +" <placeholder name='pre-main-toolbar'>\n" +" <toolitem action='save-and-close'/>\n" +" </placeholder>\n" +" </toolbar>\n" +"</ui>"; + +static gpointer parent_class = NULL; + +static void +handle_error (GError **error) +{ + if (*error != NULL) { + g_warning ("%s", (*error)->message); + g_clear_error (error); + } +} + +static void +action_close_cb (GtkAction *action, + ESignatureEditor *editor) +{ + gboolean something_changed = FALSE; + const gchar *original_name; + const gchar *signature_name; + + original_name = editor->priv->original_name; + signature_name = gtk_entry_get_text (GTK_ENTRY (editor->priv->entry)); + + something_changed |= gtkhtml_editor_has_undo (GTKHTML_EDITOR (editor)); + something_changed |= (strcmp (signature_name, original_name) != 0); + + if (something_changed) { + gint response; + + response = e_error_run ( + GTK_WINDOW (editor), + "mail:ask-signature-changed", NULL); + if (response == GTK_RESPONSE_YES) { + GtkActionGroup *action_group; + + action_group = editor->priv->action_group; + action = gtk_action_group_get_action ( + action_group, "save-and-close"); + gtk_action_activate (action); + return; + } else if (response == GTK_RESPONSE_CANCEL) + return; + } + + gtk_widget_destroy (GTK_WIDGET (editor)); +} + +static void +action_save_and_close_cb (GtkAction *action, + ESignatureEditor *editor) +{ + GtkWidget *entry; + ESignatureList *signature_list; + ESignature *signature; + ESignature *same_name; + const gchar *filename; + gchar *signature_name; + gboolean html; + GError *error = NULL; + + entry = editor->priv->entry; + html = gtkhtml_editor_get_html_mode (GTKHTML_EDITOR (editor)); + + if (editor->priv->signature == NULL) { + signature = e_signature_new (); + signature->name = g_strdup (_("Unnamed")); + signature->script = FALSE; + signature->html = html; + + /* FIXME Pass a GError and deal with it. */ + signature->filename = e_create_signature_file (NULL); + } else { + signature = g_object_ref (editor->priv->signature); + signature->html = html; + } + + filename = signature->filename; + gtkhtml_editor_save (GTKHTML_EDITOR (editor), filename, html, &error); + + if (error != NULL) { + e_error_run ( + GTK_WINDOW (editor), + "mail:no-save-signature", + error->message, NULL); + g_clear_error (&error); + return; + } + + signature_list = e_get_signature_list (); + + signature_name = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry))); + g_strstrip (signature_name); + + /* Make sure the signature name is not blank. */ + if (*signature_name == '\0') { + e_error_run ( + GTK_WINDOW (editor), + "mail:blank-signature", NULL); + gtk_widget_grab_focus (entry); + g_free (signature_name); + return; + } + + /* Don't overwrite an existing signature of the same name. + * XXX ESignatureList misuses const. */ + same_name = (ESignature *) e_signature_list_find ( + signature_list, E_SIGNATURE_FIND_NAME, signature_name); + if (same_name != NULL && strcmp (signature->uid, same_name->uid) != 0) { + e_error_run ( + GTK_WINDOW (editor), + "mail:signature-already-exists", + signature_name, NULL); + gtk_widget_grab_focus (entry); + g_free (signature_name); + return; + } + + g_free (signature->name); + signature->name = signature_name; + + if (editor->priv->signature != NULL) + e_signature_list_change (signature_list, signature); + else + e_signature_list_add (signature_list, signature); + e_signature_list_save (signature_list); + + gtk_widget_destroy (GTK_WIDGET (editor)); +} + +static GtkActionEntry entries[] = { + + { "close", + GTK_STOCK_CLOSE, + N_("_Close"), + "<Control>w", + NULL, + G_CALLBACK (action_close_cb) }, + + { "save-and-close", + GTK_STOCK_SAVE, + N_("_Save and Close"), + "<Control>Return", + NULL, + G_CALLBACK (action_save_and_close_cb) }, + + { "file-menu", + NULL, + N_("_File"), + NULL, + NULL, + NULL } +}; + +static gboolean +signature_editor_delete_event_cb (ESignatureEditor *editor, + GdkEvent *event) +{ + GtkActionGroup *action_group; + GtkAction *action; + + action_group = editor->priv->action_group; + action = gtk_action_group_get_action (action_group, "close"); + gtk_action_activate (action); + + return TRUE; +} + +static void +signature_editor_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_SIGNATURE: + e_signature_editor_set_signature ( + E_SIGNATURE_EDITOR (object), + g_value_get_object (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +signature_editor_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_SIGNATURE: + g_value_set_object ( + value, e_signature_editor_get_signature ( + E_SIGNATURE_EDITOR (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +signature_editor_dispose (GObject *object) +{ + ESignatureEditorPrivate *priv; + + priv = E_SIGNATURE_EDITOR_GET_PRIVATE (object); + + if (priv->action_group != NULL) { + g_object_unref (priv->action_group); + priv->action_group = NULL; + } + + if (priv->signature != NULL) { + g_object_unref (priv->signature); + priv->signature = NULL; + } + + if (priv->entry != NULL) { + g_object_unref (priv->entry); + priv->entry = NULL; + } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +signature_editor_finalize (GObject *object) +{ + ESignatureEditorPrivate *priv; + + priv = E_SIGNATURE_EDITOR_GET_PRIVATE (object); + + g_free (priv->original_name); + + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +signature_editor_class_init (ESignatureEditorClass *class) +{ + GObjectClass *object_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (ESignatureEditorPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = signature_editor_set_property; + object_class->get_property = signature_editor_get_property; + object_class->dispose = signature_editor_dispose; + object_class->finalize = signature_editor_finalize; + + g_object_class_install_property ( + object_class, + PROP_SIGNATURE, + g_param_spec_object ( + "signature", + NULL, + NULL, + E_TYPE_SIGNATURE, + G_PARAM_READWRITE)); +} + +static void +signature_editor_init (ESignatureEditor *editor) +{ + GtkActionGroup *action_group; + GtkUIManager *ui_manager; + GtkWidget *container; + GtkWidget *widget; + GtkWidget *vbox; + GError *error = NULL; + + editor->priv = E_SIGNATURE_EDITOR_GET_PRIVATE (editor); + vbox = GTKHTML_EDITOR (editor)->vbox; + + ui_manager = gtkhtml_editor_get_ui_manager (GTKHTML_EDITOR (editor)); + + gtk_ui_manager_add_ui_from_string (ui_manager, ui, -1, &error); + handle_error (&error); + + action_group = gtk_action_group_new ("signature"); + gtk_action_group_set_translation_domain ( + action_group, GETTEXT_PACKAGE); + gtk_action_group_add_actions ( + action_group, entries, + G_N_ELEMENTS (entries), editor); + gtk_ui_manager_insert_action_group (ui_manager, action_group, 0); + editor->priv->action_group = g_object_ref (action_group); + + gtk_ui_manager_ensure_update (ui_manager); + + gtk_window_set_title (GTK_WINDOW (editor), _("Edit Signature")); + + widget = gtk_hbox_new (FALSE, 6); + gtk_container_set_border_width (GTK_CONTAINER (widget), 6); + gtk_box_pack_start (GTK_BOX (vbox), widget, FALSE, FALSE, 0); + /* Position 2 should be between the main and style toolbars. */ + gtk_box_reorder_child (GTK_BOX (vbox), widget, 2); + gtk_widget_show (widget); + container = widget; + + widget = gtk_entry_new (); + gtk_box_pack_end (GTK_BOX (container), widget, TRUE, TRUE, 0); + editor->priv->entry = g_object_ref_sink (widget); + gtk_widget_show (widget); + + widget = gtk_label_new_with_mnemonic (_("_Signature Name:")); + gtk_label_set_mnemonic_widget (GTK_LABEL (widget), editor->priv->entry); + gtk_box_pack_end (GTK_BOX (container), widget, FALSE, FALSE, 0); + gtk_widget_show (widget); + + g_signal_connect ( + editor, "delete-event", + G_CALLBACK (signature_editor_delete_event_cb), NULL); + + e_signature_editor_set_signature (editor, NULL); +} + +GType +e_signature_editor_get_type (void) +{ + static GType type = 0; + + if (G_UNLIKELY (type == 0)) { + static const GTypeInfo type_info = { + sizeof (ESignatureEditorClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) signature_editor_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (ESignatureEditor), + 0, /* n_preallocs */ + (GInstanceInitFunc) signature_editor_init, + NULL /* value_table */ + }; + + type = g_type_register_static ( + GTKHTML_TYPE_EDITOR, "ESignatureEditor", + &type_info, 0); + } + + return type; +} + +GtkWidget * +e_signature_editor_new (void) +{ + return g_object_new (E_TYPE_SIGNATURE_EDITOR, NULL); +} + +ESignature * +e_signature_editor_get_signature (ESignatureEditor *editor) +{ + g_return_val_if_fail (E_IS_SIGNATURE_EDITOR (editor), NULL); + + return editor->priv->signature; +} + +void +e_signature_editor_set_signature (ESignatureEditor *editor, + ESignature *signature) +{ + const gchar *filename; + const gchar *signature_name; + gchar *contents; + gsize length; + GError *error = NULL; + + g_return_if_fail (E_IS_SIGNATURE_EDITOR (editor)); + + if (signature != NULL) + g_return_if_fail (E_SIGNATURE (signature)); + + if (editor->priv->signature != NULL) { + g_object_unref (editor->priv->signature); + editor->priv->signature = NULL; + } + + if (signature == NULL) + goto exit; + + editor->priv->signature = g_object_ref (signature); + + /* Load signature content. */ + + filename = signature->filename; + + if (signature->html) + g_file_get_contents (filename, &contents, &length, &error); + else { + gchar *data; + + data = e_read_signature_file (signature, FALSE, &error); + if (data != NULL) + contents = g_strdup_printf ("<PRE>\n%s", data); + else + contents = NULL; + length = -1; + g_free (data); + } + + if (error == NULL) { + gtkhtml_editor_set_html_mode ( + GTKHTML_EDITOR (editor), signature->html); + gtkhtml_editor_set_text_html ( + GTKHTML_EDITOR (editor), contents, length); + g_free (contents); + } else { + g_warning ("%s", error->message); + g_error_free (error); + } + +exit: + if (signature != NULL) + signature_name = signature->name; + else + signature_name = _("Unnamed"); + + /* Set the entry text before we grab focus. */ + g_free (editor->priv->original_name); + editor->priv->original_name = g_strdup (signature_name); + gtk_entry_set_text (GTK_ENTRY (editor->priv->entry), signature_name); + + /* Set the focus appropriately. If this is a new signature, draw + * the user's attention to the signature name entry. Otherwise go + * straight to the editing area. */ + if (signature == NULL) + gtk_widget_grab_focus (editor->priv->entry); + else { + GtkHTML *html; + + html = gtkhtml_editor_get_html (GTKHTML_EDITOR (editor)); + gtk_widget_grab_focus (GTK_WIDGET (html)); + } + + g_object_notify (G_OBJECT (editor), "signature"); +} diff --git a/widgets/misc/e-signature-editor.h b/widgets/misc/e-signature-editor.h new file mode 100644 index 0000000000..9d6c37ac87 --- /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..0c145e9821 --- /dev/null +++ b/widgets/misc/e-signature-manager.c @@ -0,0 +1,746 @@ +/* + * e-signature-manager.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-signature-manager.h" + +#include <glib/gi18n.h> +#include <glib/gstdio.h> +#include <gdk/gdkkeysyms.h> +#include "e-util/e-binding.h" +#include "e-signature-tree-view.h" +#include "e-signature-script-dialog.h" + +#define E_SIGNATURE_MANAGER_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_SIGNATURE_MANAGER, ESignatureManagerPrivate)) + +struct _ESignatureManagerPrivate { + ESignatureList *signature_list; + + GtkWidget *tree_view; + GtkWidget *add_button; + GtkWidget *add_script_button; + GtkWidget *edit_button; + GtkWidget *remove_button; + + guint allow_scripts : 1; + guint prefer_html : 1; +}; + +enum { + PROP_0, + PROP_ALLOW_SCRIPTS, + PROP_PREFER_HTML, + PROP_SIGNATURE_LIST +}; + +enum { + ADD_SIGNATURE, + ADD_SIGNATURE_SCRIPT, + EDITOR_CREATED, + EDIT_SIGNATURE, + REMOVE_SIGNATURE, + LAST_SIGNAL +}; + +static gpointer parent_class; +static guint signals[LAST_SIGNAL]; + +static void +signature_manager_emit_editor_created (ESignatureManager *manager, + GtkWidget *editor) +{ + g_return_if_fail (E_IS_SIGNATURE_EDITOR (editor)); + + g_signal_emit (manager, signals[EDITOR_CREATED], 0, editor); +} + +static gboolean +signature_manager_key_press_event_cb (ESignatureManager *manager, + GdkEventKey *event) +{ + if (event->keyval == GDK_Delete) { + e_signature_manager_remove_signature (manager); + return TRUE; + } + + return FALSE; +} + +static gboolean +signature_manager_run_script_dialog (ESignatureManager *manager, + ESignature *signature, + const gchar *title) +{ + GtkWidget *dialog; + GFile *script_file; + const gchar *script_name; + gboolean success = FALSE; + gpointer parent; + + parent = gtk_widget_get_toplevel (GTK_WIDGET (manager)); + parent = GTK_WIDGET_TOPLEVEL (parent) ? parent : NULL; + + dialog = e_signature_script_dialog_new (parent); + gtk_window_set_title (GTK_WINDOW (dialog), title); + + if (signature->filename != NULL && signature->name != NULL) { + + script_file = g_file_new_for_path (signature->filename); + script_name = signature->name; + + e_signature_script_dialog_set_script_file ( + E_SIGNATURE_SCRIPT_DIALOG (dialog), script_file); + e_signature_script_dialog_set_script_name ( + E_SIGNATURE_SCRIPT_DIALOG (dialog), script_name); + + g_object_unref (script_file); + } + + if (gtk_dialog_run (GTK_DIALOG (dialog)) != GTK_RESPONSE_OK) + goto exit; + + script_file = e_signature_script_dialog_get_script_file ( + E_SIGNATURE_SCRIPT_DIALOG (dialog)); + script_name = e_signature_script_dialog_get_script_name ( + E_SIGNATURE_SCRIPT_DIALOG (dialog)); + + g_free (signature->filename); + signature->filename = g_file_get_path (script_file); + + g_free (signature->name); + signature->name = g_strdup (script_name); + + g_object_unref (script_file); + + success = TRUE; + +exit: + gtk_widget_destroy (dialog); + + return success; +} + +static void +signature_manager_selection_changed_cb (ESignatureManager *manager, + GtkTreeSelection *selection) +{ + GtkWidget *edit_button; + GtkWidget *remove_button; + GtkTreeModel *model; + GtkTreeIter iter; + + edit_button = manager->priv->edit_button; + remove_button = manager->priv->remove_button; + + if (gtk_tree_selection_get_selected (selection, &model, &iter)) { + gtk_widget_set_sensitive (edit_button, TRUE); + gtk_widget_set_sensitive (remove_button, TRUE); + } else { + gtk_widget_set_sensitive (edit_button, FALSE); + gtk_widget_set_sensitive (remove_button, FALSE); + } +} + +static void +signature_manager_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_ALLOW_SCRIPTS: + e_signature_manager_set_allow_scripts ( + E_SIGNATURE_MANAGER (object), + g_value_get_boolean (value)); + return; + + case PROP_PREFER_HTML: + e_signature_manager_set_prefer_html ( + E_SIGNATURE_MANAGER (object), + g_value_get_boolean (value)); + return; + + case PROP_SIGNATURE_LIST: + e_signature_manager_set_signature_list ( + E_SIGNATURE_MANAGER (object), + g_value_get_object (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +signature_manager_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_ALLOW_SCRIPTS: + g_value_set_boolean ( + value, + e_signature_manager_get_allow_scripts ( + E_SIGNATURE_MANAGER (object))); + return; + + case PROP_PREFER_HTML: + g_value_set_boolean ( + value, + e_signature_manager_get_prefer_html ( + E_SIGNATURE_MANAGER (object))); + return; + + case PROP_SIGNATURE_LIST: + g_value_set_object ( + value, + e_signature_manager_get_signature_list ( + E_SIGNATURE_MANAGER (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +signature_manager_dispose (GObject *object) +{ + ESignatureManagerPrivate *priv; + + priv = E_SIGNATURE_MANAGER_GET_PRIVATE (object); + + if (priv->signature_list != NULL) { + g_object_unref (priv->signature_list); + priv->signature_list = NULL; + } + + if (priv->tree_view != NULL) { + g_object_unref (priv->tree_view); + priv->tree_view = NULL; + } + + if (priv->add_button != NULL) { + g_object_unref (priv->add_button); + priv->add_button = NULL; + } + + if (priv->add_script_button != NULL) { + g_object_unref (priv->add_script_button); + priv->add_script_button = NULL; + } + + if (priv->edit_button != NULL) { + g_object_unref (priv->edit_button); + priv->edit_button = NULL; + } + + if (priv->remove_button != NULL) { + g_object_unref (priv->remove_button); + priv->remove_button = NULL; + } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +signature_manager_add_signature (ESignatureManager *manager) +{ + ESignatureTreeView *tree_view; + GtkWidget *editor; + + tree_view = e_signature_manager_get_tree_view (manager); + + editor = e_signature_editor_new (); + gtkhtml_editor_set_html_mode ( + GTKHTML_EDITOR (editor), manager->priv->prefer_html); + signature_manager_emit_editor_created (manager, editor); + + gtk_widget_grab_focus (GTK_WIDGET (tree_view)); +} + +static void +signature_manager_add_signature_script (ESignatureManager *manager) +{ + ESignatureTreeView *tree_view; + ESignatureList *signature_list; + ESignature *signature; + const gchar *title; + + title = _("Add Signature Script"); + tree_view = e_signature_manager_get_tree_view (manager); + signature_list = e_signature_manager_get_signature_list (manager); + + signature = e_signature_new (); + signature->script = TRUE; + signature->html = TRUE; + + if (signature_manager_run_script_dialog (manager, signature, title)) + e_signature_list_add (signature_list, signature); + + e_signature_list_save (signature_list); + g_object_unref (signature); + + gtk_widget_grab_focus (GTK_WIDGET (tree_view)); +} + +static void +signature_manager_editor_created (ESignatureManager *manager, + ESignatureEditor *editor) +{ + GtkWindowPosition position; + gpointer parent; + + position = GTK_WIN_POS_CENTER_ON_PARENT; + parent = gtk_widget_get_toplevel (GTK_WIDGET (manager)); + parent = GTK_WIDGET_TOPLEVEL (parent) ? parent : NULL; + + gtk_window_set_transient_for (GTK_WINDOW (editor), parent); + gtk_window_set_position (GTK_WINDOW (editor), position); + gtk_widget_show (GTK_WIDGET (editor)); +} + +static void +signature_manager_edit_signature (ESignatureManager *manager) +{ + ESignatureTreeView *tree_view; + ESignatureList *signature_list; + ESignature *signature; + GtkWidget *editor; + const gchar *title; + gchar *filename; + + tree_view = e_signature_manager_get_tree_view (manager); + signature = e_signature_tree_view_get_selected (tree_view); + signature_list = e_signature_manager_get_signature_list (manager); + + if (signature == NULL) + return; + + if (signature->script) + goto script; + + filename = signature->filename; + if (filename == NULL || *filename == '\0') { + g_free (filename); + filename = g_strdup (_("Unnamed")); + signature->filename = filename; + } + + editor = e_signature_editor_new (); + e_signature_editor_set_signature ( + E_SIGNATURE_EDITOR (editor), signature); + signature_manager_emit_editor_created (manager, editor); + + goto exit; + +script: + title = _("Edit Signature Script"); + + if (signature_manager_run_script_dialog (manager, signature, title)) + e_signature_list_change (signature_list, signature); + + e_signature_list_save (signature_list); + +exit: + gtk_widget_grab_focus (GTK_WIDGET (tree_view)); + + g_object_unref (signature); +} + +static void +signature_manager_remove_signature (ESignatureManager *manager) +{ + ESignatureTreeView *tree_view; + ESignatureList *signature_list; + ESignature *signature; + + tree_view = e_signature_manager_get_tree_view (manager); + signature = e_signature_tree_view_get_selected (tree_view); + signature_list = e_signature_tree_view_get_signature_list (tree_view); + + if (signature == NULL) + return; + + if (signature->filename != NULL && !signature->script) + g_unlink (signature->filename); + + e_signature_list_remove (signature_list, signature); + e_signature_list_save (signature_list); + + gtk_widget_grab_focus (GTK_WIDGET (tree_view)); +} + +static void +signature_manager_class_init (ESignatureManagerClass *class) +{ + GObjectClass *object_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (ESignatureManagerPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = signature_manager_set_property; + object_class->get_property = signature_manager_get_property; + object_class->dispose = signature_manager_dispose; + + class->add_signature = signature_manager_add_signature; + class->add_signature_script = signature_manager_add_signature_script; + class->editor_created = signature_manager_editor_created; + class->edit_signature = signature_manager_edit_signature; + class->remove_signature = signature_manager_remove_signature; + + g_object_class_install_property ( + object_class, + PROP_ALLOW_SCRIPTS, + g_param_spec_boolean ( + "allow-scripts", + "Allow Scripts", + NULL, + TRUE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + g_object_class_install_property ( + object_class, + PROP_PREFER_HTML, + g_param_spec_boolean ( + "prefer-html", + "Prefer HTML", + NULL, + TRUE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + g_object_class_install_property ( + object_class, + PROP_SIGNATURE_LIST, + g_param_spec_object ( + "signature-list", + "Signature List", + NULL, + E_TYPE_SIGNATURE_LIST, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + signals[ADD_SIGNATURE] = g_signal_new ( + "add-signature", + G_OBJECT_CLASS_TYPE (class), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (ESignatureManagerClass, add_signature), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + signals[ADD_SIGNATURE_SCRIPT] = g_signal_new ( + "add-signature-script", + G_OBJECT_CLASS_TYPE (class), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (ESignatureManagerClass, add_signature_script), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + signals[EDITOR_CREATED] = g_signal_new ( + "editor-created", + G_OBJECT_CLASS_TYPE (class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ESignatureManagerClass, editor_created), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + E_TYPE_SIGNATURE_EDITOR); + + signals[EDIT_SIGNATURE] = g_signal_new ( + "edit-signature", + G_OBJECT_CLASS_TYPE (class), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (ESignatureManagerClass, edit_signature), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + signals[REMOVE_SIGNATURE] = g_signal_new ( + "remove-signature", + G_OBJECT_CLASS_TYPE (class), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (ESignatureManagerClass, remove_signature), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); +} + +static void +signature_manager_init (ESignatureManager *manager) +{ + GtkTreeSelection *selection; + GtkWidget *container; + GtkWidget *widget; + + manager->priv = E_SIGNATURE_MANAGER_GET_PRIVATE (manager); + + gtk_table_resize (GTK_TABLE (manager), 1, 2); + gtk_table_set_col_spacings (GTK_TABLE (manager), 6); + gtk_table_set_row_spacings (GTK_TABLE (manager), 12); + + container = GTK_WIDGET (manager); + + widget = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy ( + GTK_SCROLLED_WINDOW (widget), + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_set_shadow_type ( + GTK_SCROLLED_WINDOW (widget), GTK_SHADOW_IN); + gtk_table_attach ( + GTK_TABLE (container), widget, 0, 1, 0, 1, + GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); + gtk_widget_show (widget); + + container = widget; + + widget = e_signature_tree_view_new (); + gtk_container_add (GTK_CONTAINER (container), widget); + manager->priv->tree_view = g_object_ref (widget); + gtk_widget_show (widget); + + e_mutual_binding_new ( + G_OBJECT (manager), "signature-list", + G_OBJECT (widget), "signature-list"); + + g_signal_connect_swapped ( + widget, "key-press-event", + G_CALLBACK (signature_manager_key_press_event_cb), + manager); + + g_signal_connect_swapped ( + widget, "row-activated", + G_CALLBACK (e_signature_manager_edit_signature), + manager); + + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget)); + + g_signal_connect_swapped ( + selection, "changed", + G_CALLBACK (signature_manager_selection_changed_cb), + manager); + + container = GTK_WIDGET (manager); + + widget = gtk_vbutton_box_new (); + gtk_button_box_set_layout ( + GTK_BUTTON_BOX (widget), GTK_BUTTONBOX_START); + gtk_box_set_spacing (GTK_BOX (widget), 6); + gtk_table_attach ( + GTK_TABLE (container), widget, + 1, 2, 0, 2, 0, GTK_FILL, 0, 0); + gtk_widget_show (widget); + + container = widget; + + widget = gtk_button_new_from_stock (GTK_STOCK_ADD); + gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0); + manager->priv->add_button = g_object_ref (widget); + gtk_widget_show (widget); + + g_signal_connect_swapped ( + widget, "clicked", + G_CALLBACK (e_signature_manager_add_signature), + manager); + + widget = gtk_button_new_with_mnemonic (_("Add _Script")); + gtk_button_set_image ( + GTK_BUTTON (widget), gtk_image_new_from_stock ( + GTK_STOCK_EXECUTE, GTK_ICON_SIZE_BUTTON)); + gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0); + manager->priv->add_script_button = g_object_ref (widget); + gtk_widget_show (widget); + + e_binding_new ( + G_OBJECT (manager), "allow-scripts", + G_OBJECT (widget), "sensitive"); + + g_signal_connect_swapped ( + widget, "clicked", + G_CALLBACK (e_signature_manager_add_signature_script), + manager); + + widget = gtk_button_new_from_stock (GTK_STOCK_EDIT); + gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0); + manager->priv->edit_button = g_object_ref (widget); + gtk_widget_show (widget); + + g_signal_connect_swapped ( + widget, "clicked", + G_CALLBACK (e_signature_manager_edit_signature), + manager); + + widget = gtk_button_new_from_stock (GTK_STOCK_REMOVE); + gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0); + manager->priv->remove_button = g_object_ref (widget); + gtk_widget_show (widget); + + g_signal_connect_swapped ( + widget, "clicked", + G_CALLBACK (e_signature_manager_remove_signature), + manager); +} + +GType +e_signature_manager_get_type (void) +{ + static GType type = 0; + + if (G_UNLIKELY (type == 0)) { + static const GTypeInfo type_info = { + sizeof (ESignatureManagerClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) signature_manager_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_init */ + sizeof (ESignatureManager), + 0, /* n_preallocs */ + (GInstanceInitFunc) signature_manager_init, + NULL /* value_table */ + }; + + type = g_type_register_static ( + GTK_TYPE_TABLE, "ESignatureManager", &type_info, 0); + } + + return type; +} + +GtkWidget * +e_signature_manager_new (ESignatureList *signature_list) +{ + g_return_val_if_fail (E_IS_SIGNATURE_LIST (signature_list), NULL); + + return g_object_new ( + E_TYPE_SIGNATURE_MANAGER, + "signature-list", signature_list, NULL); +} + +void +e_signature_manager_add_signature (ESignatureManager *manager) +{ + g_return_if_fail (E_IS_SIGNATURE_MANAGER (manager)); + + g_signal_emit (manager, signals[ADD_SIGNATURE], 0); +} + +void +e_signature_manager_add_signature_script (ESignatureManager *manager) +{ + g_return_if_fail (E_IS_SIGNATURE_MANAGER (manager)); + + g_signal_emit (manager, signals[ADD_SIGNATURE_SCRIPT], 0); +} + +void +e_signature_manager_edit_signature (ESignatureManager *manager) +{ + g_return_if_fail (E_IS_SIGNATURE_MANAGER (manager)); + + g_signal_emit (manager, signals[EDIT_SIGNATURE], 0); +} + +void +e_signature_manager_remove_signature (ESignatureManager *manager) +{ + g_return_if_fail (E_IS_SIGNATURE_MANAGER (manager)); + + g_signal_emit (manager, signals[REMOVE_SIGNATURE], 0); +} + +gboolean +e_signature_manager_get_allow_scripts (ESignatureManager *manager) +{ + g_return_val_if_fail (E_IS_SIGNATURE_MANAGER (manager), FALSE); + + return manager->priv->allow_scripts; +} + +void +e_signature_manager_set_allow_scripts (ESignatureManager *manager, + gboolean allow_scripts) +{ + g_return_if_fail (E_IS_SIGNATURE_MANAGER (manager)); + + manager->priv->allow_scripts = allow_scripts; + + g_object_notify (G_OBJECT (manager), "allow-scripts"); +} + +gboolean +e_signature_manager_get_prefer_html (ESignatureManager *manager) +{ + g_return_val_if_fail (E_IS_SIGNATURE_MANAGER (manager), FALSE); + + return manager->priv->prefer_html; +} + +void +e_signature_manager_set_prefer_html (ESignatureManager *manager, + gboolean prefer_html) +{ + g_return_if_fail (E_IS_SIGNATURE_MANAGER (manager)); + + manager->priv->prefer_html = prefer_html; + + g_object_notify (G_OBJECT (manager), "prefer-html"); +} + +ESignatureList * +e_signature_manager_get_signature_list (ESignatureManager *manager) +{ + g_return_val_if_fail (E_IS_SIGNATURE_MANAGER (manager), NULL); + + return manager->priv->signature_list; +} + +void +e_signature_manager_set_signature_list (ESignatureManager *manager, + ESignatureList *signature_list) +{ + g_return_if_fail (E_IS_SIGNATURE_MANAGER (manager)); + + if (signature_list != NULL) { + g_return_if_fail (E_IS_SIGNATURE_LIST (signature_list)); + g_object_ref (signature_list); + } + + if (manager->priv->signature_list != NULL) + g_object_unref (manager->priv->signature_list); + + manager->priv->signature_list = signature_list; + + g_object_notify (G_OBJECT (manager), "signature-list"); +} + +ESignatureTreeView * +e_signature_manager_get_tree_view (ESignatureManager *manager) +{ + g_return_val_if_fail (E_IS_SIGNATURE_MANAGER (manager), NULL); + + return E_SIGNATURE_TREE_VIEW (manager->priv->tree_view); +} diff --git a/widgets/misc/e-signature-manager.h b/widgets/misc/e-signature-manager.h new file mode 100644 index 0000000000..6c182badab --- /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 <widgets/misc/e-signature-editor.h> +#include <widgets/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..d618e05daa --- /dev/null +++ b/widgets/misc/e-signature-preview.c @@ -0,0 +1,344 @@ +/* + * e-signature-preview.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-signature-preview.h" + +#include <fcntl.h> +#include <string.h> +#include <unistd.h> +#include <glib/gstdio.h> +#include "e-util/e-signature-utils.h" + +#define E_SIGNATURE_PREVIEW_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_SIGNATURE_PREVIEW, ESignaturePreviewPrivate)) + +enum { + PROP_0, + PROP_ALLOW_SCRIPTS, + PROP_SIGNATURE +}; + +enum { + REFRESH, + LAST_SIGNAL +}; + +struct _ESignaturePreviewPrivate { + ESignature *signature; + guint allow_scripts : 1; +}; + +static gpointer parent_class; +static guint signals[LAST_SIGNAL]; + +static void +signature_preview_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_ALLOW_SCRIPTS: + e_signature_preview_set_allow_scripts ( + E_SIGNATURE_PREVIEW (object), + g_value_get_boolean (value)); + return; + + case PROP_SIGNATURE: + e_signature_preview_set_signature ( + E_SIGNATURE_PREVIEW (object), + g_value_get_object (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +signature_preview_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_ALLOW_SCRIPTS: + g_value_set_boolean ( + value, e_signature_preview_get_allow_scripts ( + E_SIGNATURE_PREVIEW (object))); + return; + + case PROP_SIGNATURE: + g_value_set_object ( + value, e_signature_preview_get_signature ( + E_SIGNATURE_PREVIEW (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +signature_preview_dispose (GObject *object) +{ + ESignaturePreviewPrivate *priv; + + priv = E_SIGNATURE_PREVIEW_GET_PRIVATE (object); + + if (priv->signature != NULL) { + g_object_unref (priv->signature); + priv->signature = NULL; + } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +signature_preview_url_requested (GtkHTML *html, + const gchar *url, + GtkHTMLStream *handle) +{ + GtkHTMLStreamStatus status; + gchar buffer[128]; + gchar *filename; + gssize size; + gint fd; + + /* FIXME Use GInputStream for this. */ + + if (g_str_has_prefix (url, "file:")) + filename = g_filename_from_uri (url, NULL, NULL); + else + filename = g_strdup (url); + fd = g_open (filename, O_RDONLY, 0); + g_free (filename); + + status = GTK_HTML_STREAM_OK; + if (fd != -1) { + while ((size = read (fd, buffer, sizeof (buffer)))) { + if (size == -1) { + status = GTK_HTML_STREAM_ERROR; + break; + } else + gtk_html_write (html, handle, buffer, size); + } + } else + status = GTK_HTML_STREAM_ERROR; + + gtk_html_end (html, handle, status); + + if (fd > 0) + close (fd); +} + +static void +signature_preview_refresh (ESignaturePreview *preview) +{ + GtkHTML *html; + ESignature *signature; + gchar *content = NULL; + gsize length; + + /* XXX We should show error messages in the preview. */ + + html = GTK_HTML (preview); + signature = e_signature_preview_get_signature (preview); + + if (signature == NULL) + goto clear; + + if (signature->script && !preview->priv->allow_scripts) + goto clear; + + if (signature->script) + content = e_run_signature_script (signature->filename); + else + content = e_read_signature_file (signature, FALSE, NULL); + + if (content == NULL || *content == '\0') + goto clear; + + length = strlen (content); + + if (signature->html) + gtk_html_load_from_string (html, content, length); + else { + GtkHTMLStream *stream; + + stream = gtk_html_begin_content ( + html, "text/html; charset=utf-8"); + gtk_html_write (html, stream, "<PRE>", 5); + if (length > 0) + gtk_html_write (html, stream, content, length); + gtk_html_write (html, stream, "</PRE>", 6); + gtk_html_end (html, stream, GTK_HTML_STREAM_OK); + } + + g_free (content); + return; + +clear: + gtk_html_load_from_string (html, " ", 1); + g_free (content); +} + +static void +signature_preview_class_init (ESignaturePreviewClass *class) +{ + GObjectClass *object_class; + GtkHTMLClass *html_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (ESignaturePreviewPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = signature_preview_set_property; + object_class->get_property = signature_preview_get_property; + object_class->dispose = signature_preview_dispose; + + html_class = GTK_HTML_CLASS (class); + html_class->url_requested = signature_preview_url_requested; + + class->refresh = signature_preview_refresh; + + g_object_class_install_property ( + object_class, + PROP_ALLOW_SCRIPTS, + g_param_spec_boolean ( + "allow-scripts", + "Allow Scripts", + NULL, + TRUE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + g_object_class_install_property ( + object_class, + PROP_SIGNATURE, + g_param_spec_object ( + "signature", + "Signature", + NULL, + E_TYPE_SIGNATURE, + G_PARAM_READWRITE)); + + signals[REFRESH] = g_signal_new ( + "refresh", + G_TYPE_FROM_CLASS (class), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (ESignaturePreviewClass, refresh), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); +} + +static void +signature_preview_init (ESignaturePreview *preview) +{ + preview->priv = E_SIGNATURE_PREVIEW_GET_PRIVATE (preview); +} + +GType +e_signature_preview_get_type (void) +{ + static GType type = 0; + + if (G_UNLIKELY (type == 0)) { + static const GTypeInfo type_info = { + sizeof (ESignaturePreviewClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) signature_preview_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (ESignaturePreview), + 0, /* n_preallocs */ + (GInstanceInitFunc) signature_preview_init, + NULL /* value_table */ + }; + + type = g_type_register_static ( + GTK_TYPE_HTML, "ESignaturePreview", &type_info, 0); + } + + return type; +} + +GtkWidget * +e_signature_preview_new (void) +{ + return g_object_new (E_TYPE_SIGNATURE_PREVIEW, NULL); +} + +void +e_signature_preview_refresh (ESignaturePreview *preview) +{ + g_return_if_fail (E_IS_SIGNATURE_PREVIEW (preview)); + + g_signal_emit (preview, signals[REFRESH], 0); +} + +gboolean +e_signature_preview_get_allow_scripts (ESignaturePreview *preview) +{ + g_return_val_if_fail (E_IS_SIGNATURE_PREVIEW (preview), FALSE); + + return preview->priv->allow_scripts; +} + +void +e_signature_preview_set_allow_scripts (ESignaturePreview *preview, + gboolean allow_scripts) +{ + g_return_if_fail (E_IS_SIGNATURE_PREVIEW (preview)); + + preview->priv->allow_scripts = allow_scripts; + g_object_notify (G_OBJECT (preview), "allow-scripts"); +} + +ESignature * +e_signature_preview_get_signature (ESignaturePreview *preview) +{ + g_return_val_if_fail (E_IS_SIGNATURE_PREVIEW (preview), NULL); + + return preview->priv->signature; +} + +void +e_signature_preview_set_signature (ESignaturePreview *preview, + ESignature *signature) +{ + g_return_if_fail (E_IS_SIGNATURE_PREVIEW (preview)); + + if (signature != NULL) { + g_return_if_fail (E_IS_SIGNATURE (signature)); + g_object_ref (signature); + } + + if (preview->priv->signature != NULL) + g_object_unref (preview->priv->signature); + + preview->priv->signature = signature; + g_object_notify (G_OBJECT (preview), "signature"); + + e_signature_preview_refresh (preview); +} diff --git a/widgets/misc/e-signature-preview.h b/widgets/misc/e-signature-preview.h new file mode 100644 index 0000000000..2cedcc1d2f --- /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..06e021b046 --- /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..4cd7f05632 --- /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..1f6d75b5b5 --- /dev/null +++ b/widgets/misc/e-signature-tree-view.c @@ -0,0 +1,445 @@ +/* + * e-signature-tree-view.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-signature-tree-view.h" + +#define E_SIGNATURE_TREE_VIEW_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_SIGNATURE_TREE_VIEW, ESignatureTreeViewPrivate)) + +enum { + COLUMN_STRING, + COLUMN_SIGNATURE +}; + +enum { + PROP_0, + PROP_SELECTED, + PROP_SIGNATURE_LIST +}; + +enum { + REFRESHED, + LAST_SIGNAL +}; + +struct _ESignatureTreeViewPrivate { + ESignatureList *signature_list; + GHashTable *index; +}; + +static gpointer parent_class; +static guint signals[LAST_SIGNAL]; + +static void +signature_tree_view_refresh_cb (ESignatureList *signature_list, + ESignature *unused, + ESignatureTreeView *tree_view) +{ + GtkListStore *store; + GtkTreeModel *model; + GtkTreeIter tree_iter; + EIterator *signature_iter; + ESignature *signature; + GHashTable *index; + GList *list = NULL; + GList *iter; + + store = gtk_list_store_new (2, G_TYPE_STRING, E_TYPE_SIGNATURE); + model = GTK_TREE_MODEL (store); + index = tree_view->priv->index; + + g_hash_table_remove_all (index); + + if (signature_list == NULL) + goto skip; + + /* Build a list of ESignatures to display. */ + signature_iter = e_list_get_iterator (E_LIST (signature_list)); + while (e_iterator_is_valid (signature_iter)) { + + /* XXX EIterator misuses const. */ + signature = (ESignature *) e_iterator_get (signature_iter); + list = g_list_prepend (list, signature); + e_iterator_next (signature_iter); + } + g_object_unref (signature_iter); + + list = g_list_reverse (list); + + /* Populate the list store and index. */ + for (iter = list; iter != NULL; iter = iter->next) { + GtkTreeRowReference *reference; + GtkTreePath *path; + + signature = iter->data; + + /* Skip autogenerated signatures. */ + if (signature->autogen) + continue; + + gtk_list_store_append (store, &tree_iter); + gtk_list_store_set ( + store, &tree_iter, + COLUMN_STRING, signature->name, + COLUMN_SIGNATURE, signature, -1); + + path = gtk_tree_model_get_path (model, &tree_iter); + reference = gtk_tree_row_reference_new (model, path); + g_hash_table_insert (index, signature, reference); + gtk_tree_path_free (path); + } + +skip: + /* Restore the previously selected signature. */ + signature = e_signature_tree_view_get_selected (tree_view); + if (signature != NULL) + g_object_ref (signature); + gtk_tree_view_set_model (GTK_TREE_VIEW (tree_view), model); + e_signature_tree_view_set_selected (tree_view, signature); + if (signature != NULL) + g_object_unref (signature); + + g_signal_emit (tree_view, signals[REFRESHED], 0); +} + +static void +signature_tree_view_selection_changed_cb (ESignatureTreeView *tree_view) +{ + g_object_notify (G_OBJECT (tree_view), "selected"); +} + +static GObject * +signature_tree_view_constructor (GType type, + guint n_construct_properties, + GObjectConstructParam *construct_properties) +{ + GObject *object; + GtkTreeView *tree_view; + GtkTreeViewColumn *column; + GtkCellRenderer *renderer; + + /* Chain up to parent's constructor() method. */ + object = G_OBJECT_CLASS (parent_class)->constructor ( + type, n_construct_properties, construct_properties); + + tree_view = GTK_TREE_VIEW (object); + gtk_tree_view_set_headers_visible (tree_view, FALSE); + + column = gtk_tree_view_column_new (); + renderer = gtk_cell_renderer_text_new (); + gtk_tree_view_column_pack_start (column, renderer, TRUE); + gtk_tree_view_column_add_attribute ( + column, renderer, "text", COLUMN_STRING); + gtk_tree_view_append_column (tree_view, column); + + return object; +} + +static void +signature_tree_view_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_SELECTED: + e_signature_tree_view_set_selected ( + E_SIGNATURE_TREE_VIEW (object), + g_value_get_object (value)); + return; + + case PROP_SIGNATURE_LIST: + e_signature_tree_view_set_signature_list ( + E_SIGNATURE_TREE_VIEW (object), + g_value_get_object (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +signature_tree_view_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_SELECTED: + g_value_set_object ( + value, + e_signature_tree_view_get_selected ( + E_SIGNATURE_TREE_VIEW (object))); + return; + + case PROP_SIGNATURE_LIST: + g_value_set_object ( + value, + e_signature_tree_view_get_signature_list ( + E_SIGNATURE_TREE_VIEW (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +signature_tree_view_dispose (GObject *object) +{ + ESignatureTreeViewPrivate *priv; + + priv = E_SIGNATURE_TREE_VIEW_GET_PRIVATE (object); + + if (priv->signature_list != NULL) { + g_signal_handlers_disconnect_by_func ( + priv->signature_list, + signature_tree_view_refresh_cb, object); + g_object_unref (priv->signature_list); + priv->signature_list = NULL; + } + + g_hash_table_remove_all (priv->index); + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +signature_tree_view_finalize (GObject *object) +{ + ESignatureTreeViewPrivate *priv; + + priv = E_SIGNATURE_TREE_VIEW_GET_PRIVATE (object); + + g_hash_table_destroy (priv->index); + + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +signature_tree_view_class_init (ESignatureTreeViewClass *class) +{ + GObjectClass *object_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (ESignatureTreeViewPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->constructor = signature_tree_view_constructor; + object_class->set_property = signature_tree_view_set_property; + object_class->get_property = signature_tree_view_get_property; + object_class->dispose = signature_tree_view_dispose; + object_class->finalize = signature_tree_view_finalize; + + g_object_class_install_property ( + object_class, + PROP_SELECTED, + g_param_spec_object ( + "selected", + "Selected Signature", + NULL, + E_TYPE_SIGNATURE, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_SIGNATURE_LIST, + g_param_spec_object ( + "signature-list", + "Signature List", + NULL, + E_TYPE_SIGNATURE_LIST, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + signals[REFRESHED] = g_signal_new ( + "refreshed", + G_TYPE_FROM_CLASS (class), + G_SIGNAL_RUN_LAST, + 0, NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); +} + +static void +signature_tree_view_init (ESignatureTreeView *tree_view) +{ + GHashTable *index; + GtkTreeSelection *selection; + + /* Reverse-lookup index */ + index = g_hash_table_new_full ( + g_direct_hash, g_direct_equal, + (GDestroyNotify) g_object_unref, + (GDestroyNotify) gtk_tree_row_reference_free); + + tree_view->priv = E_SIGNATURE_TREE_VIEW_GET_PRIVATE (tree_view); + tree_view->priv->index = index; + + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view)); + + g_signal_connect_swapped ( + selection, "changed", + G_CALLBACK (signature_tree_view_selection_changed_cb), + tree_view); +} + +GType +e_signature_tree_view_get_type (void) +{ + static GType type = 0; + + if (G_UNLIKELY (type == 0)) { + static const GTypeInfo type_info = { + sizeof (ESignatureTreeViewClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) signature_tree_view_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (ESignatureTreeView), + 0, /* n_preallocs */ + (GInstanceInitFunc) signature_tree_view_init, + NULL /* value_table */ + }; + + type = g_type_register_static ( + GTK_TYPE_TREE_VIEW, "ESignatureTreeView", + &type_info, 0); + } + + return type; +} + +GtkWidget * +e_signature_tree_view_new (void) +{ + return g_object_new (E_TYPE_SIGNATURE_TREE_VIEW, NULL); +} + +ESignatureList * +e_signature_tree_view_get_signature_list (ESignatureTreeView *tree_view) +{ + g_return_val_if_fail (E_IS_SIGNATURE_TREE_VIEW (tree_view), NULL); + + return tree_view->priv->signature_list; +} + +void +e_signature_tree_view_set_signature_list (ESignatureTreeView *tree_view, + ESignatureList *signature_list) +{ + ESignatureTreeViewPrivate *priv; + + g_return_if_fail (E_IS_SIGNATURE_TREE_VIEW (tree_view)); + + if (signature_list != NULL) + g_return_if_fail (E_IS_SIGNATURE_LIST (signature_list)); + + priv = E_SIGNATURE_TREE_VIEW_GET_PRIVATE (tree_view); + + if (priv->signature_list != NULL) { + g_signal_handlers_disconnect_by_func ( + priv->signature_list, + signature_tree_view_refresh_cb, tree_view); + g_object_unref (priv->signature_list); + priv->signature_list = NULL; + } + + if (signature_list != NULL) { + priv->signature_list = g_object_ref (signature_list); + + /* Listen for changes to the signature list. */ + g_signal_connect ( + priv->signature_list, "signature-added", + G_CALLBACK (signature_tree_view_refresh_cb), + tree_view); + g_signal_connect ( + priv->signature_list, "signature-changed", + G_CALLBACK (signature_tree_view_refresh_cb), + tree_view); + g_signal_connect ( + priv->signature_list, "signature-removed", + G_CALLBACK (signature_tree_view_refresh_cb), + tree_view); + } + + signature_tree_view_refresh_cb (signature_list, NULL, tree_view); + + g_object_notify (G_OBJECT (tree_view), "signature-list"); +} + +ESignature * +e_signature_tree_view_get_selected (ESignatureTreeView *tree_view) +{ + ESignature *signature; + GtkTreeSelection *selection; + GtkTreeModel *model; + GtkTreeIter iter; + + g_return_val_if_fail (E_IS_SIGNATURE_TREE_VIEW (tree_view), NULL); + + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view)); + if (!gtk_tree_selection_get_selected (selection, &model, &iter)) + return NULL; + + gtk_tree_model_get (model, &iter, COLUMN_SIGNATURE, &signature, -1); + + return signature; +} + +gboolean +e_signature_tree_view_set_selected (ESignatureTreeView *tree_view, + ESignature *signature) +{ + GtkTreeRowReference *reference; + GtkTreeSelection *selection; + GtkTreePath *path; + + g_return_val_if_fail (E_IS_SIGNATURE_TREE_VIEW (tree_view), FALSE); + + if (signature != NULL) + g_return_val_if_fail (E_IS_SIGNATURE (signature), FALSE); + + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view)); + + /* NULL means clear the selection. */ + if (signature == NULL) { + gtk_tree_selection_unselect_all (selection); + return TRUE; + } + + /* Lookup the tree row reference for the signature. */ + reference = g_hash_table_lookup (tree_view->priv->index, signature); + if (reference == NULL) + return FALSE; + + /* Select the referenced path. */ + path = gtk_tree_row_reference_get_path (reference); + gtk_tree_selection_select_path (selection, path); + gtk_tree_path_free (path); + + g_object_notify (G_OBJECT (tree_view), "selected"); + + return TRUE; +} diff --git a/widgets/misc/e-signature-tree-view.h b/widgets/misc/e-signature-tree-view.h new file mode 100644 index 0000000000..3afe569136 --- /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 8400f298f7..0000000000 --- a/widgets/misc/e-task-bar.c +++ /dev/null @@ -1,302 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see <http://www.gnu.org/licenses/> - * - * - * Authors: - * Ettore Perazzoli <ettore@ximian.com> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "e-task-bar.h" - -struct _ETaskBarPrivate -{ - GtkWidget *message_label; - GtkHBox *hbox; -}; - -/* WARNING: Ugly hack starts here. */ -#define MAX_ACTIVITIES_PER_COMPONENT 2 - -G_DEFINE_TYPE (ETaskBar, e_task_bar, GTK_TYPE_HBOX) - -#if 0 -static void -reduce_displayed_activities_per_component (ETaskBar *task_bar) -{ - GHashTable *component_ids_hash; - GtkBox *box; - GList *p; - - component_ids_hash = g_hash_table_new (g_str_hash, g_str_equal); - - box = GTK_BOX (task_bar->priv->hbox); - - for (p = box->children; p != NULL; p = p->next) { - GtkBoxChild *child; - const char *component_id; - void *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, (void *) component_id, GINT_TO_POINTER (1)); - } else { - int 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, (void *) 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 char *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, - int n) -{ - ETaskWidget *task_widget; - - g_return_if_fail (task_bar != NULL); - g_return_if_fail (E_IS_TASK_BAR (task_bar)); - g_return_if_fail (n >= 0); - - task_widget = e_task_bar_get_task_widget (task_bar, n); - gtk_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, - int n) -{ - GtkBoxChild *child_info; - - g_return_val_if_fail (task_bar != NULL, NULL); - g_return_val_if_fail (E_IS_TASK_BAR (task_bar), NULL); - - child_info = (GtkBoxChild *) g_list_nth (GTK_BOX (task_bar->priv->hbox)->children, n)->data; - - return E_TASK_WIDGET (child_info->widget); -} - diff --git a/widgets/misc/e-task-bar.h b/widgets/misc/e-task-bar.h deleted file mode 100644 index 363e062ee8..0000000000 --- a/widgets/misc/e-task-bar.h +++ /dev/null @@ -1,81 +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> - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#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 char *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, - int 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, - int n); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#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 d545613998..0000000000 --- a/widgets/misc/e-task-widget.c +++ /dev/null @@ -1,291 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see <http://www.gnu.org/licenses/> - * - * - * Authors: - * Ettore Perazzoli <ettore@ximian.com> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "e-task-widget.h" -#include "e-spinner.h" - -#include <glib/gi18n.h> - - -#define SPACING 2 - -struct _ETaskWidgetPrivate { - char *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 char *component_id, - const char *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 char *component_id, - const char *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 char *component_id, - const char *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 char *stock, const char *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 char *information, - double completion) -{ - ETaskWidgetPrivate *priv; - char *text; - - g_return_if_fail (task_widget != NULL); - g_return_if_fail (E_IS_TASK_WIDGET (task_widget)); - g_return_if_fail (information != NULL); - - priv = task_widget->priv; - - if (completion < 0.0) { - /* For Translator only: %s is status message that is displayed (eg "moving items", "updating objects") */ - text = g_strdup_printf (_("%s (...)"), information); - } else { - int percent_complete; - percent_complete = (int) (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 char * -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 e478e91145..0000000000 --- a/widgets/misc/e-task-widget.h +++ /dev/null @@ -1,82 +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> - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#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 char *component_id, - const char *information, - void (*cancel_func) (gpointer data), - gpointer data); -GtkWidget * e_task_widget_new (const char *component_id, - const char *information); -GtkWidget * e_task_widget_new_with_cancel (const char *component_id, - const char *information, - void (*cancel_func) (gpointer data), - gpointer data); -void e_task_widget_update (ETaskWidget *task_widget, - const char *information, - double completion); -GtkWidget * e_task_widget_update_image (ETaskWidget *task_widget, - const char *stock, - const char *text); -void e_task_wiget_alert (ETaskWidget *task_widget); -void e_task_wiget_unalert (ETaskWidget *task_widget); -const char * e_task_widget_get_component_id (ETaskWidget *task_widget); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#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..878d6b87a3 --- /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..b395f39bde --- /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/test-calendar.c b/widgets/misc/test-calendar.c index 117def6190..f4fe6d3039 100644 --- a/widgets/misc/test-calendar.c +++ b/widgets/misc/test-calendar.c @@ -118,7 +118,7 @@ on_date_range_changed (ECalendarItem *calitem) start_day, start_month + 1, start_year, end_day, end_month + 1, end_year); - /* These days should appear bold. Remember month is 0 to 11. */ + /* These days should windowear bold. Remember month is 0 to 11. */ e_calendar_item_mark_day (calitem, 2000, 7, 26, /* 26th Aug 2000. */ E_CALENDAR_ITEM_MARK_BOLD); 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 f0a7ca4d0e..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, - void *data) -{ - printf ("%s activated.\n", (char *) data); -} - -static GnomeUIInfo ui_info[] = { - { GNOME_APP_UI_ITEM, "_New", "Create a new file", item_activated, "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, "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, "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, "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, "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, "file/close", NULL, - GNOME_APP_PIXMAP_STOCK, GTK_STOCK_CLOSE, 0, 0, NULL }, - { GNOME_APP_UI_ITEM, "E_xit", "Exit the program", item_activated, "file/exit", NULL, - GNOME_APP_PIXMAP_STOCK, GTK_STOCK_QUIT, 'q', GDK_CONTROL_MASK, NULL }, - GNOMEUIINFO_END -}; - - -int -main (int argc, char **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 c8b442b23a..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" - -int -main (int argc, char **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 2ef47483ed..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 (); -} - -int -main (int argc, char **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 bc52f493c6..bc53f98c58 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) { int i; for (i = 0; i < NUM_PAGES; i ++) { GtkWidget *widget; - GtkWidget *page; - char *string; - char *title; - char *description; + char *caption; + char *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; } - int main (int argc, char **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 (); |