[epiphany] Redesign Preferences Privacy Page - Make the Clear Cookies, Passwords and Clear Personal Data rows a



commit f3bd850a953a53d382719393165bdbf81c36abf8
Author: Yetizone <andreii lisita gmail com>
Date:   Wed Jun 10 13:14:13 2020 +0300

    Redesign Preferences Privacy Page
    - Make the Clear Cookies, Passwords and Clear Personal Data rows actionable
    - Remove the GtkButton from these rows and replace them with a GtkImage
    - Replace the Cookies, Passwords and Personal Data dialogs with views contained inside a HdyDeck in the 
Preferences Dialog
    - Use HdyWindow in the Preferences Dialog
    
    Closes https://gitlab.gnome.org/GNOME/epiphany/-/issues/1057

 src/ephy-shell.c                                   |   7 +-
 src/meson.build                                    |   9 +-
 .../{clear-data-dialog.c => clear-data-view.c}     | 162 +++---
 .../{clear-data-dialog.h => clear-data-view.h}     |   6 +-
 .../{cookies-dialog.c => ephy-cookies-view.c}      |  58 +-
 .../{passwords-dialog.h => ephy-cookies-view.h}    |   9 +-
 src/preferences/ephy-data-view.c                   | 631 +++++++++++++++++++++
 src/preferences/ephy-data-view.h                   |  62 ++
 src/preferences/ephy-prefs-dialog.c                | 152 +++++
 .../{prefs-dialog.h => ephy-prefs-dialog.h}        |   8 +-
 .../{passwords-dialog.c => passwords-view.c}       | 179 ++----
 .../{cookies-dialog.h => passwords-view.h}         |   9 +-
 src/preferences/prefs-dialog.c                     |  73 ---
 src/preferences/prefs-general-page.c               |  15 +-
 src/preferences/prefs-general-page.h               |   5 +-
 src/preferences/prefs-privacy-page.c               | 105 ++--
 src/resources/epiphany.gresource.xml               |   7 +-
 .../{clear-data-dialog.ui => clear-data-view.ui}   |   2 +-
 .../gtk/{cookies-dialog.ui => cookies-view.ui}     |   2 +-
 src/resources/gtk/data-view.ui                     | 274 +++++++++
 .../gtk/{passwords-dialog.ui => passwords-view.ui} |   2 +-
 src/resources/gtk/prefs-dialog.ui                  | 150 +++--
 src/resources/gtk/prefs-privacy-page.ui            |  50 +-
 23 files changed, 1471 insertions(+), 506 deletions(-)
---
diff --git a/src/ephy-shell.c b/src/ephy-shell.c
index 73a77cbea..d850b3f49 100644
--- a/src/ephy-shell.c
+++ b/src/ephy-shell.c
@@ -34,6 +34,7 @@
 #include "ephy-lockdown.h"
 #include "ephy-notification.h"
 #include "ephy-prefs.h"
+#include "ephy-prefs-dialog.h"
 #include "ephy-session.h"
 #include "ephy-settings.h"
 #include "ephy-sync-utils.h"
@@ -43,7 +44,6 @@
 #include "ephy-web-app-utils.h"
 #include "ephy-web-view.h"
 #include "ephy-window.h"
-#include "prefs-dialog.h"
 #include "window-commands.h"
 
 #include <glib/gi18n.h>
@@ -1201,9 +1201,8 @@ GObject *
 ephy_shell_get_prefs_dialog (EphyShell *shell)
 {
   if (shell->prefs_dialog == NULL) {
-    shell->prefs_dialog = g_object_new (EPHY_TYPE_PREFS_DIALOG,
-                                        "use-header-bar", TRUE,
-                                        NULL);
+    shell->prefs_dialog = g_object_new (EPHY_TYPE_PREFS_DIALOG, NULL);
+
     g_signal_connect (shell->prefs_dialog,
                       "destroy",
                       G_CALLBACK (gtk_widget_destroyed),
diff --git a/src/meson.build b/src/meson.build
index 03999ca59..4593942a0 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -44,13 +44,14 @@ libephymain_sources = [
   'ephy-tab-label.c',
   'ephy-window.c',
   'popup-commands.c',
-  'preferences/clear-data-dialog.c',
-  'preferences/cookies-dialog.c',
+  'preferences/clear-data-view.c',
+  'preferences/ephy-cookies-view.c',
   'preferences/ephy-data-dialog.c',
+  'preferences/ephy-data-view.c',
+  'preferences/ephy-prefs-dialog.c',
   'preferences/ephy-search-engine-dialog.c',
-  'preferences/passwords-dialog.c',
+  'preferences/passwords-view.c',
   'preferences/prefs-appearance-page.c',
-  'preferences/prefs-dialog.c',
   'preferences/prefs-general-page.c',
   'preferences/prefs-privacy-page.c',
   'preferences/prefs-sync-page.c',
diff --git a/src/preferences/clear-data-dialog.c b/src/preferences/clear-data-view.c
similarity index 64%
rename from src/preferences/clear-data-dialog.c
rename to src/preferences/clear-data-view.c
index 29a47a701..022d49625 100644
--- a/src/preferences/clear-data-dialog.c
+++ b/src/preferences/clear-data-view.c
@@ -19,7 +19,7 @@
  */
 
 #include "config.h"
-#include "clear-data-dialog.h"
+#include "clear-data-view.h"
 
 #include <glib/gi18n.h>
 #include <gtk/gtk.h>
@@ -37,8 +37,8 @@ typedef enum {
   TIMESPAN_FOREVER
 } Timespan;
 
-struct _ClearDataDialog {
-  EphyDataDialog parent_instance;
+struct _ClearDataView {
+  EphyDataView parent_instance;
 
   GtkWidget *treeview;
   GtkTreeModel *treestore;
@@ -57,7 +57,7 @@ enum {
   SENSITIVE_COLUMN
 };
 
-G_DEFINE_TYPE (ClearDataDialog, clear_data_dialog, EPHY_TYPE_DATA_DIALOG)
+G_DEFINE_TYPE (ClearDataView, clear_data_view, EPHY_TYPE_DATA_VIEW)
 
 #define PERSISTENT_DATA_TYPES WEBKIT_WEBSITE_DATA_DISK_CACHE | \
   WEBKIT_WEBSITE_DATA_OFFLINE_APPLICATION_CACHE | \
@@ -117,7 +117,7 @@ get_timespan_for_combo_value (Timespan timespan)
 static void
 website_data_fetched_cb (WebKitWebsiteDataManager *manager,
                          GAsyncResult             *result,
-                         ClearDataDialog          *dialog)
+                         ClearDataView            *clear_data_view)
 {
   GList *data_list;
   GtkTreeStore *treestore;
@@ -129,19 +129,19 @@ website_data_fetched_cb (WebKitWebsiteDataManager *manager,
     return;
   }
 
-  ephy_data_dialog_set_is_loading (EPHY_DATA_DIALOG (dialog), FALSE);
+  ephy_data_view_set_is_loading (EPHY_DATA_VIEW (clear_data_view), FALSE);
 
   if (!data_list) {
-    ephy_data_dialog_set_has_data (EPHY_DATA_DIALOG (dialog), FALSE);
+    ephy_data_view_set_has_data (EPHY_DATA_VIEW (clear_data_view), FALSE);
 
     if (error)
       g_error_free (error);
     return;
   }
 
-  ephy_data_dialog_set_has_data (EPHY_DATA_DIALOG (dialog), TRUE);
+  ephy_data_view_set_has_data (EPHY_DATA_VIEW (clear_data_view), TRUE);
 
-  treestore = GTK_TREE_STORE (dialog->treestore);
+  treestore = GTK_TREE_STORE (clear_data_view->treestore);
   for (guint i = 0; i < G_N_ELEMENTS (data_entries); i++) {
     GtkTreeIter parent_iter;
     gboolean empty = TRUE;
@@ -164,7 +164,7 @@ website_data_fetched_cb (WebKitWebsiteDataManager *manager,
                                          ACTIVE_COLUMN, data_entries[i].initial_state,
                                          NAME_COLUMN, webkit_website_data_get_name (data),
                                          DATA_COLUMN, webkit_website_data_ref (data),
-                                         SENSITIVE_COLUMN, dialog->timespan == TIMESPAN_FOREVER,
+                                         SENSITIVE_COLUMN, clear_data_view->timespan == TIMESPAN_FOREVER,
                                          -1);
       empty = FALSE;
     }
@@ -188,7 +188,7 @@ all_children_visible (GtkTreeModel       *model,
 }
 
 static void
-on_clear_all_clicked (ClearDataDialog *dialog)
+on_clear_all_clicked (ClearDataView *clear_data_view)
 {
   GtkTreeIter top_iter;
   WebKitWebsiteDataTypes types_to_clear = 0;
@@ -196,33 +196,31 @@ on_clear_all_clicked (ClearDataDialog *dialog)
   WebKitWebsiteDataTypes types_to_remove = 0;
   GTimeSpan timespan;
 
-  if (!gtk_tree_model_get_iter_first (dialog->treestore, &top_iter)) {
-    gtk_widget_destroy (GTK_WIDGET (dialog));
+  if (!gtk_tree_model_get_iter_first (clear_data_view->treestore, &top_iter))
     return;
-  }
 
-  timespan = get_timespan_for_combo_value (dialog->timespan);
+  timespan = get_timespan_for_combo_value (clear_data_view->timespan);
 
   do {
     guint type;
     gboolean active;
     GtkTreeIter child_iter;
 
-    gtk_tree_model_get (dialog->treestore, &top_iter,
+    gtk_tree_model_get (clear_data_view->treestore, &top_iter,
                         TYPE_COLUMN, &type,
                         ACTIVE_COLUMN, &active,
                         -1);
-    if (active && (timespan || all_children_visible (dialog->treestore, &top_iter, 
dialog->treemodelfilter))) {
+    if (active && (timespan || all_children_visible (clear_data_view->treestore, &top_iter, 
clear_data_view->treemodelfilter))) {
       types_to_clear |= type;
-    } else if (!timespan && gtk_tree_model_iter_children (dialog->treestore, &child_iter, &top_iter)) {
+    } else if (!timespan && gtk_tree_model_iter_children (clear_data_view->treestore, &child_iter, 
&top_iter)) {
       gboolean empty = TRUE;
 
       do {
         WebKitWebsiteData *data;
         GtkTreeIter filter_iter;
 
-        if (gtk_tree_model_filter_convert_child_iter_to_iter (dialog->treemodelfilter, &filter_iter, 
&child_iter)) {
-          gtk_tree_model_get (dialog->treestore, &child_iter,
+        if (gtk_tree_model_filter_convert_child_iter_to_iter (clear_data_view->treemodelfilter, 
&filter_iter, &child_iter)) {
+          gtk_tree_model_get (clear_data_view->treestore, &child_iter,
                               ACTIVE_COLUMN, &active,
                               DATA_COLUMN, &data,
                               -1);
@@ -233,12 +231,12 @@ on_clear_all_clicked (ClearDataDialog *dialog)
           } else
             webkit_website_data_unref (data);
         }
-      } while (gtk_tree_model_iter_next (dialog->treestore, &child_iter));
+      } while (gtk_tree_model_iter_next (clear_data_view->treestore, &child_iter));
 
       if (!empty)
         types_to_remove |= type;
     }
-  } while (gtk_tree_model_iter_next (dialog->treestore, &top_iter));
+  } while (gtk_tree_model_iter_next (clear_data_view->treestore, &top_iter));
 
   if (types_to_clear) {
     webkit_website_data_manager_clear (get_website_data_manger (),
@@ -253,46 +251,54 @@ on_clear_all_clicked (ClearDataDialog *dialog)
   }
 
   g_list_free_full (data_to_remove, (GDestroyNotify)webkit_website_data_unref);
-  gtk_widget_destroy (GTK_WIDGET (dialog));
+
+  /* Reload tree */
+  ephy_data_view_set_is_loading (EPHY_DATA_VIEW (clear_data_view), TRUE);
+  gtk_tree_store_clear (GTK_TREE_STORE (clear_data_view->treestore));
+  webkit_website_data_manager_fetch (get_website_data_manger (),
+                                     PERSISTENT_DATA_TYPES,
+                                     clear_data_view->cancellable,
+                                     (GAsyncReadyCallback)website_data_fetched_cb,
+                                     clear_data_view);
 }
 
 static void
 item_toggled_cb (GtkCellRendererToggle *renderer,
                  const char            *path_str,
-                 ClearDataDialog       *dialog)
+                 ClearDataView         *clear_data_view)
 {
   GtkTreePath *path = gtk_tree_path_new_from_string (path_str);
   GtkTreeIter filter_iter, iter;
   gboolean active;
 
-  gtk_tree_model_get_iter (GTK_TREE_MODEL (dialog->treemodelfilter),
+  gtk_tree_model_get_iter (GTK_TREE_MODEL (clear_data_view->treemodelfilter),
                            &filter_iter, path);
-  gtk_tree_model_filter_convert_iter_to_child_iter (dialog->treemodelfilter,
+  gtk_tree_model_filter_convert_iter_to_child_iter (clear_data_view->treemodelfilter,
                                                     &iter, &filter_iter);
-  gtk_tree_model_get (dialog->treestore, &iter,
+  gtk_tree_model_get (clear_data_view->treestore, &iter,
                       ACTIVE_COLUMN, &active,
                       -1);
-  gtk_tree_store_set (GTK_TREE_STORE (dialog->treestore), &iter,
+  gtk_tree_store_set (GTK_TREE_STORE (clear_data_view->treestore), &iter,
                       ACTIVE_COLUMN, !active,
                       -1);
 
-  if (gtk_tree_model_iter_has_child (dialog->treestore, &iter)) {
+  if (gtk_tree_model_iter_has_child (clear_data_view->treestore, &iter)) {
     GtkTreeIter child_iter;
 
-    gtk_tree_model_iter_children (dialog->treestore, &child_iter, &iter);
+    gtk_tree_model_iter_children (clear_data_view->treestore, &child_iter, &iter);
     do {
-      gtk_tree_store_set (GTK_TREE_STORE (dialog->treestore), &child_iter,
+      gtk_tree_store_set (GTK_TREE_STORE (clear_data_view->treestore), &child_iter,
                           ACTIVE_COLUMN, !active,
                           -1);
-    } while (gtk_tree_model_iter_next (dialog->treestore, &child_iter));
+    } while (gtk_tree_model_iter_next (clear_data_view->treestore, &child_iter));
   } else {
     GtkTreeIter parent_iter;
 
     /* Update the parent */
-    gtk_tree_model_iter_parent (dialog->treestore, &parent_iter, &iter);
+    gtk_tree_model_iter_parent (clear_data_view->treestore, &parent_iter, &iter);
     if (active) {
       /* When unchecking a child we know the parent should be unchecked too */
-      gtk_tree_store_set (GTK_TREE_STORE (dialog->treestore), &parent_iter,
+      gtk_tree_store_set (GTK_TREE_STORE (clear_data_view->treestore), &parent_iter,
                           ACTIVE_COLUMN, FALSE,
                           -1);
     } else {
@@ -300,15 +306,15 @@ item_toggled_cb (GtkCellRendererToggle *renderer,
       gboolean all_active = TRUE;
 
       /* When checking a child, parent should be checked if all its children are */
-      gtk_tree_model_iter_children (dialog->treestore, &child_iter, &parent_iter);
+      gtk_tree_model_iter_children (clear_data_view->treestore, &child_iter, &parent_iter);
       do {
-        gtk_tree_model_get (dialog->treestore, &child_iter,
+        gtk_tree_model_get (clear_data_view->treestore, &child_iter,
                             ACTIVE_COLUMN, &all_active,
                             -1);
-      } while (all_active && gtk_tree_model_iter_next (dialog->treestore, &child_iter));
+      } while (all_active && gtk_tree_model_iter_next (clear_data_view->treestore, &child_iter));
 
       if (all_active) {
-        gtk_tree_store_set (GTK_TREE_STORE (dialog->treestore), &parent_iter,
+        gtk_tree_store_set (GTK_TREE_STORE (clear_data_view->treestore), &parent_iter,
                             ACTIVE_COLUMN, TRUE,
                             -1);
       }
@@ -319,14 +325,14 @@ item_toggled_cb (GtkCellRendererToggle *renderer,
 }
 
 static gboolean
-update_item_sensitivity (GtkTreeModel    *model,
-                         GtkTreePath     *path,
-                         GtkTreeIter     *iter,
-                         ClearDataDialog *dialog)
+update_item_sensitivity (GtkTreeModel  *model,
+                         GtkTreePath   *path,
+                         GtkTreeIter   *iter,
+                         ClearDataView *clear_data_view)
 {
   if (!gtk_tree_model_iter_has_child (model, iter)) {
     gtk_tree_store_set (GTK_TREE_STORE (model), iter,
-                        SENSITIVE_COLUMN, dialog->timespan == TIMESPAN_FOREVER,
+                        SENSITIVE_COLUMN, clear_data_view->timespan == TIMESPAN_FOREVER,
                         -1);
   }
 
@@ -334,32 +340,32 @@ update_item_sensitivity (GtkTreeModel    *model,
 }
 
 static void
-timespan_combo_changed_cb (GtkComboBox     *combo,
-                           ClearDataDialog *dialog)
+timespan_combo_changed_cb (GtkComboBox   *combo,
+                           ClearDataView *clear_data_view)
 {
   gint active;
   gboolean was_forever;
 
   active = gtk_combo_box_get_active (combo);
-  was_forever = dialog->timespan == TIMESPAN_FOREVER;
-  dialog->timespan = active;
+  was_forever = clear_data_view->timespan == TIMESPAN_FOREVER;
+  clear_data_view->timespan = active;
   if (active == TIMESPAN_FOREVER || was_forever) {
-    gtk_tree_model_foreach (dialog->treestore,
+    gtk_tree_model_foreach (clear_data_view->treestore,
                             (GtkTreeModelForeachFunc)update_item_sensitivity,
-                            dialog);
+                            clear_data_view);
   }
 }
 
 static void
-search_text_changed_cb (ClearDataDialog *dialog)
+search_text_changed_cb (ClearDataView *clear_data_view)
 {
-  gtk_tree_model_filter_refilter (dialog->treemodelfilter);
+  gtk_tree_model_filter_refilter (clear_data_view->treemodelfilter);
 }
 
 static gboolean
-row_visible_func (GtkTreeModel    *model,
-                  GtkTreeIter     *iter,
-                  ClearDataDialog *dialog)
+row_visible_func (GtkTreeModel  *model,
+                  GtkTreeIter   *iter,
+                  ClearDataView *clear_data_view)
 {
   const char *search_text;
   char *name;
@@ -368,7 +374,7 @@ row_visible_func (GtkTreeModel    *model,
   if (gtk_tree_model_iter_has_child (model, iter))
     return TRUE;
 
-  search_text = ephy_data_dialog_get_search_text (EPHY_DATA_DIALOG (dialog));
+  search_text = ephy_data_view_get_search_text (EPHY_DATA_VIEW (clear_data_view));
   if (!search_text || search_text[0] == '\0')
     return TRUE;
 
@@ -385,7 +391,7 @@ row_visible_func (GtkTreeModel    *model,
 
     gtk_tree_model_iter_parent (model, &parent_iter, iter);
     path = gtk_tree_model_get_path (model, &parent_iter);
-    gtk_tree_view_expand_row (GTK_TREE_VIEW (dialog->treeview), path, FALSE);
+    gtk_tree_view_expand_row (GTK_TREE_VIEW (clear_data_view->treeview), path, FALSE);
     gtk_tree_path_free (path);
   }
 
@@ -393,33 +399,33 @@ row_visible_func (GtkTreeModel    *model,
 }
 
 static void
-clear_data_dialog_dispose (GObject *object)
+clear_data_view_dispose (GObject *object)
 {
-  ClearDataDialog *dialog = (ClearDataDialog *)object;
+  ClearDataView *clear_data_view = (ClearDataView *)object;
 
-  g_cancellable_cancel (dialog->cancellable);
-  g_clear_object (&dialog->cancellable);
+  g_cancellable_cancel (clear_data_view->cancellable);
+  g_clear_object (&clear_data_view->cancellable);
 
-  G_OBJECT_CLASS (clear_data_dialog_parent_class)->dispose (object);
+  G_OBJECT_CLASS (clear_data_view_parent_class)->dispose (object);
 }
 
 static void
-clear_data_dialog_class_init (ClearDataDialogClass *klass)
+clear_data_view_class_init (ClearDataViewClass *klass)
 {
   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
-  object_class->dispose = clear_data_dialog_dispose;
+  object_class->dispose = clear_data_view_dispose;
 
   g_type_ensure (WEBKIT_TYPE_WEBSITE_DATA);
 
   gtk_widget_class_set_template_from_resource (widget_class,
-                                               "/org/gnome/epiphany/gtk/clear-data-dialog.ui");
+                                               "/org/gnome/epiphany/gtk/clear-data-view.ui");
 
-  gtk_widget_class_bind_template_child (widget_class, ClearDataDialog, treeview);
-  gtk_widget_class_bind_template_child (widget_class, ClearDataDialog, treestore);
-  gtk_widget_class_bind_template_child (widget_class, ClearDataDialog, treemodelfilter);
-  gtk_widget_class_bind_template_child (widget_class, ClearDataDialog, timespan_combo);
+  gtk_widget_class_bind_template_child (widget_class, ClearDataView, treeview);
+  gtk_widget_class_bind_template_child (widget_class, ClearDataView, treestore);
+  gtk_widget_class_bind_template_child (widget_class, ClearDataView, treemodelfilter);
+  gtk_widget_class_bind_template_child (widget_class, ClearDataView, timespan_combo);
   gtk_widget_class_bind_template_callback (widget_class, item_toggled_cb);
   gtk_widget_class_bind_template_callback (widget_class, timespan_combo_changed_cb);
   gtk_widget_class_bind_template_callback (widget_class, on_clear_all_clicked);
@@ -427,25 +433,25 @@ clear_data_dialog_class_init (ClearDataDialogClass *klass)
 }
 
 static void
-clear_data_dialog_init (ClearDataDialog *dialog)
+clear_data_view_init (ClearDataView *clear_data_view)
 {
-  gtk_widget_init_template (GTK_WIDGET (dialog));
+  gtk_widget_init_template (GTK_WIDGET (clear_data_view));
 
-  gtk_tree_model_filter_set_visible_func (dialog->treemodelfilter,
+  gtk_tree_model_filter_set_visible_func (clear_data_view->treemodelfilter,
                                           (GtkTreeModelFilterVisibleFunc)row_visible_func,
-                                          dialog,
+                                          clear_data_view,
                                           NULL);
 
-  gtk_combo_box_set_active (GTK_COMBO_BOX (dialog->timespan_combo),
-                            dialog->timespan);
+  gtk_combo_box_set_active (GTK_COMBO_BOX (clear_data_view->timespan_combo),
+                            clear_data_view->timespan);
 
-  ephy_data_dialog_set_is_loading (EPHY_DATA_DIALOG (dialog), TRUE);
+  ephy_data_view_set_is_loading (EPHY_DATA_VIEW (clear_data_view), TRUE);
 
-  dialog->cancellable = g_cancellable_new ();
+  clear_data_view->cancellable = g_cancellable_new ();
 
   webkit_website_data_manager_fetch (get_website_data_manger (),
                                      PERSISTENT_DATA_TYPES,
-                                     dialog->cancellable,
+                                     clear_data_view->cancellable,
                                      (GAsyncReadyCallback)website_data_fetched_cb,
-                                     dialog);
+                                     clear_data_view);
 }
diff --git a/src/preferences/clear-data-dialog.h b/src/preferences/clear-data-view.h
similarity index 82%
rename from src/preferences/clear-data-dialog.h
rename to src/preferences/clear-data-view.h
index e38eae12c..348635db8 100644
--- a/src/preferences/clear-data-dialog.h
+++ b/src/preferences/clear-data-view.h
@@ -23,12 +23,12 @@
 #include <glib-object.h>
 #include <gtk/gtk.h>
 
-#include "ephy-data-dialog.h"
+#include "ephy-data-view.h"
 
 G_BEGIN_DECLS
 
-#define EPHY_TYPE_CLEAR_DATA_DIALOG (clear_data_dialog_get_type ())
+#define EPHY_TYPE_CLEAR_DATA_VIEW (clear_data_view_get_type ())
 
-G_DECLARE_FINAL_TYPE (ClearDataDialog, clear_data_dialog, EPHY, CLEAR_DATA_DIALOG, EphyDataDialog)
+G_DECLARE_FINAL_TYPE (ClearDataView, clear_data_view, EPHY, CLEAR_DATA_VIEW, EphyDataView)
 
 G_END_DECLS
diff --git a/src/preferences/cookies-dialog.c b/src/preferences/ephy-cookies-view.c
similarity index 79%
rename from src/preferences/cookies-dialog.c
rename to src/preferences/ephy-cookies-view.c
index 776050b09..080ac2862 100644
--- a/src/preferences/cookies-dialog.c
+++ b/src/preferences/ephy-cookies-view.c
@@ -32,10 +32,10 @@
 #include "ephy-string.h"
 #include "ephy-shell.h"
 
-#include "cookies-dialog.h"
+#include "ephy-cookies-view.h"
 
-struct _EphyCookiesDialog {
-  EphyDataDialog parent_instance;
+struct _EphyCookiesView {
+  EphyDataView parent_instance;
 
   GtkWidget *cookies_listbox;
 
@@ -44,9 +44,9 @@ struct _EphyCookiesDialog {
   WebKitWebsiteDataManager *data_manager;
 };
 
-G_DEFINE_TYPE (EphyCookiesDialog, ephy_cookies_dialog, EPHY_TYPE_DATA_DIALOG)
+G_DEFINE_TYPE (EphyCookiesView, ephy_cookies_view, EPHY_TYPE_DATA_VIEW)
 
-static void populate_model (EphyCookiesDialog *self);
+static void populate_model (EphyCookiesView *self);
 
 static void
 clear_listbox (GtkWidget *listbox)
@@ -62,10 +62,10 @@ clear_listbox (GtkWidget *listbox)
 }
 
 static void
-reload_model (EphyCookiesDialog *self)
+reload_model (EphyCookiesView *self)
 {
   clear_listbox (self->cookies_listbox);
-  ephy_data_dialog_set_has_data (EPHY_DATA_DIALOG (self), FALSE);
+  ephy_data_view_set_has_data (EPHY_DATA_VIEW (self), FALSE);
   populate_model (self);
 }
 
@@ -73,7 +73,7 @@ static void
 forget_clicked (GtkButton *button,
                 gpointer   user_data)
 {
-  EphyCookiesDialog *self = EPHY_COOKIES_DIALOG (user_data);
+  EphyCookiesView *self = EPHY_COOKIES_VIEW (user_data);
   GtkListBoxRow *row = g_object_get_data (G_OBJECT (button), "row");
   GList *data_to_remove = NULL;
   WebKitWebsiteData *data = NULL;
@@ -91,9 +91,9 @@ forget_clicked (GtkButton *button,
 }
 
 static void
-on_search_text_changed (EphyCookiesDialog *self)
+on_search_text_changed (EphyCookiesView *self)
 {
-  ephy_data_dialog_set_has_search_results (EPHY_DATA_DIALOG (self), FALSE);
+  ephy_data_view_set_has_search_results (EPHY_DATA_VIEW (self), FALSE);
   gtk_list_box_invalidate_filter (GTK_LIST_BOX (self->cookies_listbox));
 }
 
@@ -102,29 +102,29 @@ forget_all (GSimpleAction *action,
             GVariant      *parameter,
             gpointer       user_data)
 {
-  EphyCookiesDialog *self = EPHY_COOKIES_DIALOG (user_data);
+  EphyCookiesView *self = EPHY_COOKIES_VIEW (user_data);
 
   webkit_website_data_manager_clear (self->data_manager, WEBKIT_WEBSITE_DATA_COOKIES, 0, NULL, NULL, NULL);
   reload_model (self);
 }
 
 static void
-ephy_cookies_dialog_class_init (EphyCookiesDialogClass *klass)
+ephy_cookies_view_class_init (EphyCookiesViewClass *klass)
 {
   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
 
   g_type_ensure (WEBKIT_TYPE_WEBSITE_DATA);
 
   gtk_widget_class_set_template_from_resource (widget_class,
-                                               "/org/gnome/epiphany/gtk/cookies-dialog.ui");
+                                               "/org/gnome/epiphany/gtk/cookies-view.ui");
 
-  gtk_widget_class_bind_template_child (widget_class, EphyCookiesDialog, cookies_listbox);
+  gtk_widget_class_bind_template_child (widget_class, EphyCookiesView, cookies_listbox);
 
   gtk_widget_class_bind_template_callback (widget_class, on_search_text_changed);
 }
 
 static void
-cookie_add (EphyCookiesDialog *self,
+cookie_add (EphyCookiesView   *self,
             WebKitWebsiteData *data)
 {
   GtkWidget *row;
@@ -152,11 +152,11 @@ cookie_add (EphyCookiesDialog *self,
 static void
 get_domains_with_cookies_cb (WebKitWebsiteDataManager *data_manager,
                              GAsyncResult             *result,
-                             EphyCookiesDialog        *self)
+                             EphyCookiesView          *self)
 {
   GList *data_list;
 
-  ephy_data_dialog_set_is_loading (EPHY_DATA_DIALOG (self), FALSE);
+  ephy_data_view_set_is_loading (EPHY_DATA_VIEW (self), FALSE);
   data_list = webkit_website_data_manager_fetch_finish (data_manager, result, NULL);
   if (!data_list)
     return;
@@ -167,15 +167,15 @@ get_domains_with_cookies_cb (WebKitWebsiteDataManager *data_manager,
   /* The list items have been consumed, so we need only to free the list. */
   g_list_free (data_list);
 
-  ephy_data_dialog_set_has_data (EPHY_DATA_DIALOG (self), TRUE);
+  ephy_data_view_set_has_data (EPHY_DATA_VIEW (self), TRUE);
 }
 
 static void
-populate_model (EphyCookiesDialog *self)
+populate_model (EphyCookiesView *self)
 {
-  g_assert (!ephy_data_dialog_get_has_data (EPHY_DATA_DIALOG (self)));
+  g_assert (!ephy_data_view_get_has_data (EPHY_DATA_VIEW (self)));
 
-  ephy_data_dialog_set_is_loading (EPHY_DATA_DIALOG (self), TRUE);
+  ephy_data_view_set_is_loading (EPHY_DATA_VIEW (self), TRUE);
   webkit_website_data_manager_fetch (self->data_manager,
                                      WEBKIT_WEBSITE_DATA_COOKIES,
                                      NULL,
@@ -184,7 +184,7 @@ populate_model (EphyCookiesDialog *self)
 }
 
 static GActionGroup *
-create_action_group (EphyCookiesDialog *self)
+create_action_group (EphyCookiesView *self)
 {
   const GActionEntry entries[] = {
     { "forget-all", forget_all }
@@ -202,15 +202,15 @@ static gboolean
 filter_func (GtkListBoxRow *row,
              gpointer       user_data)
 {
-  EphyCookiesDialog *self = EPHY_COOKIES_DIALOG (user_data);
-  const gchar *search_text = ephy_data_dialog_get_search_text (EPHY_DATA_DIALOG (self));
+  EphyCookiesView *self = EPHY_COOKIES_VIEW (user_data);
+  const gchar *search_text = ephy_data_view_get_search_text (EPHY_DATA_VIEW (self));
   gboolean result = TRUE;
 
   if (search_text)
     result = !!strstr (hdy_action_row_get_title (HDY_ACTION_ROW (row)), search_text);
 
   if (result)
-    ephy_data_dialog_set_has_search_results (EPHY_DATA_DIALOG (self), TRUE);
+    ephy_data_view_set_has_search_results (EPHY_DATA_VIEW (self), TRUE);
 
   gtk_widget_set_visible (GTK_WIDGET (row), result);
 
@@ -218,7 +218,7 @@ filter_func (GtkListBoxRow *row,
 }
 
 static void
-ephy_cookies_dialog_init (EphyCookiesDialog *self)
+ephy_cookies_view_init (EphyCookiesView *self)
 {
   WebKitWebContext *web_context;
   EphyEmbedShell *shell = ephy_embed_shell_get_default ();
@@ -235,9 +235,3 @@ ephy_cookies_dialog_init (EphyCookiesDialog *self)
 
   gtk_list_box_set_filter_func (GTK_LIST_BOX (self->cookies_listbox), filter_func, self, NULL);
 }
-
-EphyCookiesDialog *
-ephy_cookies_dialog_new (void)
-{
-  return g_object_new (EPHY_TYPE_COOKIES_DIALOG, NULL);
-}
diff --git a/src/preferences/passwords-dialog.h b/src/preferences/ephy-cookies-view.h
similarity index 72%
rename from src/preferences/passwords-dialog.h
rename to src/preferences/ephy-cookies-view.h
index b31ccde87..b3d30a5f8 100644
--- a/src/preferences/passwords-dialog.h
+++ b/src/preferences/ephy-cookies-view.h
@@ -20,14 +20,11 @@
 
 #pragma once
 
-#include "ephy-data-dialog.h"
-#include "ephy-password-manager.h"
+#include "ephy-data-view.h"
 
 G_BEGIN_DECLS
 
-#define EPHY_TYPE_PASSWORDS_DIALOG (ephy_passwords_dialog_get_type ())
-G_DECLARE_FINAL_TYPE (EphyPasswordsDialog, ephy_passwords_dialog, EPHY, PASSWORDS_DIALOG, EphyDataDialog);
-
-EphyPasswordsDialog *ephy_passwords_dialog_new (EphyPasswordManager *manager);
+#define EPHY_TYPE_COOKIES_VIEW (ephy_cookies_view_get_type ())
+G_DECLARE_FINAL_TYPE (EphyCookiesView, ephy_cookies_view, EPHY, COOKIES_VIEW, EphyDataView);
 
 G_END_DECLS
diff --git a/src/preferences/ephy-data-view.c b/src/preferences/ephy-data-view.c
new file mode 100644
index 000000000..a10d8af10
--- /dev/null
+++ b/src/preferences/ephy-data-view.c
@@ -0,0 +1,631 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ *  Copyright © 2019 Purism SPC
+ *
+ *  This file is part of Epiphany.
+ *
+ *  Epiphany is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  Epiphany 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 General Public License
+ *  along with Epiphany.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "ephy-data-view.h"
+
+#include <ctype.h>
+
+typedef struct {
+  GtkWidget *box;
+  GtkWidget *child;
+  GtkWidget *header_bar;
+  GtkWidget *back_button;
+  GtkWidget *clear_all_button;
+  GtkWidget *search_bar;
+  GtkWidget *search_entry;
+  GtkWidget *search_button;
+  GtkWidget *stack;
+  GtkWidget *empty_title_label;
+  GtkWidget *empty_description_label;
+  GtkWidget *spinner;
+
+  gboolean is_loading : 1;
+  gboolean has_data : 1;
+  gboolean has_search_results : 1;
+  gboolean can_clear : 1;
+  char *search_text;
+} EphyDataViewPrivate;
+
+G_DEFINE_TYPE_WITH_PRIVATE (EphyDataView, ephy_data_view, GTK_TYPE_BIN)
+
+enum {
+  PROP_0,
+  PROP_TITLE,
+  PROP_CLEAR_ALL_ACTION_NAME,
+  PROP_CLEAR_ALL_ACTION_TARGET,
+  PROP_CLEAR_ALL_DESCRIPTION,
+  PROP_SEARCH_DESCRIPTION,
+  PROP_EMPTY_TITLE,
+  PROP_EMPTY_DESCRIPTION,
+  PROP_SEARCH_TEXT,
+  PROP_IS_LOADING,
+  PROP_HAS_DATA,
+  PROP_HAS_SEARCH_RESULTS,
+  PROP_CAN_CLEAR,
+  LAST_PROP,
+};
+
+static GParamSpec *obj_properties[LAST_PROP];
+
+enum {
+  BACK_BUTTON_CLICKED,
+  CLEAR_ALL_CLICKED,
+  LAST_SIGNAL,
+};
+
+static gint signals[LAST_SIGNAL] = { 0 };
+
+static void
+update (EphyDataView *self)
+{
+  EphyDataViewPrivate *priv = ephy_data_view_get_instance_private (self);
+  gboolean has_data = priv->has_data && priv->child && gtk_widget_get_visible (priv->child);
+
+  if (priv->is_loading) {
+    gtk_stack_set_visible_child_name (GTK_STACK (priv->stack), "loading");
+    gtk_spinner_start (GTK_SPINNER (priv->spinner));
+  } else {
+    if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->search_button))) {
+      if (has_data && priv->has_search_results)
+        gtk_stack_set_visible_child (GTK_STACK (priv->stack), priv->child);
+      else
+        gtk_stack_set_visible_child_name (GTK_STACK (priv->stack), "no-results");
+    } else {
+      if (has_data)
+        gtk_stack_set_visible_child (GTK_STACK (priv->stack), priv->child);
+      else
+        gtk_stack_set_visible_child_name (GTK_STACK (priv->stack), "empty");
+    }
+    gtk_spinner_stop (GTK_SPINNER (priv->spinner));
+  }
+
+  gtk_widget_set_sensitive (priv->clear_all_button, has_data && priv->can_clear);
+  gtk_widget_set_sensitive (priv->search_button, has_data);
+}
+
+static void
+on_back_button_clicked (GtkWidget    *button,
+                        EphyDataView *self)
+{
+  g_signal_emit (self, signals[BACK_BUTTON_CLICKED], 0);
+}
+
+static void
+on_clear_all_button_clicked (EphyDataView *self)
+{
+  g_signal_emit (self, signals[CLEAR_ALL_CLICKED], 0);
+}
+
+static void
+on_search_entry_changed (GtkSearchEntry *entry,
+                         EphyDataView   *self)
+{
+  EphyDataViewPrivate *priv = ephy_data_view_get_instance_private (self);
+  const char *text;
+
+  text = gtk_entry_get_text (GTK_ENTRY (entry));
+  g_free (priv->search_text);
+  priv->search_text = g_strdup (text);
+
+  g_object_notify_by_pspec (G_OBJECT (self), obj_properties[PROP_SEARCH_TEXT]);
+}
+
+gboolean
+ephy_data_view_handle_event (EphyDataView *self,
+                             GdkEvent     *event)
+{
+  EphyDataViewPrivate *priv = ephy_data_view_get_instance_private (self);
+  GdkEventKey *key = (GdkEventKey *)event;
+  gint result;
+
+  /* Firstly, we check if the HdySearchBar can handle the event */
+  result = hdy_search_bar_handle_event (HDY_SEARCH_BAR (priv->search_bar), event);
+
+  if (result == GDK_EVENT_STOP)
+    return result;
+
+  /* Secondly, we check for the shortcuts implemented by the data views */
+  /* Ctrl + F */
+  if ((key->state & GDK_CONTROL_MASK) && key->keyval == GDK_KEY_f) {
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->search_button), TRUE);
+    return GDK_EVENT_STOP;
+  }
+
+  /* Shift + Delete */
+  if ((key->state & GDK_SHIFT_MASK) && key->keyval == GDK_KEY_Delete) {
+    gtk_button_clicked (GTK_BUTTON (priv->clear_all_button));
+    return GDK_EVENT_STOP;
+  }
+
+  /* Finally, we check for the Escape key */
+  if (key->keyval == GDK_KEY_Escape) {
+    if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->search_button)))
+      /* If the user presses the Escape key and the search bar is hidden,
+       * we want the event to have the same effect as clicking the back button*/
+      gtk_button_clicked (GTK_BUTTON (priv->back_button));
+    else
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->search_button), FALSE);
+
+    return GDK_EVENT_STOP;
+  }
+
+  return GDK_EVENT_PROPAGATE;
+}
+
+static void
+ephy_data_view_set_property (GObject      *object,
+                             guint         prop_id,
+                             const GValue *value,
+                             GParamSpec   *pspec)
+{
+  EphyDataView *self = EPHY_DATA_VIEW (object);
+  EphyDataViewPrivate *priv = ephy_data_view_get_instance_private (self);
+
+  switch (prop_id) {
+    case PROP_TITLE:
+      gtk_header_bar_set_title (GTK_HEADER_BAR (priv->header_bar), g_value_get_string (value));
+      break;
+    case PROP_CLEAR_ALL_ACTION_NAME:
+      gtk_actionable_set_action_name (GTK_ACTIONABLE (priv->clear_all_button), g_value_get_string (value));
+      break;
+    case PROP_CLEAR_ALL_ACTION_TARGET:
+      gtk_actionable_set_action_target_value (GTK_ACTIONABLE (priv->clear_all_button), g_value_get_variant 
(value));
+      break;
+    case PROP_CLEAR_ALL_DESCRIPTION:
+      ephy_data_view_set_clear_all_description (self, g_value_get_string (value));
+      break;
+    case PROP_SEARCH_DESCRIPTION:
+      gtk_entry_set_placeholder_text (GTK_ENTRY (priv->search_entry), g_value_get_string (value));
+      atk_object_set_description (gtk_widget_get_accessible (GTK_WIDGET (self)), g_value_get_string (value));
+      break;
+    case PROP_EMPTY_TITLE:
+      gtk_label_set_text (GTK_LABEL (priv->empty_title_label), g_value_get_string (value));
+      break;
+    case PROP_EMPTY_DESCRIPTION:
+      gtk_label_set_text (GTK_LABEL (priv->empty_description_label), g_value_get_string (value));
+      break;
+    case PROP_IS_LOADING:
+      ephy_data_view_set_is_loading (self, g_value_get_boolean (value));
+      break;
+    case PROP_HAS_DATA:
+      ephy_data_view_set_has_data (self, g_value_get_boolean (value));
+      break;
+    case PROP_HAS_SEARCH_RESULTS:
+      ephy_data_view_set_has_search_results (self, g_value_get_boolean (value));
+      break;
+    case PROP_CAN_CLEAR:
+      ephy_data_view_set_can_clear (self, g_value_get_boolean (value));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+ephy_data_view_get_property (GObject    *object,
+                             guint       prop_id,
+                             GValue     *value,
+                             GParamSpec *pspec)
+{
+  EphyDataView *self = EPHY_DATA_VIEW (object);
+  EphyDataViewPrivate *priv = ephy_data_view_get_instance_private (self);
+
+  switch (prop_id) {
+    case PROP_TITLE:
+      g_value_set_string (value, gtk_header_bar_get_title (GTK_HEADER_BAR (priv->header_bar)));
+      break;
+    case PROP_CLEAR_ALL_ACTION_NAME:
+      g_value_set_string (value, gtk_actionable_get_action_name (GTK_ACTIONABLE (priv->clear_all_button)));
+      break;
+    case PROP_CLEAR_ALL_ACTION_TARGET:
+      g_value_set_variant (value, gtk_actionable_get_action_target_value (GTK_ACTIONABLE 
(priv->clear_all_button)));
+      break;
+    case PROP_CLEAR_ALL_DESCRIPTION:
+      g_value_set_string (value, ephy_data_view_get_clear_all_description (self));
+      break;
+    case PROP_SEARCH_DESCRIPTION:
+      g_value_set_string (value, gtk_entry_get_placeholder_text (GTK_ENTRY (priv->search_entry)));
+      break;
+    case PROP_EMPTY_TITLE:
+      g_value_set_string (value, gtk_label_get_text (GTK_LABEL (priv->empty_title_label)));
+      break;
+    case PROP_EMPTY_DESCRIPTION:
+      g_value_set_string (value, gtk_label_get_text (GTK_LABEL (priv->empty_description_label)));
+      break;
+    case PROP_SEARCH_TEXT:
+      g_value_set_string (value, ephy_data_view_get_search_text (self));
+      break;
+    case PROP_IS_LOADING:
+      g_value_set_boolean (value, ephy_data_view_get_is_loading (self));
+      break;
+    case PROP_HAS_DATA:
+      g_value_set_boolean (value, ephy_data_view_get_has_data (self));
+      break;
+    case PROP_HAS_SEARCH_RESULTS:
+      g_value_set_boolean (value, ephy_data_view_get_has_search_results (self));
+      break;
+    case PROP_CAN_CLEAR:
+      g_value_set_boolean (value, ephy_data_view_get_can_clear (self));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+ephy_data_view_finalize (GObject *object)
+{
+  EphyDataView *self = EPHY_DATA_VIEW (object);
+  EphyDataViewPrivate *priv = ephy_data_view_get_instance_private (self);
+
+  g_free (priv->search_text);
+
+  G_OBJECT_CLASS (ephy_data_view_parent_class)->finalize (object);
+}
+
+static void
+ephy_data_view_add (GtkContainer *container,
+                    GtkWidget    *child)
+{
+  EphyDataView *self = EPHY_DATA_VIEW (container);
+  EphyDataViewPrivate *priv = ephy_data_view_get_instance_private (self);
+
+  if (!priv->box) {
+    GTK_CONTAINER_CLASS (ephy_data_view_parent_class)->add (container, child);
+    return;
+  }
+
+  g_assert (!priv->child);
+
+  priv->child = child;
+  gtk_container_add (GTK_CONTAINER (priv->stack), child);
+
+  update (self);
+}
+
+static void
+ephy_data_view_class_init (EphyDataViewClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+  GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
+
+  object_class->set_property = ephy_data_view_set_property;
+  object_class->get_property = ephy_data_view_get_property;
+  object_class->finalize = ephy_data_view_finalize;
+
+  container_class->add = ephy_data_view_add;
+
+  obj_properties[PROP_TITLE] =
+    g_param_spec_string ("title",
+                         "Title",
+                         "The title used for the top HdyHeaderBar",
+                         NULL,
+                         G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+  obj_properties[PROP_CLEAR_ALL_ACTION_NAME] =
+    g_param_spec_string ("clear-all-action-name",
+                         "'Clear all' action name",
+                         "The name of the action associated to the 'Clear all' button",
+                         NULL,
+                         G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+  obj_properties[PROP_CLEAR_ALL_ACTION_TARGET] =
+    g_param_spec_variant ("clear-all-action-target",
+                          "'Clear all' action target value",
+                          "The parameter for 'Clear all' action invocations",
+                          G_VARIANT_TYPE_ANY, NULL,
+                          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+  obj_properties[PROP_CLEAR_ALL_DESCRIPTION] =
+    g_param_spec_string ("clear-all-description",
+                         "'Clear all' description",
+                         "The description of the 'Clear all' action",
+                         NULL,
+                         G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+  obj_properties[PROP_SEARCH_DESCRIPTION] =
+    g_param_spec_string ("search-description",
+                         "'Search' description",
+                         "The description of the 'Search' action",
+                         NULL,
+                         G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+  obj_properties[PROP_EMPTY_TITLE] =
+    g_param_spec_string ("empty-title",
+                         "'Empty' title",
+                         "The title of the 'Empty' state page",
+                         NULL,
+                         G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+  obj_properties[PROP_EMPTY_DESCRIPTION] =
+    g_param_spec_string ("empty-description",
+                         "'Empty' description",
+                         "The description of the 'Empty' state page",
+                         NULL,
+                         G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+  obj_properties[PROP_SEARCH_TEXT] =
+    g_param_spec_string ("search-text",
+                         "Search text",
+                         "The text of the search entry",
+                         NULL,
+                         G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
+  obj_properties[PROP_IS_LOADING] =
+    g_param_spec_boolean ("is-loading",
+                          "Is loading",
+                          "Whether the dialog is loading its data",
+                          FALSE,
+                          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+  obj_properties[PROP_HAS_DATA] =
+    g_param_spec_boolean ("has-data",
+                          "Has data",
+                          "Whether the dialog has data",
+                          FALSE,
+                          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+  obj_properties[PROP_HAS_SEARCH_RESULTS] =
+    g_param_spec_boolean ("has-search-results",
+                          "Has search results",
+                          "Whether the dialog has search results",
+                          FALSE,
+                          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+  obj_properties[PROP_CAN_CLEAR] =
+    g_param_spec_boolean ("can-clear",
+                          "Can clear",
+                          "Whether the data can be cleared",
+                          FALSE,
+                          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+  g_object_class_install_properties (object_class, LAST_PROP, obj_properties);
+
+  signals[BACK_BUTTON_CLICKED] =
+    g_signal_new ("back-button-clicked",
+                  EPHY_TYPE_DATA_VIEW,
+                  G_SIGNAL_RUN_LAST,
+                  0, NULL, NULL, NULL,
+                  G_TYPE_NONE, 0);
+
+  /**
+   * EphyLocationEntry::user-changed:
+   * @entry: the object on which the signal is emitted
+   *
+   * Emitted when the user changes the contents of the internal #GtkEntry
+   *
+   */
+  signals[CLEAR_ALL_CLICKED] =
+    g_signal_new ("clear-all-clicked",
+                  G_OBJECT_CLASS_TYPE (klass),
+                  G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST,
+                  0, NULL, NULL, NULL,
+                  G_TYPE_NONE,
+                  0,
+                  G_TYPE_NONE);
+
+  gtk_widget_class_set_template_from_resource (widget_class,
+                                               "/org/gnome/epiphany/gtk/data-view.ui");
+
+  gtk_widget_class_bind_template_child_private (widget_class, EphyDataView, box);
+  gtk_widget_class_bind_template_child_private (widget_class, EphyDataView, header_bar);
+  gtk_widget_class_bind_template_child_private (widget_class, EphyDataView, back_button);
+  gtk_widget_class_bind_template_child_private (widget_class, EphyDataView, clear_all_button);
+  gtk_widget_class_bind_template_child_private (widget_class, EphyDataView, empty_title_label);
+  gtk_widget_class_bind_template_child_private (widget_class, EphyDataView, empty_description_label);
+  gtk_widget_class_bind_template_child_private (widget_class, EphyDataView, search_bar);
+  gtk_widget_class_bind_template_child_private (widget_class, EphyDataView, search_button);
+  gtk_widget_class_bind_template_child_private (widget_class, EphyDataView, search_entry);
+  gtk_widget_class_bind_template_child_private (widget_class, EphyDataView, spinner);
+  gtk_widget_class_bind_template_child_private (widget_class, EphyDataView, stack);
+
+  gtk_widget_class_bind_template_callback (widget_class, on_back_button_clicked);
+  gtk_widget_class_bind_template_callback (widget_class, on_clear_all_button_clicked);
+  gtk_widget_class_bind_template_callback (widget_class, on_search_entry_changed);
+}
+
+static void
+ephy_data_view_init (EphyDataView *self)
+{
+  EphyDataViewPrivate *priv = ephy_data_view_get_instance_private (self);
+
+  gtk_widget_init_template (GTK_WIDGET (self));
+
+  hdy_search_bar_connect_entry (HDY_SEARCH_BAR (priv->search_bar), GTK_ENTRY (priv->search_entry));
+
+  update (self);
+}
+
+const gchar *
+ephy_data_view_get_clear_all_description (EphyDataView *self)
+{
+  EphyDataViewPrivate *priv;
+
+  g_assert (EPHY_IS_DATA_VIEW (self));
+
+  priv = ephy_data_view_get_instance_private (self);
+
+  return gtk_widget_get_tooltip_text (GTK_WIDGET (priv->clear_all_button));
+}
+
+void
+ephy_data_view_set_clear_all_description (EphyDataView *self,
+                                          const gchar  *description)
+{
+  EphyDataViewPrivate *priv;
+
+  g_assert (EPHY_IS_DATA_VIEW (self));
+
+  priv = ephy_data_view_get_instance_private (self);
+
+  if (g_strcmp0 (gtk_widget_get_tooltip_text (GTK_WIDGET (priv->clear_all_button)), description) == 0)
+    return;
+
+  gtk_widget_set_tooltip_text (GTK_WIDGET (priv->clear_all_button), description);
+
+  g_object_notify_by_pspec (G_OBJECT (self), obj_properties[PROP_CLEAR_ALL_DESCRIPTION]);
+}
+
+gboolean
+ephy_data_view_get_is_loading (EphyDataView *self)
+{
+  EphyDataViewPrivate *priv;
+
+  g_assert (EPHY_IS_DATA_VIEW (self));
+
+  priv = ephy_data_view_get_instance_private (self);
+
+  return priv->is_loading;
+}
+
+void
+ephy_data_view_set_is_loading (EphyDataView *self,
+                               gboolean      is_loading)
+{
+  EphyDataViewPrivate *priv;
+
+  g_assert (EPHY_IS_DATA_VIEW (self));
+
+  priv = ephy_data_view_get_instance_private (self);
+  is_loading = !!is_loading;
+
+  if (priv->is_loading == is_loading)
+    return;
+
+  priv->is_loading = is_loading;
+
+  update (self);
+
+  g_object_notify_by_pspec (G_OBJECT (self), obj_properties[PROP_IS_LOADING]);
+}
+
+gboolean
+ephy_data_view_get_has_data (EphyDataView *self)
+{
+  EphyDataViewPrivate *priv;
+
+  g_assert (EPHY_IS_DATA_VIEW (self));
+
+  priv = ephy_data_view_get_instance_private (self);
+
+  return priv->has_data;
+}
+
+void
+ephy_data_view_set_has_data (EphyDataView *self,
+                             gboolean      has_data)
+{
+  EphyDataViewPrivate *priv;
+
+  g_assert (EPHY_IS_DATA_VIEW (self));
+
+  priv = ephy_data_view_get_instance_private (self);
+  has_data = !!has_data;
+
+  if (priv->has_data == has_data)
+    return;
+
+  priv->has_data = has_data;
+
+  update (self);
+
+  g_object_notify_by_pspec (G_OBJECT (self), obj_properties[PROP_HAS_DATA]);
+}
+
+gboolean
+ephy_data_view_get_has_search_results (EphyDataView *self)
+{
+  EphyDataViewPrivate *priv;
+
+  g_assert (EPHY_IS_DATA_VIEW (self));
+
+  priv = ephy_data_view_get_instance_private (self);
+
+  return priv->has_search_results;
+}
+
+void
+ephy_data_view_set_has_search_results (EphyDataView *self,
+                                       gboolean      has_search_results)
+{
+  EphyDataViewPrivate *priv;
+
+  g_assert (EPHY_IS_DATA_VIEW (self));
+
+  priv = ephy_data_view_get_instance_private (self);
+  has_search_results = !!has_search_results;
+
+  if (priv->has_search_results == has_search_results)
+    return;
+
+  priv->has_search_results = has_search_results;
+
+  update (self);
+
+  g_object_notify_by_pspec (G_OBJECT (self), obj_properties[PROP_HAS_SEARCH_RESULTS]);
+}
+
+gboolean
+ephy_data_view_get_can_clear (EphyDataView *self)
+{
+  EphyDataViewPrivate *priv;
+
+  g_assert (EPHY_IS_DATA_VIEW (self));
+
+  priv = ephy_data_view_get_instance_private (self);
+
+  return priv->can_clear;
+}
+
+void
+ephy_data_view_set_can_clear (EphyDataView *self,
+                              gboolean      can_clear)
+{
+  EphyDataViewPrivate *priv;
+
+  g_assert (EPHY_IS_DATA_VIEW (self));
+
+  priv = ephy_data_view_get_instance_private (self);
+  can_clear = !!can_clear;
+
+  if (priv->can_clear == can_clear)
+    return;
+
+  priv->can_clear = can_clear;
+
+  update (self);
+
+  g_object_notify_by_pspec (G_OBJECT (self), obj_properties[PROP_CAN_CLEAR]);
+}
+
+const gchar *
+ephy_data_view_get_search_text (EphyDataView *self)
+{
+  EphyDataViewPrivate *priv;
+
+  g_assert (EPHY_IS_DATA_VIEW (self));
+
+  priv = ephy_data_view_get_instance_private (self);
+
+  return priv->search_text;
+}
diff --git a/src/preferences/ephy-data-view.h b/src/preferences/ephy-data-view.h
new file mode 100644
index 000000000..821c4f7d8
--- /dev/null
+++ b/src/preferences/ephy-data-view.h
@@ -0,0 +1,62 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ *  Copyright © 2019 Purism SPC
+ *
+ *  This file is part of Epiphany.
+ *
+ *  Epiphany is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  Epiphany 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 General Public License
+ *  along with Epiphany.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#define HANDY_USE_UNSTABLE_API
+#include <handy.h>
+
+G_BEGIN_DECLS
+
+#define EPHY_TYPE_DATA_VIEW (ephy_data_view_get_type ())
+
+G_DECLARE_DERIVABLE_TYPE (EphyDataView, ephy_data_view, EPHY, DATA_VIEW, GtkBin)
+
+struct _EphyDataViewClass
+{
+  GtkBinClass parent_class;
+};
+
+const gchar *ephy_data_view_get_clear_all_description (EphyDataView *self);
+void         ephy_data_view_set_clear_all_description (EphyDataView *self,
+                                                       const gchar  *description);
+
+gboolean ephy_data_view_get_is_loading (EphyDataView *self);
+void     ephy_data_view_set_is_loading (EphyDataView *self,
+                                        gboolean      is_loading);
+
+gboolean ephy_data_view_get_has_data (EphyDataView *self);
+void     ephy_data_view_set_has_data (EphyDataView *self,
+                                      gboolean      has_data);
+
+gboolean ephy_data_view_get_has_search_results (EphyDataView *self);
+void     ephy_data_view_set_has_search_results (EphyDataView *self,
+                                                gboolean      has_search_results);
+
+gboolean ephy_data_view_get_can_clear (EphyDataView *self);
+void     ephy_data_view_set_can_clear (EphyDataView *self,
+                                       gboolean      can_clear);
+
+const gchar *ephy_data_view_get_search_text (EphyDataView *self);
+
+gboolean ephy_data_view_handle_event (EphyDataView *self,
+                                      GdkEvent     *event);
+
+G_END_DECLS
diff --git a/src/preferences/ephy-prefs-dialog.c b/src/preferences/ephy-prefs-dialog.c
new file mode 100644
index 000000000..e43cac7cb
--- /dev/null
+++ b/src/preferences/ephy-prefs-dialog.c
@@ -0,0 +1,152 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ *  Copyright © 2000-2003 Marco Pesenti Gritti
+ *  Copyright © 2003, 2004, 2005 Christian Persch
+ *  Copyright © 2010, 2017 Igalia S.L.
+ *
+ *  This file is part of Epiphany.
+ *
+ *  Epiphany is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  Epiphany 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 General Public License
+ *  along with Epiphany.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "ephy-data-view.h"
+#include "ephy-embed-utils.h"
+#include "ephy-gui.h"
+#include "ephy-prefs-dialog.h"
+#include "prefs-general-page.h"
+#include "prefs-sync-page.h"
+
+struct _EphyPrefsDialog {
+  HdyWindow parent_instance;
+
+  HdyDeck *deck;
+  GtkWidget *prefs_pages_view;
+  GtkWidget *notebook;
+
+  PrefsGeneralPage *general_page;
+  PrefsSyncPage *sync_page;
+
+  GtkStack *data_views_stack;
+  GtkWidget *active_data_view;
+  GtkWidget *clear_cookies_view;
+  GtkWidget *passwords_view;
+  GtkWidget *clear_data_view;
+};
+
+G_DEFINE_TYPE (EphyPrefsDialog, ephy_prefs_dialog, HDY_TYPE_WINDOW)
+
+static gboolean
+on_key_press_event (EphyPrefsDialog *prefs_dialog,
+                    GdkEvent        *event,
+                    gpointer         user_data)
+{
+  EphyDataView *active_data_view = EPHY_DATA_VIEW (prefs_dialog->active_data_view);
+
+  /* If the user is currently viewing one the data views,
+   * then we want to redirect any key events there */
+  if (active_data_view)
+    return ephy_data_view_handle_event (active_data_view, event);
+
+  return GDK_EVENT_PROPAGATE;
+}
+
+static void
+on_delete_event (EphyPrefsDialog *prefs_dialog)
+{
+  prefs_general_page_on_pd_delete_event (prefs_dialog->general_page);
+  gtk_widget_destroy (GTK_WIDGET (prefs_dialog));
+}
+
+static void
+present_data_view (EphyPrefsDialog *prefs_dialog,
+                   GtkWidget       *presented_view)
+{
+  gtk_stack_set_visible_child (prefs_dialog->data_views_stack, presented_view);
+  hdy_deck_navigate (prefs_dialog->deck, HDY_NAVIGATION_DIRECTION_FORWARD);
+  prefs_dialog->active_data_view = presented_view;
+}
+
+static void
+on_clear_cookies_row_activated (GtkWidget       *privacy_page,
+                                EphyPrefsDialog *prefs_dialog)
+{
+  present_data_view (prefs_dialog, prefs_dialog->clear_cookies_view);
+}
+
+static void
+on_passwords_row_activated (GtkWidget       *privacy_page,
+                            EphyPrefsDialog *prefs_dialog)
+{
+  present_data_view (prefs_dialog, prefs_dialog->passwords_view);
+}
+
+static void
+on_clear_data_row_activated (GtkWidget       *privacy_page,
+                             EphyPrefsDialog *prefs_dialog)
+{
+  present_data_view (prefs_dialog, prefs_dialog->clear_data_view);
+}
+
+static void
+on_any_data_view_back_button_clicked (GtkWidget       *data_view,
+                                      EphyPrefsDialog *prefs_dialog)
+{
+  prefs_dialog->active_data_view = NULL;
+  hdy_deck_navigate (prefs_dialog->deck, HDY_NAVIGATION_DIRECTION_BACK);
+}
+
+static void
+ephy_prefs_dialog_class_init (EphyPrefsDialogClass *klass)
+{
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+  gtk_widget_class_set_template_from_resource (widget_class,
+                                               "/org/gnome/epiphany/gtk/prefs-dialog.ui");
+
+  gtk_widget_class_bind_template_child (widget_class, EphyPrefsDialog, deck);
+  gtk_widget_class_bind_template_child (widget_class, EphyPrefsDialog, prefs_pages_view);
+  gtk_widget_class_bind_template_child (widget_class, EphyPrefsDialog, notebook);
+  gtk_widget_class_bind_template_child (widget_class, EphyPrefsDialog, general_page);
+  gtk_widget_class_bind_template_child (widget_class, EphyPrefsDialog, sync_page);
+  gtk_widget_class_bind_template_child (widget_class, EphyPrefsDialog, data_views_stack);
+  gtk_widget_class_bind_template_child (widget_class, EphyPrefsDialog, clear_cookies_view);
+  gtk_widget_class_bind_template_child (widget_class, EphyPrefsDialog, passwords_view);
+  gtk_widget_class_bind_template_child (widget_class, EphyPrefsDialog, clear_data_view);
+
+  /* Template file callbacks */
+  gtk_widget_class_bind_template_callback (widget_class, on_key_press_event);
+  gtk_widget_class_bind_template_callback (widget_class, on_delete_event);
+  gtk_widget_class_bind_template_callback (widget_class, on_clear_cookies_row_activated);
+  gtk_widget_class_bind_template_callback (widget_class, on_passwords_row_activated);
+  gtk_widget_class_bind_template_callback (widget_class, on_clear_data_row_activated);
+  gtk_widget_class_bind_template_callback (widget_class, on_any_data_view_back_button_clicked);
+}
+
+static void
+ephy_prefs_dialog_init (EphyPrefsDialog *dialog)
+{
+  EphyEmbedShellMode mode = ephy_embed_shell_get_mode (ephy_embed_shell_get_default ());
+
+  gtk_widget_init_template (GTK_WIDGET (dialog));
+  gtk_window_set_icon_name (GTK_WINDOW (dialog), APPLICATION_ID);
+
+  if (mode == EPHY_EMBED_SHELL_MODE_BROWSER)
+    prefs_sync_page_setup (dialog->sync_page);
+  else
+    gtk_notebook_remove_page (GTK_NOTEBOOK (dialog->notebook), -1);
+
+  ephy_gui_ensure_window_group (GTK_WINDOW (dialog));
+}
diff --git a/src/preferences/prefs-dialog.h b/src/preferences/ephy-prefs-dialog.h
similarity index 81%
rename from src/preferences/prefs-dialog.h
rename to src/preferences/ephy-prefs-dialog.h
index fc2e21039..cbca5f596 100644
--- a/src/preferences/prefs-dialog.h
+++ b/src/preferences/ephy-prefs-dialog.h
@@ -21,13 +21,13 @@
 
 #pragma once
 
-#include <glib-object.h>
-#include <gtk/gtk.h>
+#define HANDY_USE_UNSTABLE_API
+#include <handy.h>
 
 G_BEGIN_DECLS
 
-#define EPHY_TYPE_PREFS_DIALOG (prefs_dialog_get_type ())
+#define EPHY_TYPE_PREFS_DIALOG (ephy_prefs_dialog_get_type ())
 
-G_DECLARE_FINAL_TYPE (PrefsDialog, prefs_dialog, EPHY, PREFS_DIALOG, GtkDialog)
+G_DECLARE_FINAL_TYPE (EphyPrefsDialog, ephy_prefs_dialog, EPHY, PREFS_DIALOG, HdyWindow)
 
 G_END_DECLS
diff --git a/src/preferences/passwords-dialog.c b/src/preferences/passwords-view.c
similarity index 65%
rename from src/preferences/passwords-dialog.c
rename to src/preferences/passwords-view.c
index b07ed095a..ef10c4c86 100644
--- a/src/preferences/passwords-dialog.c
+++ b/src/preferences/passwords-view.c
@@ -32,12 +32,13 @@
 #define SECRET_API_SUBJECT_TO_CHANGE
 #include <libsecret/secret.h>
 
+#include "ephy-shell.h"
 #include "ephy-gui.h"
 #include "ephy-uri-helpers.h"
-#include "passwords-dialog.h"
+#include "passwords-view.h"
 
-struct _EphyPasswordsDialog {
-  EphyDataDialog parent_instance;
+struct _EphyPasswordsView {
+  EphyDataView parent_instance;
 
   EphyPasswordManager *manager;
   GList *records;
@@ -47,66 +48,19 @@ struct _EphyPasswordsDialog {
   GActionGroup *action_group;
 };
 
-G_DEFINE_TYPE (EphyPasswordsDialog, ephy_passwords_dialog, EPHY_TYPE_DATA_DIALOG)
+G_DEFINE_TYPE (EphyPasswordsView, ephy_passwords_view, EPHY_TYPE_DATA_VIEW)
 
-enum {
-  PROP_0,
-  PROP_PASSWORD_MANAGER,
-  LAST_PROP
-};
-
-static GParamSpec *obj_properties[LAST_PROP];
-
-static void populate_model (EphyPasswordsDialog *dialog);
-
-static void
-ephy_passwords_dialog_set_property (GObject      *object,
-                                    guint         prop_id,
-                                    const GValue *value,
-                                    GParamSpec   *pspec)
-{
-  EphyPasswordsDialog *dialog = EPHY_PASSWORDS_DIALOG (object);
-
-  switch (prop_id) {
-    case PROP_PASSWORD_MANAGER:
-      if (dialog->manager)
-        g_object_unref (dialog->manager);
-      dialog->manager = g_object_ref (g_value_get_object (value));
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-  }
-}
-
-static void
-ephy_passwords_dialog_get_property (GObject    *object,
-                                    guint       prop_id,
-                                    GValue     *value,
-                                    GParamSpec *pspec)
-{
-  EphyPasswordsDialog *dialog = EPHY_PASSWORDS_DIALOG (object);
-
-  switch (prop_id) {
-    case PROP_PASSWORD_MANAGER:
-      g_value_set_object (value, dialog->manager);
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-  }
-}
+static void populate_model (EphyPasswordsView *passwords_view);
 
 static void
-ephy_passwords_dialog_dispose (GObject *object)
+ephy_passwords_view_dispose (GObject *object)
 {
-  EphyPasswordsDialog *dialog = EPHY_PASSWORDS_DIALOG (object);
-
-  g_clear_object (&dialog->manager);
+  EphyPasswordsView *passwords_view = EPHY_PASSWORDS_VIEW (object);
 
-  g_list_free_full (dialog->records, g_object_unref);
-  dialog->records = NULL;
+  g_list_free_full (passwords_view->records, g_object_unref);
+  passwords_view->records = NULL;
 
-  G_OBJECT_CLASS (ephy_passwords_dialog_parent_class)->dispose (object);
+  G_OBJECT_CLASS (ephy_passwords_view_parent_class)->dispose (object);
 }
 
 static void
@@ -124,9 +78,9 @@ clear_listbox (GtkWidget *listbox)
 }
 
 static void
-on_search_text_changed (EphyPasswordsDialog *dialog)
+on_search_text_changed (EphyPasswordsView *passwords_view)
 {
-  gtk_list_box_invalidate_filter (GTK_LIST_BOX (dialog->listbox));
+  gtk_list_box_invalidate_filter (GTK_LIST_BOX (passwords_view->listbox));
 }
 
 
@@ -135,17 +89,17 @@ forget_clicked (GtkWidget *button,
                 gpointer   user_data)
 {
   EphyPasswordRecord *record = EPHY_PASSWORD_RECORD (user_data);
-  EphyPasswordsDialog *dialog = g_object_get_data (G_OBJECT (record), "dialog");
+  EphyPasswordsView *passwords_view = g_object_get_data (G_OBJECT (record), "passwords-view");
 
-  ephy_password_manager_forget (dialog->manager, ephy_password_record_get_id (record));
-  clear_listbox (dialog->listbox);
+  ephy_password_manager_forget (passwords_view->manager, ephy_password_record_get_id (record));
+  clear_listbox (passwords_view->listbox);
 
-  g_list_free_full (dialog->records, g_object_unref);
-  dialog->records = NULL;
+  g_list_free_full (passwords_view->records, g_object_unref);
+  passwords_view->records = NULL;
 
-  ephy_data_dialog_set_has_data (EPHY_DATA_DIALOG (dialog), FALSE);
+  ephy_data_view_set_has_data (EPHY_DATA_VIEW (passwords_view), FALSE);
 
-  populate_model (dialog);
+  populate_model (passwords_view);
 }
 
 
@@ -170,35 +124,24 @@ copy_username_clicked (GtkWidget *button,
 }
 
 static void
-ephy_passwords_dialog_class_init (EphyPasswordsDialogClass *klass)
+ephy_passwords_view_class_init (EphyPasswordsViewClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
 
-  object_class->set_property = ephy_passwords_dialog_set_property;
-  object_class->get_property = ephy_passwords_dialog_get_property;
-  object_class->dispose = ephy_passwords_dialog_dispose;
-
-  obj_properties[PROP_PASSWORD_MANAGER] =
-    g_param_spec_object ("password-manager",
-                         "Password manager",
-                         "Password Manager",
-                         EPHY_TYPE_PASSWORD_MANAGER,
-                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
-
-  g_object_class_install_properties (object_class, LAST_PROP, obj_properties);
+  object_class->dispose = ephy_passwords_view_dispose;
 
   gtk_widget_class_set_template_from_resource (widget_class,
-                                               "/org/gnome/epiphany/gtk/passwords-dialog.ui");
+                                               "/org/gnome/epiphany/gtk/passwords-view.ui");
 
-  gtk_widget_class_bind_template_child (widget_class, EphyPasswordsDialog, listbox);
+  gtk_widget_class_bind_template_child (widget_class, EphyPasswordsView, listbox);
   gtk_widget_class_bind_template_callback (widget_class, on_search_text_changed);
 }
 
 static void
-confirmation_dialog_response_cb (GtkWidget           *dialog,
-                                 int                  response,
-                                 EphyPasswordsDialog *self)
+confirmation_dialog_response_cb (GtkWidget         *dialog,
+                                 int                response,
+                                 EphyPasswordsView *self)
 {
   gtk_widget_destroy (dialog);
 
@@ -206,7 +149,7 @@ confirmation_dialog_response_cb (GtkWidget           *dialog,
     ephy_password_manager_forget_all (self->manager);
 
     clear_listbox (self->listbox);
-    ephy_data_dialog_set_has_data (EPHY_DATA_DIALOG (self), FALSE);
+    ephy_data_view_set_has_data (EPHY_DATA_VIEW (self), FALSE);
 
     g_list_free_full (self->records, g_object_unref);
     self->records = NULL;
@@ -214,7 +157,7 @@ confirmation_dialog_response_cb (GtkWidget           *dialog,
 }
 
 static GtkWidget *
-confirmation_dialog_construct (EphyPasswordsDialog *self)
+confirmation_dialog_construct (EphyPasswordsView *self)
 {
   GtkWidget *dialog, *button;
 
@@ -248,7 +191,7 @@ forget_all (GSimpleAction *action,
             GVariant      *parameter,
             gpointer       user_data)
 {
-  EphyPasswordsDialog *self = EPHY_PASSWORDS_DIALOG (user_data);
+  EphyPasswordsView *self = EPHY_PASSWORDS_VIEW (user_data);
 
   if (!self->confirmation_dialog) {
     GtkWidget **confirmation_dialog;
@@ -266,9 +209,9 @@ static void
 populate_model_cb (GList    *records,
                    gpointer  user_data)
 {
-  EphyPasswordsDialog *dialog = EPHY_PASSWORDS_DIALOG (user_data);
+  EphyPasswordsView *passwords_view = EPHY_PASSWORDS_VIEW (user_data);
 
-  ephy_data_dialog_set_is_loading (EPHY_DATA_DIALOG (dialog), FALSE);
+  ephy_data_view_set_is_loading (EPHY_DATA_VIEW (passwords_view), FALSE);
 
   for (GList *l = records; l && l->data; l = l->next) {
     EphyPasswordRecord *record = EPHY_PASSWORD_RECORD (l->data);
@@ -364,35 +307,35 @@ populate_model_cb (GList    *records,
     g_signal_connect (button, "clicked", G_CALLBACK (forget_clicked), record);
     gtk_container_add (GTK_CONTAINER (sub_row), button);
 
-    g_object_set_data (G_OBJECT (record), "dialog", dialog);
+    g_object_set_data (G_OBJECT (record), "passwords-view", passwords_view);
 
-    gtk_list_box_insert (GTK_LIST_BOX (dialog->listbox), row, -1);
+    gtk_list_box_insert (GTK_LIST_BOX (passwords_view->listbox), row, -1);
   }
 
   if (g_list_length (records)) {
-    ephy_data_dialog_set_has_data (EPHY_DATA_DIALOG (dialog), TRUE);
-    gtk_widget_show_all (dialog->listbox);
+    ephy_data_view_set_has_data (EPHY_DATA_VIEW (passwords_view), TRUE);
+    gtk_widget_show_all (passwords_view->listbox);
   }
 
-  g_assert (!dialog->records);
-  dialog->records = g_list_copy_deep (records, (GCopyFunc)g_object_ref, NULL);
+  g_assert (!passwords_view->records);
+  passwords_view->records = g_list_copy_deep (records, (GCopyFunc)g_object_ref, NULL);
 }
 
 static void
-populate_model (EphyPasswordsDialog *dialog)
+populate_model (EphyPasswordsView *passwords_view)
 {
-  g_assert (EPHY_IS_PASSWORDS_DIALOG (dialog));
-  g_assert (!ephy_data_dialog_get_has_data (EPHY_DATA_DIALOG (dialog)));
+  g_assert (EPHY_IS_PASSWORDS_VIEW (passwords_view));
+  g_assert (!ephy_data_view_get_has_data (EPHY_DATA_VIEW (passwords_view)));
 
-  ephy_data_dialog_set_is_loading (EPHY_DATA_DIALOG (dialog), TRUE);
+  ephy_data_view_set_is_loading (EPHY_DATA_VIEW (passwords_view), TRUE);
   /* Ask for all password records. */
-  ephy_password_manager_query (dialog->manager,
+  ephy_password_manager_query (passwords_view->manager,
                                NULL, NULL, NULL, NULL, NULL, NULL,
-                               populate_model_cb, dialog);
+                               populate_model_cb, passwords_view);
 }
 
 static GActionGroup *
-create_action_group (EphyPasswordsDialog *dialog)
+create_action_group (EphyPasswordsView *passwords_view)
 {
   const GActionEntry entries[] = {
     { "forget-all", forget_all },
@@ -401,7 +344,7 @@ create_action_group (EphyPasswordsDialog *dialog)
   GSimpleActionGroup *group;
 
   group = g_simple_action_group_new ();
-  g_action_map_add_action_entries (G_ACTION_MAP (group), entries, G_N_ELEMENTS (entries), dialog);
+  g_action_map_add_action_entries (G_ACTION_MAP (group), entries, G_N_ELEMENTS (entries), passwords_view);
 
   return G_ACTION_GROUP (group);
 }
@@ -410,21 +353,21 @@ static void
 show_dialog_cb (GtkWidget *widget,
                 gpointer   user_data)
 {
-  EphyPasswordsDialog *dialog = EPHY_PASSWORDS_DIALOG (widget);
+  EphyPasswordsView *passwords_view = EPHY_PASSWORDS_VIEW (widget);
 
-  populate_model (dialog);
+  populate_model (passwords_view);
 }
 
 static gboolean
 password_filter (GtkListBoxRow *row,
                  gpointer       user_data)
 {
-  EphyPasswordsDialog *dialog = EPHY_PASSWORDS_DIALOG (user_data);
+  EphyPasswordsView *passwords_view = EPHY_PASSWORDS_VIEW (user_data);
   EphyPasswordRecord *record = g_object_get_data (G_OBJECT (row), "record");
   const char *username;
   const char *origin;
   gboolean visible = FALSE;
-  const char *search_text = ephy_data_dialog_get_search_text (EPHY_DATA_DIALOG (dialog));
+  const char *search_text = ephy_data_view_get_search_text (EPHY_DATA_VIEW (passwords_view));
 
   if (search_text == NULL) {
     gtk_widget_show (GTK_WIDGET (row));
@@ -446,23 +389,17 @@ password_filter (GtkListBoxRow *row,
 }
 
 static void
-ephy_passwords_dialog_init (EphyPasswordsDialog *dialog)
+ephy_passwords_view_init (EphyPasswordsView *passwords_view)
 {
-  gtk_widget_init_template (GTK_WIDGET (dialog));
+  passwords_view->manager = ephy_embed_shell_get_password_manager (EPHY_EMBED_SHELL (ephy_shell_get_default 
()));
 
-  dialog->action_group = create_action_group (dialog);
-  gtk_widget_insert_action_group (GTK_WIDGET (dialog), "passwords", dialog->action_group);
+  gtk_widget_init_template (GTK_WIDGET (passwords_view));
 
-  g_signal_connect (GTK_WIDGET (dialog), "show", G_CALLBACK (show_dialog_cb), NULL);
+  passwords_view->action_group = create_action_group (passwords_view);
+  gtk_widget_insert_action_group (GTK_WIDGET (passwords_view), "passwords", passwords_view->action_group);
 
-  gtk_list_box_set_filter_func (GTK_LIST_BOX (dialog->listbox), password_filter, dialog, NULL);
-  gtk_list_box_set_selection_mode (GTK_LIST_BOX (dialog->listbox), GTK_SELECTION_NONE);
-}
+  g_signal_connect (GTK_WIDGET (passwords_view), "show", G_CALLBACK (show_dialog_cb), NULL);
 
-EphyPasswordsDialog *
-ephy_passwords_dialog_new (EphyPasswordManager *manager)
-{
-  return EPHY_PASSWORDS_DIALOG (g_object_new (EPHY_TYPE_PASSWORDS_DIALOG,
-                                              "password-manager", manager,
-                                              NULL));
+  gtk_list_box_set_filter_func (GTK_LIST_BOX (passwords_view->listbox), password_filter, passwords_view, 
NULL);
+  gtk_list_box_set_selection_mode (GTK_LIST_BOX (passwords_view->listbox), GTK_SELECTION_NONE);
 }
diff --git a/src/preferences/cookies-dialog.h b/src/preferences/passwords-view.h
similarity index 77%
rename from src/preferences/cookies-dialog.h
rename to src/preferences/passwords-view.h
index 12194ef5d..a53c4ea6d 100644
--- a/src/preferences/cookies-dialog.h
+++ b/src/preferences/passwords-view.h
@@ -20,13 +20,12 @@
 
 #pragma once
 
-#include "ephy-data-dialog.h"
+#include "ephy-data-view.h"
+#include "ephy-password-manager.h"
 
 G_BEGIN_DECLS
 
-#define EPHY_TYPE_COOKIES_DIALOG (ephy_cookies_dialog_get_type ())
-G_DECLARE_FINAL_TYPE (EphyCookiesDialog, ephy_cookies_dialog, EPHY, COOKIES_DIALOG, EphyDataDialog);
-
-EphyCookiesDialog *ephy_cookies_dialog_new (void);
+#define EPHY_TYPE_PASSWORDS_VIEW (ephy_passwords_view_get_type ())
+G_DECLARE_FINAL_TYPE (EphyPasswordsView, ephy_passwords_view, EPHY, PASSWORDS_VIEW, EphyDataView);
 
 G_END_DECLS
diff --git a/src/preferences/prefs-general-page.c b/src/preferences/prefs-general-page.c
index ab55ab464..855412fbc 100644
--- a/src/preferences/prefs-general-page.c
+++ b/src/preferences/prefs-general-page.c
@@ -894,18 +894,14 @@ on_webapp_entry_changed (GtkEditable      *editable,
   prefs_general_page_save_web_application (dialog);
 }
 
-static void
-prefs_dialog_response_cb (GtkWidget        *widget,
-                          int               response,
-                          PrefsGeneralPage *general_page)
+void
+prefs_general_page_on_pd_delete_event (PrefsGeneralPage *general_page)
 {
   if (general_page->webapp_save_id) {
     g_source_remove (general_page->webapp_save_id);
     general_page->webapp_save_id = 0;
     save_web_application (general_page);
   }
-
-  gtk_widget_destroy (widget);
 }
 
 static void
@@ -1228,13 +1224,6 @@ init_lang_listbox (PrefsGeneralPage *general_page)
   }
 }
 
-void
-prefs_general_page_connect_pd_response (PrefsGeneralPage *general_page,
-                                        PrefsDialog      *pd)
-{
-  g_signal_connect (pd, "response", G_CALLBACK (prefs_dialog_response_cb), general_page);
-}
-
 static void
 setup_general_page (PrefsGeneralPage *general_page)
 {
diff --git a/src/preferences/prefs-general-page.h b/src/preferences/prefs-general-page.h
index 2955cc922..509074145 100644
--- a/src/preferences/prefs-general-page.h
+++ b/src/preferences/prefs-general-page.h
@@ -25,7 +25,7 @@
 #define HANDY_USE_UNSTABLE_API
 #include <handy.h>
 
-#include "prefs-dialog.h"
+#include "ephy-prefs-dialog.h"
 
 G_BEGIN_DECLS
 
@@ -33,7 +33,6 @@ G_BEGIN_DECLS
 
 G_DECLARE_FINAL_TYPE (PrefsGeneralPage, prefs_general_page, EPHY, PREFS_GENERAL_PAGE, HdyPreferencesPage)
 
-void prefs_general_page_connect_pd_response (PrefsGeneralPage *general_page,
-                                             PrefsDialog      *pd);
+void prefs_general_page_on_pd_delete_event (PrefsGeneralPage *general_page);
 
 G_END_DECLS
diff --git a/src/preferences/prefs-privacy-page.c b/src/preferences/prefs-privacy-page.c
index 5b0989c24..997926579 100644
--- a/src/preferences/prefs-privacy-page.c
+++ b/src/preferences/prefs-privacy-page.c
@@ -22,12 +22,17 @@
 
 #include "prefs-privacy-page.h"
 
-#include "cookies-dialog.h"
-#include "clear-data-dialog.h"
-#include "passwords-dialog.h"
 #include "ephy-settings.h"
 #include "ephy-shell.h"
 
+enum {
+  CLEAR_COOKIES_ROW_ACTIVATED,
+  PASSWORDS_ROW_ACTIVATED,
+  CLEAR_DATA_ROW_ACTIVATED,
+
+  LAST_SIGNAL
+};
+
 struct _PrefsPrivacyPage {
   HdyPreferencesPage parent_instance;
 
@@ -43,43 +48,31 @@ struct _PrefsPrivacyPage {
 
   /* Passwords */
   GtkWidget *remember_passwords_switch;
-
-  /* Personal Data */
-  GtkWidget *clear_personal_data_button;
 };
 
+static guint signals[LAST_SIGNAL];
+
 G_DEFINE_TYPE (PrefsPrivacyPage, prefs_privacy_page, HDY_TYPE_PREFERENCES_PAGE)
 
 static void
-on_manage_cookies_button_clicked (GtkWidget        *button,
-                                  PrefsPrivacyPage *privacy_page)
+on_clear_cookies_row_activated (GtkWidget        *row,
+                                PrefsPrivacyPage *privacy_page)
 {
-  EphyCookiesDialog *cookies_dialog;
-  GtkWindow *prefs_dialog;
-
-  cookies_dialog = ephy_cookies_dialog_new ();
-  prefs_dialog = GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (privacy_page)));
-
-  gtk_window_set_transient_for (GTK_WINDOW (cookies_dialog), prefs_dialog);
-  gtk_window_set_modal (GTK_WINDOW (cookies_dialog), TRUE);
-  gtk_window_present_with_time (GTK_WINDOW (cookies_dialog), gtk_get_current_event_time ());
+  g_signal_emit (privacy_page, signals[CLEAR_COOKIES_ROW_ACTIVATED], 0);
 }
 
 static void
-on_manage_passwords_button_clicked (GtkWidget        *button,
-                                    PrefsPrivacyPage *privacy_page)
+on_passwords_row_activated (GtkWidget        *row,
+                            PrefsPrivacyPage *privacy_page)
 {
-  EphyPasswordsDialog *passwords_dialog;
-  EphyPasswordManager *password_manager;
-  GtkWindow *prefs_dialog;
-
-  password_manager = ephy_embed_shell_get_password_manager (EPHY_EMBED_SHELL (ephy_shell_get_default ()));
-  passwords_dialog = ephy_passwords_dialog_new (password_manager);
-  prefs_dialog = GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (privacy_page)));
+  g_signal_emit (privacy_page, signals[PASSWORDS_ROW_ACTIVATED], 0);
+}
 
-  gtk_window_set_transient_for (GTK_WINDOW (passwords_dialog), prefs_dialog);
-  gtk_window_set_modal (GTK_WINDOW (passwords_dialog), TRUE);
-  gtk_window_present_with_time (GTK_WINDOW (passwords_dialog), gtk_get_current_event_time ());
+static void
+on_clear_data_row_activated (GtkWidget        *row,
+                             PrefsPrivacyPage *privacy_page)
+{
+  g_signal_emit (privacy_page, signals[CLEAR_DATA_ROW_ACTIVATED], 0);
 }
 
 static gboolean
@@ -124,21 +117,6 @@ cookies_set_mapping (const GValue       *value,
   return variant;
 }
 
-static void
-clear_personal_data_button_clicked_cb (GtkWidget        *button,
-                                       PrefsPrivacyPage *privacy_page)
-{
-  ClearDataDialog *clear_dialog;
-  GtkWindow *prefs_dialog;
-
-  clear_dialog = g_object_new (EPHY_TYPE_CLEAR_DATA_DIALOG, NULL);
-  prefs_dialog = GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (privacy_page)));
-
-  gtk_window_set_transient_for (GTK_WINDOW (clear_dialog), prefs_dialog);
-  gtk_window_set_modal (GTK_WINDOW (clear_dialog), TRUE);
-  gtk_window_present_with_time (GTK_WINDOW (clear_dialog), gtk_get_current_event_time ());
-}
-
 static void
 setup_privacy_page (PrefsPrivacyPage *privacy_page)
 {
@@ -206,14 +184,6 @@ setup_privacy_page (PrefsPrivacyPage *privacy_page)
                    privacy_page->remember_passwords_switch,
                    "active",
                    G_SETTINGS_BIND_DEFAULT);
-
-  /* ======================================================================== */
-  /* ========================== Personal Data =============================== */
-  /* ======================================================================== */
-  g_signal_connect (privacy_page->clear_personal_data_button,
-                    "clicked",
-                    G_CALLBACK (clear_personal_data_button_clicked_cb),
-                    privacy_page);
 }
 
 static void
@@ -224,6 +194,27 @@ prefs_privacy_page_class_init (PrefsPrivacyPageClass *klass)
   gtk_widget_class_set_template_from_resource (widget_class,
                                                "/org/gnome/epiphany/gtk/prefs-privacy-page.ui");
 
+  signals[CLEAR_COOKIES_ROW_ACTIVATED] =
+    g_signal_new ("clear-cookies-row-activated",
+                  EPHY_TYPE_PREFS_PRIVACY_PAGE,
+                  G_SIGNAL_RUN_LAST,
+                  0, NULL, NULL, NULL,
+                  G_TYPE_NONE, 0);
+
+  signals[PASSWORDS_ROW_ACTIVATED] =
+    g_signal_new ("passwords-row-activated",
+                  EPHY_TYPE_PREFS_PRIVACY_PAGE,
+                  G_SIGNAL_RUN_LAST,
+                  0, NULL, NULL, NULL,
+                  G_TYPE_NONE, 0);
+
+  signals[CLEAR_DATA_ROW_ACTIVATED] =
+    g_signal_new ("clear-data-row-activated",
+                  EPHY_TYPE_PREFS_PRIVACY_PAGE,
+                  G_SIGNAL_RUN_LAST,
+                  0, NULL, NULL, NULL,
+                  G_TYPE_NONE, 0);
+
   /* Web Content */
   gtk_widget_class_bind_template_child (widget_class, PrefsPrivacyPage, popups_allow_switch);
   gtk_widget_class_bind_template_child (widget_class, PrefsPrivacyPage, adblock_allow_switch);
@@ -237,12 +228,10 @@ prefs_privacy_page_class_init (PrefsPrivacyPageClass *klass)
   /* Passwords */
   gtk_widget_class_bind_template_child (widget_class, PrefsPrivacyPage, remember_passwords_switch);
 
-  /* Personal Data */
-  gtk_widget_class_bind_template_child (widget_class, PrefsPrivacyPage, clear_personal_data_button);
-
-  /* Signals */
-  gtk_widget_class_bind_template_callback (widget_class, on_manage_cookies_button_clicked);
-  gtk_widget_class_bind_template_callback (widget_class, on_manage_passwords_button_clicked);
+  /* Template file callbacks */
+  gtk_widget_class_bind_template_callback (widget_class, on_clear_cookies_row_activated);
+  gtk_widget_class_bind_template_callback (widget_class, on_passwords_row_activated);
+  gtk_widget_class_bind_template_callback (widget_class, on_clear_data_row_activated);
 }
 
 static void
diff --git a/src/resources/epiphany.gresource.xml b/src/resources/epiphany.gresource.xml
index 055015b80..e050fbfed 100644
--- a/src/resources/epiphany.gresource.xml
+++ b/src/resources/epiphany.gresource.xml
@@ -18,9 +18,10 @@
     <file preprocess="xml-stripblanks" compressed="true">gtk/bookmark-properties-grid.ui</file>
     <file preprocess="xml-stripblanks" compressed="true">gtk/bookmark-row.ui</file>
     <file preprocess="xml-stripblanks" compressed="true">gtk/bookmarks-popover.ui</file>
-    <file preprocess="xml-stripblanks" compressed="true">gtk/clear-data-dialog.ui</file>
-    <file preprocess="xml-stripblanks" compressed="true">gtk/cookies-dialog.ui</file>
+    <file preprocess="xml-stripblanks" compressed="true">gtk/clear-data-view.ui</file>
+    <file preprocess="xml-stripblanks" compressed="true">gtk/cookies-view.ui</file>
     <file preprocess="xml-stripblanks" compressed="true">gtk/data-dialog.ui</file>
+    <file preprocess="xml-stripblanks" compressed="true">gtk/data-view.ui</file>
     <file preprocess="xml-stripblanks" compressed="true">gtk/encoding-dialog.ui</file>
     <file preprocess="xml-stripblanks" compressed="true">gtk/encoding-row.ui</file>
     <file preprocess="xml-stripblanks" compressed="true">gtk/history-dialog.ui</file>
@@ -30,7 +31,7 @@
     <file preprocess="xml-stripblanks" compressed="true">gtk/pages-button.ui</file>
     <file preprocess="xml-stripblanks" compressed="true">gtk/pages-popover.ui</file>
     <file preprocess="xml-stripblanks" compressed="true">gtk/pages-view.ui</file>
-    <file preprocess="xml-stripblanks" compressed="true">gtk/passwords-dialog.ui</file>
+    <file preprocess="xml-stripblanks" compressed="true">gtk/passwords-view.ui</file>
     <file preprocess="xml-stripblanks" compressed="true">gtk/prefs-appearance-page.ui</file>
     <file preprocess="xml-stripblanks" compressed="true">gtk/prefs-dialog.ui</file>
     <file preprocess="xml-stripblanks" compressed="true">gtk/prefs-general-page.ui</file>
diff --git a/src/resources/gtk/clear-data-dialog.ui b/src/resources/gtk/clear-data-view.ui
similarity index 99%
rename from src/resources/gtk/clear-data-dialog.ui
rename to src/resources/gtk/clear-data-view.ui
index 042830400..064d7260b 100644
--- a/src/resources/gtk/clear-data-dialog.ui
+++ b/src/resources/gtk/clear-data-view.ui
@@ -18,7 +18,7 @@
   <object class="GtkTreeModelFilter" id="treemodelfilter">
     <property name="child_model">treestore</property>
   </object>
-  <template class="ClearDataDialog" parent="EphyDataDialog">
+  <template class="ClearDataView" parent="EphyDataView">
     <property name="title" translatable="yes">Personal Data</property>
     <property name="clear_all_description" translatable="yes">Remove all personal data</property>
     <property name="search_description" translatable="yes">Search personal data</property>
diff --git a/src/resources/gtk/cookies-dialog.ui b/src/resources/gtk/cookies-view.ui
similarity index 96%
rename from src/resources/gtk/cookies-dialog.ui
rename to src/resources/gtk/cookies-view.ui
index 12dc1913a..1d45bcb64 100644
--- a/src/resources/gtk/cookies-dialog.ui
+++ b/src/resources/gtk/cookies-view.ui
@@ -3,7 +3,7 @@
 <interface>
   <requires lib="gtk+" version="3.20"/>
   <requires lib="libhandy" version="0.0"/>
-  <template class="EphyCookiesDialog" parent="EphyDataDialog">
+  <template class="EphyCookiesView" parent="EphyDataView">
     <property name="title" translatable="yes">Cookies</property>
     <property name="clear_all_action_name">cookies.forget-all</property>
     <property name="clear_all_description" translatable="yes">Remove all cookies</property>
diff --git a/src/resources/gtk/data-view.ui b/src/resources/gtk/data-view.ui
new file mode 100644
index 000000000..9cd6653c2
--- /dev/null
+++ b/src/resources/gtk/data-view.ui
@@ -0,0 +1,274 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <requires lib="gtk+" version="3.20"/>
+  <requires lib="libhandy" version="0.0"/>
+  <object class="GtkImage" id="search_image">
+    <property name="visible">True</property>
+    <property name="can_focus">False</property>
+    <property name="icon_name">edit-find-symbolic</property>
+  </object>
+  <object class="GtkImage" id="clear_all_image">
+    <property name="visible">True</property>
+    <property name="can_focus">False</property>
+    <property name="icon_name">user-trash-symbolic</property>
+  </object>
+  <object class="GtkImage" id="back_image">
+    <property name="visible">True</property>
+    <property name="can_focus">False</property>
+    <property name="icon_name">go-previous-symbolic</property>
+  </object>
+  <template class="EphyDataView" parent="GtkBin">
+    <child>
+      <object class="GtkBox" id="box">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="orientation">vertical</property>
+        <child>
+          <object class="HdyWindowHandle">
+            <property name="visible">True</property>
+            <child>
+              <object class="GtkHeaderBar" id="header_bar">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="show_close_button">True</property>
+                <child>
+                  <object class="GtkButton" id="back_button">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="image">back_image</property>
+                    <signal name="clicked" handler="on_back_button_clicked"/>
+                  </object>
+                </child>
+                <child>
+                  <object class="GtkButton" id="clear_all_button">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">True</property>
+                    <property name="image">clear_all_image</property>
+                    <property name="always_show_image">True</property>
+                    <signal name="clicked" handler="on_clear_all_button_clicked" swapped="yes"/>
+                    <style>
+                      <class name="destructive-action"/>
+                      <class name="image-button"/>
+                    </style>
+                  </object>
+                </child>
+                <child>
+                  <object class="GtkToggleButton" id="search_button">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">True</property>
+                    <property name="image">search_image</property>
+                    <property name="always_show_image">True</property>
+                    <property name="active" bind-source="search_bar" bind-property="search-mode-enabled" 
bind-flags="sync-create|bidirectional"/>
+                    <style>
+                      <class name="image-button"/>
+                    </style>
+                    <child internal-child="accessible">
+                      <object class="AtkObject">
+                        <property name="AtkObject::accessible-name" translatable="yes">Search</property>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="pack_type">end</property>
+                  </packing>
+                </child>
+              </object>
+            </child>
+          </object>
+        </child>
+        <child>
+          <object class="HdySearchBar" id="search_bar">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="valign">start</property>
+            <property name="hexpand">True</property>
+            <property name="search_mode_enabled">False</property>
+            <child>
+              <object class="HdyClamp">
+                <property name="visible">True</property>
+                <property name="hexpand">True</property>
+                <child>
+                  <object class="GtkSearchEntry" id="search_entry">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="hexpand">True</property>
+                    <property name="primary_icon_name">edit-find-symbolic</property>
+                    <property name="primary_icon_activatable">False</property>
+                    <property name="primary_icon_sensitive">False</property>
+                    <signal name="search-changed" handler="on_search_entry_changed" swapped="no"/>
+                  </object>
+                </child>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkStack" id="stack">
+            <property name="can_focus">False</property>
+            <property name="expand">True</property>
+            <property name="visible">True</property>
+            <child>
+              <object class="GtkSpinner" id="spinner">
+                <property name="can_focus">False</property>
+                <property name="visible">True</property>
+              </object>
+              <packing>
+                <property name="name">loading</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkScrolledWindow">
+                <property name="can_focus">False</property>
+                <property name="expand">True</property>
+                <property name="hscrollbar_policy">never</property>
+                <property name="visible">True</property>
+                <child>
+                  <object class="GtkBox">
+                    <property name="can_focus">False</property>
+                    <property name="halign">center</property>
+                    <property name="orientation">vertical</property>
+                    <property name="valign">center</property>
+                    <property name="vexpand">True</property>
+                    <property name="visible">True</property>
+                    <child>
+                      <object class="GtkImage">
+                        <property name="can_focus">False</property>
+                        <property name="icon_name">web-browser-symbolic</property>
+                        <property name="icon_size">0</property>
+                        <property name="margin_bottom">18</property>
+                        <property name="pixel_size">128</property>
+                        <property name="valign">center</property>
+                        <property name="visible">True</property>
+                        <style>
+                          <class name="dim-label"/>
+                        </style>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkBox">
+                        <property name="can_focus">False</property>
+                        <property name="margin_end">12</property>
+                        <property name="margin_start">12</property>
+                        <property name="orientation">vertical</property>
+                        <property name="visible">True</property>
+                        <child>
+                          <object class="GtkLabel" id="empty_title_label">
+                            <property name="can_focus">False</property>
+                            <property name="halign">center</property>
+                            <property name="justify">center</property>
+                            <property name="margin_bottom">12</property>
+                            <property name="opacity">0.5</property>
+                            <property name="visible">True</property>
+                            <property name="wrap">True</property>
+                            <attributes>
+                              <attribute name="scale" value="2"/>
+                              <attribute name="weight" value="bold"/>
+                            </attributes>
+                          </object>
+                        </child>
+                        <child>
+                          <object class="GtkLabel" id="empty_description_label">
+                            <property name="can_focus">False</property>
+                            <property name="justify">center</property>
+                            <property name="margin_bottom">6</property>
+                            <property name="opacity">0.5</property>
+                            <property name="use_markup">True</property>
+                            <property name="visible">True</property>
+                            <property name="wrap">True</property>
+                          </object>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+              </object>
+              <packing>
+                <property name="name">empty</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkScrolledWindow">
+                <property name="can_focus">False</property>
+                <property name="expand">True</property>
+                <property name="hscrollbar_policy">never</property>
+                <property name="visible">True</property>
+                <child>
+                  <object class="GtkBox">
+                    <property name="can_focus">False</property>
+                    <property name="halign">center</property>
+                    <property name="orientation">vertical</property>
+                    <property name="valign">center</property>
+                    <property name="vexpand">True</property>
+                    <property name="visible">True</property>
+                    <child>
+                      <object class="GtkImage">
+                        <property name="can_focus">False</property>
+                        <property name="icon_name">edit-find-symbolic</property>
+                        <property name="icon_size">0</property>
+                        <property name="margin_bottom">18</property>
+                        <property name="pixel_size">128</property>
+                        <property name="valign">center</property>
+                        <property name="visible">True</property>
+                        <style>
+                          <class name="dim-label"/>
+                        </style>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkBox">
+                        <property name="can_focus">False</property>
+                        <property name="margin_end">12</property>
+                        <property name="margin_start">12</property>
+                        <property name="orientation">vertical</property>
+                        <property name="visible">True</property>
+                        <child>
+                          <object class="GtkLabel">
+                            <property name="can_focus">False</property>
+                            <property name="halign">center</property>
+                            <property name="justify">center</property>
+                            <property name="label" translatable="yes">No Results Found</property>
+                            <property name="margin_bottom">12</property>
+                            <property name="opacity">0.5</property>
+                            <property name="visible">True</property>
+                            <property name="wrap">True</property>
+                            <attributes>
+                              <attribute name="scale" value="2"/>
+                              <attribute name="weight" value="bold"/>
+                            </attributes>
+                          </object>
+                        </child>
+                        <child>
+                          <object class="GtkLabel">
+                            <property name="can_focus">False</property>
+                            <property name="justify">center</property>
+                            <property name="label" translatable="yes">Try a different search</property>
+                            <property name="margin_bottom">6</property>
+                            <property name="opacity">0.5</property>
+                            <property name="use_markup">True</property>
+                            <property name="visible">True</property>
+                            <property name="wrap">True</property>
+                          </object>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+              </object>
+              <packing>
+                <property name="name">no-results</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">True</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+  </template>
+</interface>
diff --git a/src/resources/gtk/passwords-dialog.ui b/src/resources/gtk/passwords-view.ui
similarity index 98%
rename from src/resources/gtk/passwords-dialog.ui
rename to src/resources/gtk/passwords-view.ui
index a0f3274ef..5ee5d4921 100644
--- a/src/resources/gtk/passwords-dialog.ui
+++ b/src/resources/gtk/passwords-view.ui
@@ -21,7 +21,7 @@
   <object class="GtkTreeModelSort" id="treemodelsort">
     <property name="model">treemodelfilter</property>
   </object>
-  <template class="EphyPasswordsDialog" parent="EphyDataDialog">
+  <template class="EphyPasswordsView" parent="EphyDataView">
     <property name="title" translatable="yes">Passwords</property>
     <property name="clear_all_action_name">passwords.forget-all</property>
     <property name="clear_all_description" translatable="yes">Remove all passwords</property>
diff --git a/src/resources/gtk/prefs-dialog.ui b/src/resources/gtk/prefs-dialog.ui
index 09f50ad2a..4428943b0 100644
--- a/src/resources/gtk/prefs-dialog.ui
+++ b/src/resources/gtk/prefs-dialog.ui
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <interface>
   <requires lib="gtk+" version="3.0"/>
-  <template class="PrefsDialog" parent="GtkDialog">
+  <template class="EphyPrefsDialog" parent="HdyWindow">
     <property name="role">epiphany-preferences</property>
     <property name="modal">True</property>
     <property name="window-position">center</property>
@@ -10,87 +10,121 @@
     <property name="type-hint">dialog</property>
     <property name="default-width">600</property>
     <property name="default-height">800</property>
-    <child internal-child="headerbar">
-      <object class="GtkHeaderBar">
-        <property name="title" translatable="yes">Preferences</property>
-        <property name="show-close-button">True</property>
-      </object>
-    </child>
-    <child internal-child="vbox">
-      <object class="GtkBox">
+    <signal name="key-press-event" handler="on_key_press_event"/>
+    <signal name="delete-event" handler="on_delete_event"/>
+    <child>
+      <object class="HdyDeck" id="deck">
         <property name="visible">True</property>
-        <property name="orientation">vertical</property>
-        <property name="spacing">2</property>
-        <property name="border_width">0</property>
+        <property name="can-swipe-back">True</property>
         <child>
-          <object class="GtkNotebook" id="notebook">
+          <object class="GtkBox" id="prefs_pages_view">
             <property name="visible">True</property>
-            <property name="scrollable">True</property>
-            <property name="show_border">False</property>
+            <property name="orientation">vertical</property>
             <child>
-              <object class="PrefsGeneralPage" id="general_page">
-              </object>
-            </child>
-            <child type="tab">
-              <object class="GtkLabel">
+              <object class="HdyHeaderBar">
                 <property name="visible">True</property>
-                <property name="label" translatable="yes">General</property>
+                <property name="title" translatable="yes">Preferences</property>
+                <property name="show-close-button">True</property>
               </object>
-              <packing>
-                <property name="tab_fill">False</property>
-              </packing>
             </child>
             <child>
-              <object class="PrefsPrivacyPage">
-              </object>
-              <packing>
-                <property name="position">1</property>
-              </packing>
-            </child>
-            <child type="tab">
-              <object class="GtkLabel">
+              <object class="GtkNotebook" id="notebook">
                 <property name="visible">True</property>
-                <property name="label" translatable="yes">Privacy</property>
+                <property name="scrollable">True</property>
+                <property name="show_border">False</property>
+                <child>
+                  <object class="PrefsGeneralPage" id="general_page">
+                  </object>
+                </child>
+                <child type="tab">
+                  <object class="GtkLabel">
+                    <property name="visible">True</property>
+                    <property name="label" translatable="yes">General</property>
+                  </object>
+                  <packing>
+                    <property name="tab_fill">False</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="PrefsPrivacyPage">
+                    <signal name="clear-cookies-row-activated" handler="on_clear_cookies_row_activated"/>
+                    <signal name="passwords-row-activated" handler="on_passwords_row_activated"/>
+                    <signal name="clear-data-row-activated" handler="on_clear_data_row_activated"/>
+                  </object>
+                  <packing>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+                <child type="tab">
+                  <object class="GtkLabel">
+                    <property name="visible">True</property>
+                    <property name="label" translatable="yes">Privacy</property>
+                  </object>
+                  <packing>
+                    <property name="position">1</property>
+                    <property name="tab_fill">False</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="PrefsAppearancePage">
+                  </object>
+                  <packing>
+                    <property name="position">2</property>
+                  </packing>
+                </child>
+                <child type="tab">
+                  <object class="GtkLabel">
+                    <property name="visible">True</property>
+                    <property name="label" translatable="yes">Appearance</property>
+                  </object>
+                  <packing>
+                    <property name="position">2</property>
+                    <property name="tab_fill">False</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="PrefsSyncPage" id="sync_page">
+                  </object>
+                </child>
+                <child type="tab">
+                  <object class="GtkLabel">
+                    <property name="visible">True</property>
+                    <property name="label" translatable="yes">Sync</property>
+                  </object>
+                  <packing>
+                    <property name="tab_fill">False</property>
+                  </packing>
+                </child>
               </object>
               <packing>
-                <property name="position">1</property>
-                <property name="tab_fill">False</property>
+                <property name="expand">True</property>
               </packing>
             </child>
+          </object>
+        </child>
+        <child>
+          <object class="GtkStack" id="data_views_stack">
+            <property name="transition-type">GTK_STACK_TRANSITION_TYPE_NONE</property>
+            <property name="visible">True</property>
             <child>
-              <object class="PrefsAppearancePage">
-              </object>
-              <packing>
-                <property name="position">2</property>
-              </packing>
-            </child>
-            <child type="tab">
-              <object class="GtkLabel">
+              <object class="EphyCookiesView" id="clear_cookies_view">
                 <property name="visible">True</property>
-                <property name="label" translatable="yes">Appearance</property>
+                <signal name="back-button-clicked" handler="on_any_data_view_back_button_clicked"/>
               </object>
-              <packing>
-                <property name="position">2</property>
-                <property name="tab_fill">False</property>
-              </packing>
             </child>
             <child>
-              <object class="PrefsSyncPage" id="sync_page">
+              <object class="EphyPasswordsView" id="passwords_view">
+                <property name="visible">True</property>
+                <signal name="back-button-clicked" handler="on_any_data_view_back_button_clicked"/>
               </object>
             </child>
-            <child type="tab">
-              <object class="GtkLabel">
+            <child>
+              <object class="ClearDataView" id="clear_data_view">
                 <property name="visible">True</property>
-                <property name="label" translatable="yes">Sync</property>
+                <signal name="back-button-clicked" handler="on_any_data_view_back_button_clicked"/>
               </object>
-              <packing>
-                <property name="tab_fill">False</property>
-              </packing>
             </child>
           </object>
-          <packing>
-            <property name="expand">True</property>
-          </packing>
         </child>
       </object>
     </child>
diff --git a/src/resources/gtk/prefs-privacy-page.ui b/src/resources/gtk/prefs-privacy-page.ui
index f7e63a81b..721b57fdb 100644
--- a/src/resources/gtk/prefs-privacy-page.ui
+++ b/src/resources/gtk/prefs-privacy-page.ui
@@ -62,24 +62,15 @@
         <property name="visible">True</property>
         <child>
           <object class="HdyActionRow">
-            <property name="activatable">False</property>
+            <property name="activatable">True</property>
             <property name="title" translatable="yes">Clear _Cookies</property>
             <property name="use_underline">True</property>
             <property name="visible">True</property>
+            <signal name="activated" handler="on_clear_cookies_row_activated"/>
             <child>
-              <object class="GtkButton">
-                <property name="valign">center</property>
+              <object class="GtkImage">
+                <property name="icon_name">go-next-symbolic</property>
                 <property name="visible">True</property>
-                <signal name="clicked" handler="on_manage_cookies_button_clicked"/>
-                <style>
-                  <class name="image-button"/>
-                </style>
-                <child>
-                  <object class="GtkImage">
-                    <property name="icon_name">emblem-system-symbolic</property>
-                    <property name="visible">True</property>
-                  </object>
-                </child>
               </object>
             </child>
           </object>
@@ -137,24 +128,15 @@
         <property name="visible">True</property>
         <child>
           <object class="HdyActionRow">
-            <property name="activatable">False</property>
+            <property name="activatable">True</property>
             <property name="title" translatable="yes">_Passwords</property>
             <property name="use_underline">True</property>
             <property name="visible">True</property>
+            <signal name="activated" handler="on_passwords_row_activated"/>
             <child>
-              <object class="GtkButton">
-                <property name="valign">center</property>
+              <object class="GtkImage">
+                <property name="icon_name">go-next-symbolic</property>
                 <property name="visible">True</property>
-                <signal name="clicked" handler="on_manage_passwords_button_clicked"/>
-                <style>
-                  <class name="image-button"/>
-                </style>
-                <child>
-                  <object class="GtkImage">
-                    <property name="icon_name">emblem-system-symbolic</property>
-                    <property name="visible">True</property>
-                  </object>
-                </child>
               </object>
             </child>
           </object>
@@ -181,24 +163,16 @@
         <property name="visible">True</property>
         <child>
           <object class="HdyActionRow">
-            <property name="activatable">False</property>
+            <property name="activatable">True</property>
             <property name="subtitle" translatable="yes">You can clear stored personal data.</property>
             <property name="title" translatable="yes">Clear Personal _Data</property>
             <property name="use_underline">True</property>
             <property name="visible">True</property>
+            <signal name="activated" handler="on_clear_data_row_activated"/>
             <child>
-              <object class="GtkButton" id="clear_personal_data_button">
-                <property name="valign">center</property>
+              <object class="GtkImage">
+                <property name="icon_name">go-next-symbolic</property>
                 <property name="visible">True</property>
-                <style>
-                  <class name="image-button"/>
-                </style>
-                <child>
-                  <object class="GtkImage">
-                    <property name="icon_name">emblem-system-symbolic</property>
-                    <property name="visible">True</property>
-                  </object>
-                </child>
               </object>
             </child>
           </object>


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]