gnome-applets r10648 - in trunk: . trashapplet trashapplet/src
- From: ryanl svn gnome org
- To: svn-commits-list gnome org
- Subject: gnome-applets r10648 - in trunk: . trashapplet trashapplet/src
- Date: Wed, 13 Feb 2008 01:04:10 +0000 (GMT)
Author: ryanl
Date: Wed Feb 13 01:04:10 2008
New Revision: 10648
URL: http://svn.gnome.org/viewvc/gnome-applets?rev=10648&view=rev
Log:
2008-02-12 Ryan Lortie <desrt desrt ca>
* configure.in: PKG_CHECK_MODULES for GIO
* Makefile.am: move trashapplet to not depend on gnome-vfs
2008-02-12 Ryan Lortie <desrt desrt ca>
* src/trash-monitor.h:
* src/trash-monitor.c:
* src/trashapplet.h:
* src/trashapplet.c:
* src/Makefile.am: move from GnomeVFS -> GIO. Note REGRESSION: no
longer do we have a progress dialog for emptying the trash.
Closes bug #509759.
Modified:
trunk/ChangeLog
trunk/Makefile.am
trunk/configure.in
trunk/trashapplet/ChangeLog
trunk/trashapplet/src/Makefile.am
trunk/trashapplet/src/trash-monitor.c
trunk/trashapplet/src/trash-monitor.h
trunk/trashapplet/src/trashapplet.c
trunk/trashapplet/src/trashapplet.h
Modified: trunk/Makefile.am
==============================================================================
--- trunk/Makefile.am (original)
+++ trunk/Makefile.am Wed Feb 13 01:04:10 2008
@@ -7,8 +7,7 @@
vfs_applets = \
drivemount \
- gweather \
- trashapplet
+ gweather
if BUILD_GNOME_VFS_APPLETS
vfs_SUBDIRS = $(vfs_applets)
endif
@@ -45,12 +44,13 @@
invest_applet_SUBDIR = invest-applet
endif
-always_built_SUBDIRS = \
+always_built_SUBDIRS = \
charpick \
geyes \
mini-commander \
gkb-new \
stickynotes \
+ trashapplet \
null_applet
SUBDIRS = \
Modified: trunk/configure.in
==============================================================================
--- trunk/configure.in (original)
+++ trunk/configure.in Wed Feb 13 01:04:10 2008
@@ -13,6 +13,7 @@
dnl ***************************************************************************
GTK_REQUIRED=2.11.0
GLIB_REQUIRED=2.13.0
+GIO_REQUIRED=2.15.3
LIBGNOME_REQUIRED=2.8.0
LIBGNOMEUI_REQUIRED=2.8.0
GNOME_VFS_REQUIRED=2.15.4
@@ -110,6 +111,11 @@
AC_SUBST(GAILUTIL_CFLAGS)
AC_SUBST(GAILUTIL_LIBS)
+dnl -- check for gio (required) ------------------------------------------
+PKG_CHECK_MODULES(GIO, gio-2.0 >= $GIO_REQUIRED)
+AC_SUBST(GIO_CFLAGS)
+AC_SUBST(GIO_LIBS)
+
dnl -- Check for GTK+ 2.0 (required) ------------------------------------------
PKG_CHECK_MODULES(GTK, gtk+-2.0 >= $GTK_REQUIRED)
AC_SUBST(GTK_FLAGS)
@@ -271,13 +277,6 @@
AC_SUBST(XML2_CFLAGS)
AC_SUBST(XML2_LIBS)
-dnl -- check for libgweather (required for gweather applet) ------------------
-PKG_CHECK_MODULES(LIBGWEATHER, gweather >= $GWEATHER_REQUIRED)
-AC_SUBST(LIBGWEATHER_CFLAGS)
-AC_SUBST(LIBGWEATHER_LIBS)
-LIBGWEATHER_LOCATIONS=`pkg-config --variable=locations_file gweather`
-AC_SUBST(LIBGWEATHER_LOCATIONS)
-
dnl ***************************************************************************
dnl *** find paths to installed binaries ***
dnl ***************************************************************************
Modified: trunk/trashapplet/src/Makefile.am
==============================================================================
--- trunk/trashapplet/src/Makefile.am (original)
+++ trunk/trashapplet/src/Makefile.am Wed Feb 13 01:04:10 2008
@@ -1,6 +1,6 @@
INCLUDES = -I$(top_srcdir) \
$(GNOME_APPLETS_CFLAGS) \
- $(GNOME_VFS_APPLETS_CFLAGS) \
+ $(GIO_CFLAGS) \
$(LIBGLADE_CFLAGS)
libexec_PROGRAMS = trashapplet
@@ -13,7 +13,7 @@
xstuff.c \
xstuff.h
-trashapplet_LDADD = \
- $(GNOME_APPLETS_LIBS) \
- $(GNOME_VFS_APPLETS_LIBS) \
+trashapplet_LDADD = \
+ $(GNOME_APPLETS_LIBS) \
+ $(GIO_LIBS) \
$(LIBGLADE_LIBS)
Modified: trunk/trashapplet/src/trash-monitor.c
==============================================================================
--- trunk/trashapplet/src/trash-monitor.c (original)
+++ trunk/trashapplet/src/trash-monitor.c Wed Feb 13 01:04:10 2008
@@ -1,8 +1,7 @@
/*
* trash-monitor.c: monitor the state of the trash directories.
*
- * Copyright (C) 1999, 2000 Eazel, Inc.
- * Copyright (C) 2004 Canonical Ltd.
+ * Copyright  2008 Ryan Lortie, Matthias Clasen
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@@ -20,428 +19,372 @@
* 02111-1307, USA.
*/
+#include <gio/gio.h>
+
#include "trash-monitor.h"
-#include <string.h>
-#include <libgnomevfs/gnome-vfs.h>
-struct _TrashMonitor {
+/* theory of operation:
+ *
+ * it's not possible to use file monitoring to keep track of the exact number
+ * of items in the trash, so we operate in the following way:
+ *
+ * 1) always keep track of if the trash is empty or not.
+ *
+ * - on initialisation, we check if there is at least one item in the
+ * trash and decide based on that if it is empty or not.
+ *
+ * - if we receive a file monitor "created" event then the trash is no
+ * longer empty
+ *
+ * - if we receive a file monitor "deleted" event, we need to check again
+ * (for at least one item) to determine emptiness. this is done with a
+ * timeout of 0.1s that is reschedule on each delete so that we don't
+ * do a query for every single delete event (think: "empty trash").
+ *
+ * - if the empty state changes, emit "notify::empty"
+ *
+ * 2) only query the actual number of items in the trash when requested
+ *
+ * - keep a cache and used the cached value if present.
+ *
+ * - we know when the trash is empty, so no need to check in this case
+ * either.
+ *
+ * - else, manually scan the trash directory.
+ *
+ * - invalidate the cache on file monitor events. even though we can't
+ * be *absolutely* sure that it changed, emit "notify::items".
+ */
+
+struct _TrashMonitor
+{
GObject parent;
- GHashTable *volumes;
- gint total_item_count;
- gint notify_id;
+ GFile *trash;
+ gboolean empty;
+ guint empty_check_id;
+ GFileMonitor *file_monitor;
+
+ gboolean counted_items_valid;
+ int counted_items;
};
-struct _TrashMonitorClass {
+struct _TrashMonitorClass
+{
GObjectClass parent_class;
-
- void (* item_count_changed) (TrashMonitor *monitor);
};
-typedef struct {
- TrashMonitor *monitor;
- GnomeVFSVolume *volume;
- gchar *trash_uri;
- GnomeVFSAsyncHandle *find_handle;
- GnomeVFSMonitorHandle *trash_change_monitor;
- gint item_count;
-} VolumeInfo;
-
-
-static void trash_monitor_init (TrashMonitor *monitor);
-static void trash_monitor_class_init (TrashMonitorClass *class);
-
-enum {
- ITEM_COUNT_CHANGED,
- LAST_SIGNAL
+enum
+{
+ PROP_NONE,
+ PROP_EMPTY,
+ PROP_ITEMS
};
-static GObjectClass *parent_class;
-static guint signals[LAST_SIGNAL];
-
-static void volume_mounted_callback (GnomeVFSVolumeMonitor *volume_monitor,
- GnomeVFSVolume *volume,
- TrashMonitor *monitor);
-static void volume_unmount_started_callback (GnomeVFSVolumeMonitor *volume_monitor,
- GnomeVFSVolume *volume,
- TrashMonitor *monitor);
+G_DEFINE_TYPE (TrashMonitor, trash_monitor, G_TYPE_OBJECT);
-static void add_volume (TrashMonitor *monitor, GnomeVFSVolume *volume);
-static void remove_volume (TrashMonitor *monitor, GnomeVFSVolume *volume);
+static void
+trash_monitor_check_empty (TrashMonitor *monitor)
+{
+ GFileEnumerator *enumerator;
+ GError *error = NULL;
+ gboolean empty;
-static void trash_changed_queue_notify (TrashMonitor *monitor);
+ enumerator = g_file_enumerate_children (monitor->trash, "",
+ G_FILE_QUERY_INFO_NONE,
+ NULL, &error);
-G_DEFINE_TYPE (TrashMonitor, trash_monitor, G_TYPE_OBJECT)
+ if (enumerator)
+ {
+ GFileInfo *info;
+ if ((info = g_file_enumerator_next_file (enumerator, NULL, NULL)))
+ {
+ g_object_unref (info);
-static void
-trash_monitor_class_init (TrashMonitorClass *class)
-{
- parent_class = g_type_class_peek_parent (class);
+ /* not empty, clearly */
+ empty = FALSE;
+ }
+ else
+ {
+ /* couldn't even read one file. empty. */
+ empty = TRUE;
+ }
- signals[ITEM_COUNT_CHANGED] = g_signal_new
- ("item_count_changed",
- G_TYPE_FROM_CLASS (class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (TrashMonitorClass, item_count_changed),
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
-}
+ g_object_unref (enumerator);
+ }
+ else
+ {
+ static gboolean showed_warning;
+
+ if (!showed_warning)
+ {
+ g_warning ("could not obtain enumerator for trash:///: %s",
+ error->message);
+ showed_warning = TRUE;
+ }
-static void
-trash_monitor_init (TrashMonitor *monitor)
-{
- GnomeVFSVolumeMonitor *volume_monitor;
- GList *volumes, *tmp;
+ g_error_free (error);
- monitor->volumes = g_hash_table_new (NULL, NULL);
- monitor->total_item_count = 0;
- monitor->notify_id = 0;
-
- volume_monitor = gnome_vfs_get_volume_monitor ();
-
- g_signal_connect_object (volume_monitor, "volume_mounted",
- G_CALLBACK (volume_mounted_callback),
- monitor, 0);
- g_signal_connect_object (volume_monitor, "volume_pre_unmount",
- G_CALLBACK (volume_unmount_started_callback),
- monitor, 0);
-
- volumes = gnome_vfs_volume_monitor_get_mounted_volumes (volume_monitor);
- for (tmp = volumes; tmp != NULL; tmp = tmp->next) {
- GnomeVFSVolume *volume = tmp->data;
+ /* can't even open the trash directory. assume empty. */
+ empty = TRUE;
+ }
- add_volume (monitor, volume);
- gnome_vfs_volume_unref (volume);
- }
- g_list_free (volumes);
+ if (empty != monitor->empty)
+ {
+ monitor->empty = empty;
+ g_object_notify (G_OBJECT (monitor), "empty");
+ }
}
-TrashMonitor *
-trash_monitor_get (void)
+static gboolean
+trash_monitor_idle_check_empty (gpointer user_data)
{
- static TrashMonitor *monitor;
+ TrashMonitor *monitor = user_data;
- if (!monitor) {
- monitor = g_object_new (TRASH_TYPE_MONITOR, NULL);
- }
- return monitor;
-}
+ trash_monitor_check_empty (monitor);
+ monitor->empty_check_id = 0;
-static void
-volume_mounted_callback (GnomeVFSVolumeMonitor *volume_monitor,
- GnomeVFSVolume *volume,
- TrashMonitor *monitor)
-{
- add_volume (monitor, volume);
+ return FALSE;
}
-static void
-volume_unmount_started_callback (GnomeVFSVolumeMonitor *volume_monitor,
- GnomeVFSVolume *volume,
- TrashMonitor *monitor)
+static int
+trash_monitor_count_items (TrashMonitor *monitor)
{
- remove_volume (monitor, volume);
-}
-
-static void
-trash_dir_changed (GnomeVFSMonitorHandle *handle,
- const gchar *monitor_uri,
- const gchar *info_uri,
- GnomeVFSMonitorEventType type,
- gpointer user_data)
-{
- VolumeInfo *volinfo;
- GnomeVFSResult res;
- GList *dirlist, *tmp;
- gint count = 0;
-
- volinfo = user_data;
-
- res = gnome_vfs_directory_list_load (&dirlist, volinfo->trash_uri,
- GNOME_VFS_FILE_INFO_FOLLOW_LINKS);
- if (res != GNOME_VFS_OK) {
- g_warning("GNOME VFS Error: %s", gnome_vfs_result_to_string (res));
- return;
- }
+ GFileEnumerator *enumerator;
+ GError *error = NULL;
+ GFileInfo *info;
+ int total;
+
+ if (monitor->counted_items_valid)
+ return monitor->counted_items;
+
+ if (monitor->empty)
+ {
+ monitor->counted_items = 0;
+ return 0;
+ }
- for (tmp = dirlist; tmp != NULL; tmp = tmp->next) {
- GnomeVFSFileInfo *info = tmp->data;
+ enumerator = g_file_enumerate_children (monitor->trash, "",
+ G_FILE_QUERY_INFO_NONE, NULL, NULL);
- if (!strcmp (info->name, ".") || !strcmp (info->name, ".."))
- continue;
- count++;
- }
- gnome_vfs_file_info_list_free (dirlist);
-
- if (count != volinfo->item_count) {
- volinfo->item_count = count;
- trash_changed_queue_notify (volinfo->monitor);
- }
-}
+ if (enumerator == NULL)
+ /* the empty-check will have already thrown a g_warning for this */
+ return 0;
+
+ total = 0;
+ while ((info = g_file_enumerator_next_file (enumerator, NULL, NULL)))
+ {
+ g_object_unref (info);
+ total++;
+ }
-static void
-find_directory_callback (GnomeVFSAsyncHandle *handle,
- GList *results,
- gpointer callback_data)
-{
- VolumeInfo *volinfo;
- GnomeVFSFindDirectoryResult *result;
- GnomeVFSResult res;
-
- volinfo = callback_data;
-
- /* we are done finding the volume */
- volinfo->find_handle = NULL;
-
- /* If we can't find the trash, ignore it silently. */
- result = results->data;
- if (result->result != GNOME_VFS_OK)
- return;
+ if (error)
+ {
+ static gboolean showed_warning;
+
+ if (!showed_warning)
+ {
+ g_warning ("error while enumerating trash:///: %s\n",
+ error->message);
+ showed_warning = TRUE;
+ }
- volinfo->trash_uri = gnome_vfs_uri_to_string (result->uri,
- GNOME_VFS_URI_HIDE_NONE);
- /* g_message ("found trash dir: %s", volinfo->trash_uri); */
-
- /* simulate a change to update the directory count */
- trash_dir_changed (NULL, NULL, NULL, GNOME_VFS_MONITOR_EVENT_CHANGED,
- volinfo);
-
- res = gnome_vfs_monitor_add (&volinfo->trash_change_monitor,
- volinfo->trash_uri, GNOME_VFS_MONITOR_DIRECTORY,
- trash_dir_changed,
- volinfo);
-
- if (res != GNOME_VFS_OK) {
- g_warning("GNOME VFS Error: %s", gnome_vfs_result_to_string (res));
- volinfo->trash_change_monitor = NULL;
- }
-}
+ g_error_free (error);
+ }
+ else
+ {
+ monitor->counted_items_valid = TRUE;
+ monitor->counted_items = total;
+ }
-static gboolean
-get_trash_volume (TrashMonitor *monitor,
- GnomeVFSVolume *volume,
- VolumeInfo **volinfo,
- GnomeVFSURI **mount_uri)
-{
- char *uri_str;
-
- *volinfo = g_hash_table_lookup (monitor->volumes, volume);
-
- if (*volinfo != NULL && (*volinfo)->trash_uri != NULL)
- return FALSE;
-
- if (!gnome_vfs_volume_handles_trash (volume))
- return FALSE;
-
- uri_str = gnome_vfs_volume_get_activation_uri (volume);
- *mount_uri = gnome_vfs_uri_new (uri_str);
- g_free (uri_str);
-
- if (*volinfo == NULL) {
- *volinfo = g_new0 (VolumeInfo, 1);
- (*volinfo)->monitor = monitor;
- (*volinfo)->volume = gnome_vfs_volume_ref (volume);
- g_hash_table_insert (monitor->volumes, volume, *volinfo);
- }
+ g_object_unref (enumerator);
- return TRUE;
+ return total;
}
static void
-add_volume (TrashMonitor *monitor, GnomeVFSVolume *volume)
+trash_monitor_changed (GFileMonitor *file_monitor,
+ GFile *child,
+ GFile *other_file,
+ GFileMonitorEvent event_type,
+ gpointer user_data)
{
- VolumeInfo *volinfo;
- GnomeVFSURI *mount_uri;
- GList vfs_uri_as_list;
-
- if (!get_trash_volume (monitor, volume, &volinfo, &mount_uri))
- return;
-
- if (volinfo->find_handle) {
- /* already searchinf for trash */
- gnome_vfs_uri_unref (mount_uri);
- return;
- }
+ TrashMonitor *monitor = user_data;
-
- vfs_uri_as_list.data = mount_uri;
- vfs_uri_as_list.next = NULL;
- vfs_uri_as_list.prev = NULL;
-
- gnome_vfs_async_find_directory (&volinfo->find_handle, &vfs_uri_as_list,
- GNOME_VFS_DIRECTORY_KIND_TRASH,
- FALSE, TRUE, 0777,
- GNOME_VFS_PRIORITY_DEFAULT,
- find_directory_callback, volinfo);
- gnome_vfs_uri_unref (mount_uri);
+ switch (event_type)
+ {
+ case G_FILE_MONITOR_EVENT_DELETED:
+ /* wait until 0.1s after the last delete event before checking.
+ * this prevents us from re-checking for every delete event while
+ * emptying the trash.
+ */
+ if (monitor->empty_check_id)
+ g_source_remove (monitor->empty_check_id);
+
+ monitor->empty_check_id = g_timeout_add (100,
+ trash_monitor_idle_check_empty,
+ monitor);
+ break;
+
+ case G_FILE_MONITOR_EVENT_CREATED:
+ if (monitor->empty)
+ {
+ /* not any more... */
+ monitor->empty = FALSE;
+ g_object_notify (G_OBJECT (monitor), "empty");
+ }
+ break;
+
+ default:
+ return;
+ }
+
+ if (monitor->counted_items_valid)
+ {
+ monitor->counted_items_valid = FALSE;
+ g_object_notify (G_OBJECT (monitor), "items");
+ }
}
static void
-remove_volume (TrashMonitor *monitor, GnomeVFSVolume *volume)
+trash_monitor_get_property (GObject *object, guint prop_id,
+ GValue *value, GParamSpec *pspec)
{
- VolumeInfo *volinfo;
+ TrashMonitor *monitor = TRASH_MONITOR (object);
- volinfo = g_hash_table_lookup (monitor->volumes, volume);
- if (volinfo != NULL) {
- g_hash_table_remove (monitor->volumes, volume);
-
- /* g_message ("removing volume %s", volinfo->trash_uri); */
- if (volinfo->find_handle != NULL)
- gnome_vfs_async_cancel (volinfo->find_handle);
- if (volinfo->trash_change_monitor != NULL)
- gnome_vfs_monitor_cancel (volinfo->trash_change_monitor);
-
- if (volinfo->trash_uri)
- g_free (volinfo->trash_uri);
-
- /* if this volume contained some trash, then notify that the trash
- * state has changed */
- if (volinfo->item_count != 0)
- trash_changed_queue_notify (monitor);
+ switch (prop_id)
+ {
+ case PROP_EMPTY:
+ g_value_set_boolean (value, monitor->empty);
+ break;
+
+ case PROP_ITEMS:
+ g_value_set_int (value, trash_monitor_count_items (monitor));
+ break;
- gnome_vfs_volume_unref (volinfo->volume);
- g_free (volinfo);
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
-/* --- */
-
static void
-readd_volumes (gpointer key, gpointer value, gpointer user_data)
-{
- TrashMonitor *monitor = user_data;
- GnomeVFSVolume *volume;
-
- volume = key;
- add_volume (monitor, volume);
-}
-void
-trash_monitor_recheck_trash_dirs (TrashMonitor *monitor)
+trash_monitor_class_init (TrashMonitorClass *class)
{
- /* call add_volume() on each volume, to add trash dirs where missing */
- g_hash_table_foreach (monitor->volumes, readd_volumes, monitor);
-}
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
-/* --- */
+ object_class->get_property = trash_monitor_get_property;
-void
-trash_monitor_empty_trash (TrashMonitor *monitor,
- GnomeVFSAsyncHandle **handle,
- GnomeVFSAsyncXferProgressCallback func,
- gpointer user_data)
-{
- GList *trash_dirs = NULL, *volumes, *tmp;
- GnomeVFSVolume *volume;
- GnomeVFSURI *mount_uri, *trash_uri;
- gchar *uri_str;
-
- /* collect the trash directories */
- volumes = gnome_vfs_volume_monitor_get_mounted_volumes (gnome_vfs_get_volume_monitor ());
- for (tmp = volumes; tmp != NULL; tmp = tmp->next) {
- volume = tmp->data;
- if (gnome_vfs_volume_handles_trash (volume)) {
- /* get the mount point for this volume */
- uri_str = gnome_vfs_volume_get_activation_uri (volume);
- mount_uri = gnome_vfs_uri_new (uri_str);
- g_free (uri_str);
-
- g_assert (mount_uri != NULL);
-
- /* Look for the trash directory. Since we tell it not to create or
- * look for the dir, it doesn't block. */
- if (gnome_vfs_find_directory (mount_uri,
- GNOME_VFS_DIRECTORY_KIND_TRASH, &trash_uri,
- FALSE, FALSE, 0777) == GNOME_VFS_OK) {
- trash_dirs = g_list_prepend (trash_dirs, trash_uri);
- }
- gnome_vfs_uri_unref (mount_uri);
- }
- gnome_vfs_volume_unref (volume);
- }
- g_list_free (volumes);
-
- if (trash_dirs != NULL)
- gnome_vfs_async_xfer (handle, trash_dirs, NULL,
- GNOME_VFS_XFER_EMPTY_DIRECTORIES,
- GNOME_VFS_XFER_ERROR_MODE_ABORT,
- GNOME_VFS_XFER_OVERWRITE_MODE_REPLACE,
- GNOME_VFS_PRIORITY_DEFAULT,
- func, user_data, NULL, NULL);
- gnome_vfs_uri_list_free (trash_dirs);
+ g_object_class_install_property (object_class, PROP_EMPTY,
+ g_param_spec_boolean ("empty",
+ "trash is empty",
+ "true if the trash is empty",
+ TRUE,
+ G_PARAM_READABLE));
+
+ g_object_class_install_property (object_class, PROP_ITEMS,
+ g_param_spec_int ("items",
+ "item count",
+ "the number of items in the trash",
+ 0, G_MAXINT, 0,
+ G_PARAM_READABLE));
}
-
-/* --- */
-
static void
-count_items (gpointer key, gpointer value, gpointer user_data)
+trash_monitor_init (TrashMonitor *monitor)
{
- VolumeInfo *volinfo;
- gint *item_count;
+ GError *error;
+
+ monitor->trash = g_file_new_for_uri ("trash:///");
+ monitor->file_monitor = g_file_monitor_directory (monitor->trash, 0,
+ NULL, &error);
+
+ if (monitor->file_monitor == NULL)
+ {
+ g_warning ("failed to register watch on trash:///: %s", error->message);
+ g_error_free (error);
+ }
+
+ trash_monitor_check_empty (monitor);
- volinfo = value;
- item_count = user_data;
- *item_count += volinfo->item_count;
+ g_signal_connect_object (monitor->file_monitor, "changed",
+ G_CALLBACK (trash_monitor_changed), monitor, 0);
}
-static gboolean
-trash_changed_notify (gpointer user_data)
+TrashMonitor *
+trash_monitor_new (void)
{
- TrashMonitor *monitor = user_data;
- gint item_count;
-
- /* reset notification id */
- monitor->notify_id = 0;
+ static TrashMonitor *monitor;
- /* count the volumes */
- item_count = 0;
- g_hash_table_foreach (monitor->volumes, count_items, &item_count);
-
- /* if the item count has changed ... */
- if (item_count != monitor->total_item_count) {
- monitor->total_item_count = item_count;
- /* g_message ("item count is %d", item_count); */
- g_signal_emit (monitor, signals[ITEM_COUNT_CHANGED], 0);
- }
+ if (!monitor)
+ monitor = g_object_new (TRASH_TYPE_MONITOR, NULL);
- return FALSE;
+ return g_object_ref (monitor);
}
+/*
+ * if @file is a directory, delete its contents (but not @file itself).
+ * if @file is not a directory, do nothing.
+ */
static void
-trash_changed_queue_notify (TrashMonitor *monitor)
+trash_monitor_delete_contents (GFile *file,
+ GCancellable *cancellable)
{
- /* already queued */
- if (monitor->notify_id != 0)
+ GFileEnumerator *enumerator;
+ GFileInfo *info;
+ GFile *child;
+
+ if (g_cancellable_is_cancelled (cancellable))
return;
- monitor->notify_id = g_idle_add (trash_changed_notify, monitor);
-}
+ enumerator = g_file_enumerate_children (file,
+ G_FILE_ATTRIBUTE_STANDARD_NAME,
+ G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
+ cancellable, NULL);
+ if (enumerator)
+ {
+ while ((info = g_file_enumerator_next_file (enumerator,
+ cancellable, NULL)) != NULL)
+ {
+ child = g_file_get_child (file, g_file_info_get_name (info));
+
+ /* it's just as fast to assume that all entries are subdirectories
+ * and try to erase their contents as it is to actually do the
+ * extra stat() call up front...
+ */
+ trash_monitor_delete_contents (child, cancellable);
+
+ g_file_delete (child, cancellable, NULL);
+
+ g_object_unref (child);
+ g_object_unref (info);
+
+ if (g_cancellable_is_cancelled (cancellable))
+ break;
+ }
-int
-trash_monitor_get_item_count (TrashMonitor *monitor)
-{
- return monitor->total_item_count;
+ g_object_unref (enumerator);
+ }
}
-/* --- */
-
-#ifdef TEST_TRASH_MONITOR
-int
-main (int argc, char **argv)
+static gboolean
+trash_monitor_empty_job (GIOSchedulerJob *job,
+ GCancellable *cancellable,
+ gpointer user_data)
{
- TrashMonitor *monitor;
-
- if (!gnome_vfs_init ()) {
- g_printerr ("Can not initialise gnome-vfs.\n");
- return 1;
- }
+ TrashMonitor *monitor = user_data;
- monitor = trash_monitor_get ();
+ trash_monitor_delete_contents (monitor->trash, cancellable);
- g_main_loop_run (g_main_loop_new (NULL, FALSE));
+ return FALSE;
+}
- return 0;
+void
+trash_monitor_empty_trash (TrashMonitor *monitor,
+ GCancellable *cancellable,
+ gpointer func,
+ gpointer user_data)
+{
+ g_io_scheduler_push_job (trash_monitor_empty_job,
+ monitor, NULL, 0, cancellable);
}
-#endif
Modified: trunk/trashapplet/src/trash-monitor.h
==============================================================================
--- trunk/trashapplet/src/trash-monitor.h (original)
+++ trunk/trashapplet/src/trash-monitor.h Wed Feb 13 01:04:10 2008
@@ -1,8 +1,7 @@
/*
* trash-monitor.h: monitor the state of the trash directories.
*
- * Copyright (C) 1999, 2000 Eazel, Inc.
- * Copyright (C) 2004 Canonical Ltd.
+ * Copyright  2008 Ryan Lortie, Matthias Clasen
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@@ -23,27 +22,21 @@
#ifndef __TRASH_MONITOR_H__
#define __TRASH_MONITOR_H__
-#include <libgnomevfs/gnome-vfs.h>
+#include <gio/gio.h>
typedef struct _TrashMonitor TrashMonitor;
typedef struct _TrashMonitorClass TrashMonitorClass;
-#define TRASH_TYPE_MONITOR (trash_monitor_get_type ())
-#define TRASH_MONITOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TRASH_TYPE_MONITOR, TrashMonitor))
-#define TRASH_MONITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TRASH_TYPE_MONITOR, TrashMonitorClass))
-#define TRASH_IS_MONITOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TRASH_TYPE_MONITOR))
-#define TRASH_IS_MONITOR_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE ((obj), TRASH_TYPE_MONITOR))
-#define TRASH_MONITOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TRASH_TYPE_MONITOR, TrashMonitorClass))
-
-GType trash_monitor_get_type (void);
-TrashMonitor *trash_monitor_get (void);
-
-/* check if new trash dirs have been created */
-void trash_monitor_recheck_trash_dirs (TrashMonitor *monitor);
-void trash_monitor_empty_trash (TrashMonitor *monitor,
- GnomeVFSAsyncHandle **handle,
- GnomeVFSAsyncXferProgressCallback func,
- gpointer user_data);
-int trash_monitor_get_item_count (TrashMonitor *monitor);
+#define TRASH_TYPE_MONITOR (trash_monitor_get_type ())
+#define TRASH_MONITOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+ TRASH_TYPE_MONITOR, TrashMonitor))
+
+GType trash_monitor_get_type (void);
+TrashMonitor *trash_monitor_new (void);
+
+void trash_monitor_empty_trash (TrashMonitor *monitor,
+ GCancellable *cancellable,
+ gpointer func,
+ gpointer user_data);
#endif
Modified: trunk/trashapplet/src/trashapplet.c
==============================================================================
--- trunk/trashapplet/src/trashapplet.c (original)
+++ trunk/trashapplet/src/trashapplet.c Wed Feb 13 01:04:10 2008
@@ -3,6 +3,8 @@
*
* Copyright (c) 2004 Michiel Sikkes <michiel eyesopened nl>,
* 2004 Emmanuele Bassi <ebassi gmail com>
+ * 2008 Ryan Lortie <desrt desrt ca>
+ * Matthias Clasen <mclasen redhat com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@@ -31,6 +33,7 @@
#include <gconf/gconf-client.h>
#include <libgnome/gnome-help.h>
#include <glade/glade.h>
+#include <gio/gio.h>
#include "trashapplet.h"
#include "trash-monitor.h"
@@ -98,33 +101,66 @@
};
static void trash_applet_queue_update (TrashApplet *applet);
-static void item_count_changed (TrashMonitor *monitor,
- TrashApplet *applet);
+static void empty_changed (GObject *monitor,
+ GParamSpec *pspace,
+ gpointer user_data);
+
+static gboolean
+trash_applet_query_tooltip (GtkWidget *widget,
+ gint x,
+ gint y,
+ gboolean keyboard_tip,
+ GtkTooltip *tooltip)
+{
+ TrashApplet *applet = TRASH_APPLET (widget);
+ gint items;
+
+ g_object_get (applet->monitor, "items", &items, NULL);
+
+ if (items)
+ {
+ char *text;
+
+ text = g_strdup_printf (ngettext ("%d Item in Trash",
+ "%d Items in Trash",
+ items), items);
+ gtk_tooltip_set_text (tooltip, text);
+ g_free (text);
+ }
+ else
+ gtk_tooltip_set_text (tooltip, _("No Items in Trash"));
+
+ return TRUE;
+}
static void
trash_applet_class_init (TrashAppletClass *class)
{
- GTK_OBJECT_CLASS (class)->destroy = trash_applet_destroy;
- GTK_WIDGET_CLASS (class)->size_allocate = trash_applet_size_allocate;
- GTK_WIDGET_CLASS (class)->button_release_event = trash_applet_button_release;
- GTK_WIDGET_CLASS (class)->key_press_event = trash_applet_key_press;
- GTK_WIDGET_CLASS (class)->drag_leave = trash_applet_drag_leave;
- GTK_WIDGET_CLASS (class)->drag_motion = trash_applet_drag_motion;
- GTK_WIDGET_CLASS (class)->drag_data_received = trash_applet_drag_data_received;
- PANEL_APPLET_CLASS (class)->change_orient = trash_applet_change_orient;
- PANEL_APPLET_CLASS (class)->change_background = trash_applet_change_background;
+ PanelAppletClass *applet_class = PANEL_APPLET_CLASS (class);
+ GtkObjectClass *gtkobject_class = GTK_OBJECT_CLASS (class);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
+
+ gtkobject_class->destroy = trash_applet_destroy;
+ widget_class->size_allocate = trash_applet_size_allocate;
+ widget_class->button_release_event = trash_applet_button_release;
+ widget_class->key_press_event = trash_applet_key_press;
+ widget_class->drag_leave = trash_applet_drag_leave;
+ widget_class->drag_motion = trash_applet_drag_motion;
+ widget_class->drag_data_received = trash_applet_drag_data_received;
+ widget_class->query_tooltip = trash_applet_query_tooltip;
+ applet_class->change_orient = trash_applet_change_orient;
+ applet_class->change_background = trash_applet_change_background;
}
static void
trash_applet_init (TrashApplet *applet)
{
- GnomeVFSResult res;
- GnomeVFSURI *trash_uri;
-
gtk_window_set_default_icon_name (TRASH_ICON_FULL);
panel_applet_set_flags (PANEL_APPLET (applet),
PANEL_APPLET_EXPAND_MINOR);
+ gtk_widget_set_has_tooltip (GTK_WIDGET (applet), TRUE);
+
/* get the default gconf client */
if (!client)
client = gconf_client_get_default ();
@@ -148,28 +184,13 @@
gtk_widget_show (applet->image);
applet->icon_state = TRASH_STATE_UNKNOWN;
- /* create local trash directory if needed */
- res = gnome_vfs_find_directory (NULL,
- GNOME_VFS_DIRECTORY_KIND_TRASH,
- &trash_uri,
- TRUE,
- TRUE,
- 0700);
- if (trash_uri)
- gnome_vfs_uri_unref (trash_uri);
- if (res != GNOME_VFS_OK) {
- g_warning (_("Unable to find the Trash directory: %s"),
- gnome_vfs_result_to_string (res));
- }
-
/* set up trash monitor */
- applet->monitor = trash_monitor_get ();
+ applet->monitor = trash_monitor_new ();
applet->monitor_signal_id =
- g_signal_connect (applet->monitor, "item_count_changed",
- G_CALLBACK (item_count_changed), applet);
+ g_signal_connect (applet->monitor, "notify::empty",
+ G_CALLBACK (empty_changed), applet);
/* initial state */
- applet->item_count = -1;
applet->is_empty = TRUE;
applet->drag_hover = FALSE;
@@ -197,6 +218,8 @@
applet->monitor_signal_id);
applet->monitor_signal_id = 0;
+ g_object_unref (applet->monitor);
+
if (applet->update_id)
g_source_remove (applet->update_id);
applet->update_id = 0;
@@ -239,6 +262,7 @@
break;
case PANEL_APPLET_ORIENT_UP:
case PANEL_APPLET_ORIENT_DOWN:
+ default:
applet->orient = GTK_ORIENTATION_HORIZONTAL;
new_size = GTK_WIDGET (applet)->allocation.height;
break;
@@ -360,17 +384,17 @@
}
static void
-item_count_changed (TrashMonitor *monitor,
- TrashApplet *applet)
+empty_changed (GObject *monitor,
+ GParamSpec *pspac,
+ gpointer user_data)
{
- trash_applet_queue_update (applet);
+ trash_applet_queue_update (TRASH_APPLET (user_data));
}
static gboolean
trash_applet_update (gpointer user_data)
{
TrashApplet *applet = TRASH_APPLET (user_data);
- gint new_item_count;
BonoboUIComponent *popup_component;
char *tip_text;
TrashState new_state = TRASH_STATE_UNKNOWN;
@@ -378,13 +402,14 @@
GdkScreen *screen;
GtkIconTheme *icon_theme;
GdkPixbuf *pixbuf, *scaled;
+ gboolean is_empty;
applet->update_id = 0;
- new_item_count = trash_monitor_get_item_count (applet->monitor);
- if (new_item_count != applet->item_count) {
- applet->item_count = new_item_count;
- applet->is_empty = (applet->item_count == 0);
+ g_object_get (applet->monitor, "empty", &is_empty, NULL);
+ if (is_empty != applet->is_empty)
+ {
+ applet->is_empty = is_empty;
/* set sensitivity on the "empty trash" context menu item */
popup_component = panel_applet_get_popup_component (PANEL_APPLET (applet));
@@ -393,20 +418,6 @@
"sensitive",
applet->is_empty ? "0" : "1",
NULL);
-
- switch (applet->item_count) {
- case 0:
- tip_text = g_strdup (_("No Items in Trash"));
- break;
- default:
- tip_text = g_strdup_printf (ngettext (
- "%d Item in Trash",
- "%d Items in Trash",
- applet->item_count),
- applet->item_count);
- }
- gtk_widget_set_tooltip_text (GTK_WIDGET (applet), tip_text);
- g_free (tip_text);
}
/* work out what icon to use */
@@ -503,65 +514,6 @@
g_free (error_string);
}
-static gint
-update_transfer_callback (GnomeVFSAsyncHandle *handle,
- GnomeVFSXferProgressInfo *progress_info,
- gpointer user_data)
-{
- TrashApplet *applet = TRASH_APPLET (user_data);
- GladeXML *xml = applet->xml;
-
- if (progress_info->files_total != 0) {
- GtkWidget *progressbar;
- gdouble fraction;
- gchar *progress_message;
-
- progressbar = glade_xml_get_widget (xml, "progressbar");
-
- fraction = (gulong) progress_info->file_index / (gulong) progress_info->files_total;
- gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (progressbar), fraction);
-
- progress_message = g_strdup_printf (_("Removing item %d of %d"),
- progress_info->file_index,
- progress_info->files_total);
- gtk_progress_bar_set_text (GTK_PROGRESS_BAR (progressbar),
- progress_message);
-
- g_free (progress_message);
- }
-
- if (progress_info->source_name != NULL) {
- GtkWidget *location_label;
- GtkWidget *file_label;
- GnomeVFSURI *uri;
- gchar *short_name;
- gchar *from_location;
- gchar *file;
-
- location_label = glade_xml_get_widget (xml, "location_label");
- file_label = glade_xml_get_widget (xml, "file_label");
-
- uri = gnome_vfs_uri_new (progress_info->source_name);
-
- from_location = gnome_vfs_uri_extract_dirname (uri);
-
- short_name = gnome_vfs_uri_extract_short_name (uri);
- file = g_strdup_printf ("<i>%s %s</i>",
- _("Removing:"),
- short_name);
- g_free (short_name);
-
- gtk_label_set_markup (GTK_LABEL (location_label), from_location);
- gtk_label_set_markup (GTK_LABEL (file_label), file);
-
- g_free (from_location);
- g_free (file);
- gnome_vfs_uri_unref (uri);
- }
-
- return 1;
-}
-
/* this function is based on the one with the same name in
libnautilus-private/nautilus-file-operations.c */
#define NAUTILUS_PREFERENCES_CONFIRM_TRASH "/apps/nautilus/preferences/confirm_trash"
@@ -627,13 +579,11 @@
}
static void
-on_empty_trash_cancel (GtkWidget *widget, GnomeVFSAsyncHandle **handle)
+on_empty_trash_cancel (GtkWidget *widget,
+ GCancellable *cancellable)
{
- if (handle != NULL) {
- gnome_vfs_async_cancel ((GnomeVFSAsyncHandle *) handle);
- }
-
- gtk_widget_hide (widget);
+ g_cancellable_cancel (cancellable);
+ gtk_widget_hide (widget);
}
static void
@@ -643,7 +593,7 @@
{
GtkWidget *dialog;
- GnomeVFSAsyncHandle *hnd;
+ GCancellable *cancellable;
g_return_if_fail (TRASH_IS_APPLET (applet));
@@ -656,16 +606,17 @@
if (!applet->xml)
applet->xml = glade_xml_new (GNOME_GLADEDIR "/trashapplet.glade", NULL, NULL);
- dialog = glade_xml_get_widget(applet->xml, "empty_trash");
+ dialog = glade_xml_get_widget (applet->xml, "empty_trash");
- g_signal_connect(dialog, "response", G_CALLBACK (on_empty_trash_cancel), &hnd);
+ cancellable = g_cancellable_new ();
+ g_signal_connect (dialog, "response", G_CALLBACK (on_empty_trash_cancel), cancellable);
- gtk_widget_show_all(dialog);
+ gtk_widget_show_all (dialog);
trash_monitor_empty_trash (applet->monitor,
- &hnd, update_transfer_callback, applet);
+ cancellable, NULL, applet);
- gtk_widget_hide(dialog);
+ gtk_widget_hide (dialog);
}
@@ -846,80 +797,50 @@
guint time_)
{
TrashApplet *applet = TRASH_APPLET (widget);
- GList *list, *scan;
- GList *source_uri_list, *target_uri_list, *unmovable_uri_list;
- GnomeVFSResult result;
-
- list = gnome_vfs_uri_list_parse ((gchar *)selectiondata->data);
-
- source_uri_list = NULL;
- target_uri_list = NULL;
- unmovable_uri_list = NULL;
- for (scan = g_list_first (list); scan; scan = g_list_next (scan)) {
- GnomeVFSURI *source_uri = scan->data;
- GnomeVFSURI *trash_uri, *target_uri;
- gchar *source_basename;
-
- /* find the trash directory for this file */
- result = gnome_vfs_find_directory (source_uri,
- GNOME_VFS_DIRECTORY_KIND_TRASH,
- &trash_uri, TRUE, FALSE, 0);
- if (result != GNOME_VFS_OK) {
- unmovable_uri_list = g_list_prepend (unmovable_uri_list,
- gnome_vfs_uri_ref (source_uri));
- continue;
+ gchar **list;
+ gint i;
+ GList *trashed = NULL;
+ GList *untrashable = NULL;
+ GList *l;
+ GError *error = NULL;
+
+ list = g_uri_list_extract_uris ((gchar *)selectiondata->data);
+
+ for (i = 0; list[i]; i++) {
+ GFile *file;
+
+ file = g_file_new_for_uri (list[i]);
+ if (!g_file_trash (file, NULL, NULL)) {
+ untrashable = g_list_prepend (untrashable, file);
}
-
- source_basename = gnome_vfs_uri_extract_short_name
- (source_uri);
-
- target_uri = gnome_vfs_uri_append_file_name(trash_uri,
- source_basename);
- g_free (source_basename);
- gnome_vfs_uri_unref (trash_uri);
-
- source_uri_list = g_list_prepend (source_uri_list,
- gnome_vfs_uri_ref (source_uri));
- target_uri_list = g_list_prepend (target_uri_list,
- target_uri);
- }
-
- gnome_vfs_uri_list_free(list);
-
- /* we might have added a trash dir, so recheck */
- trash_monitor_recheck_trash_dirs (applet->monitor);
-
- if (source_uri_list) {
- result = gnome_vfs_xfer_uri_list (source_uri_list, target_uri_list,
- GNOME_VFS_XFER_REMOVESOURCE |
- GNOME_VFS_XFER_RECURSIVE,
- GNOME_VFS_XFER_ERROR_MODE_ABORT,
- GNOME_VFS_XFER_OVERWRITE_MODE_REPLACE,
- NULL, NULL);
- gnome_vfs_uri_list_free (source_uri_list);
- gnome_vfs_uri_list_free (target_uri_list);
- if (result != GNOME_VFS_OK) {
- error_dialog (applet, _("Unable to move to trash:\n%s"),
- gnome_vfs_result_to_string (result));
+ else {
+ trashed = g_list_prepend (trashed, file);
}
}
- if (unmovable_uri_list) {
- if (confirm_delete_immediately (widget,
- g_list_length (unmovable_uri_list),
- source_uri_list == NULL)) {
- result = gnome_vfs_xfer_delete_list (unmovable_uri_list,
- GNOME_VFS_XFER_ERROR_MODE_ABORT,
- GNOME_VFS_XFER_RECURSIVE,
- NULL, NULL);
- } else {
- result = GNOME_VFS_OK;
- }
- gnome_vfs_uri_list_free (unmovable_uri_list);
- if (result != GNOME_VFS_OK) {
- error_dialog (applet, _("Unable to move to trash:\n%s"),
- gnome_vfs_result_to_string (result));
+
+ if (untrashable) {
+ if (confirm_delete_immediately (widget,
+ g_list_length (untrashable),
+ trashed == NULL)) {
+ for (l = untrashable; l; l = l->next) {
+ if (!g_file_delete (l->data, NULL, &error)) {
+ error_dialog (applet,
+ _("Unable to delete '%s': %s"),
+ g_file_get_uri (l->data),
+ error->message);
+ g_clear_error (&error);
+ }
+ }
}
}
+
+ g_list_foreach (untrashable, (GFunc)g_object_unref, NULL);
+ g_list_free (untrashable);
+ g_list_foreach (trashed, (GFunc)g_object_unref, NULL);
+ g_list_free (trashed);
+
+ g_strfreev (list);
+
gtk_drag_finish (context, TRUE, FALSE, time_);
}
@@ -951,6 +872,8 @@
int
main (int argc, char *argv [])
{
+ g_thread_init (NULL);
+
/* gettext stuff */
bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
Modified: trunk/trashapplet/src/trashapplet.h
==============================================================================
--- trunk/trashapplet/src/trashapplet.h (original)
+++ trunk/trashapplet/src/trashapplet.h Wed Feb 13 01:04:10 2008
@@ -59,7 +59,6 @@
GtkWidget *image;
TrashState icon_state;
- gint item_count;
gboolean is_empty;
gboolean drag_hover;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]