mirror of
https://gitlab.gnome.org/GNOME/nautilus
synced 2024-10-03 06:25:36 +00:00
136742e4ef
* Tons of files: Because lots of recent bugs were due to "signal handler called after object gone" problems, switched many calls of g_signal_connect and g_signal_connect_swapped to use g_signal_connect_object instead. Also did other signal-related cleanup and changed some destroys to finalizes. * libnautilus/nautilus-view-standard-main.h: We no longer need to include nautilus-view.h in here. So include it in the files that use this instead. Did merges from stable branch: 2001-10-25 Darin Adler <darin@bentspoon.com> * libnautilus-private/nautilus-directory.c: (call_files_changed_common), (call_files_changed_free_list), (call_files_changed_unref_free_list), (nautilus_directory_notify_files_changed): Move call to nautilus_directory_add_file_to_work_queue into a better bottleneck; now it catches all the notify cases, not just changed. Also tell it to re-get top-left text and link info too when we get a changed notice. * src/file-manager/fm-directory-view.c: (queue_pending_files): Don't use the timeout (and the hysteresis) when queuing files once the initial directory load is complete. Doing this was causing delays processing changes that came in later, which we don't want. * src/nautilus-sidebar-title.c: (item_count_ready), (monitor_add), (update_all), (nautilus_sidebar_title_set_file): Monitor the directory count once we get it the first time. This makes sure that changes in the directory count get reflected in the sidebar without creating a race with the main view to see who calculates it first. 2001-10-25 Alex Larsson <alexl@redhat.com> * libnautilus-private/nautilus-directory.c (nautilus_directory_notify_files_changed): Call nautilus_directory_add_file_to_work_queue() when file_info is invalidated. Otherwise it will not be read again.
288 lines
8.2 KiB
C
288 lines
8.2 KiB
C
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
|
|
|
|
/*
|
|
nautilus-trash-monitor.c: Nautilus trash state watcher.
|
|
|
|
Copyright (C) 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, write to the
|
|
Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
Boston, MA 02111-1307, USA.
|
|
|
|
Author: Pavel Cisler <pavel@eazel.com>
|
|
*/
|
|
|
|
#include <config.h>
|
|
#include "nautilus-trash-monitor.h"
|
|
|
|
#include "nautilus-directory-notify.h"
|
|
#include "nautilus-directory.h"
|
|
#include "nautilus-file-attributes.h"
|
|
#include "nautilus-trash-directory.h"
|
|
#include <eel/eel-debug.h>
|
|
#include <eel/eel-gtk-macros.h>
|
|
#include <eel/eel-vfs-extensions.h>
|
|
#include <gtk/gtksignal.h>
|
|
#include <libgnomevfs/gnome-vfs-find-directory.h>
|
|
#include <libgnomevfs/gnome-vfs-types.h>
|
|
#include <libgnomevfs/gnome-vfs-uri.h>
|
|
#include <libgnomevfs/gnome-vfs-utils.h>
|
|
|
|
struct NautilusTrashMonitorDetails {
|
|
NautilusDirectory *trash_directory;
|
|
gboolean empty;
|
|
};
|
|
|
|
enum {
|
|
TRASH_STATE_CHANGED,
|
|
CHECK_TRASH_DIRECTORY_ADDED,
|
|
LAST_SIGNAL
|
|
};
|
|
|
|
static guint signals[LAST_SIGNAL];
|
|
static NautilusTrashMonitor *nautilus_trash_monitor;
|
|
|
|
static void nautilus_trash_monitor_class_init (NautilusTrashMonitorClass *klass);
|
|
static void nautilus_trash_monitor_init (gpointer object,
|
|
gpointer klass);
|
|
static void destroy (GtkObject *object);
|
|
|
|
EEL_CLASS_BOILERPLATE (NautilusTrashMonitor, nautilus_trash_monitor, GTK_TYPE_OBJECT)
|
|
|
|
static void
|
|
nautilus_trash_monitor_class_init (NautilusTrashMonitorClass *klass)
|
|
{
|
|
GtkObjectClass *object_class;
|
|
|
|
object_class = GTK_OBJECT_CLASS (klass);
|
|
|
|
object_class->destroy = destroy;
|
|
|
|
signals[TRASH_STATE_CHANGED] = g_signal_new
|
|
("trash_state_changed",
|
|
G_TYPE_FROM_CLASS (object_class),
|
|
G_SIGNAL_RUN_LAST,
|
|
G_STRUCT_OFFSET (NautilusTrashMonitorClass, trash_state_changed),
|
|
NULL, NULL,
|
|
g_cclosure_marshal_VOID__BOOLEAN,
|
|
G_TYPE_NONE, 1,
|
|
G_TYPE_BOOLEAN);
|
|
|
|
signals[CHECK_TRASH_DIRECTORY_ADDED] = g_signal_new
|
|
("check_trash_directory_added",
|
|
G_TYPE_FROM_CLASS (object_class),
|
|
G_SIGNAL_RUN_LAST,
|
|
G_STRUCT_OFFSET (NautilusTrashMonitorClass, check_trash_directory_added),
|
|
NULL, NULL,
|
|
g_cclosure_marshal_VOID__POINTER,
|
|
G_TYPE_NONE, 1,
|
|
G_TYPE_POINTER);
|
|
}
|
|
|
|
static void
|
|
nautilus_trash_files_changed_callback (NautilusDirectory *directory, GList *files,
|
|
gpointer callback_data)
|
|
{
|
|
NautilusTrashMonitor *trash_monitor;
|
|
gboolean old_empty_state;
|
|
NautilusFile *file;
|
|
|
|
trash_monitor = callback_data;
|
|
g_assert (NAUTILUS_IS_TRASH_MONITOR (trash_monitor));
|
|
g_assert (trash_monitor->details->trash_directory == directory);
|
|
|
|
/* Something about the Trash NautilusDirectory changed, find out if
|
|
* it affected the empty state.
|
|
*/
|
|
old_empty_state = trash_monitor->details->empty;
|
|
trash_monitor->details->empty = !nautilus_directory_is_not_empty (directory);
|
|
|
|
if (old_empty_state != trash_monitor->details->empty) {
|
|
file = nautilus_file_get (EEL_TRASH_URI);
|
|
nautilus_file_changed (file);
|
|
nautilus_file_unref (file);
|
|
|
|
/* trash got empty or full, notify everyone who cares */
|
|
g_signal_emit (trash_monitor,
|
|
signals[TRASH_STATE_CHANGED], 0,
|
|
trash_monitor->details->empty);
|
|
}
|
|
}
|
|
|
|
static void
|
|
nautilus_trash_monitor_init (gpointer object, gpointer klass)
|
|
{
|
|
NautilusDirectory *trash_directory;
|
|
NautilusTrashMonitor *trash_monitor;
|
|
GList *attributes;
|
|
|
|
trash_monitor = NAUTILUS_TRASH_MONITOR (object);
|
|
|
|
/* set up a NautilusDirectory for the Trash directory to monitor */
|
|
|
|
trash_directory = nautilus_directory_get (EEL_TRASH_URI);
|
|
|
|
trash_monitor->details = g_new0 (NautilusTrashMonitorDetails, 1);
|
|
trash_monitor->details->trash_directory = trash_directory;
|
|
trash_monitor->details->empty = TRUE;
|
|
|
|
attributes = g_list_prepend (NULL, NAUTILUS_FILE_ATTRIBUTE_METADATA);
|
|
|
|
/* Make sure we get notified about changes */
|
|
nautilus_directory_file_monitor_add
|
|
(trash_directory, trash_monitor, TRUE, TRUE, attributes,
|
|
nautilus_trash_files_changed_callback, trash_monitor);
|
|
|
|
g_list_free (attributes);
|
|
|
|
g_signal_connect_object (trash_directory, "files_added",
|
|
G_CALLBACK (nautilus_trash_files_changed_callback), trash_monitor, 0);
|
|
g_signal_connect_object (trash_directory, "files_changed",
|
|
G_CALLBACK (nautilus_trash_files_changed_callback), trash_monitor, 0);
|
|
}
|
|
|
|
static void
|
|
destroy (GtkObject *object)
|
|
{
|
|
NautilusTrashMonitor *trash_monitor;
|
|
|
|
trash_monitor = NAUTILUS_TRASH_MONITOR (object);
|
|
|
|
nautilus_directory_file_monitor_remove
|
|
(trash_monitor->details->trash_directory,
|
|
trash_monitor);
|
|
nautilus_directory_unref (trash_monitor->details->trash_directory);
|
|
g_free (trash_monitor->details);
|
|
}
|
|
|
|
static void
|
|
unref_trash_monitor (void)
|
|
{
|
|
g_object_unref (nautilus_trash_monitor);
|
|
}
|
|
|
|
NautilusTrashMonitor *
|
|
nautilus_trash_monitor_get (void)
|
|
{
|
|
NautilusDirectory *trash_directory;
|
|
|
|
if (nautilus_trash_monitor == NULL) {
|
|
/* not running yet, start it up */
|
|
|
|
/* the trash directory object will get created by this */
|
|
trash_directory = nautilus_directory_get (EEL_TRASH_URI);
|
|
|
|
nautilus_trash_monitor = NAUTILUS_TRASH_MONITOR
|
|
(g_object_new (NAUTILUS_TYPE_TRASH_MONITOR, NULL));
|
|
g_object_ref (nautilus_trash_monitor);
|
|
gtk_object_sink (GTK_OBJECT (nautilus_trash_monitor));
|
|
eel_debug_call_at_shutdown (unref_trash_monitor);
|
|
|
|
/* make sure we get signalled when trash directories get added */
|
|
nautilus_trash_directory_finish_initializing
|
|
(NAUTILUS_TRASH_DIRECTORY (trash_directory));
|
|
|
|
nautilus_directory_unref (trash_directory);
|
|
}
|
|
|
|
return nautilus_trash_monitor;
|
|
}
|
|
|
|
gboolean
|
|
nautilus_trash_monitor_is_empty (void)
|
|
{
|
|
return nautilus_trash_monitor_get ()->details->empty;
|
|
}
|
|
|
|
static gboolean
|
|
add_one_volume_trash (const NautilusVolume *volume,
|
|
gpointer callback_data)
|
|
{
|
|
char *uri_str;
|
|
GnomeVFSURI *volume_mount_point_uri;
|
|
GnomeVFSURI *trash_uri;
|
|
GList **result;
|
|
|
|
result = (GList **) callback_data;
|
|
|
|
if (nautilus_volume_should_integrate_trash (volume)) {
|
|
|
|
/* Get the uri of the volume mount point as the place
|
|
* "near" which to look for trash on the given volume.
|
|
*/
|
|
uri_str = gnome_vfs_get_uri_from_local_path (nautilus_volume_get_mount_path (volume));
|
|
volume_mount_point_uri = gnome_vfs_uri_new (uri_str);
|
|
g_free (uri_str);
|
|
|
|
g_assert (volume_mount_point_uri != NULL);
|
|
|
|
/* Look for trash. It is OK to use a sync call here because
|
|
* the options we use (don't create, don't look for it if we
|
|
* already don't know where it is) do not cause any IO.
|
|
*/
|
|
if (gnome_vfs_find_directory (volume_mount_point_uri,
|
|
GNOME_VFS_DIRECTORY_KIND_TRASH, &trash_uri,
|
|
FALSE, FALSE, 0777) == GNOME_VFS_OK) {
|
|
|
|
/* found trash, put it on the list */
|
|
*result = g_list_prepend (*result, trash_uri);
|
|
}
|
|
|
|
gnome_vfs_uri_unref (volume_mount_point_uri);
|
|
}
|
|
|
|
/* don't stop iterating */
|
|
return FALSE;
|
|
}
|
|
|
|
GList *
|
|
nautilus_trash_monitor_get_trash_directories (void)
|
|
{
|
|
GList *result;
|
|
|
|
result = NULL;
|
|
|
|
/* Collect the trash directories on all the mounted volumes. */
|
|
nautilus_volume_monitor_each_mounted_volume
|
|
(nautilus_volume_monitor_get (), add_one_volume_trash, &result);
|
|
|
|
return result;
|
|
}
|
|
|
|
static gboolean
|
|
add_one_trash_directory_if_needed (const NautilusVolume *volume,
|
|
gpointer callback_data)
|
|
{
|
|
NautilusTrashMonitor *trash_monitor;
|
|
|
|
trash_monitor = NAUTILUS_TRASH_MONITOR (callback_data);
|
|
g_signal_emit (trash_monitor,
|
|
signals[CHECK_TRASH_DIRECTORY_ADDED], 0,
|
|
volume);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
void
|
|
nautilus_trash_monitor_add_new_trash_directories (void)
|
|
{
|
|
NautilusTrashMonitor *trash_monitor;
|
|
|
|
trash_monitor = nautilus_trash_monitor_get ();
|
|
nautilus_volume_monitor_each_mounted_volume
|
|
(nautilus_volume_monitor_get (), add_one_trash_directory_if_needed,
|
|
trash_monitor);
|
|
}
|
|
|