This commit implements design changes from https://live.gnome.org/Design/SystemSettings/Printers. The new printer dialog gets informations about connected devices from CUPS server asynchronously and separately for each backend now. Entering an address into the entry and pressing the icon inside the entry or enter starts to detect printers on the entered host. Entering a text which is a substring of a name of a device or its location filters the list to contain just devicess with the string in it (e.g. Canon will keep devices with "Canon" in their name). The PpNewPrinterDialog is regular object now. It emits signal "pre-response" when dialog is closed and a printer is being added and signal "response" when the new printer was added, addition of the new printer failed or the dialog was cancelled. This commit removes FirewallD support from new printer dialog. (#683229)
1522 lines
46 KiB
C
1522 lines
46 KiB
C
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
|
*
|
|
* Copyright 2009-2010 Red Hat, Inc,
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <unistd.h>
|
|
#include <stdlib.h>
|
|
|
|
#include <glib.h>
|
|
#include <glib/gi18n.h>
|
|
#include <glib/gstdio.h>
|
|
#include <gtk/gtk.h>
|
|
|
|
#include <cups/cups.h>
|
|
|
|
#include "pp-new-printer-dialog.h"
|
|
#include "pp-utils.h"
|
|
#include "pp-host.h"
|
|
#include "pp-cups.h"
|
|
#include "pp-new-printer.h"
|
|
|
|
#ifdef GDK_WINDOWING_X11
|
|
#include <gdk/gdkx.h>
|
|
#endif
|
|
|
|
#if (CUPS_VERSION_MAJOR > 1) || (CUPS_VERSION_MINOR > 5)
|
|
#define HAVE_CUPS_1_6 1
|
|
#endif
|
|
|
|
#ifndef HAVE_CUPS_1_6
|
|
#define ippGetState(ipp) ipp->state
|
|
#endif
|
|
|
|
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
|
|
{
|
|
DEVICE_ICON_COLUMN = 0,
|
|
DEVICE_NAME_COLUMN,
|
|
DEVICE_DISPLAY_NAME_COLUMN,
|
|
DEVICE_N_COLUMNS
|
|
};
|
|
|
|
typedef struct
|
|
{
|
|
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;
|
|
|
|
struct _PpNewPrinterDialogPrivate
|
|
{
|
|
GtkBuilder *builder;
|
|
|
|
GList *devices;
|
|
GList *new_devices;
|
|
|
|
cups_dest_t *dests;
|
|
gint num_of_dests;
|
|
|
|
GCancellable *cancellable;
|
|
|
|
gboolean cups_searching;
|
|
gboolean remote_cups_searching;
|
|
gboolean snmp_searching;
|
|
|
|
GtkCellRenderer *text_renderer;
|
|
GtkCellRenderer *icon_renderer;
|
|
|
|
GtkWidget *dialog;
|
|
};
|
|
|
|
#define PP_NEW_PRINTER_DIALOG_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), PP_TYPE_NEW_PRINTER_DIALOG, PpNewPrinterDialogPrivate))
|
|
|
|
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
|
|
pp_new_printer_dialog_init (PpNewPrinterDialog *dialog)
|
|
{
|
|
PpNewPrinterDialogPrivate *priv;
|
|
GtkStyleContext *context;
|
|
GtkWidget *widget;
|
|
GError *error = NULL;
|
|
gchar *objects[] = { "dialog", NULL };
|
|
guint builder_result;
|
|
|
|
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)
|
|
{
|
|
g_warning ("Could not load ui: %s", error->message);
|
|
g_error_free (error);
|
|
}
|
|
|
|
/* 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)
|
|
{
|
|
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 *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 (priv->builder, "devices-treeview");
|
|
|
|
widget = (GtkWidget*)
|
|
gtk_builder_get_object (priv->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));
|
|
}
|
|
|
|
static void
|
|
add_device_to_list (PpNewPrinterDialog *dialog,
|
|
PpPrintDevice *device,
|
|
gboolean new_device)
|
|
{
|
|
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;
|
|
|
|
if (device)
|
|
{
|
|
if (device->device_id ||
|
|
device->device_ppd ||
|
|
(device->host_name &&
|
|
device->acquisition_method == ACQUISITION_METHOD_REMOTE_CUPS_SERVER))
|
|
{
|
|
network_device = FALSE;
|
|
|
|
if (device->device_class &&
|
|
g_strcmp0 (device->device_class, "network") == 0)
|
|
network_device = TRUE;
|
|
|
|
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)
|
|
{
|
|
name = get_tag_value (device->device_id, "mdl");
|
|
if (!name)
|
|
name = get_tag_value (device->device_id, "model");
|
|
}
|
|
|
|
if (!name &&
|
|
device->device_make_and_model &&
|
|
device->device_make_and_model[0] != '\0')
|
|
{
|
|
name = g_strdup (device->device_make_and_model);
|
|
}
|
|
|
|
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)
|
|
{
|
|
new_name = g_strdup_printf ("%s %d", name, name_index);
|
|
name_index++;
|
|
}
|
|
else
|
|
{
|
|
new_name = g_strdup (name);
|
|
}
|
|
|
|
if (new_name)
|
|
{
|
|
new_canonized_name = g_strcanon (g_strdup (new_name), ALLOWED_CHARACTERS, '-');
|
|
}
|
|
|
|
already_present = FALSE;
|
|
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)
|
|
{
|
|
item = (TDevice *) iter->data;
|
|
if (g_strcmp0 (item->device_name, new_canonized_name) == 0)
|
|
already_present = TRUE;
|
|
}
|
|
|
|
for (iter = priv->new_devices; iter; iter = iter->next)
|
|
{
|
|
item = (TDevice *) iter->data;
|
|
if (g_strcmp0 (item->device_name, new_canonized_name) == 0)
|
|
already_present = TRUE;
|
|
}
|
|
|
|
if (already_present)
|
|
{
|
|
g_free (new_name);
|
|
g_free (new_canonized_name);
|
|
}
|
|
else
|
|
{
|
|
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
|
|
priv->devices = g_list_append (priv->devices, store_device);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
add_devices_to_list (PpNewPrinterDialog *dialog,
|
|
GList *devices,
|
|
gboolean new_device)
|
|
{
|
|
GList *iter;
|
|
|
|
for (iter = devices; iter; iter = iter->next)
|
|
{
|
|
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;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static void
|
|
t_device_free (gpointer data)
|
|
{
|
|
if (data)
|
|
{
|
|
TDevice *device = (TDevice *) data;
|
|
|
|
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
|
|
update_spinner_state (PpNewPrinterDialog *dialog)
|
|
{
|
|
PpNewPrinterDialogPrivate *priv = dialog->priv;
|
|
GtkWidget *spinner;
|
|
|
|
if (priv->cups_searching ||
|
|
priv->remote_cups_searching ||
|
|
priv->snmp_searching)
|
|
{
|
|
spinner = (GtkWidget*)
|
|
gtk_builder_get_object (priv->builder, "spinner");
|
|
gtk_spinner_start (GTK_SPINNER (spinner));
|
|
gtk_widget_show (spinner);
|
|
}
|
|
else
|
|
{
|
|
spinner = (GtkWidget*)
|
|
gtk_builder_get_object (priv->builder, "spinner");
|
|
gtk_spinner_stop (GTK_SPINNER (spinner));
|
|
gtk_widget_hide (spinner);
|
|
}
|
|
}
|
|
|
|
static void
|
|
group_physical_devices_cb (gchar ***device_uris,
|
|
gpointer user_data)
|
|
{
|
|
PpNewPrinterDialog *dialog = (PpNewPrinterDialog *) user_data;
|
|
PpNewPrinterDialogPrivate *priv = dialog->priv;
|
|
TDevice *device, *tmp;
|
|
gint i, j;
|
|
|
|
if (device_uris)
|
|
{
|
|
for (i = 0; device_uris[i]; i++)
|
|
{
|
|
if (device_uris[i])
|
|
{
|
|
for (j = 0; device_uris[i][j]; j++)
|
|
{
|
|
device = device_in_list (device_uris[i][j], priv->devices);
|
|
if (device)
|
|
break;
|
|
}
|
|
|
|
if (device)
|
|
{
|
|
for (j = 0; device_uris[i][j]; j++)
|
|
{
|
|
tmp = device_in_list (device_uris[i][j], priv->new_devices);
|
|
if (tmp)
|
|
{
|
|
priv->new_devices = g_list_remove (priv->new_devices, tmp);
|
|
t_device_free (tmp);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (j = 0; device_uris[i][j]; j++)
|
|
{
|
|
tmp = device_in_list (device_uris[i][j], priv->new_devices);
|
|
if (tmp)
|
|
{
|
|
priv->new_devices = g_list_remove (priv->new_devices, tmp);
|
|
if (j == 0)
|
|
{
|
|
priv->devices = g_list_append (priv->devices, tmp);
|
|
}
|
|
else
|
|
{
|
|
t_device_free (tmp);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
for (i = 0; device_uris[i]; i++)
|
|
{
|
|
for (j = 0; device_uris[i][j]; j++)
|
|
{
|
|
g_free (device_uris[i][j]);
|
|
}
|
|
|
|
g_free (device_uris[i]);
|
|
}
|
|
|
|
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)
|
|
{
|
|
GVariantIter *iter;
|
|
GVariantIter *subiter;
|
|
GVariant *item;
|
|
GVariant *subitem;
|
|
gchar *device_uri;
|
|
|
|
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)))
|
|
{
|
|
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)))
|
|
{
|
|
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)
|
|
{
|
|
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++;
|
|
}
|
|
|
|
for (iter = devices; iter; iter = iter->next)
|
|
{
|
|
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++;
|
|
}
|
|
|
|
bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
|
|
if (bus)
|
|
{
|
|
g_variant_builder_init (&device_list, G_VARIANT_TYPE ("a{sv}"));
|
|
|
|
for (i = 0; i < length; i++)
|
|
{
|
|
if (all_devices[i]->device_uri)
|
|
{
|
|
g_variant_builder_init (&device_hash, G_VARIANT_TYPE ("a{ss}"));
|
|
|
|
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 ("Failed to get system bus: %s", error->message);
|
|
g_error_free (error);
|
|
group_physical_devices_cb (NULL, user_data);
|
|
}
|
|
|
|
for (i = 0; i < length; i++)
|
|
{
|
|
if (all_devices[i])
|
|
{
|
|
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]);
|
|
}
|
|
}
|
|
|
|
g_free (all_devices);
|
|
}
|
|
else
|
|
{
|
|
actualize_devices_list (dialog);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
actualize_devices_list (dialog);
|
|
}
|
|
}
|
|
|
|
for (iter = devices; iter; iter = iter->next)
|
|
pp_print_device_free ((PpPrintDevice *) iter->data);
|
|
g_list_free (devices);
|
|
}
|
|
|
|
static void
|
|
get_snmp_devices_cb (GObject *source_object,
|
|
GAsyncResult *res,
|
|
gpointer user_data)
|
|
{
|
|
PpNewPrinterDialog *dialog;
|
|
PpNewPrinterDialogPrivate *priv;
|
|
PpHost *host = (PpHost *) source_object;
|
|
GError *error = NULL;
|
|
PpDevicesList *result;
|
|
GList *iter;
|
|
|
|
result = pp_host_get_snmp_devices_finish (host, res, &error);
|
|
g_object_unref (source_object);
|
|
|
|
if (result)
|
|
{
|
|
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);
|
|
}
|
|
}
|
|
|
|
static void
|
|
get_remote_cups_devices_cb (GObject *source_object,
|
|
GAsyncResult *res,
|
|
gpointer user_data)
|
|
{
|
|
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 ("<b>%s</b>\n<small><span foreground=\"#555555\">%s</span></small>",
|
|
device->display_name,
|
|
device->device_location);
|
|
else
|
|
display_string = g_markup_printf_escaped ("<b>%s</b>\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 ("<b>%s</b>\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);
|
|
}
|
|
}
|