Commit 9fbf6aaa authored by Milan Crha's avatar Milan Crha

Bug 202257 - Configurable folder tree sorting

Closes https://bugzilla.gnome.org/show_bug.cgi?id=202257
parent f68d7c5f
......@@ -48,6 +48,8 @@
<menuitem action='mail-tools-subscriptions'/>
<menuitem action='mail-folder-unsubscribe'/>
<separator/>
<menuitem action='mail-folder-edit-sort-order'/>
<separator/>
<menuitem action='mail-folder-copy'/>
<menuitem action='mail-folder-move'/>
<separator/>
......
......@@ -333,6 +333,7 @@ src/mail/e-mail-config-welcome-page.c
src/mail/e-mail-config-window.c
src/mail/e-mail-display.c
src/mail/e-mail-folder-create-dialog.c
src/mail/e-mail-folder-sort-order-dialog.c
src/mail/e-mail-free-form-exp.c
src/mail/e-mail-junk-options.c
src/mail/e-mail-label-dialog.c
......
......@@ -66,6 +66,7 @@ set(SOURCES
e-mail-display-popup-extension.c
e-mail-folder-create-dialog.c
e-mail-folder-pane.c
e-mail-folder-sort-order-dialog.c
e-mail-folder-tweaks.c
e-mail-free-form-exp.c
e-mail-junk-options.c
......@@ -155,6 +156,7 @@ set(HEADERS
e-mail-enums.h
e-mail-folder-create-dialog.h
e-mail-folder-pane.h
e-mail-folder-sort-order-dialog.h
e-mail-folder-tweaks.h
e-mail-free-form-exp.h
e-mail-junk-options.h
......
This diff is collapsed.
/*
* Copyright (C) 2019 Red Hat, Inc. (www.redhat.com)
*
* This library is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef E_MAIL_FOLDER_SORT_ORDER_DIALOG_H
#define E_MAIL_FOLDER_SORT_ORDER_DIALOG_H
#include <gtk/gtk.h>
#include <mail/em-folder-tree.h>
#include <mail/em-folder-tree-model.h>
/* Standard GObject macros */
#define E_TYPE_MAIL_FOLDER_SORT_ORDER_DIALOG \
(e_mail_folder_sort_order_dialog_get_type ())
#define E_MAIL_FOLDER_SORT_ORDER_DIALOG(obj) \
(G_TYPE_CHECK_INSTANCE_CAST \
((obj), E_TYPE_MAIL_FOLDER_SORT_ORDER_DIALOG, EMailFolderSortOrderDialog))
#define E_MAIL_FOLDER_SORT_ORDER_DIALOG_CLASS(cls) \
(G_TYPE_CHECK_CLASS_CAST \
((cls), E_TYPE_MAIL_FOLDER_SORT_ORDER_DIALOG, EMailFolderSortOrderDialogClass))
#define E_IS_MAIL_FOLDER_SORT_ORDER_DIALOG(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE \
((obj), E_TYPE_MAIL_FOLDER_SORT_ORDER_DIALOG))
#define E_IS_MAIL_FOLDER_SORT_ORDER_DIALOG_CLASS(cls) \
(G_TYPE_CHECK_CLASS_TYPE \
((cls), E_TYPE_MAIL_FOLDER_SORT_ORDER_DIALOG))
#define E_MAIL_FOLDER_SORT_ORDER_DIALOG_GET_CLASS(obj) \
(G_TYPE_INSTANCE_GET_CLASS \
((obj), E_TYPE_MAIL_FOLDER_SORT_ORDER_DIALOG, EMailFolderSortOrderDialogClass))
G_BEGIN_DECLS
typedef struct _EMailFolderSortOrderDialog EMailFolderSortOrderDialog;
typedef struct _EMailFolderSortOrderDialogClass EMailFolderSortOrderDialogClass;
typedef struct _EMailFolderSortOrderDialogPrivate EMailFolderSortOrderDialogPrivate;
struct _EMailFolderSortOrderDialog {
/*< private >*/
GtkDialog parent;
EMailFolderSortOrderDialogPrivate *priv;
};
struct _EMailFolderSortOrderDialogClass {
/*< private >*/
GtkDialogClass parent_class;
};
GType e_mail_folder_sort_order_dialog_get_type (void);
GtkWidget * e_mail_folder_sort_order_dialog_new (GtkWindow *parent,
CamelStore *store,
const gchar *folder_uri);
G_END_DECLS
#endif /* E_MAIL_FOLDER_SORT_ORDER_DIALOG_H */
......@@ -26,6 +26,7 @@
#define KEY_TEXT_COLOR "Color"
#define KEY_ICON_FILENAME "Icon"
#define KEY_SORT_ORDER "Sort"
struct _EMailFolderTweaksPrivate {
gchar *config_filename;
......@@ -73,6 +74,31 @@ mail_folder_tweaks_schedule_save (EMailFolderTweaks *tweaks)
}
}
static gboolean
mail_folder_tweaks_remove_key (EMailFolderTweaks *tweaks,
const gchar *folder_uri,
const gchar *key)
{
gboolean changed;
changed = g_key_file_remove_key (tweaks->priv->config, folder_uri, key, NULL);
if (changed) {
gchar **keys;
keys = g_key_file_get_keys (tweaks->priv->config, folder_uri, NULL, NULL);
/* Remove the whole group, if it's the last key in it */
if (!keys || !keys[0]) {
g_key_file_remove_group (tweaks->priv->config, folder_uri, NULL);
}
g_strfreev (keys);
}
return changed;
}
static gchar *
mail_folder_tweaks_dup_string (EMailFolderTweaks *tweaks,
const gchar *folder_uri,
......@@ -98,19 +124,7 @@ mail_folder_tweaks_set_string (EMailFolderTweaks *tweaks,
g_return_if_fail (key != NULL);
if (!value || !*value) {
changed = g_key_file_remove_key (tweaks->priv->config, folder_uri, key, NULL);
if (changed) {
gchar **keys;
keys = g_key_file_get_keys (tweaks->priv->config, folder_uri, NULL, NULL);
/* Remove the whole group, if it's the last key in it */
if (!keys || !keys[0]) {
g_key_file_remove_group (tweaks->priv->config, folder_uri, NULL);
}
g_strfreev (keys);
}
changed = mail_folder_tweaks_remove_key (tweaks, folder_uri, key);
} else {
gchar *stored;
......@@ -129,6 +143,49 @@ mail_folder_tweaks_set_string (EMailFolderTweaks *tweaks,
}
}
static guint
mail_folder_tweaks_get_uint (EMailFolderTweaks *tweaks,
const gchar *folder_uri,
const gchar *key)
{
g_return_val_if_fail (E_IS_MAIL_FOLDER_TWEAKS (tweaks), 0);
g_return_val_if_fail (folder_uri != NULL, 0);
g_return_val_if_fail (key != NULL, 0);
return (guint) g_key_file_get_uint64 (tweaks->priv->config, folder_uri, key, NULL);
}
static void
mail_folder_tweaks_set_uint (EMailFolderTweaks *tweaks,
const gchar *folder_uri,
const gchar *key,
guint value)
{
gboolean changed;
g_return_if_fail (E_IS_MAIL_FOLDER_TWEAKS (tweaks));
g_return_if_fail (folder_uri != NULL);
g_return_if_fail (key != NULL);
if (!value) {
changed = mail_folder_tweaks_remove_key (tweaks, folder_uri, key);
} else {
guint stored;
stored = mail_folder_tweaks_get_uint (tweaks, folder_uri, key);
changed = stored != value;
if (changed)
g_key_file_set_uint64 (tweaks->priv->config, folder_uri, key, (guint64) value);
}
if (changed) {
mail_folder_tweaks_schedule_save (tweaks);
g_signal_emit (tweaks, signals[CHANGED], 0, folder_uri, NULL);
}
}
static GObject *
e_mail_folder_tweaks_constructor (GType type,
guint n_construct_properties,
......@@ -217,7 +274,7 @@ e_mail_folder_tweaks_remove_for_folders (EMailFolderTweaks *tweaks,
for (ii = 0; groups[ii]; ii++) {
if (g_str_has_prefix (groups[ii], top_folder_uri)) {
changed = g_key_file_remove_group (tweaks->priv->config, groups[ii], NULL);
changed = g_key_file_remove_group (tweaks->priv->config, groups[ii], NULL) || changed;
}
}
......@@ -274,8 +331,8 @@ gchar *
e_mail_folder_tweaks_dup_icon_filename (EMailFolderTweaks *tweaks,
const gchar *folder_uri)
{
g_return_val_if_fail (E_IS_MAIL_FOLDER_TWEAKS (tweaks), FALSE);
g_return_val_if_fail (folder_uri != NULL, FALSE);
g_return_val_if_fail (E_IS_MAIL_FOLDER_TWEAKS (tweaks), NULL);
g_return_val_if_fail (folder_uri != NULL, NULL);
return mail_folder_tweaks_dup_string (tweaks, folder_uri, KEY_ICON_FILENAME);
}
......@@ -290,3 +347,51 @@ e_mail_folder_tweaks_set_icon_filename (EMailFolderTweaks *tweaks,
mail_folder_tweaks_set_string (tweaks, folder_uri, KEY_ICON_FILENAME, icon_filename);
}
/* returns 0 as not set/do not know */
guint
e_mail_folder_tweaks_get_sort_order (EMailFolderTweaks *tweaks,
const gchar *folder_uri)
{
g_return_val_if_fail (E_IS_MAIL_FOLDER_TWEAKS (tweaks), 0);
g_return_val_if_fail (folder_uri != NULL, 0);
return mail_folder_tweaks_get_uint (tweaks, folder_uri, KEY_SORT_ORDER);
}
/* Use 0 as 'sort_order' to unset the value */
void
e_mail_folder_tweaks_set_sort_order (EMailFolderTweaks *tweaks,
const gchar *folder_uri,
guint sort_order)
{
g_return_if_fail (E_IS_MAIL_FOLDER_TWEAKS (tweaks));
g_return_if_fail (folder_uri != NULL);
mail_folder_tweaks_set_uint (tweaks, folder_uri, KEY_SORT_ORDER, sort_order);
}
void
e_mail_folder_tweaks_remove_sort_order_for_folders (EMailFolderTweaks *tweaks,
const gchar *top_folder_uri)
{
gchar **groups;
gint ii;
g_return_if_fail (E_IS_MAIL_FOLDER_TWEAKS (tweaks));
g_return_if_fail (top_folder_uri != NULL);
groups = g_key_file_get_groups (tweaks->priv->config, NULL);
if (!groups)
return;
for (ii = 0; groups[ii]; ii++) {
if (g_str_has_prefix (groups[ii], top_folder_uri) &&
g_key_file_has_key (tweaks->priv->config, groups[ii], KEY_SORT_ORDER, NULL)) {
e_mail_folder_tweaks_set_sort_order (tweaks, groups[ii], 0);
}
}
g_strfreev (groups);
}
......@@ -80,6 +80,16 @@ void e_mail_folder_tweaks_set_icon_filename
(EMailFolderTweaks *tweaks,
const gchar *folder_uri,
const gchar *icon_filename);
guint e_mail_folder_tweaks_get_sort_order
(EMailFolderTweaks *tweaks,
const gchar *folder_uri);
void e_mail_folder_tweaks_set_sort_order
(EMailFolderTweaks *tweaks,
const gchar *folder_uri,
guint sort_order);
void e_mail_folder_tweaks_remove_sort_order_for_folders
(EMailFolderTweaks *tweaks,
const gchar *top_folder_uri);
G_END_DECLS
......
......@@ -414,6 +414,7 @@ folder_tree_model_sort (GtkTreeModel *model,
gboolean b_is_store;
const gchar *store_uid = NULL;
guint32 flags_a, flags_b;
guint sort_order_a = 0, sort_order_b = 0;
gint rv = -2;
folder_tree_model = EM_FOLDER_TREE_MODEL (model);
......@@ -424,6 +425,7 @@ folder_tree_model_sort (GtkTreeModel *model,
COL_OBJECT_CAMEL_STORE, &service_a,
COL_STRING_DISPLAY_NAME, &aname,
COL_UINT_FLAGS, &flags_a,
COL_UINT_SORT_ORDER, &sort_order_a,
-1);
gtk_tree_model_get (
......@@ -432,12 +434,20 @@ folder_tree_model_sort (GtkTreeModel *model,
COL_OBJECT_CAMEL_STORE, &service_b,
COL_STRING_DISPLAY_NAME, &bname,
COL_UINT_FLAGS, &flags_b,
COL_UINT_SORT_ORDER, &sort_order_b,
-1);
if (CAMEL_IS_SERVICE (service_a))
store_uid = camel_service_get_uid (service_a);
if (a_is_store && b_is_store) {
if (!a_is_store && !b_is_store && (sort_order_a || sort_order_b)) {
if (sort_order_a && sort_order_b)
rv = sort_order_a < sort_order_b ? -1 : (sort_order_a > sort_order_b ? 1 : 0);
else if (sort_order_a)
rv = -1;
else
rv = 1;
} else if (a_is_store && b_is_store) {
rv = e_mail_account_store_compare_services (
folder_tree_model->priv->account_store,
service_a, service_b);
......@@ -769,7 +779,8 @@ folder_tree_model_constructed (GObject *object)
G_TYPE_BOOLEAN, /* status spinner visible */
G_TYPE_STRING, /* COL_STRING_FOLDER_URI */
G_TYPE_ICON, /* COL_GICON_CUSTOM_ICON */
GDK_TYPE_RGBA /* COL_RGBA_FOREGROUND_RGBA */
GDK_TYPE_RGBA, /* COL_RGBA_FOREGROUND_RGBA */
G_TYPE_UINT /* COL_UINT_SORT_ORDER */
};
g_warn_if_fail (G_N_ELEMENTS (col_types) == NUM_COLUMNS);
......@@ -2030,6 +2041,7 @@ em_folder_tree_model_update_row_tweaks (EMFolderTreeModel *model,
GIcon *custom_icon = NULL;
GdkRGBA *foreground = NULL, rgba;
gchar *folder_uri = NULL, *icon_filename;
guint sort_order;
g_return_if_fail (EM_IS_FOLDER_TREE_MODEL (model));
g_return_if_fail (iter != NULL);
......@@ -2055,9 +2067,12 @@ em_folder_tree_model_update_row_tweaks (EMFolderTreeModel *model,
g_clear_object (&file);
}
sort_order = e_mail_folder_tweaks_get_sort_order (model->priv->folder_tweaks, folder_uri);
gtk_tree_store_set (GTK_TREE_STORE (model), iter,
COL_GICON_CUSTOM_ICON, custom_icon,
COL_RGBA_FOREGROUND_RGBA, foreground,
COL_UINT_SORT_ORDER, sort_order,
-1);
g_clear_object (&custom_icon);
......
......@@ -80,6 +80,7 @@ enum {
COL_STRING_FOLDER_URI, /* folder URI */
COL_GICON_CUSTOM_ICON, /* a custom icon to use for the folder; NULL to use COL_STRING_ICON_NAME */
COL_RGBA_FOREGROUND_RGBA, /* GdkRGBA for the foreground color; can be NULL */
COL_UINT_SORT_ORDER, /* 0 - use default; non-zero - define sort order on its level */
NUM_COLUMNS
};
......
......@@ -20,6 +20,8 @@
#include "evolution-config.h"
#include "mail/e-mail-folder-sort-order-dialog.h"
#include "e-mail-shell-view-private.h"
static void
......@@ -438,6 +440,36 @@ action_mail_folder_delete_cb (GtkAction *action,
g_free (selected_folder_name);
}
static void
action_mail_folder_edit_sort_order_cb (GtkAction *action,
EMailShellView *mail_shell_view)
{
EMailView *mail_view;
EMFolderTree *folder_tree;
CamelStore *store;
GtkWidget *dialog;
GtkWindow *window;
gchar *selected_uri;
folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_view->priv->mail_shell_sidebar);
store = em_folder_tree_ref_selected_store (folder_tree);
g_return_if_fail (store != NULL);
selected_uri = em_folder_tree_get_selected_uri (folder_tree);
mail_view = e_mail_shell_content_get_mail_view (mail_shell_view->priv->mail_shell_content);
window = e_mail_reader_get_window (E_MAIL_READER (mail_view));
dialog = e_mail_folder_sort_order_dialog_new (window, store, selected_uri);
gtk_dialog_run (GTK_DIALOG (dialog));
gtk_widget_destroy (dialog);
g_object_unref (store);
g_free (selected_uri);
}
static void
action_mail_folder_expunge_cb (GtkAction *action,
EMailShellView *mail_shell_view)
......@@ -1598,6 +1630,13 @@ static GtkActionEntry mail_entries[] = {
N_("Permanently remove this folder"),
G_CALLBACK (action_mail_folder_delete_cb) },
{ "mail-folder-edit-sort-order",
NULL,
N_("Edit Sort _Order…"),
NULL,
N_("Change sort order of the folders in the folder tree"),
G_CALLBACK (action_mail_folder_edit_sort_order_cb) },
{ "mail-folder-expunge",
NULL,
N_("E_xpunge"),
......
......@@ -76,6 +76,8 @@
E_SHELL_WINDOW_ACTION ((window), "mail-folder-copy")
#define E_SHELL_WINDOW_ACTION_MAIL_FOLDER_DELETE(window) \
E_SHELL_WINDOW_ACTION ((window), "mail-folder-delete")
#define E_SHELL_WINDOW_ACTION_MAIL_FOLDER_EDIT_SORT_ORDER(window) \
E_SHELL_WINDOW_ACTION ((window), "mail-folder-edit-sort-order")
#define E_SHELL_WINDOW_ACTION_MAIL_FOLDER_EXPUNGE(window) \
E_SHELL_WINDOW_ACTION ((window), "mail-folder-expunge")
#define E_SHELL_WINDOW_ACTION_MAIL_FOLDER_MARK_ALL_AS_READ(window) \
......
......@@ -1405,6 +1405,10 @@ mail_shell_view_update_actions (EShellView *shell_view)
sensitive = folder_is_selected && folder_can_be_deleted;
gtk_action_set_sensitive (action, sensitive);
action = ACTION (MAIL_FOLDER_EDIT_SORT_ORDER);
sensitive = folder_is_selected || folder_is_store;
gtk_action_set_sensitive (action, sensitive);
action = ACTION (MAIL_FOLDER_EXPUNGE);
sensitive = folder_is_selected && (!folder_is_virtual || mail_shell_view->priv->vfolder_allow_expunge);
gtk_action_set_sensitive (action, sensitive);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment