X-Git-Url: http://git.maemo.org/git/?a=blobdiff_plain;f=src%2Fwidgets%2Fmodest-folder-view.c;h=aefadb13b356c336f62edd8e45349e321a20b0bb;hb=29f871b2e8ae1e859919c5682f69ef8238ffaae4;hp=9ae28e149e2f35ce8f165ad2e1ed50759df378a6;hpb=b22ec780fbe4629d4200f40b8fdced00f50990f8;p=modest diff --git a/src/widgets/modest-folder-view.c b/src/widgets/modest-folder-view.c index 9ae28e1..aefadb1 100644 --- a/src/widgets/modest-folder-view.c +++ b/src/widgets/modest-folder-view.c @@ -36,10 +36,13 @@ #include #include #include +#include +#include #include #include #include #include +#include #include "modest-folder-view.h" @@ -53,13 +56,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 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, @@ -68,13 +70,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; @@ -149,13 +148,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); @@ -167,69 +191,6 @@ 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) -{ - 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; -} - static void icon_cell_data (GtkTreeViewColumn *column, GtkCellRenderer *renderer, @@ -248,43 +209,41 @@ 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); break; case TNY_FOLDER_TYPE_INBOX: - pixbuf = modest_icon_factory_get_small_icon (MODEST_FOLDER_ICON_INBOX); + pixbuf = modest_icon_factory_get_icon (MODEST_FOLDER_ICON_INBOX); break; case TNY_FOLDER_TYPE_OUTBOX: - pixbuf = modest_icon_factory_get_small_icon (MODEST_FOLDER_ICON_OUTBOX); + pixbuf = modest_icon_factory_get_icon (MODEST_FOLDER_ICON_OUTBOX); break; case TNY_FOLDER_TYPE_JUNK: - pixbuf = modest_icon_factory_get_small_icon (MODEST_FOLDER_ICON_JUNK); + pixbuf = modest_icon_factory_get_icon (MODEST_FOLDER_ICON_JUNK); break; case TNY_FOLDER_TYPE_SENT: - pixbuf = modest_icon_factory_get_small_icon (MODEST_FOLDER_ICON_SENT); + pixbuf = modest_icon_factory_get_icon (MODEST_FOLDER_ICON_SENT); break; case TNY_FOLDER_TYPE_DRAFTS: - pixbuf = modest_icon_factory_get_small_icon (MODEST_FOLDER_ICON_DRAFTS); + pixbuf = modest_icon_factory_get_icon (MODEST_FOLDER_ICON_DRAFTS); break; case TNY_FOLDER_TYPE_NOTES: - pixbuf = modest_icon_factory_get_small_icon (MODEST_FOLDER_ICON_NOTES); + pixbuf = modest_icon_factory_get_icon (MODEST_FOLDER_ICON_NOTES); break; case TNY_FOLDER_TYPE_CALENDAR: - pixbuf = modest_icon_factory_get_small_icon (MODEST_FOLDER_ICON_CALENDAR); + pixbuf = modest_icon_factory_get_icon (MODEST_FOLDER_ICON_CALENDAR); break; case TNY_FOLDER_TYPE_CONTACTS: - pixbuf = modest_icon_factory_get_small_icon (MODEST_FOLDER_ICON_CONTACTS); + pixbuf = modest_icon_factory_get_icon (MODEST_FOLDER_ICON_CONTACTS); break; case TNY_FOLDER_TYPE_NORMAL: default: - pixbuf = modest_icon_factory_get_small_icon (MODEST_FOLDER_ICON_NORMAL); + pixbuf = modest_icon_factory_get_icon (MODEST_FOLDER_ICON_NORMAL); break; } @@ -307,7 +266,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; @@ -338,34 +296,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)); - while (!tny_iterator_is_done (iter)) { - g_signal_handler_disconnect (G_OBJECT (tny_iterator_get_current (iter)), - priv->store_accounts_handlers [i++]); - tny_iterator_next (iter); - } - g_object_unref (G_OBJECT (iter)); -} - - -static void modest_folder_view_finalize (GObject *obj) { ModestFolderViewPrivate *priv; @@ -386,12 +316,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 +333,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,7 +384,6 @@ 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); } @@ -470,69 +391,29 @@ modest_folder_view_new (ModestTnyAccountStore *account_store, 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) { - ModestFolderViewPrivate *priv; - TnyIterator *iter; - guint len; - - priv = MODEST_FOLDER_VIEW_GET_PRIVATE(self); - - /* Listen to subscription changes */ - len = tny_list_get_length (TNY_LIST (account_list)); + GtkTreePath *path; + path = gtk_tree_path_new_first (); - g_assert (priv->store_accounts_handlers == NULL); /* don't leak */ - priv->store_accounts_handlers = g_malloc0 (sizeof (guint) * len); - 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)) { - gint i = 0; - - priv->view_is_empty = FALSE; - do { - - 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); - } while (!tny_iterator_is_done (iter)); - } - g_object_unref (G_OBJECT (iter)); + gtk_tree_path_free (path); } @@ -546,25 +427,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; } @@ -586,15 +475,11 @@ 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, @@ -604,45 +489,93 @@ on_selection_changed (GtkTreeSelection *sel, gpointer user_data) if (type == TNY_FOLDER_TYPE_ROOT) return; - + /* emit 2 signals: one for the unselection of the old one, * and one for the selection of the new on */ g_signal_emit (G_OBJECT(tree_view), signals[FOLDER_SELECTION_CHANGED_SIGNAL], 0, 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 update_model (self, MODEST_TNY_ACCOUNT_STORE(account_store)); /* ugly */ +} + +TnyFolder * +modest_folder_view_get_selected (ModestFolderView *self) +{ + ModestFolderViewPrivate *priv; + + g_return_val_if_fail (self, NULL); + + priv = MODEST_FOLDER_VIEW_GET_PRIVATE(self); + if (priv->cur_folder) + g_object_ref (priv->cur_folder); + + return priv->cur_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); + + /* 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 retval; + return cmp; }