* Add new header settings parameter (sort) to select
[modest] / src / widgets / modest-folder-view.c
index 3b3ec91..d2705a3 100644 (file)
@@ -29,7 +29,7 @@
 
 #include <glib/gi18n.h>
 #include <string.h>
-
+#include <gdk/gdkkeysyms.h>
 #include <tny-account-store-view.h>
 #include <tny-gtk-account-list-model.h>
 #include <tny-gtk-folder-store-tree-model.h>
@@ -78,6 +78,19 @@ static gint         cmp_rows               (GtkTreeModel *tree_model,
                                            GtkTreeIter *iter2,
                                            gpointer user_data);
 
+static gboolean     filter_row             (GtkTreeModel *model,
+                                           GtkTreeIter *iter,
+                                           gpointer data);
+
+static gboolean     on_key_pressed         (GtkWidget *self,
+                                           GdkEventKey *event,
+                                           gpointer user_data);
+
+static void         on_configuration_key_changed         (ModestConf* conf, 
+                                                         const gchar *key, 
+                                                         ModestConfEvent event, 
+                                                         ModestFolderView *self);
+
 /* DnD functions */
 static void         on_drag_data_get       (GtkWidget *widget, 
                                            GdkDragContext *context, 
@@ -106,35 +119,27 @@ static gint         expand_row_timeout     (gpointer data);
 
 static void         setup_drag_and_drop    (GtkTreeView *self);
 
-static gboolean     on_key_pressed         (GtkWidget *self,
-                                           GdkEventKey *event,
-                                           gpointer user_data);
-
-static void         on_configuration_key_changed         (ModestConf* conf, 
-                                                         const gchar *key, 
-                                                         ModestConfEvent event, 
-                                                         ModestFolderView *self);
-
 enum {
        FOLDER_SELECTION_CHANGED_SIGNAL,
+       FOLDER_DISPLAY_NAME_CHANGED_SIGNAL,
        LAST_SIGNAL
 };
 
 typedef struct _ModestFolderViewPrivate ModestFolderViewPrivate;
 struct _ModestFolderViewPrivate {
-       TnyAccountStore     *account_store;
-       TnyFolder           *cur_folder;
-       GtkTreeRowReference *cur_row;
+       TnyAccountStore      *account_store;
+       TnyFolderStore       *cur_folder_store;
 
-       gulong               account_update_signal;
-       gulong               changed_signal;
-       gulong               accounts_reloaded_signal;
+       gulong                account_update_signal;
+       gulong                changed_signal;
+       gulong                accounts_reloaded_signal;
        
-       GtkTreeSelection    *cur_selection;
-       TnyFolderStoreQuery *query;
-       guint                timer_expander;
+       GtkTreeSelection     *cur_selection;
+       TnyFolderStoreQuery  *query;
+       guint                 timer_expander;
 
-       gchar               *local_account_name;
+       gchar                *local_account_name;
+       ModestFolderViewStyle style;
 };
 #define MODEST_FOLDER_VIEW_GET_PRIVATE(o)                      \
        (G_TYPE_INSTANCE_GET_PRIVATE((o),                       \
@@ -202,6 +207,23 @@ modest_folder_view_class_init (ModestFolderViewClass *klass)
                              NULL, NULL,
                              modest_marshal_VOID__POINTER_BOOLEAN,
                              G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_BOOLEAN);
+
+       /*
+        * This signal is emitted whenever the currently selected
+        * folder display name is computed. Note that the name could
+        * be different to the folder name, because we could append
+        * the unread messages count to the folder name to build the
+        * folder display name
+        */
+       signals[FOLDER_DISPLAY_NAME_CHANGED_SIGNAL] = 
+               g_signal_new ("folder-display-name-changed",
+                             G_TYPE_FROM_CLASS (gobject_class),
+                             G_SIGNAL_RUN_FIRST,
+                             G_STRUCT_OFFSET (ModestFolderViewClass,
+                                              folder_display_name_changed),
+                             NULL, NULL,
+                             g_cclosure_marshal_VOID__STRING,
+                             G_TYPE_NONE, 1, G_TYPE_STRING);
 }
 
 
@@ -210,9 +232,10 @@ static void
 text_cell_data  (GtkTreeViewColumn *column,  GtkCellRenderer *renderer,
                 GtkTreeModel *tree_model,  GtkTreeIter *iter,  gpointer data)
 {
+       ModestFolderViewPrivate *priv;
        GObject *rendobj;
        gchar *fname = NULL;
-       gint unread;
+       gint unread, all;
        TnyFolderType type;
        GObject *instance = NULL;
        
@@ -221,6 +244,7 @@ text_cell_data  (GtkTreeViewColumn *column,  GtkCellRenderer *renderer,
 
        gtk_tree_model_get (tree_model, iter,
                            TNY_GTK_FOLDER_STORE_TREE_MODEL_NAME_COLUMN, &fname,
+                           TNY_GTK_FOLDER_STORE_TREE_MODEL_ALL_COLUMN, &all,
                            TNY_GTK_FOLDER_STORE_TREE_MODEL_UNREAD_COLUMN, &unread,
                            TNY_GTK_FOLDER_STORE_TREE_MODEL_TYPE_COLUMN, &type,
                            TNY_GTK_FOLDER_STORE_TREE_MODEL_INSTANCE_COLUMN, &instance,
@@ -234,8 +258,13 @@ text_cell_data  (GtkTreeViewColumn *column,  GtkCellRenderer *renderer,
                g_free (fname);
                return;
        }
+
+       
+       priv =  MODEST_FOLDER_VIEW_GET_PRIVATE (data);
        
        if (type != TNY_FOLDER_TYPE_ROOT) {
+               gint number;
+
                if (modest_tny_folder_is_local_folder (TNY_FOLDER (instance))) {
                        TnyFolderType type;
                        type = modest_tny_folder_get_local_folder_type (TNY_FOLDER (instance));
@@ -245,20 +274,32 @@ text_cell_data  (GtkTreeViewColumn *column,  GtkCellRenderer *renderer,
                        }
                }
 
+               /* Select the number to show */
+               if ((type == TNY_FOLDER_TYPE_DRAFTS) || (type == TNY_FOLDER_TYPE_OUTBOX))
+                       number = all;
+               else
+                       number = unread;
+
                /* Use bold font style if there are unread messages */                  
                if (unread > 0) {
                        gchar *folder_title = g_strdup_printf ("%s (%d)", fname, unread);
                        g_object_set (rendobj,"text", folder_title,  "weight", 800, NULL);
+                       if (G_OBJECT (priv->cur_folder_store) == instance)
+                               g_signal_emit (G_OBJECT(data), 
+                                              signals[FOLDER_DISPLAY_NAME_CHANGED_SIGNAL], 0,
+                                              folder_title);
                        g_free (folder_title);
-               } else 
+               } else {
                        g_object_set (rendobj,"text", fname, "weight", 400, NULL);
+                       if (G_OBJECT (priv->cur_folder_store) == instance)
+                               g_signal_emit (G_OBJECT(data), 
+                                              signals[FOLDER_DISPLAY_NAME_CHANGED_SIGNAL], 0,
+                                              fname);
+               }
 
        } else {
-               ModestFolderViewPrivate *priv;
                const gchar *account_name = NULL;
                const gchar *account_id = NULL;
-       
-               priv =  MODEST_FOLDER_VIEW_GET_PRIVATE (data);
 
                /* If it's a server account */
                account_id = tny_account_get_id (TNY_ACCOUNT (instance));
@@ -272,6 +313,12 @@ text_cell_data  (GtkTreeViewColumn *column,  GtkCellRenderer *renderer,
                        }
                }
 
+               /* Notify display name observers */
+               if (G_OBJECT (priv->cur_folder_store) == instance)
+                       g_signal_emit (G_OBJECT(data),
+                                      signals[FOLDER_DISPLAY_NAME_CHANGED_SIGNAL], 0,
+                                      account_name);
+
                /* Use bold font style */
                g_object_set (rendobj,"text", account_name, "weight", 800, NULL);
        }
@@ -368,9 +415,9 @@ modest_folder_view_init (ModestFolderView *obj)
        
        priv->timer_expander = 0;
        priv->account_store  = NULL;
-       priv->cur_folder     = NULL;
-       priv->cur_row        = NULL;
+       priv->cur_folder_store     = NULL;
        priv->query          = NULL;
+       priv->style          = MODEST_FOLDER_VIEW_STYLE_SHOW_ALL;
 
        /* Initialize the local account name */
        conf = modest_runtime_get_conf();
@@ -561,6 +608,7 @@ modest_folder_view_new (TnyFolderStoreQuery *query)
        sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(self));
        priv->changed_signal = g_signal_connect (sel, "changed",
                                                 G_CALLBACK (on_selection_changed), self);
+
        return GTK_WIDGET(self);
 }
 
@@ -578,19 +626,66 @@ expand_root_items (ModestFolderView *self)
        gtk_tree_path_free (path);
 }
 
+/*
+ * HACK: we use this function to implement the
+ * MODEST_FOLDER_VIEW_STYLE_SHOW_ONE style. This implementation
+ * assumes that the model has the following order (which is currently
+ * true) Remote folders->Local folders->MMC folders, so the rows of
+ * the first level (that represent the accounts) are received in the
+ * same order. So basically it uses a static variable to register that
+ * a remote account has already being shown to hide the others
+ * (returning NULL). When the function evaluates the local or the MMC
+ * accounts is time to reset the static variable in order to get it
+ * ready for the next time the tree model needs to be shown.
+ */
+static gboolean 
+filter_row (GtkTreeModel *model,
+           GtkTreeIter *iter,
+           gpointer data)
+{
+       static gboolean found = FALSE;
+       gboolean retval;
+       gint type;
+       GObject *instance;
+
+       gtk_tree_model_get (model, iter,
+                           TNY_GTK_FOLDER_STORE_TREE_MODEL_TYPE_COLUMN, &type,
+                           TNY_GTK_FOLDER_STORE_TREE_MODEL_INSTANCE_COLUMN, &instance,
+                           -1);
+
+       if (type == TNY_FOLDER_TYPE_ROOT) {
+               const gchar *account_id = tny_account_get_id (TNY_ACCOUNT (instance));
+
+               if (strcmp (account_id, MODEST_LOCAL_FOLDERS_ACCOUNT_ID) &&
+                   strcmp (account_id, MODEST_MMC_ACCOUNT_ID)) {
+
+                       if (!found) {
+                               found = TRUE;
+                               retval = TRUE;
+                       } else
+                               retval = FALSE;
+               } else {
+                       found = FALSE;
+                       retval = TRUE;
+               }
+       } else
+               retval = TRUE;
+
+       return retval;
+}
+
 static gboolean
 update_model (ModestFolderView *self, ModestTnyAccountStore *account_store)
 {
        ModestFolderViewPrivate *priv;
-
        TnyList          *account_list;
-       GtkTreeModel     *model, *sortable;
+       GtkTreeModel     *model;
 
        g_return_val_if_fail (account_store, FALSE);
 
        priv =  MODEST_FOLDER_VIEW_GET_PRIVATE(self);
        
-       /* Notify that there is no folder selected*/
+       /* Notify that there is no folder selected */
        g_signal_emit (G_OBJECT(self), 
                       signals[FOLDER_SELECTION_CHANGED_SIGNAL], 0,
                       NULL, TRUE);
@@ -605,6 +700,8 @@ update_model (ModestFolderView *self, ModestTnyAccountStore *account_store)
                                        account_list,
                                        TNY_ACCOUNT_STORE_STORE_ACCOUNTS);      
        if (account_list) {
+               GtkTreeModel *filter_model = NULL, *sortable = NULL;
+
                sortable = gtk_tree_model_sort_new_with_model (model);
                gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE(sortable),
                                                      TNY_GTK_FOLDER_STORE_TREE_MODEL_NAME_COLUMN, 
@@ -613,8 +710,18 @@ update_model (ModestFolderView *self, ModestTnyAccountStore *account_store)
                                                 TNY_GTK_FOLDER_STORE_TREE_MODEL_NAME_COLUMN,
                                                 cmp_rows, NULL, NULL);
 
+               /* Create filter model */
+               if (priv->style == MODEST_FOLDER_VIEW_STYLE_SHOW_ONE) {
+                       filter_model = gtk_tree_model_filter_new (sortable, NULL);
+                       gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter_model),
+                                                               filter_row,
+                                                               NULL,
+                                                               NULL);
+               }
+
                /* Set new model */
-               gtk_tree_view_set_model (GTK_TREE_VIEW(self), sortable);
+               gtk_tree_view_set_model (GTK_TREE_VIEW(self), 
+                                        (filter_model) ? filter_model : sortable);
                expand_root_items (self); /* expand all account folders */
                g_object_unref (account_list);
        }
@@ -626,10 +733,9 @@ update_model (ModestFolderView *self, ModestTnyAccountStore *account_store)
 static void
 on_selection_changed (GtkTreeSelection *sel, gpointer user_data)
 {
-       GtkTreeModel            *model_sort, *model;
-       TnyFolder               *folder = NULL;
-       GtkTreeIter             iter, iter_sort;
-       GtkTreePath            *path;
+       GtkTreeModel            *model;
+       TnyFolderStore          *folder = NULL;
+       GtkTreeIter             iter;
        ModestFolderView        *tree_view;
        ModestFolderViewPrivate *priv;
        gint                    type;
@@ -641,21 +747,18 @@ on_selection_changed (GtkTreeSelection *sel, gpointer user_data)
        priv->cur_selection = sel;
        
        /* folder was _un_selected if true */
-       if (!gtk_tree_selection_get_selected (sel, &model_sort, &iter_sort)) {
-               if (priv->cur_folder)
-                       g_object_unref (priv->cur_folder);
-               if (priv->cur_row)
-                       gtk_tree_row_reference_free (priv->cur_row);
-               priv->cur_folder = NULL;
-               priv->cur_row = NULL;
+       if (!gtk_tree_selection_get_selected (sel, &model, &iter)) {
+               if (priv->cur_folder_store)
+                       g_object_unref (priv->cur_folder_store);
+               priv->cur_folder_store = NULL;
+
+               /* Notify the display name observers */
+               g_signal_emit (G_OBJECT(user_data), 
+                              signals[FOLDER_DISPLAY_NAME_CHANGED_SIGNAL], 0,
+                              NULL);
                return; 
        }
 
-       model = gtk_tree_model_sort_get_model (GTK_TREE_MODEL_SORT (model_sort));
-       gtk_tree_model_sort_convert_iter_to_child_iter (GTK_TREE_MODEL_SORT (model_sort),
-                                                       &iter,
-                                                       &iter_sort);
-
        tree_view = MODEST_FOLDER_VIEW (user_data);
 
        gtk_tree_model_get (model, &iter,
@@ -664,28 +767,20 @@ on_selection_changed (GtkTreeSelection *sel, gpointer user_data)
                            -1);
 
        /* If the folder is the same do not notify */
-       if ((type == TNY_FOLDER_TYPE_ROOT) || (priv->cur_folder == folder)) {
+       if (priv->cur_folder_store == folder) {
                g_object_unref (folder);
                return;
        }
        
        /* Current folder was unselected */
-       if (priv->cur_folder) {
+       if (priv->cur_folder_store) {
                g_signal_emit (G_OBJECT(tree_view), signals[FOLDER_SELECTION_CHANGED_SIGNAL], 0,
-                              priv->cur_folder, FALSE);
-               g_object_unref (priv->cur_folder);
+                              priv->cur_folder_store, FALSE);
+               g_object_unref (priv->cur_folder_store);
        }
 
-       if (priv->cur_row)
-               gtk_tree_row_reference_free (priv->cur_row);
-
        /* New current references */
-       path = gtk_tree_model_get_path (model_sort, &iter_sort);
-       priv->cur_folder = folder;
-       priv->cur_row = gtk_tree_row_reference_new (model_sort, path);
-
-       /* Frees */
-       gtk_tree_path_free (path);
+       priv->cur_folder_store = folder;
 
        /* New folder has been selected */
        g_signal_emit (G_OBJECT(tree_view), 
@@ -693,7 +788,7 @@ on_selection_changed (GtkTreeSelection *sel, gpointer user_data)
                       0, folder, TRUE); 
 }
 
-TnyFolder *
+TnyFolderStore *
 modest_folder_view_get_selected (ModestFolderView *self)
 {
        ModestFolderViewPrivate *priv;
@@ -701,12 +796,18 @@ modest_folder_view_get_selected (ModestFolderView *self)
        g_return_val_if_fail (self, NULL);
        
        priv = MODEST_FOLDER_VIEW_GET_PRIVATE(self);
-       if (priv->cur_folder)
-               g_object_ref (priv->cur_folder);
+       if (priv->cur_folder_store)
+               g_object_ref (priv->cur_folder_store);
 
-       return priv->cur_folder;
+       return priv->cur_folder_store;
 }
 
+/*
+ * This function orders the mail accounts following the next rules
+ * 1st - remote accounts
+ * 2nd - local account
+ * 3rd - MMC account
+ */
 static gint
 cmp_rows (GtkTreeModel *tree_model, GtkTreeIter *iter1, GtkTreeIter *iter2,
          gpointer user_data)
@@ -715,7 +816,7 @@ cmp_rows (GtkTreeModel *tree_model, GtkTreeIter *iter1, GtkTreeIter *iter2,
        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,
@@ -726,25 +827,35 @@ cmp_rows (GtkTreeModel *tree_model, GtkTreeIter *iter1, GtkTreeIter *iter2,
                            TNY_GTK_FOLDER_STORE_TREE_MODEL_INSTANCE_COLUMN, &folder2,
                            -1);
 
-       /* local_folders should be the last one */
+       /* Order must be: Remote accounts -> Local account -> MMC account */
        if (type == TNY_FOLDER_TYPE_ROOT) {
-               /* the account name is also the name of the root folder
-                * in case of local folders */
-               if (name1 && strcmp (name1, MODEST_LOCAL_FOLDERS_ACCOUNT_NAME) == 0)
+               const gchar *account_id = tny_account_get_id (TNY_ACCOUNT (folder1));
+               const gchar *account_id2 = tny_account_get_id (TNY_ACCOUNT (folder2));
+
+               if (!strcmp (account_id, MODEST_MMC_ACCOUNT_ID))
                        cmp = +1;
-               else if (name2 && strcmp (name2, MODEST_LOCAL_FOLDERS_ACCOUNT_NAME) == 0)
-                       cmp = -1;
-               else 
-                       cmp = modest_text_utils_utf8_strcmp (name1, name2, TRUE);
+               else {
+                       if (!strcmp (account_id, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
+                               if (!strcmp (account_id2, MODEST_MMC_ACCOUNT_ID))
+                                       cmp = -1;
+                               else
+                                       cmp = +1;
+                       } else {
+                               if (!strcmp (account_id2, MODEST_LOCAL_FOLDERS_ACCOUNT_ID) ||
+                                   !strcmp (account_id2, MODEST_MMC_ACCOUNT_ID))
+                                       cmp = -1;
+                               else
+                                       cmp = modest_text_utils_utf8_strcmp (name1, name2, TRUE);
+                       }
+               }
        } else 
                cmp = modest_text_utils_utf8_strcmp (name1, name2, TRUE);
-
        
        if (folder1)
                g_object_unref(G_OBJECT(folder1));
        if (folder2)
                g_object_unref(G_OBJECT(folder2));
-       
+
        g_free (name1);
        g_free (name2);
 
@@ -1289,3 +1400,16 @@ on_configuration_key_changed (ModestConf* conf,
        gtk_tree_view_column_queue_resize (tree_column);
 #endif
 }
+
+void 
+modest_folder_view_set_style (ModestFolderView *self,
+                             ModestFolderViewStyle style)
+{
+       ModestFolderViewPrivate *priv;
+
+       g_return_if_fail (self);
+       
+       priv = MODEST_FOLDER_VIEW_GET_PRIVATE(self);
+
+       priv->style = style;
+}