[Kazehakase-devel 2224] ローカルファイル名を補完

Back to archive index

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;
 };


Kazehakase-devel メーリングリストの案内
Back to archive index