diff options
Diffstat (limited to 'mail/em-folder-selection-button.c')
-rw-r--r-- | mail/em-folder-selection-button.c | 545 |
1 files changed, 367 insertions, 178 deletions
diff --git a/mail/em-folder-selection-button.c b/mail/em-folder-selection-button.c index 9257c57b5d..f85d3d84fb 100644 --- a/mail/em-folder-selection-button.c +++ b/mail/em-folder-selection-button.c @@ -25,11 +25,9 @@ #endif #include <string.h> - -#include <e-util/e-util.h> #include <glib/gi18n.h> +#include <e-util/e-util.h> -#include "mail-component.h" #include "mail-config.h" #include "em-folder-tree.h" #include "em-folder-selector.h" @@ -37,250 +35,419 @@ #include "em-folder-selection-button.h" -static void em_folder_selection_button_class_init (EMFolderSelectionButtonClass *klass); -static void em_folder_selection_button_init (EMFolderSelectionButton *emfsb); -static void em_folder_selection_button_destroy (GtkObject *obj); -static void em_folder_selection_button_finalize (GObject *obj); -static void em_folder_selection_button_clicked (GtkButton *button); - -static GtkButtonClass *parent_class = NULL; +#define EM_FOLDER_SELECTION_BUTTON_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), EM_TYPE_FOLDER_SELECTION_BUTTON, EMFolderSelectionButtonPrivate)) struct _EMFolderSelectionButtonPrivate { + gpointer model; /* weak pointer */ + GtkWidget *icon; GtkWidget *label; - GtkWidget *selector; - - char *uri; /* for single-select mode */ + gchar *uri; /* for single-select mode */ GList *uris; /* for multi-select mode */ - char *title; - char *caption; + gchar *title; + gchar *caption; gboolean multiple_select; }; enum { + PROP_0, + PROP_CAPTION, + PROP_MODEL, + PROP_MULTISELECT, + PROP_TITLE +}; + +enum { SELECTED, LAST_SIGNAL }; -static guint signals[LAST_SIGNAL] = { 0 }; +static gpointer parent_class; +static guint signals[LAST_SIGNAL]; -GType -em_folder_selection_button_get_type (void) +static void +folder_selection_button_unselected (EMFolderSelectionButton *button) { - static GType type = 0; + const gchar *text; - if (!type) { - static const GTypeInfo info = { - sizeof (EMFolderSelectionButtonClass), - NULL, /* base_class_init */ - NULL, /* base_class_finalize */ - (GClassInitFunc) em_folder_selection_button_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (EMFolderSelectionButton), - 0, /* n_preallocs */ - (GInstanceInitFunc) em_folder_selection_button_init, - }; + text = _("<click here to select a folder>"); + gtk_image_set_from_pixbuf (GTK_IMAGE (button->priv->icon), NULL); + gtk_label_set_text (GTK_LABEL (button->priv->label), text); +} - type = g_type_register_static (GTK_TYPE_BUTTON, "EMFolderSelectionButton", &info, 0); +static void +folder_selection_button_set_contents (EMFolderSelectionButton *button) +{ + EAccount *account; + GtkLabel *label; + const gchar *uri; + gchar *folder_name; + + uri = button->priv->uri; + label = GTK_LABEL (button->priv->label); + folder_name = em_utils_folder_name_from_uri (uri); + + if (folder_name == NULL) { + folder_selection_button_unselected (button); + return; } - return type; + account = mail_config_get_account_by_source_url (uri); + + if (account != NULL) { + gchar *tmp = folder_name; + + folder_name = g_strdup_printf ( + "%s/%s", e_account_get_string ( + account, E_ACCOUNT_NAME), _(folder_name)); + gtk_label_set_text (label, folder_name); + g_free (tmp); + } else + gtk_label_set_text (label, _(folder_name)); + + g_free (folder_name); } static void -em_folder_selection_button_class_init (EMFolderSelectionButtonClass *klass) +folder_selection_button_set_model (EMFolderSelectionButton *button, + EMFolderTreeModel *model) { - GObjectClass *object_class = G_OBJECT_CLASS (klass); - GtkObjectClass *gtk_object_class = GTK_OBJECT_CLASS (klass); - GtkButtonClass *button_class = GTK_BUTTON_CLASS (klass); - - parent_class = g_type_class_ref (GTK_TYPE_BUTTON); - - object_class->finalize = em_folder_selection_button_finalize; - gtk_object_class->destroy = em_folder_selection_button_destroy; - button_class->clicked = em_folder_selection_button_clicked; - - signals[SELECTED] = g_signal_new ("selected", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (EMFolderSelectionButtonClass, selected), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); + g_return_if_fail (button->priv->model == NULL); + + button->priv->model = model; + + g_object_add_weak_pointer ( + G_OBJECT (model), &button->priv->model); } static void -set_contents_unselected (EMFolderSelectionButton *button) +folder_selection_button_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) { - gtk_image_set_from_pixbuf (GTK_IMAGE (button->priv->icon), NULL); - gtk_label_set_text (GTK_LABEL (button->priv->label), _("<click here to select a folder>")); + switch (property_id) { + case PROP_CAPTION: + em_folder_selection_button_set_caption ( + EM_FOLDER_SELECTION_BUTTON (object), + g_value_get_string (value)); + return; + + case PROP_MODEL: + folder_selection_button_set_model ( + EM_FOLDER_SELECTION_BUTTON (object), + g_value_get_object (value)); + return; + + case PROP_MULTISELECT: + em_folder_selection_button_set_multiselect ( + EM_FOLDER_SELECTION_BUTTON (object), + g_value_get_boolean (value)); + return; + + case PROP_TITLE: + em_folder_selection_button_set_title ( + EM_FOLDER_SELECTION_BUTTON (object), + g_value_get_string (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } static void -set_contents (EMFolderSelectionButton *button) +folder_selection_button_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) { - struct _EMFolderSelectionButtonPrivate *priv = button->priv; - char *folder_name = em_utils_folder_name_from_uri (priv->uri); + switch (property_id) { + case PROP_CAPTION: + g_value_set_string ( + value, + em_folder_selection_button_get_caption ( + EM_FOLDER_SELECTION_BUTTON (object))); + return; + + case PROP_MODEL: + g_value_set_object ( + value, + em_folder_selection_button_get_model ( + EM_FOLDER_SELECTION_BUTTON (object))); + return; + + case PROP_MULTISELECT: + g_value_set_boolean ( + value, + em_folder_selection_button_get_multiselect ( + EM_FOLDER_SELECTION_BUTTON (object))); + return; + + case PROP_TITLE: + g_value_set_string ( + value, + em_folder_selection_button_get_title ( + EM_FOLDER_SELECTION_BUTTON (object))); + return; + } - if (folder_name) { - EAccount *account = mail_config_get_account_by_source_url (priv->uri); + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} - if (account) { - char *tmp = folder_name; - folder_name = g_strdup_printf ("%s/%s", e_account_get_string (account, E_ACCOUNT_NAME), _(folder_name)); - g_free (tmp); - gtk_label_set_text (GTK_LABEL (priv->label), folder_name); - } else - gtk_label_set_text (GTK_LABEL (priv->label), _(folder_name)); +static void +folder_selection_button_dispose (GObject *object) +{ + EMFolderSelectionButtonPrivate *priv; - g_free (folder_name); - } else { - set_contents_unselected (button); + priv = EM_FOLDER_SELECTION_BUTTON_GET_PRIVATE (object); + + if (priv->model != NULL) { + g_object_remove_weak_pointer ( + G_OBJECT (priv->model), &priv->model); + priv->model = NULL; } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); } static void -em_folder_selection_button_init (EMFolderSelectionButton *emfsb) +folder_selection_button_finalize (GObject *object) { - struct _EMFolderSelectionButtonPrivate *priv; - GtkWidget *box; + EMFolderSelectionButtonPrivate *priv; - priv = g_new0 (struct _EMFolderSelectionButtonPrivate, 1); - emfsb->priv = priv; + priv = EM_FOLDER_SELECTION_BUTTON_GET_PRIVATE (object); - priv->multiple_select = FALSE; + g_list_foreach (priv->uris, (GFunc) g_free, NULL); + g_list_free (priv->uris); - box = gtk_hbox_new (FALSE, 4); + g_free (priv->title); + g_free (priv->caption); + g_free (priv->uri); - priv->icon = gtk_image_new (); - gtk_widget_show (priv->icon); - gtk_box_pack_start (GTK_BOX (box), priv->icon, FALSE, TRUE, 0); + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (parent_class)->finalize (object); +} - priv->label = gtk_label_new (""); - gtk_widget_show (priv->label); - gtk_label_set_justify (GTK_LABEL (priv->label), GTK_JUSTIFY_LEFT); - gtk_misc_set_alignment (GTK_MISC (priv->label), 0.0, 0.0); - gtk_box_pack_start (GTK_BOX (box), priv->label, TRUE, TRUE, 0); +static void +folder_selection_button_destroy (GtkObject *object) +{ + EMFolderSelectionButtonPrivate *priv; - gtk_widget_show (box); - gtk_container_add (GTK_CONTAINER (emfsb), box); + priv = EM_FOLDER_SELECTION_BUTTON_GET_PRIVATE (object); - set_contents (emfsb); + /* Chain up to parent's destroy() method. */ + GTK_OBJECT_CLASS (parent_class)->destroy (object); } static void -em_folder_selection_button_destroy (GtkObject *obj) +folder_selection_button_clicked (GtkButton *button) { - struct _EMFolderSelectionButtonPrivate *priv = ((EMFolderSelectionButton *) obj)->priv; + EMFolderSelectionButtonPrivate *priv; + EMFolderTree *emft; + GtkWidget *dialog; + + priv = EM_FOLDER_SELECTION_BUTTON_GET_PRIVATE (button); + + /* Chain up to parent's clicked() method. */ + GTK_BUTTON_CLASS (parent_class)->clicked (button); + + emft = (EMFolderTree *) em_folder_tree_new_with_model (priv->model); + + em_folder_tree_set_multiselect (emft, priv->multiple_select); + em_folder_tree_set_excluded ( + emft, EMFT_EXCLUDE_NOSELECT | + EMFT_EXCLUDE_VIRTUAL | EMFT_EXCLUDE_VTRASH); + + dialog = em_folder_selector_new ( + emft, EM_FOLDER_SELECTOR_CAN_CREATE, + priv->title, priv->caption, NULL); + + if (priv->multiple_select) + em_folder_selector_set_selected_list ( + EM_FOLDER_SELECTOR (dialog), priv->uris); + else + em_folder_selector_set_selected ( + EM_FOLDER_SELECTOR (dialog), priv->uri); - if (priv->selector) { - gtk_widget_destroy(priv->selector); - priv->selector = NULL; + if (gtk_dialog_run (GTK_DIALOG (dialog)) != GTK_RESPONSE_OK) + goto exit; + + if (priv->multiple_select) { + GList *uris; + + uris = em_folder_selector_get_selected_uris ( + EM_FOLDER_SELECTOR (dialog)); + em_folder_selection_button_set_selection_mult ( + EM_FOLDER_SELECTION_BUTTON (button), uris); + } else { + const gchar *uri; + + uri = em_folder_selector_get_selected_uri ( + EM_FOLDER_SELECTOR (dialog)); + em_folder_selection_button_set_selection ( + EM_FOLDER_SELECTION_BUTTON (button), uri); } - GTK_OBJECT_CLASS (parent_class)->destroy (obj); + g_signal_emit (button, signals[SELECTED], 0); + +exit: + gtk_widget_destroy (dialog); } static void -em_folder_selection_button_finalize (GObject *obj) +folder_selection_button_class_init (EMFolderSelectionButtonClass *class) { - struct _EMFolderSelectionButtonPrivate *priv = ((EMFolderSelectionButton *) obj)->priv; + GObjectClass *object_class; + GtkObjectClass *gtk_object_class; + GtkButtonClass *button_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EMFolderSelectionButtonPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = folder_selection_button_set_property; + object_class->get_property = folder_selection_button_get_property; + object_class->dispose = folder_selection_button_dispose; + object_class->finalize = folder_selection_button_finalize; + + gtk_object_class = GTK_OBJECT_CLASS (class); + gtk_object_class->destroy = folder_selection_button_destroy; + + button_class = GTK_BUTTON_CLASS (class); + button_class->clicked = folder_selection_button_clicked; + + signals[SELECTED] = g_signal_new ( + "selected", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (EMFolderSelectionButtonClass, selected), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); +} - GList *lst = ((EMFolderSelectionButton*) obj)->priv->uris; - g_list_foreach (lst, (GFunc) g_free, NULL); - g_list_free (lst); +static void +folder_selection_button_init (EMFolderSelectionButton *emfsb) +{ + struct _EMFolderSelectionButtonPrivate *priv; + GtkWidget *box; - g_free (priv->title); - g_free (priv->caption); - g_free (priv->uri); - g_free (priv); + emfsb->priv = EM_FOLDER_SELECTION_BUTTON_GET_PRIVATE (emfsb); + + emfsb->priv->multiple_select = FALSE; - G_OBJECT_CLASS (parent_class)->finalize (obj); + box = gtk_hbox_new (FALSE, 4); + + emfsb->priv->icon = gtk_image_new (); + gtk_widget_show (priv->icon); + gtk_box_pack_start (GTK_BOX (box), emfsb->priv->icon, FALSE, TRUE, 0); + + emfsb->priv->label = gtk_label_new (""); + gtk_widget_show (emfsb->priv->label); + gtk_label_set_justify (GTK_LABEL (emfsb->priv->label), GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment (GTK_MISC (emfsb->priv->label), 0.0, 0.0); + gtk_box_pack_start (GTK_BOX (box), emfsb->priv->label, TRUE, TRUE, 0); + + gtk_widget_show (box); + gtk_container_add (GTK_CONTAINER (emfsb), box); + + folder_selection_button_set_contents (emfsb); } -static void -emfsb_selector_response (EMFolderSelector *emfs, int response, EMFolderSelectionButton *button) +GType +em_folder_selection_button_get_type (void) { - if (response == GTK_RESPONSE_OK) { - if (button->priv->multiple_select) { - GList *uris = em_folder_selector_get_selected_uris (emfs); + static GType type = 0; - em_folder_selection_button_set_selection_mult (button, uris); - g_signal_emit (button, signals[SELECTED], 0); - } else { - const char *uri = em_folder_selector_get_selected_uri (emfs); + if (G_UNLIKELY (type == 0)) { + static const GTypeInfo type_info = { + sizeof (EMFolderSelectionButtonClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) folder_selection_button_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EMFolderSelectionButton), + 0, /* n_preallocs */ + (GInstanceInitFunc) folder_selection_button_init, + NULL /* value_table */ + }; - em_folder_selection_button_set_selection (button, uri); - g_signal_emit (button, signals[SELECTED], 0); - } + type = g_type_register_static ( + GTK_TYPE_BUTTON, "EMFolderSelectionButton", + &type_info, 0); } - gtk_widget_destroy ((GtkWidget *) emfs); + return type; } -static void -em_folder_selection_button_clicked (GtkButton *button) +GtkWidget * +em_folder_selection_button_new (EMFolderTreeModel *model, + const gchar *title, + const gchar *caption) { - struct _EMFolderSelectionButtonPrivate *priv = EM_FOLDER_SELECTION_BUTTON (button)->priv; - EMFolderTreeModel *model; - EMFolderTree *emft; - GtkWidget *dialog; + g_return_val_if_fail (EM_IS_FOLDER_TREE_MODEL (model), NULL); - if (GTK_BUTTON_CLASS (parent_class)->clicked != NULL) - (* GTK_BUTTON_CLASS (parent_class)->clicked) (button); + return g_object_new ( + EM_TYPE_FOLDER_SELECTION_BUTTON, + "model", model, "title", title, + "caption", caption, NULL); +} - if (priv->selector) { - gtk_window_present((GtkWindow *)priv->selector); - return; - } +EMFolderTreeModel * +em_folder_selection_button_get_model (EMFolderSelectionButton *button) +{ + g_return_val_if_fail (EM_IS_FOLDER_SELECTION_BUTTON (button), NULL); - model = mail_component_peek_tree_model (mail_component_peek ()); - emft = (EMFolderTree *) em_folder_tree_new_with_model (model); - g_object_unref (model); - em_folder_tree_set_multiselect (emft, priv->multiple_select); - em_folder_tree_set_excluded(emft, EMFT_EXCLUDE_NOSELECT|EMFT_EXCLUDE_VIRTUAL|EMFT_EXCLUDE_VTRASH); - dialog = em_folder_selector_new (emft, EM_FOLDER_SELECTOR_CAN_CREATE, priv->title, priv->caption, NULL); - if (priv->multiple_select) - em_folder_selector_set_selected_list ((EMFolderSelector *) dialog, priv->uris); - else - em_folder_selector_set_selected ((EMFolderSelector *) dialog, priv->uri); - g_signal_connect (dialog, "response", G_CALLBACK (emfsb_selector_response), button); - priv->selector = dialog; - g_signal_connect(dialog, "destroy", G_CALLBACK(gtk_widget_destroyed), &priv->selector); - gtk_widget_show (dialog); + return button->priv->model; } -GtkWidget * -em_folder_selection_button_new (const char *title, const char *caption) +const gchar * +em_folder_selection_button_get_caption (EMFolderSelectionButton *button) { - EMFolderSelectionButton *button = g_object_new (EM_TYPE_FOLDER_SELECTION_BUTTON, NULL); + g_return_val_if_fail (EM_IS_FOLDER_SELECTION_BUTTON (button), NULL); - button->priv->title = g_strdup (title); + return button->priv->caption; +} + +void +em_folder_selection_button_set_caption (EMFolderSelectionButton *button, + const gchar *caption) +{ + g_return_if_fail (EM_IS_FOLDER_SELECTION_BUTTON (button)); + + g_free (button->priv->caption); button->priv->caption = g_strdup (caption); - return GTK_WIDGET (button); + g_object_notify (G_OBJECT (button), "caption"); } -void -em_folder_selection_button_set_selection (EMFolderSelectionButton *button, const char *uri) +gboolean +em_folder_selection_button_get_multiselect (EMFolderSelectionButton *button) { - struct _EMFolderSelectionButtonPrivate *priv = button->priv; + g_return_val_if_fail (EM_IS_FOLDER_SELECTION_BUTTON (button), FALSE); + + return button->priv->multiple_select; +} +void +em_folder_selection_button_set_multiselect (EMFolderSelectionButton *button, + gboolean multiselect) +{ g_return_if_fail (EM_IS_FOLDER_SELECTION_BUTTON (button)); - if (priv->uri != uri) { - g_free (priv->uri); - priv->uri = g_strdup (uri); - } + button->priv->multiple_select = multiselect; - set_contents (button); + g_object_notify (G_OBJECT (button), "multiselect"); } -const char * +const gchar * em_folder_selection_button_get_selection (EMFolderSelectionButton *button) { g_return_val_if_fail (EM_IS_FOLDER_SELECTION_BUTTON (button), NULL); @@ -289,20 +456,40 @@ em_folder_selection_button_get_selection (EMFolderSelectionButton *button) } void -em_folder_selection_button_set_selection_mult (EMFolderSelectionButton *button, GList *uris) +em_folder_selection_button_set_selection (EMFolderSelectionButton *button, + const gchar *uri) +{ + g_return_if_fail (EM_IS_FOLDER_SELECTION_BUTTON (button)); + + if (g_strcmp0 (button->priv->uri, uri) == 0) + return; + + g_free (button->priv->uri); + button->priv->uri = g_strdup (uri); + + folder_selection_button_set_contents (button); +} + +GList * +em_folder_selection_button_get_selection_mult (EMFolderSelectionButton *button) +{ + g_return_val_if_fail (EM_IS_FOLDER_SELECTION_BUTTON (button), NULL); + + return button->priv->uris; +} + +void +em_folder_selection_button_set_selection_mult (EMFolderSelectionButton *button, + GList *uris) { - struct _EMFolderSelectionButtonPrivate *priv = button->priv; char *caption, *tmp, *tmp2; g_return_if_fail (EM_IS_FOLDER_SELECTION_BUTTON (button)); - if (priv->uris) { - g_list_foreach (priv->uris, (GFunc) g_free, NULL); - g_list_free (priv->uris); - priv->uris = NULL; - } + g_list_foreach (button->priv->uris, (GFunc) g_free, NULL); + g_list_free (button->priv->uris); - priv->uris = uris; + button->priv->uris = uris; /* compile the name */ caption = g_strdup (""); @@ -319,34 +506,36 @@ em_folder_selection_button_set_selection_mult (EMFolderSelectionButton *button, /* apparently, we do not know this folder, so we'll just skip it */ g_free (uris->data); uris = g_list_next (uris); - priv->uris = g_list_remove (priv->uris, uris->data); + button->priv->uris = g_list_remove ( + button->priv->uris, uris->data); } } if (caption[0]) - gtk_label_set_text (GTK_LABEL (priv->label), caption + 2); + gtk_label_set_text ( + GTK_LABEL (button->priv->label), caption + 2); else - set_contents_unselected (button); + folder_selection_button_unselected (button); g_free (caption); } -GList * -em_folder_selection_button_get_selection_mult (EMFolderSelectionButton *button) +const gchar * +em_folder_selection_button_get_title (EMFolderSelectionButton *button) { - g_return_val_if_fail (EM_IS_FOLDER_SELECTION_BUTTON (button), NULL); + g_return_val_if_fail (EM_FOLDER_SELECTION_BUTTON (button), NULL); - return button->priv->uris; + return button->priv->title; } void -em_folder_selection_button_set_multiselect (EMFolderSelectionButton *button, gboolean value) +em_folder_selection_button_set_title (EMFolderSelectionButton *button, + const gchar *title) { - button->priv->multiple_select = value; -} + g_return_if_fail (EM_FOLDER_SELECTION_BUTTON (button)); -gboolean -em_folder_selection_button_get_multiselect (EMFolderSelectionButton *button) -{ - return button->priv->multiple_select; + g_free (button->priv->title); + button->priv->title = g_strdup (title); + + g_object_notify (G_OBJECT (button), "title"); } |