
2006-05-04 Alexander Larsson <alexl@redhat.com> * gtk/gtk.symbols: Added new symbols * gtk/gtkpagesetupunixdialog.c: * gtk/gtkprintunixdialog.c: Destroy backends when finalizing dialogs. Fix printer leak in selected_printer_changed. * gtk/gtkprintbackend.[ch]: Convert from interface to baseclass. Move printer hashtable here so that the baseclass can handle the slightly complicated ownership model. Add gtk_print_backend_destroy which runs the dispose method, causing the ref-cycles between the backend and its printers to be broken. Add gtk_print_backend_unref_at_idle(). * gtk/gtkprinter.[ch]: GtkPrinter objects now ref their backend so that its always availible, since its needed for the printer object to work. This causes a reference-cycle that is broken using gtk_print_backend_destroy. Add gtk_printer_compare. * gtk/gtkprintoperation-private.h: * gtk/gtkprintoperation-unix.c: * gtk/gtkprintoperation.c: Implement !show_dialog for unix. Make sure the print data is fully spooled before returning from a sync run_dialog. * modules/printbackends/cups/gtkcupsutils.[ch]: Add gtk_cups_request_ipp_add_strings * modules/printbackends/cups/gtkprintbackendcups.c: * modules/printbackends/cups/gtkprintercups.c: * modules/printbackends/lpr/gtkprintbackendlpr.c: * modules/printbackends/pdf/gtkprintbackendpdf.c: Convert backends to derive instead of implementing interface. Move common code into baseclass. CUPS: Remove the printer polling in dispose, not finalize. In the cups watch, remove the backend at idle instead of immediately, since the unref can cause the module to be unloaded. Limit the number of printer attributes requested Get printer uri in initial printer listing so that we can use the printer object immediately. * tests/Makefile.am: * tests/testnouiprint.c: Add testcase for !show_dialog.
755 lines
19 KiB
C
755 lines
19 KiB
C
/* GTK - The GIMP Toolkit
|
|
* gtkprintoperation-unix.c: Print Operation Details for Unix and Unix like platforms
|
|
* Copyright (C) 2006, Red Hat, Inc.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This library 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
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the
|
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
* Boston, MA 02111-1307, USA.
|
|
*/
|
|
|
|
#include "config.h"
|
|
#ifdef HAVE_UNISTD_H
|
|
#include <unistd.h>
|
|
#endif
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <string.h>
|
|
|
|
#include "gtkprintoperation-private.h"
|
|
#include "gtkmarshal.h"
|
|
#include "gtkmessagedialog.h"
|
|
|
|
#include "gtkprintunixdialog.h"
|
|
#include "gtkpagesetupunixdialog.h"
|
|
#include "gtkprintbackend.h"
|
|
#include "gtkprinter.h"
|
|
#include "gtkprintjob.h"
|
|
#include "gtkalias.h"
|
|
#include "gtkintl.h"
|
|
|
|
typedef struct {
|
|
GtkPrintJob *job; /* the job we are sending to the printer */
|
|
gulong job_status_changed_tag;
|
|
GtkWindow *parent; /* just in case we need to throw error dialogs */
|
|
GMainLoop *loop;
|
|
gboolean data_sent;
|
|
} GtkPrintOperationUnix;
|
|
|
|
typedef struct _PrinterFinder PrinterFinder;
|
|
|
|
static void printer_finder_free (PrinterFinder *finder);
|
|
static void find_printer (const char *printer,
|
|
GFunc func,
|
|
gpointer data);
|
|
|
|
static void
|
|
unix_start_page (GtkPrintOperation *op,
|
|
GtkPrintContext *print_context,
|
|
GtkPageSetup *page_setup)
|
|
{
|
|
|
|
}
|
|
|
|
static void
|
|
unix_end_page (GtkPrintOperation *op,
|
|
GtkPrintContext *print_context)
|
|
{
|
|
cairo_t *cr;
|
|
|
|
cr = gtk_print_context_get_cairo (print_context);
|
|
cairo_show_page (cr);
|
|
}
|
|
|
|
static void
|
|
op_unix_free (GtkPrintOperationUnix *op_unix)
|
|
{
|
|
if (op_unix->job)
|
|
{
|
|
g_signal_handler_disconnect (op_unix->job,
|
|
op_unix->job_status_changed_tag);
|
|
g_object_unref (op_unix->job);
|
|
}
|
|
|
|
g_free (op_unix);
|
|
}
|
|
|
|
static void
|
|
unix_finish_send (GtkPrintJob *job,
|
|
void *user_data,
|
|
GError *error)
|
|
{
|
|
GtkPrintOperationUnix *op_unix;
|
|
|
|
op_unix = (GtkPrintOperationUnix *) user_data;
|
|
|
|
if (error != NULL)
|
|
{
|
|
GtkWidget *edialog;
|
|
edialog = gtk_message_dialog_new (op_unix->parent,
|
|
GTK_DIALOG_DESTROY_WITH_PARENT,
|
|
GTK_MESSAGE_ERROR,
|
|
GTK_BUTTONS_CLOSE,
|
|
_("Error printing") /* FIXME better text */);
|
|
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (edialog),
|
|
"%s", error->message);
|
|
gtk_window_set_modal (GTK_WINDOW (edialog), TRUE);
|
|
g_signal_connect (edialog, "response",
|
|
G_CALLBACK (gtk_widget_destroy), NULL);
|
|
|
|
gtk_window_present (GTK_WINDOW (edialog));
|
|
}
|
|
|
|
op_unix->data_sent = TRUE;
|
|
if (op_unix->loop)
|
|
g_main_loop_quit (op_unix->loop);
|
|
}
|
|
|
|
static void
|
|
unix_end_run (GtkPrintOperation *op,
|
|
gboolean wait)
|
|
{
|
|
GtkPrintOperationUnix *op_unix = op->priv->platform_data;
|
|
|
|
if (wait)
|
|
op_unix->loop = g_main_loop_new (NULL, FALSE);
|
|
|
|
/* TODO: Check for error */
|
|
gtk_print_job_send (op_unix->job,
|
|
unix_finish_send,
|
|
op_unix, NULL,
|
|
NULL);
|
|
|
|
if (wait)
|
|
{
|
|
if (!op_unix->data_sent)
|
|
{
|
|
GDK_THREADS_LEAVE ();
|
|
g_main_loop_run (op_unix->loop);
|
|
GDK_THREADS_ENTER ();
|
|
}
|
|
g_main_loop_unref (op_unix->loop);
|
|
}
|
|
}
|
|
|
|
static void
|
|
job_status_changed_cb (GtkPrintJob *job,
|
|
GtkPrintOperation *op)
|
|
{
|
|
_gtk_print_operation_set_status (op, gtk_print_job_get_status (job), NULL);
|
|
}
|
|
|
|
|
|
static GtkWidget *
|
|
get_print_dialog (GtkPrintOperation *op,
|
|
GtkWindow *parent)
|
|
{
|
|
GtkPrintOperationPrivate *priv = op->priv;
|
|
GtkWidget *pd;
|
|
GtkPageSetup *page_setup;
|
|
|
|
pd = gtk_print_unix_dialog_new (NULL, parent);
|
|
|
|
if (priv->print_settings)
|
|
gtk_print_unix_dialog_set_settings (GTK_PRINT_UNIX_DIALOG (pd),
|
|
priv->print_settings);
|
|
if (priv->default_page_setup)
|
|
page_setup = gtk_page_setup_copy (priv->default_page_setup);
|
|
else
|
|
page_setup = gtk_page_setup_new ();
|
|
|
|
gtk_print_unix_dialog_set_page_setup (GTK_PRINT_UNIX_DIALOG (pd),
|
|
page_setup);
|
|
g_object_unref (page_setup);
|
|
|
|
return pd;
|
|
}
|
|
|
|
typedef struct {
|
|
GtkPrintOperation *op;
|
|
gboolean do_print;
|
|
GError **error;
|
|
GtkPrintOperationResult result;
|
|
GtkPrintOperationPrintFunc print_cb;
|
|
GDestroyNotify destroy;
|
|
GtkWindow *parent;
|
|
GMainLoop *loop;
|
|
} PrintResponseData;
|
|
|
|
static void
|
|
print_response_data_free (gpointer data)
|
|
{
|
|
PrintResponseData *rdata = data;
|
|
|
|
g_object_unref (rdata->op);
|
|
g_free (rdata);
|
|
}
|
|
|
|
static void
|
|
finish_print (PrintResponseData *rdata,
|
|
GtkPrinter *printer,
|
|
GtkPageSetup *page_setup,
|
|
GtkPrintSettings *settings)
|
|
{
|
|
GtkPrintOperation *op = rdata->op;
|
|
GtkPrintOperationPrivate *priv = op->priv;
|
|
|
|
priv->start_page = unix_start_page;
|
|
priv->end_page = unix_end_page;
|
|
priv->end_run = unix_end_run;
|
|
|
|
if (rdata->do_print)
|
|
{
|
|
GtkPrintOperationUnix *op_unix;
|
|
|
|
gtk_print_operation_set_print_settings (op, settings);
|
|
|
|
op_unix = g_new0 (GtkPrintOperationUnix, 1);
|
|
op_unix->job = gtk_print_job_new (priv->job_name,
|
|
printer,
|
|
settings,
|
|
page_setup);
|
|
|
|
rdata->op->priv->surface = gtk_print_job_get_surface (op_unix->job, rdata->error);
|
|
if (op->priv->surface == NULL)
|
|
{
|
|
rdata->do_print = FALSE;
|
|
op_unix_free (op_unix);
|
|
rdata->result = GTK_PRINT_OPERATION_RESULT_ERROR;
|
|
goto out;
|
|
}
|
|
|
|
_gtk_print_operation_set_status (op, gtk_print_job_get_status (op_unix->job), NULL);
|
|
op_unix->job_status_changed_tag =
|
|
g_signal_connect (op_unix->job, "status_changed",
|
|
G_CALLBACK (job_status_changed_cb), op);
|
|
|
|
op_unix->parent = rdata->parent;
|
|
|
|
priv->dpi_x = 72;
|
|
priv->dpi_y = 72;
|
|
|
|
priv->platform_data = op_unix;
|
|
priv->free_platform_data = (GDestroyNotify) op_unix_free;
|
|
|
|
priv->print_pages = op_unix->job->print_pages;
|
|
priv->page_ranges = op_unix->job->page_ranges;
|
|
priv->num_page_ranges = op_unix->job->num_page_ranges;
|
|
|
|
priv->manual_num_copies = op_unix->job->num_copies;
|
|
priv->manual_collation = op_unix->job->collate;
|
|
priv->manual_reverse = op_unix->job->reverse;
|
|
priv->manual_page_set = op_unix->job->page_set;
|
|
priv->manual_scale = op_unix->job->scale;
|
|
priv->manual_orientation = op_unix->job->rotate_to_orientation;
|
|
}
|
|
|
|
out:
|
|
if (rdata->print_cb)
|
|
{
|
|
if (rdata->do_print)
|
|
rdata->print_cb (op, FALSE);
|
|
else
|
|
_gtk_print_operation_set_status (op, GTK_PRINT_STATUS_FINISHED_ABORTED, NULL);
|
|
}
|
|
|
|
if (rdata->destroy)
|
|
rdata->destroy (rdata);
|
|
}
|
|
|
|
static void
|
|
handle_print_response (GtkWidget *dialog,
|
|
gint response,
|
|
gpointer data)
|
|
{
|
|
GtkPrintUnixDialog *pd = GTK_PRINT_UNIX_DIALOG (dialog);
|
|
PrintResponseData *rdata = data;
|
|
GtkPrintSettings *settings = NULL;
|
|
GtkPageSetup *page_setup = NULL;
|
|
GtkPrinter *printer = NULL;
|
|
|
|
if (response == GTK_RESPONSE_OK)
|
|
{
|
|
rdata->result = GTK_PRINT_OPERATION_RESULT_APPLY;
|
|
|
|
printer = gtk_print_unix_dialog_get_selected_printer (GTK_PRINT_UNIX_DIALOG (pd));
|
|
if (printer == NULL)
|
|
goto out;
|
|
|
|
rdata->do_print = TRUE;
|
|
|
|
settings = gtk_print_unix_dialog_get_settings (GTK_PRINT_UNIX_DIALOG (pd));
|
|
page_setup = gtk_print_unix_dialog_get_page_setup (GTK_PRINT_UNIX_DIALOG (pd));
|
|
}
|
|
|
|
out:
|
|
finish_print (rdata, printer, page_setup, settings);
|
|
|
|
if (settings)
|
|
g_object_unref (settings);
|
|
|
|
gtk_widget_destroy (GTK_WIDGET (pd));
|
|
}
|
|
|
|
|
|
static void
|
|
found_printer (GtkPrinter *printer,
|
|
PrintResponseData *rdata)
|
|
{
|
|
GtkPrintOperation *op = rdata->op;
|
|
GtkPrintOperationPrivate *priv = op->priv;
|
|
GtkPrintSettings *settings = NULL;
|
|
GtkPageSetup *page_setup = NULL;
|
|
|
|
if (rdata->loop)
|
|
g_main_loop_quit (rdata->loop);
|
|
|
|
if (printer != NULL) {
|
|
rdata->result = GTK_PRINT_OPERATION_RESULT_APPLY;
|
|
|
|
rdata->do_print = TRUE;
|
|
|
|
if (priv->print_settings)
|
|
settings = gtk_print_settings_copy (priv->print_settings);
|
|
else
|
|
settings = gtk_print_settings_new ();
|
|
|
|
gtk_print_settings_set_printer (settings,
|
|
gtk_printer_get_name (printer));
|
|
|
|
if (priv->default_page_setup)
|
|
page_setup = gtk_page_setup_copy (priv->default_page_setup);
|
|
else
|
|
page_setup = gtk_page_setup_new ();
|
|
}
|
|
|
|
finish_print (rdata, printer, page_setup, settings);
|
|
|
|
if (settings)
|
|
g_object_unref (settings);
|
|
|
|
if (page_setup)
|
|
g_object_unref (page_setup);
|
|
}
|
|
|
|
void
|
|
_gtk_print_operation_platform_backend_run_dialog_async (GtkPrintOperation *op,
|
|
GtkWindow *parent,
|
|
GtkPrintOperationPrintFunc print_cb)
|
|
{
|
|
GtkWidget *pd;
|
|
PrintResponseData *rdata;
|
|
const char *printer_name;
|
|
|
|
rdata = g_new (PrintResponseData, 1);
|
|
rdata->op = g_object_ref (op);
|
|
rdata->do_print = FALSE;
|
|
rdata->result = GTK_PRINT_OPERATION_RESULT_CANCEL;
|
|
rdata->error = NULL;
|
|
rdata->print_cb = print_cb;
|
|
rdata->parent = parent;
|
|
rdata->loop = NULL;
|
|
rdata->destroy = print_response_data_free;
|
|
|
|
if (op->priv->show_dialog)
|
|
{
|
|
pd = get_print_dialog (op, parent);
|
|
gtk_window_set_modal (GTK_WINDOW (pd), TRUE);
|
|
|
|
g_signal_connect (pd, "response",
|
|
G_CALLBACK (handle_print_response), rdata);
|
|
|
|
gtk_window_present (GTK_WINDOW (pd));
|
|
}
|
|
else
|
|
{
|
|
printer_name = NULL;
|
|
if (op->priv->print_settings)
|
|
printer_name = gtk_print_settings_get_printer (op->priv->print_settings);
|
|
|
|
find_printer (printer_name,
|
|
(GFunc) found_printer, rdata);
|
|
}
|
|
}
|
|
|
|
GtkPrintOperationResult
|
|
_gtk_print_operation_platform_backend_run_dialog (GtkPrintOperation *op,
|
|
GtkWindow *parent,
|
|
gboolean *do_print,
|
|
GError **error)
|
|
{
|
|
GtkWidget *pd;
|
|
PrintResponseData rdata;
|
|
gint response;
|
|
const char *printer_name;
|
|
|
|
rdata.op = op;
|
|
rdata.do_print = FALSE;
|
|
rdata.result = GTK_PRINT_OPERATION_RESULT_CANCEL;
|
|
rdata.error = error;
|
|
rdata.print_cb = NULL;
|
|
rdata.destroy = NULL;
|
|
rdata.parent = parent;
|
|
rdata.loop = NULL;
|
|
|
|
if (op->priv->show_dialog)
|
|
{
|
|
pd = get_print_dialog (op, parent);
|
|
response = gtk_dialog_run (GTK_DIALOG (pd));
|
|
handle_print_response (pd, response, &rdata);
|
|
}
|
|
else
|
|
{
|
|
printer_name = NULL;
|
|
if (op->priv->print_settings)
|
|
printer_name = gtk_print_settings_get_printer (op->priv->print_settings);
|
|
|
|
rdata.loop = g_main_loop_new (NULL, FALSE);
|
|
find_printer (printer_name,
|
|
(GFunc) found_printer, &rdata);
|
|
|
|
GDK_THREADS_LEAVE ();
|
|
g_main_loop_run (rdata.loop);
|
|
GDK_THREADS_ENTER ();
|
|
|
|
g_main_loop_unref (rdata.loop);
|
|
}
|
|
|
|
*do_print = rdata.do_print;
|
|
|
|
return rdata.result;
|
|
}
|
|
|
|
|
|
typedef struct {
|
|
GtkPageSetup *page_setup;
|
|
GtkPageSetupDoneFunc done_cb;
|
|
gpointer data;
|
|
GDestroyNotify destroy;
|
|
} PageSetupResponseData;
|
|
|
|
static void
|
|
page_setup_data_free (gpointer data)
|
|
{
|
|
PageSetupResponseData *rdata = data;
|
|
|
|
g_object_unref (rdata->page_setup);
|
|
g_free (rdata);
|
|
}
|
|
|
|
static void
|
|
handle_page_setup_response (GtkWidget *dialog,
|
|
gint response,
|
|
gpointer data)
|
|
{
|
|
GtkPageSetupUnixDialog *psd;
|
|
PageSetupResponseData *rdata = data;
|
|
|
|
psd = GTK_PAGE_SETUP_UNIX_DIALOG (dialog);
|
|
if (response == GTK_RESPONSE_OK)
|
|
rdata->page_setup = gtk_page_setup_unix_dialog_get_page_setup (psd);
|
|
|
|
gtk_widget_destroy (dialog);
|
|
|
|
if (rdata->done_cb)
|
|
rdata->done_cb (rdata->page_setup, rdata->data);
|
|
|
|
if (rdata->destroy)
|
|
rdata->destroy (rdata);
|
|
}
|
|
|
|
static GtkWidget *
|
|
get_page_setup_dialog (GtkWindow *parent,
|
|
GtkPageSetup *page_setup,
|
|
GtkPrintSettings *settings)
|
|
{
|
|
GtkWidget *dialog;
|
|
|
|
dialog = gtk_page_setup_unix_dialog_new (NULL, parent);
|
|
if (page_setup)
|
|
gtk_page_setup_unix_dialog_set_page_setup (GTK_PAGE_SETUP_UNIX_DIALOG (dialog),
|
|
page_setup);
|
|
gtk_page_setup_unix_dialog_set_print_settings (GTK_PAGE_SETUP_UNIX_DIALOG (dialog),
|
|
settings);
|
|
|
|
return dialog;
|
|
}
|
|
|
|
/**
|
|
* gtk_print_run_page_setup_dialog:
|
|
* @parent: transient parent, or %NULL
|
|
* @page_setup: an existing #GtkPageSetup, or %NULL
|
|
* @settings: a #GtkPrintSettings
|
|
*
|
|
* Runs a page setup dialog, letting the user modify the values from
|
|
* @page_setup. If the user cancels the dialog, the returned #GtkPageSetup
|
|
* is identical to the passed in @page_setup, otherwise it contains the
|
|
* modifications done in the dialog.
|
|
*
|
|
* Note that this function may use a recursive mainloop to show the page
|
|
* setup dialog. See gtk_print_run_page_setup_dialog_async() if this is
|
|
* a problem.
|
|
*
|
|
* Return value: a new #GtkPageSetup
|
|
*
|
|
* Since: 2.10
|
|
*/
|
|
GtkPageSetup *
|
|
gtk_print_run_page_setup_dialog (GtkWindow *parent,
|
|
GtkPageSetup *page_setup,
|
|
GtkPrintSettings *settings)
|
|
{
|
|
GtkWidget *dialog;
|
|
gint response;
|
|
PageSetupResponseData rdata;
|
|
|
|
rdata.page_setup = NULL;
|
|
rdata.done_cb = NULL;
|
|
rdata.data = NULL;
|
|
rdata.destroy = NULL;
|
|
|
|
dialog = get_page_setup_dialog (parent, page_setup, settings);
|
|
response = gtk_dialog_run (GTK_DIALOG (dialog));
|
|
handle_page_setup_response (dialog, response, &rdata);
|
|
|
|
if (rdata.page_setup)
|
|
return rdata.page_setup;
|
|
else if (page_setup)
|
|
return gtk_page_setup_copy (page_setup);
|
|
else
|
|
return gtk_page_setup_new ();
|
|
}
|
|
|
|
/**
|
|
* gtk_print_run_page_setup_dialog_async:
|
|
* @parent: transient parent, or %NULL
|
|
* @page_setup: an existing #GtkPageSetup, or %NULL
|
|
* @settings: a #GtkPrintSettings
|
|
* @done_cb: a function to call when the user saves the modified page setup
|
|
* @data: user data to pass to @done_cb
|
|
*
|
|
* Runs a page setup dialog, letting the user modify the values from @page_setup.
|
|
*
|
|
* In contrast to gtk_print_run_page_setup_dialog(), this function returns after
|
|
* showing the page setup dialog on platforms that support this, and calls @done_cb
|
|
* from a signal handler for the ::response signal of the dialog.
|
|
*
|
|
* Since: 2.10
|
|
*/
|
|
void
|
|
gtk_print_run_page_setup_dialog_async (GtkWindow *parent,
|
|
GtkPageSetup *page_setup,
|
|
GtkPrintSettings *settings,
|
|
GtkPageSetupDoneFunc done_cb,
|
|
gpointer data)
|
|
{
|
|
GtkWidget *dialog;
|
|
PageSetupResponseData *rdata;
|
|
|
|
dialog = get_page_setup_dialog (parent, page_setup, settings);
|
|
gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
|
|
|
|
rdata = g_new (PageSetupResponseData, 1);
|
|
rdata->page_setup = NULL;
|
|
rdata->done_cb = done_cb;
|
|
rdata->data = data;
|
|
rdata->destroy = page_setup_data_free;
|
|
|
|
g_signal_connect (dialog, "response",
|
|
G_CALLBACK (handle_page_setup_response), rdata);
|
|
|
|
gtk_window_present (GTK_WINDOW (dialog));
|
|
}
|
|
|
|
struct _PrinterFinder {
|
|
gboolean found_printer;
|
|
GFunc func;
|
|
gpointer data;
|
|
char *printer_name;
|
|
GList *backends;
|
|
guint timeout_tag;
|
|
GtkPrinter *printer;
|
|
GtkPrinter *default_printer;
|
|
GtkPrinter *first_printer;
|
|
};
|
|
|
|
static gboolean
|
|
find_printer_idle (gpointer data)
|
|
{
|
|
PrinterFinder *finder = data;
|
|
GtkPrinter *printer;
|
|
|
|
if (finder->printer != NULL)
|
|
printer = finder->printer;
|
|
else if (finder->default_printer != NULL)
|
|
printer = finder->default_printer;
|
|
else if (finder->first_printer != NULL)
|
|
printer = finder->first_printer;
|
|
else
|
|
printer = NULL;
|
|
|
|
finder->func (printer, finder->data);
|
|
|
|
printer_finder_free (finder);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static void
|
|
printer_added_cb (GtkPrintBackend *backend,
|
|
GtkPrinter *printer,
|
|
PrinterFinder *finder)
|
|
{
|
|
if (gtk_printer_is_virtual (printer) ||
|
|
finder->found_printer)
|
|
return;
|
|
|
|
if (finder->printer_name != NULL &&
|
|
strcmp (gtk_printer_get_name (printer), finder->printer_name) == 0)
|
|
{
|
|
finder->printer = g_object_ref (printer);
|
|
finder->found_printer = TRUE;
|
|
}
|
|
else if (finder->default_printer == NULL &&
|
|
gtk_printer_is_default (printer))
|
|
{
|
|
finder->default_printer = g_object_ref (printer);
|
|
if (finder->printer_name == NULL)
|
|
finder->found_printer = TRUE;
|
|
}
|
|
else
|
|
if (finder->first_printer == NULL)
|
|
finder->first_printer = g_object_ref (printer);
|
|
|
|
if (finder->found_printer)
|
|
g_idle_add (find_printer_idle, finder);
|
|
}
|
|
|
|
static void
|
|
printer_list_done_cb (GtkPrintBackend *backend,
|
|
PrinterFinder *finder)
|
|
{
|
|
finder->backends = g_list_remove (finder->backends, backend);
|
|
|
|
g_signal_handlers_disconnect_by_func (backend, printer_added_cb, finder);
|
|
g_signal_handlers_disconnect_by_func (backend, printer_list_done_cb, finder);
|
|
|
|
gtk_print_backend_destroy (backend);
|
|
g_object_unref (backend);
|
|
|
|
if (finder->backends == NULL && !finder->found_printer)
|
|
g_idle_add (find_printer_idle, finder);
|
|
}
|
|
|
|
static void
|
|
find_printer_init (PrinterFinder *finder,
|
|
GtkPrintBackend *backend)
|
|
{
|
|
GList *list;
|
|
GList *node;
|
|
|
|
list = gtk_print_backend_get_printer_list (backend);
|
|
|
|
node = list;
|
|
while (node != NULL)
|
|
{
|
|
printer_added_cb (backend, node->data, finder);
|
|
node = node->next;
|
|
|
|
if (finder->found_printer)
|
|
break;
|
|
}
|
|
|
|
g_list_free (list);
|
|
|
|
if (gtk_print_backend_printer_list_is_done (backend))
|
|
{
|
|
finder->backends = g_list_remove (finder->backends, backend);
|
|
gtk_print_backend_destroy (backend);
|
|
g_object_unref (backend);
|
|
}
|
|
else
|
|
{
|
|
g_signal_connect (backend,
|
|
"printer-added",
|
|
(GCallback) printer_added_cb,
|
|
finder);
|
|
g_signal_connect (backend,
|
|
"printer-list-done",
|
|
(GCallback) printer_list_done_cb,
|
|
finder);
|
|
}
|
|
|
|
}
|
|
|
|
static void
|
|
printer_finder_free (PrinterFinder *finder)
|
|
{
|
|
GList *l;
|
|
|
|
g_free (finder->printer_name);
|
|
|
|
if (finder->printer)
|
|
g_object_unref (finder->printer);
|
|
|
|
if (finder->default_printer)
|
|
g_object_unref (finder->default_printer);
|
|
|
|
if (finder->first_printer)
|
|
g_object_unref (finder->first_printer);
|
|
|
|
for (l = finder->backends; l != NULL; l = l->next)
|
|
{
|
|
GtkPrintBackend *backend = l->data;
|
|
g_signal_handlers_disconnect_by_func (backend, printer_added_cb, finder);
|
|
g_signal_handlers_disconnect_by_func (backend, printer_list_done_cb, finder);
|
|
gtk_print_backend_destroy (backend);
|
|
g_object_unref (backend);
|
|
}
|
|
|
|
g_list_free (finder->backends);
|
|
|
|
g_free (finder);
|
|
}
|
|
|
|
static void
|
|
find_printer (const char *printer,
|
|
GFunc func,
|
|
gpointer data)
|
|
{
|
|
GList *node, *next;
|
|
PrinterFinder *finder;
|
|
|
|
finder = g_new0 (PrinterFinder, 1);
|
|
|
|
finder->printer_name = g_strdup (printer);
|
|
finder->func = func;
|
|
finder->data = data;
|
|
|
|
finder->backends = NULL;
|
|
if (g_module_supported ())
|
|
finder->backends = gtk_print_backend_load_modules ();
|
|
|
|
for (node = finder->backends; !finder->found_printer && node != NULL; node = next)
|
|
{
|
|
next = node->next;
|
|
find_printer_init (finder, GTK_PRINT_BACKEND (node->data));
|
|
}
|
|
|
|
if (finder->backends == NULL && !finder->found_printer)
|
|
g_idle_add (find_printer_idle, finder);
|
|
}
|
|
|
|
#define __GTK_PRINT_OPERATION_UNIX_C__
|
|
#include "gtkaliasdef.c"
|