YA gtk_filesel patch
- From: Lars Clausen <lrclause cs uiuc edu>
- To: gtk-devel-list gnome org
- Subject: YA gtk_filesel patch
- Date: 06 Nov 2000 21:14:09 -0600
Here comes the filesel patch of the week. This time we've added
persistence of the visible history. It adds two interface functions,
gtk_filesel_set_history_filename() and gtk_filesel_get_history_filename().
If they are not called, we use $HOME/.gtk/<g_get_prgname()>/ to store the
data.
Note that the patch includes all our previous filesel patches as well.
-Lars
--
Lars Clausen (http://shasta.cs.uiuc.edu/~lrclause) | Hårdgrim of Numenor
"I do not agree with a word that you say, but I | Retainer of Sir Kegg
will defend to the death your right to say it." | of Westfield
--Evelyn Beatrice Hall paraphrasing Voltaire | Chaos Berserker of Khorne
===File ~/src/GTK/gtk_filesel_persistent_history.diff=======
diff -bBru gtk+-1.2.8-orig/gtk/gtkfilesel.c gtk+-1.2.8/gtk/gtkfilesel.c
--- gtk+-1.2.8-orig/gtk/gtkfilesel.c Wed Oct 18 15:05:25 2000
+++ gtk+-1.2.8/gtk/gtkfilesel.c Mon Nov 6 17:26:34 2000
@@ -55,6 +55,7 @@
#include "gtkclist.h"
#include "gtkdialog.h"
#include "gtkintl.h"
+#include "gtkcombo.h"
#define DIR_LIST_WIDTH 180
#define DIR_LIST_HEIGHT 180
@@ -322,7 +323,10 @@
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 void gtk_file_selection_home (GtkWidget *widget, gpointer data);
+static void gtk_file_selection_save_history(GtkFileSelection *filesel);
+static void gtk_file_selection_load_history(GtkFileSelection *filesel);
static GtkWindowClass *parent_class = NULL;
@@ -368,6 +372,30 @@
}
static void
+gtk_file_selection_file_chosen( GtkWidget *widget, gpointer data) {
+ GtkFileSelection *filesel = GTK_FILE_SELECTION(widget);
+ gchar *filename = gtk_file_selection_get_filename(filesel);
+ GList *elem = NULL;
+
+ if ((elem = g_list_find_custom(filesel->last_selected_files,
+ filename, strcmp)) != NULL) {
+ filesel->last_selected_files = g_list_remove_link(filesel->last_selected_files, elem);
+ g_free(elem->data);
+ g_list_free(elem);
+ }
+
+ filesel->last_selected_files = g_list_prepend(filesel->last_selected_files, g_strdup(filename));
+ if (g_list_length(filesel->last_selected_files) >
+ GTK_FILE_SELECTION_VISUAL_HISTORY_LENGTH) {
+ GList *last = g_list_last(filesel->last_selected_files);
+ filesel->last_selected_files = g_list_remove_link(filesel->last_selected_files, last);
+ g_free(last->data);
+ g_list_free(last);
+ }
+ gtk_file_selection_save_history(filesel);
+}
+
+static void
gtk_file_selection_init (GtkFileSelection *filesel)
{
GtkWidget *entry_vbox;
@@ -488,7 +516,10 @@
gtk_box_pack_start (GTK_BOX (entry_vbox), label, FALSE, FALSE, 0);
gtk_widget_show (label);
- filesel->selection_entry = gtk_entry_new ();
+ filesel->selection_combo = gtk_combo_new();
+ gtk_combo_disable_activate(GTK_COMBO(filesel->selection_combo));
+
+ filesel->selection_entry = GTK_COMBO(filesel->selection_combo)->entry;
gtk_signal_connect (GTK_OBJECT (filesel->selection_entry), "key_press_event",
(GtkSignalFunc) gtk_file_selection_key_press, filesel);
gtk_signal_connect_object (GTK_OBJECT (filesel->selection_entry), "focus_in_event",
@@ -497,8 +528,11 @@
gtk_signal_connect_object (GTK_OBJECT (filesel->selection_entry), "activate",
(GtkSignalFunc) gtk_button_clicked,
GTK_OBJECT (filesel->ok_button));
- gtk_box_pack_start (GTK_BOX (entry_vbox), filesel->selection_entry, TRUE, TRUE, 0);
- gtk_widget_show (filesel->selection_entry);
+ gtk_signal_connect_object (GTK_OBJECT (filesel->ok_button), "clicked",
+ (GtkSignalFunc) gtk_file_selection_file_chosen,
+ GTK_OBJECT(filesel));
+ gtk_box_pack_start (GTK_BOX (entry_vbox), filesel->selection_combo, TRUE, TRUE, 0);
+ gtk_widget_show (filesel->selection_combo);
if (!cmpl_state_okay (filesel->cmpl_state))
{
@@ -567,6 +601,17 @@
gtk_widget_show (filesel->fileop_ren_file);
}
+ if (!filesel->fileop_home)
+ {
+ filesel->fileop_home = gtk_button_new_with_label (_("Home"));
+ gtk_signal_connect (GTK_OBJECT (filesel->fileop_home), "clicked",
+ (GtkSignalFunc) gtk_file_selection_home,
+ (gpointer) filesel);
+ gtk_box_pack_start (GTK_BOX (filesel->button_area),
+ filesel->fileop_home, TRUE, TRUE, 0);
+ gtk_widget_show (filesel->fileop_home);
+ }
+
gtk_widget_queue_resize(GTK_WIDGET(filesel));
}
@@ -576,6 +621,11 @@
g_return_if_fail (filesel != NULL);
g_return_if_fail (GTK_IS_FILE_SELECTION (filesel));
+ if (filesel->fileop_home)
+ {
+ gtk_widget_destroy (filesel->fileop_home);
+ filesel->fileop_home = NULL;
+ }
if (filesel->fileop_ren_file)
{
gtk_widget_destroy (filesel->fileop_ren_file);
@@ -700,6 +750,191 @@
(* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
}
+static void
+unmake_directories(gchar *dirname, gchar *until) {
+ if (strcmp(dirname, until) && strcmp(dirname, "/")) {
+ if (!rmdir(dirname)) {
+ dirname = g_dirname(dirname);
+ unmake_directories(dirname, until);
+ g_free(dirname);
+ }
+ }
+}
+
+static gchar *
+make_directories(gchar *filename) {
+ struct stat dummy;
+
+ if ((stat(filename, &dummy) == -1) &&
+ errno == ENOENT) {
+ gchar *dirname = g_dirname(filename);
+ gchar *created = make_directories(dirname);
+ if (created) {
+ int retval = mkdir(filename, 0700);
+ if (retval == -1) {
+ g_warning("Unable to create history directory %s: %s\n",
+ filename, strerror(errno));
+ unmake_directories(dirname, created);
+ created = NULL;
+ }
+ g_print("Making dir %s\n", filename);
+ }
+ g_free(dirname);
+ return created;
+ } else {
+ return filename;
+ }
+}
+
+void
+gtk_file_selection_set_history_filename(GtkFileSelection *filesel,
+ gchar *filename)
+{
+ g_assert(filesel != NULL);
+
+ if (filename == NULL) {
+ filename = "file_dialog_history";
+ }
+
+ g_print("Setting persistence filename %s\n", filename);
+
+ if (*filename == '/')
+ filesel->file_history_filename = strdup(filename);
+ else {
+ gchar *full_filename;
+ char *home_dir = getenv("HOME");
+ gchar *dirname;
+ if (home_dir == NULL) {
+ g_warning("Couldn't find home directory!");
+ home_dir = "/tmp";
+ }
+ if (!strcmp(home_dir, "/") && getpid() != 0) {
+ home_dir = "/tmp";
+ }
+ full_filename = g_strdup_printf("%s/.gtk/%s/%s",
+ home_dir, g_get_prgname(), filename);
+ g_print("Setting persistence filename %s\n", full_filename);
+
+ dirname = g_dirname(full_filename);
+ if (make_directories(dirname) == NULL) {
+ filesel->file_history_filename = (gchar *)-1;
+ } else {
+ filesel->file_history_filename = full_filename;
+ }
+ g_free(dirname);
+ }
+}
+
+gchar *
+gtk_file_selection_get_history_filename(GtkFileSelection *filesel)
+{
+ return filesel->file_history_filename;
+}
+
+static void
+gtk_file_selection_load_history(GtkFileSelection *filesel) {
+ FILE *history_file;
+ GList *elem = NULL;
+ GString *history_entry;
+
+ if (filesel->file_history_filename == NULL)
+ gtk_file_selection_set_history_filename(filesel, NULL);
+ if (filesel->file_history_filename == (gchar *)-1)
+ return;
+
+ history_file = fopen(filesel->file_history_filename, "r");
+ if (history_file == NULL) {
+ /* Not a fail -- file might not have been written yet */
+ if (errno == ENOENT) return;
+ g_warning("Couldn't open file dialog persistence file %s: %s\n",
+ filesel->file_history_filename, strerror(errno));
+ return;
+ }
+ history_entry = g_string_new("");
+ while (!feof(history_file)) {
+ char buf[80];
+ int len = 0;
+ buf[0] = '\0';
+ do {
+ if (feof(history_file)) {
+ break;
+ }
+ if (fgets(buf, 80, history_file) == EOF) {
+ g_warning("Couldn't read file dialog persistence file %s: %s\n",
+ filesel->file_history_filename, strerror(errno));
+ g_string_free(history_entry, TRUE);
+ /* Failed reading, but we might as well use what we got */
+ filesel->last_selected_files = g_list_reverse(elem);
+ goto FAIL;
+ }
+ len += strlen(buf);
+ history_entry = g_string_append(history_entry, buf);
+ } while (!strchr(buf, '\n'));
+ if (len > 0) {
+ g_print("Found entry %s\n", history_entry->str);
+ /* Chop! */
+ history_entry = g_string_truncate(history_entry, len-1);
+ elem = g_list_prepend(elem, strdup(history_entry->str));
+ g_string_truncate(history_entry, 0);
+ }
+ }
+ g_string_free(history_entry, TRUE);
+ filesel->last_selected_files = g_list_reverse(elem);
+ if (fclose(history_file)) {
+ g_warning("Failed closing file dialog persistence file %s: %s\n",
+ filesel->file_history_filename, strerror(errno));
+ goto FAIL;
+ }
+ return;
+
+ FAIL:
+ g_free(filesel->file_history_filename);
+ filesel->file_history_filename = (gchar *)-1;
+ return;
+}
+
+static void
+gtk_file_selection_save_history(GtkFileSelection *filesel) {
+ FILE *history_file;
+ GList *file_list;
+
+ if (filesel->file_history_filename == NULL)
+ gtk_file_selection_set_history_filename(filesel, NULL);
+ if (filesel->file_history_filename == (gchar *)-1)
+ return;
+
+ history_file = fopen(filesel->file_history_filename, "w");
+ if (history_file == NULL) {
+ g_warning("Couldn't write file dialog persistence file %s: %s\n",
+ filesel->file_history_filename, strerror(errno));
+ goto FAIL;
+ }
+ file_list = filesel->last_selected_files;
+ while (file_list != NULL) {
+ if (fprintf(history_file, file_list->data) == 0) {
+ g_warning("Failed writing file dialog persistence file %s: %s\n",
+ filesel->file_history_filename, strerror(errno));
+ goto FAIL;
+ }
+ if (fprintf(history_file, "\n") == 0) {
+ g_warning("Failed writing file dialog persistence file %s: %s\n",
+ filesel->file_history_filename, strerror(errno));
+ goto FAIL;
+ }
+ file_list = g_list_next(file_list);
+ }
+ if (fclose(history_file)) {
+ g_warning("Failed closing file dialog persistence file %s: %s\n",
+ filesel->file_history_filename, strerror(errno));
+ goto FAIL;
+ }
+ return;
+ FAIL:
+ g_free(filesel->file_history_filename);
+ filesel->file_history_filename = (gchar *)-1;
+ return;
+}
+
/* Begin file operations callbacks */
static void
@@ -1082,6 +1317,28 @@
}
+static void
+gtk_file_selection_home (GtkWidget *widget, gpointer data)
+{
+ GtkFileSelection *fs = data;
+ char *home_dir = getenv("HOME");
+
+ g_return_if_fail (fs != NULL);
+ g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
+
+ if (home_dir == NULL) {
+ /* Pop up error dialog */
+ gtk_file_selection_fileop_error (fs, "No home directory found.");
+ return;
+ }
+
+ home_dir = g_strconcat(home_dir, "/", NULL);
+
+ gtk_file_selection_populate (fs, home_dir, FALSE);
+
+ g_free(home_dir); /* Does gtk_file_selection_populate keep it? */
+}
+
static gint
gtk_file_selection_key_press (GtkWidget *widget,
GdkEventKey *event,
@@ -1248,7 +1505,7 @@
else
gtk_entry_set_text (GTK_ENTRY (fs->selection_entry), filename);
- g_free (filename);
+ g_free(filename);
}
}
@@ -1281,16 +1538,40 @@
break;
default:
+ /*
gtk_entry_set_text (GTK_ENTRY (fs->selection_entry), filename);
+ */
break;
}
else
+ gtk_file_selection_populate (fs, filename, FALSE);
+ /*
gtk_entry_set_text (GTK_ENTRY (fs->selection_entry), filename);
+ */
g_free (filename);
}
}
+static gint
+gtk_file_selection_find_last_row(GtkFileSelection *fs) {
+ gchar *name = fs->last_selected_files->data;
+ GList *rows = GTK_CLIST(fs->file_list)->row_list;
+ int i = 0;
+
+ name = g_basename(name);
+
+ for (; rows != NULL; rows = g_list_next(rows)) {
+ GtkCListRow *row = GTK_CLIST_ROW(rows);
+
+ if (!strcmp(name, row->cell->u.text))
+ return i;
+ i++;
+ }
+
+ return -1;
+}
+
static void
gtk_file_selection_populate (GtkFileSelection *fs,
gchar *rel_path,
@@ -1431,8 +1712,37 @@
}
else
{
+ if (fs->selection_entry) {
+ gchar * basename;
+ basename = g_basename(gtk_entry_get_text(GTK_ENTRY(fs->selection_entry)));
+ if (basename == NULL) {
+ g_print("NULL basename");
+ } else if (basename != gtk_entry_get_text(GTK_ENTRY(fs->selection_entry))) {
+ basename = strdup(basename);
+ gtk_entry_set_text (GTK_ENTRY (fs->selection_entry), basename);
+ g_free(basename);
+ }
+
+ if (!fs->last_selected_files) {
+ gtk_file_selection_load_history(fs);
+ }
+
+ if (fs->last_selected_files) {
+ gint row;
+ row = gtk_file_selection_find_last_row(fs);
+ if (row != -1) {
+ gtk_clist_moveto(GTK_CLIST(fs->file_list),
+ row, 0, .5, 0.0);
+ }
+ gtk_combo_set_popdown_strings(GTK_COMBO(fs->selection_combo),
+ fs->last_selected_files);
+ }
+ }
+
+ /*
if (fs->selection_entry)
gtk_entry_set_text (GTK_ENTRY (fs->selection_entry), "");
+ */
}
if (!did_recurse)
diff -bBru gtk+-1.2.8-orig/gtk/gtkfilesel.h gtk+-1.2.8/gtk/gtkfilesel.h
--- gtk+-1.2.8-orig/gtk/gtkfilesel.h Wed Oct 18 15:05:25 2000
+++ gtk+-1.2.8/gtk/gtkfilesel.h Mon Nov 6 15:27:48 2000
@@ -42,9 +42,9 @@
#define GTK_FILE_SELECTION_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_FILE_SELECTION, GtkFileSelectionClass))
#define GTK_IS_FILE_SELECTION(obj) (GTK_CHECK_TYPE ((obj), GTK_TYPE_FILE_SELECTION))
#define GTK_IS_FILE_SELECTION_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GTK_TYPE_FILE_SELECTION))
+#define GTK_FILE_SELECTION_VISUAL_HISTORY_LENGTH 5
-
-typedef struct _GtkFileSelection GtkFileSelection;
+ typedef struct _GtkFileSelection GtkFileSelection;
typedef struct _GtkFileSelectionClass GtkFileSelectionClass;
struct _GtkFileSelection
@@ -74,6 +74,11 @@
GtkWidget *button_area;
GtkWidget *action_area;
+ GtkWidget *fileop_home;
+
+ GtkWidget *selection_combo;
+ GList *last_selected_files;
+ gchar *file_history_filename;
};
struct _GtkFileSelectionClass
@@ -91,7 +96,9 @@
const gchar *pattern);
void gtk_file_selection_show_fileop_buttons (GtkFileSelection *filesel);
void gtk_file_selection_hide_fileop_buttons (GtkFileSelection *filesel);
-
+void gtk_file_selection_set_history_filename(GtkFileSelection *filesel,
+ gchar *filename);
+gchar *gtk_file_selection_get_history_filename(GtkFileSelection *filesel);
#ifdef __cplusplus
}
============================================================
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]