[gnome-control-center/wip/feborges/new-printers-panel: 2/2] printers: Introduce new printers panel



commit e1e61a8893ae2c9e52331db091853728c800ba10
Author: Felipe Borges <felipeborges gnome org>
Date:   Mon Jan 25 16:05:23 2016 +0100

    printers: Introduce new printers panel
    
    https://wiki.gnome.org/Design/SystemSettings/Printers
    
    FIXME: provide more details in this commit message

 panels/printers/Makefile.am            |    4 +
 panels/printers/cc-printers-panel.c    | 2862 ++++----------------------------
 panels/printers/details-dialog.ui      |  163 ++
 panels/printers/pp-details-dialog.c    |  365 ++++
 panels/printers/pp-details-dialog.h    |   43 +
 panels/printers/pp-printer-entry.c     |  547 ++++++
 panels/printers/pp-printer-entry.h     |   44 +
 panels/printers/printer-entry.ui       |  260 +++
 panels/printers/printers.gresource.xml |    2 +
 panels/printers/printers.ui            |  716 +--------
 10 files changed, 1791 insertions(+), 3215 deletions(-)
---
diff --git a/panels/printers/Makefile.am b/panels/printers/Makefile.am
index 7fb2c17..2240508 100644
--- a/panels/printers/Makefile.am
+++ b/panels/printers/Makefile.am
@@ -41,12 +41,16 @@ libprinters_la_SOURCES =            \
        pp-job.h                        \
        pp-jobs-dialog.c                \
        pp-jobs-dialog.h                \
+       pp-details-dialog.c             \
+       pp-details-dialog.h             \
        pp-authentication-dialog.c      \
        pp-authentication-dialog.h      \
        pp-samba.c                      \
        pp-samba.h                      \
        pp-print-device.c               \
        pp-print-device.h               \
+       pp-printer-entry.c              \
+       pp-printer-entry.h              \
        cc-printers-panel.c             \
        cc-printers-panel.h
 
diff --git a/panels/printers/cc-printers-panel.c b/panels/printers/cc-printers-panel.c
index a09908c..f7a0251 100644
--- a/panels/printers/cc-printers-panel.c
+++ b/panels/printers/cc-printers-panel.c
@@ -31,25 +31,20 @@
 
 #include <math.h>
 
-#include "cc-editable-entry.h"
 #include "pp-new-printer-dialog.h"
 #include "pp-ppd-selection-dialog.h"
-#include "pp-options-dialog.h"
-#include "pp-jobs-dialog.h"
 #include "pp-utils.h"
 #include "pp-maintenance-command.h"
 #include "pp-cups.h"
 #include "pp-job.h"
 
+#include "pp-printer-entry.h"
+
 CC_PANEL_REGISTER (CcPrintersPanel, cc_printers_panel)
 
 #define PRINTERS_PANEL_PRIVATE(o) \
   (G_TYPE_INSTANCE_GET_PRIVATE ((o), CC_TYPE_PRINTERS_PANEL, CcPrintersPanelPrivate))
 
-#define SUPPLY_BAR_HEIGHT 20
-
-#define EMPTY_TEXT "\xe2\x80\x94"
-
 #define RENEW_INTERVAL        500
 #define SUBSCRIPTION_DURATION 600
 
@@ -74,12 +69,7 @@ struct _CcPrintersPanelPrivate
   GtkBuilder *builder;
 
   cups_dest_t *dests;
-  gchar **dest_model_names;
-  gchar **ppd_file_names;
   int num_dests;
-  int current_dest;
-
-  int num_jobs;
 
   GPermission *permission;
 
@@ -87,8 +77,6 @@ struct _CcPrintersPanelPrivate
 
   PpNewPrinterDialog   *pp_new_printer_dialog;
   PpPPDSelectionDialog *pp_ppd_selection_dialog;
-  PpOptionsDialog      *pp_options_dialog;
-  PpJobsDialog         *pp_jobs_dialog;
 
   GDBusProxy      *cups_proxy;
   GDBusConnection *cups_bus_connection;
@@ -97,10 +85,8 @@ struct _CcPrintersPanelPrivate
   guint            cups_status_check_id;
   guint            dbus_subscription_id;
 
-  GtkWidget    *popup_menu;
   GList        *driver_change_list;
   GCancellable *get_ppd_name_cancellable;
-  gboolean      getting_ppd_names;
   PPDList      *all_ppds_list;
   GHashTable   *preferred_drivers;
   GCancellable *get_all_ppds_cancellable;
@@ -121,211 +107,12 @@ typedef struct
   GCancellable *cancellable;
 } SetPPDItem;
 
-static void update_jobs_count (CcPrintersPanel *self);
 static void actualize_printers_list (CcPrintersPanel *self);
 static void update_sensitivity (gpointer user_data);
-static void printer_disable_cb (GObject *gobject, GParamSpec *pspec, gpointer user_data);
-static void printer_set_default_cb (GtkToggleButton *button, gpointer user_data);
 static void detach_from_cups_notifier (gpointer data);
 static void free_dests (CcPrintersPanel *self);
 
 static void
-cc_printers_panel_get_property (GObject    *object,
-                               guint       property_id,
-                               GValue     *value,
-                               GParamSpec *pspec)
-{
-  switch (property_id)
-    {
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
-    }
-}
-
-static void
-cc_printers_panel_set_property (GObject      *object,
-                               guint         property_id,
-                               const GValue *value,
-                               GParamSpec   *pspec)
-{
-  switch (property_id)
-    {
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
-    }
-}
-
-static void
-cc_printers_panel_dispose (GObject *object)
-{
-  CcPrintersPanelPrivate *priv = CC_PRINTERS_PANEL (object)->priv;
-
-  if (priv->pp_new_printer_dialog)
-    g_clear_object (&priv->pp_new_printer_dialog);
-
-  free_dests (CC_PRINTERS_PANEL (object));
-
-  g_clear_pointer (&priv->new_printer_name, g_free);
-  g_clear_pointer (&priv->new_printer_location, g_free);
-  g_clear_pointer (&priv->new_printer_make_and_model, g_free);
-
-  if (priv->builder)
-    {
-      g_object_unref (priv->builder);
-      priv->builder = NULL;
-    }
-
-  if (priv->lockdown_settings)
-    {
-      g_object_unref (priv->lockdown_settings);
-      priv->lockdown_settings = NULL;
-    }
-
-  if (priv->permission)
-    {
-      g_object_unref (priv->permission);
-      priv->permission = NULL;
-    }
-
-  g_cancellable_cancel (priv->subscription_renew_cancellable);
-  g_clear_object (&priv->subscription_renew_cancellable);
-
-  detach_from_cups_notifier (CC_PRINTERS_PANEL (object));
-
-  if (priv->cups_status_check_id > 0)
-    {
-      g_source_remove (priv->cups_status_check_id);
-      priv->cups_status_check_id = 0;
-    }
-
-  if (priv->all_ppds_list)
-    {
-      ppd_list_free (priv->all_ppds_list);
-      priv->all_ppds_list = NULL;
-    }
-
-  if (priv->preferred_drivers)
-    {
-      g_hash_table_unref (priv->preferred_drivers);
-      priv->preferred_drivers = NULL;
-    }
-
-  if (priv->get_all_ppds_cancellable)
-    {
-      g_cancellable_cancel (priv->get_all_ppds_cancellable);
-      g_object_unref (priv->get_all_ppds_cancellable);
-      priv->get_all_ppds_cancellable = NULL;
-    }
-
-  if (priv->driver_change_list)
-    {
-      GList *iter;
-
-      for (iter = priv->driver_change_list; iter; iter = iter->next)
-        {
-          SetPPDItem *item = (SetPPDItem *) iter->data;
-
-          g_cancellable_cancel (item->cancellable);
-          g_object_unref (item->cancellable);
-          g_free (item->printer_name);
-          g_free (item);
-        }
-
-      g_list_free (priv->driver_change_list);
-      priv->driver_change_list = NULL;
-    }
-
-  G_OBJECT_CLASS (cc_printers_panel_parent_class)->dispose (object);
-}
-
-static void
-cc_printers_panel_finalize (GObject *object)
-{
-  G_OBJECT_CLASS (cc_printers_panel_parent_class)->finalize (object);
-}
-
-static GPermission *
-cc_printers_panel_get_permission (CcPanel *panel)
-{
-  CcPrintersPanelPrivate *priv = CC_PRINTERS_PANEL (panel)->priv;
-
-  return priv->permission;
-}
-
-static const char *
-cc_printers_panel_get_help_uri (CcPanel *panel)
-{
-  return "help:gnome-help/printing";
-}
-
-static void
-cc_printers_panel_class_init (CcPrintersPanelClass *klass)
-{
-  GObjectClass *object_class = G_OBJECT_CLASS (klass);
-  CcPanelClass *panel_class = CC_PANEL_CLASS (klass);
-
-  g_type_class_add_private (klass, sizeof (CcPrintersPanelPrivate));
-
-  object_class->get_property = cc_printers_panel_get_property;
-  object_class->set_property = cc_printers_panel_set_property;
-  object_class->dispose = cc_printers_panel_dispose;
-  object_class->finalize = cc_printers_panel_finalize;
-
-  panel_class->get_permission = cc_printers_panel_get_permission;
-  panel_class->get_help_uri = cc_printers_panel_get_help_uri;
-}
-
-static void
-on_get_job_attributes_cb (GObject      *source_object,
-                          GAsyncResult *res,
-                          gpointer      user_data)
-{
-  CcPrintersPanel        *self = (CcPrintersPanel*) user_data;
-  CcPrintersPanelPrivate *priv;
-  const gchar            *job_originating_user_name;
-  const gchar            *job_printer_uri;
-  GVariant               *attributes;
-  GVariant               *username;
-  GVariant               *printer_uri;
-  GError                 *error = NULL;
-
-  priv = PRINTERS_PANEL_PRIVATE (self);
-
-  attributes = pp_job_get_attributes_finish (PP_JOB (source_object), res, &error);
-  g_object_unref (source_object);
-
-  if (attributes != NULL)
-    {
-      if ((username = g_variant_lookup_value (attributes, "job-originating-user-name", G_VARIANT_TYPE 
("as"))) != NULL)
-       {
-         if ((printer_uri = g_variant_lookup_value (attributes, "job-printer-uri", G_VARIANT_TYPE ("as"))) 
!= NULL)
-            {
-              job_originating_user_name = g_variant_get_string (g_variant_get_child_value (username, 0), 
NULL);
-              job_printer_uri = g_variant_get_string (g_variant_get_child_value (printer_uri, 0), NULL);
-
-              if (job_originating_user_name != NULL && job_printer_uri != NULL &&
-                  g_strcmp0 (job_originating_user_name, cupsUser ()) == 0 &&
-                  g_strrstr (job_printer_uri, "/") != 0 &&
-                  priv->current_dest >= 0 &&
-                  priv->current_dest < priv->num_dests &&
-                  priv->dests != NULL &&
-                  g_strcmp0 (g_strrstr (job_printer_uri, "/") + 1,
-                                        priv->dests[priv->current_dest].name) == 0)
-                {
-                  update_jobs_count (self);
-                }
-
-             g_variant_unref (printer_uri);
-            }
-
-         g_variant_unref (username);
-       }
-
-      g_variant_unref (attributes);
-    }
-}
-
-static void
 on_cups_notification (GDBusConnection *connection,
                       const char      *sender_name,
                       const char      *object_path,
@@ -396,12 +183,14 @@ on_cups_notification (GDBusConnection *connection,
   else if (g_strcmp0 (signal_name, "JobCreated") == 0 ||
            g_strcmp0 (signal_name, "JobCompleted") == 0)
     {
-      job = g_object_new (PP_TYPE_JOB, "id", job_id, NULL);
+      // FIXME
+      /*job = g_object_new (PP_TYPE_JOB, "id", job_id, NULL);
       pp_job_get_attributes_async (job,
                                    requested_attrs,
                                    NULL,
                                    on_get_job_attributes_cb,
-                                   self);
+                                   self);*/
+      g_printf("\n");
     }
 }
 
@@ -579,554 +368,189 @@ static void
 free_dests (CcPrintersPanel *self)
 {
   CcPrintersPanelPrivate *priv;
-  gint                    i;
 
   priv = PRINTERS_PANEL_PRIVATE (self);
 
   if (priv->num_dests > 0)
     {
-      for (i = 0; i < priv->num_dests; i++)
-        {
-          g_free (priv->dest_model_names[i]);
-          if (priv->ppd_file_names[i]) {
-            g_unlink (priv->ppd_file_names[i]);
-            g_free (priv->ppd_file_names[i]);
-          }
-        }
-      g_free (priv->dest_model_names);
-      g_free (priv->ppd_file_names);
       cupsFreeDests (priv->num_dests, priv->dests);
     }
   priv->dests = NULL;
   priv->num_dests = 0;
-  priv->current_dest = -1;
-  priv->dest_model_names = NULL;
-  priv->ppd_file_names = NULL;
 }
 
-enum
-{
-  NOTEBOOK_INFO_PAGE = 0,
-  NOTEBOOK_NO_PRINTERS_PAGE,
-  NOTEBOOK_NO_CUPS_PAGE,
-  NOTEBOOK_N_PAGES
-};
-
-enum
-{
-  PRINTER_ID_COLUMN,
-  PRINTER_NAME_COLUMN,
-  PRINTER_PAUSED_COLUMN,
-  PRINTER_DEFAULT_ICON_COLUMN,
-  PRINTER_ICON_COLUMN,
-  PRINTER_N_COLUMNS
-};
-
 static void
-printer_selection_changed_cb (GtkTreeSelection *selection,
-                              gpointer          user_data)
+add_printer_entry (CcPrintersPanel *self,
+                   cups_dest_t      printer)
 {
   CcPrintersPanelPrivate *priv;
-  CcPrintersPanel        *self = (CcPrintersPanel*) user_data;
-  GtkTreeModel           *model;
-  cups_ptype_t            type = 0;
-  GtkTreeIter             iter;
-  GtkWidget              *widget;
-  GtkWidget              *model_button_label;
-  GtkWidget              *model_label;
-  gboolean                is_accepting_jobs = TRUE;
-  GValue                  value = G_VALUE_INIT;
-  gchar                  *printer_make_and_model = NULL;
-  gchar                  *printer_model = NULL;
-  gchar                  *reason = NULL;
-  gchar                 **printer_reasons = NULL;
-  gchar                  *marker_types = NULL;
-  gchar                  *printer_name = NULL;
-  gchar                  *printer_icon = NULL;
-  gchar                  *printer_type = NULL;
-  gchar                  *supply_type = NULL;
-  gchar                  *printer_uri = NULL;
-  gchar                  *location = NULL;
-  gchar                  *status = NULL;
-  gchar                  *device_uri = NULL;
-  gchar                  *printer_hostname = NULL;
-  int                     printer_state = 3;
-  int                     id = -1;
-  int                     i, j;
-  static const char * const reasons[] =
-    {
-      "toner-low",
-      "toner-empty",
-      "developer-low",
-      "developer-empty",
-      "marker-supply-low",
-      "marker-supply-empty",
-      "cover-open",
-      "door-open",
-      "media-low",
-      "media-empty",
-      "offline",
-      "paused",
-      "marker-waste-almost-full",
-      "marker-waste-full",
-      "opc-near-eol",
-      "opc-life-over"
-    };
-  static const char * statuses[] =
-    {
-      /* Translators: The printer is low on toner */
-      N_("Low on toner"),
-      /* Translators: The printer has no toner left */
-      N_("Out of toner"),
-      /* Translators: "Developer" is a chemical for photo development,
-       * http://en.wikipedia.org/wiki/Photographic_developer */
-      N_("Low on developer"),
-      /* Translators: "Developer" is a chemical for photo development,
-       * http://en.wikipedia.org/wiki/Photographic_developer */
-      N_("Out of developer"),
-      /* Translators: "marker" is one color bin of the printer */
-      N_("Low on a marker supply"),
-      /* Translators: "marker" is one color bin of the printer */
-      N_("Out of a marker supply"),
-      /* Translators: One or more covers on the printer are open */
-      N_("Open cover"),
-      /* Translators: One or more doors on the printer are open */
-      N_("Open door"),
-      /* Translators: At least one input tray is low on media */
-      N_("Low on paper"),
-      /* Translators: At least one input tray is empty */
-      N_("Out of paper"),
-      /* Translators: The printer is offline */
-      NC_("printer state", "Offline"),
-      /* Translators: Someone has stopped the Printer */
-      NC_("printer state", "Stopped"),
-      /* Translators: The printer marker supply waste receptacle is almost full */
-      N_("Waste receptacle almost full"),
-      /* Translators: The printer marker supply waste receptacle is full */
-      N_("Waste receptacle full"),
-      /* Translators: Optical photo conductors are used in laser printers */
-      N_("The optical photo conductor is near end of life"),
-      /* Translators: Optical photo conductors are used in laser printers */
-      N_("The optical photo conductor is no longer functioning")
-    };
+  PpPrinterEntry         *printer_entry;
+  GtkWidget              *content;
 
   priv = PRINTERS_PANEL_PRIVATE (self);
 
-  if (gtk_tree_selection_get_selected (selection, &model, &iter))
-    {
-      gtk_tree_model_get (model, &iter,
-                         PRINTER_ID_COLUMN, &id,
-                         PRINTER_NAME_COLUMN, &printer_name,
-                         PRINTER_ICON_COLUMN, &printer_icon,
-                         -1);
-    }
-  else
-    id = -1;
-
-  priv->current_dest = id;
-
-  update_jobs_count (self);
-
-  if (priv->current_dest >= 0 &&
-      priv->current_dest < priv->num_dests &&
-      priv->dests != NULL)
-    {
-      widget = (GtkWidget*)
-        gtk_builder_get_object (priv->builder, "notebook");
-      if (gtk_notebook_get_current_page (GTK_NOTEBOOK (widget)) >= NOTEBOOK_NO_PRINTERS_PAGE)
-        gtk_notebook_set_current_page (GTK_NOTEBOOK (widget), NOTEBOOK_INFO_PAGE);
-
-      for (i = 0; i < priv->dests[id].num_options; i++)
-        {
-          if (g_strcmp0 (priv->dests[priv->current_dest].options[i].name, "printer-location") == 0)
-            location = g_strdup (priv->dests[priv->current_dest].options[i].value);
-          else if (g_strcmp0 (priv->dests[priv->current_dest].options[i].name, "printer-state") == 0)
-            printer_state = atoi (priv->dests[priv->current_dest].options[i].value);
-          else if (g_strcmp0 (priv->dests[priv->current_dest].options[i].name, "printer-state-reasons") == 0)
-            reason = priv->dests[priv->current_dest].options[i].value;
-          else if (g_strcmp0 (priv->dests[priv->current_dest].options[i].name, "marker-types") == 0)
-            marker_types = priv->dests[priv->current_dest].options[i].value;
-          else if (g_strcmp0 (priv->dests[priv->current_dest].options[i].name, "printer-make-and-model") == 
0)
-            printer_make_and_model = priv->dests[priv->current_dest].options[i].value;
-          else if (g_strcmp0 (priv->dests[priv->current_dest].options[i].name, "printer-uri-supported") == 0)
-            printer_uri = priv->dests[priv->current_dest].options[i].value;
-          else if (g_strcmp0 (priv->dests[priv->current_dest].options[i].name, "printer-type") == 0)
-            printer_type = priv->dests[priv->current_dest].options[i].value;
-          else if (g_strcmp0 (priv->dests[priv->current_dest].options[i].name, "device-uri") == 0)
-            device_uri = priv->dests[priv->current_dest].options[i].value;
-          else if (g_strcmp0 (priv->dests[priv->current_dest].options[i].name, "printer-is-accepting-jobs") 
== 0)
-            {
-              if (g_strcmp0 (priv->dests[priv->current_dest].options[i].value, "true") == 0)
-                is_accepting_jobs = TRUE;
-              else
-                is_accepting_jobs = FALSE;
-            }
-        }
-
-      if (priv->ppd_file_names[priv->current_dest] == NULL)
-        priv->ppd_file_names[priv->current_dest] =
-          g_strdup (cupsGetPPD (priv->dests[priv->current_dest].name));
-
-      if (priv->dest_model_names[priv->current_dest] == NULL)
-        priv->dest_model_names[priv->current_dest] =
-          get_ppd_attribute (priv->ppd_file_names[priv->current_dest],
-                             "ModelName");
+  content = (GtkWidget*) gtk_builder_get_object (priv->builder, "content");
 
-      printer_model = g_strdup (priv->dest_model_names[priv->current_dest]);
-
-      if (printer_model == NULL && printer_make_and_model)
-        {
-          gchar *breakpoint = NULL, *tmp = NULL, *tmp2 = NULL;
-          gchar  backup;
-          size_t length = 0;
-          gchar *forbiden[] = {
-              "foomatic",
-              ",",
-              "hpijs",
-              "hpcups",
-              "(recommended)",
-              "postscript (recommended)",
-              NULL };
-
-          tmp = g_ascii_strdown (printer_make_and_model, -1);
-
-          for (i = 0; i < g_strv_length (forbiden); i++)
-            {
-              tmp2 = g_strrstr (tmp, forbiden[i]);
-              if (breakpoint == NULL || 
-                  (tmp2 != NULL && tmp2 < breakpoint))
-                breakpoint = tmp2;
-            }
-
-          if (breakpoint)
-            {
-              backup = *breakpoint;
-              *breakpoint = '\0';
-              length = strlen (tmp);
-              *breakpoint = backup;
-              g_free (tmp);
-
-              if (length > 0)
-                printer_model = g_strndup (printer_make_and_model, length);
-            }
-          else
-            printer_model = g_strdup (printer_make_and_model);
-        }
-
-      if (priv->new_printer_name &&
-          g_strcmp0 (priv->new_printer_name, printer_name) == 0)
-        {
-          /* Translators: Printer's state (printer is being configured right now) */
-          status = g_strdup ( C_("printer state", "Configuring"));
-        }
-
-      /* Find the first of the most severe reasons
-       * and show it in the status field
-       */
-      if (!status &&
-          reason &&
-          !g_str_equal (reason, "none"))
-        {
-          int errors = 0, warnings = 0, reports = 0;
-          int error_index = -1, warning_index = -1, report_index = -1;
-
-          printer_reasons = g_strsplit (reason, ",", -1);
-          for (i = 0; i < g_strv_length (printer_reasons); i++)
-            {
-              for (j = 0; j < G_N_ELEMENTS (reasons); j++)
-                if (strncmp (printer_reasons[i],
-                             reasons[j],
-                             strlen (reasons[j])) == 0)
-                    {
-                      if (g_str_has_suffix (printer_reasons[i], "-report"))
-                        {
-                          if (reports == 0)
-                            report_index = j;
-                          reports++;
-                        }
-                      else if (g_str_has_suffix (printer_reasons[i], "-warning"))
-                        {
-                          if (warnings == 0)
-                            warning_index = j;
-                          warnings++;
-                        }
-                      else
-                        {
-                          if (errors == 0)
-                            error_index = j;
-                          errors++;
-                        }
-                    }
-            }
-          g_strfreev (printer_reasons);
-
-          if (error_index >= 0)
-            status = g_strdup (_(statuses[error_index]));
-          else if (warning_index >= 0)
-            status = g_strdup (_(statuses[warning_index]));
-          else if (report_index >= 0)
-            status = g_strdup (_(statuses[report_index]));
-        }
-
-      if (status == NULL)
-        {
-          switch (printer_state)
-            {
-              case 3:
-                if (is_accepting_jobs)
-                  {
-                    /* Translators: Printer's state (can start new job without waiting) */
-                    status = g_strdup ( C_("printer state", "Ready"));
-                  }
-                else
-                  {
-                    /* Translators: Printer's state (printer is ready but doesn't accept new jobs) */
-                    status = g_strdup ( C_("printer state", "Does not accept jobs"));
-                  }
-                break;
-              case 4:
-                /* Translators: Printer's state (jobs are processing) */
-                status = g_strdup ( C_("printer state", "Processing"));
-                break;
-              case 5:
-                /* Translators: Printer's state (no jobs can be processed) */
-                status = g_strdup ( C_("printer state", "Stopped"));
-                break;
-            }
-        }
-
-      widget = (GtkWidget*)
-        gtk_builder_get_object (priv->builder, "printer-icon");
-      g_value_init (&value, G_TYPE_INT);
-      g_object_get_property ((GObject *) widget, "icon-size", &value);
-
-      if (printer_icon)
-        {
-          gtk_image_set_from_icon_name ((GtkImage *) widget, printer_icon, g_value_get_int (&value));
-          g_free (printer_icon);
-        }
-      else
-        gtk_image_set_from_icon_name ((GtkImage *) widget, "printer", g_value_get_int (&value));
-
-      widget = (GtkWidget*)
-        gtk_builder_get_object (priv->builder, "printer-name-label");
-
-      if (printer_name)
-        {
-          cc_editable_entry_set_text (CC_EDITABLE_ENTRY (widget), printer_name);
-          g_free (printer_name);
-        }
-      else
-        cc_editable_entry_set_text (CC_EDITABLE_ENTRY (widget), EMPTY_TEXT);
-
-
-      widget = (GtkWidget*)
-        gtk_builder_get_object (priv->builder, "printer-status-label");
-
-      if (status)
-        {
-          cc_editable_entry_set_text (CC_EDITABLE_ENTRY (widget), status);
-          g_free (status);
-        }
-      else
-        cc_editable_entry_set_text (CC_EDITABLE_ENTRY (widget), EMPTY_TEXT);
-
-
-      widget = (GtkWidget*)
-        gtk_builder_get_object (priv->builder, "printer-location-label");
-
-      if (location)
-        {
-          cc_editable_entry_set_text (CC_EDITABLE_ENTRY (widget), location);
-          g_free (location);
-        }
-      else
-        cc_editable_entry_set_text (CC_EDITABLE_ENTRY (widget), EMPTY_TEXT);
-
-
-      model_button_label = GTK_WIDGET (gtk_builder_get_object (priv->builder, "printer-model-button-label"));
-
-      model_label = (GtkWidget*)
-        gtk_builder_get_object (priv->builder, "printer-model-label");
-
-      if (printer_model)
-        {
-          gtk_label_set_text (GTK_LABEL (model_button_label), printer_model);
-          gtk_label_set_text (GTK_LABEL (model_label), printer_model);
-          g_free (printer_model);
-        }
-      else
-        {
-          gtk_label_set_text (GTK_LABEL (model_button_label), EMPTY_TEXT);
-          gtk_label_set_text (GTK_LABEL (model_label), EMPTY_TEXT);
-        }
+  printer_entry = pp_printer_entry_new (printer);
 
+  gtk_box_pack_start (GTK_BOX (content), GTK_WIDGET (printer_entry), TRUE, TRUE, 5);
+  gtk_widget_show_all (content);
+}
 
-      widget = (GtkWidget*)
-        gtk_builder_get_object (priv->builder, "printer-ip-address-label");
+static gboolean
+can_add_printer (CcPrintersPanel *self)
+{
+  CcPrintersPanelPrivate *priv;
+  const char             *cups_server = NULL;
+  gboolean local_server = TRUE;
+  gboolean no_cups = FALSE; /* FIXME */
 
-      if (printer_type)
-        type = atoi (printer_type);
+  priv = PRINTERS_PANEL_PRIVATE (self);
 
-      printer_hostname = printer_get_hostname (type, device_uri, printer_uri);
+  cups_server = cupsServer ();
+  if (cups_server &&
+      g_ascii_strncasecmp (cups_server, "localhost", 9) != 0 &&
+      g_ascii_strncasecmp (cups_server, "127.0.0.1", 9) != 0 &&
+      g_ascii_strncasecmp (cups_server, "::1", 3) != 0 &&
+      cups_server[0] != '/')
+    local_server = FALSE;
 
-      if (printer_hostname)
-        {
-          cc_editable_entry_set_text (CC_EDITABLE_ENTRY (widget), printer_hostname);
-          g_free (printer_hostname);
-        }
-      else
-        cc_editable_entry_set_text (CC_EDITABLE_ENTRY (widget), EMPTY_TEXT);
+  return local_server && !no_cups && !priv->new_printer_name;
+}
 
+static void
+update_sensitivity (gpointer user_data)
+{
+  CcPrintersPanelPrivate  *priv;
+  CcPrintersPanel         *self = (CcPrintersPanel*) user_data;
+  GtkWidget               *widget;
 
-      widget = (GtkWidget*)
-        gtk_builder_get_object (priv->builder, "printer-disable-switch");
+  priv = PRINTERS_PANEL_PRIVATE (self);
 
-      g_signal_handlers_block_by_func (G_OBJECT (widget), printer_disable_cb, self);
-      gtk_switch_set_active (GTK_SWITCH (widget), printer_state != 5 && is_accepting_jobs);
-      g_signal_handlers_unblock_by_func (G_OBJECT (widget), printer_disable_cb, self);
+  widget = (GtkWidget*) gtk_builder_get_object (priv->builder, "printer-add-button2");
+  gtk_widget_set_sensitive (widget, can_add_printer (self));
+}
 
+static void
+on_permission_changed (GPermission *permission,
+                       GParamSpec  *pspec,
+                       gpointer     data)
+{
+  update_sensitivity (data);
+}
 
-      widget = (GtkWidget*)
-        gtk_builder_get_object (priv->builder, "printer-default-check-button");
+static void
+on_lockdown_settings_changed (GSettings  *settings,
+                              const char *key,
+                              gpointer    user_data)
+{
+  CcPrintersPanelPrivate  *priv;
+  CcPrintersPanel         *self = (CcPrintersPanel*) user_data;
 
-      g_signal_handlers_block_by_func (G_OBJECT (widget), printer_set_default_cb, self);
-      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), priv->dests[id].is_default);
-      g_signal_handlers_unblock_by_func (G_OBJECT (widget), printer_set_default_cb, self);
+  if (g_str_equal (key, "disable-print-setup") == FALSE)
+    return;
 
+  priv = PRINTERS_PANEL_PRIVATE (self);
 
-      widget = (GtkWidget*)
-        gtk_builder_get_object (priv->builder, "supply-drawing-area");
-      gtk_widget_set_size_request (widget, -1, SUPPLY_BAR_HEIGHT);
-      gtk_widget_queue_draw (widget);
+#if 0
+  /* FIXME */
+  gtk_widget_set_sensitive (priv->lock_button,
+    !g_settings_get_boolean (priv->lockdown_settings, "disable-print-setup"));
+#endif
 
+  on_permission_changed (priv->permission, NULL, user_data);
+}
 
-      widget = (GtkWidget*)
-        gtk_builder_get_object (priv->builder, "supply-label");
+static void
+cups_status_check_cb (GObject      *source_object,
+                      GAsyncResult *result,
+                      gpointer      user_data)
+{
+  CcPrintersPanelPrivate *priv;
+  CcPrintersPanel        *self = (CcPrintersPanel*) user_data;
+  gboolean                success;
+  PpCups                 *cups = PP_CUPS (source_object);
 
-      if (marker_types && g_strrstr (marker_types, "toner") != NULL)
-        /* Translators: Toner supply */
-        supply_type = g_strdup ( _("Toner Level"));
-      else if (marker_types && g_strrstr (marker_types, "ink") != NULL)
-        /* Translators: Ink supply */
-        supply_type = g_strdup ( _("Ink Level"));
-      else
-        /* Translators: By supply we mean ink, toner, staples, water, ... */
-        supply_type = g_strdup ( _("Supply Level"));
+  priv = self->priv;
 
-      if (supply_type)
-        {
-          gtk_label_set_text (GTK_LABEL (widget), supply_type);
-          g_free (supply_type);
-        }
-      else
-        gtk_label_set_text (GTK_LABEL (widget), EMPTY_TEXT);
-    }
-  else
+  success = pp_cups_connection_test_finish (cups, result);
+  if (success)
     {
-      if (id == -1)
-        {
-          if (priv->new_printer_name &&
-              g_strcmp0 (priv->new_printer_name, printer_name) == 0)
-            {
-              /* Translators: Printer's state (printer is being installed right now) */
-              status = g_strdup ( C_("printer state", "Installing"));
-              location = g_strdup (priv->new_printer_location);
-              printer_model = g_strdup (priv->new_printer_make_and_model);
-
-              widget = (GtkWidget*)
-                gtk_builder_get_object (priv->builder, "notebook");
-              if (gtk_notebook_get_current_page (GTK_NOTEBOOK (widget)) >= NOTEBOOK_NO_PRINTERS_PAGE)
-                gtk_notebook_set_current_page (GTK_NOTEBOOK (widget), NOTEBOOK_INFO_PAGE);
-            }
-        }
+      actualize_printers_list (self);
+      attach_to_cups_notifier (self);
 
-      widget = (GtkWidget*)
-        gtk_builder_get_object (priv->builder, "printer-icon");
-      g_value_init (&value, G_TYPE_INT);
-      g_object_get_property ((GObject *) widget, "icon-size", &value);
+      g_source_remove (priv->cups_status_check_id);
+      priv->cups_status_check_id = 0;
+    }
 
-      if (printer_icon)
-        {
-          gtk_image_set_from_icon_name ((GtkImage *) widget, printer_icon, g_value_get_int (&value));
-          g_free (printer_icon);
-        }
-      else
-        gtk_image_set_from_icon_name ((GtkImage *) widget, "printer", g_value_get_int (&value));
+  g_object_unref (cups);
+}
 
-      widget = (GtkWidget*)
-        gtk_builder_get_object (priv->builder, "printer-name-label");
-      if (printer_name)
-        {
-          cc_editable_entry_set_text (CC_EDITABLE_ENTRY (widget), printer_name);
-          g_free (printer_name);
-        }
-      else
-        cc_editable_entry_set_text (CC_EDITABLE_ENTRY (widget), EMPTY_TEXT);
+static gboolean
+cups_status_check (gpointer user_data)
+{
+  CcPrintersPanelPrivate  *priv;
+  CcPrintersPanel         *self = (CcPrintersPanel*) user_data;
+  PpCups                  *cups;
 
-      widget = (GtkWidget*)
-        gtk_builder_get_object (priv->builder, "printer-status-label");
-      if (status)
-        {
-          cc_editable_entry_set_text (CC_EDITABLE_ENTRY (widget), status);
-          g_free (status);
-        }
-      else
-        cc_editable_entry_set_text (CC_EDITABLE_ENTRY (widget), EMPTY_TEXT);
+  priv = self->priv;
 
-      widget = (GtkWidget*)
-        gtk_builder_get_object (priv->builder, "printer-location-label");
+  cups = pp_cups_new ();
+  pp_cups_connection_test_async (cups, cups_status_check_cb, self);
 
-      if (location)
-        {
-          cc_editable_entry_set_text (CC_EDITABLE_ENTRY (widget), location);
-          g_free (location);
-        }
-      else
-        cc_editable_entry_set_text (CC_EDITABLE_ENTRY (widget), EMPTY_TEXT);
+  return priv->cups_status_check_id != 0;
+}
 
+static void
+connection_test_cb (GObject      *source_object,
+                    GAsyncResult *result,
+                    gpointer      user_data)
+{
+  CcPrintersPanelPrivate *priv;
+  CcPrintersPanel        *self = (CcPrintersPanel*) user_data;
+  gboolean                success;
+  PpCups                 *cups = PP_CUPS (source_object);
 
-      model_button_label = GTK_WIDGET (gtk_builder_get_object (priv->builder, "printer-model-button-label"));
+  priv = self->priv;
 
-      model_label = (GtkWidget*)
-        gtk_builder_get_object (priv->builder, "printer-model-label");
+  success = pp_cups_connection_test_finish (cups, result);
+  if (!success)
+    {
+      priv->cups_status_check_id =
+        g_timeout_add_seconds (CUPS_STATUS_CHECK_INTERVAL, cups_status_check, self);
+    }
 
-      if (printer_model)
-        {
-          gtk_label_set_text (GTK_LABEL (model_button_label), printer_model);
-          gtk_label_set_text (GTK_LABEL (model_label), printer_model);
-          g_free (printer_model);
-        }
-      else
-        {
-          gtk_label_set_text (GTK_LABEL (model_button_label), EMPTY_TEXT);
-          gtk_label_set_text (GTK_LABEL (model_label), EMPTY_TEXT);
-        }
+  g_object_unref (cups);
+}
 
-      widget = (GtkWidget*)
-        gtk_builder_get_object (priv->builder, "printer-ip-address-label");
-      cc_editable_entry_set_text (CC_EDITABLE_ENTRY (widget), EMPTY_TEXT);
+static void
+get_all_ppds_async_cb (PPDList  *ppds,
+                       gpointer  user_data)
+{
+  CcPrintersPanelPrivate *priv;
+  CcPrintersPanel        *self = (CcPrintersPanel*) user_data;
 
-      widget = (GtkWidget*)
-        gtk_builder_get_object (priv->builder, "printer-jobs-label");
-      cc_editable_entry_set_text (CC_EDITABLE_ENTRY (widget), EMPTY_TEXT);
+  priv = self->priv = PRINTERS_PANEL_PRIVATE (self);
 
-      widget = (GtkWidget*)
-        gtk_builder_get_object (priv->builder, "printer-disable-switch");
+  priv->all_ppds_list = ppds;
 
-      g_signal_handlers_block_by_func (G_OBJECT (widget), printer_disable_cb, self);
-      gtk_switch_set_active (GTK_SWITCH (widget), FALSE);
-      g_signal_handlers_unblock_by_func (G_OBJECT (widget), printer_disable_cb, self);
+  if (priv->pp_ppd_selection_dialog)
+    pp_ppd_selection_dialog_set_ppd_list (priv->pp_ppd_selection_dialog,
+                                          priv->all_ppds_list);
 
-      widget = (GtkWidget*)
-        gtk_builder_get_object (priv->builder, "printer-default-check-button");
+  if (priv->pp_new_printer_dialog)
+    pp_new_printer_dialog_set_ppd_list (priv->pp_new_printer_dialog,
+                                        priv->all_ppds_list);
 
-      g_signal_handlers_block_by_func (G_OBJECT (widget), printer_set_default_cb, self);
-      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), FALSE);
-      g_signal_handlers_unblock_by_func (G_OBJECT (widget), printer_set_default_cb, self);
-    }
+  g_object_unref (priv->get_all_ppds_cancellable);
+  priv->get_all_ppds_cancellable = NULL;
+}
 
-  update_sensitivity (self);
+static void
+clear_all_printer_entries (GtkWidget       *widget,
+                          GtkWidget       *container)
+{
+  gtk_container_remove (GTK_CONTAINER (container), widget);
 }
 
 static void
@@ -1135,16 +559,15 @@ set_current_page (GObject      *source_object,
                   gpointer      user_data)
 {
   GtkWidget *widget = GTK_WIDGET (user_data);
-  PpCups    *cups = PP_CUPS (source_object);
   gboolean   success;
+  PpCups    *cups = PP_CUPS (source_object);
 
   success = pp_cups_connection_test_finish (cups, result);
   g_object_unref (source_object);
 
   if (success)
-    gtk_notebook_set_current_page (GTK_NOTEBOOK (widget), NOTEBOOK_NO_PRINTERS_PAGE);
-  else
-    gtk_notebook_set_current_page (GTK_NOTEBOOK (widget), NOTEBOOK_NO_CUPS_PAGE);
+    gtk_stack_set_visible_child_name (GTK_STACK (widget), "empty-state");
+  // else FIXME no cups page
 }
 
 static void
@@ -1153,50 +576,13 @@ actualize_printers_list_cb (GObject      *source_object,
                             gpointer      user_data)
 {
   CcPrintersPanelPrivate *priv;
-  GtkTreeSelection       *selection;
   CcPrintersPanel        *self = (CcPrintersPanel*) user_data;
-  GtkListStore           *store;
-  cups_ptype_t            printer_type = 0;
-  GtkTreeModel           *model;
-  GtkTreeIter             selected_iter;
-  GtkTreeView            *treeview;
-  GtkTreeIter             iter;
-  cups_job_t             *jobs = NULL;
   GtkWidget              *widget;
-  gboolean                paused = FALSE;
-  gboolean                selected_iter_set = FALSE;
-  gboolean                valid = FALSE;
   PpCups                 *cups = PP_CUPS (source_object);
   PpCupsDests            *cups_dests;
-  gchar                  *current_printer_name = NULL;
-  gchar                  *printer_icon_name = NULL;
-  gchar                  *default_icon_name = NULL;
-  gchar                  *device_uri = NULL;
-  gint                    new_printer_position = 0;
-  int                     current_dest = -1;
-  int                     i, j;
-  int                     num_jobs = 0;
-
-  priv = PRINTERS_PANEL_PRIVATE (self);
-
-  treeview = (GtkTreeView*)
-    gtk_builder_get_object (priv->builder, "printers-treeview");
-
-  if ((selection = gtk_tree_view_get_selection (treeview)) != NULL &&
-      gtk_tree_selection_get_selected (selection, &model, &iter))
-    {
-      gtk_tree_model_get (model, &iter,
-                         PRINTER_NAME_COLUMN, &current_printer_name,
-                         -1);
-    }
+  int                     i;
 
-  if (priv->new_printer_name &&
-      priv->select_new_printer)
-    {
-      g_free (current_printer_name);
-      current_printer_name = g_strdup (priv->new_printer_name);
-      priv->select_new_printer = FALSE;
-    }
+  priv = self->priv;
 
   free_dests (self);
   cups_dests = pp_cups_get_dests_finish (cups, result, NULL);
@@ -1205,198 +591,21 @@ actualize_printers_list_cb (GObject      *source_object,
   priv->num_dests = cups_dests->num_of_dests;
   g_free (cups_dests);
 
-  priv->dest_model_names = g_new0 (gchar *, priv->num_dests);
-  priv->ppd_file_names = g_new0 (gchar *, priv->num_dests);
-
-  store = gtk_list_store_new (PRINTER_N_COLUMNS,
-                              G_TYPE_INT,
-                              G_TYPE_STRING,
-                              G_TYPE_BOOLEAN,
-                              G_TYPE_STRING,
-                              G_TYPE_STRING);
+  widget = (GtkWidget*)
+    gtk_builder_get_object (priv->builder, "main-vbox");
 
   if (priv->num_dests == 0 && !priv->new_printer_name)
-    {
-      widget = (GtkWidget*)
-        gtk_builder_get_object (priv->builder, "notebook");
-
-      pp_cups_connection_test_async (g_object_ref (cups), set_current_page, widget);
-
-      gtk_widget_set_sensitive (GTK_WIDGET (treeview), FALSE);
-    }
+    pp_cups_connection_test_async (g_object_ref (cups), set_current_page, self);
   else
-    gtk_widget_set_sensitive (GTK_WIDGET (treeview), TRUE);
-
-  g_object_unref (cups);
-
-  for (i = 0; i < priv->num_dests; i++)
-    {
-      gchar *instance;
-
-      if (priv->new_printer_name && new_printer_position >= 0)
-        {
-          gint comparison_result = g_ascii_strcasecmp (priv->dests[i].name, priv->new_printer_name);
-
-          if (comparison_result < 0)
-            new_printer_position = i + 1;
-          else if (comparison_result == 0)
-            new_printer_position = -1;
-        }
-
-      gtk_list_store_append (store, &iter);
-
-      if (priv->dests[i].instance)
-        {
-          instance = g_strdup_printf ("%s / %s", priv->dests[i].name, priv->dests[i].instance);
-        }
-      else
-        {
-          instance = g_strdup (priv->dests[i].name);
-        }
-
-      for (j = 0; j < priv->dests[i].num_options; j++)
-        {
-          if (g_strcmp0 (priv->dests[i].options[j].name, "printer-state") == 0)
-            paused = (g_strcmp0 (priv->dests[i].options[j].value, "5") == 0);
-          else if (g_strcmp0 (priv->dests[i].options[j].name, "device-uri") == 0)
-            device_uri = priv->dests[i].options[j].value;
-          else if (g_strcmp0 (priv->dests[i].options[j].name, "printer-type") == 0)
-            printer_type = atoi (priv->dests[i].options[j].value);
-        }
-
-      if (priv->dests[i].is_default)
-        default_icon_name = g_strdup ("object-select-symbolic");
-      else
-        default_icon_name = NULL;
-
-      if (printer_is_local (printer_type, device_uri))
-        printer_icon_name = g_strdup ("printer");
-      else
-        printer_icon_name = g_strdup ("printer-network");
-
-      gtk_list_store_set (store, &iter,
-                          PRINTER_ID_COLUMN, i,
-                          PRINTER_NAME_COLUMN, instance,
-                          PRINTER_PAUSED_COLUMN, paused,
-                          PRINTER_DEFAULT_ICON_COLUMN, default_icon_name,
-                          PRINTER_ICON_COLUMN, printer_icon_name,
-                          -1);
-
-      if (g_strcmp0 (current_printer_name, instance) == 0)
-        {
-          current_dest = i;
-          selected_iter = iter;
-          selected_iter_set = TRUE;
-        }
+    gtk_stack_set_visible_child_name (GTK_STACK (widget), "printers-list");
 
-      g_free (instance);
-      g_free (printer_icon_name);
-      g_free (default_icon_name);
-    }
-
-  if (priv->new_printer_name && new_printer_position >= 0)
-    {
-      gtk_list_store_insert (store, &iter, new_printer_position);
-      gtk_list_store_set (store, &iter,
-                          PRINTER_ID_COLUMN, -1,
-                          PRINTER_NAME_COLUMN, priv->new_printer_name,
-                          PRINTER_PAUSED_COLUMN, TRUE,
-                          PRINTER_DEFAULT_ICON_COLUMN, NULL,
-                          PRINTER_ICON_COLUMN, priv->new_printer_on_network ?
-                            "printer-network" : "printer",
-                          -1);
-
-      if (g_strcmp0 (current_printer_name, priv->new_printer_name) == 0)
-        {
-          selected_iter = iter;
-          selected_iter_set = TRUE;
-        }
-    }
-
-  g_signal_handlers_block_by_func (
-    G_OBJECT (gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview))),
-    printer_selection_changed_cb,
-    self);
-
-  gtk_tree_view_set_model (treeview, GTK_TREE_MODEL (store));
-
-  g_signal_handlers_unblock_by_func (
-    G_OBJECT (gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview))),
-    printer_selection_changed_cb,
-    self);
-
-  if (selected_iter_set)
-    {
-      priv->current_dest = current_dest;
-      gtk_tree_selection_select_iter (
-        gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)),
-        &selected_iter);
-    }
-  else
-    {
-      num_jobs = cupsGetJobs (&jobs, NULL, 1, CUPS_WHICHJOBS_ALL);
-
-      /* Select last used printer */
-      if (num_jobs > 0)
-        {
-          for (i = 0; i < priv->num_dests; i++)
-            if (g_strcmp0 (priv->dests[i].name, jobs[num_jobs - 1].dest) == 0)
-              {
-                priv->current_dest = i;
-                break;
-              }
-          cupsFreeJobs (num_jobs, jobs);
-        }
-
-      /* Select default printer */
-      if (priv->current_dest < 0)
-        {
-          for (i = 0; i < priv->num_dests; i++)
-            if (priv->dests[i].is_default)
-              {
-                priv->current_dest = i;
-                break;
-              }
-        }
-
-      if (priv->current_dest >= 0)
-        {
-          gint id;
-          valid = gtk_tree_model_get_iter_first ((GtkTreeModel *) store,
-                                                 &selected_iter);
-
-          while (valid)
-            {
-              gtk_tree_model_get ((GtkTreeModel *) store, &selected_iter,
-                                  PRINTER_ID_COLUMN, &id,
-                                  -1);
-              if (id == priv->current_dest)
-                break;
-
-              valid = gtk_tree_model_iter_next ((GtkTreeModel *) store,
-                                                &selected_iter);
-            }
-
-          gtk_tree_selection_select_iter (
-            gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)),
-            &selected_iter);
-        }
-      else if (priv->num_dests > 0)
-        {
-          /* Select first printer */
-          gtk_tree_model_get_iter_first ((GtkTreeModel *) store,
-                                         &selected_iter);
-
-          gtk_tree_selection_select_iter (
-            gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)),
-            &selected_iter);
-        }
-    }
+  widget = (GtkWidget*)
+    gtk_builder_get_object (priv->builder, "content");
 
-  g_free (current_printer_name);
-  g_object_unref (store);
+  gtk_container_foreach (GTK_CONTAINER (widget), (GtkCallback)clear_all_printer_entries, widget);
 
-  update_sensitivity (self);
+  for (i = 0; i < priv->num_dests; i++)
+      add_printer_entry (self, priv->dests[i]);
 }
 
 static void
@@ -1409,429 +618,6 @@ actualize_printers_list (CcPrintersPanel *self)
 }
 
 static void
-set_cell_sensitivity_func (GtkTreeViewColumn *tree_column,
-                           GtkCellRenderer   *cell,
-                           GtkTreeModel      *tree_model,
-                           GtkTreeIter       *iter,
-                           gpointer           func_data)
-{
-  CcPrintersPanelPrivate *priv;
-  CcPrintersPanel        *self = (CcPrintersPanel*) func_data;
-  gboolean                paused = FALSE;
-
-  priv = PRINTERS_PANEL_PRIVATE (self);
-
-  gtk_tree_model_get (tree_model, iter, PRINTER_PAUSED_COLUMN, &paused, -1);
-
-  if (priv->num_dests == 0)
-    g_object_set (G_OBJECT (cell),
-                  "ellipsize", PANGO_ELLIPSIZE_NONE,
-                  "width-chars", -1,
-                  NULL);
-  else
-    g_object_set (G_OBJECT (cell),
-                  "ellipsize", PANGO_ELLIPSIZE_END,
-                  "width-chars", 18,
-                  NULL);
-
-  g_object_set (cell, "sensitive", !paused, NULL);
-}
-
-static void
-set_pixbuf_cell_sensitivity_func (GtkTreeViewColumn *tree_column,
-                                  GtkCellRenderer   *cell,
-                                  GtkTreeModel      *tree_model,
-                                  GtkTreeIter       *iter,
-                                  gpointer           func_data)
-{
-  gboolean paused = FALSE;
-
-  gtk_tree_model_get (tree_model, iter, PRINTER_PAUSED_COLUMN, &paused, -1);
-  g_object_set (cell, "sensitive", !paused, NULL);
-}
-
-static void
-populate_printers_list (CcPrintersPanel *self)
-{
-  CcPrintersPanelPrivate *priv;
-  GtkTreeViewColumn      *column;
-  GtkCellRenderer        *icon_renderer;
-  GtkCellRenderer        *icon_renderer2;
-  GtkCellRenderer        *renderer;
-  GtkWidget              *treeview;
-  int                     icon_width;
-
-  priv = PRINTERS_PANEL_PRIVATE (self);
-
-  treeview = (GtkWidget*)
-    gtk_builder_get_object (priv->builder, "printers-treeview");
-
-  g_signal_connect (gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)),
-                    "changed", G_CALLBACK (printer_selection_changed_cb), self);
-
-  actualize_printers_list (self);
-
-
-  icon_renderer = gtk_cell_renderer_pixbuf_new ();
-  g_object_set (icon_renderer, "stock-size", GTK_ICON_SIZE_LARGE_TOOLBAR, NULL);
-  gtk_cell_renderer_set_padding (icon_renderer, 4, 4);
-  column = gtk_tree_view_column_new_with_attributes ("Icon", icon_renderer,
-                                                     "icon-name", PRINTER_ICON_COLUMN, NULL);
-  gtk_tree_view_column_set_cell_data_func (column, icon_renderer, set_pixbuf_cell_sensitivity_func,
-                                           self, NULL);
-  gtk_tree_view_column_set_expand (column, FALSE);
-  gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
-
-
-  renderer = gtk_cell_renderer_text_new ();
-  g_object_set (G_OBJECT (renderer),
-                "ellipsize", PANGO_ELLIPSIZE_MIDDLE,
-                "max-width-chars", 18, NULL);
-  column = gtk_tree_view_column_new_with_attributes ("Printer", renderer,
-                                                     "text", PRINTER_NAME_COLUMN, NULL);
-  gtk_tree_view_column_set_cell_data_func (column, renderer, set_cell_sensitivity_func,
-                                           self, NULL);
-  gtk_tree_view_column_set_expand (column, FALSE);
-  gtk_tree_view_column_set_min_width (column, 120);
-  gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
-
-
-  icon_renderer2 = gtk_cell_renderer_pixbuf_new ();
-  g_object_set (G_OBJECT (icon_renderer2), "follow-state", TRUE, NULL);
-  column = gtk_tree_view_column_new_with_attributes ("Default", icon_renderer2,
-                                                     "icon-name", PRINTER_DEFAULT_ICON_COLUMN, NULL);
-  gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &icon_width, NULL);
-  gtk_cell_renderer_set_fixed_size (icon_renderer2, icon_width, -1);
-  gtk_tree_view_column_set_expand (column, FALSE);
-  gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
-}
-
-enum
-{
-  JOB_ID_COLUMN,
-  JOB_TITLE_COLUMN,
-  JOB_STATE_COLUMN,
-  JOB_CREATION_TIME_COLUMN,
-  JOB_N_COLUMNS
-};
-
-static void
-update_jobs_count (CcPrintersPanel *self)
-{
-  CcPrintersPanelPrivate *priv;
-  cups_job_t             *jobs;
-  GtkWidget              *widget;
-  gchar                  *active_jobs = NULL;
-  gint                    num_jobs;
-
-  priv = PRINTERS_PANEL_PRIVATE (self);
-
-  priv->num_jobs = -1;
-
-  if (priv->current_dest >= 0 &&
-      priv->current_dest < priv->num_dests &&
-      priv->dests != NULL)
-    {
-      priv->num_jobs = cupsGetJobs (&jobs, priv->dests[priv->current_dest].name, 1, CUPS_WHICHJOBS_ACTIVE);
-      if (priv->num_jobs > 0)
-        cupsFreeJobs (priv->num_jobs, jobs);
-
-      num_jobs = priv->num_jobs < 0 ? 0 : (guint) priv->num_jobs;
-      /* Translators: there is n active print jobs on this printer */
-      active_jobs = g_strdup_printf (ngettext ("%u active", "%u active", num_jobs), num_jobs);
-    }
-
-  widget = (GtkWidget*)
-    gtk_builder_get_object (priv->builder, "printer-jobs-label");
-
-  if (active_jobs)
-    {
-      cc_editable_entry_set_text (CC_EDITABLE_ENTRY (widget), active_jobs);
-      g_free (active_jobs);
-    }
-  else
-    cc_editable_entry_set_text (CC_EDITABLE_ENTRY (widget), EMPTY_TEXT);
-
-  if (priv->pp_jobs_dialog)
-    {
-      pp_jobs_dialog_update (priv->pp_jobs_dialog);
-    }
-}
-
-static void
-printer_disable_cb (GObject    *gobject,
-                    GParamSpec *pspec,
-                    gpointer    user_data)
-{
-  CcPrintersPanelPrivate *priv;
-  CcPrintersPanel        *self = (CcPrintersPanel*) user_data;
-  gboolean                paused = FALSE;
-  gboolean                is_accepting_jobs = TRUE;
-  char                   *name = NULL;
-  int                     i;
-
-  priv = PRINTERS_PANEL_PRIVATE (self);
-
-  if (priv->current_dest >= 0 &&
-      priv->current_dest < priv->num_dests &&
-      priv->dests != NULL)
-    {
-      name = priv->dests[priv->current_dest].name;
-
-      for (i = 0; i < priv->dests[priv->current_dest].num_options; i++)
-        {
-          if (g_strcmp0 (priv->dests[priv->current_dest].options[i].name, "printer-state") == 0)
-            paused = (g_strcmp0 (priv->dests[priv->current_dest].options[i].value, "5") == 0);
-          else if (g_strcmp0 (priv->dests[priv->current_dest].options[i].name, "printer-is-accepting-jobs") 
== 0)
-            {
-              if (g_strcmp0 (priv->dests[priv->current_dest].options[i].value, "true") == 0)
-                is_accepting_jobs = TRUE;
-              else
-                is_accepting_jobs = FALSE;
-            }
-        }
-    }
-
-  if (name)
-    {
-      if (!paused && is_accepting_jobs)
-        {
-          printer_set_enabled (name, FALSE);
-          printer_set_accepting_jobs (name, FALSE, NULL);
-        }
-      else
-        {
-          if (paused)
-            printer_set_enabled (name, TRUE);
-
-          if (!is_accepting_jobs)
-            printer_set_accepting_jobs (name, TRUE, NULL);
-        }
-
-      actualize_printers_list (self);
-    }
-}
-
-typedef struct {
-  gchar *color;
-  gchar *type;
-  gchar *name;
-  gint   level;
-} MarkerItem;
-
-static gint
-markers_cmp (gconstpointer a,
-             gconstpointer b)
-{
-  MarkerItem *x = (MarkerItem*) a;
-  MarkerItem *y = (MarkerItem*) b;
-
-  if (x->level < y->level)
-    return 1;
-  else if (x->level == y->level)
-    return 0;
-  else
-    return -1;
-}
-
-static void
-rounded_rectangle (cairo_t *cr, double x, double y, double w, double h, double r)
-{
-    cairo_new_sub_path (cr);
-    cairo_arc (cr, x + r, y + r, r, M_PI, 3 * M_PI / 2);
-    cairo_arc (cr, x + w - r, y + r, r, 3 *M_PI / 2, 2 * M_PI);
-    cairo_arc (cr, x + w - r, y + h - r, r, 0, M_PI / 2);
-    cairo_arc (cr, x + r, y + h - r, r, M_PI / 2, M_PI);
-    cairo_close_path (cr);
-}
-
-static gboolean
-supply_levels_draw_cb (GtkWidget *widget,
-                       cairo_t *cr,
-                       gpointer user_data)
-{
-  CcPrintersPanelPrivate *priv;
-  CcPrintersPanel        *self = (CcPrintersPanel*) user_data;
-  GtkStyleContext        *context;
-  gchar                  *marker_levels = NULL;
-  gchar                  *marker_colors = NULL;
-  gchar                  *marker_names = NULL;
-  gchar                  *marker_types = NULL;
-  gchar                  *tooltip_text = NULL;
-  gint                    width;
-  gint                    height;
-  int                     i;
-
-  priv = PRINTERS_PANEL_PRIVATE (self);
-
-  context = gtk_widget_get_style_context (widget);
-
-  width = gtk_widget_get_allocated_width (widget);
-  height = gtk_widget_get_allocated_height (widget);
-
-  gtk_render_background (context, cr, 0, 0, width, height);
-
-  if (priv->current_dest >= 0 &&
-      priv->current_dest < priv->num_dests &&
-      priv->dests != NULL)
-    {
-      for (i = 0; i < priv->dests[priv->current_dest].num_options; i++)
-        {
-          if (g_strcmp0 (priv->dests[priv->current_dest].options[i].name, "marker-names") == 0)
-            marker_names = g_strcompress (priv->dests[priv->current_dest].options[i].value);
-          else if (g_strcmp0 (priv->dests[priv->current_dest].options[i].name, "marker-levels") == 0)
-            marker_levels = priv->dests[priv->current_dest].options[i].value;
-          else if (g_strcmp0 (priv->dests[priv->current_dest].options[i].name, "marker-colors") == 0)
-            marker_colors = priv->dests[priv->current_dest].options[i].value;
-          else if (g_strcmp0 (priv->dests[priv->current_dest].options[i].name, "marker-types") == 0)
-            marker_types = priv->dests[priv->current_dest].options[i].value;
-        }
-
-      if (marker_levels && marker_colors && marker_names && marker_types)
-        {
-          GSList   *markers = NULL;
-          GSList   *tmp_list = NULL;
-          GValue    int_val = G_VALUE_INIT;
-          gchar   **marker_levelsv = NULL;
-          gchar   **marker_colorsv = NULL;
-          gchar   **marker_namesv = NULL;
-          gchar   **marker_typesv = NULL;
-          gchar    *tmp = NULL;
-          gint      border_radius = 0;
-
-          gtk_style_context_save (context);
-          gtk_style_context_add_class (context, GTK_STYLE_CLASS_BUTTON);
-
-          gtk_style_context_get_property (
-            context, GTK_STYLE_PROPERTY_BORDER_RADIUS, 0, &int_val);
-          if (G_VALUE_HOLDS_INT (&int_val))
-            border_radius = g_value_get_int (&int_val);
-
-          marker_levelsv = g_strsplit (marker_levels, ",", -1);
-          marker_colorsv = g_strsplit (marker_colors, ",", -1);
-          marker_namesv = g_strsplit (marker_names, ",", -1);
-          marker_typesv = g_strsplit (marker_types, ",", -1);
-
-          if (g_strv_length (marker_levelsv) == g_strv_length (marker_colorsv) &&
-              g_strv_length (marker_colorsv) == g_strv_length (marker_namesv) &&
-              g_strv_length (marker_namesv) == g_strv_length (marker_typesv))
-            {
-              for (i = 0; i < g_strv_length (marker_levelsv); i++)
-                {
-                  MarkerItem *marker;
-
-                  if (g_strcmp0 (marker_typesv[i], "ink") == 0 ||
-                      g_strcmp0 (marker_typesv[i], "toner") == 0 ||
-                      g_strcmp0 (marker_typesv[i], "inkCartridge") == 0 ||
-                      g_strcmp0 (marker_typesv[i], "tonerCartridge") == 0)
-                    {
-                      marker = g_new0 (MarkerItem, 1);
-                      marker->type = g_strdup (marker_typesv[i]);
-                      marker->name = g_strdup (marker_namesv[i]);
-                      marker->color = g_strdup (marker_colorsv[i]);
-                      marker->level = atoi (marker_levelsv[i]);
-
-                      markers = g_slist_prepend (markers, marker);
-                    }
-                }
-
-              markers = g_slist_sort (markers, markers_cmp);
-
-              for (tmp_list = markers; tmp_list; tmp_list = tmp_list->next)
-                {
-                  GdkRGBA color = {0.0, 0.0, 0.0, 1.0};
-                  double  display_value;
-                  int     value;
-
-                  value = ((MarkerItem*) tmp_list->data)->level;
-
-                  gdk_rgba_parse (&color, ((MarkerItem*) tmp_list->data)->color);
-
-                  if (value > 0)
-                    {
-                      display_value = value / 100.0 * (width - 3.0);
-                      gdk_cairo_set_source_rgba (cr, &color);
-                      rounded_rectangle (cr, 1.5, 1.5, display_value, SUPPLY_BAR_HEIGHT - 3.0, 
border_radius);
-                      cairo_fill (cr);
-                    }
-
-                  if (tooltip_text)
-                    {
-                      tmp = g_strdup_printf ("%s\n%s",
-                                             tooltip_text,
-                                             ((MarkerItem*) tmp_list->data)->name);
-                      g_free (tooltip_text);
-                      tooltip_text = tmp;
-                      tmp = NULL;
-                    }
-                  else
-                    tooltip_text = g_strdup_printf ("%s",
-                                                    ((MarkerItem*) tmp_list->data)->name);
-                }
-
-              gtk_render_frame (context, cr, 1, 1, width - 2, SUPPLY_BAR_HEIGHT - 2);
-
-              for (tmp_list = markers; tmp_list; tmp_list = tmp_list->next)
-                {
-                  g_free (((MarkerItem*) tmp_list->data)->name);
-                  g_free (((MarkerItem*) tmp_list->data)->type);
-                  g_free (((MarkerItem*) tmp_list->data)->color);
-                }
-              g_slist_free_full (markers, g_free);
-            }
-
-          gtk_style_context_restore (context);
-
-          g_strfreev (marker_levelsv);
-          g_strfreev (marker_colorsv);
-          g_strfreev (marker_namesv);
-          g_strfreev (marker_typesv);
-        }
-
-      g_free (marker_names);
-
-      if (tooltip_text)
-        {
-          gtk_widget_set_tooltip_text (widget, tooltip_text);
-          g_free (tooltip_text);
-        }
-      else
-        {
-          gtk_widget_set_tooltip_text (widget, NULL);
-          gtk_widget_set_has_tooltip (widget, FALSE);
-        }
-    }
-
-  return TRUE;
-}
-
-static void
-printer_set_default_cb (GtkToggleButton *button,
-                        gpointer         user_data)
-{
-  CcPrintersPanelPrivate *priv;
-  CcPrintersPanel        *self = (CcPrintersPanel*) user_data;
-  char                   *name = NULL;
-
-  priv = PRINTERS_PANEL_PRIVATE (self);
-
-  if (priv->current_dest >= 0 &&
-      priv->current_dest < priv->num_dests &&
-      priv->dests != NULL)
-    name = priv->dests[priv->current_dest].name;
-
-  if (name)
-    {
-      printer_set_default (name);
-      actualize_printers_list (self);
-
-      g_signal_handlers_block_by_func (G_OBJECT (button), printer_set_default_cb, self);
-      gtk_toggle_button_set_active (button, priv->dests[priv->current_dest].is_default);
-      g_signal_handlers_unblock_by_func (G_OBJECT (button), printer_set_default_cb, self);
-  }
-}
-
-static void
 new_printer_dialog_pre_response_cb (PpNewPrinterDialog *dialog,
                                     const gchar        *device_name,
                                     const gchar        *device_location,
@@ -1917,1301 +703,257 @@ printer_add_cb (GtkToolButton *toolbutton,
 }
 
 static void
-printer_remove_cb (GtkToolButton *toolbutton,
-                   gpointer       user_data)
+cc_printers_panel_init (CcPrintersPanel *self)
 {
   CcPrintersPanelPrivate *priv;
-  CcPrintersPanel        *self = (CcPrintersPanel*) user_data;
-  char                   *printer_name = NULL;
-
-  priv = PRINTERS_PANEL_PRIVATE (self);
-
-  if (priv->current_dest >= 0 &&
-      priv->current_dest < priv->num_dests &&
-      priv->dests != NULL)
-    printer_name = priv->dests[priv->current_dest].name;
-
-  if (printer_name && printer_delete (printer_name))
-    actualize_printers_list (self);
-}
-
-static void
-printer_name_edit_cb (GtkWidget *entry,
-                      gpointer   user_data)
-{
-  CcPrintersPanelPrivate  *priv;
-  CcPrintersPanel         *self = (CcPrintersPanel*) user_data;
-  const gchar             *new_name;
-  gchar                   *old_name = NULL;
-  gint                     i;
-
-  priv = PRINTERS_PANEL_PRIVATE (self);
-
-  new_name = cc_editable_entry_get_text (CC_EDITABLE_ENTRY (entry));
-
-  if (priv->current_dest >= 0 &&
-      priv->current_dest < priv->num_dests &&
-      priv->dests != NULL)
-    old_name = priv->dests[priv->current_dest].name;
-
-  if (printer_rename (old_name, new_name))
-    {
-      free_dests (self);
-      priv->num_dests = cupsGetDests (&priv->dests);
-      priv->dest_model_names = g_new0 (gchar *, priv->num_dests);
-      priv->ppd_file_names = g_new0 (gchar *, priv->num_dests);
-
-      for (i = 0; i < priv->num_dests; i++)
-        if (g_strcmp0 (priv->dests[i].name, new_name) == 0)
-          {
-            priv->current_dest  = i;
-            break;
-          }
-    }
-
-  actualize_printers_list (self);
-}
-
-static void
-printer_location_edit_cb (GtkWidget *entry,
-                          gpointer   user_data)
-{
-  CcPrintersPanelPrivate  *priv;
-  CcPrintersPanel         *self = (CcPrintersPanel*) user_data;
-  const gchar             *location;
-  gchar                   *printer_name = NULL;
-
-  priv = PRINTERS_PANEL_PRIVATE (self);
+  GtkWidget              *top_widget;
+  GtkWidget              *widget;
+  PpCups                 *cups;
+  GError                 *error = NULL;
+  gchar                  *objects[] = { "main-vbox", NULL };
+  guint                   builder_result;
 
-  location = cc_editable_entry_get_text (CC_EDITABLE_ENTRY (entry));
+  priv = self->priv = PRINTERS_PANEL_PRIVATE (self);
+  g_resources_register (cc_printers_get_resource ());
 
-  if (priv->current_dest >= 0 &&
-      priv->current_dest < priv->num_dests &&
-      priv->dests != NULL)
-    printer_name = priv->dests[priv->current_dest].name;
+  /* initialize main data structure */
+  priv->builder = gtk_builder_new ();
+  priv->dests = NULL;
+  priv->num_dests = 0;
 
-  if (printer_name && location &&
-      printer_set_location (printer_name, location))
-    actualize_printers_list (self);
-}
+  priv->pp_new_printer_dialog = NULL;
 
-static void
-set_ppd_cb (gchar    *printer_name,
-            gboolean  success,
-            gpointer  user_data)
-{
-  CcPrintersPanelPrivate *priv;
-  CcPrintersPanel        *self = (CcPrintersPanel*) user_data;
-  GList                  *iter;
+  priv->subscription_id = 0;
+  priv->cups_status_check_id = 0;
+  priv->subscription_renewal_id = 0;
+  priv->cups_proxy = NULL;
+  priv->cups_bus_connection = NULL;
+  priv->dbus_subscription_id = 0;
 
-  priv = PRINTERS_PANEL_PRIVATE (self);
+  priv->new_printer_name = NULL;
+  priv->new_printer_location = NULL;
+  priv->new_printer_make_and_model = NULL;
+  priv->new_printer_on_network = FALSE;
+  priv->select_new_printer = FALSE;
 
-  for (iter = priv->driver_change_list; iter; iter = iter->next)
-    {
-      SetPPDItem *item = (SetPPDItem *) iter->data;
+  priv->permission = NULL;
+  priv->lockdown_settings = NULL;
 
-      if (g_strcmp0 (item->printer_name, printer_name) == 0)
-        {
-          priv->driver_change_list = g_list_remove_link (priv->driver_change_list, iter);
+  priv->all_ppds_list = NULL;
+  priv->get_all_ppds_cancellable = NULL;
 
-          g_object_unref (item->cancellable);
-          g_free (item->printer_name);
-          g_free (item);
-          g_list_free (iter);
-          break;
-        }
-    }
+  priv->preferred_drivers = NULL;
 
-  update_sensitivity (self);
+  builder_result = gtk_builder_add_objects_from_resource (priv->builder,
+                                                          "/org/gnome/control-center/printers/printers.ui",
+                                                          objects, &error);
 
-  if (success)
+  if (builder_result == 0)
     {
-      actualize_printers_list (self);
+      /* Translators: The XML file containing user interface can not be loaded */
+      g_warning (_("Could not load ui: %s"), error->message);
+      g_error_free (error);
+      return;
     }
 
-  g_free (printer_name);
-}
-
-static void
-select_ppd_manually (GtkMenuItem *menuitem,
-                     gpointer     user_data)
-{
-  CcPrintersPanelPrivate *priv;
-  CcPrintersPanel        *self = (CcPrintersPanel*) user_data;
-  GtkFileFilter          *filter;
-  GtkWidget              *dialog;
-  gchar                  *printer_name = NULL;
-
-  priv = PRINTERS_PANEL_PRIVATE (self);
-
-  gtk_menu_shell_cancel (GTK_MENU_SHELL (priv->popup_menu));
-
-  dialog = gtk_file_chooser_dialog_new (_("Select PPD File"),
-                                        GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (self))),
-                                        GTK_FILE_CHOOSER_ACTION_OPEN,
-                                        _("_Cancel"), GTK_RESPONSE_CANCEL,
-                                        _("_Open"), GTK_RESPONSE_ACCEPT,
-                                        NULL);
-
-  filter = gtk_file_filter_new ();
-  gtk_file_filter_set_name (filter,
-    _("PostScript Printer Description files (*.ppd, *.PPD, *.ppd.gz, *.PPD.gz, *.PPD.GZ)"));
-  gtk_file_filter_add_pattern (filter, "*.ppd");
-  gtk_file_filter_add_pattern (filter, "*.PPD");
-  gtk_file_filter_add_pattern (filter, "*.ppd.gz");
-  gtk_file_filter_add_pattern (filter, "*.PPD.gz");
-  gtk_file_filter_add_pattern (filter, "*.PPD.GZ");
-
-  gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (dialog), filter);
+  /* add the top level widget */
+  top_widget = (GtkWidget*)
+    gtk_builder_get_object (priv->builder, "main-vbox");
 
-  if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
-    {
-      gchar *ppd_filename;
+  /* connect signals */
+  widget = (GtkWidget*)
+    gtk_builder_get_object (priv->builder, "printer-add-button2");
+  g_signal_connect (widget, "clicked", G_CALLBACK (printer_add_cb), self);
 
-      ppd_filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
+  priv->lockdown_settings = g_settings_new ("org.gnome.desktop.lockdown");
+  if (priv->lockdown_settings)
+    g_signal_connect_object (priv->lockdown_settings,
+                             "changed",
+                             G_CALLBACK (on_lockdown_settings_changed),
+                             self,
+                             G_CONNECT_AFTER);
 
-      if (priv->current_dest >= 0 &&
-          priv->current_dest < priv->num_dests &&
-          priv->dests != NULL)
-        printer_name = priv->dests[priv->current_dest].name;
+  actualize_printers_list (self);
+  attach_to_cups_notifier (self);
 
-      if (printer_name && ppd_filename)
-        {
-          SetPPDItem *item;
-
-          item = g_new0 (SetPPDItem, 1);
-          item->printer_name = g_strdup (printer_name);
-          item->cancellable = g_cancellable_new ();
-
-          priv->driver_change_list =
-            g_list_prepend (priv->driver_change_list, item);
-          update_sensitivity (self);
-          printer_set_ppd_file_async (printer_name,
-                                      ppd_filename,
-                                      item->cancellable,
-                                      set_ppd_cb,
-                                      user_data);
-        }
+  priv->get_all_ppds_cancellable = g_cancellable_new ();
+  get_all_ppds_async (priv->get_all_ppds_cancellable,
+                      get_all_ppds_async_cb,
+                      self);
 
-      g_free (ppd_filename);
-    }
+  cups = pp_cups_new ();
+  pp_cups_connection_test_async (cups, connection_test_cb, self);
 
-  gtk_widget_destroy (dialog);
+  gtk_container_add (GTK_CONTAINER (self), top_widget);
+  gtk_widget_show_all (GTK_WIDGET (self));
 }
 
 static void
-ppd_selection_dialog_response_cb (GtkDialog *dialog,
-                                  gint       response_id,
-                                  gpointer   user_data)
+cc_printers_panel_get_property (GObject    *object,
+                               guint       property_id,
+                               GValue     *value,
+                               GParamSpec *pspec)
 {
-  CcPrintersPanelPrivate *priv;
-  CcPrintersPanel        *self = (CcPrintersPanel*) user_data;
-  gchar                  *printer_name = NULL;
-
-  priv = PRINTERS_PANEL_PRIVATE (self);
-
-  if (response_id == GTK_RESPONSE_OK)
+  switch (property_id)
     {
-      gchar *ppd_name;
-
-      ppd_name = pp_ppd_selection_dialog_get_ppd_name (priv->pp_ppd_selection_dialog);
-
-      if (priv->current_dest >= 0 &&
-          priv->current_dest < priv->num_dests &&
-          priv->dests != NULL)
-        printer_name = priv->dests[priv->current_dest].name;
-
-      if (printer_name && ppd_name)
-        {
-          SetPPDItem *item;
-
-          item = g_new0 (SetPPDItem, 1);
-          item->printer_name = g_strdup (printer_name);
-          item->cancellable = g_cancellable_new ();
-
-          priv->driver_change_list = g_list_prepend (priv->driver_change_list,
-                                                     item);
-          update_sensitivity (self);
-          printer_set_ppd_async (printer_name,
-                                 ppd_name,
-                                 item->cancellable,
-                                 set_ppd_cb,
-                                 user_data);
-        }
-
-      g_free (ppd_name);
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
     }
-
-  pp_ppd_selection_dialog_free (priv->pp_ppd_selection_dialog);
-  priv->pp_ppd_selection_dialog = NULL;
 }
 
 static void
-select_ppd_in_dialog (GtkMenuItem *menuitem,
-                      gpointer     user_data)
+cc_printers_panel_set_property (GObject      *object,
+                               guint         property_id,
+                               const GValue *value,
+                               GParamSpec   *pspec)
 {
-  CcPrintersPanelPrivate *priv;
-  CcPrintersPanel        *self = (CcPrintersPanel*) user_data;
-  GtkWidget              *widget;
-  gchar                  *device_id = NULL;
-  gchar                  *manufacturer = NULL;
-
-  priv = PRINTERS_PANEL_PRIVATE (self);
-
-  widget = (GtkWidget*)
-    gtk_builder_get_object (priv->builder, "main-vbox");
-
-  if (!priv->pp_ppd_selection_dialog)
+  switch (property_id)
     {
-      if (priv->current_dest >= 0 &&
-          priv->current_dest < priv->num_dests)
-        {
-          device_id =
-            get_ppd_attribute (priv->ppd_file_names[priv->current_dest],
-                               "1284DeviceID");
-
-          if (device_id)
-            {
-              manufacturer = get_tag_value (device_id, "mfg");
-              if (!manufacturer)
-                manufacturer = get_tag_value (device_id, "manufacturer");
-            }
-
-          if (manufacturer == NULL)
-            {
-              manufacturer =
-                get_ppd_attribute (priv->ppd_file_names[priv->current_dest],
-                                   "Manufacturer");
-            }
-
-          if (manufacturer == NULL)
-            {
-              manufacturer = g_strdup ("Raw");
-            }
-        }
-
-      priv->pp_ppd_selection_dialog = pp_ppd_selection_dialog_new (
-        GTK_WINDOW (gtk_widget_get_toplevel (widget)),
-        priv->all_ppds_list,
-        manufacturer,
-        ppd_selection_dialog_response_cb,
-        self);
-
-      g_free (manufacturer);
-      g_free (device_id);
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
     }
 }
 
 static void
-set_ppd_from_list (GtkMenuItem *menuitem,
-                   gpointer     user_data)
+cc_printers_panel_dispose (GObject *object)
 {
-  CcPrintersPanelPrivate *priv;
-  CcPrintersPanel        *self = (CcPrintersPanel*) user_data;
-  gchar                  *printer_name = NULL;
-  gchar                  *ppd_name;
-
-  priv = PRINTERS_PANEL_PRIVATE (self);
-
-  ppd_name = (gchar *) g_object_get_data (G_OBJECT (menuitem), "ppd-name");
+  CcPrintersPanelPrivate *priv = CC_PRINTERS_PANEL (object)->priv;
 
-  if (priv->current_dest >= 0 &&
-      priv->current_dest < priv->num_dests &&
-      priv->dests != NULL)
-    printer_name = priv->dests[priv->current_dest].name;
+  if (priv->pp_new_printer_dialog)
+    g_clear_object (&priv->pp_new_printer_dialog);
 
-  if (printer_name && ppd_name)
-    {
-      SetPPDItem *item;
-
-      item = g_new0 (SetPPDItem, 1);
-      item->printer_name = g_strdup (printer_name);
-      item->cancellable = g_cancellable_new ();
-
-      priv->driver_change_list = g_list_prepend (priv->driver_change_list,
-                                                 item);
-      update_sensitivity (self);
-      printer_set_ppd_async (printer_name,
-                             ppd_name,
-                             item->cancellable,
-                             set_ppd_cb,
-                             user_data);
-    }
-}
+  free_dests (CC_PRINTERS_PANEL (object));
 
-static void
-ppd_names_free (gpointer user_data)
-{
-  PPDName **names = (PPDName **) user_data;
-  gint      i;
+  g_clear_pointer (&priv->new_printer_name, g_free);
+  g_clear_pointer (&priv->new_printer_location, g_free);
+  g_clear_pointer (&priv->new_printer_make_and_model, g_free);
 
-  if (names)
+  if (priv->builder)
     {
-      for (i = 0; names[i]; i++)
-        {
-          g_free (names[i]->ppd_name);
-          g_free (names[i]->ppd_display_name);
-          g_free (names[i]);
-        }
-
-      g_free (names);
+      g_object_unref (priv->builder);
+      priv->builder = NULL;
     }
-}
-
-static void
-get_ppd_names_cb (PPDName     **names,
-                  const gchar  *printer_name,
-                  gboolean      cancelled,
-                  gpointer      user_data)
-{
-  CcPrintersPanelPrivate  *priv;
-  CcPrintersPanel         *self = (CcPrintersPanel*) user_data;
-  GtkWidget               *informal = NULL;
-  GtkWidget               *placeholders[3];
-  GtkWidget               *spinner;
-  gpointer                 value = NULL;
-  gboolean                 found = FALSE;
-  PPDName                **hash_names = NULL;
-  GList                   *children, *iter;
-  gint                     i;
-
-  priv = PRINTERS_PANEL_PRIVATE (self);
-
-  priv->getting_ppd_names = FALSE;
 
-  for (i = 0; i < 3; i++)
-    placeholders[i] = NULL;
-
-  children = gtk_container_get_children (GTK_CONTAINER (priv->popup_menu));
-  if (children)
+  if (priv->lockdown_settings)
     {
-      for (iter = children; iter; iter = iter->next)
-        {
-          if (g_strcmp0 ((gchar *) g_object_get_data (G_OBJECT (iter->data), "purpose"),
-                         "informal") == 0)
-              informal = GTK_WIDGET (iter->data);
-          else if (g_strcmp0 ((gchar *) g_object_get_data (G_OBJECT (iter->data), "purpose"),
-                              "placeholder1") == 0)
-              placeholders[0] = GTK_WIDGET (iter->data);
-          else if (g_strcmp0 ((gchar *) g_object_get_data (G_OBJECT (iter->data), "purpose"),
-                              "placeholder2") == 0)
-              placeholders[1] = GTK_WIDGET (iter->data);
-          else if (g_strcmp0 ((gchar *) g_object_get_data (G_OBJECT (iter->data), "purpose"),
-                              "placeholder3") == 0)
-              placeholders[2] = GTK_WIDGET (iter->data);
-        }
-
-      g_list_free (children);
+      g_object_unref (priv->lockdown_settings);
+      priv->lockdown_settings = NULL;
     }
 
-  if (!priv->preferred_drivers)
+  if (priv->permission)
     {
-      priv->preferred_drivers = g_hash_table_new_full (g_str_hash, g_str_equal,
-                                                       g_free, ppd_names_free);
+      g_object_unref (priv->permission);
+      priv->permission = NULL;
     }
 
-  if (!cancelled &&
-      !g_hash_table_lookup_extended (priv->preferred_drivers,
-                                     printer_name, NULL, NULL))
-    g_hash_table_insert (priv->preferred_drivers, g_strdup (printer_name), names);
-
-  if (priv->preferred_drivers &&
-      g_hash_table_lookup_extended (priv->preferred_drivers,
-                                    printer_name, NULL, &value))
-    {
-      hash_names = (PPDName **) value;
-      if (hash_names)
-        {
-          for (i = 0; hash_names[i]; i++)
-            {
-              if (placeholders[i])
-                {
-                  gtk_menu_item_set_label (GTK_MENU_ITEM (placeholders[i]),
-                                           hash_names[i]->ppd_display_name);
-                  g_object_set_data_full (G_OBJECT (placeholders[i]),
-                                          "ppd-name",
-                                          g_strdup (hash_names[i]->ppd_name),
-                                              g_free);
-                  g_signal_connect (placeholders[i],
-                                    "activate",
-                                    G_CALLBACK (set_ppd_from_list),
-                                    self);
-                  gtk_widget_set_sensitive (GTK_WIDGET (placeholders[i]), TRUE);
-                  gtk_widget_show (placeholders[i]);
-                }
-            }
-
-          found = TRUE;
-        }
-      else
-        {
-          found = FALSE;
-        }
-    }
+  detach_from_cups_notifier (CC_PRINTERS_PANEL (object));
 
-  if (informal)
+  if (priv->cups_status_check_id > 0)
     {
-      spinner = g_object_get_data (G_OBJECT (informal), "spinner");
-      if (spinner)
-        {
-          gtk_widget_hide (spinner);
-          gtk_spinner_stop (GTK_SPINNER (spinner));
-        }
-
-      if (found)
-        gtk_widget_hide (informal);
-      else
-        gtk_label_set_text (GTK_LABEL (g_object_get_data (G_OBJECT (informal), "label")),
-                            _("No suitable driver found"));
+      g_source_remove (priv->cups_status_check_id);
+      priv->cups_status_check_id = 0;
     }
 
-  gtk_widget_show_all (priv->popup_menu);
-
-  update_sensitivity (self);
-}
-
-static void
-popup_menu_done (GtkMenuShell *menushell,
-                 gpointer      user_data)
-{
-  CcPrintersPanelPrivate *priv;
-  CcPrintersPanel        *self = (CcPrintersPanel*) user_data;
-
-  priv = PRINTERS_PANEL_PRIVATE (self);
-
-  if (priv->get_ppd_name_cancellable)
+  if (priv->all_ppds_list)
     {
-      g_cancellable_cancel (priv->get_ppd_name_cancellable);
-      g_object_unref (priv->get_ppd_name_cancellable);
-      priv->get_ppd_name_cancellable = NULL;
+      ppd_list_free (priv->all_ppds_list);
+      priv->all_ppds_list = NULL;
     }
-}
 
-static void
-popup_model_menu_cb (GtkButton *button,
-                     gpointer   user_data)
-{
-  CcPrintersPanelPrivate *priv;
-  CcPrintersPanel        *self = (CcPrintersPanel*) user_data;
-  GtkWidget              *spinner;
-  GtkWidget              *item;
-  GtkWidget              *label;
-  GtkWidget              *box;
-
-  priv = PRINTERS_PANEL_PRIVATE (self);
-
-  priv->popup_menu = gtk_menu_new ();
-  g_signal_connect (priv->popup_menu,
-                    "selection-done",
-                    G_CALLBACK (popup_menu_done),
-                    user_data);
-
-  /*
-   * These placeholders are a workaround for a situation
-   * when we want to actually append new menu item in a callback.
-   * But unfortunately it is not possible to connect to "activate"
-   * signal of such menu item (appended after gtk_menu_popup()).
-   */
-  item = gtk_menu_item_new_with_label ("");
-  g_object_set_data_full (G_OBJECT (item), "purpose",
-                          g_strdup ("placeholder1"), g_free);
-  gtk_menu_shell_append (GTK_MENU_SHELL (priv->popup_menu), item);
-  gtk_widget_set_no_show_all (item, TRUE);
-  gtk_widget_hide (item);
-
-  item = gtk_menu_item_new_with_label ("");
-  g_object_set_data_full (G_OBJECT (item), "purpose",
-                          g_strdup ("placeholder2"), g_free);
-  gtk_menu_shell_append (GTK_MENU_SHELL (priv->popup_menu), item);
-  gtk_widget_set_no_show_all (item, TRUE);
-  gtk_widget_hide (item);
-
-  item = gtk_menu_item_new_with_label ("");
-  g_object_set_data_full (G_OBJECT (item), "purpose",
-                          g_strdup ("placeholder3"), g_free);
-  gtk_menu_shell_append (GTK_MENU_SHELL (priv->popup_menu), item);
-  gtk_widget_set_no_show_all (item, TRUE);
-  gtk_widget_hide (item);
-
-  label = gtk_label_new (_("Searching for preferred drivers…"));
-  spinner = gtk_spinner_new ();
-  gtk_spinner_start (GTK_SPINNER (spinner));
-  box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
-  gtk_container_add (GTK_CONTAINER (box), spinner);
-  gtk_container_add (GTK_CONTAINER (box), label);
-  item = gtk_menu_item_new ();
-  gtk_container_add (GTK_CONTAINER (item), box);
-  gtk_widget_show_all (item);
-  g_object_set_data_full (G_OBJECT (item), "purpose",
-                          g_strdup ("informal"), g_free);
-  g_object_set_data (G_OBJECT (item), "spinner", spinner);
-  g_object_set_data (G_OBJECT (item), "label", label);
-  gtk_widget_set_sensitive (item, FALSE);
-  gtk_menu_shell_append (GTK_MENU_SHELL (priv->popup_menu), item);
-  gtk_widget_set_no_show_all (item, TRUE);
-  gtk_widget_show (item);
-
-  item = gtk_separator_menu_item_new ();
-  gtk_menu_shell_append (GTK_MENU_SHELL (priv->popup_menu), item);
-
-  item = gtk_menu_item_new_with_label (_("Select from database…"));
-  g_object_set_data_full (G_OBJECT (item), "purpose",
-                          g_strdup ("ppd-select"), g_free);
-  g_signal_connect (item, "activate", G_CALLBACK (select_ppd_in_dialog), self);
-  gtk_menu_shell_append (GTK_MENU_SHELL (priv->popup_menu), item);
-
-  item = gtk_separator_menu_item_new ();
-  gtk_menu_shell_append (GTK_MENU_SHELL (priv->popup_menu), item);
-
-  item = gtk_menu_item_new_with_label (_("Provide PPD File…"));
-  g_object_set_data_full (G_OBJECT (item), "purpose",
-                          g_strdup ("ppdfile-select"), g_free);
-  g_signal_connect (item, "activate", G_CALLBACK (select_ppd_manually), self);
-  gtk_menu_shell_append (GTK_MENU_SHELL (priv->popup_menu), item);
-
-  gtk_widget_show_all (priv->popup_menu);
-
-  gtk_menu_popup (GTK_MENU (priv->popup_menu),
-                  NULL, NULL, NULL, NULL, 0,
-                  gtk_get_current_event_time());
-
-  if (priv->current_dest >= 0 &&
-      priv->current_dest < priv->num_dests &&
-      priv->dests != NULL)
+  if (priv->preferred_drivers)
     {
-      if (priv->preferred_drivers &&
-          g_hash_table_lookup_extended (priv->preferred_drivers,
-                                        priv->dests[priv->current_dest].name,
-                                        NULL, NULL))
-        {
-          get_ppd_names_cb (NULL,
-                            priv->dests[priv->current_dest].name,
-                            FALSE,
-                            user_data);
-        }
-      else
-        {
-          priv->get_ppd_name_cancellable = g_cancellable_new ();
-          priv->getting_ppd_names = TRUE;
-          get_ppd_names_async (priv->dests[priv->current_dest].name,
-                               3,
-                               priv->get_ppd_name_cancellable,
-                               get_ppd_names_cb,
-                               user_data);
-
-          update_sensitivity (self);
-        }
+      g_hash_table_unref (priv->preferred_drivers);
+      priv->preferred_drivers = NULL;
     }
-}
-
-static void
-pp_maintenance_command_execute_cb (GObject      *source_object,
-                                   GAsyncResult *res,
-                                   gpointer      user_data)
-{
-  PpMaintenanceCommand *command = (PpMaintenanceCommand *) source_object;
-  GError               *error = NULL;
-
-  pp_maintenance_command_execute_finish (command, res, &error);
-
-  g_object_unref (command);
-}
-
-static void
-test_page_cb (GtkButton *button,
-              gpointer   user_data)
-{
-  CcPrintersPanelPrivate  *priv;
-  CcPrintersPanel         *self = (CcPrintersPanel*) user_data;
-  cups_ptype_t             type = 0;
-  const gchar             *printer_type = NULL;
-  gchar                   *printer_name = NULL;
-  gint                     i;
-
-  priv = PRINTERS_PANEL_PRIVATE (self);
 
-  if (priv->current_dest >= 0 &&
-      priv->current_dest < priv->num_dests &&
-      priv->dests != NULL)
-    {
-      printer_name = priv->dests[priv->current_dest].name;
-      printer_type = cupsGetOption ("printer-type",
-                                    priv->dests[priv->current_dest].num_options,
-                                    priv->dests[priv->current_dest].options);
-      if (printer_type)
-        type = atoi (printer_type);
-    }
+  priv->subscription_renew_cancellable = g_cancellable_new ();
 
-  if (printer_name)
+  if (priv->get_all_ppds_cancellable)
     {
-      const gchar  *const dirs[] = { "/usr/share/cups",
-                                     "/usr/local/share/cups",
-                                     NULL };
-      const gchar  *testprint[] = { "%s/data/testprint",
-                                    "%s/data/testprint.ps",
-                                    NULL };
-      const gchar **pattern;
-      const gchar  *datadir = NULL;
-      http_t       *http = NULL;
-      gchar        *printer_uri = NULL;
-      gchar        *filename = NULL;
-      gchar        *resource = NULL;
-      ipp_t        *response = NULL;
-      ipp_t        *request;
-
-      if ((datadir = getenv ("CUPS_DATADIR")) != NULL)
-        {
-          for (pattern = testprint; *pattern != NULL; pattern++)
-            {
-              filename = g_strdup_printf (*pattern, datadir);
-              if (g_access (filename, R_OK) == 0)
-                break;
-              else
-                {
-                  g_free (filename);
-                  filename = NULL;
-                }
-            }
-        }
-      else
-        {
-          for (i = 0; (datadir = dirs[i]) != NULL && filename == NULL; i++)
-            {
-              for (pattern = testprint; *pattern != NULL; pattern++)
-                {
-                  filename = g_strdup_printf (*pattern, datadir);
-                  if (g_access (filename, R_OK) == 0)
-                    break;
-                  else
-                    {
-                      g_free (filename);
-                      filename = NULL;
-                    }
-                }
-            }
-        }
-
-      if (filename)
-        {
-          if (type & CUPS_PRINTER_CLASS)
-            {
-              printer_uri = g_strdup_printf ("ipp://localhost/classes/%s", printer_name);
-              resource = g_strdup_printf ("/classes/%s", printer_name);
-            }
-          else
-            {
-              printer_uri = g_strdup_printf ("ipp://localhost/printers/%s", printer_name);
-              resource = g_strdup_printf ("/printers/%s", printer_name);
-            }
-
-          http = httpConnectEncrypt (cupsServer (), ippPort (), cupsEncryption ());
-          if (http)
-            {
-              request = ippNewRequest (IPP_PRINT_JOB);
-              ippAddString (request, IPP_TAG_OPERATION, IPP_TAG_URI,
-                            "printer-uri", NULL, printer_uri);
-              ippAddString (request, IPP_TAG_OPERATION, IPP_TAG_NAME,
-                            "requesting-user-name", NULL, cupsUser ());
-              ippAddString (request, IPP_TAG_OPERATION, IPP_TAG_NAME,
-              /* Translators: Name of job which makes printer to print test page */
-                            "job-name", NULL, _("Test page"));
-              response = cupsDoFileRequest (http, request, resource, filename);
-              httpClose (http);
-            }
-
-          if (response)
-            {
-              if (ippGetState (response) == IPP_ERROR)
-                g_warning ("An error has occured during printing of test page.");
-              ippDelete (response);
-            }
-
-          g_free (filename);
-          g_free (printer_uri);
-          g_free (resource);
-        }
-      else
-        {
-          PpMaintenanceCommand *command;
-
-          command = pp_maintenance_command_new (printer_name,
-                                                "PrintSelfTestPage",
-          /* Translators: Name of job which makes printer to print test page */
-                                                _("Test page"));
-
-          pp_maintenance_command_execute_async (command, NULL, pp_maintenance_command_execute_cb, self);
-        }
+      g_cancellable_cancel (priv->get_all_ppds_cancellable);
+      g_object_unref (priv->get_all_ppds_cancellable);
+      priv->get_all_ppds_cancellable = NULL;
     }
-}
-
-static void
-update_sensitivity (gpointer user_data)
-{
-  CcPrintersPanelPrivate  *priv;
-  GtkTreeSelection        *selection;
-  CcPrintersPanel         *self = (CcPrintersPanel*) user_data;
-  cups_ptype_t             type = 0;
-  GtkTreeModel            *model;
-  GtkTreeView             *treeview;
-  GtkTreeIter              tree_iter;
-  const char              *cups_server = NULL;
-  GtkWidget               *widget;
-  gboolean                 is_authorized;
-  gboolean                 is_discovered = FALSE;
-  gboolean                 is_class = FALSE;
-  gboolean                 is_changing_driver = FALSE;
-  gboolean                 printer_selected;
-  gboolean                 local_server = TRUE;
-  gboolean                 no_cups = FALSE;
-  gboolean                 is_new = FALSE;
-  gboolean                 already_present_local;
-  GList                   *iter;
-  gchar                   *current_printer_name = NULL;
-  gchar                   *no_printer_label;
-  gint                     i;
-
-  priv = PRINTERS_PANEL_PRIVATE (self);
 
-  is_authorized =
-    priv->permission &&
-    g_permission_get_allowed (G_PERMISSION (priv->permission)) &&
-    priv->lockdown_settings &&
-    !g_settings_get_boolean (priv->lockdown_settings, "disable-print-setup");
-
-  printer_selected = priv->current_dest >= 0 &&
-                     priv->current_dest < priv->num_dests &&
-                     priv->dests != NULL;
-
-  if (printer_selected)
+  if (priv->driver_change_list)
     {
-      for (i = 0; i < priv->dests[priv->current_dest].num_options; i++)
-        {
-          if (g_strcmp0 (priv->dests[priv->current_dest].options[i].name, "printer-type") == 0)
-            {
-              type = atoi (priv->dests[priv->current_dest].options[i].value);
-              is_discovered = type & CUPS_PRINTER_DISCOVERED;
-              is_class = type & CUPS_PRINTER_CLASS;
-              break;
-            }
-        }
+      GList *iter;
 
       for (iter = priv->driver_change_list; iter; iter = iter->next)
         {
           SetPPDItem *item = (SetPPDItem *) iter->data;
 
-          if (g_strcmp0 (item->printer_name, priv->dests[priv->current_dest].name) == 0)
-            {
-              is_changing_driver = TRUE;
-            }
+          g_cancellable_cancel (item->cancellable);
+          g_object_unref (item->cancellable);
+          g_free (item->printer_name);
+          g_free (item);
         }
-    }
-
-  treeview = (GtkTreeView*)
-    gtk_builder_get_object (priv->builder, "printers-treeview");
-
-  selection = gtk_tree_view_get_selection (treeview);
-  if (selection &&
-      gtk_tree_selection_get_selected (selection, &model, &tree_iter))
-    {
-      gtk_tree_model_get (model, &tree_iter,
-                          PRINTER_NAME_COLUMN, &current_printer_name,
-                          -1);
-    }
-
-  if (priv->new_printer_name &&
-      g_strcmp0 (priv->new_printer_name, current_printer_name) == 0)
-    {
-      printer_selected = TRUE;
-      is_discovered = FALSE;
-      is_class = FALSE;
-      is_new = TRUE;
-    }
-
-  g_free (current_printer_name);
-
-  cups_server = cupsServer ();
-  if (cups_server &&
-      g_ascii_strncasecmp (cups_server, "localhost", 9) != 0 &&
-      g_ascii_strncasecmp (cups_server, "127.0.0.1", 9) != 0 &&
-      g_ascii_strncasecmp (cups_server, "::1", 3) != 0 &&
-      cups_server[0] != '/')
-    local_server = FALSE;
-
-  widget = (GtkWidget*) gtk_builder_get_object (priv->builder, "notebook");
-  if (gtk_notebook_get_current_page (GTK_NOTEBOOK (widget)) == NOTEBOOK_NO_CUPS_PAGE)
-    no_cups = TRUE;
 
-  already_present_local = local_server && !is_discovered && is_authorized && !is_new;
-
-  widget = (GtkWidget*) gtk_builder_get_object (priv->builder, "printer-add-button");
-  gtk_widget_set_sensitive (widget, local_server && is_authorized && !no_cups && !priv->new_printer_name);
-
-  widget = (GtkWidget*) gtk_builder_get_object (priv->builder, "printer-add-button2");
-  gtk_widget_set_sensitive (widget, local_server && is_authorized && !no_cups && !priv->new_printer_name);
-
-  widget = (GtkWidget*) gtk_builder_get_object (priv->builder, "no-printer-label");
-  no_printer_label = g_strdup_printf ("<span size=\"larger\" weight=\"bold\">%s</span>", _("No printers"));
-  gtk_label_set_markup (GTK_LABEL (widget), no_printer_label);
-  g_free (no_printer_label);
-
-  widget = (GtkWidget*) gtk_builder_get_object (priv->builder, "printer-remove-button");
-  gtk_widget_set_sensitive (widget, already_present_local && printer_selected && !no_cups);
-
-  widget = (GtkWidget*) gtk_builder_get_object (priv->builder, "printer-disable-switch");
-  gtk_widget_set_sensitive (widget, already_present_local);
-
-  widget = (GtkWidget*) gtk_builder_get_object (priv->builder, "printer-default-check-button");
-  gtk_widget_set_sensitive (widget, is_authorized && !is_new);
-
-  widget = (GtkWidget*) gtk_builder_get_object (priv->builder, "print-test-page-button");
-  gtk_widget_set_sensitive (widget, printer_selected && !is_new);
-
-  widget = (GtkWidget*) gtk_builder_get_object (priv->builder, "printer-options-button");
-  gtk_widget_set_sensitive (widget, printer_selected && local_server && !is_discovered &&
-                            !priv->pp_options_dialog && !is_new);
-
-  widget = (GtkWidget*) gtk_builder_get_object (priv->builder, "printer-jobs-button");
-  gtk_widget_set_sensitive (widget, printer_selected && !is_new);
-
-  widget = (GtkWidget*) gtk_builder_get_object (priv->builder, "printer-icon");
-  gtk_widget_set_sensitive (widget, printer_selected);
-
-  widget = (GtkWidget*) gtk_builder_get_object (priv->builder, "printer-name-label");
-  cc_editable_entry_set_editable (CC_EDITABLE_ENTRY (widget), already_present_local);
-
-  widget = (GtkWidget*) gtk_builder_get_object (priv->builder, "printer-location-label");
-  cc_editable_entry_set_editable (CC_EDITABLE_ENTRY (widget), already_present_local);
-
-  widget = (GtkWidget*) gtk_builder_get_object (priv->builder, "printer-model-notebook");
-  if (is_changing_driver)
-    {
-      gtk_notebook_set_current_page (GTK_NOTEBOOK (widget), 2);
-    }
-  else
-    {
-      if (already_present_local && !is_class && !priv->getting_ppd_names)
-        gtk_notebook_set_current_page (GTK_NOTEBOOK (widget), 0);
-      else
-        gtk_notebook_set_current_page (GTK_NOTEBOOK (widget), 1);
-    }
-}
-
-static void
-on_permission_changed (GPermission *permission,
-                       GParamSpec  *pspec,
-                       gpointer     data)
-{
-  update_sensitivity (data);
-}
-
-static void
-on_lockdown_settings_changed (GSettings  *settings,
-                              const char *key,
-                              gpointer    user_data)
-{
-  CcPrintersPanelPrivate  *priv;
-  CcPrintersPanel         *self = (CcPrintersPanel*) user_data;
-
-  if (g_str_equal (key, "disable-print-setup") == FALSE)
-    return;
-
-  priv = PRINTERS_PANEL_PRIVATE (self);
-
-#if 0
-  /* FIXME */
-  gtk_widget_set_sensitive (priv->lock_button,
-    !g_settings_get_boolean (priv->lockdown_settings, "disable-print-setup"));
-#endif
-
-  on_permission_changed (priv->permission, NULL, user_data);
-}
-
-static void
-printer_options_response_cb (GtkDialog *dialog,
-                             gint       response_id,
-                             gpointer   user_data)
-{
-  CcPrintersPanelPrivate *priv;
-  CcPrintersPanel        *self = (CcPrintersPanel*) user_data;
-
-  priv = PRINTERS_PANEL_PRIVATE (self);
-
-  pp_options_dialog_free (priv->pp_options_dialog);
-  priv->pp_options_dialog = NULL;
-  update_sensitivity (self);
-
-  if (response_id == GTK_RESPONSE_OK)
-    actualize_printers_list (self);
-}
-
-static void
-printer_options_cb (GtkToolButton *toolbutton,
-                    gpointer       user_data)
-{
-  CcPrintersPanelPrivate *priv;
-  CcPrintersPanel        *self = (CcPrintersPanel*) user_data;
-  GtkWidget              *widget;
-  gboolean                is_authorized;
-
-  priv = PRINTERS_PANEL_PRIVATE (self);
-
-  widget = (GtkWidget*)
-    gtk_builder_get_object (priv->builder, "main-vbox");
-
-  is_authorized =
-    priv->permission &&
-    g_permission_get_allowed (G_PERMISSION (priv->permission)) &&
-    priv->lockdown_settings &&
-    !g_settings_get_boolean (priv->lockdown_settings, "disable-print-setup");
-
-  if (priv->current_dest >= 0 &&
-      priv->current_dest < priv->num_dests &&
-      priv->dests != NULL)
-    {
-      priv->pp_options_dialog = pp_options_dialog_new (
-        GTK_WINDOW (gtk_widget_get_toplevel (widget)),
-        printer_options_response_cb,
-        self,
-        priv->dests[priv->current_dest].name,
-        is_authorized);
-      update_sensitivity (self);
-    }
-}
-
-static void
-cups_status_check_cb (GObject      *source_object,
-                      GAsyncResult *result,
-                      gpointer      user_data)
-{
-  CcPrintersPanelPrivate *priv;
-  CcPrintersPanel        *self = (CcPrintersPanel*) user_data;
-  gboolean                success;
-  PpCups                 *cups = PP_CUPS (source_object);
-
-  priv = self->priv;
-
-  success = pp_cups_connection_test_finish (cups, result);
-  if (success)
-    {
-      actualize_printers_list (self);
-      attach_to_cups_notifier (self);
-
-      g_source_remove (priv->cups_status_check_id);
-      priv->cups_status_check_id = 0;
+      g_list_free (priv->driver_change_list);
+      priv->driver_change_list = NULL;
     }
 
-  g_object_unref (cups);
-}
-
-static gboolean
-cups_status_check (gpointer user_data)
-{
-  CcPrintersPanelPrivate  *priv;
-  CcPrintersPanel         *self = (CcPrintersPanel*) user_data;
-  PpCups                  *cups;
-
-  priv = self->priv;
-
-  cups = pp_cups_new ();
-  pp_cups_connection_test_async (cups, cups_status_check_cb, self);
-
-  return priv->cups_status_check_id != 0;
+  G_OBJECT_CLASS (cc_printers_panel_parent_class)->dispose (object);
 }
 
 static void
-connection_test_cb (GObject      *source_object,
-                    GAsyncResult *result,
-                    gpointer      user_data)
+cc_printers_panel_finalize (GObject *object)
 {
-  CcPrintersPanelPrivate *priv;
-  CcPrintersPanel        *self = (CcPrintersPanel*) user_data;
-  gboolean                success;
-  PpCups                 *cups = PP_CUPS (source_object);
-
-  priv = self->priv;
-
-  success = pp_cups_connection_test_finish (cups, result);
-  if (!success)
-    {
-      priv->cups_status_check_id =
-        g_timeout_add_seconds (CUPS_STATUS_CHECK_INTERVAL, cups_status_check, self);
-    }
-
-  g_object_unref (cups);
+  G_OBJECT_CLASS (cc_printers_panel_parent_class)->finalize (object);
 }
 
-static void
-get_all_ppds_async_cb (PPDList  *ppds,
-                       gpointer  user_data)
+static GPermission *
+cc_printers_panel_get_permission (CcPanel *panel)
 {
-  CcPrintersPanelPrivate *priv;
-  CcPrintersPanel        *self = (CcPrintersPanel*) user_data;
-
-  priv = self->priv = PRINTERS_PANEL_PRIVATE (self);
-
-  priv->all_ppds_list = ppds;
-
-  if (priv->pp_ppd_selection_dialog)
-    pp_ppd_selection_dialog_set_ppd_list (priv->pp_ppd_selection_dialog,
-                                          priv->all_ppds_list);
-
-  if (priv->pp_new_printer_dialog)
-    pp_new_printer_dialog_set_ppd_list (priv->pp_new_printer_dialog,
-                                        priv->all_ppds_list);
+  CcPrintersPanelPrivate *priv = CC_PRINTERS_PANEL (panel)->priv;
 
-  g_object_unref (priv->get_all_ppds_cancellable);
-  priv->get_all_ppds_cancellable = NULL;
+  return priv->permission;
 }
 
-static void
-update_label_padding (GtkWidget     *widget,
-                      GtkAllocation *allocation,
-                      gpointer       user_data)
+static const char *
+cc_printers_panel_get_help_uri (CcPanel *panel)
 {
-  CcPrintersPanelPrivate *priv;
-  CcPrintersPanel        *self = (CcPrintersPanel*) user_data;
-  GtkAllocation           allocation1, allocation2;
-  GtkWidget              *label;
-  GtkWidget              *sublabel;
-  gint                    offset;
-  gint                    margin;
-
-  priv = PRINTERS_PANEL_PRIVATE (self);
-
-  sublabel = gtk_bin_get_child (GTK_BIN (widget));
-  if (sublabel)
-    {
-      gtk_widget_get_allocation (widget, &allocation1);
-      gtk_widget_get_allocation (sublabel, &allocation2);
-
-      offset = allocation2.x - allocation1.x;
-
-      label = (GtkWidget*)
-        gtk_builder_get_object (priv->builder, "printer-model-label");
-
-      margin = gtk_widget_get_margin_start (label);
-      if (offset != margin)
-        gtk_widget_set_margin_start (label, offset);
-
-      label = GTK_WIDGET (gtk_builder_get_object (priv->builder, "printer-model-setting"));
-
-      margin = gtk_widget_get_margin_start (label);
-      if (offset != margin)
-        gtk_widget_set_margin_start (label, offset);
-    }
+  return "help:gnome-help/printing";
 }
 
 static void
-jobs_dialog_response_cb (GtkDialog *dialog,
-                         gint       response_id,
-                         gpointer   user_data)
+cc_printers_panel_constructed (GObject *object)
 {
-  CcPrintersPanelPrivate *priv;
-  CcPrintersPanel        *self = (CcPrintersPanel*) user_data;
+  CcPrintersPanel *self = CC_PRINTERS_PANEL (object);
+  GtkWidget       *add_button;
+  CcShell         *shell;
 
-  priv = PRINTERS_PANEL_PRIVATE (self);
+  G_OBJECT_CLASS (cc_printers_panel_parent_class)->constructed (object);
 
-  pp_jobs_dialog_free (priv->pp_jobs_dialog);
-  priv->pp_jobs_dialog = NULL;
-}
+  /* Add "Add" button to shell header */
+  shell = cc_panel_get_shell (CC_PANEL (self));
 
-static void
-printer_jobs_cb (GtkToolButton *toolbutton,
-                 gpointer       user_data)
-{
-  CcPrintersPanelPrivate *priv;
-  CcPrintersPanel        *self = (CcPrintersPanel*) user_data;
-  GtkWidget              *widget;
-
-  priv = PRINTERS_PANEL_PRIVATE (self);
+  add_button = gtk_button_new_with_mnemonic (_("Add"));
+  gtk_style_context_add_class (gtk_widget_get_style_context (add_button),
+                              "suggested-action");
+  gtk_widget_set_visible (add_button, can_add_printer (self));
 
-  widget = (GtkWidget*)
-    gtk_builder_get_object (priv->builder, "main-vbox");
+  cc_shell_embed_widget_in_header (shell, add_button);
 
-  if (priv->current_dest >= 0 &&
-      priv->current_dest < priv->num_dests &&
-      priv->dests != NULL)
-    priv->pp_jobs_dialog = pp_jobs_dialog_new (
-      GTK_WINDOW (gtk_widget_get_toplevel (widget)),
-      jobs_dialog_response_cb,
-      self,
-      priv->dests[priv->current_dest].name);
+  g_signal_connect (GTK_BUTTON (add_button), "clicked",
+                   G_CALLBACK (printer_add_cb),
+                   self);
 }
 
 static void
-cc_printers_panel_init (CcPrintersPanel *self)
+cc_printers_panel_class_init (CcPrintersPanelClass *klass)
 {
-  CcPrintersPanelPrivate *priv;
-  GtkWidget              *top_widget;
-  GtkWidget              *widget;
-  PpCups                 *cups;
-  GError                 *error = NULL;
-  gchar                  *objects[] = { "main-vbox", NULL };
-  GtkStyleContext        *context;
-  guint                   builder_result;
-
-  priv = self->priv = PRINTERS_PANEL_PRIVATE (self);
-  g_resources_register (cc_printers_get_resource ());
-
-  /* initialize main data structure */
-  priv->builder = gtk_builder_new ();
-  priv->dests = NULL;
-  priv->dest_model_names = NULL;
-  priv->ppd_file_names = NULL;
-  priv->num_dests = 0;
-  priv->current_dest = -1;
-
-  priv->num_jobs = 0;
-
-  priv->pp_new_printer_dialog = NULL;
-  priv->pp_options_dialog = NULL;
-
-  priv->subscription_id = 0;
-  priv->cups_status_check_id = 0;
-  priv->subscription_renewal_id = 0;
-  priv->cups_proxy = NULL;
-  priv->cups_bus_connection = NULL;
-  priv->dbus_subscription_id = 0;
-
-  priv->new_printer_name = NULL;
-  priv->new_printer_location = NULL;
-  priv->new_printer_make_and_model = NULL;
-  priv->new_printer_on_network = FALSE;
-  priv->select_new_printer = FALSE;
-
-  priv->permission = NULL;
-  priv->lockdown_settings = NULL;
-
-  priv->getting_ppd_names = FALSE;
-
-  priv->all_ppds_list = NULL;
-  priv->get_all_ppds_cancellable = NULL;
-
-  priv->preferred_drivers = NULL;
-
-  builder_result = gtk_builder_add_objects_from_resource (priv->builder,
-                                                          "/org/gnome/control-center/printers/printers.ui",
-                                                          objects, &error);
-
-  if (builder_result == 0)
-    {
-      /* Translators: The XML file containing user interface can not be loaded */
-      g_warning (_("Could not load ui: %s"), error->message);
-      g_error_free (error);
-      return;
-    }
-
-  /* add the top level widget */
-  top_widget = (GtkWidget*)
-    gtk_builder_get_object (priv->builder, "main-vbox");
-
-  /* connect signals */
-  widget = (GtkWidget*)
-    gtk_builder_get_object (priv->builder, "printer-add-button");
-  g_signal_connect (widget, "clicked", G_CALLBACK (printer_add_cb), self);
-
-  widget = (GtkWidget*)
-    gtk_builder_get_object (priv->builder, "printer-add-button2");
-  g_signal_connect (widget, "clicked", G_CALLBACK (printer_add_cb), self);
-
-  widget = (GtkWidget*)
-    gtk_builder_get_object (priv->builder, "printer-remove-button");
-  g_signal_connect (widget, "clicked", G_CALLBACK (printer_remove_cb), self);
-
-  widget = (GtkWidget*)
-    gtk_builder_get_object (priv->builder, "printer-disable-switch");
-  g_signal_connect (widget, "notify::active", G_CALLBACK (printer_disable_cb), self);
-
-  widget = (GtkWidget*)
-    gtk_builder_get_object (priv->builder, "supply-drawing-area");
-  g_signal_connect (widget, "draw", G_CALLBACK (supply_levels_draw_cb), self);
-
-  widget = (GtkWidget*)
-    gtk_builder_get_object (priv->builder, "printer-default-check-button");
-  g_signal_connect (widget, "toggled", G_CALLBACK (printer_set_default_cb), self);
-
-  widget = (GtkWidget*)
-    gtk_builder_get_object (priv->builder, "print-test-page-button");
-  g_signal_connect (widget, "clicked", G_CALLBACK (test_page_cb), self);
-
-  widget = (GtkWidget*)
-    gtk_builder_get_object (priv->builder, "printer-jobs-button");
-  g_signal_connect (widget, "clicked", G_CALLBACK (printer_jobs_cb), self);
-
-  widget = (GtkWidget*)
-    gtk_builder_get_object (priv->builder, "printer-options-button");
-  g_signal_connect (widget, "clicked", G_CALLBACK (printer_options_cb), self);
-
-  widget = (GtkWidget*)
-    gtk_builder_get_object (priv->builder, "printer-name-label");
-  g_signal_connect (widget, "editing-done", G_CALLBACK (printer_name_edit_cb), self);
-
-  widget = (GtkWidget*)
-    gtk_builder_get_object (priv->builder, "printer-location-label");
-  g_signal_connect (widget, "editing-done", G_CALLBACK (printer_location_edit_cb), self);
-
-  priv->lockdown_settings = g_settings_new ("org.gnome.desktop.lockdown");
-  if (priv->lockdown_settings)
-    g_signal_connect_object (priv->lockdown_settings,
-                             "changed",
-                             G_CALLBACK (on_lockdown_settings_changed),
-                             self,
-                             G_CONNECT_AFTER);
-
-  widget = (GtkWidget*)
-    gtk_builder_get_object (priv->builder, "printer-model-button");
-  g_signal_connect (widget, "clicked", G_CALLBACK (popup_model_menu_cb), self);
-  g_signal_connect (widget, "size-allocate", G_CALLBACK (update_label_padding), self);
-
-
-  /* Set junctions */
-  widget = (GtkWidget*)
-    gtk_builder_get_object (priv->builder, "printers-scrolledwindow");
-  context = gtk_widget_get_style_context (widget);
-  gtk_style_context_set_junction_sides (context, GTK_JUNCTION_BOTTOM);
-
-  widget = (GtkWidget*)
-    gtk_builder_get_object (priv->builder, "printers-toolbar");
-  context = gtk_widget_get_style_context (widget);
-  gtk_style_context_set_junction_sides (context, GTK_JUNCTION_TOP);
-
-
-  /* Make model label and ip-address label selectable */
-  widget = (GtkWidget*)
-    gtk_builder_get_object (priv->builder, "printer-ip-address-label");
-  cc_editable_entry_set_selectable (CC_EDITABLE_ENTRY (widget), TRUE);
-
-
-  /* Add unlock button */
-  priv->permission = (GPermission *)polkit_permission_new_sync (
-    "org.opensuse.cupspkhelper.mechanism.all-edit", NULL, NULL, NULL);
-  if (priv->permission != NULL)
-    {
-      g_signal_connect_object (priv->permission,
-                               "notify",
-                               G_CALLBACK (on_permission_changed),
-                               self,
-                               G_CONNECT_AFTER);
-      on_permission_changed (priv->permission, NULL, self);
-    }
-  else
-    g_warning ("Your system does not have the cups-pk-helper's policy \
-\"org.opensuse.cupspkhelper.mechanism.all-edit\" installed. \
-Please check your installation");
-
-  priv->subscription_renew_cancellable = g_cancellable_new ();
-
-  populate_printers_list (self);
-  attach_to_cups_notifier (self);
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  CcPanelClass *panel_class = CC_PANEL_CLASS (klass);
 
-  priv->get_all_ppds_cancellable = g_cancellable_new ();
-  get_all_ppds_async (priv->get_all_ppds_cancellable,
-                      get_all_ppds_async_cb,
-                      self);
+  g_type_class_add_private (klass, sizeof (CcPrintersPanelPrivate));
 
-  cups = pp_cups_new ();
-  pp_cups_connection_test_async (cups, connection_test_cb, self);
+  object_class->get_property = cc_printers_panel_get_property;
+  object_class->set_property = cc_printers_panel_set_property;
+  object_class->dispose = cc_printers_panel_dispose;
+  object_class->finalize = cc_printers_panel_finalize;
+  object_class->constructed = cc_printers_panel_constructed;
 
-  gtk_container_add (GTK_CONTAINER (self), top_widget);
-  gtk_widget_show_all (GTK_WIDGET (self));
+  panel_class->get_permission = cc_printers_panel_get_permission;
+  panel_class->get_help_uri = cc_printers_panel_get_help_uri;
 }
diff --git a/panels/printers/details-dialog.ui b/panels/printers/details-dialog.ui
new file mode 100644
index 0000000..3ef919a
--- /dev/null
+++ b/panels/printers/details-dialog.ui
@@ -0,0 +1,163 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.18.3 -->
+<interface>
+  <requires lib="gtk+" version="3.12"/>
+  <object class="GtkDialog" id="details-dialog">
+    <property name="can_focus">False</property>
+    <property name="border_width">0</property>
+    <property name="resizable">False</property>
+    <property name="modal">True</property>
+    <property name="destroy_with_parent">True</property>
+    <property name="type_hint">dialog</property>
+    <property name="use-header-bar">1</property>
+    <child internal-child="vbox">
+      <object class="GtkBox">
+        <property name="margin">20</property>
+        <property name="halign">center</property>
+        <child>
+          <object class="GtkGrid">
+            <property name="row-spacing">10</property>
+            <property name="column-spacing">10</property>
+            <child>
+              <object class="GtkLabel">
+                <property name="label" translatable="yes">Name</property>
+                <property name="halign">end</property>
+                <style>
+                  <class name="dim-label"/>
+                </style>
+              </object>
+              <packing>
+                <property name="left-attach">0</property>
+                <property name="top-attach">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkEntry" id="printer-name-entry">
+                <property name="halign">fill</property>
+                <property name="width_request">320</property>
+              </object>
+              <packing>
+                <property name="left-attach">1</property>
+                <property name="top-attach">0</property>
+              </packing>
+            </child>
+
+            <child>
+              <object class="GtkLabel">
+                <property name="label" translatable="yes">Location</property>
+                <property name="halign">end</property>
+                <style>
+                  <class name="dim-label"/>
+                </style>
+              </object>
+              <packing>
+                <property name="left-attach">0</property>
+                <property name="top-attach">2</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkEntry" id="printer-location-entry">
+                <property name="width_request">320</property>
+                <property name="halign">fill</property>
+              </object>
+              <packing>
+                <property name="left-attach">1</property>
+                <property name="top-attach">2</property>
+              </packing>
+            </child>
+
+            <child>
+              <object class="GtkLabel">
+                <property name="label" translatable="yes">Address</property>
+                <property name="halign">end</property>
+                <style>
+                  <class name="dim-label"/>
+                </style>
+              </object>
+              <packing>
+                <property name="left-attach">0</property>
+                <property name="top-attach">3</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="printer-address-label">
+                <property name="label">192.168.0.1</property>
+                <property name="halign">start</property>
+              </object>
+              <packing>
+                <property name="left-attach">1</property>
+                <property name="top-attach">3</property>
+              </packing>
+            </child>
+
+            <child>
+              <object class="GtkLabel">
+                <property name="label" translatable="yes">Driver</property>
+                <property name="halign">end</property>
+                <style>
+                  <class name="dim-label"/>
+                </style>
+              </object>
+              <packing>
+                <property name="left-attach">0</property>
+                <property name="top-attach">4</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="printer-model-label">
+                <property name="label">HP Inkjet Delux 9000</property>
+                <property name="halign">start</property>
+              </object>
+              <packing>
+                <property name="left-attach">1</property>
+                <property name="top-attach">4</property>
+              </packing>
+            </child>
+
+            <child>
+              <object class="GtkButtonBox">
+                <property name="orientation">vertical</property>
+                <property name="spacing">10</property>
+                <property name="halign">start</property>
+                <child>
+                  <object class="GtkButton" id="search-for-drivers-button">
+                    <property name="label" translatable="yes">Search for Drivers</property>
+                    <property name="halign">fill</property>
+                  </object>
+                </child>
+
+                <child>
+                  <object class="GtkButton" id="select-from-database-button">
+                    <property name="label" translatable="yes">Select from Database…</property>
+                    <property name="halign">fill</property>
+                  </object>
+                </child>
+
+                <child>
+                  <object class="GtkButton" id="install-ppd-button">
+                    <property name="label" translatable="yes">Install PPD File…</property>
+                    <property name="halign">fill</property>
+                  </object>
+                </child>
+              </object>
+              <packing>
+                <property name="left-attach">1</property>
+                <property name="top-attach">5</property>
+              </packing>
+
+            </child>
+          </object>
+        </child>
+      </object>
+    </child>
+  </object>
+
+  <object class="GtkSizeGroup">
+    <property name="mode">horizontal</property>
+    <widgets>
+      <widget name="search-for-drivers-button"/>
+      <widget name="select-from-database-button"/>
+      <widget name="install-ppd-button"/>
+    </widgets>
+  </object>
+</interface>
diff --git a/panels/printers/pp-details-dialog.c b/panels/printers/pp-details-dialog.c
new file mode 100644
index 0000000..a190e13
--- /dev/null
+++ b/panels/printers/pp-details-dialog.c
@@ -0,0 +1,365 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright 2016  Red Hat, Inc,
+ *
+ * This program 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Felipe Borges <feborges redhat com>
+ */
+
+#include "config.h"
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib/gstdio.h>
+#include <gtk/gtk.h>
+
+#include <cups/cups.h>
+#include <cups/ppd.h>
+
+#include "cc-editable-entry.h"
+#include "pp-details-dialog.h"
+#include "pp-ppd-selection-dialog.h"
+#include "pp-utils.h"
+
+struct _PpDetailsDialog {
+  GtkBuilder *builder;
+  GtkWidget  *parent;
+
+  GtkWidget  *dialog;
+
+  UserResponseCallback user_callback;
+  gpointer             user_data;
+
+  gchar        *printer_name;
+  gchar        *ppd_file_name;
+  PPDList      *all_ppds_list;
+  GCancellable *get_all_ppds_cancellable;
+
+  /* Dialogs */
+  PpPPDSelectionDialog *pp_ppd_selection_dialog;
+};
+
+static gboolean
+printer_name_edit_cb (GtkWidget *entry,
+                      GdkEventFocus *event,
+                      PpDetailsDialog *dialog)
+{
+  const gchar *new_name;
+
+  // FIXME: update the header bar title
+
+  new_name = gtk_entry_get_text (GTK_ENTRY (entry));
+
+  printer_rename (dialog->printer_name, new_name); // FIXME: it has to be async
+
+  dialog->printer_name = g_strdup (new_name);
+
+  return FALSE;
+}
+
+static gboolean
+printer_location_edit_cb (GtkWidget *entry,
+                          GdkEventFocus *event,
+                          PpDetailsDialog *dialog)
+{
+  const gchar             *location;
+
+  location = gtk_entry_get_text (GTK_ENTRY (entry));
+
+  // FIXME: do this async
+  // FIXME: actualize printers list
+  printer_set_location (dialog->printer_name, location);
+
+  return FALSE;
+}
+
+static void
+search_for_drivers (GtkButton       *button,
+                    PpDetailsDialog *dialog)
+{
+  g_print ("search_for_drivers\n");
+}
+
+static void
+set_ppd_cb (gchar    *printer_name,
+            gboolean  success,
+            gpointer  user_data)
+{
+  PpDetailsDialog *dialog = (PpDetailsDialog*) user_data;
+  GtkWidget *widget;
+
+  widget = (GtkWidget *) gtk_builder_get_object (dialog->builder, "printer-model-label");
+  gtk_label_set_text (GTK_LABEL (widget), dialog->ppd_file_name);
+}
+
+static void
+ppd_selection_dialog_response_cb (GtkDialog *dialog,
+                                  gint       response_id,
+                                  gpointer   user_data)
+{
+  PpDetailsDialog *self = (PpDetailsDialog*) user_data;
+
+  if (response_id == GTK_RESPONSE_OK)
+    {
+      gchar *ppd_name;
+
+      ppd_name = pp_ppd_selection_dialog_get_ppd_name (self->pp_ppd_selection_dialog);
+
+      if (self->printer_name && ppd_name)
+        {
+          GCancellable *cancellable;
+
+          cancellable = g_cancellable_new ();
+
+          printer_set_ppd_async (self->printer_name,
+                                 ppd_name,
+                                 cancellable,
+                                 set_ppd_cb,
+                                 self);
+
+          self->ppd_file_name = g_strdup (ppd_name);
+        }
+
+      g_free (ppd_name);
+    }
+
+  pp_ppd_selection_dialog_free (self->pp_ppd_selection_dialog);
+  self->pp_ppd_selection_dialog = NULL;
+}
+
+static void
+select_ppd_in_dialog (GtkButton       *button,
+                      PpDetailsDialog *self)
+{
+  gchar                  *device_id = NULL;
+  gchar                  *manufacturer = NULL;
+
+  self->ppd_file_name = g_strdup (cupsGetPPD (self->printer_name));
+
+  if (!self->pp_ppd_selection_dialog)
+    {
+      device_id =
+        get_ppd_attribute (self->ppd_file_name,
+                           "1284DeviceID");
+
+      if (device_id)
+        {
+          manufacturer = get_tag_value (device_id, "mfg");
+          if (!manufacturer)
+            manufacturer = get_tag_value (device_id, "manufacturer");
+          }
+
+        if (manufacturer == NULL)
+          {
+            manufacturer =
+              get_ppd_attribute (self->ppd_file_name,
+                                 "Manufacturer");
+          }
+
+        if (manufacturer == NULL)
+          {
+            manufacturer = g_strdup ("Raw");
+          }
+
+      self->pp_ppd_selection_dialog = pp_ppd_selection_dialog_new (
+        GTK_WINDOW (gtk_widget_get_toplevel (self->dialog)),
+        NULL,
+        manufacturer,
+        ppd_selection_dialog_response_cb,
+        self);
+
+      g_free (manufacturer);
+      g_free (device_id);
+    }
+}
+
+static void
+select_ppd_manually (GtkButton       *button,
+                     PpDetailsDialog *self)
+{
+  GtkFileFilter          *filter;
+  GtkWidget              *dialog;
+
+  dialog = gtk_file_chooser_dialog_new (_("Select PPD File"),
+                                        GTK_WINDOW (self->dialog),
+                                        GTK_FILE_CHOOSER_ACTION_OPEN,
+                                        _("_Cancel"), GTK_RESPONSE_CANCEL,
+                                        _("_Open"), GTK_RESPONSE_ACCEPT,
+                                        NULL);
+
+  filter = gtk_file_filter_new ();
+  gtk_file_filter_set_name (filter,
+    _("PostScript Printer Description files (*.ppd, *.PPD, *.ppd.gz, *.PPD.gz, *.PPD.GZ)"));
+  gtk_file_filter_add_pattern (filter, "*.ppd");
+  gtk_file_filter_add_pattern (filter, "*.PPD");
+  gtk_file_filter_add_pattern (filter, "*.ppd.gz");
+  gtk_file_filter_add_pattern (filter, "*.PPD.gz");
+  gtk_file_filter_add_pattern (filter, "*.PPD.GZ");
+
+  gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (dialog), filter);
+
+  if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
+    {
+      gchar *ppd_filename;
+
+      ppd_filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
+
+      if (self->printer_name && ppd_filename)
+        {
+          GCancellable *cancellable;
+
+          cancellable = g_cancellable_new ();
+
+          printer_set_ppd_file_async (self->printer_name,
+                                      ppd_filename,
+                                      cancellable,
+                                      set_ppd_cb,
+                                      self);
+        }
+
+      g_free (ppd_filename);
+    }
+
+  gtk_widget_destroy (dialog);
+}
+
+static void
+get_all_ppds_async_cb (PPDList  *ppds,
+                       gpointer  user_data)
+{
+  PpDetailsDialog *self = user_data;
+
+  self->all_ppds_list = ppds;
+
+  if (self->pp_ppd_selection_dialog)
+    pp_ppd_selection_dialog_set_ppd_list (self->pp_ppd_selection_dialog,
+                                          self->all_ppds_list);
+
+  g_object_unref (self->get_all_ppds_cancellable);
+  self->get_all_ppds_cancellable = NULL;
+}
+
+PpDetailsDialog *
+pp_details_dialog_new (GtkWindow            *parent,
+                       UserResponseCallback  user_callback,
+                       gpointer              user_data,
+                       gchar                *printer_name,
+                       gchar                *printer_location,
+                       gchar                *printer_address,
+                       gchar                *printer_make_and_model,
+                       gboolean              sensitive)
+{
+  PpDetailsDialog *dialog;
+  GtkWidget       *widget;
+  GError          *error = NULL;
+  gchar           *objects[] = { "details-dialog", NULL };
+  gchar           *title;
+  gchar           *printer_url;
+  guint            builder_result;
+
+  dialog = g_new0 (PpDetailsDialog, 1);
+
+  dialog->builder = gtk_builder_new ();
+  dialog->parent = GTK_WIDGET (parent);
+
+  builder_result = gtk_builder_add_objects_from_resource (dialog->builder,
+                                                          
"/org/gnome/control-center/printers/details-dialog.ui",
+                                                          objects, &error);
+  if (builder_result == 0)
+    {
+      g_warning ("Could not load ui: %s", error->message);
+      g_error_free (error);
+      return NULL;
+    }
+
+  dialog->dialog = (GtkWidget *) gtk_builder_get_object (dialog->builder, "details-dialog");
+  dialog->user_callback = user_callback;
+  dialog->user_data = user_data;
+  dialog->printer_name = g_strdup (printer_name);
+  dialog->ppd_file_name = NULL;
+
+  title = g_strdup_printf (C_("Printer Details dialog title", "%s Details"), printer_name);
+  gtk_window_set_title (GTK_WINDOW (dialog->dialog), title);
+
+  widget = (GtkWidget *) gtk_builder_get_object (dialog->builder, "printer-address-label");
+  printer_url = g_strdup_printf ("<a href=\"http://%s\";>%s</a>", printer_address, printer_address);
+  gtk_label_set_markup (GTK_LABEL (widget), printer_url);
+  g_free (printer_url);
+
+  /* connect signals */
+  widget = (GtkWidget *) gtk_builder_get_object (dialog->builder, "printer-name-entry");
+  gtk_entry_set_text (GTK_ENTRY (widget), printer_name);
+  g_signal_connect (widget, "focus-out-event", G_CALLBACK (printer_name_edit_cb), dialog);
+
+  widget = (GtkWidget *) gtk_builder_get_object (dialog->builder, "printer-location-entry");
+  gtk_entry_set_text (GTK_ENTRY (widget), printer_location);
+  g_signal_connect (widget, "focus-out-event", G_CALLBACK (printer_location_edit_cb), dialog);
+
+  widget = (GtkWidget *) gtk_builder_get_object (dialog->builder, "printer-model-label");
+  gtk_label_set_text (GTK_LABEL (widget), printer_make_and_model);
+
+  widget = (GtkWidget *) gtk_builder_get_object (dialog->builder, "search-for-drivers-button");
+  g_signal_connect (widget, "clicked", G_CALLBACK (search_for_drivers), dialog);
+
+  widget = (GtkWidget *) gtk_builder_get_object (dialog->builder, "select-from-database-button");
+  g_signal_connect (widget, "clicked", G_CALLBACK (select_ppd_in_dialog), dialog);
+
+  widget = (GtkWidget *) gtk_builder_get_object (dialog->builder, "install-ppd-button");
+  g_signal_connect (widget, "clicked", G_CALLBACK (select_ppd_manually), dialog);
+
+  gtk_window_set_transient_for (GTK_WINDOW (dialog->dialog), GTK_WINDOW (parent));
+  gtk_widget_show_all (GTK_WIDGET (dialog->dialog));
+
+  if (dialog->all_ppds_list == NULL)
+    {
+      dialog->get_all_ppds_cancellable = g_cancellable_new ();
+      get_all_ppds_async (dialog->get_all_ppds_cancellable, get_all_ppds_async_cb, dialog);
+    }
+
+  return dialog;
+}
+
+void
+pp_details_dialog_free (PpDetailsDialog *dialog)
+{
+  gtk_widget_destroy (GTK_WIDGET (dialog->dialog));
+  dialog->dialog = NULL;
+
+  g_object_unref (dialog->builder);
+  dialog->builder = NULL;
+
+  g_free (dialog->printer_name);
+  dialog->printer_name = NULL;
+
+  if (dialog->all_ppds_list)
+    {
+      ppd_list_free (dialog->all_ppds_list);
+      dialog->all_ppds_list = NULL;
+    }
+
+  if (dialog->get_all_ppds_cancellable)
+    {
+      g_cancellable_cancel (dialog->get_all_ppds_cancellable);
+      g_object_unref (dialog->get_all_ppds_cancellable);
+      dialog->get_all_ppds_cancellable = NULL;
+    }
+
+  g_free (dialog);
+}
diff --git a/panels/printers/pp-details-dialog.h b/panels/printers/pp-details-dialog.h
new file mode 100644
index 0000000..5d9d10a
--- /dev/null
+++ b/panels/printers/pp-details-dialog.h
@@ -0,0 +1,43 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright 2016  Red Hat, Inc,
+ *
+ * This program 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Felipe Borges <feborges redhat com>
+ */
+
+#ifndef __PP_DETAILS_DIALOG_H__
+#define __PP_DETAILS_DIALOG_H__
+
+#include <gtk/gtk.h>
+#include "pp-utils.h"
+
+G_BEGIN_DECLS
+
+typedef struct _PpDetailsDialog PpDetailsDialog;
+
+PpDetailsDialog *pp_details_dialog_new  (GtkWindow            *parent,
+                                         UserResponseCallback  user_callback,
+                                         gpointer              user_data,
+                                         gchar                *printer_name,
+                                         gchar                *printer_location,
+                                         gchar                *printer_address,
+                                         gchar                *printer_make_and_model,
+                                         gboolean              sensitive);
+void             pp_details_dialog_free (PpDetailsDialog      *dialog);
+
+G_END_DECLS
+
+#endif
diff --git a/panels/printers/pp-printer-entry.c b/panels/printers/pp-printer-entry.c
new file mode 100644
index 0000000..1e6e863
--- /dev/null
+++ b/panels/printers/pp-printer-entry.c
@@ -0,0 +1,547 @@
+/*
+ * Copyright 2016  Red Hat, Inc
+ *
+ * This program 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Felipe Borges <feborges redhat com>
+ */
+
+#include <config.h>
+
+#include "pp-printer-entry.h"
+#include <gtk/gtk.h>
+#include <glib/gi18n-lib.h>
+#include <glib/gstdio.h>
+
+#include "pp-details-dialog.h"
+#include "pp-options-dialog.h"
+#include "pp-jobs-dialog.h"
+#include "pp-utils.h"
+
+#define SUPPLY_BAR_HEIGHT 12
+
+struct _PpPrinterEntry
+{
+  GtkBox parent;
+
+  gchar    *printer_uri;
+  gchar    *printer_name;
+  gchar    *ppd_file_name;
+  int       num_jobs;
+  gboolean  is_accepting_jobs;
+  gchar    *printer_make_and_model;
+  gchar    *printer_location;
+  gchar    *printer_hostname;
+
+  /* Widgets */
+  GtkImage       *printer_icon;
+  GtkLabel       *printer_status;
+  GtkLabel       *printer_name_label;
+  GtkLabel       *printer_model_label;
+  GtkLabel       *printer_model;
+  GtkLabel       *printer_location_label;
+  GtkLabel       *printer_location_address_label;
+  GtkDrawingArea *supply_drawing_area;
+  GtkWidget      *show_jobs_dialog_button;
+  GtkCheckButton *printer_default_checkbutton;
+
+  /* Dialogs */
+  PpOptionsDialog *pp_options_dialog;
+  PpDetailsDialog *pp_details_dialog;
+  PpJobsDialog    *pp_jobs_dialog;
+};
+
+struct _PpPrinterEntryClass
+{
+  GtkBoxClass parent_class;
+};
+
+G_DEFINE_TYPE (PpPrinterEntry, pp_printer_entry, GTK_TYPE_BOX)
+
+static void
+pp_printer_entry_init (PpPrinterEntry *self)
+{
+  gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+typedef struct {
+  gchar *color;
+  gchar *type;
+  gchar *name;
+  gint   level;
+} MarkerItem;
+
+static gint
+markers_cmp (gconstpointer a,
+             gconstpointer b)
+{
+  MarkerItem *x = (MarkerItem*) a;
+  MarkerItem *y = (MarkerItem*) b;
+
+  if (x->level < y->level)
+    return 1;
+  else if (x->level == y->level)
+    return 0;
+  else
+    return -1;
+}
+
+static gchar *
+sanitize_printer_model (gchar *printer_make_and_model)
+{
+  gchar  *breakpoint = NULL, *tmp = NULL, *tmp2 = NULL;
+  gchar  *printer_model = NULL;
+  gchar   backup;
+  size_t  length = 0;
+  gchar  *forbiden[] = {
+    "foomatic",
+    ",",
+    "hpijs",
+    "hpcups",
+    "(recommended)",
+    "postscript (recommended)",
+    NULL };
+  int     i;
+
+  tmp = g_ascii_strdown (printer_make_and_model, -1);
+
+  for (i = 0; i < g_strv_length (forbiden); i++)
+    {
+      tmp2 = g_strrstr (tmp, forbiden[i]);
+      if (breakpoint == NULL ||
+         (tmp2 != NULL && tmp2 < breakpoint))
+           breakpoint = tmp2;
+    }
+
+    if (breakpoint)
+      {
+        backup = *breakpoint;
+        *breakpoint = '\0';
+        length = strlen (tmp);
+        *breakpoint = backup;
+        g_free (tmp);
+
+        if (length > 0)
+          printer_model = g_strndup (printer_make_and_model, length);
+      }
+    else
+      printer_model = g_strdup (printer_make_and_model);
+
+  return printer_model;
+}
+
+static gboolean
+supply_levels_draw_cb (GtkWidget   *widget,
+                       cairo_t     *cr,
+                       InkLevelData *inklevel)
+{
+  GtkStyleContext        *context;
+  gchar                  *tooltip_text = NULL;
+  gint                    width;
+  gint                    height;
+  int                     i;
+
+  context = gtk_widget_get_style_context (widget);
+
+  width = gtk_widget_get_allocated_width (widget);
+  height = gtk_widget_get_allocated_height (widget);
+
+  gtk_render_background (context, cr, 0, 0, width, height);
+
+  if (inklevel->marker_levels && inklevel->marker_colors && inklevel->marker_names && inklevel->marker_types)
+    {
+      GSList   *markers = NULL;
+      GSList   *tmp_list = NULL;
+      gchar   **marker_levelsv = NULL;
+      gchar   **marker_colorsv = NULL;
+      gchar   **marker_namesv = NULL;
+      gchar   **marker_typesv = NULL;
+      gchar    *tmp = NULL;
+
+      gtk_style_context_save (context);
+
+      marker_levelsv = g_strsplit (inklevel->marker_levels, ",", -1);
+      marker_colorsv = g_strsplit (inklevel->marker_colors, ",", -1);
+      marker_namesv = g_strsplit (inklevel->marker_names, ",", -1);
+      marker_typesv = g_strsplit (inklevel->marker_types, ",", -1);
+
+      if (g_strv_length (marker_levelsv) == g_strv_length (marker_colorsv) &&
+          g_strv_length (marker_colorsv) == g_strv_length (marker_namesv) &&
+          g_strv_length (marker_namesv) == g_strv_length (marker_typesv))
+        {
+          for (i = 0; i < g_strv_length (marker_levelsv); i++)
+            {
+              MarkerItem *marker;
+
+              if (g_strcmp0 (marker_typesv[i], "ink") == 0 ||
+                  g_strcmp0 (marker_typesv[i], "toner") == 0 ||
+                  g_strcmp0 (marker_typesv[i], "inkCartridge") == 0 ||
+                  g_strcmp0 (marker_typesv[i], "tonerCartridge") == 0)
+                {
+                  marker = g_new0 (MarkerItem, 1);
+                  marker->type = g_strdup (marker_typesv[i]);
+                  marker->name = g_strdup (marker_namesv[i]);
+                  marker->color = g_strdup (marker_colorsv[i]);
+                  marker->level = atoi (marker_levelsv[i]);
+
+                  markers = g_slist_prepend (markers, marker);
+                }
+            }
+
+            markers = g_slist_sort (markers, markers_cmp);
+
+            for (tmp_list = markers; tmp_list; tmp_list = tmp_list->next)
+              {
+                GdkRGBA color = {0.0, 0.0, 0.0, 1.0};
+                double  display_value;
+                int     value;
+
+                value = ((MarkerItem*) tmp_list->data)->level;
+
+                gdk_rgba_parse (&color, ((MarkerItem*) tmp_list->data)->color);
+
+                if (value > 0)
+                  {
+                    display_value = value / 100.0 * (width - 3.0);
+                    gdk_cairo_set_source_rgba (cr, &color);
+                   cairo_rectangle (cr, 3.5, 3.5, display_value, SUPPLY_BAR_HEIGHT - 3.0);
+                    cairo_fill (cr);
+                  }
+
+                if (tooltip_text)
+                  {
+                    tmp = g_strdup_printf ("%s\n%s",
+                                           tooltip_text,
+                                           ((MarkerItem*) tmp_list->data)->name);
+                    g_free (tooltip_text);
+                    tooltip_text = tmp;
+                    tmp = NULL;
+                  }
+                else
+                  tooltip_text = g_strdup_printf ("%s",
+                                                  ((MarkerItem*) tmp_list->data)->name);
+              }
+
+            gtk_render_frame (context, cr, 1, 1, width - 1, SUPPLY_BAR_HEIGHT + 3);
+
+            for (tmp_list = markers; tmp_list; tmp_list = tmp_list->next)
+              {
+                g_free (((MarkerItem*) tmp_list->data)->name);
+                g_free (((MarkerItem*) tmp_list->data)->type);
+                g_free (((MarkerItem*) tmp_list->data)->color);
+              }
+            g_slist_free_full (markers, g_free);
+          }
+
+        gtk_style_context_restore (context);
+
+      // free inkLevelData
+
+    if (tooltip_text)
+      {
+        gtk_widget_set_tooltip_text (widget, tooltip_text);
+        g_free (tooltip_text);
+      }
+    else
+      {
+        gtk_widget_set_tooltip_text (widget, NULL);
+        gtk_widget_set_has_tooltip (widget, FALSE);
+      }
+    }
+
+  return TRUE;
+}
+
+static void
+printer_options_dialog_cb (GtkDialog *dialog,
+                        gint       response_id,
+                        gpointer   user_data)
+{
+  PpPrinterEntry *self = PP_PRINTER_ENTRY (user_data);
+
+  pp_options_dialog_free (self->pp_options_dialog);
+  self->pp_options_dialog = NULL;
+}
+
+static void
+on_show_printer_options_dialog (GtkButton      *button,
+                               PpPrinterEntry *self)
+{
+  gboolean   is_authorized = TRUE; // FIXME
+
+  self->pp_options_dialog = pp_options_dialog_new (
+    GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (self))),
+    printer_options_dialog_cb,
+    self,
+    self->printer_name,
+    is_authorized);
+}
+
+static void
+details_dialog_cb (GtkDialog  *dialog,
+                  gint        response_id,
+                  gpointer    user_data)
+{
+  PpPrinterEntry *self = PP_PRINTER_ENTRY (user_data);
+
+  pp_details_dialog_free (self->pp_details_dialog);
+  self->pp_details_dialog = NULL;
+}
+
+static void
+on_show_printer_details_dialog (GtkButton      *button,
+                               PpPrinterEntry *self)
+{
+  self->pp_details_dialog = pp_details_dialog_new (
+    GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (self))),
+    details_dialog_cb,
+    self,
+    self->printer_name,
+    self->printer_location,
+    self->printer_hostname,
+    self->printer_make_and_model,
+    TRUE);
+}
+
+static void
+set_as_default_printer (GtkToggleButton *button,
+                       PpPrinterEntry  *self)
+{
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (self->printer_default_checkbutton), TRUE);
+  printer_set_default (self->printer_name);
+
+  // update printers list here
+}
+
+static void
+remove_printer (GtkButton *button,
+               PpPrinterEntry *self)
+{
+  printer_delete (self->printer_name);
+}
+
+static void
+update_jobs_count (PpPrinterEntry *self)
+{
+  cups_job_t *jobs;
+  gchar      *button_label;
+  gint       *num_paused_jobs = 0;
+  gint        num_jobs;
+  int         i;
+
+  // FIXME do this async
+  self->num_jobs = cupsGetJobs (&jobs, self->printer_name, 1, CUPS_WHICHJOBS_ACTIVE);
+  if (self->num_jobs > 0)
+    cupsFreeJobs (self->num_jobs, jobs);
+
+  num_jobs = self->num_jobs < 0 ? 0 : (guint) self->num_jobs;
+
+  for (i = 0; i < num_jobs; i++)
+    if (jobs[i].state == IPP_JOB_HELD)
+      num_paused_jobs++;
+
+  if (self->num_jobs <= 0)
+    button_label = g_strdup ("No Active Jobs");
+  else
+    if (num_paused_jobs > 0)
+      button_label = g_strdup_printf ("%u Paused Jobs", num_jobs);
+    else
+      button_label = g_strdup_printf ("%u Jobs", num_jobs);
+
+  gtk_button_set_label (GTK_BUTTON (self->show_jobs_dialog_button), button_label);
+  gtk_widget_set_sensitive (self->show_jobs_dialog_button, self->is_accepting_jobs);
+
+  g_free (button_label);
+}
+
+static void
+jobs_dialog_response_cb (GtkDialog  *dialog,
+                        gint        response_id,
+                        gpointer    user_data)
+{
+  PpPrinterEntry *self = PP_PRINTER_ENTRY (user_data);
+
+  pp_jobs_dialog_free (self->pp_jobs_dialog);
+  self->pp_jobs_dialog = NULL;
+}
+
+static void
+show_jobs_dialog (GtkButton      *button,
+                 PpPrinterEntry *self)
+{
+  self->pp_jobs_dialog = pp_jobs_dialog_new (
+    GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (self))),
+    jobs_dialog_response_cb,
+    self,
+    self->printer_name);
+}
+
+PpPrinterEntry *
+pp_printer_entry_new (cups_dest_t  printer)
+{
+  PpPrinterEntry *self;
+  InkLevelData   *inklevel;
+  cups_ptype_t    printer_type = 0;
+  gboolean        is_accepting_jobs;
+  gchar          *instance;
+  gchar          *printer_uri = NULL;
+  gchar          *location = NULL;
+  gchar          *printer_icon_name = NULL;
+  gchar          *default_icon_name = NULL;
+  gchar          *printer_make_and_model = NULL;
+  gchar          *printer_status = NULL;
+  int             printer_state = 3;
+  int             i;
+
+  self = g_object_new (PP_PRINTER_ENTRY_TYPE, NULL);
+
+  inklevel = g_slice_new0 (InkLevelData);
+
+  if (printer.instance)
+    {
+      instance = g_strdup_printf ("%s / %s", printer.name, printer.instance);
+    }
+  else
+    {
+      instance = g_strdup (printer.name);
+    }
+
+  for (i = 0; i < printer.num_options; i++)
+    {
+      if (g_strcmp0 (printer.options[i].name, "device-uri") == 0)
+        self->printer_uri = printer.options[i].value;
+      else if (g_strcmp0 (printer.options[i].name, "printer-uri-supported") == 0)
+        printer_uri = printer.options[i].value;
+      else if (g_strcmp0 (printer.options[i].name, "printer-type") == 0)
+        printer_type = atoi (printer.options[i].value);
+      else if (g_strcmp0 (printer.options[i].name, "printer-location") == 0)
+        location = printer.options[i].value;
+      else if (g_strcmp0 (printer.options[i].name, "marker-names") == 0)
+        inklevel->marker_names = g_strcompress (printer.options[i].value);
+      else if (g_strcmp0 (printer.options[i].name, "marker-levels") == 0)
+        inklevel->marker_levels = printer.options[i].value;
+      else if (g_strcmp0 (printer.options[i].name, "marker-colors") == 0)
+        inklevel->marker_colors = printer.options[i].value;
+      else if (g_strcmp0 (printer.options[i].name, "marker-types") == 0)
+        inklevel->marker_types = printer.options[i].value;
+      else if (g_strcmp0 (printer.options[i].name, "printer-make-and-model") == 0)
+        printer_make_and_model = printer.options[i].value;
+      else if (g_strcmp0 (printer.options[i].name, "printer-state") == 0)
+        printer_state = atoi (printer.options[i].value);
+      else if (g_strcmp0 (printer.options[i].name, "printer-is-accepting-jobs") == 0)
+        {
+          if (g_strcmp0 (printer.options[i].value, "true") == 0)
+            is_accepting_jobs = TRUE;
+          else
+            is_accepting_jobs = FALSE;
+        }
+    }
+
+  switch (printer_state)
+    {
+      case 3:
+        if (is_accepting_jobs)
+          {
+            /* Translators: Printer's state (can start new job without waiting) */
+            printer_status = g_strdup ( C_("printer state", "Ready"));
+          }
+        else
+          {
+            /* Translators: Printer's state (printer is ready but doesn't accept new jobs) */
+            printer_status = g_strdup ( C_("printer state", "Does not accept jobs"));
+          }
+        break;
+      case 4:
+        /* Translators: Printer's state (jobs are processing) */
+        printer_status = g_strdup ( C_("printer state", "Processing"));
+        break;
+      case 5:
+        /* Translators: Printer's state (no jobs can be processed) */
+        printer_status = g_strdup ( C_("printer state", "Stopped"));
+        break;
+    }
+
+  if (printer_is_local (printer_type, self->printer_uri))
+    printer_icon_name = g_strdup ("printer");
+  else
+    printer_icon_name = g_strdup ("printer-network");
+
+  self->printer_name = printer.name;
+  self->is_accepting_jobs = is_accepting_jobs;
+  self->printer_make_and_model = printer_make_and_model;
+  self->printer_location = location;
+
+  self->printer_hostname = printer_get_hostname (printer_type, self->printer_uri, printer_uri);
+
+  gtk_image_set_from_icon_name (self->printer_icon, printer_icon_name, GTK_ICON_SIZE_DIALOG);
+  gtk_label_set_text (self->printer_status, printer_status);
+  gtk_label_set_text (self->printer_name_label, instance);
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (self->printer_default_checkbutton), printer.is_default);
+
+  self->printer_make_and_model = sanitize_printer_model (printer_make_and_model);
+
+  if (self->printer_make_and_model == NULL)
+    {
+      gtk_widget_hide (GTK_WIDGET (self->printer_model_label));
+      gtk_widget_hide (GTK_WIDGET (self->printer_model));
+    }
+
+  gtk_label_set_text (self->printer_model, self->printer_make_and_model);
+
+  if (location[0] == '\0')
+    {
+      gtk_widget_hide (GTK_WIDGET (self->printer_location_label));
+      gtk_widget_hide (GTK_WIDGET (self->printer_location_address_label));
+    }
+
+  gtk_label_set_text (self->printer_location_address_label, location);
+
+  g_signal_connect (self->supply_drawing_area, "draw", G_CALLBACK (supply_levels_draw_cb), inklevel);
+
+  update_jobs_count (self);
+
+  self->pp_options_dialog = NULL;
+  self->pp_details_dialog = NULL;
+  self->pp_jobs_dialog = NULL;
+
+  g_free (printer_icon_name);
+  g_free (default_icon_name);
+
+  return self;
+}
+
+static void
+pp_printer_entry_class_init (PpPrinterEntryClass *klass)
+{
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+  gtk_widget_class_set_template_from_resource (widget_class, 
"/org/gnome/control-center/printers/printer-entry.ui");
+
+  gtk_widget_class_bind_template_child (widget_class, PpPrinterEntry, printer_icon);
+  gtk_widget_class_bind_template_child (widget_class, PpPrinterEntry, printer_name_label);
+  gtk_widget_class_bind_template_child (widget_class, PpPrinterEntry, printer_status);
+  gtk_widget_class_bind_template_child (widget_class, PpPrinterEntry, printer_model_label);
+  gtk_widget_class_bind_template_child (widget_class, PpPrinterEntry, printer_model);
+  gtk_widget_class_bind_template_child (widget_class, PpPrinterEntry, printer_location_label);
+  gtk_widget_class_bind_template_child (widget_class, PpPrinterEntry, printer_location_address_label);
+  gtk_widget_class_bind_template_child (widget_class, PpPrinterEntry, supply_drawing_area);
+  gtk_widget_class_bind_template_child (widget_class, PpPrinterEntry, printer_default_checkbutton);
+  gtk_widget_class_bind_template_child (widget_class, PpPrinterEntry, show_jobs_dialog_button);
+
+  gtk_widget_class_bind_template_callback (widget_class, on_show_printer_options_dialog);
+  gtk_widget_class_bind_template_callback (widget_class, on_show_printer_details_dialog);
+  gtk_widget_class_bind_template_callback (widget_class, set_as_default_printer);
+  gtk_widget_class_bind_template_callback (widget_class, remove_printer);
+  gtk_widget_class_bind_template_callback (widget_class, show_jobs_dialog);
+}
diff --git a/panels/printers/pp-printer-entry.h b/panels/printers/pp-printer-entry.h
new file mode 100644
index 0000000..fce1e2c
--- /dev/null
+++ b/panels/printers/pp-printer-entry.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2016  Red Hat, Inc
+ *
+ * This program 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Felipe Borges <feborges redhat com>
+ */
+
+#ifndef PP_PRINTER_ENTRY_H
+#define PP_PRINTER_ENTRY_H
+
+#include <gtk/gtk.h>
+#include <cups/cups.h>
+
+#define PP_PRINTER_ENTRY_TYPE (pp_printer_entry_get_type ())
+#define PP_PRINTER_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PP_PRINTER_ENTRY_TYPE, PpPrinterEntry))
+
+typedef struct _PpPrinterEntry         PpPrinterEntry;
+typedef struct _PpPrinterEntryClass    PpPrinterEntryClass;
+
+typedef struct
+{
+  gchar *marker_names;
+  gchar *marker_levels;
+  gchar *marker_colors;
+  gchar *marker_types;
+} InkLevelData;
+
+GType          pp_printer_entry_get_type       (void);
+
+PpPrinterEntry *pp_printer_entry_new           (cups_dest_t printer);
+
+#endif /* PP_PRINTER_ENTRY_H */
diff --git a/panels/printers/printer-entry.ui b/panels/printers/printer-entry.ui
new file mode 100644
index 0000000..e0a84c7
--- /dev/null
+++ b/panels/printers/printer-entry.ui
@@ -0,0 +1,260 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <!-- interface-requires gtk+ 3.8 -->
+  <object class="GtkPopover" id="printer-menu">
+    <child>
+      <object class="GtkGrid">
+        <property name="visible">True</property>
+        <property name="margin">10</property>
+        <child>
+          <object class="GtkModelButton">
+           <property name="visible">True</property>
+           <property name="text" translatable="yes">Printing Options</property>
+            <signal name="clicked" handler="on_show_printer_options_dialog"/>
+         </object>
+          <packing>
+            <property name="left-attach">1</property>
+            <property name="top-attach">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkModelButton">
+            <property name="visible">True</property>
+           <property name="text" translatable="yes">Printer Details</property>
+           <signal name="clicked" handler="on_show_printer_details_dialog"/>
+         </object>
+          <packing>
+            <property name="left-attach">1</property>
+            <property name="top-attach">1</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkCheckButton" id="printer_default_checkbutton">
+            <property name="visible">True</property>
+            <property name="valign">center</property>
+            <signal name="toggled" handler="set_as_default_printer"/>
+          </object>
+          <packing>
+            <property name="left-attach">0</property>
+            <property name="top-attach">2</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkModelButton">
+            <property name="visible">True</property>
+           <property name="text" translatable="yes">Use Printer by Default</property>
+           <signal name="clicked" handler="set_as_default_printer"/>
+         </object>
+          <packing>
+            <property name="left-attach">1</property>
+            <property name="top-attach">2</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkModelButton" id="remove_printer_menuitem">
+            <property name="visible">True</property>
+           <property name="text" translatable="yes">Remove Printer</property>
+           <signal name="clicked" handler="remove_printer"/>
+         </object>
+          <packing>
+            <property name="left-attach">1</property>
+            <property name="top-attach">3</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+  </object>
+
+  <template class="PpPrinterEntry" parent="GtkBox">
+    <child>
+      <object class="GtkFrame" id="content_area">
+        <property name="visible">True</property>
+        <property name="valign">start</property>
+        <style>
+          <class name="view"/>
+        </style>
+        <child>
+          <object class="GtkGrid">
+            <property name="visible">True</property>
+            <property name="row-spacing">10</property>
+            <property name="column-spacing">15</property>
+            <property name="margin_start">20</property>
+            <property name="margin_end">20</property>
+            <property name="margin_top">5</property>
+            <property name="margin_bottom">20</property>
+            <property name="no-show-all">True</property>
+            <child>
+              <object class="GtkImage" id="printer_icon">
+                <property name="visible">True</property>
+                <property name="pixel-size">64</property>
+                <property name="icon_name">printer</property>
+                <property name="halign">end</property>
+              </object>
+              <packing>
+                <property name="left-attach">0</property>
+                <property name="top-attach">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkGrid" id="printer_name_grid">
+                <property name="visible">True</property>
+                <property name="margin">10</property>
+                <property name="margin_start">0</property>
+                <property name="halign">start</property>
+                <child>
+                 <object class="GtkLabel" id="printer_name_label">
+                   <property name="visible">True</property>
+                   <property name="halign">start</property>
+                   <property name="ellipsize">PANGO_ELLIPSIZE_MIDDLE</property>
+                   <property name="max-width-chars">30</property>
+                   <attributes>
+                     <attribute name="weight" value="bold"/>
+                      <attribute name="scale" value="1.5"/>
+                   </attributes>
+                  </object>
+                  <packing>
+                    <property name="left-attach">0</property>
+                    <property name="top-attach">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="printer_status">
+                   <property name="visible">True</property>
+                    <property name="halign">start</property>
+                  </object>
+                  <packing>
+                    <property name="left-attach">0</property>
+                    <property name="top-attach">1</property>
+                  </packing>
+                </child>
+              </object>
+              <packing>
+                <property name="left-attach">1</property>
+                <property name="top-attach">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkBox">
+                <property name="visible">True</property>
+                <property name="spacing">5</property>
+                <property name="orientation">horizontal</property>
+                <child>
+                  <object class="GtkButton" id="show_jobs_dialog_button">
+                    <property name="visible">True</property>
+                    <property name="valign">center</property>
+                    <property name="can_focus">True</property>
+                    <signal name="clicked" handler="show_jobs_dialog"/>
+                  </object>
+                </child>
+                <child>
+                  <object class="GtkMenuButton">
+                    <property name="visible">True</property>
+                    <property name="valign">center</property>
+                    <property name="popover">printer-menu</property>
+                    <child>
+                      <object class="GtkImage">
+                        <property name="visible">True</property>
+                        <property name="icon_name">emblem-system-symbolic</property>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+              </object>
+              <packing>
+                <property name="left-attach">2</property>
+                <property name="top-attach">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="printer_model_label">
+                <property name="visible">True</property>
+                <property name="label" translatable="yes">Model</property>
+                <property name="ellipsize">PANGO_ELLIPSIZE_MIDDLE</property>
+               <property name="max-width-chars">30</property>
+                <property name="halign">end</property>
+                <style>
+                  <class name="dim-label"/>
+                </style>
+              </object>
+              <packing>
+                <property name="left-attach">0</property>
+                <property name="top-attach">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="printer_model">
+               <property name="visible">True</property>
+                <property name="halign">start</property>
+              </object>
+              <packing>
+                <property name="left-attach">1</property>
+                <property name="top-attach">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="printer_location_label">
+                <property name="visible">True</property>
+                <property name="label" translatable="yes">Location</property>
+                <property name="ellipsize">PANGO_ELLIPSIZE_MIDDLE</property>
+               <property name="max-width-chars">30</property>
+                <property name="halign">end</property>
+                <style>
+                  <class name="dim-label"/>
+                </style>
+              </object>
+              <packing>
+                <property name="left-attach">0</property>
+                <property name="top-attach">2</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="printer_location_address_label">
+               <property name="visible">True</property>
+                <property name="halign">start</property>
+              </object>
+              <packing>
+                <property name="left-attach">1</property>
+                <property name="top-attach">2</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="printer_inklevel_label">
+               <property name="visible">True</property>
+                <property name="label" translatable="yes">Ink Level</property>
+                <property name="halign">end</property>
+                <style>
+                  <class name="dim-label"/>
+                </style>
+              </object>
+              <packing>
+                <property name="left-attach">0</property>
+                <property name="top-attach">3</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkFrame" id="supply_frame">
+                <property name="visible">True</property>
+                <property name="width_request">300</property>
+                <property name="halign">start</property>
+                <property name="shadow_type">in</property>
+                <property name="halign">start</property>
+                <property name="margin_top">1</property>
+                <child>
+                  <object class="GtkDrawingArea" id="supply_drawing_area">
+                    <property name="visible">True</property>
+                    <property name="margin_top">1</property>
+                  </object>
+                </child>
+              </object>
+              <packing>
+                <property name="left-attach">1</property>
+                <property name="top-attach">3</property>
+              </packing>
+            </child>
+          </object>
+        </child>
+     </object>
+    </child>
+  </template>
+
+</interface>
diff --git a/panels/printers/printers.gresource.xml b/panels/printers/printers.gresource.xml
index 607055e..4644752 100644
--- a/panels/printers/printers.gresource.xml
+++ b/panels/printers/printers.gresource.xml
@@ -5,7 +5,9 @@
     <file preprocess="xml-stripblanks">jobs-dialog.ui</file>
     <file preprocess="xml-stripblanks">new-printer-dialog.ui</file>
     <file preprocess="xml-stripblanks">options-dialog.ui</file>
+    <file preprocess="xml-stripblanks">details-dialog.ui</file>
     <file preprocess="xml-stripblanks">ppd-selection-dialog.ui</file>
+    <file preprocess="xml-stripblanks">printer-entry.ui</file>
     <file preprocess="xml-stripblanks">printers.ui</file>
   </gresource>
 </gresources>
diff --git a/panels/printers/printers.ui b/panels/printers/printers.ui
index f27efca..1644107 100644
--- a/panels/printers/printers.ui
+++ b/panels/printers/printers.ui
@@ -2,682 +2,88 @@
 <interface>
   <requires lib="gtk+" version="3.12"/>
   <!-- interface-naming-policy project-wide -->
-  <object class="GtkBox" id="main-vbox">
-    <property name="border_width">10</property>
-    <property name="orientation">vertical</property>
-    <property name="spacing">10</property>
-    <property name="margin-start">6</property>
-    <property name="margin-end">6</property>
-    <property name="margin-top">6</property>
-    <property name="margin-bottom">6</property>
+  <object class="GtkStack" id="main-vbox">
+    <property name="visible">True</property>
+    <property name="can_focus">True</property>
+    <property name="height_request">560</property>
     <child>
-      <object class="GtkBox" id="hbox1">
+      <object class="GtkScrolledWindow">
         <property name="visible">True</property>
-        <property name="spacing">10</property>
+        <property name="can_focus">True</property>
+        <property name="shadow_type">none</property>
+        <property name="hscrollbar_policy">never</property>
+        <property name="expand">True</property>
         <child>
-          <object class="GtkBox" id="vbox4">
+          <object class="GtkBox" id="content">
             <property name="visible">True</property>
             <property name="orientation">vertical</property>
-            <child>
-              <object class="GtkScrolledWindow" id="printers-scrolledwindow">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="hscrollbar_policy">never</property>
-                <property name="vscrollbar_policy">automatic</property>
-                <property name="shadow_type">in</property>
-                <child>
-                  <object class="GtkTreeView" id="printers-treeview">
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="headers_visible">False</property>
-                    <property name="width-request">200</property>
-                  </object>
-                </child>
-              </object>
-              <packing>
-                <property name="expand">True</property>
-                <property name="position">0</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkToolbar" id="printers-toolbar">
-                <property name="visible">True</property>
-                <property name="icon_size">1</property>
-                <property name="icon_size_set">True</property>
-                <property name="toolbar-style">icons</property>
-                <style>
-                  <class name="inline-toolbar"/>
-                </style>
-                <child>
-                  <object class="GtkToolButton" id="printer-add-button">
-                    <property name="visible">True</property>
-                    <property name="sensitive">True</property>
-                    <property name="use_underline">True</property>
-                    <property name="icon_name">list-add-symbolic</property>
-                    <property name="label" translatable="yes">Add Printer</property>
-                  </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="homogeneous">True</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkToolButton" id="printer-remove-button">
-                    <property name="visible">True</property>
-                    <property name="use_underline">True</property>
-                    <property name="icon_name">list-remove-symbolic</property>
-                    <property name="label" translatable="yes">Remove Printer</property>
-                  </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="homogeneous">True</property>
-                  </packing>
-                </child>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="position">1</property>
-              </packing>
-            </child>
+            <property name="spacing">20</property>
+            <property name="halign">center</property>
+            <property name="margin_top">30</property>
+          </object>
+        </child>
+      </object>
+      <packing>
+        <property name="name">printers-list</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkBox">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="spacing">10</property>
+        <property name="orientation">vertical</property>
+        <property name="valign">center</property>
+        <child>
+          <object class="GtkImage">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="valign">start</property>
+            <property name="pixel_size">64</property>
+            <property name="icon_name">printer-symbolic</property>
+            <style>
+              <class name="dim-label"/>
+            </style>
           </object>
           <packing>
             <property name="expand">False</property>
+            <property name="fill">False</property>
             <property name="position">0</property>
           </packing>
         </child>
         <child>
-          <object class="GtkNotebook" id="notebook">
+          <object class="GtkLabel">
             <property name="visible">True</property>
-            <property name="can_focus">True</property>
-            <property name="show_tabs">False</property>
-            <property name="show_border">False</property>
-            <child>
-              <object class="GtkBox" id="vbox1">
-                <property name="visible">True</property>
-                <property name="orientation">vertical</property>
-                <property name="spacing">10</property>
-                <child>
-                  <object class="GtkTable" id="table1">
-                    <property name="visible">True</property>
-                    <property name="n_rows">8</property>
-                    <property name="n_columns">3</property>
-                    <property name="column_spacing">6</property>
-                    <property name="row_spacing">6</property>
-                    <child>
-                      <object class="GtkLabel" id="supply-label">
-                        <property name="visible">True</property>
-                        <property name="xalign">1</property>
-                        <property name="label" translatable="yes" comments="Translators: By supply we mean 
ink, toner, staples, water, ...">Supply</property>
-                        <style>
-                          <class name="dim-label"/>
-                        </style>
-                      </object>
-                      <packing>
-                        <property name="top_attach">5</property>
-                        <property name="bottom_attach">6</property>
-                        <property name="x_options">GTK_FILL</property>
-                        <property name="y_options">GTK_FILL</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="label10">
-                        <property name="visible">True</property>
-                        <property name="xalign">1</property>
-                        <property name="label" translatable="yes" comments="Translators: Location of the 
printer (e.g. Lab, 1st floor,...).">Location</property>
-                        <style>
-                          <class name="dim-label"/>
-                        </style>
-                      </object>
-                      <packing>
-                        <property name="top_attach">2</property>
-                        <property name="bottom_attach">3</property>
-                        <property name="x_options">GTK_FILL</property>
-                        <property name="y_options">GTK_FILL</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkDrawingArea" id="supply-drawing-area">
-                        <property name="visible">True</property>
-                      </object>
-                      <packing>
-                        <property name="left_attach">1</property>
-                        <property name="right_attach">3</property>
-                        <property name="top_attach">5</property>
-                        <property name="bottom_attach">6</property>
-                        <property name="y_options">GTK_FILL</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="CcEditableEntry" id="printer-location-label">
-                        <property name="visible">True</property>
-                        <property name="halign">fill</property>
-                        <property name="text">---</property>
-                        <property name="ellipsize">PANGO_ELLIPSIZE_MIDDLE</property>
-                        <accessibility>
-                          <relation type="labelled-by" target="label10"/>
-                        </accessibility>
-                      </object>
-                      <packing>
-                        <property name="left_attach">1</property>
-                        <property name="right_attach">3</property>
-                        <property name="top_attach">2</property>
-                        <property name="bottom_attach">3</property>
-                        <property name="y_options">GTK_FILL</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="CcEditableEntry" id="printer-status-label">
-                        <property name="visible">True</property>
-                        <property name="text">Printing…</property>
-                      </object>
-                      <packing>
-                        <property name="left_attach">1</property>
-                        <property name="right_attach">2</property>
-                        <property name="top_attach">1</property>
-                        <property name="bottom_attach">2</property>
-                        <property name="y_options">GTK_FILL</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkCheckButton" id="printer-default-check-button">
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="receives_default">False</property>
-                        <property name="draw_indicator">True</property>
-                        <child>
-                          <object class="GtkLabel" id="label8">
-                            <property name="visible">True</property>
-                            <property name="label" translatable="yes" comments="Translators: This checkbox 
is checked when the default printer is selected.">_Default printer</property>
-                            <property name="use_underline">True</property>
-                            <attributes>
-                              <attribute name="style" value="normal"/>
-                            </attributes>
-                          </object>
-                        </child>
-                      </object>
-                      <packing>
-                        <property name="left_attach">1</property>
-                        <property name="top_attach">7</property>
-                        <property name="bottom_attach">8</property>
-                        <property name="y_options">GTK_FILL</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="label12">
-                        <property name="visible">True</property>
-                        <property name="label" translatable="yes"></property>
-                      </object>
-                      <packing>
-                        <property name="top_attach">7</property>
-                        <property name="bottom_attach">8</property>
-                        <property name="x_options">GTK_FILL</property>
-                        <property name="y_options">GTK_FILL</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="label3">
-                        <property name="visible">True</property>
-                        <property name="xalign">1</property>
-                        <property name="label" translatable="yes">Jobs</property>
-                        <style>
-                          <class name="dim-label"/>
-                        </style>
-                      </object>
-                      <packing>
-                        <property name="top_attach">6</property>
-                        <property name="bottom_attach">7</property>
-                        <property name="x_options">GTK_FILL</property>
-                        <property name="y_options"></property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="CcEditableEntry" id="printer-jobs-label">
-                        <property name="visible">True</property>
-                        <property name="text" translatable="no">0 active</property>
-                      </object>
-                      <packing>
-                        <property name="left_attach">1</property>
-                        <property name="top_attach">6</property>
-                        <property name="bottom_attach">7</property>
-                        <property name="y_options">GTK_FILL</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkButton" id="printer-jobs-button">
-                        <property name="label" translatable="yes" comments="Translators: Opens a dialog 
containing printer's jobs">Show _Jobs</property>
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="receives_default">True</property>
-                        <property name="use_underline">True</property>
-                        <property name="halign">GTK_ALIGN_END</property>
-                        <property name="valign">GTK_ALIGN_CENTER</property>
-                        <accessibility>
-                          <relation type="labelled-by" target="label3"/>
-                          <relation type="labelled-by" target="printer-jobs-label"/>
-                        </accessibility>
-                      </object>
-                      <packing>
-                        <property name="left_attach">2</property>
-                        <property name="right_attach">3</property>
-                        <property name="top_attach">6</property>
-                        <property name="bottom_attach">7</property>
-                        <property name="x_options">GTK_FILL</property>
-                        <property name="y_options">GTK_FILL</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="CcEditableEntry" id="printer-name-label">
-                        <property name="visible">True</property>
-                        <property name="halign">fill</property>
-                        <property name="valign">end</property>
-                        <property name="text">Printer</property>
-                        <property name="weight">700</property>
-                        <property name="scale">1.2</property>
-                        <property name="ellipsize">PANGO_ELLIPSIZE_MIDDLE</property>
-                      </object>
-                      <packing>
-                        <property name="left_attach">1</property>
-                        <property name="right_attach">2</property>
-                        <property name="y_options">GTK_FILL</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkImage" id="printer-icon">
-                        <property name="visible">True</property>
-                        <property name="halign">end</property>
-                        <property name="pixel_size">64</property>
-                        <property name="icon_name">printer</property>
-                      </object>
-                      <packing>
-                        <property name="bottom_attach">2</property>
-                        <property name="x_options">GTK_FILL</property>
-                        <property name="y_options">GTK_FILL</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="label14">
-                        <property name="visible">True</property>
-                        <property name="xalign">1</property>
-                        <property name="label" translatable="yes">Model</property>
-                        <style>
-                          <class name="dim-label"/>
-                        </style>
-                      </object>
-                      <packing>
-                        <property name="top_attach">3</property>
-                        <property name="bottom_attach">4</property>
-                        <property name="x_options">GTK_FILL</property>
-                        <property name="y_options">GTK_FILL</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="label15">
-                        <property name="visible">True</property>
-                        <property name="xalign">1</property>
-                        <property name="label" translatable="yes">IP Address</property>
-                        <style>
-                          <class name="dim-label"/>
-                        </style>
-                      </object>
-                      <packing>
-                        <property name="top_attach">4</property>
-                        <property name="bottom_attach">5</property>
-                        <property name="x_options">GTK_FILL</property>
-                        <property name="y_options">GTK_FILL</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkNotebook" id="printer-model-notebook">
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="show_tabs">False</property>
-                        <property name="show_border">False</property>
-                        <child>
-                          <object class="GtkButton" id="printer-model-button">
-                            <property name="use_action_appearance">False</property>
-                            <property name="visible">True</property>
-                            <property name="can_focus">True</property>
-                            <property name="receives_default">True</property>
-                            <property name="use_action_appearance">False</property>
-                            <property name="relief">none</property>
-                            <property name="halign">fill</property>
-                            <child>
-                              <object class="GtkLabel" id="printer-model-button-label">
-                                <property name="visible">True</property>
-                                <property name="can_focus">False</property>
-                                <property name="xalign">0</property>
-                                <property name="margin-start">8</property>
-                                <property name="label" translatable="no">label</property>
-                              </object>
-                            </child>
-                            <accessibility>
-                              <relation type="labelled-by" target="label14"/>
-                            </accessibility>
-                          </object>
-                        </child>
-                        <child type="tab">
-                          <object class="GtkLabel" id="label7">
-                            <property name="visible">True</property>
-                            <property name="can_focus">False</property>
-                            <property name="label" translatable="yes">page 1</property>
-                          </object>
-                          <packing>
-                            <property name="tab_fill">False</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkLabel" id="printer-model-label">
-                            <property name="visible">True</property>
-                            <property name="selectable">True</property>
-                            <property name="can_focus">False</property>
-                            <property name="xalign">0</property>
-                            <property name="label" translatable="yes">label</property>
-                          </object>
-                          <packing>
-                            <property name="position">1</property>
-                          </packing>
-                        </child>
-                        <child type="tab">
-                          <object class="GtkLabel" id="label13">
-                            <property name="visible">True</property>
-                            <property name="can_focus">False</property>
-                            <property name="label" translatable="yes">page 2</property>
-                          </object>
-                          <packing>
-                            <property name="position">1</property>
-                            <property name="tab_fill">False</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkLabel" id="printer-model-setting">
-                            <property name="visible">True</property>
-                            <property name="sensitive">False</property>
-                            <property name="can_focus">False</property>
-                            <property name="xalign">0</property>
-                            <property name="label" translatable="yes">Setting new driver…</property>
-                          </object>
-                          <packing>
-                            <property name="position">2</property>
-                          </packing>
-                        </child>
-                        <child type="tab">
-                          <object class="GtkLabel" id="label16">
-                            <property name="visible">True</property>
-                            <property name="can_focus">False</property>
-                            <property name="label" translatable="yes">page 3</property>
-                          </object>
-                          <packing>
-                            <property name="position">2</property>
-                            <property name="tab_fill">False</property>
-                          </packing>
-                        </child>
-                      </object>
-                      <packing>
-                        <property name="left_attach">1</property>
-                        <property name="right_attach">3</property>
-                        <property name="top_attach">3</property>
-                        <property name="bottom_attach">4</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="CcEditableEntry" id="printer-ip-address-label">
-                        <property name="visible">True</property>
-                        <property name="text">---</property>
-                        <accessibility>
-                          <relation type="labelled-by" target="label15"/>
-                        </accessibility>
-                      </object>
-                      <packing>
-                        <property name="left_attach">1</property>
-                        <property name="top_attach">4</property>
-                        <property name="bottom_attach">5</property>
-                        <property name="y_options">GTK_FILL</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkSwitch" id="printer-disable-switch">
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="receives_default">True</property>
-                        <property name="halign">GTK_ALIGN_END</property>
-                        <property name="valign">GTK_ALIGN_CENTER</property>
-                      </object>
-                      <packing>
-                        <property name="left_attach">2</property>
-                        <property name="right_attach">3</property>
-                        <property name="bottom_attach">2</property>
-                        <property name="x_options">GTK_FILL</property>
-                        <property name="y_options">GTK_FILL</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="label18">
-                        <property name="visible">True</property>
-                      </object>
-                      <packing>
-                        <property name="left_attach">2</property>
-                        <property name="right_attach">3</property>
-                        <property name="top_attach">4</property>
-                        <property name="bottom_attach">5</property>
-                        <property name="x_options">0</property>
-                        <property name="y_options">0</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="label20">
-                        <property name="visible">True</property>
-                      </object>
-                      <packing>
-                        <property name="left_attach">2</property>
-                        <property name="right_attach">3</property>
-                        <property name="top_attach">7</property>
-                        <property name="bottom_attach">8</property>
-                        <property name="x_options">0</property>
-                        <property name="y_options">0</property>
-                      </packing>
-                    </child>
-                  </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="position">0</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkButtonBox" id="hbuttonbox1">
-                    <property name="visible">True</property>
-                    <property name="spacing">5</property>
-                    <property name="homogeneous">True</property>
-                    <child>
-                      <object class="GtkButton" id="print-test-page-button">
-                        <property name="label" translatable="yes" comments="Translators: This button 
executes command which prints test page.">Print _Test Page</property>
-                        <property name="use_underline">True</property>
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="receives_default">True</property>
-                      </object>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="fill">False</property>
-                        <property name="position">0</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkButton" id="printer-options-button">
-                        <property name="label" translatable="yes" comments="Translators: This button opens 
printer's options tab">_Options</property>
-                        <property name="visible">True</property>
-                        <property name="use_underline">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="receives_default">True</property>
-                      </object>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="fill">False</property>
-                        <property name="position">1</property>
-                      </packing>
-                    </child>
-                  </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="pack_type">end</property>
-                    <property name="position">1</property>
-                  </packing>
-                </child>
-              </object>
-              <packing>
-                <property name="tab_expand">True</property>
-              </packing>
-            </child>
-            <child type="tab">
-              <object class="GtkLabel" id="label2">
-                <property name="visible">True</property>
-                <property name="label">Info</property>
-              </object>
-              <packing>
-                <property name="tab_fill">False</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkBox" id="hbuttonbox2">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="spacing">10</property>
-                <property name="orientation">vertical</property>
-                <property name="valign">center</property>
-                <child>
-                  <object class="GtkImage" id="no-printer-image">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="valign">start</property>
-                    <property name="pixel_size">64</property>
-                    <property name="icon_name">printer-symbolic</property>
-                    <style>
-                      <class name="dim-label"/>
-                    </style>
-                  </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">False</property>
-                    <property name="position">0</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkLabel" id="no-printer-label">
-                    <property name="visible">True</property>
-                    <style>
-                      <class name="dim-label"/>
-                    </style>
-                  </object>
-                  <packing>
-                    <property name="position">1</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkButton" id="printer-add-button2">
-                    <property name="label" translatable="yes" comments="Translators: This button adds new 
printer.">Add a Printer</property>
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="receives_default">True</property>
-                    <property name="halign">center</property>
-                    <property name="relief">normal</property>
-                    <style>
-                      <class name="suggested-action"/>
-                    </style>
-                  </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">False</property>
-                    <property name="position">2</property>
-                  </packing>
-                </child>
-              </object>
-              <packing>
-                <property name="position">1</property>
-              </packing>
-            </child>
-            <child type="tab">
-              <object class="GtkLabel" id="label21">
-                <property name="visible">True</property>
-                <property name="label">No printers</property>
-              </object>
-              <packing>
-                <property name="position">1</property>
-                <property name="tab_fill">False</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkBox" id="vbox7">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="spacing">20</property>
-                <property name="orientation">vertical</property>
-                <child>
-                  <object class="GtkLabel" id="no-cups-label">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="yalign">1</property>
-                    <property name="label" translatable="yes" comments="Translators: The CUPS server is not 
running (we can not connect to it).">Sorry! The system printing service
-doesn't seem to be available.</property>
-                  </object>
-                  <packing>
-                    <property name="expand">True</property>
-                    <property name="fill">True</property>
-                    <property name="position">0</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkImage" id="image1">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="valign">start</property>
-                    <property name="pixel_size">64</property>
-                    <property name="icon_name">computer-fail</property>
-                  </object>
-                  <packing>
-                    <property name="expand">True</property>
-                    <property name="fill">True</property>
-                    <property name="position">1</property>
-                  </packing>
-                </child>
-              </object>
-              <packing>
-                <property name="position">2</property>
-              </packing>
-            </child>
-            <child type="tab">
-              <object class="GtkLabel" id="label9">
-                <property name="visible">True</property>
-                <property name="label">No cups</property>
-              </object>
-              <packing>
-                <property name="position">2</property>
-                <property name="tab_fill">False</property>
-              </packing>
-            </child>
+            <style>
+              <class name="dim-label"/>
+            </style>
           </object>
           <packing>
-            <property name="expand">True</property>
-            <property name="fill">True</property>
             <property name="position">1</property>
           </packing>
         </child>
+        <child>
+          <object class="GtkButton" id="printer-add-button2">
+            <property name="label" translatable="yes" comments="Translators: This button adds new 
printer.">Add a Printer</property>
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="receives_default">True</property>
+            <property name="halign">center</property>
+            <property name="relief">normal</property>
+            <style>
+              <class name="suggested-action"/>
+            </style>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="position">2</property>
+          </packing>
+        </child>
       </object>
       <packing>
-        <property name="expand">True</property>
-        <property name="fill">True</property>
-        <property name="position">0</property>
+        <property name="name">empty-state</property>
       </packing>
     </child>
   </object>
-  <object class="GtkSizeGroup" id="sizegroup1">
-   <widgets>
-      <widget name="back-button-1"/>
-      <widget name="back-spacer-label-1"/>
-   </widgets>
-  </object>
-  <object class="GtkSizeGroup" id="sizegroup2">
-   <widgets>
-      <widget name="back-button-2"/>
-      <widget name="back-spacer-label-2"/>
-   </widgets>
-  </object>
 </interface>


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