1934 lines
64 KiB
Diff
1934 lines
64 KiB
Diff
Support desktop items defined by the sysadmin
|
|
|
|
This adds a GConf key /apps/nautilus/desktop/predefined_items_dir which points to
|
|
a directory which holds .desktop files. These files will be shown in the user's desktop.
|
|
|
|
Git repository at http://gitorious.org/projects/nautilus/repos/mainline - branch sysadmin-desktop-items
|
|
|
|
diff --git a/libnautilus-private/apps_nautilus_preferences.schemas.in b/libnautilus-private/apps_nautilus_preferences.schemas.in
|
|
index ca45081..c180132 100644
|
|
--- a/libnautilus-private/apps_nautilus_preferences.schemas.in
|
|
+++ b/libnautilus-private/apps_nautilus_preferences.schemas.in
|
|
@@ -1072,5 +1072,21 @@ most cases, this should be left alone. -->Sans 10</default>
|
|
</locale>
|
|
</schema>
|
|
|
|
+ <schema>
|
|
+ <key>/schemas/apps/nautilus/desktop/predefined_items_dir</key>
|
|
+ <applyto>/apps/nautilus/desktop/predefined_items_dir</applyto>
|
|
+ <owner>nautilus</owner>
|
|
+ <type>string</type>
|
|
+ <locale name="C">
|
|
+ <short>Directory for storing predefined desktop items</short>
|
|
+ <long>
|
|
+ Desktop files (*.desktop) which appear in this directory
|
|
+ will be shown on the user's desktop. System administrators
|
|
+ can use this feature to define desktop shortcuts which
|
|
+ appear for users.
|
|
+ </long>
|
|
+ </locale>
|
|
+ </schema>
|
|
+
|
|
</schemalist>
|
|
</gconfschemafile>
|
|
diff --git a/libnautilus-private/nautilus-debug-log.c b/libnautilus-private/nautilus-debug-log.c
|
|
index f4ce320..ad84b4b 100644
|
|
--- a/libnautilus-private/nautilus-debug-log.c
|
|
+++ b/libnautilus-private/nautilus-debug-log.c
|
|
@@ -222,6 +222,14 @@ nautilus_debug_log_with_uri_list (gboolean is_milestone, const char *domain, con
|
|
const char *format, ...)
|
|
{
|
|
va_list args;
|
|
+ GList node;
|
|
+
|
|
+ if (!uris) {
|
|
+ node.data = "[no files]";
|
|
+ node.prev = NULL;
|
|
+ node.next = NULL;
|
|
+ uris = &node;
|
|
+ }
|
|
|
|
va_start (args, format);
|
|
nautilus_debug_logv (is_milestone, domain, uris, format, args);
|
|
@@ -235,6 +243,7 @@ nautilus_debug_log_with_file_list (gboolean is_milestone, const char *domain, GL
|
|
va_list args;
|
|
GList *uris;
|
|
GList *l;
|
|
+ GList node;
|
|
|
|
uris = NULL;
|
|
|
|
@@ -260,11 +269,20 @@ nautilus_debug_log_with_file_list (gboolean is_milestone, const char *domain, GL
|
|
|
|
uris = g_list_reverse (uris);
|
|
|
|
+ if (!uris) {
|
|
+ node.data = "[no files]";
|
|
+ node.prev = NULL;
|
|
+ node.next = NULL;
|
|
+ uris = &node;
|
|
+ }
|
|
+
|
|
va_start (args, format);
|
|
nautilus_debug_logv (is_milestone, domain, uris, format, args);
|
|
va_end (args);
|
|
|
|
- eel_g_list_free_deep (uris);
|
|
+ if (uris != &node) {
|
|
+ eel_g_list_free_deep (uris);
|
|
+ }
|
|
}
|
|
|
|
gboolean
|
|
diff --git a/libnautilus-private/nautilus-debug-log.h b/libnautilus-private/nautilus-debug-log.h
|
|
index ad0152e..2976a1f 100644
|
|
--- a/libnautilus-private/nautilus-debug-log.h
|
|
+++ b/libnautilus-private/nautilus-debug-log.h
|
|
@@ -27,10 +27,13 @@
|
|
|
|
#include <glib.h>
|
|
|
|
-#define NAUTILUS_DEBUG_LOG_DOMAIN_USER "USER" /* always enabled */
|
|
-#define NAUTILUS_DEBUG_LOG_DOMAIN_ASYNC "async" /* when asynchronous notifications come in */
|
|
-#define NAUTILUS_DEBUG_LOG_DOMAIN_GLOG "GLog" /* used for GLog messages; don't use it yourself */
|
|
-#define NAUTILUS_DEBUG_LOG_DOMAIN_LOCKDOWN "lockdown" /* when things get *not* done due to lockdown */
|
|
+#define NAUTILUS_DEBUG_LOG_DOMAIN_USER "USER" /* always enabled */
|
|
+#define NAUTILUS_DEBUG_LOG_DOMAIN_ASYNC "async" /* when asynchronous notifications come in */
|
|
+#define NAUTILUS_DEBUG_LOG_DOMAIN_GLOG "GLog" /* used for GLog messages; don't use it yourself */
|
|
+#define NAUTILUS_DEBUG_LOG_DOMAIN_LOCKDOWN "lockdown" /* when things get *not* done due to lockdown */
|
|
+#define NAUTILUS_DEBUG_LOG_DOMAIN_DESKTOP_ITEMS "desktop-items" /* used for predefined desktop items (this is useful for sysadmins) */
|
|
+#define NAUTILUS_DEBUG_LOG_DOMAIN_DEBUG_DESKTOP_ITEMS "debug-desktop-items" /* debugging the machinery for predefined desktop items */
|
|
+#define NAUTILUS_DEBUG_LOG_DOMAIN_ICON_POSITIONS "icon-positions" /* debugging where icon positions get loaded/saved */
|
|
|
|
void nautilus_debug_log (gboolean is_milestone, const char *domain, const char *format, ...);
|
|
|
|
diff --git a/libnautilus-private/nautilus-desktop-directory.c b/libnautilus-private/nautilus-desktop-directory.c
|
|
index 0c5333e..f8970ef 100644
|
|
--- a/libnautilus-private/nautilus-desktop-directory.c
|
|
+++ b/libnautilus-private/nautilus-desktop-directory.c
|
|
@@ -24,34 +24,83 @@
|
|
Author: Alexander Larsson <alexl@redhat.com>
|
|
*/
|
|
|
|
+/* Note that we use two debug domains here:
|
|
+ * NAUTILUS_DEBUG_LOG_DOMAIN_DESKTOP_ITEMS - "desktop-items"
|
|
+ * NAUTILUS_DEBUG_LOG_DOMAIN_DEBUG_DESKTOP_ITEMS - "debug-desktop-items"
|
|
+ *
|
|
+ * The first one is logged as a milestone during initialization, and is actually useful to the sysadmin if he wants to
|
|
+ * debug his predefined desktop items: the log will contain info on which items are defined to be mandatory or not.
|
|
+ *
|
|
+ * The second one is internal to Nautilus, and is used for debugging purposes only (it traces the code flow among the
|
|
+ * interesting parts of this source file).
|
|
+ */
|
|
+
|
|
#include <config.h>
|
|
#include "nautilus-desktop-directory.h"
|
|
|
|
+#include "nautilus-debug-log.h"
|
|
#include "nautilus-directory-private.h"
|
|
#include "nautilus-file.h"
|
|
#include "nautilus-file-private.h"
|
|
#include "nautilus-file-utilities.h"
|
|
#include "nautilus-global-preferences.h"
|
|
#include <eel/eel-glib-extensions.h>
|
|
+#include <glib/gi18n.h>
|
|
#include <gtk/gtk.h>
|
|
+#include <libgnome/gnome-desktop-item.h>
|
|
#include <libgnome/gnome-macros.h>
|
|
|
|
struct NautilusDesktopDirectoryDetails {
|
|
NautilusDirectory *real_directory;
|
|
+ NautilusDirectory *predefined_items_dir;
|
|
GHashTable *callbacks;
|
|
GHashTable *monitors;
|
|
+
|
|
+ /* We store the "combined" files from the real_directory and the
|
|
+ * predefined_items_dir in the name_to_pairs_hash table.
|
|
+ *
|
|
+ * The hash table maps strings (file names) to FilePair structs. The
|
|
+ * strings live in the "name" field of those structs, to make memory
|
|
+ * management easier (i.e. the keys in the hash table need not to be
|
|
+ * memory-managed separately).
|
|
+ *
|
|
+ * We use the hash to answer the question, "do we already have a file
|
|
+ * with this name?", as the predefined items override the user's items
|
|
+ * (or vice-versa) based on matching filenames.
|
|
+ *
|
|
+ * The file_to_pairs_hash answers the question, "do we have a pair
|
|
+ * (which one?) for the specified file?".
|
|
+ *
|
|
+ * Within a FilePair in name_to_pairs_hash, both files are ref'ed.
|
|
+ *
|
|
+ * Within file_to_pairs_hash, the "key" file is *NOT* ref'ed, since it
|
|
+ * is already ref'ed by a corresponding FilePair.
|
|
+ */
|
|
+ GHashTable *name_to_pairs_hash;
|
|
+ GHashTable *file_to_pairs_hash;
|
|
+
|
|
+ eel_boolean_bit files_are_combined : 1;
|
|
+ eel_boolean_bit initializing : 1;
|
|
+ eel_boolean_bit real_directory_pending : 1;
|
|
+ eel_boolean_bit predefined_items_dir_pending : 1;
|
|
};
|
|
|
|
+/* Structs of this type are stored in NautilusDesktopDirectory->name_to_pairs_hash */
|
|
+typedef struct {
|
|
+ char *name;
|
|
+
|
|
+ NautilusFile *user_file;
|
|
+ NautilusFile *predefined_file;
|
|
+
|
|
+ gboolean predefined_overrides_user;
|
|
+} FilePair;
|
|
+
|
|
typedef struct {
|
|
NautilusDesktopDirectory *desktop_dir;
|
|
NautilusDirectoryCallback callback;
|
|
gpointer callback_data;
|
|
|
|
- NautilusFileAttributes wait_for_attributes;
|
|
- gboolean wait_for_file_list;
|
|
-
|
|
GList *non_ready_directories;
|
|
- GList *merged_file_list;
|
|
} MergedCallback;
|
|
|
|
|
|
@@ -64,24 +113,50 @@ typedef struct {
|
|
} MergedMonitor;
|
|
|
|
static void desktop_directory_changed_callback (gpointer data);
|
|
+static GList *desktop_get_file_list (NautilusDirectory *directory);
|
|
+
|
|
+static gboolean directories_are_done_loading (NautilusDesktopDirectory *directory);
|
|
+static void predefined_items_dir_changed_callback (gpointer data);
|
|
+
|
|
+static void forward_files_changed_cover (NautilusDirectory *directory, GList *files, gpointer callback_data);
|
|
|
|
GNOME_CLASS_BOILERPLATE (NautilusDesktopDirectory, nautilus_desktop_directory,
|
|
NautilusDirectory, NAUTILUS_TYPE_DIRECTORY)
|
|
|
|
+static gboolean
|
|
+pair_shows_file (FilePair *pair, NautilusFile *file)
|
|
+{
|
|
+ return ((file == pair->user_file && !pair->predefined_overrides_user)
|
|
+ || (file == pair->predefined_file && pair->predefined_overrides_user));
|
|
+}
|
|
|
|
static gboolean
|
|
desktop_contains_file (NautilusDirectory *directory,
|
|
NautilusFile *file)
|
|
{
|
|
NautilusDesktopDirectory *desktop;
|
|
+ FilePair *pair;
|
|
+ gboolean result;
|
|
+ char *uri;
|
|
|
|
desktop = NAUTILUS_DESKTOP_DIRECTORY (directory);
|
|
|
|
- if (nautilus_directory_contains_file (desktop->details->real_directory, file)) {
|
|
- return TRUE;
|
|
+ pair = g_hash_table_lookup (desktop->details->file_to_pairs_hash, file);
|
|
+
|
|
+ if (pair != NULL) {
|
|
+ result = pair_shows_file (pair, file);
|
|
+ } else {
|
|
+ result = file->details->directory == directory; /* this is just for desktop links from NautilusDesktopLinkMonitor */
|
|
}
|
|
|
|
- return file->details->directory == directory;
|
|
+ uri = nautilus_file_get_uri (file);
|
|
+ nautilus_debug_log (FALSE, NAUTILUS_DEBUG_LOG_DOMAIN_DEBUG_DESKTOP_ITEMS,
|
|
+ "desktop_contains_file (%s): %d",
|
|
+ uri,
|
|
+ result);
|
|
+ g_free (uri);
|
|
+
|
|
+ return result;
|
|
}
|
|
|
|
static guint
|
|
@@ -114,15 +189,72 @@ merged_callback_destroy (MergedCallback *merged_callback)
|
|
g_assert (NAUTILUS_IS_DESKTOP_DIRECTORY (merged_callback->desktop_dir));
|
|
|
|
g_list_free (merged_callback->non_ready_directories);
|
|
- nautilus_file_list_free (merged_callback->merged_file_list);
|
|
g_free (merged_callback);
|
|
}
|
|
|
|
static void
|
|
+add_file_from_pair_to_list_cb (gpointer key, gpointer value, gpointer data)
|
|
+{
|
|
+ FilePair *pair;
|
|
+ GList **list_ptr;
|
|
+ NautilusFile *file;
|
|
+
|
|
+ pair = value;
|
|
+ list_ptr = data;
|
|
+
|
|
+ file = pair->predefined_overrides_user ? pair->predefined_file : pair->user_file;
|
|
+ nautilus_file_ref (file);
|
|
+
|
|
+ *list_ptr = g_list_prepend (*list_ptr, file);
|
|
+}
|
|
+
|
|
+static GList *
|
|
+get_combined_files (NautilusDesktopDirectory *desktop)
|
|
+{
|
|
+ GList *combined;
|
|
+
|
|
+ combined = NULL;
|
|
+ g_hash_table_foreach (desktop->details->name_to_pairs_hash, add_file_from_pair_to_list_cb, &combined);
|
|
+ return combined;
|
|
+}
|
|
+
|
|
+static GList *
|
|
+get_desktop_links (NautilusDesktopDirectory *desktop, gboolean include_tentative_files)
|
|
+{
|
|
+ if (include_tentative_files) {
|
|
+ return nautilus_file_list_copy (NAUTILUS_DIRECTORY (desktop)->details->file_list);
|
|
+ } else {
|
|
+ /* This is because nautilus-directory.c:real_get_file_list() stripts out the tentative files */
|
|
+ return GNOME_CALL_PARENT_WITH_DEFAULT (NAUTILUS_DIRECTORY_CLASS, get_file_list, (NAUTILUS_DIRECTORY (desktop)), NULL);
|
|
+ }
|
|
+}
|
|
+
|
|
+static GList *
|
|
+get_file_list (NautilusDesktopDirectory *desktop, gboolean include_tentative_files)
|
|
+{
|
|
+ GList *combined_file_list;
|
|
+ GList *file_list_from_desktop_links;
|
|
+
|
|
+ combined_file_list = get_combined_files (desktop);
|
|
+
|
|
+ file_list_from_desktop_links = get_desktop_links (desktop, include_tentative_files);
|
|
+
|
|
+ combined_file_list = g_list_concat (combined_file_list, file_list_from_desktop_links);
|
|
+
|
|
+ return combined_file_list;
|
|
+
|
|
+}
|
|
+
|
|
+static void
|
|
merged_callback_check_done (MergedCallback *merged_callback)
|
|
{
|
|
+ NautilusDesktopDirectory *desktop;
|
|
+ GList *files;
|
|
+
|
|
+ desktop = merged_callback->desktop_dir;
|
|
+
|
|
/* Check if we are ready. */
|
|
- if (merged_callback->non_ready_directories != NULL) {
|
|
+ if (merged_callback->non_ready_directories != NULL || !desktop->details->files_are_combined) {
|
|
return;
|
|
}
|
|
|
|
@@ -130,10 +262,18 @@ merged_callback_check_done (MergedCallback *merged_callback)
|
|
g_hash_table_steal (merged_callback->desktop_dir->details->callbacks, merged_callback);
|
|
|
|
/* We are ready, so do the real callback. */
|
|
- (* merged_callback->callback) (NAUTILUS_DIRECTORY (merged_callback->desktop_dir),
|
|
- merged_callback->merged_file_list,
|
|
+
|
|
+ files = get_file_list (desktop, TRUE);
|
|
+
|
|
+ nautilus_debug_log_with_file_list (FALSE, NAUTILUS_DEBUG_LOG_DOMAIN_DEBUG_DESKTOP_ITEMS, files,
|
|
+ "merged_callback_check_done: we are done; calling callback with files");
|
|
+
|
|
+ (* merged_callback->callback) (NAUTILUS_DIRECTORY (desktop),
|
|
+ files,
|
|
merged_callback->callback_data);
|
|
|
|
+ nautilus_file_list_free (files);
|
|
+
|
|
/* And we are done. */
|
|
merged_callback_destroy (merged_callback);
|
|
}
|
|
@@ -144,7 +284,330 @@ merged_callback_remove_directory (MergedCallback *merged_callback,
|
|
{
|
|
merged_callback->non_ready_directories = g_list_remove
|
|
(merged_callback->non_ready_directories, directory);
|
|
- merged_callback_check_done (merged_callback);
|
|
+}
|
|
+
|
|
+static FilePair *
|
|
+create_file_pair (NautilusDesktopDirectory *desktop, NautilusFile *file, gboolean is_predefined, gboolean *is_new_pair)
|
|
+{
|
|
+ char *name;
|
|
+ FilePair *pair;
|
|
+
|
|
+ /* Sanity check */
|
|
+
|
|
+ pair = g_hash_table_lookup (desktop->details->file_to_pairs_hash, file);
|
|
+ g_assert (pair == NULL);
|
|
+
|
|
+ /* Create the pair or add to it */
|
|
+
|
|
+ name = nautilus_file_get_name (file);
|
|
+
|
|
+ pair = g_hash_table_lookup (desktop->details->name_to_pairs_hash, name);
|
|
+
|
|
+ nautilus_file_ref (file);
|
|
+
|
|
+ if (pair == NULL) {
|
|
+ if (is_new_pair) {
|
|
+ *is_new_pair = TRUE;
|
|
+ }
|
|
+
|
|
+ pair = g_slice_new (FilePair);
|
|
+
|
|
+ pair->name = name;
|
|
+ pair->user_file = is_predefined ? NULL : file;
|
|
+ pair->predefined_file = is_predefined ? file : NULL;
|
|
+
|
|
+ pair->predefined_overrides_user = FALSE; /* we don't know yet */
|
|
+
|
|
+ g_hash_table_insert (desktop->details->name_to_pairs_hash, name, pair);
|
|
+ } else {
|
|
+ if (is_new_pair) {
|
|
+ *is_new_pair = FALSE;
|
|
+ }
|
|
+
|
|
+ g_free (name);
|
|
+
|
|
+ if (is_predefined) {
|
|
+ g_assert (pair->predefined_file == NULL);
|
|
+ pair->predefined_file = file;
|
|
+ } else {
|
|
+ g_assert (pair->user_file == NULL);
|
|
+ pair->user_file = file;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ g_hash_table_insert (desktop->details->file_to_pairs_hash, file, pair);
|
|
+
|
|
+ return pair;
|
|
+}
|
|
+
|
|
+static void
|
|
+log_pair (FilePair *pair, gboolean is_new_pair)
|
|
+{
|
|
+ nautilus_debug_log (FALSE, NAUTILUS_DEBUG_LOG_DOMAIN_DEBUG_DESKTOP_ITEMS,
|
|
+ "%s pair %p: %s - predefined=%p user=%p predefined_overrides_user=%d",
|
|
+ is_new_pair ? "New" : "Existing",
|
|
+ pair,
|
|
+ pair->name,
|
|
+ pair->predefined_file,
|
|
+ pair->user_file,
|
|
+ pair->predefined_overrides_user);
|
|
+}
|
|
+
|
|
+static void
|
|
+create_file_pairs_for_directory (NautilusDesktopDirectory *desktop, NautilusDirectory *directory, gboolean is_predefined)
|
|
+{
|
|
+ GList *list;
|
|
+ GList *l;
|
|
+
|
|
+ if (directory == NULL) {
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ list = nautilus_directory_get_file_list (directory);
|
|
+
|
|
+ nautilus_debug_log_with_file_list (FALSE, NAUTILUS_DEBUG_LOG_DOMAIN_DEBUG_DESKTOP_ITEMS, list,
|
|
+ "create_file_pairs_for_directory(): Creating pairs for files");
|
|
+
|
|
+ for (l = list; l; l = l->next) {
|
|
+ FilePair *pair;
|
|
+ gboolean is_new_pair;
|
|
+
|
|
+ pair = create_file_pair (desktop, NAUTILUS_FILE (l->data), is_predefined, &is_new_pair);
|
|
+ log_pair (pair, is_new_pair);
|
|
+ }
|
|
+
|
|
+ nautilus_file_list_free (list);
|
|
+}
|
|
+
|
|
+static char *
|
|
+get_file_contents (NautilusFile *file, gsize *length, GError **error)
|
|
+{
|
|
+ GFile *location;
|
|
+ char *path;
|
|
+ char *contents;
|
|
+
|
|
+ location = nautilus_file_get_location (file);
|
|
+ path = g_file_get_path (location);
|
|
+ contents = NULL;
|
|
+
|
|
+ if (path == NULL) {
|
|
+ char *uri;
|
|
+
|
|
+ uri = g_file_get_uri (location);
|
|
+ g_set_error (error,
|
|
+ G_IO_ERROR,
|
|
+ G_IO_ERROR_FAILED,
|
|
+ _("Cannot read remote item: %s"),
|
|
+ uri);
|
|
+ g_free (uri);
|
|
+
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ if (!g_file_get_contents (path, &contents, length, error)) {
|
|
+ contents = NULL;
|
|
+ }
|
|
+
|
|
+out:
|
|
+ return contents;
|
|
+}
|
|
+
|
|
+static gboolean
|
|
+predefined_desktop_item_is_mandatory (GnomeDesktopItem *item)
|
|
+{
|
|
+ /* If the desktop item does not have X-XDG-Is-Mandatory defined, then we
|
|
+ * assume it to be mandatory. This is so that the sysadmin can just
|
|
+ * copy existing .desktop files into the directory for predefined items,
|
|
+ * and assume that they will override anything the user tries to use.
|
|
+ */
|
|
+ return (!gnome_desktop_item_attr_exists (item, "X-XDG-Is-Mandatory")
|
|
+ || gnome_desktop_item_get_boolean (item, "X-XDG-Is-Mandatory"));
|
|
+}
|
|
+
|
|
+static gboolean
|
|
+predefined_file_should_override_user_file (NautilusDesktopDirectory *desktop, NautilusFile *predefined, NautilusFile *user)
|
|
+{
|
|
+ gsize predefined_length;
|
|
+ char *predefined_contents;
|
|
+ char *predefined_uri;
|
|
+ char *user_uri;
|
|
+ GnomeDesktopItem *predefined_item;
|
|
+ GError *error;
|
|
+ gboolean should_override;
|
|
+ time_t predefined_mtime, user_mtime;
|
|
+ const char *reason;
|
|
+
|
|
+ should_override = FALSE;
|
|
+ reason = "the predefined item is not mandatory";
|
|
+
|
|
+ predefined_uri = nautilus_file_get_uri (predefined);
|
|
+ user_uri = nautilus_file_get_uri (user);
|
|
+ predefined_item = NULL;
|
|
+
|
|
+ /* Can we discard either file trivially? */
|
|
+
|
|
+ if (!nautilus_file_is_mime_type (predefined, "application/x-desktop")) {
|
|
+ reason = "predefined items which are not .desktop files always override user items";
|
|
+ should_override = TRUE;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ if (!nautilus_file_is_mime_type (user, "application/x-desktop")) {
|
|
+ reason = "predefined items always override user items that are not .desktop files";
|
|
+ should_override = TRUE;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ /* Read the predefined .desktop file */
|
|
+
|
|
+ /* FIXME: reading the file asynchronously is left as an exercise for the reader */
|
|
+
|
|
+ error = NULL;
|
|
+ predefined_contents = get_file_contents (predefined, &predefined_length, &error);
|
|
+ if (predefined_contents == NULL) {
|
|
+ /* can't determine contents trivially? let it override the user's stuff, anyway */
|
|
+ nautilus_directory_emit_load_error (NAUTILUS_DIRECTORY (desktop), error);
|
|
+ nautilus_debug_log (desktop->details->initializing, NAUTILUS_DEBUG_LOG_DOMAIN_DESKTOP_ITEMS,
|
|
+ "Error reading predefined item %s: %s",
|
|
+ predefined_uri,
|
|
+ error->message);
|
|
+ g_error_free (error);
|
|
+
|
|
+ reason = "user items will not override predefined items that have with errors";
|
|
+ should_override = TRUE;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ predefined_item = gnome_desktop_item_new_from_string (predefined_uri,
|
|
+ predefined_contents,
|
|
+ predefined_length,
|
|
+ GNOME_DESKTOP_ITEM_LOAD_NO_TRANSLATIONS,
|
|
+ &error);
|
|
+
|
|
+ if (predefined_item == NULL) {
|
|
+ /* can't read desktop file? let it override the user's stuff, anyway */
|
|
+ nautilus_directory_emit_load_error (NAUTILUS_DIRECTORY (desktop), error);
|
|
+ nautilus_debug_log (desktop->details->initializing, NAUTILUS_DEBUG_LOG_DOMAIN_DESKTOP_ITEMS,
|
|
+ "Error parsing predefined item %s: %s",
|
|
+ predefined_uri,
|
|
+ error->message);
|
|
+ g_error_free (error);
|
|
+
|
|
+ reason = "user items will not override predefined items that have with errors";
|
|
+ should_override = TRUE;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ /* Mandatory? */
|
|
+
|
|
+ if (predefined_desktop_item_is_mandatory (predefined_item)) {
|
|
+ reason = "the predefined item is mandatory (include \"X-XDG-Is-Mandatory=false\" to make it non-mandatory)";
|
|
+ should_override = TRUE;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ /* Not mandatory. But if the predefined item is newer than the user's, then it overrides the user's. */
|
|
+
|
|
+ predefined_mtime = nautilus_file_get_mtime (predefined);
|
|
+ user_mtime = nautilus_file_get_mtime (user);
|
|
+
|
|
+ if (predefined_mtime > user_mtime) {
|
|
+ reason = "the predefined item is newer than the user item";
|
|
+ should_override = TRUE;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+out:
|
|
+
|
|
+ if (predefined_item != NULL) {
|
|
+ gnome_desktop_item_unref (predefined_item);
|
|
+ }
|
|
+
|
|
+ nautilus_debug_log (desktop->details->initializing, NAUTILUS_DEBUG_LOG_DOMAIN_DESKTOP_ITEMS,
|
|
+ "Predefined item %s %s override user item %s because %s",
|
|
+ predefined_uri,
|
|
+ should_override ? "will" : "will not",
|
|
+ user_uri,
|
|
+ reason);
|
|
+
|
|
+ g_free (predefined_uri);
|
|
+ g_free (user_uri);
|
|
+
|
|
+ return should_override;
|
|
+}
|
|
+
|
|
+static void
|
|
+resolve_overrides_in_file_pair (NautilusDesktopDirectory *desktop, FilePair *pair)
|
|
+{
|
|
+ if (pair->user_file != NULL && pair->predefined_file != NULL) {
|
|
+ pair->predefined_overrides_user = predefined_file_should_override_user_file (desktop, pair->predefined_file, pair->user_file);
|
|
+ } else {
|
|
+ char *predefined_uri, *user_uri;
|
|
+
|
|
+ pair->predefined_overrides_user = pair->predefined_file != NULL;
|
|
+ g_assert (pair->predefined_overrides_user || pair->user_file != NULL);
|
|
+
|
|
+ predefined_uri = pair->predefined_file ? nautilus_file_get_uri (pair->predefined_file) : NULL;
|
|
+ user_uri = pair->user_file ? nautilus_file_get_uri (pair->user_file) : NULL;
|
|
+
|
|
+ nautilus_debug_log (desktop->details->initializing, NAUTILUS_DEBUG_LOG_DOMAIN_DESKTOP_ITEMS,
|
|
+ "%s %s is used as it has no counterpart",
|
|
+ pair->predefined_overrides_user ? "Predefined item" : "User item",
|
|
+ predefined_uri ? predefined_uri : user_uri);
|
|
+
|
|
+ g_free (predefined_uri);
|
|
+ g_free (user_uri);
|
|
+ }
|
|
+}
|
|
+
|
|
+static void
|
|
+find_overriden_files_cb (gpointer key, gpointer value, gpointer data)
|
|
+{
|
|
+ NautilusDesktopDirectory *desktop;
|
|
+ FilePair *pair;
|
|
+
|
|
+ desktop = NAUTILUS_DESKTOP_DIRECTORY (data);
|
|
+ pair = value;
|
|
+
|
|
+ resolve_overrides_in_file_pair (desktop, pair);
|
|
+}
|
|
+
|
|
+static void
|
|
+combine_real_and_predefined_directories (NautilusDesktopDirectory *desktop)
|
|
+{
|
|
+ g_assert (directories_are_done_loading (desktop));
|
|
+
|
|
+ if (desktop->details->files_are_combined) {
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ desktop->details->files_are_combined = TRUE;
|
|
+
|
|
+ /* 1. Create pairs for the files */
|
|
+
|
|
+ create_file_pairs_for_directory (desktop, desktop->details->real_directory, FALSE);
|
|
+ create_file_pairs_for_directory (desktop, desktop->details->predefined_items_dir, TRUE);
|
|
+
|
|
+ /* 2. Figure out which files get overriden */
|
|
+
|
|
+ g_hash_table_foreach (desktop->details->name_to_pairs_hash, find_overriden_files_cb, desktop);
|
|
+
|
|
+ desktop->details->initializing = FALSE;
|
|
+}
|
|
+
|
|
+static const char *
|
|
+get_debug_dirname (NautilusDesktopDirectory *desktop, NautilusDirectory *directory)
|
|
+{
|
|
+ if (directory == NAUTILUS_DIRECTORY (desktop)) {
|
|
+ return "desktop directory";
|
|
+ } else if (directory == desktop->details->real_directory) {
|
|
+ return "real directory";
|
|
+ } else if (directory == desktop->details->predefined_items_dir) {
|
|
+ return "predefined items directory";
|
|
+ } else {
|
|
+ g_assert_not_reached ();
|
|
+ return NULL;
|
|
+ }
|
|
}
|
|
|
|
static void
|
|
@@ -153,6 +616,8 @@ directory_ready_callback (NautilusDirectory *directory,
|
|
gpointer callback_data)
|
|
{
|
|
MergedCallback *merged_callback;
|
|
+ NautilusDesktopDirectory *desktop;
|
|
+ const char *dirname;
|
|
|
|
g_assert (NAUTILUS_IS_DIRECTORY (directory));
|
|
g_assert (callback_data != NULL);
|
|
@@ -160,13 +625,13 @@ directory_ready_callback (NautilusDirectory *directory,
|
|
merged_callback = callback_data;
|
|
g_assert (g_list_find (merged_callback->non_ready_directories, directory) != NULL);
|
|
|
|
- /* Update based on this call. */
|
|
- merged_callback->merged_file_list = g_list_concat
|
|
- (merged_callback->merged_file_list,
|
|
- nautilus_file_list_copy (files));
|
|
+ desktop = merged_callback->desktop_dir;
|
|
+
|
|
+ dirname = get_debug_dirname (desktop, directory);
|
|
|
|
/* Check if we are ready. */
|
|
merged_callback_remove_directory (merged_callback, directory);
|
|
+ merged_callback_check_done (merged_callback);
|
|
}
|
|
|
|
static void
|
|
@@ -179,6 +644,12 @@ desktop_call_when_ready (NautilusDirectory *directory,
|
|
NautilusDesktopDirectory *desktop;
|
|
MergedCallback search_key, *merged_callback;
|
|
|
|
+ nautilus_debug_log (FALSE, NAUTILUS_DEBUG_LOG_DOMAIN_DEBUG_DESKTOP_ITEMS,
|
|
+ "desktop_call_when_ready (file_attributes=0x%x, wait_for_file_list=%d, callback=%p)",
|
|
+ (int) file_attributes,
|
|
+ (int) wait_for_file_list,
|
|
+ callback);
|
|
+
|
|
desktop = NAUTILUS_DESKTOP_DIRECTORY (directory);
|
|
|
|
/* Check to be sure we aren't overwriting. */
|
|
@@ -194,36 +665,49 @@ desktop_call_when_ready (NautilusDirectory *directory,
|
|
merged_callback->desktop_dir = desktop;
|
|
merged_callback->callback = callback;
|
|
merged_callback->callback_data = callback_data;
|
|
- merged_callback->wait_for_attributes = file_attributes;
|
|
- merged_callback->wait_for_file_list = wait_for_file_list;
|
|
+
|
|
+ /* The three non-ready directories are ourselves, the real_directory and the predefined_items_dir */
|
|
+
|
|
merged_callback->non_ready_directories = g_list_prepend
|
|
(merged_callback->non_ready_directories, directory);
|
|
merged_callback->non_ready_directories = g_list_prepend
|
|
(merged_callback->non_ready_directories, desktop->details->real_directory);
|
|
|
|
-
|
|
- merged_callback->merged_file_list = g_list_concat (NULL,
|
|
- nautilus_file_list_copy (directory->details->file_list));
|
|
+ if (desktop->details->predefined_items_dir != NULL) {
|
|
+ merged_callback->non_ready_directories = g_list_prepend
|
|
+ (merged_callback->non_ready_directories, desktop->details->predefined_items_dir);
|
|
+ }
|
|
|
|
/* Put it in the hash table. */
|
|
g_hash_table_insert (desktop->details->callbacks,
|
|
merged_callback, merged_callback);
|
|
|
|
- /* Now tell all the directories about it. */
|
|
+ /* Now tell all the directories about it. We always pass TRUE for
|
|
+ * wait_for_file_list since *we* can't know which files to proxy until
|
|
+ * we have all the ones from the child directories.
|
|
+ */
|
|
nautilus_directory_call_when_ready
|
|
(desktop->details->real_directory,
|
|
- merged_callback->wait_for_attributes,
|
|
- merged_callback->wait_for_file_list,
|
|
+ file_attributes,
|
|
+ TRUE,
|
|
directory_ready_callback, merged_callback);
|
|
+
|
|
+ if (desktop->details->predefined_items_dir != NULL) {
|
|
+ nautilus_directory_call_when_ready
|
|
+ (desktop->details->predefined_items_dir,
|
|
+ file_attributes,
|
|
+ TRUE,
|
|
+ directory_ready_callback, merged_callback);
|
|
+ }
|
|
+
|
|
nautilus_directory_call_when_ready_internal
|
|
(directory,
|
|
NULL,
|
|
- merged_callback->wait_for_attributes,
|
|
- merged_callback->wait_for_file_list,
|
|
+ file_attributes,
|
|
+ FALSE, /* ... but the desktop directory doesn't support wait_for_file_list = TRUE */
|
|
directory_ready_callback,
|
|
NULL,
|
|
merged_callback);
|
|
-
|
|
}
|
|
|
|
static void
|
|
@@ -235,6 +719,10 @@ desktop_cancel_callback (NautilusDirectory *directory,
|
|
MergedCallback search_key, *merged_callback;
|
|
GList *node;
|
|
|
|
+ nautilus_debug_log (FALSE, NAUTILUS_DEBUG_LOG_DOMAIN_DEBUG_DESKTOP_ITEMS,
|
|
+ "desktop_cancel_callback (callback=%p)",
|
|
+ callback);
|
|
+
|
|
desktop = NAUTILUS_DESKTOP_DIRECTORY (directory);
|
|
|
|
/* Find the entry in the table. */
|
|
@@ -267,15 +755,19 @@ merged_monitor_destroy (MergedMonitor *monitor)
|
|
/* Call through to the real directory remove calls. */
|
|
nautilus_directory_file_monitor_remove (desktop->details->real_directory, monitor);
|
|
|
|
+ if (desktop->details->predefined_items_dir != NULL) {
|
|
+ nautilus_directory_file_monitor_remove (desktop->details->predefined_items_dir, monitor);
|
|
+ }
|
|
+
|
|
nautilus_directory_monitor_remove_internal (NAUTILUS_DIRECTORY (desktop), NULL, monitor);
|
|
|
|
g_free (monitor);
|
|
}
|
|
|
|
static void
|
|
-build_merged_callback_list (NautilusDirectory *directory,
|
|
- GList *file_list,
|
|
- gpointer callback_data)
|
|
+build_file_list_cb (NautilusDirectory *directory,
|
|
+ GList *file_list,
|
|
+ gpointer callback_data)
|
|
{
|
|
GList **merged_list;
|
|
|
|
@@ -285,6 +777,66 @@ build_merged_callback_list (NautilusDirectory *directory,
|
|
}
|
|
|
|
static void
|
|
+add_file_monitor_and_emit_paired_files (NautilusDesktopDirectory *desktop,
|
|
+ NautilusDirectory *directory,
|
|
+ MergedMonitor *monitor,
|
|
+ gboolean monitor_hidden_files,
|
|
+ gboolean monitor_backup_files,
|
|
+ NautilusFileAttributes file_attributes,
|
|
+ NautilusDirectoryCallback callback,
|
|
+ gpointer callback_data)
|
|
+{
|
|
+ GList *unpaired_files;
|
|
+ GList *l;
|
|
+ GList *paired_files;
|
|
+
|
|
+ if (directory == NULL) {
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ unpaired_files = NULL;
|
|
+
|
|
+ nautilus_directory_file_monitor_add (directory,
|
|
+ monitor,
|
|
+ monitor_hidden_files,
|
|
+ monitor_backup_files,
|
|
+ file_attributes,
|
|
+ build_file_list_cb, &unpaired_files);
|
|
+
|
|
+ /* For each of those files from the directory, pick the ones that are being used in one of our pairs */
|
|
+
|
|
+ paired_files = NULL;
|
|
+
|
|
+ for (l = unpaired_files; l; l = l->next) {
|
|
+ NautilusFile *file;
|
|
+ FilePair *pair;
|
|
+
|
|
+ file = NAUTILUS_FILE (l->data);
|
|
+ pair = g_hash_table_lookup (desktop->details->file_to_pairs_hash, file);
|
|
+
|
|
+ if (pair == NULL) {
|
|
+ continue; /* maybe we haven't been notified yet about that file; we'll handle it later anyway */
|
|
+ }
|
|
+
|
|
+ if (pair_shows_file (pair, file)) {
|
|
+ paired_files = g_list_prepend (paired_files, file);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (callback != NULL) {
|
|
+ nautilus_debug_log_with_file_list (FALSE, NAUTILUS_DEBUG_LOG_DOMAIN_DEBUG_DESKTOP_ITEMS, paired_files,
|
|
+ "add_file_monitor_and_emit_paired_files: calling callback %p on directory files",
|
|
+ callback);
|
|
+
|
|
+ (* callback) (NAUTILUS_DIRECTORY (desktop), paired_files, callback_data);
|
|
+ }
|
|
+
|
|
+ nautilus_file_list_free (unpaired_files);
|
|
+ g_list_free (paired_files);
|
|
+
|
|
+}
|
|
+
|
|
+static void
|
|
desktop_monitor_add (NautilusDirectory *directory,
|
|
gconstpointer client,
|
|
gboolean monitor_hidden_files,
|
|
@@ -295,7 +847,14 @@ desktop_monitor_add (NautilusDirectory *directory,
|
|
{
|
|
NautilusDesktopDirectory *desktop;
|
|
MergedMonitor *monitor;
|
|
- GList *merged_callback_list;
|
|
+
|
|
+ nautilus_debug_log (FALSE, NAUTILUS_DEBUG_LOG_DOMAIN_DEBUG_DESKTOP_ITEMS,
|
|
+ "desktop_monitor_add (client=%p, monitor_hidden_files=%d, monitor_backup_files=%d, file_attributes=0x%x, callback=%p)",
|
|
+ client,
|
|
+ (int) monitor_hidden_files,
|
|
+ (int) monitor_backup_files,
|
|
+ (int) file_attributes,
|
|
+ callback);
|
|
|
|
desktop = NAUTILUS_DESKTOP_DIRECTORY (directory);
|
|
|
|
@@ -315,25 +874,40 @@ desktop_monitor_add (NautilusDirectory *directory,
|
|
monitor->monitor_backup_files = monitor_backup_files;
|
|
monitor->monitor_attributes = file_attributes;
|
|
|
|
- /* Call through to the real directory add calls. */
|
|
- merged_callback_list = NULL;
|
|
-
|
|
- /* Call up to real dir */
|
|
- nautilus_directory_file_monitor_add
|
|
- (desktop->details->real_directory, monitor,
|
|
- monitor_hidden_files, monitor_backup_files,
|
|
- file_attributes,
|
|
- build_merged_callback_list, &merged_callback_list);
|
|
-
|
|
- /* Handle the desktop part */
|
|
- merged_callback_list = g_list_concat (merged_callback_list,
|
|
- nautilus_file_list_copy (directory->details->file_list));
|
|
+ /* Call through to the real directories' add calls. */
|
|
+
|
|
+ add_file_monitor_and_emit_paired_files (desktop,
|
|
+ desktop->details->real_directory,
|
|
+ monitor,
|
|
+ monitor_hidden_files,
|
|
+ monitor_backup_files,
|
|
+ file_attributes,
|
|
+ callback,
|
|
+ callback_data);
|
|
+
|
|
+ add_file_monitor_and_emit_paired_files (desktop,
|
|
+ desktop->details->predefined_items_dir,
|
|
+ monitor,
|
|
+ monitor_hidden_files,
|
|
+ monitor_backup_files,
|
|
+ file_attributes,
|
|
+ callback,
|
|
+ callback_data);
|
|
+
|
|
+ /* Call the callback on our desktop links */
|
|
|
|
-
|
|
if (callback != NULL) {
|
|
- (* callback) (directory, merged_callback_list, callback_data);
|
|
+ GList *desktop_link_files;
|
|
+
|
|
+ desktop_link_files = get_desktop_links (desktop, TRUE);
|
|
+
|
|
+ nautilus_debug_log_with_file_list (FALSE, NAUTILUS_DEBUG_LOG_DOMAIN_DEBUG_DESKTOP_ITEMS, desktop_link_files,
|
|
+ "desktop_monitor_add: calling callback %p on desktop link files",
|
|
+ callback);
|
|
+
|
|
+ (* callback) (NAUTILUS_DIRECTORY (desktop), desktop_link_files, callback_data);
|
|
+ nautilus_file_list_free (desktop_link_files);
|
|
}
|
|
- nautilus_file_list_free (merged_callback_list);
|
|
}
|
|
|
|
static void
|
|
@@ -342,6 +916,10 @@ desktop_monitor_remove (NautilusDirectory *directory,
|
|
{
|
|
NautilusDesktopDirectory *desktop;
|
|
MergedMonitor *monitor;
|
|
+
|
|
+ nautilus_debug_log (FALSE, NAUTILUS_DEBUG_LOG_DOMAIN_DEBUG_DESKTOP_ITEMS,
|
|
+ "desktop_monitor_remove (client=%p)",
|
|
+ client);
|
|
|
|
desktop = NAUTILUS_DESKTOP_DIRECTORY (directory);
|
|
|
|
@@ -354,55 +932,143 @@ desktop_monitor_remove (NautilusDirectory *directory,
|
|
}
|
|
|
|
static void
|
|
+free_file_pair (FilePair *pair)
|
|
+{
|
|
+ g_free (pair->name);
|
|
+ pair->name = NULL;
|
|
+
|
|
+ nautilus_file_unref (pair->user_file);
|
|
+ nautilus_file_unref (pair->predefined_file);
|
|
+
|
|
+ pair->user_file = NULL;
|
|
+ pair->predefined_file = NULL;
|
|
+
|
|
+ g_slice_free (FilePair, pair);
|
|
+}
|
|
+
|
|
+static void
|
|
+free_file_pair_cb (gpointer key, gpointer value, gpointer data)
|
|
+{
|
|
+ FilePair *pair;
|
|
+
|
|
+ pair = value;
|
|
+ g_assert ((char *) key == pair->name);
|
|
+
|
|
+ free_file_pair (pair);
|
|
+}
|
|
+
|
|
+static void
|
|
+destroy_pair_hashes (NautilusDesktopDirectory *desktop)
|
|
+{
|
|
+ g_hash_table_foreach (desktop->details->name_to_pairs_hash, free_file_pair_cb, NULL);
|
|
+ g_hash_table_destroy (desktop->details->name_to_pairs_hash);
|
|
+
|
|
+ g_hash_table_destroy (desktop->details->file_to_pairs_hash); /* its keys/values were already freed by the call above */
|
|
+
|
|
+ desktop->details->name_to_pairs_hash = NULL;
|
|
+ desktop->details->file_to_pairs_hash = NULL;
|
|
+}
|
|
+
|
|
+static void
|
|
+create_pair_hashes (NautilusDesktopDirectory *desktop)
|
|
+{
|
|
+ g_assert (desktop->details->name_to_pairs_hash == NULL);
|
|
+ g_assert (desktop->details->file_to_pairs_hash == NULL);
|
|
+
|
|
+ desktop->details->name_to_pairs_hash = g_hash_table_new (g_str_hash, g_str_equal);
|
|
+ desktop->details->file_to_pairs_hash = g_hash_table_new (g_direct_hash, g_direct_equal);
|
|
+}
|
|
+
|
|
+static void
|
|
+invalidate_combined_files (NautilusDesktopDirectory *desktop)
|
|
+{
|
|
+ destroy_pair_hashes (desktop);
|
|
+ create_pair_hashes (desktop);
|
|
+
|
|
+ desktop->details->files_are_combined = FALSE;
|
|
+}
|
|
+
|
|
+static void
|
|
desktop_force_reload (NautilusDirectory *directory)
|
|
{
|
|
NautilusDesktopDirectory *desktop;
|
|
|
|
+ nautilus_debug_log (FALSE, NAUTILUS_DEBUG_LOG_DOMAIN_DEBUG_DESKTOP_ITEMS,
|
|
+ "desktop_force_reload(): invalidating files");
|
|
+
|
|
desktop = NAUTILUS_DESKTOP_DIRECTORY (directory);
|
|
|
|
+ invalidate_combined_files (desktop);
|
|
+
|
|
+ /* Set the pending flags before we start reloading any of the directories */
|
|
+
|
|
+ desktop->details->real_directory_pending = TRUE;
|
|
+
|
|
+ if (desktop->details->predefined_items_dir != NULL) {
|
|
+ desktop->details->predefined_items_dir_pending = TRUE;
|
|
+ }
|
|
+
|
|
+ /* Reload! */
|
|
+
|
|
nautilus_directory_force_reload (desktop->details->real_directory);
|
|
|
|
- /* We don't invalidate the files in desktop, since they are always
|
|
- up to date. (And we don't ever want to mark them invalid.) */
|
|
+ if (desktop->details->predefined_items_dir != NULL) {
|
|
+ nautilus_directory_force_reload (desktop->details->predefined_items_dir);
|
|
+ }
|
|
+
|
|
+ /* We don't invalidate the "fake" files in desktop (for Home, Computer,
|
|
+ volumes, etc.), since they are always up to date. (And we don't ever
|
|
+ want to mark them invalid.) */
|
|
}
|
|
|
|
static gboolean
|
|
desktop_are_all_files_seen (NautilusDirectory *directory)
|
|
{
|
|
NautilusDesktopDirectory *desktop;
|
|
+ gboolean result;
|
|
|
|
desktop = NAUTILUS_DESKTOP_DIRECTORY (directory);
|
|
|
|
- if (!nautilus_directory_are_all_files_seen (desktop->details->real_directory)) {
|
|
- return FALSE;
|
|
- }
|
|
+ result = desktop->details->files_are_combined;
|
|
+
|
|
+ nautilus_debug_log (FALSE, NAUTILUS_DEBUG_LOG_DOMAIN_DEBUG_DESKTOP_ITEMS,
|
|
+ "desktop_are_all_files_seen(): %d",
|
|
+ result);
|
|
|
|
- return TRUE;
|
|
+ return result;
|
|
}
|
|
|
|
static gboolean
|
|
desktop_is_not_empty (NautilusDirectory *directory)
|
|
{
|
|
NautilusDesktopDirectory *desktop;
|
|
+ gboolean result;
|
|
|
|
desktop = NAUTILUS_DESKTOP_DIRECTORY (directory);
|
|
|
|
- if (nautilus_directory_is_not_empty (desktop->details->real_directory)) {
|
|
- return TRUE;
|
|
+ if (g_hash_table_size (desktop->details->name_to_pairs_hash) != 0) {
|
|
+ result = TRUE;
|
|
+ } else {
|
|
+ result = directory->details->file_list != NULL; /* this is just for desktop links from NautilusDesktopLinkMonitor */
|
|
}
|
|
|
|
- return directory->details->file_list != NULL;
|
|
+ nautilus_debug_log (FALSE, NAUTILUS_DEBUG_LOG_DOMAIN_DEBUG_DESKTOP_ITEMS,
|
|
+ "desktop_is_not_empty(): %d",
|
|
+ result);
|
|
+
|
|
+ return result;
|
|
}
|
|
|
|
static GList *
|
|
desktop_get_file_list (NautilusDirectory *directory)
|
|
{
|
|
- GList *real_dir_file_list, *desktop_dir_file_list;
|
|
- real_dir_file_list = nautilus_directory_get_file_list
|
|
- (NAUTILUS_DESKTOP_DIRECTORY (directory)->details->real_directory);
|
|
- desktop_dir_file_list = GNOME_CALL_PARENT_WITH_DEFAULT
|
|
- (NAUTILUS_DIRECTORY_CLASS, get_file_list, (directory), NULL);
|
|
- return g_list_concat (real_dir_file_list, desktop_dir_file_list);
|
|
+ GList *result;
|
|
+
|
|
+ result = get_file_list (NAUTILUS_DESKTOP_DIRECTORY (directory), FALSE);
|
|
+ nautilus_debug_log_with_file_list (FALSE, NAUTILUS_DEBUG_LOG_DOMAIN_DEBUG_DESKTOP_ITEMS, result,
|
|
+ "desktop_get_file_list(): returning list of files");
|
|
+
|
|
+ return result;
|
|
}
|
|
|
|
NautilusDirectory *
|
|
@@ -412,7 +1078,6 @@ nautilus_desktop_directory_get_real_directory (NautilusDesktopDirectory *desktop
|
|
return desktop->details->real_directory;
|
|
}
|
|
|
|
-
|
|
static void
|
|
desktop_finalize (GObject *object)
|
|
{
|
|
@@ -422,39 +1087,455 @@ desktop_finalize (GObject *object)
|
|
|
|
nautilus_directory_unref (desktop->details->real_directory);
|
|
|
|
+ if (desktop->details->predefined_items_dir != NULL) {
|
|
+ nautilus_directory_unref (desktop->details->predefined_items_dir);
|
|
+ }
|
|
+
|
|
g_hash_table_destroy (desktop->details->callbacks);
|
|
g_hash_table_destroy (desktop->details->monitors);
|
|
+
|
|
+ destroy_pair_hashes (desktop);
|
|
+
|
|
g_free (desktop->details);
|
|
|
|
eel_preferences_remove_callback (NAUTILUS_PREFERENCES_DESKTOP_IS_HOME_DIR,
|
|
desktop_directory_changed_callback,
|
|
desktop);
|
|
+ eel_preferences_remove_callback (NAUTILUS_PREFERENCES_DESKTOP_PREDEFINED_ITEMS_DIR,
|
|
+ predefined_items_dir_changed_callback,
|
|
+ desktop);
|
|
|
|
G_OBJECT_CLASS (parent_class)->finalize (object);
|
|
}
|
|
|
|
static void
|
|
-done_loading_callback (NautilusDirectory *real_directory,
|
|
- NautilusDesktopDirectory *desktop)
|
|
+load_error_callback (NautilusDirectory *directory, GError *error, NautilusDesktopDirectory *desktop)
|
|
+{
|
|
+ nautilus_debug_log (FALSE, NAUTILUS_DEBUG_LOG_DOMAIN_DESKTOP_ITEMS,
|
|
+ "Error while loading %s: %s",
|
|
+ get_debug_dirname (desktop, directory),
|
|
+ error->message);
|
|
+
|
|
+ nautilus_directory_emit_load_error (NAUTILUS_DIRECTORY (desktop), error);
|
|
+}
|
|
+
|
|
+static gboolean
|
|
+directories_are_done_loading (NautilusDesktopDirectory *desktop)
|
|
{
|
|
- nautilus_directory_emit_done_loading (NAUTILUS_DIRECTORY (desktop));
|
|
+ gboolean real_is_done;
|
|
+ gboolean predefined_is_done;
|
|
+
|
|
+ real_is_done = !desktop->details->real_directory_pending;
|
|
+
|
|
+ predefined_is_done = (desktop->details->predefined_items_dir == NULL || !desktop->details->predefined_items_dir_pending);
|
|
+
|
|
+ return real_is_done && predefined_is_done;
|
|
}
|
|
|
|
+static void
|
|
+emit_pending_callback_cb (gpointer key, gpointer value, gpointer data)
|
|
+{
|
|
+ MergedCallback *merged_callback;
|
|
+
|
|
+ merged_callback = key;
|
|
+ merged_callback_check_done (merged_callback);
|
|
+}
|
|
|
|
static void
|
|
-forward_files_added_cover (NautilusDirectory *real_directory,
|
|
+emit_pending_callbacks (NautilusDesktopDirectory *desktop)
|
|
+{
|
|
+ g_hash_table_foreach (desktop->details->callbacks, emit_pending_callback_cb, desktop);
|
|
+}
|
|
+
|
|
+static void
|
|
+done_loading_callback (NautilusDirectory *directory,
|
|
+ NautilusDesktopDirectory *desktop)
|
|
+{
|
|
+ if (directory == desktop->details->real_directory) {
|
|
+ desktop->details->real_directory_pending = FALSE;
|
|
+ } else if (directory == desktop->details->predefined_items_dir) {
|
|
+ desktop->details->predefined_items_dir_pending = FALSE;
|
|
+ } else {
|
|
+ g_assert_not_reached ();
|
|
+ }
|
|
+
|
|
+ if (directories_are_done_loading (desktop)) {
|
|
+ nautilus_debug_log (FALSE, NAUTILUS_DEBUG_LOG_DOMAIN_DEBUG_DESKTOP_ITEMS,
|
|
+ "done_loading_callback(): %s and all directories are done; will combine files, emit callbacks, and emit done_loading",
|
|
+ get_debug_dirname (desktop, directory));
|
|
+
|
|
+ combine_real_and_predefined_directories (desktop);
|
|
+ emit_pending_callbacks (desktop);
|
|
+ nautilus_directory_emit_done_loading (NAUTILUS_DIRECTORY (desktop));
|
|
+ } else {
|
|
+ nautilus_debug_log (FALSE, NAUTILUS_DEBUG_LOG_DOMAIN_DEBUG_DESKTOP_ITEMS,
|
|
+ "done_loading_callback(): %s is done loading, but not all dirs are ready yet",
|
|
+ get_debug_dirname (desktop, directory));
|
|
+ }
|
|
+}
|
|
+
|
|
+static void
|
|
+forward_files_added_cover (NautilusDirectory *directory,
|
|
GList *files,
|
|
gpointer callback_data)
|
|
{
|
|
- nautilus_directory_emit_files_added (NAUTILUS_DIRECTORY (callback_data), files);
|
|
+ NautilusDesktopDirectory *desktop;
|
|
+ gboolean is_predefined_dir;
|
|
+ GList *l;
|
|
+ GList *files_removed;
|
|
+ GList *files_added;
|
|
+
|
|
+ desktop = NAUTILUS_DESKTOP_DIRECTORY (callback_data);
|
|
+
|
|
+ nautilus_debug_log_with_file_list (FALSE, NAUTILUS_DEBUG_LOG_DOMAIN_DEBUG_DESKTOP_ITEMS, files,
|
|
+ "forward_files_added_cover(): files got added to %s. files_are_combined=%d",
|
|
+ get_debug_dirname (desktop, directory),
|
|
+ desktop->details->files_are_combined);
|
|
+
|
|
+ if (!desktop->details->files_are_combined) {
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ if (directory == desktop->details->real_directory) {
|
|
+ is_predefined_dir = FALSE;
|
|
+ } else if (directory == desktop->details->predefined_items_dir) {
|
|
+ is_predefined_dir = TRUE;
|
|
+ } else {
|
|
+ g_assert_not_reached ();
|
|
+ }
|
|
+
|
|
+ files_removed = NULL;
|
|
+ files_added = NULL;
|
|
+
|
|
+ for (l = files; l; l = l->next) {
|
|
+ NautilusFile *file;
|
|
+ FilePair *pair;
|
|
+ gboolean is_new_pair;
|
|
+ gboolean predefined_was_being_used;
|
|
+ char *uri;
|
|
+
|
|
+ file = NAUTILUS_FILE (l->data);
|
|
+
|
|
+ uri = nautilus_file_get_uri (file);
|
|
+
|
|
+ nautilus_debug_log (FALSE, NAUTILUS_DEBUG_LOG_DOMAIN_DESKTOP_ITEMS,
|
|
+ "File added to %s: %s -- determining if it gets overriden",
|
|
+ is_predefined_dir ? "predefined items" : "user items",
|
|
+ uri);
|
|
+
|
|
+ pair = g_hash_table_lookup (desktop->details->file_to_pairs_hash, file);
|
|
+ if (pair != NULL) {
|
|
+ GList node;
|
|
+
|
|
+ /* Sometimes we get a files-added signal from one of the
|
|
+ * child directories, even though the file in question
|
|
+ * *has* already been emitted by a files-changed signal.
|
|
+ * In that case, we already know about the file and
|
|
+ * should not create a new pair for it. We'll handle
|
|
+ * that case as if the file had just been changed.
|
|
+ */
|
|
+
|
|
+ node.data = file;
|
|
+ node.prev = NULL;
|
|
+ node.next = NULL;
|
|
+
|
|
+ nautilus_debug_log (FALSE, NAUTILUS_DEBUG_LOG_DOMAIN_DEBUG_DESKTOP_ITEMS,
|
|
+ "Got 'added' for %s but we already knew about it; will consider it as a file that changed",
|
|
+ uri);
|
|
+ forward_files_changed_cover (directory, &node, desktop);
|
|
+ g_free (uri);
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ pair = create_file_pair (desktop, NAUTILUS_FILE (l->data), is_predefined_dir, &is_new_pair);
|
|
+ log_pair (pair, is_new_pair);
|
|
+ predefined_was_being_used = pair->predefined_overrides_user;
|
|
+
|
|
+ resolve_overrides_in_file_pair (desktop, pair);
|
|
+
|
|
+ if (is_new_pair) {
|
|
+ nautilus_debug_log (FALSE, NAUTILUS_DEBUG_LOG_DOMAIN_DESKTOP_ITEMS,
|
|
+ "%s will appear in the user's desktop (it has no %s counterpart)",
|
|
+ uri,
|
|
+ is_predefined_dir ? "user" : "predefined");
|
|
+
|
|
+ files_added = g_list_prepend (files_added, file);
|
|
+ } else {
|
|
+ gboolean log_replacement;
|
|
+
|
|
+ log_replacement = FALSE;
|
|
+ if (predefined_was_being_used) {
|
|
+ g_assert (!is_predefined_dir && file == pair->user_file);
|
|
+
|
|
+ if (!pair->predefined_overrides_user) {
|
|
+ log_replacement = TRUE;
|
|
+ files_removed = g_list_prepend (files_removed, pair->predefined_file);
|
|
+ files_added = g_list_prepend (files_added, pair->user_file);
|
|
+ }
|
|
+ } else {
|
|
+ g_assert (is_predefined_dir && file == pair->predefined_file);
|
|
+
|
|
+ if (pair->predefined_overrides_user) {
|
|
+ log_replacement = TRUE;
|
|
+ files_removed = g_list_prepend (files_removed, pair->user_file);
|
|
+ files_added = g_list_prepend (files_added, pair->predefined_file);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (log_replacement) {
|
|
+ nautilus_debug_log (FALSE, NAUTILUS_DEBUG_LOG_DOMAIN_DESKTOP_ITEMS,
|
|
+ "%s replaces what was in the user's desktop",
|
|
+ uri);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ g_free (uri);
|
|
+ }
|
|
+
|
|
+ nautilus_debug_log_with_file_list (FALSE, NAUTILUS_DEBUG_LOG_DOMAIN_DEBUG_DESKTOP_ITEMS, files_removed,
|
|
+ "forward_files_added_cover: emitting removed files");
|
|
+ nautilus_debug_log_with_file_list (FALSE, NAUTILUS_DEBUG_LOG_DOMAIN_DEBUG_DESKTOP_ITEMS, files_added,
|
|
+ "forward_files_added_cover: emitting added files");
|
|
+
|
|
+ nautilus_directory_emit_files_changed (NAUTILUS_DIRECTORY (desktop), files_removed);
|
|
+ nautilus_directory_emit_files_added (NAUTILUS_DIRECTORY (desktop), files_added);
|
|
+
|
|
+ g_list_free (files_removed);
|
|
+ g_list_free (files_added);
|
|
}
|
|
|
|
static void
|
|
-forward_files_changed_cover (NautilusDirectory *real_directory,
|
|
+forward_files_changed_cover (NautilusDirectory *directory,
|
|
GList *files,
|
|
gpointer callback_data)
|
|
{
|
|
- nautilus_directory_emit_files_changed (NAUTILUS_DIRECTORY (callback_data), files);
|
|
+ NautilusDesktopDirectory *desktop;
|
|
+ gboolean is_predefined_dir;
|
|
+ GList *l;
|
|
+ GList *files_changed;
|
|
+ GList *files_added;
|
|
+
|
|
+ desktop = NAUTILUS_DESKTOP_DIRECTORY (callback_data);
|
|
+
|
|
+ nautilus_debug_log_with_file_list (FALSE, NAUTILUS_DEBUG_LOG_DOMAIN_DEBUG_DESKTOP_ITEMS, files,
|
|
+ "forward_files_changed_cover(): files got changed in %s. files_are_combined=%d",
|
|
+ get_debug_dirname (desktop, directory),
|
|
+ desktop->details->files_are_combined);
|
|
+
|
|
+ if (!desktop->details->files_are_combined) {
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ if (directory == desktop->details->real_directory) {
|
|
+ is_predefined_dir = FALSE;
|
|
+ } else if (directory == desktop->details->predefined_items_dir) {
|
|
+ is_predefined_dir = TRUE;
|
|
+ } else {
|
|
+ g_assert_not_reached ();
|
|
+ }
|
|
+
|
|
+ files_changed = NULL;
|
|
+ files_added = NULL;
|
|
+
|
|
+ for (l = files; l; l = l->next) {
|
|
+ NautilusFile *file;
|
|
+ FilePair *pair;
|
|
+ char *uri;
|
|
+
|
|
+ file = NAUTILUS_FILE (l->data);
|
|
+ uri = nautilus_file_get_uri (file);
|
|
+
|
|
+ nautilus_debug_log (FALSE, NAUTILUS_DEBUG_LOG_DOMAIN_DESKTOP_ITEMS,
|
|
+ "File changed in %s: %s -- determining if it gets overriden",
|
|
+ is_predefined_dir ? "predefined items" : "user items",
|
|
+ uri);
|
|
+
|
|
+ pair = g_hash_table_lookup (desktop->details->file_to_pairs_hash, file);
|
|
+
|
|
+ if (pair == NULL) {
|
|
+ GList node;
|
|
+
|
|
+ /* Huh, we didn't know about that file? Act as if it had been added. */
|
|
+
|
|
+ node.data = file;
|
|
+ node.prev = NULL;
|
|
+ node.next = NULL;
|
|
+
|
|
+ if (nautilus_directory_contains_file (directory, file)) {
|
|
+ nautilus_debug_log (FALSE, NAUTILUS_DEBUG_LOG_DOMAIN_DESKTOP_ITEMS,
|
|
+ "Trying to add %s as a new file",
|
|
+ uri);
|
|
+ forward_files_added_cover (directory, &node, callback_data);
|
|
+ } else {
|
|
+ nautilus_debug_log (FALSE, NAUTILUS_DEBUG_LOG_DOMAIN_DESKTOP_ITEMS,
|
|
+ "Ignoring %s - it no longer exists in its directory",
|
|
+ uri);
|
|
+ }
|
|
+ } else {
|
|
+ gboolean predefined_was_being_used;
|
|
+
|
|
+ predefined_was_being_used = pair->predefined_overrides_user;
|
|
+
|
|
+ if (nautilus_directory_contains_file (directory, file)) {
|
|
+ char *name;
|
|
+ gboolean same_name;
|
|
+
|
|
+ name = nautilus_file_get_name (file);
|
|
+ same_name = strcmp (name, pair->name) == 0;
|
|
+ g_free (name);
|
|
+
|
|
+ if (same_name) {
|
|
+ /* The file still belongs within its pair */
|
|
+ resolve_overrides_in_file_pair (desktop, pair);
|
|
+
|
|
+ if (predefined_was_being_used == pair->predefined_overrides_user) {
|
|
+ if (pair_shows_file (pair, file)) {
|
|
+ nautilus_debug_log (FALSE, NAUTILUS_DEBUG_LOG_DOMAIN_DEBUG_DESKTOP_ITEMS,
|
|
+ "%s is still shown; will emit changed for it",
|
|
+ uri);
|
|
+ files_changed = g_list_prepend (files_changed, file);
|
|
+ } else {
|
|
+ /* Otherwise we weren't exposing the file anyway, so the caller
|
|
+ * doesn't need to know that it changed.
|
|
+ */
|
|
+ nautilus_debug_log (FALSE, NAUTILUS_DEBUG_LOG_DOMAIN_DEBUG_DESKTOP_ITEMS,
|
|
+ "%s changed but wasn't being shown anyway; will ignore it",
|
|
+ uri);
|
|
+ }
|
|
+ } else {
|
|
+ NautilusFile *changed;
|
|
+ NautilusFile *added;
|
|
+ char *added_uri;
|
|
+
|
|
+ if (predefined_was_being_used) {
|
|
+ changed = pair->user_file; /* "got removed from our view" */
|
|
+ added = pair->predefined_file;
|
|
+ } else {
|
|
+ changed = pair->predefined_file; /* as above */
|
|
+ added = pair->user_file;
|
|
+ }
|
|
+
|
|
+ added_uri = nautilus_file_get_uri (added);
|
|
+ nautilus_debug_log (FALSE, NAUTILUS_DEBUG_LOG_DOMAIN_DEBUG_DESKTOP_ITEMS,
|
|
+ "%s is no longer shown; will emit it as changed and emit its pair %s as added",
|
|
+ uri,
|
|
+ added_uri);
|
|
+ g_free (added_uri);
|
|
+
|
|
+ files_changed = g_list_prepend (files_changed, changed);
|
|
+ files_added = g_list_prepend (files_added, added);
|
|
+ }
|
|
+ } else {
|
|
+ GList node;
|
|
+ NautilusFile *remaining_file;
|
|
+
|
|
+ nautilus_debug_log (FALSE, NAUTILUS_DEBUG_LOG_DOMAIN_DEBUG_DESKTOP_ITEMS,
|
|
+ "%s changed name from %s; will emit changed for it, and call files_added to move it to a new pair",
|
|
+ uri,
|
|
+ pair->name);
|
|
+
|
|
+ /* The file no longer belongs in this pair */
|
|
+
|
|
+ g_hash_table_remove (desktop->details->file_to_pairs_hash, file);
|
|
+
|
|
+ if (file == pair->predefined_file) {
|
|
+ pair->predefined_file = NULL;
|
|
+ pair->predefined_overrides_user = FALSE;
|
|
+ remaining_file = pair->user_file;
|
|
+ } else {
|
|
+ g_assert (file == pair->user_file);
|
|
+ pair->user_file = NULL;
|
|
+ pair->predefined_overrides_user = TRUE;
|
|
+ remaining_file = pair->predefined_file;
|
|
+ }
|
|
+
|
|
+ if (remaining_file == NULL) {
|
|
+ g_hash_table_remove (desktop->details->name_to_pairs_hash, pair->name);
|
|
+ free_file_pair (pair);
|
|
+ } else {
|
|
+ files_added = g_list_prepend (files_added, remaining_file);
|
|
+ }
|
|
+
|
|
+ node.data = file;
|
|
+ node.prev = NULL;
|
|
+ node.next = NULL;
|
|
+ nautilus_directory_emit_files_changed (NAUTILUS_DIRECTORY (desktop), &node);
|
|
+
|
|
+ /* Re-insert the file in a new pair */
|
|
+
|
|
+ node.data = file;
|
|
+ node.prev = NULL;
|
|
+ node.next = NULL;
|
|
+ forward_files_added_cover (directory, &node, callback_data);
|
|
+
|
|
+ nautilus_file_unref (file); /* as it was referenced in the old pair */
|
|
+ }
|
|
+ } else {
|
|
+ NautilusFile *remaining_file;
|
|
+
|
|
+ nautilus_debug_log (FALSE, NAUTILUS_DEBUG_LOG_DOMAIN_DEBUG_DESKTOP_ITEMS,
|
|
+ "%s no longer exists in the %s directory; will emit changed for it",
|
|
+ uri,
|
|
+ get_debug_dirname (desktop, directory));
|
|
+
|
|
+ /* The file no longer exists in its directory
|
|
+ * (it got deleted or something), so we'll
|
|
+ * remove it from our pair.
|
|
+ */
|
|
+
|
|
+ files_changed = g_list_prepend (files_changed, file);
|
|
+ g_hash_table_remove (desktop->details->file_to_pairs_hash, file);
|
|
+
|
|
+ if (file == pair->predefined_file) {
|
|
+ pair->predefined_file = NULL;
|
|
+ pair->predefined_overrides_user = FALSE;
|
|
+ remaining_file = pair->user_file;
|
|
+ } else {
|
|
+ g_assert (file == pair->user_file);
|
|
+ pair->user_file = NULL;
|
|
+ pair->predefined_overrides_user = TRUE;
|
|
+ remaining_file = pair->predefined_file;
|
|
+ }
|
|
+
|
|
+ nautilus_file_unref (file);
|
|
+
|
|
+ if (remaining_file == NULL) {
|
|
+ g_hash_table_remove (desktop->details->name_to_pairs_hash, pair->name);
|
|
+ free_file_pair (pair);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ g_free (uri);
|
|
+ }
|
|
+
|
|
+ nautilus_debug_log_with_file_list (FALSE, NAUTILUS_DEBUG_LOG_DOMAIN_DEBUG_DESKTOP_ITEMS, files_changed,
|
|
+ "forward_files_changed_cover: emitting changed files");
|
|
+ nautilus_debug_log_with_file_list (FALSE, NAUTILUS_DEBUG_LOG_DOMAIN_DEBUG_DESKTOP_ITEMS, files_added,
|
|
+ "forward_files_changed_cover: emitting added files");
|
|
+
|
|
+ nautilus_directory_emit_files_changed (NAUTILUS_DIRECTORY (desktop), files_changed);
|
|
+ nautilus_directory_emit_files_added (NAUTILUS_DIRECTORY (desktop), files_added);
|
|
+
|
|
+ g_list_free (files_changed);
|
|
+ g_list_free (files_added);
|
|
+}
|
|
+
|
|
+static void
|
|
+discard_directory (NautilusDesktopDirectory *desktop, NautilusDirectory *dir)
|
|
+{
|
|
+ if (dir == NULL) {
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ g_hash_table_foreach_remove (desktop->details->callbacks, (GHRFunc) gtk_true, NULL);
|
|
+ g_hash_table_foreach_remove (desktop->details->monitors, (GHRFunc) gtk_true, NULL);
|
|
+
|
|
+ g_signal_handlers_disconnect_by_func (dir, done_loading_callback, desktop);
|
|
+ g_signal_handlers_disconnect_by_func (dir, forward_files_added_cover, desktop);
|
|
+ g_signal_handlers_disconnect_by_func (dir, forward_files_changed_cover, desktop);
|
|
+
|
|
+ nautilus_directory_unref (dir);
|
|
}
|
|
|
|
static void
|
|
@@ -464,17 +1545,10 @@ update_desktop_directory (NautilusDesktopDirectory *desktop)
|
|
char *desktop_uri;
|
|
NautilusDirectory *real_directory;
|
|
|
|
- real_directory = desktop->details->real_directory;
|
|
- if (real_directory != NULL) {
|
|
- g_hash_table_foreach_remove (desktop->details->callbacks, (GHRFunc) gtk_true, NULL);
|
|
- g_hash_table_foreach_remove (desktop->details->monitors, (GHRFunc) gtk_true, NULL);
|
|
+ invalidate_combined_files (desktop);
|
|
|
|
- g_signal_handlers_disconnect_by_func (real_directory, done_loading_callback, desktop);
|
|
- g_signal_handlers_disconnect_by_func (real_directory, forward_files_added_cover, desktop);
|
|
- g_signal_handlers_disconnect_by_func (real_directory, forward_files_changed_cover, desktop);
|
|
-
|
|
- nautilus_directory_unref (real_directory);
|
|
- }
|
|
+ discard_directory (desktop, desktop->details->real_directory);
|
|
+ desktop->details->real_directory = NULL;
|
|
|
|
desktop_path = nautilus_get_desktop_directory ();
|
|
desktop_uri = g_filename_to_uri (desktop_path, NULL, NULL);
|
|
@@ -482,6 +1556,8 @@ update_desktop_directory (NautilusDesktopDirectory *desktop)
|
|
g_free (desktop_uri);
|
|
g_free (desktop_path);
|
|
|
|
+ g_signal_connect_object (real_directory, "load_error",
|
|
+ G_CALLBACK (load_error_callback), desktop, 0);
|
|
g_signal_connect_object (real_directory, "done_loading",
|
|
G_CALLBACK (done_loading_callback), desktop, 0);
|
|
g_signal_connect_object (real_directory, "files_added",
|
|
@@ -490,6 +1566,7 @@ update_desktop_directory (NautilusDesktopDirectory *desktop)
|
|
G_CALLBACK (forward_files_changed_cover), desktop, 0);
|
|
|
|
desktop->details->real_directory = real_directory;
|
|
+ desktop->details->real_directory_pending = TRUE;
|
|
}
|
|
|
|
static void
|
|
@@ -500,8 +1577,64 @@ desktop_directory_changed_callback (gpointer data)
|
|
}
|
|
|
|
static void
|
|
+update_predefined_items_dir (NautilusDesktopDirectory *desktop)
|
|
+{
|
|
+ NautilusDirectory *predefined_items_dir;
|
|
+ char *dirname;
|
|
+ char *uri;
|
|
+
|
|
+ invalidate_combined_files (desktop);
|
|
+
|
|
+ discard_directory (desktop, desktop->details->predefined_items_dir);
|
|
+ desktop->details->predefined_items_dir = NULL;
|
|
+
|
|
+ dirname = eel_preferences_get (NAUTILUS_PREFERENCES_DESKTOP_PREDEFINED_ITEMS_DIR);
|
|
+ if (dirname == NULL || *dirname == 0) {
|
|
+ nautilus_debug_log (FALSE, NAUTILUS_DEBUG_LOG_DOMAIN_DESKTOP_ITEMS,
|
|
+ "The predefined_items_dir key is not set; will not have predefined desktop items");
|
|
+ g_free (dirname);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ nautilus_debug_log (desktop->details->initializing, NAUTILUS_DEBUG_LOG_DOMAIN_DESKTOP_ITEMS,
|
|
+ "Using predefined_items_dir = %s", dirname);
|
|
+
|
|
+ uri = g_filename_to_uri (dirname, NULL, NULL);
|
|
+ predefined_items_dir = nautilus_directory_get_by_uri (uri);
|
|
+ g_free (uri);
|
|
+ g_free (dirname);
|
|
+
|
|
+ g_signal_connect_object (predefined_items_dir, "load_error",
|
|
+ G_CALLBACK (load_error_callback), desktop, 0);
|
|
+ g_signal_connect_object (predefined_items_dir, "done_loading",
|
|
+ G_CALLBACK (done_loading_callback), desktop, 0);
|
|
+ g_signal_connect_object (predefined_items_dir, "files_added",
|
|
+ G_CALLBACK (forward_files_added_cover), desktop, 0);
|
|
+ g_signal_connect_object (predefined_items_dir, "files_changed",
|
|
+ G_CALLBACK (forward_files_changed_cover), desktop, 0);
|
|
+
|
|
+ desktop->details->predefined_items_dir = predefined_items_dir;
|
|
+ desktop->details->predefined_items_dir_pending = TRUE;
|
|
+}
|
|
+
|
|
+static void
|
|
+predefined_items_dir_changed_callback (gpointer data)
|
|
+{
|
|
+ NautilusDesktopDirectory *desktop = NAUTILUS_DESKTOP_DIRECTORY (data);
|
|
+
|
|
+ nautilus_debug_log (FALSE, NAUTILUS_DEBUG_LOG_DOMAIN_DESKTOP_ITEMS,
|
|
+ "GConf key for the path for predefined desktop items changed; refreshing...");
|
|
+
|
|
+ update_predefined_items_dir (desktop);
|
|
+ nautilus_directory_force_reload (NAUTILUS_DIRECTORY (desktop));
|
|
+}
|
|
+
|
|
+static void
|
|
nautilus_desktop_directory_instance_init (NautilusDesktopDirectory *desktop)
|
|
{
|
|
+ nautilus_debug_log (TRUE, NAUTILUS_DEBUG_LOG_DOMAIN_DESKTOP_ITEMS,
|
|
+ "Creating the NautilusDesktopDirectory");
|
|
+
|
|
desktop->details = g_new0 (NautilusDesktopDirectoryDetails, 1);
|
|
|
|
desktop->details->callbacks = g_hash_table_new_full
|
|
@@ -510,11 +1643,19 @@ nautilus_desktop_directory_instance_init (NautilusDesktopDirectory *desktop)
|
|
desktop->details->monitors = g_hash_table_new_full (NULL, NULL,
|
|
NULL, (GDestroyNotify)merged_monitor_destroy);
|
|
|
|
+ create_pair_hashes (desktop);
|
|
+
|
|
+ desktop->details->initializing = TRUE;
|
|
+
|
|
update_desktop_directory (NAUTILUS_DESKTOP_DIRECTORY (desktop));
|
|
+ update_predefined_items_dir (desktop);
|
|
|
|
eel_preferences_add_callback (NAUTILUS_PREFERENCES_DESKTOP_IS_HOME_DIR,
|
|
desktop_directory_changed_callback,
|
|
desktop);
|
|
+ eel_preferences_add_callback (NAUTILUS_PREFERENCES_DESKTOP_PREDEFINED_ITEMS_DIR,
|
|
+ predefined_items_dir_changed_callback,
|
|
+ desktop);
|
|
}
|
|
|
|
static void
|
|
diff --git a/libnautilus-private/nautilus-desktop-icon-file.c b/libnautilus-private/nautilus-desktop-icon-file.c
|
|
index 3802dd9..120df10 100644
|
|
--- a/libnautilus-private/nautilus-desktop-icon-file.c
|
|
+++ b/libnautilus-private/nautilus-desktop-icon-file.c
|
|
@@ -26,6 +26,7 @@
|
|
#include <config.h>
|
|
#include "nautilus-desktop-icon-file.h"
|
|
|
|
+#include "nautilus-debug-log.h"
|
|
#include "nautilus-directory-notify.h"
|
|
#include "nautilus-directory-private.h"
|
|
#include "nautilus-file-attributes.h"
|
|
@@ -291,6 +292,9 @@ nautilus_desktop_icon_file_new (NautilusDesktopLink *link)
|
|
list.prev = NULL;
|
|
nautilus_directory_emit_files_added (directory, &list);
|
|
|
|
+ nautilus_debug_log_with_file_list (FALSE, NAUTILUS_DEBUG_LOG_DOMAIN_DEBUG_DESKTOP_ITEMS, &list,
|
|
+ "Created desktop icon file and notified directory:");
|
|
+
|
|
return icon_file;
|
|
}
|
|
|
|
diff --git a/libnautilus-private/nautilus-desktop-link-monitor.c b/libnautilus-private/nautilus-desktop-link-monitor.c
|
|
index 9abdd64..976ccd8 100644
|
|
--- a/libnautilus-private/nautilus-desktop-link-monitor.c
|
|
+++ b/libnautilus-private/nautilus-desktop-link-monitor.c
|
|
@@ -23,6 +23,7 @@
|
|
*/
|
|
|
|
#include <config.h>
|
|
+#include "nautilus-debug-log.h"
|
|
#include "nautilus-desktop-link-monitor.h"
|
|
#include "nautilus-desktop-link.h"
|
|
#include "nautilus-desktop-icon-file.h"
|
|
@@ -356,6 +357,9 @@ nautilus_desktop_link_monitor_init (gpointer object, gpointer klass)
|
|
GList *l, *mounts;
|
|
GMount *mount;
|
|
|
|
+ nautilus_debug_log (FALSE, NAUTILUS_DEBUG_LOG_DOMAIN_DESKTOP_ITEMS,
|
|
+ "Initializing desktop link monitor with all its links");
|
|
+
|
|
monitor = NAUTILUS_DESKTOP_LINK_MONITOR (object);
|
|
|
|
the_link_monitor = monitor;
|
|
diff --git a/libnautilus-private/nautilus-directory-async.c b/libnautilus-private/nautilus-directory-async.c
|
|
index cbe0419..ba67a75 100644
|
|
--- a/libnautilus-private/nautilus-directory-async.c
|
|
+++ b/libnautilus-private/nautilus-directory-async.c
|
|
@@ -24,6 +24,7 @@
|
|
|
|
#include <config.h>
|
|
|
|
+#include "nautilus-debug-log.h"
|
|
#include "nautilus-directory-metafile.h"
|
|
#include "nautilus-directory-notify.h"
|
|
#include "nautilus-directory-private.h"
|
|
@@ -1039,6 +1040,15 @@ directory_load_done (NautilusDirectory *directory,
|
|
GError *error)
|
|
{
|
|
GList *node;
|
|
+ char *uri;
|
|
+
|
|
+ uri = nautilus_directory_get_uri (directory);
|
|
+ nautilus_debug_log (FALSE, NAUTILUS_DEBUG_LOG_DOMAIN_ASYNC,
|
|
+ "Directory %p (%s): directory_load_done: %s",
|
|
+ directory,
|
|
+ uri,
|
|
+ error ? error->message : "success");
|
|
+ g_free (uri);
|
|
|
|
directory->details->directory_loaded = TRUE;
|
|
directory->details->directory_loaded_sent_notification = FALSE;
|
|
diff --git a/libnautilus-private/nautilus-directory.c b/libnautilus-private/nautilus-directory.c
|
|
index 9e6e435..b5d75e1 100644
|
|
--- a/libnautilus-private/nautilus-directory.c
|
|
+++ b/libnautilus-private/nautilus-directory.c
|
|
@@ -25,6 +25,7 @@
|
|
#include <config.h>
|
|
#include "nautilus-directory-private.h"
|
|
|
|
+#include "nautilus-debug-log.h"
|
|
#include "nautilus-directory-metafile.h"
|
|
#include "nautilus-directory-notify.h"
|
|
#include "nautilus-file-attributes.h"
|
|
@@ -1593,6 +1594,8 @@ nautilus_directory_schedule_position_set (GList *position_setting_list)
|
|
char str[64];
|
|
|
|
for (p = position_setting_list; p != NULL; p = p->next) {
|
|
+ GList node;
|
|
+
|
|
item = (NautilusFileChangesQueuePosition *) p->data;
|
|
|
|
file = nautilus_file_get (item->location);
|
|
@@ -1608,6 +1611,12 @@ nautilus_directory_schedule_position_set (GList *position_setting_list)
|
|
NULL,
|
|
str);
|
|
|
|
+ node.data = file;
|
|
+ node.prev = NULL;
|
|
+ node.next = NULL;
|
|
+ nautilus_debug_log_with_file_list (FALSE, NAUTILUS_DEBUG_LOG_DOMAIN_ICON_POSITIONS, &node,
|
|
+ "Directory - saving icon position to \"%s\"", str);
|
|
+
|
|
if (item->set) {
|
|
g_snprintf (str, sizeof (str), "%d", item->screen);
|
|
} else {
|
|
diff --git a/libnautilus-private/nautilus-global-preferences.h b/libnautilus-private/nautilus-global-preferences.h
|
|
index e3de760..d414bed 100644
|
|
--- a/libnautilus-private/nautilus-global-preferences.h
|
|
+++ b/libnautilus-private/nautilus-global-preferences.h
|
|
@@ -214,6 +214,7 @@ typedef enum
|
|
#define NAUTILUS_PREFERENCES_DESKTOP_VOLUMES_VISIBLE "desktop/volumes_visible"
|
|
#define NAUTILUS_PREFERENCES_DESKTOP_NETWORK_VISIBLE "desktop/network_icon_visible"
|
|
#define NAUTILUS_PREFERENCES_DESKTOP_NETWORK_NAME "desktop/network_icon_name"
|
|
+#define NAUTILUS_PREFERENCES_DESKTOP_PREDEFINED_ITEMS_DIR "desktop/predefined_items_dir"
|
|
|
|
void nautilus_global_preferences_init (void);
|
|
char *nautilus_global_preferences_get_default_folder_viewer_preference_as_iid (void);
|
|
diff --git a/src/file-manager/fm-directory-view.c b/src/file-manager/fm-directory-view.c
|
|
index 78d5044..5eafc70 100644
|
|
--- a/src/file-manager/fm-directory-view.c
|
|
+++ b/src/file-manager/fm-directory-view.c
|
|
@@ -8264,14 +8264,11 @@ load_directory (FMDirectoryView *view,
|
|
|
|
view->details->reported_load_error = FALSE;
|
|
|
|
- /* FIXME bugzilla.gnome.org 45062: In theory, we also need to monitor metadata here (as
|
|
- * well as doing a call when ready), in case external forces
|
|
- * change the directory's file metadata.
|
|
- */
|
|
attributes =
|
|
NAUTILUS_FILE_ATTRIBUTE_INFO |
|
|
NAUTILUS_FILE_ATTRIBUTE_MOUNT |
|
|
- NAUTILUS_FILE_ATTRIBUTE_FILESYSTEM_INFO;
|
|
+ NAUTILUS_FILE_ATTRIBUTE_FILESYSTEM_INFO |
|
|
+ NAUTILUS_FILE_ATTRIBUTE_METADATA;
|
|
view->details->metadata_for_directory_as_file_pending = TRUE;
|
|
view->details->metadata_for_files_in_directory_pending = TRUE;
|
|
nautilus_file_call_when_ready
|
|
diff --git a/src/file-manager/fm-icon-view.c b/src/file-manager/fm-icon-view.c
|
|
index a5186d6..827ad5e 100644
|
|
--- a/src/file-manager/fm-icon-view.c
|
|
+++ b/src/file-manager/fm-icon-view.c
|
|
@@ -42,6 +42,7 @@
|
|
#include <gtk/gtk.h>
|
|
#include <glib/gi18n.h>
|
|
#include <gio/gio.h>
|
|
+#include <libnautilus-private/nautilus-debug-log.h>
|
|
#include <libnautilus-private/nautilus-directory-background.h>
|
|
#include <libnautilus-private/nautilus-directory.h>
|
|
#include <libnautilus-private/nautilus-dnd.h>
|
|
@@ -236,6 +237,7 @@ get_stored_icon_position_callback (NautilusIconContainer *container,
|
|
char *position_string, *scale_string;
|
|
gboolean position_good;
|
|
char c;
|
|
+ GList node;
|
|
|
|
g_assert (NAUTILUS_IS_ICON_CONTAINER (container));
|
|
g_assert (NAUTILUS_IS_FILE (file));
|
|
@@ -252,6 +254,13 @@ get_stored_icon_position_callback (NautilusIconContainer *container,
|
|
position_good = sscanf
|
|
(position_string, " %d , %d %c",
|
|
&position->x, &position->y, &c) == 2;
|
|
+
|
|
+ node.data = file;
|
|
+ node.prev = NULL;
|
|
+ node.next = NULL;
|
|
+ nautilus_debug_log_with_file_list (FALSE, NAUTILUS_DEBUG_LOG_DOMAIN_ICON_POSITIONS, &node,
|
|
+ "get_stored_icon_position_callback(): read icon position as \"%s\"", position_string);
|
|
+
|
|
g_free (position_string);
|
|
|
|
/* If it is the desktop directory, maybe the gnome-libs metadata has information about it */
|
|
@@ -2274,11 +2283,20 @@ icon_position_changed_callback (NautilusIconContainer *container,
|
|
|
|
/* Store the new position of the icon in the metadata. */
|
|
if (!fm_icon_view_using_auto_layout (icon_view)) {
|
|
+ GList node;
|
|
+
|
|
position_string = g_strdup_printf
|
|
("%d,%d", position->x, position->y);
|
|
nautilus_file_set_metadata
|
|
(file, NAUTILUS_METADATA_KEY_ICON_POSITION,
|
|
NULL, position_string);
|
|
+
|
|
+ node.data = file;
|
|
+ node.prev = NULL;
|
|
+ node.next = NULL;
|
|
+ nautilus_debug_log_with_file_list (FALSE, NAUTILUS_DEBUG_LOG_DOMAIN_ICON_POSITIONS, &node,
|
|
+ "icon_position_changed_callback() - saving icon position to \"%s\"", position_string);
|
|
+
|
|
g_free (position_string);
|
|
}
|
|
|
|
diff --git a/src/nautilus-desktop-window.c b/src/nautilus-desktop-window.c
|
|
index 6871bde..ea0fc61 100644
|
|
--- a/src/nautilus-desktop-window.c
|
|
+++ b/src/nautilus-desktop-window.c
|
|
@@ -33,6 +33,7 @@
|
|
#include <eel/eel-gtk-macros.h>
|
|
#include <eel/eel-vfs-extensions.h>
|
|
#include <libgnome/gnome-macros.h>
|
|
+#include <libnautilus-private/nautilus-debug-log.h>
|
|
#include <libnautilus-private/nautilus-file-utilities.h>
|
|
#include <libnautilus-private/nautilus-icon-names.h>
|
|
#include <gio/gio.h>
|
|
@@ -118,6 +119,9 @@ nautilus_desktop_window_new (NautilusApplication *application,
|
|
width_request = gdk_screen_get_width (screen);
|
|
height_request = gdk_screen_get_height (screen);
|
|
|
|
+ nautilus_debug_log (TRUE, NAUTILUS_DEBUG_LOG_DOMAIN_DESKTOP_ITEMS,
|
|
+ "Initializing desktop window with size %dx%d", width_request, height_request);
|
|
+
|
|
window = NAUTILUS_DESKTOP_WINDOW
|
|
(gtk_widget_new (nautilus_desktop_window_get_type(),
|
|
"app", application,
|