From: Sergio Villar Senin Date: Fri, 16 Jan 2009 09:10:00 +0000 (+0000) Subject: * Fixes NB#97352, do not show folders once an account is deleted X-Git-Tag: git_migration_finished~790 X-Git-Url: http://git.maemo.org/git/?p=modest;a=commitdiff_plain;h=47e59a3f8bc90d80baf789ed0e0f684eef07e4eb * Fixes NB#97352, do not show folders once an account is deleted * Added get_inner_models * Added outbox-deleted handler * Added signal emissions and signal connections * Connect signal to remove the outbox when updating the model as well * Use tny_list_remove to remove outbox instead of gtk_tree_model functions pmo-trunk-r7159 --- diff --git a/src/hildon2/modest-platform.c b/src/hildon2/modest-platform.c index 2f5ea4c..f49690f 100644 --- a/src/hildon2/modest-platform.c +++ b/src/hildon2/modest-platform.c @@ -520,7 +520,7 @@ modest_platform_get_icon (const gchar *name, guint icon_size) */ if (!name || strlen(name) == 0) return NULL; - + current_theme = gtk_icon_theme_get_default (); pixbuf = gtk_icon_theme_load_icon (current_theme, name, icon_size, GTK_ICON_LOOKUP_NO_SVG, diff --git a/src/modest-tny-local-folders-account.c b/src/modest-tny-local-folders-account.c index d9e6c2a..3410305 100644 --- a/src/modest-tny-local-folders-account.c +++ b/src/modest-tny-local-folders-account.c @@ -65,6 +65,13 @@ static TnyFolder* create_folder (TnyFolderStore *self, const gchar *name, GError **err); +enum { + OUTBOX_DELETED_SIGNAL, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = {0}; + static void modest_tny_local_folders_account_finalize (GObject *object) { @@ -82,11 +89,24 @@ static void modest_tny_local_folders_account_class_init (ModestTnyLocalFoldersAccountClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); - + g_type_class_add_private (klass, sizeof (ModestTnyLocalFoldersAccountPrivate)); - + object_class->finalize = modest_tny_local_folders_account_finalize; - + + /* Signals */ + + /* Note that this signal is removed before unsetting my own + reference to outbox, this means that by the time of this + call, modest_tny_local_folders_account_get_merged_outbox is + still valid. The reason is that the listeners of the signal + might want to do something with the outbox instance */ + signals[OUTBOX_DELETED_SIGNAL] = g_signal_new + ("outbox-deleted", MODEST_TYPE_TNY_LOCAL_FOLDERS_ACCOUNT, + G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET + (ModestTnyLocalFoldersAccountClass, outbox_deleted), NULL, + NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + /* Override virtual functions from the parent class: */ TNY_CAMEL_STORE_ACCOUNT_CLASS(klass)->get_folders = get_folders; TNY_CAMEL_STORE_ACCOUNT_CLASS(klass)->create_folder = create_folder; @@ -248,10 +268,12 @@ modest_tny_local_folders_account_add_folder_to_outbox (ModestTnyLocalFoldersAcco /* Create on-demand */ if (!priv->outbox_folder) { - priv->outbox_folder = TNY_MERGE_FOLDER (tny_merge_folder_new_with_ui_locker (_("mcen_me_folder_outbox"), tny_gtk_lockable_new ())); - + priv->outbox_folder = (TnyMergeFolder *) + tny_merge_folder_new_with_ui_locker (_("mcen_me_folder_outbox"), + tny_gtk_lockable_new ()); /* Set type to outbox */ - tny_merge_folder_set_folder_type (priv->outbox_folder, TNY_FOLDER_TYPE_OUTBOX); + tny_merge_folder_set_folder_type (priv->outbox_folder, + TNY_FOLDER_TYPE_OUTBOX); } /* Add outbox to the global OUTBOX folder */ @@ -277,6 +299,10 @@ modest_tny_local_folders_account_remove_folder_from_outbox (ModestTnyLocalFolder merged_folders = tny_simple_list_new (); tny_merge_folder_get_folders (priv->outbox_folder, merged_folders); if (tny_list_get_length (merged_folders) == 0) { + /* Emit signal */ + g_signal_emit ((GObject *)self, signals[OUTBOX_DELETED_SIGNAL], 0); + + /* Unref my own reference */ g_object_unref (priv->outbox_folder); priv->outbox_folder = NULL; } diff --git a/src/modest-tny-local-folders-account.h b/src/modest-tny-local-folders-account.h index af41f8f..92cdca0 100644 --- a/src/modest-tny-local-folders-account.h +++ b/src/modest-tny-local-folders-account.h @@ -61,11 +61,15 @@ G_BEGIN_DECLS * of its own. */ typedef struct { - TnyCamelStoreAccount parent; + TnyCamelStoreAccount parent; } ModestTnyLocalFoldersAccount; typedef struct { - TnyCamelStoreAccountClass parent_class; + TnyCamelStoreAccountClass parent_class; + + /* Signal */ + void (*outbox_deleted) (ModestTnyLocalFoldersAccount *self); + } ModestTnyLocalFoldersAccountClass; GType modest_tny_local_folders_account_get_type (void); diff --git a/src/widgets/modest-folder-view.c b/src/widgets/modest-folder-view.c index d952c08..64f9379 100644 --- a/src/widgets/modest-folder-view.c +++ b/src/widgets/modest-folder-view.c @@ -193,6 +193,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 +240,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 +348,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) @@ -1078,7 +1120,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 */ @@ -1138,6 +1180,7 @@ modest_folder_view_finalize (GObject *obj) { ModestFolderViewPrivate *priv; GtkTreeSelection *sel; + TnyAccount *local_account; g_return_if_fail (obj); @@ -1148,6 +1191,16 @@ modest_folder_view_finalize (GObject *obj) priv->timer_expander = 0; } + local_account = (TnyAccount *) + modest_tny_account_store_get_local_folders_account ((ModestTnyAccountStore *)priv->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); @@ -1252,12 +1305,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 */ @@ -1275,31 +1350,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)); @@ -1357,7 +1430,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; @@ -1366,26 +1439,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 */ @@ -1396,12 +1458,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)); @@ -1419,7 +1479,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; @@ -1458,21 +1518,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 */ @@ -1838,6 +1898,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_TNY_ACCOUNT_STORE (priv->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),