Kouhei Sutou
kou****@cozmi*****
2005年 6月 16日 (木) 08:21:20 JST
須藤です. ロケーションエントリへ入力しているURIが「file:///」または「/」 から始まっている場合は補完候補にローカルにあるファイルのパス を追加するパッチです. # inline-completionと組み合わせるとうれしいかも. -------------- next part -------------- Index: src/actions/kz-location-entry-action.c =================================================================== RCS file: /cvsroot/kazehakase/kazehakase/src/actions/kz-location-entry-action.c,v retrieving revision 1.43 diff -u -p -r1.43 kz-location-entry-action.c --- src/actions/kz-location-entry-action.c 14 Jun 2005 02:11:30 -0000 1.43 +++ src/actions/kz-location-entry-action.c 15 Jun 2005 23:17:20 -0000 @@ -25,6 +25,8 @@ #include <stdlib.h> #include <gdk/gdkkeysyms.h> #include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> #include <glib/gi18n.h> #include "kazehakase.h" @@ -33,6 +35,7 @@ #include "kz-bookmark.h" #include "kz-smart-bookmark.h" #include "kz-actions.h" +#include "eggregex.h" #define KZ_LOCATION_ENTRY_ACTION_KEY "KzLocationEntryAction::Action" @@ -62,6 +65,10 @@ static void kz_location_entry_action_dis static void kz_location_entry_action_history_changed (KzHistoryAction *action); static void kz_location_entry_action_sync_history (KzLocationEntryAction *action); +static void kz_location_entry_action_reset_history (KzLocationEntryAction *action); +static void kz_location_entry_action_clear_history (KzLocationEntryAction *action); +static void cb_editable_changed (GtkEditable *editable, + KzLocationEntryAction *action); static gboolean cb_entry_key_press (GtkWidget *widget, GdkEventKey *event, KzLocationEntryAction *action); @@ -152,11 +159,7 @@ kz_location_entry_action_dispose (GObjec action->kz = NULL; } - if (action->history) - { - g_object_unref(action->history); - action->history = NULL; - } + kz_location_entry_action_clear_history(action); if (action->bookmark) { @@ -231,6 +234,8 @@ kz_location_entry_action_activate (GtkAc g_return_if_fail(KZ_IS_LOCATION_ENTRY_ACTION(action)); entry_action = KZ_LOCATION_ENTRY_ACTION(action); + kz_location_entry_action_reset_history(entry_action); + entry_action->activating = TRUE; if (GTK_ACTION_CLASS(parent_class)->activate) GTK_ACTION_CLASS(parent_class)->activate(action); @@ -272,6 +277,8 @@ kz_location_entry_action_connect_proxy ( g_object_set_data(G_OBJECT(entry), KZ_LOCATION_ENTRY_ACTION_KEY, action); + g_signal_connect(entry, "changed", + G_CALLBACK(cb_editable_changed), action); g_signal_connect(entry, "key-press-event", G_CALLBACK(cb_entry_key_press), action); g_signal_connect(entry, "populate-popup", @@ -292,6 +299,10 @@ kz_location_entry_action_disconnect_prox { g_signal_handlers_disconnect_by_func (entry, + G_CALLBACK(cb_editable_changed), + action); + g_signal_handlers_disconnect_by_func + (entry, G_CALLBACK(cb_entry_key_press), action); g_signal_handlers_disconnect_by_func @@ -423,6 +434,8 @@ kz_location_entry_action_restore_history g_list_foreach(history, (GFunc) g_free, NULL); g_list_free(history); + kz_location_entry_action_clear_history(action); + kz_entry_action_set_text(KZ_ENTRY_ACTION(action), text); g_free(text); } @@ -459,6 +472,167 @@ kz_location_entry_action_sync_history (K action->synchronizing = FALSE; } +static void +kz_location_entry_action_reset_history(KzLocationEntryAction *action) +{ + if (action->history) + { + kz_history_action_set_history(KZ_HISTORY_ACTION(action), + action->history); + kz_location_entry_action_clear_history(action); + } +} + +static void +kz_location_entry_action_clear_history(KzLocationEntryAction *action) +{ + if (action->history) + { + g_list_foreach(action->history, (GFunc)g_free, NULL); + g_list_free(action->history); + action->history = NULL; + } +} + + +static void +get_file_path_from_uri(const gchar *uri, gchar **path, gchar **prefix) +{ + GError *error = NULL; + EggRegex *regex; + + *path = NULL; + *prefix = NULL; + + g_return_if_fail(uri); + + regex = egg_regex_new("^\\s*(file://|)(/.*)\\s*", + EGG_REGEX_CASELESS | EGG_REGEX_EXTENDED, + 0, &error); + + if (error) + { + g_warning("%s", error->message); + g_error_free(error); + return; + } + + if (egg_regex_match(regex, uri, -1, 0) > 0) + { + *prefix = egg_regex_fetch(regex, uri, 1); + *path = egg_regex_fetch(regex, uri, 2); + } + + egg_regex_free(regex); +} + +static gboolean +is_dir(const gchar *path) +{ + gboolean result = FALSE; + struct stat buf; + + if (stat(path, &buf) == 0) + { + result = S_ISDIR(buf.st_mode); + } + + return result; +} + +static void +kz_location_entry_action_add_file_path_to_history(KzLocationEntryAction *action, + const gchar *path, + const gchar *prefix) +{ + GDir *dir; + gchar *dir_name = g_path_get_dirname(path); + gchar *base_name = g_path_get_basename(path); + + dir = g_dir_open(dir_name, 0, NULL); + + if (dir) + { + GList *list = g_list_alloc(); + gchar *dir_base_name = g_path_get_basename(dir_name); + gboolean is_dir_path = (strcmp(base_name, dir_base_name) == 0); + const gchar *name; + gchar *full_path; + gchar *full_uri; + + for (name = g_dir_read_name(dir); + name; + name = g_dir_read_name(dir)) + { + + if (!is_dir_path && + strncmp(base_name, name, strlen(base_name)) != 0) + continue; + + full_path = g_build_filename(dir_name, name, NULL); + full_uri = g_strconcat(prefix, full_path, + is_dir(full_path) ? G_DIR_SEPARATOR_S : NULL, + NULL); + list = g_list_append(list, full_uri); + + g_free(full_path); + } + + g_dir_close(dir); + + g_list_concat(list, + kz_history_action_get_history(KZ_HISTORY_ACTION(action))); + kz_history_action_set_history(KZ_HISTORY_ACTION(action), list); + + g_free(dir_base_name); + g_list_foreach(list, (GFunc)g_free, NULL); + g_list_free(list); + } + + g_free(base_name); + g_free(dir_name); +} + +static void +kz_location_entry_action_setup_file_completion(KzLocationEntryAction *action) +{ + const gchar *uri = kz_entry_action_get_text(KZ_ENTRY_ACTION(action)); + gchar *path, *prefix; + + get_file_path_from_uri(uri, &path, &prefix); + + if (path) + { + if (action->history) + { + kz_history_action_set_history(KZ_HISTORY_ACTION(action), + action->history); + } + else + { + action->history = + kz_history_action_get_history(KZ_HISTORY_ACTION(action)); + } + kz_location_entry_action_add_file_path_to_history(action, + path, + prefix); + g_free(path); + g_free(prefix); + } + else + { + kz_location_entry_action_reset_history(action); + } +} + + +static void +cb_editable_changed (GtkEditable *editable, KzLocationEntryAction *action) +{ + if (KZ_HISTORY_ACTION(action)->completion) + kz_location_entry_action_setup_file_completion(action); +} + static gboolean cb_entry_key_press (GtkWidget *widget, GdkEventKey *event, Index: src/actions/kz-location-entry-action.h =================================================================== RCS file: /cvsroot/kazehakase/kazehakase/src/actions/kz-location-entry-action.h,v retrieving revision 1.7 diff -u -p -r1.7 kz-location-entry-action.h --- src/actions/kz-location-entry-action.h 25 Nov 2004 07:28:47 -0000 1.7 +++ src/actions/kz-location-entry-action.h 15 Jun 2005 23:17:20 -0000 @@ -42,7 +42,7 @@ struct _KzLocationEntryAction KzHistoryAction parent; KzWindow *kz; KzBookmark *bookmark; - KzBookmark *history; + GList *history; gboolean activating; gboolean synchronizing; };