summaryrefslogtreecommitdiff
path: root/libnautilus-private/nautilus-directory-async.c
diff options
context:
space:
mode:
Diffstat (limited to 'libnautilus-private/nautilus-directory-async.c')
-rw-r--r--libnautilus-private/nautilus-directory-async.c879
1 files changed, 562 insertions, 317 deletions
diff --git a/libnautilus-private/nautilus-directory-async.c b/libnautilus-private/nautilus-directory-async.c
index 4e2fbd212..5ed4ee009 100644
--- a/libnautilus-private/nautilus-directory-async.c
+++ b/libnautilus-private/nautilus-directory-async.c
@@ -38,6 +38,8 @@
#include <ctype.h>
#include <libxml/parser.h>
#include <libxml/xmlmemory.h>
+#include <libgnome/gnome-metadata.h>
+#include <libgnome/gnome-mime-info.h>
#include <gtk/gtkmain.h>
#include <stdlib.h>
#include <stdio.h>
@@ -68,7 +70,7 @@ struct TopLeftTextReadState {
EelReadFileHandle *handle;
};
-struct ActivationURIReadState {
+struct LinkInfoReadState {
NautilusFile *file;
EelReadFileHandle *handle;
};
@@ -102,13 +104,27 @@ static GHashTable *async_jobs;
#endif
/* Forward declarations for functions that need them. */
-static void deep_count_load (NautilusDirectory *directory,
- const char *uri);
-static gboolean request_is_satisfied (NautilusDirectory *directory,
- NautilusFile *file,
- Request *request);
-static void cancel_loading_attributes (NautilusDirectory *directory,
- GList *file_attributes);
+static void deep_count_load (NautilusDirectory *directory,
+ const char *uri);
+static gboolean request_is_satisfied (NautilusDirectory *directory,
+ NautilusFile *file,
+ Request *request);
+static void cancel_loading_attributes (NautilusDirectory *directory,
+ GList *file_attributes);
+static void add_all_files_to_work_queue (NautilusDirectory *directory);
+static void link_info_done (NautilusDirectory *directory,
+ NautilusFile *file,
+ const char *uri,
+ const char *name,
+ const char *icon);
+static gboolean file_needs_high_priority_work_done (NautilusDirectory *directory,
+ NautilusFile *file);
+static gboolean file_needs_low_priority_work_done (NautilusDirectory *directory,
+ NautilusFile *file);
+static void move_file_to_low_priority_queue (NautilusDirectory *directory,
+ NautilusFile *file);
+
+
/* Some helpers for case-insensitive strings.
* Move to nautilus-glib-extensions?
@@ -376,14 +392,13 @@ top_left_cancel (NautilusDirectory *directory)
}
static void
-activation_uri_cancel (NautilusDirectory *directory)
+link_info_cancel (NautilusDirectory *directory)
{
- if (directory->details->activation_uri_read_state != NULL) {
- eel_read_file_cancel (directory->details->activation_uri_read_state->handle);
- g_free (directory->details->activation_uri_read_state);
- directory->details->activation_uri_read_state = NULL;
-
- async_job_end (directory, "activation URI");
+ if (directory->details->link_info_read_state != NULL) {
+ eel_read_file_cancel (directory->details->link_info_read_state->handle);
+ g_free (directory->details->link_info_read_state);
+ directory->details->link_info_read_state = NULL;
+ async_job_end (directory, "link info");
}
}
@@ -536,13 +551,15 @@ nautilus_directory_set_up_request (Request *request,
NAUTILUS_FILE_ATTRIBUTE_ACTIVATION_URI,
eel_strcmp_compare_func) != NULL) {
request->file_info = TRUE;
- request->activation_uri = TRUE;
+ request->link_info = TRUE;
+ }
+
+ if (g_list_find_custom (file_attributes,
+ NAUTILUS_FILE_ATTRIBUTE_CUSTOM_NAME,
+ eel_strcmp_compare_func) != NULL) {
+ request->file_info = TRUE;
+ request->link_info = TRUE;
}
-
- request->metafile |= g_list_find_custom
- (file_attributes,
- NAUTILUS_FILE_ATTRIBUTE_METADATA,
- eel_strcmp_compare_func) != NULL;
/* FIXME bugzilla.gnome.org 42435:
* Some file attributes are really pieces of metadata.
@@ -555,10 +572,19 @@ nautilus_directory_set_up_request (Request *request,
* directly (would need some funky char trick to prevent
* namespace collisions).
*/
+ if (g_list_find_custom (file_attributes,
+ NAUTILUS_FILE_ATTRIBUTE_CUSTOM_ICON,
+ eel_strcmp_compare_func) != NULL) {
+ request->metafile = TRUE;
+ request->file_info = TRUE;
+ request->link_info = TRUE;
+ }
+
request->metafile |= g_list_find_custom
(file_attributes,
- NAUTILUS_FILE_ATTRIBUTE_CUSTOM_ICON,
+ NAUTILUS_FILE_ATTRIBUTE_METADATA,
eel_strcmp_compare_func) != NULL;
+
}
void
@@ -618,6 +644,13 @@ nautilus_directory_monitor_add_internal (NautilusDirectory *directory,
nautilus_directory_register_metadata_monitor (directory);
}
+ /* Put the monitor file or all the files on the work queue. */
+ if (file != NULL) {
+ nautilus_directory_add_file_to_work_queue (directory, file);
+ } else {
+ add_all_files_to_work_queue (directory);
+ }
+
/* Kick off I/O. */
nautilus_directory_async_state_changed (directory);
}
@@ -1052,6 +1085,8 @@ nautilus_directory_monitor_remove_internal (NautilusDirectory *directory,
update_metadata_monitors (directory);
+ /* XXX - do we need to remove anything from the work queue? */
+
nautilus_directory_async_state_changed (directory);
}
@@ -1080,6 +1115,9 @@ nautilus_directory_remove_file_monitors (NautilusDirectory *directory,
}
update_metadata_monitors (directory);
+
+ /* XXX - do we need to remove anything from the work queue? */
+
nautilus_directory_async_state_changed (directory);
return (FileMonitors *) result;
@@ -1103,6 +1141,8 @@ nautilus_directory_add_file_monitors (NautilusDirectory *directory,
list = &directory->details->monitor_list;
*list = g_list_concat (*list, (GList *) monitors);
+ nautilus_directory_add_file_to_work_queue (directory, file);
+
update_metadata_monitors (directory);
nautilus_directory_async_state_changed (directory);
}
@@ -1224,6 +1264,13 @@ nautilus_directory_call_when_ready_internal (NautilusDirectory *directory,
nautilus_directory_register_metadata_monitor (directory);
}
+ /* Put the callback file or all the files on the work queue. */
+ if (file != NULL) {
+ nautilus_directory_add_file_to_work_queue (directory, file);
+ } else {
+ add_all_files_to_work_queue (directory);
+ }
+
nautilus_directory_async_state_changed (directory);
}
@@ -1325,7 +1372,10 @@ directory_count_callback (GnomeVFSAsyncHandle *handle,
/* Record either a failure or success. */
if (result != GNOME_VFS_ERROR_EOF) {
count_file->details->directory_count_failed = TRUE;
+ count_file->details->got_directory_count = FALSE;
+ count_file->details->directory_count = 0;
} else {
+ count_file->details->directory_count_failed = FALSE;
count_file->details->got_directory_count = TRUE;
count_file->details->directory_count = entries_read;
}
@@ -1459,9 +1509,9 @@ nautilus_async_destroying_file (NautilusFile *file)
directory->details->top_left_read_state->file = NULL;
changed = TRUE;
}
- if (directory->details->activation_uri_read_state != NULL
- && directory->details->activation_uri_read_state->file == file) {
- directory->details->activation_uri_read_state->file = NULL;
+ if (directory->details->link_info_read_state != NULL
+ && directory->details->link_info_read_state->file == file) {
+ directory->details->link_info_read_state->file = NULL;
changed = TRUE;
}
@@ -1474,9 +1524,8 @@ nautilus_async_destroying_file (NautilusFile *file)
static gboolean
lacks_directory_count (NautilusFile *file)
{
- return nautilus_file_is_directory (file)
- && nautilus_file_should_show_directory_item_count (file)
- && !file->details->directory_count_is_up_to_date;
+ return !file->details->directory_count_is_up_to_date
+ && nautilus_file_should_show_directory_item_count (file);
}
static gboolean
@@ -1495,9 +1544,9 @@ wants_directory_count (const Request *request)
static gboolean
lacks_top_left (NautilusFile *file)
{
- return nautilus_file_should_get_top_left_text (file)
- && nautilus_file_contains_text (file)
- && !file->details->top_left_text_is_up_to_date;
+ return file->details->file_info_is_up_to_date &&
+ !file->details->top_left_text_is_up_to_date
+ && nautilus_file_should_get_top_left_text (file);
}
static gboolean
@@ -1522,8 +1571,7 @@ wants_info (const Request *request)
static gboolean
lacks_deep_count (NautilusFile *file)
{
- return nautilus_file_is_directory (file)
- && file->details->deep_counts_status != NAUTILUS_REQUEST_DONE;
+ return file->details->deep_counts_status != NAUTILUS_REQUEST_DONE;
}
static gboolean
@@ -1535,8 +1583,7 @@ wants_deep_count (const Request *request)
static gboolean
lacks_mime_list (NautilusFile *file)
{
- return nautilus_file_is_directory (file)
- && !file->details->mime_list_is_up_to_date;
+ return !file->details->mime_list_is_up_to_date;
}
static gboolean
@@ -1553,16 +1600,28 @@ wants_mime_list (const Request *request)
}
static gboolean
-lacks_activation_uri (NautilusFile *file)
-{
- return file->details->info != NULL
- && !file->details->activation_uri_is_up_to_date;
+lacks_link_info (NautilusFile *file)
+{
+ if (file->details->file_info_is_up_to_date &&
+ !file->details->link_info_is_up_to_date) {
+ if ((nautilus_file_is_mime_type (file, "application/x-gmc-link") &&
+ nautilus_file_is_in_desktop (file)) ||
+ nautilus_file_is_nautilus_link (file) ||
+ nautilus_file_is_directory (file)) {
+ return TRUE;
+ } else {
+ link_info_done (file->details->directory, file, NULL, NULL, NULL);
+ return FALSE;
+ }
+ } else {
+ return FALSE;
+ }
}
static gboolean
-wants_activation_uri (const Request *request)
+wants_link_info (const Request *request)
{
- return request->activation_uri;
+ return request->link_info;
}
@@ -1628,8 +1687,8 @@ request_is_satisfied (NautilusDirectory *directory,
}
}
- if (request->activation_uri) {
- if (has_problem (directory, file, lacks_activation_uri)) {
+ if (request->link_info) {
+ if (has_problem (directory, file, lacks_link_info)) {
return FALSE;
}
}
@@ -1845,7 +1904,7 @@ nautilus_directory_stop_monitoring_file_list (NautilusDirectory *directory)
}
static void
-file_list_start (NautilusDirectory *directory)
+file_list_start_or_stop (NautilusDirectory *directory)
{
if (nautilus_directory_is_anyone_monitoring_file_list (directory)) {
start_monitoring_file_list (directory);
@@ -1857,21 +1916,12 @@ file_list_start (NautilusDirectory *directory)
void
nautilus_file_invalidate_count_and_mime_list (NautilusFile *file)
{
- NautilusDirectory *parent_directory;
+ GList *attributes = NULL;
- parent_directory = file->details->directory;
-
- if (parent_directory->details->count_file == file) {
- directory_count_cancel (parent_directory);
- }
- if (parent_directory->details->mime_list_file == file) {
- mime_list_cancel (parent_directory);
- }
-
- file->details->directory_count_is_up_to_date = FALSE;
- file->details->mime_list_is_up_to_date = FALSE;
+ attributes = g_list_prepend (attributes, NAUTILUS_FILE_ATTRIBUTE_DIRECTORY_ITEM_COUNT);
+ attributes = g_list_prepend (attributes, NAUTILUS_FILE_ATTRIBUTE_DIRECTORY_ITEM_MIME_TYPES);
- nautilus_directory_async_state_changed (parent_directory);
+ nautilus_file_invalidate_attributes (file, attributes);
}
@@ -1927,6 +1977,7 @@ nautilus_directory_force_reload_internal (NautilusDirectory *directory,
/* Start a new directory count. */
nautilus_directory_invalidate_count_and_mime_list (directory);
+ add_all_files_to_work_queue (directory);
nautilus_directory_async_state_changed (directory);
}
@@ -1990,108 +2041,11 @@ is_needy (NautilusFile *file,
return FALSE;
}
-static NautilusFile *
-select_needy_file (NautilusDirectory *directory,
- FileCheck check_missing,
- RequestCheck check_wanted)
-{
- GList *node, *node_2;
- ReadyCallback *callback;
- Monitor *monitor;
- NautilusFile *file;
-
- /* Quick out if no one is interested. */
- for (node = directory->details->call_when_ready_list;
- node != NULL; node = node->next) {
- callback = node->data;
- if ((* check_wanted) (&callback->request)) {
- break;
- }
- }
- if (node == NULL) {
- for (node = directory->details->monitor_list;
- node != NULL; node = node->next) {
- monitor = node->data;
- if ((* check_wanted) (&monitor->request)) {
- break;
- }
- }
- if (node == NULL) {
- return NULL;
- }
- }
-
- /* Search for a file that has an unfulfilled request. */
- for (node = directory->details->file_list;
- node != NULL; node = node->next) {
- file = node->data;
- if ((* check_missing) (file)) {
- for (node_2 = directory->details->call_when_ready_list;
- node_2 != NULL; node_2 = node_2->next) {
- callback = node_2->data;
- if ((callback->file == NULL || callback->file == file)
- && (* check_wanted) (&callback->request)) {
- break;
- }
- }
- if (node_2 != NULL) {
- return file;
- }
- for (node_2 = directory->details->monitor_list;
- node_2 != NULL; node_2 = node_2->next) {
- monitor = node_2->data;
- if (monitor_includes_file (monitor, file)
- && (* check_wanted) (&monitor->request)) {
- break;
- }
- }
- if (node_2 != NULL) {
- return file;
- }
- }
- }
-
- /* Finally, check the file for the directory itself. */
- file = directory->details->as_file;
- if (file != NULL) {
- if ((* check_missing) (file)) {
- for (node_2 = directory->details->call_when_ready_list;
- node_2 != NULL; node_2 = node_2->next) {
- callback = node_2->data;
- if (callback->file == file
- && (* check_wanted) (&callback->request)) {
- break;
- }
- }
- if (node_2 != NULL) {
- return file;
- }
- for (node_2 = directory->details->monitor_list;
- node_2 != NULL; node_2 = node_2->next) {
- monitor = node_2->data;
- if (monitor->file == file
- && (* check_wanted) (&monitor->request)) {
- break;
- }
- }
- if (node_2 != NULL) {
- return file;
- }
- }
- }
-
- return NULL;
-}
-
static void
-directory_count_start (NautilusDirectory *directory)
+directory_count_stop (NautilusDirectory *directory)
{
NautilusFile *file;
- char *uri;
- /* If there's already a count in progress, check to be sure
- * it's still wanted.
- */
if (directory->details->count_in_progress != NULL) {
file = directory->details->count_file;
if (file != NULL) {
@@ -2107,12 +2061,30 @@ directory_count_start (NautilusDirectory *directory)
/* The count is not wanted, so stop it. */
directory_count_cancel (directory);
}
+}
- /* Figure out which file to get a count for. */
- file = select_needy_file (directory,
- should_get_directory_count_now,
- wants_directory_count);
- if (file == NULL) {
+static void
+directory_count_start (NautilusDirectory *directory,
+ NautilusFile *file)
+{
+ char *uri;
+
+ if (directory->details->count_in_progress != NULL) {
+ return;
+ }
+
+ if (!is_needy (file,
+ should_get_directory_count_now,
+ wants_directory_count)) {
+ return;
+ }
+
+ if (!nautilus_file_is_directory (file)) {
+ file->details->directory_count_is_up_to_date = TRUE;
+ file->details->directory_count_failed = FALSE;
+ file->details->got_directory_count = FALSE;
+
+ nautilus_directory_async_state_changed (directory);
return;
}
@@ -2251,14 +2223,10 @@ deep_count_load (NautilusDirectory *directory, const char *uri)
}
static void
-deep_count_start (NautilusDirectory *directory)
+deep_count_stop (NautilusDirectory *directory)
{
NautilusFile *file;
- char *uri;
- /* If there's already a count in progress, check to be sure
- * it's still wanted.
- */
if (directory->details->deep_count_in_progress != NULL) {
file = directory->details->deep_count_file;
if (file != NULL) {
@@ -2274,12 +2242,28 @@ deep_count_start (NautilusDirectory *directory)
/* The count is not wanted, so stop it. */
deep_count_cancel (directory);
}
+}
- /* Figure out which file to get a count for. */
- file = select_needy_file (directory,
- lacks_deep_count,
- wants_deep_count);
- if (file == NULL) {
+static void
+deep_count_start (NautilusDirectory *directory,
+ NautilusFile *file)
+{
+ char *uri;
+
+ if (directory->details->deep_count_in_progress != NULL) {
+ return;
+ }
+
+ if (!is_needy (file,
+ lacks_deep_count,
+ wants_deep_count)) {
+ return;
+ }
+
+ if (!nautilus_file_is_directory (file)) {
+ file->details->deep_counts_status = NAUTILUS_REQUEST_NOT_STARTED;
+
+ nautilus_directory_async_state_changed (directory);
return;
}
@@ -2386,14 +2370,10 @@ mime_list_load (NautilusDirectory *directory, const char *uri)
}
static void
-mime_list_start (NautilusDirectory *directory)
+mime_list_stop (NautilusDirectory *directory)
{
NautilusFile *file;
- char *uri;
- /* If there's already a count in progress, check to be sure
- * it's still wanted.
- */
if (directory->details->mime_list_in_progress != NULL) {
file = directory->details->mime_list_file;
if (file != NULL) {
@@ -2409,12 +2389,34 @@ mime_list_start (NautilusDirectory *directory)
/* The count is not wanted, so stop it. */
mime_list_cancel (directory);
}
+}
+
+static void
+mime_list_start (NautilusDirectory *directory,
+ NautilusFile *file)
+{
+ char *uri;
+
+ mime_list_stop (directory);
+
+ if (directory->details->mime_list_in_progress != NULL) {
+ return;
+ }
/* Figure out which file to get a mime list for. */
- file = select_needy_file (directory,
- should_get_mime_list,
- wants_mime_list);
- if (file == NULL) {
+ if (!is_needy (file,
+ should_get_mime_list,
+ wants_mime_list)) {
+ return;
+ }
+
+ if (!nautilus_file_is_directory (file)) {
+ g_list_free (file->details->mime_list);
+ file->details->mime_list_failed = FALSE;
+ file->details->got_directory_count = FALSE;
+ file->details->mime_list_is_up_to_date = TRUE;
+
+ nautilus_directory_async_state_changed (directory);
return;
}
@@ -2446,8 +2448,6 @@ top_left_read_done (NautilusDirectory *directory)
g_assert (directory->details->top_left_read_state->handle == NULL);
g_assert (NAUTILUS_IS_FILE (directory->details->top_left_read_state->file));
- directory->details->top_left_read_state->file->details->got_top_left_text = TRUE;
-
g_free (directory->details->top_left_read_state);
directory->details->top_left_read_state = NULL;
@@ -2466,10 +2466,7 @@ top_left_read_callback (GnomeVFSResult result,
directory = NAUTILUS_DIRECTORY (callback_data);
- nautilus_directory_ref (directory);
-
directory->details->top_left_read_state->handle = NULL;
-
directory->details->top_left_read_state->file->details->top_left_text_is_up_to_date = TRUE;
changed_file = NULL;
@@ -2479,21 +2476,16 @@ top_left_read_callback (GnomeVFSResult result,
nautilus_extract_top_left_text (file_contents, bytes_read);
directory->details->top_left_read_state->file->details->got_top_left_text = TRUE;
-
- changed_file = directory->details->top_left_read_state->file;
- nautilus_file_ref (changed_file);
-
- g_free (file_contents);
+ } else {
+ g_free (directory->details->top_left_read_state->file->details->top_left_text);
+ directory->details->top_left_read_state->file->details->got_top_left_text = FALSE;
}
-
- top_left_read_done (directory);
- if (changed_file != NULL) {
- nautilus_file_changed (changed_file);
- nautilus_file_unref (changed_file);
- }
+ g_free (file_contents);
- nautilus_directory_unref (directory);
+ nautilus_file_changed (directory->details->top_left_read_state->file);
+
+ top_left_read_done (directory);
}
static gboolean
@@ -2509,14 +2501,10 @@ top_left_read_more_callback (GnomeVFSFileSize bytes_read,
}
static void
-top_left_start (NautilusDirectory *directory)
+top_left_stop (NautilusDirectory *directory)
{
NautilusFile *file;
- char *uri;
- /* If there's already a read in progress, check to be sure
- * it's still wanted.
- */
if (directory->details->top_left_read_state != NULL) {
file = directory->details->top_left_read_state->file;
if (file != NULL) {
@@ -2532,12 +2520,31 @@ top_left_start (NautilusDirectory *directory)
/* The top left is not wanted, so stop it. */
top_left_cancel (directory);
}
+}
+
+static void
+top_left_start (NautilusDirectory *directory,
+ NautilusFile *file)
+{
+ char *uri;
+
+ if (directory->details->top_left_read_state != NULL) {
+ return;
+ }
/* Figure out which file to read the top left for. */
- file = select_needy_file (directory,
- lacks_top_left,
- wants_top_left);
- if (file == NULL) {
+ if (!is_needy (file,
+ lacks_top_left,
+ wants_top_left)) {
+ return;
+ }
+
+ if (!nautilus_file_contains_text (file)) {
+ g_free (file->details->top_left_text);
+ file->details->got_top_left_text = FALSE;
+ file->details->top_left_text_is_up_to_date = TRUE;
+
+ nautilus_directory_async_state_changed (directory);
return;
}
@@ -2615,16 +2622,10 @@ get_info_callback (GnomeVFSAsyncHandle *handle,
}
static void
-file_info_start (NautilusDirectory *directory)
+file_info_stop (NautilusDirectory *directory)
{
NautilusFile *file;
- char *uri;
- GnomeVFSURI *vfs_uri;
- GList fake_list;
- /* If there's already a file info fetch in progress, check to
- * be sure it's still wanted.
- */
if (directory->details->get_info_in_progress != NULL) {
file = directory->details->get_info_file;
if (file != NULL) {
@@ -2638,27 +2639,42 @@ file_info_start (NautilusDirectory *directory)
/* The info is not wanted, so stop it. */
file_info_cancel (directory);
}
+}
+
+static void
+file_info_start (NautilusDirectory *directory,
+ NautilusFile *file)
+{
+ char *uri;
+ GnomeVFSURI *vfs_uri;
+ GList fake_list;
+
+ file_info_stop (directory);
+
+ if (directory->details->get_info_in_progress != NULL) {
+ return;
+ }
- /* Figure out which file to get file info for. */
- do {
- file = select_needy_file (directory, lacks_info, wants_info);
- if (file == NULL) {
- return;
- }
-
- uri = nautilus_file_get_uri (file);
- vfs_uri = gnome_vfs_uri_new (uri);
- g_free (uri);
-
- if (vfs_uri == NULL) {
- file->details->file_info_is_up_to_date = TRUE;
- file->details->get_info_failed = TRUE;
- file->details->get_info_error = GNOME_VFS_ERROR_INVALID_URI;
- nautilus_file_changed (file);
- }
- } while (vfs_uri == NULL);
+ if (!is_needy (file, lacks_info, wants_info)) {
+ return;
+ }
+
+ uri = nautilus_file_get_uri (file);
+ vfs_uri = gnome_vfs_uri_new (uri);
+ g_free (uri);
+
+ /* If we can't even get info, fill in the info and go on.
+ */
+
+ if (vfs_uri == NULL) {
+ file->details->file_info_is_up_to_date = TRUE;
+ file->details->get_info_failed = TRUE;
+ file->details->get_info_error = GNOME_VFS_ERROR_INVALID_URI;
+
+ nautilus_directory_async_state_changed (directory);
+ return;
+ }
- /* Found one we need to get the info for. */
if (!async_job_start (directory, "file info")) {
return;
}
@@ -2676,44 +2692,56 @@ file_info_start (NautilusDirectory *directory)
gnome_vfs_uri_unref (vfs_uri);
}
+
static void
-activation_uri_done (NautilusDirectory *directory,
- NautilusFile *file,
- const char *uri)
+link_info_done (NautilusDirectory *directory,
+ NautilusFile *file,
+ const char *uri,
+ const char *name,
+ const char *icon)
{
- file->details->activation_uri_is_up_to_date = TRUE;
+ file->details->link_info_is_up_to_date = TRUE;
- file->details->got_activation_uri = TRUE;
+ file->details->got_link_info = TRUE;
g_free (file->details->activation_uri);
+ g_free (file->details->custom_name);
+ g_free (file->details->custom_icon_uri);
file->details->activation_uri = g_strdup (uri);
+ file->details->custom_name = g_strdup (name);
+ file->details->custom_icon_uri = g_strdup (icon);
- nautilus_file_changed (file);
-
- async_job_end (directory, "activation URI");
nautilus_directory_async_state_changed (directory);
}
+
static void
-activation_uri_read_done (NautilusDirectory *directory,
- const char *uri)
+link_info_read_done (NautilusDirectory *directory,
+ const char *uri,
+ const char *name,
+ const char *icon)
{
NautilusFile *file;
- file = directory->details->activation_uri_read_state->file;
- g_free (directory->details->activation_uri_read_state);
- directory->details->activation_uri_read_state = NULL;
+ file = directory->details->link_info_read_state->file;
+ g_free (directory->details->link_info_read_state);
+ directory->details->link_info_read_state = NULL;
- activation_uri_done (directory, file, uri);
+ nautilus_file_ref (file);
+ link_info_done (directory, file, uri, name, icon);
+ nautilus_file_changed (file);
+ nautilus_file_unref (file);
+ async_job_end (directory, "link info");
}
+
static void
-activation_uri_nautilus_link_read_callback (GnomeVFSResult result,
- GnomeVFSFileSize bytes_read,
- char *file_contents,
- gpointer callback_data)
+link_info_nautilus_link_read_callback (GnomeVFSResult result,
+ GnomeVFSFileSize bytes_read,
+ char *file_contents,
+ gpointer callback_data)
{
NautilusDirectory *directory;
- char *buffer, *uri;
+ char *buffer, *uri, *name, *icon;
directory = NAUTILUS_DIRECTORY (callback_data);
@@ -2724,29 +2752,39 @@ activation_uri_nautilus_link_read_callback (GnomeVFSResult result,
/* FIXME bugzilla.gnome.org 42433: We should report this error to the user. */
g_free (file_contents);
uri = NULL;
+ name = NULL;
+ icon = NULL;
} else {
/* The gnome-xml parser requires a zero-terminated array. */
buffer = g_realloc (file_contents, bytes_read + 1);
buffer[bytes_read] = '\0';
uri = nautilus_link_get_link_uri_given_file_contents (buffer, bytes_read);
+ name = nautilus_link_get_link_name_given_file_contents (buffer, bytes_read);
+ icon = nautilus_link_get_link_icon_given_file_contents (buffer, bytes_read);
g_free (buffer);
}
- activation_uri_read_done (directory, uri);
+ link_info_read_done (directory, uri, name, icon);
g_free (uri);
+ g_free (name);
+ g_free (icon);
nautilus_directory_unref (directory);
}
+
+
+
static void
-activation_uri_gmc_link_read_callback (GnomeVFSResult result,
- GnomeVFSFileSize bytes_read,
- char *file_contents,
- gpointer callback_data)
+link_info_gmc_link_read_callback (GnomeVFSResult result,
+ GnomeVFSFileSize bytes_read,
+ char *file_contents,
+ gpointer callback_data)
{
NautilusDirectory *directory;
- char *end_of_line, *uri;
-
+ char *end_of_line, *uri, *name, *path, *icon, *icon_path;
+ int size, res;
+
directory = NAUTILUS_DIRECTORY (callback_data);
nautilus_directory_ref (directory);
@@ -2755,6 +2793,8 @@ activation_uri_gmc_link_read_callback (GnomeVFSResult result,
if (result != GNOME_VFS_OK || !eel_str_has_prefix (file_contents, "URL: ")) {
/* FIXME bugzilla.gnome.org 42433: We should report this error to the user. */
uri = NULL;
+ name = NULL;
+ icon = NULL;
} else {
/* Make sure we don't run off the end of the buffer. */
end_of_line = memchr (file_contents, '\n', bytes_read);
@@ -2763,19 +2803,51 @@ activation_uri_gmc_link_read_callback (GnomeVFSResult result,
} else {
uri = g_strndup (file_contents, bytes_read);
}
+
+ path = gnome_vfs_get_local_path_from_uri (uri);
+
+ if (path != NULL) {
+ /* FIXME: this gnome_metata_get call is synchronous, but better to
+ * have it here where the results will at least be cached than in
+ * nautilus_file_get_name.
+ */
+ res = gnome_metadata_get (path, "icon-name", &size, &name);
+ } else {
+ res = -1;
+ }
+
+ if (res == 0) {
+ name = NULL;
+ }
+
+ if (path != NULL) {
+ res = gnome_metadata_get (path, "icon-filename", &size, &icon_path);
+ } else {
+ res = -1;
+ }
+
+ if (res == 0 && icon_path != NULL) {
+ icon = gnome_vfs_get_uri_from_local_path (icon_path);
+ g_free (icon_path);
+ } else {
+ icon = NULL;
+ }
+
}
g_free (file_contents);
- activation_uri_read_done (directory, uri ? uri + 5 : NULL);
+ link_info_read_done (directory, uri ? uri + 5 : NULL, name, icon);
g_free (uri);
+ g_free (name);
+ g_free (icon);
nautilus_directory_unref (directory);
}
static gboolean
-activation_uri_gmc_link_read_more_callback (GnomeVFSFileSize bytes_read,
- const char *file_contents,
- gpointer callback_data)
+link_info_gmc_link_read_more_callback (GnomeVFSFileSize bytes_read,
+ const char *file_contents,
+ gpointer callback_data)
{
g_assert (NAUTILUS_IS_DIRECTORY (callback_data));
@@ -2783,96 +2855,165 @@ activation_uri_gmc_link_read_more_callback (GnomeVFSFileSize bytes_read,
return bytes_read < 512;
}
+static char *
+make_dot_directory_uri (const char *uri)
+{
+ char *dot_directory_uri;
+ GnomeVFSURI *vfs_uri;
+ GnomeVFSURI *dot_dir_vfs_uri;
+
+ /* FIXME: what we really need is a uri_append_file_name call
+ * that works on strings, so we can avoid the VFS parsing step.
+ */
+
+ vfs_uri = gnome_vfs_uri_new (uri);
+ if (vfs_uri == NULL) {
+ return NULL;
+ }
+
+ dot_dir_vfs_uri = gnome_vfs_uri_append_file_name (vfs_uri, ".directory");
+ dot_directory_uri = gnome_vfs_uri_to_string (dot_dir_vfs_uri, GNOME_VFS_URI_HIDE_NONE);
+
+ gnome_vfs_uri_unref (vfs_uri);
+ gnome_vfs_uri_unref (dot_dir_vfs_uri);
+
+ return dot_directory_uri;
+}
+
+
static void
-activation_uri_start (NautilusDirectory *directory)
+link_info_stop (NautilusDirectory *directory)
{
NautilusFile *file;
- char *mime_type, *uri;
- gboolean gmc_style_link, nautilus_style_link;
- /* If there's already a activation URI read in progress, check
- * to be sure it's still wanted.
- */
- if (directory->details->activation_uri_read_state != NULL) {
- file = directory->details->activation_uri_read_state->file;
+ if (directory->details->link_info_read_state != NULL) {
+ file = directory->details->link_info_read_state->file;
+
if (file != NULL) {
g_assert (NAUTILUS_IS_FILE (file));
g_assert (file->details->directory == directory);
if (is_needy (file,
- lacks_activation_uri,
- wants_activation_uri)) {
+ lacks_link_info,
+ wants_link_info)) {
return;
}
}
- /* The count is not wanted, so stop it. */
- activation_uri_cancel (directory);
+ /* The link info is not wanted, so stop it. */
+ link_info_cancel (directory);
}
+}
- /* Figure out which file to get activation_uri for. */
- file = select_needy_file (directory,
- lacks_activation_uri,
- wants_activation_uri);
- if (file == NULL) {
+
+static void
+link_info_start (NautilusDirectory *directory,
+ NautilusFile *file)
+{
+ char *uri, *dot_directory_uri = NULL;
+ gboolean gmc_style_link, nautilus_style_link, is_directory;
+
+ if (directory->details->link_info_read_state != NULL) {
return;
}
- if (!async_job_start (directory, "activation URI")) {
+ if (!is_needy (file,
+ lacks_link_info,
+ wants_link_info)) {
return;
}
/* Figure out if it is a link. */
- mime_type = nautilus_file_get_mime_type (file);
- gmc_style_link = eel_strcasecmp (mime_type, "application/x-gmc-link") == 0;
- g_free (mime_type);
+ gmc_style_link = nautilus_file_is_mime_type (file, "application/x-gmc-link") &&
+ nautilus_file_is_in_desktop (file);
nautilus_style_link = nautilus_file_is_nautilus_link (file);
+ is_directory = nautilus_file_is_directory (file);
+
+ uri = nautilus_file_get_uri (file);
+
+ if (is_directory) {
+ dot_directory_uri = make_dot_directory_uri (uri);
+ }
/* If it's not a link we are done. If it is, we need to read it. */
- if (!(gmc_style_link || nautilus_style_link)) {
- activation_uri_done (directory, file, NULL);
+ if (!(gmc_style_link || nautilus_style_link || (is_directory && dot_directory_uri != NULL) )) {
+ link_info_done (directory, file, NULL, NULL, NULL);
} else {
- directory->details->activation_uri_read_state = g_new0 (ActivationURIReadState, 1);
- directory->details->activation_uri_read_state->file = file;
- uri = nautilus_file_get_uri (file);
+ if (!async_job_start (directory, "link info")) {
+ g_free (dot_directory_uri);
+ g_free (uri);
+ return;
+ }
+
+ directory->details->link_info_read_state = g_new0 (LinkInfoReadState, 1);
+ directory->details->link_info_read_state->file = file;
if (gmc_style_link) {
- directory->details->activation_uri_read_state->handle = eel_read_file_async
+ directory->details->link_info_read_state->handle = eel_read_file_async
(uri,
- activation_uri_gmc_link_read_callback,
- activation_uri_gmc_link_read_more_callback,
+ link_info_gmc_link_read_callback,
+ link_info_gmc_link_read_more_callback,
directory);
+ } else if (is_directory) {
+ directory->details->link_info_read_state->handle = eel_read_entire_file_async
+ (dot_directory_uri,
+ link_info_nautilus_link_read_callback,
+ directory);
+ g_free (dot_directory_uri);
} else {
- directory->details->activation_uri_read_state->handle = eel_read_entire_file_async
+ directory->details->link_info_read_state->handle = eel_read_entire_file_async
(uri,
- activation_uri_nautilus_link_read_callback,
+ link_info_nautilus_link_read_callback,
directory);
}
- g_free (uri);
}
+ g_free (uri);
}
static void
start_or_stop_io (NautilusDirectory *directory)
{
- /* Start or stop getting file info. */
- file_info_start (directory);
+ NautilusFile *file;
/* Start or stop reading files. */
- file_list_start (directory);
-
- /* Start or stop getting directory counts. */
- directory_count_start (directory);
- deep_count_start (directory);
+ file_list_start_or_stop (directory);
+
+ /* Stop any no longer wanted attribute fetches. */
+ file_info_stop (directory);
+ directory_count_stop (directory);
+ deep_count_stop (directory);
+ mime_list_stop (directory);
+ top_left_stop (directory);
+ link_info_stop (directory);
+
+ /* Take files that are all done off the queue. */
+ while (!nautilus_file_queue_is_empty (directory->details->high_priority_queue)) {
+ file = nautilus_file_queue_head (directory->details->high_priority_queue);
+
+ if (file_needs_high_priority_work_done (directory, file)) {
+ /* Start getting attributes if possible */
+ file_info_start (directory, file);
+ link_info_start (directory, file);
+ return;
+ } else {
+ move_file_to_low_priority_queue (directory, file);
+ }
+ }
- /* Start or stop getting mime lists. */
- mime_list_start (directory);
+ /* High priority queue must be empty */
+ while (!nautilus_file_queue_is_empty (directory->details->low_priority_queue)) {
+ file = nautilus_file_queue_head (directory->details->low_priority_queue);
- /* Start or stop getting top left pieces of files. */
- top_left_start (directory);
+ if (file_needs_low_priority_work_done (directory, file)) {
+ /* Start getting attributes if possible */
+ directory_count_start (directory, file);
+ deep_count_start (directory, file);
+ mime_list_start (directory, file);
+ top_left_start (directory, file);
+ return;
+ } else {
+ nautilus_directory_remove_file_from_work_queue (directory, file);
- /* Start or stop getting activation URIs, which includes
- * reading the contents of Nautilus and GMC link files.
- */
- activation_uri_start (directory);
+ }
+ }
}
/* Call this when the monitor or call when ready list changes,
@@ -2916,11 +3057,11 @@ void
nautilus_directory_cancel (NautilusDirectory *directory)
{
/* Arbitrary order (kept alphabetical). */
- activation_uri_cancel (directory);
deep_count_cancel (directory);
directory_count_cancel (directory);
file_info_cancel (directory);
file_list_cancel (directory);
+ link_info_cancel (directory);
mime_list_cancel (directory);
top_left_cancel (directory);
@@ -2980,15 +3121,16 @@ cancel_file_info_for_file (NautilusDirectory *directory,
}
static void
-cancel_activation_uri_for_file (NautilusDirectory *directory,
+cancel_link_info_for_file (NautilusDirectory *directory,
NautilusFile *file)
{
- if (directory->details->activation_uri_read_state != NULL &&
- directory->details->activation_uri_read_state->file == file) {
- activation_uri_cancel (directory);
+ if (directory->details->link_info_read_state != NULL &&
+ directory->details->link_info_read_state->file == file) {
+ link_info_cancel (directory);
}
}
+
static void
cancel_loading_attributes (NautilusDirectory *directory,
GList *file_attributes)
@@ -3013,8 +3155,8 @@ cancel_loading_attributes (NautilusDirectory *directory,
if (request.file_info) {
file_info_cancel (directory);
}
- if (request.activation_uri) {
- file_info_cancel (directory);
+ if (request.link_info) {
+ link_info_cancel (directory);
}
/* FIXME bugzilla.gnome.org 45064: implement cancelling metadata when we
@@ -3048,8 +3190,8 @@ nautilus_directory_cancel_loading_file_attributes (NautilusDirectory *directory,
if (request.file_info) {
cancel_file_info_for_file (directory, file);
}
- if (request.activation_uri) {
- cancel_activation_uri_for_file (directory, file);
+ if (request.link_info) {
+ cancel_link_info_for_file (directory, file);
}
/* FIXME bugzilla.gnome.org 45064: implement cancelling metadata when we
@@ -3057,3 +3199,106 @@ nautilus_directory_cancel_loading_file_attributes (NautilusDirectory *directory,
nautilus_directory_async_state_changed (directory);
}
+
+
+
+static gboolean
+file_needs_high_priority_work_done (NautilusDirectory *directory,
+ NautilusFile *file)
+{
+ if (is_needy (file, lacks_info, wants_info)) {
+ return TRUE;
+ }
+
+ if (is_needy (file, lacks_link_info, wants_link_info)) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gboolean
+file_needs_low_priority_work_done (NautilusDirectory *directory,
+ NautilusFile *file)
+{
+ if (is_needy (file, lacks_directory_count, wants_directory_count)) {
+ return TRUE;
+ }
+
+ if (is_needy (file, lacks_deep_count, wants_deep_count)) {
+ return TRUE;
+ }
+
+ if (is_needy (file, lacks_mime_list, wants_mime_list)) {
+ return TRUE;
+ }
+
+ if (is_needy (file, lacks_top_left, wants_top_left)) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gboolean
+file_needs_work_done (NautilusDirectory *directory,
+ NautilusFile *file)
+{
+ return (file_needs_high_priority_work_done (directory, file) ||
+ file_needs_low_priority_work_done (directory, file));
+}
+
+
+void
+nautilus_directory_add_file_to_work_queue (NautilusDirectory *directory,
+ NautilusFile *file)
+{
+ if (!file_needs_work_done (directory, file)) {
+ return;
+ }
+
+ nautilus_file_queue_enqueue (directory->details->high_priority_queue,
+ file);
+}
+
+
+static void
+add_all_files_to_work_queue (NautilusDirectory *directory)
+{
+ GList *node;
+ NautilusFile *file;
+
+ for (node = directory->details->file_list; node != NULL; node = node->next) {
+ file = NAUTILUS_FILE (node->data);
+
+ nautilus_directory_add_file_to_work_queue (directory, file);
+ }
+}
+
+void
+nautilus_directory_remove_file_from_work_queue (NautilusDirectory *directory,
+ NautilusFile *file)
+{
+ nautilus_file_queue_remove (directory->details->high_priority_queue,
+ file);
+ nautilus_file_queue_remove (directory->details->low_priority_queue,
+ file);
+}
+
+
+static void
+move_file_to_low_priority_queue (NautilusDirectory *directory,
+ NautilusFile *file)
+{
+ if (!file_needs_low_priority_work_done (directory, file)) {
+ nautilus_file_queue_remove (directory->details->high_priority_queue,
+ file);
+ return;
+ }
+
+ /* Must add before removing to avoid ref underflow */
+ nautilus_file_queue_enqueue (directory->details->low_priority_queue,
+ file);
+ nautilus_file_queue_remove (directory->details->high_priority_queue,
+ file);
+}