* Fixes NB#97352, do not show folders once an account is deleted
authorSergio Villar Senin <svillar@igalia.com>
Fri, 16 Jan 2009 09:10:00 +0000 (09:10 +0000)
committerSergio Villar Senin <svillar@igalia.com>
Fri, 16 Jan 2009 09:10:00 +0000 (09:10 +0000)
* 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

src/hildon2/modest-platform.c
src/modest-tny-local-folders-account.c
src/modest-tny-local-folders-account.h
src/widgets/modest-folder-view.c

index 2f5ea4c..f49690f 100644 (file)
@@ -520,7 +520,7 @@ modest_platform_get_icon (const gchar *name, guint icon_size)
         */
        if (!name || strlen(name) == 0)
                return NULL;
         */
        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,
        current_theme = gtk_icon_theme_get_default ();
        pixbuf = gtk_icon_theme_load_icon (current_theme, name, icon_size,
                                           GTK_ICON_LOOKUP_NO_SVG,
index d9e6c2a..3410305 100644 (file)
@@ -65,6 +65,13 @@ static TnyFolder*   create_folder  (TnyFolderStore *self,
                                    const gchar *name, 
                                    GError **err);
 
                                    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)
 {
 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);
 modest_tny_local_folders_account_class_init (ModestTnyLocalFoldersAccountClass *klass)
 {
        GObjectClass *object_class = G_OBJECT_CLASS (klass);
-       
+
        g_type_class_add_private (klass, sizeof (ModestTnyLocalFoldersAccountPrivate));
        g_type_class_add_private (klass, sizeof (ModestTnyLocalFoldersAccountPrivate));
-       
+
        object_class->finalize = modest_tny_local_folders_account_finalize;
        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;
        /* 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) {
 
        /* 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 */
                /* 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 */
        }
 
        /* 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) {
        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;
        }
                g_object_unref (priv->outbox_folder);
                priv->outbox_folder = NULL;
        }
index af41f8f..92cdca0 100644 (file)
@@ -61,11 +61,15 @@ G_BEGIN_DECLS
  * of its own.
  */
 typedef struct {
  * of its own.
  */
 typedef struct {
-  TnyCamelStoreAccount parent;
+       TnyCamelStoreAccount parent;
 } ModestTnyLocalFoldersAccount;
 
 typedef struct {
 } 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);
 } ModestTnyLocalFoldersAccountClass;
 
 GType modest_tny_local_folders_account_get_type (void);
index d952c08..64f9379 100644 (file)
@@ -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 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,
 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;
        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),                       \
 };
 #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)
 /* 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->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 */
        priv->reexpand = TRUE;
 
        /* Initialize the local account name */
@@ -1138,6 +1180,7 @@ modest_folder_view_finalize (GObject *obj)
 {
        ModestFolderViewPrivate *priv;
        GtkTreeSelection    *sel;
 {
        ModestFolderViewPrivate *priv;
        GtkTreeSelection    *sel;
+       TnyAccount *local_account;
 
        g_return_if_fail (obj);
 
 
        g_return_if_fail (obj);
 
@@ -1148,6 +1191,16 @@ modest_folder_view_finalize (GObject *obj)
                priv->timer_expander = 0;
        }
 
                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);
        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
 }
 
 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;
 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 */
 
        /* 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);
 
                                              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;
                return;
-       }
 
        /* Insert the account in the model */
 
        /* 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));
 
        /* 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;
 {
        ModestFolderView *self;
        ModestFolderViewPrivate *priv;
-       GtkTreeModel *sort_model, *filter_model;
+       GtkTreeModel *model, *filter_model;
        GtkTreeSelection *sel;
        gboolean same_account;
 
        GtkTreeSelection *sel;
        gboolean same_account;
 
@@ -1366,26 +1439,15 @@ on_account_changed (TnyAccountStore *account_store,
        if (TNY_IS_TRANSPORT_ACCOUNT (tny_account))
                return;
 
        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 */
        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;
                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 */
 
        /* 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 */
        }
 
        /* 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 */
 
        /* 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));
 
        /* 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;
 {
        ModestFolderView *self = NULL;
        ModestFolderViewPrivate *priv;
-       GtkTreeModel *sort_model, *filter_model;
+       GtkTreeModel *model, *filter_model;
        GtkTreeSelection *sel = NULL;
        gboolean same_account = FALSE;
 
        GtkTreeSelection *sel = NULL;
        gboolean same_account = FALSE;
 
@@ -1458,21 +1518,21 @@ on_account_removed (TnyAccountStore *account_store,
                g_object_unref (folder_to_select_account);
        }
 
                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;
                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 */
 
        /* 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
 
        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),
        /* Get the accounts: */
        tny_account_store_get_accounts (TNY_ACCOUNT_STORE(account_store),
                                        TNY_LIST (model),