diff options
Diffstat (limited to 'mail/message-list.c')
-rw-r--r-- | mail/message-list.c | 325 |
1 files changed, 220 insertions, 105 deletions
diff --git a/mail/message-list.c b/mail/message-list.c index 92c740bb9d..714768ef21 100644 --- a/mail/message-list.c +++ b/mail/message-list.c @@ -50,10 +50,12 @@ #include "e-util/e-profile-event.h" #include "e-util/e-util-private.h" #include "e-util/e-util.h" -#include "e-util/e-util-labels.h" #include "misc/e-gui-utils.h" +#include "shell/e-shell.h" +#include "shell/e-shell-settings.h" + #include "table/e-cell-checkbox.h" #include "table/e-cell-hbox.h" #include "table/e-cell-date.h" @@ -67,7 +69,7 @@ #include "table/e-cell-vbox.h" #include "table/e-cell-hbox.h" -#include "em-popup.h" +#include "e-mail-label-list-store.h" #include "em-utils.h" #include "mail-config.h" #include "mail-mt.h" @@ -97,6 +99,10 @@ #define d(x) #define t(x) +#define MESSAGE_LIST_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), MESSAGE_LIST_TYPE, MessageListPrivate)) + struct _MLSelection { GPtrArray *uids; CamelFolder *folder; @@ -106,6 +112,8 @@ struct _MLSelection { struct _MessageListPrivate { GtkWidget *invisible; /* 4 selection */ + EShellBackend *shell_backend; + struct _MLSelection clipboard; gboolean destroyed; @@ -113,12 +121,17 @@ struct _MessageListPrivate { gboolean any_row_changed; /* save state before regen list when this is set to true */ }; +enum { + PROP_0, + PROP_SHELL_BACKEND +}; + static struct { const gchar *target; GdkAtom atom; guint32 actions; } ml_drag_info[] = { - { "x-uid-list", NULL, GDK_ACTION_ASK|GDK_ACTION_MOVE|GDK_ACTION_COPY }, + { "x-uid-list", NULL, GDK_ACTION_MOVE|GDK_ACTION_COPY }, { "message/rfc822", NULL, GDK_ACTION_COPY }, { "text/uri-list", NULL, GDK_ACTION_COPY }, }; @@ -808,7 +821,7 @@ message_list_invert_selection (MessageList *message_list) void message_list_copy(MessageList *ml, gboolean cut) { - struct _MessageListPrivate *p = ml->priv; + MessageListPrivate *p = ml->priv; GPtrArray *uids; clear_selection(ml, &p->clipboard); @@ -1220,53 +1233,124 @@ sanitize_recipients (const gchar *string) } static gint -get_all_labels (CamelMessageInfo *msg_info, gchar **label_str, gboolean get_tags) -{ +get_all_labels (MessageList *message_list, + CamelMessageInfo *msg_info, + gchar **label_str, + gboolean get_tags) +{ + EShell *shell; + EShellBackend *shell_backend; + EShellSettings *shell_settings; + EMailLabelListStore *store; + GtkTreeIter iter; GString *str; + const gchar *property_name; const gchar *old_label; + gchar *new_label; gint count = 0; const CamelFlag *flag; - GSList *labels; - labels = mail_config_get_labels (); + shell_backend = message_list_get_shell_backend (message_list); + shell = e_shell_backend_get_shell (shell_backend); + shell_settings = e_shell_get_shell_settings (shell); + + property_name = "mail-label-list-store"; + store = e_shell_settings_get_object (shell_settings, property_name); + str = g_string_new (""); for (flag = camel_message_info_user_flags (msg_info); flag; flag = flag->next) { - const gchar *name = e_util_labels_get_name (labels, flag->name); + gchar *item; - if (name) { - if (str->len) - g_string_append (str, ", "); + if (!e_mail_label_list_store_lookup (store, flag->name, &iter)) + continue; - if (get_tags) - name = flag->name; + if (get_tags) + item = e_mail_label_list_store_get_tag (store, &iter); + else + item = e_mail_label_list_store_get_name (store, &iter); - g_string_append (str, name); - count++; - } + if (str->len) + g_string_append (str, ", "); + + g_string_append (str, item); + count++; + + g_free (item); } - old_label = e_util_labels_get_new_tag (camel_message_info_user_tag (msg_info, "label")); + old_label = camel_message_info_user_tag (msg_info, "label"); + if (old_label == NULL) + goto exit; + + /* Convert old-style labels ("<name>") to "$Label<name>". */ + new_label = g_alloca (strlen (old_label) + 10); + g_stpcpy (g_stpcpy (new_label, "$Label"), old_label); - if (old_label != NULL) { - const gchar *name = NULL; + if (e_mail_label_list_store_lookup (store, new_label, &iter)) { + gchar *name = NULL; if (str->len) g_string_append (str, ", "); if (!get_tags) - name = e_util_labels_get_name (labels, old_label); + name = e_mail_label_list_store_get_name (store, &iter); g_string_append (str, (get_tags || !name) ? old_label : name); - ++count; + count++; + + g_free (name); } +exit: *label_str = g_string_free (str, FALSE); + g_object_unref (store); + return count; } static const gchar * +get_label_color (MessageList *message_list, + const gchar *tag) +{ + EShell *shell; + EShellBackend *shell_backend; + EShellSettings *shell_settings; + EMailLabelListStore *store; + GtkTreeIter iter; + GdkColor color; + const gchar *property_name; + const gchar *interned = NULL; + gchar *color_spec; + + /* FIXME get_all_labels() should return an array of tree iterators, + * not strings. Now we just have to lookup the tag again. */ + + shell_backend = message_list_get_shell_backend (message_list); + shell = e_shell_backend_get_shell (shell_backend); + shell_settings = e_shell_get_shell_settings (shell); + + property_name = "mail-label-list-store"; + store = e_shell_settings_get_object (shell_settings, property_name); + + if (!e_mail_label_list_store_lookup (store, tag, &iter)) + goto exit; + + e_mail_label_list_store_get_color (store, &iter, &color); + + /* XXX Hack to avoid returning an allocated string. */ + color_spec = gdk_color_to_string (&color); + interned = g_intern_string (color_spec); + g_free (color_spec); + +exit: + g_object_unref (store); + + return interned; +} + +static const gchar * get_trimmed_subject (CamelMessageInfo *info) { const gchar *subject; @@ -1467,9 +1551,8 @@ ml_tree_value_at (ETreeModel *etm, ETreePath path, gint col, gpointer model_data completed = camel_message_info_user_tag(msg_info, "completed-on"); followup = camel_message_info_user_tag(msg_info, "follow-up"); if (colour == NULL) { - if ((n = get_all_labels (msg_info, &labels_string, TRUE)) == 1) { - - colour = e_util_labels_get_color_str (mail_config_get_labels (), labels_string); + if ((n = get_all_labels (message_list, msg_info, &labels_string, TRUE)) == 1) { + colour = get_label_color (message_list, labels_string); } else if (camel_message_info_flags(msg_info) & CAMEL_MESSAGE_FLAGGED) { /* FIXME: extract from the important.xpm somehow. */ colour = "#A7453E"; @@ -1548,7 +1631,7 @@ ml_tree_value_at (ETreeModel *etm, ETreePath path, gint col, gpointer model_data cleansed_str = g_string_new (""); - if (get_all_labels (msg_info, &str, FALSE)) { + if (get_all_labels (message_list, msg_info, &str, FALSE)) { gint i; for (i = 0; str[i] != '\0'; ++i) { if (str[i] != '_') { @@ -1950,7 +2033,7 @@ ml_selection_get(GtkWidget *widget, GtkSelectionData *data, guint info, guint ti static gboolean ml_selection_clear_event(GtkWidget *widget, GdkEventSelection *event, MessageList *ml) { - struct _MessageListPrivate *p = ml->priv; + MessageListPrivate *p = ml->priv; clear_selection(ml, &p->clipboard); @@ -2079,48 +2162,6 @@ ml_drop_action(struct _drop_msg *m) } static void -ml_drop_popup_copy(EPopup *ep, EPopupItem *item, gpointer data) -{ - struct _drop_msg *m = data; - - m->action = GDK_ACTION_COPY; - ml_drop_action(m); -} - -static void -ml_drop_popup_move(EPopup *ep, EPopupItem *item, gpointer data) -{ - struct _drop_msg *m = data; - - m->action = GDK_ACTION_MOVE; - ml_drop_action(m); -} - -static void -ml_drop_popup_cancel(EPopup *ep, EPopupItem *item, gpointer data) -{ - struct _drop_msg *m = data; - - m->aborted = TRUE; - mail_msg_unref(m); -} - -static EPopupItem ml_drop_popup_menu[] = { - { E_POPUP_ITEM, (gchar *) "00.emc.02", (gchar *) N_("_Copy"), ml_drop_popup_copy, NULL, (gchar *) "folder-copy", 0 }, - { E_POPUP_ITEM, (gchar *) "00.emc.03", (gchar *) N_("_Move"), ml_drop_popup_move, NULL, (gchar *) "folder-move", 0 }, - { E_POPUP_BAR, (gchar *) "10.emc" }, - { E_POPUP_ITEM, (gchar *) "99.emc.00", (gchar *) N_("Cancel _Drag"), ml_drop_popup_cancel, NULL, NULL, 0 }, -}; - -static void -ml_drop_popup_free(EPopup *ep, GSList *items, gpointer data) -{ - g_slist_free(items); - - /* FIXME: free data if no item was selected? */ -} - -static void ml_tree_drag_data_received (ETree *tree, gint row, ETreePath path, gint col, GdkDragContext *context, gint x, gint y, GtkSelectionData *data, guint info, @@ -2146,22 +2187,7 @@ ml_tree_drag_data_received (ETree *tree, gint row, ETreePath path, gint col, memcpy(m->selection->data, data->data, data->length); m->selection->length = data->length; - if (context->action == GDK_ACTION_ASK) { - EMPopup *emp; - GSList *menus = NULL; - GtkMenu *menu; - gint i; - - emp = em_popup_new("org.gnome.mail.messagelist.popup.drop"); - for (i=0;i<sizeof(ml_drop_popup_menu)/sizeof(ml_drop_popup_menu[0]);i++) - menus = g_slist_append(menus, &ml_drop_popup_menu[i]); - - e_popup_add_items((EPopup *)emp, menus, NULL, ml_drop_popup_free, m); - menu = e_popup_create_menu_once((EPopup *)emp, NULL, 0); - gtk_menu_popup(menu, NULL, NULL, NULL, NULL, 0, gtk_get_current_event_time()); - } else { - ml_drop_action(m); - } + ml_drop_action(m); } struct search_child_struct { @@ -2222,8 +2248,6 @@ ml_tree_drag_motion(ETree *tree, GdkDragContext *context, gint x, gint y, guint action = context->suggested_action; if (action == GDK_ACTION_COPY && (actions & GDK_ACTION_MOVE)) action = GDK_ACTION_MOVE; - else if (action == GDK_ACTION_ASK && (actions & (GDK_ACTION_MOVE|GDK_ACTION_COPY)) != (GDK_ACTION_MOVE|GDK_ACTION_COPY)) - action = GDK_ACTION_MOVE; gdk_drag_status(context, action, time); @@ -2245,13 +2269,25 @@ on_model_row_changed (ETableModel *model, gint row, MessageList *ml) /* * GObject::init */ + +static void +message_list_set_shell_backend (MessageList *message_list, + EShellBackend *shell_backend) +{ + g_return_if_fail (message_list->priv->shell_backend == NULL); + + message_list->priv->shell_backend = g_object_ref (shell_backend); +} + static void message_list_init (MessageList *message_list) { - struct _MessageListPrivate *p; + MessageListPrivate *p; GtkAdjustment *adjustment; GdkAtom matom; + message_list->priv = MESSAGE_LIST_GET_PRIVATE (message_list); + adjustment = (GtkAdjustment *) gtk_adjustment_new (0.0, 0.0, G_MAXDOUBLE, 0.0, 0.0, 0.0); gtk_scrolled_window_set_vadjustment ((GtkScrolledWindow *) message_list, adjustment); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (message_list), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS); @@ -2280,7 +2316,7 @@ message_list_init (MessageList *message_list) message_list->regen_lock = g_mutex_new (); /* TODO: Should this only get the selection if we're realised? */ - p = message_list->priv = g_malloc0(sizeof(*message_list->priv)); + p = message_list->priv; p->invisible = gtk_invisible_new(); p->destroyed = FALSE; g_object_ref_sink(p->invisible); @@ -2301,7 +2337,7 @@ static void message_list_destroy(GtkObject *object) { MessageList *message_list = MESSAGE_LIST (object); - struct _MessageListPrivate *p = message_list->priv; + MessageListPrivate *p = message_list->priv; p->destroyed = TRUE; @@ -2353,14 +2389,65 @@ message_list_destroy(GtkObject *object) message_list->seen_id = 0; } + /* Chain up to parent's destroy() method. */ GTK_OBJECT_CLASS (message_list_parent_class)->destroy(object); } static void -message_list_finalise (GObject *object) +message_list_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_SHELL_BACKEND: + message_list_set_shell_backend ( + MESSAGE_LIST (object), + g_value_get_object (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +message_list_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_SHELL_BACKEND: + g_value_set_object ( + value, message_list_get_shell_backend ( + MESSAGE_LIST (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +message_list_dispose (GObject *object) +{ + MessageListPrivate *priv; + + priv = MESSAGE_LIST_GET_PRIVATE (object); + + if (priv->shell_backend != NULL) { + g_object_unref (priv->shell_backend); + priv->shell_backend = NULL; + } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (message_list_parent_class)->dispose (object); +} + +static void +message_list_finalize (GObject *object) { MessageList *message_list = MESSAGE_LIST (object); - struct _MessageListPrivate *p = message_list->priv; + MessageListPrivate *priv = message_list->priv; g_hash_table_destroy (message_list->normalised_hash); @@ -2390,10 +2477,9 @@ message_list_finalise (GObject *object) g_free(message_list->folder_uri); message_list->folder_uri = NULL; - clear_selection(message_list, &p->clipboard); - - g_free(p); + clear_selection(message_list, &priv->clipboard); + /* Chain up to parent's finalize() method. */ G_OBJECT_CLASS (message_list_parent_class)->finalize (object); } @@ -2401,17 +2487,36 @@ message_list_finalise (GObject *object) * GObjectClass::init */ static void -message_list_class_init (MessageListClass *message_list_class) +message_list_class_init (MessageListClass *class) { - GObjectClass *object_class = (GObjectClass *) message_list_class; - GtkObjectClass *gtkobject_class = (GtkObjectClass *) message_list_class; + GObjectClass *object_class; + GtkObjectClass *gtk_object_class; gint i; for (i=0;i<sizeof(ml_drag_info)/sizeof(ml_drag_info[0]);i++) ml_drag_info[i].atom = gdk_atom_intern(ml_drag_info[i].target, FALSE); - object_class->finalize = message_list_finalise; - gtkobject_class->destroy = message_list_destroy; + g_type_class_add_private (class, sizeof (MessageListPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = message_list_set_property; + object_class->get_property = message_list_get_property; + object_class->dispose = message_list_dispose; + object_class->finalize = message_list_finalize; + + gtk_object_class = GTK_OBJECT_CLASS (class); + gtk_object_class->destroy = message_list_destroy; + + g_object_class_install_property ( + object_class, + PROP_SHELL_BACKEND, + g_param_spec_object ( + "shell-backend", + _("Shell Backend"), + _("The mail shell backend"), + E_TYPE_SHELL_BACKEND, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY)); message_list_signals[MESSAGE_SELECTED] = g_signal_new ("message_selected", @@ -2541,14 +2646,14 @@ message_list_construct (MessageList *message_list) e_tree_drag_source_set(message_list->tree, GDK_BUTTON1_MASK, ml_drag_types, sizeof(ml_drag_types)/sizeof(ml_drag_types[0]), - GDK_ACTION_MOVE|GDK_ACTION_COPY|GDK_ACTION_ASK); + GDK_ACTION_MOVE|GDK_ACTION_COPY); g_signal_connect(message_list->tree, "tree_drag_data_get", G_CALLBACK(ml_tree_drag_data_get), message_list); e_tree_drag_dest_set(message_list->tree, GTK_DEST_DEFAULT_ALL, ml_drop_types, sizeof(ml_drop_types)/sizeof(ml_drop_types[0]), - GDK_ACTION_MOVE|GDK_ACTION_COPY|GDK_ACTION_ASK); + GDK_ACTION_MOVE|GDK_ACTION_COPY); g_signal_connect(message_list->tree, "tree_drag_data_received", G_CALLBACK(ml_tree_drag_data_received), message_list); @@ -2563,19 +2668,30 @@ message_list_construct (MessageList *message_list) * Returns a new message-list widget. **/ GtkWidget * -message_list_new (void) +message_list_new (EShellBackend *shell_backend) { MessageList *message_list; + g_return_val_if_fail (E_IS_SHELL_BACKEND (shell_backend), NULL); + message_list = MESSAGE_LIST (g_object_new(message_list_get_type (), "hadjustment", NULL, "vadjustment", NULL, + "shell-backend", shell_backend, NULL)); message_list_construct (message_list); return GTK_WIDGET (message_list); } +EShellBackend * +message_list_get_shell_backend (MessageList *message_list) +{ + g_return_val_if_fail (IS_MESSAGE_LIST (message_list), NULL); + + return message_list->priv->shell_backend; +} + static void clear_info(gchar *key, ETreePath *node, MessageList *ml) { @@ -4069,9 +4185,8 @@ regen_list_exec (struct _regen_list_msg *m) if ((!is_deleted || (is_deleted && !m->hidedel)) && (!is_junk || (is_junk && !m->hidejunk))) g_ptr_array_add (uids, (gpointer) camel_pstring_strdup (looking_for)); - - camel_folder_free_message_info (m->folder, looking_info); } + } } } |