/* Glimmer - gnome-file-selector.c * * 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 program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #include #include #include #include #include #include #include #ifdef _GNU_SOURCE #include #else #define _GNU_SOURCE #include /* On Solaris 2.7 we need to undef this again. */ #undef _GNU_SOURCE #endif #include "gnome-file-selector.h" #include "xpm/file-selector-dots.xpm" #include "xpm/file-selector-no-dots.xpm" #include "xpm/file-selector-details.xpm" #include "xpm/file-selector-no-details.xpm" #include "xpm/file-selector-desktop.xpm" #include "xpm/file-selector-documents.xpm" #include "xpm/file-selector-file.xpm" #include "xpm/file-selector-home.xpm" #include "xpm/file-selector-include.xpm" #include "xpm/file-selector-source.xpm" #include "xpm/folder_closed.xpm" typedef struct { gchar *name; GnomeVFSFilePermissions permissions; GnomeVFSFileSize size; } FileInfo; /* function declarations */ static void gnome_file_selector_class_init(GnomeFileSelectorClass * klass); static void gnome_file_selector_init(GnomeFileSelector * file_selector); static void gnome_file_selector_destroy(GtkObject * object); static void dir_select_event(GtkCList * list, gint row, gint col, GdkEvent * event, GnomeFileSelector * file_selector); static void dir_unselect_event(GtkCList * list, gint row, gint col, GdkEvent * event, GnomeFileSelector * file_selector); static void file_select_event(GtkCList * list, gint row, gint col, GdkEvent * event, GnomeFileSelector * file_selector); static void file_unselect_event(GtkCList * list, gint row, gint col, GdkEvent * event, GnomeFileSelector * file_selector); static void hash_remove_func(gchar * key, GtkWidget * data, gpointer d); static gint dir_compare_func(FileInfo * finfo1, FileInfo * finfo2); static gint gnome_file_selector_dir_key_press(GtkWidget * widget, GdkEventKey * event, GnomeFileSelector * file_selector); static gint gnome_file_selector_file_key_press(GtkWidget * widget, GdkEventKey * event, GnomeFileSelector * file_selector); static gint find_row_with_char(GtkCList * list, gchar c); static void refresh_listing(GtkWidget * widget, GnomeFileSelector * file_selector); static void history_go_back(GtkWidget * widget, GnomeFileSelector * file_selector); static void history_go_forward(GtkWidget * widget, GnomeFileSelector * file_selector); static void goto_parent(GtkWidget * widget, GnomeFileSelector * file_selector); static void check_ok_button_cb(GtkWidget * widget, GnomeFileSelector * file_selector); static gchar *get_parent_dir(const gchar * path); static gchar *build_full_path(const gchar * path, const gchar * selection); static GnomeVFSURI *build_uri_path(const gchar * path, const gchar * selection); static void check_goto_dir(GtkWidget * widget, GnomeFileSelector * file_selector); static void check_filter(GtkWidget * widget, GnomeFileSelector * file_selector); static void check_goto(GtkWidget * widget, GnomeFileSelector * file_selector); static void create_directory(GtkWidget * widget, GnomeFileSelector * file_selector); static void delete_file(GtkWidget * widget, GnomeFileSelector * file_selector); static void rename_file(GtkWidget * widget, GnomeFileSelector * file_selector); static void save_entry_text_cb(GtkWidget * entry, GnomeFileSelector * file_selector); static gboolean check_dir_exists(gchar * path); static gboolean check_file_exists(gchar * filename); static gboolean check_path_local(gchar * path); static void check_history_list_length(GnomeFileSelector * file_selector); static void goto_item_directory(GtkWidget * item, GnomeFileSelector * file_selector); static void path_free(gpointer data); static void toggle_show_dots(GtkToggleButton * button, GnomeFileSelector * file_selector); static void toggle_show_details(GtkToggleButton * button, GnomeFileSelector * file_selector); static void recreate_clist_directory_list(GnomeFileSelector * file_selector, GtkWidget * parent); static void recreate_clist_file_list(GnomeFileSelector * file_selector, GtkWidget * parent); static gchar *build_rwx_values(GnomeVFSFilePermissions permissions); static gint file_entry_key_press(GtkWidget * widget, GdkEventKey * event, GnomeFileSelector * file_selector); static gboolean try_complete(GnomeFileSelector * file_selector); static void free_fileinfo_list(GList * finfolist); /* end function declarations */ static GtkWindowClass *parent_class = NULL; GtkType gnome_file_selector_get_type(void) { static GtkType filelist_type = 0; if (!filelist_type) { static const GtkTypeInfo filelist_info = { "GnomeFileSelector", sizeof(GnomeFileSelector), sizeof(GnomeFileSelectorClass), (GtkClassInitFunc) gnome_file_selector_class_init, (GtkObjectInitFunc) gnome_file_selector_init, NULL, NULL, (GtkClassInitFunc) NULL, }; filelist_type = gtk_type_unique(GTK_TYPE_WINDOW, &filelist_info); } return (filelist_type); } static void gnome_file_selector_class_init(GnomeFileSelectorClass * klass) { GtkObjectClass *object_class; object_class = (GtkObjectClass *) klass; parent_class = gtk_type_class(GTK_TYPE_WINDOW); object_class->destroy = gnome_file_selector_destroy; } static void gnome_file_selector_init(GnomeFileSelector * file_selector) { file_selector->history_combo = NULL; file_selector->directory_list = NULL; file_selector->file_selector = NULL; file_selector->path = 0; file_selector->selected_row = -1; file_selector->history_position = -1; file_selector->show_dots = TRUE; file_selector->history_max = 10; file_selector->pixmaps = NULL; if (!gnome_vfs_initialized()) gnome_vfs_init(); } GtkWidget * gnome_file_selector_new(GnomeFileSelectorType type, gboolean show_dots, gboolean show_details, GList ** directory_history) { gchar path[256]; g_snprintf(path, sizeof(path), "%s", g_get_home_dir()); return (gnome_file_selector_new_with_path (path, type, show_dots, show_details, directory_history)); } GtkWidget * gnome_file_selector_new_with_path(gchar * path, GnomeFileSelectorType type, gboolean show_dots, gboolean show_details, GList ** directory_history) { GnomeFileSelector *file_selector; GtkWidget *main_box; GtkWidget *top_box; GtkWidget *util_box; GtkWidget *toolbar; GtkWidget *pixmapwid; GtkWidget *hbox; GtkWidget *paned; GtkWidget *scrolled_window1; GtkWidget *scrolled_window2; GtkWidget *label; GtkWidget *hsep; GtkWidget *parent_button; GtkWidget *refresh_button; GtkWidget *tool_item; gchar *item_path; file_selector = gtk_type_new(GNOME_TYPE_FILELIST); file_selector->type = type; file_selector->show_dots = show_dots; file_selector->show_details = show_details; file_selector->history = directory_history; gtk_container_set_border_width(GTK_CONTAINER(file_selector), 5); main_box = gtk_vbox_new(FALSE, 5); gtk_container_add(GTK_CONTAINER(file_selector), main_box); gtk_widget_show(main_box); top_box = gtk_hbox_new(FALSE, 5); gtk_box_pack_start(GTK_BOX(main_box), top_box, TRUE, TRUE, 0); gtk_widget_show(top_box); toolbar = gtk_toolbar_new(GTK_ORIENTATION_HORIZONTAL, GTK_TOOLBAR_ICONS); gtk_box_pack_start(GTK_BOX(top_box), toolbar, TRUE, TRUE, 0); gtk_toolbar_set_button_relief(GTK_TOOLBAR(toolbar), GTK_RELIEF_NONE); gtk_toolbar_set_space_style(GTK_TOOLBAR(toolbar), GTK_TOOLBAR_SPACE_LINE); gtk_toolbar_set_space_size(GTK_TOOLBAR(toolbar), 8); gtk_widget_show(toolbar); pixmapwid = gnome_stock_pixmap_widget_at_size(GTK_WIDGET(file_selector), GNOME_STOCK_PIXMAP_BACK, 21, 21); file_selector->back_button = gtk_toolbar_append_item(GTK_TOOLBAR(toolbar), 0, "Go back to a previous directory", 0, pixmapwid, GTK_SIGNAL_FUNC(history_go_back), file_selector); pixmapwid = gnome_stock_pixmap_widget_at_size(GTK_WIDGET(file_selector), GNOME_STOCK_PIXMAP_FORWARD, 21, 21); file_selector->forward_button = gtk_toolbar_append_item(GTK_TOOLBAR(toolbar), 0, "Go to the next directory", 0, pixmapwid, GTK_SIGNAL_FUNC(history_go_forward), file_selector); gtk_toolbar_append_space(GTK_TOOLBAR(toolbar)); pixmapwid = gnome_stock_pixmap_widget_at_size(GTK_WIDGET(file_selector), GNOME_STOCK_PIXMAP_UNDO, 21, 21); parent_button = gtk_toolbar_append_item(GTK_TOOLBAR(toolbar), 0, "Go to parent directory", 0, pixmapwid, GTK_SIGNAL_FUNC(goto_parent), file_selector); pixmapwid = gnome_stock_pixmap_widget_at_size(GTK_WIDGET(file_selector), GNOME_STOCK_PIXMAP_REFRESH, 21, 21); refresh_button = gtk_toolbar_append_item(GTK_TOOLBAR(toolbar), 0, "Refresh listing", 0, pixmapwid, GTK_SIGNAL_FUNC(refresh_listing), file_selector); gtk_toolbar_append_space(GTK_TOOLBAR(toolbar)); pixmapwid = gnome_stock_pixmap_widget_at_size(GTK_WIDGET(file_selector), GNOME_STOCK_PIXMAP_OPEN, 21, 21); file_selector->create_button = gtk_toolbar_append_item(GTK_TOOLBAR(toolbar), 0, "Create directory", 0, pixmapwid, GTK_SIGNAL_FUNC(create_directory), file_selector); pixmapwid = gnome_stock_pixmap_widget_at_size(GTK_WIDGET(file_selector), GNOME_STOCK_PIXMAP_CLOSE, 21, 21); file_selector->delete_button = gtk_toolbar_append_item(GTK_TOOLBAR(toolbar), 0, "Delete file", 0, pixmapwid, GTK_SIGNAL_FUNC(delete_file), file_selector); pixmapwid = gnome_stock_pixmap_widget_at_size(GTK_WIDGET(file_selector), GNOME_STOCK_PIXMAP_CONVERT, 21, 21); file_selector->rename_button = gtk_toolbar_append_item(GTK_TOOLBAR(toolbar), 0, "Rename file", 0, pixmapwid, GTK_SIGNAL_FUNC(rename_file), file_selector); gtk_toolbar_append_space(GTK_TOOLBAR(toolbar)); file_selector->dots_toggle = gtk_toggle_button_new(); gtk_container_add(GTK_CONTAINER(file_selector->dots_toggle), gnome_pixmap_new_from_xpm_d(file_selector-> show_dots ? file_selector_dots_xpm : file_selector_no_dots_xpm)); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (file_selector->dots_toggle), file_selector->show_dots); gtk_signal_connect(GTK_OBJECT(file_selector->dots_toggle), "toggled", GTK_SIGNAL_FUNC(toggle_show_dots), file_selector); gtk_widget_show_all(file_selector->dots_toggle); gtk_toolbar_append_widget(GTK_TOOLBAR(toolbar), file_selector->dots_toggle, "Toggle visibility of hidden files", NULL); file_selector->details_toggle = gtk_toggle_button_new(); gtk_container_add(GTK_CONTAINER(file_selector->details_toggle), gnome_pixmap_new_from_xpm_d(file_selector-> show_details ? file_selector_details_xpm : file_selector_no_details_xpm)); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (file_selector->details_toggle), file_selector->show_details); gtk_signal_connect(GTK_OBJECT(file_selector->details_toggle), "toggled", GTK_SIGNAL_FUNC(toggle_show_details), file_selector); gtk_widget_show_all(file_selector->details_toggle); gtk_toolbar_append_widget(GTK_TOOLBAR(toolbar), file_selector->details_toggle, "Toggle visibility of files attributes", NULL); util_box = gtk_hbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(main_box), util_box, TRUE, TRUE, 0); gtk_widget_show(util_box); label = gtk_label_new("Directory: "); gtk_box_pack_start(GTK_BOX(util_box), label, FALSE, FALSE, 0); gtk_widget_show(label); file_selector->history_combo = gtk_combo_new(); gtk_combo_disable_activate(GTK_COMBO(file_selector->history_combo)); if (*(file_selector->history)) { gtk_combo_set_popdown_strings(GTK_COMBO(file_selector->history_combo), *(file_selector->history)); } gtk_box_pack_start(GTK_BOX(util_box), file_selector->history_combo, TRUE, TRUE, 0); gtk_signal_connect(GTK_OBJECT (GTK_COMBO(file_selector->history_combo)->entry), "changed", GTK_SIGNAL_FUNC(check_ok_button_cb), file_selector); gtk_signal_connect(GTK_OBJECT (GTK_COMBO(file_selector->history_combo)->entry), "activate", GTK_SIGNAL_FUNC(check_goto_dir), file_selector); gtk_widget_show(file_selector->history_combo); hbox = gtk_hbox_new(FALSE, 5); gtk_box_pack_start(GTK_BOX(main_box), hbox, TRUE, TRUE, 0); gtk_widget_show(hbox); toolbar = gtk_toolbar_new(GTK_ORIENTATION_VERTICAL, GTK_TOOLBAR_ICONS); gtk_box_pack_start(GTK_BOX(hbox), toolbar, FALSE, FALSE, 0); gtk_toolbar_set_button_relief(GTK_TOOLBAR(toolbar), GTK_RELIEF_NONE); gtk_toolbar_set_space_style(GTK_TOOLBAR(toolbar), GTK_TOOLBAR_SPACE_LINE); gtk_toolbar_set_space_size(GTK_TOOLBAR(toolbar), 8); gtk_widget_show(toolbar); pixmapwid = gnome_pixmap_new_from_xpm_d(file_selector_home_xpm); item_path = g_strconcat(g_get_home_dir(), "/", NULL); tool_item = gtk_toolbar_append_item(GTK_TOOLBAR(toolbar), 0, "Home", 0, pixmapwid, GTK_SIGNAL_FUNC(goto_item_directory), file_selector); gtk_object_set_data_full(GTK_OBJECT(tool_item), "pathname", item_path, (GtkDestroyNotify) path_free); pixmapwid = gnome_pixmap_new_from_xpm_d(file_selector_desktop_xpm); item_path = g_strconcat(g_get_home_dir(), "/.gnome-desktop/", NULL); tool_item = gtk_toolbar_append_item(GTK_TOOLBAR(toolbar), 0, "Desktop", 0, pixmapwid, GTK_SIGNAL_FUNC(goto_item_directory), file_selector); gtk_object_set_data_full(GTK_OBJECT(tool_item), "pathname", item_path, (GtkDestroyNotify) path_free); pixmapwid = gnome_pixmap_new_from_xpm_d(file_selector_documents_xpm); item_path = g_strconcat(g_get_home_dir(), "/Documents/", NULL); tool_item = gtk_toolbar_append_item(GTK_TOOLBAR(toolbar), 0, "Documents", 0, pixmapwid, GTK_SIGNAL_FUNC(goto_item_directory), file_selector); gtk_object_set_data_full(GTK_OBJECT(tool_item), "pathname", item_path, (GtkDestroyNotify) path_free); pixmapwid = gnome_pixmap_new_from_xpm_d(file_selector_source_xpm); item_path = g_strconcat(g_get_home_dir(), "/src/", NULL); tool_item = gtk_toolbar_append_item(GTK_TOOLBAR(toolbar), 0, "Sources", 0, pixmapwid, GTK_SIGNAL_FUNC(goto_item_directory), file_selector); gtk_object_set_data_full(GTK_OBJECT(tool_item), "pathname", item_path, (GtkDestroyNotify) path_free); pixmapwid = gnome_pixmap_new_from_xpm_d(file_selector_include_xpm); item_path = g_strconcat(PREFIX, "/include/", NULL); tool_item = gtk_toolbar_append_item(GTK_TOOLBAR(toolbar), 0, "Include", 0, pixmapwid, GTK_SIGNAL_FUNC(goto_item_directory), file_selector); gtk_object_set_data_full(GTK_OBJECT(tool_item), "pathname", item_path, (GtkDestroyNotify) path_free); paned = gtk_hpaned_new(); gtk_box_pack_start(GTK_BOX(hbox), paned, TRUE, TRUE, 0); gtk_widget_show(paned); scrolled_window1 = gtk_scrolled_window_new(0, 0); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window1), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_widget_set_usize(scrolled_window1, 200, 250); gtk_widget_show(scrolled_window1); gtk_paned_add1(GTK_PANED(paned), scrolled_window1); scrolled_window2 = gtk_scrolled_window_new(0, 0); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window2), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_widget_set_usize(scrolled_window2, 300, 250); gtk_widget_show(scrolled_window2); gtk_paned_add2(GTK_PANED(paned), scrolled_window2); recreate_clist_directory_list(file_selector, scrolled_window1); recreate_clist_file_list(file_selector, scrolled_window2); util_box = gtk_hbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(main_box), util_box, TRUE, TRUE, 0); gtk_widget_show(util_box); label = gtk_label_new("Selection: "); gtk_box_pack_start(GTK_BOX(util_box), label, FALSE, FALSE, 0); gtk_widget_show(label); file_selector->selection_entry = gtk_entry_new(); gtk_box_pack_start(GTK_BOX(util_box), file_selector->selection_entry, TRUE, TRUE, 0); gtk_signal_connect(GTK_OBJECT(file_selector->selection_entry), "changed", GTK_SIGNAL_FUNC(check_ok_button_cb), file_selector); gtk_signal_connect(GTK_OBJECT(file_selector->selection_entry), "activate", GTK_SIGNAL_FUNC(check_goto), file_selector); gtk_signal_connect(GTK_OBJECT(file_selector->selection_entry), "key_press_event", GTK_SIGNAL_FUNC(file_entry_key_press), file_selector); gtk_widget_show(file_selector->selection_entry); /* Make the filter */ util_box = gtk_hbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(main_box), util_box, TRUE, TRUE, 0); gtk_widget_show(util_box); label = gtk_label_new("Filter: "); gtk_box_pack_start(GTK_BOX(util_box), label, FALSE, FALSE, 0); gtk_widget_show(label); file_selector->filter_entry = gtk_entry_new(); gtk_box_pack_start(GTK_BOX(util_box), file_selector->filter_entry, TRUE, TRUE, 0); gtk_signal_connect(GTK_OBJECT(file_selector->filter_entry), "activate", GTK_SIGNAL_FUNC(check_filter), file_selector); gtk_widget_show(file_selector->filter_entry); hsep = gtk_hseparator_new(); gtk_box_pack_start(GTK_BOX(main_box), hsep, TRUE, TRUE, 10); gtk_widget_show(hsep); util_box = gtk_hbutton_box_new(); gtk_box_pack_start(GTK_BOX(main_box), util_box, FALSE, TRUE, 0); gtk_button_box_set_layout(GTK_BUTTON_BOX(util_box), gnome_preferences_get_button_layout()); gtk_button_box_set_spacing(GTK_BUTTON_BOX(util_box), GNOME_PAD); gtk_widget_show(util_box); file_selector->ok_button = gnome_stock_button(GNOME_STOCK_BUTTON_OK); gtk_box_pack_start(GTK_BOX(util_box), file_selector->ok_button, FALSE, FALSE, 5); GTK_WIDGET_SET_FLAGS(file_selector->ok_button, GTK_CAN_DEFAULT); gtk_widget_set_sensitive(file_selector->ok_button, FALSE); gtk_widget_show(file_selector->ok_button); file_selector->cancel_button = gnome_stock_button(GNOME_STOCK_BUTTON_CANCEL); gtk_box_pack_start(GTK_BOX(util_box), file_selector->cancel_button, FALSE, FALSE, 5); GTK_WIDGET_SET_FLAGS(file_selector->cancel_button, GTK_CAN_DEFAULT); gtk_widget_grab_default(file_selector->cancel_button); gtk_widget_show(file_selector->cancel_button); file_selector->folder = (GnomePixmap *) gnome_pixmap_new_from_xpm_d(folder_closed_xpm); file_selector->file = (GnomePixmap *) gnome_pixmap_new_from_xpm_d(file_selector_file_xpm); file_selector->pixmaps = g_hash_table_new(g_str_hash, g_str_equal); if (!gnome_file_selector_set_directory(file_selector, path)) gnome_file_selector_set_directory(file_selector, g_get_home_dir()); gtk_widget_grab_focus(file_selector->selection_entry); return GTK_WIDGET(file_selector); } static void gnome_file_selector_destroy(GtkObject * object) { GtkWidget *file_selector; g_return_if_fail(object != NULL); g_return_if_fail(GNOME_IS_FILELIST(object)); file_selector = GTK_WIDGET(object); if (GNOME_FILE_SELECTOR(file_selector)->pixmaps) g_hash_table_foreach_remove(GNOME_FILE_SELECTOR(file_selector)-> pixmaps, (GHRFunc) hash_remove_func, NULL); gtk_widget_destroy(GTK_WIDGET(GNOME_FILE_SELECTOR(file_selector)->file)); gtk_widget_destroy(GTK_WIDGET(GNOME_FILE_SELECTOR(file_selector)->folder)); if (GNOME_FILE_SELECTOR(file_selector)->path) g_free(GNOME_FILE_SELECTOR(file_selector)->path); gtk_widget_destroy(file_selector); } static void dir_select_event(GtkCList * list, gint row, gint col, GdkEvent * event, GnomeFileSelector * file_selector) { gchar *path; gchar *selected; file_selector->selected_row = row; gtk_clist_get_pixtext(list, row, 0, &selected, NULL, NULL, NULL); if (event && event->type == GDK_2BUTTON_PRESS) { if (!strcmp(selected, ".")) { gnome_file_selector_set_directory(file_selector, file_selector->path); } else if (!strcmp(selected, "..")) { path = get_parent_dir(file_selector->path); gnome_file_selector_set_directory(file_selector, path); g_free(path); } else { path = build_full_path(file_selector->path, selected); gnome_file_selector_set_directory(file_selector, path); g_free(path); } } else if (event) { gtk_clist_unselect_all(GTK_CLIST(file_selector->file_selector)); } } static void dir_unselect_event(GtkCList * list, gint row, gint col, GdkEvent * event, GnomeFileSelector * file_selector) { file_selector->selected_row = -1; } static void file_select_event(GtkCList * list, gint row, gint col, GdkEvent * event, GnomeFileSelector * file_selector) { gchar *selected; file_selector->selected_row = row; gtk_clist_get_pixtext(list, row, 0, &selected, NULL, NULL, NULL); gtk_entry_set_text(GTK_ENTRY(file_selector->selection_entry), selected); if (event && event->type == GDK_2BUTTON_PRESS) { gtk_signal_emit_by_name(GTK_OBJECT(file_selector->ok_button), "clicked", NULL); } else if (event) { gtk_clist_unselect_all(GTK_CLIST(file_selector->directory_list)); } } static void file_unselect_event(GtkCList * tree, gint row, gint col, GdkEvent * event, GnomeFileSelector * file_selector) { file_selector->selected_row = -1; gtk_entry_set_text(GTK_ENTRY(file_selector->selection_entry), ""); } static void hash_remove_func(gchar * key, GtkWidget * data, gpointer d) { gtk_widget_destroy(data); } static void g_func_free_fileinfo(gpointer data, gpointer user_data) { if (data) { g_free(((FileInfo *) data)->name); g_free(data); } } static void free_fileinfo_list(GList * finfolist) { if (finfolist) { g_list_foreach(finfolist, g_func_free_fileinfo, NULL); g_list_free(finfolist); } } /* Note: dirs_list is destroyed during the call */ static void populate_directory_list(GnomeFileSelector * file_selector, GList * dirs_list) { GList *temp = NULL; FileInfo *file_info = NULL; gchar *append1[2] = { NULL, NULL }; gchar *append3[4] = { NULL, NULL, NULL, NULL }; gchar *str = NULL; recreate_clist_directory_list(file_selector, NULL); gtk_clist_freeze(GTK_CLIST(file_selector->directory_list)); gtk_clist_clear(GTK_CLIST(file_selector->directory_list)); for (temp = dirs_list; temp; temp = temp->next) { file_info = (FileInfo *) temp->data; str = file_info->name; if (!file_selector->show_details) { append1[0] = str; gtk_clist_append(GTK_CLIST(file_selector->directory_list), append1); } else { append3[0] = str; append3[1] = gnome_vfs_format_file_size_for_display(file_info->size); append3[2] = build_rwx_values(file_info->permissions); gtk_clist_append(GTK_CLIST(file_selector->directory_list), append3); g_free(append3[1]); } gtk_clist_set_pixtext(GTK_CLIST(file_selector->directory_list), GTK_CLIST(file_selector->directory_list)-> rows - 1, 0, str, 4, file_selector->folder->pixmap, file_selector->folder->mask); g_free(file_info->name); g_free(file_info); } g_list_free(dirs_list); gtk_clist_thaw(GTK_CLIST(file_selector->directory_list)); } /* Note: files_list is destroyed during the call */ static void populate_file_list(GnomeFileSelector * file_selector, GList * files_list) { GList *temp = NULL; FileInfo *file_info = NULL; gchar *append1[2] = { NULL, NULL }; gchar *append3[4] = { NULL, NULL, NULL, NULL }; GnomePixmap *pixmap = NULL; gchar *pixstr = NULL; GHashTable *new_hash = NULL; gchar *str = NULL; recreate_clist_file_list(file_selector, NULL); new_hash = g_hash_table_new(g_str_hash, g_str_equal); gtk_clist_freeze(GTK_CLIST(file_selector->file_selector)); gtk_clist_clear(GTK_CLIST(file_selector->file_selector)); for (temp = files_list; temp; temp = temp->next) { file_info = (FileInfo *) temp->data; str = file_info->name; pixmap = NULL; pixstr = (gchar *) gnome_vfs_mime_get_value((gchar *) gnome_vfs_mime_type_from_name (str), "icon-filename"); if (pixstr) { pixmap = g_hash_table_lookup(new_hash, pixstr); if (!pixmap) { pixmap = g_hash_table_lookup(file_selector->pixmaps, pixstr); if (pixmap) { g_hash_table_remove(file_selector->pixmaps, pixstr); } else if (check_file_exists(pixstr)) { pixmap = (GnomePixmap *) gnome_pixmap_new_from_file_at_size(pixstr, 18, 18); } if (pixmap) { g_hash_table_insert(new_hash, pixstr, pixmap); } } } if (!pixmap) pixmap = file_selector->file; if (!file_selector->show_details) { append1[0] = str; gtk_clist_append(GTK_CLIST(file_selector->file_selector), append1); } else { append3[0] = str; append3[1] = gnome_vfs_format_file_size_for_display(file_info->size); append3[2] = build_rwx_values(file_info->permissions); gtk_clist_append(GTK_CLIST(file_selector->file_selector), append3); g_free(append3[1]); } gtk_clist_set_pixtext(GTK_CLIST(file_selector->file_selector), GTK_CLIST(file_selector->file_selector)->rows - 1, 0, str, 4, pixmap->pixmap, pixmap->mask); g_free(str); } g_list_free(files_list); gtk_clist_thaw(GTK_CLIST(file_selector->file_selector)); g_hash_table_foreach_remove(file_selector->pixmaps, (GHRFunc) hash_remove_func, NULL); file_selector->pixmaps = new_hash; } gboolean gnome_file_selector_get_listing(GnomeFileSelector * file_selector) { GnomeVFSDirectoryHandle *dir_handle = NULL; GnomeVFSFileInfo *finfo = NULL; gchar *str = NULL; gchar *filter = NULL; GList *dirs_list = NULL; GList *files_list = NULL; GnomeVFSResult result; FileInfo *file_info = NULL; gboolean retval = FALSE; if (check_dir_exists(file_selector->path)) { if (gnome_vfs_directory_open (&dir_handle, file_selector->path, GNOME_VFS_FILE_INFO_FOLLOW_LINKS, NULL) == GNOME_VFS_OK) { filter = gtk_entry_get_text(GTK_ENTRY(file_selector->filter_entry)); if (filter && strlen(filter) < 1) filter = NULL; finfo = gnome_vfs_file_info_new(); gnome_vfs_file_info_ref(finfo); while ((result = gnome_vfs_directory_read_next(dir_handle, finfo)) == GNOME_VFS_OK) { file_info = (FileInfo *) g_malloc0(sizeof(FileInfo)); str = file_info->name = g_strdup(finfo->name); file_info->permissions = finfo->permissions; file_info->size = finfo->size; if (!file_selector->show_dots && str[0] == '.' && strcmp(str, ".") && strcmp(str, "..")) { g_free(file_info->name); g_free(file_info); } else if (finfo->type == GNOME_VFS_FILE_TYPE_DIRECTORY) { dirs_list = g_list_prepend(dirs_list, file_info); } else if (finfo->type == GNOME_VFS_FILE_TYPE_REGULAR && (!filter || (filter && ((fnmatch (filter, finfo->mime_type, FNM_CASEFOLD) == 0) || (fnmatch (filter, finfo->name, FNM_CASEFOLD) == 0))))) { files_list = g_list_prepend(files_list, file_info); } else { g_free(file_info->name); g_free(file_info); } } gnome_vfs_directory_close(dir_handle); gnome_vfs_file_info_unref(finfo); } dirs_list = g_list_sort(dirs_list, (GCompareFunc) dir_compare_func); files_list = g_list_sort(files_list, (GCompareFunc) dir_compare_func); populate_directory_list(file_selector, dirs_list); populate_file_list(file_selector, files_list); gtk_widget_grab_focus(file_selector->selection_entry); retval = TRUE; } else { g_warning("The directory was not found!\n"); } return retval; } static gboolean try_complete(GnomeFileSelector * file_selector) { const gchar *p; const gchar *complete; gchar *path; gchar *append = NULL; gchar *ptr = NULL; GnomeVFSDirectoryHandle *handle = NULL; gboolean retval = FALSE; p = gtk_entry_get_text(GTK_ENTRY (GTK_COMBO(file_selector->history_combo)->entry)); complete = gtk_entry_get_text(GTK_ENTRY(file_selector->selection_entry)); if (!complete || strlen(complete) < 1) return FALSE; path = g_strdup(p); if (complete[0] == '/') { g_free(path); ptr = strrchr(complete, '/'); if (ptr != complete) { path = g_strndup(complete, ptr - complete); } else { path = g_strdup("/"); } ptr++; append = *ptr ? g_strdup(ptr) : NULL; } else if (complete[0] == '~') { g_free(path); /* FIXME: will give the wrong directory if remote or if ~user specified */ path = g_strdup(g_get_home_dir()); if (strlen(complete) > 2 && complete[1] == '/') { append = g_strdup(&complete[2]); } } else if (!strcmp(complete, "..")) { ptr = path; path = build_full_path(path, complete); g_free(ptr); } else if ((ptr = strrchr(complete, '/'))) { gchar *temp; gchar *old_path; old_path = path; temp = g_strndup(complete, ptr - complete); path = build_full_path(path, temp); g_free(old_path); g_free(temp); ptr++; append = *ptr ? g_strdup(ptr) : NULL; } else { append = g_strdup(complete); } if (!append || (append && strlen(append) < 1)) { if (gnome_file_selector_set_directory(file_selector, path)) gtk_entry_set_text(GTK_ENTRY(file_selector->selection_entry), ""); } else if (gnome_vfs_directory_open(&handle, path, GNOME_VFS_FILE_INFO_FOLLOW_LINKS, NULL) == GNOME_VFS_OK) { GnomeVFSFileInfo *finfo; FileInfo *desc; GList *dirlist = NULL; GList *filelist = NULL; finfo = gnome_vfs_file_info_new(); while (gnome_vfs_directory_read_next(handle, finfo) == GNOME_VFS_OK) { if ((strncmp(append, finfo->name, strlen(append)) == 0) && strcmp(finfo->name, ".") && strcmp(finfo->name, "..")) { desc = g_malloc0(sizeof(FileInfo)); desc->name = g_strdup(finfo->name); desc->permissions = finfo->permissions; desc->size = finfo->size; if (finfo->type == GNOME_VFS_FILE_TYPE_DIRECTORY) dirlist = g_list_append(dirlist, desc); else filelist = g_list_append(filelist, desc); } } gnome_vfs_file_info_unref(finfo); if ((g_list_length(dirlist) == 1) && (g_list_length(filelist) == 0)) { gchar *uri_path; desc = (FileInfo *) dirlist->data; uri_path = build_full_path(path, desc->name); gnome_file_selector_set_directory(file_selector, uri_path); gtk_entry_set_text(GTK_ENTRY(file_selector->selection_entry), ""); g_free(uri_path); g_free(desc->name); g_free(desc); g_list_free(dirlist); retval = TRUE; } else if ((g_list_length(filelist) == 1) && (g_list_length(dirlist) == 0)) { desc = (FileInfo *) filelist->data; gtk_entry_set_text(GTK_ENTRY(file_selector->selection_entry), desc->name); populate_file_list(file_selector, filelist); /* This is freed during populate_file_list. Ugly semantics and probably should be changed g_free (desc->name); g_free (desc); g_list_free (filelist); */ retval = TRUE; } else if ((g_list_length(dirlist) > 0) || (g_list_length(filelist) > 0)) { populate_directory_list(file_selector, dirlist); populate_file_list(file_selector, filelist); retval = TRUE; } else { free_fileinfo_list(dirlist); free_fileinfo_list(filelist); } } g_free(path); g_free(append); return retval; } static gint dir_compare_func(FileInfo * finfo1, FileInfo * finfo2) { return (strcmp(finfo1->name, finfo2->name)); } /* External "Get" Functions */ gchar * gnome_file_selector_get_filename(GnomeFileSelector * file_selector) { gchar *path = NULL; gchar *filename = NULL; gchar *full = NULL; g_return_val_if_fail(file_selector != NULL, NULL); g_return_val_if_fail(GNOME_IS_FILELIST(file_selector), NULL); path = gtk_entry_get_text(GTK_ENTRY (GTK_COMBO(file_selector->history_combo)->entry)); filename = gtk_entry_get_text(GTK_ENTRY(file_selector->selection_entry)); full = build_full_path(path, filename); return (full); } GnomeVFSURI * gnome_file_selector_get_uri(GnomeFileSelector * file_selector) { GnomeVFSURI *uri; gchar *path = NULL; gchar *filename = NULL; g_return_val_if_fail(file_selector != NULL, NULL); g_return_val_if_fail(GNOME_IS_FILELIST(file_selector), NULL); path = gtk_entry_get_text(GTK_ENTRY (GTK_COMBO(file_selector->history_combo)->entry)); filename = gtk_entry_get_text(GTK_ENTRY(file_selector->selection_entry)); uri = build_uri_path(path, filename); return (uri); } GList * gnome_file_selector_get_uri_list(GnomeFileSelector * file_selector) { GtkCList *list; GList *files_list = NULL; GList *iter; gchar *path; gchar *filename; gint row; list = GTK_CLIST(file_selector->file_selector); path = gtk_entry_get_text(GTK_ENTRY (GTK_COMBO(file_selector->history_combo)->entry)); filename = gtk_entry_get_text(GTK_ENTRY(file_selector->selection_entry)); if (list->selection) { for (iter = list->selection; iter; iter = iter->next) { row = GPOINTER_TO_INT(iter->data); gtk_clist_get_pixtext(list, row, 0, &filename, NULL, NULL, NULL); files_list = g_list_append(files_list, build_uri_path(path, filename)); } } else { files_list = g_list_append(files_list, build_uri_path(path, filename)); } return (files_list); } gchar * gnome_file_selector_get_path(GnomeFileSelector * file_selector) { g_return_val_if_fail(file_selector != NULL, NULL); g_return_val_if_fail(GNOME_IS_FILELIST(file_selector), NULL); return (file_selector->path); } gboolean gnome_file_selector_set_directory(GnomeFileSelector * file_selector, gchar path[]) { gpointer temp = NULL; gboolean retval = FALSE; g_return_val_if_fail(file_selector != NULL, FALSE); g_return_val_if_fail(GNOME_IS_FILELIST(file_selector), FALSE); temp = file_selector->path; file_selector->path = build_full_path(path, ""); if (!file_selector->path) { file_selector->path = temp; return FALSE; } if (gnome_file_selector_get_listing(file_selector)) { gtk_entry_set_text(GTK_ENTRY (GTK_COMBO(file_selector->history_combo)->entry), file_selector->path); if (!temp || (temp && file_selector->path && strcmp(temp, file_selector->path))) gnome_file_selector_history_add_string(file_selector, file_selector->path); g_free(temp); retval = TRUE; } else { g_free(file_selector->path); file_selector->path = temp; } gtk_widget_grab_focus(file_selector->selection_entry); return retval; } void gnome_file_selector_set_title(GnomeFileSelector * file_selector, gchar * title) { g_return_if_fail(file_selector != NULL); g_return_if_fail(GNOME_IS_FILELIST(file_selector)); gtk_window_set_title(GTK_WINDOW(file_selector), title); } static gint gnome_file_selector_dir_key_press(GtkWidget * widget, GdkEventKey * event, GnomeFileSelector * file_selector) { GtkCList *clist; gint row; gint skip_rows = 0; gfloat left = 0.0; gchar *util = NULL; gchar *selected = NULL; gboolean del = FALSE; clist = GTK_CLIST(widget); row = file_selector->selected_row > -1 ? file_selector->selected_row : 0; skip_rows = clist->clist_window_height / (clist->row_height + 1); left = (float) clist->clist_window_height / (float) (clist->row_height + 1); left -= skip_rows; if (left < .5) skip_rows--; if (event->keyval == GDK_Return && file_selector->selected_row >= 0) { gtk_clist_get_pixtext(clist, file_selector->selected_row, 0, &selected, NULL, NULL, NULL); if (!strcmp(selected, ".")) { gnome_file_selector_set_directory(file_selector, file_selector->path); } else if (!strcmp(selected, "..")) { util = get_parent_dir(file_selector->path); gnome_file_selector_set_directory(file_selector, util); g_free(util); } else { util = build_full_path(file_selector->path, selected); gnome_file_selector_set_directory(file_selector, util); g_free(util); } gtk_signal_emit_stop_by_name(GTK_OBJECT (file_selector->directory_list), "key_press_event"); return (TRUE); } else if ((event->keyval >= 'a' && event->keyval <= 'z') || (event->keyval >= 'A' && event->keyval <= 'Z')) { gint found; found = find_row_with_char(clist, event->keyval); if (found != -1) { gtk_clist_moveto(clist, found, 0, 0.0, 0.0); } return (TRUE); } else if (event->keyval == GDK_Up) row--; else if (event->keyval == GDK_Down) row++; else if (event->keyval == GDK_Page_Up) row -= skip_rows; else if (event->keyval == GDK_Page_Down) row += skip_rows; if (row >= 0 && row < clist->rows) { gtk_clist_select_row(clist, row, 0); if (del) gtk_clist_moveto(clist, row, 0, 0.0, 0.0); } else if (row < 0 && clist->rows) { gtk_clist_select_row(clist, 0, 0); gtk_clist_moveto(clist, 0, 0, 0.0, 0.0); } else if (row > clist->rows) { gtk_clist_select_row(clist, clist->rows - 1, 0); gtk_clist_moveto(clist, clist->rows - 1, 0, 1.0, 1.0); } return (TRUE); } static gint gnome_file_selector_file_key_press(GtkWidget * widget, GdkEventKey * event, GnomeFileSelector * file_selector) { GtkCList *clist; gint row; gint skip_rows = 0; gfloat left = 0.0; gboolean del = FALSE; clist = GTK_CLIST(widget); row = file_selector->selected_row > -1 ? file_selector->selected_row : 0; skip_rows = clist->clist_window_height / (clist->row_height + 1); left = (float) clist->clist_window_height / (float) (clist->row_height + 1); left -= skip_rows; if (left < .5) skip_rows--; if (event->keyval == GDK_Return && file_selector->selected_row >= 0) { gtk_signal_emit_by_name(GTK_OBJECT(file_selector->ok_button), "clicked", NULL); return (TRUE); } else if (event->keyval == GDK_Up) row--; else if (event->keyval == GDK_Down) row++; else if (event->keyval == GDK_Page_Up) row -= skip_rows; else if (event->keyval == GDK_Page_Down) row += skip_rows; else if (event->keyval == GDK_Delete) { gtk_signal_emit_by_name(GTK_OBJECT(file_selector->delete_button), "clicked", file_selector); gtk_widget_grab_focus(GTK_WIDGET(clist)); del = TRUE; } else if (event->keyval == GDK_Insert) { gtk_signal_emit_by_name(GTK_OBJECT(file_selector->rename_button), "clicked", file_selector); gtk_widget_grab_focus(GTK_WIDGET(clist)); del = TRUE; } else if ((event->keyval >= 'a' && event->keyval <= 'z') || (event->keyval >= 'A' && event->keyval <= 'Z')) { gint found; found = find_row_with_char(clist, event->keyval); if (found != -1) { gtk_clist_moveto(clist, found, 0, 0.0, 0.0); } return (TRUE); } if (row >= 0 && row < clist->rows) { gtk_clist_unselect_all(clist); gtk_clist_select_row(clist, row, 0); if (del) gtk_clist_moveto(clist, row, 0, 0.0, 0.0); } else if (row < 0 && clist->rows) { gtk_clist_unselect_all(clist); gtk_clist_select_row(clist, 0, 0); gtk_clist_moveto(clist, 0, 0, 0.0, 0.0); } else if (row > clist->rows) { gtk_clist_unselect_all(clist); gtk_clist_select_row(clist, clist->rows - 1, 0); gtk_clist_moveto(clist, clist->rows - 1, 0, 1.0, 1.0); } return (TRUE); } static gint file_entry_key_press(GtkWidget * widget, GdkEventKey * event, GnomeFileSelector * file_selector) { g_return_val_if_fail(widget != NULL, FALSE); g_return_val_if_fail(event != NULL, FALSE); if (event->keyval == GDK_Tab) { try_complete(file_selector); gtk_signal_emit_stop_by_name(GTK_OBJECT(widget), "key_press_event"); gtk_widget_grab_focus(file_selector->selection_entry); return TRUE; } return FALSE; } static gint find_row_with_char(GtkCList * list, gchar c) { gint row; gint found_row = -1; gchar *text; for (row = 0; row < list->rows; row++) { gtk_clist_get_pixtext(list, row, 0, &text, NULL, NULL, NULL); if (text[0] == c || (strlen(text) > 1 && text[0] == '.' && text[1] == c)) { found_row = row; break; } } return (found_row); } static void refresh_listing(GtkWidget * widget, GnomeFileSelector * file_selector) { gnome_file_selector_set_directory(file_selector, file_selector->path); } static void history_go_back(GtkWidget * widget, GnomeFileSelector * file_selector) { gpointer temp = NULL; file_selector->history_position++; if ((temp = g_list_nth_data(*(file_selector->history), file_selector->history_position + 1))) { g_free(file_selector->path); file_selector->path = g_strdup(temp); gtk_entry_set_text(GTK_ENTRY (GTK_COMBO(file_selector->history_combo)->entry), file_selector->path); gnome_file_selector_get_listing(file_selector); } } static void history_go_forward(GtkWidget * widget, GnomeFileSelector * file_selector) { if (file_selector->history_position >= 0) { gpointer temp = NULL; file_selector->history_position--; if ((temp = g_list_nth_data(*(file_selector->history), file_selector->history_position + 1))) { g_free(file_selector->path); file_selector->path = g_strdup(temp); gtk_entry_set_text(GTK_ENTRY (GTK_COMBO(file_selector->history_combo)-> entry), file_selector->path); gnome_file_selector_get_listing(file_selector); } } } static void goto_parent(GtkWidget * widget, GnomeFileSelector * file_selector) { gchar *string, *parent; string = build_full_path(file_selector->path, ""); parent = get_parent_dir(string); gnome_file_selector_set_directory(file_selector, parent); g_free(parent); g_free(string); } static void check_ok_button_cb(GtkWidget * widget, GnomeFileSelector * file_selector) { gchar *path, *selected, *string; path = gtk_entry_get_text(GTK_ENTRY (GTK_COMBO(file_selector->history_combo)->entry)); selected = gtk_entry_get_text(GTK_ENTRY(file_selector->selection_entry)); string = build_full_path(path, selected); if (check_path_local(string) && check_dir_exists(string)) { gtk_widget_set_sensitive(file_selector->ok_button, FALSE); gtk_widget_set_sensitive(file_selector->delete_button, FALSE); gtk_widget_set_sensitive(file_selector->rename_button, FALSE); gtk_widget_set_sensitive(file_selector->create_button, TRUE); } else { gtk_widget_set_sensitive(file_selector->ok_button, TRUE); gtk_widget_set_sensitive(file_selector->create_button, FALSE); if (check_path_local(string) && selected && strlen(selected) && check_file_exists(string)) { gtk_widget_set_sensitive(file_selector->delete_button, TRUE); gtk_widget_set_sensitive(file_selector->rename_button, TRUE); } else { gtk_widget_set_sensitive(file_selector->delete_button, FALSE); gtk_widget_set_sensitive(file_selector->rename_button, FALSE); } } if (g_list_nth_data (*(file_selector->history), file_selector->history_position + 2)) gtk_widget_set_sensitive(file_selector->back_button, TRUE); else gtk_widget_set_sensitive(file_selector->back_button, FALSE); if (file_selector->history_position >= 0) gtk_widget_set_sensitive(file_selector->forward_button, TRUE); else gtk_widget_set_sensitive(file_selector->forward_button, FALSE); g_free(string); } static gchar * get_parent_dir(const gchar * path) { GnomeVFSURI *uri; GnomeVFSURI *new; gchar *text = NULL; uri = gnome_vfs_uri_new(path); if (uri) { new = gnome_vfs_uri_get_parent(uri); if (new) { text = gnome_vfs_uri_to_string(new, GNOME_VFS_URI_HIDE_NONE); gnome_vfs_uri_unref(new); } else { text = gnome_vfs_uri_to_string(uri, GNOME_VFS_URI_HIDE_NONE); } gnome_vfs_uri_unref(uri); } return (text); } static gchar * build_full_path(const gchar * path, const gchar * selection) { GnomeVFSURI *uri; GnomeVFSURI *full_uri; gchar *text = NULL; gchar *temp = NULL; uri = gnome_vfs_uri_new(path); if (uri) { if (selection) { full_uri = gnome_vfs_uri_append_string(uri, selection); gnome_vfs_uri_unref(uri); uri = full_uri; } text = gnome_vfs_uri_to_string(uri, GNOME_VFS_URI_HIDE_NONE); gnome_vfs_uri_unref(uri); temp = gnome_vfs_unescape_string(text, "/"); g_free(text); text = temp; } return (text); } static GnomeVFSURI * build_uri_path(const gchar * path, const gchar * selection) { GnomeVFSURI *uri; GnomeVFSURI *full_uri; uri = gnome_vfs_uri_new(path); if (uri && selection) { full_uri = gnome_vfs_uri_append_string(uri, selection); gnome_vfs_uri_unref(uri); uri = full_uri; } return (uri); } static void check_goto_dir(GtkWidget * widget, GnomeFileSelector * file_selector) { gchar *path; path = gtk_entry_get_text(GTK_ENTRY (GTK_COMBO(file_selector->history_combo)->entry)); if (!gnome_file_selector_set_directory(file_selector, path)) gtk_widget_grab_focus(GTK_COMBO(file_selector->history_combo)->entry); else gtk_widget_grab_focus(file_selector->selection_entry); } static void check_filter(GtkWidget * widget, GnomeFileSelector * file_selector) { gchar *filter; filter = gtk_entry_get_text(GTK_ENTRY(file_selector->filter_entry)); gnome_file_selector_get_listing(file_selector); } static void check_goto(GtkWidget * widget, GnomeFileSelector * file_selector) { gchar *string, *path, *selected; path = gtk_entry_get_text(GTK_ENTRY (GTK_COMBO(file_selector->history_combo)->entry)); selected = gtk_entry_get_text(GTK_ENTRY(file_selector->selection_entry)); string = build_full_path(path, selected); if (!check_dir_exists(string)) { gtk_signal_emit_by_name(GTK_OBJECT(file_selector->ok_button), "clicked", NULL); } else { if (gnome_file_selector_set_directory(file_selector, string)) gtk_entry_set_text(GTK_ENTRY(file_selector->selection_entry), ""); } g_free(string); } static void create_directory(GtkWidget * widget, GnomeFileSelector * file_selector) { GnomeDialog *dialog; GtkWidget *hbox; GtkWidget *pixmap; GtkWidget *label; GtkWidget *entry; gchar *path; gchar *new_name; gchar *string; gchar *name; gint result; path = gtk_entry_get_text(GTK_ENTRY (GTK_COMBO(file_selector->history_combo)->entry)); dialog = (GnomeDialog *) gnome_dialog_new("Create Directory...", GNOME_STOCK_BUTTON_OK, GNOME_STOCK_BUTTON_CANCEL, NULL); hbox = gtk_hbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(dialog->vbox), hbox, FALSE, FALSE, 0); gtk_widget_show(hbox); name = gnome_pixmap_file("gnome-question.png"); if (name) { pixmap = gnome_pixmap_new_from_file(name); gtk_box_pack_start(GTK_BOX(hbox), pixmap, FALSE, FALSE, 10); gtk_widget_show(pixmap); } string = g_strconcat("Create: ", NULL); label = gtk_label_new(string); gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 5); gtk_widget_show(label); entry = gtk_entry_new(); gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 5); gtk_signal_connect(GTK_OBJECT(entry), "destroy", GTK_SIGNAL_FUNC(save_entry_text_cb), file_selector); gtk_widget_show(entry); gnome_dialog_set_default(dialog, 1); gnome_dialog_set_parent(dialog, GTK_WINDOW(file_selector)); result = gnome_dialog_run_and_close(dialog); if (!result) { GnomeVFSResult vfs; new_name = build_full_path(path, file_selector->entry_text); vfs = gnome_vfs_make_directory(new_name, GNOME_VFS_PERM_USER_ALL | GNOME_VFS_PERM_GROUP_ALL | GNOME_VFS_PERM_OTHER_READ | GNOME_VFS_PERM_OTHER_EXEC); if (vfs != GNOME_VFS_OK) g_warning("gnome-vfs error: %s.", gnome_vfs_result_to_string(vfs)); refresh_listing(NULL, file_selector); g_free(new_name); } g_free(file_selector->entry_text); file_selector->entry_text = NULL; g_free(string); } static void delete_file(GtkWidget * widget, GnomeFileSelector * file_selector) { GnomeDialog *dialog; GtkWidget *box; GtkWidget *pixmap; GtkWidget *label; gchar *path; gchar *selected; gchar *full; gchar *string; gchar *name; gint result; path = gtk_entry_get_text(GTK_ENTRY (GTK_COMBO(file_selector->history_combo)->entry)); selected = gtk_entry_get_text(GTK_ENTRY(file_selector->selection_entry)); full = build_full_path(path, selected); dialog = (GnomeDialog *) gnome_dialog_new("Delete File...", GNOME_STOCK_BUTTON_YES, GNOME_STOCK_BUTTON_NO, NULL); box = gtk_hbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(dialog->vbox), box, FALSE, FALSE, 0); gtk_widget_show(box); name = gnome_pixmap_file("gnome-question.png"); if (name) { pixmap = gnome_pixmap_new_from_file(name); gtk_box_pack_start(GTK_BOX(box), pixmap, FALSE, FALSE, 10); gtk_widget_show(pixmap); } string = g_strconcat("Are you sure you want to delete \"", selected, "\" ?", NULL); label = gtk_label_new(string); gtk_box_pack_start(GTK_BOX(box), label, TRUE, TRUE, 5); gtk_widget_show(label); gnome_dialog_set_default(dialog, 1); gnome_dialog_set_parent(dialog, GTK_WINDOW(file_selector)); result = gnome_dialog_run_and_close(dialog); if (!result) { GnomeVFSResult vfs; vfs = gnome_vfs_unlink(full); if (vfs != GNOME_VFS_OK) g_warning("gnome-vfs error: %s.", gnome_vfs_result_to_string(vfs)); gtk_entry_set_text(GTK_ENTRY(file_selector->selection_entry), ""); refresh_listing(NULL, file_selector); } g_free(string); g_free(full); } static void rename_file(GtkWidget * widget, GnomeFileSelector * file_selector) { GnomeDialog *dialog; GtkWidget *hbox; GtkWidget *vbox; GtkWidget *pixmap; GtkWidget *label; GtkWidget *entry; gchar *path; gchar *selected; gchar *full; gchar *new_name; gchar *string; gchar *name; gint result; path = gtk_entry_get_text(GTK_ENTRY (GTK_COMBO(file_selector->history_combo)->entry)); selected = gtk_entry_get_text(GTK_ENTRY(file_selector->selection_entry)); full = build_full_path(path, selected); dialog = (GnomeDialog *) gnome_dialog_new("Rename File...", GNOME_STOCK_BUTTON_OK, GNOME_STOCK_BUTTON_CANCEL, NULL); hbox = gtk_hbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(dialog->vbox), hbox, FALSE, FALSE, 0); gtk_widget_show(hbox); name = gnome_pixmap_file("gnome-question.png"); if (name) { pixmap = gnome_pixmap_new_from_file(name); gtk_box_pack_start(GTK_BOX(hbox), pixmap, FALSE, FALSE, 10); gtk_widget_show(pixmap); } vbox = gtk_vbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 0); gtk_widget_show(vbox); string = g_strconcat("Rename \"", selected, "\" to:", NULL); label = gtk_label_new(string); gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 5); gtk_widget_show(label); entry = gtk_entry_new(); gtk_box_pack_start(GTK_BOX(vbox), entry, TRUE, TRUE, 5); gtk_entry_set_text(GTK_ENTRY(entry), selected); gtk_signal_connect(GTK_OBJECT(entry), "destroy", GTK_SIGNAL_FUNC(save_entry_text_cb), file_selector); gtk_widget_show(entry); gnome_dialog_set_default(dialog, 1); gnome_dialog_set_parent(dialog, GTK_WINDOW(file_selector)); result = gnome_dialog_run_and_close(dialog); if (!result) { GnomeVFSResult vfs; new_name = build_full_path(path, file_selector->entry_text); g_print("%s - %s.\n", full, new_name); vfs = gnome_vfs_move(full, new_name, TRUE); if (vfs != GNOME_VFS_OK) g_warning("gnome-vfs error: %s.", gnome_vfs_result_to_string(vfs)); gtk_entry_set_text(GTK_ENTRY(file_selector->selection_entry), ""); refresh_listing(NULL, file_selector); g_free(new_name); } g_free(file_selector->entry_text); file_selector->entry_text = NULL; g_free(string); g_free(full); } static void save_entry_text_cb(GtkWidget * entry, GnomeFileSelector * file_selector) { gchar *text; text = gtk_entry_get_text(GTK_ENTRY(entry)); file_selector->entry_text = g_new0(char, strlen(text) + 1); strcpy(file_selector->entry_text, text); } static gboolean check_dir_exists(gchar * path) { GnomeVFSResult result; GnomeVFSFileInfo *finfo; gboolean exists = FALSE; if (!path) return (FALSE); finfo = gnome_vfs_file_info_new(); result = gnome_vfs_get_file_info(path, finfo, GNOME_VFS_FILE_INFO_FOLLOW_LINKS); if (result == GNOME_VFS_OK) { gnome_vfs_file_info_ref(finfo); if (finfo->type == GNOME_VFS_FILE_TYPE_DIRECTORY) { exists = TRUE; } gnome_vfs_file_info_unref(finfo); } return (exists); } static gboolean check_file_exists(gchar * filename) { GnomeVFSResult result; GnomeVFSFileInfo *finfo; gboolean exists = FALSE; finfo = gnome_vfs_file_info_new(); result = gnome_vfs_get_file_info(filename, finfo, GNOME_VFS_FILE_INFO_FOLLOW_LINKS); if (result == GNOME_VFS_OK) { gnome_vfs_file_info_ref(finfo); if (finfo->type == GNOME_VFS_FILE_TYPE_REGULAR) { exists = TRUE; } gnome_vfs_file_info_unref(finfo); } return (exists); } static gboolean check_path_local(gchar * path) { GnomeVFSURI *uri; gboolean local = FALSE; if (path) { uri = gnome_vfs_uri_new(path); if (uri) { if (gnome_vfs_uri_is_local(uri)) local = TRUE; gnome_vfs_uri_unref(uri); } } return (local); } void gnome_file_selector_set_show_dots(GnomeFileSelector * file_selector, gboolean show_dots) { g_return_if_fail(file_selector != NULL); g_return_if_fail(GNOME_IS_FILELIST(file_selector)); file_selector->show_dots = show_dots; gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (file_selector->dots_toggle), file_selector->show_dots); gnome_file_selector_get_listing(file_selector); } gboolean gnome_file_selector_show_dots(GnomeFileSelector * file_selector) { g_return_val_if_fail(file_selector != NULL, FALSE); g_return_val_if_fail(GNOME_IS_FILELIST(file_selector), FALSE); return (file_selector->show_dots); } void gnome_file_selector_set_show_details(GnomeFileSelector * file_selector, gboolean show_details) { g_return_if_fail(file_selector != NULL); g_return_if_fail(GNOME_IS_FILELIST(file_selector)); file_selector->show_details = show_details; gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (file_selector->details_toggle), file_selector->show_details); gnome_file_selector_get_listing(file_selector); } gboolean gnome_file_selector_show_details(GnomeFileSelector * file_selector) { g_return_val_if_fail(file_selector != NULL, FALSE); g_return_val_if_fail(GNOME_IS_FILELIST(file_selector), FALSE); return (file_selector->show_details); } void gnome_file_selector_set_history_max(GnomeFileSelector * file_selector, gint history_max) { g_return_if_fail(file_selector != NULL); g_return_if_fail(GNOME_IS_FILELIST(file_selector)); file_selector->history_max = history_max; check_history_list_length(file_selector); } gint gnome_file_selector_history_max(GnomeFileSelector * file_selector) { g_return_val_if_fail(file_selector != NULL, -1); g_return_val_if_fail(GNOME_IS_FILELIST(file_selector), -1); return (file_selector->history_max); } void gnome_file_selector_set_history(GnomeFileSelector * file_selector, GList ** history) { if ((!file_selector) || (!history)) return; file_selector->history = history; gtk_combo_set_popdown_strings(GTK_COMBO(file_selector->history_combo), *(history)); } GList * gnome_file_selector_history(GnomeFileSelector * file_selector) { if (!file_selector) return NULL; return *(file_selector->history); } gboolean gnome_file_selector_history_add_string(GnomeFileSelector * file_selector, gchar * string) { *(file_selector->history) = g_list_prepend(*(file_selector->history), g_strdup(string)); check_history_list_length(file_selector); gtk_combo_set_popdown_strings(GTK_COMBO(file_selector->history_combo), *(file_selector->history)); file_selector->history_position = -1; if (g_list_length(*(file_selector->history)) == file_selector->history_max) { return (TRUE); } else { return (FALSE); } } static void check_history_list_length(GnomeFileSelector * file_selector) { GList *ptr; gpointer temp; while (g_list_length(*(file_selector->history)) > file_selector->history_max) { ptr = g_list_nth(*(file_selector->history), g_list_length(*(file_selector->history)) - 1); if (ptr) { temp = ptr->data; *(file_selector->history) = g_list_remove(*(file_selector->history), ptr->data); g_free(ptr->data); } } } static void goto_item_directory(GtkWidget * item, GnomeFileSelector * file_selector) { gchar *path; path = gtk_object_get_data(GTK_OBJECT(item), "pathname"); gnome_file_selector_set_directory(file_selector, path); } static void path_free(gpointer data) { g_free(data); } static void toggle_show_dots(GtkToggleButton * button, GnomeFileSelector * file_selector) { file_selector->show_dots = button->active; gnome_file_selector_get_listing(file_selector); if (GTK_BIN(button)->child) { gtk_widget_destroy(GTK_BIN(button)->child); } if (button->active) gtk_container_add(GTK_CONTAINER(button), gnome_pixmap_new_from_xpm_d(file_selector_dots_xpm)); else gtk_container_add(GTK_CONTAINER(button), gnome_pixmap_new_from_xpm_d (file_selector_no_dots_xpm)); gtk_widget_show_all(GTK_WIDGET(button)); } static void toggle_show_details(GtkToggleButton * button, GnomeFileSelector * file_selector) { file_selector->show_details = button->active; gnome_file_selector_get_listing(file_selector); if (GTK_BIN(button)->child) { gtk_widget_destroy(GTK_BIN(button)->child); } if (button->active) gtk_container_add(GTK_CONTAINER(button), gnome_pixmap_new_from_xpm_d (file_selector_details_xpm)); else gtk_container_add(GTK_CONTAINER(button), gnome_pixmap_new_from_xpm_d (file_selector_no_details_xpm)); gtk_widget_show_all(GTK_WIDGET(button)); } static void recreate_clist_directory_list(GnomeFileSelector * file_selector, GtkWidget * parent) { GtkWidget *scrolled; if (!parent) { if (!file_selector->show_details && GTK_CLIST(file_selector->directory_list)->columns == 1) return; else if (file_selector->show_details && GTK_CLIST(file_selector->directory_list)->columns == 3) return; } scrolled = parent ? parent : file_selector->directory_list->parent; if (file_selector->directory_list) gtk_widget_destroy(file_selector->directory_list); if (!file_selector->show_details) { file_selector->directory_list = gtk_clist_new(1); gtk_clist_set_column_title(GTK_CLIST(file_selector->directory_list), 0, "Directories"); } else { file_selector->directory_list = gtk_clist_new(3); gtk_clist_set_column_title(GTK_CLIST(file_selector->directory_list), 0, "Directories"); gtk_clist_set_column_auto_resize(GTK_CLIST (file_selector->directory_list), 0, TRUE); gtk_clist_set_column_title(GTK_CLIST(file_selector->directory_list), 1, "Size"); gtk_clist_set_column_auto_resize(GTK_CLIST (file_selector->directory_list), 1, TRUE); gtk_clist_set_column_title(GTK_CLIST(file_selector->directory_list), 2, "Permissions"); gtk_clist_set_column_auto_resize(GTK_CLIST (file_selector->directory_list), 2, TRUE); } gtk_clist_set_selection_mode(GTK_CLIST(file_selector->directory_list), GTK_SELECTION_SINGLE); gtk_clist_set_shadow_type(GTK_CLIST(file_selector->directory_list), GTK_SHADOW_ETCHED_IN); gtk_clist_set_column_justification(GTK_CLIST (file_selector->directory_list), 0, GTK_JUSTIFY_LEFT); gtk_clist_set_row_height(GTK_CLIST(file_selector->directory_list), 18); gtk_clist_column_titles_show(GTK_CLIST(file_selector->directory_list)); gtk_clist_column_titles_passive(GTK_CLIST(file_selector->directory_list)); gtk_container_add(GTK_CONTAINER(scrolled), file_selector->directory_list); gtk_signal_connect(GTK_OBJECT(file_selector->directory_list), "key_press_event", GTK_SIGNAL_FUNC(gnome_file_selector_dir_key_press), file_selector); gtk_signal_connect(GTK_OBJECT(file_selector->directory_list), "select_row", GTK_SIGNAL_FUNC(dir_select_event), file_selector); gtk_signal_connect(GTK_OBJECT(file_selector->directory_list), "unselect_row", GTK_SIGNAL_FUNC(dir_unselect_event), file_selector); gtk_widget_show(file_selector->directory_list); } static void recreate_clist_file_list(GnomeFileSelector * file_selector, GtkWidget * parent) { GtkWidget *scrolled; if (!parent) { if (!file_selector->show_details && GTK_CLIST(file_selector->file_selector)->columns == 1) return; else if (file_selector->show_details && GTK_CLIST(file_selector->file_selector)->columns == 3) return; } scrolled = parent ? parent : file_selector->file_selector->parent; if (file_selector->file_selector) gtk_widget_destroy(file_selector->file_selector); if (!file_selector->show_details) { file_selector->file_selector = gtk_clist_new(1); gtk_clist_set_column_title(GTK_CLIST(file_selector->file_selector), 0, "Files"); } else { file_selector->file_selector = gtk_clist_new(3); gtk_clist_set_column_title(GTK_CLIST(file_selector->file_selector), 0, "Files"); gtk_clist_set_column_auto_resize(GTK_CLIST (file_selector->file_selector), 0, TRUE); gtk_clist_set_column_title(GTK_CLIST(file_selector->file_selector), 1, "Size"); gtk_clist_set_column_auto_resize(GTK_CLIST (file_selector->file_selector), 1, TRUE); gtk_clist_set_column_title(GTK_CLIST(file_selector->file_selector), 2, "Permissions"); gtk_clist_set_column_auto_resize(GTK_CLIST (file_selector->file_selector), 1, TRUE); } if (file_selector->type == GNOME_FILE_SELECTOR_MULTIPLE) gtk_clist_set_selection_mode(GTK_CLIST(file_selector->file_selector), GTK_SELECTION_MULTIPLE); else gtk_clist_set_selection_mode(GTK_CLIST(file_selector->file_selector), GTK_SELECTION_SINGLE); gtk_clist_set_shadow_type(GTK_CLIST(file_selector->file_selector), GTK_SHADOW_ETCHED_IN); gtk_clist_set_column_justification(GTK_CLIST (file_selector->file_selector), 0, GTK_JUSTIFY_LEFT); gtk_clist_set_row_height(GTK_CLIST(file_selector->file_selector), 18); gtk_clist_column_titles_show(GTK_CLIST(file_selector->file_selector)); gtk_clist_column_titles_passive(GTK_CLIST(file_selector->file_selector)); gtk_container_add(GTK_CONTAINER(scrolled), file_selector->file_selector); gtk_signal_connect(GTK_OBJECT(file_selector->file_selector), "key_press_event", GTK_SIGNAL_FUNC(gnome_file_selector_file_key_press), file_selector); gtk_signal_connect(GTK_OBJECT(file_selector->file_selector), "select_row", GTK_SIGNAL_FUNC(file_select_event), file_selector); gtk_signal_connect(GTK_OBJECT(file_selector->file_selector), "unselect_row", GTK_SIGNAL_FUNC(file_unselect_event), file_selector); gtk_widget_show(file_selector->file_selector); } static gchar * build_rwx_values(GnomeVFSFilePermissions permissions) { gchar *value; value = g_strdup("[---][---][---]"); if (permissions & GNOME_VFS_PERM_USER_READ) value[1] = 'r'; if (permissions & GNOME_VFS_PERM_USER_WRITE) value[2] = 'w'; if (permissions & GNOME_VFS_PERM_USER_EXEC) value[3] = 'x'; if (permissions & GNOME_VFS_PERM_GROUP_READ) value[6] = 'r'; if (permissions & GNOME_VFS_PERM_GROUP_WRITE) value[7] = 'w'; if (permissions & GNOME_VFS_PERM_GROUP_EXEC) value[8] = 'x'; if (permissions & GNOME_VFS_PERM_OTHER_READ) value[11] = 'r'; if (permissions & GNOME_VFS_PERM_OTHER_WRITE) value[12] = 'w'; if (permissions & GNOME_VFS_PERM_OTHER_EXEC) value[13] = 'x'; return (value); }