diff options
author | Alexander Larsson <alexl@src.gnome.org> | 2005-12-12 16:59:19 +0000 |
---|---|---|
committer | Alexander Larsson <alexl@src.gnome.org> | 2005-12-12 16:59:19 +0000 |
commit | 671e4bdaa4d07b039015bedfcb5d42026e5d099e (patch) | |
tree | 7e983d1089740a57bc6e8848219aa3032c4e9056 /libnautilus-private | |
parent | f03608b0904ed20850e7ba49d397a7d41330a298 (diff) | |
download | nautilus-671e4bdaa4d07b039015bedfcb5d42026e5d099e.tar.gz |
--- Merged the nautilus-search2 branch ---
Diffstat (limited to 'libnautilus-private')
34 files changed, 3163 insertions, 85 deletions
diff --git a/libnautilus-private/Makefile.am b/libnautilus-private/Makefile.am index d3abe35ca..d01102961 100644 --- a/libnautilus-private/Makefile.am +++ b/libnautilus-private/Makefile.am @@ -8,6 +8,7 @@ INCLUDES = \ -I$(top_srcdir)/cut-n-paste-code \ $(CORE_CFLAGS) \ $(DISABLE_DEPRECATED_CFLAGS) \ + $(BEAGLE_CFLAGS) \ -DDATADIR=\""$(datadir)"\" \ -DSYSCONFDIR=\""$(sysconfdir)"\" \ -DNAUTILUS_DATADIR=\""$(datadir)/nautilus"\" \ @@ -27,8 +28,10 @@ libnautilus_private_la_LDFLAGS = \ libnautilus_private_la_LIBADD = \ $(dependency_static_libs) \ + $(BEAGLE_LIBS) \ $(top_builddir)/libnautilus-extension/libnautilus-extension.la \ - $(CORE_LIBS) + $(CORE_LIBS) \ + $(NULL) nautilus_metafile_server_idl_sources = \ nautilus-metafile-server-stubs.c \ @@ -151,10 +154,22 @@ libnautilus_private_la_SOURCES = \ nautilus-program-choosing.h \ nautilus-recent.c \ nautilus-recent.h \ + nautilus-saved-search-file.c \ + nautilus-saved-search-file.h \ + nautilus-search-directory.c \ + nautilus-search-directory.h \ + nautilus-search-directory-file.c \ + nautilus-search-directory-file.h \ + nautilus-search-engine.c \ + nautilus-search-engine.h \ + nautilus-search-engine-simple.c \ + nautilus-search-engine-simple.h \ nautilus-sidebar-provider.c \ nautilus-sidebar-provider.h \ nautilus-sidebar.c \ nautilus-sidebar.h \ + nautilus-query.c \ + nautilus-query.h \ nautilus-thumbnails.c \ nautilus-thumbnails.h \ nautilus-trash-directory.c \ @@ -188,6 +203,12 @@ libnautilus_private_la_SOURCES = \ nautilus-window-info.h \ $(NULL) +if HAVE_BEAGLE +libnautilus_private_la_SOURCES += \ + nautilus-search-engine-beagle.c + nautilus-search-engine-beagle.h +endif + $(lib_LTLIBRARIES): $(dependency_static_libs) $(nautilus_metafile_server_idl_sources): nautilus_metafile_server_idl_stamp diff --git a/libnautilus-private/nautilus-directory-async.c b/libnautilus-private/nautilus-directory-async.c index 20e46c75b..87dc9cfee 100644 --- a/libnautilus-private/nautilus-directory-async.c +++ b/libnautilus-private/nautilus-directory-async.c @@ -1002,7 +1002,7 @@ directory_load_done (NautilusDirectory *directory, } nautilus_directory_emit_load_error (directory, - result); + result, NULL); } /* Call the idle function right away. */ diff --git a/libnautilus-private/nautilus-directory-metafile.c b/libnautilus-private/nautilus-directory-metafile.c index 840d96d66..d6b8ee230 100644 --- a/libnautilus-private/nautilus-directory-metafile.c +++ b/libnautilus-private/nautilus-directory-metafile.c @@ -158,8 +158,6 @@ get_metafile (NautilusDirectory *directory) g_free (uri); } - g_assert (directory->details->metafile_corba_object != CORBA_OBJECT_NIL); - return directory->details->metafile_corba_object; } @@ -168,12 +166,19 @@ nautilus_directory_is_metadata_read (NautilusDirectory *directory) { CORBA_Environment ev; gboolean result; + Nautilus_Metafile metafile; g_return_val_if_fail (NAUTILUS_IS_DIRECTORY (directory), FALSE); CORBA_exception_init (&ev); - result = Nautilus_Metafile_is_read (get_metafile (directory), &ev); + metafile = get_metafile (directory); + + if (metafile == CORBA_OBJECT_NIL) { + return TRUE; + } + + result = Nautilus_Metafile_is_read (metafile, &ev); /* FIXME bugzilla.gnome.org 46664: examine ev for errors */ CORBA_exception_free (&ev); @@ -191,6 +196,7 @@ nautilus_directory_get_file_metadata (NautilusDirectory *directory, char *result; const char *non_null_default; CORBA_char *corba_value; + Nautilus_Metafile metafile; g_return_val_if_fail (NAUTILUS_IS_DIRECTORY (directory), g_strdup (default_metadata)); g_return_val_if_fail (!eel_str_is_empty (file_name), g_strdup (default_metadata)); @@ -201,7 +207,13 @@ nautilus_directory_get_file_metadata (NautilusDirectory *directory, CORBA_exception_init (&ev); - corba_value = Nautilus_Metafile_get (get_metafile (directory), file_name, key, non_null_default, &ev); + metafile = get_metafile (directory); + + if (metafile == CORBA_OBJECT_NIL) { + return g_strdup (default_metadata); + } + + corba_value = Nautilus_Metafile_get (metafile, file_name, key, non_null_default, &ev); if (ev._major != CORBA_NO_EXCEPTION) { g_warning ("Failed to get file metadata."); @@ -235,16 +247,23 @@ nautilus_directory_get_file_metadata_list (NautilusDirectory *directory, GList *result; Nautilus_MetadataList *corba_value; CORBA_unsigned_long buf_pos; + Nautilus_Metafile metafile; g_return_val_if_fail (NAUTILUS_IS_DIRECTORY (directory), NULL); g_return_val_if_fail (!eel_str_is_empty (file_name), NULL); g_return_val_if_fail (!eel_str_is_empty (list_key), NULL); g_return_val_if_fail (!eel_str_is_empty (list_subkey), NULL); - CORBA_exception_init (&ev); + metafile = get_metafile (directory); - corba_value = Nautilus_Metafile_get_list (get_metafile (directory), file_name, list_key, list_subkey, &ev); + if (metafile == CORBA_OBJECT_NIL) { + return NULL; + } + CORBA_exception_init (&ev); + + corba_value = Nautilus_Metafile_get_list (metafile, file_name, list_key, list_subkey, &ev); + /* FIXME bugzilla.gnome.org 46664: examine ev for errors */ CORBA_exception_free (&ev); @@ -266,11 +285,18 @@ nautilus_directory_set_file_metadata (NautilusDirectory *directory, const char *metadata) { CORBA_Environment ev; + Nautilus_Metafile metafile; g_return_if_fail (NAUTILUS_IS_DIRECTORY (directory)); g_return_if_fail (!eel_str_is_empty (file_name)); g_return_if_fail (!eel_str_is_empty (key)); + metafile = get_metafile (directory); + + if (metafile == CORBA_OBJECT_NIL) { + return; + } + /* We can't pass NULL as a CORBA_string - pass "" instead. */ if (default_metadata == NULL) { @@ -282,7 +308,7 @@ nautilus_directory_set_file_metadata (NautilusDirectory *directory, CORBA_exception_init (&ev); - Nautilus_Metafile_set (get_metafile (directory), file_name, key, default_metadata, metadata, &ev); + Nautilus_Metafile_set (metafile, file_name, key, default_metadata, metadata, &ev); /* FIXME bugzilla.gnome.org 46664: examine ev for errors */ CORBA_exception_free (&ev); @@ -296,7 +322,7 @@ nautilus_directory_set_file_metadata_list (NautilusDirectory *directory, GList *list) { CORBA_Environment ev; - + Nautilus_Metafile metafile; Nautilus_MetadataList *corba_list; int len; int buf_pos; @@ -306,7 +332,13 @@ nautilus_directory_set_file_metadata_list (NautilusDirectory *directory, g_return_if_fail (!eel_str_is_empty (file_name)); g_return_if_fail (!eel_str_is_empty (list_key)); g_return_if_fail (!eel_str_is_empty (list_subkey)); - + + metafile = get_metafile (directory); + + if (metafile == CORBA_OBJECT_NIL) { + return; + } + len = g_list_length (list); corba_list = Nautilus_MetadataList__alloc (); @@ -329,7 +361,7 @@ nautilus_directory_set_file_metadata_list (NautilusDirectory *directory, CORBA_exception_init (&ev); - Nautilus_Metafile_set_list (get_metafile (directory), file_name, list_key, list_subkey, corba_list, &ev); + Nautilus_Metafile_set_list (metafile, file_name, list_key, list_subkey, corba_list, &ev); /* FIXME bugzilla.gnome.org 46664: examine ev for errors */ CORBA_exception_free (&ev); @@ -438,17 +470,24 @@ nautilus_directory_copy_file_metadata (NautilusDirectory *source_directory, { CORBA_Environment ev; char *destination_uri; + Nautilus_Metafile metafile; g_return_if_fail (NAUTILUS_IS_DIRECTORY (source_directory)); g_return_if_fail (source_file_name != NULL); g_return_if_fail (NAUTILUS_IS_DIRECTORY (destination_directory)); g_return_if_fail (destination_file_name != NULL); - + + metafile = get_metafile (source_directory); + + if (metafile == CORBA_OBJECT_NIL) { + return; + } + destination_uri = nautilus_directory_get_uri (destination_directory); CORBA_exception_init (&ev); - Nautilus_Metafile_copy (get_metafile (source_directory), source_file_name, + Nautilus_Metafile_copy (metafile, source_file_name, destination_uri, destination_file_name, &ev); /* FIXME bugzilla.gnome.org 46664: examine ev for errors */ @@ -462,13 +501,20 @@ nautilus_directory_remove_file_metadata (NautilusDirectory *directory, const char *file_name) { CORBA_Environment ev; + Nautilus_Metafile metafile; g_return_if_fail (NAUTILUS_IS_DIRECTORY (directory)); g_return_if_fail (file_name != NULL); - + + metafile = get_metafile (directory); + + if (metafile == CORBA_OBJECT_NIL) { + return; + } + CORBA_exception_init (&ev); - Nautilus_Metafile_remove (get_metafile (directory), file_name, &ev); + Nautilus_Metafile_remove (metafile, file_name, &ev); /* FIXME bugzilla.gnome.org 46664: examine ev for errors */ CORBA_exception_free (&ev); @@ -480,14 +526,21 @@ nautilus_directory_rename_file_metadata (NautilusDirectory *directory, const char *new_file_name) { CORBA_Environment ev; + Nautilus_Metafile metafile; g_return_if_fail (NAUTILUS_IS_DIRECTORY (directory)); g_return_if_fail (old_file_name != NULL); g_return_if_fail (new_file_name != NULL); - + + metafile = get_metafile (directory); + + if (metafile == CORBA_OBJECT_NIL) { + return; + } + CORBA_exception_init (&ev); - Nautilus_Metafile_rename (get_metafile (directory), old_file_name, new_file_name, &ev); + Nautilus_Metafile_rename (metafile, old_file_name, new_file_name, &ev); /* FIXME bugzilla.gnome.org 46664: examine ev for errors */ CORBA_exception_free (&ev); @@ -498,13 +551,20 @@ nautilus_directory_rename_directory_metadata (NautilusDirectory *directory, const char *new_directory_uri) { CORBA_Environment ev; + Nautilus_Metafile metafile; g_return_if_fail (NAUTILUS_IS_DIRECTORY (directory)); g_return_if_fail (new_directory_uri != NULL); - + + metafile = get_metafile (directory); + + if (metafile == CORBA_OBJECT_NIL) { + return; + } + CORBA_exception_init (&ev); - Nautilus_Metafile_rename_directory (get_metafile (directory), new_directory_uri, &ev); + Nautilus_Metafile_rename_directory (metafile, new_directory_uri, &ev); /* FIXME bugzilla.gnome.org 46664: examine ev for errors */ CORBA_exception_free (&ev); @@ -514,6 +574,7 @@ void nautilus_directory_register_metadata_monitor (NautilusDirectory *directory) { CORBA_Environment ev; + Nautilus_Metafile metafile; g_return_if_fail (NAUTILUS_IS_DIRECTORY (directory)); @@ -522,12 +583,18 @@ nautilus_directory_register_metadata_monitor (NautilusDirectory *directory) return; } + metafile = get_metafile (directory); + + if (metafile == CORBA_OBJECT_NIL) { + return; + } + directory->details->metafile_monitor = nautilus_metafile_monitor_new (directory); CORBA_exception_init (&ev); Nautilus_Metafile_register_monitor - (get_metafile (directory), + (metafile, BONOBO_OBJREF (directory->details->metafile_monitor), &ev); @@ -539,14 +606,21 @@ void nautilus_directory_unregister_metadata_monitor (NautilusDirectory *directory) { CORBA_Environment ev; + Nautilus_Metafile metafile; g_return_if_fail (NAUTILUS_IS_DIRECTORY (directory)); g_return_if_fail (NAUTILUS_IS_METAFILE_MONITOR (directory->details->metafile_monitor)); + metafile = get_metafile (directory); + + if (metafile == CORBA_OBJECT_NIL) { + return; + } + CORBA_exception_init (&ev); Nautilus_Metafile_unregister_monitor - (get_metafile (directory), + (metafile, BONOBO_OBJREF (directory->details->metafile_monitor), &ev); diff --git a/libnautilus-private/nautilus-directory-private.h b/libnautilus-private/nautilus-directory-private.h index 4c0cf4e0c..930084f93 100644 --- a/libnautilus-private/nautilus-directory-private.h +++ b/libnautilus-private/nautilus-directory-private.h @@ -192,7 +192,8 @@ void nautilus_directory_emit_change_signals (NautilusD void emit_change_signals_for_all_files (NautilusDirectory *directory); void nautilus_directory_emit_done_loading (NautilusDirectory *directory); void nautilus_directory_emit_load_error (NautilusDirectory *directory, - GnomeVFSResult error_result); + GnomeVFSResult error_result, + const char *error_message); NautilusDirectory *nautilus_directory_get_internal (const char *uri, gboolean create); char * nautilus_directory_get_name_for_self_as_new_file (NautilusDirectory *directory); diff --git a/libnautilus-private/nautilus-directory.c b/libnautilus-private/nautilus-directory.c index 4831480f5..c31b345ca 100644 --- a/libnautilus-private/nautilus-directory.c +++ b/libnautilus-private/nautilus-directory.c @@ -30,8 +30,10 @@ #include "nautilus-file-attributes.h" #include "nautilus-file-private.h" #include "nautilus-file-utilities.h" +#include "nautilus-search-directory.h" #include "nautilus-global-preferences.h" #include "nautilus-lib-self-check-functions.h" +#include "nautilus-marshal.h" #include "nautilus-metadata.h" #include "nautilus-metafile.h" #include "nautilus-desktop-directory.h" @@ -71,6 +73,7 @@ static void nautilus_directory_class_init (NautilusDirectoryClass static NautilusDirectory *nautilus_directory_new (const char *uri); static char * real_get_name_for_self_as_new_file (NautilusDirectory *directory); static GList * real_get_file_list (NautilusDirectory *directory); +static gboolean real_is_editable (NautilusDirectory *directory); static void set_directory_uri (NautilusDirectory *directory, const char *new_uri); @@ -117,11 +120,12 @@ nautilus_directory_class_init (NautilusDirectoryClass *klass) G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (NautilusDirectoryClass, load_error), NULL, NULL, - g_cclosure_marshal_VOID__INT, - G_TYPE_NONE, 1, G_TYPE_INT); + nautilus_marshal_VOID__INT_STRING, + G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_STRING); klass->get_name_for_self_as_new_file = real_get_name_for_self_as_new_file; klass->get_file_list = real_get_file_list; + klass->is_editable = real_is_editable; g_type_class_add_private (klass, sizeof (NautilusDirectoryDetails)); } @@ -143,16 +147,17 @@ nautilus_directory_init (gpointer object, gpointer klass) directory->details->hidden_file_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); } -void +NautilusDirectory * nautilus_directory_ref (NautilusDirectory *directory) { if (directory == NULL) { - return; + return directory; } - g_return_if_fail (NAUTILUS_IS_DIRECTORY (directory)); + g_return_val_if_fail (NAUTILUS_IS_DIRECTORY (directory), NULL); g_object_ref (directory); + return directory; } void @@ -515,6 +520,10 @@ nautilus_directory_new (const char *uri) directory = NAUTILUS_DIRECTORY (g_object_new (NAUTILUS_TYPE_TRASH_DIRECTORY, NULL)); } else if (eel_uri_is_desktop (uri)) { directory = NAUTILUS_DIRECTORY (g_object_new (NAUTILUS_TYPE_DESKTOP_DIRECTORY, NULL)); + } else if (eel_uri_is_search (uri)) { + directory = NAUTILUS_DIRECTORY (g_object_new (NAUTILUS_TYPE_SEARCH_DIRECTORY, NULL)); + } else if (g_str_has_suffix (uri, NAUTILUS_SAVED_SEARCH_EXTENSION)) { + directory = NAUTILUS_DIRECTORY (nautilus_search_directory_new_from_saved_search (uri)); } else { directory = NAUTILUS_DIRECTORY (g_object_new (NAUTILUS_TYPE_VFS_DIRECTORY, NULL)); } @@ -764,11 +773,12 @@ nautilus_directory_emit_done_loading (NautilusDirectory *directory) void nautilus_directory_emit_load_error (NautilusDirectory *directory, - GnomeVFSResult error_result) + GnomeVFSResult error_result, + const char *error_message) { g_signal_emit (directory, signals[LOAD_ERROR], 0, - error_result); + error_result, error_message); } @@ -994,7 +1004,6 @@ nautilus_directory_notify_files_added (GList *uris) nautilus_directory_unref (directory); } - /* Now get file info for the new files. This creates NautilusFile * objects for the new files, and sends out a files_added signal. */ @@ -1652,6 +1661,20 @@ real_get_file_list (NautilusDirectory *directory) return non_tentative_files; } +static gboolean +real_is_editable (NautilusDirectory *directory) +{ + return TRUE; +} + +gboolean +nautilus_directory_is_editable (NautilusDirectory *directory) +{ + return EEL_CALL_METHOD_WITH_RETURN_VALUE + (NAUTILUS_DIRECTORY_CLASS, directory, + is_editable, (directory)); +} + GList * nautilus_directory_match_pattern (NautilusDirectory *directory, const char *pattern) { diff --git a/libnautilus-private/nautilus-directory.h b/libnautilus-private/nautilus-directory.h index c708daaaa..10571bb4a 100644 --- a/libnautilus-private/nautilus-directory.h +++ b/libnautilus-private/nautilus-directory.h @@ -100,7 +100,9 @@ typedef struct */ void (* done_loading) (NautilusDirectory *directory); - void (* load_error) (NautilusDirectory *directory); + void (* load_error) (NautilusDirectory *directory, + GnomeVFSResult error_result, + const char *error_message); /*** Virtual functions for subclasses to override. ***/ gboolean (* contains_file) (NautilusDirectory *directory, @@ -134,6 +136,12 @@ typedef struct * the list of standard icons (Computer, Home, Trash) on the desktop. */ GList * (* get_file_list) (NautilusDirectory *directory); + + /* Should return FALSE if the directory is read-only and doesn't + * allow setting of metadata. + * An example of this is the search directory. + */ + gboolean (* is_editable) (NautilusDirectory *directory); } NautilusDirectoryClass; /* Basic GObject requirements. */ @@ -151,7 +159,7 @@ NautilusDirectory *nautilus_directory_get_for_file (NautilusFile * 1) You don't have to cast to GtkObject *, so using these is type safe. * 2) You are allowed to call these with NULL, */ -void nautilus_directory_ref (NautilusDirectory *directory); +NautilusDirectory *nautilus_directory_ref (NautilusDirectory *directory); void nautilus_directory_unref (NautilusDirectory *directory); /* Access to a URI. */ @@ -227,5 +235,7 @@ GList * nautilus_directory_list_sort_by_uri (GList /* Fast way to check if a directory is the desktop directory */ gboolean nautilus_directory_is_desktop_directory (NautilusDirectory *directory); +gboolean nautilus_directory_is_editable (NautilusDirectory *directory); + #endif /* NAUTILUS_DIRECTORY_H */ diff --git a/libnautilus-private/nautilus-file-dnd.c b/libnautilus-private/nautilus-file-dnd.c index fd55a3d5c..4729831d6 100644 --- a/libnautilus-private/nautilus-file-dnd.c +++ b/libnautilus-private/nautilus-file-dnd.c @@ -28,6 +28,7 @@ #include "nautilus-desktop-icon-file.h" #include "nautilus-dnd.h" +#include "nautilus-directory.h" #include <eel/eel-glib-extensions.h> #include <eel/eel-string.h> @@ -35,14 +36,20 @@ gboolean nautilus_drag_can_accept_item (NautilusFile *drop_target_item, const char *item_uri) { + NautilusDirectory *directory; + gboolean res; + if (nautilus_file_matches_uri (drop_target_item, item_uri)) { /* can't accept itself */ return FALSE; } if (nautilus_file_is_directory (drop_target_item)) { - /* target is a directory, accept anything */ - return TRUE; + /* target is a directory, accept if editable */ + directory = nautilus_directory_get_for_file (drop_target_item); + res = nautilus_directory_is_editable (directory); + nautilus_directory_unref (directory); + return res; } if (NAUTILUS_IS_DESKTOP_ICON_FILE (drop_target_item)) { diff --git a/libnautilus-private/nautilus-file-private.h b/libnautilus-private/nautilus-file-private.h index 24466f8ab..7faae5a85 100644 --- a/libnautilus-private/nautilus-file-private.h +++ b/libnautilus-private/nautilus-file-private.h @@ -151,7 +151,6 @@ struct NautilusFileDetails NautilusFile *nautilus_file_new_from_info (NautilusDirectory *directory, GnomeVFSFileInfo *info); -NautilusFile *nautilus_file_get_existing (const char *uri); void nautilus_file_emit_changed (NautilusFile *file); void nautilus_file_mark_gone (NautilusFile *file); gboolean nautilus_file_info_missing (NautilusFile *file, diff --git a/libnautilus-private/nautilus-file-utilities.c b/libnautilus-private/nautilus-file-utilities.c index d5fc80833..0f4fbc74f 100644 --- a/libnautilus-private/nautilus-file-utilities.c +++ b/libnautilus-private/nautilus-file-utilities.c @@ -30,6 +30,7 @@ #include "nautilus-metadata.h" #include "nautilus-metafile.h" #include "nautilus-file.h" +#include "nautilus-search-directory.h" #include <eel/eel-glib-extensions.h> #include <eel/eel-string.h> #include <eel/eel-vfs-extensions.h> @@ -56,10 +57,26 @@ nautilus_compute_title_for_uri (const char *text_uri) GnomeVFSURI *uri; char *title, *displayname; const char *hostname; - + NautilusDirectory *directory; + NautilusQuery *query; hostname = NULL; if (text_uri) { + if (eel_uri_is_search (text_uri)) { + directory = nautilus_directory_get (text_uri); + + query = nautilus_search_directory_get_query (NAUTILUS_SEARCH_DIRECTORY (directory)); + nautilus_directory_unref (directory); + + if (query != NULL) { + title = nautilus_query_to_readable_string (query); + g_object_unref (query); + } else { + title = g_strdup (_("Search")); + } + + return title; + } file = nautilus_file_get (text_uri); uri = gnome_vfs_uri_new (text_uri); if (uri && !gnome_vfs_uri_is_local (uri)) { @@ -208,6 +225,13 @@ nautilus_get_desktop_directory_uri_no_create (void) } char * +nautilus_get_home_directory_uri (void) +{ + return gnome_vfs_get_uri_from_local_path (g_get_home_dir ()); +} + + +char * nautilus_get_templates_directory (void) { return g_build_filename (g_get_home_dir(), @@ -237,6 +261,22 @@ nautilus_get_templates_directory_uri (void) return uri; } +char * +nautilus_get_searches_directory (void) +{ + char *user_dir; + char *searches_dir; + + user_dir = nautilus_get_user_directory (); + searches_dir = g_build_filename (user_dir, "searches", NULL); + g_free (user_dir); + + if (!g_file_test (searches_dir, G_FILE_TEST_EXISTS)) + mkdir (searches_dir, DEFAULT_NAUTILUS_DIRECTORY_MODE); + + return searches_dir; +} + /* These need to be reset to NULL when desktop_is_home_dir changes */ static char *escaped_desktop_dir = NULL; static char *escaped_desktop_dir_dirname = NULL; diff --git a/libnautilus-private/nautilus-file-utilities.h b/libnautilus-private/nautilus-file-utilities.h index 15b04c68c..ac8a520ea 100644 --- a/libnautilus-private/nautilus-file-utilities.h +++ b/libnautilus-private/nautilus-file-utilities.h @@ -27,6 +27,9 @@ #include <libgnomevfs/gnome-vfs-types.h> +#define NAUTILUS_SAVED_SEARCH_EXTENSION ".savedSearch" +#define NAUTILUS_SAVED_SEARCH_MIMETYPE "application/x-gnome-saved-search" + /* Recognizing special file names. */ gboolean nautilus_file_name_matches_hidden_pattern (const char *name_or_relative_uri); gboolean nautilus_file_name_matches_backup_pattern (const char *name_or_relative_uri); @@ -37,6 +40,7 @@ gboolean nautilus_file_name_matches_backup_pattern (const char *name_or_relati char * nautilus_get_user_directory (void); char * nautilus_get_desktop_directory (void); char * nautilus_get_desktop_directory_uri (void); +char * nautilus_get_home_directory_uri (void); gboolean nautilus_is_desktop_directory_file_escaped (char *escaped_dirname, char *escaped_filename); gboolean nautilus_is_desktop_directory_escaped (char *escaped_dir); @@ -49,6 +53,8 @@ char * nautilus_get_templates_directory (void); char * nautilus_get_templates_directory_uri (void); void nautilus_create_templates_directory (void); +char * nautilus_get_searches_directory (void); + char * nautilus_compute_title_for_uri (const char *text_uri); /* This function returns something that needs to be freed with g_free, diff --git a/libnautilus-private/nautilus-file.c b/libnautilus-private/nautilus-file.c index bd0daa4c1..aa55dd441 100644 --- a/libnautilus-private/nautilus-file.c +++ b/libnautilus-private/nautilus-file.c @@ -40,10 +40,13 @@ #include "nautilus-link-desktop-file.h" #include "nautilus-metadata.h" #include "nautilus-module.h" +#include "nautilus-search-directory.h" +#include "nautilus-search-directory-file.h" #include "nautilus-thumbnails.h" #include "nautilus-trash-directory.h" #include "nautilus-trash-file.h" #include "nautilus-vfs-file.h" +#include "nautilus-saved-search-file.h" #include <eel/eel-debug.h> #include <eel/eel-glib-extensions.h> #include <eel/eel-gtk-extensions.h> @@ -72,12 +75,15 @@ /* Time in seconds to cache getpwuid results */ #define GETPWUID_CACHE_TIME (5*60) + #undef NAUTILUS_FILE_DEBUG_REF +#undef NAUTILUS_FILE_DEBUG_REF_VALGRIND -#ifdef NAUTILUS_FILE_DEBUG_REF -extern void eazel_dump_stack_trace (const char *print_prefix, - int num_levels); -/* from libleakcheck.so */ +#ifdef NAUTILUS_FILE_DEBUG_REF_VALGRIND +#include <valgrind/valgrind.h> +#define DEBUG_REF_PRINTF VALGRIND_PRINTF_BACKTRACE +#else +#define DEBUG_REF_PRINTF printf #endif /* Files that start with these characters sort after files that don't. */ @@ -195,20 +201,28 @@ nautilus_file_new_from_relative_uri (NautilusDirectory *directory, file = NULL; g_assert_not_reached (); } + } else if (NAUTILUS_IS_SEARCH_DIRECTORY (directory)) { + if (self_owned) { + file = NAUTILUS_FILE (g_object_new (NAUTILUS_TYPE_SEARCH_DIRECTORY_FILE, NULL)); + } else { + file = NULL; + g_assert_not_reached (); + } + } else if (g_str_has_suffix (relative_uri, NAUTILUS_SAVED_SEARCH_EXTENSION)) { + file = NAUTILUS_FILE (g_object_new (NAUTILUS_TYPE_SAVED_SEARCH_FILE, NULL)); } else { file = NAUTILUS_FILE (g_object_new (NAUTILUS_TYPE_VFS_FILE, NULL)); } -#ifdef NAUTILUS_FILE_DEBUG_REF - printf("%10p ref'd\n", file); - eazel_dump_stack_trace ("\t", 10); -#endif - nautilus_directory_ref (directory); file->details->directory = directory; file->details->relative_uri = g_strdup (relative_uri); +#ifdef NAUTILUS_FILE_DEBUG_REF + DEBUG_REF_PRINTF("%10p ref'd", file); +#endif + return file; } @@ -305,17 +319,23 @@ nautilus_file_new_from_info (NautilusDirectory *directory, g_return_val_if_fail (NAUTILUS_IS_DIRECTORY (directory), NULL); g_return_val_if_fail (info != NULL, NULL); - file = NAUTILUS_FILE (g_object_new (NAUTILUS_TYPE_VFS_FILE, NULL)); - -#ifdef NAUTILUS_FILE_DEBUG_REF - printf("%10p ref'd\n", file); - eazel_dump_stack_trace ("\t", 10); -#endif + if (info->mime_type && + strcmp (info->mime_type, NAUTILUS_SAVED_SEARCH_MIMETYPE) == 0) { + file = NAUTILUS_FILE (g_object_new (NAUTILUS_TYPE_SAVED_SEARCH_FILE, NULL)); + } else { + file = NAUTILUS_FILE (g_object_new (NAUTILUS_TYPE_VFS_FILE, NULL)); + } nautilus_directory_ref (directory); file->details->directory = directory; update_info_and_name (file, info, FALSE); + + +#ifdef NAUTILUS_FILE_DEBUG_REF + DEBUG_REF_PRINTF("%10p ref'd", file); +#endif + return file; } @@ -397,14 +417,22 @@ nautilus_file_get_internal (const char *uri, gboolean create) file_name = nautilus_directory_get_name_for_self_as_new_file (directory); relative_uri = gnome_vfs_escape_string (file_name); g_free (file_name); - } else if (eel_uri_is_desktop (uri)) { - /* Special case desktop files here. They have no vfs_uri */ - relative_uri_tmp = uri + strlen (EEL_DESKTOP_URI); + } else if (eel_uri_is_desktop (uri) || + eel_uri_is_search (uri)) { + /* Special case virtual methods like desktop and search + files here. They have no vfs_uri. */ + relative_uri_tmp = uri; + /* Skip "method:" */ + while (*relative_uri_tmp != 0 && *relative_uri_tmp != ':') { + relative_uri_tmp++; + } + relative_uri_tmp++; + /* Skip initial slashes */ while (*relative_uri_tmp == '/') { relative_uri_tmp++; } relative_uri = strdup (relative_uri_tmp); - } + } } /* Check to see if it's a file that's already known. */ @@ -524,12 +552,10 @@ nautilus_file_ref (NautilusFile *file) g_return_val_if_fail (NAUTILUS_IS_FILE (file), NULL); #ifdef NAUTILUS_FILE_DEBUG_REF - printf("%10p ref'd\n", file); - eazel_dump_stack_trace ("\t", 10); + DEBUG_REF_PRINTF("%10p ref'd", file); #endif - - g_object_ref (file); - return file; + + return g_object_ref (file); } void @@ -542,10 +568,9 @@ nautilus_file_unref (NautilusFile *file) g_return_if_fail (NAUTILUS_IS_FILE (file)); #ifdef NAUTILUS_FILE_DEBUG_REF - printf("%10p unref'd\n", file); - eazel_dump_stack_trace ("\t", 10); + DEBUG_REF_PRINTF("%10p unref'd", file); #endif - + g_object_unref (file); } diff --git a/libnautilus-private/nautilus-file.h b/libnautilus-private/nautilus-file.h index bb2562a18..d14d0e07a 100644 --- a/libnautilus-private/nautilus-file.h +++ b/libnautilus-private/nautilus-file.h @@ -97,6 +97,9 @@ GType nautilus_file_get_type (void); /* Getting at a single file. */ NautilusFile * nautilus_file_get (const char *uri); +/* Get a file only if the nautilus version already exists */ +NautilusFile * nautilus_file_get_existing (const char *uri); + /* Covers for gtk_object_ref and gtk_object_unref that provide two conveniences: * 1) You don't have to cast to GtkObject *, so using these is type safe. * 2) You are allowed to call these with NULL, diff --git a/libnautilus-private/nautilus-icon-container.c b/libnautilus-private/nautilus-icon-container.c index db92bb4a5..85207694f 100644 --- a/libnautilus-private/nautilus-icon-container.c +++ b/libnautilus-private/nautilus-icon-container.c @@ -3558,6 +3558,7 @@ motion_notify_event (GtkWidget *widget, NautilusIconContainerDetails *details; double world_x, world_y; int canvas_x, canvas_y; + GdkDragAction actions; container = NAUTILUS_ICON_CONTAINER (widget); details = container->details; @@ -3588,13 +3589,16 @@ motion_notify_event (GtkWidget *widget, &canvas_x, &canvas_y); + actions = GDK_ACTION_COPY + | GDK_ACTION_LINK + | GDK_ACTION_ASK; + + if (container->details->drag_allow_moves) { + actions |= GDK_ACTION_MOVE; + } + nautilus_icon_dnd_begin_drag (container, - details->drag_state == DRAG_STATE_MOVE_OR_COPY - ? (GDK_ACTION_MOVE - | GDK_ACTION_COPY - | GDK_ACTION_LINK - | GDK_ACTION_ASK) - : GDK_ACTION_ASK, + actions, details->drag_button, event, canvas_x, @@ -7216,6 +7220,23 @@ nautilus_icon_container_get_icon_description (NautilusIconContainer *container, } } +gboolean +nautilus_icon_container_get_allow_moves (NautilusIconContainer *container) +{ + g_return_val_if_fail (NAUTILUS_IS_ICON_CONTAINER (container), FALSE); + + return container->details->drag_allow_moves; +} + +void +nautilus_icon_container_set_allow_moves (NautilusIconContainer *container, + gboolean allow_moves) +{ + g_return_if_fail (NAUTILUS_IS_ICON_CONTAINER (container)); + + container->details->drag_allow_moves = allow_moves; +} + /* NautilusIconContainerAccessible */ static NautilusIconContainerAccessiblePrivate * diff --git a/libnautilus-private/nautilus-icon-container.h b/libnautilus-private/nautilus-icon-container.h index c3fe4c5ae..83b899ed8 100644 --- a/libnautilus-private/nautilus-icon-container.h +++ b/libnautilus-private/nautilus-icon-container.h @@ -287,5 +287,8 @@ void nautilus_icon_container_set_use_drop_shadows (Nautilu gboolean use_drop_shadows); char* nautilus_icon_container_get_icon_description (NautilusIconContainer *container, NautilusIconData *data); +gboolean nautilus_icon_container_get_allow_moves (NautilusIconContainer *container); +void nautilus_icon_container_set_allow_moves (NautilusIconContainer *container, + gboolean allow_moves); #endif /* NAUTILUS_ICON_CONTAINER_H */ diff --git a/libnautilus-private/nautilus-icon-factory.c b/libnautilus-private/nautilus-icon-factory.c index 10ddfb888..e47f97dbe 100644 --- a/libnautilus-private/nautilus-icon-factory.c +++ b/libnautilus-private/nautilus-icon-factory.c @@ -830,6 +830,9 @@ get_special_icon_for_file (NautilusFile *file) } else { ret = ICON_NAME_TRASH_FULL; } + } else if (eel_uri_is_search (uri)) { + /* FIXME: We really need a better icon than this */ + ret = "gnome-searchtool"; } g_free (uri); diff --git a/libnautilus-private/nautilus-icon-private.h b/libnautilus-private/nautilus-icon-private.h index ae8a993a4..442b2dfa5 100644 --- a/libnautilus-private/nautilus-icon-private.h +++ b/libnautilus-private/nautilus-icon-private.h @@ -155,6 +155,7 @@ struct NautilusIconContainerDetails { DragState drag_state; gboolean drag_started; StretchState stretch_start; + gboolean drag_allow_moves; gboolean icon_selected_on_button_down; NautilusIcon *double_click_icon[2]; /* Both clicks in a double click need to be on the same icon */ diff --git a/libnautilus-private/nautilus-marshal.list b/libnautilus-private/nautilus-marshal.list index 5b7826c1b..beeff9dc5 100644 --- a/libnautilus-private/nautilus-marshal.list +++ b/libnautilus-private/nautilus-marshal.list @@ -1,17 +1,20 @@ -STRING:VOID -OBJECT:BOXED BOOLEAN:POINTER BOOLEAN:VOID -INT:POINTER,INT INT:POINTER,BOOLEAN +INT:POINTER,INT INT:POINTER,POINTER +OBJECT:BOXED POINTER:VOID +STRING:VOID VOID:DOUBLE -VOID:STRING,ENUM,INT,INT +VOID:INT,STRING +VOID:OBJECT,BOOLEAN +VOID:OBJECT,OBJECT +VOID:POINTER,ENUM VOID:POINTER,POINTER VOID:POINTER,POINTER +VOID:POINTER,POINTER,POINTER,ENUM,INT,INT VOID:POINTER,STRING VOID:POINTER,STRING,ENUM,INT,INT +VOID:STRING,ENUM,INT,INT VOID:STRING,STRING -VOID:POINTER,POINTER,POINTER,ENUM,INT,INT -VOID:POINTER,ENUM diff --git a/libnautilus-private/nautilus-metafile-factory.c b/libnautilus-private/nautilus-metafile-factory.c index eadd69336..c939b440b 100644 --- a/libnautilus-private/nautilus-metafile-factory.c +++ b/libnautilus-private/nautilus-metafile-factory.c @@ -54,6 +54,10 @@ corba_open (PortableServer_Servant servant, metafile = nautilus_metafile_get (directory); + if (!metafile) { + return CORBA_OBJECT_NIL; + } + return CORBA_Object_duplicate (BONOBO_OBJREF (metafile), ev); } diff --git a/libnautilus-private/nautilus-metafile.c b/libnautilus-private/nautilus-metafile.c index 7ddefd490..f0541c163 100644 --- a/libnautilus-private/nautilus-metafile.c +++ b/libnautilus-private/nautilus-metafile.c @@ -249,7 +249,12 @@ nautilus_metafile_get (const char *directory_uri) char *canonical_uri; g_return_val_if_fail (directory_uri != NULL, NULL); - + + /* We don't have metafiles for search uris */ + if (eel_uri_is_search (directory_uri)) { + return NULL; + } + if (metafiles == NULL) { metafiles = eel_g_hash_table_new_free_at_exit (g_str_hash, g_str_equal, __FILE__ ": metafiles"); diff --git a/libnautilus-private/nautilus-query.c b/libnautilus-private/nautilus-query.c new file mode 100644 index 000000000..b8e761a63 --- /dev/null +++ b/libnautilus-private/nautilus-query.c @@ -0,0 +1,372 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* + * Copyright (C) 2005 Novell, Inc. + * + * Nautilus is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Nautilus 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 + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; see the file COPYING. If not, + * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: Anders Carlsson <andersca@imendio.com> + * + */ + +#include <config.h> +#include <string.h> + +#include "nautilus-query.h" +#include <libgnomevfs/gnome-vfs-utils.h> +#include <eel/eel-gtk-macros.h> +#include <eel/eel-glib-extensions.h> + +struct NautilusQueryDetails { + char *text; + char *location_uri; + GList *mime_types; +}; + +static void nautilus_query_class_init (NautilusQueryClass *class); +static void nautilus_query_init (NautilusQuery *query); + +G_DEFINE_TYPE (NautilusQuery, + nautilus_query, + G_TYPE_OBJECT); + +static GObjectClass *parent_class = NULL; + +static void +finalize (GObject *object) +{ + NautilusQuery *query; + + query = NAUTILUS_QUERY (object); + + g_free (query->details->text); + g_free (query->details); + + EEL_CALL_PARENT (G_OBJECT_CLASS, finalize, (object)); +} + +static void +nautilus_query_class_init (NautilusQueryClass *class) +{ + GObjectClass *gobject_class; + + parent_class = g_type_class_peek_parent (class); + + gobject_class = G_OBJECT_CLASS (class); + gobject_class->finalize = finalize; +} + +static void +nautilus_query_init (NautilusQuery *query) +{ + query->details = g_new0 (NautilusQueryDetails, 1); +} + +NautilusQuery * +nautilus_query_new (void) +{ + return g_object_new (NAUTILUS_TYPE_QUERY, NULL); +} + + +char * +nautilus_query_get_text (NautilusQuery *query) +{ + return g_strdup (query->details->text); +} + +void +nautilus_query_set_text (NautilusQuery *query, const char *text) +{ + g_free (query->details->text); + query->details->text = g_strdup (text); +} + +char * +nautilus_query_get_location (NautilusQuery *query) +{ + return g_strdup (query->details->location_uri); +} + +void +nautilus_query_set_location (NautilusQuery *query, const char *uri) +{ + g_free (query->details->location_uri); + query->details->location_uri = g_strdup (uri); +} + +GList * +nautilus_query_get_mime_types (NautilusQuery *query) +{ + return eel_g_str_list_copy (query->details->mime_types); +} + +void +nautilus_query_set_mime_types (NautilusQuery *query, GList *mime_types) +{ + eel_g_list_free_deep (query->details->mime_types); + query->details->mime_types = eel_g_str_list_copy (mime_types); +} + +void +nautilus_query_add_mime_type (NautilusQuery *query, const char *mime_type) +{ + query->details->mime_types = g_list_append (query->details->mime_types, + g_strdup (mime_type)); +} + +char * +nautilus_query_to_readable_string (NautilusQuery *query) +{ + if (!query || !query->details->text) { + return g_strdup ("Search"); + } + + return g_strdup_printf ("Search for \"%s\"", query->details->text); +} + +static char * +encode_home_uri (const char *uri) +{ + char *home_uri; + const char *encoded_uri; + + home_uri = gnome_vfs_get_uri_from_local_path (g_get_home_dir ()); + + if (g_str_has_prefix (uri, home_uri)) { + encoded_uri = uri + strlen (home_uri); + if (*encoded_uri == '/') { + encoded_uri++; + } + } else { + encoded_uri = uri; + } + + g_free (home_uri); + + return g_markup_escape_text (encoded_uri, -1); +} + +static char * +decode_home_uri (const char *uri) +{ + char *home_uri; + char *decoded_uri; + + if (g_str_has_prefix (uri, "file:")) { + decoded_uri = g_strdup (uri); + } else { + home_uri = gnome_vfs_get_uri_from_local_path (g_get_home_dir ()); + + decoded_uri = g_strconcat (home_uri, "/", uri, NULL); + + g_free (home_uri); + } + + return decoded_uri; +} + + +typedef struct { + NautilusQuery *query; + gboolean in_text; + gboolean in_location; + gboolean in_mimetypes; + gboolean in_mimetype; +} ParserInfo; + +static void +start_element_cb (GMarkupParseContext *ctx, + const char *element_name, + const char **attribute_names, + const char **attribute_values, + gpointer user_data, + GError **err) +{ + ParserInfo *info; + + info = (ParserInfo *) user_data; + + if (strcmp (element_name, "text") == 0) + info->in_text = TRUE; + else if (strcmp (element_name, "location") == 0) + info->in_location = TRUE; + else if (strcmp (element_name, "mimetypes") == 0) + info->in_mimetypes = TRUE; + else if (strcmp (element_name, "mimetype") == 0) + info->in_mimetype = TRUE; +} + +static void +end_element_cb (GMarkupParseContext *ctx, + const char *element_name, + gpointer user_data, + GError **err) +{ + ParserInfo *info; + + info = (ParserInfo *) user_data; + + if (strcmp (element_name, "text") == 0) + info->in_text = FALSE; + else if (strcmp (element_name, "location") == 0) + info->in_location = FALSE; + else if (strcmp (element_name, "mimetypes") == 0) + info->in_mimetypes = FALSE; + else if (strcmp (element_name, "mimetype") == 0) + info->in_mimetype = FALSE; +} + +static void +text_cb (GMarkupParseContext *ctx, + const char *text, + gsize text_len, + gpointer user_data, + GError **err) +{ + ParserInfo *info; + char *t, *uri; + + info = (ParserInfo *) user_data; + + t = g_strndup (text, text_len); + + if (info->in_text) { + nautilus_query_set_text (info->query, t); + } else if (info->in_location) { + uri = decode_home_uri (t); + nautilus_query_set_location (info->query, uri); + g_free (uri); + } else if (info->in_mimetypes && info->in_mimetype) { + nautilus_query_add_mime_type (info->query, t); + } + + g_free (t); + +} + +static void +error_cb (GMarkupParseContext *ctx, + GError *err, + gpointer user_data) +{ +} + +static GMarkupParser parser = { + start_element_cb, + end_element_cb, + text_cb, + NULL, + error_cb +}; + + +static NautilusQuery * +nautilus_query_parse_xml (char *xml, gsize xml_len) +{ + ParserInfo info = { NULL }; + GMarkupParseContext *ctx; + + if (xml_len == -1) { + xml_len = strlen (xml); + } + + info.query = nautilus_query_new (); + info.in_text = FALSE; + + ctx = g_markup_parse_context_new (&parser, 0, &info, NULL); + g_markup_parse_context_parse (ctx, xml, xml_len, NULL); + + return info.query; +} + + +NautilusQuery * +nautilus_query_load (char *file) +{ + NautilusQuery *query; + char *xml; + gsize xml_len; + + if (!g_file_test (file, G_FILE_TEST_EXISTS)) { + return NULL; + } + + + g_file_get_contents (file, &xml, &xml_len, NULL); + query = nautilus_query_parse_xml (xml, xml_len); + g_free (xml); + + return query; +} + +static char * +nautilus_query_to_xml (NautilusQuery *query) +{ + GString *xml; + char *text; + char *uri; + char *mimetype; + GList *l; + + xml = g_string_new (""); + g_string_append (xml, + "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + "<query version=\"1.0\">\n"); + + text = g_markup_escape_text (query->details->text, -1); + g_string_append_printf (xml, " <text>%s</text>\n", text); + g_free (text); + + if (query->details->location_uri) { + uri = encode_home_uri (query->details->location_uri); + g_string_append_printf (xml, " <location>%s</location>\n", uri); + g_free (uri); + } + + if (query->details->mime_types) { + g_string_append (xml, " <mimetypes>\n"); + for (l = query->details->mime_types; l != NULL; l = l->next) { + mimetype = g_markup_escape_text (l->data, -1); + g_string_append_printf (xml, " <mimetype>%s</mimetype>\n", mimetype); + g_free (mimetype); + } + g_string_append (xml, " </mimetypes>\n"); + } + + g_string_append (xml, "</query>\n"); + + return g_string_free (xml, FALSE); +} + +gboolean +nautilus_query_save (NautilusQuery *query, char *file) +{ + char *xml; + GError *err = NULL; + gboolean res; + + + res = TRUE; + xml = nautilus_query_to_xml (query); + g_file_set_contents (file, xml, strlen (xml), &err); + g_free (xml); + + if (err != NULL) { + res = FALSE; + g_error_free (err); + } + return res; +} diff --git a/libnautilus-private/nautilus-query.h b/libnautilus-private/nautilus-query.h new file mode 100644 index 000000000..fae278042 --- /dev/null +++ b/libnautilus-private/nautilus-query.h @@ -0,0 +1,67 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* + * Copyright (C) 2005 Novell, Inc. + * + * Nautilus is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Nautilus 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 + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; see the file COPYING. If not, + * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: Anders Carlsson <andersca@imendio.com> + * + */ + +#ifndef NAUTILUS_QUERY_H +#define NAUTILUS_QUERY_H + +#include <glib-object.h> +#include <libgnomevfs/gnome-vfs-result.h> + +#define NAUTILUS_TYPE_QUERY (nautilus_query_get_type ()) +#define NAUTILUS_QUERY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NAUTILUS_TYPE_QUERY, NautilusQuery)) +#define NAUTILUS_QUERY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NAUTILUS_TYPE_QUERY, NautilusQueryClass)) +#define NAUTILUS_IS_QUERY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NAUTILUS_TYPE_QUERY)) +#define NAUTILUS_IS_QUERY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NAUTILUS_TYPE_QUERY)) +#define NAUTILUS_QUERY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NAUTILUS_TYPE_QUERY, NautilusQueryClass)) + +typedef struct NautilusQueryDetails NautilusQueryDetails; + +typedef struct NautilusQuery { + GObject parent; + NautilusQueryDetails *details; +} NautilusQuery; + +typedef struct { + GObjectClass parent_class; +} NautilusQueryClass; + +GType nautilus_query_get_type (void); +gboolean nautilus_query_enabled (void); + +NautilusQuery* nautilus_query_new (void); + +char * nautilus_query_get_text (NautilusQuery *query); +void nautilus_query_set_text (NautilusQuery *query, const char *text); + +char * nautilus_query_get_location (NautilusQuery *query); +void nautilus_query_set_location (NautilusQuery *query, const char *uri); + +GList * nautilus_query_get_mime_types (NautilusQuery *query); +void nautilus_query_set_mime_types (NautilusQuery *query, GList *mime_types); +void nautilus_query_add_mime_type (NautilusQuery *query, const char *mime_type); + +char * nautilus_query_to_readable_string (NautilusQuery *query); +NautilusQuery *nautilus_query_load (char *file); +gboolean nautilus_query_save (NautilusQuery *query, char *file); + +#endif /* NAUTILUS_QUERY_H */ diff --git a/libnautilus-private/nautilus-saved-search-file.c b/libnautilus-private/nautilus-saved-search-file.c new file mode 100644 index 000000000..35ce6d6a3 --- /dev/null +++ b/libnautilus-private/nautilus-saved-search-file.c @@ -0,0 +1,62 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- + + nautilus-saved-search-file.h: Subclass of NautilusVFSFile to implement the + the case of a Saved Search file. + + Copyright (C) 2005 Red Hat, Inc + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program 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 + General Public License for more details. + + You should have received a copy of the GNU 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. + + Author: Alexander Larsson +*/ +#include <config.h> +#include "nautilus-saved-search-file.h" +#include <eel/eel-gtk-macros.h> + +static void nautilus_saved_search_file_init (gpointer object, gpointer klass); +static void nautilus_saved_search_file_class_init (gpointer klass); + +EEL_CLASS_BOILERPLATE (NautilusSavedSearchFile, + nautilus_saved_search_file, + NAUTILUS_TYPE_VFS_FILE) + + + +static void +nautilus_saved_search_file_init (gpointer object, gpointer klass) +{ + NautilusVFSFile *file; + + file = NAUTILUS_VFS_FILE (object); + +} + +static GnomeVFSFileType +saved_search_get_file_type (NautilusFile *file) +{ + return GNOME_VFS_FILE_TYPE_DIRECTORY; +} + +static void +nautilus_saved_search_file_class_init (gpointer klass) +{ + NautilusFileClass *file_class; + + file_class = NAUTILUS_FILE_CLASS (klass); + + file_class->get_file_type = saved_search_get_file_type; +} + diff --git a/libnautilus-private/nautilus-saved-search-file.h b/libnautilus-private/nautilus-saved-search-file.h new file mode 100644 index 000000000..16cf35943 --- /dev/null +++ b/libnautilus-private/nautilus-saved-search-file.h @@ -0,0 +1,54 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- + + nautilus-saved-search-file.h: Subclass of NautilusVFSFile to implement the + the case of a Saved Search file. + + Copyright (C) 2005 Red Hat, Inc + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program 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 + General Public License for more details. + + You should have received a copy of the GNU 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. + + Author: Alexander Larsson +*/ + +#ifndef NAUTILUS_SAVED_SEARCH_FILE_H +#define NAUTILUS_SAVED_SEARCH_FILE_H + +#include <libnautilus-private/nautilus-vfs-file.h> + +#define NAUTILUS_TYPE_SAVED_SEARCH_FILE \ + (nautilus_saved_search_file_get_type ()) +#define NAUTILUS_SAVED_SEARCH_FILE(obj) \ + (GTK_CHECK_CAST ((obj), NAUTILUS_TYPE_SAVED_SEARCH_FILE, NautilusSavedSearchFile)) +#define NAUTILUS_SAVED_SEARCH_FILE_CLASS(klass) \ + (GTK_CHECK_CLASS_CAST ((klass), NAUTILUS_TYPE_SAVED_SEARCH_FILE, NautilusSavedSearchFileClass)) +#define NAUTILUS_IS_SAVED_SEARCH_FILE(obj) \ + (GTK_CHECK_TYPE ((obj), NAUTILUS_TYPE_SAVED_SEARCH_FILE)) +#define NAUTILUS_IS_SAVED_SEARCH_FILE_CLASS(klass) \ + (GTK_CHECK_CLASS_TYPE ((klass), NAUTILUS_TYPE_SAVED_SEARCH_FILE)) + +typedef struct NautilusSavedSearchFileDetails NautilusSavedSearchFileDetails; + +typedef struct { + NautilusFile parent_slot; +} NautilusSavedSearchFile; + +typedef struct { + NautilusFileClass parent_slot; +} NautilusSavedSearchFileClass; + +GType nautilus_saved_search_file_get_type (void); + +#endif /* NAUTILUS_SAVED_SEARCH_FILE_H */ diff --git a/libnautilus-private/nautilus-search-directory-file.c b/libnautilus-private/nautilus-search-directory-file.c new file mode 100644 index 000000000..86c077a94 --- /dev/null +++ b/libnautilus-private/nautilus-search-directory-file.c @@ -0,0 +1,239 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- + + nautilus-search-directory-file.c: Subclass of NautilusFile to help implement the + searches + + Copyright (C) 2005 Novell, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program 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 + General Public License for more details. + + You should have received a copy of the GNU 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. + + Author: Anders Carlsson <andersca@imendio.com> +*/ + +#include <config.h> +#include "nautilus-search-directory-file.h" + +#include "nautilus-directory-notify.h" +#include "nautilus-directory-private.h" +#include "nautilus-file-attributes.h" +#include "nautilus-file-private.h" +#include "nautilus-file-utilities.h" +#include <eel/eel-glib-extensions.h> +#include <eel/eel-gtk-macros.h> +#include "nautilus-search-directory.h" +#include <gtk/gtksignal.h> +#include <libgnome/gnome-i18n.h> +#include <string.h> + +static void nautilus_search_directory_file_init (gpointer object, + gpointer klass); +static void nautilus_search_directory_file_class_init (gpointer klass); + +EEL_CLASS_BOILERPLATE (NautilusSearchDirectoryFile, + nautilus_search_directory_file, + NAUTILUS_TYPE_FILE); + +struct NautilusSearchDirectoryFileDetails { + NautilusSearchDirectory *search_directory; +}; + +static void +search_directory_file_monitor_add (NautilusFile *file, + gconstpointer client, + NautilusFileAttributes attributes) +{ + /* No need for monitoring, we always emit changed when files + are added/removed, and no other metadata changes */ +} + +static void +search_directory_file_monitor_remove (NautilusFile *file, + gconstpointer client) +{ + /* Do nothing here, we don't have any monitors */ +} + +static void +search_directory_file_call_when_ready (NautilusFile *file, + NautilusFileAttributes file_attributes, + NautilusFileCallback callback, + gpointer callback_data) + +{ + /* All data for directory-as-file is always uptodate */ + (* callback) (file, callback_data); +} + +static void +search_directory_file_cancel_call_when_ready (NautilusFile *file, + NautilusFileCallback callback, + gpointer callback_data) +{ + /* Do nothing here, we don't have any pending calls */ +} + + +static gboolean +search_directory_file_check_if_ready (NautilusFile *file, + NautilusFileAttributes attributes) +{ + return TRUE; +} + +static GnomeVFSFileType +search_directory_file_get_file_type (NautilusFile *file) +{ + return GNOME_VFS_FILE_TYPE_DIRECTORY; +} + +static gboolean +search_directory_file_get_item_count (NautilusFile *file, + guint *count, + gboolean *count_unreadable) +{ + NautilusSearchDirectory *search_dir; + GList *file_list; + + if (count) { + search_dir = NAUTILUS_SEARCH_DIRECTORY (file->details->directory); + + file_list = nautilus_directory_get_file_list (file->details->directory); + + *count = g_list_length (file_list); + + nautilus_file_list_free (file_list); + } + + return TRUE; +} + +static NautilusRequestStatus +search_directory_file_get_deep_counts (NautilusFile *file, + guint *directory_count, + guint *file_count, + guint *unreadable_directory_count, + GnomeVFSFileSize *total_size) +{ + NautilusSearchDirectory *search_dir; + NautilusFile *dir_file; + GList *file_list, *l; + guint dirs, files; + GnomeVFSFileType type; + + search_dir = NAUTILUS_SEARCH_DIRECTORY (file->details->directory); + + file_list = nautilus_directory_get_file_list (file->details->directory); + + dirs = files = 0; + for (l = file_list; l != NULL; l = l->next) { + dir_file = NAUTILUS_FILE (l->data); + type = nautilus_file_get_file_type (dir_file); + if (type == GNOME_VFS_FILE_TYPE_DIRECTORY) { + dirs++; + } else { + files++; + } + } + + if (directory_count != NULL) { + *directory_count = dirs; + } + if (file_count != NULL) { + *file_count = files; + } + if (unreadable_directory_count != NULL) { + *unreadable_directory_count = 0; + } + if (total_size != NULL) { + /* FIXME: Maybe we want to calculate this? */ + *total_size = 0; + } + + nautilus_file_list_free (file_list); + + return NAUTILUS_REQUEST_DONE; +} + +static char * +search_directory_file_get_where_string (NautilusFile *file) +{ + return g_strdup (_("Search")); +} + +static void +nautilus_search_directory_file_init (gpointer object, gpointer klass) +{ + NautilusSearchDirectoryFile *search_file; + NautilusFile *file; + GnomeVFSFileInfo *file_info; + + search_file = NAUTILUS_SEARCH_DIRECTORY_FILE (object); + file = NAUTILUS_FILE(object); + + file_info = file->details->info = gnome_vfs_file_info_new (); + + file_info->name = g_strdup (_("Search")); + file_info->mime_type = g_strdup ("x-directory/normal"); + file_info->type = GNOME_VFS_FILE_TYPE_DIRECTORY; + file_info->flags = GNOME_VFS_FILE_FLAGS_NONE; + file_info->link_count = 1; + file_info->size = 0; + file_info->permissions = + GNOME_VFS_PERM_OTHER_WRITE | + GNOME_VFS_PERM_GROUP_WRITE | + GNOME_VFS_PERM_USER_READ | + GNOME_VFS_PERM_OTHER_READ | + GNOME_VFS_PERM_GROUP_READ; + + file_info->valid_fields = GNOME_VFS_FILE_INFO_FIELDS_TYPE | + GNOME_VFS_FILE_INFO_FIELDS_FLAGS | + GNOME_VFS_FILE_INFO_FIELDS_MIME_TYPE | + GNOME_VFS_FILE_INFO_FIELDS_SIZE | + GNOME_VFS_FILE_INFO_FIELDS_PERMISSIONS | + GNOME_VFS_FILE_INFO_FIELDS_LINK_COUNT; + + file->details->file_info_is_up_to_date = TRUE; + + file->details->display_name = g_strdup (_("Search")); + file->details->custom_icon = NULL; + file->details->activation_uri = NULL; + file->details->got_link_info = TRUE; + file->details->link_info_is_up_to_date = TRUE; + + file->details->directory_count = 0; + file->details->got_directory_count = TRUE; + file->details->directory_count_is_up_to_date = TRUE; +} + +static void +nautilus_search_directory_file_class_init (gpointer klass) +{ + GObjectClass *object_class; + NautilusFileClass *file_class; + + object_class = G_OBJECT_CLASS (klass); + file_class = NAUTILUS_FILE_CLASS (klass); + + file_class->monitor_add = search_directory_file_monitor_add; + file_class->monitor_remove = search_directory_file_monitor_remove; + file_class->call_when_ready = search_directory_file_call_when_ready; + file_class->cancel_call_when_ready = search_directory_file_cancel_call_when_ready; + file_class->get_file_type = search_directory_file_get_file_type; + file_class->check_if_ready = search_directory_file_check_if_ready; + file_class->get_item_count = search_directory_file_get_item_count; + file_class->get_deep_counts = search_directory_file_get_deep_counts; + file_class->get_where_string = search_directory_file_get_where_string; +} diff --git a/libnautilus-private/nautilus-search-directory-file.h b/libnautilus-private/nautilus-search-directory-file.h new file mode 100644 index 000000000..57432f887 --- /dev/null +++ b/libnautilus-private/nautilus-search-directory-file.h @@ -0,0 +1,55 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- + + nautilus-search-directory-file.h: Subclass of NautilusFile to implement the + the case of the search directory + + Copyright (C) 2003 Red Hat, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program 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 + General Public License for more details. + + You should have received a copy of the GNU 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. + + Author: Alexander Larsson <alexl@redhat.com> +*/ + +#ifndef NAUTILUS_SEARCH_DIRECTORY_FILE_H +#define NAUTILUS_SEARCH_DIRECTORY_FILE_H + +#include <libnautilus-private/nautilus-file.h> + +#define NAUTILUS_TYPE_SEARCH_DIRECTORY_FILE \ + (nautilus_search_directory_file_get_type ()) +#define NAUTILUS_SEARCH_DIRECTORY_FILE(obj) \ + (GTK_CHECK_CAST ((obj), NAUTILUS_TYPE_SEARCH_DIRECTORY_FILE, NautilusSearchDirectoryFile)) +#define NAUTILUS_SEARCH_DIRECTORY_FILE_CLASS(klass) \ + (GTK_CHECK_CLASS_CAST ((klass), NAUTILUS_TYPE_SEARCH_DIRECTORY_FILE, NautilusSearchDirectoryFileClass)) +#define NAUTILUS_IS_SEARCH_DIRECTORY_FILE(obj) \ + (GTK_CHECK_TYPE ((obj), NAUTILUS_TYPE_SEARCH_DIRECTORY_FILE)) +#define NAUTILUS_IS_SEARCH_DIRECTORY_FILE_CLASS(klass) \ + (GTK_CHECK_CLASS_TYPE ((klass), NAUTILUS_TYPE_SEARCH_DIRECTORY_FILE)) + +typedef struct NautilusSearchDirectoryFileDetails NautilusSearchDirectoryFileDetails; + +typedef struct { + NautilusFile parent_slot; + NautilusSearchDirectoryFileDetails *details; +} NautilusSearchDirectoryFile; + +typedef struct { + NautilusFileClass parent_slot; +} NautilusSearchDirectoryFileClass; + +GType nautilus_search_directory_file_get_type (void); + +#endif /* NAUTILUS_SEARCH_DIRECTORY_FILE_H */ diff --git a/libnautilus-private/nautilus-search-directory.c b/libnautilus-private/nautilus-search-directory.c new file mode 100644 index 000000000..2172bc245 --- /dev/null +++ b/libnautilus-private/nautilus-search-directory.c @@ -0,0 +1,864 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* + Copyright (C) 2005 Novell, Inc + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program 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 + General Public License for more details. + + You should have received a copy of the GNU 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. + + Author: Anders Carlsson <andersca@imendio.com> +*/ + +#include <config.h> +#include "nautilus-search-directory.h" + +#include "nautilus-directory-private.h" +#include "nautilus-file.h" +#include "nautilus-file-private.h" +#include "nautilus-file-utilities.h" +#include "nautilus-search-engine.h" +#include <eel/eel-glib-extensions.h> +#include <libgnomevfs/gnome-vfs-utils.h> +#include <gtk/gtksignal.h> +#include <libgnome/gnome-macros.h> +#include <string.h> +#include <sys/time.h> + +struct NautilusSearchDirectoryDetails { + NautilusQuery *query; + char *saved_search_uri; + gboolean modified; + + NautilusSearchEngine *engine; + + gboolean search_running; + gboolean search_finished; + + GList *files; + GHashTable *file_hash; + + GList *monitor_list; + GList *callback_list; + GList *pending_callback_list; +}; + +typedef struct { + gboolean monitor_hidden_files; + gboolean monitor_backup_files; + NautilusFileAttributes monitor_attributes; + + gconstpointer client; +} SearchMonitor; + +typedef struct { + NautilusSearchDirectory *search_directory; + + NautilusDirectoryCallback callback; + gpointer callback_data; + + NautilusFileAttributes wait_for_attributes; + gboolean wait_for_file_list; + GList *file_list; + GHashTable *non_ready_hash; +} SearchCallback; + +GNOME_CLASS_BOILERPLATE (NautilusSearchDirectory, nautilus_search_directory, + NautilusDirectory, NAUTILUS_TYPE_DIRECTORY) + +static void search_engine_hits_added (NautilusSearchEngine *engine, GList *hits, NautilusSearchDirectory *search); +static void search_engine_hits_subtracted (NautilusSearchEngine *engine, GList *hits, NautilusSearchDirectory *search); +static void search_engine_finished (NautilusSearchEngine *engine, NautilusSearchDirectory *search); +static void search_engine_error (NautilusSearchEngine *engine, const char *error, NautilusSearchDirectory *search); +static void search_callback_file_ready_callback (NautilusFile *file, gpointer data); +static void file_changed (NautilusFile *file, NautilusSearchDirectory *search); + +static void +ensure_search_engine (NautilusSearchDirectory *search) +{ + if (!search->details->engine) { + search->details->engine = nautilus_search_engine_new (); + g_signal_connect (search->details->engine, "hits-added", + G_CALLBACK (search_engine_hits_added), + search); + g_signal_connect (search->details->engine, "hits-subtracted", + G_CALLBACK (search_engine_hits_subtracted), + search); + g_signal_connect (search->details->engine, "finished", + G_CALLBACK (search_engine_finished), + search); + g_signal_connect (search->details->engine, "error", + G_CALLBACK (search_engine_error), + search); + } +} + +static void +reset_file_list (NautilusSearchDirectory *search) +{ + GList *list, *monitor_list; + NautilusFile *file; + SearchMonitor *monitor; + + /* Remove file connections */ + for (list = search->details->files; list != NULL; list = list->next) { + file = list->data; + + /* Disconnect change handler */ + g_signal_handlers_disconnect_by_func (file, file_changed, search); + + /* Remove monitors */ + for (monitor_list = search->details->monitor_list; monitor_list; + monitor_list = monitor_list->next) { + monitor = monitor_list->data; + nautilus_file_monitor_remove (file, monitor); + } + } + + nautilus_file_list_free (search->details->files); + search->details->files = NULL; +} + +static void +start_or_stop_search_engine (NautilusSearchDirectory *search, gboolean adding) +{ + if (adding && (search->details->monitor_list || + search->details->pending_callback_list) && + search->details->query && + !search->details->search_running) { + /* We need to start the search engine */ + search->details->search_running = TRUE; + search->details->search_finished = FALSE; + ensure_search_engine (search); + nautilus_search_engine_set_query (search->details->engine, search->details->query); + + reset_file_list (search); + + nautilus_search_engine_start (search->details->engine); + } else if (!adding && !search->details->monitor_list && + !search->details->pending_callback_list && + search->details->engine && + search->details->search_running) { + search->details->search_running = FALSE; + nautilus_search_engine_stop (search->details->engine); + + reset_file_list (search); + } + +} + +static void +file_changed (NautilusFile *file, NautilusSearchDirectory *search) +{ + GList list; + + list.data = file; + list.next = NULL; + + nautilus_directory_emit_files_changed (NAUTILUS_DIRECTORY (search), &list); +} + +static void +search_monitor_add (NautilusDirectory *directory, + gconstpointer client, + gboolean monitor_hidden_files, + gboolean monitor_backup_files, + NautilusFileAttributes file_attributes, + NautilusDirectoryCallback callback, + gpointer callback_data) +{ + GList *list; + SearchMonitor *monitor; + NautilusSearchDirectory *search; + NautilusFile *file; + + search = NAUTILUS_SEARCH_DIRECTORY (directory); + + monitor = g_new0 (SearchMonitor, 1); + monitor->monitor_hidden_files = monitor_hidden_files; + monitor->monitor_backup_files = monitor_backup_files; + monitor->monitor_attributes = file_attributes; + monitor->client = client; + + search->details->monitor_list = g_list_prepend (search->details->monitor_list, monitor); + + if (callback != NULL) { + (* callback) (directory, search->details->files, callback_data); + } + + for (list = search->details->files; list != NULL; list = list->next) { + file = list->data; + + /* Add monitors */ + nautilus_file_monitor_add (file, monitor, file_attributes); + } + + start_or_stop_search_engine (search, TRUE); +} + +static void +search_monitor_remove_file_monitors (SearchMonitor *monitor, NautilusSearchDirectory *search) +{ + GList *list; + NautilusFile *file; + + for (list = search->details->files; list != NULL; list = list->next) { + file = list->data; + + nautilus_file_monitor_remove (file, monitor); + } +} + +static void +search_monitor_destroy (SearchMonitor *monitor, NautilusSearchDirectory *search) +{ + search_monitor_remove_file_monitors (monitor, search); + + g_free (monitor); +} + +static void +search_monitor_remove (NautilusDirectory *directory, + gconstpointer client) +{ + NautilusSearchDirectory *search; + SearchMonitor *monitor; + GList *list; + + search = NAUTILUS_SEARCH_DIRECTORY (directory); + + for (list = search->details->monitor_list; list != NULL; list = list->next) { + monitor = list->data; + + if (monitor->client == client) { + search->details->monitor_list = g_list_delete_link (search->details->monitor_list, list); + + search_monitor_destroy (monitor, search); + + break; + } + } + + start_or_stop_search_engine (search, FALSE); +} + +static void +cancel_call_when_ready (gpointer key, gpointer value, gpointer user_data) +{ + SearchCallback *search_callback; + NautilusFile *file; + + file = key; + search_callback = user_data; + + nautilus_file_cancel_call_when_ready (file, search_callback_file_ready_callback, + search_callback); +} + +static void +search_callback_destroy (SearchCallback *search_callback) +{ + if (search_callback->non_ready_hash) { + g_hash_table_foreach (search_callback->non_ready_hash, cancel_call_when_ready, search_callback); + g_hash_table_destroy (search_callback->non_ready_hash); + } + + nautilus_file_list_free (search_callback->file_list); + + g_free (search_callback); +} + +static void +search_callback_invoke_and_destroy (SearchCallback *search_callback) +{ + search_callback->callback (NAUTILUS_DIRECTORY (search_callback->search_directory), + search_callback->file_list, + search_callback->callback_data); + + search_callback->search_directory->details->callback_list = + g_list_remove (search_callback->search_directory->details->callback_list, search_callback); + + search_callback_destroy (search_callback); +} + +static void +search_callback_file_ready_callback (NautilusFile *file, gpointer data) +{ + SearchCallback *search_callback = data; + + g_hash_table_remove (search_callback->non_ready_hash, file); + + if (g_hash_table_size (search_callback->non_ready_hash) == 0) { + search_callback_invoke_and_destroy (search_callback); + } +} + +static void +search_callback_add_file_callbacks (SearchCallback *callback) +{ + GList *file_list_copy, *list; + NautilusFile *file; + + file_list_copy = g_list_copy (callback->file_list); + + for (list = file_list_copy; list != NULL; list = list->next) { + file = list->data; + + nautilus_file_call_when_ready (file, + callback->wait_for_attributes, + search_callback_file_ready_callback, + callback); + } + g_list_free (file_list_copy); +} + +static SearchCallback * +search_callback_find (NautilusSearchDirectory *search, NautilusDirectoryCallback callback, gpointer callback_data) +{ + SearchCallback *search_callback; + GList *list; + + for (list = search->details->callback_list; list != NULL; list = list->next) { + search_callback = list->data; + + if (search_callback->callback == callback && + search_callback->callback_data == callback_data) { + return search_callback; + } + } + + return NULL; +} + +static SearchCallback * +search_callback_find_pending (NautilusSearchDirectory *search, NautilusDirectoryCallback callback, gpointer callback_data) +{ + SearchCallback *search_callback; + GList *list; + + for (list = search->details->pending_callback_list; list != NULL; list = list->next) { + search_callback = list->data; + + if (search_callback->callback == callback && + search_callback->callback_data == callback_data) { + return search_callback; + } + } + + return NULL; +} + +static GHashTable * +file_list_to_hash_table (GList *file_list) +{ + GList *list; + GHashTable *table; + + if (!file_list) + return NULL; + + table = g_hash_table_new (NULL, NULL); + + for (list = file_list; list != NULL; list = list->next) { + g_hash_table_insert (table, list->data, list->data); + } + + return table; +} + +static void +search_call_when_ready (NautilusDirectory *directory, + NautilusFileAttributes file_attributes, + gboolean wait_for_file_list, + NautilusDirectoryCallback callback, + gpointer callback_data) +{ + NautilusSearchDirectory *search; + SearchCallback *search_callback; + + search = NAUTILUS_SEARCH_DIRECTORY (directory); + + search_callback = search_callback_find (search, callback, callback_data); + if (search_callback == NULL) { + search_callback = search_callback_find_pending (search, callback, callback_data); + } + + if (search_callback) { + g_warning ("tried to add a new callback while an old one was pending"); + return; + } + + search_callback = g_new0 (SearchCallback, 1); + search_callback->search_directory = search; + search_callback->callback = callback; + search_callback->callback_data = callback_data; + search_callback->wait_for_attributes = file_attributes; + search_callback->wait_for_file_list = wait_for_file_list; + + if (wait_for_file_list && !search->details->search_finished) { + /* Add it to the pending callback list, which will be + * processed when the directory has finished loading + */ + search->details->pending_callback_list = + g_list_prepend (search->details->pending_callback_list, search_callback); + + /* We might need to start the search engine */ + start_or_stop_search_engine (search, TRUE); + } else { + search_callback->file_list = nautilus_file_list_copy (search->details->files); + search_callback->non_ready_hash = file_list_to_hash_table (search->details->files); + + if (!search_callback->non_ready_hash) { + /* If there are no ready files, we invoke the callback + with an empty list. + */ + search_callback_invoke_and_destroy (search_callback); + } else { + search->details->callback_list = g_list_prepend (search->details->callback_list, search_callback); + search_callback_add_file_callbacks (search_callback); + } + } +} + +static void +search_cancel_callback (NautilusDirectory *directory, + NautilusDirectoryCallback callback, + gpointer callback_data) +{ + NautilusSearchDirectory *search; + SearchCallback *search_callback; + + search = NAUTILUS_SEARCH_DIRECTORY (directory); + search_callback = search_callback_find (search, callback, callback_data); + + if (search_callback) { + search->details->callback_list = g_list_remove (search->details->callback_list, search_callback); + + search_callback_destroy (search_callback); + + return; + } + + /* Check for a pending callback */ + search_callback = search_callback_find_pending (search, callback, callback_data); + + if (search_callback) { + search->details->pending_callback_list = g_list_remove (search->details->pending_callback_list, search_callback); + + search_callback_destroy (search_callback); + + /* We might need to stop the search engine now */ + start_or_stop_search_engine (search, FALSE); + } +} + + +static void +search_engine_hits_added (NautilusSearchEngine *engine, GList *hits, + NautilusSearchDirectory *search) +{ + GList *hit_list; + GList *file_list; + NautilusFile *file; + char *uri; + SearchMonitor *monitor; + GList *monitor_list; + + file_list = NULL; + + for (hit_list = hits; hit_list != NULL; hit_list = hit_list->next) { + uri = hit_list->data; + + if (g_str_has_suffix (uri, NAUTILUS_SAVED_SEARCH_EXTENSION)) { + /* Never return saved searches themselves as hits */ + continue; + } + + file = nautilus_file_get (uri); + + for (monitor_list = search->details->monitor_list; monitor_list; monitor_list = monitor_list->next) { + monitor = monitor_list->data; + + /* Add monitors */ + nautilus_file_monitor_add (file, monitor, monitor->monitor_attributes); + } + + g_signal_connect (file, "changed", G_CALLBACK (file_changed), search), + + file_list = g_list_prepend (file_list, file); + } + + search->details->files = g_list_concat (search->details->files, file_list); + + nautilus_directory_emit_files_added (NAUTILUS_DIRECTORY (search), file_list); + + file = nautilus_directory_get_corresponding_file (NAUTILUS_DIRECTORY (search)); + nautilus_file_emit_changed (file); + nautilus_file_unref (file); +} + +static void +search_engine_hits_subtracted (NautilusSearchEngine *engine, GList *hits, + NautilusSearchDirectory *search) +{ + GList *hit_list; + GList *monitor_list; + SearchMonitor *monitor; + GList *file_list; + char *uri; + NautilusFile *file; + + file_list = NULL; + + for (hit_list = hits; hit_list != NULL; hit_list = hit_list->next) { + uri = hit_list->data; + file = nautilus_file_get (uri); + + for (monitor_list = search->details->monitor_list; monitor_list; + monitor_list = monitor_list->next) { + monitor = monitor_list->data; + /* Remove monitors */ + nautilus_file_monitor_remove (file, monitor); + } + + g_signal_handlers_disconnect_by_func (file, file_changed, search); + + search->details->files = g_list_remove (search->details->files, file); + + file_list = g_list_prepend (file_list, file); + } + + nautilus_directory_emit_files_changed (NAUTILUS_DIRECTORY (search), file_list); + + nautilus_file_list_free (file_list); + + file = nautilus_directory_get_corresponding_file (NAUTILUS_DIRECTORY (search)); + nautilus_file_emit_changed (file); + nautilus_file_unref (file); +} + +static void +search_callback_add_pending_file_callbacks (SearchCallback *callback) +{ + callback->file_list = nautilus_file_list_copy (callback->search_directory->details->files); + callback->non_ready_hash = file_list_to_hash_table (callback->search_directory->details->files); + + search_callback_add_file_callbacks (callback); +} + +static void +search_engine_error (NautilusSearchEngine *engine, const char *error_message, NautilusSearchDirectory *search) +{ + nautilus_directory_emit_load_error (NAUTILUS_DIRECTORY (search), + -1, error_message); +} + +static void +search_engine_finished (NautilusSearchEngine *engine, NautilusSearchDirectory *search) +{ + search->details->search_finished = TRUE; + + nautilus_directory_emit_done_loading (NAUTILUS_DIRECTORY (search)); + + /* Add all file callbacks */ + g_list_foreach (search->details->pending_callback_list, + (GFunc)search_callback_add_pending_file_callbacks, NULL); + search->details->callback_list = g_list_concat (search->details->callback_list, + search->details->pending_callback_list); + + g_list_free (search->details->pending_callback_list); + search->details->pending_callback_list = NULL; +} + +static void +search_force_reload (NautilusDirectory *directory) +{ + NautilusSearchDirectory *search; + + search = NAUTILUS_SEARCH_DIRECTORY (directory); + + if (!search->details->query) { + return; + } + + search->details->search_finished = FALSE; + + if (!search->details->engine) { + return; + } + + /* Remove file monitors */ + reset_file_list (search); + + if (search->details->search_running) { + nautilus_search_engine_stop (search->details->engine); + nautilus_search_engine_set_query (search->details->engine, search->details->query); + nautilus_search_engine_start (search->details->engine); + } +} + +static gboolean +search_are_all_files_seen (NautilusDirectory *directory) +{ + NautilusSearchDirectory *search; + + search = NAUTILUS_SEARCH_DIRECTORY (directory); + + return (!search->details->query || + search->details->search_finished); +} + +static gboolean +search_contains_file (NautilusDirectory *directory, + NautilusFile *file) +{ + NautilusSearchDirectory *search; + + search = NAUTILUS_SEARCH_DIRECTORY (directory); + + /* FIXME: Maybe put the files in a hash */ + return (g_list_find (search->details->files, file) != NULL); +} + +static GList * +search_get_file_list (NautilusDirectory *directory) +{ + NautilusSearchDirectory *search; + + search = NAUTILUS_SEARCH_DIRECTORY (directory); + + return nautilus_file_list_copy (search->details->files); +} + + +static gboolean +search_is_editable (NautilusDirectory *directory) +{ + return FALSE; +} + +static void +search_dispose (GObject *object) +{ + NautilusSearchDirectory *search; + GList *list; + + search = NAUTILUS_SEARCH_DIRECTORY (object); + + /* Remove search monitors */ + if (search->details->monitor_list) { + for (list = search->details->monitor_list; list != NULL; list = list->next) { + search_monitor_destroy ((SearchMonitor *)list->data, search); + } + + g_list_free (search->details->monitor_list); + search->details->monitor_list = NULL; + } + + reset_file_list (search); + + if (search->details->callback_list) { + /* Remove callbacks */ + g_list_foreach (search->details->callback_list, + (GFunc)search_callback_destroy, NULL); + g_list_free (search->details->callback_list); + search->details->callback_list = NULL; + } + + if (search->details->pending_callback_list) { + g_list_foreach (search->details->pending_callback_list, + (GFunc)search_callback_destroy, NULL); + g_list_free (search->details->pending_callback_list); + search->details->pending_callback_list = NULL; + } + + if (search->details->query) { + g_object_unref (search->details->query); + search->details->query = NULL; + } + + if (search->details->engine) { + if (search->details->search_running) { + nautilus_search_engine_stop (search->details->engine); + } + + g_object_unref (search->details->engine); + search->details->engine = NULL; + } + + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +search_finalize (GObject *object) +{ + NautilusSearchDirectory *search; + + search = NAUTILUS_SEARCH_DIRECTORY (object); + + g_free (search->details->saved_search_uri); + + g_free (search->details); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +nautilus_search_directory_instance_init (NautilusSearchDirectory *search) +{ + search->details = g_new0 (NautilusSearchDirectoryDetails, 1); +} + +static void +nautilus_search_directory_class_init (NautilusSearchDirectoryClass *class) +{ + NautilusDirectoryClass *directory_class; + + G_OBJECT_CLASS (class)->dispose = search_dispose; + G_OBJECT_CLASS (class)->finalize = search_finalize; + + directory_class = NAUTILUS_DIRECTORY_CLASS (class); + + directory_class->are_all_files_seen = search_are_all_files_seen; + directory_class->contains_file = search_contains_file; + directory_class->force_reload = search_force_reload; + directory_class->call_when_ready = search_call_when_ready; + directory_class->cancel_callback = search_cancel_callback; + + directory_class->file_monitor_add = search_monitor_add; + directory_class->file_monitor_remove = search_monitor_remove; + + directory_class->get_file_list = search_get_file_list; + directory_class->is_editable = search_is_editable; +} + +char * +nautilus_search_directory_generate_new_uri (void) +{ + static int counter = 0; + struct timeval tv; + char *uri; + + gettimeofday (&tv, NULL); + + uri = g_strdup_printf (EEL_SEARCH_URI"///%ld-%ld-%d/", tv.tv_sec, tv.tv_usec, counter++); + + return uri; +} + + +void +nautilus_search_directory_set_query (NautilusSearchDirectory *search, + NautilusQuery *query) +{ + if (search->details->query != query) { + search->details->modified = TRUE; + } + + if (query) { + g_object_ref (query); + } + + if (search->details->query) { + g_object_unref (search->details->query); + } + + search->details->query = query; +} + +NautilusQuery * +nautilus_search_directory_get_query (NautilusSearchDirectory *search) +{ + if (search->details->query != NULL) { + return g_object_ref (search->details->query); + } + + return NULL; +} + +NautilusSearchDirectory * +nautilus_search_directory_new_from_saved_search (const char *uri) +{ + NautilusSearchDirectory *search; + NautilusQuery *query; + char *file; + + search = NAUTILUS_SEARCH_DIRECTORY (g_object_new (NAUTILUS_TYPE_SEARCH_DIRECTORY, NULL)); + + search->details->saved_search_uri = g_strdup (uri); + + file = gnome_vfs_get_local_path_from_uri (uri); + if (file != NULL) { + query = nautilus_query_load (file); + if (query != NULL) { + nautilus_search_directory_set_query (search, query); + g_object_unref (query); + } + g_free (file); + } else { + g_warning ("Non-local saved searches not supported"); + } + + search->details->modified = FALSE; + return search; +} + +gboolean +nautilus_search_directory_is_saved_search (NautilusSearchDirectory *search) +{ + return search->details->saved_search_uri != NULL; +} + +gboolean +nautilus_search_directory_is_modified (NautilusSearchDirectory *search) +{ + return search->details->modified; +} + +gboolean +nautilus_search_directory_is_indexed (NautilusSearchDirectory *search) +{ + ensure_search_engine (search); + return nautilus_search_engine_is_indexed (search->details->engine); +} + + +void +nautilus_search_directory_save_to_file (NautilusSearchDirectory *search, + const char *save_file_uri) +{ + char *file; + + file = gnome_vfs_get_local_path_from_uri (save_file_uri); + if (file == NULL) { + return; + } + + if (search->details->query != NULL) { + nautilus_query_save (search->details->query, file); + } + + g_free (file); +} + +void +nautilus_search_directory_save_search (NautilusSearchDirectory *search) +{ + if (search->details->saved_search_uri == NULL) { + return; + } + + nautilus_search_directory_save_to_file (search, + search->details->saved_search_uri); + search->details->modified = FALSE; +} diff --git a/libnautilus-private/nautilus-search-directory.h b/libnautilus-private/nautilus-search-directory.h new file mode 100644 index 000000000..c00869206 --- /dev/null +++ b/libnautilus-private/nautilus-search-directory.h @@ -0,0 +1,70 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- + + nautilus-search-directory.h: Subclass of NautilusDirectory to implement + a virtual directory consisting of the search directory and the search + icons + + Copyright (C) 2005 Novell, Inc + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program 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 + General Public License for more details. + + You should have received a copy of the GNU 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. +*/ + +#ifndef NAUTILUS_SEARCH_DIRECTORY_H +#define NAUTILUS_SEARCH_DIRECTORY_H + +#include <libnautilus-private/nautilus-directory.h> +#include <libnautilus-private/nautilus-query.h> + +#define NAUTILUS_TYPE_SEARCH_DIRECTORY \ + (nautilus_search_directory_get_type ()) +#define NAUTILUS_SEARCH_DIRECTORY(obj) \ + (GTK_CHECK_CAST ((obj), NAUTILUS_TYPE_SEARCH_DIRECTORY, NautilusSearchDirectory)) +#define NAUTILUS_SEARCH_DIRECTORY_CLASS(klass) \ + (GTK_CHECK_CLASS_CAST ((klass), NAUTILUS_TYPE_SEARCH_DIRECTORY, NautilusSearchDirectoryClass)) +#define NAUTILUS_IS_SEARCH_DIRECTORY(obj) \ + (GTK_CHECK_TYPE ((obj), NAUTILUS_TYPE_SEARCH_DIRECTORY)) +#define NAUTILUS_IS_SEARCH_DIRECTORY_CLASS(klass) \ + (GTK_CHECK_CLASS_TYPE ((klass), NAUTILUS_TYPE_SEARCH_DIRECTORY)) + +typedef struct NautilusSearchDirectoryDetails NautilusSearchDirectoryDetails; + +typedef struct { + NautilusDirectory parent_slot; + NautilusSearchDirectoryDetails *details; +} NautilusSearchDirectory; + +typedef struct { + NautilusDirectoryClass parent_slot; +} NautilusSearchDirectoryClass; + +GType nautilus_search_directory_get_type (void); + +char *nautilus_search_directory_generate_new_uri (void); + +NautilusSearchDirectory *nautilus_search_directory_new_from_saved_search (const char *uri); + +gboolean nautilus_search_directory_is_saved_search (NautilusSearchDirectory *search); +gboolean nautilus_search_directory_is_modified (NautilusSearchDirectory *search); +gboolean nautilus_search_directory_is_indexed (NautilusSearchDirectory *search); +void nautilus_search_directory_save_search (NautilusSearchDirectory *search); +void nautilus_search_directory_save_to_file (NautilusSearchDirectory *search, + const char *save_file_uri); + +NautilusQuery *nautilus_search_directory_get_query (NautilusSearchDirectory *search); +void nautilus_search_directory_set_query (NautilusSearchDirectory *search, + NautilusQuery *query); + +#endif /* NAUTILUS_SEARCH_DIRECTORY_H */ diff --git a/libnautilus-private/nautilus-search-engine-beagle.c b/libnautilus-private/nautilus-search-engine-beagle.c new file mode 100644 index 000000000..e86f10d01 --- /dev/null +++ b/libnautilus-private/nautilus-search-engine-beagle.c @@ -0,0 +1,289 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* + * Copyright (C) 2005 Novell, Inc. + * + * Nautilus is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Nautilus 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 + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; see the file COPYING. If not, + * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: Anders Carlsson <andersca@imendio.com> + * + */ + +#include <config.h> +#include "nautilus-search-engine-beagle.h" +#include <beagle/beagle.h> + +#include <eel/eel-gtk-macros.h> +#include <eel/eel-glib-extensions.h> + +struct NautilusSearchEngineBeagleDetails { + BeagleClient *client; + NautilusQuery *query; + + BeagleQuery *current_query; + char *current_query_uri_prefix; + gboolean query_finished; +}; + + +static void nautilus_search_engine_beagle_class_init (NautilusSearchEngineBeagleClass *class); +static void nautilus_search_engine_beagle_init (NautilusSearchEngineBeagle *engine); + +G_DEFINE_TYPE (NautilusSearchEngineBeagle, + nautilus_search_engine_beagle, + NAUTILUS_TYPE_SEARCH_ENGINE); + +static NautilusSearchEngineClass *parent_class = NULL; + +static void +finalize (GObject *object) +{ + NautilusSearchEngineBeagle *beagle; + + beagle = NAUTILUS_SEARCH_ENGINE_BEAGLE (object); + + if (beagle->details->current_query) { + g_object_unref (beagle->details->current_query); + beagle->details->current_query = NULL; + g_free (beagle->details->current_query_uri_prefix); + beagle->details->current_query_uri_prefix = NULL; + } + + if (beagle->details->query) { + g_object_unref (beagle->details->query); + beagle->details->query = NULL; + } + + if (beagle->details->client) { + g_object_unref (beagle->details->client); + beagle->details->client = NULL; + } + + g_free (beagle->details); + + EEL_CALL_PARENT (G_OBJECT_CLASS, finalize, (object)); +} + +static void +beagle_hits_added (BeagleQuery *query, + BeagleHitsAddedResponse *response, + NautilusSearchEngineBeagle *engine) +{ + GSList *hits, *list; + GList *hit_uris; + const char *uri; + + hit_uris = NULL; + + hits = beagle_hits_added_response_get_hits (response); + + for (list = hits; list != NULL; list = list->next) { + BeagleHit *hit = BEAGLE_HIT (list->data); + + uri = beagle_hit_get_uri (hit); + + if (engine->details->current_query_uri_prefix && + !g_str_has_prefix (uri, engine->details->current_query_uri_prefix)) { + continue; + } + + hit_uris = g_list_prepend (hit_uris, (char *)uri); + } + + nautilus_search_engine_hits_added (NAUTILUS_SEARCH_ENGINE (engine), hit_uris); + g_list_free (hit_uris); +} + +static void +beagle_hits_subtracted (BeagleQuery *query, + BeagleHitsSubtractedResponse *response, + NautilusSearchEngineBeagle *engine) +{ + GSList *uris, *list; + GList *hit_uris; + + hit_uris = NULL; + + uris = beagle_hits_subtracted_response_get_uris (response); + + for (list = uris; list != NULL; list = list->next) { + hit_uris = g_list_prepend (hit_uris, (char *)list->data); + } + + nautilus_search_engine_hits_subtracted (NAUTILUS_SEARCH_ENGINE (engine), hit_uris); + g_list_free (hit_uris); +} + +static void +beagle_finished (BeagleQuery *query, + BeagleFinishedResponse *response, + NautilusSearchEngineBeagle *engine) +{ + /* For some reason we keep getting finished events, + * only emit finished once */ + if (engine->details->query_finished) { + return; + } + + engine->details->query_finished = TRUE; + nautilus_search_engine_finished (NAUTILUS_SEARCH_ENGINE (engine)); +} + +static void +beagle_error (BeagleQuery *query, + GError *error, + NautilusSearchEngineBeagle *engine) +{ + nautilus_search_engine_error (NAUTILUS_SEARCH_ENGINE (engine), error->message); +} + +static void +nautilus_search_engine_beagle_start (NautilusSearchEngine *engine) +{ + NautilusSearchEngineBeagle *beagle; + GError *error; + GList *mimetypes, *l; + char *text, *mimetype; + + error = NULL; + beagle = NAUTILUS_SEARCH_ENGINE_BEAGLE (engine); + + if (beagle->details->current_query) { + return; + } + + beagle->details->query_finished = FALSE; + beagle->details->current_query = beagle_query_new (); + g_signal_connect (beagle->details->current_query, + "hits-added", G_CALLBACK (beagle_hits_added), engine); + g_signal_connect (beagle->details->current_query, + "hits-subtracted", G_CALLBACK (beagle_hits_subtracted), engine); + g_signal_connect (beagle->details->current_query, + "finished", G_CALLBACK (beagle_finished), engine); + g_signal_connect (beagle->details->current_query, + "error", G_CALLBACK (beagle_error), engine); + + /* We only want files */ + beagle_query_add_hit_type (beagle->details->current_query, + "File"); + beagle_query_set_max_hits (beagle->details->current_query, + 1000); + + text = nautilus_query_get_text (beagle->details->query); + beagle_query_add_text (beagle->details->current_query, + text); + + mimetypes = nautilus_query_get_mime_types (beagle->details->query); + for (l = mimetypes; l != NULL; l = l->next) { + mimetype = l->data; + beagle_query_add_mime_type (beagle->details->current_query, + mimetype); + } + + beagle->details->current_query_uri_prefix = nautilus_query_get_location (beagle->details->query); + + if (!beagle_client_send_request_async (beagle->details->client, + BEAGLE_REQUEST (beagle->details->current_query), &error)) { + nautilus_search_engine_error (engine, error->message); + g_error_free (error); + } + + /* These must live during the lifetime of the query */ + g_free (text); + eel_g_list_free_deep (mimetypes); +} + +static void +nautilus_search_engine_beagle_stop (NautilusSearchEngine *engine) +{ + NautilusSearchEngineBeagle *beagle; + + beagle = NAUTILUS_SEARCH_ENGINE_BEAGLE (engine); + + if (beagle->details->current_query) { + g_object_unref (beagle->details->current_query); + beagle->details->current_query = NULL; + g_free (beagle->details->current_query_uri_prefix); + beagle->details->current_query_uri_prefix = NULL; + } +} + +static gboolean +nautilus_search_engine_beagle_is_indexed (NautilusSearchEngine *engine) +{ + return TRUE; +} + +static void +nautilus_search_engine_beagle_set_query (NautilusSearchEngine *engine, NautilusQuery *query) +{ + NautilusSearchEngineBeagle *beagle; + + beagle = NAUTILUS_SEARCH_ENGINE_BEAGLE (engine); + + if (query) { + g_object_ref (query); + } + + if (beagle->details->query) { + g_object_unref (beagle->details->query); + } + + beagle->details->query = query; +} + +static void +nautilus_search_engine_beagle_class_init (NautilusSearchEngineBeagleClass *class) +{ + GObjectClass *gobject_class; + NautilusSearchEngineClass *engine_class; + + parent_class = g_type_class_peek_parent (class); + + gobject_class = G_OBJECT_CLASS (class); + gobject_class->finalize = finalize; + + engine_class = NAUTILUS_SEARCH_ENGINE_CLASS (class); + engine_class->set_query = nautilus_search_engine_beagle_set_query; + engine_class->start = nautilus_search_engine_beagle_start; + engine_class->stop = nautilus_search_engine_beagle_stop; + engine_class->is_indexed = nautilus_search_engine_beagle_is_indexed; +} + +static void +nautilus_search_engine_beagle_init (NautilusSearchEngineBeagle *engine) +{ + engine->details = g_new0 (NautilusSearchEngineBeagleDetails, 1); +} + + +NautilusSearchEngine * +nautilus_search_engine_beagle_new (void) +{ + NautilusSearchEngineBeagle *engine; + BeagleClient *client; + + client = beagle_client_new (NULL); + + if (client == NULL) { + return NULL; + } + + engine = g_object_new (NAUTILUS_TYPE_SEARCH_ENGINE_BEAGLE, NULL); + + engine->details->client = client; + + return NAUTILUS_SEARCH_ENGINE (engine); +} diff --git a/libnautilus-private/nautilus-search-engine-beagle.h b/libnautilus-private/nautilus-search-engine-beagle.h new file mode 100644 index 000000000..7ee801b37 --- /dev/null +++ b/libnautilus-private/nautilus-search-engine-beagle.h @@ -0,0 +1,51 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* + * Copyright (C) 2005 Novell, Inc. + * + * Nautilus is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Nautilus 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 + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; see the file COPYING. If not, + * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: Anders Carlsson <andersca@imendio.com> + * + */ + +#ifndef NAUTILUS_SEARCH_ENGINE_BEAGLE_H +#define NAUTILUS_SEARCH_ENGINE_BEAGLE_H + +#include <libnautilus-private/nautilus-search-engine.h> + +#define NAUTILUS_TYPE_SEARCH_ENGINE_BEAGLE (nautilus_search_engine_beagle_get_type ()) +#define NAUTILUS_SEARCH_ENGINE_BEAGLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NAUTILUS_TYPE_SEARCH_ENGINE_BEAGLE, NautilusSearchEngineBeagle)) +#define NAUTILUS_SEARCH_ENGINE_BEAGLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NAUTILUS_TYPE_SEARCH_ENGINE_BEAGLE, NautilusSearchEngineBeagleClass)) +#define NAUTILUS_IS_SEARCH_ENGINE_BEAGLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NAUTILUS_TYPE_SEARCH_ENGINE_BEAGLE)) +#define NAUTILUS_IS_SEARCH_ENGINE_BEAGLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NAUTILUS_TYPE_SEARCH_ENGINE_BEAGLE)) +#define NAUTILUS_SEARCH_ENGINE_BEAGLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NAUTILUS_TYPE_SEARCH_ENGINE_BEAGLE, NautilusSearchEngineBeagleClass)) + +typedef struct NautilusSearchEngineBeagleDetails NautilusSearchEngineBeagleDetails; + +typedef struct NautilusSearchEngineBeagle { + NautilusSearchEngine parent; + NautilusSearchEngineBeagleDetails *details; +} NautilusSearchEngineBeagle; + +typedef struct { + NautilusSearchEngineClass parent_class; +} NautilusSearchEngineBeagleClass; + +GType nautilus_search_engine_beagle_get_type (void); + +NautilusSearchEngine* nautilus_search_engine_beagle_new (void); + +#endif /* NAUTILUS_SEARCH_ENGINE_BEAGLE_H */ diff --git a/libnautilus-private/nautilus-search-engine-simple.c b/libnautilus-private/nautilus-search-engine-simple.c new file mode 100644 index 000000000..7e5d5f314 --- /dev/null +++ b/libnautilus-private/nautilus-search-engine-simple.c @@ -0,0 +1,370 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* + * Copyright (C) 2005 Red Hat, Inc + * + * Nautilus is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Nautilus 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 + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; see the file COPYING. If not, + * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: Alexander Larsson <alexl@redhat.com> + * + */ + +#include <config.h> +#include "nautilus-search-engine-simple.h" + +#include <string.h> +#include <glib/gstrfuncs.h> +#include <eel/eel-gtk-macros.h> +#include <eel/eel-glib-extensions.h> +#include <libgnomevfs/gnome-vfs-directory.h> + +#define BATCH_SIZE 500 + +typedef struct { + NautilusSearchEngineSimple *engine; + + GnomeVFSURI *uri; + GList *mime_types; + char **words; + GList *found_list; + + gint n_processed_files; + GList *uri_hits; + + /* accessed on both threads: */ + volatile gboolean cancelled; +} SearchThreadData; + + +struct NautilusSearchEngineSimpleDetails { + NautilusQuery *query; + + SearchThreadData *active_search; + + gboolean query_finished; +}; + + +static void nautilus_search_engine_simple_class_init (NautilusSearchEngineSimpleClass *class); +static void nautilus_search_engine_simple_init (NautilusSearchEngineSimple *engine); + +G_DEFINE_TYPE (NautilusSearchEngineSimple, + nautilus_search_engine_simple, + NAUTILUS_TYPE_SEARCH_ENGINE); + +static NautilusSearchEngineClass *parent_class = NULL; + +static void +finalize (GObject *object) +{ + NautilusSearchEngineSimple *simple; + + simple = NAUTILUS_SEARCH_ENGINE_SIMPLE (object); + + if (simple->details->query) { + g_object_unref (simple->details->query); + simple->details->query = NULL; + } + + g_free (simple->details); + + EEL_CALL_PARENT (G_OBJECT_CLASS, finalize, (object)); +} + +static SearchThreadData * +search_thread_data_new (NautilusSearchEngineSimple *engine, + NautilusQuery *query) +{ + SearchThreadData *data; + char *text, *lower, *uri; + + data = g_new0 (SearchThreadData, 1); + + data->engine = engine; + uri = nautilus_query_get_location (query); + if (uri != NULL) { + data->uri = gnome_vfs_uri_new (uri); + g_free (uri); + } + if (data->uri == NULL) { + data->uri = gnome_vfs_uri_new ("file:///"); + } + + text = nautilus_query_get_text (query); + lower = g_ascii_strdown (text, -1); + data->words = g_strsplit (lower, " ", -1); + g_free (text); + g_free (lower); + + data->mime_types = nautilus_query_get_mime_types (query); + + return data; +} + +static void +search_thread_data_free (SearchThreadData *data) +{ + gnome_vfs_uri_unref (data->uri); + g_strfreev (data->words); + eel_g_list_free_deep (data->mime_types); + g_free (data); +} + +static gboolean +search_thread_done_idle (gpointer user_data) +{ + SearchThreadData *data; + + data = user_data; + + if (!data->cancelled) { + nautilus_search_engine_finished (NAUTILUS_SEARCH_ENGINE (data->engine)); + data->engine->details->active_search = NULL; + } + + search_thread_data_free (data); + + return FALSE; +} + +typedef struct { + GList *uris; + SearchThreadData *thread_data; +} SearchHits; + + +static gboolean +search_thread_add_hits_idle (gpointer user_data) +{ + SearchHits *hits; + + hits = user_data; + + if (!hits->thread_data->cancelled) { + nautilus_search_engine_hits_added (NAUTILUS_SEARCH_ENGINE (hits->thread_data->engine), + hits->uris); + } + + eel_g_list_free_deep (hits->uris); + g_free (hits); + + return FALSE; +} + +static void +send_batch (SearchThreadData *data) +{ + SearchHits *hits; + + data->n_processed_files = 0; + + if (data->uri_hits) { + hits = g_new (SearchHits, 1); + hits->uris = data->uri_hits; + hits->thread_data = data; + g_idle_add (search_thread_add_hits_idle, hits); + } + data->uri_hits = NULL; +} + +static gboolean +search_visit_func (const gchar *rel_path, + GnomeVFSFileInfo *info, + gboolean recursing_will_loop, + gpointer user_data, + gboolean *recurse) +{ + SearchThreadData *data; + int i; + char *lower_name; + GnomeVFSURI *uri; + gboolean hit; + GList *l; + gboolean is_hidden; + + data = user_data; + + if (data->cancelled) { + return FALSE; + } + + is_hidden = *info->name == '.'; + + if (recursing_will_loop || is_hidden) { + *recurse = FALSE; + } else { + *recurse = TRUE; + } + + hit = FALSE; + + if (!is_hidden) { + lower_name = g_ascii_strdown (info->name, -1); + + hit = TRUE; + for (i = 0; data->words[i] != NULL; i++) { + if (strstr (lower_name, data->words[i]) == NULL) { + hit = FALSE; + break; + } + } + g_free (lower_name); + } + + if (hit && data->mime_types != NULL) { + hit = FALSE; + + if (info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_MIME_TYPE) { + for (l = data->mime_types; l != NULL; l = l->next) { + if (strcmp (info->mime_type, l->data) == 0) { + hit = TRUE; + break; + } + } + } + } + + if (hit) { + uri = gnome_vfs_uri_append_string (data->uri, rel_path); + data->uri_hits = g_list_prepend (data->uri_hits, gnome_vfs_uri_to_string (uri, 0)); + gnome_vfs_uri_unref (uri); + } + + data->n_processed_files++; + + if (data->n_processed_files > BATCH_SIZE) { + send_batch (data); + } + + + return TRUE; +} + + + +static gpointer +search_thread_func (gpointer user_data) +{ + SearchThreadData *data; + GnomeVFSResult res; + + data = user_data; + + res = gnome_vfs_directory_visit_uri (data->uri, + GNOME_VFS_FILE_INFO_GET_MIME_TYPE | GNOME_VFS_FILE_INFO_FOLLOW_LINKS, + GNOME_VFS_DIRECTORY_VISIT_LOOPCHECK, + search_visit_func, + data); + send_batch (data); + + g_idle_add (search_thread_done_idle, data); + + return NULL; +} + +static void +nautilus_search_engine_simple_start (NautilusSearchEngine *engine) +{ + NautilusSearchEngineSimple *simple; + SearchThreadData *data; + + simple = NAUTILUS_SEARCH_ENGINE_SIMPLE (engine); + + if (simple->details->active_search != NULL) { + return; + } + + if (simple->details->query == NULL) { + return; + } + + data = search_thread_data_new (simple, simple->details->query); + + g_thread_create (search_thread_func, data, FALSE, NULL); + + simple->details->active_search = data; +} + +static void +nautilus_search_engine_simple_stop (NautilusSearchEngine *engine) +{ + NautilusSearchEngineSimple *simple; + + simple = NAUTILUS_SEARCH_ENGINE_SIMPLE (engine); + + if (simple->details->active_search != NULL) { + simple->details->active_search->cancelled = TRUE; + simple->details->active_search = NULL; + } +} + +static gboolean +nautilus_search_engine_simple_is_indexed (NautilusSearchEngine *engine) +{ + return FALSE; +} + +static void +nautilus_search_engine_simple_set_query (NautilusSearchEngine *engine, NautilusQuery *query) +{ + NautilusSearchEngineSimple *simple; + + simple = NAUTILUS_SEARCH_ENGINE_SIMPLE (engine); + + if (query) { + g_object_ref (query); + } + + if (simple->details->query) { + g_object_unref (simple->details->query); + } + + simple->details->query = query; +} + +static void +nautilus_search_engine_simple_class_init (NautilusSearchEngineSimpleClass *class) +{ + GObjectClass *gobject_class; + NautilusSearchEngineClass *engine_class; + + parent_class = g_type_class_peek_parent (class); + + gobject_class = G_OBJECT_CLASS (class); + gobject_class->finalize = finalize; + + engine_class = NAUTILUS_SEARCH_ENGINE_CLASS (class); + engine_class->set_query = nautilus_search_engine_simple_set_query; + engine_class->start = nautilus_search_engine_simple_start; + engine_class->stop = nautilus_search_engine_simple_stop; + engine_class->is_indexed = nautilus_search_engine_simple_is_indexed; +} + +static void +nautilus_search_engine_simple_init (NautilusSearchEngineSimple *engine) +{ + engine->details = g_new0 (NautilusSearchEngineSimpleDetails, 1); +} + + +NautilusSearchEngine * +nautilus_search_engine_simple_new (void) +{ + NautilusSearchEngine *engine; + + engine = g_object_new (NAUTILUS_TYPE_SEARCH_ENGINE_SIMPLE, NULL); + + return engine; +} diff --git a/libnautilus-private/nautilus-search-engine-simple.h b/libnautilus-private/nautilus-search-engine-simple.h new file mode 100644 index 000000000..be7bfb1b0 --- /dev/null +++ b/libnautilus-private/nautilus-search-engine-simple.h @@ -0,0 +1,51 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* + * Copyright (C) 2005 Red Hat, Inc + * + * Nautilus is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Nautilus 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 + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; see the file COPYING. If not, + * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: Alexander Larsson <alexl@redhat.com> + * + */ + +#ifndef NAUTILUS_SEARCH_ENGINE_SIMPLE_H +#define NAUTILUS_SEARCH_ENGINE_SIMPLE_H + +#include <libnautilus-private/nautilus-search-engine.h> + +#define NAUTILUS_TYPE_SEARCH_ENGINE_SIMPLE (nautilus_search_engine_simple_get_type ()) +#define NAUTILUS_SEARCH_ENGINE_SIMPLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NAUTILUS_TYPE_SEARCH_ENGINE_SIMPLE, NautilusSearchEngineSimple)) +#define NAUTILUS_SEARCH_ENGINE_SIMPLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NAUTILUS_TYPE_SEARCH_ENGINE_SIMPLE, NautilusSearchEngineSimpleClass)) +#define NAUTILUS_IS_SEARCH_ENGINE_SIMPLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NAUTILUS_TYPE_SEARCH_ENGINE_SIMPLE)) +#define NAUTILUS_IS_SEARCH_ENGINE_SIMPLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NAUTILUS_TYPE_SEARCH_ENGINE_SIMPLE)) +#define NAUTILUS_SEARCH_ENGINE_SIMPLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NAUTILUS_TYPE_SEARCH_ENGINE_SIMPLE, NautilusSearchEngineSimpleClass)) + +typedef struct NautilusSearchEngineSimpleDetails NautilusSearchEngineSimpleDetails; + +typedef struct NautilusSearchEngineSimple { + NautilusSearchEngine parent; + NautilusSearchEngineSimpleDetails *details; +} NautilusSearchEngineSimple; + +typedef struct { + NautilusSearchEngineClass parent_class; +} NautilusSearchEngineSimpleClass; + +GType nautilus_search_engine_simple_get_type (void); + +NautilusSearchEngine* nautilus_search_engine_simple_new (void); + +#endif /* NAUTILUS_SEARCH_ENGINE_SIMPLE_H */ diff --git a/libnautilus-private/nautilus-search-engine.c b/libnautilus-private/nautilus-search-engine.c new file mode 100644 index 000000000..d98b1f40e --- /dev/null +++ b/libnautilus-private/nautilus-search-engine.c @@ -0,0 +1,207 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* + * Copyright (C) 2005 Novell, Inc. + * + * Nautilus is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Nautilus 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 + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; see the file COPYING. If not, + * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: Anders Carlsson <andersca@imendio.com> + * + */ + +#include <config.h> +#include "nautilus-search-engine.h" +#include "nautilus-search-engine-beagle.h" +#include "nautilus-search-engine-simple.h" + +#include <eel/eel-gtk-macros.h> + +struct NautilusSearchEngineDetails { + int none; +}; + +enum { + HITS_ADDED, + HITS_SUBTRACTED, + FINISHED, + ERROR, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL]; + +static void nautilus_search_engine_class_init (NautilusSearchEngineClass *class); +static void nautilus_search_engine_init (NautilusSearchEngine *engine); + +G_DEFINE_ABSTRACT_TYPE (NautilusSearchEngine, + nautilus_search_engine, + G_TYPE_OBJECT); + +static GObjectClass *parent_class = NULL; + +static void +finalize (GObject *object) +{ + NautilusSearchEngine *engine; + + engine = NAUTILUS_SEARCH_ENGINE (object); + + g_free (engine->details); + + EEL_CALL_PARENT (G_OBJECT_CLASS, finalize, (object)); +} + +static void +nautilus_search_engine_class_init (NautilusSearchEngineClass *class) +{ + GObjectClass *gobject_class; + + parent_class = g_type_class_peek_parent (class); + + gobject_class = G_OBJECT_CLASS (class); + gobject_class->finalize = finalize; + + signals[HITS_ADDED] = + g_signal_new ("hits-added", + G_TYPE_FROM_CLASS (class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (NautilusSearchEngineClass, hits_added), + NULL, NULL, + g_cclosure_marshal_VOID__POINTER, + G_TYPE_NONE, 1, + G_TYPE_POINTER); + + signals[HITS_SUBTRACTED] = + g_signal_new ("hits-subtracted", + G_TYPE_FROM_CLASS (class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (NautilusSearchEngineClass, hits_subtracted), + NULL, NULL, + g_cclosure_marshal_VOID__POINTER, + G_TYPE_NONE, 1, + G_TYPE_POINTER); + + signals[FINISHED] = + g_signal_new ("finished", + G_TYPE_FROM_CLASS (class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (NautilusSearchEngineClass, finished), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + signals[ERROR] = + g_signal_new ("error", + G_TYPE_FROM_CLASS (class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (NautilusSearchEngineClass, error), + NULL, NULL, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, 1, + G_TYPE_STRING); + +} + +static void +nautilus_search_engine_init (NautilusSearchEngine *engine) +{ + engine->details = g_new0 (NautilusSearchEngineDetails, 1); +} + +NautilusSearchEngine * +nautilus_search_engine_new (void) +{ + NautilusSearchEngine *engine; + +#ifdef HAVE_BEAGLE + engine = nautilus_search_engine_beagle_new (); + if (engine) { + return engine; + } +#endif + engine = nautilus_search_engine_simple_new (); + return engine; +} + +void +nautilus_search_engine_set_query (NautilusSearchEngine *engine, NautilusQuery *query) +{ + g_return_if_fail (NAUTILUS_IS_SEARCH_ENGINE (engine)); + g_return_if_fail (NAUTILUS_SEARCH_ENGINE_GET_CLASS (engine)->set_query != NULL); + + NAUTILUS_SEARCH_ENGINE_GET_CLASS (engine)->set_query (engine, query); +} + +void +nautilus_search_engine_start (NautilusSearchEngine *engine) +{ + g_return_if_fail (NAUTILUS_IS_SEARCH_ENGINE (engine)); + g_return_if_fail (NAUTILUS_SEARCH_ENGINE_GET_CLASS (engine)->start != NULL); + + NAUTILUS_SEARCH_ENGINE_GET_CLASS (engine)->start (engine); +} + + +void +nautilus_search_engine_stop (NautilusSearchEngine *engine) +{ + g_return_if_fail (NAUTILUS_IS_SEARCH_ENGINE (engine)); + g_return_if_fail (NAUTILUS_SEARCH_ENGINE_GET_CLASS (engine)->stop != NULL); + + NAUTILUS_SEARCH_ENGINE_GET_CLASS (engine)->stop (engine); +} + +gboolean +nautilus_search_engine_is_indexed (NautilusSearchEngine *engine) +{ + g_return_val_if_fail (NAUTILUS_IS_SEARCH_ENGINE (engine), FALSE); + g_return_val_if_fail (NAUTILUS_SEARCH_ENGINE_GET_CLASS (engine)->is_indexed != NULL, FALSE); + + return NAUTILUS_SEARCH_ENGINE_GET_CLASS (engine)->is_indexed (engine); +} + +void +nautilus_search_engine_hits_added (NautilusSearchEngine *engine, GList *hits) +{ + g_return_if_fail (NAUTILUS_IS_SEARCH_ENGINE (engine)); + + g_signal_emit (engine, signals[HITS_ADDED], 0, hits); +} + + +void +nautilus_search_engine_hits_subtracted (NautilusSearchEngine *engine, GList *hits) +{ + g_return_if_fail (NAUTILUS_IS_SEARCH_ENGINE (engine)); + + g_signal_emit (engine, signals[HITS_SUBTRACTED], 0, hits); +} + + +void +nautilus_search_engine_finished (NautilusSearchEngine *engine) +{ + g_return_if_fail (NAUTILUS_IS_SEARCH_ENGINE (engine)); + + g_signal_emit (engine, signals[FINISHED], 0); +} + +void +nautilus_search_engine_error (NautilusSearchEngine *engine, const char *error_message) +{ + g_return_if_fail (NAUTILUS_IS_SEARCH_ENGINE (engine)); + + g_signal_emit (engine, signals[ERROR], 0, error_message); +} diff --git a/libnautilus-private/nautilus-search-engine.h b/libnautilus-private/nautilus-search-engine.h new file mode 100644 index 000000000..79e68aeb3 --- /dev/null +++ b/libnautilus-private/nautilus-search-engine.h @@ -0,0 +1,76 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* + * Copyright (C) 2005 Novell, Inc. + * + * Nautilus is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Nautilus 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 + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; see the file COPYING. If not, + * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: Anders Carlsson <andersca@imendio.com> + * + */ + +#ifndef NAUTILUS_SEARCH_ENGINE_H +#define NAUTILUS_SEARCH_ENGINE_H + +#include <glib-object.h> +#include <libgnomevfs/gnome-vfs-result.h> +#include <libnautilus-private/nautilus-query.h> + +#define NAUTILUS_TYPE_SEARCH_ENGINE (nautilus_search_engine_get_type ()) +#define NAUTILUS_SEARCH_ENGINE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NAUTILUS_TYPE_SEARCH_ENGINE, NautilusSearchEngine)) +#define NAUTILUS_SEARCH_ENGINE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NAUTILUS_TYPE_SEARCH_ENGINE, NautilusSearchEngineClass)) +#define NAUTILUS_IS_SEARCH_ENGINE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NAUTILUS_TYPE_SEARCH_ENGINE)) +#define NAUTILUS_IS_SEARCH_ENGINE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NAUTILUS_TYPE_SEARCH_ENGINE)) +#define NAUTILUS_SEARCH_ENGINE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NAUTILUS_TYPE_SEARCH_ENGINE, NautilusSearchEngineClass)) + +typedef struct NautilusSearchEngineDetails NautilusSearchEngineDetails; + +typedef struct NautilusSearchEngine { + GObject parent; + NautilusSearchEngineDetails *details; +} NautilusSearchEngine; + +typedef struct { + GObjectClass parent_class; + + /* VTable */ + void (*set_query) (NautilusSearchEngine *engine, NautilusQuery *query); + void (*start) (NautilusSearchEngine *engine); + void (*stop) (NautilusSearchEngine *engine); + gboolean (*is_indexed) (NautilusSearchEngine *engine); + + /* Signals */ + void (*hits_added) (NautilusSearchEngine *engine, GList *hits); + void (*hits_subtracted) (NautilusSearchEngine *engine, GList *hits); + void (*finished) (NautilusSearchEngine *engine); + void (*error) (NautilusSearchEngine *engine, const char *error_message); +} NautilusSearchEngineClass; + +GType nautilus_search_engine_get_type (void); +gboolean nautilus_search_engine_enabled (void); + +NautilusSearchEngine* nautilus_search_engine_new (void); + +void nautilus_search_engine_set_query (NautilusSearchEngine *engine, NautilusQuery *query); +void nautilus_search_engine_start (NautilusSearchEngine *engine); +void nautilus_search_engine_stop (NautilusSearchEngine *engine); +gboolean nautilus_search_engine_is_indexed (NautilusSearchEngine *engine); + +void nautilus_search_engine_hits_added (NautilusSearchEngine *engine, GList *hits); +void nautilus_search_engine_hits_subtracted (NautilusSearchEngine *engine, GList *hits); +void nautilus_search_engine_finished (NautilusSearchEngine *engine); +void nautilus_search_engine_error (NautilusSearchEngine *engine, const char *error_message); + +#endif /* NAUTILUS_SEARCH_ENGINE_H */ diff --git a/libnautilus-private/nautilus-tree-view-drag-dest.c b/libnautilus-private/nautilus-tree-view-drag-dest.c index 4d6b3aedb..1d0c94df8 100644 --- a/libnautilus-private/nautilus-tree-view-drag-dest.c +++ b/libnautilus-private/nautilus-tree-view-drag-dest.c @@ -310,21 +310,23 @@ get_drop_path (NautilusTreeViewDragDest *dest, return NULL; } - file = file_for_path (dest, path); - - ret = NULL; + ret = gtk_tree_path_copy (path); + file = file_for_path (dest, ret); - if (!file || !nautilus_drag_can_accept_items (file, dest->details->drag_list)){ + /* Go up the tree until we find a file that can accept a drop */ + while (file == NULL /* dummy row */ || + !nautilus_drag_can_accept_items (file, dest->details->drag_list)) { if (gtk_tree_path_get_depth (path) == 1) { + gtk_tree_path_free (ret); ret = NULL; + break; } else { - ret = gtk_tree_path_copy (path); gtk_tree_path_up (ret); + + nautilus_file_unref (file); + file = file_for_path (dest, ret); } - } else { - ret = gtk_tree_path_copy (path); } - nautilus_file_unref (file); return ret; |