| /* testfilechooser.c |
| * Copyright (C) 2003 Red Hat, Inc. |
| * Author: Owen Taylor |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Library General Public |
| * License as published by the Free Software Foundation; either |
| * version 2 of the License, or (at your option) any later version. |
| * |
| * This library 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 |
| * Library General Public License for more details. |
| * |
| * You should have received a copy of the GNU Library General Public |
| * License along with this library. If not, see <http://www.gnu.org/licenses/>. |
| */ |
| #include "config.h" |
| |
| #include <string.h> |
| #include <sys/types.h> |
| #include <sys/stat.h> |
| #include <stdlib.h> |
| #include <time.h> |
| #ifdef HAVE_UNISTD_H |
| #include <unistd.h> |
| #endif |
| #include <gtk/gtk.h> |
| |
| #ifdef G_OS_WIN32 |
| # include <io.h> |
| # define localtime_r(t,b) *(b) = *localtime (t) |
| # ifndef S_ISREG |
| # define S_ISREG(m) ((m) & _S_IFREG) |
| # endif |
| #endif |
| |
| #if 0 |
| static GtkWidget *preview_label; |
| static GtkWidget *preview_image; |
| #endif |
| static GtkFileChooserAction action; |
| |
| static void |
| response_cb (GtkDialog *dialog, |
| int response_id, |
| gpointer data) |
| { |
| gboolean *done = data; |
| |
| if (response_id == GTK_RESPONSE_OK) |
| { |
| GListModel *files; |
| guint i, n; |
| |
| files = gtk_file_chooser_get_files (GTK_FILE_CHOOSER (dialog)); |
| n = g_list_model_get_n_items (files); |
| |
| g_print ("Selected files:\n"); |
| for (i = 0; i < n; i++) |
| { |
| GFile *file = g_list_model_get_item (files, i); |
| char *uri = g_file_get_uri (file); |
| g_print (" %s\n", uri ? uri : "(null)"); |
| g_free (uri); |
| g_object_unref (file); |
| } |
| |
| g_object_unref (files); |
| } |
| else |
| g_print ("Dialog was closed\n"); |
| |
| *done = TRUE; |
| |
| g_main_context_wakeup (NULL); |
| } |
| |
| static void |
| filter_changed (GtkFileChooserDialog *dialog, |
| gpointer data) |
| { |
| g_print ("file filter changed\n"); |
| } |
| |
| #include <stdio.h> |
| #include <errno.h> |
| #define _(s) (s) |
| |
| |
| static void |
| set_current_folder (GtkFileChooser *chooser, |
| const char *name) |
| { |
| GFile *file = g_file_new_for_path (name); |
| if (!gtk_file_chooser_set_current_folder (chooser, file, NULL)) |
| { |
| GtkWidget *dialog; |
| |
| dialog = gtk_message_dialog_new (GTK_WINDOW (chooser), |
| GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, |
| GTK_MESSAGE_ERROR, |
| GTK_BUTTONS_CLOSE, |
| "Could not set the folder to %s", |
| name); |
| gtk_widget_show (dialog); |
| g_signal_connect (dialog, "response", |
| G_CALLBACK (gtk_window_destroy), |
| NULL); |
| } |
| g_object_unref (file); |
| } |
| |
| static void |
| set_folder_nonexistent_cb (GtkButton *button, |
| GtkFileChooser *chooser) |
| { |
| set_current_folder (chooser, "/nonexistent"); |
| } |
| |
| static void |
| set_folder_existing_nonexistent_cb (GtkButton *button, |
| GtkFileChooser *chooser) |
| { |
| set_current_folder (chooser, "/usr/nonexistent"); |
| } |
| |
| static void |
| set_filename (GtkFileChooser *chooser, |
| const char *name) |
| { |
| GFile *file = g_file_new_for_path (name); |
| if (!gtk_file_chooser_set_file (chooser, file, NULL)) |
| { |
| GtkWidget *dialog; |
| |
| dialog = gtk_message_dialog_new (GTK_WINDOW (chooser), |
| GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, |
| GTK_MESSAGE_ERROR, |
| GTK_BUTTONS_CLOSE, |
| "Could not select %s", |
| name); |
| gtk_widget_show (dialog); |
| g_signal_connect (dialog, "response", |
| G_CALLBACK (gtk_window_destroy), |
| NULL); |
| } |
| g_object_unref (file); |
| } |
| |
| static void |
| set_filename_nonexistent_cb (GtkButton *button, |
| GtkFileChooser *chooser) |
| { |
| set_filename (chooser, "/nonexistent"); |
| } |
| |
| static void |
| set_filename_existing_nonexistent_cb (GtkButton *button, |
| GtkFileChooser *chooser) |
| { |
| set_filename (chooser, "/usr/nonexistent"); |
| } |
| |
| static void |
| get_selection_cb (GtkButton *button, |
| GtkFileChooser *chooser) |
| { |
| GListModel *selection; |
| guint i, n; |
| |
| selection = gtk_file_chooser_get_files (chooser); |
| n = g_list_model_get_n_items (selection); |
| |
| g_print ("Selection: "); |
| |
| for (i = 0; i < n; i++) |
| { |
| GFile *file = g_list_model_get_item (selection, i); |
| char *uri = g_file_get_uri (file); |
| g_print ("%s\n", uri); |
| g_free (uri); |
| g_object_unref (file); |
| } |
| |
| g_object_unref (selection); |
| } |
| |
| static void |
| get_current_name_cb (GtkButton *button, |
| GtkFileChooser *chooser) |
| { |
| char *name; |
| |
| name = gtk_file_chooser_get_current_name (chooser); |
| g_print ("Current name: %s\n", name ? name : "NULL"); |
| g_free (name); |
| } |
| |
| static void |
| unmap_and_remap_cb (GtkButton *button, |
| GtkFileChooser *chooser) |
| { |
| gtk_widget_hide (GTK_WIDGET (chooser)); |
| gtk_widget_show (GTK_WIDGET (chooser)); |
| } |
| |
| static void |
| kill_dependent (GtkWindow *win, GtkWidget *dep) |
| { |
| gtk_window_destroy (GTK_WINDOW (dep)); |
| } |
| |
| int |
| main (int argc, char **argv) |
| { |
| GtkWidget *control_window; |
| GtkWidget *vbbox; |
| GtkWidget *button; |
| GtkWidget *dialog; |
| GtkFileFilter *filter; |
| gboolean force_rtl = FALSE; |
| gboolean multiple = FALSE; |
| char *action_arg = NULL; |
| char *initial_filename = NULL; |
| char *initial_folder = NULL; |
| GFile *file; |
| GError *error = NULL; |
| GOptionEntry options[] = { |
| { "action", 'a', 0, G_OPTION_ARG_STRING, &action_arg, "Filechooser action", "ACTION" }, |
| { "multiple", 'm', 0, G_OPTION_ARG_NONE, &multiple, "Select multiple", NULL }, |
| { "right-to-left", 'r', 0, G_OPTION_ARG_NONE, &force_rtl, "Force right-to-left layout.", NULL }, |
| { "initial-filename", 'f', 0, G_OPTION_ARG_FILENAME, &initial_filename, "Initial filename to select", "FILENAME" }, |
| { "initial-folder", 'F', 0, G_OPTION_ARG_FILENAME, &initial_folder, "Initial folder to show", "FILENAME" }, |
| { NULL } |
| }; |
| GOptionContext *context; |
| gboolean done = FALSE; |
| |
| context = g_option_context_new (""); |
| g_option_context_add_main_entries (context, options, NULL); |
| if (!g_option_context_parse (context, &argc, &argv, &error)) |
| { |
| g_print ("Failed to parse args: %s\n", error->message); |
| g_error_free (error); |
| return 1; |
| } |
| g_option_context_free (context); |
| |
| gtk_init (); |
| |
| if (initial_filename && initial_folder) |
| { |
| g_print ("Only one of --initial-filename and --initial-folder may be specified"); |
| return 1; |
| } |
| |
| if (force_rtl) |
| gtk_widget_set_default_direction (GTK_TEXT_DIR_RTL); |
| |
| action = GTK_FILE_CHOOSER_ACTION_OPEN; |
| |
| if (action_arg != NULL) |
| { |
| if (! strcmp ("open", action_arg)) |
| action = GTK_FILE_CHOOSER_ACTION_OPEN; |
| else if (! strcmp ("save", action_arg)) |
| action = GTK_FILE_CHOOSER_ACTION_SAVE; |
| else if (! strcmp ("select_folder", action_arg)) |
| action = GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER; |
| else |
| { |
| g_print ("--action must be one of \"open\", \"save\", \"select_folder\"\n"); |
| return 1; |
| } |
| |
| g_free (action_arg); |
| } |
| |
| dialog = g_object_new (GTK_TYPE_FILE_CHOOSER_DIALOG, |
| "action", action, |
| "select-multiple", multiple, |
| NULL); |
| |
| switch (action) |
| { |
| case GTK_FILE_CHOOSER_ACTION_OPEN: |
| case GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER: |
| gtk_window_set_title (GTK_WINDOW (dialog), "Select a file"); |
| gtk_dialog_add_buttons (GTK_DIALOG (dialog), |
| _("_Cancel"), GTK_RESPONSE_CANCEL, |
| _("_Open"), GTK_RESPONSE_OK, |
| NULL); |
| break; |
| case GTK_FILE_CHOOSER_ACTION_SAVE: |
| gtk_window_set_title (GTK_WINDOW (dialog), "Save a file"); |
| gtk_dialog_add_buttons (GTK_DIALOG (dialog), |
| _("_Cancel"), GTK_RESPONSE_CANCEL, |
| _("_Save"), GTK_RESPONSE_OK, |
| NULL); |
| break; |
| default: |
| g_assert_not_reached (); |
| } |
| gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK); |
| |
| g_signal_connect (dialog, "response", |
| G_CALLBACK (response_cb), &done); |
| |
| /* Filters */ |
| filter = gtk_file_filter_new (); |
| gtk_file_filter_set_name (filter, "All Files"); |
| gtk_file_filter_add_pattern (filter, "*"); |
| gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter); |
| |
| /* Make this filter the default */ |
| gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (dialog), filter); |
| g_object_unref (filter); |
| |
| filter = gtk_file_filter_new (); |
| gtk_file_filter_set_name (filter, "Starts with D"); |
| gtk_file_filter_add_pattern (filter, "D*"); |
| gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter); |
| g_object_unref (filter); |
| |
| g_signal_connect (dialog, "notify::filter", |
| G_CALLBACK (filter_changed), NULL); |
| |
| filter = gtk_file_filter_new (); |
| gtk_file_filter_set_name (filter, "PNG and JPEG"); |
| gtk_file_filter_add_mime_type (filter, "image/jpeg"); |
| gtk_file_filter_add_mime_type (filter, "image/png"); |
| gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter); |
| g_object_unref (filter); |
| |
| filter = gtk_file_filter_new (); |
| gtk_file_filter_set_name (filter, "Images"); |
| gtk_file_filter_add_pixbuf_formats (filter); |
| gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter); |
| g_object_unref (filter); |
| |
| /* Choices */ |
| |
| gtk_file_chooser_add_choice (GTK_FILE_CHOOSER (dialog), "choice1", |
| "Choose one:", |
| (const char *[]){"one", "two", "three", NULL}, |
| (const char *[]){"One", "Two", "Three", NULL}); |
| gtk_file_chooser_set_choice (GTK_FILE_CHOOSER (dialog), "choice1", "two"); |
| |
| /* Shortcuts */ |
| |
| file = g_file_new_for_uri ("file:///usr/share/pixmaps"); |
| gtk_file_chooser_add_shortcut_folder (GTK_FILE_CHOOSER (dialog), file, NULL); |
| g_object_unref (file); |
| |
| file = g_file_new_for_path (g_get_user_special_dir (G_USER_DIRECTORY_MUSIC)); |
| gtk_file_chooser_add_shortcut_folder (GTK_FILE_CHOOSER (dialog), file, NULL); |
| g_object_unref (file); |
| |
| /* Initial filename or folder */ |
| |
| if (initial_filename) |
| set_filename (GTK_FILE_CHOOSER (dialog), initial_filename); |
| |
| if (initial_folder) |
| set_current_folder (GTK_FILE_CHOOSER (dialog), initial_folder); |
| |
| /* show_all() to reveal bugs in composite widget handling */ |
| gtk_widget_show (dialog); |
| |
| /* Extra controls for manipulating the test environment |
| */ |
| |
| control_window = gtk_window_new (); |
| |
| vbbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); |
| gtk_window_set_child (GTK_WINDOW (control_window), vbbox); |
| |
| button = gtk_button_new_with_label ("set_current_folder (\"/nonexistent\")"); |
| gtk_box_append (GTK_BOX (vbbox), button); |
| g_signal_connect (button, "clicked", |
| G_CALLBACK (set_folder_nonexistent_cb), dialog); |
| |
| button = gtk_button_new_with_label ("set_current_folder (\"/usr/nonexistent\")"); |
| gtk_box_append (GTK_BOX (vbbox), button); |
| g_signal_connect (button, "clicked", |
| G_CALLBACK (set_folder_existing_nonexistent_cb), dialog); |
| |
| button = gtk_button_new_with_label ("set_filename (\"/nonexistent\")"); |
| gtk_box_append (GTK_BOX (vbbox), button); |
| g_signal_connect (button, "clicked", |
| G_CALLBACK (set_filename_nonexistent_cb), dialog); |
| |
| button = gtk_button_new_with_label ("set_filename (\"/usr/nonexistent\")"); |
| gtk_box_append (GTK_BOX (vbbox), button); |
| g_signal_connect (button, "clicked", |
| G_CALLBACK (set_filename_existing_nonexistent_cb), dialog); |
| |
| button = gtk_button_new_with_label ("Get selection"); |
| gtk_box_append (GTK_BOX (vbbox), button); |
| g_signal_connect (button, "clicked", |
| G_CALLBACK (get_selection_cb), dialog); |
| |
| button = gtk_button_new_with_label ("Get current name"); |
| gtk_box_append (GTK_BOX (vbbox), button); |
| g_signal_connect (button, "clicked", |
| G_CALLBACK (get_current_name_cb), dialog); |
| |
| button = gtk_button_new_with_label ("Unmap and remap"); |
| gtk_box_append (GTK_BOX (vbbox), button); |
| g_signal_connect (button, "clicked", |
| G_CALLBACK (unmap_and_remap_cb), dialog); |
| |
| gtk_widget_show (control_window); |
| |
| g_signal_connect (dialog, "destroy", |
| G_CALLBACK (kill_dependent), control_window); |
| |
| /* We need to hold a ref until we have destroyed the widgets, just in case |
| * someone else destroys them. We explicitly destroy windows to catch leaks. |
| */ |
| g_object_ref (dialog); |
| while (!done) |
| g_main_context_iteration (NULL, TRUE); |
| gtk_window_destroy (GTK_WINDOW (dialog)); |
| g_object_unref (dialog); |
| |
| return 0; |
| } |