diff --git a/panels/printers/cc-printers-panel.c b/panels/printers/cc-printers-panel.c index 70a04fc1b..85f29b270 100644 --- a/panels/printers/cc-printers-panel.c +++ b/panels/printers/cc-printers-panel.c @@ -37,6 +37,7 @@ #include "pp-options-dialog.h" #include "pp-jobs-dialog.h" #include "pp-utils.h" +#include "pp-maintenance-command.h" CC_PANEL_REGISTER (CcPrintersPanel, cc_printers_panel) @@ -104,6 +105,12 @@ struct _CcPrintersPanelPrivate GHashTable *preferred_drivers; GCancellable *get_all_ppds_cancellable; + gchar *new_printer_name; + gchar *new_printer_location; + gchar *new_printer_make_and_model; + gboolean new_printer_on_network; + gboolean select_new_printer; + gpointer dummy; }; @@ -153,13 +160,14 @@ cc_printers_panel_dispose (GObject *object) CcPrintersPanelPrivate *priv = CC_PRINTERS_PANEL (object)->priv; if (priv->pp_new_printer_dialog) - { - pp_new_printer_dialog_free (priv->pp_new_printer_dialog); - priv->pp_new_printer_dialog = NULL; - } + 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); @@ -538,7 +546,6 @@ printer_selection_changed_cb (GtkTreeSelection *selection, GtkWidget *widget; GtkWidget *model_button; GtkWidget *model_label; - gboolean sensitive; GValue value = G_VALUE_INIT; gchar *printer_make_and_model = NULL; gchar *printer_model = NULL; @@ -710,10 +717,19 @@ printer_selection_changed_cb (GtkTreeSelection *selection, 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 (reason && g_strcmp0 (reason, "none") != 0) + 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; @@ -871,11 +887,9 @@ printer_selection_changed_cb (GtkTreeSelection *selection, widget = (GtkWidget*) gtk_builder_get_object (priv->builder, "printer-default-check-button"); - sensitive = gtk_widget_get_sensitive (widget); 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); - gtk_widget_set_sensitive (widget, sensitive); widget = (GtkWidget*) @@ -907,33 +921,107 @@ printer_selection_changed_cb (GtkTreeSelection *selection, } else { + 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); + } + } + + 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"); - cc_editable_entry_set_text (CC_EDITABLE_ENTRY (widget), ""); + 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"); - cc_editable_entry_set_text (CC_EDITABLE_ENTRY (widget), ""); + 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"); - cc_editable_entry_set_text (CC_EDITABLE_ENTRY (widget), ""); - widget = (GtkWidget*) + 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 = (GtkWidget*) gtk_builder_get_object (priv->builder, "printer-model-button"); - gtk_button_set_label (GTK_BUTTON (widget), ""); - widget = (GtkWidget*) + model_label = (GtkWidget*) gtk_builder_get_object (priv->builder, "printer-model-label"); - gtk_label_set_text (GTK_LABEL (widget), ""); + + if (printer_model) + { + gtk_button_set_label (GTK_BUTTON (model_button), printer_model); + gtk_label_set_text (GTK_LABEL (model_label), printer_model); + g_free (printer_model); + } + else + { + gtk_button_set_label (GTK_BUTTON (model_button), EMPTY_TEXT); + gtk_label_set_text (GTK_LABEL (model_label), EMPTY_TEXT); + } widget = (GtkWidget*) gtk_builder_get_object (priv->builder, "printer-ip-address-label"); - cc_editable_entry_set_text (CC_EDITABLE_ENTRY (widget), ""); + cc_editable_entry_set_text (CC_EDITABLE_ENTRY (widget), EMPTY_TEXT); widget = (GtkWidget*) gtk_builder_get_object (priv->builder, "printer-jobs-label"); - cc_editable_entry_set_text (CC_EDITABLE_ENTRY (widget), ""); + cc_editable_entry_set_text (CC_EDITABLE_ENTRY (widget), EMPTY_TEXT); + + widget = (GtkWidget*) + gtk_builder_get_object (priv->builder, "printer-disable-switch"); + + 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); + + widget = (GtkWidget*) + gtk_builder_get_object (priv->builder, "printer-default-check-button"); + + 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); } update_sensitivity (self); @@ -943,34 +1031,47 @@ static void actualize_printers_list (CcPrintersPanel *self) { CcPrintersPanelPrivate *priv; + GtkTreeSelection *selection; 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; http_t *http; - gchar *current_printer_instance = NULL; 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); - if (priv->current_dest >= 0 && - priv->current_dest < priv->num_dests && - priv->dests != NULL) + 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)) { - current_printer_name = g_strdup (priv->dests[priv->current_dest].name); - if (priv->dests[priv->current_dest].instance) - current_printer_instance = g_strdup (priv->dests[priv->current_dest].instance); + gtk_tree_model_get (model, &iter, + PRINTER_NAME_COLUMN, ¤t_printer_name, + -1); + } + + 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; } free_dests (self); @@ -978,9 +1079,6 @@ actualize_printers_list (CcPrintersPanel *self) priv->dest_model_names = g_new0 (gchar *, priv->num_dests); priv->ppd_file_names = g_new0 (gchar *, priv->num_dests); - treeview = (GtkTreeView*) - gtk_builder_get_object (priv->builder, "printers-treeview"); - store = gtk_list_store_new (PRINTER_N_COLUMNS, G_TYPE_INT, G_TYPE_STRING, @@ -988,7 +1086,7 @@ actualize_printers_list (CcPrintersPanel *self) G_TYPE_STRING, G_TYPE_STRING); - if (priv->num_dests == 0) + if (priv->num_dests == 0 && !priv->new_printer_name) { widget = (GtkWidget*) gtk_builder_get_object (priv->builder, "notebook"); @@ -1020,30 +1118,25 @@ actualize_printers_list (CcPrintersPanel *self) { 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); - - if (current_printer_instance && - g_strcmp0 (current_printer_name, priv->dests[i].name) == 0 && - g_strcmp0 (current_printer_instance, priv->dests[i].instance) == 0) - { - current_dest = i; - selected_iter = iter; - } } else { instance = g_strdup (priv->dests[i].name); - - if (current_printer_instance == NULL && - g_strcmp0 (current_printer_name, priv->dests[i].name) == 0) - { - current_dest = i; - selected_iter = iter; - } } for (j = 0; j < priv->dests[i].num_options; j++) @@ -1074,11 +1167,37 @@ actualize_printers_list (CcPrintersPanel *self) 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; + } + 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, @@ -1091,7 +1210,7 @@ actualize_printers_list (CcPrintersPanel *self) printer_selection_changed_cb, self); - if (current_dest >= 0) + if (selected_iter_set) { priv->current_dest = current_dest; gtk_tree_selection_select_iter ( @@ -1160,7 +1279,6 @@ actualize_printers_list (CcPrintersPanel *self) } g_free (current_printer_name); - g_free (current_printer_instance); g_object_unref (store); update_sensitivity (self); @@ -1192,14 +1310,20 @@ set_cell_sensitivity_func (GtkTreeViewColumn *tree_column, "width-chars", 18, NULL); - if (paused) - g_object_set (cell, - "sensitive", FALSE, - NULL); - else - g_object_set (cell, - "sensitive", TRUE, - 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 @@ -1228,6 +1352,8 @@ populate_printers_list (CcPrintersPanel *self) 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); @@ -1524,7 +1650,7 @@ supply_levels_draw_cb (GtkWidget *widget, gtk_widget_set_has_tooltip (widget, FALSE); } } - + return TRUE; } @@ -1555,21 +1681,45 @@ printer_set_default_cb (GtkToggleButton *button, } static void -new_printer_dialog_response_cb (GtkDialog *dialog, - gint response_id, - gpointer user_data) +new_printer_dialog_pre_response_cb (PpNewPrinterDialog *dialog, + const gchar *device_name, + const gchar *device_location, + const gchar *device_make_and_model, + gboolean is_network_device, + gpointer user_data) { CcPrintersPanelPrivate *priv; CcPrintersPanel *self = (CcPrintersPanel*) user_data; priv = PRINTERS_PANEL_PRIVATE (self); - pp_new_printer_dialog_free (priv->pp_new_printer_dialog); - priv->pp_new_printer_dialog = NULL; + priv->new_printer_name = g_strdup (device_name); + priv->new_printer_location = g_strdup (device_location); + priv->new_printer_make_and_model = g_strdup (device_make_and_model); + priv->new_printer_on_network = is_network_device; + priv->select_new_printer = TRUE; - if (response_id == GTK_RESPONSE_OK) - actualize_printers_list (self); - else if (response_id == GTK_RESPONSE_REJECT) + actualize_printers_list (self); +} + +static void +new_printer_dialog_response_cb (PpNewPrinterDialog *dialog, + gint response_id, + gpointer user_data) +{ + CcPrintersPanelPrivate *priv; + CcPrintersPanel *self = (CcPrintersPanel*) user_data; + + priv = PRINTERS_PANEL_PRIVATE (self); + + if (priv->pp_new_printer_dialog) + g_clear_object (&priv->pp_new_printer_dialog); + + 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 (response_id == GTK_RESPONSE_REJECT) { GtkWidget *message_dialog; @@ -1585,6 +1735,8 @@ new_printer_dialog_response_cb (GtkDialog *dialog, NULL); gtk_widget_show (message_dialog); } + + actualize_printers_list (self); } static void @@ -1593,17 +1745,22 @@ printer_add_cb (GtkToolButton *toolbutton, { CcPrintersPanelPrivate *priv; CcPrintersPanel *self = (CcPrintersPanel*) user_data; - GtkWidget *widget; + GtkWidget *toplevel; priv = PRINTERS_PANEL_PRIVATE (self); - widget = (GtkWidget*) - gtk_builder_get_object (priv->builder, "main-vbox"); + toplevel = gtk_widget_get_toplevel (GTK_WIDGET (self)); + priv->pp_new_printer_dialog = PP_NEW_PRINTER_DIALOG (pp_new_printer_dialog_new (GTK_WINDOW (toplevel))); - priv->pp_new_printer_dialog = pp_new_printer_dialog_new ( - GTK_WINDOW (gtk_widget_get_toplevel (widget)), - new_printer_dialog_response_cb, - self); + g_signal_connect (priv->pp_new_printer_dialog, + "pre-response", + G_CALLBACK (new_printer_dialog_pre_response_cb), + self); + + g_signal_connect (priv->pp_new_printer_dialog, + "response", + G_CALLBACK (new_printer_dialog_response_cb), + self); } static void @@ -2184,6 +2341,19 @@ popup_model_menu_cb (GtkButton *button, } } +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) @@ -2286,23 +2456,27 @@ test_page_cb (GtkButton *button, 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 { - response = execute_maintenance_command (printer_name, - "PrintSelfTestPage", - /* Translators: Name of job which makes printer to print test page */ - _("Test page")); - } + PpMaintenanceCommand *command; - if (response) - { - if (ippGetState (response) == IPP_ERROR) - g_warning ("An error has occured during printing of test page."); - ippDelete (response); + 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); } } } @@ -2311,8 +2485,12 @@ 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; @@ -2322,7 +2500,10 @@ update_sensitivity (gpointer user_data) 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; gint i; priv = PRINTERS_PANEL_PRIVATE (self); @@ -2361,6 +2542,29 @@ update_sensitivity (gpointer user_data) } } + 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, ¤t_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 && @@ -2373,39 +2577,41 @@ update_sensitivity (gpointer user_data) 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); + 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); + gtk_widget_set_sensitive (widget, local_server && is_authorized && !no_cups && !priv->new_printer_name); widget = (GtkWidget*) gtk_builder_get_object (priv->builder, "printer-remove-button"); - gtk_widget_set_sensitive (widget, local_server && !is_discovered && is_authorized && printer_selected && !no_cups); + 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, local_server && !is_discovered && is_authorized); + 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); + 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); + 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); + !priv->pp_options_dialog && !is_new); widget = (GtkWidget*) gtk_builder_get_object (priv->builder, "printer-jobs-button"); - gtk_widget_set_sensitive (widget, printer_selected); + 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), local_server && !is_discovered && is_authorized); + 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), local_server && !is_discovered && is_authorized); + 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) @@ -2414,7 +2620,7 @@ update_sensitivity (gpointer user_data) } else { - if (local_server && !is_discovered && is_authorized && !is_class && !priv->getting_ppd_names) + 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); @@ -2648,6 +2854,12 @@ cc_printers_panel_init (CcPrintersPanel *self) 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; diff --git a/panels/printers/new-printer-dialog.ui b/panels/printers/new-printer-dialog.ui index fa490872c..07d946a81 100644 --- a/panels/printers/new-printer-dialog.ui +++ b/panels/printers/new-printer-dialog.ui @@ -1,378 +1,230 @@ - + - - + - 500 - 350 - 5 + 500 + 350 + False + 5 False - dialog + True + True + dialog - + True + False vertical - 2 - - - True - vertical - 10 - - - True - 0 - Add a New Printer - - - - - - False - 0 - - - - - True - 10 - - - True - True - False - False - - - 0 - - - - - True - True - False - False - - - True - True - False - False - - - True - True - automatic - automatic - - - True - True - False - - - - - - - True - False - page 1 - - - False - - - - - True - True - 6 - False - word - 10 - 10 - - - 1 - - - - - True - False - page 2 - - - 1 - False - - - - - - - True - page 1 - - - False - - - - - True - vertical - 10 - - - True - True - False - False - - - True - True - never - automatic - - - True - True - False - False - - - - - - - True - False - page 1 - - - False - - - - - True - True - 6 - False - word - 10 - 10 - - - 1 - - - - - True - False - page 2 - - - 1 - False - - - - - 0 - - - - - True - - - True - 0 - A_ddress: - True - address-entry - - - 0 - - - - - True - True - - - - 1 - - - - - False - 1 - - - - - True - - - _Search by Address - True - True - True - False - True - - - 0 - - - - - True - - - 2 - - - - - False - 2 - - - - - 1 - - - - - True - page 2 - - - 1 - False - - - - - True - True - 6 - False - word - 10 - 10 - - - 2 - - - - - True - page 3 - - - 2 - False - - - - - 1 - - - - - 1 - - - - - 1 - - + 10 - + True - end + False - + + _Cancel + False True - - - True - - - False - False - - - - - True - 0 - 5 - - - - 1 - - + True + True + False + True False True 0 - True - - - - - _Cancel - True - True - True - True - - - 1 _Add - True + False True + False True True + False + True + False + True 2 False + True end 0 + + + True + False + + + True + False + 10 + + + True + False + 0 + Add a New Printer + + + + + + False + True + 0 + + + + + True + False + vertical + + + True + True + in + + + True + True + False + + + + + + + + True + True + 0 + + + + + True + False + icons + 1 + + + + False + True + False + False + + + True + False + + + 24 + 24 + True + False + + + + + + False + True + 10 + 0 + + + + + True + True + True + + True + True + gtk-find + Search for network printers or filter result + Search for network printers or filter result + Enter address of a printer or a text to filter results + + + True + True + 1 + + + + + 24 + 24 + True + False + + + True + False + True + + + + + False + True + 10 + 2 + + + + + + + True + True + + + + + False + True + 1 + + + + + True + True + 1 + + + + + + + True + True + 1 + + - new-printer-cancel-button - new-printer-add-button + new-printer-cancel-button + new-printer-add-button diff --git a/panels/printers/pp-new-printer-dialog.c b/panels/printers/pp-new-printer-dialog.c index 0d3ddb0aa..88c7a9ded 100644 --- a/panels/printers/pp-new-printer-dialog.c +++ b/panels/printers/pp-new-printer-dialog.c @@ -22,8 +22,6 @@ #include #include -#include -#include #include #include @@ -31,26 +29,17 @@ #include #include -#include #include "pp-new-printer-dialog.h" #include "pp-utils.h" - -#include +#include "pp-host.h" +#include "pp-cups.h" +#include "pp-new-printer.h" #ifdef GDK_WINDOWING_X11 #include #endif -#define PACKAGE_KIT_BUS "org.freedesktop.PackageKit" -#define PACKAGE_KIT_PATH "/org/freedesktop/PackageKit" -#define PACKAGE_KIT_MODIFY_IFACE "org.freedesktop.PackageKit.Modify" -#define PACKAGE_KIT_QUERY_IFACE "org.freedesktop.PackageKit.Query" - -#define FIREWALLD_BUS "org.fedoraproject.FirewallD" -#define FIREWALLD_PATH "/org/fedoraproject/FirewallD" -#define FIREWALLD_IFACE "org.fedoraproject.FirewallD" - #if (CUPS_VERSION_MAJOR > 1) || (CUPS_VERSION_MINOR > 5) #define HAVE_CUPS_1_6 1 #endif @@ -59,198 +48,327 @@ #define ippGetState(ipp) ipp->state #endif -static void pp_new_printer_dialog_hide (PpNewPrinterDialog *pp); -static void actualize_devices_list (PpNewPrinterDialog *pp); +static void actualize_devices_list (PpNewPrinterDialog *dialog); +static void populate_devices_list (PpNewPrinterDialog *dialog); +static void search_address_cb2 (GtkEntry *entry, + GtkEntryIconPosition icon_pos, + GdkEvent *event, + gpointer user_data); +static void search_address_cb (GtkEntry *entry, + gpointer user_data); +static void new_printer_dialog_response_cb (GtkDialog *_dialog, + gint response_id, + gpointer user_data); +static void t_device_free (gpointer data); enum { - NOTEBOOK_LOCAL_PAGE = 0, - NOTEBOOK_NETWORK_PAGE, - NOTEBOOK_N_PAGES -}; - -enum -{ - DEVICE_TYPE_ID_COLUMN = 0, - DEVICE_TYPE_NAME_COLUMN, - DEVICE_TYPE_TYPE_COLUMN, - DEVICE_TYPE_N_COLUMNS -}; - -enum -{ - DEVICE_ID_COLUMN = 0, + DEVICE_ICON_COLUMN = 0, DEVICE_NAME_COLUMN, + DEVICE_DISPLAY_NAME_COLUMN, DEVICE_N_COLUMNS }; -enum +typedef struct { - DEVICE_TYPE_LOCAL = 0, - DEVICE_TYPE_NETWORK -}; + gchar *display_name; + gchar *device_name; + gchar *device_original_name; + gchar *device_info; + gchar *device_location; + gchar *device_make_and_model; + gchar *device_uri; + gchar *device_id; + gchar *device_ppd; + gchar *host_name; + gint host_port; + gboolean network_device; + gint acquisition_method; + gboolean show; +} TDevice; -enum +struct _PpNewPrinterDialogPrivate { - STANDARD_TAB = 0, - WARNING_TAB -}; - -typedef struct{ - gchar *device_class; - gchar *device_id; - gchar *device_info; - gchar *device_make_and_model; - gchar *device_uri; - gchar *device_location; - gchar *device_ppd_uri; - gchar *display_name; - gchar *hostname; - gint host_port; - gboolean show; - gboolean found; -} CupsDevice; - -struct _PpNewPrinterDialog { GtkBuilder *builder; - GtkWidget *parent; - GtkWidget *dialog; + GList *devices; + GList *new_devices; - gchar **device_connection_types; - gint num_device_connection_types; - - CupsDevice *devices; - gint num_devices; - - UserResponseCallback user_callback; - gpointer user_data; + cups_dest_t *dests; + gint num_of_dests; GCancellable *cancellable; - gchar *warning; - gboolean show_warning; - gboolean searching; + gboolean cups_searching; + gboolean remote_cups_searching; + gboolean snmp_searching; + + GtkCellRenderer *text_renderer; + GtkCellRenderer *icon_renderer; + + GtkWidget *dialog; }; -static void -show_notification (gchar *primary_text, - gchar *secondary_text, - gchar *icon_name) -{ - if (primary_text) - { - NotifyNotification *notification; - notification = notify_notification_new (primary_text, - secondary_text, - icon_name); - notify_notification_set_app_name (notification, _("Printers")); - notify_notification_set_hint (notification, "transient", g_variant_new_boolean (TRUE)); +#define PP_NEW_PRINTER_DIALOG_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), PP_TYPE_NEW_PRINTER_DIALOG, PpNewPrinterDialogPrivate)) - notify_notification_show (notification, NULL); - g_object_unref (notification); +static void pp_new_printer_dialog_finalize (GObject *object); + +enum { + PRE_RESPONSE, + RESPONSE, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +G_DEFINE_TYPE (PpNewPrinterDialog, pp_new_printer_dialog, G_TYPE_OBJECT) + +static void +pp_new_printer_dialog_class_init (PpNewPrinterDialogClass *klass) +{ + GObjectClass *object_class; + + object_class = G_OBJECT_CLASS (klass); + object_class->finalize = pp_new_printer_dialog_finalize; + + g_type_class_add_private (object_class, sizeof (PpNewPrinterDialogPrivate)); + + /** + * PpNewPrinterDialog::pre-response: + * @device: the device that is being added + * + * The signal which gets emitted when the new printer dialog is closed. + */ + signals[PRE_RESPONSE] = + g_signal_new ("pre-response", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (PpNewPrinterDialogClass, pre_response), + NULL, NULL, + g_cclosure_marshal_generic, + G_TYPE_NONE, 4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN); + + /** + * PpNewPrinterDialog::response: + * @response-id: response id of dialog + * + * The signal which gets emitted after the printer is added and configured. + */ + signals[RESPONSE] = + g_signal_new ("response", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (PpNewPrinterDialogClass, response), + NULL, NULL, + g_cclosure_marshal_generic, + G_TYPE_NONE, 1, G_TYPE_INT); +} + + +PpNewPrinterDialog * +pp_new_printer_dialog_new (GtkWindow *parent) +{ + PpNewPrinterDialogPrivate *priv; + PpNewPrinterDialog *dialog; + + dialog = g_object_new (PP_TYPE_NEW_PRINTER_DIALOG, NULL); + priv = dialog->priv; + + gtk_window_set_transient_for (GTK_WINDOW (priv->dialog), GTK_WINDOW (parent)); + + return PP_NEW_PRINTER_DIALOG (dialog); +} + +static void +emit_pre_response (PpNewPrinterDialog *dialog, + const gchar *device_name, + const gchar *device_location, + const gchar *device_make_and_model, + gboolean network_device) +{ + g_signal_emit (dialog, + signals[PRE_RESPONSE], + 0, + device_name, + device_location, + device_make_and_model, + network_device); +} + +static void +emit_response (PpNewPrinterDialog *dialog, + gint response_id) +{ + g_signal_emit (dialog, signals[RESPONSE], 0, response_id); +} + +/* + * Modify padding of the content area of the GtkDialog + * so it is aligned with the action area. + */ +static void +update_alignment_padding (GtkWidget *widget, + GtkAllocation *allocation, + gpointer user_data) +{ + PpNewPrinterDialog *dialog = (PpNewPrinterDialog*) user_data; + PpNewPrinterDialogPrivate *priv = dialog->priv; + GtkAllocation allocation1, allocation2; + GtkWidget *action_area; + GtkWidget *content_area; + gint offset_left, offset_right; + guint padding_left, padding_right, + padding_top, padding_bottom; + + action_area = (GtkWidget*) + gtk_builder_get_object (priv->builder, "dialog-action-area1"); + gtk_widget_get_allocation (action_area, &allocation2); + + content_area = (GtkWidget*) + gtk_builder_get_object (priv->builder, "content-alignment"); + gtk_widget_get_allocation (content_area, &allocation1); + + offset_left = allocation2.x - allocation1.x; + offset_right = (allocation1.x + allocation1.width) - + (allocation2.x + allocation2.width); + + gtk_alignment_get_padding (GTK_ALIGNMENT (content_area), + &padding_top, &padding_bottom, + &padding_left, &padding_right); + if (allocation1.x >= 0 && allocation2.x >= 0) + { + if (offset_left > 0 && offset_left != padding_left) + gtk_alignment_set_padding (GTK_ALIGNMENT (content_area), + padding_top, padding_bottom, + offset_left, padding_right); + + gtk_alignment_get_padding (GTK_ALIGNMENT (content_area), + &padding_top, &padding_bottom, + &padding_left, &padding_right); + if (offset_right > 0 && offset_right != padding_right) + gtk_alignment_set_padding (GTK_ALIGNMENT (content_area), + padding_top, padding_bottom, + padding_left, offset_right); } } static void -device_type_selection_changed_cb (GtkTreeSelection *selection, - gpointer user_data) +pp_new_printer_dialog_init (PpNewPrinterDialog *dialog) { - PpNewPrinterDialog *pp = (PpNewPrinterDialog *) user_data; - GtkTreeModel *model; - GtkTreeIter iter; - GtkWidget *treeview = NULL; - GtkWidget *notebook = NULL; - GtkWidget *widget; - gchar *device_type_name = NULL; - gint device_type_id = -1; - gint device_type = -1; + PpNewPrinterDialogPrivate *priv; + GtkStyleContext *context; + GtkWidget *widget; + GError *error = NULL; + gchar *objects[] = { "dialog", NULL }; + guint builder_result; - if (gtk_tree_selection_get_selected (selection, &model, &iter)) + priv = PP_NEW_PRINTER_DIALOG_GET_PRIVATE (dialog); + dialog->priv = priv; + + priv->builder = gtk_builder_new (); + + builder_result = gtk_builder_add_objects_from_file (priv->builder, + DATADIR"/new-printer-dialog.ui", + objects, &error); + + if (builder_result == 0) { - gtk_tree_model_get (model, &iter, - DEVICE_TYPE_ID_COLUMN, &device_type_id, - DEVICE_TYPE_NAME_COLUMN, &device_type_name, - DEVICE_TYPE_TYPE_COLUMN, &device_type, - -1); + g_warning ("Could not load ui: %s", error->message); + g_error_free (error); } - if (device_type >= 0) + /* GCancellable for cancelling of async operations */ + priv->cancellable = g_cancellable_new (); + + priv->devices = NULL; + priv->new_devices = NULL; + priv->dests = NULL; + priv->num_of_dests = 0; + priv->cups_searching = FALSE; + priv->remote_cups_searching = FALSE; + priv->snmp_searching = FALSE; + priv->text_renderer = NULL; + priv->icon_renderer = NULL; + + /* Construct dialog */ + priv->dialog = (GtkWidget*) gtk_builder_get_object (priv->builder, "dialog"); + + /* Connect signals */ + g_signal_connect (priv->dialog, "response", G_CALLBACK (new_printer_dialog_response_cb), dialog); + g_signal_connect (priv->dialog, "size-allocate", G_CALLBACK (update_alignment_padding), dialog); + + widget = (GtkWidget*) + gtk_builder_get_object (priv->builder, "search-entry"); + g_signal_connect (widget, "icon-press", G_CALLBACK (search_address_cb2), dialog); + g_signal_connect (widget, "activate", G_CALLBACK (search_address_cb), dialog); + + /* Set junctions */ + widget = (GtkWidget*) + gtk_builder_get_object (priv->builder, "scrolledwindow1"); + 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, "toolbar1"); + context = gtk_widget_get_style_context (widget); + gtk_style_context_set_junction_sides (context, GTK_JUNCTION_TOP); + + /* Fill with data */ + populate_devices_list (dialog); + + gtk_widget_show (priv->dialog); +} + +static void +pp_new_printer_dialog_finalize (GObject *object) +{ + PpNewPrinterDialog *dialog = PP_NEW_PRINTER_DIALOG (object); + PpNewPrinterDialogPrivate *priv = dialog->priv; + + priv->text_renderer = NULL; + priv->icon_renderer = NULL; + + if (priv->cancellable) { - widget = (GtkWidget*) - gtk_builder_get_object (pp->builder, "device-type-notebook"); - - gtk_notebook_set_current_page (GTK_NOTEBOOK (widget), device_type); - - if (device_type == DEVICE_TYPE_LOCAL) - { - treeview = (GtkWidget*) - gtk_builder_get_object (pp->builder, "local-devices-treeview"); - notebook = (GtkWidget*) - gtk_builder_get_object (pp->builder, "local-devices-notebook"); - } - else if (device_type == DEVICE_TYPE_NETWORK) - { - treeview = (GtkWidget*) - gtk_builder_get_object (pp->builder, "network-devices-treeview"); - notebook = (GtkWidget*) - gtk_builder_get_object (pp->builder, "network-devices-notebook"); - } - - if (notebook) - { - if (pp->show_warning && device_type == DEVICE_TYPE_NETWORK) - gtk_notebook_set_current_page (GTK_NOTEBOOK (notebook), WARNING_TAB); - else - gtk_notebook_set_current_page (GTK_NOTEBOOK (notebook), STANDARD_TAB); - } - - widget = (GtkWidget*) - gtk_builder_get_object (pp->builder, "new-printer-add-button"); - - if (treeview) - gtk_widget_set_sensitive (widget, - gtk_tree_selection_get_selected ( - gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)), - &model, - &iter)); + g_cancellable_cancel (priv->cancellable); + g_clear_object (&priv->cancellable); } + + if (priv->builder) + g_clear_object (&priv->builder); + + g_list_free_full (priv->devices, t_device_free); + priv->devices = NULL; + + g_list_free_full (priv->new_devices, t_device_free); + priv->new_devices = NULL; + + if (priv->num_of_dests > 0) + { + cupsFreeDests (priv->num_of_dests, priv->dests); + priv->num_of_dests = 0; + priv->dests = NULL; + } + + G_OBJECT_CLASS (pp_new_printer_dialog_parent_class)->finalize (object); } static void device_selection_changed_cb (GtkTreeSelection *selection, gpointer user_data) { - PpNewPrinterDialog *pp = (PpNewPrinterDialog *) user_data; - GtkTreeModel *model; - GtkTreeIter iter; - GtkWidget *treeview = NULL; - GtkWidget *widget; - gchar *device_type_name = NULL; - gint device_type_id = -1; - gint device_type = -1; + PpNewPrinterDialog *dialog = PP_NEW_PRINTER_DIALOG (user_data); + PpNewPrinterDialogPrivate *priv = dialog->priv; + GtkTreeModel *model; + GtkTreeIter iter; + GtkWidget *treeview = NULL; + GtkWidget *widget; treeview = (GtkWidget*) - gtk_builder_get_object (pp->builder, "device-types-treeview"); - - if (gtk_tree_selection_get_selected ( - gtk_tree_view_get_selection ( - GTK_TREE_VIEW (treeview)), &model, &iter)) - gtk_tree_model_get (model, &iter, - DEVICE_TYPE_ID_COLUMN, &device_type_id, - DEVICE_TYPE_NAME_COLUMN, &device_type_name, - DEVICE_TYPE_TYPE_COLUMN, &device_type, - -1); - - if (device_type == DEVICE_TYPE_LOCAL) - treeview = (GtkWidget*) - gtk_builder_get_object (pp->builder, "local-devices-treeview"); - else if (device_type == DEVICE_TYPE_NETWORK) - treeview = (GtkWidget*) - gtk_builder_get_object (pp->builder, "network-devices-treeview"); + gtk_builder_get_object (priv->builder, "devices-treeview"); widget = (GtkWidget*) - gtk_builder_get_object (pp->builder, "new-printer-add-button"); + gtk_builder_get_object (priv->builder, "new-printer-add-button"); if (treeview) gtk_widget_set_sensitive (widget, @@ -261,1846 +379,1144 @@ device_selection_changed_cb (GtkTreeSelection *selection, } static void -free_devices (PpNewPrinterDialog *pp) +add_device_to_list (PpNewPrinterDialog *dialog, + PpPrintDevice *device, + gboolean new_device) { - int i; + PpNewPrinterDialogPrivate *priv = dialog->priv; + gboolean network_device; + gboolean already_present; + TDevice *store_device; + TDevice *item; + GList *iter; + gchar *name = NULL; + gchar *canonized_name = NULL; + gchar *new_name; + gchar *new_canonized_name = NULL; + gint name_index, j; - for (i = 0; i < pp->num_devices; i++) + if (device) { - g_free (pp->devices[i].device_class); - g_free (pp->devices[i].device_id); - g_free (pp->devices[i].device_info); - g_free (pp->devices[i].device_make_and_model); - g_free (pp->devices[i].device_uri); - g_free (pp->devices[i].device_location); - g_free (pp->devices[i].device_ppd_uri); - g_free (pp->devices[i].display_name); - g_free (pp->devices[i].hostname); - } - - pp->num_devices = 0; - pp->devices = NULL; -} - -static void -store_device_parameter (gpointer key, - gpointer value, - gpointer user_data) -{ - PpNewPrinterDialog *pp = (PpNewPrinterDialog *) user_data; - gchar *cut; - gint index = -1; - - cut = g_strrstr ((gchar *)key, ":"); - if (cut) - index = atoi ((gchar *)cut + 1); - - if (index >= 0) - { - if (g_str_has_prefix ((gchar *)key, "device-class")) - pp->devices[index].device_class = g_strdup ((gchar *)value); - else if (g_str_has_prefix ((gchar *)key, "device-id")) - pp->devices[index].device_id = g_strdup ((gchar *)value); - else if (g_str_has_prefix ((gchar *)key, "device-info")) - pp->devices[index].device_info = g_strdup ((gchar *)value); - else if (g_str_has_prefix ((gchar *)key, "device-make-and-model")) - pp->devices[index].device_make_and_model = g_strdup ((gchar *)value); - else if (g_str_has_prefix ((gchar *)key, "device-uri")) - pp->devices[index].device_uri = g_strdup ((gchar *)value); - else if (g_str_has_prefix ((gchar *)key, "device-location")) - pp->devices[index].device_location = g_strdup ((gchar *)value); - } -} - -static void -devices_get_cb (GObject *source_object, - GAsyncResult *res, - gpointer user_data) -{ - PpNewPrinterDialog *pp = user_data; - cups_dest_t *dests; - GHashTable *devices = NULL; - GDBusConnection *bus; - GtkWidget *widget = NULL; - GVariant *dg_output = NULL; - gboolean already_present; - GError *error = NULL; - gchar *new_name = NULL; - gchar *device_uri = NULL; - char *ret_error = NULL; - gint i, j, k; - gint name_index; - gint num_dests; - - - dg_output = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object), - res, - &error); - - /* Do nothing if cancelled */ - if (!dg_output && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) - { - g_error_free (error); - return; - } - - if (dg_output) - { - if (g_variant_n_children (dg_output) == 2) + if (device->device_id || + device->device_ppd || + (device->host_name && + device->acquisition_method == ACQUISITION_METHOD_REMOTE_CUPS_SERVER)) { - GVariant *devices_variant = NULL; + network_device = FALSE; - g_variant_get (dg_output, "(&s@a{ss})", - &ret_error, - &devices_variant); + if (device->device_class && + g_strcmp0 (device->device_class, "network") == 0) + network_device = TRUE; - if (devices_variant) + store_device = g_new0 (TDevice, 1); + store_device->device_original_name = g_strdup (device->device_name); + store_device->device_info = g_strdup (device->device_info); + store_device->device_location = g_strdup (device->device_location); + store_device->device_make_and_model = g_strdup (device->device_make_and_model); + store_device->device_uri = g_strdup (device->device_uri); + store_device->device_id = g_strdup (device->device_id); + store_device->device_ppd = g_strdup (device->device_ppd); + store_device->host_name = g_strdup (device->host_name); + store_device->host_port = device->host_port; + store_device->network_device = network_device; + store_device->acquisition_method = device->acquisition_method; + store_device->show = TRUE; + + if (device->device_id) { - if (g_variant_is_of_type (devices_variant, G_VARIANT_TYPE ("a{ss}"))) - { - GVariantIter *iter; - GVariant *item; - g_variant_get (devices_variant, - "a{ss}", - &iter); - devices = g_hash_table_new (g_str_hash, g_str_equal); - while ((item = g_variant_iter_next_value (iter))) - { - gchar *key; - gchar *value; - g_variant_get (item, - "{ss}", - &key, - &value); - - g_hash_table_insert (devices, key, value); - - g_variant_unref (item); - } - } - g_variant_unref (devices_variant); + name = get_tag_value (device->device_id, "mdl"); + if (!name) + name = get_tag_value (device->device_id, "model"); } - } - g_variant_unref (dg_output); - } - else - { - g_warning ("%s", error->message); - g_error_free (error); - } - g_object_unref (source_object); - - if (ret_error && ret_error[0] != '\0') - g_warning ("%s", ret_error); - - free_devices (pp); - if (devices) - { - GList *keys; - GList *iter; - gchar *cut; - gint max_index = -1; - gint index; - - keys = g_hash_table_get_keys (devices); - for (iter = keys; iter; iter = iter->next) - { - index = -1; - - cut = g_strrstr ((gchar *)iter->data, ":"); - if (cut) - index = atoi (cut + 1); - - if (index > max_index) - max_index = index; - } - - if (max_index >= 0) - { - pp->num_devices = max_index + 1; - pp->devices = g_new0 (CupsDevice, pp->num_devices); - - g_hash_table_foreach (devices, store_device_parameter, pp); - - /* Assign names to devices */ - for (i = 0; i < pp->num_devices; i++) + if (!name && + device->device_make_and_model && + device->device_make_and_model[0] != '\0') { - gchar *name = NULL; + name = g_strdup (device->device_make_and_model); + } - if (pp->devices[i].device_id) + if (!name && + device->device_name && + device->device_name[0] != '\0') + { + name = g_strdup (device->device_name); + } + + if (!name && + device->device_info && + device->device_info[0] != '\0') + { + name = g_strdup (device->device_info); + } + + g_strstrip (name); + + name_index = 2; + already_present = FALSE; + do + { + if (already_present) { - name = get_tag_value (pp->devices[i].device_id, "mdl"); - if (!name) - name = get_tag_value (pp->devices[i].device_id, "model"); - - if (name) - name = g_strcanon (name, ALLOWED_CHARACTERS, '-'); + new_name = g_strdup_printf ("%s %d", name, name_index); + name_index++; + } + else + { + new_name = g_strdup (name); } - if (!name && - pp->devices[i].device_info) + if (new_name) { - name = g_strdup (pp->devices[i].device_info); - if (name) - name = g_strcanon (name, ALLOWED_CHARACTERS, '-'); + new_canonized_name = g_strcanon (g_strdup (new_name), ALLOWED_CHARACTERS, '-'); } - name_index = 2; already_present = FALSE; - num_dests = cupsGetDests (&dests); - do + for (j = 0; j < priv->num_of_dests; j++) + if (g_strcmp0 (priv->dests[j].name, new_canonized_name) == 0) + already_present = TRUE; + + for (iter = priv->devices; iter; iter = iter->next) { - if (already_present) - { - new_name = g_strdup_printf ("%s-%d", name, name_index); - name_index++; - } - else - new_name = g_strdup (name); - - already_present = FALSE; - for (j = 0; j < num_dests; j++) - if (g_strcmp0 (dests[j].name, new_name) == 0) - already_present = TRUE; - - if (already_present) - g_free (new_name); - else - { - g_free (name); - name = new_name; - } - } while (already_present); - cupsFreeDests (num_dests, dests); - - pp->devices[i].display_name = name; - } - - /* Set show bool - * Don't show duplicates. - * Show devices with device-id. - * Other preferences should apply here. - */ - bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error); - if (bus) - { - GVariantBuilder device_list; - GVariantBuilder device_hash; - GVariant *output = NULL; - GVariant *array = NULL; - GVariant *subarray = NULL; - - g_variant_builder_init (&device_list, G_VARIANT_TYPE ("a{sv}")); - - for (i = 0; i < pp->num_devices; i++) - { - if (pp->devices[i].device_uri) - { - g_variant_builder_init (&device_hash, G_VARIANT_TYPE ("a{ss}")); - - if (pp->devices[i].device_id) - g_variant_builder_add (&device_hash, - "{ss}", - "device-id", - pp->devices[i].device_id); - - if (pp->devices[i].device_make_and_model) - g_variant_builder_add (&device_hash, - "{ss}", - "device-make-and-model", - pp->devices[i].device_make_and_model); - - if (pp->devices[i].device_class) - g_variant_builder_add (&device_hash, - "{ss}", - "device-class", - pp->devices[i].device_class); - - g_variant_builder_add (&device_list, - "{sv}", - pp->devices[i].device_uri, - g_variant_builder_end (&device_hash)); - } + item = (TDevice *) iter->data; + if (g_strcmp0 (item->device_name, new_canonized_name) == 0) + already_present = TRUE; } - output = g_dbus_connection_call_sync (bus, - SCP_BUS, - SCP_PATH, - SCP_IFACE, - "GroupPhysicalDevices", - g_variant_new ("(v)", g_variant_builder_end (&device_list)), - NULL, - G_DBUS_CALL_FLAGS_NONE, - 60000, - NULL, - &error); - - if (output && g_variant_n_children (output) == 1) + for (iter = priv->new_devices; iter; iter = iter->next) { - array = g_variant_get_child_value (output, 0); - if (array) - { - for (i = 0; i < g_variant_n_children (array); i++) - { - subarray = g_variant_get_child_value (array, i); - if (subarray) - { - device_uri = g_strdup (g_variant_get_string ( - g_variant_get_child_value (subarray, 0), - NULL)); - - for (k = 0; k < pp->num_devices; k++) - if (g_str_has_prefix (pp->devices[k].device_uri, device_uri)) - pp->devices[k].show = TRUE; - - g_free (device_uri); - } - } - } + item = (TDevice *) iter->data; + if (g_strcmp0 (item->device_name, new_canonized_name) == 0) + already_present = TRUE; } - if (output) - g_variant_unref (output); - g_object_unref (bus); - } - - if (error) - { - if (bus == NULL || - (error->domain == G_DBUS_ERROR && - (error->code == G_DBUS_ERROR_SERVICE_UNKNOWN || - error->code == G_DBUS_ERROR_UNKNOWN_METHOD))) - g_warning ("Install system-config-printer which provides \ -DBus method \"GroupPhysicalDevices\" to group duplicates in device list."); - - for (i = 0; i < pp->num_devices; i++) - pp->devices[i].show = TRUE; - } - - for (i = 0; i < pp->num_devices; i++) - if (!pp->devices[i].device_id) - pp->devices[i].show = FALSE; - } - - g_hash_table_destroy (devices); - actualize_devices_list (pp); - } - - widget = (GtkWidget*) - gtk_builder_get_object (pp->builder, "get-devices-status-label"); - gtk_label_set_text (GTK_LABEL (widget), " "); - - widget = (GtkWidget*) - gtk_builder_get_object (pp->builder, "spinner"); - gtk_spinner_stop (GTK_SPINNER (widget)); - gtk_widget_set_sensitive (widget, FALSE); - gtk_widget_hide (widget); - - if (pp->cancellable != NULL) - { - g_object_unref (pp->cancellable); - pp->cancellable = NULL; - } -} - -static void -devices_get (PpNewPrinterDialog *pp) -{ - GDBusProxy *proxy; - GError *error = NULL; - GVariantBuilder *in_include = NULL; - GVariantBuilder *in_exclude = NULL; - GtkWidget *widget = NULL; - - pp->searching = TRUE; - - proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - MECHANISM_BUS, - "/", - MECHANISM_BUS, - NULL, - &error); - - if (!proxy) - { - g_warning ("%s", error->message); - g_error_free (error); - pp->searching = FALSE; - return; - } - - if (pp->show_warning) - { - widget = (GtkWidget*) - gtk_builder_get_object (pp->builder, "local-devices-notebook"); - gtk_notebook_set_current_page (GTK_NOTEBOOK (widget), WARNING_TAB); - - widget = (GtkWidget*) - gtk_builder_get_object (pp->builder, "network-devices-notebook"); - gtk_notebook_set_current_page (GTK_NOTEBOOK (widget), WARNING_TAB); - } - - in_include = g_variant_builder_new (G_VARIANT_TYPE ("as")); - in_exclude = g_variant_builder_new (G_VARIANT_TYPE ("as")); - - widget = (GtkWidget*) - gtk_builder_get_object (pp->builder, "get-devices-status-label"); - gtk_label_set_text (GTK_LABEL (widget), _("Getting devices...")); - - widget = (GtkWidget*) - gtk_builder_get_object (pp->builder, "spinner"); - gtk_spinner_start (GTK_SPINNER (widget)); - gtk_widget_set_sensitive (widget, TRUE); - gtk_widget_show (widget); - - pp->cancellable = g_cancellable_new (); - - g_dbus_proxy_call (proxy, - "DevicesGet", - g_variant_new ("(iiasas)", - 0, - 60, - in_include, - in_exclude), - G_DBUS_CALL_FLAGS_NONE, - 60000, - pp->cancellable, - devices_get_cb, - pp); - - pp->searching = FALSE; -} - -static gchar ** -line_split (gchar *line) -{ - gboolean escaped = FALSE; - gboolean quoted = FALSE; - gboolean in_word = FALSE; - gchar **words = NULL; - gchar **result = NULL; - gchar *buffer = NULL; - gchar ch; - gint n = 0; - gint i, j = 0, k = 0; - - if (line) - { - n = strlen (line); - words = g_new0 (gchar *, n + 1); - buffer = g_new0 (gchar, n + 1); - - for (i = 0; i < n; i++) - { - ch = line[i]; - - if (escaped) - { - buffer[k++] = ch; - escaped = FALSE; - continue; - } - - if (ch == '\\') - { - in_word = TRUE; - escaped = TRUE; - continue; - } - - if (in_word) - { - if (quoted) + if (already_present) { - if (ch == '"') - quoted = FALSE; - else - buffer[k++] = ch; + g_free (new_name); + g_free (new_canonized_name); } - else if (g_ascii_isspace (ch)) - { - words[j++] = g_strdup (buffer); - memset (buffer, 0, n + 1); - k = 0; - in_word = FALSE; - } - else if (ch == '"') - quoted = TRUE; else - buffer[k++] = ch; - } + { + g_free (name); + g_free (canonized_name); + name = new_name; + canonized_name = new_canonized_name; + } + } while (already_present); + + store_device->display_name = g_strdup (canonized_name); + store_device->device_name = canonized_name; + g_free (name); + + if (new_device) + priv->new_devices = g_list_append (priv->new_devices, store_device); else - { - if (ch == '"') - { - in_word = TRUE; - quoted = TRUE; - } - else if (!g_ascii_isspace (ch)) - { - in_word = TRUE; - buffer[k++] = ch; - } - } + priv->devices = g_list_append (priv->devices, store_device); } } - - if (buffer && buffer[0] != '\0') - words[j++] = g_strdup (buffer); - - result = g_strdupv (words); - g_strfreev (words); - g_free (buffer); - - return result; } static void -service_enable (gchar *service_name, - gint service_timeout) +add_devices_to_list (PpNewPrinterDialog *dialog, + GList *devices, + gboolean new_device) { - GDBusConnection *bus; - GVariant *output = NULL; - GError *error = NULL; + GList *iter; - bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error); - if (!bus) + for (iter = devices; iter; iter = iter->next) { - g_warning ("%s", error->message); - g_error_free (error); - return; + add_device_to_list (dialog, (PpPrintDevice *) iter->data, new_device); + } +} + +static TDevice * +device_in_list (gchar *device_uri, + GList *device_list) +{ + GList *iter; + TDevice *device; + + for (iter = device_list; iter; iter = iter->next) + { + device = (TDevice *) iter->data; + /* GroupPhysicalDevices returns uris without port numbers */ + if (g_str_has_prefix (device->device_uri, device_uri)) + return device; } - output = g_dbus_connection_call_sync (bus, - FIREWALLD_BUS, - FIREWALLD_PATH, - FIREWALLD_IFACE, - "enableService", - g_variant_new ("(si)", - service_name, - service_timeout), - NULL, - G_DBUS_CALL_FLAGS_NONE, - 60000, - NULL, - &error); + return NULL; +} - g_object_unref (bus); +static void +t_device_free (gpointer data) +{ + if (data) + { + TDevice *device = (TDevice *) data; - if (output) - { - g_variant_unref (output); - } - else - { - g_warning ("%s", error->message); - g_error_free (error); + g_free (device->display_name); + g_free (device->device_name); + g_free (device->device_original_name); + g_free (device->device_info); + g_free (device->device_location); + g_free (device->device_make_and_model); + g_free (device->device_uri); + g_free (device->device_id); + g_free (device->device_ppd); + g_free (device); } } static void -service_disable (gchar *service_name) +update_spinner_state (PpNewPrinterDialog *dialog) { - GDBusConnection *bus; - GVariant *output = NULL; - GError *error = NULL; + PpNewPrinterDialogPrivate *priv = dialog->priv; + GtkWidget *spinner; - bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error); - if (!bus) + if (priv->cups_searching || + priv->remote_cups_searching || + priv->snmp_searching) { - g_warning ("%s", error->message); - g_error_free (error); - return; - } - - output = g_dbus_connection_call_sync (bus, - FIREWALLD_BUS, - FIREWALLD_PATH, - FIREWALLD_IFACE, - "disableService", - g_variant_new ("(s)", service_name), - NULL, - G_DBUS_CALL_FLAGS_NONE, - 60000, - NULL, - &error); - - g_object_unref (bus); - - if (output) - { - g_variant_unref (output); + spinner = (GtkWidget*) + gtk_builder_get_object (priv->builder, "spinner"); + gtk_spinner_start (GTK_SPINNER (spinner)); + gtk_widget_show (spinner); } else { - g_warning ("%s", error->message); - g_error_free (error); + spinner = (GtkWidget*) + gtk_builder_get_object (priv->builder, "spinner"); + gtk_spinner_stop (GTK_SPINNER (spinner)); + gtk_widget_hide (spinner); } } -static gboolean -service_enabled (gchar *service_name) -{ - GDBusConnection *bus; - GVariant *output = NULL; - GError *error = NULL; - gint query_result = 0; - - bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error); - if (!bus) - { - g_warning ("%s", error->message); - g_error_free (error); - return FALSE; - } - - output = g_dbus_connection_call_sync (bus, - FIREWALLD_BUS, - FIREWALLD_PATH, - FIREWALLD_IFACE, - "queryService", - g_variant_new ("(s)", service_name), - G_VARIANT_TYPE ("(i)"), - G_DBUS_CALL_FLAGS_NONE, - 60000, - NULL, - &error); - - g_object_unref (bus); - - if (output) - { - if (g_variant_n_children (output) == 1) - g_variant_get (output, "(i)", &query_result); - g_variant_unref (output); - } - else - { - g_warning ("%s", error->message); - g_error_free (error); - return FALSE; - } - - if (query_result > 0) - return TRUE; - else - return FALSE; -} - -static gboolean -dbus_method_available (gchar *name, - gchar *path, - gchar *iface, - gchar *method) -{ - GDBusConnection *bus; - GError *error = NULL; - GVariant *output = NULL; - gboolean result = FALSE; - - bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error); - if (!bus) - { - g_warning ("%s", error->message); - g_error_free (error); - return FALSE; - } - - output = g_dbus_connection_call_sync (bus, - name, - path, - iface, - method, - NULL, - NULL, - G_DBUS_CALL_FLAGS_NONE, - 60000, - NULL, - &error); - - g_object_unref (bus); - - if (output) - { - g_variant_unref (output); - result = TRUE; - } - else - { - if (error->domain == G_DBUS_ERROR && - error->code == G_DBUS_ERROR_SERVICE_UNKNOWN) - result = FALSE; - else - result = TRUE; - } - - return result; -} - static void -search_address_cb (GtkToggleButton *togglebutton, - gpointer user_data) +group_physical_devices_cb (gchar ***device_uris, + gpointer user_data) { - PpNewPrinterDialog *pp = (PpNewPrinterDialog*) user_data; - GtkWidget *widget; - gint i; + PpNewPrinterDialog *dialog = (PpNewPrinterDialog *) user_data; + PpNewPrinterDialogPrivate *priv = dialog->priv; + TDevice *device, *tmp; + gint i, j; - pp->searching = TRUE; - - widget = (GtkWidget*) - gtk_builder_get_object (pp->builder, "search-by-address-checkbutton"); - - if (widget && gtk_toggle_button_get_active (togglebutton)) + if (device_uris) { - gchar *uri = NULL; - - widget = (GtkWidget*) - gtk_builder_get_object (pp->builder, "address-entry"); - uri = g_strdup (gtk_entry_get_text (GTK_ENTRY (widget))); - - if (uri && uri[0] != '\0') + for (i = 0; device_uris[i]; i++) { - cups_dest_t *dests = NULL; - http_t *http; - GError *error = NULL; - gchar *tmp = NULL; - gchar *host = NULL; - gchar *port_string = NULL; - gchar *position; - gchar *command; - gchar *standard_output = NULL; - gint exit_status = -1; - gint num_dests = 0; - gint length; - int port = 631; - - if (g_strrstr (uri, "://")) - tmp = g_strrstr (uri, "://") + 3; - else - tmp = uri; - - if (g_strrstr (tmp, "@")) - tmp = g_strrstr (tmp, "@") + 1; - - if ((position = g_strrstr (tmp, "/"))) + if (device_uris[i]) { - *position = '\0'; - host = g_strdup (tmp); - *position = '/'; - } - else - host = g_strdup (tmp); - - if ((position = g_strrstr (host, ":"))) - { - *position = '\0'; - port_string = position + 1; - } - - if (port_string) - port = atoi (port_string); - - if (host) - { - /* Use CUPS to get printer's informations */ - http = httpConnectEncrypt (host, port, cupsEncryption ()); - if (http) + for (j = 0; device_uris[i][j]; j++) { - gchar *device_uri = NULL; - gchar *device_ppd_uri = NULL; - - num_dests = cupsGetDests2 (http, &dests); - - if (num_dests > 0) - { - CupsDevice *devices = NULL; - devices = g_new0 (CupsDevice, pp->num_devices + num_dests); - - for (i = 0; i < pp->num_devices; i++) - { - devices[i] = pp->devices[i]; - pp->devices[i].device_class = NULL; - pp->devices[i].device_id = NULL; - pp->devices[i].device_info = NULL; - pp->devices[i].device_make_and_model = NULL; - pp->devices[i].device_uri = NULL; - pp->devices[i].device_location = NULL; - pp->devices[i].device_ppd_uri = NULL; - pp->devices[i].display_name = NULL; - pp->devices[i].hostname = NULL; - } - - g_free (pp->devices); - pp->devices = devices; - - for (i = 0; i < num_dests; i++) - { - device_uri = g_strdup_printf ("ipp://%s:%d/printers/%s", host, port, dests[i].name); - device_ppd_uri = g_strdup_printf ("%s.ppd", device_uri); - - pp->devices[pp->num_devices + i].device_class = g_strdup ("network"); - pp->devices[pp->num_devices + i].device_uri = device_uri; - pp->devices[pp->num_devices + i].display_name = g_strdup (dests[i].name); - pp->devices[pp->num_devices + i].device_ppd_uri = device_ppd_uri; - pp->devices[pp->num_devices + i].show = TRUE; - pp->devices[pp->num_devices + i].hostname = g_strdup (host); - pp->devices[pp->num_devices + i].host_port = port; - pp->devices[pp->num_devices + i].found = TRUE; - } - - pp->num_devices += num_dests; - } - - httpClose (http); + device = device_in_list (device_uris[i][j], priv->devices); + if (device) + break; } - /* Use SNMP to get printer's informations */ - command = g_strdup_printf ("/usr/lib/cups/backend/snmp %s", host); - if (g_spawn_command_line_sync (command, &standard_output, NULL, &exit_status, &error)) + if (device) { - if (exit_status == 0 && standard_output) + for (j = 0; device_uris[i][j]; j++) { - gchar **printer_informations = NULL; - - printer_informations = line_split (standard_output); - length = g_strv_length (printer_informations); - - if (length >= 4) + tmp = device_in_list (device_uris[i][j], priv->new_devices); + if (tmp) { - CupsDevice *devices = NULL; - devices = g_new0 (CupsDevice, pp->num_devices + 1); - - for (i = 0; i < pp->num_devices; i++) - { - devices[i] = pp->devices[i]; - pp->devices[i].device_class = NULL; - pp->devices[i].device_id = NULL; - pp->devices[i].device_info = NULL; - pp->devices[i].device_make_and_model = NULL; - pp->devices[i].device_uri = NULL; - pp->devices[i].device_location = NULL; - pp->devices[i].device_ppd_uri = NULL; - pp->devices[i].display_name = NULL; - pp->devices[i].hostname = NULL; - } - - g_free (pp->devices); - pp->devices = devices; - - pp->devices[pp->num_devices].device_class = g_strdup (printer_informations[0]); - pp->devices[pp->num_devices].device_uri = g_strdup (printer_informations[1]); - pp->devices[pp->num_devices].device_make_and_model = g_strdup (printer_informations[2]); - pp->devices[pp->num_devices].device_info = g_strdup (printer_informations[3]); - pp->devices[pp->num_devices].display_name = g_strdup (printer_informations[3]); - pp->devices[pp->num_devices].display_name = - g_strcanon (pp->devices[pp->num_devices].display_name, ALLOWED_CHARACTERS, '-'); - pp->devices[pp->num_devices].show = TRUE; - pp->devices[pp->num_devices].hostname = g_strdup (host); - pp->devices[pp->num_devices].host_port = port; - pp->devices[pp->num_devices].found = TRUE; - - if (length >= 5 && printer_informations[4][0] != '\0') - pp->devices[pp->num_devices].device_id = g_strdup (printer_informations[4]); - - if (length >= 6 && printer_informations[5][0] != '\0') - pp->devices[pp->num_devices].device_location = g_strdup (printer_informations[5]); - - pp->num_devices++; + priv->new_devices = g_list_remove (priv->new_devices, tmp); + t_device_free (tmp); } - g_strfreev (printer_informations); - g_free (standard_output); } } else { - g_warning ("%s", error->message); - g_error_free (error); - } - - g_free (command); - g_free (host); - } - } - g_free (uri); - } - else - { - gint length = 0; - gint j = 0; - - for (i = 0; i < pp->num_devices; i++) - if (!pp->devices[i].found) - length++; - - CupsDevice *devices = NULL; - devices = g_new0 (CupsDevice, length); - - for (i = 0; i < pp->num_devices; i++) - { - if (!pp->devices[i].found) - { - devices[j] = pp->devices[i]; - pp->devices[i].device_class = NULL; - pp->devices[i].device_id = NULL; - pp->devices[i].device_info = NULL; - pp->devices[i].device_make_and_model = NULL; - pp->devices[i].device_uri = NULL; - pp->devices[i].device_location = NULL; - pp->devices[i].device_ppd_uri = NULL; - pp->devices[i].display_name = NULL; - pp->devices[i].hostname = NULL; - j++; - } - } - - g_free (pp->devices); - pp->devices = devices; - pp->num_devices = length; - } - - pp->searching = FALSE; - - actualize_devices_list (pp); -} - -static void -actualize_devices_list (PpNewPrinterDialog *pp) -{ - GtkListStore *network_store; - GtkListStore *local_store; - GtkTreeModel *model; - GtkTreeView *network_treeview; - GtkTreeView *local_treeview; - GtkTreeIter iter; - GtkWidget *treeview; - GtkWidget *widget; - GtkWidget *local_notebook; - GtkWidget *network_notebook; - gboolean no_local_device = TRUE; - gboolean no_network_device = TRUE; - gint i; - gint device_type = -1; - - network_treeview = (GtkTreeView*) - gtk_builder_get_object (pp->builder, "network-devices-treeview"); - - local_treeview = (GtkTreeView*) - gtk_builder_get_object (pp->builder, "local-devices-treeview"); - - network_store = gtk_list_store_new (DEVICE_N_COLUMNS, - G_TYPE_INT, - G_TYPE_STRING); - - local_store = gtk_list_store_new (DEVICE_N_COLUMNS, - G_TYPE_INT, - G_TYPE_STRING); - - for (i = 0; i < pp->num_devices; i++) - { - if ((pp->devices[i].device_id || pp->devices[i].device_ppd_uri) && - pp->devices[i].show) - { - if (g_strcmp0 (pp->devices[i].device_class, "network") == 0) - { - gtk_list_store_append (network_store, &iter); - gtk_list_store_set (network_store, &iter, - DEVICE_ID_COLUMN, i, - DEVICE_NAME_COLUMN, pp->devices[i].display_name, - -1); - pp->show_warning = FALSE; - no_network_device = FALSE; - } - else if (g_strcmp0 (pp->devices[i].device_class, "direct") == 0) - { - gtk_list_store_append (local_store, &iter); - gtk_list_store_set (local_store, &iter, - DEVICE_ID_COLUMN, i, - DEVICE_NAME_COLUMN, pp->devices[i].display_name, - -1); - no_local_device = FALSE; - } - } - } - - if (no_local_device && !pp->searching) - { - gtk_list_store_append (local_store, &iter); - gtk_list_store_set (local_store, &iter, - DEVICE_ID_COLUMN, 0, - /* Translators: No localy connected printers were found */ - DEVICE_NAME_COLUMN, _("No local printers found"), - -1); - gtk_widget_set_sensitive (GTK_WIDGET (local_treeview), FALSE); - } - else - gtk_widget_set_sensitive (GTK_WIDGET (local_treeview), TRUE); - - if (no_network_device && !pp->show_warning && !pp->searching) - { - gtk_list_store_append (network_store, &iter); - gtk_list_store_set (network_store, &iter, - DEVICE_ID_COLUMN, 0, - /* Translators: No network printers were found */ - DEVICE_NAME_COLUMN, _("No network printers found"), - -1); - gtk_widget_set_sensitive (GTK_WIDGET (network_treeview), FALSE); - } - else - gtk_widget_set_sensitive (GTK_WIDGET (network_treeview), TRUE); - - gtk_tree_view_set_model (network_treeview, GTK_TREE_MODEL (network_store)); - gtk_tree_view_set_model (local_treeview, GTK_TREE_MODEL (local_store)); - - if (!no_network_device && - gtk_tree_model_get_iter_first ((GtkTreeModel *) network_store, &iter)) - gtk_tree_selection_select_iter ( - gtk_tree_view_get_selection (GTK_TREE_VIEW (network_treeview)), - &iter); - - if (!no_local_device && - gtk_tree_model_get_iter_first ((GtkTreeModel *) local_store, &iter)) - gtk_tree_selection_select_iter ( - gtk_tree_view_get_selection (GTK_TREE_VIEW (local_treeview)), - &iter); - - treeview = (GtkWidget*) - gtk_builder_get_object (pp->builder, "device-types-treeview"); - - if (gtk_tree_selection_get_selected ( - gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)), &model, &iter)) - gtk_tree_model_get (model, &iter, - DEVICE_TYPE_TYPE_COLUMN, &device_type, - -1); - - widget = (GtkWidget*) - gtk_builder_get_object (pp->builder, "device-type-notebook"); - - local_notebook = (GtkWidget*) - gtk_builder_get_object (pp->builder, "local-devices-notebook"); - - network_notebook = (GtkWidget*) - gtk_builder_get_object (pp->builder, "network-devices-notebook"); - - gtk_notebook_set_current_page (GTK_NOTEBOOK (network_notebook), pp->show_warning ? WARNING_TAB : STANDARD_TAB); - gtk_notebook_set_current_page (GTK_NOTEBOOK (local_notebook), STANDARD_TAB); - gtk_notebook_set_current_page (GTK_NOTEBOOK (widget), device_type); - - g_object_unref (network_store); - g_object_unref (local_store); -} - -static void -populate_devices_list (PpNewPrinterDialog *pp) -{ - GtkTreeViewColumn *column; - GtkCellRenderer *renderer; - GtkTextBuffer *text_buffer; - GtkTextView *warning_textview; - GtkTextIter text_iter; - GtkWidget *network_treeview; - GtkWidget *local_treeview; - - network_treeview = (GtkWidget*) - gtk_builder_get_object (pp->builder, "network-devices-treeview"); - - local_treeview = (GtkWidget*) - gtk_builder_get_object (pp->builder, "local-devices-treeview"); - - g_signal_connect (gtk_tree_view_get_selection (GTK_TREE_VIEW (network_treeview)), - "changed", G_CALLBACK (device_selection_changed_cb), pp); - - g_signal_connect (gtk_tree_view_get_selection (GTK_TREE_VIEW (local_treeview)), - "changed", G_CALLBACK (device_selection_changed_cb), pp); - - actualize_devices_list (pp); - - if (dbus_method_available (FIREWALLD_BUS, - FIREWALLD_PATH, - FIREWALLD_IFACE, - "getServices")) - { - if (!service_enabled ("mdns")) - service_enable ("mdns", 300); - - if (!service_enabled ("ipp")) - service_enable ("ipp", 300); - - if (!service_enabled ("ipp-client")) - service_enable ("ipp-client", 300); - - if (!service_enabled ("samba-client")) - service_enable ("samba-client", 300); - } - else - { - pp->warning = g_strdup (_("FirewallD is not running. \ -Network printer detection needs services mdns, ipp, ipp-client \ -and samba-client enabled on firewall.")); - - warning_textview = (GtkTextView*) - gtk_builder_get_object (pp->builder, "local-warning"); - text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (warning_textview)); - - gtk_text_buffer_set_text (text_buffer, "", 0); - gtk_text_buffer_get_iter_at_offset (text_buffer, &text_iter, 0); - gtk_text_buffer_insert (text_buffer, &text_iter, pp->warning, -1); - - warning_textview = (GtkTextView*) - gtk_builder_get_object (pp->builder, "network-warning"); - text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (warning_textview)); - - gtk_text_buffer_set_text (text_buffer, "", 0); - gtk_text_buffer_get_iter_at_offset (text_buffer, &text_iter, 0); - gtk_text_buffer_insert (text_buffer, &text_iter, pp->warning, -1); - - pp->show_warning = TRUE; - } - - devices_get (pp); - - renderer = gtk_cell_renderer_text_new (); - - /* Translators: Column of devices which can be installed */ - column = gtk_tree_view_column_new_with_attributes (_("Devices"), renderer, - "text", DEVICE_NAME_COLUMN, NULL); - gtk_tree_view_append_column (GTK_TREE_VIEW (network_treeview), column); - - /* Translators: Column of devices which can be installed */ - column = gtk_tree_view_column_new_with_attributes (_("Devices"), renderer, - "text", DEVICE_NAME_COLUMN, NULL); - gtk_tree_view_append_column (GTK_TREE_VIEW (local_treeview), column); -} - -static void -actualize_device_types_list (PpNewPrinterDialog *pp) -{ - GtkListStore *store; - GtkTreeView *treeview; - GtkTreeIter iter; - gint i; - - treeview = (GtkTreeView*) - gtk_builder_get_object (pp->builder, "device-types-treeview"); - - store = gtk_list_store_new (DEVICE_TYPE_N_COLUMNS, - G_TYPE_INT, - G_TYPE_STRING, - G_TYPE_INT); - - pp->device_connection_types = g_new (gchar*, 2); - pp->num_device_connection_types = 2; - - /* Translators: Local means local printers */ - pp->device_connection_types[0] = g_strdup (C_("printer type", "Local")); - /* Translators: Network means network printers */ - pp->device_connection_types[1] = g_strdup (C_("printer type", "Network")); - - for (i = 0; i < pp->num_device_connection_types; i++) - { - gtk_list_store_append (store, &iter); - gtk_list_store_set (store, &iter, - DEVICE_TYPE_ID_COLUMN, i, - DEVICE_TYPE_NAME_COLUMN, pp->device_connection_types[i], - DEVICE_TYPE_TYPE_COLUMN, i, - -1); - } - - gtk_tree_view_set_model (treeview, GTK_TREE_MODEL (store)); - - gtk_tree_model_get_iter_first ((GtkTreeModel *) store, - &iter); - - gtk_tree_selection_select_iter ( - gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)), - &iter); - - g_object_unref (store); -} - -static void -populate_device_types_list (PpNewPrinterDialog *pp) -{ - GtkTreeViewColumn *column; - GtkCellRenderer *renderer; - GtkWidget *treeview; - - treeview = (GtkWidget*) - gtk_builder_get_object (pp->builder, "device-types-treeview"); - - actualize_device_types_list (pp); - - g_signal_connect (gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)), - "changed", G_CALLBACK (device_type_selection_changed_cb), pp); - - renderer = gtk_cell_renderer_text_new (); - /* Translators: Device types column (network or local) */ - column = gtk_tree_view_column_new_with_attributes (_("Device types"), renderer, - "text", DEVICE_TYPE_NAME_COLUMN, NULL); - gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column); -} - -static GList * -glist_uniq (GList *list) -{ - GList *result = NULL; - GList *iter = NULL; - GList *tmp = NULL; - - for (iter = list; iter; iter = iter->next) - { - if (tmp == NULL || - g_strcmp0 ((gchar *) tmp->data, (gchar *) iter->data) != 0) - { - tmp = iter; - result = g_list_append (result, g_strdup (iter->data)); - } - } - - g_list_free_full (list, g_free); - - return result; -} - -static void -new_printer_add_button_cb (GtkButton *button, - gpointer user_data) -{ - PpNewPrinterDialog *pp = (PpNewPrinterDialog*) user_data; - GtkResponseType dialog_response = GTK_RESPONSE_OK; - GtkTreeModel *model; - cups_dest_t *dests; - GtkTreeIter iter; - GtkWidget *treeview; - gboolean success = FALSE; - PPDName *ppd_name = NULL; - gchar *device_name = NULL; - gint device_id = -1; - gint device_type = -1; - gint i; - int num_dests; - - treeview = (GtkWidget*) - gtk_builder_get_object (pp->builder, "device-types-treeview"); - - if (gtk_tree_selection_get_selected ( - gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)), &model, &iter)) - gtk_tree_model_get (model, &iter, - DEVICE_TYPE_TYPE_COLUMN, &device_type, - -1); - - switch (device_type) - { - case DEVICE_TYPE_LOCAL: - treeview = (GtkWidget*) - gtk_builder_get_object (pp->builder, "local-devices-treeview"); - break; - case DEVICE_TYPE_NETWORK: - treeview = (GtkWidget*) - gtk_builder_get_object (pp->builder, "network-devices-treeview"); - break; - default: - treeview = NULL; - break; - } - - if (treeview && - gtk_tree_selection_get_selected ( - gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)), &model, &iter)) - { - gtk_tree_model_get (model, &iter, - DEVICE_ID_COLUMN, &device_id, - DEVICE_NAME_COLUMN, &device_name, - -1); - } - - if (device_id >= 0) - { - if (pp->devices[device_id].device_ppd_uri) - { - http_t *http; - - http = httpConnectEncrypt (pp->devices[device_id].hostname, - pp->devices[device_id].host_port, - cupsEncryption ()); - - if (http) - { - const char *ppd_file_name; - - ppd_file_name = cupsGetPPD2 (http, pp->devices[device_id].display_name); - - if (ppd_file_name) - { - GDBusConnection *bus; - GError *error = NULL; - - bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error); - if (!bus) + for (j = 0; device_uris[i][j]; j++) { - g_warning ("Failed to get system bus: %s", error->message); - g_error_free (error); - } - else - { - GVariant *output; - - output = g_dbus_connection_call_sync (bus, - MECHANISM_BUS, - "/", - MECHANISM_BUS, - "PrinterAddWithPpdFile", - g_variant_new ("(sssss)", - pp->devices[device_id].display_name, - pp->devices[device_id].device_uri, - ppd_file_name, - pp->devices[device_id].device_info ? pp->devices[device_id].device_info : "", - pp->devices[device_id].device_location ? pp->devices[device_id].device_location : ""), - G_VARIANT_TYPE ("(s)"), - G_DBUS_CALL_FLAGS_NONE, - -1, - NULL, - &error); - g_object_unref (bus); - - if (output) + tmp = device_in_list (device_uris[i][j], priv->new_devices); + if (tmp) { - const gchar *ret_error; - - g_variant_get (output, "(&s)", &ret_error); - if (ret_error[0] != '\0') + priv->new_devices = g_list_remove (priv->new_devices, tmp); + if (j == 0) { - g_warning ("%s", ret_error); - dialog_response = GTK_RESPONSE_REJECT; + priv->devices = g_list_append (priv->devices, tmp); } else - success = TRUE; - - g_variant_unref (output); - } - else - { - g_warning ("%s", error->message); - g_error_free (error); - dialog_response = GTK_RESPONSE_REJECT; + { + t_device_free (tmp); + } } } - - g_unlink (ppd_file_name); - } - else - { - dialog_response = GTK_RESPONSE_REJECT; - g_warning ("Getting of PPD for %s from %s:%d failed.", - pp->devices[device_id].display_name, - pp->devices[device_id].hostname, - pp->devices[device_id].host_port); } } } - else if (pp->devices[device_id].device_id) + + for (i = 0; device_uris[i]; i++) { - /* Try whether CUPS has a driver for the new printer */ - ppd_name = get_ppd_name (pp->devices[device_id].device_id, - pp->devices[device_id].device_make_and_model, - pp->devices[device_id].device_uri); - - if (ppd_name == NULL || ppd_name->ppd_match_level < PPD_EXACT_MATCH) + for (j = 0; device_uris[i][j]; j++) { - /* Try PackageKit to install printer driver */ - GDBusConnection *bus; - GError *error = NULL; - - bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error); - if (!bus) - { - g_warning ("Failed to get session bus: %s", error->message); - g_error_free (error); - } - else - { - GVariantBuilder array_builder; - GVariant *output; - guint window_id = 0; - - g_variant_builder_init (&array_builder, G_VARIANT_TYPE ("as")); - g_variant_builder_add (&array_builder, "s", pp->devices[device_id].device_id); - -#ifdef GDK_WINDOWING_X11 - window_id = GDK_WINDOW_XID (gtk_widget_get_window (GTK_WIDGET (pp->dialog))); -#endif - - output = g_dbus_connection_call_sync (bus, - PACKAGE_KIT_BUS, - PACKAGE_KIT_PATH, - PACKAGE_KIT_MODIFY_IFACE, - "InstallPrinterDrivers", - g_variant_new ("(uass)", - window_id, - &array_builder, - "hide-finished"), - G_VARIANT_TYPE ("()"), - G_DBUS_CALL_FLAGS_NONE, - 3600000, - NULL, - &error); - g_object_unref (bus); - - if (output) - g_variant_unref (output); - else - { - g_warning ("%s", error->message); - g_error_free (error); - } - - if (ppd_name) - { - g_free (ppd_name->ppd_name); - g_free (ppd_name); - } - - /* Search CUPS for driver */ - ppd_name = get_ppd_name (pp->devices[device_id].device_id, - pp->devices[device_id].device_make_and_model, - pp->devices[device_id].device_uri); - } + g_free (device_uris[i][j]); } - /* Add the new printer */ - if (ppd_name && ppd_name->ppd_name) - { - GDBusConnection *bus; - GError *error = NULL; - GVariant *output; - - bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error); - if (!bus) - { - g_warning ("Failed to get system bus: %s", error->message); - g_error_free (error); - } - else - { - output = g_dbus_connection_call_sync (bus, - MECHANISM_BUS, - "/", - MECHANISM_BUS, - "PrinterAdd", - g_variant_new ("(sssss)", - pp->devices[device_id].display_name, - pp->devices[device_id].device_uri, - ppd_name->ppd_name, - pp->devices[device_id].device_info ? pp->devices[device_id].device_info : "", - pp->devices[device_id].device_location ? pp->devices[device_id].device_location : ""), - G_VARIANT_TYPE ("(s)"), - G_DBUS_CALL_FLAGS_NONE, - -1, - NULL, - &error); - g_object_unref (bus); - - if (output) - { - const gchar *ret_error; - - g_variant_get (output, "(&s)", &ret_error); - if (ret_error[0] != '\0') - { - g_warning ("%s", ret_error); - dialog_response = GTK_RESPONSE_REJECT; - } - - g_variant_unref (output); - } - else - { - g_warning ("%s", error->message); - g_error_free (error); - dialog_response = GTK_RESPONSE_REJECT; - } - } - - g_free (ppd_name->ppd_name); - g_free (ppd_name); - } - - num_dests = cupsGetDests (&dests); - for (i = 0; i < num_dests; i++) - if (g_strcmp0 (dests[i].name, pp->devices[device_id].display_name) == 0) - success = TRUE; - cupsFreeDests (num_dests, dests); + g_free (device_uris[i]); } - /* Set some options of the new printer */ - if (success) + g_free (device_uris); + } + else + { + priv->devices = g_list_concat (priv->devices, priv->new_devices); + priv->new_devices = NULL; + } + + actualize_devices_list (dialog); +} + +static void +group_physical_devices_dbus_cb (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + GVariant *output; + GError *error = NULL; + gchar ***result = NULL; + gint i, j; + + output = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object), + res, + &error); + g_object_unref (source_object); + + if (output) + { + GVariant *array; + + g_variant_get (output, "(@aas)", &array); + + if (array) { - const char *ppd_file_name = NULL; - GDBusConnection *bus; - GError *error = NULL; + GVariantIter *iter; + GVariantIter *subiter; + GVariant *item; + GVariant *subitem; + gchar *device_uri; - ppd_file_name = cupsGetPPD (pp->devices[device_id].display_name); - - printer_set_accepting_jobs (pp->devices[device_id].display_name, TRUE, NULL); - printer_set_enabled (pp->devices[device_id].display_name, TRUE); - - if (g_strcmp0 (pp->devices[device_id].device_class, "direct") == 0) + result = g_new0 (gchar **, g_variant_n_children (array) + 1); + g_variant_get (array, "aas", &iter); + i = 0; + while ((item = g_variant_iter_next_value (iter))) { - gchar *commands = get_dest_attr (pp->devices[device_id].display_name, "printer-commands"); - gchar *commands_lowercase = g_ascii_strdown (commands, -1); - ipp_t *response = NULL; - - if (g_strrstr (commands_lowercase, "autoconfigure")) + result[i] = g_new0 (gchar *, g_variant_n_children (item) + 1); + g_variant_get (item, "as", &subiter); + j = 0; + while ((subitem = g_variant_iter_next_value (subiter))) { - response = execute_maintenance_command (pp->devices[device_id].display_name, - "AutoConfigure", - /* Translators: Name of job which makes printer to autoconfigure itself */ - _("Automatic configuration")); - if (response) + g_variant_get (subitem, "s", &device_uri); + + result[i][j] = device_uri; + + g_variant_unref (subitem); + j++; + } + + g_variant_unref (item); + i++; + } + + g_variant_unref (array); + } + + g_variant_unref (output); + } + else if (error && + error->domain == G_DBUS_ERROR && + (error->code == G_DBUS_ERROR_SERVICE_UNKNOWN || + error->code == G_DBUS_ERROR_UNKNOWN_METHOD)) + { + g_warning ("Install system-config-printer which provides \ +DBus method \"GroupPhysicalDevices\" to group duplicates in device list."); + } + else + { + if (error->domain != G_IO_ERROR || + error->code != G_IO_ERROR_CANCELLED) + g_warning ("%s", error->message); + } + + if (!error || + error->domain != G_IO_ERROR || + error->code != G_IO_ERROR_CANCELLED) + group_physical_devices_cb (result, user_data); + + if (error) + g_error_free (error); +} + +static void +get_cups_devices_cb (GList *devices, + gboolean finished, + gboolean cancelled, + gpointer user_data) +{ + PpNewPrinterDialog *dialog; + PpNewPrinterDialogPrivate *priv; + GDBusConnection *bus; + GVariantBuilder device_list; + GVariantBuilder device_hash; + PpPrintDevice **all_devices; + PpPrintDevice *pp_device; + TDevice *device; + GError *error = NULL; + GList *iter; + gint length, i; + + + if (!cancelled) + { + dialog = (PpNewPrinterDialog*) user_data; + priv = dialog->priv; + + if (finished) + { + priv->cups_searching = FALSE; + } + + if (devices) + { + add_devices_to_list (dialog, + devices, + TRUE); + + length = g_list_length (priv->devices) + g_list_length (devices); + if (length > 0) + { + all_devices = g_new0 (PpPrintDevice *, length); + + i = 0; + for (iter = priv->devices; iter; iter = iter->next) + { + device = (TDevice *) iter->data; + if (device) { - if (ippGetState (response) == IPP_ERROR) - g_warning ("An error has occured during automatic configuration of new printer."); - ippDelete (response); + all_devices[i] = g_new0 (PpPrintDevice, 1); + all_devices[i]->device_id = g_strdup (device->device_id); + all_devices[i]->device_make_and_model = g_strdup (device->device_make_and_model); + all_devices[i]->device_class = device->network_device ? g_strdup ("network") : strdup ("direct"); + all_devices[i]->device_uri = g_strdup (device->device_uri); } + i++; } - g_free (commands); - g_free (commands_lowercase); - } - printer_set_default_media_size (pp->devices[device_id].display_name); - - if (pp->devices[device_id].device_uri && - dbus_method_available (FIREWALLD_BUS, - FIREWALLD_PATH, - FIREWALLD_IFACE, - "getServices")) - { - if (g_str_has_prefix (pp->devices[device_id].device_uri, "dnssd:") || - g_str_has_prefix (pp->devices[device_id].device_uri, "mdns:")) + for (iter = devices; iter; iter = iter->next) { - show_notification (_("Opening firewall for mDNS connections"), - NULL, - "dialog-information-symbolic"); - service_disable ("mdns"); - service_enable ("mdns", 0); + pp_device = (PpPrintDevice *) iter->data; + if (pp_device) + { + all_devices[i] = g_new0 (PpPrintDevice, 1); + all_devices[i]->device_id = g_strdup (pp_device->device_id); + all_devices[i]->device_make_and_model = g_strdup (pp_device->device_make_and_model); + all_devices[i]->device_class = g_strdup (pp_device->device_class); + all_devices[i]->device_uri = g_strdup (pp_device->device_uri); + } + i++; } - if (g_strrstr (pp->devices[device_id].device_uri, "smb:") != NULL) - { - show_notification (_("Opening firewall for Samba connections"), - NULL, - "dialog-information-symbolic"); - service_disable ("samba-client"); - service_enable ("samba-client", 0); - } - - if (g_strrstr (pp->devices[device_id].device_uri, "ipp:") != NULL) - { - show_notification (_("Opening firewall for IPP connections"), - NULL, - "dialog-information-symbolic"); - service_disable ("ipp"); - service_enable ("ipp", 0); - service_disable ("ipp-client"); - service_enable ("ipp-client", 0); - } - } - - if (ppd_file_name) - { - GVariant *output; - GVariant *array; - GList *executables = NULL; - GList *packages = NULL; - - error = NULL; - bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error); if (bus) { - output = g_dbus_connection_call_sync (bus, - SCP_BUS, - SCP_PATH, - SCP_IFACE, - "MissingExecutables", - g_variant_new ("(s)", ppd_file_name), - NULL, - G_DBUS_CALL_FLAGS_NONE, - 60000, - NULL, - &error); - g_object_unref (bus); + g_variant_builder_init (&device_list, G_VARIANT_TYPE ("a{sv}")); - if (output) + for (i = 0; i < length; i++) { - if (g_variant_n_children (output) == 1) + if (all_devices[i]->device_uri) { - array = g_variant_get_child_value (output, 0); - if (array) - { - for (i = 0; i < g_variant_n_children (array); i++) - { - executables = g_list_append ( - executables, - g_strdup (g_variant_get_string ( - g_variant_get_child_value (array, i), - NULL))); - } - } - } - g_variant_unref (output); - } - } + g_variant_builder_init (&device_hash, G_VARIANT_TYPE ("a{ss}")); - if (bus == NULL || - (error && - error->domain == G_DBUS_ERROR && - (error->code == G_DBUS_ERROR_SERVICE_UNKNOWN || - error->code == G_DBUS_ERROR_UNKNOWN_METHOD))) + if (all_devices[i]->device_id) + g_variant_builder_add (&device_hash, + "{ss}", + "device-id", + all_devices[i]->device_id); + + if (all_devices[i]->device_make_and_model) + g_variant_builder_add (&device_hash, + "{ss}", + "device-make-and-model", + all_devices[i]->device_make_and_model); + + if (all_devices[i]->device_class) + g_variant_builder_add (&device_hash, + "{ss}", + "device-class", + all_devices[i]->device_class); + + g_variant_builder_add (&device_list, + "{sv}", + all_devices[i]->device_uri, + g_variant_builder_end (&device_hash)); + } + } + + g_dbus_connection_call (bus, + SCP_BUS, + SCP_PATH, + SCP_IFACE, + "GroupPhysicalDevices", + g_variant_new ("(v)", g_variant_builder_end (&device_list)), + G_VARIANT_TYPE ("(aas)"), + G_DBUS_CALL_FLAGS_NONE, + -1, + priv->cancellable, + group_physical_devices_dbus_cb, + dialog); + } + else { - g_warning ("Install system-config-printer which provides \ -DBus method \"MissingExecutables\" to find missing executables and filters."); + g_warning ("Failed to get system bus: %s", error->message); g_error_free (error); + group_physical_devices_cb (NULL, user_data); } - executables = g_list_sort (executables, (GCompareFunc) g_strcmp0); - executables = glist_uniq (executables); - - if (executables) + for (i = 0; i < length; i++) { - bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error); - if (bus) + if (all_devices[i]) { - GList *exec_iter; - - for (exec_iter = executables; exec_iter; exec_iter = exec_iter->next) - { - output = g_dbus_connection_call_sync (bus, - PACKAGE_KIT_BUS, - PACKAGE_KIT_PATH, - PACKAGE_KIT_QUERY_IFACE, - "SearchFile", - g_variant_new ("(ss)", - (gchar *) exec_iter->data, - ""), - G_VARIANT_TYPE ("(bs)"), - G_DBUS_CALL_FLAGS_NONE, - 60000, - NULL, - &error); - - if (output) - { - gboolean installed; - gchar *package; - - g_variant_get (output, - "(bs)", - &installed, - &package); - if (!installed) - packages = g_list_append (packages, g_strdup (package)); - g_variant_unref (output); - } - else - { - g_warning ("%s", error->message); - g_error_free (error); - } - } - - g_object_unref (bus); + g_free (all_devices[i]->device_id); + g_free (all_devices[i]->device_make_and_model); + g_free (all_devices[i]->device_class); + g_free (all_devices[i]->device_uri); + g_free (all_devices[i]); } - else - { - g_warning ("%s", error->message); - g_error_free (error); - } - - g_list_free_full (executables, g_free); } - packages = g_list_sort (packages, (GCompareFunc) g_strcmp0); - packages = glist_uniq (packages); - - if (packages) - { - bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error); - if (bus) - { - GVariantBuilder array_builder; - GList *pkg_iter; - guint window_id = 0; - - g_variant_builder_init (&array_builder, G_VARIANT_TYPE ("as")); - - for (pkg_iter = packages; pkg_iter; pkg_iter = pkg_iter->next) - g_variant_builder_add (&array_builder, - "s", - (gchar *) pkg_iter->data); - -#ifdef GDK_WINDOWING_X11 - window_id = GDK_WINDOW_XID (gtk_widget_get_window (GTK_WIDGET (pp->dialog))), -#endif - - output = g_dbus_connection_call_sync (bus, - PACKAGE_KIT_BUS, - PACKAGE_KIT_PATH, - PACKAGE_KIT_MODIFY_IFACE, - "InstallPackageNames", - g_variant_new ("(uass)", - window_id, - &array_builder, - "hide-finished"), - NULL, - G_DBUS_CALL_FLAGS_NONE, - 60000, - NULL, - &error); - g_object_unref (bus); - - if (output) - { - g_variant_unref (output); - } - else - { - g_warning ("%s", error->message); - g_error_free (error); - } - } - else - { - g_warning ("%s", error->message); - g_error_free (error); - } - - g_list_free_full (packages, g_free); - } + g_free (all_devices); } - - if (ppd_file_name) - g_unlink (ppd_file_name); + else + { + actualize_devices_list (dialog); + } + } + else + { + actualize_devices_list (dialog); } } - pp_new_printer_dialog_hide (pp); - pp->user_callback (GTK_DIALOG (pp->dialog), dialog_response, pp->user_data); + for (iter = devices; iter; iter = iter->next) + pp_print_device_free ((PpPrintDevice *) iter->data); + g_list_free (devices); } static void -new_printer_cancel_button_cb (GtkButton *button, - gpointer user_data) +get_snmp_devices_cb (GObject *source_object, + GAsyncResult *res, + gpointer user_data) { - PpNewPrinterDialog *pp = (PpNewPrinterDialog*) user_data; + PpNewPrinterDialog *dialog; + PpNewPrinterDialogPrivate *priv; + PpHost *host = (PpHost *) source_object; + GError *error = NULL; + PpDevicesList *result; + GList *iter; - pp_new_printer_dialog_hide (pp); - pp->user_callback (GTK_DIALOG (pp->dialog), GTK_RESPONSE_CANCEL, pp->user_data); -} + result = pp_host_get_snmp_devices_finish (host, res, &error); + g_object_unref (source_object); -PpNewPrinterDialog * -pp_new_printer_dialog_new (GtkWindow *parent, - UserResponseCallback user_callback, - gpointer user_data) -{ - PpNewPrinterDialog *pp; - GtkWidget *widget; - GError *error = NULL; - gchar *objects[] = { "dialog", "main-vbox", NULL }; - guint builder_result; - - pp = g_new0 (PpNewPrinterDialog, 1); - - pp->builder = gtk_builder_new (); - pp->parent = GTK_WIDGET (parent); - - builder_result = gtk_builder_add_objects_from_file (pp->builder, - DATADIR"/new-printer-dialog.ui", - objects, &error); - - if (builder_result == 0) + if (result) { - g_warning ("Could not load ui: %s", error->message); + dialog = PP_NEW_PRINTER_DIALOG (user_data); + priv = dialog->priv; + + priv->snmp_searching = FALSE; + update_spinner_state (dialog); + + if (result->devices) + { + add_devices_to_list (dialog, + result->devices, + FALSE); + } + + actualize_devices_list (dialog); + + for (iter = result->devices; iter; iter = iter->next) + pp_print_device_free ((PpPrintDevice *) iter->data); + g_list_free (result->devices); + g_free (result); + } + else + { + if (error->domain != G_IO_ERROR || + error->code != G_IO_ERROR_CANCELLED) + { + dialog = PP_NEW_PRINTER_DIALOG (user_data); + priv = dialog->priv; + + g_warning ("%s", error->message); + + priv->snmp_searching = FALSE; + update_spinner_state (dialog); + } + g_error_free (error); - return NULL; } - - pp->device_connection_types = NULL; - pp->num_device_connection_types = 0; - - pp->devices = NULL; - pp->num_devices = 0; - - pp->dialog = (GtkWidget *) gtk_builder_get_object (pp->builder, "dialog"); - - pp->user_callback = user_callback; - pp->user_data = user_data; - - pp->cancellable = NULL; - pp->warning = NULL; - pp->show_warning = FALSE; - - /* connect signals */ - g_signal_connect (pp->dialog, "delete-event", G_CALLBACK (gtk_widget_hide_on_delete), NULL); - - widget = (GtkWidget*) - gtk_builder_get_object (pp->builder, "new-printer-add-button"); - g_signal_connect (widget, "clicked", G_CALLBACK (new_printer_add_button_cb), pp); - gtk_widget_set_sensitive (widget, FALSE); - - widget = (GtkWidget*) - gtk_builder_get_object (pp->builder, "new-printer-cancel-button"); - g_signal_connect (widget, "clicked", G_CALLBACK (new_printer_cancel_button_cb), pp); - - widget = (GtkWidget*) - gtk_builder_get_object (pp->builder, "search-by-address-checkbutton"); - g_signal_connect (widget, "toggled", G_CALLBACK (search_address_cb), pp); - - gtk_window_set_transient_for (GTK_WINDOW (pp->dialog), GTK_WINDOW (parent)); - gtk_window_set_modal (GTK_WINDOW (pp->dialog), TRUE); - gtk_window_present (GTK_WINDOW (pp->dialog)); - gtk_widget_show_all (GTK_WIDGET (pp->dialog)); - - pp->searching = TRUE; - populate_device_types_list (pp); - populate_devices_list (pp); - - return pp; -} - -void -pp_new_printer_dialog_free (PpNewPrinterDialog *pp) -{ - gint i; - - for (i = 0; i < pp->num_device_connection_types; i++) - g_free (pp->device_connection_types[i]); - g_free (pp->device_connection_types); - pp->device_connection_types = NULL; - - free_devices (pp); - - gtk_widget_destroy (GTK_WIDGET (pp->dialog)); - pp->dialog = NULL; - - g_object_unref (pp->builder); - pp->builder = NULL; - - if (pp->cancellable) - { - g_cancellable_cancel (pp->cancellable); - g_object_unref (pp->cancellable); - } - - g_free (pp->warning); - - g_free (pp); } static void -pp_new_printer_dialog_hide (PpNewPrinterDialog *pp) +get_remote_cups_devices_cb (GObject *source_object, + GAsyncResult *res, + gpointer user_data) { - gtk_widget_hide (GTK_WIDGET (pp->dialog)); + PpNewPrinterDialog *dialog; + PpNewPrinterDialogPrivate *priv; + PpHost *host = (PpHost *) source_object; + GError *error = NULL; + PpDevicesList *result; + GList *iter; + + result = pp_host_get_remote_cups_devices_finish (host, res, &error); + g_object_unref (source_object); + + if (result) + { + dialog = PP_NEW_PRINTER_DIALOG (user_data); + priv = dialog->priv; + + priv->remote_cups_searching = FALSE; + update_spinner_state (dialog); + + if (result->devices) + { + add_devices_to_list (dialog, + result->devices, + FALSE); + } + + actualize_devices_list (dialog); + + for (iter = result->devices; iter; iter = iter->next) + pp_print_device_free ((PpPrintDevice *) iter->data); + g_list_free (result->devices); + g_free (result); + } + else + { + if (error->domain != G_IO_ERROR || + error->code != G_IO_ERROR_CANCELLED) + { + dialog = PP_NEW_PRINTER_DIALOG (user_data); + priv = dialog->priv; + + g_warning ("%s", error->message); + + priv->remote_cups_searching = FALSE; + update_spinner_state (dialog); + } + + g_error_free (error); + } +} + +static void +get_cups_devices (PpNewPrinterDialog *dialog) +{ + PpNewPrinterDialogPrivate *priv = dialog->priv; + + priv->cups_searching = TRUE; + update_spinner_state (dialog); + + get_cups_devices_async (priv->cancellable, + get_cups_devices_cb, + dialog); +} + +static gboolean +parse_uri (gchar *uri, + gchar **host, + gint *port) +{ + gchar *tmp = NULL; + gchar *resulting_host = NULL; + gchar *port_string = NULL; + gchar *position; + int resulting_port = 631; + + if (g_strrstr (uri, "://")) + tmp = g_strrstr (uri, "://") + 3; + else + tmp = uri; + + if (g_strrstr (tmp, "@")) + tmp = g_strrstr (tmp, "@") + 1; + + if ((position = g_strrstr (tmp, "/"))) + { + *position = '\0'; + resulting_host = g_strdup (tmp); + *position = '/'; + } + else + resulting_host = g_strdup (tmp); + + if ((position = g_strrstr (resulting_host, ":"))) + { + *position = '\0'; + port_string = position + 1; + } + + if (port_string) + resulting_port = atoi (port_string); + + *host = resulting_host; + *port = resulting_port; + + return TRUE; +} + + +static void +search_address_cb (GtkEntry *entry, + gpointer user_data) +{ + PpNewPrinterDialog *dialog = PP_NEW_PRINTER_DIALOG (user_data); + PpNewPrinterDialogPrivate *priv = dialog->priv; + gboolean found = FALSE; + gboolean subfound; + TDevice *device; + GList *iter, *tmp; + gchar *text; + gchar *lowercase_name; + gchar *lowercase_location; + gchar *lowercase_text; + gchar **words; + gint words_length = 0; + gint i; + + text = g_strdup (gtk_entry_get_text (entry)); + + lowercase_text = g_ascii_strdown (text, -1); + words = g_strsplit_set (lowercase_text, " ", -1); + g_free (lowercase_text); + + if (words) + { + words_length = g_strv_length (words); + + for (iter = priv->devices; iter; iter = iter->next) + { + device = iter->data; + + lowercase_name = g_ascii_strdown (device->device_name, -1); + if (device->device_location) + lowercase_location = g_ascii_strdown (device->device_location, -1); + else + lowercase_location = NULL; + + subfound = TRUE; + for (i = 0; words[i]; i++) + { + if (!g_strrstr (lowercase_name, words[i]) && + (!lowercase_location || !g_strrstr (lowercase_location, words[i]))) + subfound = FALSE; + } + + if (subfound) + { + device->show = TRUE; + found = TRUE; + } + else + { + device->show = FALSE; + } + + g_free (lowercase_location); + g_free (lowercase_name); + } + + g_strfreev (words); + } + + if (!found && words_length == 1) + { + iter = priv->devices; + while (iter) + { + device = iter->data; + device->show = TRUE; + + if (device->acquisition_method == ACQUISITION_METHOD_REMOTE_CUPS_SERVER || + device->acquisition_method == ACQUISITION_METHOD_SNMP) + { + tmp = iter; + iter = iter->next; + priv->devices = g_list_remove_link (priv->devices, tmp); + g_list_free_full (tmp, t_device_free); + } + else + iter = iter->next; + } + + iter = priv->new_devices; + while (iter) + { + device = iter->data; + + if (device->acquisition_method == ACQUISITION_METHOD_REMOTE_CUPS_SERVER || + device->acquisition_method == ACQUISITION_METHOD_SNMP) + { + tmp = iter; + iter = iter->next; + priv->new_devices = g_list_remove_link (priv->new_devices, tmp); + g_list_free_full (tmp, t_device_free); + } + else + iter = iter->next; + } + + if (text && text[0] != '\0') + { + gchar *host = NULL; + gint port = 631; + + parse_uri (text, &host, &port); + + if (host) + { + PpHost *snmp_host; + PpHost *remote_cups_host; + + snmp_host = pp_host_new (host, port); + remote_cups_host = g_object_ref (snmp_host); + + priv->remote_cups_searching = TRUE; + priv->snmp_searching = TRUE; + update_spinner_state (dialog); + + pp_host_get_remote_cups_devices_async (snmp_host, + priv->cancellable, + get_remote_cups_devices_cb, + dialog); + + pp_host_get_snmp_devices_async (remote_cups_host, + priv->cancellable, + get_snmp_devices_cb, + dialog); + + g_free (host); + } + } + } + + actualize_devices_list (dialog); + + g_free (text); +} + +static void +search_address_cb2 (GtkEntry *entry, + GtkEntryIconPosition icon_pos, + GdkEvent *event, + gpointer user_data) +{ + search_address_cb (entry, user_data); +} + +static void +actualize_devices_list (PpNewPrinterDialog *dialog) +{ + PpNewPrinterDialogPrivate *priv = dialog->priv; + GtkTreeViewColumn *column; + GtkTreeSelection *selection; + GtkListStore *store; + GtkTreeView *treeview; + GtkTreeIter iter; + gboolean no_device = TRUE; + TDevice *device; + gfloat yalign; + GList *item; + gchar *display_string; + + treeview = (GtkTreeView *) + gtk_builder_get_object (priv->builder, "devices-treeview"); + + store = gtk_list_store_new (3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING); + + for (item = priv->devices; item; item = item->next) + { + device = (TDevice *) item->data; + + if (device->display_name && + (device->device_id || + device->device_ppd || + (device->host_name && + device->acquisition_method == ACQUISITION_METHOD_REMOTE_CUPS_SERVER)) && + device->show) + { + if (device->device_location) + display_string = g_markup_printf_escaped ("%s\n%s", + device->display_name, + device->device_location); + else + display_string = g_markup_printf_escaped ("%s\n ", + device->display_name); + + gtk_list_store_append (store, &iter); + gtk_list_store_set (store, &iter, + DEVICE_ICON_COLUMN, device->network_device ? "printer-network" : "printer", + DEVICE_NAME_COLUMN, device->device_name, + DEVICE_DISPLAY_NAME_COLUMN, display_string, + -1); + no_device = FALSE; + + g_free (display_string); + } + } + + column = gtk_tree_view_get_column (treeview, 0); + if (priv->text_renderer) + gtk_cell_renderer_get_alignment (priv->text_renderer, NULL, &yalign); + + if (no_device && + !priv->cups_searching && + !priv->remote_cups_searching && + !priv->snmp_searching) + { + if (priv->text_renderer) + gtk_cell_renderer_set_alignment (priv->text_renderer, 0.5, yalign); + + if (column) + gtk_tree_view_column_set_max_width (column, 0); + + gtk_widget_set_sensitive (GTK_WIDGET (treeview), FALSE); + + display_string = g_markup_printf_escaped ("%s\n", + /* Translators: No printers were found */ + _("No printers detected.")); + + gtk_list_store_append (store, &iter); + gtk_list_store_set (store, &iter, + DEVICE_DISPLAY_NAME_COLUMN, display_string, + -1); + + g_free (display_string); + } + else + { + if (priv->text_renderer) + gtk_cell_renderer_set_alignment (priv->text_renderer, 0.0, yalign); + + if (column) + { + gtk_tree_view_column_set_max_width (column, -1); + gtk_tree_view_column_set_min_width (column, 80); + } + gtk_widget_set_sensitive (GTK_WIDGET (treeview), TRUE); + } + + gtk_tree_view_set_model (treeview, GTK_TREE_MODEL (store)); + + if (!no_device && + gtk_tree_model_get_iter_first ((GtkTreeModel *) store, &iter) && + (selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview))) != NULL) + gtk_tree_selection_select_iter (selection, &iter); + + g_object_unref (store); + update_spinner_state (dialog); +} + +static void +cups_get_dests_cb (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + PpNewPrinterDialog *dialog; + PpNewPrinterDialogPrivate *priv; + PpCupsDests *dests; + PpCups *cups = (PpCups *) source_object; + GError *error = NULL; + + dests = pp_cups_get_dests_finish (cups, res, &error); + g_object_unref (source_object); + + if (dests) + { + dialog = PP_NEW_PRINTER_DIALOG (user_data); + priv = dialog->priv; + + priv->dests = dests->dests; + priv->num_of_dests = dests->num_of_dests; + + get_cups_devices (dialog); + } + else + { + if (error->domain != G_IO_ERROR || + error->code != G_IO_ERROR_CANCELLED) + { + dialog = PP_NEW_PRINTER_DIALOG (user_data); + + g_warning ("%s", error->message); + + get_cups_devices (dialog); + } + + g_error_free (error); + } +} + +static void +populate_devices_list (PpNewPrinterDialog *dialog) +{ + PpNewPrinterDialogPrivate *priv = dialog->priv; + GtkTreeViewColumn *column; + GtkWidget *treeview; + PpCups *cups; + + treeview = (GtkWidget*) + gtk_builder_get_object (priv->builder, "devices-treeview"); + + g_signal_connect (gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)), + "changed", G_CALLBACK (device_selection_changed_cb), dialog); + + priv->icon_renderer = gtk_cell_renderer_pixbuf_new (); + g_object_set (priv->icon_renderer, "stock-size", GTK_ICON_SIZE_DIALOG, NULL); + gtk_cell_renderer_set_alignment (priv->icon_renderer, 1.0, 0.5); + gtk_cell_renderer_set_padding (priv->icon_renderer, 4, 4); + column = gtk_tree_view_column_new_with_attributes ("Icon", priv->icon_renderer, + "icon-name", DEVICE_ICON_COLUMN, NULL); + gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column); + + + priv->text_renderer = gtk_cell_renderer_text_new (); + column = gtk_tree_view_column_new_with_attributes ("Devices", priv->text_renderer, + "markup", DEVICE_DISPLAY_NAME_COLUMN, NULL); + gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column); + + cups = pp_cups_new (); + pp_cups_get_dests_async (cups, priv->cancellable, cups_get_dests_cb, dialog); +} + +static void +printer_add_async_cb (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + PpNewPrinterDialog *dialog; + GtkResponseType response_id = GTK_RESPONSE_OK; + PpNewPrinter *new_printer = (PpNewPrinter *) source_object; + gboolean success; + GError *error = NULL; + + success = pp_new_printer_add_finish (new_printer, res, &error); + g_object_unref (source_object); + + if (success) + { + dialog = PP_NEW_PRINTER_DIALOG (user_data); + + emit_response (dialog, response_id); + } + else + { + if (error->domain != G_IO_ERROR || + error->code != G_IO_ERROR_CANCELLED) + { + dialog = PP_NEW_PRINTER_DIALOG (user_data); + + g_warning ("%s", error->message); + + response_id = GTK_RESPONSE_REJECT; + + emit_response (dialog, response_id); + } + + g_error_free (error); + } +} + +static void +new_printer_dialog_response_cb (GtkDialog *_dialog, + gint response_id, + gpointer user_data) +{ + PpNewPrinterDialog *dialog = (PpNewPrinterDialog*) user_data; + PpNewPrinterDialogPrivate *priv = dialog->priv; + GtkTreeModel *model; + GtkTreeIter iter; + GtkWidget *treeview; + TDevice *device = NULL; + TDevice *tmp; + GList *list_iter; + gchar *device_name = NULL; + + gtk_widget_hide (GTK_WIDGET (_dialog)); + + if (response_id == GTK_RESPONSE_OK) + { + g_cancellable_cancel (priv->cancellable); + g_clear_object (&priv->cancellable); + + treeview = (GtkWidget*) + gtk_builder_get_object (priv->builder, "devices-treeview"); + + if (treeview && + gtk_tree_selection_get_selected ( + gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)), &model, &iter)) + { + gtk_tree_model_get (model, &iter, + DEVICE_NAME_COLUMN, &device_name, + -1); + } + + for (list_iter = priv->devices; list_iter; list_iter = list_iter->next) + { + tmp = (TDevice *) list_iter->data; + if (tmp && g_strcmp0 (tmp->device_name, device_name) == 0) + { + device = tmp; + break; + } + } + + if (device) + { + PpNewPrinter *new_printer; + guint window_id = 0; + + emit_pre_response (dialog, + device->device_name, + device->device_location, + device->device_make_and_model, + device->network_device); + +#ifdef GDK_WINDOWING_X11 + window_id = GDK_WINDOW_XID (gtk_widget_get_window (GTK_WIDGET (_dialog))); +#endif + + new_printer = pp_new_printer_new (); + g_object_set (new_printer, + "name", device->device_name, + "original-name""", device->device_original_name, + "device-uri", device->device_uri, + "device-id", device->device_id, + "ppd-name", device->device_ppd, + "ppd-file-name", device->device_ppd, + "info", device->device_info, + "location", device->device_location, + "make-and-model", device->device_make_and_model, + "host-name", device->host_name, + "host-port", device->host_port, + "is-network-device", device->network_device, + "window-id", window_id, + NULL); + + priv->cancellable = g_cancellable_new (); + + pp_new_printer_add_async (new_printer, + priv->cancellable, + printer_add_async_cb, + dialog); + } + } + else + { + emit_response (dialog, GTK_RESPONSE_CANCEL); + } } diff --git a/panels/printers/pp-new-printer-dialog.h b/panels/printers/pp-new-printer-dialog.h index 618c0d716..ba4eb881a 100644 --- a/panels/printers/pp-new-printer-dialog.h +++ b/panels/printers/pp-new-printer-dialog.h @@ -25,15 +25,40 @@ G_BEGIN_DECLS -typedef struct _PpNewPrinterDialog PpNewPrinterDialog; +#define PP_TYPE_NEW_PRINTER_DIALOG (pp_new_printer_dialog_get_type ()) +#define PP_NEW_PRINTER_DIALOG(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PP_TYPE_NEW_PRINTER_DIALOG, PpNewPrinterDialog)) +#define PP_NEW_PRINTER_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PP_TYPE_NEW_PRINTER_DIALOG, PpNewPrinterDialogClass)) +#define PP_IS_NEW_PRINTER_DIALOG(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PP_TYPE_NEW_PRINTER_DIALOG)) +#define PP_IS_NEW_PRINTER_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PP_TYPE_NEW_PRINTER_DIALOG)) +#define PP_NEW_PRINTER_DIALOG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PP_TYPE_NEW_PRINTER_DIALOG, PpNewPrinterDialogClass)) -typedef void (*UserResponseCallback) (GtkDialog *dialog, gint response_id, gpointer user_data); +typedef struct _PpNewPrinterDialog PpNewPrinterDialog; +typedef struct _PpNewPrinterDialogClass PpNewPrinterDialogClass; +typedef struct _PpNewPrinterDialogPrivate PpNewPrinterDialogPrivate; -PpNewPrinterDialog *pp_new_printer_dialog_new (GtkWindow *parent, - UserResponseCallback user_callback, - gpointer user_data); -void pp_new_printer_dialog_free (PpNewPrinterDialog *dialog); +struct _PpNewPrinterDialog +{ + GObject parent_instance; + PpNewPrinterDialogPrivate *priv; +}; + +struct _PpNewPrinterDialogClass +{ + GObjectClass parent_class; + + void (*pre_response) (PpNewPrinterDialog *dialog, + const gchar *device_name, + const gchar *device_location, + const gchar *device_make_and_model, + gboolean is_network_device); + + void (*response) (PpNewPrinterDialog *dialog, + gint response_id); +}; + +GType pp_new_printer_dialog_get_type (void) G_GNUC_CONST; +PpNewPrinterDialog *pp_new_printer_dialog_new (GtkWindow *parent); G_END_DECLS -#endif +#endif /* __PP_NEW_PRINTER_DIALOG_H__ */