Make the dialog bigger (600x400). Add padding between list of manufacturers and the list of drivers. Add padding to manufacturers and drivers lists. Change Manufacturers and Drivers to singular. Trigger resizing of treeview when list has changed so it has optimal width. https://bugzilla.gnome.org/show_bug.cgi?id=690448
457 lines
15 KiB
C
457 lines
15 KiB
C
/* -*- 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 2 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);
|
|
gtk_tree_view_columns_autosize (models_treeview);
|
|
}
|
|
|
|
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;
|
|
GtkWidget *header;
|
|
|
|
manufacturers_treeview = (GtkTreeView*)
|
|
gtk_builder_get_object (dialog->builder, "ppd-selection-manufacturers-treeview");
|
|
|
|
renderer = gtk_cell_renderer_text_new ();
|
|
gtk_cell_renderer_set_padding (renderer, 10, 0);
|
|
|
|
/* Translators: Name of column showing printer manufacturers */
|
|
column = gtk_tree_view_column_new_with_attributes (_("Manufacturer"), renderer,
|
|
"text", PPD_MANUFACTURERS_DISPLAY_NAMES_COLUMN, NULL);
|
|
gtk_tree_view_column_set_expand (column, TRUE);
|
|
header = gtk_label_new (gtk_tree_view_column_get_title (column));
|
|
gtk_misc_set_padding (GTK_MISC (header), 10, 0);
|
|
gtk_tree_view_column_set_widget (column, header);
|
|
gtk_widget_show (header);
|
|
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 ();
|
|
gtk_cell_renderer_set_padding (renderer, 10, 0);
|
|
|
|
/* Translators: Name of column showing printer drivers */
|
|
column = gtk_tree_view_column_new_with_attributes (_("Driver"), renderer,
|
|
"text", PPD_DISPLAY_NAMES_COLUMN,
|
|
NULL);
|
|
gtk_tree_view_column_set_expand (column, TRUE);
|
|
header = gtk_label_new (gtk_tree_view_column_get_title (column));
|
|
gtk_misc_set_padding (GTK_MISC (header), 10, 0);
|
|
gtk_tree_view_column_set_widget (column, header);
|
|
gtk_widget_show (header);
|
|
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_resource (dialog->builder,
|
|
"/org/gnome/control-center/printers/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));
|
|
}
|