The dialog is now displayed by calling gtk_dialog_run and gtk_window_set_transient_for in the window displaying the dialog. Cleanup is handled using gtk_widget_destroy. Destructors in the windows using the dialog no longer cleanup the dialog as it is assumed it will be either cleaned up after the response callback, or handled by the destroy_with_parent property set on the dialog itself.
381 lines
12 KiB
C
381 lines
12 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, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
* 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"
|
|
|
|
enum
|
|
{
|
|
PPD_NAMES_COLUMN = 0,
|
|
PPD_DISPLAY_NAMES_COLUMN
|
|
};
|
|
|
|
enum
|
|
{
|
|
PPD_MANUFACTURERS_NAMES_COLUMN = 0,
|
|
PPD_MANUFACTURERS_DISPLAY_NAMES_COLUMN
|
|
};
|
|
|
|
|
|
struct _PpPPDSelectionDialog {
|
|
GtkDialog parent_instance;
|
|
|
|
GtkButton *ppd_selection_select_button;
|
|
GtkSpinner *ppd_spinner;
|
|
GtkLabel *progress_label;
|
|
GtkTreeView *ppd_selection_manufacturers_treeview;
|
|
GtkTreeView *ppd_selection_models_treeview;
|
|
|
|
UserResponseCallback user_callback;
|
|
gpointer user_data;
|
|
|
|
gchar *ppd_name;
|
|
gchar *ppd_display_name;
|
|
gchar *manufacturer;
|
|
|
|
PPDList *list;
|
|
};
|
|
|
|
G_DEFINE_TYPE (PpPPDSelectionDialog, pp_ppd_selection_dialog, GTK_TYPE_DIALOG)
|
|
|
|
static void
|
|
manufacturer_selection_changed_cb (PpPPDSelectionDialog *self)
|
|
{
|
|
GtkTreeView *treeview;
|
|
g_autoptr(GtkListStore) store = NULL;
|
|
GtkTreeModel *model;
|
|
GtkTreeIter iter;
|
|
GtkTreeView *models_treeview;
|
|
gchar *manufacturer_name = NULL;
|
|
gint i, index;
|
|
|
|
treeview = self->ppd_selection_manufacturers_treeview;
|
|
if (gtk_tree_selection_get_selected (gtk_tree_view_get_selection (treeview), &model, &iter))
|
|
{
|
|
gtk_tree_model_get (model, &iter,
|
|
PPD_MANUFACTURERS_NAMES_COLUMN, &manufacturer_name,
|
|
-1);
|
|
}
|
|
|
|
if (manufacturer_name)
|
|
{
|
|
index = -1;
|
|
for (i = 0; i < self->list->num_of_manufacturers; i++)
|
|
{
|
|
if (g_strcmp0 (manufacturer_name,
|
|
self->list->manufacturers[i]->manufacturer_name) == 0)
|
|
{
|
|
index = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (index >= 0)
|
|
{
|
|
models_treeview = self->ppd_selection_models_treeview;
|
|
|
|
store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING);
|
|
|
|
for (i = 0; i < self->list->manufacturers[index]->num_of_ppds; i++)
|
|
{
|
|
gtk_list_store_append (store, &iter);
|
|
gtk_list_store_set (store, &iter,
|
|
PPD_NAMES_COLUMN, self->list->manufacturers[index]->ppds[i]->ppd_name,
|
|
PPD_DISPLAY_NAMES_COLUMN, self->list->manufacturers[index]->ppds[i]->ppd_display_name,
|
|
-1);
|
|
}
|
|
|
|
gtk_tree_view_set_model (models_treeview, GTK_TREE_MODEL (store));
|
|
gtk_tree_view_columns_autosize (models_treeview);
|
|
}
|
|
|
|
g_free (manufacturer_name);
|
|
}
|
|
}
|
|
|
|
static void
|
|
model_selection_changed_cb (PpPPDSelectionDialog *self)
|
|
{
|
|
GtkTreeView *treeview;
|
|
GtkTreeModel *model;
|
|
GtkTreeIter iter;
|
|
GtkButton *ppd_select_button;
|
|
gchar *model_name = NULL;
|
|
|
|
treeview = self->ppd_selection_models_treeview;
|
|
if (gtk_tree_selection_get_selected (gtk_tree_view_get_selection (treeview), &model, &iter))
|
|
{
|
|
gtk_tree_model_get (model, &iter,
|
|
PPD_NAMES_COLUMN, &model_name,
|
|
-1);
|
|
}
|
|
|
|
ppd_select_button = self->ppd_selection_select_button;
|
|
|
|
if (model_name)
|
|
{
|
|
gtk_widget_set_sensitive (GTK_WIDGET (ppd_select_button), TRUE);
|
|
g_free (model_name);
|
|
}
|
|
else
|
|
{
|
|
gtk_widget_set_sensitive (GTK_WIDGET (ppd_select_button), FALSE);
|
|
}
|
|
}
|
|
|
|
static void
|
|
fill_ppds_list (PpPPDSelectionDialog *self)
|
|
{
|
|
GtkTreeSelection *selection;
|
|
g_autoptr(GtkListStore) store = NULL;
|
|
GtkTreePath *path;
|
|
GtkTreeView *treeview;
|
|
GtkTreeIter iter;
|
|
GtkTreeIter *preselect_iter = NULL;
|
|
gint i;
|
|
|
|
gtk_widget_hide (GTK_WIDGET (self->ppd_spinner));
|
|
gtk_spinner_stop (self->ppd_spinner);
|
|
|
|
gtk_widget_hide (GTK_WIDGET (self->progress_label));
|
|
|
|
treeview = self->ppd_selection_manufacturers_treeview;
|
|
|
|
if (self->list)
|
|
{
|
|
store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING);
|
|
|
|
for (i = 0; i < self->list->num_of_manufacturers; i++)
|
|
{
|
|
gtk_list_store_append (store, &iter);
|
|
gtk_list_store_set (store, &iter,
|
|
PPD_MANUFACTURERS_NAMES_COLUMN, self->list->manufacturers[i]->manufacturer_name,
|
|
PPD_MANUFACTURERS_DISPLAY_NAMES_COLUMN, self->list->manufacturers[i]->manufacturer_display_name,
|
|
-1);
|
|
|
|
if (g_strcmp0 (self->manufacturer,
|
|
self->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);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
populate_dialog (PpPPDSelectionDialog *self)
|
|
{
|
|
GtkTreeViewColumn *column;
|
|
GtkCellRenderer *renderer;
|
|
GtkTreeView *manufacturers_treeview;
|
|
GtkTreeView *models_treeview;
|
|
GtkWidget *header;
|
|
|
|
manufacturers_treeview = self->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_widget_set_margin_start (header, 10);
|
|
gtk_tree_view_column_set_widget (column, header);
|
|
gtk_widget_show (header);
|
|
gtk_tree_view_append_column (manufacturers_treeview, column);
|
|
|
|
|
|
models_treeview = self->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_widget_set_margin_start (header, 10);
|
|
gtk_tree_view_column_set_widget (column, header);
|
|
gtk_widget_show (header);
|
|
gtk_tree_view_append_column (models_treeview, column);
|
|
|
|
|
|
g_signal_connect_object (gtk_tree_view_get_selection (models_treeview),
|
|
"changed", G_CALLBACK (model_selection_changed_cb), self, G_CONNECT_SWAPPED);
|
|
|
|
g_signal_connect_object (gtk_tree_view_get_selection (manufacturers_treeview),
|
|
"changed", G_CALLBACK (manufacturer_selection_changed_cb), self, G_CONNECT_SWAPPED);
|
|
|
|
if (!self->list)
|
|
{
|
|
gtk_widget_show (GTK_WIDGET (self->ppd_spinner));
|
|
gtk_spinner_start (self->ppd_spinner);
|
|
|
|
gtk_widget_show (GTK_WIDGET (self->progress_label));
|
|
}
|
|
else
|
|
{
|
|
fill_ppds_list (self);
|
|
}
|
|
}
|
|
|
|
static void
|
|
ppd_selection_dialog_response_cb (PpPPDSelectionDialog *self,
|
|
gint response_id)
|
|
{
|
|
GtkTreeSelection *selection;
|
|
GtkTreeModel *model;
|
|
GtkTreeView *models_treeview;
|
|
GtkTreeIter iter;
|
|
|
|
if (response_id == GTK_RESPONSE_OK)
|
|
{
|
|
models_treeview = self->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, &self->ppd_name,
|
|
PPD_DISPLAY_NAMES_COLUMN, &self->ppd_display_name,
|
|
-1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
self->user_callback (GTK_DIALOG (self), response_id, self->user_data);
|
|
}
|
|
|
|
PpPPDSelectionDialog *
|
|
pp_ppd_selection_dialog_new (PPDList *ppd_list,
|
|
const gchar *manufacturer,
|
|
UserResponseCallback user_callback,
|
|
gpointer user_data)
|
|
{
|
|
PpPPDSelectionDialog *self;
|
|
|
|
self = g_object_new (pp_ppd_selection_dialog_get_type (), NULL);
|
|
|
|
self->user_callback = user_callback;
|
|
self->user_data = user_data;
|
|
|
|
self->list = ppd_list_copy (ppd_list);
|
|
|
|
self->manufacturer = get_standard_manufacturers_name (manufacturer);
|
|
|
|
/* connect signal */
|
|
g_signal_connect_object (self, "response", G_CALLBACK (ppd_selection_dialog_response_cb), self, G_CONNECT_SWAPPED);
|
|
|
|
gtk_spinner_start (self->ppd_spinner);
|
|
|
|
populate_dialog (self);
|
|
|
|
return self;
|
|
}
|
|
|
|
static void
|
|
pp_ppd_selection_dialog_dispose (GObject *object)
|
|
{
|
|
PpPPDSelectionDialog *self = PP_PPD_SELECTION_DIALOG (object);
|
|
|
|
g_clear_pointer (&self->ppd_name, g_free);
|
|
g_clear_pointer (&self->ppd_display_name, g_free);
|
|
g_clear_pointer (&self->manufacturer, g_free);
|
|
|
|
G_OBJECT_CLASS (pp_ppd_selection_dialog_parent_class)->dispose (object);
|
|
}
|
|
|
|
void
|
|
pp_ppd_selection_dialog_class_init (PpPPDSelectionDialogClass *klass)
|
|
{
|
|
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
|
|
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/printers/ppd-selection-dialog.ui");
|
|
gtk_widget_class_bind_template_child (widget_class, PpPPDSelectionDialog, ppd_selection_select_button);
|
|
gtk_widget_class_bind_template_child (widget_class, PpPPDSelectionDialog, ppd_spinner);
|
|
gtk_widget_class_bind_template_child (widget_class, PpPPDSelectionDialog, progress_label);
|
|
gtk_widget_class_bind_template_child (widget_class, PpPPDSelectionDialog, ppd_selection_manufacturers_treeview);
|
|
gtk_widget_class_bind_template_child (widget_class, PpPPDSelectionDialog, ppd_selection_models_treeview);
|
|
|
|
object_class->dispose = pp_ppd_selection_dialog_dispose;
|
|
}
|
|
|
|
void
|
|
pp_ppd_selection_dialog_init (PpPPDSelectionDialog *self)
|
|
{
|
|
gtk_widget_init_template (GTK_WIDGET (self));
|
|
}
|
|
|
|
gchar *
|
|
pp_ppd_selection_dialog_get_ppd_name (PpPPDSelectionDialog *self)
|
|
{
|
|
return g_strdup (self->ppd_name);
|
|
}
|
|
|
|
gchar *
|
|
pp_ppd_selection_dialog_get_ppd_display_name (PpPPDSelectionDialog *self)
|
|
{
|
|
return g_strdup (self->ppd_display_name);
|
|
}
|
|
|
|
void
|
|
pp_ppd_selection_dialog_set_ppd_list (PpPPDSelectionDialog *self,
|
|
PPDList *list)
|
|
{
|
|
self->list = list;
|
|
fill_ppds_list (self);
|
|
}
|