summaryrefslogtreecommitdiff
path: root/libnautilus-private
diff options
context:
space:
mode:
Diffstat (limited to 'libnautilus-private')
-rw-r--r--libnautilus-private/Makefile.am8
-rw-r--r--libnautilus-private/nautilus-desktop-file-loader.c1223
-rw-r--r--libnautilus-private/nautilus-desktop-file-loader.h85
-rw-r--r--libnautilus-private/nautilus-directory-async.c879
-rw-r--r--libnautilus-private/nautilus-directory-private.h18
-rw-r--r--libnautilus-private/nautilus-directory.c10
-rw-r--r--libnautilus-private/nautilus-file-attributes.h23
-rw-r--r--libnautilus-private/nautilus-file-private.h8
-rw-r--r--libnautilus-private/nautilus-file-queue.c125
-rw-r--r--libnautilus-private/nautilus-file-queue.h52
-rw-r--r--libnautilus-private/nautilus-file.c127
-rw-r--r--libnautilus-private/nautilus-file.h3
-rw-r--r--libnautilus-private/nautilus-icon-container.c70
-rw-r--r--libnautilus-private/nautilus-icon-factory.c173
-rw-r--r--libnautilus-private/nautilus-icon-factory.h5
-rw-r--r--libnautilus-private/nautilus-icon-private.h1
-rw-r--r--libnautilus-private/nautilus-link-desktop-file.c532
-rw-r--r--libnautilus-private/nautilus-link-desktop-file.h61
-rw-r--r--libnautilus-private/nautilus-link-historical.c435
-rw-r--r--libnautilus-private/nautilus-link-historical.h60
-rw-r--r--libnautilus-private/nautilus-link.c628
-rw-r--r--libnautilus-private/nautilus-link.h18
22 files changed, 3575 insertions, 969 deletions
diff --git a/libnautilus-private/Makefile.am b/libnautilus-private/Makefile.am
index 29ac4a442..ce52aa572 100644
--- a/libnautilus-private/Makefile.am
+++ b/libnautilus-private/Makefile.am
@@ -48,6 +48,7 @@ libnautilus_private_la_SOURCES = \
nautilus-bookmark.c \
nautilus-customization-data.c \
nautilus-default-file-icon.c \
+ nautilus-desktop-file-loader.c \
nautilus-directory-async.c \
nautilus-directory-background.c \
nautilus-directory-metafile-monitor.c \
@@ -60,6 +61,7 @@ libnautilus_private_la_SOURCES = \
nautilus-file-changes-queue.c \
nautilus-file-dnd.c \
nautilus-file-operations-progress.c \
+ nautilus-file-queue.c \
nautilus-file-operations.c \
nautilus-file-utilities.c \
nautilus-file.c \
@@ -75,6 +77,8 @@ libnautilus_private_la_SOURCES = \
nautilus-lib-self-check-functions.c \
nautilus-link-set.c \
nautilus-link.c \
+ nautilus-link-desktop-file.c \
+ nautilus-link-historical.c \
nautilus-medusa-support.c \
nautilus-merged-directory.c \
nautilus-metafile-factory.c \
@@ -106,6 +110,7 @@ libnautilus_private_la_SOURCES = \
nautilus-cdrom-extensions.h \
nautilus-customization-data.h \
nautilus-default-file-icon.h \
+ nautilus-desktop-file-loader.h \
nautilus-directory-background.h \
nautilus-directory-metafile-monitor.h \
nautilus-directory-metafile.h \
@@ -124,6 +129,7 @@ libnautilus_private_la_SOURCES = \
nautilus-file-private.h \
nautilus-file-utilities.h \
nautilus-file.h \
+ nautilus-file-queue.h \
nautilus-font-factory.h \
nautilus-global-preferences.h \
nautilus-horizontal-splitter.h \
@@ -139,6 +145,8 @@ libnautilus_private_la_SOURCES = \
nautilus-lib-self-check-functions.h \
nautilus-link-set.h \
nautilus-link.h \
+ nautilus-link-desktop-file.h \
+ nautilus-link-historical.h \
nautilus-medusa-support.h \
nautilus-merged-directory.h \
nautilus-metadata.h \
diff --git a/libnautilus-private/nautilus-desktop-file-loader.c b/libnautilus-private/nautilus-desktop-file-loader.c
new file mode 100644
index 000000000..734afdf9f
--- /dev/null
+++ b/libnautilus-private/nautilus-desktop-file-loader.c
@@ -0,0 +1,1223 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: 8; c-basic-offset: 8 -*- */
+
+/* nautilus-desktop-file-loader.c
+
+ Copyright (C) 2001 Red Hat, Inc.
+
+ Developers: Havoc Pennington <hp@redhat.com>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License
+ as published by the Free Software Foundation; either version 2 of
+ the License, or (at your option) any later version.
+
+ The library is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place -
+ Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include <config.h>
+#include "nautilus-desktop-file-loader.h"
+#include "nautilus-program-choosing.h"
+
+#include <libgnome/libgnome.h>
+#include <libgnomevfs/gnome-vfs-ops.h>
+#include <eel/eel-gnome-extensions.h>
+#include <eel/eel-vfs-extensions.h>
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <ctype.h>
+#include <locale.h>
+#include <iconv.h>
+#include <langinfo.h>
+
+typedef struct NautilusDesktopFileSection NautilusDesktopFileSection;
+typedef struct NautilusDesktopFileAddition NautilusDesktopFileAddition;
+typedef struct NautilusDesktopFileForeachData NautilusDesktopFileForeachData;
+
+typedef void (* NautilusDesktopFileForeachFunc) (NautilusDesktopFile *df,
+ const char *name,
+ gpointer data);
+
+
+struct NautilusDesktopFile {
+ char **lines;
+
+ /* hash of section names, from pointer to start of name (just after
+ * bracket) to NautilusDesktopFileSection structs
+ */
+ GHashTable *section_hash;
+ GList *addition_list;
+
+ NautilusDesktopFileSection *main_section;
+};
+
+struct NautilusDesktopFileSection {
+ /* pointer into a line of df->lines for start of name */
+ const char *name;
+
+ /* hash of keys in the section,
+ * from pointer to start of key name to
+ * pointer to start of value, not copied
+ * from df->lines
+ */
+ GHashTable *key_hash;
+
+ /* First line in the section (not the [section name] line,
+ * but the one after that)
+ */
+ char **start_line;
+};
+
+struct NautilusDesktopFileAddition {
+ NautilusDesktopFileSection *section;
+ char *name;
+ char *value;
+
+ /* used for saving */
+ gboolean saving_section;
+};
+
+struct NautilusDesktopFileForeachData {
+ NautilusDesktopFile *df;
+ NautilusDesktopFileForeachFunc func;
+ gpointer user_data;
+ gboolean include_localized;
+};
+
+char** nautilus_desktop_file_get_lines (NautilusDesktopFile *df);
+void nautilus_desktop_file_foreach_section (NautilusDesktopFile *df,
+ NautilusDesktopFileForeachFunc func,
+ gpointer user_data);
+void nautilus_desktop_file_foreach_key (NautilusDesktopFile *df,
+ const char *section,
+ gboolean include_localized,
+ NautilusDesktopFileForeachFunc func,
+ gpointer user_data);
+
+static NautilusDesktopFile * nautilus_desktop_file_new (void);
+static void hash_lines (NautilusDesktopFile *df);
+static NautilusDesktopFileSection* section_new (const char *name,
+ char **start_line);
+static void section_free (NautilusDesktopFileSection *sect);
+static char* section_dup_name (NautilusDesktopFileSection *sect);
+static char* validated_strdup (const char *str);
+static NautilusDesktopFileAddition* addition_new (NautilusDesktopFileSection *section,
+ const char *name,
+ const char *value);
+static void addition_free (NautilusDesktopFileAddition *addition);
+
+
+static NautilusDesktopFile*
+nautilus_desktop_file_new (void)
+{
+ NautilusDesktopFile *df;
+
+ df = g_new0 (NautilusDesktopFile, 1);
+
+ return df;
+}
+
+GnomeVFSResult
+nautilus_desktop_file_load (const char *uri,
+ NautilusDesktopFile **desktop_file)
+{
+ char *contents;
+ NautilusDesktopFile *df;
+ GnomeVFSResult result;
+ int file_size;
+
+ *desktop_file = NULL;
+ result = eel_read_entire_file (uri, &file_size,
+ &contents);
+ if (result != GNOME_VFS_OK) {
+ return result;
+ }
+
+ df = nautilus_desktop_file_from_string (contents);
+
+ g_free (contents);
+
+ *desktop_file = df;
+
+ return GNOME_VFS_OK;
+}
+
+NautilusDesktopFile*
+nautilus_desktop_file_from_string (const char *data)
+{
+ NautilusDesktopFile *df;
+
+ df = nautilus_desktop_file_new ();
+
+ df->lines = g_strsplit (data, "\n", G_MAXINT);
+
+ hash_lines (df);
+
+ return df;
+}
+
+static GnomeVFSResult
+write_all (GnomeVFSHandle *handle,
+ gconstpointer buffer,
+ GnomeVFSFileSize bytes)
+{
+ GnomeVFSFileSize bytes_written;
+ GnomeVFSResult result;
+
+ while (bytes > 0) {
+ result = gnome_vfs_write (handle, buffer,
+ bytes, &bytes_written);
+ if (result != GNOME_VFS_OK) {
+ return result;
+ }
+ bytes -= bytes_written;
+ }
+
+ return GNOME_VFS_OK;
+}
+
+GnomeVFSResult
+nautilus_desktop_file_save (NautilusDesktopFile *df,
+ const char *uri)
+{
+ NautilusDesktopFileAddition *addition;
+ GnomeVFSHandle *handle;
+ GnomeVFSResult result;
+ char *old_val;
+ GList *list;
+ gint i;
+
+ g_return_val_if_fail (df != NULL, FALSE);
+ g_return_val_if_fail (df->lines != NULL, FALSE);
+
+ result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_WRITE);
+ if (result != GNOME_VFS_OK) {
+ return result;
+ }
+
+ for (i = 0; df->lines[i] != NULL; i++) {
+ gboolean handled_line;
+
+ handled_line = FALSE;
+ for (list = df->addition_list; list; list = list->next) {
+ addition = (NautilusDesktopFileAddition *)list->data;
+
+ if (addition->section->start_line[0] == df->lines[i]) {
+ addition->saving_section = TRUE;
+ }
+
+ if (addition->saving_section && df->lines[i][0] == '[') {
+ addition->saving_section = FALSE;
+ }
+
+ if (addition->saving_section &&
+ (strncmp (addition->name, df->lines[i], strlen (addition->name)) == 0)) {
+ old_val = strstr (df->lines[i], "=");
+ if (old_val == NULL) {
+ continue;
+ }
+ result = write_all (handle,
+ df->lines[i],
+ old_val + 1 - df->lines[i]);
+ if (result != GNOME_VFS_OK) {
+ gnome_vfs_close (handle);
+ return result;
+ }
+ result = write_all (handle,
+ addition->value,
+ strlen (addition->value));
+ if (result != GNOME_VFS_OK) {
+ gnome_vfs_close (handle);
+ return result;
+ }
+ result = write_all (handle, "\n", 1);
+ if (result != GNOME_VFS_OK) {
+ gnome_vfs_close (handle);
+ return result;
+ }
+
+ handled_line = TRUE;
+ }
+ }
+ if (handled_line == FALSE) {
+ result = write_all (handle,
+ df->lines[i],
+ strlen (df->lines[i]));
+ if (result != GNOME_VFS_OK) {
+ gnome_vfs_close (handle);
+ return result;
+ }
+ result = write_all (handle, "\n", 1);
+ if (result != GNOME_VFS_OK) {
+ gnome_vfs_close (handle);
+ return result;
+ }
+ }
+ }
+
+ gnome_vfs_close (handle);
+ return GNOME_VFS_OK;
+}
+
+static void
+destroy_foreach (gpointer key, gpointer value, gpointer data)
+{
+ section_free (value);
+}
+
+
+void
+nautilus_desktop_file_free (NautilusDesktopFile *df)
+{
+ if (df->section_hash != NULL) {
+ g_hash_table_foreach (df->section_hash, destroy_foreach, NULL);
+ g_hash_table_destroy (df->section_hash);
+ }
+
+ g_list_foreach (df->addition_list, (GFunc) addition_free, NULL);
+ g_list_free (df->addition_list);
+ if (df->lines != NULL)
+ g_strfreev (df->lines);
+
+ g_free (df);
+}
+
+
+/* This is cut and pasted from glib 1.3.x
+ * It should be removed when porting to glib 2
+ */
+/**
+ * g_strdupv:
+ * @str_array: %NULL-terminated array of strings
+ *
+ * Copies %NULL-terminated array of strings. The copy is a deep copy;
+ * the new array should be freed by first freeing each string, then
+ * the array itself. g_strfreev() does this for you. If called
+ * on a %NULL value, g_strdupv() simply returns %NULL.
+ *
+ * Return value: a new %NULL-terminated array of strings
+ **/
+static gchar**
+cnp_g_strdupv (gchar **str_array)
+{
+ if (str_array) {
+ gint i;
+ gchar **retval;
+
+ i = 0;
+ while (str_array[i])
+ ++i;
+
+ retval = g_new (gchar*, i + 1);
+
+ i = 0;
+ while (str_array[i]) {
+ retval[i] = g_strdup (str_array[i]);
+ ++i;
+ }
+ retval[i] = NULL;
+
+ return retval;
+ } else {
+ return NULL;
+ }
+}
+
+char**
+nautilus_desktop_file_get_lines (NautilusDesktopFile *df)
+{
+ return cnp_g_strdupv (df->lines);
+}
+
+/* Custom hash functions allow us to avoid strdups */
+static gboolean
+key_equal (gconstpointer v1,
+ gconstpointer v2)
+{
+ const gchar *p1 = v1;
+ const gchar *p2 = v2;
+
+ /* we count '=' and ' ' as terminator
+ * and don't count leading/trailing spaces
+ */
+
+ while (isspace ((guchar)*p1)) {
+ ++p1;
+ }
+
+ while (isspace ((guchar)*p2)) {
+ ++p2;
+ }
+
+ while (*p1 && *p2 &&
+ *p1 != '=' && *p2 != '=' &&
+ !isspace ((guchar)*p1) && !isspace ((guchar)*p2)) {
+ if (*p1 != *p2) {
+ return FALSE;
+ }
+
+ ++p1;
+ ++p2;
+ }
+
+ if (*p1 && *p1 != '=' && !isspace ((guchar)*p1)) {
+ return FALSE;
+ }
+
+ if (*p2 && *p2 != '=' && !isspace ((guchar)*p2)) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static guint
+key_hash (gconstpointer key)
+{
+ const char *p = key;
+ guint h = *p;
+
+ /* we count '=' and ' ' as terminator
+ * and don't count leading/trailing spaces
+ */
+
+ while (isspace ((guchar)*p)) {
+ ++p;
+ }
+
+ if (h) {
+ for (p += 1; *p != '\0' && *p != '=' && !isspace ((guchar)*p); p++) {
+ h = (h << 5) - h + *p;
+ }
+ }
+
+ return h;
+}
+
+static gboolean
+section_equal (gconstpointer v1,
+ gconstpointer v2)
+{
+ const gchar *p1 = v1;
+ const gchar *p2 = v2;
+
+ /* we count ']' as terminator */
+
+ while (*p1 && *p2 &&
+ *p1 != ']' && *p2 != ']') {
+ if (*p1 != *p2) {
+ return FALSE;
+ }
+
+ ++p1;
+ ++p2;
+ }
+
+ if (*p1 && *p1 != ']') {
+ return FALSE;
+ }
+
+ if (*p2 && *p2 != ']') {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static guint
+section_hash (gconstpointer key)
+{
+ const char *p = key;
+ guint h = *p;
+
+ /* we count ']' as terminator */
+
+ if (h) {
+ for (p += 1; *p != '\0' && *p != ']'; p++) {
+ h = (h << 5) - h + *p;
+ }
+ }
+
+ return h;
+}
+
+static void
+hash_lines (NautilusDesktopFile *df)
+{
+ NautilusDesktopFileSection *current_sect;
+ const char *eq;
+ const char *p;
+ char **iter;
+
+ if (df->section_hash == NULL) {
+ df->section_hash = g_hash_table_new (section_hash, section_equal);
+ }
+
+ current_sect = NULL;
+ iter = df->lines;
+
+ while (iter != NULL && *iter != NULL) {
+ p = *iter;
+
+ while (isspace ((guchar)*p)) {
+ ++p;
+ }
+
+ /* blank or comment lines */
+ if (*p == '\0' || *p == '#') {
+ goto next;
+ }
+
+ if (*p == '[') {
+ /* Begin a section */
+ ++p;
+
+ if (*p != ']' &&
+ strchr (p, ']') != NULL) {
+ current_sect = section_new (p, iter + 1);
+
+ g_hash_table_insert (df->section_hash,
+ (char*) current_sect->name,
+ current_sect);
+
+ if (df->main_section == NULL &&
+ (section_equal (current_sect->name, "Desktop Entry") ||
+ section_equal (current_sect->name, "KDE Desktop Entry"))) {
+ df->main_section = current_sect;
+ }
+ }
+ } else {
+ /* should be a key=value line, if not
+ * it's some invalid crap
+ */
+ eq = strchr (p, '=');
+ if (eq == NULL) {
+ goto next;
+ } else {
+ if (current_sect) {
+ ++eq;
+ while (isspace ((guchar)*eq)) {
+ ++eq;
+ }
+ /* could overwrite an earlier copy of
+ * the same key name in this section
+ */
+ g_hash_table_insert (current_sect->key_hash,
+ (char*) p, (char*) eq);
+ }
+ }
+ }
+
+ next:
+ ++iter;
+ }
+}
+
+static NautilusDesktopFileSection*
+section_new (const char *name,
+ char **start_line)
+{
+ NautilusDesktopFileSection *sect;
+
+ sect = g_new (NautilusDesktopFileSection, 1);
+
+ sect->name = name;
+ sect->start_line = start_line;
+ sect->key_hash = g_hash_table_new (key_hash, key_equal);
+
+ return sect;
+}
+
+static void
+section_free (NautilusDesktopFileSection *sect)
+{
+ g_hash_table_destroy (sect->key_hash);
+ g_free (sect);
+}
+
+
+static NautilusDesktopFileAddition *
+addition_new (NautilusDesktopFileSection *section,
+ const char *name,
+ const char *value)
+{
+ NautilusDesktopFileAddition *addition;
+
+ addition = g_new (NautilusDesktopFileAddition, 1);
+
+ addition->section = section;
+ addition->name = g_strdup (name);
+ addition->value = g_strdup (value);
+
+ return addition;
+}
+
+static void
+addition_free (NautilusDesktopFileAddition *addition)
+{
+ g_free (addition->name);
+ g_free (addition->value);
+ g_free (addition);
+}
+
+static char*
+section_dup_name (NautilusDesktopFileSection *sect)
+{
+ const char *name_end;
+
+ name_end = strchr (sect->name, ']');
+
+ g_assert (name_end); /* we were supposed to verify this on initial parse */
+
+ return g_strndup (sect->name, name_end - sect->name);
+}
+
+static NautilusDesktopFileSection*
+get_section (NautilusDesktopFile *df,
+ const char *section)
+{
+ if (df->section_hash == NULL) {
+ return NULL;
+ }
+
+ if (section == NULL) {
+ return df->main_section;
+ } else {
+ return g_hash_table_lookup (df->section_hash, section);
+ }
+}
+
+static void
+section_foreach (gpointer key, gpointer value, gpointer data)
+{
+ NautilusDesktopFileForeachData *fd;
+ NautilusDesktopFileSection *sect;
+ char *name;
+
+ fd = data;
+ sect = value;
+
+ name = section_dup_name (sect);
+
+ (* fd->func) (fd->df, name, fd->user_data);
+
+ g_free (name);
+}
+
+void
+nautilus_desktop_file_foreach_section (NautilusDesktopFile *df,
+ NautilusDesktopFileForeachFunc func,
+ gpointer user_data)
+{
+ if (df->section_hash != NULL) {
+ NautilusDesktopFileForeachData fd;
+
+ fd.df = df;
+ fd.func = func;
+ fd.user_data = user_data;
+ fd.include_localized = FALSE; /* not used */
+
+ g_hash_table_foreach (df->section_hash, section_foreach, &fd);
+ }
+}
+
+
+static void
+key_foreach (gpointer key, gpointer value, gpointer data)
+{
+ NautilusDesktopFileForeachData *fd;
+ char *key_end;
+ char *name;
+
+ fd = data;
+
+ key_end = (char*) key;
+ while (*key_end &&
+ !isspace ((guchar)*key_end) &&
+ *key_end != '=') {
+ ++key_end;
+ }
+
+ name = g_strndup (key, key_end - (char*)key);
+
+ if (fd->include_localized ||
+ (!fd->include_localized && strchr (name, '[') == NULL)) {
+ (* fd->func) (fd->df, name, fd->user_data);
+ }
+
+ g_free (name);
+}
+
+void
+nautilus_desktop_file_foreach_key (NautilusDesktopFile *df,
+ const char *section,
+ gboolean include_localized,
+ NautilusDesktopFileForeachFunc func,
+ gpointer user_data)
+{
+ NautilusDesktopFileSection *sect;
+
+ sect = get_section (df, section);
+
+ if (sect) {
+ NautilusDesktopFileForeachData fd;
+
+ fd.df = df;
+ fd.func = func;
+ fd.user_data = user_data;
+ fd.include_localized = include_localized;
+
+ g_hash_table_foreach (sect->key_hash, key_foreach, &fd);
+ }
+}
+
+static const char*
+get_keyval (NautilusDesktopFile *df,
+ const char *section,
+ const char *keyname)
+{
+ NautilusDesktopFileSection *sect;
+ const char *strval;
+
+ sect = get_section (df, section);
+
+ if (sect == NULL) {
+ return FALSE;
+ }
+
+ strval = g_hash_table_lookup (sect->key_hash,
+ keyname);
+
+ return strval;
+}
+
+static gboolean
+parse_boolean (const char *strval,
+ int len,
+ gboolean *val)
+{
+ if (len < 0) {
+ len = strlen (strval);
+ }
+
+ if (*strval == '1') {
+ *val = TRUE;
+ return TRUE;
+ } else if (len > 3 &&
+ strval[0] == 't' && strval[1] == 'r' &&
+ strval[2] == 'u' && strval[3] == 'e') {
+ *val = TRUE;
+ return TRUE;
+ } else if (*strval == '0') {
+ *val = FALSE;
+ return TRUE;
+ } else if (len > 4 &&
+ strval[0] == 'f' && strval[1] == 'a' &&
+ strval[2] == 'l' && strval[3] == 's' &&
+ strval[4] == 'e') {
+ *val = FALSE;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gboolean
+parse_number (const char *strval,
+ int len,
+ double *val)
+{
+ char *end;
+ double tmp;
+
+ if (len < 0) {
+ len = strlen (strval);
+ }
+
+ tmp = strtod (strval, &end);
+ if (strval == end) {
+ return FALSE;
+ }
+
+ *val = tmp;
+ return TRUE;
+}
+
+
+static void
+get_locale (char **lang,
+ char **lang_country)
+{
+ const char *uscore_pos;
+ const char *at_pos;
+ const char *dot_pos;
+ const char *end_pos;
+ const char *locale;
+ const char *start_lang;
+ const char *end_lang;
+ const char *end_country;
+
+ *lang = NULL;
+ *lang_country = NULL;
+
+ locale = setlocale (LC_MESSAGES, NULL);
+
+ if (locale == NULL) {
+ return;
+ }
+
+ /* lang_country.encoding@modifier */
+
+ uscore_pos = strchr (locale, '_');
+ dot_pos = strchr (uscore_pos ? uscore_pos : locale, '.');
+ at_pos = strchr ((dot_pos != NULL) ? dot_pos : ((uscore_pos != NULL) ? uscore_pos : locale), '@');
+ end_pos = locale + strlen (locale);
+
+ start_lang = locale;
+ end_lang = ((uscore_pos != NULL) ? uscore_pos :
+ ((dot_pos != NULL) ? dot_pos :
+ ((at_pos != NULL) ? at_pos : end_pos)));
+ end_country = ((dot_pos != NULL) ? dot_pos :
+ ((at_pos != NULL) ? at_pos : end_pos));
+
+ if (uscore_pos == NULL) {
+ *lang = g_strndup (start_lang, end_lang - start_lang);
+ } else {
+ *lang = g_strndup (start_lang, end_lang - start_lang);
+ *lang_country = g_strndup (start_lang,
+ end_country - start_lang);
+ }
+}
+
+gboolean
+nautilus_desktop_file_get_boolean (NautilusDesktopFile *df,
+ const char *section,
+ const char *keyname,
+ gboolean *val)
+{
+ const char *strval;
+
+ strval = get_keyval (df, section, keyname);
+
+ if (strval == NULL) {
+ return FALSE;
+ }
+
+ return parse_boolean (strval, -1, val);
+}
+
+gboolean
+nautilus_desktop_file_get_number (NautilusDesktopFile *df,
+ const char *section,
+ const char *keyname,
+ double *val)
+{
+ const char *strval;
+
+ strval = get_keyval (df, section, keyname);
+
+ if (strval == NULL) {
+ return FALSE;
+ }
+
+ return parse_number (strval, -1, val);
+}
+
+/* Totally bogus UTF-8 stuff */
+gboolean
+nautilus_desktop_file_get_string (NautilusDesktopFile *df,
+ const char *section,
+ const char *keyname,
+ char **val)
+{
+ const char *strval;
+ char *tmp;
+
+ strval = get_keyval (df, section, keyname);
+
+ if (strval == NULL) {
+ return FALSE;
+ }
+
+ tmp = validated_strdup (strval);
+
+ if (tmp != NULL) {
+ *val = tmp;
+ }
+
+ return tmp != NULL;
+}
+
+gboolean
+nautilus_desktop_file_get_locale_string (NautilusDesktopFile *df,
+ const char *section,
+ const char *keyname,
+ char **val)
+{
+ const char *strval;
+ char *lang;
+ char *lang_country;
+ char *s;
+
+ strval = NULL;
+ get_locale (&lang, &lang_country);
+
+ /* FIXME - we need to try de_DE.ENCODING in addition to what
+ * we are trying here.
+ */
+
+ /* Try "Foo[de_DE]" */
+ if (lang_country) {
+ s = g_strconcat (keyname, "[", lang_country, "]", NULL);
+ strval = get_keyval (df, section, s);
+ g_free (s);
+ if (strval != NULL)
+ goto done;
+ }
+
+ /* Try "Foo[de]" */
+ if (lang) {
+ s = g_strconcat (keyname, "[", lang, "]", NULL);
+ strval = get_keyval (df, section, s);
+ g_free (s);
+ if (strval != NULL)
+ goto done;
+ }
+
+ /* Fall back to not localized */
+ strval = get_keyval (df, section, keyname);
+
+ done:
+ g_free (lang);
+ g_free (lang_country);
+
+ if (strval == NULL) {
+ return FALSE;
+ } else {
+ char *tmp = validated_strdup (strval);
+
+ if (tmp != NULL) {
+ *val = tmp;
+ }
+ return tmp != NULL;
+ }
+}
+
+gboolean
+nautilus_desktop_file_get_regexp (NautilusDesktopFile *df,
+ const char *section,
+ const char *keyname,
+ char **val)
+{
+ return nautilus_desktop_file_get_string (df, section, keyname, val);
+}
+
+/* This is extremely broken */
+
+#define F 0 /* character never appears in text */
+#define T 1 /* character appears in plain ASCII text */
+#define I 2 /* character appears in ISO-8859 text */
+#define X 3 /* character appears in non-ISO extended ASCII (Mac, IBM PC) */
+
+static char text_chars[256] = {
+ /* BEL BS HT LF FF CR */
+ F, F, F, F, F, F, F, T, T, T, T, F, T, T, F, F, /* 0x0X */
+ /* ESC */
+ F, F, F, F, F, F, F, F, F, F, F, T, F, F, F, F, /* 0x1X */
+ T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, /* 0x2X */
+ T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, /* 0x3X */
+ T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, /* 0x4X */
+ T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, /* 0x5X */
+ T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, /* 0x6X */
+ T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, F, /* 0x7X */
+ /* NEL */
+ X, X, X, X, X, T, X, X, X, X, X, X, X, X, X, X, /* 0x8X */
+ X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, /* 0x9X */
+ I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, /* 0xaX */
+ I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, /* 0xbX */
+ I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, /* 0xcX */
+ I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, /* 0xdX */
+ I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, /* 0xeX */
+ I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I /* 0xfX */
+};
+
+static int
+looks_utf8 (const unsigned char *buf,
+ int nbytes,
+ unsigned long *ubuf,
+ int *ulen)
+{
+ int i, n;
+ unsigned long c;
+ int gotone = 0;
+
+ *ulen = 0;
+
+ for (i = 0; i < nbytes; i++) {
+ if ((buf[i] & 0x80) == 0) { /* 0xxxxxxx is plain ASCII */
+ /*
+ * Even if the whole file is valid UTF-8 sequences,
+ * still reject it if it uses weird control characters.
+ */
+ if (text_chars[buf[i]] != T) {
+ return 0;
+ }
+
+ if (ubuf != NULL) {
+ ubuf[(*ulen)++] = buf[i];
+ }
+ } else if ((buf[i] & 0x40) == 0) { /* 10xxxxxx never 1st byte */
+
+ return 0;
+ } else { /* 11xxxxxx begins UTF-8 */
+ int following;
+
+ if ((buf[i] & 0x20) == 0) { /* 110xxxxx */
+ c = buf[i] & 0x1f;
+ following = 1;
+ } else if ((buf[i] & 0x10) == 0) { /* 1110xxxx */
+ c = buf[i] & 0x0f;
+ following = 2;
+ } else if ((buf[i] & 0x08) == 0) { /* 11110xxx */
+ c = buf[i] & 0x07;
+ following = 3;
+ } else if ((buf[i] & 0x04) == 0) { /* 111110xx */
+ c = buf[i] & 0x03;
+ following = 4;
+ } else if ((buf[i] & 0x02) == 0) { /* 1111110x */
+ c = buf[i] & 0x01;
+ following = 5;
+ } else {
+ return 0;
+ }
+
+ for (n = 0; n < following; n++) {
+ i++;
+ if (i >= nbytes) {
+ goto done;
+ }
+
+ if ((buf[i] & 0x80) == 0 || (buf[i] & 0x40)) {
+ return 0;
+ }
+
+ c = (c << 6) + (buf[i] & 0x3f);
+ }
+
+ if (ubuf != NULL) {
+ ubuf[(*ulen)++] = c;
+ }
+ gotone = 1;
+ }
+ }
+ done:
+ return gotone; /* don't claim it's UTF-8 if it's all 7-bit */
+}
+
+G_LOCK_DEFINE_STATIC (init_validate);
+
+static char*
+validated_strdup (const char *str)
+{
+ static gchar *locale;
+ static gboolean initialized = FALSE;
+ gchar *pout, *pin, *buf;
+ gint len, ulen = 0, ib, ob;
+ iconv_t fd;
+
+ G_LOCK (init_validate);
+ if (!initialized) {
+ /* whee, we are totally unportable (broken too) */
+ setlocale (LC_CTYPE, "");
+ locale = nl_langinfo (CODESET);
+ initialized = TRUE;
+ }
+ G_UNLOCK (init_validate);
+
+ buf = NULL;
+
+ len = strlen (str);
+ if (looks_utf8 (str, len, NULL, &ulen)) {
+ if ((fd = iconv_open (locale, "UTF-8")) != (iconv_t)-1) {
+ ib = len;
+ ob = ib * 3;
+ pout = buf = g_new0 (gchar, ob);
+ pin = (char*) str;
+
+ /* not portable either */
+
+ if (iconv (fd, &pin, &ib, &pout, &ob) == (size_t)-1) {
+ g_free (buf);
+ buf = NULL;
+ }
+
+ iconv_close (fd);
+ }
+ } else {
+ buf = g_strdup (str);
+ }
+
+ return buf;
+}
+
+/* This is cut and pasted from glib 1.3.x
+ * It should be removed when porting to glib 2
+ */
+static void
+cnp_g_string_append_len (GString *str,
+ const char *s,
+ int len)
+{
+ if (len < 0) {
+ g_string_append (str, s);
+ } else {
+ char *tmp;
+ tmp = g_strndup (s, len);
+ g_string_append (str, tmp);
+ g_free (tmp);
+ }
+}
+
+static char*
+nautilus_desktop_file_sub_formats (NautilusDesktopFile *df,
+ const char *src)
+{
+ GString *new;
+ const char *p;
+ const char *end;
+ char *retval;
+
+ new = g_string_new ("");
+
+ p = src;
+ end = src;
+
+ p = strchr (p, '%');
+ while (p) {
+ if (p != end) {
+ /* Append what we just scanned over */
+ cnp_g_string_append_len (new, end, p - end);
+ }
+
+ end = p;
+
+ ++p; /* past the % */
+ switch (*p) {
+ case 'f':
+ case 'F':
+ case 'u':
+ case 'U':
+ case 'd':
+ case 'D':
+ case 'n':
+ case 'N':
+ case 'i':
+ case 'm':
+ case 'c':
+ case 'k':
+ case 'v':
+ /* We don't actually sub anything for now */
+ ++p;
+ break;
+ case '%':
+ /* Escaped % */
+ g_string_append (new, "%");
+ ++p;
+ break;
+ default:
+ /* some broken .desktop-spec-incompliant crack;
+ * try just skipping it.
+ */
+ ++p;
+ break;
+ }
+
+ p = strchr (p, '%');
+ }
+
+ g_string_append (new, end);
+
+ retval = new->str;
+ g_string_free (new, FALSE);
+ return retval;
+}
+
+void
+nautilus_desktop_file_launch (NautilusDesktopFile *df)
+{
+ char *type;
+ char *url;
+ char *exec;
+ char *subst;
+
+
+
+ if (!nautilus_desktop_file_get_string (df, NULL, "Type", &type)) {
+ return;
+ }
+
+ if (strcmp (type, "Link") == 0) {
+ url = NULL;
+ nautilus_desktop_file_get_string (df, NULL, "URL", &url);
+
+ if (url != NULL) {
+ gnome_url_show (url);
+ }
+
+ g_free (url);
+ } else if (strcmp (type, "Application") == 0) {
+ exec = NULL;
+ nautilus_desktop_file_get_string (df, NULL, "Exec", &exec);
+
+ if (exec != NULL) {
+ gboolean in_terminal;
+
+ subst = nautilus_desktop_file_sub_formats (df, exec);
+
+ in_terminal = FALSE;
+ nautilus_desktop_file_get_boolean (df, NULL, "Terminal", &in_terminal);
+
+ nautilus_launch_application_from_command ("",
+ subst,
+ NULL,
+ in_terminal);
+ g_free (subst);
+ }
+
+ g_free (exec);
+ }
+
+ g_free (type);
+}
+
+
+gboolean
+nautilus_desktop_file_set_string (NautilusDesktopFile *df,
+ const char *section,
+ const char *keyname,
+ const char *value)
+{
+ NautilusDesktopFileSection *sect;
+ NautilusDesktopFileAddition *addition;
+
+ sect = get_section (df, section);
+ if (sect == NULL) {
+ return FALSE;
+ }
+
+ addition = addition_new (sect, keyname, value);
+ df->addition_list = g_list_append (df->addition_list, addition);
+
+ return TRUE;
+}
diff --git a/libnautilus-private/nautilus-desktop-file-loader.h b/libnautilus-private/nautilus-desktop-file-loader.h
new file mode 100644
index 000000000..e82303707
--- /dev/null
+++ b/libnautilus-private/nautilus-desktop-file-loader.h
@@ -0,0 +1,85 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: 8; c-basic-offset: 8 -*- */
+
+/* eel-desktop-file-loader.h
+
+ Copyright (C) 2001 Red Hat, Inc.
+
+ Developers: Havoc Pennington <hp@redhat.com>
+ Alexander Larsson <alexl@redhat.com>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License
+ as published by the Free Software Foundation; either version 2 of
+ the License, or (at your option) any later version.
+
+ The library is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place -
+ Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#ifndef NAUTILUS_DESKTOP_FILE_LOADER_H
+#define NAUTILUS_DESKTOP_FILE_LOADER_H
+
+#include <glib.h>
+#include <libgnomevfs/gnome-vfs-result.h>
+
+typedef struct NautilusDesktopFile NautilusDesktopFile;
+
+/* This is a quick-hack to read and modify .desktop files.
+ * It has severe limitations, but does what nautilus
+ * needs right now. You cannot create new sections or add non-existing keys.
+ *
+ * The right way to solve this is to write a good desktop file parser
+ * and put it in another library for use by the panel, nautilus etc.
+ */
+
+GnomeVFSResult nautilus_desktop_file_load (const char *uri,
+ NautilusDesktopFile **desktop_file);
+NautilusDesktopFile *nautilus_desktop_file_from_string (const char *data);
+GnomeVFSResult nautilus_desktop_file_save (NautilusDesktopFile *df,
+ const char *uri);
+void nautilus_desktop_file_free (NautilusDesktopFile *df);
+
+/* This is crap, it just ignores the %f etc. in the exec string,
+ * and has no error handling.
+ */
+void nautilus_desktop_file_launch (NautilusDesktopFile *df);
+
+
+gboolean nautilus_desktop_file_get_boolean (NautilusDesktopFile *df,
+ const char *section,
+ const char *keyname,
+ gboolean *val);
+gboolean nautilus_desktop_file_get_number (NautilusDesktopFile *df,
+ const char *section,
+ const char *keyname,
+ double *val);
+gboolean nautilus_desktop_file_get_string (NautilusDesktopFile *df,
+ const char *section,
+ const char *keyname,
+ char **val);
+gboolean nautilus_desktop_file_get_locale_string (NautilusDesktopFile *df,
+ const char *section,
+ const char *keyname,
+ char **val);
+gboolean nautilus_desktop_file_get_regexp (NautilusDesktopFile *df,
+ const char *section,
+ const char *keyname,
+ char **val);
+gboolean nautilus_desktop_file_set_string (NautilusDesktopFile *df,
+ const char *section,
+ const char *keyname,
+ const char *value);
+
+
+/* Some getters and setters are missing, they should be added as needed */
+
+
+#endif /* NAUTILUS_DESKTOP_FILE_LOADER_H */
diff --git a/libnautilus-private/nautilus-directory-async.c b/libnautilus-private/nautilus-directory-async.c
index 4e2fbd212..5ed4ee009 100644
--- a/libnautilus-private/nautilus-directory-async.c
+++ b/libnautilus-private/nautilus-directory-async.c
@@ -38,6 +38,8 @@
#include <ctype.h>
#include <libxml/parser.h>
#include <libxml/xmlmemory.h>
+#include <libgnome/gnome-metadata.h>
+#include <libgnome/gnome-mime-info.h>
#include <gtk/gtkmain.h>
#include <stdlib.h>
#include <stdio.h>
@@ -68,7 +70,7 @@ struct TopLeftTextReadState {
EelReadFileHandle *handle;
};
-struct ActivationURIReadState {
+struct LinkInfoReadState {
NautilusFile *file;
EelReadFileHandle *handle;
};
@@ -102,13 +104,27 @@ static GHashTable *async_jobs;
#endif
/* Forward declarations for functions that need them. */
-static void deep_count_load (NautilusDirectory *directory,
- const char *uri);
-static gboolean request_is_satisfied (NautilusDirectory *directory,
- NautilusFile *file,
- Request *request);
-static void cancel_loading_attributes (NautilusDirectory *directory,
- GList *file_attributes);
+static void deep_count_load (NautilusDirectory *directory,
+ const char *uri);
+static gboolean request_is_satisfied (NautilusDirectory *directory,
+ NautilusFile *file,
+ Request *request);
+static void cancel_loading_attributes (NautilusDirectory *directory,
+ GList *file_attributes);
+static void add_all_files_to_work_queue (NautilusDirectory *directory);
+static void link_info_done (NautilusDirectory *directory,
+ NautilusFile *file,
+ const char *uri,
+ const char *name,
+ const char *icon);
+static gboolean file_needs_high_priority_work_done (NautilusDirectory *directory,
+ NautilusFile *file);
+static gboolean file_needs_low_priority_work_done (NautilusDirectory *directory,
+ NautilusFile *file);
+static void move_file_to_low_priority_queue (NautilusDirectory *directory,
+ NautilusFile *file);
+
+
/* Some helpers for case-insensitive strings.
* Move to nautilus-glib-extensions?
@@ -376,14 +392,13 @@ top_left_cancel (NautilusDirectory *directory)
}
static void
-activation_uri_cancel (NautilusDirectory *directory)
+link_info_cancel (NautilusDirectory *directory)
{
- if (directory->details->activation_uri_read_state != NULL) {
- eel_read_file_cancel (directory->details->activation_uri_read_state->handle);
- g_free (directory->details->activation_uri_read_state);
- directory->details->activation_uri_read_state = NULL;
-
- async_job_end (directory, "activation URI");
+ if (directory->details->link_info_read_state != NULL) {
+ eel_read_file_cancel (directory->details->link_info_read_state->handle);
+ g_free (directory->details->link_info_read_state);
+ directory->details->link_info_read_state = NULL;
+ async_job_end (directory, "link info");
}
}
@@ -536,13 +551,15 @@ nautilus_directory_set_up_request (Request *request,
NAUTILUS_FILE_ATTRIBUTE_ACTIVATION_URI,
eel_strcmp_compare_func) != NULL) {
request->file_info = TRUE;
- request->activation_uri = TRUE;
+ request->link_info = TRUE;
+ }
+
+ if (g_list_find_custom (file_attributes,
+ NAUTILUS_FILE_ATTRIBUTE_CUSTOM_NAME,
+ eel_strcmp_compare_func) != NULL) {
+ request->file_info = TRUE;
+ request->link_info = TRUE;
}
-
- request->metafile |= g_list_find_custom
- (file_attributes,
- NAUTILUS_FILE_ATTRIBUTE_METADATA,
- eel_strcmp_compare_func) != NULL;
/* FIXME bugzilla.gnome.org 42435:
* Some file attributes are really pieces of metadata.
@@ -555,10 +572,19 @@ nautilus_directory_set_up_request (Request *request,
* directly (would need some funky char trick to prevent
* namespace collisions).
*/
+ if (g_list_find_custom (file_attributes,
+ NAUTILUS_FILE_ATTRIBUTE_CUSTOM_ICON,
+ eel_strcmp_compare_func) != NULL) {
+ request->metafile = TRUE;
+ request->file_info = TRUE;
+ request->link_info = TRUE;
+ }
+
request->metafile |= g_list_find_custom
(file_attributes,
- NAUTILUS_FILE_ATTRIBUTE_CUSTOM_ICON,
+ NAUTILUS_FILE_ATTRIBUTE_METADATA,
eel_strcmp_compare_func) != NULL;
+
}
void
@@ -618,6 +644,13 @@ nautilus_directory_monitor_add_internal (NautilusDirectory *directory,
nautilus_directory_register_metadata_monitor (directory);
}
+ /* Put the monitor file or all the files on the work queue. */
+ if (file != NULL) {
+ nautilus_directory_add_file_to_work_queue (directory, file);
+ } else {
+ add_all_files_to_work_queue (directory);
+ }
+
/* Kick off I/O. */
nautilus_directory_async_state_changed (directory);
}
@@ -1052,6 +1085,8 @@ nautilus_directory_monitor_remove_internal (NautilusDirectory *directory,
update_metadata_monitors (directory);
+ /* XXX - do we need to remove anything from the work queue? */
+
nautilus_directory_async_state_changed (directory);
}
@@ -1080,6 +1115,9 @@ nautilus_directory_remove_file_monitors (NautilusDirectory *directory,
}
update_metadata_monitors (directory);
+
+ /* XXX - do we need to remove anything from the work queue? */
+
nautilus_directory_async_state_changed (directory);
return (FileMonitors *) result;
@@ -1103,6 +1141,8 @@ nautilus_directory_add_file_monitors (NautilusDirectory *directory,
list = &directory->details->monitor_list;
*list = g_list_concat (*list, (GList *) monitors);
+ nautilus_directory_add_file_to_work_queue (directory, file);
+
update_metadata_monitors (directory);
nautilus_directory_async_state_changed (directory);
}
@@ -1224,6 +1264,13 @@ nautilus_directory_call_when_ready_internal (NautilusDirectory *directory,
nautilus_directory_register_metadata_monitor (directory);
}
+ /* Put the callback file or all the files on the work queue. */
+ if (file != NULL) {
+ nautilus_directory_add_file_to_work_queue (directory, file);
+ } else {
+ add_all_files_to_work_queue (directory);
+ }
+
nautilus_directory_async_state_changed (directory);
}
@@ -1325,7 +1372,10 @@ directory_count_callback (GnomeVFSAsyncHandle *handle,
/* Record either a failure or success. */
if (result != GNOME_VFS_ERROR_EOF) {
count_file->details->directory_count_failed = TRUE;
+ count_file->details->got_directory_count = FALSE;
+ count_file->details->directory_count = 0;
} else {
+ count_file->details->directory_count_failed = FALSE;
count_file->details->got_directory_count = TRUE;
count_file->details->directory_count = entries_read;
}
@@ -1459,9 +1509,9 @@ nautilus_async_destroying_file (NautilusFile *file)
directory->details->top_left_read_state->file = NULL;
changed = TRUE;
}
- if (directory->details->activation_uri_read_state != NULL
- && directory->details->activation_uri_read_state->file == file) {
- directory->details->activation_uri_read_state->file = NULL;
+ if (directory->details->link_info_read_state != NULL
+ && directory->details->link_info_read_state->file == file) {
+ directory->details->link_info_read_state->file = NULL;
changed = TRUE;
}
@@ -1474,9 +1524,8 @@ nautilus_async_destroying_file (NautilusFile *file)
static gboolean
lacks_directory_count (NautilusFile *file)
{
- return nautilus_file_is_directory (file)
- && nautilus_file_should_show_directory_item_count (file)
- && !file->details->directory_count_is_up_to_date;
+ return !file->details->directory_count_is_up_to_date
+ && nautilus_file_should_show_directory_item_count (file);
}
static gboolean
@@ -1495,9 +1544,9 @@ wants_directory_count (const Request *request)
static gboolean
lacks_top_left (NautilusFile *file)
{
- return nautilus_file_should_get_top_left_text (file)
- && nautilus_file_contains_text (file)
- && !file->details->top_left_text_is_up_to_date;
+ return file->details->file_info_is_up_to_date &&
+ !file->details->top_left_text_is_up_to_date
+ && nautilus_file_should_get_top_left_text (file);
}
static gboolean
@@ -1522,8 +1571,7 @@ wants_info (const Request *request)
static gboolean
lacks_deep_count (NautilusFile *file)
{
- return nautilus_file_is_directory (file)
- && file->details->deep_counts_status != NAUTILUS_REQUEST_DONE;
+ return file->details->deep_counts_status != NAUTILUS_REQUEST_DONE;
}
static gboolean
@@ -1535,8 +1583,7 @@ wants_deep_count (const Request *request)
static gboolean
lacks_mime_list (NautilusFile *file)
{
- return nautilus_file_is_directory (file)
- && !file->details->mime_list_is_up_to_date;
+ return !file->details->mime_list_is_up_to_date;
}
static gboolean
@@ -1553,16 +1600,28 @@ wants_mime_list (const Request *request)
}
static gboolean
-lacks_activation_uri (NautilusFile *file)
-{
- return file->details->info != NULL
- && !file->details->activation_uri_is_up_to_date;
+lacks_link_info (NautilusFile *file)
+{
+ if (file->details->file_info_is_up_to_date &&
+ !file->details->link_info_is_up_to_date) {
+ if ((nautilus_file_is_mime_type (file, "application/x-gmc-link") &&
+ nautilus_file_is_in_desktop (file)) ||
+ nautilus_file_is_nautilus_link (file) ||
+ nautilus_file_is_directory (file)) {
+ return TRUE;
+ } else {
+ link_info_done (file->details->directory, file, NULL, NULL, NULL);
+ return FALSE;
+ }
+ } else {
+ return FALSE;
+ }
}
static gboolean
-wants_activation_uri (const Request *request)
+wants_link_info (const Request *request)
{
- return request->activation_uri;
+ return request->link_info;
}
@@ -1628,8 +1687,8 @@ request_is_satisfied (NautilusDirectory *directory,
}
}
- if (request->activation_uri) {
- if (has_problem (directory, file, lacks_activation_uri)) {
+ if (request->link_info) {
+ if (has_problem (directory, file, lacks_link_info)) {
return FALSE;
}
}
@@ -1845,7 +1904,7 @@ nautilus_directory_stop_monitoring_file_list (NautilusDirectory *directory)
}
static void
-file_list_start (NautilusDirectory *directory)
+file_list_start_or_stop (NautilusDirectory *directory)
{
if (nautilus_directory_is_anyone_monitoring_file_list (directory)) {
start_monitoring_file_list (directory);
@@ -1857,21 +1916,12 @@ file_list_start (NautilusDirectory *directory)
void
nautilus_file_invalidate_count_and_mime_list (NautilusFile *file)
{
- NautilusDirectory *parent_directory;
+ GList *attributes = NULL;
- parent_directory = file->details->directory;
-
- if (parent_directory->details->count_file == file) {
- directory_count_cancel (parent_directory);
- }
- if (parent_directory->details->mime_list_file == file) {
- mime_list_cancel (parent_directory);
- }
-
- file->details->directory_count_is_up_to_date = FALSE;
- file->details->mime_list_is_up_to_date = FALSE;
+ attributes = g_list_prepend (attributes, NAUTILUS_FILE_ATTRIBUTE_DIRECTORY_ITEM_COUNT);
+ attributes = g_list_prepend (attributes, NAUTILUS_FILE_ATTRIBUTE_DIRECTORY_ITEM_MIME_TYPES);
- nautilus_directory_async_state_changed (parent_directory);
+ nautilus_file_invalidate_attributes (file, attributes);
}
@@ -1927,6 +1977,7 @@ nautilus_directory_force_reload_internal (NautilusDirectory *directory,
/* Start a new directory count. */
nautilus_directory_invalidate_count_and_mime_list (directory);
+ add_all_files_to_work_queue (directory);
nautilus_directory_async_state_changed (directory);
}
@@ -1990,108 +2041,11 @@ is_needy (NautilusFile *file,
return FALSE;
}
-static NautilusFile *
-select_needy_file (NautilusDirectory *directory,
- FileCheck check_missing,
- RequestCheck check_wanted)
-{
- GList *node, *node_2;
- ReadyCallback *callback;
- Monitor *monitor;
- NautilusFile *file;
-
- /* Quick out if no one is interested. */
- for (node = directory->details->call_when_ready_list;
- node != NULL; node = node->next) {
- callback = node->data;
- if ((* check_wanted) (&callback->request)) {
- break;
- }
- }
- if (node == NULL) {
- for (node = directory->details->monitor_list;
- node != NULL; node = node->next) {
- monitor = node->data;
- if ((* check_wanted) (&monitor->request)) {
- break;
- }
- }
- if (node == NULL) {
- return NULL;
- }
- }
-
- /* Search for a file that has an unfulfilled request. */
- for (node = directory->details->file_list;
- node != NULL; node = node->next) {
- file = node->data;
- if ((* check_missing) (file)) {
- for (node_2 = directory->details->call_when_ready_list;
- node_2 != NULL; node_2 = node_2->next) {
- callback = node_2->data;
- if ((callback->file == NULL || callback->file == file)
- && (* check_wanted) (&callback->request)) {
- break;
- }
- }
- if (node_2 != NULL) {
- return file;
- }
- for (node_2 = directory->details->monitor_list;
- node_2 != NULL; node_2 = node_2->next) {
- monitor = node_2->data;
- if (monitor_includes_file (monitor, file)
- && (* check_wanted) (&monitor->request)) {
- break;
- }
- }
- if (node_2 != NULL) {
- return file;
- }
- }
- }
-
- /* Finally, check the file for the directory itself. */
- file = directory->details->as_file;
- if (file != NULL) {
- if ((* check_missing) (file)) {
- for (node_2 = directory->details->call_when_ready_list;
- node_2 != NULL; node_2 = node_2->next) {
- callback = node_2->data;
- if (callback->file == file
- && (* check_wanted) (&callback->request)) {
- break;
- }
- }
- if (node_2 != NULL) {
- return file;
- }
- for (node_2 = directory->details->monitor_list;
- node_2 != NULL; node_2 = node_2->next) {
- monitor = node_2->data;
- if (monitor->file == file
- && (* check_wanted) (&monitor->request)) {
- break;
- }
- }
- if (node_2 != NULL) {
- return file;
- }
- }
- }
-
- return NULL;
-}
-
static void
-directory_count_start (NautilusDirectory *directory)
+directory_count_stop (NautilusDirectory *directory)
{
NautilusFile *file;
- char *uri;
- /* If there's already a count in progress, check to be sure
- * it's still wanted.
- */
if (directory->details->count_in_progress != NULL) {
file = directory->details->count_file;
if (file != NULL) {
@@ -2107,12 +2061,30 @@ directory_count_start (NautilusDirectory *directory)
/* The count is not wanted, so stop it. */
directory_count_cancel (directory);
}
+}
- /* Figure out which file to get a count for. */
- file = select_needy_file (directory,
- should_get_directory_count_now,
- wants_directory_count);
- if (file == NULL) {
+static void
+directory_count_start (NautilusDirectory *directory,
+ NautilusFile *file)
+{
+ char *uri;
+
+ if (directory->details->count_in_progress != NULL) {
+ return;
+ }
+
+ if (!is_needy (file,
+ should_get_directory_count_now,
+ wants_directory_count)) {
+ return;
+ }
+
+ if (!nautilus_file_is_directory (file)) {
+ file->details->directory_count_is_up_to_date = TRUE;
+ file->details->directory_count_failed = FALSE;
+ file->details->got_directory_count = FALSE;
+
+ nautilus_directory_async_state_changed (directory);
return;
}
@@ -2251,14 +2223,10 @@ deep_count_load (NautilusDirectory *directory, const char *uri)
}
static void
-deep_count_start (NautilusDirectory *directory)
+deep_count_stop (NautilusDirectory *directory)
{
NautilusFile *file;
- char *uri;
- /* If there's already a count in progress, check to be sure
- * it's still wanted.
- */
if (directory->details->deep_count_in_progress != NULL) {
file = directory->details->deep_count_file;
if (file != NULL) {
@@ -2274,12 +2242,28 @@ deep_count_start (NautilusDirectory *directory)
/* The count is not wanted, so stop it. */
deep_count_cancel (directory);
}
+}
- /* Figure out which file to get a count for. */
- file = select_needy_file (directory,
- lacks_deep_count,
- wants_deep_count);
- if (file == NULL) {
+static void
+deep_count_start (NautilusDirectory *directory,
+ NautilusFile *file)
+{
+ char *uri;
+
+ if (directory->details->deep_count_in_progress != NULL) {
+ return;
+ }
+
+ if (!is_needy (file,
+ lacks_deep_count,
+ wants_deep_count)) {
+ return;
+ }
+
+ if (!nautilus_file_is_directory (file)) {
+ file->details->deep_counts_status = NAUTILUS_REQUEST_NOT_STARTED;
+
+ nautilus_directory_async_state_changed (directory);
return;
}
@@ -2386,14 +2370,10 @@ mime_list_load (NautilusDirectory *directory, const char *uri)
}
static void
-mime_list_start (NautilusDirectory *directory)
+mime_list_stop (NautilusDirectory *directory)
{
NautilusFile *file;
- char *uri;
- /* If there's already a count in progress, check to be sure
- * it's still wanted.
- */
if (directory->details->mime_list_in_progress != NULL) {
file = directory->details->mime_list_file;
if (file != NULL) {
@@ -2409,12 +2389,34 @@ mime_list_start (NautilusDirectory *directory)
/* The count is not wanted, so stop it. */
mime_list_cancel (directory);
}
+}
+
+static void
+mime_list_start (NautilusDirectory *directory,
+ NautilusFile *file)
+{
+ char *uri;
+
+ mime_list_stop (directory);
+
+ if (directory->details->mime_list_in_progress != NULL) {
+ return;
+ }
/* Figure out which file to get a mime list for. */
- file = select_needy_file (directory,
- should_get_mime_list,
- wants_mime_list);
- if (file == NULL) {
+ if (!is_needy (file,
+ should_get_mime_list,
+ wants_mime_list)) {
+ return;
+ }
+
+ if (!nautilus_file_is_directory (file)) {
+ g_list_free (file->details->mime_list);
+ file->details->mime_list_failed = FALSE;
+ file->details->got_directory_count = FALSE;
+ file->details->mime_list_is_up_to_date = TRUE;
+
+ nautilus_directory_async_state_changed (directory);
return;
}
@@ -2446,8 +2448,6 @@ top_left_read_done (NautilusDirectory *directory)
g_assert (directory->details->top_left_read_state->handle == NULL);
g_assert (NAUTILUS_IS_FILE (directory->details->top_left_read_state->file));
- directory->details->top_left_read_state->file->details->got_top_left_text = TRUE;
-
g_free (directory->details->top_left_read_state);
directory->details->top_left_read_state = NULL;
@@ -2466,10 +2466,7 @@ top_left_read_callback (GnomeVFSResult result,
directory = NAUTILUS_DIRECTORY (callback_data);
- nautilus_directory_ref (directory);
-
directory->details->top_left_read_state->handle = NULL;
-
directory->details->top_left_read_state->file->details->top_left_text_is_up_to_date = TRUE;
changed_file = NULL;
@@ -2479,21 +2476,16 @@ top_left_read_callback (GnomeVFSResult result,
nautilus_extract_top_left_text (file_contents, bytes_read);
directory->details->top_left_read_state->file->details->got_top_left_text = TRUE;
-
- changed_file = directory->details->top_left_read_state->file;
- nautilus_file_ref (changed_file);
-
- g_free (file_contents);
+ } else {
+ g_free (directory->details->top_left_read_state->file->details->top_left_text);
+ directory->details->top_left_read_state->file->details->got_top_left_text = FALSE;
}
-
- top_left_read_done (directory);
- if (changed_file != NULL) {
- nautilus_file_changed (changed_file);
- nautilus_file_unref (changed_file);
- }
+ g_free (file_contents);
- nautilus_directory_unref (directory);
+ nautilus_file_changed (directory->details->top_left_read_state->file);
+
+ top_left_read_done (directory);
}
static gboolean
@@ -2509,14 +2501,10 @@ top_left_read_more_callback (GnomeVFSFileSize bytes_read,
}
static void
-top_left_start (NautilusDirectory *directory)
+top_left_stop (NautilusDirectory *directory)
{
NautilusFile *file;
- char *uri;
- /* If there's already a read in progress, check to be sure
- * it's still wanted.
- */
if (directory->details->top_left_read_state != NULL) {
file = directory->details->top_left_read_state->file;
if (file != NULL) {
@@ -2532,12 +2520,31 @@ top_left_start (NautilusDirectory *directory)
/* The top left is not wanted, so stop it. */
top_left_cancel (directory);
}
+}
+
+static void
+top_left_start (NautilusDirectory *directory,
+ NautilusFile *file)
+{
+ char *uri;
+
+ if (directory->details->top_left_read_state != NULL) {
+ return;
+ }
/* Figure out which file to read the top left for. */
- file = select_needy_file (directory,
- lacks_top_left,
- wants_top_left);
- if (file == NULL) {
+ if (!is_needy (file,
+ lacks_top_left,
+ wants_top_left)) {
+ return;
+ }
+
+ if (!nautilus_file_contains_text (file)) {
+ g_free (file->details->top_left_text);
+ file->details->got_top_left_text = FALSE;
+ file->details->top_left_text_is_up_to_date = TRUE;
+
+ nautilus_directory_async_state_changed (directory);
return;
}
@@ -2615,16 +2622,10 @@ get_info_callback (GnomeVFSAsyncHandle *handle,
}
static void
-file_info_start (NautilusDirectory *directory)
+file_info_stop (NautilusDirectory *directory)
{
NautilusFile *file;
- char *uri;
- GnomeVFSURI *vfs_uri;
- GList fake_list;
- /* If there's already a file info fetch in progress, check to
- * be sure it's still wanted.
- */
if (directory->details->get_info_in_progress != NULL) {
file = directory->details->get_info_file;
if (file != NULL) {
@@ -2638,27 +2639,42 @@ file_info_start (NautilusDirectory *directory)
/* The info is not wanted, so stop it. */
file_info_cancel (directory);
}
+}
+
+static void
+file_info_start (NautilusDirectory *directory,
+ NautilusFile *file)
+{
+ char *uri;
+ GnomeVFSURI *vfs_uri;
+ GList fake_list;
+
+ file_info_stop (directory);
+
+ if (directory->details->get_info_in_progress != NULL) {
+ return;
+ }
- /* Figure out which file to get file info for. */
- do {
- file = select_needy_file (directory, lacks_info, wants_info);
- if (file == NULL) {
- return;
- }
-
- uri = nautilus_file_get_uri (file);
- vfs_uri = gnome_vfs_uri_new (uri);
- g_free (uri);
-
- if (vfs_uri == NULL) {
- file->details->file_info_is_up_to_date = TRUE;
- file->details->get_info_failed = TRUE;
- file->details->get_info_error = GNOME_VFS_ERROR_INVALID_URI;
- nautilus_file_changed (file);
- }
- } while (vfs_uri == NULL);
+ if (!is_needy (file, lacks_info, wants_info)) {
+ return;
+ }
+
+ uri = nautilus_file_get_uri (file);
+ vfs_uri = gnome_vfs_uri_new (uri);
+ g_free (uri);
+
+ /* If we can't even get info, fill in the info and go on.
+ */
+
+ if (vfs_uri == NULL) {
+ file->details->file_info_is_up_to_date = TRUE;
+ file->details->get_info_failed = TRUE;
+ file->details->get_info_error = GNOME_VFS_ERROR_INVALID_URI;
+
+ nautilus_directory_async_state_changed (directory);
+ return;
+ }
- /* Found one we need to get the info for. */
if (!async_job_start (directory, "file info")) {
return;
}
@@ -2676,44 +2692,56 @@ file_info_start (NautilusDirectory *directory)
gnome_vfs_uri_unref (vfs_uri);
}
+
static void
-activation_uri_done (NautilusDirectory *directory,
- NautilusFile *file,
- const char *uri)
+link_info_done (NautilusDirectory *directory,
+ NautilusFile *file,
+ const char *uri,
+ const char *name,
+ const char *icon)
{
- file->details->activation_uri_is_up_to_date = TRUE;
+ file->details->link_info_is_up_to_date = TRUE;
- file->details->got_activation_uri = TRUE;
+ file->details->got_link_info = TRUE;
g_free (file->details->activation_uri);
+ g_free (file->details->custom_name);
+ g_free (file->details->custom_icon_uri);
file->details->activation_uri = g_strdup (uri);
+ file->details->custom_name = g_strdup (name);
+ file->details->custom_icon_uri = g_strdup (icon);
- nautilus_file_changed (file);
-
- async_job_end (directory, "activation URI");
nautilus_directory_async_state_changed (directory);
}
+
static void
-activation_uri_read_done (NautilusDirectory *directory,
- const char *uri)
+link_info_read_done (NautilusDirectory *directory,
+ const char *uri,
+ const char *name,
+ const char *icon)
{
NautilusFile *file;
- file = directory->details->activation_uri_read_state->file;
- g_free (directory->details->activation_uri_read_state);
- directory->details->activation_uri_read_state = NULL;
+ file = directory->details->link_info_read_state->file;
+ g_free (directory->details->link_info_read_state);
+ directory->details->link_info_read_state = NULL;
- activation_uri_done (directory, file, uri);
+ nautilus_file_ref (file);
+ link_info_done (directory, file, uri, name, icon);
+ nautilus_file_changed (file);
+ nautilus_file_unref (file);
+ async_job_end (directory, "link info");
}
+
static void
-activation_uri_nautilus_link_read_callback (GnomeVFSResult result,
- GnomeVFSFileSize bytes_read,
- char *file_contents,
- gpointer callback_data)
+link_info_nautilus_link_read_callback (GnomeVFSResult result,
+ GnomeVFSFileSize bytes_read,
+ char *file_contents,
+ gpointer callback_data)
{
NautilusDirectory *directory;
- char *buffer, *uri;
+ char *buffer, *uri, *name, *icon;
directory = NAUTILUS_DIRECTORY (callback_data);
@@ -2724,29 +2752,39 @@ activation_uri_nautilus_link_read_callback (GnomeVFSResult result,
/* FIXME bugzilla.gnome.org 42433: We should report this error to the user. */
g_free (file_contents);
uri = NULL;
+ name = NULL;
+ icon = NULL;
} else {
/* The gnome-xml parser requires a zero-terminated array. */
buffer = g_realloc (file_contents, bytes_read + 1);
buffer[bytes_read] = '\0';
uri = nautilus_link_get_link_uri_given_file_contents (buffer, bytes_read);
+ name = nautilus_link_get_link_name_given_file_contents (buffer, bytes_read);
+ icon = nautilus_link_get_link_icon_given_file_contents (buffer, bytes_read);
g_free (buffer);
}
- activation_uri_read_done (directory, uri);
+ link_info_read_done (directory, uri, name, icon);
g_free (uri);
+ g_free (name);
+ g_free (icon);
nautilus_directory_unref (directory);
}
+
+
+
static void
-activation_uri_gmc_link_read_callback (GnomeVFSResult result,
- GnomeVFSFileSize bytes_read,
- char *file_contents,
- gpointer callback_data)
+link_info_gmc_link_read_callback (GnomeVFSResult result,
+ GnomeVFSFileSize bytes_read,
+ char *file_contents,
+ gpointer callback_data)
{
NautilusDirectory *directory;
- char *end_of_line, *uri;
-
+ char *end_of_line, *uri, *name, *path, *icon, *icon_path;
+ int size, res;
+
directory = NAUTILUS_DIRECTORY (callback_data);
nautilus_directory_ref (directory);
@@ -2755,6 +2793,8 @@ activation_uri_gmc_link_read_callback (GnomeVFSResult result,
if (result != GNOME_VFS_OK || !eel_str_has_prefix (file_contents, "URL: ")) {
/* FIXME bugzilla.gnome.org 42433: We should report this error to the user. */
uri = NULL;
+ name = NULL;
+ icon = NULL;
} else {
/* Make sure we don't run off the end of the buffer. */
end_of_line = memchr (file_contents, '\n', bytes_read);
@@ -2763,19 +2803,51 @@ activation_uri_gmc_link_read_callback (GnomeVFSResult result,
} else {
uri = g_strndup (file_contents, bytes_read);
}
+
+ path = gnome_vfs_get_local_path_from_uri (uri);
+
+ if (path != NULL) {
+ /* FIXME: this gnome_metata_get call is synchronous, but better to
+ * have it here where the results will at least be cached than in
+ * nautilus_file_get_name.
+ */
+ res = gnome_metadata_get (path, "icon-name", &size, &name);
+ } else {
+ res = -1;
+ }
+
+ if (res == 0) {
+ name = NULL;
+ }
+
+ if (path != NULL) {
+ res = gnome_metadata_get (path, "icon-filename", &size, &icon_path);
+ } else {
+ res = -1;
+ }
+
+ if (res == 0 && icon_path != NULL) {
+ icon = gnome_vfs_get_uri_from_local_path (icon_path);
+ g_free (icon_path);
+ } else {
+ icon = NULL;
+ }
+
}
g_free (file_contents);
- activation_uri_read_done (directory, uri ? uri + 5 : NULL);
+ link_info_read_done (directory, uri ? uri + 5 : NULL, name, icon);
g_free (uri);
+ g_free (name);
+ g_free (icon);
nautilus_directory_unref (directory);
}
static gboolean
-activation_uri_gmc_link_read_more_callback (GnomeVFSFileSize bytes_read,
- const char *file_contents,
- gpointer callback_data)
+link_info_gmc_link_read_more_callback (GnomeVFSFileSize bytes_read,
+ const char *file_contents,
+ gpointer callback_data)
{
g_assert (NAUTILUS_IS_DIRECTORY (callback_data));
@@ -2783,96 +2855,165 @@ activation_uri_gmc_link_read_more_callback (GnomeVFSFileSize bytes_read,
return bytes_read < 512;
}
+static char *
+make_dot_directory_uri (const char *uri)
+{
+ char *dot_directory_uri;
+ GnomeVFSURI *vfs_uri;
+ GnomeVFSURI *dot_dir_vfs_uri;
+
+ /* FIXME: what we really need is a uri_append_file_name call
+ * that works on strings, so we can avoid the VFS parsing step.
+ */
+
+ vfs_uri = gnome_vfs_uri_new (uri);
+ if (vfs_uri == NULL) {
+ return NULL;
+ }
+
+ dot_dir_vfs_uri = gnome_vfs_uri_append_file_name (vfs_uri, ".directory");
+ dot_directory_uri = gnome_vfs_uri_to_string (dot_dir_vfs_uri, GNOME_VFS_URI_HIDE_NONE);
+
+ gnome_vfs_uri_unref (vfs_uri);
+ gnome_vfs_uri_unref (dot_dir_vfs_uri);
+
+ return dot_directory_uri;
+}
+
+
static void
-activation_uri_start (NautilusDirectory *directory)
+link_info_stop (NautilusDirectory *directory)
{
NautilusFile *file;
- char *mime_type, *uri;
- gboolean gmc_style_link, nautilus_style_link;
- /* If there's already a activation URI read in progress, check
- * to be sure it's still wanted.
- */
- if (directory->details->activation_uri_read_state != NULL) {
- file = directory->details->activation_uri_read_state->file;
+ if (directory->details->link_info_read_state != NULL) {
+ file = directory->details->link_info_read_state->file;
+
if (file != NULL) {
g_assert (NAUTILUS_IS_FILE (file));
g_assert (file->details->directory == directory);
if (is_needy (file,
- lacks_activation_uri,
- wants_activation_uri)) {
+ lacks_link_info,
+ wants_link_info)) {
return;
}
}
- /* The count is not wanted, so stop it. */
- activation_uri_cancel (directory);
+ /* The link info is not wanted, so stop it. */
+ link_info_cancel (directory);
}
+}
- /* Figure out which file to get activation_uri for. */
- file = select_needy_file (directory,
- lacks_activation_uri,
- wants_activation_uri);
- if (file == NULL) {
+
+static void
+link_info_start (NautilusDirectory *directory,
+ NautilusFile *file)
+{
+ char *uri, *dot_directory_uri = NULL;
+ gboolean gmc_style_link, nautilus_style_link, is_directory;
+
+ if (directory->details->link_info_read_state != NULL) {
return;
}
- if (!async_job_start (directory, "activation URI")) {
+ if (!is_needy (file,
+ lacks_link_info,
+ wants_link_info)) {
return;
}
/* Figure out if it is a link. */
- mime_type = nautilus_file_get_mime_type (file);
- gmc_style_link = eel_strcasecmp (mime_type, "application/x-gmc-link") == 0;
- g_free (mime_type);
+ gmc_style_link = nautilus_file_is_mime_type (file, "application/x-gmc-link") &&
+ nautilus_file_is_in_desktop (file);
nautilus_style_link = nautilus_file_is_nautilus_link (file);
+ is_directory = nautilus_file_is_directory (file);
+
+ uri = nautilus_file_get_uri (file);
+
+ if (is_directory) {
+ dot_directory_uri = make_dot_directory_uri (uri);
+ }
/* If it's not a link we are done. If it is, we need to read it. */
- if (!(gmc_style_link || nautilus_style_link)) {
- activation_uri_done (directory, file, NULL);
+ if (!(gmc_style_link || nautilus_style_link || (is_directory && dot_directory_uri != NULL) )) {
+ link_info_done (directory, file, NULL, NULL, NULL);
} else {
- directory->details->activation_uri_read_state = g_new0 (ActivationURIReadState, 1);
- directory->details->activation_uri_read_state->file = file;
- uri = nautilus_file_get_uri (file);
+ if (!async_job_start (directory, "link info")) {
+ g_free (dot_directory_uri);
+ g_free (uri);
+ return;
+ }
+
+ directory->details->link_info_read_state = g_new0 (LinkInfoReadState, 1);
+ directory->details->link_info_read_state->file = file;
if (gmc_style_link) {
- directory->details->activation_uri_read_state->handle = eel_read_file_async
+ directory->details->link_info_read_state->handle = eel_read_file_async
(uri,
- activation_uri_gmc_link_read_callback,
- activation_uri_gmc_link_read_more_callback,
+ link_info_gmc_link_read_callback,
+ link_info_gmc_link_read_more_callback,
directory);
+ } else if (is_directory) {
+ directory->details->link_info_read_state->handle = eel_read_entire_file_async
+ (dot_directory_uri,
+ link_info_nautilus_link_read_callback,
+ directory);
+ g_free (dot_directory_uri);
} else {
- directory->details->activation_uri_read_state->handle = eel_read_entire_file_async
+ directory->details->link_info_read_state->handle = eel_read_entire_file_async
(uri,
- activation_uri_nautilus_link_read_callback,
+ link_info_nautilus_link_read_callback,
directory);
}
- g_free (uri);
}
+ g_free (uri);
}
static void
start_or_stop_io (NautilusDirectory *directory)
{
- /* Start or stop getting file info. */
- file_info_start (directory);
+ NautilusFile *file;
/* Start or stop reading files. */
- file_list_start (directory);
-
- /* Start or stop getting directory counts. */
- directory_count_start (directory);
- deep_count_start (directory);
+ file_list_start_or_stop (directory);
+
+ /* Stop any no longer wanted attribute fetches. */
+ file_info_stop (directory);
+ directory_count_stop (directory);
+ deep_count_stop (directory);
+ mime_list_stop (directory);
+ top_left_stop (directory);
+ link_info_stop (directory);
+
+ /* Take files that are all done off the queue. */
+ while (!nautilus_file_queue_is_empty (directory->details->high_priority_queue)) {
+ file = nautilus_file_queue_head (directory->details->high_priority_queue);
+
+ if (file_needs_high_priority_work_done (directory, file)) {
+ /* Start getting attributes if possible */
+ file_info_start (directory, file);
+ link_info_start (directory, file);
+ return;
+ } else {
+ move_file_to_low_priority_queue (directory, file);
+ }
+ }
- /* Start or stop getting mime lists. */
- mime_list_start (directory);
+ /* High priority queue must be empty */
+ while (!nautilus_file_queue_is_empty (directory->details->low_priority_queue)) {
+ file = nautilus_file_queue_head (directory->details->low_priority_queue);
- /* Start or stop getting top left pieces of files. */
- top_left_start (directory);
+ if (file_needs_low_priority_work_done (directory, file)) {
+ /* Start getting attributes if possible */
+ directory_count_start (directory, file);
+ deep_count_start (directory, file);
+ mime_list_start (directory, file);
+ top_left_start (directory, file);
+ return;
+ } else {
+ nautilus_directory_remove_file_from_work_queue (directory, file);
- /* Start or stop getting activation URIs, which includes
- * reading the contents of Nautilus and GMC link files.
- */
- activation_uri_start (directory);
+ }
+ }
}
/* Call this when the monitor or call when ready list changes,
@@ -2916,11 +3057,11 @@ void
nautilus_directory_cancel (NautilusDirectory *directory)
{
/* Arbitrary order (kept alphabetical). */
- activation_uri_cancel (directory);
deep_count_cancel (directory);
directory_count_cancel (directory);
file_info_cancel (directory);
file_list_cancel (directory);
+ link_info_cancel (directory);
mime_list_cancel (directory);
top_left_cancel (directory);
@@ -2980,15 +3121,16 @@ cancel_file_info_for_file (NautilusDirectory *directory,
}
static void
-cancel_activation_uri_for_file (NautilusDirectory *directory,
+cancel_link_info_for_file (NautilusDirectory *directory,
NautilusFile *file)
{
- if (directory->details->activation_uri_read_state != NULL &&
- directory->details->activation_uri_read_state->file == file) {
- activation_uri_cancel (directory);
+ if (directory->details->link_info_read_state != NULL &&
+ directory->details->link_info_read_state->file == file) {
+ link_info_cancel (directory);
}
}
+
static void
cancel_loading_attributes (NautilusDirectory *directory,
GList *file_attributes)
@@ -3013,8 +3155,8 @@ cancel_loading_attributes (NautilusDirectory *directory,
if (request.file_info) {
file_info_cancel (directory);
}
- if (request.activation_uri) {
- file_info_cancel (directory);
+ if (request.link_info) {
+ link_info_cancel (directory);
}
/* FIXME bugzilla.gnome.org 45064: implement cancelling metadata when we
@@ -3048,8 +3190,8 @@ nautilus_directory_cancel_loading_file_attributes (NautilusDirectory *directory,
if (request.file_info) {
cancel_file_info_for_file (directory, file);
}
- if (request.activation_uri) {
- cancel_activation_uri_for_file (directory, file);
+ if (request.link_info) {
+ cancel_link_info_for_file (directory, file);
}
/* FIXME bugzilla.gnome.org 45064: implement cancelling metadata when we
@@ -3057,3 +3199,106 @@ nautilus_directory_cancel_loading_file_attributes (NautilusDirectory *directory,
nautilus_directory_async_state_changed (directory);
}
+
+
+
+static gboolean
+file_needs_high_priority_work_done (NautilusDirectory *directory,
+ NautilusFile *file)
+{
+ if (is_needy (file, lacks_info, wants_info)) {
+ return TRUE;
+ }
+
+ if (is_needy (file, lacks_link_info, wants_link_info)) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gboolean
+file_needs_low_priority_work_done (NautilusDirectory *directory,
+ NautilusFile *file)
+{
+ if (is_needy (file, lacks_directory_count, wants_directory_count)) {
+ return TRUE;
+ }
+
+ if (is_needy (file, lacks_deep_count, wants_deep_count)) {
+ return TRUE;
+ }
+
+ if (is_needy (file, lacks_mime_list, wants_mime_list)) {
+ return TRUE;
+ }
+
+ if (is_needy (file, lacks_top_left, wants_top_left)) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gboolean
+file_needs_work_done (NautilusDirectory *directory,
+ NautilusFile *file)
+{
+ return (file_needs_high_priority_work_done (directory, file) ||
+ file_needs_low_priority_work_done (directory, file));
+}
+
+
+void
+nautilus_directory_add_file_to_work_queue (NautilusDirectory *directory,
+ NautilusFile *file)
+{
+ if (!file_needs_work_done (directory, file)) {
+ return;
+ }
+
+ nautilus_file_queue_enqueue (directory->details->high_priority_queue,
+ file);
+}
+
+
+static void
+add_all_files_to_work_queue (NautilusDirectory *directory)
+{
+ GList *node;
+ NautilusFile *file;
+
+ for (node = directory->details->file_list; node != NULL; node = node->next) {
+ file = NAUTILUS_FILE (node->data);
+
+ nautilus_directory_add_file_to_work_queue (directory, file);
+ }
+}
+
+void
+nautilus_directory_remove_file_from_work_queue (NautilusDirectory *directory,
+ NautilusFile *file)
+{
+ nautilus_file_queue_remove (directory->details->high_priority_queue,
+ file);
+ nautilus_file_queue_remove (directory->details->low_priority_queue,
+ file);
+}
+
+
+static void
+move_file_to_low_priority_queue (NautilusDirectory *directory,
+ NautilusFile *file)
+{
+ if (!file_needs_low_priority_work_done (directory, file)) {
+ nautilus_file_queue_remove (directory->details->high_priority_queue,
+ file);
+ return;
+ }
+
+ /* Must add before removing to avoid ref underflow */
+ nautilus_file_queue_enqueue (directory->details->low_priority_queue,
+ file);
+ nautilus_file_queue_remove (directory->details->high_priority_queue,
+ file);
+}
diff --git a/libnautilus-private/nautilus-directory-private.h b/libnautilus-private/nautilus-directory-private.h
index b7742d4d1..0546990cf 100644
--- a/libnautilus-private/nautilus-directory-private.h
+++ b/libnautilus-private/nautilus-directory-private.h
@@ -27,6 +27,7 @@
#include "nautilus-file.h"
#include "nautilus-metafile-server.h"
#include "nautilus-monitor.h"
+#include "nautilus-file-queue.h"
#include <eel/eel-vfs-extensions.h>
#include <libxml/tree.h>
#include <libgnomevfs/gnome-vfs-file-info.h>
@@ -35,7 +36,7 @@
#include <libgnomevfs/gnome-vfs-utils.h>
#include <libnautilus/nautilus-idle-queue.h>
-typedef struct ActivationURIReadState ActivationURIReadState;
+typedef struct LinkInfoReadState LinkInfoReadState;
typedef struct TopLeftTextReadState TopLeftTextReadState;
typedef struct FileMonitors FileMonitors;
@@ -50,6 +51,10 @@ struct NautilusDirectoryDetails
GList *file_list;
GHashTable *file_hash;
+ /* Queues of files needing some I/O done. */
+ NautilusFileQueue *high_priority_queue;
+ NautilusFileQueue *low_priority_queue;
+
/* These lists are going to be pretty short. If we think they
* are going to get big, we can use hash tables instead.
*/
@@ -97,14 +102,15 @@ struct NautilusDirectoryDetails
GnomeVFSAsyncHandle *get_info_in_progress;
TopLeftTextReadState *top_left_read_state;
- ActivationURIReadState *activation_uri_read_state;
+
+ LinkInfoReadState *link_info_read_state;
GList *file_operations_in_progress; /* list of FileOperation * */
};
/* A request for information about one or more files. */
typedef struct {
- gboolean activation_uri;
+ gboolean link_info;
gboolean deep_count;
gboolean directory_count;
gboolean file_info;
@@ -205,6 +211,12 @@ void nautilus_directory_end_file_name_change (NautilusD
GList *node);
void nautilus_directory_moved (const char *from_uri,
const char *to_uri);
+/* Interface to the work queue. */
+
+void nautilus_directory_add_file_to_work_queue (NautilusDirectory *directory,
+ NautilusFile *file);
+void nautilus_directory_remove_file_from_work_queue (NautilusDirectory *directory,
+ NautilusFile *file);
/* debugging functions */
int nautilus_directory_number_outstanding (void);
diff --git a/libnautilus-private/nautilus-directory.c b/libnautilus-private/nautilus-directory.c
index da5a91cc8..8fd819f59 100644
--- a/libnautilus-private/nautilus-directory.c
+++ b/libnautilus-private/nautilus-directory.c
@@ -128,6 +128,8 @@ nautilus_directory_initialize (gpointer object, gpointer klass)
directory->details = g_new0 (NautilusDirectoryDetails, 1);
directory->details->file_hash = g_hash_table_new (g_str_hash, g_str_equal);
+ directory->details->high_priority_queue = nautilus_file_queue_new ();
+ directory->details->low_priority_queue = nautilus_file_queue_new ();
directory->details->idle_queue = nautilus_idle_queue_new ();
}
@@ -195,6 +197,8 @@ nautilus_directory_destroy (GtkObject *object)
}
g_assert (directory->details->file_list == NULL);
g_hash_table_destroy (directory->details->file_hash);
+ nautilus_file_queue_destroy (directory->details->high_priority_queue);
+ nautilus_file_queue_destroy (directory->details->low_priority_queue);
nautilus_idle_queue_destroy (directory->details->idle_queue);
g_assert (directory->details->directory_load_in_progress == NULL);
g_assert (directory->details->count_in_progress == NULL);
@@ -309,7 +313,8 @@ nautilus_directory_make_uri_canonical (const char *uri)
* created. (See bugzilla.gnome.org 43322 for an example.)
*/
canonical = eel_str_strip_trailing_chr (canonical_maybe_trailing_slash, '/');
- if (strcmp (canonical, canonical_maybe_trailing_slash) != 0) {
+ if (strcmp (canonical, canonical_maybe_trailing_slash) != 0 &&
+ strcmp (canonical, "favorites:") != 0) {
/* If some trailing '/' were stripped, there's the possibility,
* that we stripped away all the '/' from a uri that has only
* '/' characters. If you change this code, check to make sure
@@ -561,6 +566,7 @@ nautilus_directory_add_file (NautilusDirectory *directory, NautilusFile *file)
/* Ref if we are monitoring. */
if (nautilus_directory_is_file_list_monitored (directory)) {
nautilus_file_ref (file);
+ nautilus_directory_add_file_to_work_queue (directory, file);
}
}
@@ -583,6 +589,8 @@ nautilus_directory_remove_file (NautilusDirectory *directory, NautilusFile *file
(directory->details->file_list, node);
g_list_free_1 (node);
+ nautilus_directory_remove_file_from_work_queue (directory, file);
+
if (!file->details->unconfirmed) {
directory->details->confirmed_file_count--;
}
diff --git a/libnautilus-private/nautilus-file-attributes.h b/libnautilus-private/nautilus-file-attributes.h
index c71e8caf6..df28ad33b 100644
--- a/libnautilus-private/nautilus-file-attributes.h
+++ b/libnautilus-private/nautilus-file-attributes.h
@@ -29,16 +29,17 @@
* interest in changes to the attributes or when waiting for them.
*/
-#define NAUTILUS_FILE_ATTRIBUTE_ACTIVATION_URI "activation URI"
-#define NAUTILUS_FILE_ATTRIBUTE_CAPABILITIES "capabilities"
-#define NAUTILUS_FILE_ATTRIBUTE_CUSTOM_ICON "custom icon"
-#define NAUTILUS_FILE_ATTRIBUTE_DEEP_COUNTS "deep counts"
-#define NAUTILUS_FILE_ATTRIBUTE_DIRECTORY_ITEM_COUNT "directory item count"
-#define NAUTILUS_FILE_ATTRIBUTE_DIRECTORY_ITEM_MIME_TYPES "directory item MIME types"
-#define NAUTILUS_FILE_ATTRIBUTE_FILE_TYPE "file type"
-#define NAUTILUS_FILE_ATTRIBUTE_IS_DIRECTORY "is directory"
-#define NAUTILUS_FILE_ATTRIBUTE_METADATA "metadata"
-#define NAUTILUS_FILE_ATTRIBUTE_MIME_TYPE "MIME type"
-#define NAUTILUS_FILE_ATTRIBUTE_TOP_LEFT_TEXT "top left text"
+#define NAUTILUS_FILE_ATTRIBUTE_ACTIVATION_URI "activation URI"
+#define NAUTILUS_FILE_ATTRIBUTE_CAPABILITIES "capabilities"
+#define NAUTILUS_FILE_ATTRIBUTE_CUSTOM_ICON "custom icon"
+#define NAUTILUS_FILE_ATTRIBUTE_DEEP_COUNTS "deep counts"
+#define NAUTILUS_FILE_ATTRIBUTE_DIRECTORY_ITEM_COUNT "directory item count"
+#define NAUTILUS_FILE_ATTRIBUTE_DIRECTORY_ITEM_MIME_TYPES "directory item MIME types"
+#define NAUTILUS_FILE_ATTRIBUTE_FILE_TYPE "file type"
+#define NAUTILUS_FILE_ATTRIBUTE_IS_DIRECTORY "is directory"
+#define NAUTILUS_FILE_ATTRIBUTE_METADATA "metadata"
+#define NAUTILUS_FILE_ATTRIBUTE_MIME_TYPE "MIME type"
+#define NAUTILUS_FILE_ATTRIBUTE_TOP_LEFT_TEXT "top left text"
+#define NAUTILUS_FILE_ATTRIBUTE_CUSTOM_NAME "custom name"
#endif /* NAUTILUS_FILE_ATTRIBUTES_H */
diff --git a/libnautilus-private/nautilus-file-private.h b/libnautilus-private/nautilus-file-private.h
index 3df51e700..0e09a4bbf 100644
--- a/libnautilus-private/nautilus-file-private.h
+++ b/libnautilus-private/nautilus-file-private.h
@@ -67,6 +67,10 @@ struct NautilusFileDetails
GList *mime_list; /* If this is a directory, the list of MIME types in it. */
char *top_left_text;
+
+ /* Info you might get from a link (.desktop, .directory or nautilus link) */
+ char *custom_name;
+ char *custom_icon_uri;
char *activation_uri;
/* The following is for file operations in progress. Since
@@ -109,8 +113,8 @@ struct NautilusFileDetails
eel_boolean_bit got_top_left_text : 1;
eel_boolean_bit top_left_text_is_up_to_date : 1;
- eel_boolean_bit got_activation_uri : 1;
- eel_boolean_bit activation_uri_is_up_to_date : 1;
+ eel_boolean_bit got_link_info : 1;
+ eel_boolean_bit link_info_is_up_to_date : 1;
};
NautilusFile *nautilus_file_new_from_info (NautilusDirectory *directory,
diff --git a/libnautilus-private/nautilus-file-queue.c b/libnautilus-private/nautilus-file-queue.c
new file mode 100644
index 000000000..a7ea8fdf2
--- /dev/null
+++ b/libnautilus-private/nautilus-file-queue.c
@@ -0,0 +1,125 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-
+
+ Copyright (C) 2001 Maciej Stachowiak
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public
+ License along with this program; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Author: Maciej Stachowiak <mjs@noisehavoc.org>
+*/
+
+#include <config.h>
+#include "nautilus-file-queue.h"
+
+#include <glib.h>
+
+struct NautilusFileQueue {
+ GList *head;
+ GList *tail;
+ GHashTable *item_to_link_map;
+};
+
+NautilusFileQueue *
+nautilus_file_queue_new (void)
+{
+ NautilusFileQueue *queue;
+
+ queue = g_new0 (NautilusFileQueue, 1);
+ queue->item_to_link_map = g_hash_table_new (g_direct_hash, g_direct_equal);
+
+ return queue;
+}
+
+void
+nautilus_file_queue_destroy (NautilusFileQueue *queue)
+{
+ g_hash_table_destroy (queue->item_to_link_map);
+ nautilus_file_list_free (queue->head);
+ g_free (queue);
+}
+
+void
+nautilus_file_queue_enqueue (NautilusFileQueue *queue,
+ NautilusFile *file)
+{
+ if (g_hash_table_lookup (queue->item_to_link_map, file) != NULL) {
+ /* It's already on the queue. */
+ return;
+ }
+
+ if (queue->tail == NULL) {
+ queue->head = g_list_append (NULL, file);
+ queue->tail = queue->head;
+ } else {
+ g_list_append (queue->tail, file);
+ queue->tail = queue->tail->next;
+ }
+
+ nautilus_file_ref (file);
+ g_hash_table_insert (queue->item_to_link_map, file, queue->tail);
+}
+
+NautilusFile *
+nautilus_file_queue_dequeue (NautilusFileQueue *queue)
+{
+ NautilusFile *file;
+
+ file = nautilus_file_queue_head (queue);
+ nautilus_file_queue_remove (queue, file);
+
+ return file;
+}
+
+
+void
+nautilus_file_queue_remove (NautilusFileQueue *queue,
+ NautilusFile *file)
+{
+ GList *link;
+
+ link = g_hash_table_lookup (queue->item_to_link_map, file);
+
+ if (link == NULL) {
+ /* It's not on the queue */
+ return;
+ }
+
+ if (link == queue->tail) {
+ /* Need to special-case removing the tail. */
+ queue->tail = queue->tail->prev;
+ }
+
+ queue->head = g_list_remove_link (queue->head, link);
+ g_list_free (link);
+ g_hash_table_remove (queue->item_to_link_map, file);
+
+ nautilus_file_unref (file);
+}
+
+NautilusFile *
+nautilus_file_queue_head (NautilusFileQueue *queue)
+{
+ if (queue->head == NULL) {
+ return NULL;
+ }
+
+ return NAUTILUS_FILE (queue->head->data);
+}
+
+gboolean
+nautilus_file_queue_is_empty (NautilusFileQueue *queue)
+{
+ return (queue->head == NULL);
+}
diff --git a/libnautilus-private/nautilus-file-queue.h b/libnautilus-private/nautilus-file-queue.h
new file mode 100644
index 000000000..92331d46f
--- /dev/null
+++ b/libnautilus-private/nautilus-file-queue.h
@@ -0,0 +1,52 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-
+
+ Copyright (C) 2001 Maciej Stachowiak
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public
+ License along with this program; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Author: Maciej Stachowiak <mjs@noisehavoc.org>
+*/
+
+#ifndef NAUTILUS_FILE_QUEUE_H
+#define NAUTILUS_FILE_QUEUE_H
+
+#include <libnautilus-private/nautilus-file.h>
+
+typedef struct NautilusFileQueue NautilusFileQueue;
+
+NautilusFileQueue *nautilus_file_queue_new (void);
+void nautilus_file_queue_destroy (NautilusFileQueue *queue);
+
+/* Add a file to the tail of the queue, unless it's already in the queue */
+void nautilus_file_queue_enqueue (NautilusFileQueue *queue,
+ NautilusFile *file);
+
+/* Return the file at the head of the queue after removing it from the
+ * queue. This is dangerous unless you have another ref to the file,
+ * since it will unref it.
+ */
+NautilusFile * nautilus_file_queue_dequeue (NautilusFileQueue *queue);
+
+/* Remove a file from an arbitrary point in the queue in constant time. */
+void nautilus_file_queue_remove (NautilusFileQueue *queue,
+ NautilusFile *file);
+
+/* Get the file at the head of the queue without removing or unrefing it. */
+NautilusFile * nautilus_file_queue_head (NautilusFileQueue *queue);
+
+gboolean nautilus_file_queue_is_empty (NautilusFileQueue *queue);
+
+#endif /* NAUTILUS_FILE_CHANGES_QUEUE_H */
diff --git a/libnautilus-private/nautilus-file.c b/libnautilus-private/nautilus-file.c
index 918c34af6..1f9208b25 100644
--- a/libnautilus-private/nautilus-file.c
+++ b/libnautilus-private/nautilus-file.c
@@ -50,7 +50,6 @@
#include <libgnome/gnome-dentry.h>
#include <libgnome/gnome-i18n.h>
#include <libgnome/gnome-metadata.h>
-#include <libgnome/gnome-mime-info.h>
#include <libgnome/gnome-mime.h>
#include <libgnomevfs/gnome-vfs-file-info.h>
#include <libgnomevfs/gnome-vfs-mime-handlers.h>
@@ -449,6 +448,8 @@ destroy (GtkObject *object)
gnome_vfs_file_info_unref (file->details->info);
}
g_free (file->details->top_left_text);
+ g_free (file->details->custom_name);
+ g_free (file->details->custom_icon_uri);
g_free (file->details->activation_uri);
g_free (file->details->compare_by_emblem_cache);
@@ -2251,81 +2252,18 @@ nautilus_file_set_integer_metadata (NautilusFile *file,
metadata);
}
-
-
-
char *
nautilus_file_get_name (NautilusFile *file)
{
char *name;
- GnomeDesktopEntry *entry;
- char *path, *uri;
- char *caption;
- int size, res;
if (file == NULL) {
return NULL;
}
g_return_val_if_fail (NAUTILUS_IS_FILE (file), NULL);
-
- /* FIXME: It's very bad to do this I/O here. For one thing,
- * this means that a file's name can change when the MIME
- * type is fetched. For another, it means that there's I/O
- * done every single time nautilus_file_get_name is called.
- * This goes against the design of NautilusFile. The proper
- * way to do this is to do this I/O in an async. way when
- * the object is created, but at the very least we need to
- * change this so it only does the I/O once!
- */
- if (nautilus_file_is_mime_type (file, "application/x-gnome-app-info")) {
- uri = nautilus_file_get_uri (file);
- path = gnome_vfs_get_local_path_from_uri (uri);
-
- name = NULL;
- if (path != NULL) {
- entry = gnome_desktop_entry_load (path);
- if (entry != NULL) {
- name = g_strdup (entry->name);
- gnome_desktop_entry_free (entry);
- }
- }
-
- g_free (path);
- g_free (uri);
-
- if (name != NULL) {
- return name;
- }
- }
-
- /* FIXME: It's very bad to do this I/O here. For one thing,
- * this means that a file's name can change when the MIME
- * type is fetched. For another, it means that there's I/O
- * done every single time nautilus_file_get_name is called.
- * This goes against the design of NautilusFile. The proper
- * way to do this is to do this I/O in an async. way when
- * the object is created, but at the very least we need to
- * change this so it only does the I/O once!
- */
- /* Desktop directories contain special "URL" files, handle
- * those by using the gnome metadata caption.
- */
- if (nautilus_file_is_gmc_url (file)) {
- uri = nautilus_file_get_uri (file);
- path = gnome_vfs_get_local_path_from_uri (uri);
-
- if (path != NULL) {
- res = gnome_metadata_get (path, "icon-caption", &size, &caption);
- } else {
- res = -1;
- }
-
- g_free (path);
- g_free (uri);
-
- if (res == 0 && caption != NULL) {
- return caption;
- }
+
+ if (file->details->got_link_info && file->details->custom_name != NULL) {
+ return g_strdup (file->details->custom_name);
}
name = gnome_vfs_unescape_string (file->details->relative_uri, "/");
@@ -2375,7 +2313,7 @@ nautilus_file_get_activation_uri (NautilusFile *file)
{
g_return_val_if_fail (NAUTILUS_IS_FILE (file), NULL);
- if (!file->details->got_activation_uri) {
+ if (!file->details->got_link_info) {
return NULL;
}
return file->details->activation_uri == NULL
@@ -2383,6 +2321,26 @@ nautilus_file_get_activation_uri (NautilusFile *file)
: g_strdup (file->details->activation_uri);
}
+char *
+nautilus_file_get_custom_icon_uri (NautilusFile *file)
+{
+ char *uri;
+
+ g_return_val_if_fail (NAUTILUS_IS_FILE (file), NULL);
+
+ uri = NULL;
+
+ /* Metadata takes precedence */
+ uri = nautilus_file_get_metadata (file, NAUTILUS_METADATA_KEY_CUSTOM_ICON, NULL);
+
+ if (uri == NULL && file->details->got_link_info) {
+ uri = g_strdup (file->details->custom_icon_uri);
+ }
+
+ return uri;
+}
+
+
/* Return the actual uri associated with the passed-in file. */
char *
nautilus_file_get_uri (NautilusFile *file)
@@ -4469,7 +4427,8 @@ nautilus_file_get_symbolic_link_target_path (NautilusFile *file)
/**
* nautilus_file_is_nautilus_link
*
- * Check if this file is a nautilus link.
+ * Check if this file is a "nautilus link", meaning a historical
+ * nautilus xml link file or a desktop file.
* @file: NautilusFile representing the file in question.
*
* Returns: True if the file is a nautilus link.
@@ -4478,7 +4437,8 @@ nautilus_file_get_symbolic_link_target_path (NautilusFile *file)
gboolean
nautilus_file_is_nautilus_link (NautilusFile *file)
{
- return nautilus_file_is_mime_type (file, "application/x-nautilus-link");
+ return nautilus_file_is_mime_type (file, "application/x-nautilus-link") ||
+ nautilus_file_is_mime_type (file, "application/x-gnome-app-info");
}
/**
@@ -4552,20 +4512,17 @@ nautilus_file_get_file_info_result (NautilusFile *file)
gboolean
nautilus_file_contains_text (NautilusFile *file)
{
- char *mime_type;
- gboolean contains_text;
-
if (file == NULL) {
return FALSE;
}
g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE);
-
- mime_type = nautilus_file_get_mime_type (file);
- contains_text = eel_istr_has_prefix (mime_type, "text/");
- g_free (mime_type);
-
- return contains_text;
+
+ if (file->details->info == NULL || file->details->info->mime_type == NULL) {
+ return FALSE;
+ }
+
+ return eel_istr_has_prefix (file->details->info->mime_type, "text/");
}
/**
@@ -4875,12 +4832,11 @@ invalidate_file_info (NautilusFile *file)
}
static void
-invalidate_activation_uri (NautilusFile *file)
+invalidate_link_info (NautilusFile *file)
{
- file->details->activation_uri_is_up_to_date = FALSE;
+ file->details->link_info_is_up_to_date = FALSE;
}
-
void
nautilus_file_invalidate_attributes_internal (NautilusFile *file,
GList *file_attributes)
@@ -4908,8 +4864,8 @@ nautilus_file_invalidate_attributes_internal (NautilusFile *file,
if (request.top_left_text) {
invalidate_top_left_text (file);
}
- if (request.activation_uri) {
- invalidate_activation_uri (file);
+ if (request.link_info) {
+ invalidate_link_info (file);
}
/* FIXME bugzilla.gnome.org 45075: implement invalidating metadata */
@@ -4935,6 +4891,8 @@ nautilus_file_invalidate_attributes (NautilusFile *file,
/* Actually invalidate the values */
nautilus_file_invalidate_attributes_internal (file, file_attributes);
+
+ nautilus_directory_add_file_to_work_queue (file->details->directory, file);
/* Kick off I/O if necessary */
nautilus_directory_async_state_changed (file->details->directory);
@@ -4958,6 +4916,7 @@ nautilus_file_get_all_attributes (void)
attributes = g_list_prepend (attributes, NAUTILUS_FILE_ATTRIBUTE_METADATA);
attributes = g_list_prepend (attributes, NAUTILUS_FILE_ATTRIBUTE_MIME_TYPE);
attributes = g_list_prepend (attributes, NAUTILUS_FILE_ATTRIBUTE_TOP_LEFT_TEXT);
+ attributes = g_list_prepend (attributes, NAUTILUS_FILE_ATTRIBUTE_CUSTOM_NAME);
return attributes;
}
diff --git a/libnautilus-private/nautilus-file.h b/libnautilus-private/nautilus-file.h
index b7b034e74..e9bed7db8 100644
--- a/libnautilus-private/nautilus-file.h
+++ b/libnautilus-private/nautilus-file.h
@@ -290,6 +290,9 @@ GList *nautilus_file_list_filter_hidden_and_backup (GList
*/
char * nautilus_file_get_activation_uri (NautilusFile *file);
+/* Get custom icon (if specified by metadata or link contents) */
+char * nautilus_file_get_custom_icon_uri (NautilusFile *file);
+
/* Convenience functions for dealing with a list of NautilusFile objects that each have a ref.
* These are just convenient names for functions that work on lists of GtkObject *.
*/
diff --git a/libnautilus-private/nautilus-icon-container.c b/libnautilus-private/nautilus-icon-container.c
index 3eefcadae..e736edf51 100644
--- a/libnautilus-private/nautilus-icon-container.c
+++ b/libnautilus-private/nautilus-icon-container.c
@@ -2339,6 +2339,9 @@ destroy (GtkObject *object)
container);
nautilus_icon_container_flush_typeselect_state (container);
+
+ g_hash_table_destroy (container->details->icon_set);
+ container->details->icon_set = NULL;
g_free (container->details);
@@ -3331,6 +3334,8 @@ nautilus_icon_container_initialize (NautilusIconContainer *container)
details = g_new0 (NautilusIconContainerDetails, 1);
+ details->icon_set = g_hash_table_new (g_direct_hash, g_direct_equal);
+
details->zoom_level = NAUTILUS_ZOOM_LEVEL_STANDARD;
/* font table - this isn't exactly proportional, but it looks better than computed */
@@ -3597,6 +3602,9 @@ nautilus_icon_container_clear (NautilusIconContainer *container)
g_list_free (details->new_icons);
details->new_icons = NULL;
+ g_hash_table_destroy (details->icon_set);
+ details->icon_set = g_hash_table_new (g_direct_hash, g_direct_equal);
+
nautilus_icon_container_update_scroll_region (container);
}
@@ -3652,7 +3660,8 @@ icon_destroy (NautilusIconContainer *container,
details->icons = g_list_remove (details->icons, icon);
details->new_icons = g_list_remove (details->new_icons, icon);
-
+ g_hash_table_remove (details->icon_set, icon->data);
+
was_selected = icon->is_selected;
if (details->keyboard_focus == icon) {
@@ -3928,7 +3937,6 @@ nautilus_icon_container_add (NautilusIconContainer *container,
NautilusIconData *data)
{
NautilusIconContainerDetails *details;
- GList *p;
NautilusIcon *icon;
g_return_val_if_fail (NAUTILUS_IS_ICON_CONTAINER (container), FALSE);
@@ -3936,14 +3944,8 @@ nautilus_icon_container_add (NautilusIconContainer *container,
details = container->details;
- /* FIXME bugzilla.gnome.org 41288:
- * I guess we need to use an indexed data structure to avoid this loop.
- */
- for (p = details->icons; p != NULL; p = p->next) {
- icon = p->data;
- if (icon->data == data) {
- return FALSE;
- }
+ if (g_hash_table_lookup (details->icon_set, data) != NULL) {
+ return FALSE;
}
/* Create the new icon, including the canvas item. */
@@ -3964,6 +3966,8 @@ nautilus_icon_container_add (NautilusIconContainer *container,
details->icons = g_list_prepend (details->icons, icon);
details->new_icons = g_list_prepend (details->new_icons, icon);
+ g_hash_table_insert (details->icon_set, data, icon);
+
/* Run an idle function to add the icons. */
schedule_redo_layout (container);
@@ -3982,26 +3986,22 @@ nautilus_icon_container_remove (NautilusIconContainer *container,
NautilusIconData *data)
{
NautilusIcon *icon;
- GList *p;
g_return_val_if_fail (NAUTILUS_IS_ICON_CONTAINER (container), FALSE);
g_return_val_if_fail (data != NULL, FALSE);
end_renaming_mode (container, FALSE);
- /* FIXME bugzilla.gnome.org 41288:
- * I guess we need to use an indexed data structure to avoid this loop.
- */
- for (p = container->details->icons; p != NULL; p = p->next) {
- icon = p->data;
- if (icon->data == data) {
- icon_destroy (container, icon);
- schedule_redo_layout (container);
- return TRUE;
- }
+ icon = g_hash_table_lookup (container->details->icon_set, data);
+
+ if (icon == NULL) {
+ return FALSE;
}
- return FALSE;
+ icon_destroy (container, icon);
+ schedule_redo_layout (container);
+
+ return TRUE;
}
/**
@@ -4016,18 +4016,15 @@ nautilus_icon_container_request_update (NautilusIconContainer *container,
NautilusIconData *data)
{
NautilusIcon *icon;
- GList *p;
g_return_if_fail (NAUTILUS_IS_ICON_CONTAINER (container));
g_return_if_fail (data != NULL);
- for (p = container->details->icons; p != NULL; p = p->next) {
- icon = p->data;
- if (icon->data == data) {
- nautilus_icon_container_update_icon (container, icon);
- schedule_redo_layout (container);
- return;
- }
+ icon = g_hash_table_lookup (container->details->icon_set, data);
+
+ if (icon != NULL) {
+ nautilus_icon_container_update_icon (container, icon);
+ schedule_redo_layout (container);
}
}
@@ -4097,20 +4094,15 @@ nautilus_icon_container_request_update_all (NautilusIconContainer *container)
void
nautilus_icon_container_reveal (NautilusIconContainer *container, NautilusIconData *data)
{
- GList *p;
NautilusIcon *icon;
g_return_if_fail (NAUTILUS_IS_ICON_CONTAINER (container));
g_return_if_fail (data != NULL);
- /* FIXME bugzilla.gnome.org 41288:
- * I guess we need to use an indexed data structure to avoid this loop.
- */
- for (p = container->details->icons; p != NULL; p = p->next) {
- icon = p->data;
- if (icon->data == data) {
- reveal_icon (container, icon);
- }
+ icon = g_hash_table_lookup (container->details->icon_set, data);
+
+ if (icon != NULL) {
+ reveal_icon (container, icon);
}
}
diff --git a/libnautilus-private/nautilus-icon-factory.c b/libnautilus-private/nautilus-icon-factory.c
index b28ee2881..ea9967465 100644
--- a/libnautilus-private/nautilus-icon-factory.c
+++ b/libnautilus-private/nautilus-icon-factory.c
@@ -35,7 +35,6 @@
#include "nautilus-icon-factory-private.h"
#include "nautilus-lib-self-check-functions.h"
#include "nautilus-link.h"
-#include "nautilus-metadata.h"
#include "nautilus-theme.h"
#include "nautilus-thumbnails.h"
#include "nautilus-trash-monitor.h"
@@ -54,12 +53,13 @@
#include <gtk/gtksignal.h>
#include <libgnome/gnome-dentry.h>
#include <libgnome/gnome-i18n.h>
-#include <libgnome/gnome-metadata.h>
#include <libgnome/gnome-util.h>
#include <libgnomevfs/gnome-vfs-file-info.h>
+#include <libgnomevfs/gnome-vfs-mime.h>
#include <libgnomevfs/gnome-vfs-mime-handlers.h>
#include <libgnomevfs/gnome-vfs-mime-info.h>
#include <libgnomevfs/gnome-vfs-mime-monitor.h>
+#include <libgnomevfs/gnome-vfs-ops.h>
#include <libgnomevfs/gnome-vfs-types.h>
#include <librsvg/rsvg.h>
#include <stdio.h>
@@ -1458,26 +1458,53 @@ is_supported_mime_type (const char *mime_type)
return TRUE;
}
+static void
+image_uri_to_name_or_uri (const char *image_uri,
+ char **icon_name,
+ char **uri)
+{
+ char *icon_path;
+
+ if (image_uri == NULL) {
+ return;
+ }
+
+ /* FIXME bugzilla.eazel.com 2564: All custom icons must be in file:. */
+ icon_path = gnome_vfs_get_local_path_from_uri (image_uri);
+ if (icon_path == NULL && image_uri[0] == '/') {
+ icon_path = g_strdup (image_uri);
+ }
+ if (icon_path != NULL) {
+ if (*uri == NULL) {
+ *uri = gnome_vfs_get_uri_from_local_path (icon_path);
+ }
+ g_free (icon_path);
+ } else if (strpbrk (image_uri, ":/") == NULL) {
+ *icon_name = remove_icon_name_suffix (image_uri);
+ }
+}
+
/* key routine to get the scalable icon for a file */
NautilusScalableIcon *
nautilus_icon_factory_get_icon_for_file (NautilusFile *file, const char *modifier)
{
- char *uri, *file_uri, *file_path, *image_uri, *icon_name, *mime_type, *top_left_text;
- char *directory, *desktop_directory, *buf, *icon_path;
+ char *uri, *custom_uri, *file_uri, *icon_name, *mime_type, *top_left_text;
+ int file_size;
gboolean is_local;
- int file_size, size, res;
NautilusScalableIcon *scalable_icon;
- char *directory_uri;
- GnomeDesktopEntry *entry;
if (file == NULL) {
return NULL;
}
icon_name = NULL;
+ uri = NULL;
+
+ /* if there is a custom image in the metadata or link info, use that. */
+ custom_uri = nautilus_file_get_custom_icon_uri (file);
+ image_uri_to_name_or_uri (custom_uri, &icon_name, &uri);
+ g_free (custom_uri);
- /* if there is a custom image in the metadata, use that. */
- uri = nautilus_file_get_metadata (file, NAUTILUS_METADATA_KEY_CUSTOM_ICON, NULL);
file_uri = nautilus_file_get_uri (file);
is_local = nautilus_file_is_local (file);
mime_type = nautilus_file_get_mime_type (file);
@@ -1486,37 +1513,6 @@ nautilus_icon_factory_get_icon_for_file (NautilusFile *file, const char *modifie
or use a thumbnail if one exists. If it's too large, don't try to thumbnail it at all.
If a thumbnail is required, but does not yet exist, put an entry on the thumbnail queue so we
eventually make one */
-
- if (uri == NULL) {
- /* Do we have to check the gnome metadata?
- *
- * Do this only for the ~/.gnome-desktop directory, as it was
- * the only place where GMC used it (since everywhere else we could
- * not do it because of the imlib leaks).
- */
- desktop_directory = nautilus_get_gmc_desktop_directory ();
- directory_uri = nautilus_file_get_parent_uri (file);
- directory = gnome_vfs_get_local_path_from_uri (directory_uri);
- if (directory != NULL && strcmp (directory, desktop_directory) == 0) {
- file_path = gnome_vfs_get_local_path_from_uri (file_uri);
-
- if (file_path != NULL) {
- res = gnome_metadata_get (file_path, "icon-filename", &size, &buf);
- } else {
- res = -1;
- }
-
- if (res == 0 && buf != NULL) {
- uri = gnome_vfs_get_uri_from_local_path (buf);
- g_free (buf);
- }
-
- g_free (file_path);
- }
- g_free (directory);
- g_free (directory_uri);
- g_free (desktop_directory);
- }
/* also, dont make thumbnails for images in the thumbnails directory */
if (uri == NULL) {
@@ -1539,50 +1535,7 @@ nautilus_icon_factory_get_icon_for_file (NautilusFile *file, const char *modifie
}
}
}
-
- /* Handle nautilus link xml files, which may specify their own image */
- if (nautilus_file_is_nautilus_link (file)) {
- /* FIXME bugzilla.gnome.org 42563: This does sync. I/O and only works for local paths. */
- file_path = gnome_vfs_get_local_path_from_uri (file_uri);
- if (file_path != NULL) {
- image_uri = nautilus_link_local_get_image_uri (file_path);
- if (image_uri != NULL) {
- /* FIXME bugzilla.gnome.org 42564: All custom icons must be in file:. */
- icon_path = gnome_vfs_get_local_path_from_uri (image_uri);
- if (icon_path == NULL && image_uri[0] == '/') {
- icon_path = g_strdup (image_uri);
- }
- if (icon_path != NULL) {
- if (uri == NULL) {
- uri = gnome_vfs_get_uri_from_local_path (icon_path);
- }
- g_free (icon_path);
- } else if (strpbrk (image_uri, ":/") == NULL) {
- icon_name = remove_icon_name_suffix (image_uri);
- }
- g_free (image_uri);
- }
- g_free (file_path);
- }
- }
- /* Handle .desktop files. */
- if (uri == NULL
- && nautilus_file_is_mime_type (file, "application/x-gnome-app-info")) {
- /* FIXME bugzilla.gnome.org 42563: This does sync. I/O and only works for local paths. */
- file_path = gnome_vfs_get_local_path_from_uri (file_uri);
- if (file_path != NULL) {
- entry = gnome_desktop_entry_load (file_path);
- if (entry != NULL) {
- if (entry->icon != NULL) {
- uri = gnome_vfs_get_uri_from_local_path (entry->icon);
- }
- gnome_desktop_entry_free (entry);
- }
- g_free (file_path);
- }
- }
-
/* handle SVG files */
if (uri == NULL && icon_name == NULL
&& nautilus_file_is_mime_type (file, "image/svg")) {
@@ -1600,7 +1553,7 @@ nautilus_icon_factory_get_icon_for_file (NautilusFile *file, const char *modifie
/* Create the icon or find it in the cache if it's already there. */
scalable_icon = nautilus_scalable_icon_new_from_text_pieces
(uri, mime_type, icon_name, modifier, top_left_text);
-
+
g_free (uri);
g_free (mime_type);
g_free (icon_name);
@@ -1609,26 +1562,46 @@ nautilus_icon_factory_get_icon_for_file (NautilusFile *file, const char *modifie
return scalable_icon;
}
+
+
/**
- * nautilus_icon_factory_get_required_file_attributes
+ * nautilus_icon_factory_get_basic_file_attributes
*
- * Get the list of file attributes required to obtain a file's icon.
+ * Get the list of file attributes required to obtain a file's basic icon.
+ * This includes attributes needed to get a custom icon, but not those needed
+ * for text preview.
* Callers must free this list.
*/
GList *
-nautilus_icon_factory_get_required_file_attributes (void)
+nautilus_icon_factory_get_basic_file_attributes (void)
{
GList *attributes;
attributes = g_list_prepend (NULL, NAUTILUS_FILE_ATTRIBUTE_CUSTOM_ICON);
attributes = g_list_prepend (attributes,
NAUTILUS_FILE_ATTRIBUTE_MIME_TYPE);
+ return attributes;
+}
+
+/**
+ * nautilus_icon_factory_get_required_file_attributes
+ *
+ * Get the list of file attributes required to obtain a file's icon.
+ * Callers must free this list.
+ */
+GList *
+nautilus_icon_factory_get_required_file_attributes (void)
+{
+ GList *attributes;
+
+ attributes = nautilus_icon_factory_get_basic_file_attributes ();
attributes = g_list_prepend (attributes,
NAUTILUS_FILE_ATTRIBUTE_TOP_LEFT_TEXT);
return attributes;
}
+
/**
* nautilus_icon_factory_is_icon_ready_for_file
*
@@ -1650,6 +1623,31 @@ nautilus_icon_factory_is_icon_ready_for_file (NautilusFile *file)
return result;
}
+
+
+/**
+ * nautilus_icon_factory_is_basic_icon_ready_for_file
+ *
+ * Check whether a NautilusFile has enough information to report
+ * what its basic icon should be. This will account for custom icons
+ * but not text preview.
+ *
+ * @file: The NautilusFile in question.
+ */
+gboolean
+nautilus_icon_factory_is_basic_icon_ready_for_file (NautilusFile *file)
+{
+ GList *attributes;
+ gboolean result;
+
+ attributes = nautilus_icon_factory_get_basic_file_attributes ();
+ result = nautilus_file_check_if_ready (file, attributes);
+ g_list_free (attributes);
+
+ return result;
+}
+
+
NautilusScalableIcon *
nautilus_icon_factory_get_emblem_icon_by_name (const char *emblem_name)
{
@@ -1916,6 +1914,7 @@ load_named_icon (const char *name,
path = get_icon_file_path (name, modifier,
size_in_pixels, optimized_for_aa,
details);
+
pixbuf = load_icon_from_path (path, size_in_pixels, FALSE,
eel_str_has_prefix (name, EMBLEM_NAME_PREFIX),
optimized_for_aa);
diff --git a/libnautilus-private/nautilus-icon-factory.h b/libnautilus-private/nautilus-icon-factory.h
index 2cc4319d0..4286d69dc 100644
--- a/libnautilus-private/nautilus-icon-factory.h
+++ b/libnautilus-private/nautilus-icon-factory.h
@@ -105,6 +105,11 @@ NautilusScalableIcon *nautilus_icon_factory_get_icon_for_file (Nautil
const char *modifier);
gboolean nautilus_icon_factory_is_icon_ready_for_file (NautilusFile *file);
GList * nautilus_icon_factory_get_required_file_attributes (void);
+
+/* The calls below do not account for top-left text, allowing it to be loaded progressively. */
+gboolean nautilus_icon_factory_is_basic_icon_ready_for_file (NautilusFile *file);
+GList * nautilus_icon_factory_get_basic_file_attributes (void);
+
GList * nautilus_icon_factory_get_emblem_icons_for_file (NautilusFile *file,
EelStringList *exclude);
NautilusScalableIcon *nautilus_icon_factory_get_emblem_icon_by_name (const char *emblem_name);
diff --git a/libnautilus-private/nautilus-icon-private.h b/libnautilus-private/nautilus-icon-private.h
index e46d7447b..a7a98942a 100644
--- a/libnautilus-private/nautilus-icon-private.h
+++ b/libnautilus-private/nautilus-icon-private.h
@@ -102,6 +102,7 @@ struct NautilusIconContainerDetails {
/* List of icons. */
GList *icons;
GList *new_icons;
+ GHashTable *icon_set;
/* Current icon for keyboard navigation. */
NautilusIcon *keyboard_focus;
diff --git a/libnautilus-private/nautilus-link-desktop-file.c b/libnautilus-private/nautilus-link-desktop-file.c
new file mode 100644
index 000000000..70d3adb18
--- /dev/null
+++ b/libnautilus-private/nautilus-link-desktop-file.c
@@ -0,0 +1,532 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-
+
+ nautilus-link-desktop-file.c: .desktop link files.
+
+ Copyright (C) 2001 Red Hat, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the historicalied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public
+ License along with this program; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Authors: Jonathan Blandford <jrb@redhat.com>
+ Alexander Larsson <alexl@redhat.com>
+*/
+#include <config.h>
+#include "nautilus-link.h"
+#include "nautilus-link-desktop-file.h"
+#include "nautilus-directory-notify.h"
+#include "nautilus-directory.h"
+#include "nautilus-file-attributes.h"
+#include "nautilus-file.h"
+#include "nautilus-metadata.h"
+#include "nautilus-file-utilities.h"
+#include "nautilus-desktop-file-loader.h"
+#include <eel/eel-glib-extensions.h>
+#include <eel/eel-gnome-extensions.h>
+#include <eel/eel-stock-dialogs.h>
+#include <eel/eel-string.h>
+#include <eel/eel-xml-extensions.h>
+#include <gnome-xml/parser.h>
+#include <gnome-xml/xmlmemory.h>
+#include <libgnome/gnome-i18n.h>
+#include <libgnome/gnome-util.h>
+#include <libgnomevfs/gnome-vfs-mime.h>
+#include <libgnomevfs/gnome-vfs.h>
+#include <stdlib.h>
+
+#define NAUTILUS_LINK_GENERIC_TAG "Link"
+#define NAUTILUS_LINK_TRASH_TAG "X-nautilus-trash"
+#define NAUTILUS_LINK_MOUNT_TAG "FSDevice"
+#define NAUTILUS_LINK_HOME_TAG "X-nautilus-home"
+
+static const char *
+get_tag (NautilusLinkType type)
+{
+ switch (type) {
+ default:
+ g_assert_not_reached ();
+ /* fall through */
+ case NAUTILUS_LINK_GENERIC:
+ return NAUTILUS_LINK_GENERIC_TAG;
+ case NAUTILUS_LINK_TRASH:
+ return NAUTILUS_LINK_TRASH_TAG;
+ case NAUTILUS_LINK_MOUNT:
+ return NAUTILUS_LINK_MOUNT_TAG;
+ case NAUTILUS_LINK_HOME:
+ return NAUTILUS_LINK_HOME_TAG;
+ }
+}
+
+static gchar *
+slurp_key_string (const char *path,
+ const char *keyname,
+ gboolean localize)
+{
+ NautilusDesktopFile *desktop_file = NULL;
+ gchar *text;
+ gboolean set;
+ GnomeVFSResult result;
+ gchar *uri;
+
+ uri = gnome_vfs_get_uri_from_local_path (path);
+ if (uri == NULL) {
+ return NULL;
+ }
+
+ result = nautilus_desktop_file_load (uri, &desktop_file);
+
+ g_free (uri);
+
+ if (result != GNOME_VFS_OK) {
+ return NULL;
+ }
+
+ if (localize) {
+ set = nautilus_desktop_file_get_locale_string (desktop_file,
+ "Desktop Entry",
+ keyname,
+ &text);
+ } else {
+ set = nautilus_desktop_file_get_string (desktop_file,
+ "Desktop Entry",
+ keyname,
+ &text);
+ }
+
+ nautilus_desktop_file_free (desktop_file);
+
+ if (set == FALSE) {
+ return NULL;
+ }
+
+ return text;
+}
+
+gboolean
+nautilus_link_desktop_file_local_create (const char *directory_path,
+ const char *name,
+ const char *image,
+ const char *target_uri,
+ const GdkPoint *point,
+ NautilusLinkType type)
+{
+ gchar *path;
+ FILE *file;
+ char *uri;
+ GList dummy_list;
+ NautilusFileChangesQueuePosition item;
+ GnomeVFSHandle *handle;
+
+ g_return_val_if_fail (directory_path != NULL, FALSE);
+ g_return_val_if_fail (name != NULL, FALSE);
+ g_return_val_if_fail (image != NULL, FALSE);
+ g_return_val_if_fail (target_uri != NULL, FALSE);
+
+ path = nautilus_make_path (directory_path, name);
+ handle = NULL;
+
+ file = fopen (path, "w");
+
+ if (file == NULL) {
+ g_free (path);
+ return FALSE;
+ }
+
+ fputs ("[Desktop Entry]\nEncoding=Legacy-Mixed\nName=", file);
+ fputs (name, file);
+ fputs ("\nType=", file);
+ fputs (get_tag (type), file);
+ fputs ("\nX-Nautilus-Icon=", file);
+ fputs (image, file);
+ fputs ("\nURL=", file);
+ fputs (target_uri, file);
+ fputs ("\n", file);
+ /* ... */
+ fclose (file);
+
+ uri = gnome_vfs_get_uri_from_local_path (path);
+ dummy_list.data = uri;
+ dummy_list.next = NULL;
+ dummy_list.prev = NULL;
+ nautilus_directory_notify_files_added (&dummy_list);
+ nautilus_directory_schedule_metadata_remove (&dummy_list);
+
+ if (point != NULL) {
+ item.uri = uri;
+ item.set = TRUE;
+ item.point.x = point->x;
+ item.point.y = point->y;
+
+ dummy_list.data = &item;
+ dummy_list.next = NULL;
+ dummy_list.prev = NULL;
+
+ nautilus_directory_schedule_position_set (&dummy_list);
+ }
+
+ g_free (uri);
+ g_free (path);
+ return TRUE;
+}
+
+gboolean
+nautilus_link_desktop_file_local_set_icon (const char *path,
+ const char *icon_name)
+{
+ NautilusDesktopFile *desktop_file;
+ GnomeVFSResult result;
+ char *uri;
+
+ uri = gnome_vfs_get_uri_from_local_path (path);
+ if (uri == NULL) {
+ return FALSE;
+ }
+
+ result = nautilus_desktop_file_load (uri, &desktop_file);
+
+ if (result != GNOME_VFS_OK) {
+ g_free (uri);
+ return FALSE;
+ }
+
+ nautilus_desktop_file_set_string (desktop_file, "Desktop Entry", "X-Nautilus-Icon", icon_name);
+
+ result = nautilus_desktop_file_save (desktop_file, uri);
+ nautilus_desktop_file_free (desktop_file);
+
+ g_free (uri);
+
+ if (result != GNOME_VFS_OK) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+char *
+nautilus_link_desktop_file_local_get_text (const char *path)
+{
+ return slurp_key_string (path, "Name", TRUE);
+}
+
+char *
+nautilus_link_desktop_file_local_get_additional_text (const char *path)
+{
+ /* The comment field of current .desktop files is often bad.
+ * It just contains a copy of the name. This is probably because the
+ * panel shows the comment field as a tooltip.
+ */
+ return NULL;
+#ifdef THIS_IS_NOT_USED_RIGHT_NOW
+ gchar *type;
+ gchar *retval;
+
+ type = slurp_key_string (path, "Type", FALSE);
+ retval = NULL;
+ if (type == NULL) {
+ return NULL;
+ }
+
+ if (strcmp (type, "Application") == 0) {
+ retval = slurp_key_string (path, "Comment", TRUE);
+ }
+
+ g_free (type);
+
+ return retval;
+#endif
+}
+
+NautilusLinkType
+nautilus_link_desktop_file_local_get_link_type (const char *path)
+{
+ gchar *type;
+ NautilusLinkType retval;
+
+ type = slurp_key_string (path, "Type", FALSE);
+
+ if (type == NULL) {
+ return NAUTILUS_LINK_GENERIC;
+ }
+ if (strcmp (type, NAUTILUS_LINK_HOME_TAG) == 0) {
+ retval = NAUTILUS_LINK_HOME;
+ } else if (strcmp (type, NAUTILUS_LINK_MOUNT_TAG) == 0) {
+ retval = NAUTILUS_LINK_MOUNT;
+ } else if (strcmp (type, NAUTILUS_LINK_TRASH_TAG) == 0) {
+ retval = NAUTILUS_LINK_TRASH;
+ } else {
+ retval = NAUTILUS_LINK_GENERIC;
+ }
+
+ g_free (type);
+ return retval;
+}
+
+gboolean
+nautilus_link_desktop_file_local_is_volume_link (const char *path)
+{
+ return (nautilus_link_desktop_file_local_get_link_type (path) == NAUTILUS_LINK_MOUNT);
+}
+
+gboolean
+nautilus_link_desktop_file_local_is_home_link (const char *path)
+{
+ return (nautilus_link_desktop_file_local_get_link_type (path) == NAUTILUS_LINK_HOME);
+}
+
+gboolean
+nautilus_link_desktop_file_local_is_trash_link (const char *path)
+{
+ return (nautilus_link_desktop_file_local_get_link_type (path) == NAUTILUS_LINK_TRASH);
+}
+
+static gchar *
+nautilus_link_desktop_file_get_link_uri_from_desktop (NautilusDesktopFile *desktop_file)
+{
+ gchar *terminal_command;
+ gchar *launch_string;
+ gboolean need_term;
+ gchar *type;
+ gchar *retval;
+
+ retval = NULL;
+
+ type = NULL;
+ if (! nautilus_desktop_file_get_string (desktop_file,
+ "Desktop Entry",
+ "Type",
+ &type)) {
+ return NULL;
+ }
+
+ if (strcmp (type, "Application") == 0) {
+ if (! nautilus_desktop_file_get_string (desktop_file,
+ "Desktop Entry",
+ "Exec",
+ &launch_string)) {
+ return NULL;
+ }
+
+ need_term = FALSE;
+ nautilus_desktop_file_get_boolean (desktop_file,
+ "Desktop Entry",
+ "Terminal",
+ &need_term);
+ if (need_term) {
+ terminal_command = eel_gnome_make_terminal_command (launch_string);
+ retval = g_strconcat ("command:", terminal_command, NULL);
+ g_free (terminal_command);
+ } else {
+ retval = g_strconcat ("command:", launch_string, NULL);
+ }
+ g_free (launch_string);
+ } else if (strcmp (type, "URL") == 0) {
+ /* Some old broken desktop files use this nonstandard feature, we need handle it though */
+ nautilus_desktop_file_get_string (desktop_file,
+ "Desktop Entry",
+ "Exec",
+ &retval);
+ } else if ((strcmp (type, NAUTILUS_LINK_GENERIC_TAG) == 0) ||
+ (strcmp (type, NAUTILUS_LINK_MOUNT_TAG) == 0) ||
+ (strcmp (type, NAUTILUS_LINK_TRASH_TAG) == 0) ||
+ (strcmp (type, NAUTILUS_LINK_HOME_TAG) == 0)) {
+ nautilus_desktop_file_get_string (desktop_file,
+ "Desktop Entry",
+ "URL",
+ &retval);
+ }
+ return retval;
+}
+
+static gchar *
+nautilus_link_desktop_file_get_link_name_from_desktop (NautilusDesktopFile *desktop_file)
+{
+ gchar *name;
+
+ name = NULL;
+
+ if (nautilus_desktop_file_get_string (desktop_file,
+ "Desktop Entry",
+ "Name",
+ &name)) {
+ return name;
+ } else {
+ return NULL;
+ }
+}
+
+static gchar *
+nautilus_link_desktop_file_get_link_icon_from_desktop (NautilusDesktopFile *desktop_file)
+{
+ char *icon_uri;
+ gchar *absolute;
+ gchar *icon_name;
+
+ if (nautilus_desktop_file_get_string (desktop_file, "Desktop Entry", "X-Nautilus-Icon", &icon_uri)) {
+ return icon_uri;
+ }
+
+ /* Fall back to a standard icon. */
+ if (nautilus_desktop_file_get_string (desktop_file, "Desktop Entry", "Icon", &icon_name)) {
+ if (icon_name == NULL) {
+ return NULL;
+ }
+
+ absolute = gnome_pixmap_file (icon_name);
+ if (absolute != NULL) {
+ g_free (icon_name);
+ icon_name = absolute;
+ }
+ if (icon_name[0] == '/') {
+ icon_uri = gnome_vfs_get_uri_from_local_path (icon_name);
+ } else {
+ icon_uri = NULL;
+ }
+ g_free (icon_name);
+
+ return icon_uri;
+ }
+
+ return NULL;
+}
+
+char *
+nautilus_link_desktop_file_local_get_link_uri (const char *path)
+{
+ NautilusDesktopFile *desktop_file = NULL;
+ gchar *retval;
+ GnomeVFSResult result;
+ char *uri;
+
+ uri = gnome_vfs_get_uri_from_local_path (path);
+ if (uri == NULL) {
+ return FALSE;
+ }
+
+ result = nautilus_desktop_file_load (uri, &desktop_file);
+
+ g_free (uri);
+
+ if (result != GNOME_VFS_OK) {
+ return NULL;
+ }
+
+ retval = nautilus_link_desktop_file_get_link_uri_from_desktop (desktop_file);
+
+ nautilus_desktop_file_free (desktop_file);
+ return retval;
+}
+
+char *
+nautilus_link_desktop_file_get_link_uri_given_file_contents (const char *link_file_contents,
+ int link_file_size)
+{
+ NautilusDesktopFile *desktop_file;
+ gchar *slurp;
+ gchar *retval;
+
+ slurp = g_strndup (link_file_contents, link_file_size);
+ desktop_file = nautilus_desktop_file_from_string (slurp);
+ g_free (slurp);
+ if (desktop_file == NULL) {
+ return NULL;
+ }
+ retval = nautilus_link_desktop_file_get_link_uri_from_desktop (desktop_file);
+
+ nautilus_desktop_file_free (desktop_file);
+ return retval;
+}
+
+char *
+nautilus_link_desktop_file_get_link_name_given_file_contents (const char *link_file_contents,
+ int link_file_size)
+{
+ NautilusDesktopFile *desktop_file;
+ gchar *slurp;
+ gchar *retval;
+
+ slurp = g_strndup (link_file_contents, link_file_size);
+ desktop_file = nautilus_desktop_file_from_string (slurp);
+ g_free (slurp);
+ if (desktop_file == NULL) {
+ return NULL;
+ }
+ retval = nautilus_link_desktop_file_get_link_name_from_desktop (desktop_file);
+
+ nautilus_desktop_file_free (desktop_file);
+ return retval;
+}
+
+
+char *
+nautilus_link_desktop_file_get_link_icon_given_file_contents (const char *link_file_contents,
+ int link_file_size)
+{
+ NautilusDesktopFile *desktop_file;
+ gchar *slurp;
+ gchar *retval;
+
+ slurp = g_strndup (link_file_contents, link_file_size);
+ desktop_file = nautilus_desktop_file_from_string (slurp);
+ g_free (slurp);
+ if (desktop_file == NULL) {
+ return NULL;
+ }
+ retval = nautilus_link_desktop_file_get_link_icon_from_desktop (desktop_file);
+
+ nautilus_desktop_file_free (desktop_file);
+ return retval;
+}
+
+
+void
+nautilus_link_desktop_file_local_create_from_gnome_entry (GnomeDesktopEntry *entry,
+ const char *dest_path,
+ const GdkPoint *position)
+{
+ char *uri;
+ GList dummy_list;
+ NautilusFileChangesQueuePosition item;
+ GnomeDesktopEntry *new_entry;
+ char *file_name;
+
+ new_entry = gnome_desktop_entry_copy (entry);
+ g_free (new_entry->location);
+ file_name = g_strdup_printf ("%s.desktop", entry->name);
+ new_entry->location = nautilus_make_path (dest_path, file_name);
+ g_free (file_name);
+ gnome_desktop_entry_save (new_entry);
+
+ uri = gnome_vfs_get_uri_from_local_path (dest_path);
+ dummy_list.data = uri;
+ dummy_list.next = NULL;
+ dummy_list.prev = NULL;
+ nautilus_directory_notify_files_added (&dummy_list);
+ nautilus_directory_schedule_metadata_remove (&dummy_list);
+
+ if (position != NULL) {
+ item.uri = uri;
+ item.set = TRUE;
+ item.point.x = position->x;
+ item.point.y = position->y;
+
+ dummy_list.data = &item;
+ dummy_list.next = NULL;
+ dummy_list.prev = NULL;
+
+ nautilus_directory_schedule_position_set (&dummy_list);
+ }
+ gnome_desktop_entry_free (new_entry);
+}
+
diff --git a/libnautilus-private/nautilus-link-desktop-file.h b/libnautilus-private/nautilus-link-desktop-file.h
new file mode 100644
index 000000000..4a4d8fb22
--- /dev/null
+++ b/libnautilus-private/nautilus-link-desktop-file.h
@@ -0,0 +1,61 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-
+
+ nautilus-link-desktop-file.h: .
+
+ Copyright (C) 2001 Red Hat, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public
+ License along with this program; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Authors: Jonathan Blandford <jrb@redhat.com>
+*/
+
+#ifndef NAUTILUS_LINK_DESKTOP_FILE_H
+#define NAUTILUS_LINK_DESKTOP_FILE_H
+
+#include "nautilus-file.h"
+#include <gdk/gdk.h>
+#include <libgnome/gnome-defs.h>
+#include <libgnome/gnome-dentry.h>
+
+
+gboolean nautilus_link_desktop_file_local_create (const char *directory_path,
+ const char *name,
+ const char *image,
+ const char *target_uri,
+ const GdkPoint *point,
+ NautilusLinkType type);
+gboolean nautilus_link_desktop_file_local_set_icon (const char *path,
+ const char *icon_name);
+char * nautilus_link_desktop_file_local_get_text (const char *path);
+char * nautilus_link_desktop_file_local_get_additional_text (const char *path);
+NautilusLinkType nautilus_link_desktop_file_local_get_link_type (const char *path);
+gboolean nautilus_link_desktop_file_local_is_volume_link (const char *path);
+gboolean nautilus_link_desktop_file_local_is_home_link (const char *path);
+gboolean nautilus_link_desktop_file_local_is_trash_link (const char *path);
+char * nautilus_link_desktop_file_local_get_link_uri (const char *path);
+char * nautilus_link_desktop_file_get_link_uri_given_file_contents (const char *link_file_contents,
+ int link_file_size);
+char * nautilus_link_desktop_file_get_link_name_given_file_contents (const char *link_file_contents,
+ int link_file_size);
+char * nautilus_link_desktop_file_get_link_icon_given_file_contents (const char *link_file_contents,
+ int link_file_size);
+void nautilus_link_desktop_file_local_create_from_gnome_entry (GnomeDesktopEntry *entry,
+ const char *dest_path,
+ const GdkPoint *position);
+
+
+#endif /* NAUTILUS_LINK_DESKTOP_FILE_H */
+
diff --git a/libnautilus-private/nautilus-link-historical.c b/libnautilus-private/nautilus-link-historical.c
new file mode 100644
index 000000000..4640f6600
--- /dev/null
+++ b/libnautilus-private/nautilus-link-historical.c
@@ -0,0 +1,435 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-
+
+ nautilus-link-historical.c: xml-based link files.
+
+ Copyright (C) 1999, 2000, 2001 Eazel, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the historicalied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public
+ License along with this program; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Author: Andy Hertzfeld <andy@eazel.com>
+*/
+
+#include <config.h>
+#include "nautilus-link.h"
+#include "nautilus-link-historical.h"
+
+#include "nautilus-directory-notify.h"
+#include "nautilus-directory.h"
+#include "nautilus-file-attributes.h"
+#include "nautilus-file.h"
+#include "nautilus-metadata.h"
+#include "nautilus-file-utilities.h"
+#include <eel/eel-glib-extensions.h>
+#include <eel/eel-gnome-extensions.h>
+#include <eel/eel-stock-dialogs.h>
+#include <eel/eel-string.h>
+#include <eel/eel-vfs-extensions.h>
+#include <eel/eel-xml-extensions.h>
+#include <gnome-xml/parser.h>
+#include <gnome-xml/xmlmemory.h>
+#include <libgnome/gnome-i18n.h>
+#include <libgnome/gnome-util.h>
+#include <libgnomevfs/gnome-vfs-mime.h>
+#include <libgnomevfs/gnome-vfs.h>
+#include <stdlib.h>
+
+
+#define NAUTILUS_LINK_GENERIC_TAG "Generic Link"
+#define NAUTILUS_LINK_TRASH_TAG "Trash Link"
+#define NAUTILUS_LINK_MOUNT_TAG "Mount Link"
+#define NAUTILUS_LINK_HOME_TAG "Home Link"
+
+#define REMOTE_ICON_DIR_PERMISSIONS (GNOME_VFS_PERM_USER_ALL \
+ | GNOME_VFS_PERM_GROUP_ALL \
+ | GNOME_VFS_PERM_OTHER_ALL)
+
+typedef void (* NautilusFileFunction) (NautilusFile *file);
+
+static const char *
+get_tag (NautilusLinkType type)
+{
+ switch (type) {
+ default:
+ g_assert_not_reached ();
+ /* fall through */
+ case NAUTILUS_LINK_GENERIC:
+ return NAUTILUS_LINK_GENERIC_TAG;
+ case NAUTILUS_LINK_TRASH:
+ return NAUTILUS_LINK_TRASH_TAG;
+ case NAUTILUS_LINK_MOUNT:
+ return NAUTILUS_LINK_MOUNT_TAG;
+ case NAUTILUS_LINK_HOME:
+ return NAUTILUS_LINK_HOME_TAG;
+ }
+}
+
+static NautilusLinkType
+get_link_type (const char *tag)
+{
+ if (tag != NULL) {
+ if (strcmp (tag, NAUTILUS_LINK_TRASH_TAG) == 0) {
+ return NAUTILUS_LINK_TRASH;
+ }
+ if (strcmp (tag, NAUTILUS_LINK_MOUNT_TAG) == 0) {
+ return NAUTILUS_LINK_MOUNT;
+ }
+ if (strcmp (tag, NAUTILUS_LINK_HOME_TAG) == 0) {
+ return NAUTILUS_LINK_HOME;
+ }
+ }
+ return NAUTILUS_LINK_GENERIC;
+}
+
+gboolean
+nautilus_link_historical_local_create (const char *directory_path,
+ const char *name,
+ const char *image,
+ const char *target_uri,
+ const GdkPoint *point,
+ NautilusLinkType type)
+{
+ xmlDocPtr output_document;
+ xmlNodePtr root_node;
+ char *path;
+ int result;
+ char *uri;
+ GList dummy_list;
+ NautilusFileChangesQueuePosition item;
+
+
+ g_return_val_if_fail (directory_path != NULL, FALSE);
+ g_return_val_if_fail (name != NULL, FALSE);
+ g_return_val_if_fail (image != NULL, FALSE);
+ g_return_val_if_fail (target_uri != NULL, FALSE);
+
+ /* create a new xml document */
+ output_document = xmlNewDoc ("1.0");
+
+ /* add the root node to the output document */
+ root_node = xmlNewDocNode (output_document, NULL, "nautilus_object", NULL);
+ xmlDocSetRootElement (output_document, root_node);
+
+ /* Add mime magic string so that the mime sniffer can recognize us.
+ * Note: The value of the tag identfies what type of link this. */
+ xmlSetProp (root_node, "nautilus_link", get_tag (type));
+
+ /* Add link and custom icon tags */
+ xmlSetProp (root_node, "custom_icon", image);
+ xmlSetProp (root_node, "link", target_uri);
+
+ /* all done, so save the xml document as a link file */
+ path = nautilus_make_path (directory_path, name);
+ result = xmlSaveFile (path, output_document);
+
+ xmlFreeDoc (output_document);
+
+ if (result <= 0) {
+ g_free (path);
+ return FALSE;
+ }
+
+ /* Notify that this new file has been created. */
+ uri = gnome_vfs_get_uri_from_local_path (path);
+ dummy_list.data = uri;
+ dummy_list.next = NULL;
+ dummy_list.prev = NULL;
+ nautilus_directory_notify_files_added (&dummy_list);
+ nautilus_directory_schedule_metadata_remove (&dummy_list);
+
+ if (point != NULL) {
+ item.uri = uri;
+ item.set = TRUE;
+ item.point.x = point->x;
+ item.point.y = point->y;
+
+ dummy_list.data = &item;
+ dummy_list.next = NULL;
+ dummy_list.prev = NULL;
+
+ nautilus_directory_schedule_position_set (&dummy_list);
+ }
+
+ g_free (uri);
+
+ g_free (path);
+
+ return TRUE;
+}
+
+static char *
+xml_get_root_property (xmlDoc *doc,
+ const char *key)
+{
+ char *property, *duplicate;
+
+ /* Need to g_strdup so we can free with g_free instead of xmlFree. */
+ property = xmlGetProp (xmlDocGetRootElement (doc), key);
+ duplicate = g_strdup (property);
+ xmlFree (property);
+ return duplicate;
+}
+
+static char *
+local_get_root_property (const char *path,
+ const char *key)
+{
+ xmlDoc *document;
+ char *property;
+ const char *mime_type;
+
+ property = NULL;
+
+ /* Check mime type. Exit if it is not a nautilus link */
+ mime_type = gnome_vfs_get_file_mime_type (path, NULL, FALSE);
+ if (strcmp (mime_type, "application/x-nautilus-link") != 0) {
+ return NULL;
+ }
+
+ document = xmlParseFile (path);
+ if (document != NULL) {
+ property = xml_get_root_property (document, key);
+ xmlFreeDoc (document);
+ }
+
+ return property;
+}
+
+static gboolean
+local_set_root_property (const char *uri,
+ const char *key,
+ const char *value,
+ NautilusFileFunction extra_notify)
+{
+ xmlDocPtr document;
+ xmlNodePtr root;
+ xmlChar *old_value;
+ char *path;
+ NautilusFile *file;
+
+ path = gnome_vfs_get_local_path_from_uri (uri);
+ document = xmlParseFile (path);
+ if (document == NULL) {
+ return FALSE;
+ }
+ root = xmlDocGetRootElement (document);
+ if (root == NULL) {
+ xmlFreeDoc (document);
+ return FALSE;
+ }
+
+ /* Check if the property value is already correct. */
+ old_value = xmlGetProp (root, key);
+ if (old_value != NULL && strcmp (old_value, value) == 0) {
+ xmlFreeDoc (document);
+ xmlFree (old_value);
+ return TRUE;
+ }
+
+ xmlFree (old_value);
+
+ /* Change and write the property. */
+ xmlSetProp (root, key, value);
+ xmlSaveFile (path, document);
+ xmlFreeDoc (document);
+
+ /* Notify about the change. */
+ file = nautilus_file_get (uri);
+ if (file != NULL) {
+ if (extra_notify != NULL) {
+ (* extra_notify) (file);
+ }
+ nautilus_file_changed (file);
+ nautilus_file_unref (file);
+ }
+ g_free (path);
+
+ return TRUE;
+}
+
+
+/* Set the icon for a link file. This can only be called on local
+ * paths, and only on files known to be link files.
+ */
+gboolean
+nautilus_link_historical_local_set_icon (const char *path, const char *icon_name)
+{
+ return local_set_root_property (path,
+ NAUTILUS_METADATA_KEY_CUSTOM_ICON,
+ icon_name,
+ NULL);
+}
+
+
+/* Set the link uri for a link file. This can only be called on local
+ * paths, and only on files known to be link files.
+ */
+gboolean
+nautilus_link_historical_local_set_link_uri (const char *path, const char *link_uri)
+{
+ return local_set_root_property (path,
+ "link",
+ link_uri,
+ NULL);
+}
+
+gboolean
+nautilus_link_historical_local_set_type (const char *path,
+ NautilusLinkType type)
+{
+ return local_set_root_property (path,
+ "nautilus_link",
+ get_tag (type),
+ NULL);
+}
+
+/* returns additional text to display under the name, NULL if none */
+char *
+nautilus_link_historical_local_get_additional_text (const char *path)
+{
+ return local_get_root_property
+ (path, NAUTILUS_METADATA_KEY_EXTRA_TEXT);
+}
+
+
+/* Returns the link uri associated with a link file. */
+char *
+nautilus_link_historical_local_get_link_uri (const char *path)
+{
+ return local_get_root_property (path, "link");
+}
+
+/* Returns the link type of the link file. */
+NautilusLinkType
+nautilus_link_historical_local_get_link_type (const char *path)
+{
+ char *property;
+ NautilusLinkType type;
+
+ property = local_get_root_property (path, "nautilus_link");
+ type = get_link_type (property);
+ g_free (property);
+
+ return type;
+}
+
+/* FIXME bugzilla.eazel.com 2495:
+ * Caller has to know to pass in a file with a NUL character at the end.
+ */
+char *
+nautilus_link_historical_get_link_uri_given_file_contents (const char *file_contents,
+ int file_size)
+{
+ xmlDoc *doc;
+ char *property;
+
+ doc = xmlParseMemory ((char *) file_contents, file_size);
+ property = xml_get_root_property (doc, "link");
+ xmlFreeDoc (doc);
+ return property;
+}
+
+
+char *
+nautilus_link_historical_get_link_icon_given_file_contents (const char *file_contents,
+ int file_size)
+{
+ xmlDoc *doc;
+ char *property;
+
+ doc = xmlParseMemory ((char *) file_contents, file_size);
+ property = xml_get_root_property (doc, NAUTILUS_METADATA_KEY_CUSTOM_ICON);
+ xmlFreeDoc (doc);
+ return property;
+}
+
+
+gboolean
+nautilus_link_historical_local_is_volume_link (const char *path)
+{
+ return nautilus_link_historical_local_get_link_type (path) == NAUTILUS_LINK_MOUNT;
+}
+
+gboolean
+nautilus_link_historical_local_is_home_link (const char *path)
+{
+ return nautilus_link_historical_local_get_link_type (path) == NAUTILUS_LINK_HOME;
+}
+
+gboolean
+nautilus_link_historical_local_is_trash_link (const char *path)
+{
+ return nautilus_link_historical_local_get_link_type (path) == NAUTILUS_LINK_TRASH;
+}
+
+
+void
+nautilus_link_historical_local_create_from_gnome_entry (GnomeDesktopEntry *entry, const char *dest_path, const GdkPoint *position)
+{
+ char *icon_name;
+ char *launch_string, *terminal_command;
+ char *quoted, *arguments, *temp_str;
+ int i;
+
+ if (entry == NULL || dest_path == NULL) {
+ return;
+ }
+
+ /* Extract arguments from exec array */
+ arguments = NULL;
+ for (i = 0; i < entry->exec_length; ++i) {
+ quoted = eel_shell_quote (entry->exec[i]);
+ if (arguments == NULL) {
+ arguments = quoted;
+ } else {
+ temp_str = arguments;
+ arguments = g_strconcat (arguments, " ", quoted, NULL);
+ g_free (temp_str);
+ g_free (quoted);
+ }
+ }
+
+ if (strcmp (entry->type, "Application") == 0) {
+ if (entry->terminal) {
+ terminal_command = eel_gnome_make_terminal_command (arguments);
+ launch_string = g_strconcat ("command:", terminal_command, NULL);
+ g_free (terminal_command);
+ } else {
+ launch_string = g_strconcat ("command:", arguments, NULL);
+ }
+ } else if (strcmp (entry->type, "URL") == 0) {
+ launch_string = g_strdup (arguments);
+ } else {
+ /* Unknown .desktop file type */
+ launch_string = NULL;
+ }
+
+ if (entry->icon != NULL) {
+ icon_name = eel_make_uri_from_half_baked_uri (entry->icon);
+ } else {
+ icon_name = g_strdup ("gnome-unknown.png");
+ }
+
+ if (launch_string != NULL) {
+ nautilus_link_historical_local_create (dest_path, entry->name, icon_name,
+ launch_string, position, NAUTILUS_LINK_GENERIC);
+ }
+
+ g_free (icon_name);
+ g_free (launch_string);
+ g_free (arguments);
+}
+
+
diff --git a/libnautilus-private/nautilus-link-historical.h b/libnautilus-private/nautilus-link-historical.h
new file mode 100644
index 000000000..b181ec7af
--- /dev/null
+++ b/libnautilus-private/nautilus-link-historical.h
@@ -0,0 +1,60 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-
+
+ nautilus-link-historical.h: xml-based link files that control their appearance
+ and behavior.
+
+ Copyright (C) 2000 Eazel, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public
+ License along with this program; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Authors: Andy Hertzfeld <andy@eazel.com>
+*/
+
+#ifndef NAUTILUS_LINK_HISTORICAL_H
+#define NAUTILUS_LINK_HISTORICAL_H
+
+#include "nautilus-file.h"
+#include <gdk/gdk.h>
+#include <libgnome/gnome-defs.h>
+#include <libgnome/gnome-dentry.h>
+
+gboolean nautilus_link_historical_local_create (const char *directory_path,
+ const char *name,
+ const char *image,
+ const char *target_uri,
+ const GdkPoint *point,
+ NautilusLinkType type);
+gboolean nautilus_link_historical_local_set_icon (const char *path,
+ const char *icon_name);
+gboolean nautilus_link_historical_local_set_type (const char *path,
+ NautilusLinkType type);
+gboolean nautilus_link_historical_local_set_link_uri (const char *path,
+ const char *uri);
+char * nautilus_link_historical_local_get_additional_text (const char *path);
+NautilusLinkType nautilus_link_historical_local_get_link_type (const char *path);
+gboolean nautilus_link_historical_local_is_volume_link (const char *path);
+gboolean nautilus_link_historical_local_is_home_link (const char *path);
+gboolean nautilus_link_historical_local_is_trash_link (const char *path);
+char * nautilus_link_historical_local_get_link_uri (const char *path);
+char * nautilus_link_historical_get_link_uri_given_file_contents (const char *link_file_contents,
+ int link_file_size);
+char * nautilus_link_historical_get_link_icon_given_file_contents (const char *link_file_contents,
+ int link_file_size);
+void nautilus_link_historical_local_create_from_gnome_entry (GnomeDesktopEntry *entry,
+ const char *dest_path,
+ const GdkPoint *position);
+
+#endif /* NAUTILUS_LINK_HISTORICAL_H */
diff --git a/libnautilus-private/nautilus-link.c b/libnautilus-private/nautilus-link.c
index 47b92a292..bedf5954c 100644
--- a/libnautilus-private/nautilus-link.c
+++ b/libnautilus-private/nautilus-link.c
@@ -24,6 +24,8 @@
#include <config.h>
#include "nautilus-link.h"
+#include "nautilus-link-historical.h"
+#include "nautilus-link-desktop-file.h"
#include "nautilus-directory-notify.h"
#include "nautilus-directory.h"
@@ -45,56 +47,19 @@
#include <libgnomevfs/gnome-vfs.h>
#include <stdlib.h>
-/* Link type XML tags */
-#define NAUTILUS_LINK_GENERIC_TAG "Generic Link"
-#define NAUTILUS_LINK_TRASH_TAG "Trash Link"
-#define NAUTILUS_LINK_MOUNT_TAG "Mount Link"
-#define NAUTILUS_LINK_HOME_TAG "Home Link"
+const char *get_uri_mime_type_full (const gchar *uri_path);
-#define REMOTE_ICON_DIR_PERMISSIONS (GNOME_VFS_PERM_USER_ALL \
- | GNOME_VFS_PERM_GROUP_ALL \
- | GNOME_VFS_PERM_OTHER_ALL)
-
-typedef struct {
- char *link_uri;
- char *file_path;
-} NautilusLinkIconNotificationInfo;
-
-typedef void (* NautilusFileFunction) (NautilusFile *file);
-
-static const char *
-get_tag (NautilusLinkType type)
+const char *
+get_uri_mime_type_full (const gchar *uri_path)
{
- switch (type) {
- default:
- g_assert_not_reached ();
- /* fall through */
- case NAUTILUS_LINK_GENERIC:
- return NAUTILUS_LINK_GENERIC_TAG;
- case NAUTILUS_LINK_TRASH:
- return NAUTILUS_LINK_TRASH_TAG;
- case NAUTILUS_LINK_MOUNT:
- return NAUTILUS_LINK_MOUNT_TAG;
- case NAUTILUS_LINK_HOME:
- return NAUTILUS_LINK_HOME_TAG;
- }
-}
+ const gchar *retval;
+ GnomeVFSURI *uri;
-static NautilusLinkType
-get_link_type (const char *tag)
-{
- if (tag != NULL) {
- if (strcmp (tag, NAUTILUS_LINK_TRASH_TAG) == 0) {
- return NAUTILUS_LINK_TRASH;
- }
- if (strcmp (tag, NAUTILUS_LINK_MOUNT_TAG) == 0) {
- return NAUTILUS_LINK_MOUNT;
- }
- if (strcmp (tag, NAUTILUS_LINK_HOME_TAG) == 0) {
- return NAUTILUS_LINK_HOME;
- }
- }
- return NAUTILUS_LINK_GENERIC;
+ uri = gnome_vfs_uri_new (uri_path);
+ retval = gnome_vfs_get_mime_type (uri);
+ gnome_vfs_uri_unref (uri);
+
+ return retval;
}
gboolean
@@ -105,457 +70,292 @@ nautilus_link_local_create (const char *directory_path,
const GdkPoint *point,
NautilusLinkType type)
{
- xmlDocPtr output_document;
- xmlNodePtr root_node;
- char *path;
- int result;
- char *uri;
- GList dummy_list;
- NautilusFileChangesQueuePosition item;
+ gboolean retval;
-
- g_return_val_if_fail (directory_path != NULL, FALSE);
- g_return_val_if_fail (name != NULL, FALSE);
- g_return_val_if_fail (image != NULL, FALSE);
- g_return_val_if_fail (target_uri != NULL, FALSE);
-
- /* create a new xml document */
- output_document = xmlNewDoc ("1.0");
-
- /* add the root node to the output document */
- root_node = xmlNewDocNode (output_document, NULL, "nautilus_object", NULL);
- xmlDocSetRootElement (output_document, root_node);
-
- /* Add mime magic string so that the mime sniffer can recognize us.
- * Note: The value of the tag identfies what type of link this. */
- xmlSetProp (root_node, "nautilus_link", get_tag (type));
-
- /* Add link and custom icon tags */
- xmlSetProp (root_node, "custom_icon", image);
- xmlSetProp (root_node, "link", target_uri);
-
- /* all done, so save the xml document as a link file */
- path = nautilus_make_path (directory_path, name);
- result = xmlSaveFile (path, output_document);
-
- xmlFreeDoc (output_document);
+ retval = nautilus_link_desktop_file_local_create (directory_path,
+ name, image,
+ target_uri, point,
+ type);
- if (result <= 0) {
- g_free (path);
- return FALSE;
- }
-
- /* Notify that this new file has been created. */
- uri = gnome_vfs_get_uri_from_local_path (path);
- dummy_list.data = uri;
- dummy_list.next = NULL;
- dummy_list.prev = NULL;
- nautilus_directory_notify_files_added (&dummy_list);
- nautilus_directory_schedule_metadata_remove (&dummy_list);
-
- if (point != NULL) {
- item.uri = uri;
- item.set = TRUE;
- item.point.x = point->x;
- item.point.y = point->y;
-
- dummy_list.data = &item;
- dummy_list.next = NULL;
- dummy_list.prev = NULL;
-
- nautilus_directory_schedule_position_set (&dummy_list);
- }
-
- g_free (uri);
-
- g_free (path);
-
- return TRUE;
+ return retval;
}
-static char *
-xml_get_root_property (xmlDoc *doc,
- const char *key)
+gboolean
+nautilus_link_local_set_icon (const char *path, const char *icon_name)
{
- char *property, *duplicate;
-
- /* Need to g_strdup so we can free with g_free instead of xmlFree. */
- property = xmlGetProp (xmlDocGetRootElement (doc), key);
- duplicate = g_strdup (property);
- xmlFree (property);
- return duplicate;
-}
+ const gchar *mime_type;
+ gboolean retval;
+ NautilusFile *file;
+ GList *attributes;
-static char *
-local_get_root_property (const char *path,
- const char *key)
-{
- xmlDoc *document;
- char *property;
- const char *mime_type;
-
- property = NULL;
+ mime_type = get_uri_mime_type_full (path);
+ retval = FALSE;
- /* Check mime type. Exit if it is not a nautilus link */
- mime_type = gnome_vfs_get_file_mime_type (path, NULL, FALSE);
- if (strcmp (mime_type, "application/x-nautilus-link") != 0) {
- return NULL;
+ if (mime_type == NULL) {
+ return retval;
}
-
- document = xmlParseFile (path);
- if (document != NULL) {
- property = xml_get_root_property (document, key);
- xmlFreeDoc (document);
- }
-
- return property;
-}
-
-static gboolean
-local_set_root_property (const char *path,
- const char *key,
- const char *value,
- NautilusFileFunction extra_notify)
-{
- xmlDocPtr document;
- xmlNodePtr root;
- xmlChar *old_value;
- char *uri;
- NautilusFile *file;
- document = xmlParseFile (path);
- if (document == NULL) {
- return FALSE;
- }
- root = xmlDocGetRootElement (document);
- if (root == NULL) {
- xmlFreeDoc (document);
- return FALSE;
+ if (strcmp (mime_type, "application/x-nautilus-link") == 0) {
+ retval = nautilus_link_historical_local_set_icon (path, icon_name);
+ } else if (strcmp (mime_type, "application/x-gnome-app-info") == 0) {
+ retval = nautilus_link_desktop_file_local_set_icon (path, icon_name);
}
- /* Check if the property value is already correct. */
- old_value = xmlGetProp (root, key);
- if (old_value != NULL && strcmp (old_value, value) == 0) {
- xmlFreeDoc (document);
- xmlFree (old_value);
- return TRUE;
- }
+ file = nautilus_file_get (path);
+ attributes = g_list_prepend (NULL, NAUTILUS_FILE_ATTRIBUTE_ACTIVATION_URI);
+ nautilus_file_invalidate_attributes (file, attributes);
+ nautilus_file_unref (file);
+ g_list_free (attributes);
- xmlFree (old_value);
-
- /* Change and write the property. */
- xmlSetProp (root, key, value);
- xmlSaveFile (path, document);
- xmlFreeDoc (document);
-
- /* Notify about the change. */
- uri = gnome_vfs_get_uri_from_local_path (path);
- file = nautilus_file_get (uri);
- if (file != NULL) {
- if (extra_notify != NULL) {
- (* extra_notify) (file);
- }
- nautilus_file_changed (file);
- nautilus_file_unref (file);
- }
- g_free (uri);
-
- return TRUE;
+ return retval;
}
-/* Set the icon for a link file. This can only be called on local
- * paths, and only on files known to be link files.
- */
gboolean
-nautilus_link_local_set_icon (const char *path, const char *icon_name)
+nautilus_link_local_set_link_uri (const char *path, const char *link_uri)
{
- return local_set_root_property (path,
- NAUTILUS_METADATA_KEY_CUSTOM_ICON,
- icon_name,
- NULL);
-}
+ const gchar *mime_type;
+ gboolean retval;
+ NautilusFile *file;
+ GList *attributes;
+ mime_type = get_uri_mime_type_full (path);
+ retval = FALSE;
-static void
-forget_file_activation_uri (NautilusFile *file)
-{
- GList *attributes;
+ if (mime_type == NULL) {
+ return retval;
+ }
+ if (strcmp (mime_type, "application/x-nautilus-link") == 0) {
+ retval = nautilus_link_historical_local_set_link_uri (path, link_uri);
+ }
+ /* FIXME: May want to implement this for desktop files too */
+
+ file = nautilus_file_get (path);
attributes = g_list_prepend (NULL, NAUTILUS_FILE_ATTRIBUTE_ACTIVATION_URI);
nautilus_file_invalidate_attributes (file, attributes);
+ nautilus_file_unref (file);
g_list_free (attributes);
-}
-/* Set the link uri for a link file. This can only be called on local
- * paths, and only on files known to be link files.
- */
-gboolean
-nautilus_link_local_set_link_uri (const char *path, const char *link_uri)
-{
- return local_set_root_property (path,
- "link",
- link_uri,
- forget_file_activation_uri);
+ return retval;
}
gboolean
nautilus_link_local_set_type (const char *path,
NautilusLinkType type)
{
- return local_set_root_property (path,
- "nautilus_link",
- get_tag (type),
- NULL);
+ const gchar *mime_type;
+ gboolean retval;
+
+ mime_type = get_uri_mime_type_full (path);
+ retval = FALSE;
+
+ if (mime_type == NULL) {
+ return retval;
+ }
+
+ if (strcmp (mime_type, "application/x-nautilus-link") == 0) {
+ retval = nautilus_link_historical_local_set_type (path, type);
+ }
+ /* FIXME: May want to implement this for desktop files too */
+
+ return retval;
}
/* returns additional text to display under the name, NULL if none */
char *
nautilus_link_local_get_additional_text (const char *path)
{
- return local_get_root_property
- (path, NAUTILUS_METADATA_KEY_EXTRA_TEXT);
-}
+ const gchar *mime_type;
+ gchar *retval;
-/* utility to return the local pathname of a cached icon, given the leaf name */
-/* if the icons directory hasn't been created yet, create it */
-static char *
-make_local_path (const char *image_uri)
-{
- GnomeVFSResult result;
-
- char *escaped_uri, *local_directory_path, *local_directory_uri, *local_file_path;
-
- escaped_uri = gnome_vfs_escape_slashes (image_uri);
-
- local_directory_path = g_strconcat
- (g_get_home_dir (),
- "/.nautilus/remote_icons",
- NULL);
-
- /* We must create the directory if it doesn't exist. */
- local_directory_uri = gnome_vfs_get_uri_from_local_path (local_directory_path);
- result = gnome_vfs_make_directory (local_directory_uri, REMOTE_ICON_DIR_PERMISSIONS);
- if (result != GNOME_VFS_OK) {
- g_free (local_directory_uri);
- g_free (escaped_uri);
- g_free (local_directory_path);
- return NULL;
- }
-
- local_file_path = nautilus_make_path (local_directory_path, escaped_uri);
- g_free (local_directory_uri);
- g_free (escaped_uri);
- g_free (local_directory_path);
+ mime_type = get_uri_mime_type_full (path);
+ retval = NULL;
- return local_file_path;
-}
+ if (mime_type == NULL) {
+ return retval;
+ }
-/* utility to free the icon notification info */
+ if (strcmp (mime_type, "application/x-nautilus-link") == 0) {
+ retval = nautilus_link_historical_local_get_additional_text (path);
+ } else if (strcmp (mime_type, "application/x-gnome-app-info") == 0) {
+ retval = nautilus_link_desktop_file_local_get_additional_text (path);
+ }
-static void
-free_icon_notification_info (NautilusLinkIconNotificationInfo *info)
-{
- g_free (info->link_uri);
- g_free (info->file_path);
- g_free (info);
+ return retval;
}
-/* callback to handle the asynchronous reading of icons */
-static void
-icon_read_done_callback (GnomeVFSResult result,
- GnomeVFSFileSize file_size,
- char *file_contents,
- gpointer callback_data)
+/* Returns the link uri associated with a link file. */
+char *
+nautilus_link_local_get_link_uri (const char *path)
{
- int size;
- FILE* outfile;
- NautilusFile *file;
- NautilusLinkIconNotificationInfo *info;
-
- info = (NautilusLinkIconNotificationInfo *) callback_data;
+ const gchar *mime_type;
+ gchar *retval;
- if (result != GNOME_VFS_OK) {
- g_assert (file_contents == NULL);
- free_icon_notification_info (info);
- return;
- }
+ mime_type = get_uri_mime_type_full (path);
+ retval = NULL;
- /* write out the file into the cache area */
- size = file_size;
- outfile = fopen (info->file_path, "wb");
- fwrite (file_contents, size, 1, outfile);
- fclose (outfile);
-
- g_free (file_contents);
+ if (mime_type == NULL) {
+ return retval;
+ }
- /* tell the world that the file has changed */
- file = nautilus_file_get (info->link_uri);
- if (file != NULL) {
- nautilus_file_changed (file);
- nautilus_file_unref (file);
+ if (strcmp (mime_type, "application/x-nautilus-link") == 0) {
+ retval = nautilus_link_historical_local_get_link_uri (path);
+ } else if (strcmp (mime_type, "application/x-gnome-app-info") == 0) {
+ retval = nautilus_link_desktop_file_local_get_link_uri (path);
}
-
- /* free up the notification info */
- free_icon_notification_info (info);
+
+ return retval;
}
-/* returns the image associated with a link file */
-char *
-nautilus_link_local_get_image_uri (const char *path)
+/* Returns the link type of the link file. */
+NautilusLinkType
+nautilus_link_local_get_link_type (const char *path)
{
- xmlDoc *doc;
- char *icon_uri;
- char *local_path, *local_uri;
- NautilusLinkIconNotificationInfo *info;
-
- doc = xmlParseFile (path);
- if (doc == NULL) {
- return NULL;
- }
-
- icon_uri = xml_get_root_property (doc, NAUTILUS_METADATA_KEY_CUSTOM_ICON);
- xmlFreeDoc (doc);
+ const gchar *mime_type;
+ NautilusLinkType retval;
- if (icon_uri == NULL) {
- return NULL;
+ mime_type = get_uri_mime_type_full (path);
+ retval = NAUTILUS_LINK_GENERIC;
+
+ if (mime_type == NULL) {
+ return retval;
}
-
- /* if the image is remote, see if we can find it in our local cache */
- if (eel_is_remote_uri (icon_uri)) {
- local_path = make_local_path (icon_uri);
- if (local_path == NULL) {
- g_free (icon_uri);
- return NULL;
- }
- if (g_file_exists (local_path)) {
- g_free (icon_uri);
- local_uri = gnome_vfs_get_uri_from_local_path (local_path);
- g_free (local_path);
- return local_uri;
- }
-
- /* load it asynchronously through gnome-vfs */
- info = g_new0 (NautilusLinkIconNotificationInfo, 1);
- info->link_uri = gnome_vfs_get_uri_from_local_path (path);
- info->file_path = local_path;
- eel_read_entire_file_async (icon_uri, icon_read_done_callback, info);
-
- g_free (icon_uri);
- return NULL; /* return NULL since the icon is still loading - it will get correctly set by the callback */
+
+ if (strcmp (mime_type, "application/x-nautilus-link") == 0) {
+ retval = nautilus_link_historical_local_get_link_type (path);
+ } else if (strcmp (mime_type, "application/x-gnome-app-info") == 0) {
+ retval = nautilus_link_desktop_file_local_get_link_type (path);
}
-
- return icon_uri;
+
+ return retval;
}
-/* Returns the link uri associated with a link file. */
char *
-nautilus_link_local_get_link_uri (const char *path)
+nautilus_link_get_link_uri_given_file_contents (const char *file_contents,
+ int file_size)
{
- return local_get_root_property (path, "link");
+ const gchar *mime_type;
+ gchar *retval;
+
+ mime_type = gnome_vfs_get_mime_type_for_data (file_contents, file_size);
+ retval = NULL;
+
+ if (strcmp (mime_type, "application/x-nautilus-link") == 0) {
+ retval = nautilus_link_historical_get_link_uri_given_file_contents (file_contents, file_size);
+ } else if (strcmp (mime_type, "application/x-gnome-app-info") == 0) {
+ retval = nautilus_link_desktop_file_get_link_uri_given_file_contents (file_contents, file_size);
+ }
+
+ return retval;
}
-/* Returns the link type of the link file. */
-NautilusLinkType
-nautilus_link_local_get_link_type (const char *path)
+char *
+nautilus_link_get_link_name_given_file_contents (const char *file_contents,
+ int file_size)
{
- char *property;
- NautilusLinkType type;
-
- property = local_get_root_property (path, "nautilus_link");
- type = get_link_type (property);
- g_free (property);
+ const gchar *mime_type;
+ gchar *retval;
+
+ mime_type = gnome_vfs_get_mime_type_for_data (file_contents, file_size);
+ retval = NULL;
- return type;
+ if (strcmp (mime_type, "application/x-nautilus-link") == 0) {
+ retval = NULL;
+ } else if (strcmp (mime_type, "application/x-gnome-app-info") == 0) {
+ retval = nautilus_link_desktop_file_get_link_name_given_file_contents (file_contents, file_size);
+ }
+
+ return retval;
}
-/* FIXME bugzilla.gnome.org 42495:
- * Caller has to know to pass in a file with a NUL character at the end.
- */
char *
-nautilus_link_get_link_uri_given_file_contents (const char *file_contents,
+nautilus_link_get_link_icon_given_file_contents (const char *file_contents,
int file_size)
{
- xmlDoc *doc;
- char *property;
-
- doc = xmlParseMemory ((char *) file_contents, file_size);
- property = xml_get_root_property (doc, "link");
- xmlFreeDoc (doc);
- return property;
+ const gchar *mime_type;
+ gchar *retval;
+
+ mime_type = gnome_vfs_get_mime_type_for_data (file_contents, file_size);
+ retval = NULL;
+
+ if (strcmp (mime_type, "application/x-nautilus-link") == 0) {
+ retval = nautilus_link_historical_get_link_icon_given_file_contents (file_contents, file_size);
+ } else if (strcmp (mime_type, "application/x-gnome-app-info") == 0) {
+ retval = nautilus_link_desktop_file_get_link_icon_given_file_contents (file_contents, file_size);
+ }
+
+ return retval;
}
gboolean
nautilus_link_local_is_volume_link (const char *path)
{
- return nautilus_link_local_get_link_type (path) == NAUTILUS_LINK_MOUNT;
+ const gchar *mime_type;
+ gboolean retval;
+
+ mime_type = get_uri_mime_type_full (path);
+ retval = FALSE;
+
+ if (mime_type == NULL) {
+ return retval;
+ }
+
+ if (strcmp (mime_type, "application/x-nautilus-link") == 0) {
+ retval = nautilus_link_historical_local_is_volume_link (path);
+ } else if (strcmp (mime_type, "application/x-gnome-app-info") == 0) {
+ retval = nautilus_link_desktop_file_local_is_volume_link (path);
+ }
+
+ return retval;
}
gboolean
nautilus_link_local_is_home_link (const char *path)
{
- return nautilus_link_local_get_link_type (path) == NAUTILUS_LINK_HOME;
+ const gchar *mime_type;
+ gboolean retval;
+
+ mime_type = get_uri_mime_type_full (path);
+ retval = FALSE;
+
+ if (mime_type == NULL) {
+ return retval;
+ }
+
+ if (strcmp (mime_type, "application/x-nautilus-link") == 0) {
+ retval = nautilus_link_historical_local_is_home_link (path);
+ } else if (strcmp (mime_type, "application/x-gnome-app-info") == 0) {
+ retval = nautilus_link_desktop_file_local_is_home_link (path);
+ }
+
+ return retval;
}
gboolean
nautilus_link_local_is_trash_link (const char *path)
{
- return nautilus_link_local_get_link_type (path) == NAUTILUS_LINK_TRASH;
+ const gchar *mime_type;
+ gboolean retval;
+
+ mime_type = get_uri_mime_type_full (path);
+ retval = FALSE;
+
+ if (mime_type == NULL) {
+ return retval;
+ }
+
+ if (strcmp (mime_type, "application/x-nautilus-link") == 0) {
+ retval = nautilus_link_historical_local_is_trash_link (path);
+ } else if (strcmp (mime_type, "application/x-gnome-app-info") == 0) {
+ retval = nautilus_link_desktop_file_local_is_trash_link (path);
+ }
+
+ return retval;
}
void
nautilus_link_local_create_from_gnome_entry (GnomeDesktopEntry *entry, const char *dest_path, const GdkPoint *position)
{
- char *icon_name;
- char *launch_string, *terminal_command;
- char *quoted, *arguments, *temp_str;
- int i;
-
- if (entry == NULL || dest_path == NULL) {
- return;
- }
-
- /* Extract arguments from exec array */
- arguments = NULL;
- for (i = 0; i < entry->exec_length; ++i) {
- quoted = eel_shell_quote (entry->exec[i]);
- if (arguments == NULL) {
- arguments = quoted;
- } else {
- temp_str = arguments;
- arguments = g_strconcat (arguments, " ", quoted, NULL);
- g_free (temp_str);
- g_free (quoted);
- }
- }
-
- if (strcmp (entry->type, "Application") == 0) {
- if (entry->terminal) {
- terminal_command = eel_gnome_make_terminal_command (arguments);
- launch_string = g_strconcat ("command:", terminal_command, NULL);
- g_free (terminal_command);
- } else {
- launch_string = g_strconcat ("command:", arguments, NULL);
- }
- } else if (strcmp (entry->type, "URL") == 0) {
- launch_string = g_strdup (arguments);
- } else {
- /* Unknown .desktop file type */
- launch_string = NULL;
- }
-
- if (entry->icon != NULL) {
- icon_name = eel_make_uri_from_half_baked_uri (entry->icon);
- } else {
- icon_name = g_strdup ("gnome-unknown.png");
- }
-
- if (launch_string != NULL) {
- nautilus_link_local_create (dest_path, entry->name, icon_name,
- launch_string, position, NAUTILUS_LINK_GENERIC);
- }
-
- g_free (icon_name);
- g_free (launch_string);
- g_free (arguments);
+ nautilus_link_desktop_file_local_create_from_gnome_entry (entry, dest_path, position);
}
diff --git a/libnautilus-private/nautilus-link.h b/libnautilus-private/nautilus-link.h
index 88882ccb5..a1864b91d 100644
--- a/libnautilus-private/nautilus-link.h
+++ b/libnautilus-private/nautilus-link.h
@@ -78,13 +78,6 @@ gboolean nautilus_link_local_set_link_uri (const char
*/
char * nautilus_link_local_get_additional_text (const char *path);
-/* Returns the image associated with a link file. Despite the fact
- * that it takes a URI parameter, works only if the file is local and
- * does sync. I/O on the link, although it does async. on the image
- * and caches if the image is remote.
- */
-char * nautilus_link_local_get_image_uri (const char *path);
-
/* Returns the link type of a link file.
* Works only if the file is local and does sync. I/O
*/
@@ -115,9 +108,12 @@ gboolean nautilus_link_local_is_trash_link (const char
char * nautilus_link_local_get_link_uri (const char *path);
char * nautilus_link_get_link_uri_given_file_contents (const char *link_file_contents,
int link_file_size);
-
-void nautilus_link_local_create_from_gnome_entry (GnomeDesktopEntry *entry,
- const char *dest_path,
- const GdkPoint *position);
+char * nautilus_link_get_link_name_given_file_contents (const char *file_contents,
+ int link_file_size);
+char * nautilus_link_get_link_icon_given_file_contents (const char *file_contents,
+ int link_file_size);
+void nautilus_link_local_create_from_gnome_entry (GnomeDesktopEntry *entry,
+ const char *dest_path,
+ const GdkPoint *position);
#endif /* NAUTILUS_LINK_H */