X-Git-Url: http://git.maemo.org/git/?a=blobdiff_plain;f=src%2Fwidgets%2Fmodest-folder-view.c;h=0da3a048bcf34a2c0b2542879182d35130d4fca0;hb=1f470f4c35ef91d8c152e3d3e5ffd2fb394fb3a0;hp=14abcb5fb9da75a1a5bff0498b98a934dea902dc;hpb=fbcb77bb059d079420d4b78927f54c9b9bafea10;p=modest diff --git a/src/widgets/modest-folder-view.c b/src/widgets/modest-folder-view.c index 14abcb5..0da3a04 100644 --- a/src/widgets/modest-folder-view.c +++ b/src/widgets/modest-folder-view.c @@ -32,11 +32,8 @@ #include #include #include -#ifdef MODEST_TOOLKIT_HILDON2 #include -#else #include -#endif #include #include #include @@ -62,7 +59,7 @@ #include #include #include "modest-dnd.h" -#include +#include "modest-ui-constants.h" #include "widgets/modest-window.h" /* Folder view drag types */ @@ -193,6 +190,11 @@ static void update_style (ModestFolderView *self); static void on_notify_style (GObject *obj, GParamSpec *spec, gpointer userdata); static gint get_cmp_pos (TnyFolderType t, TnyFolder *folder_store); +static gboolean get_inner_models (ModestFolderView *self, + GtkTreeModel **filter_model, + GtkTreeModel **sort_model, + GtkTreeModel **tny_model); + enum { FOLDER_SELECTION_CHANGED_SIGNAL, FOLDER_DISPLAY_NAME_CHANGED_SIGNAL, @@ -235,6 +237,8 @@ struct _ModestFolderViewPrivate { gboolean reexpand; /* next time we expose, we'll expand all root folders */ GtkCellRenderer *messages_renderer; + + gulong outbox_deleted_handler; }; #define MODEST_FOLDER_VIEW_GET_PRIVATE(o) \ (G_TYPE_INSTANCE_GET_PRIVATE((o), \ @@ -341,6 +345,41 @@ modest_folder_view_class_init (ModestFolderViewClass *klass) } +/* Retrieves the filter, sort and tny models of the folder view. If + any of these does not exist then it returns FALSE */ +static gboolean +get_inner_models (ModestFolderView *self, + GtkTreeModel **filter_model, + GtkTreeModel **sort_model, + GtkTreeModel **tny_model) +{ + GtkTreeModel *s_model, *f_model, *t_model; + + f_model = gtk_tree_view_get_model (GTK_TREE_VIEW (self)); + if (!GTK_IS_TREE_MODEL_FILTER(f_model)) { + g_warning ("BUG: %s: not a valid filter model", __FUNCTION__); + return FALSE; + } + + s_model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (f_model)); + if (!GTK_IS_TREE_MODEL_SORT(s_model)) { + g_warning ("BUG: %s: not a valid sort model", __FUNCTION__); + return FALSE; + } + + t_model = gtk_tree_model_sort_get_model (GTK_TREE_MODEL_SORT (s_model)); + + /* Assign values */ + if (filter_model) + *filter_model = f_model; + if (sort_model) + *sort_model = s_model; + if (tny_model) + *tny_model = t_model; + + return TRUE; +} + /* Simplify checks for NULLs: */ static gboolean strings_are_equal (const gchar *a, const gchar *b) @@ -424,6 +463,42 @@ on_get_mmc_account_name (TnyStoreAccount* account, gpointer user_data) } static void +convert_parent_folders_to_dots (gchar **item_name) +{ + gint n_parents = 0; + gchar *c; + gchar *last_separator; + + if (item_name == NULL) + return; + + for (c = *item_name; *c != '\0'; c++) { + if (g_str_has_prefix (c, MODEST_FOLDER_PATH_SEPARATOR)) { + n_parents++; + } + } + + last_separator = g_strrstr (*item_name, MODEST_FOLDER_PATH_SEPARATOR); + if (last_separator != NULL) { + last_separator = last_separator + strlen (MODEST_FOLDER_PATH_SEPARATOR); + } + + if (n_parents > 0) { + GString *buffer; + gint i; + + buffer = g_string_new (""); + for (i = 0; i < n_parents; i++) { + buffer = g_string_append (buffer, MODEST_FOLDER_DOT); + } + buffer = g_string_append (buffer, last_separator); + g_free (*item_name); + *item_name = g_string_free (buffer, FALSE); + } + +} + +static void format_compact_style (gchar **item_name, GObject *instance, gboolean bold, @@ -452,6 +527,9 @@ format_compact_style (gchar **item_name, if (account == NULL) return; + /* convert parent folders to dots */ + convert_parent_folders_to_dots (item_name); + folder_name = tny_folder_get_name (folder); if (g_str_has_suffix (*item_name, folder_name)) { gchar *offset = g_strrstr (*item_name, folder_name); @@ -460,8 +538,7 @@ format_compact_style (gchar **item_name, } buffer = g_string_new (""); - buffer = g_string_append (buffer, tny_account_get_name (account)); - buffer = g_string_append (buffer, MODEST_FOLDER_PATH_SEPARATOR); + buffer = g_string_append (buffer, *item_name); if (concat_folder_name) { if (bold) buffer = g_string_append (buffer, ""); @@ -777,25 +854,25 @@ get_composite_icons (const gchar *icon_code, return retval; } -static ThreePixbufs* +static inline ThreePixbufs* get_folder_icons (TnyFolderType type, GObject *instance) { static GdkPixbuf *inbox_pixbuf = NULL, *outbox_pixbuf = NULL, *junk_pixbuf = NULL, *sent_pixbuf = NULL, *trash_pixbuf = NULL, *draft_pixbuf = NULL, - *normal_pixbuf = NULL, *anorm_pixbuf = NULL, + *normal_pixbuf = NULL, *anorm_pixbuf = NULL, *mmc_pixbuf = NULL, *ammc_pixbuf = NULL, *avirt_pixbuf = NULL; static GdkPixbuf *inbox_pixbuf_open = NULL, *outbox_pixbuf_open = NULL, *junk_pixbuf_open = NULL, *sent_pixbuf_open = NULL, *trash_pixbuf_open = NULL, *draft_pixbuf_open = NULL, - *normal_pixbuf_open = NULL, *anorm_pixbuf_open = NULL, + *normal_pixbuf_open = NULL, *anorm_pixbuf_open = NULL, *mmc_pixbuf_open = NULL, *ammc_pixbuf_open = NULL, *avirt_pixbuf_open = NULL; static GdkPixbuf *inbox_pixbuf_close = NULL, *outbox_pixbuf_close = NULL, *junk_pixbuf_close = NULL, *sent_pixbuf_close = NULL, *trash_pixbuf_close = NULL, *draft_pixbuf_close = NULL, - *normal_pixbuf_close = NULL, *anorm_pixbuf_close = NULL, + *normal_pixbuf_close = NULL, *anorm_pixbuf_close = NULL, *mmc_pixbuf_close = NULL, *ammc_pixbuf_close = NULL, *avirt_pixbuf_close = NULL; ThreePixbufs *retval = NULL; @@ -812,13 +889,21 @@ get_folder_icons (TnyFolderType type, GObject *instance) !TNY_IS_ACCOUNT (instance) && type != TNY_FOLDER_TYPE_INBOX && modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (instance))) { +#ifdef MODEST_TOOLKIT_HILDON2 + return get_composite_icons (MODEST_FOLDER_ICON_ACCOUNT, + &anorm_pixbuf, + &anorm_pixbuf_open, + &anorm_pixbuf_close); +#else return get_composite_icons (MODEST_FOLDER_ICON_NORMAL, &normal_pixbuf, &normal_pixbuf_open, &normal_pixbuf_close); +#endif } switch (type) { + case TNY_FOLDER_TYPE_INVALID: g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__); break; @@ -884,12 +969,26 @@ get_folder_icons (TnyFolderType type, GObject *instance) &draft_pixbuf_open, &draft_pixbuf_close); break; + case TNY_FOLDER_TYPE_ARCHIVE: + retval = get_composite_icons (MODEST_FOLDER_ICON_MMC_FOLDER, + &mmc_pixbuf, + &mmc_pixbuf_open, + &mmc_pixbuf_close); + break; case TNY_FOLDER_TYPE_NORMAL: default: - retval = get_composite_icons (MODEST_FOLDER_ICON_NORMAL, - &normal_pixbuf, - &normal_pixbuf_open, - &normal_pixbuf_close); + /* Memory card folders could have an special icon */ + if (modest_tny_folder_is_memory_card_folder (TNY_FOLDER (instance))) { + retval = get_composite_icons (MODEST_FOLDER_ICON_MMC_FOLDER, + &mmc_pixbuf, + &mmc_pixbuf_open, + &mmc_pixbuf_close); + } else { + retval = get_composite_icons (MODEST_FOLDER_ICON_NORMAL, + &normal_pixbuf, + &normal_pixbuf_open, + &normal_pixbuf_close); + } break; } @@ -1018,7 +1117,7 @@ modest_folder_view_init (ModestFolderView *obj) priv->cur_folder_store = NULL; priv->visible_account_id = NULL; priv->folder_to_select = NULL; - + priv->outbox_deleted_handler = 0; priv->reexpand = TRUE; /* Initialize the local account name */ @@ -1078,6 +1177,7 @@ modest_folder_view_finalize (GObject *obj) { ModestFolderViewPrivate *priv; GtkTreeSelection *sel; + TnyAccount *local_account; g_return_if_fail (obj); @@ -1088,6 +1188,16 @@ modest_folder_view_finalize (GObject *obj) priv->timer_expander = 0; } + local_account = (TnyAccount *) + modest_tny_account_store_get_local_folders_account (modest_runtime_get_account_store ()); + if (local_account) { + if (g_signal_handler_is_connected (local_account, + priv->outbox_deleted_handler)) + g_signal_handler_disconnect (local_account, + priv->outbox_deleted_handler); + g_object_unref (local_account); + } + if (priv->account_store) { g_signal_handler_disconnect (G_OBJECT(priv->account_store), priv->account_inserted_signal); @@ -1192,12 +1302,34 @@ modest_folder_view_set_account_store (TnyAccountStoreView *self, TnyAccountStore } static void +on_outbox_deleted_cb (ModestTnyLocalFoldersAccount *local_account, + gpointer user_data) +{ + ModestFolderView *self; + GtkTreeModel *model, *filter_model; + TnyFolder *outbox; + + self = MODEST_FOLDER_VIEW (user_data); + + if (!get_inner_models (self, &filter_model, NULL, &model)) + return; + + /* Remove outbox from model */ + outbox = modest_tny_local_folders_account_get_merged_outbox (local_account); + tny_list_remove (TNY_LIST (model), G_OBJECT (outbox)); + g_object_unref (outbox); + + /* Refilter view */ + gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (filter_model)); +} + +static void on_account_inserted (TnyAccountStore *account_store, TnyAccount *account, gpointer user_data) { ModestFolderViewPrivate *priv; - GtkTreeModel *sort_model, *filter_model; + GtkTreeModel *model, *filter_model; /* Ignore transport account insertions, we're not showing them in the folder view */ @@ -1215,31 +1347,29 @@ on_account_inserted (TnyAccountStore *account_store, G_OBJECT (user_data), MODEST_CONF_FOLDER_VIEW_KEY); - if (!GTK_IS_TREE_VIEW(user_data)) { - g_warning ("BUG: %s: not a valid tree view", __FUNCTION__); - return; - } - - /* Get the inner model */ - /* check, is some rare cases, we did not get the right thing here, - * NB#84097 */ - filter_model = gtk_tree_view_get_model (GTK_TREE_VIEW (user_data)); - if (!GTK_IS_TREE_MODEL_FILTER(filter_model)) { - g_warning ("BUG: %s: not a valid filter model", __FUNCTION__); - return; - } - /* check, is some rare cases, we did not get the right thing here, - * NB#84097 */ - sort_model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (filter_model)); - if (!GTK_IS_TREE_MODEL_SORT(sort_model)) { - g_warning ("BUG: %s: not a valid sort model", __FUNCTION__); + /* Get models */ + if (!get_inner_models (MODEST_FOLDER_VIEW (user_data), + &filter_model, NULL, &model)) return; - } /* Insert the account in the model */ - tny_list_append (TNY_LIST (gtk_tree_model_sort_get_model (GTK_TREE_MODEL_SORT (sort_model))), - G_OBJECT (account)); + tny_list_append (TNY_LIST (model), G_OBJECT (account)); + + /* When the model is a list store (plain representation) the + outbox is not a child of any account so we have to manually + delete it because removing the local folders account won't + delete it (because tny_folder_get_account() is not defined + for a merge folder */ + if (TNY_IS_GTK_FOLDER_LIST_STORE (model) && + MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (account)) { + + priv->outbox_deleted_handler = + g_signal_connect (account, + "outbox-deleted", + G_CALLBACK (on_outbox_deleted_cb), + user_data); + } /* Refilter the model */ gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (filter_model)); @@ -1297,7 +1427,7 @@ on_account_changed (TnyAccountStore *account_store, { ModestFolderView *self; ModestFolderViewPrivate *priv; - GtkTreeModel *sort_model, *filter_model; + GtkTreeModel *model, *filter_model; GtkTreeSelection *sel; gboolean same_account; @@ -1306,26 +1436,15 @@ on_account_changed (TnyAccountStore *account_store, if (TNY_IS_TRANSPORT_ACCOUNT (tny_account)) return; - if (!MODEST_IS_FOLDER_VIEW(user_data)) { - g_warning ("BUG: %s: not a valid folder view", __FUNCTION__); - return; - } - self = MODEST_FOLDER_VIEW (user_data); priv = MODEST_FOLDER_VIEW_GET_PRIVATE (user_data); /* Get the inner model */ - filter_model = gtk_tree_view_get_model (GTK_TREE_VIEW (user_data)); - if (!GTK_IS_TREE_MODEL_FILTER(filter_model)) { - g_warning ("BUG: %s: not a valid filter model", __FUNCTION__); + if (!get_inner_models (MODEST_FOLDER_VIEW (user_data), + &filter_model, NULL, &model)) return; - } - sort_model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (filter_model)); - if (!GTK_IS_TREE_MODEL_SORT(sort_model)) { - g_warning ("BUG: %s: not a valid sort model", __FUNCTION__); - return; - } + filter_model = gtk_tree_view_get_model (GTK_TREE_VIEW (user_data)); /* Invalidate the cur_folder_store only if the selected folder belongs to the account that is being removed */ @@ -1336,12 +1455,10 @@ on_account_changed (TnyAccountStore *account_store, } /* Remove the account from the model */ - tny_list_remove (TNY_LIST (gtk_tree_model_sort_get_model (GTK_TREE_MODEL_SORT (sort_model))), - G_OBJECT (tny_account)); + tny_list_remove (TNY_LIST (model), G_OBJECT (tny_account)); /* Insert the account in the model */ - tny_list_append (TNY_LIST (gtk_tree_model_sort_get_model (GTK_TREE_MODEL_SORT (sort_model))), - G_OBJECT (tny_account)); + tny_list_append (TNY_LIST (model), G_OBJECT (tny_account)); /* Refilter the model */ gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (filter_model)); @@ -1359,7 +1476,7 @@ on_account_removed (TnyAccountStore *account_store, { ModestFolderView *self = NULL; ModestFolderViewPrivate *priv; - GtkTreeModel *sort_model, *filter_model; + GtkTreeModel *model, *filter_model; GtkTreeSelection *sel = NULL; gboolean same_account = FALSE; @@ -1398,21 +1515,21 @@ on_account_removed (TnyAccountStore *account_store, g_object_unref (folder_to_select_account); } - /* Remove the account from the model */ - filter_model = gtk_tree_view_get_model (GTK_TREE_VIEW (self)); - if (!GTK_IS_TREE_MODEL_FILTER(filter_model)) { - g_warning ("BUG: %s: not a valid filter model", __FUNCTION__); + if (!get_inner_models (MODEST_FOLDER_VIEW (user_data), + &filter_model, NULL, &model)) return; - } - sort_model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (filter_model)); - if (!GTK_IS_TREE_MODEL_SORT(sort_model)) { - g_warning ("BUG: %s: not a valid sort model", __FUNCTION__); - return; + /* Disconnect the signal handler */ + if (TNY_IS_GTK_FOLDER_LIST_STORE (model) && + MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (account)) { + if (g_signal_handler_is_connected (account, + priv->outbox_deleted_handler)) + g_signal_handler_disconnect (account, + priv->outbox_deleted_handler); } - tny_list_remove (TNY_LIST (gtk_tree_model_sort_get_model (GTK_TREE_MODEL_SORT (sort_model))), - G_OBJECT (account)); + /* Remove the account from the model */ + tny_list_remove (TNY_LIST (model), G_OBJECT (account)); /* If the removed account is the currently viewed one then clear the configuration value. The new visible account will be the default account */ @@ -1553,6 +1670,7 @@ filter_row (GtkTreeModel *model, GtkTreeIter *iter, gpointer data) guint i; gboolean found = FALSE; gboolean cleared = FALSE; + ModestTnyFolderRules rules = 0; g_return_val_if_fail (MODEST_IS_FOLDER_VIEW (data), FALSE); priv = MODEST_FOLDER_VIEW_GET_PRIVATE (data); @@ -1570,10 +1688,6 @@ filter_row (GtkTreeModel *model, GtkTreeIter *iter, gpointer data) return FALSE; if (TNY_IS_ACCOUNT (instance)) { -#ifdef MODEST_TOOLKIT_HILDON2 - /* In hildon 2.2 we don't show the account rows */ - return FALSE; -#else TnyAccount *acc = TNY_ACCOUNT (instance); const gchar *account_id = tny_account_get_id (acc); @@ -1596,7 +1710,6 @@ filter_row (GtkTreeModel *model, GtkTreeIter *iter, gpointer data) * in the local-folders account instead: */ if (retval && MODEST_IS_TNY_OUTBOX_ACCOUNT (acc)) retval = FALSE; -#endif } else { if (priv->style == MODEST_FOLDER_VIEW_STYLE_SHOW_ONE) { /* Only show special folders for current account if needed */ @@ -1661,18 +1774,80 @@ filter_row (GtkTreeModel *model, GtkTreeIter *iter, gpointer data) } /* apply special filters */ + if (retval && (priv->filter & MODEST_FOLDER_VIEW_FILTER_HIDE_ACCOUNTS)) { + if (TNY_IS_ACCOUNT (instance)) + return FALSE; + } + if (retval && (priv->filter & MODEST_FOLDER_VIEW_FILTER_CAN_HAVE_FOLDERS)) { if (TNY_IS_FOLDER (instance)) { - TnyFolderCaps capabilities; + /* Check folder rules */ + ModestTnyFolderRules rules; - capabilities = tny_folder_get_caps (TNY_FOLDER (instance)); - retval = !(capabilities & TNY_FOLDER_CAPS_NOCHILDREN); + rules = modest_tny_folder_get_rules (TNY_FOLDER (instance)); + retval = !(rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE); + } else if (TNY_IS_ACCOUNT (instance)) { + if (modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (instance))) { + retval = FALSE; + } else { + retval = TRUE; + } + } + } + + if (retval && (priv->filter & MODEST_FOLDER_VIEW_FILTER_HIDE_MANDATORY_FOLDERS)) { + if (TNY_IS_FOLDER (instance)) { + TnyFolderType guess_type; - if (retval) { - retval = ((type != TNY_FOLDER_TYPE_DRAFTS) && - (type != TNY_FOLDER_TYPE_OUTBOX) && - (type != TNY_FOLDER_TYPE_SENT)); + if (TNY_FOLDER_TYPE_NORMAL) { + guess_type = modest_tny_folder_guess_folder_type (TNY_FOLDER (instance)); + } else { + guess_type = type; } + + switch (type) { + case TNY_FOLDER_TYPE_OUTBOX: + case TNY_FOLDER_TYPE_SENT: + case TNY_FOLDER_TYPE_DRAFTS: + case TNY_FOLDER_TYPE_ARCHIVE: + case TNY_FOLDER_TYPE_INBOX: + retval = FALSE; + break; + case TNY_FOLDER_TYPE_UNKNOWN: + case TNY_FOLDER_TYPE_NORMAL: + break; + default: + break; + } + + } else if (TNY_IS_ACCOUNT (instance)) { + retval = FALSE; + } + } + + if (retval && TNY_IS_FOLDER (instance)) { + rules = modest_tny_folder_get_rules (TNY_FOLDER (instance)); + } + + if (retval && (priv->filter & MODEST_FOLDER_VIEW_FILTER_DELETABLE)) { + if (TNY_IS_FOLDER (instance)) { + retval = !(rules & MODEST_FOLDER_RULES_FOLDER_NON_DELETABLE); + } else if (TNY_IS_ACCOUNT (instance)) { + retval = FALSE; + } + } + + if (retval && (priv->filter & MODEST_FOLDER_VIEW_FILTER_RENAMEABLE)) { + if (TNY_IS_FOLDER (instance)) { + retval = !(rules & MODEST_FOLDER_RULES_FOLDER_NON_RENAMEABLE); + } else if (TNY_IS_ACCOUNT (instance)) { + retval = FALSE; + } + } + + if (retval && (priv->filter & MODEST_FOLDER_VIEW_FILTER_MOVEABLE)) { + if (TNY_IS_FOLDER (instance)) { + retval = !(rules & MODEST_FOLDER_RULES_FOLDER_NON_MOVEABLE); } else if (TNY_IS_ACCOUNT (instance)) { retval = FALSE; } @@ -1719,6 +1894,31 @@ modest_folder_view_update_model (ModestFolderView *self, model = tny_gtk_folder_store_tree_model_new (NULL); #endif + /* When the model is a list store (plain representation) the + outbox is not a child of any account so we have to manually + delete it because removing the local folders account won't + delete it (because tny_folder_get_account() is not defined + for a merge folder */ + if (TNY_IS_GTK_FOLDER_LIST_STORE (model)) { + TnyAccount *account; + ModestTnyAccountStore *acc_store; + + acc_store = modest_runtime_get_account_store (); + account = modest_tny_account_store_get_local_folders_account (acc_store); + + if (g_signal_handler_is_connected (account, + priv->outbox_deleted_handler)) + g_signal_handler_disconnect (account, + priv->outbox_deleted_handler); + + priv->outbox_deleted_handler = + g_signal_connect (account, + "outbox-deleted", + G_CALLBACK (on_outbox_deleted_cb), + self); + g_object_unref (account); + } + /* Get the accounts: */ tny_account_store_get_accounts (TNY_ACCOUNT_STORE(account_store), TNY_LIST (model), @@ -3322,7 +3522,25 @@ modest_folder_view_set_filter (ModestFolderView *self, g_return_if_fail (MODEST_IS_FOLDER_VIEW (self)); priv = MODEST_FOLDER_VIEW_GET_PRIVATE (self); - priv->filter = filter; + priv->filter |= filter; + + filter_model = gtk_tree_view_get_model (GTK_TREE_VIEW (self)); + if (GTK_IS_TREE_MODEL_FILTER(filter_model)) { + gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (filter_model)); + } +} + +void +modest_folder_view_unset_filter (ModestFolderView *self, + ModestFolderViewFilter filter) +{ + ModestFolderViewPrivate *priv; + GtkTreeModel *filter_model; + + g_return_if_fail (MODEST_IS_FOLDER_VIEW (self)); + priv = MODEST_FOLDER_VIEW_GET_PRIVATE (self); + + priv->filter &= ~filter; filter_model = gtk_tree_view_get_model (GTK_TREE_VIEW (self)); if (GTK_IS_TREE_MODEL_FILTER(filter_model)) {