gnome-control-center/panels/printers/pp-ppd-selection-dialog.c
Brandon Nielsen c239521e9d Change PpPPDSelectionDialog to GtkDialog
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.
2021-01-08 02:49:32 +00:00

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