aboutsummaryrefslogtreecommitdiffstats
path: root/widgets
diff options
context:
space:
mode:
authorMilan Crha <mcrha@redhat.com>2011-09-26 17:45:59 +0800
committerRodrigo Moya <rodrigo@gnome-db.org>2011-09-26 18:56:08 +0800
commitd230dd72bb6aff738974ccaa91bfad5d321e9c0c (patch)
tree1c4f343340ad4a613e0016e93301fce83d2ef130 /widgets
parent3262bdb1c49d65c5fa7d2fc3b931784bfcdb57da (diff)
downloadgsoc2013-evolution-d230dd72bb6aff738974ccaa91bfad5d321e9c0c.tar.gz
gsoc2013-evolution-d230dd72bb6aff738974ccaa91bfad5d321e9c0c.tar.zst
gsoc2013-evolution-d230dd72bb6aff738974ccaa91bfad5d321e9c0c.zip
Bug #351025 - Make the order of the mail accounts configurable
Diffstat (limited to 'widgets')
-rw-r--r--widgets/misc/e-account-manager.c103
-rw-r--r--widgets/misc/e-account-tree-view.c772
-rw-r--r--widgets/misc/e-account-tree-view.h46
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