diff options
author | Milan Crha <mcrha@redhat.com> | 2011-09-26 17:45:59 +0800 |
---|---|---|
committer | Milan Crha <mcrha@redhat.com> | 2011-09-26 17:45:59 +0800 |
commit | e0548d25707ad8c4713e2e74c622a92bf4988545 (patch) | |
tree | be2dd1051fa169b90b959cd80b9729a1416d0393 /widgets | |
parent | 4046d1944855274c8a6c406392ee734943142f90 (diff) | |
download | gsoc2013-evolution-e0548d25707ad8c4713e2e74c622a92bf4988545.tar.gz gsoc2013-evolution-e0548d25707ad8c4713e2e74c622a92bf4988545.tar.zst gsoc2013-evolution-e0548d25707ad8c4713e2e74c622a92bf4988545.zip |
Bug #351025 - Make the order of the mail accounts configurable
Diffstat (limited to 'widgets')
-rw-r--r-- | widgets/misc/e-account-manager.c | 103 | ||||
-rw-r--r-- | widgets/misc/e-account-tree-view.c | 772 | ||||
-rw-r--r-- | widgets/misc/e-account-tree-view.h | 46 |
3 files changed, 916 insertions, 5 deletions
diff --git a/widgets/misc/e-account-manager.c b/widgets/misc/e-account-manager.c index e4ee68736a..b2c0583b8b 100644 --- a/widgets/misc/e-account-manager.c +++ b/widgets/misc/e-account-manager.c @@ -37,6 +37,9 @@ struct _EAccountManagerPrivate { GtkWidget *edit_button; GtkWidget *delete_button; GtkWidget *default_button; + GtkWidget *sort_toggle; + GtkWidget *sort_up_button; + GtkWidget *sort_down_button; }; enum { @@ -96,16 +99,22 @@ account_manager_selection_changed_cb (EAccountManager *manager, EAccountList *account_list; EAccount *default_account; EAccount *account; + GtkTreeModel *model = NULL; + GtkTreeIter iter1, iter2; GtkWidget *add_button; GtkWidget *edit_button; GtkWidget *delete_button; GtkWidget *default_button; + GtkWidget *sort_up_button; + GtkWidget *sort_down_button; gboolean sensitive; add_button = manager->priv->add_button; edit_button = manager->priv->edit_button; delete_button = manager->priv->delete_button; default_button = manager->priv->default_button; + sort_up_button = manager->priv->sort_up_button; + sort_down_button = manager->priv->sort_down_button; tree_view = e_account_manager_get_tree_view (manager); account = e_account_tree_view_get_selected (tree_view); @@ -126,6 +135,50 @@ account_manager_selection_changed_cb (EAccountManager *manager, sensitive = (account != NULL && account != default_account); gtk_widget_set_sensitive (default_button, sensitive); + + sensitive = !gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (manager->priv->sort_toggle)) && + gtk_tree_selection_get_selected (selection, &model, &iter1); + iter2 = iter1; + gtk_widget_set_sensitive (sort_up_button, sensitive && gtk_tree_model_iter_previous (model, &iter1)); + gtk_widget_set_sensitive (sort_down_button, sensitive && gtk_tree_model_iter_next (model, &iter2)); +} + +static void +account_manager_sort_toggled_cb (EAccountManager *manager) +{ + GtkTreeView *tree_view; + GtkTreeSelection *selection; + + tree_view = GTK_TREE_VIEW (e_account_manager_get_tree_view (manager)); + selection = gtk_tree_view_get_selection (tree_view); + + account_manager_selection_changed_cb (manager, selection); +} + +static void +account_manager_sort_up_cb (EAccountManager *manager) +{ + GtkTreeView *tree_view; + GtkTreeSelection *selection; + + tree_view = GTK_TREE_VIEW (e_account_manager_get_tree_view (manager)); + selection = gtk_tree_view_get_selection (tree_view); + + e_account_tree_view_move_up (e_account_manager_get_tree_view (manager)); + account_manager_selection_changed_cb (manager, selection); +} + +static void +account_manager_sort_down_cb (EAccountManager *manager) +{ + GtkTreeView *tree_view; + GtkTreeSelection *selection; + + tree_view = GTK_TREE_VIEW (e_account_manager_get_tree_view (manager)); + selection = gtk_tree_view_get_selection (tree_view); + + e_account_tree_view_move_down (e_account_manager_get_tree_view (manager)); + account_manager_selection_changed_cb (manager, selection); } static void @@ -195,6 +248,21 @@ account_manager_dispose (GObject *object) priv->delete_button = NULL; } + if (priv->sort_toggle != NULL) { + g_object_unref (priv->sort_toggle); + priv->sort_toggle = NULL; + } + + if (priv->sort_up_button != NULL) { + g_object_unref (priv->sort_up_button); + priv->sort_up_button = NULL; + } + + if (priv->sort_down_button != NULL) { + g_object_unref (priv->sort_down_button); + priv->sort_down_button = NULL; + } + /* Chain up to parent's dispose() method. */ G_OBJECT_CLASS (e_account_manager_parent_class)->dispose (object); } @@ -312,6 +380,23 @@ e_account_manager_init (EAccountManager *manager) container = GTK_WIDGET (manager); + widget = gtk_check_button_new_with_mnemonic (_("Use default Evolution _sort order for accounts")); + manager->priv->sort_toggle = g_object_ref (widget); + gtk_widget_show (widget); + gtk_table_attach ( + GTK_TABLE (container), widget, 0, 1, 1, 2, + GTK_EXPAND | GTK_FILL, 0, 4, 0); + + g_object_bind_property ( + manager->priv->tree_view, "sort-alpha", + widget, "active", + G_BINDING_BIDIRECTIONAL | + G_BINDING_SYNC_CREATE); + + g_signal_connect_swapped ( + widget, "toggled", + G_CALLBACK (account_manager_sort_toggled_cb), manager); + widget = gtk_vbutton_box_new (); gtk_button_box_set_layout ( GTK_BUTTON_BOX (widget), GTK_BUTTONBOX_START); @@ -361,6 +446,24 @@ e_account_manager_init (EAccountManager *manager) g_signal_connect_swapped ( widget, "clicked", G_CALLBACK (account_manager_default_clicked_cb), manager); + + widget = gtk_button_new_from_stock (GTK_STOCK_GO_UP); + gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0); + manager->priv->sort_up_button = g_object_ref (widget); + gtk_widget_show (widget); + + g_signal_connect_swapped ( + widget, "clicked", + G_CALLBACK (account_manager_sort_up_cb), manager); + + widget = gtk_button_new_from_stock (GTK_STOCK_GO_DOWN); + gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0); + manager->priv->sort_down_button = g_object_ref (widget); + gtk_widget_show (widget); + + g_signal_connect_swapped ( + widget, "clicked", + G_CALLBACK (account_manager_sort_down_cb), manager); } GtkWidget * diff --git a/widgets/misc/e-account-tree-view.c b/widgets/misc/e-account-tree-view.c index 18c39dccec..a2136433d4 100644 --- a/widgets/misc/e-account-tree-view.c +++ b/widgets/misc/e-account-tree-view.c @@ -33,25 +33,35 @@ enum { COLUMN_DEFAULT, COLUMN_ENABLED, COLUMN_NAME, - COLUMN_PROTOCOL + COLUMN_PROTOCOL, + COLUMN_SORTORDER }; enum { PROP_0, PROP_ACCOUNT_LIST, - PROP_SELECTED + PROP_SELECTED, + PROP_SORT_ALPHA, + PROP_EXPRESS_MODE, + PROP_ENABLE_LOCAL_FOLDERS, + PROP_ENABLE_SEARCH_FOLDERS }; enum { ENABLE_ACCOUNT, DISABLE_ACCOUNT, REFRESHED, + SORT_ORDER_CHANGED, LAST_SIGNAL }; struct _EAccountTreeViewPrivate { EAccountList *account_list; GHashTable *index; + gboolean sort_alpha; + gboolean express_mode; + gboolean enable_local_folders; + gboolean enable_search_folders; }; static guint signals[LAST_SIGNAL]; @@ -61,10 +71,124 @@ G_DEFINE_TYPE ( e_account_tree_view, GTK_TYPE_TREE_VIEW) +static gint +account_tree_view_sort (GtkTreeModel *model, + GtkTreeIter *a, + GtkTreeIter *b, + gpointer user_data) +{ + gint rv = -2; + gchar *aname = NULL, *bname = NULL; + EAccount *aaccount = NULL, *baccount = NULL; + guint asortorder = 0, bsortorder = 0; + + gtk_tree_model_get (model, a, + COLUMN_ACCOUNT, &aaccount, + COLUMN_NAME, &aname, + COLUMN_SORTORDER, &asortorder, + -1); + + gtk_tree_model_get (model, b, + COLUMN_ACCOUNT, &baccount, + COLUMN_NAME, &bname, + COLUMN_SORTORDER, &bsortorder, + -1); + + if ((!aaccount || !baccount || !e_account_tree_view_get_sort_alpha (user_data)) && aname && bname) { + if (e_account_tree_view_get_sort_alpha (user_data)) { + const gchar *on_this_computer = _("On This Computer"); + const gchar *search_folders = _("Search Folders"); + + if (e_account_tree_view_get_express_mode (user_data)) { + if (g_str_equal (aname, on_this_computer) && + g_str_equal (bname, search_folders)) + rv = -1; + else if (g_str_equal (bname, on_this_computer) && + g_str_equal (aname, search_folders)) + rv = 1; + else if (g_str_equal (aname, on_this_computer)) + rv = 1; + else if (g_str_equal (bname, on_this_computer)) + rv = -1; + else if (g_str_equal (aname, search_folders)) + rv = 1; + else if (g_str_equal (bname, search_folders)) + rv = -1; + } else { + if (g_str_equal (aname, on_this_computer)) + rv = -1; + else if (g_str_equal (bname, on_this_computer)) + rv = 1; + else if (g_str_equal (aname, search_folders)) + rv = 1; + else if (g_str_equal (bname, search_folders)) + rv = -1; + } + } else { + if (asortorder < bsortorder) + rv = -1; + else if (asortorder > bsortorder) + rv = 1; + else + rv = 0; + } + } + + if (rv == -2) { + if (aname == NULL) { + if (bname == NULL) + rv = 0; + else + rv = -1; + } else if (bname == NULL) + rv = 1; + + if (rv == -2) + rv = g_utf8_collate (aname, bname); + } + + g_free (aname); + g_free (bname); + + if (aaccount) + g_object_unref (aaccount); + if (baccount) + g_object_unref (baccount); + + return rv; +} + +static void +account_tree_view_normalize_sortorder_column (EAccountTreeView *tree_view) +{ + GtkListStore *list_store; + GtkTreeModel *model; + GtkTreeIter iter; + guint index; + + g_return_if_fail (tree_view != NULL); + g_return_if_fail (E_IS_ACCOUNT_TREE_VIEW (tree_view)); + + model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree_view)); + if (!model || !gtk_tree_model_get_iter_first (model, &iter)) + return; + + list_store = GTK_LIST_STORE (model); + g_return_if_fail (list_store != NULL); + + index = 1; + do { + gtk_list_store_set (list_store, &iter, COLUMN_SORTORDER, index, -1); + + index++; + } while (gtk_tree_model_iter_next (model, &iter)); +} + static gboolean account_tree_view_refresh_timeout_cb (gpointer ptree_view) { EAccountTreeView *tree_view; + EAccountTreeViewSelectedType selected; EAccountList *account_list; EAccount *account; GtkListStore *store; @@ -73,18 +197,28 @@ account_tree_view_refresh_timeout_cb (gpointer ptree_view) EIterator *account_iter; EAccount *default_account; GHashTable *index; + GSList *sort_order; GList *list = NULL; GList *iter; tree_view = ptree_view; account_list = e_account_tree_view_get_account_list (tree_view); + sort_order = e_account_tree_view_get_sort_order (tree_view); store = gtk_list_store_new ( - 5, E_TYPE_ACCOUNT, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, - G_TYPE_STRING, G_TYPE_STRING); + 6, E_TYPE_ACCOUNT, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, + G_TYPE_STRING, G_TYPE_STRING, G_TYPE_UINT); model = GTK_TREE_MODEL (store); index = tree_view->priv->index; + gtk_tree_sortable_set_default_sort_func ( + GTK_TREE_SORTABLE (model), + account_tree_view_sort, tree_view, NULL); + gtk_tree_sortable_set_sort_column_id ( + GTK_TREE_SORTABLE (model), + GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID, + GTK_SORT_ASCENDING); + g_hash_table_remove_all (index); if (account_list == NULL) @@ -148,8 +282,28 @@ account_tree_view_refresh_timeout_cb (gpointer ptree_view) camel_url_free (url); } -skip: + gtk_list_store_append (store, &tree_iter); + gtk_list_store_set ( + store, &tree_iter, + COLUMN_ACCOUNT, NULL, + COLUMN_DEFAULT, FALSE, + COLUMN_ENABLED, tree_view->priv->enable_local_folders, + COLUMN_NAME, _("On This Computer"), + COLUMN_PROTOCOL, NULL, + -1); + + gtk_list_store_append (store, &tree_iter); + gtk_list_store_set ( + store, &tree_iter, + COLUMN_ACCOUNT, NULL, + COLUMN_DEFAULT, FALSE, + COLUMN_ENABLED, tree_view->priv->enable_search_folders, + COLUMN_NAME, _("Search Folders"), + COLUMN_PROTOCOL, NULL, + -1); + skip: /* Restore the previously selected account. */ + selected = e_account_tree_view_get_selected_type (tree_view); account = e_account_tree_view_get_selected (tree_view); if (account != NULL) g_object_ref (account); @@ -157,6 +311,13 @@ skip: e_account_tree_view_set_selected (tree_view, account); if (account != NULL) g_object_unref (account); + else if (selected == E_ACCOUNT_TREE_VIEW_SELECTED_LOCAL || + selected == E_ACCOUNT_TREE_VIEW_SELECTED_VFOLDER) + e_account_tree_view_set_selected_type (tree_view, selected); + + e_account_tree_view_set_sort_order (tree_view, sort_order); + g_slist_foreach (sort_order, (GFunc) g_free, NULL); + g_slist_free (sort_order); g_signal_emit (tree_view, signals[REFRESHED], 0); @@ -302,6 +463,26 @@ account_tree_view_set_property (GObject *object, E_ACCOUNT_TREE_VIEW (object), g_value_get_object (value)); return; + case PROP_SORT_ALPHA: + e_account_tree_view_set_sort_alpha ( + E_ACCOUNT_TREE_VIEW (object), + g_value_get_boolean (value)); + return; + case PROP_EXPRESS_MODE: + e_account_tree_view_set_express_mode ( + E_ACCOUNT_TREE_VIEW (object), + g_value_get_boolean (value)); + return; + case PROP_ENABLE_LOCAL_FOLDERS: + e_account_tree_view_set_enable_local_folders ( + E_ACCOUNT_TREE_VIEW (object), + g_value_get_boolean (value)); + return; + case PROP_ENABLE_SEARCH_FOLDERS: + e_account_tree_view_set_enable_search_folders ( + E_ACCOUNT_TREE_VIEW (object), + g_value_get_boolean (value)); + return; } G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); @@ -327,6 +508,30 @@ account_tree_view_get_property (GObject *object, e_account_tree_view_get_selected ( E_ACCOUNT_TREE_VIEW (object))); return; + case PROP_SORT_ALPHA: + g_value_set_boolean ( + value, + e_account_tree_view_get_sort_alpha ( + E_ACCOUNT_TREE_VIEW (object))); + return; + case PROP_EXPRESS_MODE: + g_value_set_boolean ( + value, + e_account_tree_view_get_express_mode ( + E_ACCOUNT_TREE_VIEW (object))); + return; + case PROP_ENABLE_LOCAL_FOLDERS: + g_value_set_boolean ( + value, + e_account_tree_view_get_enable_local_folders ( + E_ACCOUNT_TREE_VIEW (object))); + return; + case PROP_ENABLE_SEARCH_FOLDERS: + g_value_set_boolean ( + value, + e_account_tree_view_get_enable_search_folders ( + E_ACCOUNT_TREE_VIEW (object))); + return; } G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); @@ -442,6 +647,46 @@ e_account_tree_view_class_init (EAccountTreeViewClass *class) G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + g_object_class_install_property ( + object_class, + PROP_SORT_ALPHA, + g_param_spec_boolean ( + "sort-alpha", + "Sort alphabetically", + NULL, + TRUE, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_EXPRESS_MODE, + g_param_spec_boolean ( + "express-mode", + "Express Mode sorting", + NULL, + FALSE, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_ENABLE_LOCAL_FOLDERS, + g_param_spec_boolean ( + "enable-local-folders", + "Enable Local Folders", + NULL, + TRUE, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_ENABLE_SEARCH_FOLDERS, + g_param_spec_boolean ( + "enable-search-folders", + "Enable Search Folders", + NULL, + TRUE, + G_PARAM_READWRITE)); + signals[ENABLE_ACCOUNT] = g_signal_new ( "enable-account", G_TYPE_FROM_CLASS (class), @@ -468,6 +713,15 @@ e_account_tree_view_class_init (EAccountTreeViewClass *class) NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + + signals[SORT_ORDER_CHANGED] = g_signal_new ( + "sort-order-changed", + G_TYPE_FROM_CLASS (class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EAccountTreeViewClass, sort_order_changed), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); } static void @@ -485,6 +739,10 @@ e_account_tree_view_init (EAccountTreeView *tree_view) tree_view->priv = G_TYPE_INSTANCE_GET_PRIVATE ( tree_view, E_TYPE_ACCOUNT_TREE_VIEW, EAccountTreeViewPrivate); tree_view->priv->index = index; + tree_view->priv->sort_alpha = TRUE; + tree_view->priv->express_mode = FALSE; + tree_view->priv->enable_local_folders = TRUE; + tree_view->priv->enable_search_folders = TRUE; selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view)); @@ -622,3 +880,507 @@ e_account_tree_view_set_selected (EAccountTreeView *tree_view, return TRUE; } + +/** + * e_account_tree_view_get_selected_type: + * @tree_view: an #EAccountTreeView + * + * Returns: What node type is selected. This is useful for virtual + * nodes "On This Computer" and "Search Folders", which doesn't have + * their #EAccount representations. if the function returns + * #E_ACCOUNT_TREE_VIEW_SELECTED_ACCOUNT, then the selected account + * can be obtained with e_account_tree_view_get_selected(). + * + * Since: 3.4 + **/ +EAccountTreeViewSelectedType +e_account_tree_view_get_selected_type (EAccountTreeView *tree_view) +{ + EAccountTreeViewSelectedType res = E_ACCOUNT_TREE_VIEW_SELECTED_NONE; + EAccount *account = NULL; + gchar *name = NULL; + GtkTreeSelection *selection; + GtkTreeModel *model; + GtkTreeIter iter; + + g_return_val_if_fail (tree_view != NULL, E_ACCOUNT_TREE_VIEW_SELECTED_NONE); + g_return_val_if_fail (E_IS_ACCOUNT_TREE_VIEW (tree_view), E_ACCOUNT_TREE_VIEW_SELECTED_NONE); + + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view)); + if (!gtk_tree_selection_get_selected (selection, &model, &iter)) + return E_ACCOUNT_TREE_VIEW_SELECTED_NONE; + + gtk_tree_model_get (model, &iter, + COLUMN_ACCOUNT, &account, + COLUMN_NAME, &name, + -1); + + if (account) { + res = E_ACCOUNT_TREE_VIEW_SELECTED_ACCOUNT; + g_object_unref (account); + } else if (name) { + if (g_str_equal (name, _("On This Computer"))) + res = E_ACCOUNT_TREE_VIEW_SELECTED_LOCAL; + else if (g_str_equal (name, _("Search Folders"))) + res = E_ACCOUNT_TREE_VIEW_SELECTED_VFOLDER; + } + + g_free (name); + + return res; +} + +/** + * e_account_tree_view_set_selected_type: + * @tree_view: an #EAccountTreeView + * @select: what to select; see below what can be used here + * + * Selects special nodes in a view. Can be only either #E_ACCOUNT_TREE_VIEW_SELECTED_LOCAL + * or #E_ACCOUNT_TREE_VIEW_SELECTED_VFOLDER. + * + * Since: 3.4 + **/ +void +e_account_tree_view_set_selected_type (EAccountTreeView *tree_view, EAccountTreeViewSelectedType select) +{ + GtkTreeSelection *selection; + GtkTreeModel *model; + GtkTreeIter iter; + gboolean found; + + g_return_if_fail (tree_view != NULL); + g_return_if_fail (E_IS_ACCOUNT_TREE_VIEW (tree_view)); + + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view)); + model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree_view)); + + if (!model || !gtk_tree_model_get_iter_first (model, &iter)) + return; + + if (select != E_ACCOUNT_TREE_VIEW_SELECTED_LOCAL && + select != E_ACCOUNT_TREE_VIEW_SELECTED_VFOLDER) + return; + + found = FALSE; + do { + gchar *name = NULL; + EAccount *account = NULL; + + gtk_tree_model_get (model, &iter, + COLUMN_ACCOUNT, &account, + COLUMN_NAME, &name, + -1); + + if (account) { + g_object_unref (account); + } else { + switch (select) { + case E_ACCOUNT_TREE_VIEW_SELECTED_LOCAL: + found = g_strcmp0 (name, _("On This Computer")) == 0; + break; + case E_ACCOUNT_TREE_VIEW_SELECTED_VFOLDER: + found = g_strcmp0 (name, _("Search Folders")) == 0; + break; + default: + break; + } + } + + g_free (name); + } while (!found && gtk_tree_model_iter_next (model, &iter)); + + if (found) + gtk_tree_selection_select_iter (selection, &iter); +} + +static guint +account_tree_view_get_slist_index (const GSList *account_uids, const gchar *uid) +{ + guint res = 0; + + while (account_uids) { + if (g_strcmp0 (uid, account_uids->data) == 0) + return res; + + account_uids = account_uids->next; + res++; + } + + return -1; +} + +/** + * e_account_tree_view_set_sort_order: + * @tree_view: an #EAccountTreeView + * @account_uids: a #GSList of account uids as string + * + * Sets user sort order for accounts based on the order + * in @account_uids. This is used only when sort + * alphabetically is set to #FALSE. + * + * Since: 3.4 + **/ +void +e_account_tree_view_set_sort_order (EAccountTreeView *tree_view, const GSList *account_uids) +{ + GtkTreeModel *model; + GtkTreeIter iter; + + g_return_if_fail (tree_view != NULL); + g_return_if_fail (E_IS_ACCOUNT_TREE_VIEW (tree_view)); + + model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree_view)); + + if (!model || !gtk_tree_model_get_iter_first (model, &iter)) + return; + + do { + gchar *name = NULL; + EAccount *account = NULL; + guint sort_order = 0; + + gtk_tree_model_get (model, &iter, + COLUMN_ACCOUNT, &account, + COLUMN_NAME, &name, + -1); + + if (account) { + sort_order = account_tree_view_get_slist_index (account_uids, account->uid) + 1; + g_object_unref (account); + } else if (g_strcmp0 (name, _("On This Computer")) == 0) { + sort_order = account_tree_view_get_slist_index (account_uids, "local") + 1; + } else if (g_strcmp0 (name, _("Search Folders")) == 0) { + sort_order = account_tree_view_get_slist_index (account_uids, "vfolder") + 1; + } else { + g_warn_if_reached (); + } + + gtk_list_store_set (GTK_LIST_STORE (model), &iter, COLUMN_SORTORDER, sort_order, -1); + g_free (name); + } while (gtk_tree_model_iter_next (model, &iter)); + + account_tree_view_normalize_sortorder_column (tree_view); + e_account_tree_view_sort_changed (tree_view); +} + +static gint +eval_order_by_sort_hash_cb (gconstpointer a, gconstpointer b, gpointer user_data) +{ + guint asortorder = GPOINTER_TO_UINT (g_hash_table_lookup (user_data, a)); + guint bsortorder = GPOINTER_TO_UINT (g_hash_table_lookup (user_data, b)); + + if (asortorder < bsortorder) + return -1; + if (asortorder > bsortorder) + return 1; + + return 0; +} + +/** + * e_account_tree_view_get_sort_order: + * @tree_view: an #EAccountTreeView + * + * Returns: Newly allocated #GSList of newly allocated strings + * containing account UIDs in order as user wish to see them. + * Each item of the returned list should be freed with g_free() + * and the list itself should be freed with g_slist_free(), when + * no longer needed. + * + * Since: 3.4 + **/ +GSList * +e_account_tree_view_get_sort_order (EAccountTreeView *tree_view) +{ + GtkTreeModel *model; + GtkTreeIter iter; + GHashTable *hash; + GSList *res = NULL; + + g_return_val_if_fail (tree_view != NULL, NULL); + g_return_val_if_fail (E_IS_ACCOUNT_TREE_VIEW (tree_view), NULL); + + model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree_view)); + + if (!model || !gtk_tree_model_get_iter_first (model, &iter)) + return NULL; + + hash = g_hash_table_new (g_direct_hash, g_direct_equal); + + do { + gchar *toadd = NULL; + gchar *name = NULL; + EAccount *account = NULL; + guint sort_order = 0; + + gtk_tree_model_get (model, &iter, + COLUMN_ACCOUNT, &account, + COLUMN_NAME, &name, + COLUMN_SORTORDER, &sort_order, + -1); + + if (account) { + toadd = g_strdup (account->uid); + g_object_unref (account); + } else if (g_strcmp0 (name, _("On This Computer")) == 0) { + toadd = g_strdup ("local"); + } else if (g_strcmp0 (name, _("Search Folders")) == 0) { + toadd = g_strdup ("vfolder"); + } else { + g_warn_if_reached (); + } + + if (toadd) { + g_hash_table_insert (hash, toadd, GUINT_TO_POINTER (sort_order)); + res = g_slist_prepend (res, toadd); + } + + g_free (name); + } while (gtk_tree_model_iter_next (model, &iter)); + + res = g_slist_sort_with_data (res, eval_order_by_sort_hash_cb, hash); + + g_hash_table_destroy (hash); + + return res; +} + +/** + * e_account_tree_view_sort_changed: + * @tree_view: an #EAccountTreeView + * + * Notifies @tree_view about sort order change, thus it resorts + * items in a view. + * + * Since: 3.4 + **/ +void +e_account_tree_view_sort_changed (EAccountTreeView *tree_view) +{ + GtkTreeModel *model; + + g_return_if_fail (tree_view != NULL); + g_return_if_fail (E_IS_ACCOUNT_TREE_VIEW (tree_view)); + + model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree_view)); + if (!model) + return; + + /* this invokes also sort on a GtkListStore */ + gtk_tree_sortable_set_default_sort_func ( + GTK_TREE_SORTABLE (model), + account_tree_view_sort, tree_view, NULL); +} + +static void +account_tree_view_swap_sort_order (EAccountTreeView *tree_view, gint direction) +{ + GtkTreeSelection *selection; + GtkTreeModel *model; + GtkTreeIter iter1, iter2; + guint sortorder1, sortorder2; + + g_return_if_fail (tree_view != NULL); + g_return_if_fail (E_IS_ACCOUNT_TREE_VIEW (tree_view)); + g_return_if_fail (direction != 0); + + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view)); + if (!gtk_tree_selection_get_selected (selection, &model, &iter1)) + return; + + iter2 = iter1; + if ((direction < 0 && !gtk_tree_model_iter_previous (model, &iter2)) || + (direction > 0 && !gtk_tree_model_iter_next (model, &iter2))) + return; + + gtk_tree_model_get (model, &iter1, COLUMN_SORTORDER, &sortorder1, -1); + gtk_tree_model_get (model, &iter2, COLUMN_SORTORDER, &sortorder2, -1); + + gtk_list_store_set (GTK_LIST_STORE (model), &iter1, COLUMN_SORTORDER, sortorder2, -1); + gtk_list_store_set (GTK_LIST_STORE (model), &iter2, COLUMN_SORTORDER, sortorder1, -1); + + e_account_tree_view_sort_changed (tree_view); + + g_signal_emit (tree_view, signals[SORT_ORDER_CHANGED], 0); +} + +/** + * e_account_tree_view_move_up: + * @tree_view: an #EAccountTreeView + * + * Moves currently selected node up within user's sort order. + * + * Since: 3.4 + **/ +void +e_account_tree_view_move_up (EAccountTreeView *tree_view) +{ + g_return_if_fail (tree_view != NULL); + g_return_if_fail (E_IS_ACCOUNT_TREE_VIEW (tree_view)); + + account_tree_view_swap_sort_order (tree_view, -1); +} + +/** + * e_account_tree_view_move_down: + * @tree_view: an #EAccountTreeView + * + * Moves currently selected node down within user's sort order. + * + * Since: 3.4 + **/ +void +e_account_tree_view_move_down (EAccountTreeView *tree_view) +{ + g_return_if_fail (tree_view != NULL); + g_return_if_fail (E_IS_ACCOUNT_TREE_VIEW (tree_view)); + + account_tree_view_swap_sort_order (tree_view, +1); +} + +void +e_account_tree_view_set_sort_alpha (EAccountTreeView *tree_view, gboolean sort_alpha) +{ + g_return_if_fail (tree_view != NULL); + g_return_if_fail (E_IS_ACCOUNT_TREE_VIEW (tree_view)); + g_return_if_fail (tree_view->priv != NULL); + + if ((tree_view->priv->sort_alpha ? 1 : 0) == (sort_alpha ? 1 : 0)) + return; + + tree_view->priv->sort_alpha = sort_alpha; + + g_object_notify (G_OBJECT (tree_view), "sort-alpha"); + e_account_tree_view_sort_changed (tree_view); +} + +gboolean +e_account_tree_view_get_sort_alpha (EAccountTreeView *tree_view) +{ + g_return_val_if_fail (tree_view != NULL, FALSE); + g_return_val_if_fail (E_IS_ACCOUNT_TREE_VIEW (tree_view), FALSE); + g_return_val_if_fail (tree_view->priv != NULL, FALSE); + + return tree_view->priv->sort_alpha; +} + +void +e_account_tree_view_set_express_mode (EAccountTreeView *tree_view, gboolean express_mode) +{ + g_return_if_fail (tree_view != NULL); + g_return_if_fail (E_IS_ACCOUNT_TREE_VIEW (tree_view)); + g_return_if_fail (tree_view->priv != NULL); + + if ((tree_view->priv->express_mode ? 1 : 0) == (express_mode ? 1 : 0)) + return; + + tree_view->priv->express_mode = express_mode; + + g_object_notify (G_OBJECT (tree_view), "express-mode"); + e_account_tree_view_sort_changed (tree_view); +} + +gboolean +e_account_tree_view_get_express_mode (EAccountTreeView *tree_view) +{ + g_return_val_if_fail (tree_view != NULL, FALSE); + g_return_val_if_fail (E_IS_ACCOUNT_TREE_VIEW (tree_view), FALSE); + g_return_val_if_fail (tree_view->priv != NULL, FALSE); + + return tree_view->priv->express_mode; +} + +static void +update_special_enable_state (EAccountTreeView *tree_view, const gchar *display_name, gboolean enabled) +{ + GtkTreeModel *model; + GtkTreeIter iter; + GtkListStore *list_store; + + g_return_if_fail (tree_view != NULL); + g_return_if_fail (display_name != NULL); + + model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree_view)); + if (!model) + return; + + list_store = GTK_LIST_STORE (model); + g_return_if_fail (list_store != NULL); + + if (!gtk_tree_model_get_iter_first (model, &iter)) + return; + + do { + gchar *name = NULL; + EAccount *account = NULL; + + gtk_tree_model_get (model, &iter, + COLUMN_ACCOUNT, &account, + COLUMN_NAME, &name, + -1); + + if (account) { + g_object_unref (account); + } else if (g_strcmp0 (name, display_name) == 0) { + gtk_list_store_set (list_store, &iter, COLUMN_ENABLED, enabled, -1); + g_free (name); + break; + } + + g_free (name); + } while (gtk_tree_model_iter_next (model, &iter)); +} + +void +e_account_tree_view_set_enable_local_folders (EAccountTreeView *tree_view, gboolean enabled) +{ + g_return_if_fail (tree_view != NULL); + g_return_if_fail (E_IS_ACCOUNT_TREE_VIEW (tree_view)); + g_return_if_fail (tree_view->priv != NULL); + + if ((tree_view->priv->enable_local_folders ? 1 : 0) == (enabled ? 1 : 0)) + return; + + tree_view->priv->enable_local_folders = enabled; + + g_object_notify (G_OBJECT (tree_view), "enable-local-folders"); + + update_special_enable_state (tree_view, _("On This Computer"), enabled); +} + +gboolean +e_account_tree_view_get_enable_local_folders (EAccountTreeView *tree_view) +{ + g_return_val_if_fail (tree_view != NULL, FALSE); + g_return_val_if_fail (E_IS_ACCOUNT_TREE_VIEW (tree_view), FALSE); + g_return_val_if_fail (tree_view->priv != NULL, FALSE); + + return tree_view->priv->enable_local_folders; +} + +void +e_account_tree_view_set_enable_search_folders (EAccountTreeView *tree_view, gboolean enabled) +{ + g_return_if_fail (tree_view != NULL); + g_return_if_fail (E_IS_ACCOUNT_TREE_VIEW (tree_view)); + g_return_if_fail (tree_view->priv != NULL); + + if ((tree_view->priv->enable_search_folders ? 1 : 0) == (enabled ? 1 : 0)) + return; + + tree_view->priv->enable_search_folders = enabled; + + g_object_notify (G_OBJECT (tree_view), "enable-search-folders"); + + update_special_enable_state (tree_view, _("Search Folders"), enabled); +} + +gboolean +e_account_tree_view_get_enable_search_folders (EAccountTreeView *tree_view) +{ + g_return_val_if_fail (tree_view != NULL, FALSE); + g_return_val_if_fail (E_IS_ACCOUNT_TREE_VIEW (tree_view), FALSE); + g_return_val_if_fail (tree_view->priv != NULL, FALSE); + + return tree_view->priv->enable_search_folders; +} diff --git a/widgets/misc/e-account-tree-view.h b/widgets/misc/e-account-tree-view.h index e9b2f7f8d3..d62d040bbd 100644 --- a/widgets/misc/e-account-tree-view.h +++ b/widgets/misc/e-account-tree-view.h @@ -47,6 +47,14 @@ G_BEGIN_DECLS +typedef enum +{ + E_ACCOUNT_TREE_VIEW_SELECTED_NONE, + E_ACCOUNT_TREE_VIEW_SELECTED_ACCOUNT, + E_ACCOUNT_TREE_VIEW_SELECTED_LOCAL, + E_ACCOUNT_TREE_VIEW_SELECTED_VFOLDER +} EAccountTreeViewSelectedType; + typedef struct _EAccountTreeView EAccountTreeView; typedef struct _EAccountTreeViewClass EAccountTreeViewClass; typedef struct _EAccountTreeViewPrivate EAccountTreeViewPrivate; @@ -62,6 +70,7 @@ struct _EAccountTreeViewClass { void (*enable_account) (EAccountTreeView *tree_view); void (*disable_account) (EAccountTreeView *tree_view); void (*refreshed) (EAccountTreeView *tree_view); + void (*sort_order_changed) (EAccountTreeView *tree_view); }; GType e_account_tree_view_get_type (void); @@ -80,6 +89,43 @@ EAccount * e_account_tree_view_get_selected gboolean e_account_tree_view_set_selected (EAccountTreeView *tree_view, EAccount *account); +EAccountTreeViewSelectedType + e_account_tree_view_get_selected_type + (EAccountTreeView *tree_view); +void e_account_tree_view_set_selected_type + (EAccountTreeView *tree_view, + EAccountTreeViewSelectedType select); + +void e_account_tree_view_set_sort_order + (EAccountTreeView *tree_view, + const GSList *account_uids); + +GSList * e_account_tree_view_get_sort_order + (EAccountTreeView *tree_view); + +void e_account_tree_view_sort_changed + (EAccountTreeView *tree_view); +void e_account_tree_view_move_up (EAccountTreeView *tree_view); +void e_account_tree_view_move_down (EAccountTreeView *tree_view); + +void e_account_tree_view_set_sort_alpha + (EAccountTreeView *tree_view, + gboolean sort_alpha); +gboolean e_account_tree_view_get_sort_alpha + (EAccountTreeView *tree_view); +void e_account_tree_view_set_express_mode + (EAccountTreeView *tree_view, + gboolean express_mode); +gboolean e_account_tree_view_get_express_mode + (EAccountTreeView *tree_view); +void e_account_tree_view_set_enable_local_folders + (EAccountTreeView *tree_view, gboolean enabled); +gboolean e_account_tree_view_get_enable_local_folders + (EAccountTreeView *tree_view); +void e_account_tree_view_set_enable_search_folders + (EAccountTreeView *tree_view, gboolean enabled); +gboolean e_account_tree_view_get_enable_search_folders + (EAccountTreeView *tree_view); G_END_DECLS |