[gnome-settings-daemon] print-notifications: Use the best PPD for new printer
- From: Bastien Nocera <hadess src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-settings-daemon] print-notifications: Use the best PPD for new printer
- Date: Fri, 9 Sep 2011 16:31:46 +0000 (UTC)
commit 130278e762691116a8f255769ce018a9e9c9dfd4
Author: Marek Kasik <mkasik redhat com>
Date: Fri Sep 9 12:10:41 2011 +0200
print-notifications: Use the best PPD for new printer
This is a backported patch from gnome-control-center which
uses system-config-printer's DBus methods to find the best
PPD for new printer if there is no exact match.
https://bugzilla.gnome.org/show_bug.cgi?id=658544
plugins/print-notifications/Makefile.am | 1 +
plugins/print-notifications/gsd-printer.c | 938 ++++++++++++++++++++++++++++-
2 files changed, 906 insertions(+), 33 deletions(-)
---
diff --git a/plugins/print-notifications/Makefile.am b/plugins/print-notifications/Makefile.am
index db221fc..fa34ac9 100644
--- a/plugins/print-notifications/Makefile.am
+++ b/plugins/print-notifications/Makefile.am
@@ -44,6 +44,7 @@ gsd_printer_CFLAGS = \
gsd_printer_LDADD = \
$(SETTINGS_PLUGIN_LIBS) \
+ $(CUPS_LIBS) \
$(LIBNOTIFY_LIBS)
EXTRA_DIST = \
diff --git a/plugins/print-notifications/gsd-printer.c b/plugins/print-notifications/gsd-printer.c
index 90fa955..b266389 100644
--- a/plugins/print-notifications/gsd-printer.c
+++ b/plugins/print-notifications/gsd-printer.c
@@ -23,6 +23,9 @@
#include <stdlib.h>
#include <libnotify/notify.h>
#include <glib/gi18n.h>
+#include <glib/gstdio.h>
+#include <cups/cups.h>
+#include <cups/ppd.h>
static GDBusNodeInfo *npn_introspection_data = NULL;
static GDBusNodeInfo *pdi_introspection_data = NULL;
@@ -37,7 +40,19 @@ static GDBusNodeInfo *pdi_introspection_data = NULL;
#define PACKAGE_KIT_BUS "org.freedesktop.PackageKit"
#define PACKAGE_KIT_PATH "/org/freedesktop/PackageKit"
-#define PACKAGE_KIT_IFACE "org.freedesktop.PackageKit.Modify"
+#define PACKAGE_KIT_MODIFY_IFACE "org.freedesktop.PackageKit.Modify"
+#define PACKAGE_KIT_QUERY_IFACE "org.freedesktop.PackageKit.Query"
+
+#define SCP_BUS "org.fedoraproject.Config.Printing"
+#define SCP_PATH "/org/fedoraproject/Config/Printing"
+#define SCP_IFACE "org.fedoraproject.Config.Printing"
+
+#define MECHANISM_BUS "org.opensuse.CupsPkHelper.Mechanism"
+
+#define ALLOWED_CHARACTERS "abcdefghijklmnopqrtsuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_/"
+
+#define DBUS_TIMEOUT 60000
+#define DBUS_INSTALL_TIMEOUT 3600000
static const gchar npn_introspection_xml[] =
"<node name='/com/redhat/NewPrinterNotification'>"
@@ -66,6 +81,827 @@ static const gchar pdi_introspection_xml[] =
" </interface>"
"</node>";
+static GHashTable *
+get_missing_executables (const gchar *ppd_file_name)
+{
+ GHashTable *executables = NULL;
+ GDBusProxy *proxy;
+ GVariant *input;
+ GVariant *output;
+ GVariant *array;
+ GError *error = NULL;
+ gint i;
+
+ if (!ppd_file_name)
+ return NULL;
+
+ proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
+ G_DBUS_PROXY_FLAGS_NONE,
+ NULL,
+ SCP_BUS,
+ SCP_PATH,
+ SCP_IFACE,
+ NULL,
+ &error);
+
+ if (!proxy) {
+ g_warning ("%s", error->message);
+ g_error_free (error);
+ return NULL;
+ }
+
+ input = g_variant_new ("(s)",
+ ppd_file_name);
+
+ output = g_dbus_proxy_call_sync (proxy,
+ "MissingExecutables",
+ input,
+ G_DBUS_CALL_FLAGS_NONE,
+ DBUS_TIMEOUT,
+ NULL,
+ &error);
+
+ if (output && g_variant_n_children (output) == 1) {
+ array = g_variant_get_child_value (output, 0);
+ if (array) {
+ executables = g_hash_table_new_full (g_str_hash, g_str_equal,
+ g_free, NULL);
+ for (i = 0; i < g_variant_n_children (array); i++) {
+ g_hash_table_insert (executables,
+ g_strdup (g_variant_get_string (
+ g_variant_get_child_value (array, i),
+ NULL)),
+ NULL);
+ }
+ }
+ }
+
+ if (output) {
+ g_variant_unref (output);
+ } else {
+ g_warning ("%s", error->message);
+ g_error_free (error);
+ }
+
+ g_variant_unref (input);
+ g_object_unref (proxy);
+
+ return executables;
+}
+
+static GHashTable *
+find_packages_for_executables (GHashTable *executables)
+{
+ GHashTableIter exec_iter;
+ GHashTable *packages = NULL;
+ GDBusProxy *proxy;
+ GVariant *input;
+ GVariant *output;
+ gpointer key, value;
+ GError *error = NULL;
+
+ if (!executables || g_hash_table_size (executables) <= 0)
+ return NULL;
+
+ proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
+ G_DBUS_PROXY_FLAGS_NONE,
+ NULL,
+ PACKAGE_KIT_BUS,
+ PACKAGE_KIT_PATH,
+ PACKAGE_KIT_QUERY_IFACE,
+ NULL,
+ &error);
+
+ if (!proxy) {
+ g_warning ("%s", error->message);
+ g_error_free (error);
+ return NULL;
+ }
+
+ packages = g_hash_table_new_full (g_str_hash, g_str_equal,
+ g_free, NULL);
+
+ g_hash_table_iter_init (&exec_iter, executables);
+ while (g_hash_table_iter_next (&exec_iter, &key, &value)) {
+ input = g_variant_new ("(ss)", (gchar *) key, "");
+
+ output = g_dbus_proxy_call_sync (proxy,
+ "SearchFile",
+ input,
+ G_DBUS_CALL_FLAGS_NONE,
+ DBUS_TIMEOUT,
+ NULL,
+ &error);
+
+ if (output) {
+ gboolean installed;
+ gchar *package;
+
+ g_variant_get (output,
+ "(bs)",
+ &installed,
+ &package);
+ if (!installed)
+ g_hash_table_insert (packages, g_strdup (package), NULL);
+ }
+
+ if (output) {
+ g_variant_unref (output);
+ } else {
+ g_warning ("%s", error->message);
+ g_error_free (error);
+ error = NULL;
+ }
+ g_variant_unref (input);
+ }
+
+ g_object_unref (proxy);
+
+ return packages;
+}
+
+static void
+install_packages (GHashTable *packages)
+{
+ GVariantBuilder array_builder;
+ GHashTableIter pkg_iter;
+ GDBusProxy *proxy;
+ GVariant *input;
+ GVariant *output;
+ gpointer key, value;
+ GError *error = NULL;
+
+ if (!packages || g_hash_table_size (packages) <= 0)
+ return;
+
+ proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
+ G_DBUS_PROXY_FLAGS_NONE,
+ NULL,
+ PACKAGE_KIT_BUS,
+ PACKAGE_KIT_PATH,
+ PACKAGE_KIT_MODIFY_IFACE,
+ NULL,
+ &error);
+
+ if (!proxy) {
+ g_warning ("%s", error->message);
+ g_error_free (error);
+ return;
+ }
+
+ g_variant_builder_init (&array_builder, G_VARIANT_TYPE ("as"));
+
+ g_hash_table_iter_init (&pkg_iter, packages);
+ while (g_hash_table_iter_next (&pkg_iter, &key, &value)) {
+ g_variant_builder_add (&array_builder,
+ "s",
+ (gchar *) key);
+ }
+
+ input = g_variant_new ("(uass)",
+ 0,
+ &array_builder,
+ "hide-finished");
+
+ output = g_dbus_proxy_call_sync (proxy,
+ "InstallPackageNames",
+ input,
+ G_DBUS_CALL_FLAGS_NONE,
+ DBUS_INSTALL_TIMEOUT,
+ NULL,
+ &error);
+
+ if (output) {
+ g_variant_unref (output);
+ } else {
+ g_warning ("%s", error->message);
+ g_error_free (error);
+ }
+
+ g_variant_unref (input);
+ g_object_unref (proxy);
+}
+
+static gchar *
+get_best_ppd (gchar *device_id,
+ gchar *device_make_and_model,
+ gchar *device_uri)
+{
+ GDBusProxy *proxy;
+ GVariant *input;
+ GVariant *output;
+ GVariant *array;
+ GVariant *tuple;
+ GError *error = NULL;
+ gchar *ppd_name = NULL;
+ gint i, j;
+ static const char * const match_levels[] = {
+ "exact-cmd",
+ "exact",
+ "close",
+ "generic",
+ "none"};
+
+ proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
+ G_DBUS_PROXY_FLAGS_NONE,
+ NULL,
+ SCP_BUS,
+ SCP_PATH,
+ SCP_IFACE,
+ NULL,
+ &error);
+
+ if (!proxy) {
+ g_warning ("%s", error->message);
+ g_error_free (error);
+ return NULL;
+ }
+
+ input = g_variant_new ("(sss)",
+ device_id ? device_id : "",
+ device_make_and_model ? device_make_and_model : "",
+ device_uri ? device_uri : "");
+
+ output = g_dbus_proxy_call_sync (proxy,
+ "GetBestDrivers",
+ input,
+ G_DBUS_CALL_FLAGS_NONE,
+ DBUS_TIMEOUT,
+ NULL,
+ &error);
+
+ if (output && g_variant_n_children (output) >= 1) {
+ array = g_variant_get_child_value (output, 0);
+ if (array)
+ for (j = 0; j < G_N_ELEMENTS (match_levels) && ppd_name == NULL; j++)
+ for (i = 0; i < g_variant_n_children (array) && ppd_name == NULL; i++) {
+ tuple = g_variant_get_child_value (array, i);
+ if (tuple && g_variant_n_children (tuple) == 2) {
+ if (g_strcmp0 (g_variant_get_string (
+ g_variant_get_child_value (tuple, 1),
+ NULL), match_levels[j]) == 0)
+ ppd_name = g_strdup (g_variant_get_string (
+ g_variant_get_child_value (tuple, 0),
+ NULL));
+ }
+ }
+ }
+
+ if (output) {
+ g_variant_unref (output);
+ } else {
+ g_warning ("%s", error->message);
+ g_error_free (error);
+ }
+
+ g_variant_unref (input);
+ g_object_unref (proxy);
+
+ return ppd_name;
+}
+
+static gchar *
+get_tag_value (const gchar *tag_string,
+ const gchar *tag_name)
+{
+ gchar **tag_string_splitted;
+ gchar *tag_value = NULL;
+ gint tag_name_length;
+ gint i;
+
+ if (tag_string && tag_name) {
+ tag_name_length = strlen (tag_name);
+ tag_string_splitted = g_strsplit (tag_string, ";", 0);
+ if (tag_string_splitted) {
+ for (i = 0; i < g_strv_length (tag_string_splitted); i++)
+ if (g_ascii_strncasecmp (tag_string_splitted[i], tag_name, tag_name_length) == 0)
+ if (strlen (tag_string_splitted[i]) > tag_name_length + 1)
+ tag_value = g_strdup (tag_string_splitted[i] + tag_name_length + 1);
+
+ g_strfreev (tag_string_splitted);
+ }
+ }
+
+ return tag_value;
+}
+
+static gchar *
+create_name (gchar *device_id)
+{
+ cups_dest_t *dests;
+ gboolean already_present = FALSE;
+ gchar *name = NULL;
+ gchar *new_name = NULL;
+ gint num_dests;
+ gint name_index = 2;
+ gint j;
+
+ if (device_id) {
+ name = get_tag_value (device_id, "mdl");
+ if (!name)
+ name = get_tag_value (device_id, "model");
+
+ if (name)
+ name = g_strcanon (name, ALLOWED_CHARACTERS, '-');
+ }
+
+ num_dests = cupsGetDests (&dests);
+ do {
+ 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);
+
+ return name;
+}
+
+static gboolean
+add_printer (gchar *printer_name,
+ gchar *device_uri,
+ gchar *ppd_name,
+ gchar *info,
+ gchar *location)
+{
+ cups_dest_t *dests;
+ GDBusProxy *proxy;
+ gboolean success = FALSE;
+ GVariant *input;
+ GVariant *output;
+ GError *error = NULL;
+ gint num_dests;
+ gint i;
+
+ if (!printer_name || !device_uri || !ppd_name)
+ return FALSE;
+
+ 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);
+ return FALSE;
+ }
+
+ input = g_variant_new ("(sssss)",
+ printer_name ? printer_name : "",
+ device_uri ? device_uri : "",
+ ppd_name ? ppd_name : "",
+ info ? info : "",
+ location ? location : "");
+
+ output = g_dbus_proxy_call_sync (proxy,
+ "PrinterAdd",
+ input,
+ G_DBUS_CALL_FLAGS_NONE,
+ DBUS_TIMEOUT,
+ NULL,
+ &error);
+
+ if (output) {
+ g_variant_unref (output);
+ } else {
+ g_warning ("%s", error->message);
+ g_error_free (error);
+ }
+
+ g_variant_unref (input);
+ g_object_unref (proxy);
+
+ num_dests = cupsGetDests (&dests);
+ for (i = 0; i < num_dests; i++)
+ if (g_strcmp0 (dests[i].name, printer_name) == 0)
+ success = TRUE;
+ cupsFreeDests (num_dests, dests);
+
+ return success;
+}
+
+static gboolean
+printer_set_enabled (const gchar *printer_name,
+ gboolean enabled)
+{
+ GDBusProxy *proxy;
+ gboolean result = TRUE;
+ GVariant *input;
+ GVariant *output;
+ GError *error = NULL;
+
+ if (!printer_name)
+ return FALSE;
+
+ 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);
+ return FALSE;
+ }
+
+ input = g_variant_new ("(sb)",
+ printer_name,
+ enabled);
+
+ output = g_dbus_proxy_call_sync (proxy,
+ "PrinterSetEnabled",
+ input,
+ G_DBUS_CALL_FLAGS_NONE,
+ DBUS_TIMEOUT,
+ NULL,
+ &error);
+
+ if (output) {
+ g_variant_unref (output);
+ } else {
+ g_warning ("%s", error->message);
+ g_error_free (error);
+ result = FALSE;
+ }
+
+ g_variant_unref (input);
+ g_object_unref (proxy);
+
+ return result;
+}
+
+static gboolean
+printer_set_accepting_jobs (const gchar *printer_name,
+ gboolean accepting_jobs,
+ const gchar *reason)
+{
+ GDBusProxy *proxy;
+ gboolean result = TRUE;
+ GVariant *input;
+ GVariant *output;
+ GError *error = NULL;
+
+ if (!printer_name)
+ return FALSE;
+
+ 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);
+ return FALSE;
+ }
+
+ input = g_variant_new ("(sbs)",
+ printer_name,
+ accepting_jobs,
+ reason ? reason : "");
+
+ output = g_dbus_proxy_call_sync (proxy,
+ "PrinterSetAcceptJobs",
+ input,
+ G_DBUS_CALL_FLAGS_NONE,
+ DBUS_TIMEOUT,
+ NULL,
+ &error);
+
+ if (output) {
+ g_variant_unref (output);
+ } else {
+ g_warning ("%s", error->message);
+ g_error_free (error);
+ result = FALSE;
+ }
+
+ g_variant_unref (input);
+ g_object_unref (proxy);
+
+ return result;
+}
+
+static ipp_t *
+execute_maintenance_command (const char *printer_name,
+ const char *command,
+ const char *title)
+{
+ http_t *http;
+ GError *error = NULL;
+ ipp_t *request = NULL;
+ ipp_t *response = NULL;
+ gchar *file_name = NULL;
+ char uri[HTTP_MAX_URI + 1];
+ int fd = -1;
+
+ http = httpConnectEncrypt (cupsServer (),
+ ippPort (),
+ cupsEncryption ());
+
+ if (!http)
+ return NULL;
+
+ request = ippNewRequest (IPP_PRINT_JOB);
+
+ g_snprintf (uri,
+ sizeof (uri),
+ "ipp://localhost/printers/%s",
+ printer_name);
+
+ ippAddString (request,
+ IPP_TAG_OPERATION,
+ IPP_TAG_URI,
+ "printer-uri",
+ NULL,
+ uri);
+
+ ippAddString (request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name",
+ NULL, title);
+
+ ippAddString (request, IPP_TAG_JOB, IPP_TAG_MIMETYPE, "document-format",
+ NULL, "application/vnd.cups-command");
+
+ fd = g_file_open_tmp ("ccXXXXXX", &file_name, &error);
+
+ if (fd != -1) {
+ FILE *file;
+
+ file = fdopen (fd, "w");
+ fprintf (file, "#CUPS-COMMAND\n");
+ fprintf (file, "%s\n", command);
+ fclose (file);
+
+ response = cupsDoFileRequest (http, request, "/", file_name);
+ g_unlink (file_name);
+ } else {
+ g_warning ("%s", error->message);
+ g_error_free (error);
+ }
+
+ g_free (file_name);
+ httpClose (http);
+
+ return response;
+}
+
+static char *
+get_dest_attr (const char *dest_name,
+ const char *attr)
+{
+ cups_dest_t *dests;
+ int num_dests;
+ cups_dest_t *dest;
+ const char *value;
+ char *ret;
+
+ if (dest_name == NULL)
+ return NULL;
+
+ ret = NULL;
+
+ num_dests = cupsGetDests (&dests);
+ if (num_dests < 1) {
+ g_debug ("Unable to get printer destinations");
+ return NULL;
+ }
+
+ dest = cupsGetDest (dest_name, NULL, num_dests, dests);
+ if (dest == NULL) {
+ g_debug ("Unable to find a printer named '%s'", dest_name);
+ goto out;
+ }
+
+ value = cupsGetOption (attr, dest->num_options, dest->options);
+ if (value == NULL) {
+ g_debug ("Unable to get %s for '%s'", attr, dest_name);
+ goto out;
+ }
+ ret = g_strdup (value);
+out:
+ cupsFreeDests (num_dests, dests);
+
+ return ret;
+}
+
+static void
+printer_autoconfigure (gchar *printer_name)
+{
+ gchar *commands;
+ gchar *commands_lowercase;
+ ipp_t *response = NULL;
+
+ if (!printer_name)
+ return;
+
+ commands = get_dest_attr (printer_name, "printer-commands");
+ commands_lowercase = g_ascii_strdown (commands, -1);
+
+ if (g_strrstr (commands_lowercase, "AutoConfigure")) {
+ response = execute_maintenance_command (printer_name,
+ "AutoConfigure",
+ ("Automatic configuration"));
+ if (response) {
+ if (response->state == IPP_ERROR)
+ g_warning ("An error has occured during automatic configuration of new printer.");
+ ippDelete (response);
+ }
+ }
+ g_free (commands);
+ g_free (commands_lowercase);
+}
+
+
+static void
+set_default_paper_size (const gchar *printer_name,
+ const gchar *ppd_file_name)
+{
+ ppd_file_t *ppd_file = NULL;
+ GDBusProxy *proxy;
+ GVariant *input;
+ GVariant *output;
+ GError *error = NULL;
+ gchar **value = NULL;
+ gchar *paper_size;
+ char *locale;
+ gint i, j, k;
+
+ 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);
+ return;
+ }
+
+ /* Set default PaperSize according to the locale */
+ locale = setlocale (LC_PAPER, NULL);
+ if (!locale)
+ locale = setlocale (LC_MESSAGES, NULL);
+
+ if (!locale) {
+ g_object_unref (proxy);
+ return;
+ }
+
+ /* CLDR 2.0 alpha
+ * http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/territory_language_information.html
+ */
+ if (g_regex_match_simple ("[^_ ]{2,3}_(BZ|CA|CL|CO|CR|GT|MX|NI|PA|PH|PR|SV|US|VE)",
+ locale, G_REGEX_ANCHORED, G_REGEX_MATCH_ANCHORED))
+ paper_size = g_strdup ("Letter");
+ else
+ paper_size = g_strdup ("A4");
+
+ if (ppd_file_name) {
+ ppd_file = ppdOpenFile (ppd_file_name);
+ if (ppd_file) {
+ ppdMarkDefaults (ppd_file);
+ for (i = 0; i < ppd_file->num_groups; i++)
+ for (j = 0; j < ppd_file->groups[i].num_options; j++)
+ if (g_strcmp0 ("PageSize", ppd_file->groups[i].options[j].keyword) == 0) {
+ for (k = 0; k < ppd_file->groups[i].options[j].num_choices; k++) {
+ if (g_ascii_strncasecmp (paper_size,
+ ppd_file->groups[i].options[j].choices[k].choice,
+ strlen (paper_size)) == 0 &&
+ !ppd_file->groups[i].options[j].choices[k].marked) {
+ value = g_new0 (gchar *, 2);
+ value[0] = g_strdup (ppd_file->groups[i].options[j].choices[k].choice);
+ break;
+ }
+ }
+ break;
+ }
+ ppdClose (ppd_file);
+ }
+ }
+
+ if (value) {
+ GVariant *array;
+
+ array = g_variant_new_strv ((const gchar * const *)value, -1);
+
+ input = g_variant_new ("(ssv)",
+ printer_name ? printer_name : "",
+ "PageSize-default",
+ array);
+
+ output = g_dbus_proxy_call_sync (proxy,
+ "PrinterAddOptionDefault",
+ input,
+ G_DBUS_CALL_FLAGS_NONE,
+ DBUS_TIMEOUT,
+ NULL,
+ &error);
+
+ if (output) {
+ g_variant_unref (output);
+ } else {
+ g_warning ("%s", error->message);
+ g_error_free (error);
+ }
+
+ g_variant_unref (input);
+ g_variant_unref (array);
+ g_strfreev (value);
+ }
+
+ g_free (paper_size);
+ g_object_unref (proxy);
+}
+
+/*
+ * Setup new printer and returns TRUE if successful.
+ */
+static gboolean
+setup_printer (gchar *device_id,
+ gchar *device_make_and_model,
+ gchar *device_uri)
+{
+ gboolean success = FALSE;
+ gchar *ppd_name;
+ gchar *printer_name;
+
+ ppd_name = get_best_ppd (device_id, device_make_and_model, device_uri);
+ printer_name = create_name (device_id);
+
+ if (!ppd_name || !printer_name || !device_uri) {
+ g_free (ppd_name);
+ g_free (printer_name);
+ return FALSE;
+ }
+
+ success = add_printer (printer_name, device_uri,
+ ppd_name, NULL, NULL);
+
+ /* Set some options of the new printer */
+ if (success) {
+ const char *ppd_file_name;
+
+ printer_set_accepting_jobs (printer_name, TRUE, NULL);
+ printer_set_enabled (printer_name, TRUE);
+ printer_autoconfigure (printer_name);
+
+ ppd_file_name = cupsGetPPD (printer_name);
+
+ if (ppd_file_name) {
+ GHashTable *executables;
+ GHashTable *packages;
+
+ set_default_paper_size (printer_name, ppd_file_name);
+
+ executables = get_missing_executables (ppd_file_name);
+ packages = find_packages_for_executables (executables);
+ install_packages (packages);
+
+ if (executables)
+ g_hash_table_destroy (executables);
+ if (packages)
+ g_hash_table_destroy (packages);
+ g_unlink (ppd_file_name);
+ }
+ }
+
+ g_free (printer_name);
+ g_free (ppd_name);
+
+ return success;
+}
+
static void
handle_method_call (GDBusConnection *connection,
const gchar *sender,
@@ -84,6 +920,8 @@ handle_method_call (GDBusConnection *connection,
gchar *des = NULL;
gchar *cmd = NULL;
gchar *device = NULL;
+ gchar *device_id;
+ gchar *make_and_model;
gint status = 0;
if (g_strcmp0 (method_name, "GetReady") == 0) {
@@ -110,30 +948,55 @@ handle_method_call (GDBusConnection *connection,
/* name is a URI, no queue was generated, because no suitable
* driver was found
*/
- /* Translators: We have no driver installed for this printer */
- primary_text = g_strdup (_("Missing printer driver"));
- if ((mfg && mdl) || des) {
- if (mfg && mdl)
- device = g_strdup_printf ("%s %s", mfg, mdl);
- else
- device = g_strdup (des);
+ device_id = g_strdup_printf ("MFG:%s;MDL:%s;DES:%s;CMD:%s;", mfg, mdl, des, cmd);
+ make_and_model = g_strdup_printf ("%s %s", mfg, mdl);
+
+ if (!setup_printer (device_id, make_and_model, name)) {
- /* Translators: We have no driver installed for the device */
- secondary_text = g_strdup_printf (_("No printer driver for %s."), device);
- g_free (device);
- }
- else
/* Translators: We have no driver installed for this printer */
- secondary_text = g_strdup (_("No driver for this printer."));
+ primary_text = g_strdup (_("Missing printer driver"));
+
+ if ((mfg && mdl) || des) {
+ if (mfg && mdl)
+ device = g_strdup_printf ("%s %s", mfg, mdl);
+ else
+ device = g_strdup (des);
+
+ /* Translators: We have no driver installed for the device */
+ secondary_text = g_strdup_printf (_("No printer driver for %s."), device);
+ g_free (device);
+ }
+ else
+ /* Translators: We have no driver installed for this printer */
+ secondary_text = g_strdup (_("No driver for this printer."));
+ }
+
+ g_free (make_and_model);
+ g_free (device_id);
}
else {
/* name is the name of the queue which hal_lpadmin has set up
* automatically.
*/
- /* TODO: handle missing packages as system-config-printer does
- */
+ const char *ppd_file_name;
+
+ ppd_file_name = cupsGetPPD (name);
+ if (ppd_file_name) {
+ GHashTable *executables;
+ GHashTable *packages;
+
+ executables = get_missing_executables (ppd_file_name);
+ packages = find_packages_for_executables (executables);
+ install_packages (packages);
+
+ if (executables)
+ g_hash_table_destroy (executables);
+ if (packages)
+ g_hash_table_destroy (packages);
+ g_unlink (ppd_file_name);
+ }
}
g_dbus_method_invocation_return_value (invocation,
@@ -158,37 +1021,46 @@ handle_method_call (GDBusConnection *connection,
NULL,
PACKAGE_KIT_BUS,
PACKAGE_KIT_PATH,
- PACKAGE_KIT_IFACE,
+ PACKAGE_KIT_MODIFY_IFACE,
NULL,
&error);
+ if (!proxy) {
+ g_warning ("%s", error->message);
+ g_error_free (error);
+ }
+
if (proxy && device) {
- GVariantBuilder *builder = NULL;
- GVariant *ipd_parameters = NULL;
+ GVariantBuilder *builder;
+ GVariant *input;
+ GVariant *output;
builder = g_variant_builder_new (G_VARIANT_TYPE ("as"));
g_variant_builder_add (builder, "s", device);
- ipd_parameters = g_variant_new ("(uass)",
- 0,
- builder,
- "hide-finished");
+ input = g_variant_new ("(uass)",
+ 0,
+ builder,
+ "hide-finished");
- g_dbus_proxy_call_sync (proxy,
- "InstallPrinterDrivers",
- ipd_parameters,
- G_DBUS_CALL_FLAGS_NONE,
- 3600000,
- NULL,
- &error);
+ output = g_dbus_proxy_call_sync (proxy,
+ "InstallPrinterDrivers",
+ input,
+ G_DBUS_CALL_FLAGS_NONE,
+ DBUS_INSTALL_TIMEOUT,
+ NULL,
+ &error);
- if (error)
+ if (output) {
+ g_variant_unref (output);
+ } else {
g_warning ("%s", error->message);
+ g_error_free (error);
+ }
- g_variant_unref (ipd_parameters);
+ g_variant_unref (input);
g_variant_builder_unref (builder);
g_object_unref (proxy);
- g_clear_error (&error);
}
g_dbus_method_invocation_return_value (invocation,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]