gnome-control-center/panels/printers/pp-ppd-selection-dialog.c
Marek Kasik 27aa41f5c1 printers: Visual improvements of driver selection dialog
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
2013-02-15 16:07:39 +01:00

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));
}