summaryrefslogtreecommitdiff
path: root/gtk
diff options
context:
space:
mode:
authorIan Main <imain@src.gnome.org>1998-01-21 07:53:07 +0000
committerIan Main <imain@src.gnome.org>1998-01-21 07:53:07 +0000
commit325dc92ad470909fba60584f844498bcb40dd9ae (patch)
treed3e1b959bee05ff98cc295361866e0817687bf4b /gtk
parentd1da1a45a08fcfdbd5adaab7540f9d3c2c570174 (diff)
downloadgdk-pixbuf-325dc92ad470909fba60584f844498bcb40dd9ae.tar.gz
New file selection dialog. Converted to use clist, added Mac-like pulldown,
and a few simple file operations. Ian Main <slow@intergate.bc.ca
Diffstat (limited to 'gtk')
-rw-r--r--gtk/gtkfilesel.c972
-rw-r--r--gtk/gtkfilesel.h9
2 files changed, 656 insertions, 325 deletions
diff --git a/gtk/gtkfilesel.c b/gtk/gtkfilesel.c
index f0853cccd..2b100c696 100644
--- a/gtk/gtkfilesel.c
+++ b/gtk/gtkfilesel.c
@@ -39,12 +39,16 @@
#include "gtkscrolledwindow.h"
#include "gtksignal.h"
#include "gtkvbox.h"
+#include "gtkmenu.h"
+#include "gtkmenuitem.h"
+#include "gtkoptionmenu.h"
+#include "gtkclist.h"
+#include "gtkdialog.h"
-
-#define DIR_LIST_WIDTH 160
-#define DIR_LIST_HEIGHT 175
-#define FILE_LIST_WIDTH 160
-#define FILE_LIST_HEIGHT 175
+#define DIR_LIST_WIDTH 180
+#define DIR_LIST_HEIGHT 180
+#define FILE_LIST_WIDTH 180
+#define FILE_LIST_HEIGHT 180
typedef struct _CompletionState CompletionState;
@@ -268,32 +272,38 @@ static void gtk_file_selection_destroy (GtkObject *object);
static gint gtk_file_selection_key_press (GtkWidget *widget,
GdkEventKey *event,
gpointer user_data);
-static gint gtk_file_selection_file_button (GtkWidget *widget,
- GdkEventButton *event,
- gpointer user_data);
-static gint gtk_file_selection_dir_button (GtkWidget *widget,
- GdkEventButton *event,
- gpointer user_data);
-static void gtk_file_selection_file_list_changed (GtkList *gtklist,
- gpointer func_data);
-static void gtk_file_selection_dir_list_changed (GtkList *gtklist,
- gpointer func_data);
+
+static void gtk_file_selection_file_button (GtkWidget *widget,
+ gint row,
+ gint column,
+ GdkEventButton *bevent,
+ gpointer user_data);
+
+static void gtk_file_selection_dir_button (GtkWidget *widget,
+ gint row,
+ gint column,
+ GdkEventButton *bevent,
+ gpointer data);
+
static void gtk_file_selection_populate (GtkFileSelection *fs,
gchar *rel_path,
gint try_complete);
static void gtk_file_selection_abort (GtkFileSelection *fs);
-static void gtk_file_selection_free_filename (GtkWidget *widget,
- gpointer client_data);
+static void gtk_file_selection_update_history_menu (GtkFileSelection *fs,
+ gchar *current_dir);
+
+static void gtk_file_selection_create_dir (GtkWidget *widget, gpointer data);
+static void gtk_file_selection_delete_file (GtkWidget *widget, gpointer data);
+static void gtk_file_selection_rename_file (GtkWidget *widget, gpointer data);
-static GtkWindowClass *parent_class = NULL;
-static gchar *list_changed_key = "_gtk_selection_changed_handler_key";
+
+static GtkWindowClass *parent_class = NULL;
/* Saves errno when something cmpl does fails. */
static gint cmpl_errno;
-
guint
gtk_file_selection_get_type ()
{
@@ -309,7 +319,7 @@ gtk_file_selection_get_type ()
(GtkClassInitFunc) gtk_file_selection_class_init,
(GtkObjectInitFunc) gtk_file_selection_init,
(GtkArgSetFunc) NULL,
- (GtkArgGetFunc) NULL,
+ (GtkArgGetFunc) NULL,
};
file_selection_type = gtk_type_unique (gtk_window_get_type (), &filesel_info);
@@ -333,91 +343,99 @@ gtk_file_selection_class_init (GtkFileSelectionClass *class)
static void
gtk_file_selection_init (GtkFileSelection *filesel)
{
- GtkWidget *dir_vbox;
- GtkWidget *file_vbox;
GtkWidget *entry_vbox;
- GtkWidget *listbox;
GtkWidget *label;
GtkWidget *list_hbox;
GtkWidget *action_area;
- gint key;
-
+ GtkWidget *pulldown_hbox;
+ GtkWidget *button_hbox;
+ GtkWidget *button;
+ char *dir_title [] = { "Directories", };
+ char *file_title [] = { "Files", };
+
filesel->cmpl_state = cmpl_init_state ();
-
- /* The dialog-sized vertical box */
+
+ /* The dialog-sized vertical box */
filesel->main_vbox = gtk_vbox_new (FALSE, 10);
gtk_container_border_width (GTK_CONTAINER (filesel), 10);
gtk_container_add (GTK_CONTAINER (filesel), filesel->main_vbox);
gtk_widget_show (filesel->main_vbox);
+ /* The horizontal box containing create, rename etc. buttons */
+ button_hbox = gtk_hbox_new (TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (filesel->main_vbox), button_hbox,
+ FALSE, FALSE, 0);
+ gtk_widget_show (button_hbox);
+
+ /* delete, create directory, and rename */
+ button = gtk_button_new_with_label ("Create Dir");
+ gtk_signal_connect (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) gtk_file_selection_create_dir,
+ (gpointer) filesel);
+ gtk_box_pack_start (GTK_BOX (button_hbox), button, TRUE, TRUE, 0);
+ gtk_widget_show (button);
+
+ button = gtk_button_new_with_label ("Delete File");
+ gtk_signal_connect (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) gtk_file_selection_delete_file,
+ (gpointer) filesel);
+ gtk_box_pack_start (GTK_BOX (button_hbox), button, TRUE, TRUE, 0);
+ gtk_widget_show (button);
+
+ button = gtk_button_new_with_label ("Rename File");
+ gtk_signal_connect (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) gtk_file_selection_rename_file,
+ (gpointer) filesel);
+ gtk_box_pack_start (GTK_BOX (button_hbox), button, TRUE, TRUE, 0);
+ gtk_widget_show (button);
+
+ /* The Help button */
+ filesel->help_button = gtk_button_new_with_label ("Help");
+ gtk_box_pack_start (GTK_BOX (button_hbox), filesel->help_button,
+ TRUE, TRUE, 5);
+ gtk_widget_show (filesel->help_button);
+
+
+ /* hbox for pulldown menu */
+ pulldown_hbox = gtk_hbox_new (TRUE, 5);
+ gtk_box_pack_start (GTK_BOX (filesel->main_vbox), pulldown_hbox, FALSE, FALSE, 0);
+ gtk_widget_show (pulldown_hbox);
+
+ /* Pulldown menu */
+ filesel->history_pulldown = gtk_option_menu_new ();
+ gtk_widget_show (filesel->history_pulldown);
+ gtk_box_pack_start (GTK_BOX (pulldown_hbox), filesel->history_pulldown,
+ FALSE, FALSE, 0);
+
/* The horizontal box containing the directory and file listboxes */
- list_hbox = gtk_hbox_new (TRUE, 5);
+ list_hbox = gtk_hbox_new (FALSE, 5);
gtk_box_pack_start (GTK_BOX (filesel->main_vbox), list_hbox, TRUE, TRUE, 0);
gtk_widget_show (list_hbox);
-
- /* The directories listbox */
- dir_vbox = gtk_vbox_new (FALSE, 2);
- gtk_box_pack_start (GTK_BOX (list_hbox), dir_vbox, TRUE, TRUE, 0);
- gtk_widget_show (dir_vbox);
-
- label = gtk_label_new ("Directories");
- gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
- gtk_box_pack_start (GTK_BOX (dir_vbox), label, FALSE, FALSE, 0);
- gtk_widget_show (label);
-
- listbox = gtk_scrolled_window_new (NULL, NULL);
- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (listbox),
- GTK_POLICY_AUTOMATIC,
- GTK_POLICY_ALWAYS);
- gtk_box_pack_start (GTK_BOX (dir_vbox), listbox, TRUE, TRUE, 0);
- gtk_widget_set_usize (listbox, DIR_LIST_WIDTH, DIR_LIST_HEIGHT);
- gtk_widget_show (listbox);
-
- filesel->dir_list = gtk_list_new ();
- gtk_list_set_selection_mode (GTK_LIST (filesel->dir_list), GTK_SELECTION_BROWSE);
- gtk_signal_connect (GTK_OBJECT (filesel->dir_list), "button_press_event",
- (GtkSignalFunc) gtk_file_selection_dir_button, filesel);
- key = gtk_signal_connect (GTK_OBJECT (filesel->dir_list),
- "selection_changed",
- (GtkSignalFunc) gtk_file_selection_dir_list_changed,
- filesel);
- gtk_object_set_data (GTK_OBJECT (filesel->dir_list), list_changed_key, (gpointer) key);
- gtk_container_add (GTK_CONTAINER (listbox), filesel->dir_list);
+ /* The directories clist */
+ filesel->dir_list = gtk_clist_new_with_titles (1, dir_title);
+ gtk_widget_set_usize (filesel->dir_list, DIR_LIST_WIDTH, DIR_LIST_HEIGHT);
+ gtk_clist_set_column_width (GTK_CLIST (filesel->dir_list), 0, 150);
+ gtk_signal_connect (GTK_OBJECT (filesel->dir_list), "select_row",
+ (GtkSignalFunc) gtk_file_selection_dir_button,
+ (gpointer) filesel);
+ gtk_clist_set_policy (GTK_CLIST (filesel->dir_list), GTK_POLICY_ALWAYS, GTK_POLICY_AUTOMATIC);
+ gtk_container_border_width (GTK_CONTAINER (filesel->dir_list), 5);
+ gtk_box_pack_start (GTK_BOX (list_hbox), filesel->dir_list, TRUE, TRUE, 0);
gtk_widget_show (filesel->dir_list);
-
- /* The files listbox */
- file_vbox = gtk_vbox_new (FALSE, 2);
- gtk_box_pack_start (GTK_BOX (list_hbox), file_vbox, TRUE, TRUE, 0);
- gtk_widget_show (file_vbox);
-
- label = gtk_label_new ("Files");
- gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
- gtk_box_pack_start (GTK_BOX (file_vbox), label, FALSE, FALSE, 0);
- gtk_widget_show (label);
-
- listbox = gtk_scrolled_window_new (NULL, NULL);
- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (listbox),
- GTK_POLICY_AUTOMATIC,
- GTK_POLICY_ALWAYS);
- gtk_box_pack_start (GTK_BOX (file_vbox), listbox, TRUE, TRUE, 0);
- gtk_widget_set_usize (listbox, FILE_LIST_WIDTH, FILE_LIST_HEIGHT);
- gtk_widget_show (listbox);
-
- filesel->file_list = gtk_list_new ();
- gtk_list_set_selection_mode (GTK_LIST (filesel->file_list), GTK_SELECTION_SINGLE);
- gtk_signal_connect (GTK_OBJECT (filesel->file_list), "button_press_event",
- (GtkSignalFunc) gtk_file_selection_file_button, filesel);
- key = gtk_signal_connect (GTK_OBJECT (filesel->file_list),
- "selection_changed",
- (GtkSignalFunc) gtk_file_selection_file_list_changed,
- filesel);
- gtk_object_set_data (GTK_OBJECT (filesel->file_list), list_changed_key, (gpointer) key);
- gtk_container_add (GTK_CONTAINER (listbox), filesel->file_list);
+ /* The files clist */
+ filesel->file_list = gtk_clist_new_with_titles (1, file_title);
+ gtk_widget_set_usize (filesel->file_list, FILE_LIST_WIDTH, FILE_LIST_HEIGHT);
+ gtk_clist_set_column_width (GTK_CLIST (filesel->file_list), 0, 150);
+ gtk_signal_connect (GTK_OBJECT (filesel->file_list), "select_row",
+ (GtkSignalFunc) gtk_file_selection_file_button,
+ (gpointer) filesel);
+ gtk_clist_set_policy (GTK_CLIST (filesel->file_list), GTK_POLICY_ALWAYS, GTK_POLICY_AUTOMATIC);
+ gtk_container_border_width (GTK_CONTAINER (filesel->file_list), 5);
+ gtk_box_pack_start (GTK_BOX (list_hbox), filesel->file_list, TRUE, TRUE, 0);
gtk_widget_show (filesel->file_list);
-
/* The action area */
action_area = gtk_hbox_new (TRUE, 10);
gtk_box_pack_end (GTK_BOX (filesel->main_vbox), action_area, FALSE, FALSE, 0);
@@ -436,13 +454,6 @@ gtk_file_selection_init (GtkFileSelection *filesel)
gtk_box_pack_start (GTK_BOX (action_area), filesel->cancel_button, TRUE, TRUE, 0);
gtk_widget_show (filesel->cancel_button);
- /* The Help button */
- filesel->help_button = gtk_button_new_with_label ("Help");
- GTK_WIDGET_SET_FLAGS (filesel->help_button, GTK_CAN_DEFAULT);
- gtk_box_pack_start (GTK_BOX (action_area), filesel->help_button, TRUE, TRUE, 0);
- gtk_widget_show (filesel->help_button);
-
-
/* The selection entry widget */
entry_vbox = gtk_vbox_new (FALSE, 2);
gtk_box_pack_end (GTK_BOX (filesel->main_vbox), entry_vbox, FALSE, FALSE, 0);
@@ -562,6 +573,365 @@ gtk_file_selection_destroy (GtkObject *object)
(* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
}
+/* Begin file operations callbacks */
+
+static void
+gtk_file_selection_fileop_error (gchar *error_message)
+{
+ GtkWidget *label;
+ GtkWidget *vbox;
+ GtkWidget *button;
+ GtkWidget *dialog;
+
+ g_return_if_fail (error_message != NULL);
+
+ /* main dialog */
+ dialog = gtk_dialog_new ();
+ /*
+ gtk_signal_connect (GTK_OBJECT (dialog), "destroy",
+ (GtkSignalFunc) gtk_file_selection_fileop_destroy,
+ (gpointer) fs);
+ */
+ gtk_window_set_title (GTK_WINDOW (dialog), "Error");
+ gtk_window_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
+
+ vbox = gtk_vbox_new(FALSE, 0);
+ gtk_container_border_width(GTK_CONTAINER(vbox), 8);
+ gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), vbox,
+ FALSE, FALSE, 0);
+ gtk_widget_show(vbox);
+
+ label = gtk_label_new(error_message);
+ gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.0);
+ gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 5);
+ gtk_widget_show(label);
+
+ /* yes, we free it */
+ g_free (error_message);
+
+ /* close button */
+ button = gtk_button_new_with_label ("Close");
+ gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) gtk_widget_destroy,
+ (gpointer) dialog);
+ gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area),
+ button, TRUE, TRUE, 0);
+ GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
+ gtk_widget_grab_default(button);
+ gtk_widget_show (button);
+
+ gtk_widget_show (dialog);
+}
+
+static void
+gtk_file_selection_fileop_destroy (GtkWidget *widget, gpointer data)
+{
+ GtkFileSelection *fs = data;
+
+ g_return_if_fail (fs != NULL);
+ g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
+
+ fs->fileop_dialog = NULL;
+}
+
+
+static void
+gtk_file_selection_create_dir_confirmed (GtkWidget *widget, gpointer data)
+{
+ GtkFileSelection *fs = data;
+ gchar *dirname;
+ gchar *path;
+ gchar *full_path;
+ gchar *buf;
+ CompletionState *cmpl_state;
+
+ g_return_if_fail (fs != NULL);
+ g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
+
+ dirname = gtk_entry_get_text (GTK_ENTRY (fs->fileop_entry));
+ cmpl_state = (CompletionState*) fs->cmpl_state;
+ path = cmpl_reference_position (cmpl_state);
+
+ full_path = g_strconcat (path, "/", dirname, NULL);
+ if ( (mkdir (full_path, 0755) < 0) )
+ {
+ buf = g_strconcat ("Error creating directory \"", dirname, "\": ",
+ g_strerror(errno), NULL);
+ gtk_file_selection_fileop_error (buf);
+ }
+ g_free (full_path);
+
+ gtk_widget_destroy (fs->fileop_dialog);
+ gtk_file_selection_populate (fs, "", FALSE);
+}
+
+static void
+gtk_file_selection_create_dir (GtkWidget *widget, gpointer data)
+{
+ GtkFileSelection *fs = data;
+ GtkWidget *label;
+ GtkWidget *dialog;
+ GtkWidget *vbox;
+ GtkWidget *button;
+
+ g_return_if_fail (fs != NULL);
+ g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
+
+ if (fs->fileop_dialog)
+ return;
+
+ /* main dialog */
+ fs->fileop_dialog = dialog = gtk_dialog_new ();
+ gtk_signal_connect (GTK_OBJECT (dialog), "destroy",
+ (GtkSignalFunc) gtk_file_selection_fileop_destroy,
+ (gpointer) fs);
+ gtk_window_set_title (GTK_WINDOW (dialog), "Create Directory");
+ gtk_window_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
+ gtk_widget_show (dialog);
+
+ vbox = gtk_vbox_new(FALSE, 0);
+ gtk_container_border_width(GTK_CONTAINER(vbox), 8);
+ gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), vbox,
+ FALSE, FALSE, 0);
+ gtk_widget_show(vbox);
+
+ label = gtk_label_new("Directory name:");
+ gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.0);
+ gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 5);
+ gtk_widget_show(label);
+
+ /* The directory entry widget */
+ fs->fileop_entry = gtk_entry_new ();
+ gtk_box_pack_start (GTK_BOX (vbox), fs->fileop_entry,
+ TRUE, TRUE, 5);
+ GTK_WIDGET_SET_FLAGS(fs->fileop_entry, GTK_CAN_DEFAULT);
+ gtk_widget_show (fs->fileop_entry);
+
+ /* buttons */
+ button = gtk_button_new_with_label ("Create");
+ gtk_signal_connect (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) gtk_file_selection_create_dir_confirmed,
+ (gpointer) fs);
+ gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area),
+ button, TRUE, TRUE, 0);
+ GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
+ gtk_widget_show(button);
+
+ button = gtk_button_new_with_label ("Cancel");
+ gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) gtk_widget_destroy,
+ (gpointer) dialog);
+ gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area),
+ button, TRUE, TRUE, 0);
+ GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
+ gtk_widget_grab_default(button);
+ gtk_widget_show (button);
+}
+
+static void
+gtk_file_selection_delete_file_confirmed (GtkWidget *widget, gpointer data)
+{
+ GtkFileSelection *fs = data;
+ CompletionState *cmpl_state;
+ gchar *path;
+ gchar *full_path;
+ gchar *buf;
+
+ g_return_if_fail (fs != NULL);
+ g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
+
+ cmpl_state = (CompletionState*) fs->cmpl_state;
+ path = cmpl_reference_position (cmpl_state);
+
+ full_path = g_strconcat (path, "/", fs->fileop_file, NULL);
+ if ( (unlink (full_path) < 0) )
+ {
+ buf = g_strconcat ("Error deleting file \"", fs->fileop_file, "\": ",
+ g_strerror(errno), NULL);
+ gtk_file_selection_fileop_error (buf);
+ }
+ g_free (full_path);
+
+ gtk_widget_destroy (fs->fileop_dialog);
+ gtk_file_selection_populate (fs, "", FALSE);
+}
+
+static void
+gtk_file_selection_delete_file (GtkWidget *widget, gpointer data)
+{
+ GtkFileSelection *fs = data;
+ GtkWidget *label;
+ GtkWidget *vbox;
+ GtkWidget *button;
+ GtkWidget *dialog;
+ gchar *filename;
+ gchar *buf;
+
+ g_return_if_fail (fs != NULL);
+ g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
+
+ if (fs->fileop_dialog)
+ return;
+
+ filename = gtk_entry_get_text (GTK_ENTRY (fs->selection_entry));
+ if (strlen(filename) < 1)
+ return;
+
+ fs->fileop_file = filename;
+
+ /* main dialog */
+ fs->fileop_dialog = dialog = gtk_dialog_new ();
+ gtk_signal_connect (GTK_OBJECT (dialog), "destroy",
+ (GtkSignalFunc) gtk_file_selection_fileop_destroy,
+ (gpointer) fs);
+ gtk_window_set_title (GTK_WINDOW (dialog), "Delete File");
+ gtk_window_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
+
+ vbox = gtk_vbox_new(FALSE, 0);
+ gtk_container_border_width(GTK_CONTAINER(vbox), 8);
+ gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), vbox,
+ FALSE, FALSE, 0);
+ gtk_widget_show(vbox);
+
+ buf = g_strconcat ("Really delete file \"", filename, "\" ?", NULL);
+ label = gtk_label_new(buf);
+ gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.0);
+ gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 5);
+ gtk_widget_show(label);
+ g_free(buf);
+
+ /* buttons */
+ button = gtk_button_new_with_label ("Delete");
+ gtk_signal_connect (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) gtk_file_selection_delete_file_confirmed,
+ (gpointer) fs);
+ gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area),
+ button, TRUE, TRUE, 0);
+ GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
+ gtk_widget_show(button);
+
+ button = gtk_button_new_with_label ("Cancel");
+ gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) gtk_widget_destroy,
+ (gpointer) dialog);
+ gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area),
+ button, TRUE, TRUE, 0);
+ GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
+ gtk_widget_grab_default(button);
+ gtk_widget_show (button);
+
+ gtk_widget_show (dialog);
+}
+
+static void
+gtk_file_selection_rename_file_confirmed (GtkWidget *widget, gpointer data)
+{
+ GtkFileSelection *fs = data;
+ gchar *buf;
+ gchar *file;
+ gchar *path;
+ gchar *new_filename;
+ gchar *old_filename;
+ CompletionState *cmpl_state;
+
+ g_return_if_fail (fs != NULL);
+ g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
+
+ file = gtk_entry_get_text (GTK_ENTRY (fs->fileop_entry));
+ cmpl_state = (CompletionState*) fs->cmpl_state;
+ path = cmpl_reference_position (cmpl_state);
+
+ new_filename = g_strconcat (path, "/", file, NULL);
+ old_filename = g_strconcat (path, "/", fs->fileop_file, NULL);
+
+ if ( (rename (old_filename, new_filename)) < 0)
+ {
+ buf = g_strconcat ("Error renaming file \"", file, "\": ",
+ g_strerror(errno), NULL);
+ gtk_file_selection_fileop_error (buf);
+ }
+ g_free (new_filename);
+ g_free (old_filename);
+
+ gtk_widget_destroy (fs->fileop_dialog);
+ gtk_file_selection_populate (fs, "", FALSE);
+}
+
+static void
+gtk_file_selection_rename_file (GtkWidget *widget, gpointer data)
+{
+ GtkFileSelection *fs = data;
+ GtkWidget *label;
+ GtkWidget *dialog;
+ GtkWidget *vbox;
+ GtkWidget *button;
+ gchar *buf;
+
+ g_return_if_fail (fs != NULL);
+ g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
+
+ if (fs->fileop_dialog)
+ return;
+
+ fs->fileop_file = gtk_entry_get_text (GTK_ENTRY (fs->selection_entry));
+ if (strlen(fs->fileop_file) < 1)
+ return;
+
+ /* main dialog */
+ fs->fileop_dialog = dialog = gtk_dialog_new ();
+ gtk_signal_connect (GTK_OBJECT (dialog), "destroy",
+ (GtkSignalFunc) gtk_file_selection_fileop_destroy,
+ (gpointer) fs);
+ gtk_window_set_title (GTK_WINDOW (dialog), "Rename File");
+ gtk_window_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
+ gtk_widget_show (dialog);
+
+ vbox = gtk_vbox_new(FALSE, 0);
+ gtk_container_border_width(GTK_CONTAINER(vbox), 8);
+ gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), vbox,
+ FALSE, FALSE, 0);
+ gtk_widget_show(vbox);
+
+ buf = g_strconcat ("Rename file \"", fs->fileop_file, "\" to:", NULL);
+ label = gtk_label_new(buf);
+ gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.0);
+ gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 5);
+ gtk_widget_show(label);
+ g_free(buf);
+
+ /* New filename entry */
+ fs->fileop_entry = gtk_entry_new ();
+ gtk_box_pack_start (GTK_BOX (vbox), fs->fileop_entry,
+ TRUE, TRUE, 5);
+ GTK_WIDGET_SET_FLAGS(fs->fileop_entry, GTK_CAN_DEFAULT);
+ gtk_widget_show (fs->fileop_entry);
+
+ gtk_entry_set_text (GTK_ENTRY (fs->fileop_entry), fs->fileop_file);
+ gtk_entry_select_region (GTK_ENTRY (fs->fileop_entry),
+ 0, strlen (fs->fileop_file));
+
+ /* buttons */
+ button = gtk_button_new_with_label ("Rename");
+ gtk_signal_connect (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) gtk_file_selection_rename_file_confirmed,
+ (gpointer) fs);
+ gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area),
+ button, TRUE, TRUE, 0);
+ GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
+ gtk_widget_show(button);
+
+ button = gtk_button_new_with_label ("Cancel");
+ gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) gtk_widget_destroy,
+ (gpointer) dialog);
+ gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area),
+ button, TRUE, TRUE, 0);
+ GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
+ gtk_widget_grab_default(button);
+ gtk_widget_show (button);
+}
+
+
static gint
gtk_file_selection_key_press (GtkWidget *widget,
GdkEventKey *event,
@@ -587,161 +957,179 @@ gtk_file_selection_key_press (GtkWidget *widget,
return FALSE;
}
-static gint
-gtk_file_selection_file_button (GtkWidget *widget,
- GdkEventButton *event,
- gpointer user_data)
-{
- GtkFileSelection *fs;
- GtkWidget *event_widget;
- gchar *filename;
- gboolean handled;
-
- g_return_val_if_fail (widget != NULL, FALSE);
- g_return_val_if_fail (event != NULL, FALSE);
-
- fs = GTK_FILE_SELECTION (user_data);
- g_return_val_if_fail (fs != NULL, FALSE);
- g_return_val_if_fail (GTK_IS_FILE_SELECTION (fs), FALSE);
+typedef struct _HistoryCallbackArg HistoryCallbackArg;
- event_widget = gtk_get_event_widget ((GdkEvent*) event);
- handled = FALSE;
- if (GTK_IS_LIST_ITEM (event_widget))
- {
- switch (event->type)
- {
- case GDK_BUTTON_PRESS:
- filename = gtk_object_get_user_data (GTK_OBJECT (event_widget));
- gtk_widget_grab_focus (fs->selection_entry);
- gtk_entry_set_text (GTK_ENTRY (fs->selection_entry), filename);
- handled = TRUE;
- break;
+struct _HistoryCallbackArg
+{
+ gchar *directory;
+ GtkWidget *menu_item;
+};
- case GDK_2BUTTON_PRESS:
- gtk_button_clicked (GTK_BUTTON (fs->ok_button));
- handled = TRUE;
- break;
+static void
+gtk_file_selection_history_callback (GtkWidget *widget, gpointer data)
+{
+ GtkFileSelection *fs = data;
+ HistoryCallbackArg *callback_arg;
+ GList *list;
- default:
- break;
- }
- }
+ g_return_if_fail (fs != NULL);
+ g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
- return handled;
+ list = fs->history_list;
+
+ while (list) {
+ callback_arg = list->data;
+
+ if (callback_arg->menu_item == widget)
+ {
+ gtk_file_selection_populate (fs, callback_arg->directory, FALSE);
+ break;
+ }
+
+ list = list->next;
+ }
}
-static void
-gtk_file_selection_file_list_changed (GtkList *list,
- gpointer func_data)
+static void
+gtk_file_selection_update_history_menu (GtkFileSelection *fs,
+ gchar *current_directory)
{
- GtkFileSelection *fs;
+ HistoryCallbackArg *callback_arg;
+ GtkWidget *menu_item;
+ GList *list;
+ gchar *current_dir;
+ gchar *directory;
+ gint dir_len;
+ gint i;
+
+ g_return_if_fail (fs != NULL);
+ g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
+ g_return_if_fail (current_directory != NULL);
+
+ list = fs->history_list;
- g_return_if_fail (func_data != NULL);
- g_return_if_fail (GTK_IS_FILE_SELECTION (func_data));
+ if (fs->history_menu)
+ {
+ while (list) {
+ callback_arg = list->data;
+ g_free (callback_arg->directory);
+ list = list->next;
+ }
+ g_list_free (fs->history_list);
+ fs->history_list = NULL;
+
+ gtk_widget_destroy (fs->history_menu);
+ }
+
+ fs->history_menu = gtk_menu_new();
- fs = GTK_FILE_SELECTION (func_data);
+ current_dir = g_strdup(current_directory);
- /* only act on an appropriate selection
- */
- if (list->selection && list->selection->data)
- {
- GtkListItem *item;
+ dir_len = strlen (current_dir);
- item = list->selection->data;
-
- if (GTK_IS_LIST_ITEM (item))
+ for (i = dir_len; i >= 0; i--)
+ {
+ /* the i == dir_len is to catch the full path for the first
+ * entry. */
+ if ( (current_dir[i] == '/') || (i == dir_len))
{
- gchar *filename;
+ /* another small hack to catch the full path */
+ if (i != dir_len)
+ current_dir[i + 1] = '\0';
+ menu_item = gtk_menu_item_new_with_label (current_dir);
+ directory = g_strdup (current_dir);
- filename = gtk_object_get_user_data (GTK_OBJECT (item));
- gtk_entry_set_text (GTK_ENTRY (fs->selection_entry), filename);
+ callback_arg = g_new (HistoryCallbackArg, 1);
+ callback_arg->menu_item = menu_item;
+ callback_arg->directory = directory;
+
+ fs->history_list = g_list_append (fs->history_list, callback_arg);
+
+ gtk_signal_connect (GTK_OBJECT (menu_item), "activate",
+ (GtkSignalFunc) gtk_file_selection_history_callback,
+ (gpointer) fs);
+ gtk_menu_append (GTK_MENU (fs->history_menu), menu_item);
+ gtk_widget_show (menu_item);
}
}
+
+ gtk_option_menu_set_menu (GTK_OPTION_MENU (fs->history_pulldown),
+ fs->history_menu);
+ g_free (current_dir);
}
-static gint
-gtk_file_selection_dir_button (GtkWidget *widget,
- GdkEventButton *event,
- gpointer user_data)
+
+
+static void
+gtk_file_selection_file_button (GtkWidget *widget,
+ gint row,
+ gint column,
+ GdkEventButton *bevent,
+ gpointer user_data)
{
- GtkFileSelection *fs;
- GtkWidget *event_widget;
+ GtkFileSelection *fs = NULL;
gchar *filename;
- gboolean handled;
-
- g_return_val_if_fail (widget != NULL, FALSE);
- g_return_val_if_fail (GTK_IS_LIST (widget), FALSE);
- g_return_val_if_fail (event != NULL, FALSE);
+
+ g_return_if_fail (GTK_IS_CLIST (widget));
fs = GTK_FILE_SELECTION (user_data);
- g_return_val_if_fail (fs != NULL, FALSE);
- g_return_val_if_fail (GTK_IS_FILE_SELECTION (fs), FALSE);
-
- event_widget = gtk_get_event_widget ((GdkEvent*) event);
- handled = FALSE;
- if (GTK_IS_LIST_ITEM (event_widget))
- {
- gint key;
-
- filename = gtk_object_get_user_data (GTK_OBJECT (event_widget));
-
- key = (gint) gtk_object_get_data (GTK_OBJECT (widget), list_changed_key);
-
- switch (event->type)
- {
- case GDK_BUTTON_PRESS:
-
- gtk_signal_handler_block (GTK_OBJECT (widget), key);
- gtk_widget_activate (GTK_WIDGET (event_widget));
- gtk_signal_handler_unblock (GTK_OBJECT (widget), key);
-
- gtk_widget_grab_focus (fs->selection_entry);
- gtk_entry_set_text (GTK_ENTRY (fs->selection_entry), filename);
- handled = TRUE;
- break;
-
- case GDK_2BUTTON_PRESS:
- gtk_file_selection_populate (fs, filename, FALSE);
- handled = TRUE;
- break;
-
- default:
- break;
- }
- }
+ g_return_if_fail (fs != NULL);
+ g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
- return handled;
+ filename = gtk_clist_get_row_data (GTK_CLIST (fs->file_list), row);
+
+ if (bevent && filename) {
+
+ switch (bevent->type)
+ {
+ case GDK_BUTTON_PRESS:
+ gtk_entry_set_text (GTK_ENTRY (fs->selection_entry), filename);
+ break;
+
+ case GDK_2BUTTON_PRESS:
+ gtk_button_clicked (GTK_BUTTON (fs->ok_button));
+ break;
+
+ default:
+ break;
+ }
+ }
}
static void
-gtk_file_selection_dir_list_changed (GtkList *list,
- gpointer func_data)
+gtk_file_selection_dir_button (GtkWidget *widget,
+ gint row,
+ gint column,
+ GdkEventButton *bevent,
+ gpointer user_data)
{
- GtkFileSelection *fs;
-
- g_return_if_fail (func_data != NULL);
- g_return_if_fail (GTK_IS_FILE_SELECTION (func_data));
+ GtkFileSelection *fs = NULL;
+ gchar *filename;
- fs = GTK_FILE_SELECTION (func_data);
+ g_return_if_fail (GTK_IS_CLIST (widget));
- /* only act on an appropriate selection
- */
- if (list->selection && list->selection->data)
- {
- GtkListItem *item;
+ fs = GTK_FILE_SELECTION (user_data);
+ g_return_if_fail (fs != NULL);
+ g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
- item = list->selection->data;
+ filename = gtk_clist_get_row_data (GTK_CLIST (fs->dir_list), row);
+
+ if (bevent && filename) {
+
+ switch (bevent->type)
+ {
+ case GDK_BUTTON_PRESS:
+ gtk_entry_set_text (GTK_ENTRY (fs->selection_entry), filename);
+ break;
- if (GTK_IS_LIST_ITEM (item))
- {
- gchar *filename;
-
- filename = gtk_object_get_user_data (GTK_OBJECT (item));
-
- if (filename)
- gtk_file_selection_populate (fs, filename, FALSE);
- }
- }
+ case GDK_2BUTTON_PRESS:
+ gtk_file_selection_populate (fs, filename, FALSE);
+ break;
+
+ default:
+ break;
+ }
+ }
}
static void
@@ -751,23 +1139,18 @@ gtk_file_selection_populate (GtkFileSelection *fs,
{
CompletionState *cmpl_state;
PossibleCompletion* poss;
- GList *dir_list = NULL;
- GList *file_list = NULL;
- GtkWidget *label;
gchar* filename;
+ gint row;
gchar* rem_path = rel_path;
gchar* sel_text;
+ gchar* text[2];
gint did_recurse = FALSE;
gint possible_count = 0;
gint selection_index = -1;
- gint dir_changed_key;
g_return_if_fail (fs != NULL);
g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
- dir_changed_key = (gint) gtk_object_get_data (GTK_OBJECT (fs->dir_list), list_changed_key);
- gtk_signal_handler_block (GTK_OBJECT (fs->dir_list), dir_changed_key);
-
cmpl_state = (CompletionState*) fs->cmpl_state;
poss = cmpl_completion_matches (rel_path, &rem_path, cmpl_state);
@@ -775,16 +1158,25 @@ gtk_file_selection_populate (GtkFileSelection *fs,
{
/* Something went wrong. */
gtk_file_selection_abort (fs);
- gtk_signal_handler_unblock (GTK_OBJECT (fs->dir_list), dir_changed_key);
return;
}
g_assert (cmpl_state->reference_dir);
- /* Set the dir_list and file_list to be GLists of strdup'd
- * filenames, including ./ and ../ */
- dir_list = g_list_prepend (dir_list, g_strdup("./"));
- dir_list = g_list_prepend (dir_list, g_strdup("../"));
+ gtk_clist_freeze (GTK_CLIST (fs->dir_list));
+ gtk_clist_clear (GTK_CLIST (fs->dir_list));
+ gtk_clist_freeze (GTK_CLIST (fs->file_list));
+ gtk_clist_clear (GTK_CLIST (fs->file_list));
+
+ /* Set the dir_list to include ./ and ../ */
+ text[1] = NULL;
+ text[0] = "./";
+ row = gtk_clist_append (GTK_CLIST (fs->dir_list), text);
+ gtk_clist_set_row_data (GTK_CLIST (fs->dir_list), row, "./");
+
+ text[0] = "../";
+ row = gtk_clist_append (GTK_CLIST (fs->dir_list), text);
+ gtk_clist_set_row_data (GTK_CLIST (fs->dir_list), row, "../");
while (poss)
{
@@ -794,25 +1186,39 @@ gtk_file_selection_populate (GtkFileSelection *fs,
filename = g_strdup (cmpl_this_completion (poss));
+ text[0] = filename;
+
if (cmpl_is_directory (poss))
{
if (strcmp (filename, "./") != 0 &&
strcmp (filename, "../") != 0)
- dir_list = g_list_prepend (dir_list, filename);
- }
+ {
+ row = gtk_clist_append (GTK_CLIST (fs->dir_list), text);
+ gtk_clist_set_row_data (GTK_CLIST (fs->dir_list), row,
+ filename);
+ }
+ }
else
- file_list = g_list_prepend (file_list, filename);
- }
+ {
+ row = gtk_clist_append (GTK_CLIST (fs->file_list), text);
+ gtk_clist_set_row_data (GTK_CLIST (fs->file_list), row,
+ filename);
+ }
+ }
poss = cmpl_next_completion (cmpl_state);
}
+ gtk_clist_thaw (GTK_CLIST (fs->dir_list));
+ gtk_clist_thaw (GTK_CLIST (fs->file_list));
+
/* File lists are set. */
g_assert (cmpl_state->reference_dir);
if (try_complete)
{
+
/* User is trying to complete filenames, so advance the user's input
* string to the updated_text, which is the common leading substring
* of all possible completions, and if its a directory attempt
@@ -820,9 +1226,10 @@ gtk_file_selection_populate (GtkFileSelection *fs,
if (cmpl_updated_text (cmpl_state)[0])
{
+
if (cmpl_updated_dir (cmpl_state))
{
- gchar* dir_name = g_strdup (cmpl_updated_text (cmpl_state));
+ gchar* dir_name = g_strdup (cmpl_updated_text (cmpl_state));
did_recurse = TRUE;
@@ -833,8 +1240,8 @@ gtk_file_selection_populate (GtkFileSelection *fs,
else
{
if (fs->selection_entry)
- gtk_entry_set_text (GTK_ENTRY (fs->selection_entry),
- cmpl_updated_text (cmpl_state));
+ gtk_entry_set_text (GTK_ENTRY (fs->selection_entry),
+ cmpl_updated_text (cmpl_state));
}
}
else
@@ -853,32 +1260,6 @@ gtk_file_selection_populate (GtkFileSelection *fs,
if (!did_recurse)
{
- GList *file_label_list = NULL;
- GList *dir_label_list = NULL;
-
- /* This reverses the lists. */
- while (file_list)
- {
- label = gtk_list_item_new_with_label (file_list->data);
- gtk_object_set_user_data (GTK_OBJECT (label), file_list->data);
- gtk_widget_show (label);
-
- file_label_list = g_list_prepend (file_label_list, label);
- file_list = file_list->next;
- }
-
- while (dir_list)
- {
- label = gtk_list_item_new_with_label (dir_list->data);
- gtk_object_set_user_data (GTK_OBJECT (label), dir_list->data);
- gtk_widget_show (label);
-
- dir_label_list = g_list_prepend (dir_label_list, label);
- dir_list = dir_list->next;
- }
-
- gtk_container_disable_resize (GTK_CONTAINER (fs));
-
if (fs->selection_entry)
gtk_entry_set_position (GTK_ENTRY (fs->selection_entry), selection_index);
@@ -893,55 +1274,12 @@ gtk_file_selection_populate (GtkFileSelection *fs,
g_free (sel_text);
}
- if (fs->dir_list)
+ if (fs->history_pulldown)
{
- gtk_container_foreach (GTK_CONTAINER (fs->dir_list),
- gtk_file_selection_free_filename, NULL);
- gtk_list_clear_items (GTK_LIST (fs->dir_list), 0, -1);
-
- if (dir_label_list)
- gtk_list_append_items (GTK_LIST (fs->dir_list), dir_label_list);
- }
- if (fs->file_list)
- {
- gtk_container_foreach (GTK_CONTAINER (fs->file_list),
- gtk_file_selection_free_filename, NULL);
- gtk_list_clear_items (GTK_LIST (fs->file_list), 0, -1);
-
- if (file_label_list)
- gtk_list_append_items (GTK_LIST (fs->file_list), file_label_list);
+ gtk_file_selection_update_history_menu (fs, cmpl_reference_position (cmpl_state));
}
-
- gtk_container_enable_resize (GTK_CONTAINER (fs));
- }
- else
- {
- GList *dir_list0 = dir_list;
- GList *file_list0 = file_list;
-
- while (dir_list)
- {
- GList *tmp = dir_list;
- dir_list = dir_list->next;
-
- if (tmp)
- g_free (tmp->data);
- }
-
- while (file_list)
- {
- GList *tmp = file_list;
- file_list = file_list->next;
-
- if (tmp)
- g_free (tmp->data);
- }
-
- g_list_free (dir_list0);
- g_list_free (file_list0);
+
}
-
- gtk_signal_handler_unblock (GTK_OBJECT (fs->dir_list), dir_changed_key);
}
static void
@@ -957,18 +1295,6 @@ gtk_file_selection_abort (GtkFileSelection *fs)
gtk_label_set (GTK_LABEL (fs->selection_text), err_buf);
}
-static void
-gtk_file_selection_free_filename (GtkWidget *widget,
- gpointer client_data)
-{
- g_return_if_fail (widget != NULL);
-
- g_free (gtk_object_get_user_data (GTK_OBJECT (widget)));
- gtk_object_set_user_data (GTK_OBJECT (widget), NULL);
-}
-
-
-
/**********************************************************************/
/* External Interface */
/**********************************************************************/
diff --git a/gtk/gtkfilesel.h b/gtk/gtkfilesel.h
index 1248ac6a9..75c24d603 100644
--- a/gtk/gtkfilesel.h
+++ b/gtk/gtkfilesel.h
@@ -48,8 +48,13 @@ struct _GtkFileSelection
GtkWidget *ok_button;
GtkWidget *cancel_button;
GtkWidget *help_button;
-
- gpointer cmpl_state;
+ GtkWidget *history_pulldown;
+ GtkWidget *history_menu;
+ GList *history_list;
+ GtkWidget *fileop_dialog;
+ GtkWidget *fileop_entry;
+ gchar *fileop_file;
+ gpointer cmpl_state;
};
struct _GtkFileSelectionClass