* fix all compiler warnings (when using gtk/ frontend)
[modest] / src / widgets / modest-folder-view.c
index b636eec..9bdb0df 100644 (file)
 #include <tny-account-store.h>
 #include <tny-account.h>
 #include <tny-folder.h>
+#include <tny-camel-folder.h>
+#include <modest-tny-folder.h>
 #include <modest-marshal.h>
 #include <modest-icon-names.h>
-#include <modest-icon-factory.h>
 #include <modest-tny-account-store.h>
-
+#include <modest-text-utils.h>
+#include <modest-runtime.h>
 #include "modest-folder-view.h"
 
 /* 'private'/'protected' functions */
@@ -53,14 +55,12 @@ static gboolean     update_model             (ModestFolderView *self,
 static gboolean     update_model_empty       (ModestFolderView *self);
 
 static void         on_selection_changed     (GtkTreeSelection *sel, gpointer data);
-static void         on_subscription_changed  (TnyStoreAccount *store_account, TnyFolder *folder,
-                                             ModestFolderView *self);
+/* static void         on_subscription_changed  (TnyStoreAccount *store_account, TnyFolder *folder, */
+/*                                           ModestFolderView *self); */
 
-static gboolean     modest_folder_view_update_model     (ModestFolderView *self,
-                                                        TnyAccountStore *account_store);
-static const gchar *get_account_name_from_folder        (GtkTreeModel *model, GtkTreeIter iter);
+static gint         cmp_rows (GtkTreeModel *tree_model, GtkTreeIter *iter1, GtkTreeIter *iter2,
+                             gpointer user_data);
 
-static void         modest_folder_view_disconnect_store_account_handlers (GtkTreeView *self);
 
 enum {
        FOLDER_SELECTION_CHANGED_SIGNAL,
@@ -69,13 +69,10 @@ enum {
 
 typedef struct _ModestFolderViewPrivate ModestFolderViewPrivate;
 struct _ModestFolderViewPrivate {
-
        TnyAccountStore     *account_store;
        TnyFolder           *cur_folder;
-       gboolean             view_is_empty;
 
        gulong               sig1, sig2;
-       gulong              *store_accounts_handlers;
        GMutex              *lock;
        GtkTreeSelection    *cur_selection;
        TnyFolderStoreQuery *query;
@@ -150,13 +147,38 @@ text_cell_data  (GtkTreeViewColumn *column,  GtkCellRenderer *renderer,
        gchar *fname;
        gint unread;
        TnyFolderType type;
+       TnyFolder *folder;
        
+       g_return_if_fail (column);
+       g_return_if_fail (tree_model);
+
        gtk_tree_model_get (tree_model, iter,
                            TNY_GTK_FOLDER_STORE_TREE_MODEL_NAME_COLUMN, &fname,
+                           TNY_GTK_FOLDER_STORE_TREE_MODEL_UNREAD_COLUMN, &unread,
                            TNY_GTK_FOLDER_STORE_TREE_MODEL_TYPE_COLUMN, &type,
-                           TNY_GTK_FOLDER_STORE_TREE_MODEL_UNREAD_COLUMN, &unread, -1);
+                           TNY_GTK_FOLDER_STORE_TREE_MODEL_INSTANCE_COLUMN, &folder,
+                           -1);
        rendobj = G_OBJECT(renderer);
 
+       if (!fname)
+               return;
+       
+       if (folder && type != TNY_FOLDER_TYPE_ROOT) { /* FIXME: tnymail bug? crashes with root folders */
+               if (modest_tny_folder_is_local_folder (folder)) {
+                       TnyFolderType type;
+                       type = modest_tny_folder_get_local_folder_type (folder);
+                       if (type != TNY_FOLDER_TYPE_UNKNOWN) {
+                               g_free (fname);
+                               fname = g_strdup(modest_local_folder_info_get_type_display_name (type));
+                       }
+               }
+       } else if (folder && type == TNY_FOLDER_TYPE_ROOT) {
+               if (strcmp (fname, MODEST_LOCAL_FOLDERS_ACCOUNT_NAME) == 0) {/* FIXME: hack */
+                       g_free (fname);
+                       fname = g_strdup (MODEST_LOCAL_FOLDERS_DISPLAY_NAME);
+               }
+       }
+                       
        if (unread > 0) {
                gchar *folder_title = g_strdup_printf ("%s (%d)", fname, unread);
                g_object_set (rendobj,"text", folder_title,  "weight", 800, NULL);
@@ -168,67 +190,33 @@ text_cell_data  (GtkTreeViewColumn *column,  GtkCellRenderer *renderer,
 }
 
 
-/* guess the folder type based on the name, or -1 in case of error */
-static TnyFolderType
-guess_type_from_name (const gchar* name)
-{
-       gint  type;
-       gchar *folder;
-       
-       if (!name)
-               return -1;
-       
-       type = TNY_FOLDER_TYPE_NORMAL;
-       folder = g_utf8_strdown (name, strlen(name));
-
-       if (strcmp (folder, "inbox") == 0 ||
-           strcmp (folder, _("inbox")) == 0)
-               type = TNY_FOLDER_TYPE_INBOX;
-       else if (strcmp (folder, "outbox") == 0 ||
-                strcmp (folder, _("outbox")) == 0)
-               type = TNY_FOLDER_TYPE_OUTBOX;
-       else if (g_str_has_prefix(folder, "junk") ||
-                g_str_has_prefix(folder, _("junk")))
-               type = TNY_FOLDER_TYPE_JUNK;
-       else if (g_str_has_prefix(folder, "trash") ||
-                g_str_has_prefix(folder, _("trash")))
-               type = TNY_FOLDER_TYPE_JUNK;
-       else if (g_str_has_prefix(folder, "sent") ||
-                g_str_has_prefix(folder, _("sent")))
-               type = TNY_FOLDER_TYPE_SENT;
-
-       /* these are not *really* TNY_ types */
-       else if (g_str_has_prefix(folder, "draft") ||
-                g_str_has_prefix(folder, _("draft")))
-               type = TNY_FOLDER_TYPE_DRAFTS;
-       else if (g_str_has_prefix(folder, "notes") ||
-                g_str_has_prefix(folder, _("notes")))
-               type = TNY_FOLDER_TYPE_NOTES;
-       else if (g_str_has_prefix(folder, "contacts") ||
-                g_str_has_prefix(folder, _("contacts")))
-               type = TNY_FOLDER_TYPE_CONTACTS;
-       else if (g_str_has_prefix(folder, "calendar") ||
-                g_str_has_prefix(folder, _("calendar")))
-               type = TNY_FOLDER_TYPE_CALENDAR;
-       
-       g_free (folder);
-       return type;
-}
-
-
-
-TnyFolderType
-modest_folder_view_guess_folder_type (TnyFolder *folder)
+static GdkPixbuf*
+get_cached_icon (const gchar *name)
 {
-       TnyFolderType type;
-
-       g_return_val_if_fail (folder, -1);
-
-       type = tny_folder_get_folder_type (folder);
-       if (type == TNY_FOLDER_TYPE_NORMAL)
-               type = guess_type_from_name (tny_folder_get_name (folder));
-
-       return type;
+       GError *err = NULL;
+       gpointer pixbuf;
+       gpointer orig_key;
+       static GHashTable *icon_cache = NULL;
+       
+       g_return_val_if_fail (name, NULL);
+
+       if (G_UNLIKELY(!icon_cache))
+               icon_cache = modest_cache_mgr_get_cache (modest_runtime_get_cache_mgr(),
+                                                        MODEST_CACHE_MGR_CACHE_TYPE_PIXBUF);
+       
+       if (!icon_cache || !g_hash_table_lookup_extended (icon_cache, name, &orig_key, &pixbuf)) {
+               pixbuf = (gpointer)gdk_pixbuf_new_from_file (name, &err);
+               if (!pixbuf) {
+                       g_printerr ("modest: error in icon factory while loading '%s': %s\n",
+                                   name, err->message);
+                       g_error_free (err);
+               }
+               /* if we cannot find it, we still insert (if we have a cache), so we get the error
+                * only once */
+               if (icon_cache)
+                       g_hash_table_insert (icon_cache, g_strdup(name),(gpointer)pixbuf);
+       }
+       return GDK_PIXBUF(pixbuf);
 }
 
 
@@ -249,53 +237,48 @@ icon_cell_data  (GtkTreeViewColumn *column,  GtkCellRenderer *renderer,
                            TNY_GTK_FOLDER_STORE_TREE_MODEL_UNREAD_COLUMN, &unread, -1);
        rendobj = G_OBJECT(renderer);
        
-       if (type == TNY_FOLDER_TYPE_NORMAL)
-               type = guess_type_from_name (fname);
-       
-       if (fname)
-               g_free (fname);
+       if (type == TNY_FOLDER_TYPE_NORMAL || type == TNY_FOLDER_TYPE_UNKNOWN) {
+               type = modest_tny_folder_guess_folder_type_from_name (fname);
+       }
+       g_free (fname);
 
        switch (type) {
        case TNY_FOLDER_TYPE_ROOT:
-               pixbuf = modest_icon_factory_get_icon (MODEST_FOLDER_ICON_ACCOUNT);
+               pixbuf = get_cached_icon (MODEST_FOLDER_ICON_ACCOUNT);
                 break;
        case TNY_FOLDER_TYPE_INBOX:
-                pixbuf = modest_icon_factory_get_small_icon (MODEST_FOLDER_ICON_INBOX);
+                pixbuf = get_cached_icon (MODEST_FOLDER_ICON_INBOX);
                 break;
         case TNY_FOLDER_TYPE_OUTBOX:
-                pixbuf = modest_icon_factory_get_small_icon (MODEST_FOLDER_ICON_OUTBOX);
+                pixbuf = get_cached_icon (MODEST_FOLDER_ICON_OUTBOX);
                 break;
         case TNY_FOLDER_TYPE_JUNK:
-                pixbuf = modest_icon_factory_get_small_icon (MODEST_FOLDER_ICON_JUNK);
+                pixbuf = get_cached_icon (MODEST_FOLDER_ICON_JUNK);
                 break;
         case TNY_FOLDER_TYPE_SENT:
-                pixbuf = modest_icon_factory_get_small_icon (MODEST_FOLDER_ICON_SENT);
+                pixbuf = get_cached_icon (MODEST_FOLDER_ICON_SENT);
+                break;
+       case TNY_FOLDER_TYPE_TRASH:
+               pixbuf = get_cached_icon (MODEST_FOLDER_ICON_TRASH);
                 break;
        case TNY_FOLDER_TYPE_DRAFTS:
-               pixbuf = modest_icon_factory_get_small_icon (MODEST_FOLDER_ICON_DRAFTS);
+               pixbuf = get_cached_icon (MODEST_FOLDER_ICON_DRAFTS);
                 break;
        case TNY_FOLDER_TYPE_NOTES:
-               pixbuf = modest_icon_factory_get_small_icon (MODEST_FOLDER_ICON_NOTES);
+               pixbuf = get_cached_icon (MODEST_FOLDER_ICON_NOTES);
                 break;
        case TNY_FOLDER_TYPE_CALENDAR:
-               pixbuf = modest_icon_factory_get_small_icon (MODEST_FOLDER_ICON_CALENDAR);
+               pixbuf = get_cached_icon (MODEST_FOLDER_ICON_CALENDAR);
                 break;
        case TNY_FOLDER_TYPE_CONTACTS:
-                pixbuf = modest_icon_factory_get_small_icon (MODEST_FOLDER_ICON_CONTACTS);
+                pixbuf = get_cached_icon (MODEST_FOLDER_ICON_CONTACTS);
                 break;
        case TNY_FOLDER_TYPE_NORMAL:
         default:
-                pixbuf = modest_icon_factory_get_small_icon (MODEST_FOLDER_ICON_NORMAL);
-                break;
+                pixbuf = get_cached_icon (MODEST_FOLDER_ICON_NORMAL);
+               break;
         }
-
-       g_object_set (rendobj,
-                     "pixbuf-expander-open",
-                     modest_icon_factory_get_icon (MODEST_FOLDER_ICON_OPEN),
-                     "pixbuf-expander-closed",
-                     modest_icon_factory_get_icon (MODEST_FOLDER_ICON_CLOSED),
-                     "pixbuf", pixbuf,
-                     NULL);
+       g_object_set (rendobj, "pixbuf", pixbuf, NULL);
 }
 
 static void
@@ -308,7 +291,6 @@ modest_folder_view_init (ModestFolderView *obj)
        
        priv =  MODEST_FOLDER_VIEW_GET_PRIVATE(obj);
        
-       priv->view_is_empty  = TRUE;
        priv->account_store  = NULL;
        priv->cur_folder     = NULL;
        priv->query          = NULL;
@@ -339,33 +321,6 @@ modest_folder_view_init (ModestFolderView *obj)
 }
 
 static void
-modest_folder_view_disconnect_store_account_handlers (GtkTreeView *self)
-{
-       TnyIterator *iter;
-       ModestFolderViewPrivate *priv;
-       GtkTreeModel *model;
-       GtkTreeModelSort *sortable;
-       gint i = 0;
-
-       sortable = GTK_TREE_MODEL_SORT (gtk_tree_view_get_model (self));
-       if (!sortable)
-               return; 
-
-       model = gtk_tree_model_sort_get_model (sortable);
-       if (!model)
-               return; 
-
-       priv =  MODEST_FOLDER_VIEW_GET_PRIVATE (self);  
-       iter = tny_list_create_iterator (TNY_LIST (model));
-       do {
-               g_signal_handler_disconnect (G_OBJECT (tny_iterator_get_current (iter)),
-                                            priv->store_accounts_handlers [i++]);
-               tny_iterator_next (iter);
-       } while (!tny_iterator_is_done (iter));
-}
-
-
-static void
 modest_folder_view_finalize (GObject *obj)
 {
        ModestFolderViewPrivate *priv;
@@ -386,12 +341,6 @@ modest_folder_view_finalize (GObject *obj)
                priv->lock = NULL;
        }
 
-       if (priv->store_accounts_handlers) {
-               modest_folder_view_disconnect_store_account_handlers (GTK_TREE_VIEW (obj));
-               g_free (priv->store_accounts_handlers);
-               priv->store_accounts_handlers = NULL;
-       }
-
        if (priv->query) {
                g_object_unref (G_OBJECT (priv->query));
                priv->query = NULL;
@@ -409,8 +358,6 @@ static void
 on_account_update (TnyAccountStore *account_store, const gchar *account,
                   gpointer user_data)
 {
-       update_model_empty (MODEST_FOLDER_VIEW(user_data));
-       
        if (!update_model (MODEST_FOLDER_VIEW(user_data), 
                           MODEST_TNY_ACCOUNT_STORE(account_store)))
                g_printerr ("modest: failed to update model for changes in '%s'",
@@ -462,92 +409,36 @@ modest_folder_view_new (ModestTnyAccountStore *account_store,
        sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(self));
        priv->sig2 = g_signal_connect (sel, "changed",
                                       G_CALLBACK(on_selection_changed), self);
-                                       
        return GTK_WIDGET(self);
 }
 
 
-const gchar *
-modest_folder_view_get_selected_account (ModestFolderView *self)
-{
-       GtkTreeModel *model;
-       GtkTreeIter iter;
-       ModestFolderViewPrivate *priv;
-       
-       g_return_val_if_fail (self, NULL);
-       priv = MODEST_FOLDER_VIEW_GET_PRIVATE(self);
-
-       gtk_tree_selection_get_selected (priv->cur_selection, &model, &iter);
-
-       return get_account_name_from_folder (model, iter);
-}
-
 static gboolean
 update_model_empty (ModestFolderView *self)
 {
-       GtkTreeIter  iter;
-       GtkTreeStore *store;
        ModestFolderViewPrivate *priv;
        
        g_return_val_if_fail (self, FALSE);
        priv = MODEST_FOLDER_VIEW_GET_PRIVATE(self);
 
-       /* Disconnect old handlers */
-       if (priv->store_accounts_handlers) {
-               modest_folder_view_disconnect_store_account_handlers (GTK_TREE_VIEW (self));
-               g_free (priv->store_accounts_handlers);
-               priv->store_accounts_handlers = NULL;
-       }
-
-       /* Create the new model */
-       store = gtk_tree_store_new (1, G_TYPE_STRING);
-       gtk_tree_store_append (store, &iter, NULL);
-
-       gtk_tree_store_set (store, &iter, 0, _("(empty)"), -1);
-
-       gtk_tree_view_set_model (GTK_TREE_VIEW(self),
-                                GTK_TREE_MODEL(store));
-       g_object_unref (store);
-
-       priv->view_is_empty = TRUE;
-
        g_signal_emit (G_OBJECT(self), signals[FOLDER_SELECTION_CHANGED_SIGNAL], 0,
                       NULL, TRUE);
        return TRUE;
 }
 
 
+/* this feels dirty; any other way to expand all the root items? */
 static void
-update_store_account_handlers (ModestFolderView *self, TnyList *account_list)
+expand_root_items (ModestFolderView *self)
 {
-       gint size;
-       ModestFolderViewPrivate *priv;
-       TnyIterator *iter;
-       
-       priv =  MODEST_FOLDER_VIEW_GET_PRIVATE(self);
-
-       /* Listen to subscription changes */
-       size = tny_list_get_length (TNY_LIST (account_list)) * sizeof (gulong);
+       GtkTreePath *path;
+       path = gtk_tree_path_new_first ();
 
-       g_assert (priv->store_accounts_handlers == NULL); /* don't leak */
-       priv->store_accounts_handlers = g_malloc0 (size);
-       iter = tny_list_create_iterator (account_list);
+       /* all folders should have child items, so.. */
+       while (gtk_tree_view_expand_row (GTK_TREE_VIEW(self), path, FALSE))
+               gtk_tree_path_next (path);
        
-       if (!tny_iterator_is_done (iter))       
-               priv->view_is_empty = FALSE; 
-       else {
-               gint i = 0;
-               while (!tny_iterator_is_done (iter)) {
-                       
-                       priv->store_accounts_handlers [i++] =
-                               g_signal_connect (G_OBJECT (tny_iterator_get_current (iter)),
-                                                 "subscription_changed",
-                                                 G_CALLBACK (on_subscription_changed),
-                                                 self);
-                       tny_iterator_next (iter);
-                       }
-       }       
-       g_object_unref (iter);                         
+       gtk_tree_path_free (path);
 }
 
 
@@ -561,25 +452,33 @@ update_model (ModestFolderView *self, ModestTnyAccountStore *account_store)
        GtkTreeModel     *model, *sortable;
 
        g_return_val_if_fail (account_store, FALSE);
+
        priv =  MODEST_FOLDER_VIEW_GET_PRIVATE(self);
        
+       /* Notify that there is no folder selected */
+       update_model_empty (self);
+       
        model        = tny_gtk_folder_store_tree_model_new (TRUE, NULL);
        account_list = TNY_LIST(model);
 
        tny_account_store_get_accounts (TNY_ACCOUNT_STORE(account_store),
                                        account_list,
-                                       TNY_ACCOUNT_STORE_STORE_ACCOUNTS);
-
+                                       TNY_ACCOUNT_STORE_STORE_ACCOUNTS);      
        if (account_list) {
                sortable = gtk_tree_model_sort_new_with_model (model);
-               gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (sortable),
+               gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE(sortable),
                                                      TNY_GTK_FOLDER_STORE_TREE_MODEL_NAME_COLUMN, 
                                                      GTK_SORT_ASCENDING);
-               gtk_tree_view_set_model (GTK_TREE_VIEW(self), sortable);
+               gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (sortable),
+                                                TNY_GTK_FOLDER_STORE_TREE_MODEL_NAME_COLUMN, 
+                                                cmp_rows, NULL, NULL);
 
-               update_store_account_handlers (self, account_list);
+               /* Set new model */
+               gtk_tree_view_set_model (GTK_TREE_VIEW(self), sortable);
+               expand_root_items (self); /* expand all account folders */
+       
        }
-
+       
        g_object_unref (model);
        return TRUE;
 }
@@ -601,24 +500,20 @@ on_selection_changed (GtkTreeSelection *sel, gpointer user_data)
        priv = MODEST_FOLDER_VIEW_GET_PRIVATE(user_data);
        priv->cur_selection = sel;
        
-       /* is_empty means that there is only the 'empty' item */
-       if (priv->view_is_empty)
-               return;
-
        /* folder was _un_selected if true */
        if (!gtk_tree_selection_get_selected (sel, &model, &iter)) {
                priv->cur_folder = NULL; /* FIXME: need this? */
                return; 
-       }
+       }
        
        tree_view = MODEST_FOLDER_VIEW (user_data);
-       gtk_tree_model_get (model, &iter, 
-                           TNY_GTK_FOLDER_STORE_TREE_MODEL_TYPE_COLUMN, &type, 
-                           TNY_GTK_FOLDER_STORE_TREE_MODEL_INSTANCE_COLUMN, &folder, 
+       gtk_tree_model_get (model, &iter,
+                           TNY_GTK_FOLDER_STORE_TREE_MODEL_TYPE_COLUMN, &type,
+                           TNY_GTK_FOLDER_STORE_TREE_MODEL_INSTANCE_COLUMN, &folder,
                            -1);
 
        if (type == TNY_FOLDER_TYPE_ROOT)
-               return; 
+               return;
        
        /* emit 2 signals: one for the unselection of the old one,
         * and one for the selection of the new on */
@@ -626,61 +521,86 @@ on_selection_changed (GtkTreeSelection *sel, gpointer user_data)
                       priv->cur_folder, FALSE);
        g_signal_emit (G_OBJECT(tree_view), signals[FOLDER_SELECTION_CHANGED_SIGNAL], 0,
                       folder, TRUE);
-       
        if (priv->cur_folder)
-               tny_folder_expunge (priv->cur_folder, NULL); /* FIXME */
+               tny_folder_sync (priv->cur_folder, TRUE, NULL); /* FIXME */
        priv->cur_folder = folder;
 
 }
 
-static void 
-on_subscription_changed  (TnyStoreAccount *store_account, 
-                         TnyFolder *folder,
-                         ModestFolderView *self)
-{
-       /* TODO: probably we won't need a full reload, just the store
-          account or even the parent of the folder */
+/* static void  */
+/* on_subscription_changed  (TnyStoreAccount *store_account,  */
+/*                       TnyFolder *folder, */
+/*                       ModestFolderView *self) */
+/* { */
+/*     /\* TODO: probably we won't need a full reload, just the store */
+/*        account or even the parent of the folder *\/ */
 
-       ModestFolderViewPrivate *priv;
+/*     ModestFolderViewPrivate *priv; */
 
-       priv =  MODEST_FOLDER_VIEW_GET_PRIVATE(self);
-       update_model (self, MODEST_TNY_ACCOUNT_STORE (priv->account_store));
-}
+/*     priv =  MODEST_FOLDER_VIEW_GET_PRIVATE(self); */
+/*     update_model (self, MODEST_TNY_ACCOUNT_STORE (priv->account_store)); */
+/* } */
 
 
-static gboolean
+gboolean
 modest_folder_view_update_model (ModestFolderView *self, TnyAccountStore *account_store)
 {
-       gboolean retval;
-
        g_return_val_if_fail (MODEST_IS_FOLDER_VIEW (self), FALSE);
-       retval = update_model (self, MODEST_TNY_ACCOUNT_STORE(account_store)); /* ugly */
 
        g_signal_emit (G_OBJECT(self), signals[FOLDER_SELECTION_CHANGED_SIGNAL],
                       0, NULL, TRUE);
-
-       return retval;
+       
+       return update_model (self, MODEST_TNY_ACCOUNT_STORE(account_store)); /* ugly */
 }
 
-
-/* ugly */
-static const gchar *
-get_account_name_from_folder (GtkTreeModel *model, GtkTreeIter iter)
+TnyFolder *
+modest_folder_view_get_selected (ModestFolderView *self)
 {
-       GtkTreePath *path;
-       GtkTreeIter new_iter;
-       TnyFolder *account_folder;
-       gint depth, i;
+       ModestFolderViewPrivate *priv;
 
-       path = gtk_tree_model_get_path (model, &iter);
-       depth = gtk_tree_path_get_depth (path);
+       g_return_val_if_fail (self, NULL);
+       
+       priv = MODEST_FOLDER_VIEW_GET_PRIVATE(self);
+       if (priv->cur_folder)
+               g_object_ref (priv->cur_folder);
 
-       for (i = 1; i < depth; ++i)
-               gtk_tree_path_up (path);
+       return priv->cur_folder;
+}
 
-       gtk_tree_model_get_iter (model, &new_iter, path);
-       gtk_tree_model_get (model, &new_iter, 
-                           TNY_GTK_FOLDER_STORE_TREE_MODEL_INSTANCE_COLUMN, &account_folder, 
+static gint
+cmp_rows (GtkTreeModel *tree_model, GtkTreeIter *iter1, GtkTreeIter *iter2,
+         gpointer user_data)
+{
+       gint cmp;
+       gchar         *name1, *name2;
+       TnyFolderType type;
+       TnyFolder     *folder1, *folder2;
+       
+       gtk_tree_model_get (tree_model, iter1,
+                           TNY_GTK_FOLDER_STORE_TREE_MODEL_NAME_COLUMN, &name1,
+                           TNY_GTK_FOLDER_STORE_TREE_MODEL_TYPE_COLUMN, &type,
+                           TNY_GTK_FOLDER_STORE_TREE_MODEL_INSTANCE_COLUMN, &folder1,
+                           -1);
+       gtk_tree_model_get (tree_model, iter2,
+                           TNY_GTK_FOLDER_STORE_TREE_MODEL_NAME_COLUMN, &name2,
+                           TNY_GTK_FOLDER_STORE_TREE_MODEL_INSTANCE_COLUMN, &folder2,
                            -1);
-       return tny_account_get_name (TNY_ACCOUNT (account_folder));
+
+       /* local_folders should be the last one */
+       if (type == TNY_FOLDER_TYPE_ROOT) {
+               /* the account name is also the name of the root folder
+                * in case of local folders */
+               if (strcmp (name1, MODEST_LOCAL_FOLDERS_ACCOUNT_NAME) == 0)
+                       cmp = +1;
+               else if (strcmp (name2, MODEST_LOCAL_FOLDERS_ACCOUNT_NAME) == 0)
+                       cmp = -1;
+               else 
+                       cmp = modest_text_utils_utf8_strcmp (name1, name2, TRUE);
+       } else 
+               cmp = modest_text_utils_utf8_strcmp (name1, name2, TRUE);
+       
+       g_free (name1);
+       g_free (name2);
+
+       return cmp;     
 }