[gnome-control-center/printers-Update-GtkListBox-of-printers-consecutively] printers: Update GtkListBox of printers consecutively
- From: Marek Kašík <mkasik src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-control-center/printers-Update-GtkListBox-of-printers-consecutively] printers: Update GtkListBox of printers consecutively
- Date: Thu, 4 Jun 2020 17:59:37 +0000 (UTC)
commit 3f7c0673233f7cac3282e718ddcf6640d1b4fce3
Author: Marek Kasik <mkasik redhat com>
Date: Thu Jun 4 19:53:13 2020 +0200
printers: Update GtkListBox of printers consecutively
Goal of this commit is to not overwhelm UI when a lot of printers is added
to CUPS. You can reproduce this situation when you add e.g. 30 printers using
lpadmin. Th UI stops to respond for some time.
To do so, the printer entries are not deleted every time there is a request
for updating of the list of printers but only new printer entries are added
and printer entries of deleted printers are removed. Other printer
entries are just updated by new method pp_printer_entry_update().
Which, by the way, is almost whole taken from pp_printer_entry_new().
This needed to add sort function for the list of printer entries. It sorts
printers according to their names not taking case into account.
In the similar manner, the filter function was extended to not show printers
which are being deleted. This needs a list of names of deleted printers
which we keep until they are really deleted.
One important thing here is the "reference" object which points to the panel
itself via its "self" key. We pass this object to the pp_printer_delete_async()'s
callback so it knows whether it can remove the printer's name from the list
of deleted printers (once the panel is being destroyed it clears the key itself).
panels/printers/cc-printers-panel.c | 231 +++++++++++++++++++++++++++++-------
panels/printers/pp-printer-entry.c | 70 +++++++----
panels/printers/pp-printer-entry.h | 4 +
3 files changed, 240 insertions(+), 65 deletions(-)
---
diff --git a/panels/printers/cc-printers-panel.c b/panels/printers/cc-printers-panel.c
index 68c5b194d..1899efe61 100644
--- a/panels/printers/cc-printers-panel.c
+++ b/panels/printers/cc-printers-panel.c
@@ -101,6 +101,8 @@ struct _CcPrintersPanel
gchar *renamed_printer_name;
gchar *old_printer_name;
gchar *deleted_printer_name;
+ GList *deleted_printers;
+ GObject *reference;
GHashTable *printer_entries;
gboolean entries_filled;
@@ -252,11 +254,37 @@ printer_removed_cb (GObject *source_object,
GAsyncResult *result,
gpointer user_data)
{
+ PpPrinter *printer = PP_PRINTER (source_object);
g_autoptr(GError) error = NULL;
+ g_autofree gchar *printer_name = NULL;
- pp_printer_delete_finish (PP_PRINTER (source_object), result, &error);
+ g_object_get (printer, "printer-name", &printer_name, NULL);
+ pp_printer_delete_finish (printer, result, &error);
g_object_unref (source_object);
+ if (user_data != NULL)
+ {
+ GObject *reference = G_OBJECT (user_data);
+
+ if (g_object_get_data (reference, "self") != NULL)
+ {
+ CcPrintersPanel *self = CC_PRINTERS_PANEL (g_object_get_data (reference, "self"));
+ GList *iter;
+
+ for (iter = self->deleted_printers; iter != NULL; iter = iter->next)
+ {
+ if (g_strcmp0 (iter->data, printer_name) == 0)
+ {
+ g_free (iter->data);
+ self->deleted_printers = g_list_delete_link (self->deleted_printers, iter);
+ break;
+ }
+ }
+ }
+
+ g_object_unref (reference);
+ }
+
if (error != NULL)
g_warning ("Printer could not be deleted: %s", error->message);
}
@@ -293,6 +321,10 @@ cc_printers_panel_dispose (GObject *object)
g_clear_pointer (&self->printer_entries, g_hash_table_destroy);
g_clear_pointer (&self->all_ppds_list, ppd_list_free);
free_dests (self);
+ g_list_free_full (self->deleted_printers, g_free);
+ self->deleted_printers = NULL;
+ g_object_set_data (self->reference, "self", NULL);
+ g_clear_object (&self->reference);
G_OBJECT_CLASS (cc_printers_panel_parent_class)->dispose (object);
}
@@ -627,10 +659,14 @@ cancel_notification_timeout (CcPrintersPanel *self)
static void
on_printer_deletion_undone (CcPrintersPanel *self)
{
+ GtkWidget *widget;
+
gtk_revealer_set_reveal_child (self->notification, FALSE);
g_clear_pointer (&self->deleted_printer_name, g_free);
- actualize_printers_list (self);
+
+ widget = (GtkWidget*) gtk_builder_get_object (self->builder, "content");
+ gtk_list_box_invalidate_filter (GTK_LIST_BOX (widget));
cancel_notification_timeout (self);
}
@@ -643,12 +679,22 @@ on_notification_dismissed (CcPrintersPanel *self)
PpPrinter *printer;
printer = pp_printer_new (self->deleted_printer_name);
+ /* The reference tells to the callback whether
+ printers panel was already destroyed so
+ it knows whether it can access the list
+ of deleted printers in it (see below).
+ */
pp_printer_delete_async (printer,
NULL,
printer_removed_cb,
- NULL);
-
- g_clear_pointer (&self->deleted_printer_name, g_free);
+ g_object_ref (self->reference));
+
+ /* List of printers which were recently deleted but are still available
+ in CUPS due to async nature of the method (e.g. quick deletion
+ of several printers).
+ */
+ self->deleted_printers = g_list_prepend (self->deleted_printers, self->deleted_printer_name);
+ self->deleted_printer_name = NULL;
}
gtk_revealer_set_reveal_child (self->notification, FALSE);
@@ -669,8 +715,7 @@ on_printer_deleted (CcPrintersPanel *self,
GtkLabel *label;
g_autofree gchar *notification_message = NULL;
g_autofree gchar *printer_name = NULL;
-
- gtk_widget_hide (GTK_WIDGET (printer_entry));
+ GtkWidget *widget;
on_notification_dismissed (self);
@@ -687,6 +732,9 @@ on_printer_deleted (CcPrintersPanel *self,
self->deleted_printer_name = g_strdup (printer_name);
+ widget = (GtkWidget*) gtk_builder_get_object (self->builder, "content");
+ gtk_list_box_invalidate_filter (GTK_LIST_BOX (widget));
+
gtk_revealer_set_reveal_child (self->notification, TRUE);
self->remove_printer_timeout_id = g_timeout_add_seconds (10, on_remove_printer_timeout, self);
@@ -771,6 +819,33 @@ set_current_page (GObject *source_object,
update_sensitivity (user_data);
}
+static void
+destroy_nonexisting_entries (PpPrinterEntry *entry,
+ gpointer user_data)
+{
+ CcPrintersPanel *self = (CcPrintersPanel *) user_data;
+ g_autofree gchar *printer_name = NULL;
+ gboolean exists = FALSE;
+ gint i;
+
+ g_object_get (G_OBJECT (entry), "printer-name", &printer_name, NULL);
+
+ for (i = 0; i < self->num_dests; i++)
+ {
+ if (g_strcmp0 (self->dests[i].name, printer_name) == 0)
+ {
+ exists = TRUE;
+ break;
+ }
+ }
+
+ if (!exists)
+ {
+ gtk_widget_destroy (GTK_WIDGET (entry));
+ g_hash_table_remove (self->printer_entries, printer_name);
+ }
+}
+
static void
actualize_printers_list_cb (GObject *source_object,
GAsyncResult *result,
@@ -782,6 +857,7 @@ actualize_printers_list_cb (GObject *source_object,
PpCupsDests *cups_dests;
gboolean new_printer_available = FALSE;
g_autoptr(GError) error = NULL;
+ gpointer item;
int i;
cups_dests = pp_cups_get_dests_finish (cups, result, &error);
@@ -809,7 +885,7 @@ actualize_printers_list_cb (GObject *source_object,
gtk_stack_set_visible_child_name (GTK_STACK (widget), "printers-list");
widget = (GtkWidget*) gtk_builder_get_object (self->builder, "content");
- gtk_container_foreach (GTK_CONTAINER (widget), (GtkCallback) gtk_widget_destroy, NULL);
+ gtk_container_foreach (GTK_CONTAINER (widget), (GtkCallback) destroy_nonexisting_entries, self);
for (i = 0; i < self->num_dests; i++)
{
@@ -820,13 +896,14 @@ actualize_printers_list_cb (GObject *source_object,
for (i = 0; i < self->num_dests; i++)
{
- if (g_strcmp0 (self->dests[i].name, self->deleted_printer_name) == 0)
- continue;
-
if (new_printer_available && g_strcmp0 (self->dests[i].name, self->old_printer_name) == 0)
continue;
- add_printer_entry (self, self->dests[i]);
+ item = g_hash_table_lookup (self->printer_entries, self->dests[i].name);
+ if (item != NULL)
+ pp_printer_entry_update (PP_PRINTER_ENTRY (item), self->dests[i], self->is_authorized);
+ else
+ add_printer_entry (self, self->dests[i]);
}
if (!self->entries_filled)
@@ -844,6 +921,30 @@ actualize_printers_list_cb (GObject *source_object,
update_sensitivity (user_data);
g_object_unref (cups);
+
+ if (self->new_printer_name != NULL)
+ {
+ GtkScrolledWindow *scrolled_window;
+ GtkAllocation allocation;
+ GtkAdjustment *adjustment;
+ GtkWidget *printer_entry;
+
+ /* Scroll the view to show the newly added printer-entry. */
+ scrolled_window = GTK_SCROLLED_WINDOW (gtk_builder_get_object (self->builder,
+ "scrolled-window"));
+ adjustment = gtk_scrolled_window_get_vadjustment (scrolled_window);
+
+ printer_entry = GTK_WIDGET (g_hash_table_lookup (self->printer_entries,
+ self->new_printer_name));
+ if (printer_entry != NULL)
+ {
+ gtk_widget_get_allocation (printer_entry, &allocation);
+ g_clear_pointer (&self->new_printer_name, g_free);
+
+ gtk_adjustment_set_value (adjustment,
+ allocation.y - gtk_widget_get_margin_top (printer_entry));
+ }
+ }
}
static void
@@ -877,11 +978,6 @@ static void
new_printer_dialog_response_cb (CcPrintersPanel *self,
gint response_id)
{
- GtkScrolledWindow *scrolled_window;
- GtkAllocation allocation;
- GtkAdjustment *adjustment;
- GtkWidget *printer_entry;
-
if (self->pp_new_printer_dialog)
g_clear_object (&self->pp_new_printer_dialog);
@@ -906,22 +1002,6 @@ new_printer_dialog_response_cb (CcPrintersPanel *self,
}
actualize_printers_list (self);
-
- if (self->new_printer_name == NULL)
- return;
-
- /* Scroll the view to show the newly added printer-entry. */
- scrolled_window = GTK_SCROLLED_WINDOW (gtk_builder_get_object (self->builder,
- "scrolled-window"));
- adjustment = gtk_scrolled_window_get_vadjustment (scrolled_window);
-
- printer_entry = GTK_WIDGET (g_hash_table_lookup (self->printer_entries,
- self->new_printer_name));
- gtk_widget_get_allocation (printer_entry, &allocation);
- g_clear_pointer (&self->new_printer_name, g_free);
-
- gtk_adjustment_set_value (adjustment,
- allocation.y - gtk_widget_get_margin_top (printer_entry));
}
static void
@@ -1105,30 +1185,85 @@ filter_function (GtkListBoxRow *row,
g_autofree gchar *location = NULL;
g_autofree gchar *printer_name = NULL;
g_autofree gchar *printer_location = NULL;
+ GList *iter;
+
+ g_object_get (G_OBJECT (row),
+ "printer-name", &printer_name,
+ "printer-location", &printer_location,
+ NULL);
search_entry = (GtkWidget*)
gtk_builder_get_object (self->builder, "search-entry");
if (gtk_entry_get_text_length (GTK_ENTRY (search_entry)) == 0)
- return TRUE;
+ {
+ retval = TRUE;
+ }
+ else
+ {
+ name = cc_util_normalize_casefold_and_unaccent (printer_name);
+ location = cc_util_normalize_casefold_and_unaccent (printer_location);
- g_object_get (G_OBJECT (row),
- "printer-name", &printer_name,
- "printer-location", &printer_location,
- NULL);
+ search = cc_util_normalize_casefold_and_unaccent (gtk_entry_get_text (GTK_ENTRY (search_entry)));
- name = cc_util_normalize_casefold_and_unaccent (printer_name);
- location = cc_util_normalize_casefold_and_unaccent (printer_location);
+ retval = strstr (name, search) != NULL;
+ if (location != NULL)
+ retval = retval || (strstr (location, search) != NULL);
+ }
- search = cc_util_normalize_casefold_and_unaccent (gtk_entry_get_text (GTK_ENTRY (search_entry)));
+ if (self->deleted_printer_name != NULL &&
+ g_strcmp0 (self->deleted_printer_name, printer_name) == 0)
+ {
+ retval = FALSE;
+ }
- retval = strstr (name, search) != NULL;
- if (location != NULL)
- retval = retval || (strstr (location, search) != NULL);
+ if (self->deleted_printers != NULL)
+ {
+ for (iter = self->deleted_printers; iter != NULL; iter = iter->next)
+ {
+ if (g_strcmp0 (iter->data, printer_name) == 0)
+ {
+ retval = FALSE;
+ break;
+ }
+ }
+ }
return retval;
}
+static gint
+sort_function (GtkListBoxRow *row1,
+ GtkListBoxRow *row2,
+ gpointer user_data)
+{
+ g_autofree gchar *printer_name1 = NULL;
+ g_autofree gchar *printer_name2 = NULL;
+
+ g_object_get (G_OBJECT (row1),
+ "printer-name", &printer_name1,
+ NULL);
+
+ g_object_get (G_OBJECT (row2),
+ "printer-name", &printer_name2,
+ NULL);
+
+ if (printer_name1 != NULL)
+ {
+ if (printer_name2 != NULL)
+ return g_ascii_strcasecmp (printer_name1, printer_name2);
+ else
+ return 1;
+ }
+ else
+ {
+ if (printer_name2 != NULL)
+ return -1;
+ else
+ return 0;
+ }
+}
+
static void
cc_printers_panel_init (CcPrintersPanel *self)
{
@@ -1164,6 +1299,8 @@ cc_printers_panel_init (CcPrintersPanel *self)
self->renamed_printer_name = NULL;
self->old_printer_name = NULL;
self->deleted_printer_name = NULL;
+ self->deleted_printers = NULL;
+ self->reference = g_object_new (G_TYPE_OBJECT, NULL);
self->permission = NULL;
self->lockdown_settings = NULL;
@@ -1179,6 +1316,8 @@ cc_printers_panel_init (CcPrintersPanel *self)
g_type_ensure (CC_TYPE_PERMISSION_INFOBAR);
+ g_object_set_data_full (self->reference, "self", self, g_free);
+
builder_result = gtk_builder_add_objects_from_resource (self->builder,
"/org/gnome/control-center/printers/printers.ui",
objects, &error);
@@ -1227,6 +1366,10 @@ cc_printers_panel_init (CcPrintersPanel *self)
"search-changed",
G_CALLBACK (gtk_list_box_invalidate_filter),
widget);
+ gtk_list_box_set_sort_func (GTK_LIST_BOX (widget),
+ sort_function,
+ NULL,
+ NULL);
self->lockdown_settings = g_settings_new ("org.gnome.desktop.lockdown");
if (self->lockdown_settings)
diff --git a/panels/printers/pp-printer-entry.c b/panels/printers/pp-printer-entry.c
index 8771b4fc5..7273982eb 100644
--- a/panels/printers/pp-printer-entry.c
+++ b/panels/printers/pp-printer-entry.c
@@ -45,7 +45,6 @@ struct _PpPrinterEntry
{
GtkListBoxRow parent;
- gchar *printer_uri;
gchar *printer_name;
gchar *ppd_file_name;
int num_jobs;
@@ -705,12 +704,35 @@ PpPrinterEntry *
pp_printer_entry_new (cups_dest_t printer,
gboolean is_authorized)
{
- PpPrinterEntry *self;
+ PpPrinterEntry *self;
+
+ self = g_object_new (PP_PRINTER_ENTRY_TYPE, "printer-name", printer.name, NULL);
+
+ self->clean_command = pp_maintenance_command_new (self->printer_name,
+ "Clean",
+ "all",
+ /* Translators: Name of job which makes printer to clean
its heads */
+ _("Clean print heads"));
+ check_clean_heads_maintenance_command (self);
+
+ g_signal_connect_object (self->supply_drawing_area, "draw", G_CALLBACK (supply_levels_draw_cb), self,
G_CONNECT_SWAPPED);
+
+ pp_printer_entry_update (self, printer, is_authorized);
+
+ return self;
+}
+
+void
+pp_printer_entry_update (PpPrinterEntry *self,
+ cups_dest_t printer,
+ gboolean is_authorized)
+{
cups_ptype_t printer_type = 0;
gboolean is_accepting_jobs = TRUE;
gboolean ink_supply_is_empty;
g_autofree gchar *instance = NULL;
const gchar *printer_uri = NULL;
+ const gchar *device_uri = NULL;
const gchar *location = NULL;
g_autofree gchar *printer_icon_name = NULL;
const gchar *printer_make_and_model = NULL;
@@ -776,8 +798,6 @@ pp_printer_entry_new (cups_dest_t printer,
N_("The optical photo conductor is no longer functioning")
};
- self = g_object_new (PP_PRINTER_ENTRY_TYPE, "printer-name", printer.name, NULL);
-
if (printer.instance)
{
instance = g_strdup_printf ("%s / %s", printer.name, printer.instance);
@@ -792,7 +812,7 @@ pp_printer_entry_new (cups_dest_t printer,
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;
+ device_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)
@@ -802,13 +822,25 @@ pp_printer_entry_new (cups_dest_t printer,
else if (g_strcmp0 (printer.options[i].name, "printer-state-reasons") == 0)
reason = printer.options[i].value;
else if (g_strcmp0 (printer.options[i].name, "marker-names") == 0)
- self->inklevel->marker_names = g_strcompress (printer.options[i].value);
+ {
+ g_free (self->inklevel->marker_names);
+ self->inklevel->marker_names = g_strcompress (g_strdup (printer.options[i].value));
+ }
else if (g_strcmp0 (printer.options[i].name, "marker-levels") == 0)
- self->inklevel->marker_levels = g_strdup (printer.options[i].value);
+ {
+ g_free (self->inklevel->marker_levels);
+ self->inklevel->marker_levels = g_strdup (printer.options[i].value);
+ }
else if (g_strcmp0 (printer.options[i].name, "marker-colors") == 0)
- self->inklevel->marker_colors = g_strdup (printer.options[i].value);
+ {
+ g_free (self->inklevel->marker_colors);
+ self->inklevel->marker_colors = g_strdup (printer.options[i].value);
+ }
else if (g_strcmp0 (printer.options[i].name, "marker-types") == 0)
- self->inklevel->marker_types = g_strdup (printer.options[i].value);
+ {
+ g_free (self->inklevel->marker_types);
+ self->inklevel->marker_types = g_strdup (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)
@@ -872,6 +904,11 @@ pp_printer_entry_new (cups_dest_t printer,
gtk_label_set_label (self->error_status, status);
gtk_widget_set_visible (GTK_WIDGET (self->printer_error), TRUE);
}
+ else
+ {
+ gtk_label_set_label (self->error_status, "");
+ gtk_widget_set_visible (GTK_WIDGET (self->printer_error), FALSE);
+ }
switch (self->printer_state)
{
@@ -897,7 +934,7 @@ pp_printer_entry_new (cups_dest_t printer,
break;
}
- if (printer_is_local (printer_type, self->printer_uri))
+ if (printer_is_local (printer_type, device_uri))
printer_icon_name = g_strdup ("printer");
else
printer_icon_name = g_strdup ("printer-network");
@@ -907,14 +944,8 @@ pp_printer_entry_new (cups_dest_t printer,
self->is_accepting_jobs = is_accepting_jobs;
self->is_authorized = is_authorized;
- self->printer_hostname = printer_get_hostname (printer_type, self->printer_uri, printer_uri);
-
- self->clean_command = pp_maintenance_command_new (self->printer_name,
- "Clean",
- "all",
- /* Translators: Name of job which makes printer to clean
its heads */
- _("Clean print heads"));
- check_clean_heads_maintenance_command (self);
+ g_free (self->printer_hostname);
+ self->printer_hostname = printer_get_hostname (printer_type, device_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);
@@ -945,7 +976,6 @@ pp_printer_entry_new (cups_dest_t printer,
gtk_label_set_text (self->printer_location_address_label, location);
}
- g_signal_connect_object (self->supply_drawing_area, "draw", G_CALLBACK (supply_levels_draw_cb), self,
G_CONNECT_SWAPPED);
ink_supply_is_empty = supply_level_is_empty (self);
gtk_widget_set_visible (GTK_WIDGET (self->printer_inklevel_label), !ink_supply_is_empty);
gtk_widget_set_visible (GTK_WIDGET (self->supply_frame), !ink_supply_is_empty);
@@ -954,8 +984,6 @@ pp_printer_entry_new (cups_dest_t printer,
gtk_widget_set_sensitive (GTK_WIDGET (self->printer_default_checkbutton), self->is_authorized);
gtk_widget_set_sensitive (GTK_WIDGET (self->remove_printer_menuitem), self->is_authorized);
-
- return self;
}
static void
diff --git a/panels/printers/pp-printer-entry.h b/panels/printers/pp-printer-entry.h
index 753231ea6..5db39d9ec 100644
--- a/panels/printers/pp-printer-entry.h
+++ b/panels/printers/pp-printer-entry.h
@@ -35,3 +35,7 @@ GSList *pp_printer_entry_get_size_group_widgets (PpPrinterEntry *self);
void pp_printer_entry_show_jobs_dialog (PpPrinterEntry *self);
void pp_printer_entry_authenticate_jobs (PpPrinterEntry *self);
+
+void pp_printer_entry_update (PpPrinterEntry *self,
+ cups_dest_t printer,
+ gboolean is_authorized);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]