printers: Allow users to change printer's PPD file
This commit adds popup window which when activated allows user to select PPD from local database of installed PPDs, select directly PPD from filesystem or select one from 3 recommended PPDs (#678637). The popup is activated by clicking on model field (the panel has to be unlocked). It starts to search for the best PPDs available immediately after its popup. All operations are asynchronous.
This commit is contained in:
parent
1b3e877ef2
commit
dd7479caea
8 changed files with 3119 additions and 33 deletions
|
@ -3,6 +3,7 @@ cappletname = printers
|
|||
uidir = $(pkgdatadir)/ui/printers
|
||||
dist_ui_DATA = \
|
||||
new-printer-dialog.ui \
|
||||
ppd-selection-dialog.ui \
|
||||
printers.ui
|
||||
|
||||
INCLUDES = \
|
||||
|
@ -18,12 +19,14 @@ ccpanelsdir = $(PANELS_DIR)
|
|||
ccpanels_LTLIBRARIES = libprinters.la
|
||||
|
||||
libprinters_la_SOURCES = \
|
||||
printers-module.c \
|
||||
pp-utils.c \
|
||||
pp-utils.h \
|
||||
pp-new-printer-dialog.c \
|
||||
pp-new-printer-dialog.h \
|
||||
cc-printers-panel.c \
|
||||
printers-module.c \
|
||||
pp-utils.c \
|
||||
pp-utils.h \
|
||||
pp-new-printer-dialog.c \
|
||||
pp-new-printer-dialog.h \
|
||||
pp-ppd-selection-dialog.c \
|
||||
pp-ppd-selection-dialog.h \
|
||||
cc-printers-panel.c \
|
||||
cc-printers-panel.h
|
||||
|
||||
libprinters_la_LIBADD = $(PRINTERS_PANEL_LIBS) $(PANEL_LIBS) $(CUPS_LIBS)
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
|
||||
#include "cc-editable-entry.h"
|
||||
#include "pp-new-printer-dialog.h"
|
||||
#include "pp-ppd-selection-dialog.h"
|
||||
#include "pp-utils.h"
|
||||
|
||||
G_DEFINE_DYNAMIC_TYPE (CcPrintersPanel, cc_printers_panel, CC_TYPE_PANEL)
|
||||
|
@ -83,6 +84,7 @@ struct _CcPrintersPanelPrivate
|
|||
GSettings *lockdown_settings;
|
||||
|
||||
PpNewPrinterDialog *pp_new_printer_dialog;
|
||||
PpPPDSelectionDialog *pp_ppd_selection_dialog;
|
||||
|
||||
GDBusProxy *cups_proxy;
|
||||
GDBusConnection *cups_bus_connection;
|
||||
|
@ -91,13 +93,21 @@ struct _CcPrintersPanelPrivate
|
|||
guint cups_status_check_id;
|
||||
guint dbus_subscription_id;
|
||||
|
||||
GtkWidget *popup_menu;
|
||||
GList *driver_change_list;
|
||||
GCancellable *get_ppd_name_cancellable;
|
||||
gboolean getting_ppd_names;
|
||||
PPDList *all_ppds_list;
|
||||
GHashTable *preferred_drivers;
|
||||
gboolean getting_all_ppds;
|
||||
|
||||
gpointer dummy;
|
||||
};
|
||||
|
||||
static void actualize_jobs_list (CcPrintersPanel *self);
|
||||
static void actualize_printers_list (CcPrintersPanel *self);
|
||||
static void actualize_allowed_users_list (CcPrintersPanel *self);
|
||||
static void actualize_sensitivity (gpointer user_data);
|
||||
static void update_sensitivity (gpointer user_data);
|
||||
static void printer_disable_cb (GObject *gobject, GParamSpec *pspec, gpointer user_data);
|
||||
static void printer_set_default_cb (GtkToggleButton *button, gpointer user_data);
|
||||
static void detach_from_cups_notifier (gpointer data);
|
||||
|
@ -180,7 +190,22 @@ cc_printers_panel_dispose (GObject *object)
|
|||
detach_from_cups_notifier (CC_PRINTERS_PANEL (object));
|
||||
|
||||
if (priv->cups_status_check_id > 0)
|
||||
g_source_remove (priv->cups_status_check_id);
|
||||
{
|
||||
g_source_remove (priv->cups_status_check_id);
|
||||
priv->cups_status_check_id = 0;
|
||||
}
|
||||
|
||||
if (priv->all_ppds_list)
|
||||
{
|
||||
ppd_list_free (priv->all_ppds_list);
|
||||
priv->all_ppds_list = NULL;
|
||||
}
|
||||
|
||||
if (priv->preferred_drivers)
|
||||
{
|
||||
g_hash_table_unref (priv->preferred_drivers);
|
||||
priv->preferred_drivers = NULL;
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (cc_printers_panel_parent_class)->dispose (object);
|
||||
}
|
||||
|
@ -502,6 +527,8 @@ printer_selection_changed_cb (GtkTreeSelection *selection,
|
|||
cups_ptype_t type = 0;
|
||||
GtkTreeIter iter;
|
||||
GtkWidget *widget;
|
||||
GtkWidget *model_button;
|
||||
GtkWidget *model_label;
|
||||
gboolean sensitive;
|
||||
GValue value = G_VALUE_INIT;
|
||||
gchar *printer_make_and_model = NULL;
|
||||
|
@ -814,16 +841,23 @@ printer_selection_changed_cb (GtkTreeSelection *selection,
|
|||
cc_editable_entry_set_text (CC_EDITABLE_ENTRY (widget), EMPTY_TEXT);
|
||||
|
||||
|
||||
widget = (GtkWidget*)
|
||||
model_button = (GtkWidget*)
|
||||
gtk_builder_get_object (priv->builder, "printer-model-button");
|
||||
|
||||
model_label = (GtkWidget*)
|
||||
gtk_builder_get_object (priv->builder, "printer-model-label");
|
||||
|
||||
if (printer_model)
|
||||
{
|
||||
cc_editable_entry_set_text (CC_EDITABLE_ENTRY (widget), 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
|
||||
cc_editable_entry_set_text (CC_EDITABLE_ENTRY (widget), EMPTY_TEXT);
|
||||
{
|
||||
gtk_button_set_label (GTK_BUTTON (model_button), EMPTY_TEXT);
|
||||
gtk_label_set_text (GTK_LABEL (model_label), EMPTY_TEXT);
|
||||
}
|
||||
|
||||
|
||||
widget = (GtkWidget*)
|
||||
|
@ -917,9 +951,13 @@ printer_selection_changed_cb (GtkTreeSelection *selection,
|
|||
gtk_builder_get_object (priv->builder, "printer-location-label");
|
||||
cc_editable_entry_set_text (CC_EDITABLE_ENTRY (widget), "");
|
||||
|
||||
widget = (GtkWidget*)
|
||||
gtk_builder_get_object (priv->builder, "printer-model-button");
|
||||
gtk_button_set_label (GTK_BUTTON (widget), "");
|
||||
|
||||
widget = (GtkWidget*)
|
||||
gtk_builder_get_object (priv->builder, "printer-model-label");
|
||||
cc_editable_entry_set_text (CC_EDITABLE_ENTRY (widget), "");
|
||||
gtk_label_set_text (GTK_LABEL (widget), "");
|
||||
|
||||
widget = (GtkWidget*)
|
||||
gtk_builder_get_object (priv->builder, "printer-ip-address-label");
|
||||
|
@ -930,7 +968,7 @@ printer_selection_changed_cb (GtkTreeSelection *selection,
|
|||
cc_editable_entry_set_text (CC_EDITABLE_ENTRY (widget), "");
|
||||
}
|
||||
|
||||
actualize_sensitivity (self);
|
||||
update_sensitivity (self);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1157,7 +1195,7 @@ actualize_printers_list (CcPrintersPanel *self)
|
|||
g_free (current_printer_instance);
|
||||
g_object_unref (store);
|
||||
|
||||
actualize_sensitivity (self);
|
||||
update_sensitivity (self);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -2179,6 +2217,475 @@ printer_location_edit_cb (GtkWidget *entry,
|
|||
actualize_printers_list (self);
|
||||
}
|
||||
|
||||
static void
|
||||
set_ppd_cb (gchar *printer_name,
|
||||
gboolean success,
|
||||
gpointer user_data)
|
||||
{
|
||||
CcPrintersPanelPrivate *priv;
|
||||
CcPrintersPanel *self = (CcPrintersPanel*) user_data;
|
||||
GList *iter;
|
||||
|
||||
priv = PRINTERS_PANEL_PRIVATE (self);
|
||||
|
||||
for (iter = priv->driver_change_list; iter; iter = iter->next)
|
||||
{
|
||||
if (g_strcmp0 ((gchar *) iter->data, printer_name) == 0)
|
||||
{
|
||||
priv->driver_change_list = g_list_remove_link (priv->driver_change_list, iter);
|
||||
g_list_free_full (iter, g_free);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
update_sensitivity (self);
|
||||
|
||||
if (success)
|
||||
{
|
||||
actualize_printers_list (self);
|
||||
}
|
||||
|
||||
g_free (printer_name);
|
||||
}
|
||||
|
||||
static void
|
||||
select_ppd_manually (GtkMenuItem *menuitem,
|
||||
gpointer user_data)
|
||||
{
|
||||
CcPrintersPanelPrivate *priv;
|
||||
CcPrintersPanel *self = (CcPrintersPanel*) user_data;
|
||||
GtkFileFilter *filter;
|
||||
GtkWidget *dialog;
|
||||
gchar *printer_name = NULL;
|
||||
|
||||
priv = PRINTERS_PANEL_PRIVATE (self);
|
||||
|
||||
gtk_menu_shell_cancel (GTK_MENU_SHELL (priv->popup_menu));
|
||||
|
||||
dialog = gtk_file_chooser_dialog_new (_("Select PPD File"),
|
||||
NULL,
|
||||
GTK_FILE_CHOOSER_ACTION_OPEN,
|
||||
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
|
||||
GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
|
||||
NULL);
|
||||
|
||||
filter = gtk_file_filter_new ();
|
||||
gtk_file_filter_set_name (filter,
|
||||
_("PostScript Printer Description files (*.ppd, *.PPD, *.ppd.gz, *.PPD.gz, *.PPD.GZ)"));
|
||||
gtk_file_filter_add_pattern (filter, "*.ppd");
|
||||
gtk_file_filter_add_pattern (filter, "*.PPD");
|
||||
gtk_file_filter_add_pattern (filter, "*.ppd.gz");
|
||||
gtk_file_filter_add_pattern (filter, "*.PPD.gz");
|
||||
gtk_file_filter_add_pattern (filter, "*.PPD.GZ");
|
||||
|
||||
gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (dialog), filter);
|
||||
|
||||
if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
|
||||
{
|
||||
gchar *ppd_filename;
|
||||
|
||||
ppd_filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
|
||||
|
||||
if (priv->current_dest >= 0 &&
|
||||
priv->current_dest < priv->num_dests &&
|
||||
priv->dests != NULL)
|
||||
printer_name = priv->dests[priv->current_dest].name;
|
||||
|
||||
if (printer_name && ppd_filename)
|
||||
{
|
||||
priv->driver_change_list =
|
||||
g_list_prepend (priv->driver_change_list, g_strdup (printer_name));
|
||||
update_sensitivity (self);
|
||||
printer_set_ppd_file_async (printer_name,
|
||||
ppd_filename,
|
||||
NULL,
|
||||
set_ppd_cb,
|
||||
user_data);
|
||||
}
|
||||
|
||||
g_free (ppd_filename);
|
||||
}
|
||||
|
||||
gtk_widget_destroy (dialog);
|
||||
}
|
||||
|
||||
static void
|
||||
ppd_selection_dialog_response_cb (GtkDialog *dialog,
|
||||
gint response_id,
|
||||
gpointer user_data)
|
||||
{
|
||||
CcPrintersPanelPrivate *priv;
|
||||
CcPrintersPanel *self = (CcPrintersPanel*) user_data;
|
||||
gchar *printer_name = NULL;
|
||||
|
||||
priv = PRINTERS_PANEL_PRIVATE (self);
|
||||
|
||||
if (response_id == GTK_RESPONSE_OK)
|
||||
{
|
||||
gchar *ppd_name;
|
||||
|
||||
ppd_name = pp_ppd_selection_dialog_get_ppd_name (priv->pp_ppd_selection_dialog);
|
||||
|
||||
if (priv->current_dest >= 0 &&
|
||||
priv->current_dest < priv->num_dests &&
|
||||
priv->dests != NULL)
|
||||
printer_name = priv->dests[priv->current_dest].name;
|
||||
|
||||
if (printer_name && ppd_name)
|
||||
{
|
||||
priv->driver_change_list = g_list_prepend (priv->driver_change_list,
|
||||
g_strdup (printer_name));
|
||||
update_sensitivity (self);
|
||||
printer_set_ppd_async (printer_name,
|
||||
ppd_name,
|
||||
NULL,
|
||||
set_ppd_cb,
|
||||
user_data);
|
||||
}
|
||||
|
||||
g_free (ppd_name);
|
||||
}
|
||||
|
||||
pp_ppd_selection_dialog_free (priv->pp_ppd_selection_dialog);
|
||||
priv->pp_ppd_selection_dialog = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
select_ppd_in_dialog (GtkMenuItem *menuitem,
|
||||
gpointer user_data)
|
||||
{
|
||||
CcPrintersPanelPrivate *priv;
|
||||
CcPrintersPanel *self = (CcPrintersPanel*) user_data;
|
||||
GtkWidget *widget;
|
||||
gchar *device_id = NULL;
|
||||
gchar *manufacturer = NULL;
|
||||
|
||||
priv = PRINTERS_PANEL_PRIVATE (self);
|
||||
|
||||
widget = (GtkWidget*)
|
||||
gtk_builder_get_object (priv->builder, "main-vbox");
|
||||
|
||||
if (!priv->pp_ppd_selection_dialog)
|
||||
{
|
||||
if (priv->current_dest >= 0 &&
|
||||
priv->current_dest < priv->num_dests)
|
||||
{
|
||||
device_id =
|
||||
get_ppd_attribute (priv->ppd_file_names[priv->current_dest],
|
||||
"1284DeviceID");
|
||||
|
||||
if (device_id)
|
||||
{
|
||||
manufacturer = get_tag_value (device_id, "mfg");
|
||||
if (!manufacturer)
|
||||
manufacturer = get_tag_value (device_id, "manufacturer");
|
||||
}
|
||||
else
|
||||
{
|
||||
manufacturer =
|
||||
get_ppd_attribute (priv->ppd_file_names[priv->current_dest],
|
||||
"Manufacturer");
|
||||
}
|
||||
}
|
||||
|
||||
priv->pp_ppd_selection_dialog = pp_ppd_selection_dialog_new (
|
||||
GTK_WINDOW (gtk_widget_get_toplevel (widget)),
|
||||
priv->all_ppds_list,
|
||||
manufacturer,
|
||||
ppd_selection_dialog_response_cb,
|
||||
self);
|
||||
|
||||
g_free (manufacturer);
|
||||
g_free (device_id);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
set_ppd_from_list (GtkMenuItem *menuitem,
|
||||
gpointer user_data)
|
||||
{
|
||||
CcPrintersPanelPrivate *priv;
|
||||
CcPrintersPanel *self = (CcPrintersPanel*) user_data;
|
||||
gchar *printer_name = NULL;
|
||||
gchar *ppd_name;
|
||||
|
||||
priv = PRINTERS_PANEL_PRIVATE (self);
|
||||
|
||||
ppd_name = (gchar *) g_object_get_data (G_OBJECT (menuitem), "ppd-name");
|
||||
|
||||
if (priv->current_dest >= 0 &&
|
||||
priv->current_dest < priv->num_dests &&
|
||||
priv->dests != NULL)
|
||||
printer_name = priv->dests[priv->current_dest].name;
|
||||
|
||||
if (printer_name && ppd_name)
|
||||
{
|
||||
priv->driver_change_list = g_list_prepend (priv->driver_change_list,
|
||||
g_strdup (printer_name));
|
||||
update_sensitivity (self);
|
||||
printer_set_ppd_async (printer_name,
|
||||
ppd_name,
|
||||
NULL,
|
||||
set_ppd_cb,
|
||||
user_data);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ppd_names_free (gpointer user_data)
|
||||
{
|
||||
PPDName **names = (PPDName **) user_data;
|
||||
gint i;
|
||||
|
||||
if (names)
|
||||
{
|
||||
for (i = 0; names[i]; i++)
|
||||
{
|
||||
g_free (names[i]->ppd_name);
|
||||
g_free (names[i]->ppd_display_name);
|
||||
g_free (names[i]);
|
||||
}
|
||||
|
||||
g_free (names);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
get_ppd_names_cb (PPDName **names,
|
||||
const gchar *printer_name,
|
||||
gboolean cancelled,
|
||||
gpointer user_data)
|
||||
{
|
||||
CcPrintersPanelPrivate *priv;
|
||||
CcPrintersPanel *self = (CcPrintersPanel*) user_data;
|
||||
GtkWidget *informal = NULL;
|
||||
GtkWidget *placeholders[3];
|
||||
GtkWidget *spinner;
|
||||
gpointer value = NULL;
|
||||
gboolean found = FALSE;
|
||||
PPDName **hash_names = NULL;
|
||||
GList *children, *iter;
|
||||
gint i;
|
||||
|
||||
priv = PRINTERS_PANEL_PRIVATE (self);
|
||||
|
||||
priv->getting_ppd_names = FALSE;
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
placeholders[i] = NULL;
|
||||
|
||||
children = gtk_container_get_children (GTK_CONTAINER (priv->popup_menu));
|
||||
if (children)
|
||||
{
|
||||
for (iter = children; iter; iter = iter->next)
|
||||
{
|
||||
if (g_strcmp0 ((gchar *) g_object_get_data (G_OBJECT (iter->data), "purpose"),
|
||||
"informal") == 0)
|
||||
informal = GTK_WIDGET (iter->data);
|
||||
else if (g_strcmp0 ((gchar *) g_object_get_data (G_OBJECT (iter->data), "purpose"),
|
||||
"placeholder1") == 0)
|
||||
placeholders[0] = GTK_WIDGET (iter->data);
|
||||
else if (g_strcmp0 ((gchar *) g_object_get_data (G_OBJECT (iter->data), "purpose"),
|
||||
"placeholder2") == 0)
|
||||
placeholders[1] = GTK_WIDGET (iter->data);
|
||||
else if (g_strcmp0 ((gchar *) g_object_get_data (G_OBJECT (iter->data), "purpose"),
|
||||
"placeholder3") == 0)
|
||||
placeholders[2] = GTK_WIDGET (iter->data);
|
||||
}
|
||||
|
||||
g_list_free (children);
|
||||
}
|
||||
|
||||
if (!priv->preferred_drivers)
|
||||
{
|
||||
priv->preferred_drivers = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||
g_free, ppd_names_free);
|
||||
}
|
||||
|
||||
if (!cancelled &&
|
||||
!g_hash_table_lookup_extended (priv->preferred_drivers,
|
||||
printer_name, NULL, NULL))
|
||||
g_hash_table_insert (priv->preferred_drivers, g_strdup (printer_name), names);
|
||||
|
||||
if (priv->preferred_drivers &&
|
||||
g_hash_table_lookup_extended (priv->preferred_drivers,
|
||||
printer_name, NULL, &value))
|
||||
{
|
||||
hash_names = (PPDName **) value;
|
||||
if (hash_names)
|
||||
{
|
||||
for (i = 0; hash_names[i]; i++)
|
||||
{
|
||||
if (placeholders[i])
|
||||
{
|
||||
gtk_menu_item_set_label (GTK_MENU_ITEM (placeholders[i]),
|
||||
hash_names[i]->ppd_display_name);
|
||||
g_object_set_data_full (G_OBJECT (placeholders[i]),
|
||||
"ppd-name",
|
||||
g_strdup (hash_names[i]->ppd_name),
|
||||
g_free);
|
||||
g_signal_connect (placeholders[i],
|
||||
"activate",
|
||||
G_CALLBACK (set_ppd_from_list),
|
||||
self);
|
||||
gtk_widget_set_sensitive (GTK_WIDGET (placeholders[i]), TRUE);
|
||||
gtk_widget_show (placeholders[i]);
|
||||
}
|
||||
}
|
||||
|
||||
found = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
found = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (informal)
|
||||
{
|
||||
gtk_image_menu_item_set_always_show_image (GTK_IMAGE_MENU_ITEM (informal), FALSE);
|
||||
|
||||
spinner = gtk_image_menu_item_get_image (GTK_IMAGE_MENU_ITEM (informal));
|
||||
if (spinner)
|
||||
gtk_spinner_stop (GTK_SPINNER (spinner));
|
||||
|
||||
if (found)
|
||||
gtk_widget_hide (informal);
|
||||
else
|
||||
gtk_menu_item_set_label (GTK_MENU_ITEM (informal), _("No suitable driver found"));
|
||||
}
|
||||
|
||||
gtk_widget_show_all (priv->popup_menu);
|
||||
|
||||
update_sensitivity (self);
|
||||
}
|
||||
|
||||
static void
|
||||
popup_menu_done (GtkMenuShell *menushell,
|
||||
gpointer user_data)
|
||||
{
|
||||
CcPrintersPanelPrivate *priv;
|
||||
CcPrintersPanel *self = (CcPrintersPanel*) user_data;
|
||||
|
||||
priv = PRINTERS_PANEL_PRIVATE (self);
|
||||
|
||||
if (priv->get_ppd_name_cancellable)
|
||||
{
|
||||
g_cancellable_cancel (priv->get_ppd_name_cancellable);
|
||||
g_object_unref (priv->get_ppd_name_cancellable);
|
||||
priv->get_ppd_name_cancellable = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
popup_model_menu_cb (GtkButton *button,
|
||||
gpointer user_data)
|
||||
{
|
||||
CcPrintersPanelPrivate *priv;
|
||||
CcPrintersPanel *self = (CcPrintersPanel*) user_data;
|
||||
GtkWidget *spinner;
|
||||
GtkWidget *item;
|
||||
|
||||
priv = PRINTERS_PANEL_PRIVATE (self);
|
||||
|
||||
priv->popup_menu = gtk_menu_new ();
|
||||
g_signal_connect (priv->popup_menu,
|
||||
"selection-done",
|
||||
G_CALLBACK (popup_menu_done),
|
||||
user_data);
|
||||
|
||||
/*
|
||||
* These placeholders are a workaround for a situation
|
||||
* when we want to actually append new menu item in a callback.
|
||||
* But unfortunately it is not possible to connect to "activate"
|
||||
* signal of such menu item (appended after gtk_menu_popup()).
|
||||
*/
|
||||
item = gtk_image_menu_item_new_with_label ("");
|
||||
g_object_set_data_full (G_OBJECT (item), "purpose",
|
||||
g_strdup ("placeholder1"), g_free);
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (priv->popup_menu), item);
|
||||
gtk_widget_set_no_show_all (item, TRUE);
|
||||
gtk_widget_hide (item);
|
||||
|
||||
item = gtk_image_menu_item_new_with_label ("");
|
||||
g_object_set_data_full (G_OBJECT (item), "purpose",
|
||||
g_strdup ("placeholder2"), g_free);
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (priv->popup_menu), item);
|
||||
gtk_widget_set_no_show_all (item, TRUE);
|
||||
gtk_widget_hide (item);
|
||||
|
||||
item = gtk_image_menu_item_new_with_label ("");
|
||||
g_object_set_data_full (G_OBJECT (item), "purpose",
|
||||
g_strdup ("placeholder3"), g_free);
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (priv->popup_menu), item);
|
||||
gtk_widget_set_no_show_all (item, TRUE);
|
||||
gtk_widget_hide (item);
|
||||
|
||||
item = gtk_image_menu_item_new_with_label (_("Searching for preferred drivers..."));
|
||||
spinner = gtk_spinner_new ();
|
||||
gtk_spinner_start (GTK_SPINNER (spinner));
|
||||
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), spinner);
|
||||
gtk_image_menu_item_set_always_show_image (GTK_IMAGE_MENU_ITEM (item), TRUE);
|
||||
g_object_set_data_full (G_OBJECT (item), "purpose",
|
||||
g_strdup ("informal"), g_free);
|
||||
gtk_widget_set_sensitive (item, FALSE);
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (priv->popup_menu), item);
|
||||
gtk_widget_set_no_show_all (item, TRUE);
|
||||
gtk_widget_show (item);
|
||||
|
||||
item = gtk_separator_menu_item_new ();
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (priv->popup_menu), item);
|
||||
|
||||
item = gtk_menu_item_new_with_label (_("Select from database..."));
|
||||
g_object_set_data_full (G_OBJECT (item), "purpose",
|
||||
g_strdup ("ppd-select"), g_free);
|
||||
g_signal_connect (item, "activate", G_CALLBACK (select_ppd_in_dialog), self);
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (priv->popup_menu), item);
|
||||
|
||||
item = gtk_separator_menu_item_new ();
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (priv->popup_menu), item);
|
||||
|
||||
item = gtk_menu_item_new_with_label (_("Provide PPD File..."));
|
||||
g_object_set_data_full (G_OBJECT (item), "purpose",
|
||||
g_strdup ("ppdfile-select"), g_free);
|
||||
g_signal_connect (item, "activate", G_CALLBACK (select_ppd_manually), self);
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (priv->popup_menu), item);
|
||||
|
||||
gtk_widget_show_all (priv->popup_menu);
|
||||
|
||||
gtk_menu_popup (GTK_MENU (priv->popup_menu),
|
||||
NULL, NULL, NULL, NULL, 0,
|
||||
gtk_get_current_event_time());
|
||||
|
||||
if (priv->current_dest >= 0 &&
|
||||
priv->current_dest < priv->num_dests &&
|
||||
priv->dests != NULL)
|
||||
{
|
||||
if (priv->preferred_drivers &&
|
||||
g_hash_table_lookup_extended (priv->preferred_drivers,
|
||||
priv->dests[priv->current_dest].name,
|
||||
NULL, NULL))
|
||||
{
|
||||
get_ppd_names_cb (NULL,
|
||||
priv->dests[priv->current_dest].name,
|
||||
FALSE,
|
||||
user_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
priv->get_ppd_name_cancellable = g_cancellable_new ();
|
||||
priv->getting_ppd_names = TRUE;
|
||||
get_ppd_names_async (priv->dests[priv->current_dest].name,
|
||||
3,
|
||||
priv->get_ppd_name_cancellable,
|
||||
get_ppd_names_cb,
|
||||
user_data);
|
||||
|
||||
update_sensitivity (self);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
test_page_cb (GtkButton *button,
|
||||
gpointer user_data)
|
||||
|
@ -2303,7 +2810,7 @@ test_page_cb (GtkButton *button,
|
|||
}
|
||||
|
||||
static void
|
||||
actualize_sensitivity (gpointer user_data)
|
||||
update_sensitivity (gpointer user_data)
|
||||
{
|
||||
CcPrintersPanelPrivate *priv;
|
||||
CcPrintersPanel *self = (CcPrintersPanel*) user_data;
|
||||
|
@ -2312,9 +2819,12 @@ actualize_sensitivity (gpointer user_data)
|
|||
GtkWidget *widget;
|
||||
gboolean is_authorized;
|
||||
gboolean is_discovered = FALSE;
|
||||
gboolean is_class = FALSE;
|
||||
gboolean is_changing_driver = FALSE;
|
||||
gboolean printer_selected;
|
||||
gboolean local_server = TRUE;
|
||||
gboolean no_cups = FALSE;
|
||||
GList *iter;
|
||||
gint i;
|
||||
|
||||
priv = PRINTERS_PANEL_PRIVATE (self);
|
||||
|
@ -2330,15 +2840,26 @@ actualize_sensitivity (gpointer user_data)
|
|||
priv->dests != NULL;
|
||||
|
||||
if (printer_selected)
|
||||
for (i = 0; i < priv->dests[priv->current_dest].num_options; i++)
|
||||
{
|
||||
if (g_strcmp0 (priv->dests[priv->current_dest].options[i].name, "printer-type") == 0)
|
||||
{
|
||||
type = atoi (priv->dests[priv->current_dest].options[i].value);
|
||||
is_discovered = type & CUPS_PRINTER_DISCOVERED;
|
||||
break;
|
||||
}
|
||||
}
|
||||
{
|
||||
for (i = 0; i < priv->dests[priv->current_dest].num_options; i++)
|
||||
{
|
||||
if (g_strcmp0 (priv->dests[priv->current_dest].options[i].name, "printer-type") == 0)
|
||||
{
|
||||
type = atoi (priv->dests[priv->current_dest].options[i].value);
|
||||
is_discovered = type & CUPS_PRINTER_DISCOVERED;
|
||||
is_class = type & CUPS_PRINTER_CLASS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (iter = priv->driver_change_list; iter; iter = iter->next)
|
||||
{
|
||||
if (g_strcmp0 ((gchar *) iter->data, priv->dests[priv->current_dest].name) == 0)
|
||||
{
|
||||
is_changing_driver = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cups_server = cupsServer ();
|
||||
if (cups_server &&
|
||||
|
@ -2390,6 +2911,19 @@ actualize_sensitivity (gpointer user_data)
|
|||
|
||||
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);
|
||||
|
||||
widget = (GtkWidget*) gtk_builder_get_object (priv->builder, "printer-model-notebook");
|
||||
if (is_changing_driver)
|
||||
{
|
||||
gtk_notebook_set_current_page (GTK_NOTEBOOK (widget), 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (local_server && !is_discovered && is_authorized && !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);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -2397,7 +2931,7 @@ on_permission_changed (GPermission *permission,
|
|||
GParamSpec *pspec,
|
||||
gpointer data)
|
||||
{
|
||||
actualize_sensitivity (data);
|
||||
update_sensitivity (data);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -2490,6 +3024,56 @@ cups_status_check (gpointer user_data)
|
|||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
get_all_ppds_async_cb (PPDList *ppds,
|
||||
gpointer user_data)
|
||||
{
|
||||
CcPrintersPanelPrivate *priv;
|
||||
CcPrintersPanel *self = (CcPrintersPanel*) user_data;
|
||||
|
||||
priv = self->priv = PRINTERS_PANEL_PRIVATE (self);
|
||||
|
||||
priv->all_ppds_list = ppds;
|
||||
|
||||
priv->getting_all_ppds = FALSE;
|
||||
|
||||
if (priv->pp_ppd_selection_dialog)
|
||||
pp_ppd_selection_dialog_set_ppd_list (priv->pp_ppd_selection_dialog,
|
||||
priv->all_ppds_list);
|
||||
}
|
||||
|
||||
static void
|
||||
update_label_padding (GtkWidget *widget,
|
||||
GtkAllocation *allocation,
|
||||
gpointer user_data)
|
||||
{
|
||||
CcPrintersPanelPrivate *priv;
|
||||
CcPrintersPanel *self = (CcPrintersPanel*) user_data;
|
||||
GtkAllocation allocation1, allocation2;
|
||||
GtkWidget *label;
|
||||
GtkWidget *sublabel;
|
||||
gint offset;
|
||||
gint pad;
|
||||
|
||||
priv = PRINTERS_PANEL_PRIVATE (self);
|
||||
|
||||
sublabel = gtk_bin_get_child (GTK_BIN (widget));
|
||||
if (sublabel)
|
||||
{
|
||||
gtk_widget_get_allocation (widget, &allocation1);
|
||||
gtk_widget_get_allocation (sublabel, &allocation2);
|
||||
|
||||
offset = allocation2.x - allocation1.x;
|
||||
|
||||
label = (GtkWidget*)
|
||||
gtk_builder_get_object (priv->builder, "printer-model-label");
|
||||
|
||||
gtk_misc_get_padding (GTK_MISC (label), &pad, NULL);
|
||||
if (offset != pad)
|
||||
gtk_misc_set_padding (GTK_MISC (label), offset, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
cc_printers_panel_init (CcPrintersPanel *self)
|
||||
{
|
||||
|
@ -2532,6 +3116,13 @@ cc_printers_panel_init (CcPrintersPanel *self)
|
|||
priv->permission = NULL;
|
||||
priv->lockdown_settings = NULL;
|
||||
|
||||
priv->getting_ppd_names = FALSE;
|
||||
|
||||
priv->all_ppds_list = NULL;
|
||||
priv->getting_all_ppds = FALSE;
|
||||
|
||||
priv->preferred_drivers = NULL;
|
||||
|
||||
builder_result = gtk_builder_add_objects_from_file (priv->builder,
|
||||
DATADIR"/printers.ui",
|
||||
objects, &error);
|
||||
|
@ -2628,6 +3219,11 @@ cc_printers_panel_init (CcPrintersPanel *self)
|
|||
G_CALLBACK (on_lockdown_settings_changed),
|
||||
self);
|
||||
|
||||
widget = (GtkWidget*)
|
||||
gtk_builder_get_object (priv->builder, "printer-model-button");
|
||||
g_signal_connect (widget, "clicked", G_CALLBACK (popup_model_menu_cb), self);
|
||||
g_signal_connect (widget, "size-allocate", G_CALLBACK (update_label_padding), self);
|
||||
|
||||
|
||||
/* Set junctions */
|
||||
widget = (GtkWidget*)
|
||||
|
@ -2666,10 +3262,6 @@ cc_printers_panel_init (CcPrintersPanel *self)
|
|||
gtk_builder_get_object (priv->builder, "printer-ip-address-label");
|
||||
cc_editable_entry_set_selectable (CC_EDITABLE_ENTRY (widget), TRUE);
|
||||
|
||||
widget = (GtkWidget*)
|
||||
gtk_builder_get_object (priv->builder, "printer-model-label");
|
||||
cc_editable_entry_set_selectable (CC_EDITABLE_ENTRY (widget), TRUE);
|
||||
|
||||
|
||||
/* Add unlock button */
|
||||
priv->permission = (GPermission *)polkit_permission_new_sync (
|
||||
|
@ -2694,6 +3286,9 @@ Please check your installation");
|
|||
populate_allowed_users_list (self);
|
||||
attach_to_cups_notifier (self);
|
||||
|
||||
priv->getting_all_ppds = TRUE;
|
||||
get_all_ppds_async (get_all_ppds_async_cb, self);
|
||||
|
||||
http = httpConnectEncrypt (cupsServer (), ippPort (), cupsEncryption ());
|
||||
if (!http)
|
||||
{
|
||||
|
|
444
panels/printers/pp-ppd-selection-dialog.c
Normal file
444
panels/printers/pp-ppd-selection-dialog.c
Normal file
|
@ -0,0 +1,444 @@
|
|||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||
*
|
||||
* Copyright 2012 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.
|
||||
*
|
||||
* Author: Marek Kasik <mkasik@redhat.com>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib/gi18n.h>
|
||||
#include <glib/gstdio.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include <cups/cups.h>
|
||||
#include <cups/ppd.h>
|
||||
|
||||
#include "pp-ppd-selection-dialog.h"
|
||||
|
||||
static void pp_ppd_selection_dialog_hide (PpPPDSelectionDialog *dialog);
|
||||
|
||||
enum
|
||||
{
|
||||
PPD_NAMES_COLUMN = 0,
|
||||
PPD_DISPLAY_NAMES_COLUMN
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
PPD_MANUFACTURERS_NAMES_COLUMN = 0,
|
||||
PPD_MANUFACTURERS_DISPLAY_NAMES_COLUMN
|
||||
};
|
||||
|
||||
|
||||
struct _PpPPDSelectionDialog {
|
||||
GtkBuilder *builder;
|
||||
GtkWidget *parent;
|
||||
GtkWidget *dialog;
|
||||
|
||||
UserResponseCallback user_callback;
|
||||
gpointer user_data;
|
||||
|
||||
gchar *ppd_name;
|
||||
GtkResponseType response;
|
||||
gchar *manufacturer;
|
||||
|
||||
PPDList *list;
|
||||
};
|
||||
|
||||
static void
|
||||
manufacturer_selection_changed_cb (GtkTreeSelection *selection,
|
||||
gpointer user_data)
|
||||
{
|
||||
PpPPDSelectionDialog *dialog = (PpPPDSelectionDialog *) user_data;
|
||||
GtkListStore *store;
|
||||
GtkTreeModel *model;
|
||||
GtkTreeIter iter;
|
||||
GtkTreeView *models_treeview;
|
||||
gchar *manufacturer_name = NULL;
|
||||
gint i, index;
|
||||
|
||||
if (gtk_tree_selection_get_selected (selection, &model, &iter))
|
||||
{
|
||||
gtk_tree_model_get (model, &iter,
|
||||
PPD_MANUFACTURERS_NAMES_COLUMN, &manufacturer_name,
|
||||
-1);
|
||||
}
|
||||
|
||||
if (manufacturer_name)
|
||||
{
|
||||
index = -1;
|
||||
for (i = 0; i < dialog->list->num_of_manufacturers; i++)
|
||||
{
|
||||
if (g_strcmp0 (manufacturer_name,
|
||||
dialog->list->manufacturers[i]->manufacturer_name) == 0)
|
||||
{
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (index >= 0)
|
||||
{
|
||||
models_treeview = (GtkTreeView*)
|
||||
gtk_builder_get_object (dialog->builder, "ppd-selection-models-treeview");
|
||||
|
||||
store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING);
|
||||
|
||||
for (i = 0; i < dialog->list->manufacturers[index]->num_of_ppds; i++)
|
||||
{
|
||||
gtk_list_store_append (store, &iter);
|
||||
gtk_list_store_set (store, &iter,
|
||||
PPD_NAMES_COLUMN, dialog->list->manufacturers[index]->ppds[i]->ppd_name,
|
||||
PPD_DISPLAY_NAMES_COLUMN, dialog->list->manufacturers[index]->ppds[i]->ppd_display_name,
|
||||
-1);
|
||||
}
|
||||
|
||||
gtk_tree_view_set_model (models_treeview, GTK_TREE_MODEL (store));
|
||||
g_object_unref (store);
|
||||
}
|
||||
|
||||
g_free (manufacturer_name);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
model_selection_changed_cb (GtkTreeSelection *selection,
|
||||
gpointer user_data)
|
||||
{
|
||||
PpPPDSelectionDialog *dialog = (PpPPDSelectionDialog *) user_data;
|
||||
GtkTreeModel *model;
|
||||
GtkTreeIter iter;
|
||||
GtkWidget *widget;
|
||||
gchar *model_name = NULL;
|
||||
|
||||
if (gtk_tree_selection_get_selected (selection, &model, &iter))
|
||||
{
|
||||
gtk_tree_model_get (model, &iter,
|
||||
PPD_NAMES_COLUMN, &model_name,
|
||||
-1);
|
||||
}
|
||||
|
||||
widget = (GtkWidget*)
|
||||
gtk_builder_get_object (dialog->builder, "ppd-selection-select-button");
|
||||
|
||||
if (model_name)
|
||||
{
|
||||
gtk_widget_set_sensitive (widget, TRUE);
|
||||
g_free (model_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_widget_set_sensitive (widget, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
fill_ppds_list (PpPPDSelectionDialog *dialog)
|
||||
{
|
||||
GtkTreeSelection *selection;
|
||||
GtkListStore *store;
|
||||
GtkTreePath *path;
|
||||
GtkTreeView *treeview;
|
||||
GtkTreeIter iter;
|
||||
GtkTreeIter *preselect_iter = NULL;
|
||||
GtkWidget *widget;
|
||||
gint i;
|
||||
|
||||
widget = (GtkWidget*)
|
||||
gtk_builder_get_object (dialog->builder, "ppd-spinner");
|
||||
gtk_widget_hide (widget);
|
||||
gtk_spinner_stop (GTK_SPINNER (widget));
|
||||
|
||||
widget = (GtkWidget*)
|
||||
gtk_builder_get_object (dialog->builder, "progress-label");
|
||||
gtk_widget_hide (widget);
|
||||
|
||||
treeview = (GtkTreeView*)
|
||||
gtk_builder_get_object (dialog->builder, "ppd-selection-manufacturers-treeview");
|
||||
|
||||
if (dialog->list)
|
||||
{
|
||||
store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING);
|
||||
|
||||
for (i = 0; i < dialog->list->num_of_manufacturers; i++)
|
||||
{
|
||||
gtk_list_store_append (store, &iter);
|
||||
gtk_list_store_set (store, &iter,
|
||||
PPD_MANUFACTURERS_NAMES_COLUMN, dialog->list->manufacturers[i]->manufacturer_name,
|
||||
PPD_MANUFACTURERS_DISPLAY_NAMES_COLUMN, dialog->list->manufacturers[i]->manufacturer_display_name,
|
||||
-1);
|
||||
|
||||
if (g_strcmp0 (dialog->manufacturer,
|
||||
dialog->list->manufacturers[i]->manufacturer_display_name) == 0)
|
||||
{
|
||||
preselect_iter = gtk_tree_iter_copy (&iter);
|
||||
}
|
||||
}
|
||||
|
||||
gtk_tree_view_set_model (treeview, GTK_TREE_MODEL (store));
|
||||
|
||||
if (preselect_iter &&
|
||||
(selection = gtk_tree_view_get_selection (treeview)) != NULL)
|
||||
{
|
||||
gtk_tree_selection_select_iter (selection, preselect_iter);
|
||||
path = gtk_tree_model_get_path (GTK_TREE_MODEL (store), preselect_iter);
|
||||
gtk_tree_view_scroll_to_cell (treeview, path, NULL, TRUE, 0.5, 0.0);
|
||||
gtk_tree_path_free (path);
|
||||
gtk_tree_iter_free (preselect_iter);
|
||||
}
|
||||
|
||||
g_object_unref (store);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
populate_dialog (PpPPDSelectionDialog *dialog)
|
||||
{
|
||||
GtkTreeViewColumn *column;
|
||||
GtkCellRenderer *renderer;
|
||||
GtkTreeView *manufacturers_treeview;
|
||||
GtkTreeView *models_treeview;
|
||||
GtkWidget *widget;
|
||||
|
||||
manufacturers_treeview = (GtkTreeView*)
|
||||
gtk_builder_get_object (dialog->builder, "ppd-selection-manufacturers-treeview");
|
||||
|
||||
renderer = gtk_cell_renderer_text_new ();
|
||||
|
||||
/* Translators: Name of column showing printer manufacturers */
|
||||
column = gtk_tree_view_column_new_with_attributes (_("Manufacturers"), renderer,
|
||||
"text", PPD_MANUFACTURERS_DISPLAY_NAMES_COLUMN, NULL);
|
||||
gtk_tree_view_column_set_expand (column, TRUE);
|
||||
gtk_tree_view_append_column (manufacturers_treeview, column);
|
||||
|
||||
|
||||
models_treeview = (GtkTreeView*)
|
||||
gtk_builder_get_object (dialog->builder, "ppd-selection-models-treeview");
|
||||
|
||||
renderer = gtk_cell_renderer_text_new ();
|
||||
|
||||
/* Translators: Name of column showing printer drivers */
|
||||
column = gtk_tree_view_column_new_with_attributes (_("Drivers"), renderer,
|
||||
"text", PPD_DISPLAY_NAMES_COLUMN, NULL);
|
||||
gtk_tree_view_column_set_expand (column, TRUE);
|
||||
gtk_tree_view_append_column (models_treeview, column);
|
||||
|
||||
|
||||
g_signal_connect (gtk_tree_view_get_selection (models_treeview),
|
||||
"changed", G_CALLBACK (model_selection_changed_cb), dialog);
|
||||
|
||||
g_signal_connect (gtk_tree_view_get_selection (manufacturers_treeview),
|
||||
"changed", G_CALLBACK (manufacturer_selection_changed_cb), dialog);
|
||||
|
||||
gtk_widget_show_all (dialog->dialog);
|
||||
|
||||
if (!dialog->list)
|
||||
{
|
||||
widget = (GtkWidget*)
|
||||
gtk_builder_get_object (dialog->builder, "ppd-spinner");
|
||||
gtk_widget_show (widget);
|
||||
gtk_spinner_start (GTK_SPINNER (widget));
|
||||
|
||||
widget = (GtkWidget*)
|
||||
gtk_builder_get_object (dialog->builder, "progress-label");
|
||||
gtk_widget_show (widget);
|
||||
}
|
||||
else
|
||||
{
|
||||
fill_ppds_list (dialog);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ppd_selection_dialog_response_cb (GtkDialog *dialog,
|
||||
gint response_id,
|
||||
gpointer user_data)
|
||||
{
|
||||
PpPPDSelectionDialog *ppd_selection_dialog = (PpPPDSelectionDialog*) user_data;
|
||||
GtkTreeSelection *selection;
|
||||
GtkTreeModel *model;
|
||||
GtkTreeView *models_treeview;
|
||||
GtkTreeIter iter;
|
||||
|
||||
pp_ppd_selection_dialog_hide (ppd_selection_dialog);
|
||||
|
||||
ppd_selection_dialog->response = response_id;
|
||||
if (response_id == GTK_RESPONSE_OK)
|
||||
{
|
||||
models_treeview = (GtkTreeView*)
|
||||
gtk_builder_get_object (ppd_selection_dialog->builder, "ppd-selection-models-treeview");
|
||||
|
||||
if (models_treeview)
|
||||
{
|
||||
selection = gtk_tree_view_get_selection (models_treeview);
|
||||
|
||||
if (selection)
|
||||
{
|
||||
if (gtk_tree_selection_get_selected (selection, &model, &iter))
|
||||
{
|
||||
gtk_tree_model_get (model, &iter,
|
||||
PPD_NAMES_COLUMN, &ppd_selection_dialog->ppd_name,
|
||||
-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ppd_selection_dialog->user_callback (GTK_DIALOG (ppd_selection_dialog->dialog),
|
||||
response_id,
|
||||
ppd_selection_dialog->user_data);
|
||||
}
|
||||
|
||||
static void
|
||||
update_alignment_padding (GtkWidget *widget,
|
||||
GtkAllocation *allocation,
|
||||
gpointer user_data)
|
||||
{
|
||||
PpPPDSelectionDialog *dialog = (PpPPDSelectionDialog*) user_data;
|
||||
GtkAllocation allocation2;
|
||||
GtkWidget *action_area;
|
||||
gint offset_left, offset_right;
|
||||
guint padding_left, padding_right,
|
||||
padding_top, padding_bottom;
|
||||
|
||||
action_area = (GtkWidget*)
|
||||
gtk_builder_get_object (dialog->builder, "dialog-action-area1");
|
||||
gtk_widget_get_allocation (action_area, &allocation2);
|
||||
|
||||
offset_left = allocation2.x - allocation->x;
|
||||
offset_right = (allocation->x + allocation->width) -
|
||||
(allocation2.x + allocation2.width);
|
||||
|
||||
gtk_alignment_get_padding (GTK_ALIGNMENT (widget),
|
||||
&padding_top, &padding_bottom,
|
||||
&padding_left, &padding_right);
|
||||
if (allocation->x >= 0 && allocation2.x >= 0)
|
||||
{
|
||||
if (offset_left > 0 && offset_left != padding_left)
|
||||
gtk_alignment_set_padding (GTK_ALIGNMENT (widget),
|
||||
padding_top, padding_bottom,
|
||||
offset_left, padding_right);
|
||||
|
||||
gtk_alignment_get_padding (GTK_ALIGNMENT (widget),
|
||||
&padding_top, &padding_bottom,
|
||||
&padding_left, &padding_right);
|
||||
if (offset_right > 0 && offset_right != padding_right)
|
||||
gtk_alignment_set_padding (GTK_ALIGNMENT (widget),
|
||||
padding_top, padding_bottom,
|
||||
padding_left, offset_right);
|
||||
}
|
||||
}
|
||||
|
||||
PpPPDSelectionDialog *
|
||||
pp_ppd_selection_dialog_new (GtkWindow *parent,
|
||||
PPDList *ppd_list,
|
||||
gchar *manufacturer,
|
||||
UserResponseCallback user_callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
PpPPDSelectionDialog *dialog;
|
||||
GtkWidget *widget;
|
||||
GError *error = NULL;
|
||||
gchar *objects[] = { "ppd-selection-dialog", NULL };
|
||||
guint builder_result;
|
||||
|
||||
dialog = g_new0 (PpPPDSelectionDialog, 1);
|
||||
|
||||
dialog->builder = gtk_builder_new ();
|
||||
dialog->parent = GTK_WIDGET (parent);
|
||||
|
||||
builder_result = gtk_builder_add_objects_from_file (dialog->builder,
|
||||
DATADIR"/ppd-selection-dialog.ui",
|
||||
objects, &error);
|
||||
|
||||
if (builder_result == 0)
|
||||
{
|
||||
g_warning ("Could not load ui: %s", error->message);
|
||||
g_error_free (error);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dialog->dialog = (GtkWidget *) gtk_builder_get_object (dialog->builder, "ppd-selection-dialog");
|
||||
dialog->user_callback = user_callback;
|
||||
dialog->user_data = user_data;
|
||||
|
||||
dialog->response = GTK_RESPONSE_NONE;
|
||||
dialog->list = ppd_list_copy (ppd_list);
|
||||
|
||||
dialog->manufacturer = get_standard_manufacturers_name (manufacturer);
|
||||
|
||||
/* connect signals */
|
||||
g_signal_connect (dialog->dialog, "delete-event", G_CALLBACK (gtk_widget_hide_on_delete), NULL);
|
||||
g_signal_connect (dialog->dialog, "response", G_CALLBACK (ppd_selection_dialog_response_cb), dialog);
|
||||
|
||||
widget = (GtkWidget*)
|
||||
gtk_builder_get_object (dialog->builder, "content-alignment");
|
||||
g_signal_connect (widget, "size-allocate", G_CALLBACK (update_alignment_padding), dialog);
|
||||
|
||||
widget = (GtkWidget*)
|
||||
gtk_builder_get_object (dialog->builder, "ppd-spinner");
|
||||
gtk_spinner_start (GTK_SPINNER (widget));
|
||||
|
||||
populate_dialog (dialog);
|
||||
|
||||
gtk_window_set_transient_for (GTK_WINDOW (dialog->dialog), GTK_WINDOW (parent));
|
||||
gtk_window_present (GTK_WINDOW (dialog->dialog));
|
||||
gtk_widget_show_all (GTK_WIDGET (dialog->dialog));
|
||||
|
||||
return dialog;
|
||||
}
|
||||
|
||||
void
|
||||
pp_ppd_selection_dialog_free (PpPPDSelectionDialog *dialog)
|
||||
{
|
||||
gtk_widget_destroy (GTK_WIDGET (dialog->dialog));
|
||||
|
||||
g_object_unref (dialog->builder);
|
||||
|
||||
g_free (dialog->ppd_name);
|
||||
|
||||
g_free (dialog->manufacturer);
|
||||
|
||||
g_free (dialog);
|
||||
}
|
||||
|
||||
gchar *
|
||||
pp_ppd_selection_dialog_get_ppd_name (PpPPDSelectionDialog *dialog)
|
||||
{
|
||||
return g_strdup (dialog->ppd_name);
|
||||
}
|
||||
|
||||
void
|
||||
pp_ppd_selection_dialog_set_ppd_list (PpPPDSelectionDialog *dialog,
|
||||
PPDList *list)
|
||||
{
|
||||
dialog->list = list;
|
||||
fill_ppds_list (dialog);
|
||||
}
|
||||
|
||||
static void
|
||||
pp_ppd_selection_dialog_hide (PpPPDSelectionDialog *dialog)
|
||||
{
|
||||
gtk_widget_hide (GTK_WIDGET (dialog->dialog));
|
||||
}
|
46
panels/printers/pp-ppd-selection-dialog.h
Normal file
46
panels/printers/pp-ppd-selection-dialog.h
Normal file
|
@ -0,0 +1,46 @@
|
|||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||
*
|
||||
* Copyright 2012 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.
|
||||
*
|
||||
* Author: Marek Kasik <mkasik@redhat.com>
|
||||
*/
|
||||
|
||||
#ifndef __PP_PPD_SELECTION_DIALOG_H__
|
||||
#define __PP_PPD_SELECTION_DIALOG_H__
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include "pp-utils.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _PpPPDSelectionDialog PpPPDSelectionDialog;
|
||||
|
||||
typedef void (*UserResponseCallback) (GtkDialog *dialog, gint response_id, gpointer user_data);
|
||||
|
||||
PpPPDSelectionDialog *pp_ppd_selection_dialog_new (GtkWindow *parent,
|
||||
PPDList *ppd_list,
|
||||
gchar *manufacturer,
|
||||
UserResponseCallback user_callback,
|
||||
gpointer user_data);
|
||||
gchar *pp_ppd_selection_dialog_get_ppd_name (PpPPDSelectionDialog *dialog);
|
||||
void pp_ppd_selection_dialog_set_ppd_list (PpPPDSelectionDialog *dialog,
|
||||
PPDList *list);
|
||||
void pp_ppd_selection_dialog_free (PpPPDSelectionDialog *dialog);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load diff
|
@ -40,9 +40,24 @@ enum
|
|||
typedef struct
|
||||
{
|
||||
gchar *ppd_name;
|
||||
gchar *ppd_display_name;
|
||||
gint ppd_match_level;
|
||||
} PPDName;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
gchar *manufacturer_name;
|
||||
gchar *manufacturer_display_name;
|
||||
PPDName **ppds;
|
||||
gsize num_of_ppds;
|
||||
} PPDManufacturerItem;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
PPDManufacturerItem **manufacturers;
|
||||
gsize num_of_manufacturers;
|
||||
} PPDList;
|
||||
|
||||
gchar *get_tag_value (const gchar *tag_string,
|
||||
const gchar *tag_name);
|
||||
|
||||
|
@ -116,6 +131,81 @@ gchar *printer_get_hostname (cups_ptype_t printer_type,
|
|||
|
||||
void printer_set_default_media_size (const gchar *printer_name);
|
||||
|
||||
typedef void (*PSPCallback) (gchar *printer_name,
|
||||
gboolean success,
|
||||
gpointer user_data);
|
||||
|
||||
void printer_set_ppd_async (const gchar *printer_name,
|
||||
const gchar *ppd_name,
|
||||
GCancellable *cancellable,
|
||||
PSPCallback callback,
|
||||
gpointer user_data);
|
||||
|
||||
void printer_set_ppd_file_async (const gchar *printer_name,
|
||||
const gchar *ppd_filename,
|
||||
GCancellable *cancellable,
|
||||
PSPCallback callback,
|
||||
gpointer user_data);
|
||||
|
||||
typedef void (*GPNCallback) (PPDName **names,
|
||||
const gchar *printer_name,
|
||||
gboolean cancelled,
|
||||
gpointer user_data);
|
||||
|
||||
void get_ppd_names_async (gchar *printer_name,
|
||||
gint count,
|
||||
GCancellable *cancellable,
|
||||
GPNCallback callback,
|
||||
gpointer user_data);
|
||||
|
||||
typedef void (*GAPCallback) (PPDList *ppds,
|
||||
gpointer user_data);
|
||||
|
||||
void get_all_ppds_async (GAPCallback callback,
|
||||
gpointer user_data);
|
||||
|
||||
PPDList *ppd_list_copy (PPDList *list);
|
||||
void ppd_list_free (PPDList *list);
|
||||
|
||||
enum
|
||||
{
|
||||
IPP_ATTRIBUTE_TYPE_INTEGER = 0,
|
||||
IPP_ATTRIBUTE_TYPE_STRING,
|
||||
IPP_ATTRIBUTE_TYPE_RANGE,
|
||||
IPP_ATTRIBUTE_TYPE_BOOLEAN
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
gboolean boolean_value;
|
||||
gchar *string_value;
|
||||
gint integer_value;
|
||||
gint lower_range;
|
||||
gint upper_range;
|
||||
} IPPAttributeValue;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
gchar *attribute_name;
|
||||
IPPAttributeValue *attribute_values;
|
||||
gint num_of_values;
|
||||
gint attribute_type;
|
||||
} IPPAttribute;
|
||||
|
||||
typedef void (*GIACallback) (GHashTable *table,
|
||||
gpointer user_data);
|
||||
|
||||
void get_ipp_attributes_async (const gchar *printer_name,
|
||||
gchar **attributes_names,
|
||||
GIACallback callback,
|
||||
gpointer user_data);
|
||||
|
||||
IPPAttribute *ipp_attribute_copy (IPPAttribute *attr);
|
||||
|
||||
void ipp_attribute_free (IPPAttribute *attr);
|
||||
|
||||
gchar *get_standard_manufacturers_name (gchar *name);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __PP_UTILS_H */
|
||||
|
|
206
panels/printers/ppd-selection-dialog.ui
Normal file
206
panels/printers/ppd-selection-dialog.ui
Normal file
|
@ -0,0 +1,206 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<!-- interface-requires gtk+ 3.0 -->
|
||||
<object class="GtkDialog" id="ppd-selection-dialog">
|
||||
<property name="width_request">500</property>
|
||||
<property name="height_request">350</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="border_width">5</property>
|
||||
<property name="title" translatable="yes"> </property>
|
||||
<property name="modal">True</property>
|
||||
<property name="destroy_with_parent">True</property>
|
||||
<property name="type_hint">dialog</property>
|
||||
<child internal-child="vbox">
|
||||
<object class="GtkBox" id="main-vbox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">10</property>
|
||||
<child internal-child="action_area">
|
||||
<object class="GtkButtonBox" id="dialog-action-area1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="layout_style">end</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="ppd-selection-cancel-button">
|
||||
<property name="label" translatable="yes">Cancel</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="ppd-selection-select-button">
|
||||
<property name="label" translatable="yes">Select</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="sensitive">False</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="box2">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkAlignment" id="alignment1">
|
||||
<property name="width_request">24</property>
|
||||
<property name="height_request">24</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkSpinner" id="ppd-spinner">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="no_show_all">True</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="progress-label">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="no_show_all">True</property>
|
||||
<property name="label" translatable="yes">Loading drivers database...</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="padding">10</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
<property name="secondary">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="pack_type">end</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkAlignment" id="content-alignment">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkBox" id="box1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">10</property>
|
||||
<child>
|
||||
<object class="GtkBox" id="box3">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow" id="scrolledwindow1">
|
||||
<property name="width_request">140</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="hscrollbar_policy">never</property>
|
||||
<property name="shadow_type">in</property>
|
||||
<child>
|
||||
<object class="GtkTreeView" id="ppd-selection-manufacturers-treeview">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<child internal-child="selection">
|
||||
<object class="GtkTreeSelection" id="treeview-selection"/>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow" id="scrolledwindow2">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="shadow_type">in</property>
|
||||
<child>
|
||||
<object class="GtkTreeView" id="ppd-selection-models-treeview">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<child internal-child="selection">
|
||||
<object class="GtkTreeSelection" id="treeview-selection1"/>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="pack_type">end</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="options-title">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="label" translatable="yes">Select Printer Driver</property>
|
||||
<attributes>
|
||||
<attribute name="weight" value="bold"/>
|
||||
</attributes>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<action-widgets>
|
||||
<action-widget response="-6">ppd-selection-cancel-button</action-widget>
|
||||
<action-widget response="-5">ppd-selection-select-button</action-widget>
|
||||
</action-widgets>
|
||||
</object>
|
||||
<object class="GtkSizeGroup" id="sizegroup1"/>
|
||||
</interface>
|
|
@ -315,17 +315,84 @@
|
|||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="CcEditableEntry" id="printer-model-label">
|
||||
<object class="GtkNotebook" id="printer-model-notebook">
|
||||
<property name="visible">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="text">---</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="show_tabs">False</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="printer-model-button">
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="relief">none</property>
|
||||
<property name="xalign">0</property>
|
||||
</object>
|
||||
</child>
|
||||
<child type="tab">
|
||||
<object class="GtkLabel" id="label7">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">page 1</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="tab_fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="printer-model-label">
|
||||
<property name="visible">True</property>
|
||||
<property name="selectable">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="label" translatable="yes">label</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child type="tab">
|
||||
<object class="GtkLabel" id="label13">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">page 2</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
<property name="tab_fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label17">
|
||||
<property name="visible">True</property>
|
||||
<property name="sensitive">False</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="xpad">10</property>
|
||||
<property name="label" translatable="yes">Setting new driver...</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child type="tab">
|
||||
<object class="GtkLabel" id="label16">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">page 3</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">2</property>
|
||||
<property name="tab_fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">3</property>
|
||||
<property name="top_attach">3</property>
|
||||
<property name="bottom_attach">4</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
|
|
Loading…
Add table
Reference in a new issue