X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtkprinteroptionwidget.c;h=44c54adf7c5f265fb7f8bc9abd4191847cecbd64;hb=aaedf5a35219b034a244730564b8fdf2b7d32540;hp=e639abf952bfef390677c19f8a5ebda99919af2f;hpb=e9f1fe16bc625a7ff2ef615a9ac3e2aabc7290b0;p=~andy%2Fgtk diff --git a/gtk/gtkprinteroptionwidget.c b/gtk/gtkprinteroptionwidget.c index e639abf95..44c54adf7 100644 --- a/gtk/gtkprinteroptionwidget.c +++ b/gtk/gtkprinteroptionwidget.c @@ -12,9 +12,7 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * License along with this library. If not, see . */ #include "config.h" @@ -24,46 +22,57 @@ #include #include "gtkintl.h" -#include "gtkalignment.h" #include "gtkcheckbutton.h" #include "gtkcelllayout.h" #include "gtkcellrenderertext.h" #include "gtkcombobox.h" -#include "gtkcomboboxentry.h" -#include "gtkfilechooserbutton.h" +#include "gtkfilechooserdialog.h" #include "gtkimage.h" #include "gtklabel.h" #include "gtkliststore.h" #include "gtkradiobutton.h" #include "gtkstock.h" -#include "gtktable.h" +#include "gtkgrid.h" #include "gtktogglebutton.h" +#include "gtkorientable.h" #include "gtkprivate.h" #include "gtkprinteroptionwidget.h" -#include "gtkalias.h" #define GTK_PRINTER_OPTION_WIDGET_GET_PRIVATE(o) \ (G_TYPE_INSTANCE_GET_PRIVATE ((o), GTK_TYPE_PRINTER_OPTION_WIDGET, GtkPrinterOptionWidgetPrivate)) +/* This defines the max file length that the file chooser + * button should display. The total length will be + * FILENAME_LENGTH_MAX+3 because the truncated name is prefixed + * with "...". + */ +#define FILENAME_LENGTH_MAX 27 + static void gtk_printer_option_widget_finalize (GObject *object); static void deconstruct_widgets (GtkPrinterOptionWidget *widget); -static void construct_widgets (GtkPrinterOptionWidget *widget); -static void update_widgets (GtkPrinterOptionWidget *widget); +static void construct_widgets (GtkPrinterOptionWidget *widget); +static void update_widgets (GtkPrinterOptionWidget *widget); + +static gchar *trim_long_filename (const gchar *filename); struct GtkPrinterOptionWidgetPrivate { GtkPrinterOption *source; gulong source_changed_handler; - + GtkWidget *check; GtkWidget *combo; GtkWidget *entry; GtkWidget *image; GtkWidget *label; - GtkWidget *filechooser; + GtkWidget *info_label; GtkWidget *box; + GtkWidget *button; + + /* the last location for save to file, that the user selected */ + gchar *last_location; }; enum { @@ -73,12 +82,12 @@ enum { enum { PROP_0, - PROP_SOURCE, + PROP_SOURCE }; static guint signals[LAST_SIGNAL] = { 0 }; -G_DEFINE_TYPE (GtkPrinterOptionWidget, gtk_printer_option_widget, GTK_TYPE_HBOX) +G_DEFINE_TYPE (GtkPrinterOptionWidget, gtk_printer_option_widget, GTK_TYPE_BOX) static void gtk_printer_option_widget_set_property (GObject *object, guint prop_id, @@ -89,7 +98,7 @@ static void gtk_printer_option_widget_get_property (GObject *object, GValue *value, GParamSpec *pspec); static gboolean gtk_printer_option_widget_mnemonic_activate (GtkWidget *widget, - gboolean group_cycling); + gboolean group_cycling); static void gtk_printer_option_widget_class_init (GtkPrinterOptionWidgetClass *class) @@ -106,7 +115,7 @@ gtk_printer_option_widget_class_init (GtkPrinterOptionWidgetClass *class) widget_class->mnemonic_activate = gtk_printer_option_widget_mnemonic_activate; - g_type_class_add_private (class, sizeof (GtkPrinterOptionWidgetPrivate)); + g_type_class_add_private (class, sizeof (GtkPrinterOptionWidgetPrivate)); signals[CHANGED] = g_signal_new ("changed", @@ -204,6 +213,8 @@ gtk_printer_option_widget_mnemonic_activate (GtkWidget *widget, return gtk_widget_mnemonic_activate (priv->combo, group_cycling); if (priv->entry) return gtk_widget_mnemonic_activate (priv->entry, group_cycling); + if (priv->button) + return gtk_widget_mnemonic_activate (priv->button, group_cycling); return FALSE; } @@ -288,11 +299,11 @@ static GtkWidget * combo_box_entry_new (void) { GtkWidget *combo_box; - combo_box = gtk_combo_box_entry_new (); + combo_box = g_object_new (GTK_TYPE_COMBO_BOX, "has-entry", TRUE, NULL); combo_box_set_model (combo_box); - gtk_combo_box_entry_set_text_column (GTK_COMBO_BOX_ENTRY (combo_box), NAME_COLUMN); + gtk_combo_box_set_entry_text_column (GTK_COMBO_BOX (combo_box), NAME_COLUMN); return combo_box; } @@ -367,25 +378,52 @@ combo_box_set (GtkWidget *combo, gtk_tree_model_foreach (model, set_cb, &set_data); } -static char * -combo_box_get (GtkWidget *combo) +static gchar * +combo_box_get (GtkWidget *combo, gboolean *custom) { GtkTreeModel *model; gchar *value; GtkTreeIter iter; - if (GTK_IS_COMBO_BOX_ENTRY (combo)) + model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo)); + + value = NULL; + if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (combo), &iter)) { - value = gtk_combo_box_get_active_text(GTK_COMBO_BOX (combo)); + gtk_tree_model_get (model, &iter, VALUE_COLUMN, &value, -1); + *custom = FALSE; } else { - model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo)); + if (gtk_combo_box_get_has_entry (GTK_COMBO_BOX (combo))) + { + value = g_strdup (gtk_entry_get_text (GTK_ENTRY (gtk_bin_get_child (GTK_BIN (combo))))); + *custom = TRUE; + } - value = NULL; - if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (combo), &iter)) - gtk_tree_model_get (model, &iter, VALUE_COLUMN, &value, -1); - } + if (!value || !gtk_tree_model_get_iter_first (model, &iter)) + return value; + + /* If the user entered an item from the dropdown list manually, return + * the non-custom option instead. */ + do + { + gchar *val, *name; + gtk_tree_model_get (model, &iter, VALUE_COLUMN, &val, + NAME_COLUMN, &name, -1); + if (g_str_equal (value, name)) + { + *custom = FALSE; + g_free (name); + g_free (value); + return val; + } + + g_free (val); + g_free (name); + } + while (gtk_tree_model_iter_next (model, &iter)); + } return value; } @@ -414,14 +452,6 @@ deconstruct_widgets (GtkPrinterOptionWidget *widget) priv->entry = NULL; } - /* make sure entry and combo are destroyed first */ - /* as we use the two of them to create the filechooser */ - if (priv->filechooser) - { - gtk_widget_destroy (priv->filechooser); - priv->filechooser = NULL; - } - if (priv->image) { gtk_widget_destroy (priv->image); @@ -433,6 +463,11 @@ deconstruct_widgets (GtkPrinterOptionWidget *widget) gtk_widget_destroy (priv->label); priv->label = NULL; } + if (priv->info_label) + { + gtk_widget_destroy (priv->info_label); + priv->info_label = NULL; + } } static void @@ -449,56 +484,100 @@ check_toggled_cb (GtkToggleButton *toggle_button, } static void -filesave_changed_cb (GtkWidget *button, - GtkPrinterOptionWidget *widget) +dialog_response_callback (GtkDialog *dialog, + gint response_id, + GtkPrinterOptionWidget *widget) { GtkPrinterOptionWidgetPrivate *priv = widget->priv; - gchar *uri, *file; + gchar *uri = NULL; + gchar *new_location = NULL; - /* TODO: how do we support nonlocal file systems? */ - file = g_filename_from_utf8 (gtk_entry_get_text (GTK_ENTRY (priv->entry)), - -1, NULL, NULL, NULL); - if (file == NULL) - return; + if (response_id == GTK_RESPONSE_ACCEPT) + { + gchar *filename; + gchar *filename_utf8; + gchar *filename_short; + + new_location = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (dialog)); + + filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog)); + filename_utf8 = g_filename_to_utf8 (filename, -1, NULL, NULL, NULL); + filename_short = trim_long_filename (filename_utf8); + gtk_button_set_label (GTK_BUTTON (priv->button), filename_short); + g_free (filename_short); + g_free (filename_utf8); + g_free (filename); + } - /* combine the value of the chooser with the value of the entry */ - g_signal_handler_block (priv->source, priv->source_changed_handler); + gtk_widget_destroy (GTK_WIDGET (dialog)); - if (g_path_is_absolute (file)) - uri = g_filename_to_uri (file, NULL, NULL); + if (new_location) + uri = new_location; else + uri = priv->last_location; + + if (uri) { - gchar *path; + gtk_printer_option_set (priv->source, uri); + emit_changed (widget); + } -#ifdef G_OS_UNIX - if (file[0] == '~' && file[1] == '/') - { - path = g_build_filename (g_get_home_dir (), file + 2, NULL); - } - else -#endif - { - gchar *directory; + g_free (new_location); + g_free (priv->last_location); + priv->last_location = NULL; - directory = gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (priv->combo)); - path = g_build_filename (directory, file, NULL); + /* unblock the handler which was blocked in the filesave_choose_cb function */ + g_signal_handler_unblock (priv->source, priv->source_changed_handler); +} - g_free (directory); - } +static void +filesave_choose_cb (GtkWidget *button, + GtkPrinterOptionWidget *widget) +{ + GtkPrinterOptionWidgetPrivate *priv = widget->priv; + gchar *last_location = NULL; + GtkWidget *dialog; + GtkWindow *toplevel; - uri = g_filename_to_uri (path, NULL, NULL); + /* this will be unblocked in the dialog_response_callback function */ + g_signal_handler_block (priv->source, priv->source_changed_handler); - g_free (path); - } + toplevel = GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (widget))); + dialog = gtk_file_chooser_dialog_new (_("Select a filename"), + toplevel, + GTK_FILE_CHOOSER_ACTION_SAVE, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + _("_Select"), GTK_RESPONSE_ACCEPT, + NULL); - if (uri) - gtk_printer_option_set (priv->source, uri); + /* The confirmation dialog will appear, when the user clicks print */ + gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), FALSE); - g_free (uri); - g_free (file); + /* select the current filename in the dialog */ + if (priv->source != NULL) + { + priv->last_location = last_location = g_strdup (priv->source->value); + if (last_location) + { + GFile *file; + gchar *basename; + gchar *basename_utf8; + + gtk_file_chooser_select_uri (GTK_FILE_CHOOSER (dialog), last_location); + file = g_file_new_for_uri (last_location); + basename = g_file_get_basename (file); + basename_utf8 = g_filename_to_utf8 (basename, -1, NULL, NULL, NULL); + gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), basename_utf8); + g_free (basename_utf8); + g_free (basename); + g_object_unref (file); + } + } - g_signal_handler_unblock (priv->source, priv->source_changed_handler); - emit_changed (widget); + g_signal_connect (dialog, "response", + G_CALLBACK (dialog_response_callback), widget); + gtk_window_set_modal (GTK_WINDOW (dialog), TRUE); + gtk_window_present (GTK_WINDOW (dialog)); } static gchar * @@ -553,25 +632,29 @@ combo_changed_cb (GtkWidget *combo, gchar *value; gchar *filtered_val = NULL; gboolean changed; + gboolean custom = TRUE; g_signal_handler_block (priv->source, priv->source_changed_handler); - value = combo_box_get (combo); + value = combo_box_get (combo, &custom); - /* handle some constraints */ - switch (priv->source->type) + /* Handle constraints if the user entered a custom value. */ + if (custom) { - case GTK_PRINTER_OPTION_TYPE_PICKONE_PASSCODE: - filtered_val = filter_numeric (value, FALSE, FALSE, &changed); - break; - case GTK_PRINTER_OPTION_TYPE_PICKONE_INT: - filtered_val = filter_numeric (value, TRUE, FALSE, &changed); - break; - case GTK_PRINTER_OPTION_TYPE_PICKONE_REAL: - filtered_val = filter_numeric (value, TRUE, TRUE, &changed); - break; - default: - break; + switch (priv->source->type) + { + case GTK_PRINTER_OPTION_TYPE_PICKONE_PASSCODE: + filtered_val = filter_numeric (value, FALSE, FALSE, &changed); + break; + case GTK_PRINTER_OPTION_TYPE_PICKONE_INT: + filtered_val = filter_numeric (value, TRUE, FALSE, &changed); + break; + case GTK_PRINTER_OPTION_TYPE_PICKONE_REAL: + filtered_val = filter_numeric (value, TRUE, TRUE, &changed); + break; + default: + break; + } } if (filtered_val) @@ -679,12 +762,14 @@ construct_widgets (GtkPrinterOptionWidget *widget) deconstruct_widgets (widget); + gtk_widget_set_sensitive (GTK_WIDGET (widget), TRUE); + if (source == NULL) { priv->combo = combo_box_new (); combo_box_append (priv->combo,_("Not available"), "None"); gtk_combo_box_set_active (GTK_COMBO_BOX (priv->combo), 0); - gtk_widget_set_sensitive (priv->combo, FALSE); + gtk_widget_set_sensitive (GTK_WIDGET (widget), FALSE); gtk_widget_show (priv->combo); gtk_box_pack_start (GTK_BOX (widget), priv->combo, TRUE, TRUE, 0); } @@ -720,12 +805,11 @@ construct_widgets (GtkPrinterOptionWidget *widget) gtk_entry_set_visibility (entry, FALSE); } } - for (i = 0; i < source->num_choices; i++) - combo_box_append (priv->combo, - source->choices_display[i], - source->choices[i]); + combo_box_append (priv->combo, + source->choices_display[i], + source->choices[i]); gtk_widget_show (priv->combo); gtk_box_pack_start (GTK_BOX (widget), priv->combo, TRUE, TRUE, 0); g_signal_connect (priv->combo, "changed", G_CALLBACK (combo_changed_cb), widget); @@ -738,15 +822,20 @@ construct_widgets (GtkPrinterOptionWidget *widget) case GTK_PRINTER_OPTION_TYPE_ALTERNATIVE: group = NULL; - priv->box = gtk_hbox_new (FALSE, 12); + priv->box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12); gtk_widget_show (priv->box); gtk_box_pack_start (GTK_BOX (widget), priv->box, TRUE, TRUE, 0); for (i = 0; i < source->num_choices; i++) - group = alternative_append (priv->box, - source->choices_display[i], - source->choices[i], - widget, - group); + { + group = alternative_append (priv->box, + source->choices_display[i], + source->choices[i], + widget, + group); + /* for mnemonic activation */ + if (i == 0) + priv->button = group->data; + } if (source->display_text) { @@ -759,6 +848,8 @@ construct_widgets (GtkPrinterOptionWidget *widget) case GTK_PRINTER_OPTION_TYPE_STRING: priv->entry = gtk_entry_new (); + gtk_entry_set_activates_default (GTK_ENTRY (priv->entry), + gtk_printer_option_get_activates_default (source)); gtk_widget_show (priv->entry); gtk_box_pack_start (GTK_BOX (widget), priv->entry, TRUE, TRUE, 0); g_signal_connect (priv->entry, "changed", G_CALLBACK (entry_changed_cb), widget); @@ -771,50 +862,31 @@ construct_widgets (GtkPrinterOptionWidget *widget) break; case GTK_PRINTER_OPTION_TYPE_FILESAVE: - { - GtkWidget *label; - - priv->filechooser = gtk_table_new (2, 2, FALSE); - gtk_table_set_row_spacings (GTK_TABLE (priv->filechooser), 6); - gtk_table_set_col_spacings (GTK_TABLE (priv->filechooser), 12); - - /* TODO: make this a gtkfilechooserentry once we move to GTK */ - priv->entry = gtk_entry_new (); - priv->combo = gtk_file_chooser_button_new (source->display_text, - GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER); - - label = gtk_label_new_with_mnemonic (_("_Name:")); - gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); - gtk_label_set_mnemonic_widget (GTK_LABEL (label), priv->entry); + priv->button = gtk_button_new (); + gtk_widget_show (priv->button); + gtk_box_pack_start (GTK_BOX (widget), priv->button, TRUE, TRUE, 0); + g_signal_connect (priv->button, "clicked", G_CALLBACK (filesave_choose_cb), widget); - gtk_table_attach (GTK_TABLE (priv->filechooser), label, - 0, 1, 0, 1, GTK_FILL, 0, - 0, 0); - - gtk_table_attach (GTK_TABLE (priv->filechooser), priv->entry, - 1, 2, 0, 1, GTK_FILL, 0, - 0, 0); - - label = gtk_label_new_with_mnemonic (_("_Save in folder:")); - gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); - gtk_label_set_mnemonic_widget (GTK_LABEL (label), priv->combo); - - gtk_table_attach (GTK_TABLE (priv->filechooser), label, - 0, 1, 1, 2, GTK_FILL, 0, - 0, 0); + text = g_strdup_printf ("%s:", source->display_text); + priv->label = gtk_label_new_with_mnemonic (text); + g_free (text); + gtk_widget_show (priv->label); - gtk_table_attach (GTK_TABLE (priv->filechooser), priv->combo, - 1, 2, 1, 2, GTK_FILL, 0, - 0, 0); + break; - gtk_widget_show_all (priv->filechooser); - gtk_box_pack_start (GTK_BOX (widget), priv->filechooser, TRUE, TRUE, 0); + case GTK_PRINTER_OPTION_TYPE_INFO: + priv->info_label = gtk_label_new (NULL); + gtk_label_set_selectable (GTK_LABEL (priv->info_label), TRUE); + gtk_widget_show (priv->info_label); + gtk_box_pack_start (GTK_BOX (widget), priv->info_label, FALSE, TRUE, 0); - g_signal_connect (priv->entry, "changed", G_CALLBACK (filesave_changed_cb), widget); + text = g_strdup_printf ("%s:", source->display_text); + priv->label = gtk_label_new_with_mnemonic (text); + g_free (text); + gtk_widget_show (priv->label); - g_signal_connect (priv->combo, "current-folder-changed", G_CALLBACK (filesave_changed_cb), widget); - } break; + default: break; } @@ -823,6 +895,45 @@ construct_widgets (GtkPrinterOptionWidget *widget) gtk_box_pack_start (GTK_BOX (widget), priv->image, FALSE, FALSE, 0); } +/** + * If the filename exceeds FILENAME_LENGTH_MAX, then trim it and replace + * the first three letters with three dots. + */ +static gchar * +trim_long_filename (const gchar *filename) +{ + const gchar *home; + gint len, offset; + gchar *result; + + home = g_get_home_dir (); + if (g_str_has_prefix (filename, home)) + { + gchar *homeless_filename; + + offset = g_utf8_strlen (home, -1); + len = g_utf8_strlen (filename, -1); + homeless_filename = g_utf8_substring (filename, offset, len); + result = g_strconcat ("~", homeless_filename, NULL); + g_free (homeless_filename); + } + else + result = g_strdup (filename); + + len = g_utf8_strlen (result, -1); + if (len > FILENAME_LENGTH_MAX) + { + gchar *suffix; + + suffix = g_utf8_substring (result, len - FILENAME_LENGTH_MAX, len); + g_free (result); + result = g_strconcat ("...", suffix, NULL); + g_free (suffix); + } + + return result; +} + static void update_widgets (GtkPrinterOptionWidget *widget) { @@ -840,7 +951,7 @@ update_widgets (GtkPrinterOptionWidget *widget) switch (source->type) { case GTK_PRINTER_OPTION_TYPE_BOOLEAN: - if (strcmp (source->value, "True") == 0) + if (g_ascii_strcasecmp (source->value, "True") == 0) gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->check), TRUE); else gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->check), FALSE); @@ -854,31 +965,50 @@ update_widgets (GtkPrinterOptionWidget *widget) case GTK_PRINTER_OPTION_TYPE_STRING: gtk_entry_set_text (GTK_ENTRY (priv->entry), source->value); break; + case GTK_PRINTER_OPTION_TYPE_PICKONE_PASSWORD: + case GTK_PRINTER_OPTION_TYPE_PICKONE_PASSCODE: + case GTK_PRINTER_OPTION_TYPE_PICKONE_REAL: + case GTK_PRINTER_OPTION_TYPE_PICKONE_INT: + case GTK_PRINTER_OPTION_TYPE_PICKONE_STRING: + { + GtkEntry *entry; + + entry = GTK_ENTRY (gtk_bin_get_child (GTK_BIN (priv->combo))); + if (gtk_printer_option_has_choice (source, source->value)) + combo_box_set (priv->combo, source->value); + else + gtk_entry_set_text (entry, source->value); + + break; + } case GTK_PRINTER_OPTION_TYPE_FILESAVE: { - gchar *filename = g_filename_from_uri (source->value, NULL, NULL); + gchar *text; + gchar *filename; + + filename = g_filename_from_uri (source->value, NULL, NULL); if (filename != NULL) { - gchar *basename, *dirname, *text; + text = g_filename_to_utf8 (filename, -1, NULL, NULL, NULL); + if (text != NULL) + { + gchar *short_filename; - basename = g_path_get_basename (filename); - dirname = g_path_get_dirname (filename); - text = g_filename_to_utf8 (basename, -1, NULL, NULL, NULL); + short_filename = trim_long_filename (text); + gtk_button_set_label (GTK_BUTTON (priv->button), short_filename); + g_free (short_filename); + } - if (text != NULL) - gtk_entry_set_text (GTK_ENTRY (priv->entry), basename); - if (g_path_is_absolute (dirname)) - gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (priv->combo), - dirname); g_free (text); - g_free (basename); - g_free (dirname); g_free (filename); } - else - gtk_entry_set_text (GTK_ENTRY (priv->entry), source->value); - break; + else + gtk_button_set_label (GTK_BUTTON (priv->button), source->value); + break; } + case GTK_PRINTER_OPTION_TYPE_INFO: + gtk_label_set_text (GTK_LABEL (priv->info_label), source->value); + break; default: break; } @@ -908,9 +1038,6 @@ gtk_printer_option_widget_get_value (GtkPrinterOptionWidget *widget) if (priv->source) return priv->source->value; - + return ""; } - -#define __GTK_PRINTER_OPTION_WIDGET_C__ -#include "gtkaliasdef.c"