diff --git a/data/images/CMakeLists.txt b/data/images/CMakeLists.txt
index 1d8ee48b48..ea58e229ed 100644
--- a/data/images/CMakeLists.txt
+++ b/data/images/CMakeLists.txt
@@ -3,6 +3,8 @@ set(images
draft-paper.png
draft-stamp.jpg
midnight-stars.jpg
+ mode-with-headerbar.png
+ mode-without-headerbar.png
paper.png
rect.png
ribbon.jpg
diff --git a/data/images/mode-with-headerbar.png b/data/images/mode-with-headerbar.png
new file mode 100644
index 0000000000..8e369aa4a6
Binary files /dev/null and b/data/images/mode-with-headerbar.png differ
diff --git a/data/images/mode-without-headerbar.png b/data/images/mode-without-headerbar.png
new file mode 100644
index 0000000000..4ddd311490
Binary files /dev/null and b/data/images/mode-without-headerbar.png differ
diff --git a/po/POTFILES.in b/po/POTFILES.in
index deb9f6cb1d..2e3bb8e83a 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -393,6 +393,7 @@ src/mail/vfoldertypes.xml.in
src/modules/accounts-window/e-accounts-window-editors.c
src/modules/accounts-window/e-collection-wizard-page.c
src/modules/accounts-window/e-webdav-browser-page.c
+src/modules/appearance-settings/evolution-appearance-settings.c
src/modules/addressbook/autocompletion-config.c
src/modules/addressbook/eab-composer-util.c
src/modules/addressbook/e-book-shell-backend.c
diff --git a/src/modules/CMakeLists.txt b/src/modules/CMakeLists.txt
index d995f4dc60..8fcc7b5bf0 100644
--- a/src/modules/CMakeLists.txt
+++ b/src/modules/CMakeLists.txt
@@ -62,6 +62,7 @@ add_subdirectory(addressbook)
add_subdirectory(calendar)
add_subdirectory(mail)
add_subdirectory(accounts-window)
+add_subdirectory(appearance-settings)
add_subdirectory(backup-restore)
add_subdirectory(book-config-carddav)
add_subdirectory(book-config-google)
diff --git a/src/modules/appearance-settings/CMakeLists.txt b/src/modules/appearance-settings/CMakeLists.txt
new file mode 100644
index 0000000000..747d0056bf
--- /dev/null
+++ b/src/modules/appearance-settings/CMakeLists.txt
@@ -0,0 +1,21 @@
+set(extra_deps
+ evolution-shell
+)
+set(sources
+ evolution-appearance-settings.c
+)
+set(extra_defines
+ -DEVOLUTION_IMAGESDIR=\"${imagesdir}\"
+)
+set(extra_cflags)
+set(extra_incdirs)
+set(extra_ldflags)
+
+add_evolution_module(module-appearance-settings
+ sources
+ extra_deps
+ extra_defines
+ extra_cflags
+ extra_incdirs
+ extra_ldflags
+)
diff --git a/src/modules/appearance-settings/evolution-appearance-settings.c b/src/modules/appearance-settings/evolution-appearance-settings.c
new file mode 100644
index 0000000000..94617bfef3
--- /dev/null
+++ b/src/modules/appearance-settings/evolution-appearance-settings.c
@@ -0,0 +1,463 @@
+/*
+ * This program 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 program 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 General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, see .
+ *
+ */
+
+#include "evolution-config.h"
+
+#include
+
+#include "e-util/e-util.h"
+#include "e-util/e-util-private.h"
+#include "shell/e-shell-window.h"
+
+/* Standard GObject macros */
+#define E_TYPE_APPEARANCE_SETTINGS \
+ (e_appearance_settings_get_type ())
+#define E_APPEARANCE_SETTINGS(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_APPEARANCE_SETTINGS, EAppearanceSettings))
+
+typedef struct _EAppearanceSettings EAppearanceSettings;
+typedef struct _EAppearanceSettingsClass EAppearanceSettingsClass;
+
+struct _EAppearanceSettings {
+ EExtension parent;
+};
+
+struct _EAppearanceSettingsClass {
+ EExtensionClass parent_class;
+};
+
+/* Module Entry Points */
+void e_module_load (GTypeModule *type_module);
+void e_module_unload (GTypeModule *type_module);
+
+/* Forward Declarations */
+GType e_appearance_settings_get_type (void);
+
+G_DEFINE_DYNAMIC_TYPE (EAppearanceSettings, e_appearance_settings, E_TYPE_EXTENSION)
+
+typedef struct _ToolbarIconSizeData {
+ gint ref_count;
+ EToolbarIconSize current_value;
+ GtkWidget *radio_default;
+ GtkWidget *radio_small;
+ GtkWidget *radio_large;
+} ToolbarIconSizeData;
+
+static void
+e_appearance_settings_toolbar_icon_size_changed_cb (GSettings *settings,
+ const gchar *key,
+ gpointer user_data)
+{
+ ToolbarIconSizeData *tisd = user_data;
+ EToolbarIconSize current_value;
+
+ g_return_if_fail (tisd != NULL);
+
+ if (g_strcmp0 (key, "toolbar-icon-size") != 0)
+ return;
+
+ current_value = g_settings_get_enum (settings, "toolbar-icon-size");
+
+ if (tisd->current_value == current_value)
+ return;
+
+ tisd->current_value = current_value;
+
+ switch (tisd->current_value) {
+ default:
+ case E_TOOLBAR_ICON_SIZE_DEFAULT:
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (tisd->radio_default), TRUE);
+ break;
+ case E_TOOLBAR_ICON_SIZE_SMALL:
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (tisd->radio_small), TRUE);
+ break;
+ case E_TOOLBAR_ICON_SIZE_LARGE:
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (tisd->radio_large), TRUE);
+ break;
+ }
+}
+
+static ToolbarIconSizeData *
+toolbar_icon_size_data_ref (ToolbarIconSizeData *tisd)
+{
+ g_atomic_int_inc (&tisd->ref_count);
+
+ return tisd;
+}
+
+static void
+toolbar_icon_size_data_unref (ToolbarIconSizeData *tisd)
+{
+ if (g_atomic_int_dec_and_test (&tisd->ref_count)) {
+ GSettings *settings;
+
+ settings = e_util_ref_settings ("org.gnome.evolution.shell");
+ g_signal_handlers_disconnect_by_func (settings, G_CALLBACK (e_appearance_settings_toolbar_icon_size_changed_cb), tisd);
+ g_clear_object (&settings);
+
+ g_free (tisd);
+ }
+}
+
+static void
+e_appearance_settings_toolbar_icon_size_toggled_cb (GtkWidget *radio_button,
+ gpointer user_data)
+{
+ ToolbarIconSizeData *tisd = user_data;
+ EToolbarIconSize new_value;
+ GSettings *settings;
+
+ g_return_if_fail (tisd != NULL);
+ g_return_if_fail (tisd->radio_default == radio_button ||
+ tisd->radio_small == radio_button ||
+ tisd->radio_large == radio_button);
+
+ if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (radio_button)))
+ return;
+
+ new_value = radio_button == tisd->radio_small ? E_TOOLBAR_ICON_SIZE_SMALL :
+ radio_button == tisd->radio_large ? E_TOOLBAR_ICON_SIZE_LARGE :
+ E_TOOLBAR_ICON_SIZE_DEFAULT;
+
+ if (new_value == tisd->current_value)
+ return;
+
+ tisd->current_value = new_value;
+
+ settings = e_util_ref_settings ("org.gnome.evolution.shell");
+ g_settings_set_enum (settings, "toolbar-icon-size", tisd->current_value);
+ g_clear_object (&settings);
+}
+
+static GtkWidget *
+e_appearance_settings_page_new (EPreferencesWindow *window)
+{
+ PangoAttrList *bold;
+ PangoAttrList *italic;
+ GtkGrid *grid;
+ GtkWidget *widget, *main_radio;
+ GSettings *settings;
+ ToolbarIconSizeData *tisd;
+ gchar *filename;
+ gint row = 0;
+
+ settings = e_util_ref_settings ("org.gnome.evolution.shell");
+
+ bold = pango_attr_list_new ();
+ pango_attr_list_insert (bold, pango_attr_weight_new (PANGO_WEIGHT_BOLD));
+
+ italic = pango_attr_list_new ();
+ pango_attr_list_insert (italic, pango_attr_style_new (PANGO_STYLE_ITALIC));
+
+ grid = GTK_GRID (gtk_grid_new ());
+ g_object_set (grid,
+ "halign", GTK_ALIGN_FILL,
+ "hexpand", TRUE,
+ "valign", GTK_ALIGN_FILL,
+ "vexpand", TRUE,
+ "border-width", 12,
+ "row-spacing", 2,
+ NULL);
+
+ widget = gtk_label_new (_("Title Bar Mode"));
+ g_object_set (widget,
+ "halign", GTK_ALIGN_START,
+ "hexpand", FALSE,
+ "attributes", bold,
+ NULL);
+
+ gtk_grid_attach (grid, widget, 0, row, 2, 1);
+ row++;
+
+ /* Translators: This is the GNOME project name; you probably do not want to translate it, apart of changing the mnemonic */
+ widget = gtk_radio_button_new_with_mnemonic (NULL, _("_GNOME"));
+ g_object_set (widget,
+ "margin-start", 12,
+ NULL);
+
+ main_radio = widget;
+
+ g_settings_bind (
+ settings, "use-header-bar",
+ widget, "active",
+ G_SETTINGS_BIND_DEFAULT);
+
+ gtk_grid_attach (grid, widget, 0, row, 2, 1);
+ row++;
+
+ filename = g_build_filename (EVOLUTION_IMAGESDIR, "mode-with-headerbar.png", NULL);
+ widget = gtk_image_new_from_file (filename);
+ g_object_set (widget,
+ "margin-start", 30,
+ "margin-bottom", 6,
+ NULL);
+ g_free (filename);
+
+ gtk_grid_attach (grid, widget, 0, row, 2, 1);
+ row++;
+
+ /* Translators: This belongs under "Title Bar Mode" setting, thus similar to "Title Bar Mode: Standard" */
+ widget = gtk_radio_button_new_with_mnemonic (NULL, _("_Standard"));
+ g_object_set (widget,
+ "margin-start", 12,
+ NULL);
+
+ gtk_radio_button_join_group (GTK_RADIO_BUTTON (widget), GTK_RADIO_BUTTON (main_radio));
+
+ gtk_grid_attach (grid, widget, 0, row, 2, 1);
+ row++;
+
+ filename = g_build_filename (EVOLUTION_IMAGESDIR, "mode-without-headerbar.png", NULL);
+ widget = gtk_image_new_from_file (filename);
+ g_object_set (widget,
+ "margin-start", 30,
+ NULL);
+ g_free (filename);
+
+ gtk_grid_attach (grid, widget, 0, row, 2, 1);
+ row++;
+
+ tisd = g_new0 (ToolbarIconSizeData, 1);
+ tisd->ref_count = 1;
+
+ widget = gtk_label_new (_("Toolbar Icon Size"));
+ g_object_set (widget,
+ "halign", GTK_ALIGN_START,
+ "hexpand", FALSE,
+ "attributes", bold,
+ "margin-top", 12,
+ NULL);
+
+ gtk_grid_attach (grid, widget, 0, row, 2, 1);
+ row++;
+
+ /* Translators: This is for "Toolbar Icon Size: Default" */
+ widget = gtk_radio_button_new_with_mnemonic (NULL, _("_Default"));
+ g_object_set (widget,
+ "margin-start", 12,
+ NULL);
+
+ main_radio = widget;
+
+ tisd->radio_default = widget;
+
+ gtk_grid_attach (grid, widget, 0, row, 2, 1);
+ row++;
+
+ /* Translators: This is for "Toolbar Icon Size: Small" */
+ widget = gtk_radio_button_new_with_mnemonic (NULL, _("Sm_all"));
+ g_object_set (widget,
+ "margin-start", 12,
+ NULL);
+
+ gtk_radio_button_join_group (GTK_RADIO_BUTTON (widget), GTK_RADIO_BUTTON (main_radio));
+ tisd->radio_small = widget;
+
+ gtk_grid_attach (grid, widget, 0, row, 2, 1);
+ row++;
+
+ /* Translators: This is for "Toolbar Icon Size: Large" */
+ widget = gtk_radio_button_new_with_mnemonic (NULL, _("_Large"));
+ g_object_set (widget,
+ "margin-start", 12,
+ NULL);
+
+ gtk_radio_button_join_group (GTK_RADIO_BUTTON (widget), GTK_RADIO_BUTTON (main_radio));
+ tisd->radio_large = widget;
+
+ gtk_grid_attach (grid, widget, 0, row, 2, 1);
+ row++;
+
+ g_signal_connect (settings, "changed::toolbar-icon-size",
+ G_CALLBACK (e_appearance_settings_toolbar_icon_size_changed_cb), tisd);
+
+ /* Read after the signal handler is connected */
+ tisd->current_value = g_settings_get_enum (settings, "toolbar-icon-size");
+
+ switch (tisd->current_value) {
+ default:
+ case E_TOOLBAR_ICON_SIZE_DEFAULT:
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (tisd->radio_default), TRUE);
+ break;
+ case E_TOOLBAR_ICON_SIZE_SMALL:
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (tisd->radio_small), TRUE);
+ break;
+ case E_TOOLBAR_ICON_SIZE_LARGE:
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (tisd->radio_large), TRUE);
+ break;
+ }
+
+ g_signal_connect_data (tisd->radio_default, "toggled",
+ G_CALLBACK (e_appearance_settings_toolbar_icon_size_toggled_cb), toolbar_icon_size_data_ref (tisd),
+ (GClosureNotify) toolbar_icon_size_data_unref, G_CONNECT_DEFAULT);
+
+ g_signal_connect_data (tisd->radio_small, "toggled",
+ G_CALLBACK (e_appearance_settings_toolbar_icon_size_toggled_cb), toolbar_icon_size_data_ref (tisd),
+ (GClosureNotify) toolbar_icon_size_data_unref, G_CONNECT_DEFAULT);
+
+ g_signal_connect_data (tisd->radio_large, "toggled",
+ G_CALLBACK (e_appearance_settings_toolbar_icon_size_toggled_cb), toolbar_icon_size_data_ref (tisd),
+ (GClosureNotify) toolbar_icon_size_data_unref, G_CONNECT_DEFAULT);
+
+ toolbar_icon_size_data_unref (tisd);
+
+ widget = gtk_label_new (_("Layout"));
+ g_object_set (widget,
+ "halign", GTK_ALIGN_START,
+ "hexpand", FALSE,
+ "attributes", bold,
+ "margin-top", 12,
+ NULL);
+
+ gtk_grid_attach (grid, widget, 0, row, 2, 1);
+ row++;
+
+ widget = gtk_check_button_new_with_mnemonic (_("Show M_enu Bar"));
+ g_object_set (widget,
+ "margin-start", 12,
+ NULL);
+
+ g_settings_bind (
+ settings, "menubar-visible",
+ widget, "active",
+ G_SETTINGS_BIND_DEFAULT);
+
+ gtk_grid_attach (grid, widget, 0, row, 2, 1);
+ row++;
+
+ widget = gtk_check_button_new_with_mnemonic (_("Show _Tool Bar"));
+ g_object_set (widget,
+ "margin-start", 12,
+ NULL);
+
+ g_settings_bind (
+ settings, "toolbar-visible",
+ widget, "active",
+ G_SETTINGS_BIND_DEFAULT);
+
+ gtk_grid_attach (grid, widget, 0, row, 2, 1);
+ row++;
+
+ widget = gtk_check_button_new_with_mnemonic (_("Show Side _Bar"));
+ g_object_set (widget,
+ "margin-start", 12,
+ NULL);
+
+ g_settings_bind (
+ settings, "sidebar-visible",
+ widget, "active",
+ G_SETTINGS_BIND_DEFAULT);
+
+ gtk_grid_attach (grid, widget, 0, row, 2, 1);
+ row++;
+
+ widget = gtk_check_button_new_with_mnemonic (_("Show Stat_us Bar"));
+ g_object_set (widget,
+ "margin-start", 12,
+ NULL);
+
+ g_settings_bind (
+ settings, "statusbar-visible",
+ widget, "active",
+ G_SETTINGS_BIND_DEFAULT);
+
+ gtk_grid_attach (grid, widget, 0, row, 2, 1);
+ row++;
+
+ widget = gtk_label_new (_("Note: Some changes will not take effect until restart"));
+ g_object_set (widget,
+ "halign", GTK_ALIGN_START,
+ "hexpand", FALSE,
+ "attributes", italic,
+ "margin-top", 12,
+ NULL);
+
+ gtk_grid_attach (grid, widget, 0, row, 2, 1);
+ row++;
+
+ pango_attr_list_unref (bold);
+ pango_attr_list_unref (italic);
+
+ widget = GTK_WIDGET (grid);
+ gtk_widget_show_all (widget);
+
+ g_clear_object (&settings);
+
+ return widget;
+}
+
+static void
+appearance_settings_constructed (GObject *object)
+{
+ EExtensible *extensible;
+ EAppearanceSettings *extension;
+ EShellWindow *shell_window;
+ EShell *shell;
+ GtkWidget *preferences_window;
+
+ extension = E_APPEARANCE_SETTINGS (object);
+ extensible = e_extension_get_extensible (E_EXTENSION (extension));
+
+ shell_window = E_SHELL_WINDOW (extensible);
+ shell = e_shell_window_get_shell (shell_window);
+ preferences_window = e_shell_get_preferences_window (shell);
+
+ e_preferences_window_add_page (
+ E_PREFERENCES_WINDOW (preferences_window),
+ "page-appearance",
+ "preferences-system",
+ _("Appearance"),
+ NULL,
+ e_appearance_settings_page_new,
+ 950);
+
+ /* Chain up to parent's method. */
+ G_OBJECT_CLASS (e_appearance_settings_parent_class)->constructed (object);
+}
+
+static void
+e_appearance_settings_class_init (EAppearanceSettingsClass *class)
+{
+ GObjectClass *object_class;
+ EExtensionClass *extension_class;
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->constructed = appearance_settings_constructed;
+
+ extension_class = E_EXTENSION_CLASS (class);
+ extension_class->extensible_type = E_TYPE_SHELL_WINDOW;
+}
+
+static void
+e_appearance_settings_class_finalize (EAppearanceSettingsClass *class)
+{
+}
+
+static void
+e_appearance_settings_init (EAppearanceSettings *extension)
+{
+}
+
+G_MODULE_EXPORT void
+e_module_load (GTypeModule *type_module)
+{
+ e_appearance_settings_register_type (type_module);
+}
+
+G_MODULE_EXPORT void
+e_module_unload (GTypeModule *type_module)
+{
+}