/*
* nautilus-directory.c: Nautilus directory model.
*
* Copyright (C) 1999, 2000, 2001 Eazel, 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, see .
*
* Author: Darin Adler
*/
#include "nautilus-directory-private.h"
#include
#include
#include
#include
#include "nautilus-directory-notify.h"
#include "nautilus-directory-private.h"
#include "nautilus-enums.h"
#include "nautilus-file-private.h"
#include "nautilus-file-queue.h"
#include "nautilus-file-utilities.h"
#include "nautilus-global-preferences.h"
#include "nautilus-lib-self-check-functions.h"
#include "nautilus-metadata.h"
#include "nautilus-profile.h"
#include "nautilus-search-directory-file.h"
#include "nautilus-search-directory.h"
#include "nautilus-starred-directory.h"
#include "nautilus-vfs-directory.h"
#include "nautilus-vfs-file.h"
enum
{
FILES_ADDED,
FILES_CHANGED,
DONE_LOADING,
LOAD_ERROR,
LAST_SIGNAL
};
enum
{
PROP_LOCATION = 1,
NUM_PROPERTIES
};
static guint signals[LAST_SIGNAL];
static GParamSpec *properties[NUM_PROPERTIES] = { NULL, };
static GHashTable *directories;
static NautilusDirectory *nautilus_directory_new (GFile *location);
static void set_directory_location (NautilusDirectory *directory,
GFile *location);
G_DEFINE_TYPE (NautilusDirectory, nautilus_directory, G_TYPE_OBJECT);
static gboolean
real_contains_file (NautilusDirectory *self,
NautilusFile *file)
{
NautilusDirectory *directory;
directory = nautilus_file_get_directory (file);
return directory == self;
}
static gboolean
real_are_all_files_seen (NautilusDirectory *directory)
{
return directory->details->directory_loaded;
}
static gboolean
real_is_not_empty (NautilusDirectory *directory)
{
return directory->details->file_list != NULL;
}
static gboolean
is_tentative (NautilusFile *file,
gpointer callback_data)
{
g_assert (callback_data == NULL);
/* Avoid returning files with !is_added, because these
* will later be sent with the files_added signal, and a
* user doing get_file_list + files_added monitoring will
* then see the file twice */
return !file->details->got_file_info || !file->details->is_added;
}
static GList *
real_get_file_list (NautilusDirectory *directory)
{
GList *tentative_files, *non_tentative_files;
tentative_files = nautilus_file_list_filter (directory->details->file_list,
&non_tentative_files, is_tentative, NULL);
nautilus_file_list_free (tentative_files);
return non_tentative_files;
}
static gboolean
real_is_editable (NautilusDirectory *directory)
{
return TRUE;
}
static NautilusFile *
real_new_file_from_filename (NautilusDirectory *directory,
const char *filename,
gboolean self_owned)
{
NautilusFile *file;
g_assert (NAUTILUS_IS_DIRECTORY (directory));
g_assert (filename != NULL);
g_assert (filename[0] != '\0');
if (NAUTILUS_IS_SEARCH_DIRECTORY (directory))
{
if (self_owned)
{
file = NAUTILUS_FILE (g_object_new (NAUTILUS_TYPE_SEARCH_DIRECTORY_FILE, NULL));
}
else
{
/* This doesn't normally happen, unless the user somehow types in a uri
* that references a file like this. (See #349840) */
file = NAUTILUS_FILE (g_object_new (NAUTILUS_TYPE_VFS_FILE, NULL));
}
}
else
{
file = NAUTILUS_FILE (g_object_new (NAUTILUS_TYPE_VFS_FILE, NULL));
}
nautilus_file_set_directory (file, directory);
return file;
}
static gboolean
real_handles_location (GFile *location)
{
/* This class is the fallback on handling any location */
return TRUE;
}
static void
nautilus_directory_finalize (GObject *object)
{
NautilusDirectory *directory;
directory = NAUTILUS_DIRECTORY (object);
g_hash_table_remove (directories, directory->details->location);
nautilus_directory_cancel (directory);
g_assert (directory->details->count_in_progress == NULL);
if (g_hash_table_size (directory->details->monitor_table) != 0)
{
GHashTableIter iter;
gpointer value;
g_warning ("destroying a NautilusDirectory while it's being monitored");
g_hash_table_iter_init (&iter, directory->details->monitor_table);
while (g_hash_table_iter_next (&iter, NULL, &value))
{
GList *list = value;
g_list_free_full (list, g_free);
}
g_hash_table_remove_all (directory->details->monitor_table);
}
g_hash_table_destroy (directory->details->monitor_table);
if (directory->details->monitor != NULL)
{
nautilus_monitor_cancel (directory->details->monitor);
}
if (directory->details->dequeue_pending_idle_id != 0)
{
g_source_remove (directory->details->dequeue_pending_idle_id);
}
if (directory->details->call_ready_idle_id != 0)
{
g_source_remove (directory->details->call_ready_idle_id);
}
if (directory->details->location)
{
g_object_unref (directory->details->location);
}
g_assert (directory->details->file_list == NULL);
g_hash_table_destroy (directory->details->file_hash);
nautilus_file_queue_destroy (directory->details->high_priority_queue);
nautilus_file_queue_destroy (directory->details->low_priority_queue);
nautilus_file_queue_destroy (directory->details->extension_queue);
g_assert (directory->details->directory_load_in_progress == NULL);
g_assert (directory->details->count_in_progress == NULL);
g_assert (directory->details->dequeue_pending_idle_id == 0);
g_list_free_full (directory->details->pending_file_info, g_object_unref);
G_OBJECT_CLASS (nautilus_directory_parent_class)->finalize (object);
}
static void
nautilus_directory_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
{
NautilusDirectory *directory = NAUTILUS_DIRECTORY (object);
switch (property_id)
{
case PROP_LOCATION:
{
set_directory_location (directory, g_value_get_object (value));
}
break;
default:
{
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
break;
}
}
static void
nautilus_directory_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
{
NautilusDirectory *directory = NAUTILUS_DIRECTORY (object);
switch (property_id)
{
case PROP_LOCATION:
{
g_value_set_object (value, directory->details->location);
}
break;
default:
{
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
break;
}
}
static void
nautilus_directory_class_init (NautilusDirectoryClass *klass)
{
GObjectClass *object_class;
object_class = G_OBJECT_CLASS (klass);
klass->contains_file = real_contains_file;
klass->are_all_files_seen = real_are_all_files_seen;
klass->is_not_empty = real_is_not_empty;
klass->get_file_list = real_get_file_list;
klass->is_editable = real_is_editable;
klass->new_file_from_filename = real_new_file_from_filename;
klass->handles_location = real_handles_location;
object_class->finalize = nautilus_directory_finalize;
object_class->set_property = nautilus_directory_set_property;
object_class->get_property = nautilus_directory_get_property;
signals[FILES_ADDED] =
g_signal_new ("files-added",
G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (NautilusDirectoryClass, files_added),
NULL, NULL,
g_cclosure_marshal_VOID__POINTER,
G_TYPE_NONE, 1, G_TYPE_POINTER);
signals[FILES_CHANGED] =
g_signal_new ("files-changed",
G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (NautilusDirectoryClass, files_changed),
NULL, NULL,
g_cclosure_marshal_VOID__POINTER,
G_TYPE_NONE, 1, G_TYPE_POINTER);
signals[DONE_LOADING] =
g_signal_new ("done-loading",
G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (NautilusDirectoryClass, done_loading),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
signals[LOAD_ERROR] =
g_signal_new ("load-error",
G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (NautilusDirectoryClass, load_error),
NULL, NULL,
g_cclosure_marshal_VOID__POINTER,
G_TYPE_NONE, 1, G_TYPE_POINTER);
properties[PROP_LOCATION] =
g_param_spec_object ("location",
"The location",
"The location of this directory",
G_TYPE_FILE,
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
g_type_class_add_private (klass, sizeof (NautilusDirectoryDetails));
g_object_class_install_properties (object_class, NUM_PROPERTIES, properties);
}
static void
nautilus_directory_init (NautilusDirectory *directory)
{
directory->details = G_TYPE_INSTANCE_GET_PRIVATE ((directory), NAUTILUS_TYPE_DIRECTORY, NautilusDirectoryDetails);
directory->details->file_hash = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, NULL);
directory->details->high_priority_queue = nautilus_file_queue_new ();
directory->details->low_priority_queue = nautilus_file_queue_new ();
directory->details->extension_queue = nautilus_file_queue_new ();
directory->details->monitor_table = g_hash_table_new (NULL, NULL);
}
NautilusDirectory *
nautilus_directory_ref (NautilusDirectory *directory)
{
if (directory == NULL)
{
return directory;
}
g_return_val_if_fail (NAUTILUS_IS_DIRECTORY (directory), NULL);
g_object_ref (directory);
return directory;
}
void
nautilus_directory_unref (NautilusDirectory *directory)
{
if (directory == NULL)
{
return;
}
g_return_if_fail (NAUTILUS_IS_DIRECTORY (directory));
g_object_unref (directory);
}
static void
collect_all_directories (gpointer key,
gpointer value,
gpointer callback_data)
{
NautilusDirectory *directory;
GList **dirs;
directory = NAUTILUS_DIRECTORY (value);
dirs = callback_data;
*dirs = g_list_prepend (*dirs, nautilus_directory_ref (directory));
}
static void
filtering_changed_callback (gpointer callback_data)
{
g_autolist (NautilusDirectory) dirs = NULL;
g_assert (callback_data == NULL);
dirs = NULL;
g_hash_table_foreach (directories, collect_all_directories, &dirs);
/* Preference about which items to show has changed, so we
* can't trust any of our precomputed directory counts.
*/
for (GList *l = dirs; l != NULL; l = l->next)
{
NautilusDirectory *directory;
directory = NAUTILUS_DIRECTORY (l->data);
nautilus_directory_invalidate_count_and_mime_list (directory);
}
}
void
emit_change_signals_for_all_files (NautilusDirectory *directory)
{
GList *files;
files = g_list_copy (directory->details->file_list);
if (directory->details->as_file != NULL)
{
files = g_list_prepend (files, directory->details->as_file);
}
nautilus_file_list_ref (files);
nautilus_directory_emit_change_signals (directory, files);
nautilus_file_list_free (files);
}
void
emit_change_signals_for_all_files_in_all_directories (void)
{
GList *dirs, *l;
NautilusDirectory *directory;
dirs = NULL;
g_hash_table_foreach (directories,
collect_all_directories,
&dirs);
for (l = dirs; l != NULL; l = l->next)
{
directory = NAUTILUS_DIRECTORY (l->data);
emit_change_signals_for_all_files (directory);
nautilus_directory_unref (directory);
}
g_list_free (dirs);
}
static void
async_state_changed_one (gpointer key,
gpointer value,
gpointer user_data)
{
NautilusDirectory *directory;
g_assert (key != NULL);
g_assert (NAUTILUS_IS_DIRECTORY (value));
g_assert (user_data == NULL);
directory = NAUTILUS_DIRECTORY (value);
nautilus_directory_async_state_changed (directory);
emit_change_signals_for_all_files (directory);
}
static void
async_data_preference_changed_callback (gpointer callback_data)
{
g_assert (callback_data == NULL);
/* Preference involving fetched async data has changed, so
* we have to kick off refetching all async data, and tell
* each file that it (might have) changed.
*/
g_hash_table_foreach (directories, async_state_changed_one, NULL);
}
static void
add_preferences_callbacks (void)
{
nautilus_global_preferences_init ();
g_signal_connect_swapped (gtk_filechooser_preferences,
"changed::" NAUTILUS_PREFERENCES_SHOW_HIDDEN_FILES,
G_CALLBACK (filtering_changed_callback),
NULL);
g_signal_connect_swapped (nautilus_preferences,
"changed::" NAUTILUS_PREFERENCES_SHOW_DIRECTORY_ITEM_COUNTS,
G_CALLBACK (async_data_preference_changed_callback),
NULL);
}
/**
* nautilus_directory_get_by_uri:
* @uri: URI of directory to get.
*
* Get a directory given a uri.
* Creates the appropriate subclass given the uri mappings.
* Returns a referenced object, not a floating one. Unref when finished.
* If two windows are viewing the same uri, the directory object is shared.
*/
NautilusDirectory *
nautilus_directory_get_internal (GFile *location,
gboolean create)
{
NautilusDirectory *directory;
/* Create the hash table first time through. */
if (directories == NULL)
{
directories = g_hash_table_new (g_file_hash, (GCompareFunc) g_file_equal);
add_preferences_callbacks ();
}
/* If the object is already in the hash table, look it up. */
directory = g_hash_table_lookup (directories,
location);
if (directory != NULL)
{
nautilus_directory_ref (directory);
}
else if (create)
{
/* Create a new directory object instead. */
directory = nautilus_directory_new (location);
if (directory == NULL)
{
return NULL;
}
/* Put it in the hash table. */
g_hash_table_insert (directories,
directory->details->location,
directory);
}
return directory;
}
NautilusDirectory *
nautilus_directory_get (GFile *location)
{
if (location == NULL)
{
return NULL;
}
return nautilus_directory_get_internal (location, TRUE);
}
NautilusDirectory *
nautilus_directory_get_existing (GFile *location)
{
if (location == NULL)
{
return NULL;
}
return nautilus_directory_get_internal (location, FALSE);
}
NautilusDirectory *
nautilus_directory_get_by_uri (const char *uri)
{
NautilusDirectory *directory;
GFile *location;
if (uri == NULL)
{
return NULL;
}
location = g_file_new_for_uri (uri);
directory = nautilus_directory_get_internal (location, TRUE);
g_object_unref (location);
return directory;
}
NautilusDirectory *
nautilus_directory_get_for_file (NautilusFile *file)
{
char *uri;
NautilusDirectory *directory;
g_return_val_if_fail (NAUTILUS_IS_FILE (file), NULL);
uri = nautilus_file_get_uri (file);
directory = nautilus_directory_get_by_uri (uri);
g_free (uri);
return directory;
}
/* Returns a reffed NautilusFile object for this directory.
*/
NautilusFile *
nautilus_directory_get_corresponding_file (NautilusDirectory *directory)
{
NautilusFile *file;
char *uri;
file = nautilus_directory_get_existing_corresponding_file (directory);
if (file == NULL)
{
uri = nautilus_directory_get_uri (directory);
file = nautilus_file_get_by_uri (uri);
g_free (uri);
}
return file;
}
/* Returns a reffed NautilusFile object for this directory, but only if the
* NautilusFile object has already been created.
*/
NautilusFile *
nautilus_directory_get_existing_corresponding_file (NautilusDirectory *directory)
{
NautilusFile *file;
char *uri;
file = directory->details->as_file;
if (file != NULL)
{
nautilus_file_ref (file);
return file;
}
uri = nautilus_directory_get_uri (directory);
file = nautilus_file_get_existing_by_uri (uri);
g_free (uri);
return file;
}
/* nautilus_directory_get_name_for_self_as_new_file:
*
* Get a name to display for the file representing this
* directory. This is called only when there's no VFS
* directory for this NautilusDirectory.
*/
char *
nautilus_directory_get_name_for_self_as_new_file (NautilusDirectory *directory)
{
GFile *file;
char *directory_uri;
char *scheme;
char *name;
char *hostname = NULL;
directory_uri = nautilus_directory_get_uri (directory);
file = g_file_new_for_uri (directory_uri);
scheme = g_file_get_uri_scheme (file);
g_object_unref (file);
nautilus_uri_parse (directory_uri, &hostname, NULL, NULL);
if (hostname == NULL || (strlen (hostname) == 0))
{
name = g_strdup (directory_uri);
}
else if (scheme == NULL)
{
name = g_strdup (hostname);
}
else
{
/* Translators: this is of the format "hostname (uri-scheme)" */
name = g_strdup_printf (_("%s (%s)"), hostname, scheme);
}
g_free (directory_uri);
g_free (scheme);
g_free (hostname);
return name;
}
char *
nautilus_directory_get_uri (NautilusDirectory *directory)
{
g_return_val_if_fail (NAUTILUS_IS_DIRECTORY (directory), NULL);
return g_file_get_uri (directory->details->location);
}
GFile *
nautilus_directory_get_location (NautilusDirectory *directory)
{
g_return_val_if_fail (NAUTILUS_IS_DIRECTORY (directory), NULL);
return g_object_ref (directory->details->location);
}
NautilusFile *
nautilus_directory_new_file_from_filename (NautilusDirectory *directory,
const char *filename,
gboolean self_owned)
{
return NAUTILUS_DIRECTORY_CLASS (G_OBJECT_GET_CLASS (directory))->new_file_from_filename (directory,
filename,
self_owned);
}
static GList *
nautilus_directory_provider_get_all (void)
{
GIOExtensionPoint *extension_point;
GList *extensions;
extension_point = g_io_extension_point_lookup (NAUTILUS_DIRECTORY_PROVIDER_EXTENSION_POINT_NAME);
if (extension_point == NULL)
{
g_warning ("Directory provider extension point not registered. Did you call nautilus_ensure_extension_points()?");
}
extensions = g_io_extension_point_get_extensions (extension_point);
return extensions;
}
static NautilusDirectory *
nautilus_directory_new (GFile *location)
{
GList *extensions;
GList *l;
GIOExtension *gio_extension;
GType handling_provider_type;
gboolean handled = FALSE;
NautilusDirectoryClass *current_provider_class;
NautilusDirectory *handling_instance;
extensions = nautilus_directory_provider_get_all ();
for (l = extensions; l != NULL; l = l->next)
{
gio_extension = l->data;
current_provider_class = NAUTILUS_DIRECTORY_CLASS (g_io_extension_ref_class (gio_extension));
if (current_provider_class->handles_location (location))
{
handling_provider_type = g_io_extension_get_type (gio_extension);
handled = TRUE;
break;
}
}
if (!handled)
{
/* This class is the fallback for any location */
handling_provider_type = NAUTILUS_TYPE_VFS_DIRECTORY;
}
handling_instance = g_object_new (handling_provider_type,
"location", location,
NULL);
return handling_instance;
}
gboolean
nautilus_directory_is_local (NautilusDirectory *directory)
{
g_return_val_if_fail (NAUTILUS_IS_DIRECTORY (directory), FALSE);
if (directory->details->location == NULL)
{
return TRUE;
}
return nautilus_directory_is_in_trash (directory) ||
nautilus_directory_is_in_recent (directory) ||
g_file_is_native (directory->details->location);
}
gboolean
nautilus_directory_is_local_or_fuse (NautilusDirectory *directory)
{
g_autofree char *path = NULL;
g_return_val_if_fail (NAUTILUS_IS_DIRECTORY (directory), FALSE);
if (directory->details->location == NULL)
{
return TRUE;
}
/* If the glib reports a path, then it can use FUSE to convert the uri
* to a local path
*/
path = g_file_get_path (directory->details->location);
return nautilus_directory_is_in_trash (directory) ||
nautilus_directory_is_in_recent (directory) ||
g_file_is_native (directory->details->location) ||
path != NULL;
}
gboolean
nautilus_directory_is_in_trash (NautilusDirectory *directory)
{
g_assert (NAUTILUS_IS_DIRECTORY (directory));
if (directory->details->location == NULL)
{
return FALSE;
}
return g_file_has_uri_scheme (directory->details->location, "trash");
}
gboolean
nautilus_directory_is_in_recent (NautilusDirectory *directory)
{
g_assert (NAUTILUS_IS_DIRECTORY (directory));
if (directory->details->location == NULL)
{
return FALSE;
}
return g_file_has_uri_scheme (directory->details->location, "recent");
}
gboolean
nautilus_directory_is_in_starred (NautilusDirectory *directory)
{
g_assert (NAUTILUS_IS_DIRECTORY (directory));
if (directory->details->location == NULL)
{
return FALSE;
}
return g_file_has_uri_scheme (directory->details->location, "starred");
}
gboolean
nautilus_directory_is_in_admin (NautilusDirectory *directory)
{
g_assert (NAUTILUS_IS_DIRECTORY (directory));
if (directory->details->location == NULL)
{
return FALSE;
}
return g_file_has_uri_scheme (directory->details->location, "admin");
}
gboolean
nautilus_directory_are_all_files_seen (NautilusDirectory *directory)
{
g_return_val_if_fail (NAUTILUS_IS_DIRECTORY (directory), FALSE);
return NAUTILUS_DIRECTORY_CLASS (G_OBJECT_GET_CLASS (directory))->are_all_files_seen (directory);
}
static void
add_to_hash_table (NautilusDirectory *directory,
NautilusFile *file,
GList *node)
{
gchar *name;
name = nautilus_file_get_name (file);
g_assert (name != NULL);
g_assert (node != NULL);
g_assert (g_hash_table_lookup (directory->details->file_hash,
name) == NULL);
g_hash_table_insert (directory->details->file_hash, name, node);
}
static GList *
extract_from_hash_table (NautilusDirectory *directory,
NautilusFile *file)
{
g_autofree gchar *name = NULL;
GList *node;
name = nautilus_file_get_name (file);
if (name == NULL)
{
return NULL;
}
/* Find the list node in the hash table. */
node = g_hash_table_lookup (directory->details->file_hash, name);
g_hash_table_remove (directory->details->file_hash, name);
return node;
}
void
nautilus_directory_add_file (NautilusDirectory *directory,
NautilusFile *file)
{
GList *node;
gboolean add_to_work_queue;
g_assert (NAUTILUS_IS_DIRECTORY (directory));
g_assert (NAUTILUS_IS_FILE (file));
/* Add to list. */
node = g_list_prepend (directory->details->file_list, file);
directory->details->file_list = node;
/* Add to hash table. */
add_to_hash_table (directory, file, node);
directory->details->confirmed_file_count++;
add_to_work_queue = FALSE;
if (nautilus_directory_is_file_list_monitored (directory))
{
/* Ref if we are monitoring, since monitoring owns the file list. */
nautilus_file_ref (file);
add_to_work_queue = TRUE;
}
else if (nautilus_directory_has_active_request_for_file (directory, file))
{
/* We're waiting for the file in a call_when_ready. Make sure
* we add the file to the work queue so that said waiter won't
* wait forever for e.g. all files in the directory to be done */
add_to_work_queue = TRUE;
}
if (add_to_work_queue)
{
nautilus_directory_add_file_to_work_queue (directory, file);
}
}
void
nautilus_directory_remove_file (NautilusDirectory *directory,
NautilusFile *file)
{
GList *node;
g_assert (NAUTILUS_IS_DIRECTORY (directory));
g_assert (NAUTILUS_IS_FILE (file));
/* Find the list node in the hash table. */
node = extract_from_hash_table (directory, file);
g_assert (node != NULL);
g_assert (node->data == file);
/* Remove the item from the list. */
directory->details->file_list = g_list_remove_link
(directory->details->file_list, node);
g_list_free_1 (node);
nautilus_directory_remove_file_from_work_queue (directory, file);
if (!file->details->unconfirmed)
{
directory->details->confirmed_file_count--;
}
/* Unref if we are monitoring. */
if (nautilus_directory_is_file_list_monitored (directory))
{
nautilus_file_unref (file);
}
}
GList *
nautilus_directory_begin_file_name_change (NautilusDirectory *directory,
NautilusFile *file)
{
/* Find the list node in the hash table. */
return extract_from_hash_table (directory, file);
}
void
nautilus_directory_end_file_name_change (NautilusDirectory *directory,
NautilusFile *file,
GList *node)
{
/* Add the list node to the hash table. */
if (node != NULL)
{
add_to_hash_table (directory, file, node);
}
}
NautilusFile *
nautilus_directory_find_file_by_name (NautilusDirectory *directory,
const char *name)
{
GList *node;
g_return_val_if_fail (NAUTILUS_IS_DIRECTORY (directory), NULL);
g_return_val_if_fail (name != NULL, NULL);
node = g_hash_table_lookup (directory->details->file_hash,
name);
return node == NULL ? NULL : NAUTILUS_FILE (node->data);
}
void
nautilus_directory_emit_files_added (NautilusDirectory *directory,
GList *added_files)
{
nautilus_profile_start (NULL);
if (added_files != NULL)
{
g_signal_emit (directory,
signals[FILES_ADDED], 0,
added_files);
}
nautilus_profile_end (NULL);
}
void
nautilus_directory_emit_files_changed (NautilusDirectory *directory,
GList *changed_files)
{
nautilus_profile_start (NULL);
if (changed_files != NULL)
{
g_signal_emit (directory,
signals[FILES_CHANGED], 0,
changed_files);
}
nautilus_profile_end (NULL);
}
void
nautilus_directory_emit_change_signals (NautilusDirectory *directory,
GList *changed_files)
{
GList *p;
nautilus_profile_start (NULL);
for (p = changed_files; p != NULL; p = p->next)
{
nautilus_file_emit_changed (p->data);
}
nautilus_directory_emit_files_changed (directory, changed_files);
nautilus_profile_end (NULL);
}
void
nautilus_directory_emit_done_loading (NautilusDirectory *directory)
{
g_signal_emit (directory,
signals[DONE_LOADING], 0);
}
void
nautilus_directory_emit_load_error (NautilusDirectory *directory,
GError *error)
{
g_signal_emit (directory,
signals[LOAD_ERROR], 0,
error);
}
/* Return a directory object for this one's parent. */
static NautilusDirectory *
get_parent_directory (GFile *location)
{
NautilusDirectory *directory;
GFile *parent;
parent = g_file_get_parent (location);
if (parent)
{
directory = nautilus_directory_get_internal (parent, TRUE);
g_object_unref (parent);
return directory;
}
return NULL;
}
/* If a directory object exists for this one's parent, then
* return it, otherwise return NULL.
*/
static NautilusDirectory *
get_parent_directory_if_exists (GFile *location)
{
NautilusDirectory *directory;
GFile *parent;
parent = g_file_get_parent (location);
if (parent)
{
directory = nautilus_directory_get_internal (parent, FALSE);
g_object_unref (parent);
return directory;
}
return NULL;
}
static void
hash_table_list_prepend (GHashTable *table,
gconstpointer key,
gpointer data)
{
GList *list;
list = g_hash_table_lookup (table, key);
list = g_list_prepend (list, data);
g_hash_table_insert (table, (gpointer) key, list);
}
static void
call_files_added_free_list (gpointer key,
gpointer value,
gpointer user_data)
{
g_assert (NAUTILUS_IS_DIRECTORY (key));
g_assert (value != NULL);
g_assert (user_data == NULL);
g_signal_emit (key,
signals[FILES_ADDED], 0,
value);
g_list_free (value);
}
static void
call_files_changed_common (NautilusDirectory *self,
GList *file_list)
{
GList *node;
NautilusFile *file;
for (node = file_list; node != NULL; node = node->next)
{
NautilusDirectory *directory;
file = node->data;
directory = nautilus_file_get_directory (file);
if (directory == self)
{
nautilus_directory_add_file_to_work_queue (self, file);
}
}
nautilus_directory_async_state_changed (self);
nautilus_directory_emit_change_signals (self, file_list);
}
static void
call_files_changed_free_list (gpointer key,
gpointer value,
gpointer user_data)
{
g_assert (value != NULL);
g_assert (user_data == NULL);
call_files_changed_common (NAUTILUS_DIRECTORY (key), value);
g_list_free (value);
}
static void
call_files_changed_unref_free_list (gpointer key,
gpointer value,
gpointer user_data)
{
g_assert (value != NULL);
g_assert (user_data == NULL);
call_files_changed_common (NAUTILUS_DIRECTORY (key), value);
nautilus_file_list_free (value);
}
static void
call_get_file_info_free_list (gpointer key,
gpointer value,
gpointer user_data)
{
NautilusDirectory *directory;
GList *files;
g_assert (NAUTILUS_IS_DIRECTORY (key));
g_assert (value != NULL);
g_assert (user_data == NULL);
directory = key;
files = value;
nautilus_directory_get_info_for_new_files (directory, files);
g_list_foreach (files, (GFunc) g_object_unref, NULL);
g_list_free (files);
}
static void
invalidate_count_and_unref (gpointer key,
gpointer value,
gpointer user_data)
{
g_assert (NAUTILUS_IS_DIRECTORY (key));
g_assert (value == key);
g_assert (user_data == NULL);
nautilus_directory_invalidate_count_and_mime_list (key);
nautilus_directory_unref (key);
}
static void
collect_parent_directories (GHashTable *hash_table,
NautilusDirectory *directory)
{
g_assert (hash_table != NULL);
g_assert (NAUTILUS_IS_DIRECTORY (directory));
if (g_hash_table_lookup (hash_table, directory) == NULL)
{
nautilus_directory_ref (directory);
g_hash_table_insert (hash_table, directory, directory);
}
}
void
nautilus_directory_notify_files_added (GList *files)
{
GHashTable *added_lists;
GList *p;
NautilusDirectory *directory;
GHashTable *parent_directories;
NautilusFile *file;
GFile *location, *parent;
nautilus_profile_start (NULL);
/* Make a list of added files in each directory. */
added_lists = g_hash_table_new (NULL, NULL);
/* Make a list of parent directories that will need their counts updated. */
parent_directories = g_hash_table_new (NULL, NULL);
for (p = files; p != NULL; p = p->next)
{
location = p->data;
/* See if the directory is already known. */
directory = get_parent_directory_if_exists (location);
if (directory == NULL)
{
/* In case the directory is not being
* monitored, but the corresponding file is,
* we must invalidate it's item count.
*/
file = NULL;
parent = g_file_get_parent (location);
if (parent)
{
file = nautilus_file_get_existing (parent);
g_object_unref (parent);
}
if (file != NULL)
{
nautilus_file_invalidate_count_and_mime_list (file);
nautilus_file_unref (file);
}
continue;
}
collect_parent_directories (parent_directories, directory);
/* If no one is monitoring files in the directory, nothing to do. */
if (!nautilus_directory_is_file_list_monitored (directory))
{
nautilus_directory_unref (directory);
continue;
}
file = nautilus_file_get_existing (location);
/* We check is_added here, because the file could have been added
* to the directory by a nautilus_file_get() but not gotten
* files_added emitted
*/
if (file && file->details->is_added)
{
/* A file already exists, it was probably renamed.
* If it was renamed this could be ignored, but
* queue a change just in case */
nautilus_file_changed (file);
nautilus_file_unref (file);
}
else
{
hash_table_list_prepend (added_lists,
directory,
g_object_ref (location));
}
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.
*/
g_hash_table_foreach (added_lists, call_get_file_info_free_list, NULL);
g_hash_table_destroy (added_lists);
/* Invalidate count for each parent directory. */
g_hash_table_foreach (parent_directories, invalidate_count_and_unref, NULL);
g_hash_table_destroy (parent_directories);
nautilus_profile_end (NULL);
}
void
nautilus_directory_notify_files_changed (GList *files)
{
GHashTable *changed_lists;
GList *node;
GFile *location;
NautilusFile *file;
/* Make a list of changed files in each directory. */
changed_lists = g_hash_table_new (NULL, NULL);
/* Go through all the notifications. */
for (node = files; node != NULL; node = node->next)
{
location = node->data;
/* Find the file. */
file = nautilus_file_get_existing (location);
if (file != NULL)
{
NautilusDirectory *directory;
directory = nautilus_file_get_directory (file);
/* Tell it to re-get info now, and later emit
* a changed signal.
*/
file->details->file_info_is_up_to_date = FALSE;
nautilus_file_invalidate_extension_info_internal (file);
hash_table_list_prepend (changed_lists, directory, file);
}
}
/* Now send out the changed signals. */
g_hash_table_foreach (changed_lists, call_files_changed_unref_free_list, NULL);
g_hash_table_destroy (changed_lists);
}
void
nautilus_directory_notify_files_removed (GList *files)
{
GHashTable *changed_lists;
GList *p;
GHashTable *parent_directories;
NautilusFile *file;
GFile *location;
/* Make a list of changed files in each directory. */
changed_lists = g_hash_table_new (NULL, NULL);
/* Make a list of parent directories that will need their counts updated. */
parent_directories = g_hash_table_new (NULL, NULL);
/* Go through all the notifications. */
for (p = files; p != NULL; p = p->next)
{
NautilusDirectory *directory;
location = p->data;
/* Update file count for parent directory if anyone might care. */
directory = get_parent_directory_if_exists (location);
if (directory != NULL)
{
collect_parent_directories (parent_directories, directory);
nautilus_directory_unref (directory);
}
/* Find the file. */
file = nautilus_file_get_existing (location);
if (file != NULL && !nautilus_file_rename_in_progress (file))
{
directory = nautilus_file_get_directory (file);
/* Mark it gone and prepare to send the changed signal. */
nautilus_file_mark_gone (file);
hash_table_list_prepend (changed_lists,
directory, nautilus_file_ref (file));
}
nautilus_file_unref (file);
}
/* Now send out the changed signals. */
g_hash_table_foreach (changed_lists, call_files_changed_unref_free_list, NULL);
g_hash_table_destroy (changed_lists);
/* Invalidate count for each parent directory. */
g_hash_table_foreach (parent_directories, invalidate_count_and_unref, NULL);
g_hash_table_destroy (parent_directories);
}
static void
set_directory_location (NautilusDirectory *directory,
GFile *location)
{
if (directory->details->location)
{
g_object_unref (directory->details->location);
}
directory->details->location = g_object_ref (location);
g_object_notify_by_pspec (G_OBJECT (directory), properties[PROP_LOCATION]);
}
static void
change_directory_location (NautilusDirectory *directory,
GFile *new_location)
{
/* I believe it's impossible for a self-owned file/directory
* to be moved. But if that did somehow happen, this function
* wouldn't do enough to handle it.
*/
g_assert (directory->details->as_file == NULL);
g_hash_table_remove (directories,
directory->details->location);
set_directory_location (directory, new_location);
g_hash_table_insert (directories,
directory->details->location,
directory);
}
typedef struct
{
GFile *container;
GList *directories;
} CollectData;
static void
collect_directories_by_container (gpointer key,
gpointer value,
gpointer callback_data)
{
NautilusDirectory *directory;
CollectData *collect_data;
GFile *location;
location = (GFile *) key;
directory = NAUTILUS_DIRECTORY (value);
collect_data = (CollectData *) callback_data;
if (g_file_has_prefix (location, collect_data->container) ||
g_file_equal (collect_data->container, location))
{
nautilus_directory_ref (directory);
collect_data->directories =
g_list_prepend (collect_data->directories,
directory);
}
}
static GList *
nautilus_directory_moved_internal (GFile *old_location,
GFile *new_location)
{
CollectData collection;
NautilusDirectory *directory;
GList *node, *affected_files;
GFile *new_directory_location;
char *relative_path;
collection.container = old_location;
collection.directories = NULL;
g_hash_table_foreach (directories,
collect_directories_by_container,
&collection);
affected_files = NULL;
for (node = collection.directories; node != NULL; node = node->next)
{
directory = NAUTILUS_DIRECTORY (node->data);
new_directory_location = NULL;
if (g_file_equal (directory->details->location, old_location))
{
new_directory_location = g_object_ref (new_location);
}
else
{
relative_path = g_file_get_relative_path (old_location,
directory->details->location);
if (relative_path != NULL)
{
new_directory_location = g_file_resolve_relative_path (new_location, relative_path);
g_free (relative_path);
}
}
if (new_directory_location)
{
change_directory_location (directory, new_directory_location);
g_object_unref (new_directory_location);
/* Collect affected files. */
if (directory->details->as_file != NULL)
{
affected_files = g_list_prepend
(affected_files,
nautilus_file_ref (directory->details->as_file));
}
affected_files = g_list_concat
(affected_files,
nautilus_file_list_copy (directory->details->file_list));
}
nautilus_directory_unref (directory);
}
g_list_free (collection.directories);
return affected_files;
}
void
nautilus_directory_moved (const char *old_uri,
const char *new_uri)
{
GList *list, *node;
GHashTable *hash;
NautilusFile *file;
GFile *old_location;
GFile *new_location;
hash = g_hash_table_new (NULL, NULL);
old_location = g_file_new_for_uri (old_uri);
new_location = g_file_new_for_uri (new_uri);
list = nautilus_directory_moved_internal (old_location, new_location);
for (node = list; node != NULL; node = node->next)
{
NautilusDirectory *directory;
file = NAUTILUS_FILE (node->data);
directory = nautilus_file_get_directory (file);
hash_table_list_prepend (hash, directory, nautilus_file_ref (file));
}
nautilus_file_list_free (list);
g_object_unref (old_location);
g_object_unref (new_location);
g_hash_table_foreach (hash, call_files_changed_unref_free_list, NULL);
g_hash_table_destroy (hash);
}
void
nautilus_directory_notify_files_moved (GList *file_pairs)
{
GList *p, *affected_files, *node;
GFilePair *pair;
NautilusFile *file;
NautilusDirectory *old_directory, *new_directory;
GHashTable *parent_directories;
GList *new_files_list, *unref_list;
GHashTable *added_lists, *changed_lists;
char *name;
NautilusFileAttributes cancel_attributes;
GFile *to_location, *from_location;
/* Make a list of added and changed files in each directory. */
new_files_list = NULL;
added_lists = g_hash_table_new (NULL, NULL);
changed_lists = g_hash_table_new (NULL, NULL);
unref_list = NULL;
/* Make a list of parent directories that will need their counts updated. */
parent_directories = g_hash_table_new (NULL, NULL);
cancel_attributes = nautilus_file_get_all_attributes ();
for (p = file_pairs; p != NULL; p = p->next)
{
pair = p->data;
from_location = pair->from;
to_location = pair->to;
/* Handle overwriting a file. */
file = nautilus_file_get_existing (to_location);
if (file != NULL)
{
NautilusDirectory *directory;
directory = nautilus_file_get_directory (file);
/* Mark it gone and prepare to send the changed signal. */
nautilus_file_mark_gone (file);
hash_table_list_prepend (changed_lists, directory, file);
collect_parent_directories (parent_directories, directory);
}
/* Update any directory objects that are affected. */
affected_files = nautilus_directory_moved_internal (from_location,
to_location);
for (node = affected_files; node != NULL; node = node->next)
{
NautilusDirectory *directory;
file = NAUTILUS_FILE (node->data);
directory = nautilus_file_get_directory (file);
hash_table_list_prepend (changed_lists, directory, file);
}
unref_list = g_list_concat (unref_list, affected_files);
/* Move an existing file. */
file = nautilus_file_get_existing (from_location);
if (file == NULL)
{
/* Handle this as if it was a new file. */
new_files_list = g_list_prepend (new_files_list,
to_location);
}
else
{
NautilusDirectory *directory;
directory = nautilus_file_get_directory (file);
/* Handle notification in the old directory. */
old_directory = directory;
collect_parent_directories (parent_directories, old_directory);
/* Cancel loading of attributes in the old directory */
nautilus_directory_cancel_loading_file_attributes
(old_directory, file, cancel_attributes);
/* Locate the new directory. */
new_directory = get_parent_directory (to_location);
collect_parent_directories (parent_directories, new_directory);
/* We can unref now -- new_directory is in the
* parent directories list so it will be
* around until the end of this function
* anyway.
*/
nautilus_directory_unref (new_directory);
/* Update the file's name and directory. */
name = g_file_get_basename (to_location);
nautilus_file_update_name_and_directory
(file, name, new_directory);
g_free (name);
/* Update file attributes */
nautilus_file_invalidate_attributes (file, NAUTILUS_FILE_ATTRIBUTE_INFO);
hash_table_list_prepend (changed_lists,
old_directory,
file);
if (old_directory != new_directory)
{
hash_table_list_prepend (added_lists,
new_directory,
file);
}
/* Unref each file once to balance out nautilus_file_get_by_uri. */
unref_list = g_list_prepend (unref_list, file);
}
}
/* Now send out the changed and added signals for existing file objects. */
g_hash_table_foreach (changed_lists, call_files_changed_free_list, NULL);
g_hash_table_destroy (changed_lists);
g_hash_table_foreach (added_lists, call_files_added_free_list, NULL);
g_hash_table_destroy (added_lists);
/* Let the file objects go. */
nautilus_file_list_free (unref_list);
/* Invalidate count for each parent directory. */
g_hash_table_foreach (parent_directories, invalidate_count_and_unref, NULL);
g_hash_table_destroy (parent_directories);
/* Separate handling for brand new file objects. */
nautilus_directory_notify_files_added (new_files_list);
g_list_free (new_files_list);
}
gboolean
nautilus_directory_contains_file (NautilusDirectory *directory,
NautilusFile *file)
{
g_return_val_if_fail (NAUTILUS_IS_DIRECTORY (directory), FALSE);
g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE);
if (nautilus_file_is_gone (file))
{
return FALSE;
}
return NAUTILUS_DIRECTORY_CLASS (G_OBJECT_GET_CLASS (directory))->contains_file (directory, file);
}
NautilusFile *
nautilus_directory_get_file_by_name (NautilusDirectory *directory,
const gchar *name)
{
GList *files;
GList *l;
NautilusFile *result = NULL;
files = nautilus_directory_get_file_list (directory);
for (l = files; l != NULL; l = l->next)
{
if (nautilus_file_compare_display_name (l->data, name) == 0)
{
result = nautilus_file_ref (l->data);
break;
}
}
nautilus_file_list_free (files);
return result;
}
void
nautilus_directory_call_when_ready (NautilusDirectory *directory,
NautilusFileAttributes file_attributes,
gboolean wait_for_all_files,
NautilusDirectoryCallback callback,
gpointer callback_data)
{
g_return_if_fail (NAUTILUS_IS_DIRECTORY (directory));
g_return_if_fail (callback != NULL);
NAUTILUS_DIRECTORY_CLASS (G_OBJECT_GET_CLASS (directory))->call_when_ready
(directory, file_attributes, wait_for_all_files,
callback, callback_data);
}
void
nautilus_directory_cancel_callback (NautilusDirectory *directory,
NautilusDirectoryCallback callback,
gpointer callback_data)
{
g_return_if_fail (NAUTILUS_IS_DIRECTORY (directory));
g_return_if_fail (callback != NULL);
NAUTILUS_DIRECTORY_CLASS (G_OBJECT_GET_CLASS (directory))->cancel_callback
(directory, callback, callback_data);
}
void
nautilus_directory_file_monitor_add (NautilusDirectory *directory,
gconstpointer client,
gboolean monitor_hidden_files,
NautilusFileAttributes file_attributes,
NautilusDirectoryCallback callback,
gpointer callback_data)
{
g_return_if_fail (NAUTILUS_IS_DIRECTORY (directory));
g_return_if_fail (client != NULL);
NAUTILUS_DIRECTORY_CLASS (G_OBJECT_GET_CLASS (directory))->file_monitor_add
(directory, client,
monitor_hidden_files,
file_attributes,
callback, callback_data);
}
void
nautilus_directory_file_monitor_remove (NautilusDirectory *directory,
gconstpointer client)
{
g_return_if_fail (NAUTILUS_IS_DIRECTORY (directory));
g_return_if_fail (client != NULL);
NAUTILUS_DIRECTORY_CLASS (G_OBJECT_GET_CLASS (directory))->file_monitor_remove
(directory, client);
}
void
nautilus_directory_force_reload (NautilusDirectory *directory)
{
g_return_if_fail (NAUTILUS_IS_DIRECTORY (directory));
NAUTILUS_DIRECTORY_CLASS (G_OBJECT_GET_CLASS (directory))->force_reload (directory);
}
gboolean
nautilus_directory_is_not_empty (NautilusDirectory *directory)
{
g_return_val_if_fail (NAUTILUS_IS_DIRECTORY (directory), FALSE);
return NAUTILUS_DIRECTORY_CLASS (G_OBJECT_GET_CLASS (directory))->is_not_empty (directory);
}
GList *
nautilus_directory_get_file_list (NautilusDirectory *directory)
{
return NAUTILUS_DIRECTORY_CLASS (G_OBJECT_GET_CLASS (directory))->get_file_list (directory);
}
gboolean
nautilus_directory_is_editable (NautilusDirectory *directory)
{
return NAUTILUS_DIRECTORY_CLASS (G_OBJECT_GET_CLASS (directory))->is_editable (directory);
}
GList *
nautilus_directory_match_pattern (NautilusDirectory *directory,
const char *pattern)
{
GList *files, *l, *ret;
GPatternSpec *spec;
ret = NULL;
spec = g_pattern_spec_new (pattern);
files = nautilus_directory_get_file_list (directory);
for (l = files; l; l = l->next)
{
NautilusFile *file;
char *name;
file = NAUTILUS_FILE (l->data);
name = nautilus_file_get_display_name (file);
if (g_pattern_match_string (spec, name))
{
ret = g_list_prepend (ret, nautilus_file_ref (file));
}
g_free (name);
}
g_pattern_spec_free (spec);
nautilus_file_list_free (files);
return ret;
}
/**
* nautilus_directory_list_ref
*
* Ref all the directories in a list.
* @list: GList of directories.
**/
GList *
nautilus_directory_list_ref (GList *list)
{
g_list_foreach (list, (GFunc) nautilus_directory_ref, NULL);
return list;
}
/**
* nautilus_directory_list_unref
*
* Unref all the directories in a list.
* @list: GList of directories.
**/
void
nautilus_directory_list_unref (GList *list)
{
g_list_foreach (list, (GFunc) nautilus_directory_unref, NULL);
}
/**
* nautilus_directory_list_free
*
* Free a list of directories after unrefing them.
* @list: GList of directories.
**/
void
nautilus_directory_list_free (GList *list)
{
nautilus_directory_list_unref (list);
g_list_free (list);
}
/**
* nautilus_directory_list_copy
*
* Copy the list of directories, making a new ref of each,
* @list: GList of directories.
**/
GList *
nautilus_directory_list_copy (GList *list)
{
return g_list_copy (nautilus_directory_list_ref (list));
}
static int
compare_by_uri (NautilusDirectory *a,
NautilusDirectory *b)
{
char *uri_a, *uri_b;
int res;
uri_a = g_file_get_uri (a->details->location);
uri_b = g_file_get_uri (b->details->location);
res = strcmp (uri_a, uri_b);
g_free (uri_a);
g_free (uri_b);
return res;
}
static int
compare_by_uri_cover (gconstpointer a,
gconstpointer b)
{
return compare_by_uri (NAUTILUS_DIRECTORY (a), NAUTILUS_DIRECTORY (b));
}
/**
* nautilus_directory_list_sort_by_uri
*
* Sort the list of directories by directory uri.
* @list: GList of directories.
**/
GList *
nautilus_directory_list_sort_by_uri (GList *list)
{
return g_list_sort (list, compare_by_uri_cover);
}
#if !defined (NAUTILUS_OMIT_SELF_CHECK)
#include
static int data_dummy;
static gboolean got_files_flag;
static void
got_files_callback (NautilusDirectory *directory,
GList *files,
gpointer callback_data)
{
g_assert (NAUTILUS_IS_DIRECTORY (directory));
g_assert (g_list_length (files) > 10);
g_assert (callback_data == &data_dummy);
got_files_flag = TRUE;
}
/* Return the number of extant NautilusDirectories */
int
nautilus_directory_number_outstanding (void)
{
return directories ? g_hash_table_size (directories) : 0;
}
void
nautilus_directory_dump (NautilusDirectory *directory)
{
g_autofree gchar *uri = NULL;
uri = g_file_get_uri (directory->details->location);
g_print ("uri: %s\n", uri);
g_print ("ref count: %d\n", G_OBJECT (directory)->ref_count);
}
void
nautilus_self_check_directory (void)
{
NautilusDirectory *directory;
NautilusFile *file;
directory = nautilus_directory_get_by_uri ("file:///etc");
file = nautilus_file_get_by_uri ("file:///etc/passwd");
EEL_CHECK_INTEGER_RESULT (g_hash_table_size (directories), 1);
nautilus_directory_file_monitor_add
(directory, &data_dummy,
TRUE, 0, NULL, NULL);
/* FIXME: these need to be updated to the new metadata infrastructure
* as make check doesn't pass.
* nautilus_file_set_metadata (file, "test", "default", "value");
* EEL_CHECK_STRING_RESULT (nautilus_file_get_metadata (file, "test", "default"), "value");
*
* nautilus_file_set_boolean_metadata (file, "test_boolean", TRUE, TRUE);
* EEL_CHECK_BOOLEAN_RESULT (nautilus_file_get_boolean_metadata (file, "test_boolean", TRUE), TRUE);
* nautilus_file_set_boolean_metadata (file, "test_boolean", TRUE, FALSE);
* EEL_CHECK_BOOLEAN_RESULT (nautilus_file_get_boolean_metadata (file, "test_boolean", TRUE), FALSE);
* EEL_CHECK_BOOLEAN_RESULT (nautilus_file_get_boolean_metadata (NULL, "test_boolean", TRUE), TRUE);
*
* nautilus_file_set_integer_metadata (file, "test_integer", 0, 17);
* EEL_CHECK_INTEGER_RESULT (nautilus_file_get_integer_metadata (file, "test_integer", 0), 17);
* nautilus_file_set_integer_metadata (file, "test_integer", 0, -1);
* EEL_CHECK_INTEGER_RESULT (nautilus_file_get_integer_metadata (file, "test_integer", 0), -1);
* nautilus_file_set_integer_metadata (file, "test_integer", 42, 42);
* EEL_CHECK_INTEGER_RESULT (nautilus_file_get_integer_metadata (file, "test_integer", 42), 42);
* EEL_CHECK_INTEGER_RESULT (nautilus_file_get_integer_metadata (NULL, "test_integer", 42), 42);
* EEL_CHECK_INTEGER_RESULT (nautilus_file_get_integer_metadata (file, "nonexistent_key", 42), 42);
*/
EEL_CHECK_BOOLEAN_RESULT (nautilus_directory_get_by_uri ("file:///etc") == directory, TRUE);
nautilus_directory_unref (directory);
EEL_CHECK_BOOLEAN_RESULT (nautilus_directory_get_by_uri ("file:///etc/") == directory, TRUE);
nautilus_directory_unref (directory);
EEL_CHECK_BOOLEAN_RESULT (nautilus_directory_get_by_uri ("file:///etc////") == directory, TRUE);
nautilus_directory_unref (directory);
nautilus_file_unref (file);
nautilus_directory_file_monitor_remove (directory, &data_dummy);
nautilus_directory_unref (directory);
while (g_hash_table_size (directories) != 0)
{
gtk_main_iteration ();
}
EEL_CHECK_INTEGER_RESULT (g_hash_table_size (directories), 0);
directory = nautilus_directory_get_by_uri ("file:///etc");
got_files_flag = FALSE;
nautilus_directory_call_when_ready (directory,
NAUTILUS_FILE_ATTRIBUTE_INFO |
NAUTILUS_FILE_ATTRIBUTE_DEEP_COUNTS,
TRUE,
got_files_callback, &data_dummy);
while (!got_files_flag)
{
gtk_main_iteration ();
}
EEL_CHECK_BOOLEAN_RESULT (directory->details->file_list == NULL, TRUE);
EEL_CHECK_INTEGER_RESULT (g_hash_table_size (directories), 1);
file = nautilus_file_get_by_uri ("file:///etc/passwd");
/* EEL_CHECK_STRING_RESULT (nautilus_file_get_metadata (file, "test", "default"), "value"); */
nautilus_file_unref (file);
nautilus_directory_unref (directory);
EEL_CHECK_INTEGER_RESULT (g_hash_table_size (directories), 0);
}
#endif /* !NAUTILUS_OMIT_SELF_CHECK */