diff options
author | Ramiro Estrugo <ramiro@src.gnome.org> | 2001-05-04 03:14:43 +0000 |
---|---|---|
committer | Ramiro Estrugo <ramiro@src.gnome.org> | 2001-05-04 03:14:43 +0000 |
commit | 90d404095e84a45c486e79ff7a9d6eeb05f8eba6 (patch) | |
tree | 636211d232efa67bac7352e519e6915a54dd100d /libnautilus-extensions | |
parent | fdea327acb1b4dadb3673c2f9c4e6a3bd9aab324 (diff) | |
download | nautilus-90d404095e84a45c486e79ff7a9d6eeb05f8eba6.tar.gz |
nautilus-extensions -> nautilus-private renaming.
Diffstat (limited to 'libnautilus-extensions')
140 files changed, 0 insertions, 63056 deletions
diff --git a/libnautilus-extensions/.cvsignore b/libnautilus-extensions/.cvsignore deleted file mode 100644 index 89d7dd9e4..000000000 --- a/libnautilus-extensions/.cvsignore +++ /dev/null @@ -1,15 +0,0 @@ -.deps -.libs -*.lo -Makefile -Makefile.in -libnautilus-extensions.la -*-skels.c -*-stubs.c -*-common.c -fsextension.h -fsextension_idl_stamp -nautilus-undo-manager-component.h -nautilus_undo_manager_component_idl_stamp -nautilus-metafile-server.h -nautilus_metafile_server_idl_stamp diff --git a/libnautilus-extensions/Makefile.am b/libnautilus-extensions/Makefile.am deleted file mode 100644 index 3eeab5019..000000000 --- a/libnautilus-extensions/Makefile.am +++ /dev/null @@ -1,211 +0,0 @@ -include $(top_srcdir)/Makefile.shared - -lib_LTLIBRARIES=libnautilus-extensions.la - -INCLUDES = \ - -I$(top_srcdir) \ - -I$(top_builddir) \ - -I$(top_builddir)/libnautilus \ - -I$(top_srcdir)/cut-n-paste-code \ - $(NAUTILUS_PRIVATE_CFLAGS) \ - $(ESD_CFLAGS) \ - $(MEDUSA_CFLAGS) \ - -DDATADIR=\""$(datadir)"\" \ - -DNAUTILUS_DATADIR=\""$(datadir)/nautilus"\" \ - $(NULL) - -dependency_static_libs = \ - $(top_builddir)/cut-n-paste-code/widgets/e-paned/libe-paned.la \ - $(top_builddir)/cut-n-paste-code/widgets/gimphwrapbox/libgtkhwrapbox.la \ - $(NULL) - -if HAVE_CDDA -CDDALIBADD = -lcdda_paranoia -lcdda_interface -else -CDDALIBADD = -endif - -libnautilus_extensions_la_LDFLAGS = \ - $(dependency_static_libs) \ - $(NAUTILUS_PRIVATE_LIBS) \ - $(ESD_LIBS) \ - $(LIBJPEG) \ - $(MEDUSA_LIBS) \ - $(CDDALIBADD) \ - $(NULL) - -nautilus_metafile_server_idl_sources = \ - nautilus-metafile-server-stubs.c \ - nautilus-metafile-server-skels.c \ - nautilus-metafile-server.h \ - nautilus-metafile-server-common.c \ - $(NULL) - -libnautilus_extensions_la_SOURCES = \ - $(nautilus_metafile_server_idl_sources) \ - nautilus-audio-player.c \ - nautilus-bonobo-extensions.c \ - nautilus-bookmark.c \ - nautilus-customization-data.c \ - nautilus-dateedit-extensions.c \ - nautilus-default-file-icon.c \ - nautilus-directory-async.c \ - nautilus-directory-background.c \ - nautilus-directory-metafile-monitor.c \ - nautilus-directory-metafile.c \ - nautilus-directory.c \ - nautilus-drag-window.c \ - nautilus-druid-page-eazel.c \ - nautilus-druid.c \ - nautilus-entry.c \ - nautilus-file-changes-queue.c \ - nautilus-file-dnd.c \ - nautilus-file-operations-progress.c \ - nautilus-file-operations.c \ - nautilus-file-utilities.c \ - nautilus-file.c \ - nautilus-font-factory.c \ - nautilus-gconf-extensions.c \ - nautilus-generous-bin.c \ - nautilus-global-preferences.c \ - nautilus-horizontal-splitter.c \ - nautilus-icon-canvas-item.c \ - nautilus-icon-container.c \ - nautilus-icon-dnd.c \ - nautilus-icon-factory.c \ - nautilus-icon-text-item.c \ - nautilus-keep-last-vertical-box.c \ - nautilus-lib-self-check-functions.c \ - nautilus-link-set.c \ - nautilus-link.c \ - nautilus-medusa-support.c \ - nautilus-merged-directory.c \ - nautilus-metafile-factory.c \ - nautilus-metafile.c \ - nautilus-mime-actions.c \ - nautilus-monitor.c \ - nautilus-preferences-box.c \ - nautilus-preferences-group.c \ - nautilus-preferences-item.c \ - nautilus-preferences-pane.c \ - nautilus-preferences.c \ - nautilus-program-chooser.c \ - nautilus-program-choosing.c \ - nautilus-search-uri.c \ - nautilus-sidebar-functions.c \ - nautilus-sound.c \ - nautilus-theme.c \ - nautilus-thumbnails.c \ - nautilus-thumbnails-jpeg.c \ - nautilus-trash-directory.c \ - nautilus-trash-file.c \ - nautilus-trash-monitor.c \ - nautilus-undo-context.c \ - nautilus-undo-manager.c \ - nautilus-undo-signal-handlers.c \ - nautilus-vfs-directory.c \ - nautilus-vfs-file.c \ - nautilus-view-identifier.c \ - nautilus-volume-monitor.c \ - $(NULL) - -# Everything is private for now -noinst_HEADERS = \ - nautilus-audio-player.h \ - nautilus-bonobo-extensions.h \ - nautilus-bookmark.h \ - nautilus-cdrom-extensions.h \ - nautilus-customization-data.h \ - nautilus-dateedit-extensions.h \ - nautilus-default-file-icon.h \ - nautilus-directory-background.h \ - nautilus-directory-metafile-monitor.h \ - nautilus-directory-metafile.h \ - nautilus-directory-notify.h \ - nautilus-directory-private.h \ - nautilus-directory.h \ - nautilus-drag-window.h \ - nautilus-druid-page-eazel.h \ - nautilus-druid.h \ - nautilus-entry.h \ - nautilus-file-attributes.h \ - nautilus-file-changes-queue.h \ - nautilus-file-dnd.h \ - nautilus-file-operations-progress.h \ - nautilus-file-operations.h \ - nautilus-file-private.h \ - nautilus-file-utilities.h \ - nautilus-file.h \ - nautilus-font-factory.h \ - nautilus-gconf-extensions.h \ - nautilus-generous-bin.h \ - nautilus-global-preferences.h \ - nautilus-horizontal-splitter.h \ - nautilus-icon-canvas-item.h \ - nautilus-icon-container.h \ - nautilus-icon-dnd.h \ - nautilus-icon-factory-private.h \ - nautilus-icon-factory.h \ - nautilus-icon-private.h \ - nautilus-icon-text-item.h \ - nautilus-iso9660.h \ - nautilus-keep-last-vertical-box.h \ - nautilus-lib-self-check-functions.h \ - nautilus-link-set.h \ - nautilus-link.h \ - nautilus-medusa-support.h \ - nautilus-merged-directory.h \ - nautilus-metadata.h \ - nautilus-metafile-factory.h \ - nautilus-metafile.h \ - nautilus-mime-actions.h \ - nautilus-monitor.h \ - nautilus-preferences-box.h \ - nautilus-preferences-group.h \ - nautilus-preferences-item.h \ - nautilus-preferences-pane.h \ - nautilus-preferences.h \ - nautilus-program-chooser.h \ - nautilus-program-choosing.h \ - nautilus-search-uri.h \ - nautilus-sidebar-functions.h \ - nautilus-sound.h \ - nautilus-theme.h \ - nautilus-thumbnails.h \ - nautilus-thumbnails-jpeg.h \ - nautilus-trash-directory.h \ - nautilus-trash-file.h \ - nautilus-trash-monitor.h \ - nautilus-undo-context.h \ - nautilus-undo-manager.h \ - nautilus-undo-signal-handlers.h \ - nautilus-vfs-directory.h \ - nautilus-vfs-file.h \ - nautilus-view-identifier.h \ - nautilus-volume-monitor.h \ - $(NULL) - -$(lib_LTLIBRARIES): $(dependency_static_libs) - -$(nautilus_metafile_server_idl_sources): nautilus_metafile_server_idl_stamp -nautilus_metafile_server_idl_stamp: nautilus-metafile-server.idl $(ORBIT_IDL) - $(ORBIT_IDL) $(IDL_CFLAGS) $(srcdir)/nautilus-metafile-server.idl - touch nautilus_metafile_server_idl_stamp - -$(libnautilus_extensions_la_OBJECTS): nautilus_metafile_server_idl_stamp - -EXTRA_DIST = \ - nautilus-metafile-server.idl \ - $(NULL) - -BUILT_SOURCES = \ - $(nautilus_metafile_server_idl_sources) \ - $(NULL) - -CLEANFILES = \ - $(nautilus_metafile_server_idl_sources) \ - nautilus_metafile_server_idl_stamp \ - $(NULL) - -dist-hook: - cd $(distdir); rm -f $(CLEANFILES) diff --git a/libnautilus-extensions/README b/libnautilus-extensions/README deleted file mode 100644 index 9938eeceb..000000000 --- a/libnautilus-extensions/README +++ /dev/null @@ -1,19 +0,0 @@ -README for nautilus/libnautilus-extensions - -This library, libnautilus-extensions, is totally private to nautilus. - -If you are writing a nautilus component, you should not use this -library or link with it in any way. - -Soon, libnautilus-extensions will be renamed to nautilus-internals to -emphasize the fact that this is code that is internal to nautilus and -not available for public consumption. - -If you think that there is something interesting in this library that -you would like to use in a third party component, please send mail to -the nautilus mailing list at: - -nautilus-list@lists.eazel.com - - - diff --git a/libnautilus-extensions/nautilus-audio-player.c b/libnautilus-extensions/nautilus-audio-player.c deleted file mode 100644 index 71f924511..000000000 --- a/libnautilus-extensions/nautilus-audio-player.c +++ /dev/null @@ -1,549 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ - -/* nautilus-audio-player.c - Simple threaded audio file playback. - - Copyright (C) 2001 Eazel, Inc. - - The Gnome 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 Gnome 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 the Gnome 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. - - Authors: Gene Z. Ragan <gzr@eazel.com> -*/ - -#include <config.h> -#include <stdlib.h> -#include <string.h> -#include <sys/types.h> -#include <unistd.h> - -#include <esd.h> - -#include "nautilus-audio-player.h" - -/* BUFFER_FRAMES represents the size of the buffer in frames. */ -#define BUFFER_FRAMES 4096 - -#define PLAYER_STREAM_NAME "nautilus-audio-player" - -typedef enum { - FORMAT_U8, - FORMAT_S8, - FORMAT_U16_LE, - FORMAT_U16_BE, - FORMAT_U16_NE, - FORMAT_S16_LE, - FORMAT_S16_BE, - FORMAT_S16_NE -} -AudioFormat; - -typedef struct { - pthread_t buffer_thread; - gint fd; - gpointer buffer; - gboolean going, prebuffer, paused; - gint buffer_size, prebuffer_size, block_size; - gint rd_index, wr_index; - gint output_time_offset; - guint64 written, output_bytes; - gint bps, ebps; - gint flush; - gint channels, frequency, latency; - AudioFormat format; - esd_format_t esd_format; - gint input_bps, input_format, input_frequency, input_channels; - char *hostname; - ESDConfig esd_config; - void *(*esd_translate)(void *, gint); -} ESDInfo; - - -static gboolean esdout_open (ESDInfo *info, - AudioFormat format, - gint rate, - gint nch); -static void esdout_close (ESDInfo *info); -static void esdout_set_audio_params (ESDInfo *info); -static void esdout_write (ESDInfo *info, - gpointer data, - int length); -static int esdout_used (ESDInfo *info); -static gboolean esdout_playing (ESDInfo *info); - -static void * -player_thread (void *arg) -{ - NautilusAudioPlayerData *data; - AFframecount frames_read; - int sample_format, frame_size, channel_count, sample_width; - double rate; - void *buffer; - ESDInfo info; - - data = arg; - - if (data == NULL) { - pthread_exit (NULL); - return (void *) 0; - } - - /* Read information from file */ - afGetSampleFormat (data->handle, AF_DEFAULT_TRACK, &sample_format, &sample_width); - frame_size = afGetFrameSize (data->handle, AF_DEFAULT_TRACK, 1); - channel_count = afGetChannels (data->handle, AF_DEFAULT_TRACK); - rate = afGetRate (data->handle, AF_DEFAULT_TRACK); - - /* Attempt to open ESD */ - if (!esdout_open (&info, sample_width == 16 ? FORMAT_S16_NE : FORMAT_U8, (int)rate, channel_count)) { - pthread_exit (NULL); - return (void *) 0; - } - - /* Read audio data from file and send it to the esd output thread */ - buffer = malloc (BUFFER_FRAMES * frame_size); - frames_read = afReadFrames (data->handle, AF_DEFAULT_TRACK, buffer, BUFFER_FRAMES); - while (frames_read > 0 && data->running) { - esdout_write (&info, buffer, frames_read * frame_size); - frames_read = afReadFrames (data->handle, AF_DEFAULT_TRACK, buffer, BUFFER_FRAMES); - } - afCloseFile (data->handle); - - /* Now wait for the esd output thread to complete it task */ - while (esdout_playing (&info) && data->running) { - usleep (20000); - } - - /* Shutdown esd output thread */ - esdout_close (&info); - - g_free (buffer); - - pthread_exit (NULL); - - return (void *) 0; -} - -NautilusAudioPlayerData * -nautilus_audio_player_play (const char *filename) -{ - AFfilehandle handle; - NautilusAudioPlayerData *data; - - handle = afOpenFile (filename, "r", NULL); - if (handle == AF_NULL_FILEHANDLE) { - return NULL; - } - - data = g_new0 (NautilusAudioPlayerData, 1); - data->handle = handle; - data->running = TRUE; - - pthread_create (&data->player_id, NULL, player_thread, data); - - return data; -} - -void -nautilus_audio_player_stop (NautilusAudioPlayerData *data) -{ - if (data == NULL) { - return; - } - - data->running = FALSE; - pthread_join (data->player_id, NULL); -} - - -static void -esdout_init (ESDInfo *info) -{ - memset (&info->esd_config, 0, sizeof (ESDConfig)); - - info->fd = 0; - info->going = FALSE; - info->paused = FALSE; - info->buffer = NULL; - info->block_size = BUFFER_FRAMES; - info->rd_index = 0; - info->wr_index = 0; - info->output_time_offset = 0; - info->written = 0; - info->output_bytes = 0; - info->hostname = NULL; - info->esd_config.port = ESD_DEFAULT_PORT; - info->esd_config.buffer_size = 3000; - info->esd_config.prebuffer = 25; -} - -static void -esdout_write (ESDInfo *info, gpointer data, int length) -{ - int count, offset; - - offset = 0; - - info->written += length; - - while (length > 0) { - count = MIN (length, info->buffer_size - info->wr_index); - memcpy ((char *)info->buffer + info->wr_index, (char *)data + offset, count); - info->wr_index = (info->wr_index + count) % info->buffer_size; - length -= count; - offset += count; - } -} - - -static gint -get_latency (ESDInfo *config) -{ - int fd, amount = 0; - -#ifndef HAVE_ESD_GET_LATENCY - esd_server_info_t *info; -#endif - - fd = esd_open_sound (config->hostname); - if (fd == -1) { - return 0; - } - -#ifdef HAVE_ESD_GET_LATENCY - amount = get_latency (fd); -#else - info = esd_get_server_info (fd); - if (info != NULL) { - if (info->format & ESD_STEREO) { - if (info->format & ESD_BITS16) - amount = (44100 * (ESD_BUF_SIZE + 64)) / info->rate; - else - amount = (44100 * (ESD_BUF_SIZE + 128)) / info->rate; - } else { - if (info->format & ESD_BITS16) - amount = (2 * 44100 * (ESD_BUF_SIZE + 128)) / info->rate; - else - amount = (2 * 44100 * (ESD_BUF_SIZE + 256)) / info->rate; - } - free (info); - } - amount += ESD_BUF_SIZE * 2; -#endif - esd_close (fd); - return amount; -} - -static void * -esd_stou8 (void *data, gint length) -{ - int len = length; - unsigned char *dat = (unsigned char *)data; - while (len-- > 0) - *dat++ ^= 0x80; - return data; -} - -static void * -esd_utos16sw (void *data, gint length) -{ - int len = length; - short *dat = data; - while ( len > 0 ) { - *dat = GUINT16_SWAP_LE_BE ( *dat ) ^ 0x8000; - dat++; - len-=2; - } - return data; -} - -static void * -esd_utos16 (void *data, gint length) -{ - int len = length; - short *dat = data; - while ( len > 0 ) { - *dat ^= 0x8000; - dat++; - len-=2; - } - return data; -} - -static void * -esd_16sw (void *data, gint length) -{ - int len = length; - short *dat = data; - while ( len > 0 ) { - *dat = GUINT16_SWAP_LE_BE( *dat ); - dat++; - len-=2; - } - return data; -} - -static void -esdout_setup_format (ESDInfo *info, AudioFormat format, gint rate, gint nch) -{ - gboolean swap_sign = FALSE; - gboolean swap_16 = FALSE; - - info->format = format; - info->frequency = rate; - info->channels = nch; - - switch (format) { - case FORMAT_S8: - swap_sign = TRUE; - case FORMAT_U8: - info->esd_format = ESD_BITS8; - break; - case FORMAT_U16_LE: - case FORMAT_U16_BE: - case FORMAT_U16_NE: - swap_sign = TRUE; - case FORMAT_S16_LE: - case FORMAT_S16_BE: - case FORMAT_S16_NE: - info->esd_format = ESD_BITS16; - break; - } - -#ifdef WORDS_BIGENDIAN - if (format == FORMAT_U16_LE || format == FORMAT_S16_LE) { -#else - if (format == FORMAT_U16_BE || format == FORMAT_S16_BE) { -#endif - swap_16 = TRUE; - } - - info->esd_translate = (void*(*)())NULL; - if (info->esd_format == ESD_BITS8) { - if (swap_sign == TRUE) { - info->esd_translate = esd_stou8; - } - } else { - if (swap_sign == TRUE) { - if (swap_16 == TRUE) { - info->esd_translate = esd_utos16sw; - } else { - info->esd_translate = esd_utos16; - } - } else { - if (swap_16 == TRUE) { - info->esd_translate = esd_16sw; - } - } - } - - info->bps = rate * nch; - if (info->esd_format == ESD_BITS16) { - info->bps *= 2; - } - - if (nch == 1) { - info->esd_format |= ESD_MONO; - } else { - info->esd_format |= ESD_STEREO; - } - - info->esd_format |= ESD_STREAM | ESD_PLAY; - - info->latency = ((get_latency (info) * info->frequency) / 44100) * info->channels; - if (info->format != FORMAT_U8 && info->format != FORMAT_S8) { - info->latency *= 2; - } -} - - -static gint -esdout_used (ESDInfo *info) -{ - if (info->wr_index >= info->rd_index) { - return info->wr_index - info->rd_index; - } - - return info->buffer_size - (info->rd_index - info->wr_index); -} - -static void -esdout_write_audio (ESDInfo *info, gint length) -{ - AudioFormat new_format; - gint new_frequency, new_channels; - char *data; - - data = (char *)info->buffer + info->rd_index; - - new_format = info->input_format; - new_frequency = info->input_frequency; - new_channels = info->input_channels; - - if (new_format != info->format || new_frequency != info->frequency || new_channels != info->channels) { - info->output_time_offset += (gint) ((info->output_bytes * 1000) / info->ebps); - info->output_bytes = 0; - esdout_setup_format (info, new_format, new_frequency, new_channels); - info->frequency = new_frequency; - info->channels = new_channels; - close (info->fd); - esdout_set_audio_params (info); - } - - if (info->esd_translate) { - info->output_bytes += write (info->fd, info->esd_translate (data, length), length); - } else { - info->output_bytes += write (info->fd, data, length); - } -} - - -static void -esdout_close (ESDInfo *info) -{ - info->going = FALSE; - info->wr_index = 0; - info->rd_index = 0; - info->going = 0; - g_free (info->hostname); - info->hostname = NULL; - pthread_join (info->buffer_thread, NULL); -} - -static void * -esdout_loop (void *arg) -{ - int length, count, used; - ESDInfo *info; - - info = arg; - - while (info->going) { - used = esdout_used (info); - - if (used > info->prebuffer_size) { - info->prebuffer = FALSE; - } - - if (used > 0 && !info->paused && !info->prebuffer) { - length = MIN (info->block_size, used); - while (length > 0) { - count = MIN (length, info->buffer_size - info->rd_index); - esdout_write_audio (info, count); - info->rd_index = (info->rd_index + count) % info->buffer_size; - length -= count; - } - } else { - usleep (10000); - } - - if (info->flush != -1) { - info->output_time_offset = info->flush; - info->written = (guint64)(info->flush / 10) * (guint64)(info->input_bps / 100); - info->rd_index = info->wr_index = info->output_bytes = 0; - info->flush = -1; - info->prebuffer = TRUE; - } - } - - close (info->fd); - g_free (info->buffer); - - while (info->going) { - usleep (10000); - } - - pthread_exit (NULL); - - return (void *) 0; -} - -static void -esdout_set_audio_params (ESDInfo *info) -{ - info->fd = esd_play_stream (info->esd_format, info->frequency, info->hostname, PLAYER_STREAM_NAME); - info->ebps = info->frequency * info->channels; - if (info->format == FORMAT_U16_BE || info->format == FORMAT_U16_LE || info->format == FORMAT_S16_BE - || info->format == FORMAT_S16_LE || info->format == FORMAT_S16_NE || info->format == FORMAT_U16_NE) { - info->ebps *= 2; - } -} - -static gboolean -esdout_open (ESDInfo *info, AudioFormat format, gint rate, gint nch) -{ - esdout_init (info); - - esdout_setup_format (info, format, rate, nch); - - info->input_format = info->format; - info->input_channels = info->channels; - info->input_frequency = info->frequency; - info->input_bps = info->bps; - - info->buffer_size = (info->esd_config.buffer_size * info->input_bps) / 1000; - if (info->buffer_size < 8192) { - info->buffer_size = 8192; - } - - info->prebuffer_size = (info->buffer_size * info->esd_config.prebuffer) / 100; - if (info->buffer_size - info->prebuffer_size < 4096) { - info->prebuffer_size = info->buffer_size - 4096; - } - - info->buffer = g_malloc0 (info->buffer_size); - - info->flush = -1; - info->prebuffer = TRUE; - info->wr_index = info->rd_index = info->output_time_offset = info->written = info->output_bytes = 0; - info->paused = FALSE; - - if (info->hostname != NULL) { - g_free (info->hostname); - } - - if (info->esd_config.use_remote) { - info->hostname = g_strdup_printf ("%s:%d", info->esd_config.server, info->esd_config.port); - } else { - info->hostname = NULL; - } - - esdout_set_audio_params (info); - if (info->fd == -1) { - g_free (info->buffer); - info->buffer = NULL; - return FALSE; - } - - info->going = TRUE; - - pthread_create (&info->buffer_thread, NULL, esdout_loop, info); - - return TRUE; -} - -static gboolean -esdout_playing (ESDInfo *info) -{ - if (!info->going) { - return FALSE; - } - - if (esdout_used (info) <= 0) { - return FALSE; - } - - return TRUE; -} - diff --git a/libnautilus-extensions/nautilus-audio-player.h b/libnautilus-extensions/nautilus-audio-player.h deleted file mode 100644 index ee1294b88..000000000 --- a/libnautilus-extensions/nautilus-audio-player.h +++ /dev/null @@ -1,55 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ - -/* nautilus-audio-player.h - Simple threaded audio file playback. - - Copyright (C) 2001 Eazel, Inc. - - The Gnome 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 Gnome 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 the Gnome 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. - - Authors: Gene Z. Ragan <gzr@eazel.com> -*/ - -#ifndef NAUTILUS_AUDIO_PLAYER__ -#define NAUTILUS_AUDIO_PLAYER__ - -#include <config.h> -#include <sys/types.h> - -#include <audiofile.h> -#include <pthread.h> -#include <glib.h> - -typedef struct { - gboolean use_remote; - gchar *server; - gint port; - gint buffer_size; - gint prebuffer; -} ESDConfig; - -typedef struct { - AFfilehandle handle; - pthread_t player_id; - gboolean running; - ESDConfig esd_config; -} NautilusAudioPlayerData; - - -NautilusAudioPlayerData *nautilus_audio_player_play (const char *filename); -void nautilus_audio_player_stop (NautilusAudioPlayerData *data); - - -#endif diff --git a/libnautilus-extensions/nautilus-bonobo-extensions.c b/libnautilus-extensions/nautilus-bonobo-extensions.c deleted file mode 100644 index b7da068c8..000000000 --- a/libnautilus-extensions/nautilus-bonobo-extensions.c +++ /dev/null @@ -1,630 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ - -/* nautilus-bonobo-extensions.c - implementation of new functions that conceptually - belong in bonobo. Perhaps some of these will be - actually rolled into bonobo someday. - - Copyright (C) 2000, 2001 Eazel, Inc. - - The Gnome 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 Gnome 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 the Gnome 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. - - Authors: John Sullivan <sullivan@eazel.com> - Darin Adler <darin@eazel.com> -*/ - -#include <config.h> -#include "nautilus-bonobo-extensions.h" - -#include <eel/eel-string.h> -#include <bonobo/bonobo-ui-util.h> -#include <gtk/gtkmain.h> -#include <libgnomevfs/gnome-vfs-utils.h> -#include <liboaf/oaf-async.h> - -struct NautilusBonoboActivationHandle { - NautilusBonoboActivationHandle **early_completion_hook; - NautilusBonoboActivationCallback callback; - gpointer callback_data; - Bonobo_Unknown activated_object; - gboolean cancel; - guint idle_id; -}; - -typedef enum { - NUMBERED_MENU_ITEM_PLAIN, - NUMBERED_MENU_ITEM_TOGGLE, - NUMBERED_MENU_ITEM_RADIO -} NumberedMenuItemType; - -void -nautilus_bonobo_set_accelerator (BonoboUIComponent *ui, - const char *path, - const char *accelerator) -{ - g_return_if_fail (BONOBO_IS_UI_COMPONENT (ui)); - bonobo_ui_component_set_prop (ui, path, - "accel", - accelerator, - NULL); -} - -void -nautilus_bonobo_set_label (BonoboUIComponent *ui, - const char *path, - const char *label) -{ - g_return_if_fail (BONOBO_IS_UI_COMPONENT (ui)); - bonobo_ui_component_set_prop (ui, path, - "label", - label, - NULL); -} - -void -nautilus_bonobo_set_tip (BonoboUIComponent *ui, - const char *path, - const char *tip) -{ - g_return_if_fail (ui != NULL); - bonobo_ui_component_set_prop (ui, path, - "tip", - tip, - NULL); -} - -void -nautilus_bonobo_set_sensitive (BonoboUIComponent *ui, - const char *path, - gboolean sensitive) -{ - g_return_if_fail (BONOBO_IS_UI_COMPONENT (ui)); - bonobo_ui_component_set_prop (ui, path, - "sensitive", - sensitive ? "1" : "0", - NULL); -} - -void -nautilus_bonobo_set_toggle_state (BonoboUIComponent *ui, - const char *path, - gboolean state) -{ - g_return_if_fail (BONOBO_IS_UI_COMPONENT (ui)); - bonobo_ui_component_set_prop (ui, path, - "state", - state ? "1" : "0", - NULL); -} - -void -nautilus_bonobo_set_hidden (BonoboUIComponent *ui, - const char *path, - gboolean hidden) -{ - g_return_if_fail (BONOBO_IS_UI_COMPONENT (ui)); - bonobo_ui_component_set_prop (ui, path, - "hidden", - hidden ? "1" : "0", - NULL); -} - -char * -nautilus_bonobo_get_label (BonoboUIComponent *ui, - const char *path) -{ - g_return_val_if_fail (BONOBO_IS_UI_COMPONENT (ui), FALSE); - - return bonobo_ui_component_get_prop (ui, path, "label", NULL); -} - -gboolean -nautilus_bonobo_get_hidden (BonoboUIComponent *ui, - const char *path) -{ - char *value; - gboolean hidden; - - g_return_val_if_fail (BONOBO_IS_UI_COMPONENT (ui), FALSE); - - value = bonobo_ui_component_get_prop (ui, path, "hidden", NULL); - - if (value == NULL) { - /* No hidden attribute means not hidden. */ - hidden = FALSE; - } else { - /* Anything other than "0" counts as TRUE */ - hidden = strcmp (value, "0") != 0; - } - - g_free (value); - - return hidden; -} - -static char * -get_numbered_menu_item_name (BonoboUIComponent *ui, - const char *container_path, - guint index) -{ - return g_strdup_printf ("%u", index); -} - -char * -nautilus_bonobo_get_numbered_menu_item_path (BonoboUIComponent *ui, - const char *container_path, - guint index) -{ - char *item_name; - char *item_path; - - g_return_val_if_fail (BONOBO_IS_UI_COMPONENT (ui), NULL); - g_return_val_if_fail (container_path != NULL, NULL); - - item_name = get_numbered_menu_item_name (ui, container_path, index); - item_path = g_strconcat (container_path, "/", item_name, NULL); - g_free (item_name); - - return item_path; -} - -char * -nautilus_bonobo_get_numbered_menu_item_command (BonoboUIComponent *ui, - const char *container_path, - guint index) -{ - char *command_name; - char *path; - - g_return_val_if_fail (BONOBO_IS_UI_COMPONENT (ui), NULL); - g_return_val_if_fail (container_path != NULL, NULL); - - path = nautilus_bonobo_get_numbered_menu_item_path (ui, container_path, index); - command_name = gnome_vfs_escape_string (path); - g_free (path); - - return command_name; -} - -guint -nautilus_bonobo_get_numbered_menu_item_index_from_command (const char *command) -{ - char *path; - char *index_string; - int index; - gboolean got_index; - - path = gnome_vfs_unescape_string (command, NULL); - index_string = strrchr (path, '/'); - - if (index_string == NULL) { - got_index = FALSE; - } else { - got_index = eel_str_to_int (index_string + 1, &index); - } - g_free (path); - - g_return_val_if_fail (got_index, 0); - - return index; -} - -char * -nautilus_bonobo_get_numbered_menu_item_container_path_from_command (const char *command) -{ - char *path; - char *index_string; - char *container_path; - - path = gnome_vfs_unescape_string (command, NULL); - index_string = strrchr (path, '/'); - - container_path = index_string == NULL - ? NULL - : g_strndup (path, index_string - path); - g_free (path); - - return container_path; -} - -static void -add_numbered_menu_item_internal (BonoboUIComponent *ui, - const char *container_path, - guint index, - const char *label, - NumberedMenuItemType type, - GdkPixbuf *pixbuf, - const char *radio_group_name) -{ - char *xml_item, *xml_command; - char *encoded_label, *command_name; - char *item_name, *pixbuf_data; - - g_assert (BONOBO_IS_UI_COMPONENT (ui)); - g_assert (container_path != NULL); - g_assert (label != NULL); - g_assert (type == NUMBERED_MENU_ITEM_PLAIN || pixbuf == NULL); - g_assert (type == NUMBERED_MENU_ITEM_RADIO || radio_group_name == NULL); - g_assert (type != NUMBERED_MENU_ITEM_RADIO || radio_group_name != NULL); - - /* Because we are constructing the XML ourselves, we need to - * encode the label. - */ - encoded_label = bonobo_ui_util_encode_str (label); - - item_name = get_numbered_menu_item_name - (ui, container_path, index); - command_name = nautilus_bonobo_get_numbered_menu_item_command - (ui, container_path, index); - - - switch (type) { - case NUMBERED_MENU_ITEM_TOGGLE: - xml_item = g_strdup_printf ("<menuitem name=\"%s\" label=\"%s\" id=\"%s\" type=\"toggle\"/>\n", - item_name, encoded_label, command_name); - break; - case NUMBERED_MENU_ITEM_RADIO: - xml_item = g_strdup_printf ("<menuitem name=\"%s\" label=\"%s\" id=\"%s\" type=\"radio\" group=\"%s\"/>\n", - item_name, encoded_label, command_name, radio_group_name); - break; - case NUMBERED_MENU_ITEM_PLAIN: - if (pixbuf != NULL) { - pixbuf_data = bonobo_ui_util_pixbuf_to_xml (pixbuf); - xml_item = g_strdup_printf ("<menuitem name=\"%s\" label=\"%s\" verb=\"%s\" pixtype=\"pixbuf\" pixname=\"%s\"/>\n", - item_name, encoded_label, command_name, pixbuf_data); - g_free (pixbuf_data); - } else { - xml_item = g_strdup_printf ("<menuitem name=\"%s\" label=\"%s\" verb=\"%s\"/>\n", - item_name, encoded_label, command_name); - } - break; - default: - g_assert_not_reached (); - xml_item = NULL; /* keep compiler happy */ - } - - g_free (encoded_label); - g_free (item_name); - - bonobo_ui_component_set (ui, container_path, xml_item, NULL); - g_free (xml_item); - - /* Make the command node here too, so callers can immediately set - * properties on it (otherwise it doesn't get created until some - * time later). - */ - xml_command = g_strdup_printf ("<cmd name=\"%s\"/>\n", command_name); - bonobo_ui_component_set (ui, "/commands", xml_command, NULL); - g_free (xml_command); - - g_free (command_name); -} - -/* Add a menu item specified by number into a given path. Used for - * dynamically creating a related series of menu items. Each index - * must be unique (normal use is to call this in a loop, and - * increment the index for each item). - */ -void -nautilus_bonobo_add_numbered_menu_item (BonoboUIComponent *ui, - const char *container_path, - guint index, - const char *label, - GdkPixbuf *pixbuf) -{ - g_return_if_fail (BONOBO_IS_UI_COMPONENT (ui)); - g_return_if_fail (container_path != NULL); - g_return_if_fail (label != NULL); - - add_numbered_menu_item_internal (ui, container_path, index, label, NUMBERED_MENU_ITEM_PLAIN, pixbuf, NULL); -} - -/* Add a menu item specified by number into a given path. Used for - * dynamically creating a related series of toggle menu items. Each index - * must be unique (normal use is to call this in a loop, and - * increment the index for each item). - */ -void -nautilus_bonobo_add_numbered_toggle_menu_item (BonoboUIComponent *ui, - const char *container_path, - guint index, - const char *label) -{ - g_return_if_fail (BONOBO_IS_UI_COMPONENT (ui)); - g_return_if_fail (container_path != NULL); - g_return_if_fail (label != NULL); - - add_numbered_menu_item_internal (ui, container_path, index, label, NUMBERED_MENU_ITEM_TOGGLE, NULL, NULL); -} - -/* Add a menu item specified by number into a given path. Used for - * dynamically creating a related series of radio menu items. Each index - * must be unique (normal use is to call this in a loop, and - * increment the index for each item). - */ -void -nautilus_bonobo_add_numbered_radio_menu_item (BonoboUIComponent *ui, - const char *container_path, - guint index, - const char *label, - const char *radio_group_name) -{ - g_return_if_fail (BONOBO_IS_UI_COMPONENT (ui)); - g_return_if_fail (container_path != NULL); - g_return_if_fail (label != NULL); - - add_numbered_menu_item_internal (ui, container_path, index, label, NUMBERED_MENU_ITEM_RADIO, NULL, radio_group_name); -} - -void -nautilus_bonobo_add_submenu (BonoboUIComponent *ui, - const char *path, - const char *label) -{ - char *xml_string, *encoded_label, *name; - - /* Because we are constructing the XML ourselves, we need to - * encode the label. - */ - encoded_label = bonobo_ui_util_encode_str (label); - - /* Labels may contain characters that are illegal in names. So - * we create the name by URI-encoding the label. - */ - name = gnome_vfs_escape_string (label); - - xml_string = g_strdup_printf ("<submenu name=\"%s\" label=\"%s\"/>\n", - name, encoded_label); - bonobo_ui_component_set (ui, path, xml_string, NULL); - - g_free (encoded_label); - g_free (name); - g_free (xml_string); -} - -void -nautilus_bonobo_add_menu_separator (BonoboUIComponent *ui, const char *path) -{ - bonobo_ui_component_set (ui, path, "<separator/>", NULL); -} - -static void -remove_commands (BonoboUIComponent *ui, const char *container_path) -{ - BonoboUINode *path_node; - BonoboUINode *child_node; - char *verb_name; - char *id_name; - - g_return_if_fail (BONOBO_IS_UI_COMPONENT (ui)); - g_return_if_fail (container_path != NULL); - - path_node = bonobo_ui_component_get_tree (ui, container_path, TRUE, NULL); - if (path_node == NULL) { - return; - } - - bonobo_ui_component_freeze (ui, NULL); - - for (child_node = bonobo_ui_node_children (path_node); - child_node != NULL; - child_node = bonobo_ui_node_next (child_node)) { - verb_name = bonobo_ui_node_get_attr (child_node, "verb"); - if (verb_name != NULL) { - bonobo_ui_component_remove_verb (ui, verb_name); - bonobo_ui_node_free_string (verb_name); - } else { - /* Only look for an id if there's no verb */ - id_name = bonobo_ui_node_get_attr (child_node, "id"); - if (id_name != NULL) { - bonobo_ui_component_remove_listener (ui, id_name); - bonobo_ui_node_free_string (id_name); - } - } - } - - bonobo_ui_component_thaw (ui, NULL); - - bonobo_ui_node_free (path_node); -} - -/** - * nautilus_bonobo_remove_menu_items_and_verbs - * - * Removes all menu items contained in a menu or placeholder, and - * their verbs. - * - * @uih: The BonoboUIHandler for this menu item. - * @container_path: The standard bonobo-style path specifier for this placeholder or submenu. - */ -void -nautilus_bonobo_remove_menu_items_and_commands (BonoboUIComponent *ui, - const char *container_path) -{ - char *remove_wildcard; - - g_return_if_fail (BONOBO_IS_UI_COMPONENT (ui)); - g_return_if_fail (container_path != NULL); - - remove_commands (ui, container_path); - - /* For speed, remove menu items themselves all in one fell swoop, - * though we removed the verbs one-by-one. - */ - remove_wildcard = g_strdup_printf ("%s/*", container_path); - bonobo_ui_component_rm (ui, remove_wildcard, NULL); - g_free (remove_wildcard); -} - -/* Call to set the user-visible label of a menu item to a string - * containing an underscore accelerator. The underscore is stripped - * off before setting the label of the command, because pop-up menu - * and toolbar button labels shouldn't have the underscore. - */ -void -nautilus_bonobo_set_label_for_menu_item_and_command (BonoboUIComponent *ui, - const char *menu_item_path, - const char *command_path, - const char *label_with_underscore) -{ - char *label_no_underscore; - - label_no_underscore = eel_str_strip_chr (label_with_underscore, '_'); - nautilus_bonobo_set_label (ui, - menu_item_path, - label_with_underscore); - nautilus_bonobo_set_label (ui, - command_path, - label_no_underscore); - - g_free (label_no_underscore); -} - -void -nautilus_bonobo_set_icon (BonoboUIComponent *ui, - const char *path, - const char *icon_relative_path) -{ - g_return_if_fail (BONOBO_IS_UI_COMPONENT (ui)); - g_return_if_fail (path != NULL); - g_return_if_fail (icon_relative_path != NULL); - - /* We don't do a get_prop here before setting since it just - * means more round-trip CORBA calls. - */ - bonobo_ui_component_set_prop (ui, path, - "pixname", - icon_relative_path, NULL); - bonobo_ui_component_set_prop (ui, path, - "pixtype", - "filename", NULL); -} - -static void -activation_handle_done (NautilusBonoboActivationHandle *handle) -{ - if (handle->early_completion_hook != NULL) { - g_assert (*handle->early_completion_hook == handle); - *handle->early_completion_hook = NULL; - } -} - -static gboolean -activation_idle_callback (gpointer callback_data) -{ - NautilusBonoboActivationHandle *handle; - - handle = (NautilusBonoboActivationHandle *) callback_data; - - (* handle->callback) (handle, - handle->activated_object, - handle->callback_data); - - activation_handle_done (handle); - g_free (handle); - - return FALSE; -} - -static void -activation_cancel (NautilusBonoboActivationHandle *handle) -{ - bonobo_object_release_unref (handle->activated_object, NULL); - - activation_handle_done (handle); - g_free (handle); -} - -static void -oaf_activation_callback (Bonobo_Unknown activated_object, - const char *error_reason, - gpointer callback_data) -{ - NautilusBonoboActivationHandle *handle; - - handle = (NautilusBonoboActivationHandle *) callback_data; - - handle->activated_object = activated_object; - - if (handle->cancel) { - activation_cancel (handle); - } else { - handle->idle_id = gtk_idle_add (activation_idle_callback, - handle); - } -} - -/** - * nautilus_bonobo_activate_from_id: - * @iid: iid of component to activate. - * @callback: callback to call when activation finished. - * @user_data: data to pass to callback when activation finished. - * - * This function will return NULL if something bad happened during - * activation. - */ -NautilusBonoboActivationHandle * -nautilus_bonobo_activate_from_id (const char *iid, - NautilusBonoboActivationCallback callback, - gpointer callback_data) -{ - NautilusBonoboActivationHandle *handle; - - g_return_val_if_fail (iid != NULL, NULL); - g_return_val_if_fail (callback != NULL, NULL); - - handle = g_new0 (NautilusBonoboActivationHandle, 1); - - handle->early_completion_hook = &handle; - handle->callback = callback; - handle->callback_data = callback_data; - - oaf_activate_from_id_async ((char *) iid, 0, - oaf_activation_callback, - handle, NULL); - - if (handle != NULL) { - handle->early_completion_hook = NULL; - } - - return handle; -} - -/** - * nautilus_bonobo_activate_stop: - * @iid: iid of component to activate. - * @callback: callback to call when activation finished. - * @user_data: data to pass to callback when activation finished. - * - * Stops activation of a component. Your callback will not be called - * after this call. - */ -void -nautilus_bonobo_activate_cancel (NautilusBonoboActivationHandle *handle) -{ - if (handle == NULL) { - return; - } - - activation_handle_done (handle); - - if (handle->idle_id == 0) { - /* no way to cancel the OAF part, so we just set a flag */ - handle->cancel = TRUE; - } else { - gtk_idle_remove (handle->idle_id); - activation_cancel (handle); - } -} diff --git a/libnautilus-extensions/nautilus-bonobo-extensions.h b/libnautilus-extensions/nautilus-bonobo-extensions.h deleted file mode 100644 index 052191f90..000000000 --- a/libnautilus-extensions/nautilus-bonobo-extensions.h +++ /dev/null @@ -1,142 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ - -/* nautilus-bonobo-extensions.h - interface for new functions that conceptually - belong in bonobo. Perhaps some of these will be - actually rolled into bonobo someday. - - Copyright (C) 2000 Eazel, Inc. - - The Gnome 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 Gnome 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 the Gnome 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. - - Author: John Sullivan <sullivan@eazel.com> -*/ - -#ifndef NAUTILUS_BONOBO_EXTENSIONS_H -#define NAUTILUS_BONOBO_EXTENSIONS_H - -#include <bonobo/bonobo-ui-component.h> -#include <bonobo/bonobo-xobject.h> -#include <gdk-pixbuf/gdk-pixbuf.h> - -typedef struct NautilusBonoboActivationHandle NautilusBonoboActivationHandle; - -typedef void (*NautilusBonoboActivationCallback) (NautilusBonoboActivationHandle *handle, - Bonobo_Unknown activated_object, - gpointer callback_data); - -void nautilus_bonobo_set_accelerator (BonoboUIComponent *ui, - const char *path, - const char *accelerator); -char * nautilus_bonobo_get_label (BonoboUIComponent *ui, - const char *path); -void nautilus_bonobo_set_label (BonoboUIComponent *ui, - const char *path, - const char *label); -void nautilus_bonobo_set_tip (BonoboUIComponent *ui, - const char *path, - const char *tip); -void nautilus_bonobo_set_sensitive (BonoboUIComponent *ui, - const char *path, - gboolean sensitive); -void nautilus_bonobo_set_toggle_state (BonoboUIComponent *ui, - const char *path, - gboolean state); -void nautilus_bonobo_set_hidden (BonoboUIComponent *ui, - const char *path, - gboolean hidden); -gboolean nautilus_bonobo_get_hidden (BonoboUIComponent *ui, - const char *path); -void nautilus_bonobo_add_numbered_menu_item (BonoboUIComponent *ui, - const char *container_path, - guint index, - const char *label, - GdkPixbuf *pixbuf); -void nautilus_bonobo_add_numbered_toggle_menu_item (BonoboUIComponent *ui, - const char *container_path, - guint index, - const char *label); -void nautilus_bonobo_add_numbered_radio_menu_item (BonoboUIComponent *ui, - const char *container_path, - guint index, - const char *label, - const char *radio_group_name); -char * nautilus_bonobo_get_numbered_menu_item_command (BonoboUIComponent *ui, - const char *container_path, - guint index); -char * nautilus_bonobo_get_numbered_menu_item_path (BonoboUIComponent *ui, - const char *container_path, - guint index); -guint nautilus_bonobo_get_numbered_menu_item_index_from_command - (const char *command); -char * nautilus_bonobo_get_numbered_menu_item_container_path_from_command - (const char *command); -void nautilus_bonobo_add_submenu (BonoboUIComponent *ui, - const char *container_path, - const char *label); -void nautilus_bonobo_add_menu_separator (BonoboUIComponent *ui, - const char *path); -void nautilus_bonobo_remove_menu_items_and_commands (BonoboUIComponent *ui, - const char *container_path); -void nautilus_bonobo_set_label_for_menu_item_and_command (BonoboUIComponent *ui, - const char *menu_item_path, - const char *command_path, - const char *label_with_underscore); -void nautilus_bonobo_set_icon (BonoboUIComponent *ui, - const char *path, - const char *icon_relative_path); - -NautilusBonoboActivationHandle *nautilus_bonobo_activate_from_id (const char *iid, - NautilusBonoboActivationCallback callback, - gpointer callback_data); -void nautilus_bonobo_activate_cancel (NautilusBonoboActivationHandle *handle); - - -/* This macro is a copy of BONOBO_X_TYPE_FUNC_FULL (from bonobo-xobject.h) - * with the addition of support for the parent_class which is defined by - * EEL_DEFINE_CLASS_BOILERPLATE and used by EEL_CALL_PARENT. - * - * Note: the argument order matches BONOBO_X_TYPE_FUNC_FULL which is different - * than EEL_DEFINE_CLASS_BOILERPLATE. - */ -#define NAUTILUS_BONOBO_X_BOILERPLATE(class_name, corba_name, parent, prefix) \ -static gpointer parent_class; /* Nautilus change */ \ -GtkType \ -prefix##_get_type (void) \ -{ \ - GtkType ptype; \ - static GtkType type = 0; \ - \ - if (type == 0) { \ - static GtkTypeInfo info = { \ - #class_name, \ - sizeof (class_name), \ - sizeof (class_name##Class), \ - (GtkClassInitFunc)prefix##_class_init, \ - (GtkObjectInitFunc)prefix##_init, \ - NULL, NULL, (GtkClassInitFunc) NULL \ - }; \ - ptype = (parent); \ - type = bonobo_x_type_unique (ptype, \ - POA_##corba_name##__init, POA_##corba_name##__fini, \ - GTK_STRUCT_OFFSET (class_name##Class, epv), \ - &info); \ - parent_class = gtk_type_class (ptype); /* Nautilus change */ \ - } \ - return type; \ -} - - -#endif /* NAUTILUS_BONOBO_EXTENSIONS_H */ diff --git a/libnautilus-extensions/nautilus-bookmark.c b/libnautilus-extensions/nautilus-bookmark.c deleted file mode 100644 index 3c16da5fe..000000000 --- a/libnautilus-extensions/nautilus-bookmark.c +++ /dev/null @@ -1,609 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ - -/* nautilus-bookmark.c - implementation of individual bookmarks. - - Copyright (C) 1999, 2000 Eazel, Inc. - - The Gnome 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 Gnome 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 the Gnome 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. - - Authors: John Sullivan <sullivan@eazel.com> -*/ - -#include <config.h> -#include "nautilus-bookmark.h" - -#include "nautilus-icon-factory.h" -#include <eel/eel-gdk-pixbuf-extensions.h> -#include <eel/eel-gtk-extensions.h> -#include <eel/eel-gtk-macros.h> -#include <eel/eel-string.h> -#include <eel/eel-vfs-extensions.h> -#include <gtk/gtkaccellabel.h> -#include <gtk/gtksignal.h> -#include <libgnome/gnome-defs.h> -#include <libgnome/gnome-util.h> -#include <libgnomeui/gtkpixmapmenuitem.h> -#include <libgnomevfs/gnome-vfs-types.h> -#include <libgnomevfs/gnome-vfs-uri.h> -#include <libgnomevfs/gnome-vfs-utils.h> - -enum { - APPEARANCE_CHANGED, - CONTENTS_CHANGED, - LAST_SIGNAL -}; - -#define GENERIC_BOOKMARK_ICON_NAME "i-bookmark" -#define MISSING_BOOKMARK_ICON_NAME "i-bookmark-missing" - -static guint signals[LAST_SIGNAL]; - -struct NautilusBookmarkDetails -{ - char *name; - char *uri; - NautilusScalableIcon *icon; - NautilusFile *file; -}; - -static void nautilus_bookmark_connect_file (NautilusBookmark *file); -static void nautilus_bookmark_disconnect_file (NautilusBookmark *file); -static void nautilus_bookmark_initialize_class (NautilusBookmarkClass *class); -static void nautilus_bookmark_initialize (NautilusBookmark *bookmark); -static GtkWidget *create_pixmap_widget_for_bookmark (NautilusBookmark *bookmark); - -EEL_DEFINE_CLASS_BOILERPLATE (NautilusBookmark, nautilus_bookmark, GTK_TYPE_OBJECT) - -/* GtkObject methods. */ - -static void -nautilus_bookmark_destroy (GtkObject *object) -{ - NautilusBookmark *bookmark; - - g_assert (NAUTILUS_IS_BOOKMARK (object)); - - bookmark = NAUTILUS_BOOKMARK(object); - - nautilus_bookmark_disconnect_file (bookmark); - - g_free (bookmark->details->name); - g_free (bookmark->details->uri); - g_free (bookmark->details); - - /* Chain up */ - EEL_CALL_PARENT (GTK_OBJECT_CLASS, destroy, (object)); -} - -/* Initialization. */ - -static void -nautilus_bookmark_initialize_class (NautilusBookmarkClass *class) -{ - GtkObjectClass *object_class; - - object_class = GTK_OBJECT_CLASS (class); - - object_class->destroy = nautilus_bookmark_destroy; - - signals[APPEARANCE_CHANGED] = - gtk_signal_new ("appearance_changed", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (NautilusBookmarkClass, appearance_changed), - gtk_marshal_NONE__NONE, - GTK_TYPE_NONE, 0); - - signals[CONTENTS_CHANGED] = - gtk_signal_new ("contents_changed", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (NautilusBookmarkClass, contents_changed), - gtk_marshal_NONE__NONE, - GTK_TYPE_NONE, 0); - - gtk_object_class_add_signals (object_class, signals, LAST_SIGNAL); - -} - -static void -nautilus_bookmark_initialize (NautilusBookmark *bookmark) -{ - bookmark->details = g_new0 (NautilusBookmarkDetails, 1); -} - -/** - * nautilus_bookmark_compare_with: - * - * Check whether two bookmarks are considered identical. - * @a: first NautilusBookmark*. - * @b: second NautilusBookmark*. - * - * Return value: 0 if @a and @b have same name and uri, 1 otherwise - * (GCompareFunc style) - **/ -int -nautilus_bookmark_compare_with (gconstpointer a, gconstpointer b) -{ - NautilusBookmark *bookmark_a; - NautilusBookmark *bookmark_b; - - g_return_val_if_fail (NAUTILUS_IS_BOOKMARK (a), 1); - g_return_val_if_fail (NAUTILUS_IS_BOOKMARK (b), 1); - - bookmark_a = NAUTILUS_BOOKMARK (a); - bookmark_b = NAUTILUS_BOOKMARK (b); - - if (strcmp (bookmark_a->details->name, - bookmark_b->details->name) != 0) { - return 1; - } - - if (!eel_uris_match (bookmark_a->details->uri, - bookmark_b->details->uri)) { - return 1; - } - - return 0; -} - -/** - * nautilus_bookmark_compare_uris: - * - * Check whether the uris of two bookmarks are for the same location. - * @a: first NautilusBookmark*. - * @b: second NautilusBookmark*. - * - * Return value: 0 if @a and @b have matching uri, 1 otherwise - * (GCompareFunc style) - **/ -int -nautilus_bookmark_compare_uris (gconstpointer a, gconstpointer b) -{ - NautilusBookmark *bookmark_a; - NautilusBookmark *bookmark_b; - - g_return_val_if_fail (NAUTILUS_IS_BOOKMARK (a), 1); - g_return_val_if_fail (NAUTILUS_IS_BOOKMARK (b), 1); - - bookmark_a = NAUTILUS_BOOKMARK (a); - bookmark_b = NAUTILUS_BOOKMARK (b); - - return !eel_uris_match (bookmark_a->details->uri, - bookmark_b->details->uri); -} - -NautilusBookmark * -nautilus_bookmark_copy (NautilusBookmark *bookmark) -{ - g_return_val_if_fail (NAUTILUS_IS_BOOKMARK (bookmark), NULL); - - return nautilus_bookmark_new_with_icon ( - bookmark->details->uri, - bookmark->details->name, - bookmark->details->icon); -} - -char * -nautilus_bookmark_get_name (NautilusBookmark *bookmark) -{ - g_return_val_if_fail(NAUTILUS_IS_BOOKMARK (bookmark), NULL); - - return g_strdup (bookmark->details->name); -} - -gboolean -nautilus_bookmark_get_pixmap_and_mask (NautilusBookmark *bookmark, - guint icon_size, - GdkPixmap **pixmap_return, - GdkBitmap **mask_return) -{ - GdkPixbuf *pixbuf; - - pixbuf = nautilus_bookmark_get_pixbuf (bookmark, icon_size, FALSE); - if (pixbuf == NULL) { - return FALSE; - } - - gdk_pixbuf_render_pixmap_and_mask (pixbuf, pixmap_return, mask_return, EEL_STANDARD_ALPHA_THRESHHOLD); - gdk_pixbuf_unref (pixbuf); - - return TRUE; -} - -GdkPixbuf * -nautilus_bookmark_get_pixbuf (NautilusBookmark *bookmark, - guint icon_size, - gboolean optimize_for_anti_aliasing) -{ - GdkPixbuf *result; - NautilusScalableIcon *icon; - - g_return_val_if_fail (NAUTILUS_IS_BOOKMARK (bookmark), NULL); - - icon = nautilus_bookmark_get_icon (bookmark); - if (icon == NULL) { - return NULL; - } - - result = nautilus_icon_factory_get_pixbuf_for_icon - (icon, - icon_size, icon_size, icon_size, icon_size, - optimize_for_anti_aliasing, - NULL, TRUE); - nautilus_scalable_icon_unref (icon); - - return result; -} - -NautilusScalableIcon * -nautilus_bookmark_get_icon (NautilusBookmark *bookmark) -{ - g_return_val_if_fail (NAUTILUS_IS_BOOKMARK (bookmark), NULL); - - /* Try to connect a file in case file exists now but didn't earlier. */ - nautilus_bookmark_connect_file (bookmark); - - if (bookmark->details->icon != NULL) { - nautilus_scalable_icon_ref (bookmark->details->icon); - } - return bookmark->details->icon; -} - -char * -nautilus_bookmark_get_uri (NautilusBookmark *bookmark) -{ - g_return_val_if_fail(NAUTILUS_IS_BOOKMARK (bookmark), NULL); - - /* Try to connect a file in case file exists now but didn't earlier. - * This allows a bookmark to update its image properly in the case - * where a new file appears with the same URI as a previously-deleted - * file. Calling connect_file here means that attempts to activate the - * bookmark will update its image if possible. - */ - nautilus_bookmark_connect_file (bookmark); - - return g_strdup (bookmark->details->uri); -} - - -/** - * nautilus_bookmark_set_name: - * - * Change the user-displayed name of a bookmark. - * @new_name: The new user-displayed name for this bookmark, mustn't be NULL. - * - **/ -void -nautilus_bookmark_set_name (NautilusBookmark *bookmark, const char *new_name) -{ - g_return_if_fail(NAUTILUS_IS_BOOKMARK (bookmark)); - g_return_if_fail (new_name != NULL); - - if (strcmp (new_name, bookmark->details->name) == 0) { - return; - } - - g_free (bookmark->details->name); - bookmark->details->name = g_strdup (new_name); - - gtk_signal_emit (GTK_OBJECT (bookmark), signals[APPEARANCE_CHANGED]); -} - -static gboolean -nautilus_bookmark_icon_is_different (NautilusBookmark *bookmark, - NautilusScalableIcon *new_icon) -{ - char *new_uri, *new_mime_type, *new_name; - char *old_uri, *old_mime_type, *old_name; - gboolean result; - - g_assert (NAUTILUS_IS_BOOKMARK (bookmark)); - g_assert (new_icon != NULL); - - /* Bookmarks don't store the modifier or embedded text. */ - nautilus_scalable_icon_get_text_pieces - (new_icon, &new_uri, &new_mime_type, &new_name, NULL, NULL); - - if (bookmark->details->icon == NULL) { - result = !eel_str_is_empty (new_uri) - || !eel_str_is_empty (new_mime_type) - || !eel_str_is_empty (new_name); - } else { - nautilus_scalable_icon_get_text_pieces - (bookmark->details->icon, &old_uri, &old_mime_type, &old_name, NULL, NULL); - - result = eel_strcmp (old_uri, new_uri) != 0 - || eel_strcmp (old_mime_type, new_mime_type) != 0 - || eel_strcmp (old_name, new_name) != 0; - - g_free (old_uri); - g_free (old_mime_type); - g_free (old_name); - } - - g_free (new_uri); - g_free (new_mime_type); - g_free (new_name); - - return result; -} - -/** - * Update icon if there's a better one available. - * Return TRUE if the icon changed. - */ -static gboolean -nautilus_bookmark_update_icon (NautilusBookmark *bookmark) -{ - NautilusScalableIcon *new_icon; - - g_assert (NAUTILUS_IS_BOOKMARK (bookmark)); - - if (bookmark->details->file == NULL) { - return FALSE; - } - - if (nautilus_icon_factory_is_icon_ready_for_file (bookmark->details->file)) { - new_icon = nautilus_icon_factory_get_icon_for_file (bookmark->details->file, NULL); - if (nautilus_bookmark_icon_is_different (bookmark, new_icon)) { - if (bookmark->details->icon != NULL) { - nautilus_scalable_icon_unref (bookmark->details->icon); - } - bookmark->details->icon = new_icon; - return TRUE; - } - nautilus_scalable_icon_unref (new_icon); - } - - return FALSE; -} - -static void -bookmark_file_changed_callback (NautilusFile *file, NautilusBookmark *bookmark) -{ - char *file_uri; - gboolean should_emit_appearance_changed_signal; - gboolean should_emit_contents_changed_signal; - - g_assert (NAUTILUS_IS_FILE (file)); - g_assert (NAUTILUS_IS_BOOKMARK (bookmark)); - g_assert (file == bookmark->details->file); - - should_emit_appearance_changed_signal = FALSE; - should_emit_contents_changed_signal = FALSE; - file_uri = nautilus_file_get_uri (file); - - if (!eel_uris_match (bookmark->details->uri, file_uri)) { - g_free (bookmark->details->uri); - bookmark->details->uri = file_uri; - should_emit_contents_changed_signal = TRUE; - } else { - g_free (file_uri); - } - - if (nautilus_file_is_gone (file)) { - /* The file we were monitoring has been deleted, - * or moved in a way that we didn't notice. Make - * a spanking new NautilusFile object for this - * location so if a new file appears in this place - * we will notice. - */ - nautilus_bookmark_disconnect_file (bookmark); - nautilus_bookmark_connect_file (bookmark); - should_emit_appearance_changed_signal = TRUE; - } else if (nautilus_bookmark_update_icon (bookmark)) { - /* File hasn't gone away, but it has changed - * in a way that affected its icon. - */ - should_emit_appearance_changed_signal = TRUE; - } - - if (should_emit_appearance_changed_signal) { - gtk_signal_emit (GTK_OBJECT (bookmark), signals[APPEARANCE_CHANGED]); - } - - if (should_emit_contents_changed_signal) { - gtk_signal_emit (GTK_OBJECT (bookmark), signals[CONTENTS_CHANGED]); - } -} - -/** - * nautilus_bookmark_set_icon_to_default: - * - * Reset the icon to either the missing bookmark icon or the generic - * bookmark icon, depending on whether the file still exists. - */ -static void -nautilus_bookmark_set_icon_to_default (NautilusBookmark *bookmark) -{ - const char *icon_name; - - if (bookmark->details->icon != NULL) { - nautilus_scalable_icon_unref (bookmark->details->icon); - } - - if (nautilus_bookmark_uri_known_not_to_exist (bookmark)) { - icon_name = MISSING_BOOKMARK_ICON_NAME; - } else { - icon_name = GENERIC_BOOKMARK_ICON_NAME; - } - bookmark->details->icon = nautilus_scalable_icon_new_from_text_pieces - (NULL, NULL, icon_name, NULL, NULL); -} - -/** - * nautilus_bookmark_new: - * - * Create a new NautilusBookmark from a text uri and a display name. - * The initial icon for the bookmark will be based on the information - * already available without any explicit action on NautilusBookmark's - * part. - * - * @uri: Any uri, even a malformed or non-existent one. - * @name: A string to display to the user as the bookmark's name. - * - * Return value: A newly allocated NautilusBookmark. - * - **/ -NautilusBookmark * -nautilus_bookmark_new (const char *uri, const char *name) -{ - return nautilus_bookmark_new_with_icon (uri, name, NULL); -} - -static void -nautilus_bookmark_disconnect_file (NautilusBookmark *bookmark) -{ - g_assert (NAUTILUS_IS_BOOKMARK (bookmark)); - - if (bookmark->details->file != NULL) { - gtk_signal_disconnect_by_func (GTK_OBJECT (bookmark->details->file), - bookmark_file_changed_callback, - bookmark); - nautilus_file_unref (bookmark->details->file); - bookmark->details->file = NULL; - } - - if (bookmark->details->icon != NULL) { - nautilus_scalable_icon_unref (bookmark->details->icon); - bookmark->details->icon = NULL; - } -} - -static void -nautilus_bookmark_connect_file (NautilusBookmark *bookmark) -{ - g_assert (NAUTILUS_IS_BOOKMARK (bookmark)); - - if (bookmark->details->file != NULL) { - return; - } - - if (!nautilus_bookmark_uri_known_not_to_exist (bookmark)) { - bookmark->details->file = nautilus_file_get (bookmark->details->uri); - g_assert (!nautilus_file_is_gone (bookmark->details->file)); - - gtk_signal_connect (GTK_OBJECT (bookmark->details->file), - "changed", - bookmark_file_changed_callback, - bookmark); - } - - /* Set icon based on available information; don't force network i/o - * to get any currently unknown information. - */ - if (!nautilus_bookmark_update_icon (bookmark)) { - if (bookmark->details->icon == NULL || bookmark->details->file == NULL) { - nautilus_bookmark_set_icon_to_default (bookmark); - } - } -} - -NautilusBookmark * -nautilus_bookmark_new_with_icon (const char *uri, const char *name, - NautilusScalableIcon *icon) -{ - NautilusBookmark *new_bookmark; - - new_bookmark = NAUTILUS_BOOKMARK (gtk_object_new (NAUTILUS_TYPE_BOOKMARK, NULL)); - gtk_object_ref (GTK_OBJECT (new_bookmark)); - gtk_object_sink (GTK_OBJECT (new_bookmark)); - - new_bookmark->details->name = g_strdup (name); - new_bookmark->details->uri = g_strdup (uri); - - if (icon != NULL) { - nautilus_scalable_icon_ref (icon); - } - new_bookmark->details->icon = icon; - - nautilus_bookmark_connect_file (new_bookmark); - - return new_bookmark; -} - -static GtkWidget * -create_pixmap_widget_for_bookmark (NautilusBookmark *bookmark) -{ - GdkPixmap *gdk_pixmap; - GdkBitmap *mask; - - if (!nautilus_bookmark_get_pixmap_and_mask (bookmark, - NAUTILUS_ICON_SIZE_FOR_MENUS, - &gdk_pixmap, - &mask)) { - return NULL; - } - - return gtk_pixmap_new (gdk_pixmap, mask); -} - -/** - * nautilus_bookmarnuk_menu_item_new: - * - * Return a menu item representing a bookmark. - * @bookmark: The bookmark the menu item represents. - * Return value: A newly-created bookmark, not yet shown. - **/ -GtkWidget * -nautilus_bookmark_menu_item_new (NautilusBookmark *bookmark) -{ - GtkWidget *menu_item; - GtkWidget *pixmap_widget; - GtkWidget *label; - char *display_name; - - /* Could check gnome_preferences_get_menus_have_icons here, but these - * are more important than stock menu icons, since they're connected to - * user data. For now let's not let them be turn-offable and see if - * anyone objects strenuously. - */ - menu_item = gtk_pixmap_menu_item_new (); - - pixmap_widget = create_pixmap_widget_for_bookmark (bookmark); - if (pixmap_widget != NULL) { - gtk_widget_show (pixmap_widget); - gtk_pixmap_menu_item_set_pixmap (GTK_PIXMAP_MENU_ITEM (menu_item), pixmap_widget); - } - display_name = eel_truncate_text_for_menu_item (bookmark->details->name); - label = gtk_label_new (display_name); - g_free (display_name); - gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); - - gtk_container_add (GTK_CONTAINER (menu_item), label); - gtk_widget_show (label); - - return menu_item; -} - -gboolean -nautilus_bookmark_uri_known_not_to_exist (NautilusBookmark *bookmark) -{ - char *path_name; - gboolean exists; - - /* Convert to a path, returning FALSE if not local. */ - path_name = gnome_vfs_get_local_path_from_uri (bookmark->details->uri); - if (path_name == NULL) { - return FALSE; - } - - /* Now check if the file exists (sync. call OK because it is local). */ - exists = g_file_exists (path_name); - g_free (path_name); - return !exists; -} diff --git a/libnautilus-extensions/nautilus-bookmark.h b/libnautilus-extensions/nautilus-bookmark.h deleted file mode 100644 index 7496d8f5e..000000000 --- a/libnautilus-extensions/nautilus-bookmark.h +++ /dev/null @@ -1,101 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ - -/* nautilus-bookmark.h - interface for individual bookmarks. - - Copyright (C) 1999, 2000 Eazel, Inc. - - The Gnome 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 Gnome 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 the Gnome 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. - - Authors: John Sullivan <sullivan@eazel.com> -*/ - -#ifndef NAUTILUS_BOOKMARK_H -#define NAUTILUS_BOOKMARK_H - -#include "nautilus-icon-factory.h" - -#include <gtk/gtkwidget.h> -#include <gdk/gdktypes.h> -#include <gdk-pixbuf/gdk-pixbuf.h> - -typedef struct NautilusBookmark NautilusBookmark; - -#define NAUTILUS_TYPE_BOOKMARK \ - (nautilus_bookmark_get_type ()) -#define NAUTILUS_BOOKMARK(obj) \ - (GTK_CHECK_CAST ((obj), NAUTILUS_TYPE_BOOKMARK, NautilusBookmark)) -#define NAUTILUS_BOOKMARK_CLASS(klass) \ - (GTK_CHECK_CLASS_CAST ((klass), NAUTILUS_TYPE_BOOKMARK, NautilusBookmarkClass)) -#define NAUTILUS_IS_BOOKMARK(obj) \ - (GTK_CHECK_TYPE ((obj), NAUTILUS_TYPE_BOOKMARK)) -#define NAUTILUS_IS_BOOKMARK_CLASS(klass) \ - (GTK_CHECK_CLASS_TYPE ((klass), NAUTILUS_TYPE_BOOKMARK)) - -typedef struct NautilusBookmarkDetails NautilusBookmarkDetails; - -struct NautilusBookmark { - GtkObject object; - NautilusBookmarkDetails *details; -}; - -struct NautilusBookmarkClass { - GtkObjectClass parent_class; - - /* Signals that clients can connect to. */ - - /* The appearance_changed signal is emitted when the bookmark's - * name or icon has changed. - */ - void (* appearance_changed) (NautilusBookmark *bookmark); - - /* The contents_changed signal is emitted when the bookmark's - * URI has changed. - */ - void (* contents_changed) (NautilusBookmark *bookmark); -}; - -typedef struct NautilusBookmarkClass NautilusBookmarkClass; - -GtkType nautilus_bookmark_get_type (void); -NautilusBookmark * nautilus_bookmark_new (const char *uri, - const char *name); -NautilusBookmark * nautilus_bookmark_new_with_icon (const char *uri, - const char *name, - NautilusScalableIcon *icon); -NautilusBookmark * nautilus_bookmark_copy (NautilusBookmark *bookmark); -char * nautilus_bookmark_get_name (NautilusBookmark *bookmark); -char * nautilus_bookmark_get_uri (NautilusBookmark *bookmark); -NautilusScalableIcon *nautilus_bookmark_get_icon (NautilusBookmark *bookmark); -void nautilus_bookmark_set_name (NautilusBookmark *bookmark, - const char *new_name); -gboolean nautilus_bookmark_uri_known_not_to_exist (NautilusBookmark *bookmark); -int nautilus_bookmark_compare_with (gconstpointer a, - gconstpointer b); -int nautilus_bookmark_compare_uris (gconstpointer a, - gconstpointer b); - -/* Helper functions for displaying bookmarks */ -gboolean nautilus_bookmark_get_pixmap_and_mask (NautilusBookmark *bookmark, - guint icon_size, - GdkPixmap **pixmap_return, - GdkBitmap **mask_return); -GdkPixbuf * nautilus_bookmark_get_pixbuf (NautilusBookmark *bookmark, - guint icon_size, - gboolean optimize_for_anti_aliasing); -GtkWidget * nautilus_bookmark_menu_item_new (NautilusBookmark *bookmark); - - -#endif /* NAUTILUS_BOOKMARK_H */ diff --git a/libnautilus-extensions/nautilus-cdrom-extensions.h b/libnautilus-extensions/nautilus-cdrom-extensions.h deleted file mode 100644 index 8a5bba51f..000000000 --- a/libnautilus-extensions/nautilus-cdrom-extensions.h +++ /dev/null @@ -1,235 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ - -/* fm-cdrom-extension.c - CDROM handliong constants copied from <linux/cdrom.h>. - - Copyright (C) 2000 Eazel, Inc. - - The Gnome 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 Gnome 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 the Gnome 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. - - Authors: Gene Z. Ragan <gzr@eazel.com> -*/ - -#ifndef FM_CDROM_EXTENSIONS_H -#define FM_CDROM_EXTENSIONS_H - -#include <sys/types.h> - -#ifdef HAVE_SYS_CDIO_H - -#include <sys/cdio.h> - -#else - -/******************************************************* - * The CD-ROM IOCTL commands -- these should be supported by - * all the various cdrom drivers. For the CD-ROM ioctls, we - * will commandeer byte 0x53, or 'S'. - *******************************************************/ -#define CDROMPAUSE 0x5301 /* Pause Audio Operation */ -#define CDROMRESUME 0x5302 /* Resume paused Audio Operation */ -#define CDROMPLAYMSF 0x5303 /* Play Audio MSF (struct cdrom_msf) */ -#define CDROMPLAYTRKIND 0x5304 /* Play Audio Track/index - (struct cdrom_ti) */ -#define CDROMREADTOCHDR 0x5305 /* Read TOC header - (struct cdrom_tochdr) */ -#define CDROMREADTOCENTRY 0x5306 /* Read TOC entry - (struct cdrom_tocentry) */ -#define CDROMSTOP 0x5307 /* Stop the cdrom drive */ -#define CDROMSTART 0x5308 /* Start the cdrom drive */ -#define CDROMEJECT 0x5309 /* Ejects the cdrom media */ -#define CDROMVOLCTRL 0x530a /* Control output volume - (struct cdrom_volctrl) */ -#define CDROMSUBCHNL 0x530b /* Read subchannel data - (struct cdrom_subchnl) */ -#define CDROMREADMODE2 0x530c /* Read CDROM mode 2 data (2336 Bytes) - (struct cdrom_read) */ -#define CDROMREADMODE1 0x530d /* Read CDROM mode 1 data (2048 Bytes) - (struct cdrom_read) */ -#define CDROMREADAUDIO 0x530e /* (struct cdrom_read_audio) */ -#define CDROMEJECT_SW 0x530f /* enable(1)/disable(0) auto-ejecting */ -#define CDROMMULTISESSION 0x5310 /* Obtain the start-of-last-session - address of multi session disks - (struct cdrom_multisession) */ -#define CDROM_GET_MCN 0x5311 /* Obtain the "Universal Product Code" - if available (struct cdrom_mcn) */ -#define CDROM_GET_UPC CDROM_GET_MCN /* This one is depricated, - but here anyway for compatability */ -#define CDROMRESET 0x5312 /* hard-reset the drive */ -#define CDROMVOLREAD 0x5313 /* Get the drive's volume setting - (struct cdrom_volctrl) */ -#define CDROMREADRAW 0x5314 /* read data in raw mode (2352 Bytes) - (struct cdrom_read) */ -/* - * These ioctls are used only used in aztcd.c and optcd.c - */ -#define CDROMREADCOOKED 0x5315 /* read data in cooked mode */ -#define CDROMSEEK 0x5316 /* seek msf address */ - -/* - * This ioctl is only used by the scsi-cd driver. - It is for playing audio in logical block addressing mode. - */ -#define CDROMPLAYBLK 0x5317 /* (struct cdrom_blk) */ - -/* - * These ioctls are only used in optcd.c - */ -#define CDROMREADALL 0x5318 /* read all 2646 bytes */ - - - -#endif /* HAVE_SYS_CDIO_H */ - - -/* - * These ioctls are (now) only in ide-cd.c for controlling - * drive spindown time. They should be implemented in the - * Uniform driver, via generic packet commands, GPCMD_MODE_SELECT_10, - * GPCMD_MODE_SENSE_10 and the GPMODE_POWER_PAGE... - * -Erik - */ -#define CDROMGETSPINDOWN 0x531d -#define CDROMSETSPINDOWN 0x531e - -/* - * These ioctls are implemented through the uniform CD-ROM driver - * They _will_ be adopted by all CD-ROM drivers, when all the CD-ROM - * drivers are eventually ported to the uniform CD-ROM driver interface. - */ -#define CDROMCLOSETRAY 0x5319 /* pendant of CDROMEJECT */ -#define CDROM_SET_OPTIONS 0x5320 /* Set behavior options */ -#define CDROM_CLEAR_OPTIONS 0x5321 /* Clear behavior options */ -#define CDROM_SELECT_SPEED 0x5322 /* Set the CD-ROM speed */ -#define CDROM_SELECT_DISC 0x5323 /* Select disc (for juke-boxes) */ -#define CDROM_MEDIA_CHANGED 0x5325 /* Check is media changed */ -#define CDROM_DRIVE_STATUS 0x5326 /* Get tray position, etc. */ -#define CDROM_DISC_STATUS 0x5327 /* Get disc type, etc. */ -#define CDROM_CHANGER_NSLOTS 0x5328 /* Get number of slots */ -#define CDROM_LOCKDOOR 0x5329 /* lock or unlock door */ -#define CDROM_DEBUG 0x5330 /* Turn debug messages on/off */ -#define CDROM_GET_CAPABILITY 0x5331 /* get capabilities */ - -/* This ioctl is only used by sbpcd at the moment */ -#define CDROMAUDIOBUFSIZ 0x5382 /* set the audio buffer size */ - -/* DVD-ROM Specific ioctls */ -#define DVD_READ_STRUCT 0x5390 /* Read structure */ -#define DVD_WRITE_STRUCT 0x5391 /* Write structure */ -#define DVD_AUTH 0x5392 /* Authentication */ - -#define CDROM_SEND_PACKET 0x5393 /* send a packet to the drive */ -#define CDROM_NEXT_WRITABLE 0x5394 /* get next writable block */ -#define CDROM_LAST_WRITTEN 0x5395 /* get last block written on disc */ - -/* Some generally useful CD-ROM information -- mostly based on the above */ -#define CD_MINS 74 /* max. minutes per CD, not really a limit */ -#define CD_SECS 60 /* seconds per minute */ -#define CD_FRAMES 75 /* frames per second */ -#define CD_SYNC_SIZE 12 /* 12 sync bytes per raw data frame */ -#define CD_MSF_OFFSET 150 /* MSF numbering offset of first frame */ -#define CD_CHUNK_SIZE 24 /* lowest-level "data bytes piece" */ -#define CD_NUM_OF_CHUNKS 98 /* chunks per frame */ -#define CD_FRAMESIZE_SUB 96 /* subchannel data "frame" size */ -#define CD_HEAD_SIZE 4 /* header (address) bytes per raw data frame */ -#define CD_SUBHEAD_SIZE 8 /* subheader bytes per raw XA data frame */ -#define CD_EDC_SIZE 4 /* bytes EDC per most raw data frame types */ -#define CD_ZERO_SIZE 8 /* bytes zero per yellow book mode 1 frame */ -#define CD_ECC_SIZE 276 /* bytes ECC per most raw data frame types */ -#define CD_FRAMESIZE 2048 /* bytes per frame, "cooked" mode */ -#define CD_FRAMESIZE_RAW 2352 /* bytes per frame, "raw" mode */ -#define CD_FRAMESIZE_RAWER 2646 /* The maximum possible returned bytes */ -/* most drives don't deliver everything: */ -#define CD_FRAMESIZE_RAW1 (CD_FRAMESIZE_RAW-CD_SYNC_SIZE) /*2340*/ -#define CD_FRAMESIZE_RAW0 (CD_FRAMESIZE_RAW-CD_SYNC_SIZE-CD_HEAD_SIZE) /*2336*/ - -#define CD_XA_HEAD (CD_HEAD_SIZE+CD_SUBHEAD_SIZE) /* "before data" part of raw XA frame */ -#define CD_XA_TAIL (CD_EDC_SIZE+CD_ECC_SIZE) /* "after data" part of raw XA frame */ -#define CD_XA_SYNC_HEAD (CD_SYNC_SIZE+CD_XA_HEAD) /* sync bytes + header of XA frame */ - -/* CD-ROM address types (cdrom_tocentry.cdte_format) */ -#define CDROM_LBA 0x01 /* "logical block": first frame is #0 */ -#define CDROM_MSF 0x02 /* "minute-second-frame": binary, not bcd here! */ - -/* bit to tell whether track is data or audio (cdrom_tocentry.cdte_ctrl) */ -#define CDROM_DATA_TRACK 0x04 - -/* The leadout track is always 0xAA, regardless of # of tracks on disc */ -#define CDROM_LEADOUT 0xAA - -/* audio states (from SCSI-2, but seen with other drives, too) */ -#define CDROM_AUDIO_INVALID 0x00 /* audio status not supported */ -#define CDROM_AUDIO_PLAY 0x11 /* audio play operation in progress */ -#define CDROM_AUDIO_PAUSED 0x12 /* audio play operation paused */ -#define CDROM_AUDIO_COMPLETED 0x13 /* audio play successfully completed */ -#define CDROM_AUDIO_ERROR 0x14 /* audio play stopped due to error */ -#define CDROM_AUDIO_NO_STATUS 0x15 /* no current audio status to return */ - -/* capability flags used with the uniform CD-ROM driver */ -#define CDC_CLOSE_TRAY 0x1 /* caddy systems _can't_ close */ -#define CDC_OPEN_TRAY 0x2 /* but _can_ eject. */ -#define CDC_LOCK 0x4 /* disable manual eject */ -#define CDC_SELECT_SPEED 0x8 /* programmable speed */ -#define CDC_SELECT_DISC 0x10 /* select disc from juke-box */ -#define CDC_MULTI_SESSION 0x20 /* read sessions>1 */ -#define CDC_MCN 0x40 /* Medium Catalog Number */ -#define CDC_MEDIA_CHANGED 0x80 /* media changed */ -#define CDC_PLAY_AUDIO 0x100 /* audio functions */ -#define CDC_RESET 0x200 /* hard reset device */ -#define CDC_IOCTLS 0x400 /* driver has non-standard ioctls */ -#define CDC_DRIVE_STATUS 0x800 /* driver implements drive status */ -#define CDC_GENERIC_PACKET 0x1000 /* driver implements generic packets */ -#define CDC_CD_R 0x2000 /* drive is a CD-R */ -#define CDC_CD_RW 0x4000 /* drive is a CD-RW */ -#define CDC_DVD 0x8000 /* drive is a DVD */ -#define CDC_DVD_R 0x10000 /* drive can write DVD-R */ -#define CDC_DVD_RAM 0x20000 /* drive can write DVD-RAM */ - -/* drive status possibilities returned by CDROM_DRIVE_STATUS ioctl */ -#define CDS_NO_INFO 0 /* if not implemented */ -#define CDS_NO_DISC 1 -#define CDS_TRAY_OPEN 2 -#define CDS_DRIVE_NOT_READY 3 -#define CDS_DISC_OK 4 - -/* return values for the CDROM_DISC_STATUS ioctl */ -/* can also return CDS_NO_[INFO|DISC], from above */ -#define CDS_AUDIO 100 -#define CDS_DATA_1 101 -#define CDS_DATA_2 102 -#define CDS_XA_2_1 103 -#define CDS_XA_2_2 104 -#define CDS_MIXED 105 - -/* User-configurable behavior options for the uniform CD-ROM driver */ -#define CDO_AUTO_CLOSE 0x1 /* close tray on first open() */ -#define CDO_AUTO_EJECT 0x2 /* open tray on last release() */ -#define CDO_USE_FFLAGS 0x4 /* use O_NONBLOCK information on open */ -#define CDO_LOCK 0x8 /* lock tray on open files */ -#define CDO_CHECK_TYPE 0x10 /* check type on open for data */ - -/* Special codes used when specifying changer slots. */ -#define CDSL_NONE ((int) (~0U>>1)-1) -#define CDSL_CURRENT ((int) (~0U>>1)) - -/* For partition based multisession access. IDE can handle 64 partitions - * per drive - SCSI CD-ROM's use minors to differentiate between the - * various drives, so we can't do multisessions the same way there. - * Use the -o session=x option to mount on them. - */ -#define CD_PART_MAX 64 -#define CD_PART_MASK (CD_PART_MAX - 1) - -#endif /* FM_CDROM_EXTENSIONS_H */ diff --git a/libnautilus-extensions/nautilus-customization-data.c b/libnautilus-extensions/nautilus-customization-data.c deleted file mode 100644 index 366c3cb92..000000000 --- a/libnautilus-extensions/nautilus-customization-data.c +++ /dev/null @@ -1,452 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ - -/* - * Nautilus - * - * Copyright (C) 2000 Eazel, Inc. - * - * Nautilus 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. - * - * Nautilus 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: Rebecca Schulman <rebecka@eazel.com> - */ - -/* nautilus-customization-data.c - functions to collect and load customization - names and imges */ - -#include <config.h> -#include <ctype.h> - -#include <gnome-xml/parser.h> -#include <gnome-xml/xmlmemory.h> - -#include <glib.h> -#include <gdk-pixbuf/gdk-pixbuf.h> -#include <gtk/gtk.h> -#include <libgnomevfs/gnome-vfs.h> -#include <string.h> -#include <libgnome/gnome-defs.h> -#include <stdlib.h> - -#include "nautilus-customization-data.h" -#include <eel/eel-gdk-extensions.h> -#include <eel/eel-gdk-pixbuf-extensions.h> -#include <eel/eel-glib-extensions.h> -#include "nautilus-file-utilities.h" -#include <eel/eel-gdk-extensions.h> -#include <eel/eel-gtk-extensions.h> -#include <eel/eel-xml-extensions.h> -#include <eel/eel-string.h> - -typedef enum { - READ_PUBLIC_CUSTOMIZATIONS, - READ_PRIVATE_CUSTOMIZATIONS -} CustomizationReadingMode; - -struct NautilusCustomizationData { - char *customization_name; - CustomizationReadingMode reading_mode; - - GList *public_file_list; - GList *private_file_list; - GList *current_file_list; - - GHashTable *name_map_hash; - - GdkPixbuf *pattern_frame; - - gboolean private_data_was_displayed; - gboolean data_is_for_a_menu; - int maximum_icon_height; - int maximum_icon_width; -}; - - -/* The Property here should be one of "emblems", "colors" or "patterns" */ -static char * get_global_customization_uri (const char *customization_name); -static char * get_private_customization_uri (const char *customization_name); -static char * get_file_path_for_mode (const NautilusCustomizationData *data, - const char *file_name); -static char* format_name_for_display (NautilusCustomizationData *data, const char *name); -static char* strip_extension (const char* string_to_strip); -static void load_name_map_hash_table (NautilusCustomizationData *data); - -NautilusCustomizationData* -nautilus_customization_data_new (const char *customization_name, - gboolean show_public_customizations, - gboolean data_is_for_a_menu, - int maximum_icon_height, - int maximum_icon_width) -{ - NautilusCustomizationData *data; - char *public_directory_uri, *private_directory_uri; - char *temp_str; - GnomeVFSResult public_result, private_result; - - data = g_new0 (NautilusCustomizationData, 1); - - public_result = GNOME_VFS_OK; - - if (show_public_customizations) { - public_directory_uri = get_global_customization_uri (customization_name); - - - public_result = gnome_vfs_directory_list_load (&data->public_file_list, - public_directory_uri, - GNOME_VFS_FILE_INFO_GET_MIME_TYPE, NULL); - g_free (public_directory_uri); - } - - private_directory_uri = get_private_customization_uri (customization_name); - private_result = gnome_vfs_directory_list_load (&data->private_file_list, - private_directory_uri, - GNOME_VFS_FILE_INFO_GET_MIME_TYPE, NULL); - g_free (private_directory_uri); - if (public_result != GNOME_VFS_OK && - private_result != GNOME_VFS_OK) { - g_warning ("Couldn't read any of the emblem directories\n"); - g_free (data); - return NULL; - } - if (private_result == GNOME_VFS_OK) { - data->reading_mode = READ_PRIVATE_CUSTOMIZATIONS; - data->current_file_list = data->private_file_list; - } - if (show_public_customizations && public_result == GNOME_VFS_OK) { - data->reading_mode = READ_PUBLIC_CUSTOMIZATIONS; - data->current_file_list = data->public_file_list; - } - - /* load the frame if necessary */ - if (!strcmp(customization_name, "patterns")) { - temp_str = nautilus_pixmap_file ("chit_frame.png"); - data->pattern_frame = gdk_pixbuf_new_from_file (temp_str); - g_free (temp_str); - } else { - data->pattern_frame = NULL; - } - - - data->private_data_was_displayed = FALSE; - data->data_is_for_a_menu = data_is_for_a_menu; - data->customization_name = g_strdup (customization_name); - - data->maximum_icon_height = maximum_icon_height; - data->maximum_icon_width = maximum_icon_width; - - load_name_map_hash_table (data); - - return data; -} - - -GnomeVFSResult -nautilus_customization_data_get_next_element_for_display (NautilusCustomizationData *data, - char **emblem_name, - GdkPixbuf **pixbuf_out, - char **label_out) -{ - GnomeVFSFileInfo *current_file_info; - - char *image_file_name, *filtered_name; - GdkPixbuf *pixbuf; - GdkPixbuf *orig_pixbuf; - - g_return_val_if_fail (data != NULL, GNOME_VFS_ERROR_BAD_PARAMETERS); - g_return_val_if_fail (emblem_name != NULL, GNOME_VFS_ERROR_BAD_PARAMETERS); - g_return_val_if_fail (pixbuf_out != NULL, GNOME_VFS_ERROR_BAD_PARAMETERS); - g_return_val_if_fail (label_out != NULL, GNOME_VFS_ERROR_BAD_PARAMETERS); - - if (data->current_file_list == NULL) { - if (data->reading_mode == READ_PUBLIC_CUSTOMIZATIONS) { - if (data->private_file_list == NULL) { - return GNOME_VFS_ERROR_EOF; - } - data->reading_mode = READ_PRIVATE_CUSTOMIZATIONS; - data->current_file_list = data->private_file_list; - return nautilus_customization_data_get_next_element_for_display (data, - emblem_name, - pixbuf_out, - label_out); - } - else { - return GNOME_VFS_ERROR_EOF; - } - } - - - current_file_info = data->current_file_list->data; - data->current_file_list = data->current_file_list->next; - - g_assert (current_file_info != NULL); - - if (!eel_istr_has_prefix (current_file_info->mime_type, "image/") || - eel_istr_has_prefix (current_file_info->name, ".")) { - - return nautilus_customization_data_get_next_element_for_display (data, - emblem_name, - pixbuf_out, - label_out); - } - - image_file_name = get_file_path_for_mode (data, - current_file_info->name); - orig_pixbuf = gdk_pixbuf_new_from_file (image_file_name); - g_free (image_file_name); - - *emblem_name = g_strdup (current_file_info->name); - - if (!strcmp(data->customization_name, "patterns")) { - pixbuf = nautilus_customization_make_pattern_chit (orig_pixbuf, data->pattern_frame, FALSE); - } else { - pixbuf = eel_gdk_pixbuf_scale_down_to_fit (orig_pixbuf, - data->maximum_icon_width, - data->maximum_icon_height); - gdk_pixbuf_unref (orig_pixbuf); - } - - *pixbuf_out = pixbuf; - - filtered_name = format_name_for_display (data, current_file_info->name); - /* If the data is for a menu, - we want to truncate it and not use the nautilus - label because anti-aliased text doesn't look right - in menus */ - if (data->data_is_for_a_menu) { - *label_out = eel_truncate_text_for_menu_item (filtered_name); - } - else { - *label_out = g_strdup (filtered_name); - } - - g_free (filtered_name); - - if (data->reading_mode == READ_PRIVATE_CUSTOMIZATIONS) { - data->private_data_was_displayed = TRUE; - } - return GNOME_VFS_OK; -} - -gboolean -nautilus_customization_data_private_data_was_displayed (NautilusCustomizationData *data) -{ - return data->private_data_was_displayed; -} - -void -nautilus_customization_data_destroy (NautilusCustomizationData *data) -{ - g_assert (data->public_file_list != NULL || - data->private_file_list != NULL); - - if (data->pattern_frame != NULL) { - gdk_pixbuf_unref (data->pattern_frame); - } - - gnome_vfs_file_info_list_free (data->public_file_list); - gnome_vfs_file_info_list_free (data->private_file_list); - - if (data->name_map_hash != NULL) { - eel_g_hash_table_destroy_deep (data->name_map_hash); - } - - g_free (data->customization_name); - g_free (data); -} - - -/* get_global_customization_directory - Get the path where a property's pixmaps are stored - @customization_name : the name of the customization to get. - Should be one of "emblems", "colors", or "paterns" - - Return value: The directory name where the customization's - public pixmaps are stored */ -static char * -get_global_customization_uri (const char *customization_name) -{ - char *directory_path, *directory_uri; - - directory_path = nautilus_make_path (NAUTILUS_DATADIR, - customization_name); - directory_uri = gnome_vfs_get_uri_from_local_path (directory_path); - - g_free (directory_path); - - return directory_uri; - -} - - -/* get_private_customization_directory - Get the path where a customization's pixmaps are stored - @customization_name : the name of the customization to get. - Should be one of "emblems", "colors", or "patterns" - - Return value: The directory name where the customization's - user-specific pixmaps are stored */ -static char * -get_private_customization_uri (const char *customization_name) -{ - char *user_directory; - char *directory_path, *directory_uri; - - user_directory = nautilus_get_user_directory (); - directory_path = nautilus_make_path (user_directory, - customization_name); - g_free (user_directory); - directory_uri = gnome_vfs_get_uri_from_local_path (directory_path); - g_free (directory_path); - - return directory_uri; -} - - -static char * -get_file_path_for_mode (const NautilusCustomizationData *data, - const char *file_name) -{ - char *directory_uri, *uri, *directory_name; - if (data->reading_mode == READ_PUBLIC_CUSTOMIZATIONS) { - directory_uri = get_global_customization_uri (data->customization_name); - } - else { - directory_uri = get_private_customization_uri (data->customization_name); - } - - uri = nautilus_make_path (directory_uri, file_name); - g_free (directory_uri); - directory_name = gnome_vfs_get_local_path_from_uri (uri); - g_free (uri); - - return directory_name; -} - -/* utility to make an attractive pattern image by compositing with a frame */ -GdkPixbuf* -nautilus_customization_make_pattern_chit (GdkPixbuf *pattern_tile, GdkPixbuf *frame, gboolean dragging) -{ - GdkPixbuf *pixbuf, *temp_pixbuf; - int frame_width, frame_height; - - - frame_width = gdk_pixbuf_get_width (frame); - frame_height = gdk_pixbuf_get_height (frame); - - /* scale the pattern tile to the proper size */ - pixbuf = gdk_pixbuf_scale_simple (pattern_tile, frame_width, frame_height, GDK_INTERP_BILINEAR); - - /* composite the mask on top of it */ - gdk_pixbuf_composite (frame, pixbuf, 0, 0, frame_width, frame_height, - 0.0, 0.0, 1.0, 1.0, GDK_INTERP_BILINEAR, 255); - - /* if we're dragging, get rid of the light-colored halo */ - if (dragging) { - temp_pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, frame_width - 6, frame_height - 6); - gdk_pixbuf_copy_area (pixbuf, 2, 2, frame_width - 6, frame_height - 6, temp_pixbuf, 0, 0); - gdk_pixbuf_unref (pixbuf); - pixbuf = temp_pixbuf; - } - - gdk_pixbuf_unref (pattern_tile); - return pixbuf; -} - - -/* utility to format the passed-in name for display by stripping the extension, mapping underscore - and capitalizing as necessary */ - -static char* -format_name_for_display (NautilusCustomizationData *data, const char* name) -{ - char *formatted_str, *mapped_name; - - /* don't display a name for the "reset" property, since its name is - contained in its image and also to help distinguish it */ - if (!eel_strcmp(name, RESET_IMAGE_NAME)) { - return g_strdup(""); - } - - /* map file names to display names using the mappings defined in the hash table */ - - formatted_str = strip_extension (name); - if (data->name_map_hash != NULL) { - mapped_name = g_hash_table_lookup (data->name_map_hash, formatted_str); - if (mapped_name) { - g_free (formatted_str); - formatted_str = g_strdup (mapped_name); - } - } - - return formatted_str; -} - -/* utility routine to allocate a hash table and load it with the appropriate - * name mapping data from the browser xml file - */ -static void -load_name_map_hash_table (NautilusCustomizationData *data) -{ - char *xml_path; - char *filename, *display_name; - - xmlDocPtr browser_data; - xmlNodePtr category_node, current_node; - - /* allocate the hash table */ - data->name_map_hash = g_hash_table_new (g_str_hash, g_str_equal); - - /* build the path name to the browser.xml file and load it */ - xml_path = nautilus_make_path (NAUTILUS_DATADIR, "browser.xml"); - if (xml_path) { - browser_data = xmlParseFile (xml_path); - g_free (xml_path); - - if (browser_data) { - /* get the category node */ - category_node = eel_xml_get_root_child_by_name_and_property (browser_data, "category", "name", data->customization_name); - current_node = category_node->childs; - - /* loop through the entries, adding a mapping to the hash table */ - while (current_node != NULL) { - display_name = eel_xml_get_property_translated (current_node, "display_name"); - filename = xmlGetProp (current_node, "filename"); - if (display_name && filename) { - g_hash_table_insert (data->name_map_hash, g_strdup (filename), g_strdup (display_name)); - } - xmlFree (filename); - xmlFree (display_name); - current_node = current_node->next; - } - - /* close the xml file */ - xmlFreeDoc (browser_data); - } - } -} - -/* utility routine to strip the extension from the passed in string */ -static char* -strip_extension (const char* string_to_strip) -{ - char *result_str, *temp_str; - if (string_to_strip == NULL) - return NULL; - - result_str = g_strdup(string_to_strip); - temp_str = strrchr(result_str, '.'); - if (temp_str) - *temp_str = '\0'; - return result_str; -} diff --git a/libnautilus-extensions/nautilus-customization-data.h b/libnautilus-extensions/nautilus-customization-data.h deleted file mode 100644 index a7fc56579..000000000 --- a/libnautilus-extensions/nautilus-customization-data.h +++ /dev/null @@ -1,71 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ - -/* - * Nautilus - * - * Copyright (C) 2000 Eazel, Inc. - * - * Nautilus 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. - * - * Nautilus 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: Rebecca Schulman <rebecka@eazel.com> - */ - -/* nautilus-customization-data.h - functions to collect and load property - names and imges */ - - - -#ifndef NAUTILUS_CUSTOMIZATION_DATA_H -#define NAUTILUS_CUSTOMIZATION_DATA_H - -#include <glib.h> -#include <gdk-pixbuf/gdk-pixbuf.h> -#include <gtk/gtklabel.h> -#include <gtk/gtkwidget.h> -#include <libgnomevfs/gnome-vfs-types.h> - -#define RESET_IMAGE_NAME "reset.png" - -typedef struct NautilusCustomizationData NautilusCustomizationData; - - - -NautilusCustomizationData* nautilus_customization_data_new (const char *customization_name, - gboolean show_public_customizations, - gboolean data_is_for_a_menu, - int maximum_icon_height, - int maximum_icon_width); - -/* Returns the following attrbiutes for a customization object (pattern, emblem) - * - * object_name - The name of the object. Usually what is used to represent it in storage. - * object_pixbuf - Pixbuf for graphical display of the object. - * object_label - Textual label display of the object. - */ -GnomeVFSResult nautilus_customization_data_get_next_element_for_display (NautilusCustomizationData *data, - char **object_name, - GdkPixbuf **object_pixbuf, - char **object_label); -gboolean nautilus_customization_data_private_data_was_displayed (NautilusCustomizationData *data); - -void nautilus_customization_data_destroy (NautilusCustomizationData *data); - - - -GdkPixbuf* nautilus_customization_make_pattern_chit (GdkPixbuf *pattern_tile, - GdkPixbuf *frame, - gboolean dragging); - -#endif /* NAUTILUS_CUSTOMIZATION_DATA_H */ diff --git a/libnautilus-extensions/nautilus-dateedit-extensions.c b/libnautilus-extensions/nautilus-dateedit-extensions.c deleted file mode 100644 index 3ddce5f6c..000000000 --- a/libnautilus-extensions/nautilus-dateedit-extensions.c +++ /dev/null @@ -1,43 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ - -/* nautilus-dateedit-extensions.c -- Extension functions to the gnome-dateedit - widget - - 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; see the file COPYING. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. - - Author: Rebecca Schulman <rebecka@eazel.com> -*/ - -#include <config.h> -#include "nautilus-dateedit-extensions.h" - -#include <eel/eel-glib-extensions.h> - -char * -nautilus_gnome_date_edit_get_date_as_string (GnomeDateEdit *dateedit) -{ - time_t selected_time; - - selected_time = gnome_date_edit_get_date (dateedit); - if (selected_time < 0) { - return NULL; - } - - /* FIXME: Why doesn't this need to be localized? */ - return eel_strdup_strftime ("%-m/%-d/%Y", localtime (&selected_time)); -} diff --git a/libnautilus-extensions/nautilus-dateedit-extensions.h b/libnautilus-extensions/nautilus-dateedit-extensions.h deleted file mode 100644 index 1eafbecf4..000000000 --- a/libnautilus-extensions/nautilus-dateedit-extensions.h +++ /dev/null @@ -1,34 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ - -/* nautilus-dateedit-extensions.h -- Extension functions to the gnome-dateedit - widget - - Copyright (C) 2001 Eazel, Inc. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public - License along with this program; see the file COPYING. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. - - Author: Rebecca Schulman <rebecka@eazel.com> -*/ - -/* This is annoying, but someone forgot time.h in the gnome-dateedit - * header, so it has to be here. A bug report about this has been - * submitted. - */ - -#include <time.h> -#include <libgnomeui/gnome-dateedit.h> - -char *nautilus_gnome_date_edit_get_date_as_string (GnomeDateEdit *dateedit); diff --git a/libnautilus-extensions/nautilus-default-file-icon.c b/libnautilus-extensions/nautilus-default-file-icon.c deleted file mode 100644 index dd103781c..000000000 --- a/libnautilus-extensions/nautilus-default-file-icon.c +++ /dev/null @@ -1,607 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- - - Default file icon used by the icon factory. - - 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. - - Author: Darin Adler <darin@eazel.com> -*/ - -#include <config.h> -#include "nautilus-default-file-icon.h" - -const int nautilus_default_file_icon_width = 48; -const int nautilus_default_file_icon_height = 48; -const unsigned char nautilus_default_file_icon[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, - 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x8c, 0x8c, 0x8c, 0xff, - 0x8c, 0x8c, 0x8c, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, - 0x00, 0x00, 0x00, 0xff, 0x8c, 0x8c, 0x8c, 0xff, 0xaa, 0xaa, 0xaa, 0xff, 0xa7, 0xa7, 0xa6, 0xff, - 0x99, 0x99, 0x99, 0xff, 0x12, 0x12, 0x12, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, - 0x00, 0x00, 0x00, 0xff, 0x02, 0x02, 0x02, 0xff, 0x26, 0x26, 0x26, 0xff, 0x96, 0x96, 0x96, 0xff, - 0xb5, 0xb5, 0xb5, 0xff, 0xb2, 0xb2, 0xb2, 0xff, 0xb1, 0xb1, 0xb0, 0xff, 0xaf, 0xaf, 0xae, 0xff, - 0xae, 0xae, 0xad, 0xff, 0x4d, 0x4d, 0x4c, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, - 0x16, 0x16, 0x16, 0xff, 0x16, 0x16, 0x16, 0xff, 0x6b, 0x6b, 0x6b, 0xff, 0x9f, 0x9f, 0x9f, 0xff, - 0xb9, 0xb9, 0xb8, 0xff, 0xb8, 0xb8, 0xb7, 0xff, 0xb8, 0xb8, 0xb7, 0xff, 0xb6, 0xb6, 0xb5, 0xff, - 0xb4, 0xb4, 0xb4, 0xff, 0xb2, 0xb2, 0xb2, 0xff, 0xb0, 0xb0, 0xb0, 0xff, 0xaf, 0xaf, 0xaf, 0xff, - 0xad, 0xad, 0xac, 0xff, 0x98, 0x98, 0x97, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0xff, 0x9d, 0x9d, 0x9d, 0xff, 0xaa, 0xaa, 0xa9, 0xff, - 0xac, 0xac, 0xab, 0xff, 0xb0, 0xb0, 0xaf, 0xff, 0xb8, 0xb8, 0xb8, 0xff, 0xb8, 0xb8, 0xb8, 0xff, - 0xb8, 0xb8, 0xb8, 0xff, 0xb7, 0xb7, 0xb7, 0xff, 0xb6, 0xb6, 0xb6, 0xff, 0xb5, 0xb5, 0xb4, 0xff, - 0xb4, 0xb4, 0xb3, 0xff, 0xb2, 0xb2, 0xb1, 0xff, 0xb1, 0xb1, 0xb0, 0xff, 0xaf, 0xaf, 0xae, 0xff, - 0xad, 0xad, 0xad, 0xff, 0xad, 0xad, 0xad, 0xff, 0x25, 0x25, 0x25, 0xff, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xff, 0xd3, 0xd3, 0xd3, 0xff, 0x7a, 0x7a, 0x7a, 0xff, 0x87, 0x87, 0x87, 0xff, - 0x9f, 0x9f, 0x9f, 0xff, 0xa8, 0xa8, 0xa7, 0xff, 0xb1, 0xb1, 0xb0, 0xff, 0xb4, 0xb4, 0xb3, 0xff, - 0xb5, 0xb5, 0xb5, 0xff, 0xb4, 0xb4, 0xb4, 0xff, 0xb4, 0xb4, 0xb4, 0xff, 0xb3, 0xb3, 0xb3, 0xff, - 0xb2, 0xb2, 0xb2, 0xff, 0xb1, 0xb1, 0xb1, 0xff, 0xb0, 0xb0, 0xaf, 0xff, 0xae, 0xae, 0xad, 0xff, - 0xae, 0xae, 0xad, 0xff, 0xad, 0xad, 0xac, 0xff, 0x87, 0x87, 0x86, 0xff, 0x00, 0x00, 0x00, 0xff, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, - 0xd5, 0xd5, 0xd5, 0xff, 0xe1, 0xe1, 0xe0, 0xff, 0x7f, 0x7f, 0x7f, 0xff, 0x6b, 0x6b, 0x6b, 0xff, - 0x80, 0x80, 0x80, 0xff, 0x9f, 0x9f, 0x9f, 0xff, 0xab, 0xab, 0xab, 0xff, 0xb0, 0xb0, 0xb0, 0xff, - 0xb2, 0xb2, 0xb1, 0xff, 0xb3, 0xb3, 0xb2, 0xff, 0xb1, 0xb1, 0xb0, 0xff, 0xb2, 0xb2, 0xb1, 0xff, - 0xaf, 0xaf, 0xaf, 0xff, 0xb0, 0xb0, 0xb0, 0xff, 0xae, 0xae, 0xae, 0xff, 0xad, 0xad, 0xad, 0xff, - 0xad, 0xad, 0xad, 0xff, 0xad, 0xad, 0xac, 0xff, 0xad, 0xad, 0xac, 0xff, 0x13, 0x13, 0x13, 0xff, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xa0, 0xa0, 0xa0, 0xff, - 0xdd, 0xdd, 0xdd, 0xff, 0xdb, 0xdb, 0xdb, 0xff, 0xcb, 0xcb, 0xcb, 0xff, 0x5a, 0x5a, 0x59, 0xff, - 0x78, 0x78, 0x78, 0xff, 0x99, 0x99, 0x98, 0xff, 0xa4, 0xa4, 0xa4, 0xff, 0xac, 0xac, 0xac, 0xff, - 0xaf, 0xaf, 0xaf, 0xff, 0xaf, 0xaf, 0xaf, 0xff, 0xaf, 0xaf, 0xaf, 0xff, 0xaf, 0xaf, 0xae, 0xff, - 0xaf, 0xaf, 0xae, 0xff, 0xae, 0xae, 0xae, 0xff, 0xad, 0xad, 0xad, 0xff, 0xad, 0xad, 0xad, 0xff, - 0xad, 0xad, 0xad, 0xff, 0xac, 0xac, 0xac, 0xff, 0xad, 0xad, 0xad, 0xff, 0x86, 0x86, 0x86, 0xff, - 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x19, 0x19, 0xff, 0xd4, 0xd4, 0xd4, 0xff, - 0xdf, 0xdf, 0xdf, 0xff, 0xdd, 0xdd, 0xdd, 0xff, 0xd3, 0xd3, 0xd3, 0xff, 0x52, 0x52, 0x52, 0xff, - 0x72, 0x72, 0x72, 0xff, 0x90, 0x90, 0x90, 0xff, 0x9d, 0x9d, 0x9c, 0xff, 0xa6, 0xa6, 0xa5, 0xff, - 0xac, 0xac, 0xac, 0xff, 0xad, 0xad, 0xad, 0xff, 0xad, 0xad, 0xad, 0xff, 0xad, 0xad, 0xad, 0xff, - 0xad, 0xad, 0xad, 0xff, 0xad, 0xad, 0xad, 0xff, 0xad, 0xad, 0xac, 0xff, 0xad, 0xad, 0xac, 0xff, - 0xac, 0xac, 0xab, 0xff, 0xad, 0xad, 0xac, 0xff, 0xad, 0xad, 0xac, 0xff, 0xad, 0xad, 0xad, 0xff, - 0x13, 0x13, 0x13, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xab, 0xab, 0xab, 0xff, 0xe4, 0xe4, 0xe4, 0xff, - 0xa7, 0xa7, 0xa6, 0xff, 0x62, 0x62, 0x61, 0xff, 0x4d, 0x4d, 0x4d, 0xff, 0x5d, 0x5d, 0x5d, 0xff, - 0x6f, 0x6f, 0x6f, 0xff, 0x8d, 0x8d, 0x8d, 0xff, 0x98, 0x98, 0x98, 0xff, 0x9e, 0x9e, 0x9e, 0xff, - 0xa5, 0xa5, 0xa5, 0xff, 0xac, 0xac, 0xab, 0xff, 0xac, 0xac, 0xac, 0xff, 0xae, 0xae, 0xad, 0xff, - 0xae, 0xae, 0xae, 0xff, 0xad, 0xad, 0xad, 0xff, 0xac, 0xac, 0xac, 0xff, 0xab, 0xab, 0xab, 0xff, - 0xac, 0xac, 0xac, 0xff, 0xad, 0xad, 0xac, 0xff, 0xae, 0xae, 0xad, 0xff, 0xaf, 0xaf, 0xae, 0xff, - 0x87, 0x87, 0x86, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x64, 0x64, 0x64, 0xff, 0x5c, 0x5c, 0x5c, 0xff, - 0x53, 0x53, 0x53, 0xff, 0x52, 0x52, 0x52, 0xff, 0x61, 0x61, 0x61, 0xff, 0x70, 0x70, 0x70, 0xff, - 0x74, 0x74, 0x74, 0xff, 0x8f, 0x8f, 0x8f, 0xff, 0x99, 0x99, 0x99, 0xff, 0x9d, 0x9d, 0x9d, 0xff, - 0xa7, 0xa7, 0xa7, 0xff, 0xac, 0xac, 0xac, 0xff, 0xac, 0xac, 0xac, 0xff, 0xaf, 0xaf, 0xae, 0xff, - 0xaf, 0xaf, 0xaf, 0xff, 0xaf, 0xaf, 0xae, 0xff, 0xae, 0xae, 0xad, 0xff, 0xac, 0xac, 0xac, 0xff, - 0xac, 0xac, 0xac, 0xff, 0xad, 0xad, 0xad, 0xff, 0xaf, 0xaf, 0xaf, 0xff, 0xb0, 0xb0, 0xb0, 0xff, - 0xb1, 0xb1, 0xb1, 0xff, 0x14, 0x14, 0x14, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x42, 0x42, 0x42, 0xff, 0x7f, 0x7f, 0x7f, 0xff, - 0x77, 0x77, 0x77, 0xff, 0x77, 0x77, 0x77, 0xff, 0x78, 0x78, 0x78, 0xff, 0x78, 0x78, 0x78, 0xff, - 0x8b, 0x8b, 0x8b, 0xff, 0x92, 0x92, 0x92, 0xff, 0x9e, 0x9e, 0x9d, 0xff, 0xa4, 0xa4, 0xa3, 0xff, - 0xad, 0xad, 0xac, 0xff, 0xb0, 0xb0, 0xb0, 0xff, 0xb1, 0xb1, 0xb1, 0xff, 0xb2, 0xb2, 0xb2, 0xff, - 0xb3, 0xb3, 0xb3, 0xff, 0xb2, 0xb2, 0xb2, 0xff, 0xb0, 0xb0, 0xaf, 0xff, 0xae, 0xae, 0xad, 0xff, - 0xaf, 0xaf, 0xae, 0xff, 0xb0, 0xb0, 0xaf, 0xff, 0xb1, 0xb1, 0xb1, 0xff, 0xb2, 0xb2, 0xb2, 0xff, - 0xb3, 0xb3, 0xb3, 0xff, 0x88, 0x88, 0x88, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x1a, 0x1a, 0xff, 0x8e, 0x8e, 0x8e, 0xff, - 0x98, 0x98, 0x97, 0xff, 0x82, 0x82, 0x81, 0xff, 0x8f, 0x8f, 0x8f, 0xff, 0x7f, 0x7f, 0x7f, 0xff, - 0x94, 0x94, 0x94, 0xff, 0x9c, 0x9c, 0x9c, 0xff, 0xa7, 0xa7, 0xa7, 0xff, 0xaf, 0xaf, 0xaf, 0xff, - 0xb1, 0xb1, 0xb1, 0xff, 0xb4, 0xb4, 0xb3, 0xff, 0xb6, 0xb6, 0xb5, 0xff, 0xb5, 0xb5, 0xb4, 0xff, - 0xb5, 0xb5, 0xb5, 0xff, 0xb4, 0xb4, 0xb4, 0xff, 0xb4, 0xb4, 0xb4, 0xff, 0xb2, 0xb2, 0xb2, 0xff, - 0xb2, 0xb2, 0xb2, 0xff, 0xb4, 0xb4, 0xb3, 0xff, 0xb5, 0xb5, 0xb4, 0xff, 0xb5, 0xb5, 0xb4, 0xff, - 0xb6, 0xb6, 0xb5, 0xff, 0xb7, 0xb7, 0xb6, 0xff, 0x27, 0x27, 0x27, 0xff, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0xff, 0xb1, 0xb1, 0xb1, 0xff, - 0xa8, 0xa8, 0xa8, 0xff, 0xa2, 0xa2, 0xa2, 0xff, 0x9f, 0x9f, 0x9f, 0xff, 0xa2, 0xa2, 0xa1, 0xff, - 0xa6, 0xa6, 0xa5, 0xff, 0xaa, 0xaa, 0xaa, 0xff, 0xaf, 0xaf, 0xaf, 0xff, 0xb2, 0xb2, 0xb2, 0xff, - 0xb6, 0xb6, 0xb6, 0xff, 0xb9, 0xb9, 0xb9, 0xff, 0xba, 0xba, 0xba, 0xff, 0xbb, 0xbb, 0xbb, 0xff, - 0xbb, 0xbb, 0xba, 0xff, 0xba, 0xba, 0xb9, 0xff, 0xba, 0xba, 0xb9, 0xff, 0xb8, 0xb8, 0xb8, 0xff, - 0xb8, 0xb8, 0xb8, 0xff, 0xb8, 0xb8, 0xb8, 0xff, 0xb8, 0xb8, 0xb8, 0xff, 0xb9, 0xb9, 0xb9, 0xff, - 0xb9, 0xb9, 0xb8, 0xff, 0xb9, 0xb9, 0xb8, 0xff, 0x8f, 0x8f, 0x8e, 0xff, 0x00, 0x00, 0x00, 0xff, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xbc, 0xbc, 0xbc, 0xff, - 0xb6, 0xb6, 0xb6, 0xff, 0xb4, 0xb4, 0xb4, 0xff, 0xb1, 0xb1, 0xb1, 0xff, 0xb1, 0xb1, 0xb1, 0xff, - 0xb0, 0xb0, 0xb0, 0xff, 0xb2, 0xb2, 0xb2, 0xff, 0xb6, 0xb6, 0xb5, 0xff, 0xba, 0xba, 0xb9, 0xff, - 0xbf, 0xbf, 0xbf, 0xff, 0xbe, 0xbe, 0xbe, 0xff, 0xbf, 0xbf, 0xbf, 0xff, 0xc0, 0xc0, 0xc0, 0xff, - 0xc0, 0xc0, 0xc0, 0xff, 0xbf, 0xbf, 0xbf, 0xff, 0xbf, 0xbf, 0xbf, 0xff, 0xbd, 0xbd, 0xbc, 0xff, - 0xbd, 0xbd, 0xbc, 0xff, 0xbd, 0xbd, 0xbc, 0xff, 0xbc, 0xbc, 0xbc, 0xff, 0xbc, 0xbc, 0xbc, 0xff, - 0xbc, 0xbc, 0xbc, 0xff, 0xbb, 0xbb, 0xbb, 0xff, 0xbb, 0xbb, 0xbb, 0xff, 0x29, 0x29, 0x29, 0xff, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xbb, 0xbb, 0xbb, 0xff, - 0xc2, 0xc2, 0xc2, 0xff, 0xbf, 0xbf, 0xbe, 0xff, 0xbb, 0xbb, 0xbb, 0xff, 0xb9, 0xb9, 0xb9, 0xff, - 0xb8, 0xb8, 0xb8, 0xff, 0xb9, 0xb9, 0xb9, 0xff, 0xbe, 0xbe, 0xbe, 0xff, 0xc3, 0xc3, 0xc3, 0xff, - 0xc4, 0xc4, 0xc4, 0xff, 0xc6, 0xc6, 0xc5, 0xff, 0xc8, 0xc8, 0xc7, 0xff, 0xc7, 0xc7, 0xc6, 0xff, - 0xc6, 0xc6, 0xc6, 0xff, 0xc5, 0xc5, 0xc5, 0xff, 0xc4, 0xc4, 0xc4, 0xff, 0xc3, 0xc3, 0xc3, 0xff, - 0xc2, 0xc2, 0xc2, 0xff, 0xc2, 0xc2, 0xc2, 0xff, 0xc2, 0xc2, 0xc1, 0xff, 0xc0, 0xc0, 0xbf, 0xff, - 0xc0, 0xc0, 0xbf, 0xff, 0xbf, 0xbf, 0xbf, 0xff, 0xbd, 0xbd, 0xbd, 0xff, 0xa8, 0xa8, 0xa8, 0xff, - 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xae, 0xae, 0xae, 0xff, - 0xcd, 0xcd, 0xcd, 0xff, 0xc8, 0xc8, 0xc8, 0xff, 0xc5, 0xc5, 0xc5, 0xff, 0xc4, 0xc4, 0xc4, 0xff, - 0xc2, 0xc2, 0xc1, 0xff, 0xc0, 0xc0, 0xc0, 0xff, 0xc6, 0xc6, 0xc6, 0xff, 0xc9, 0xc9, 0xc9, 0xff, - 0xca, 0xca, 0xca, 0xff, 0xcc, 0xcc, 0xcc, 0xff, 0xcc, 0xcc, 0xcc, 0xff, 0xcd, 0xcd, 0xcd, 0xff, - 0xcc, 0xcc, 0xcb, 0xff, 0xcb, 0xcb, 0xca, 0xff, 0xca, 0xca, 0xc9, 0xff, 0xc8, 0xc8, 0xc8, 0xff, - 0xc7, 0xc7, 0xc7, 0xff, 0xc6, 0xc6, 0xc6, 0xff, 0xc5, 0xc5, 0xc5, 0xff, 0xc4, 0xc4, 0xc4, 0xff, - 0xc4, 0xc4, 0xc4, 0xff, 0xc2, 0xc2, 0xc1, 0xff, 0xc1, 0xc1, 0xc0, 0xff, 0xc0, 0xc0, 0xbf, 0xff, - 0x7d, 0x7d, 0x7c, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x50, 0x50, 0x50, 0xff, - 0xd8, 0xd8, 0xd8, 0xff, 0xd4, 0xd4, 0xd4, 0xff, 0xd0, 0xd0, 0xd0, 0xff, 0xcd, 0xcd, 0xcd, 0xff, - 0xce, 0xce, 0xce, 0xff, 0xce, 0xce, 0xce, 0xff, 0xd0, 0xd0, 0xd0, 0xff, 0xd1, 0xd1, 0xd0, 0xff, - 0xd2, 0xd2, 0xd2, 0xff, 0xd2, 0xd2, 0xd2, 0xff, 0xd2, 0xd2, 0xd2, 0xff, 0xd1, 0xd1, 0xd1, 0xff, - 0xd1, 0xd1, 0xd1, 0xff, 0xd0, 0xd0, 0xd0, 0xff, 0xd0, 0xd0, 0xd0, 0xff, 0xce, 0xce, 0xcd, 0xff, - 0xcd, 0xcd, 0xcc, 0xff, 0xcc, 0xcc, 0xcb, 0xff, 0xc9, 0xc9, 0xc9, 0xff, 0xc8, 0xc8, 0xc8, 0xff, - 0xc6, 0xc6, 0xc6, 0xff, 0xc5, 0xc5, 0xc5, 0xff, 0xc4, 0xc4, 0xc4, 0xff, 0xc3, 0xc3, 0xc2, 0xff, - 0xc2, 0xc2, 0xc1, 0xff, 0x15, 0x15, 0x14, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, - 0xe3, 0xe3, 0xe3, 0xff, 0xe0, 0xe0, 0xdf, 0xff, 0xdb, 0xdb, 0xdb, 0xff, 0xd8, 0xd8, 0xd8, 0xff, - 0xd8, 0xd8, 0xd8, 0xff, 0xd8, 0xd8, 0xd8, 0xff, 0xd7, 0xd7, 0xd7, 0xff, 0xd8, 0xd8, 0xd8, 0xff, - 0xd9, 0xd9, 0xd9, 0xff, 0xd9, 0xd9, 0xd8, 0xff, 0xd8, 0xd8, 0xd7, 0xff, 0xd7, 0xd7, 0xd7, 0xff, - 0xd6, 0xd6, 0xd6, 0xff, 0xd4, 0xd4, 0xd4, 0xff, 0xd4, 0xd4, 0xd4, 0xff, 0xd2, 0xd2, 0xd2, 0xff, - 0xd0, 0xd0, 0xd0, 0xff, 0xce, 0xce, 0xce, 0xff, 0xcd, 0xcd, 0xcc, 0xff, 0xcc, 0xcc, 0xcb, 0xff, - 0xca, 0xca, 0xc9, 0xff, 0xc8, 0xc8, 0xc8, 0xff, 0xc7, 0xc7, 0xc7, 0xff, 0xc6, 0xc6, 0xc6, 0xff, - 0xc4, 0xc4, 0xc4, 0xff, 0x9e, 0x9e, 0x9e, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, - 0xdd, 0xdd, 0xdd, 0xff, 0xe8, 0xe8, 0xe8, 0xff, 0xe6, 0xe6, 0xe6, 0xff, 0xe3, 0xe3, 0xe3, 0xff, - 0xe1, 0xe1, 0xe0, 0xff, 0xdf, 0xdf, 0xdf, 0xff, 0xde, 0xde, 0xde, 0xff, 0xdd, 0xdd, 0xdd, 0xff, - 0xdd, 0xdd, 0xdd, 0xff, 0xdc, 0xdc, 0xdc, 0xff, 0xdc, 0xdc, 0xdc, 0xff, 0xdc, 0xdc, 0xdc, 0xff, - 0xdb, 0xdb, 0xda, 0xff, 0xdb, 0xdb, 0xda, 0xff, 0xd9, 0xd9, 0xd8, 0xff, 0xd6, 0xd6, 0xd6, 0xff, - 0xd4, 0xd4, 0xd4, 0xff, 0xd2, 0xd2, 0xd2, 0xff, 0xd1, 0xd1, 0xd1, 0xff, 0xcf, 0xcf, 0xcf, 0xff, - 0xce, 0xce, 0xce, 0xff, 0xcc, 0xcc, 0xcb, 0xff, 0xcb, 0xcb, 0xca, 0xff, 0xc9, 0xc9, 0xc8, 0xff, - 0xc6, 0xc6, 0xc6, 0xff, 0xc4, 0xc4, 0xc4, 0xff, 0x2a, 0x2a, 0x2a, 0xff, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, - 0xc9, 0xc9, 0xc9, 0xff, 0xf0, 0xf0, 0xf0, 0xff, 0xec, 0xec, 0xec, 0xff, 0xe9, 0xe9, 0xe9, 0xff, - 0xe6, 0xe6, 0xe6, 0xff, 0xe4, 0xe4, 0xe4, 0xff, 0xe3, 0xe3, 0xe3, 0xff, 0xe2, 0xe2, 0xe1, 0xff, - 0xe0, 0xe0, 0xe0, 0xff, 0xe0, 0xe0, 0xe0, 0xff, 0xe0, 0xe0, 0xe0, 0xff, 0xdf, 0xdf, 0xdf, 0xff, - 0xdf, 0xdf, 0xdf, 0xff, 0xde, 0xde, 0xde, 0xff, 0xdd, 0xdd, 0xdd, 0xff, 0xdb, 0xdb, 0xda, 0xff, - 0xd9, 0xd9, 0xd8, 0xff, 0xd7, 0xd7, 0xd6, 0xff, 0xd4, 0xd4, 0xd4, 0xff, 0xd2, 0xd2, 0xd2, 0xff, - 0xd1, 0xd1, 0xd1, 0xff, 0xcf, 0xcf, 0xcf, 0xff, 0xcd, 0xcd, 0xcd, 0xff, 0xcb, 0xcb, 0xcb, 0xff, - 0xc9, 0xc9, 0xc8, 0xff, 0xc7, 0xc7, 0xc6, 0xff, 0xae, 0xae, 0xad, 0xff, 0x00, 0x00, 0x00, 0xff, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, - 0x7b, 0x7b, 0x7b, 0xff, 0xf4, 0xf4, 0xf4, 0xff, 0xf1, 0xf1, 0xf1, 0xff, 0xee, 0xee, 0xee, 0xff, - 0xeb, 0xeb, 0xeb, 0xff, 0xe9, 0xe9, 0xe9, 0xff, 0xe7, 0xe7, 0xe7, 0xff, 0xe6, 0xe6, 0xe6, 0xff, - 0xe5, 0xe5, 0xe5, 0xff, 0xe5, 0xe5, 0xe5, 0xff, 0xe4, 0xe4, 0xe3, 0xff, 0xe3, 0xe3, 0xe3, 0xff, - 0xe2, 0xe2, 0xe2, 0xff, 0xe1, 0xe1, 0xe1, 0xff, 0xe0, 0xe0, 0xe0, 0xff, 0xde, 0xde, 0xde, 0xff, - 0xdc, 0xdc, 0xdc, 0xff, 0xda, 0xda, 0xda, 0xff, 0xd8, 0xd8, 0xd7, 0xff, 0xd6, 0xd6, 0xd5, 0xff, - 0xd4, 0xd4, 0xd3, 0xff, 0xd1, 0xd1, 0xd1, 0xff, 0xcf, 0xcf, 0xcf, 0xff, 0xcd, 0xcd, 0xcd, 0xff, - 0xcb, 0xcb, 0xcb, 0xff, 0xc9, 0xc9, 0xc9, 0xff, 0xc7, 0xc7, 0xc7, 0xff, 0xa0, 0xa0, 0x9f, 0xff, - 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x1c, 0x1c, 0x1c, 0xff, 0xf9, 0xf9, 0xf9, 0xff, 0xf6, 0xf6, 0xf6, 0xff, 0xf3, 0xf3, 0xf3, 0xff, - 0xf1, 0xf1, 0xf0, 0xff, 0xed, 0xed, 0xed, 0xff, 0xec, 0xec, 0xec, 0xff, 0xea, 0xea, 0xea, 0xff, - 0xe9, 0xe9, 0xe9, 0xff, 0xe8, 0xe8, 0xe8, 0xff, 0xe7, 0xe7, 0xe7, 0xff, 0xe7, 0xe7, 0xe7, 0xff, - 0xe6, 0xe6, 0xe6, 0xff, 0xe5, 0xe5, 0xe4, 0xff, 0xe2, 0xe2, 0xe2, 0xff, 0xe0, 0xe0, 0xe0, 0xff, - 0xde, 0xde, 0xde, 0xff, 0xdc, 0xdc, 0xdc, 0xff, 0xda, 0xda, 0xda, 0xff, 0xd8, 0xd8, 0xd8, 0xff, - 0xd6, 0xd6, 0xd6, 0xff, 0xd4, 0xd4, 0xd3, 0xff, 0xd2, 0xd2, 0xd1, 0xff, 0xd0, 0xd0, 0xcf, 0xff, - 0xcd, 0xcd, 0xcd, 0xff, 0xcb, 0xcb, 0xcb, 0xff, 0xc4, 0xc4, 0xc4, 0xff, 0x90, 0x90, 0x90, 0xff, - 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xff, 0xdb, 0xdb, 0xdb, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0xf7, 0xf7, 0xf7, 0xff, - 0xf5, 0xf5, 0xf5, 0xff, 0xf3, 0xf3, 0xf3, 0xff, 0xf1, 0xf1, 0xf1, 0xff, 0xef, 0xef, 0xee, 0xff, - 0xed, 0xed, 0xed, 0xff, 0xec, 0xec, 0xec, 0xff, 0xeb, 0xeb, 0xeb, 0xff, 0xea, 0xea, 0xea, 0xff, - 0xe8, 0xe8, 0xe8, 0xff, 0xe7, 0xe7, 0xe7, 0xff, 0xe5, 0xe5, 0xe5, 0xff, 0xe3, 0xe3, 0xe3, 0xff, - 0xe1, 0xe1, 0xe0, 0xff, 0xdf, 0xdf, 0xde, 0xff, 0xdc, 0xdc, 0xdc, 0xff, 0xda, 0xda, 0xda, 0xff, - 0xd8, 0xd8, 0xd8, 0xff, 0xd6, 0xd6, 0xd6, 0xff, 0xd4, 0xd4, 0xd4, 0xff, 0xd2, 0xd2, 0xd2, 0xff, - 0xd0, 0xd0, 0xcf, 0xff, 0x92, 0x92, 0x92, 0xff, 0x16, 0x16, 0x16, 0xff, 0x00, 0x00, 0x00, 0xff, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xff, 0xba, 0xba, 0xba, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0xfb, 0xfb, 0xfb, 0xff, - 0xf9, 0xf9, 0xf9, 0xff, 0xf7, 0xf7, 0xf7, 0xff, 0xf5, 0xf5, 0xf5, 0xff, 0xf3, 0xf3, 0xf3, 0xff, - 0xf2, 0xf2, 0xf2, 0xff, 0xf0, 0xf0, 0xf0, 0xff, 0xef, 0xef, 0xee, 0xff, 0xed, 0xed, 0xed, 0xff, - 0xeb, 0xeb, 0xeb, 0xff, 0xe9, 0xe9, 0xe9, 0xff, 0xe7, 0xe7, 0xe7, 0xff, 0xe5, 0xe5, 0xe5, 0xff, - 0xe3, 0xe3, 0xe3, 0xff, 0xe1, 0xe1, 0xe1, 0xff, 0xdf, 0xdf, 0xdf, 0xff, 0xdd, 0xdd, 0xdc, 0xff, - 0xdb, 0xdb, 0xda, 0xff, 0xd8, 0xd8, 0xd8, 0xff, 0xd6, 0xd6, 0xd6, 0xff, 0xad, 0xad, 0xad, 0xff, - 0x17, 0x17, 0x17, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x38, 0x38, 0x38, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xfd, 0xfd, 0xfd, 0xff, - 0xfd, 0xfd, 0xfd, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0xf8, 0xf8, 0xf8, 0xff, 0xf6, 0xf6, 0xf6, 0xff, - 0xf5, 0xf5, 0xf5, 0xff, 0xf3, 0xf3, 0xf3, 0xff, 0xf2, 0xf2, 0xf2, 0xff, 0xf0, 0xf0, 0xf0, 0xff, - 0xee, 0xee, 0xee, 0xff, 0xec, 0xec, 0xeb, 0xff, 0xe9, 0xe9, 0xe9, 0xff, 0xe7, 0xe7, 0xe7, 0xff, - 0xe5, 0xe5, 0xe5, 0xff, 0xe3, 0xe3, 0xe3, 0xff, 0xe1, 0xe1, 0xe1, 0xff, 0xdf, 0xdf, 0xdf, 0xff, - 0xdd, 0xdd, 0xdd, 0xff, 0xb0, 0xb0, 0xaf, 0xff, 0x17, 0x17, 0x17, 0xff, 0x00, 0x00, 0x00, 0xff, - 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xfe, 0xfe, 0xfe, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0xfb, 0xfb, 0xfa, 0xff, - 0xf8, 0xf8, 0xf8, 0xff, 0xf6, 0xf6, 0xf6, 0xff, 0xf4, 0xf4, 0xf4, 0xff, 0xf2, 0xf2, 0xf2, 0xff, - 0xf0, 0xf0, 0xf0, 0xff, 0xee, 0xee, 0xee, 0xff, 0xec, 0xec, 0xec, 0xff, 0xea, 0xea, 0xea, 0xff, - 0xe8, 0xe8, 0xe7, 0xff, 0xe6, 0xe6, 0xe5, 0xff, 0xd5, 0xd5, 0xd5, 0xff, 0xa3, 0xa3, 0xa3, 0xff, - 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, - 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xbe, 0xbe, 0xbe, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xfd, 0xff, - 0xfb, 0xfb, 0xfb, 0xff, 0xf9, 0xf9, 0xf9, 0xff, 0xf7, 0xf7, 0xf6, 0xff, 0xf4, 0xf4, 0xf4, 0xff, - 0xf2, 0xf2, 0xf2, 0xff, 0xf0, 0xf0, 0xf0, 0xff, 0xee, 0xee, 0xee, 0xff, 0xec, 0xec, 0xec, 0xff, - 0xc6, 0xc6, 0xc6, 0xff, 0x96, 0x96, 0x96, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, - 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, - 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, - 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x7d, 0x7d, 0x7d, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xfd, 0xfd, 0xfd, 0xff, 0xfb, 0xfb, 0xfb, 0xff, 0xf9, 0xf9, 0xf9, 0xff, 0xf7, 0xf7, 0xf7, 0xff, - 0xf5, 0xf5, 0xf5, 0xff, 0xf3, 0xf3, 0xf2, 0xff, 0xa0, 0xa0, 0xa0, 0xff, 0x34, 0x34, 0x34, 0xff, - 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, - 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, - 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xfb, 0xfb, 0xfb, 0xff, 0xcf, 0xcf, 0xcf, 0xff, - 0x8f, 0x8f, 0x8f, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, - 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, - 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, - 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xbe, 0xbe, 0xbe, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xe2, 0xe2, 0xe2, 0xff, 0xa7, 0xa7, 0xa7, 0xff, 0x37, 0x37, 0x37, 0xff, 0x00, 0x00, 0x00, 0xff, - 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, - 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, - 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x38, 0x38, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xe2, 0xe2, 0xe2, 0xff, 0xbb, 0xbb, 0xbb, 0xff, 0x7d, 0x7d, 0x7d, 0xff, - 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, - 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, - 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, - 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, - 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, - 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; diff --git a/libnautilus-extensions/nautilus-default-file-icon.h b/libnautilus-extensions/nautilus-default-file-icon.h deleted file mode 100644 index c35e909e0..000000000 --- a/libnautilus-extensions/nautilus-default-file-icon.h +++ /dev/null @@ -1,32 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- - - Default file icon used by the icon factory. - - 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. - - Author: Darin Adler <darin@eazel.com> -*/ - -#ifndef NAUTILUS_DEFAULT_FILE_ICON_H -#define NAUTILUS_DEFAULT_FILE_ICON_H - -extern const int nautilus_default_file_icon_width; -extern const int nautilus_default_file_icon_height; -extern const unsigned char nautilus_default_file_icon[]; - -#endif /* NAUTILUS_DEFAULT_FILE_ICON_H */ diff --git a/libnautilus-extensions/nautilus-directory-async.c b/libnautilus-extensions/nautilus-directory-async.c deleted file mode 100644 index 5d76ca8f3..000000000 --- a/libnautilus-extensions/nautilus-directory-async.c +++ /dev/null @@ -1,3078 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- - - nautilus-directory-async.c: Nautilus directory model state machine. - - Copyright (C) 1999, 2000, 2001 Eazel, Inc. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public - License along with this program; if not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. - - Author: Darin Adler <darin@eazel.com> -*/ - -#include <config.h> - -#include "nautilus-metafile.h" -#include "nautilus-directory-metafile.h" -#include "nautilus-directory-notify.h" -#include "nautilus-directory-private.h" -#include "nautilus-file-attributes.h" -#include "nautilus-file-private.h" -#include <eel/eel-glib-extensions.h> -#include "nautilus-global-preferences.h" -#include "nautilus-link.h" -#include "nautilus-search-uri.h" -#include <eel/eel-string.h> -#include <ctype.h> -#include <gnome-xml/parser.h> -#include <gnome-xml/xmlmemory.h> -#include <gtk/gtkmain.h> -#include <stdlib.h> -#include <stdio.h> - -/* turn this on to see messages about each load_directory call: */ -#if 0 -#define DEBUG_LOAD_DIRECTORY -#endif - -/* turn this on to check if async. job calls are balanced */ -#if 0 -#define DEBUG_ASYNC_JOBS -#endif - -/* turn this on to log things starting and stopping */ -#if 0 -#define DEBUG_START_STOP -#endif - - -#define DIRECTORY_LOAD_ITEMS_PER_CALLBACK 32 - -/* Keep async. jobs down to this number for all directories. */ -#define MAX_ASYNC_JOBS 10 - -struct TopLeftTextReadState { - NautilusFile *file; - EelReadFileHandle *handle; -}; - -struct ActivationURIReadState { - NautilusFile *file; - EelReadFileHandle *handle; -}; - -typedef struct { - NautilusFile *file; /* Which file, NULL means all. */ - union { - NautilusDirectoryCallback directory; - NautilusFileCallback file; - } callback; - gpointer callback_data; - Request request; -} ReadyCallback; - -typedef struct { - NautilusFile *file; /* Which file, NULL means all. */ - gboolean monitor_hidden_files; /* defines whether "all" includes hidden files */ - gboolean monitor_backup_files; /* defines whether "all" includes backup files */ - gconstpointer client; - Request request; -} Monitor; - -typedef gboolean (* RequestCheck) (const Request *); -typedef gboolean (* FileCheck) (NautilusFile *); - -/* Current number of async. jobs. */ -static int async_job_count; -static GHashTable *waiting_directories; -#ifdef DEBUG_ASYNC_JOBS -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); - -/* Some helpers for case-insensitive strings. - * Move to nautilus-glib-extensions? - */ - -static gboolean -istr_equal (gconstpointer v, gconstpointer v2) -{ - return g_strcasecmp (v, v2) == 0; -} - -static guint -istr_hash (gconstpointer key) -{ - const char *p; - guint h; - - h = 0; - for (p = key; *p != '\0'; p++) { - h = (h << 5) - h + tolower ((guchar) *p); - } - - return h; -} - -static GHashTable * -istr_set_new (void) -{ - return g_hash_table_new (istr_hash, istr_equal); -} - -static void -istr_set_insert (GHashTable *table, const char *istr) -{ - char *key; - - if (g_hash_table_lookup (table, istr) == NULL) { - key = g_strdup (istr); - g_hash_table_insert (table, key, key); - } -} - -static void -add_istr_to_list (gpointer key, gpointer value, gpointer callback_data) -{ - GList **list; - - list = callback_data; - *list = g_list_prepend (*list, g_strdup (key)); -} - -static GList * -istr_set_get_as_list (GHashTable *table) -{ - GList *list; - - list = NULL; - g_hash_table_foreach (table, add_istr_to_list, &list); - return list; -} - -static void -istr_set_destroy (GHashTable *table) -{ - eel_g_hash_table_destroy_deep (table); -} - -/* Start a job. This is really just a way of limiting the number of - * async. requests that we issue at any given time. Without this, the - * number of requests is unbounded. - */ -static gboolean -async_job_start (NautilusDirectory *directory, - const char *job) -{ -#ifdef DEBUG_ASYNC_JOBS - char *key; -#endif - -#ifdef DEBUG_START_STOP - g_message ("starting %s in %s", job, directory->details->uri); -#endif - - g_assert (async_job_count >= 0); - g_assert (async_job_count <= MAX_ASYNC_JOBS); - - if (async_job_count >= MAX_ASYNC_JOBS) { - if (waiting_directories == NULL) { - waiting_directories = eel_g_hash_table_new_free_at_exit - (NULL, NULL, - "nautilus-directory-async.c: waiting_directories"); - } - - g_hash_table_insert (waiting_directories, - directory, - directory); - - return FALSE; - } - -#ifdef DEBUG_ASYNC_JOBS - if (async_jobs == NULL) { - async_jobs = eel_g_hash_table_new_free_at_exit - (g_str_hash, g_str_equal, - "nautilus-directory-async.c: async_jobs"); - } - key = g_strconcat (directory->details->uri, ": ", job, NULL); - if (g_hash_table_lookup (async_jobs, key) != NULL) { - g_warning ("same job twice: %s in %s", - job, - directory->details->uri); - } - g_hash_table_insert (async_jobs, key, directory); -#endif - - async_job_count += 1; - return TRUE; -} - -/* End a job. */ -static void -async_job_end (NautilusDirectory *directory, - const char *job) -{ -#ifdef DEBUG_ASYNC_JOBS - char *key; - gpointer table_key, value; -#endif - -#ifdef DEBUG_START_STOP - g_message ("stopping %s in %s", job, directory->details->uri); -#endif - - g_assert (async_job_count > 0); - -#ifdef DEBUG_ASYNC_JOBS - g_assert (async_jobs != NULL); - key = g_strconcat (directory->details->uri, ": ", job, NULL); - if (!g_hash_table_lookup_extended (async_jobs, key, &table_key, &value)) { - g_warning ("ending job we didn't start: %s in %s", - job, - directory->details->uri); - } else { - g_hash_table_remove (async_jobs, key); - g_free (table_key); - } - g_free (key); -#endif - - async_job_count -= 1; -} - -/* Helper to get one value from a hash table. */ -static void -get_one_value_callback (gpointer key, gpointer value, gpointer callback_data) -{ - gpointer *returned_value; - - returned_value = callback_data; - *returned_value = value; -} - -/* return a single value from a hash table. */ -static gpointer -get_one_value (GHashTable *table) -{ - gpointer value; - - value = NULL; - if (table != NULL) { - g_hash_table_foreach (table, get_one_value_callback, &value); - } - return value; -} - -/* Wake up directories that are "blocked" as long as there are job - * slots available. - */ -static void -async_job_wake_up (void) -{ - static gboolean already_waking_up = FALSE; - gpointer value; - - g_assert (async_job_count >= 0); - g_assert (async_job_count <= MAX_ASYNC_JOBS); - - if (already_waking_up) { - return; - } - - already_waking_up = TRUE; - while (async_job_count < MAX_ASYNC_JOBS) { - value = get_one_value (waiting_directories); - if (value == NULL) { - break; - } - g_hash_table_remove (waiting_directories, value); - nautilus_directory_async_state_changed - (NAUTILUS_DIRECTORY (value)); - } - already_waking_up = FALSE; -} - -static void -directory_count_cancel (NautilusDirectory *directory) -{ - if (directory->details->count_in_progress != NULL) { - gnome_vfs_async_cancel (directory->details->count_in_progress); - directory->details->count_file = NULL; - directory->details->count_in_progress = NULL; - - async_job_end (directory, "directory count"); - } -} - -static void -deep_count_cancel (NautilusDirectory *directory) -{ - if (directory->details->deep_count_in_progress != NULL) { - g_assert (NAUTILUS_IS_FILE (directory->details->deep_count_file)); - - gnome_vfs_async_cancel (directory->details->deep_count_in_progress); - - directory->details->deep_count_file->details->deep_counts_status = NAUTILUS_REQUEST_NOT_STARTED; - - directory->details->deep_count_file = NULL; - directory->details->deep_count_in_progress = NULL; - g_free (directory->details->deep_count_uri); - directory->details->deep_count_uri = NULL; - eel_g_list_free_deep (directory->details->deep_count_subdirectories); - directory->details->deep_count_subdirectories = NULL; - - async_job_end (directory, "deep count"); - } -} - -static void -mime_list_cancel (NautilusDirectory *directory) -{ - if (directory->details->mime_list_in_progress != NULL) { - g_assert (NAUTILUS_IS_FILE (directory->details->mime_list_file)); - - gnome_vfs_async_cancel (directory->details->mime_list_in_progress); - istr_set_destroy (directory->details->mime_list_hash); - - directory->details->mime_list_file = NULL; - directory->details->mime_list_in_progress = NULL; - directory->details->mime_list_hash = NULL; - - async_job_end (directory, "MIME list"); - } -} - -static void -top_left_cancel (NautilusDirectory *directory) -{ - if (directory->details->top_left_read_state != NULL) { - eel_read_file_cancel (directory->details->top_left_read_state->handle); - g_free (directory->details->top_left_read_state); - directory->details->top_left_read_state = NULL; - - async_job_end (directory, "top left"); - } -} - -static void -activation_uri_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"); - } -} - -static void -file_info_cancel (NautilusDirectory *directory) -{ - if (directory->details->get_info_in_progress != NULL) { - gnome_vfs_async_cancel (directory->details->get_info_in_progress); - directory->details->get_info_file = NULL; - directory->details->get_info_in_progress = NULL; - - async_job_end (directory, "file info"); - } -} - -static int -monitor_key_compare (gconstpointer a, - gconstpointer data) -{ - const Monitor *monitor; - const Monitor *compare_monitor; - - monitor = a; - compare_monitor = data; - - if (monitor->client < compare_monitor->client) { - return -1; - } - if (monitor->client > compare_monitor->client) { - return +1; - } - - if (monitor->file < compare_monitor->file) { - return -1; - } - if (monitor->file > compare_monitor->file) { - return +1; - } - - return 0; -} - -static GList * -find_monitor (NautilusDirectory *directory, - NautilusFile *file, - gconstpointer client) -{ - Monitor monitor; - - monitor.client = client; - monitor.file = file; - - return g_list_find_custom (directory->details->monitor_list, - &monitor, - monitor_key_compare); -} - -static int -monitor_file_compare (gconstpointer a, - gconstpointer data) -{ - const Monitor *monitor; - NautilusFile *file; - - monitor = a; - file = (NautilusFile *) data; - - if (monitor->file < file) { - return -1; - } - if (monitor->file > file) { - return +1; - } - - return 0; -} - -static gboolean -find_any_monitor (NautilusDirectory *directory, - NautilusFile *file) -{ - return g_list_find_custom (directory->details->monitor_list, - file, - monitor_file_compare) != NULL; -} - -static void -remove_monitor_link (NautilusDirectory *directory, - GList *link) -{ - if (link != NULL) { - directory->details->monitor_list = - g_list_remove_link (directory->details->monitor_list, link); - g_free (link->data); - g_list_free_1 (link); - } -} - -static void -remove_monitor (NautilusDirectory *directory, - NautilusFile *file, - gconstpointer client) -{ - remove_monitor_link (directory, find_monitor (directory, file, client)); -} - -void -nautilus_directory_set_up_request (Request *request, - GList *file_attributes) -{ - memset (request, 0, sizeof (*request)); - - request->directory_count = g_list_find_custom - (file_attributes, - NAUTILUS_FILE_ATTRIBUTE_DIRECTORY_ITEM_COUNT, - eel_strcmp_compare_func) != NULL; - request->deep_count = g_list_find_custom - (file_attributes, - NAUTILUS_FILE_ATTRIBUTE_DEEP_COUNTS, - eel_strcmp_compare_func) != NULL; - request->mime_list = g_list_find_custom - (file_attributes, - NAUTILUS_FILE_ATTRIBUTE_DIRECTORY_ITEM_MIME_TYPES, - eel_strcmp_compare_func) != NULL; - request->file_info = g_list_find_custom - (file_attributes, - NAUTILUS_FILE_ATTRIBUTE_MIME_TYPE, - eel_strcmp_compare_func) != NULL; - request->file_info |= g_list_find_custom - (file_attributes, - NAUTILUS_FILE_ATTRIBUTE_IS_DIRECTORY, - eel_strcmp_compare_func) != NULL; - request->file_info |= g_list_find_custom - (file_attributes, - NAUTILUS_FILE_ATTRIBUTE_CAPABILITIES, - eel_strcmp_compare_func) != NULL; - request->file_info |= g_list_find_custom - (file_attributes, - NAUTILUS_FILE_ATTRIBUTE_FILE_TYPE, - eel_strcmp_compare_func) != NULL; - - if (g_list_find_custom (file_attributes, - NAUTILUS_FILE_ATTRIBUTE_TOP_LEFT_TEXT, - eel_strcmp_compare_func) != NULL) { - request->top_left_text = TRUE; - request->file_info = TRUE; - } - - if (g_list_find_custom (file_attributes, - NAUTILUS_FILE_ATTRIBUTE_ACTIVATION_URI, - eel_strcmp_compare_func) != NULL) { - request->file_info = TRUE; - request->activation_uri = TRUE; - } - - request->metafile |= g_list_find_custom - (file_attributes, - NAUTILUS_FILE_ATTRIBUTE_METADATA, - eel_strcmp_compare_func) != NULL; - - /* FIXME bugzilla.eazel.com 2435: - * Some file attributes are really pieces of metadata. - * This is a confusing/broken design, since other metadata - * pieces are handled separately from file attributes. There - * are many ways this could be changed, ranging from making - * all metadata pieces have corresponding file attributes, to - * making a single file attribute that means "get all metadata", - * to making metadata keys be acceptable as file attributes - * directly (would need some funky char trick to prevent - * namespace collisions). - */ - request->metafile |= g_list_find_custom - (file_attributes, - NAUTILUS_FILE_ATTRIBUTE_CUSTOM_ICON, - eel_strcmp_compare_func) != NULL; -} - -static gboolean -is_tentative (gpointer data, gpointer callback_data) -{ - NautilusFile *file; - - g_assert (callback_data == NULL); - - file = NAUTILUS_FILE (data); - return file->details->info == NULL; -} - -static GList * -get_non_tentative_file_list (NautilusDirectory *directory) -{ - GList *tentative_files, *non_tentative_files; - - tentative_files = eel_g_list_partition - (g_list_copy (directory->details->file_list), - is_tentative, NULL, &non_tentative_files); - g_list_free (tentative_files); - - nautilus_file_list_ref (non_tentative_files); - return non_tentative_files; -} - -void -nautilus_directory_monitor_add_internal (NautilusDirectory *directory, - NautilusFile *file, - gconstpointer client, - gboolean monitor_hidden_files, - gboolean monitor_backup_files, - GList *file_attributes) -{ - Monitor *monitor; - GList *file_list; - char *file_uri; - - g_assert (NAUTILUS_IS_DIRECTORY (directory)); - - /* Replace any current monitor for this client/file pair. */ - remove_monitor (directory, file, client); - - /* Add the new monitor. */ - monitor = g_new (Monitor, 1); - monitor->file = file; - monitor->monitor_hidden_files = monitor_hidden_files; - monitor->monitor_backup_files = monitor_backup_files; - monitor->client = client; - nautilus_directory_set_up_request (&monitor->request, file_attributes); - - monitor->request.file_list = file == NULL; - directory->details->monitor_list = - g_list_prepend (directory->details->monitor_list, monitor); - - /* Re-send the "files_added" signal for this set of files. - * Old monitorers already know about them, but it's harmless - * to hear about the same files again. - */ - if (file == NULL) { - file_list = get_non_tentative_file_list (directory); - if (file_list != NULL) { - nautilus_directory_emit_files_added - (directory, file_list); - nautilus_file_list_free (file_list); - } - } - - /* Start the "real" monitoring (FAM or whatever). */ - if (file == NULL) { - if (directory->details->monitor == NULL) { - directory->details->monitor = nautilus_monitor_directory (directory->details->uri); - } - } else { - if (file->details->monitor == NULL) { - file_uri = nautilus_file_get_uri (file); - file->details->monitor = nautilus_monitor_file (file_uri); - g_free (file_uri); - } - } - - /* We could just call update_metadata_monitors here, but we can be smarter - * since we know what monitor was just added. - */ - if (monitor->request.metafile && directory->details->metafile_monitor == NULL) { - nautilus_directory_register_metadata_monitor (directory); - } - - /* Kick off I/O. */ - nautilus_directory_async_state_changed (directory); -} - -static void -set_file_unconfirmed (NautilusFile *file, gboolean unconfirmed) -{ - NautilusDirectory *directory; - - g_assert (NAUTILUS_IS_FILE (file)); - g_assert (unconfirmed == FALSE || unconfirmed == TRUE); - - if (file->details->unconfirmed == unconfirmed) { - return; - } - file->details->unconfirmed = unconfirmed; - - directory = file->details->directory; - if (unconfirmed) { - directory->details->confirmed_file_count--; - } else { - directory->details->confirmed_file_count++; - } -} - -static gboolean show_hidden_files = TRUE; -static gboolean show_backup_files = TRUE; - -static void -show_hidden_files_changed_callback (gpointer callback_data) -{ - show_hidden_files = nautilus_preferences_get_boolean (NAUTILUS_PREFERENCES_SHOW_HIDDEN_FILES); -} - -static void -show_backup_files_changed_callback (gpointer callback_data) -{ - show_backup_files = nautilus_preferences_get_boolean (NAUTILUS_PREFERENCES_SHOW_BACKUP_FILES); -} - -static GnomeVFSDirectoryFilterOptions -get_filter_options_for_directory_count (void) -{ - static gboolean show_hidden_files_changed_callback_installed = FALSE; - static gboolean show_backup_files_changed_callback_installed = FALSE; - GnomeVFSDirectoryFilterOptions filter_options; - - filter_options = GNOME_VFS_DIRECTORY_FILTER_NOSELFDIR - | GNOME_VFS_DIRECTORY_FILTER_NOPARENTDIR; - - /* Add the callback once for the life of our process */ - if (!show_hidden_files_changed_callback_installed) { - nautilus_preferences_add_callback (NAUTILUS_PREFERENCES_SHOW_HIDDEN_FILES, - show_hidden_files_changed_callback, - NULL); - show_hidden_files_changed_callback_installed = TRUE; - - /* Peek for the first time */ - show_hidden_files_changed_callback (NULL); - } - - /* Add the callback once for the life of our process */ - if (!show_backup_files_changed_callback_installed) { - nautilus_preferences_add_callback (NAUTILUS_PREFERENCES_SHOW_BACKUP_FILES, - show_backup_files_changed_callback, - NULL); - show_backup_files_changed_callback_installed = TRUE; - - /* Peek for the first time */ - show_backup_files_changed_callback (NULL); - } - - if (!show_hidden_files) { - filter_options |= GNOME_VFS_DIRECTORY_FILTER_NODOTFILES; - } - if (!show_backup_files) { - filter_options |= GNOME_VFS_DIRECTORY_FILTER_NOBACKUPFILES; - } - - return filter_options; -} - -static void -load_directory_state_destroy (NautilusDirectory *directory) -{ - NautilusFile *file; - - if (directory->details->load_mime_list_hash != NULL) { - istr_set_destroy (directory->details->load_mime_list_hash); - directory->details->load_mime_list_hash = NULL; - } - - file = directory->details->load_directory_file; - if (file != NULL) { - directory->details->load_directory_file = NULL; - - file->details->loading_directory = FALSE; - if (file->details->directory != directory) { - nautilus_directory_async_state_changed (file->details->directory); - } - - nautilus_file_unref (file); - } - - gnome_vfs_directory_filter_destroy (directory->details->load_file_count_filter); - directory->details->load_file_count_filter = NULL; -} - -static void -load_directory_done (NautilusDirectory *directory) -{ - load_directory_state_destroy (directory); - nautilus_directory_async_state_changed (directory); -} - -static gboolean -dequeue_pending_idle_callback (gpointer callback_data) -{ - NautilusDirectory *directory; - GList *pending_file_info; - GList *node, *next; - NautilusFile *file; - GList *changed_files, *added_files; - GnomeVFSFileInfo *file_info; - - directory = NAUTILUS_DIRECTORY (callback_data); - - nautilus_directory_ref (directory); - - directory->details->dequeue_pending_idle_id = 0; - - /* Handle the files in the order we saw them. */ - pending_file_info = g_list_reverse (directory->details->pending_file_info); - directory->details->pending_file_info = NULL; - - /* If we are no longer monitoring, then throw away these. */ - if (!nautilus_directory_is_file_list_monitored (directory)) { - load_directory_done (directory); - goto drain; - } - - added_files = NULL; - changed_files = NULL; - - /* Build a list of NautilusFile objects. */ - for (node = pending_file_info; node != NULL; node = node->next) { - file_info = node->data; - - /* Update the file count. */ - /* FIXME bugzilla.eazel.com 5063: This could count a file twice if we get it - * from both load_directory and from - * new_files_callback. Not too hard to fix by moving - * this into the actual callback instead of waiting - * for the idle function. - */ - if (gnome_vfs_directory_filter_apply (directory->details->load_file_count_filter, - file_info)) { - directory->details->load_file_count += 1; - } - - /* Add the MIME type to the set. */ - if ((file_info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_MIME_TYPE) != 0 - && directory->details->load_mime_list_hash != NULL) { - istr_set_insert (directory->details->load_mime_list_hash, - file_info->mime_type); - } - - /* check if the file already exists */ - file = nautilus_directory_find_file_by_name (directory, file_info->name); - if (file != NULL) { - /* file already exists, check if it changed */ - set_file_unconfirmed (file, FALSE); - if (nautilus_file_update_info (file, file_info)) { - /* File changed, notify about the change. */ - nautilus_file_ref (file); - changed_files = g_list_prepend (changed_files, file); - } - nautilus_file_ref (file); - } else { - /* new file, create a nautilus file object and add it to the list */ - file = nautilus_file_new_from_info (directory, file_info); - nautilus_directory_add_file (directory, file); - } - added_files = g_list_prepend (added_files, file); - } - - /* If we are done loading, then we assume that any unconfirmed - * files are gone. - */ - if (directory->details->directory_loaded) { - for (node = directory->details->file_list; - node != NULL; node = next) { - file = NAUTILUS_FILE (node->data); - next = node->next; - - if (file->details->unconfirmed) { - nautilus_file_ref (file); - changed_files = g_list_prepend (changed_files, file); - - file->details->is_gone = TRUE; - nautilus_directory_remove_file (directory, file); - } - } - } - - /* Send the changed and added signals. */ - nautilus_directory_emit_change_signals (directory, changed_files); - nautilus_file_list_free (changed_files); - nautilus_directory_emit_files_added (directory, added_files); - nautilus_file_list_free (added_files); - - if (directory->details->directory_loaded - && !directory->details->directory_loaded_sent_notification) { - /* Send the done_loading signal. */ - nautilus_directory_emit_done_loading (directory); - - file = directory->details->load_directory_file; - - if (file != NULL) { - file->details->directory_count_is_up_to_date = TRUE; - file->details->got_directory_count = TRUE; - file->details->directory_count = directory->details->load_file_count; - - file->details->got_mime_list = TRUE; - file->details->mime_list_is_up_to_date = TRUE; - file->details->mime_list = istr_set_get_as_list - (directory->details->load_mime_list_hash); - - nautilus_file_changed (file); - } - - load_directory_done (directory); - - directory->details->directory_loaded_sent_notification = TRUE; - } - - drain: - gnome_vfs_file_info_list_free (pending_file_info); - - /* Get the state machine running again. */ - nautilus_directory_async_state_changed (directory); - - nautilus_directory_unref (directory); - return FALSE; -} - -void -nautilus_directory_schedule_dequeue_pending (NautilusDirectory *directory) -{ - if (directory->details->dequeue_pending_idle_id == 0) { - directory->details->dequeue_pending_idle_id - = gtk_idle_add (dequeue_pending_idle_callback, directory); - } -} - -static void -directory_load_one (NautilusDirectory *directory, - GnomeVFSFileInfo *info) -{ - if (info == NULL) { - return; - } - - /* Arrange for the "loading" part of the work. */ - gnome_vfs_file_info_ref (info); - directory->details->pending_file_info - = g_list_prepend (directory->details->pending_file_info, info); - nautilus_directory_schedule_dequeue_pending (directory); -} - -static void -directory_load_cancel (NautilusDirectory *directory) -{ - if (directory->details->directory_load_in_progress != NULL) { - gnome_vfs_async_cancel (directory->details->directory_load_in_progress); - directory->details->directory_load_in_progress = NULL; - async_job_end (directory, "file list"); - } -} - -static void -file_list_cancel (NautilusDirectory *directory) -{ - directory_load_cancel (directory); - - if (directory->details->dequeue_pending_idle_id != 0) { - gtk_idle_remove (directory->details->dequeue_pending_idle_id); - directory->details->dequeue_pending_idle_id = 0; - } - - if (directory->details->pending_file_info != NULL) { - gnome_vfs_file_info_list_free (directory->details->pending_file_info); - directory->details->pending_file_info = NULL; - } - - load_directory_state_destroy (directory); -} - -static void -directory_load_done (NautilusDirectory *directory, - GnomeVFSResult result) -{ - GList *node; - - directory_load_cancel (directory); - directory->details->directory_loaded = TRUE; - directory->details->directory_loaded_sent_notification = FALSE; - - /* Note that GNOME_VFS_OK can make it this far when the file-list - * length limit has been reached. In that case, don't treat it as - * an error. - */ - if (result != GNOME_VFS_ERROR_EOF && result != GNOME_VFS_OK) { - /* The load did not complete successfully. This means - * we don't know the status of the files in this directory. - * We clear the unconfirmed bit on each file here so that - * they won't be marked "gone" later -- we don't know enough - * about them to know whether they are really gone. - */ - for (node = directory->details->file_list; - node != NULL; node = node->next) { - set_file_unconfirmed (NAUTILUS_FILE (node->data), FALSE); - } - - nautilus_directory_emit_load_error (directory, - result); - } - - /* Call the idle function right away. */ - if (directory->details->dequeue_pending_idle_id != 0) { - gtk_idle_remove (directory->details->dequeue_pending_idle_id); - } - dequeue_pending_idle_callback (directory); -} - -static void -directory_load_callback (GnomeVFSAsyncHandle *handle, - GnomeVFSResult result, - GList *list, - guint entries_read, - gpointer callback_data) -{ - NautilusDirectory *directory; - GList *element; - - directory = NAUTILUS_DIRECTORY (callback_data); - - g_assert (directory->details->directory_load_in_progress != NULL); - g_assert (directory->details->directory_load_in_progress == handle); - - nautilus_directory_ref (directory); - - for (element = list; element != NULL; element = element->next) { - directory_load_one (directory, element->data); - } - - if (nautilus_directory_file_list_length_reached (directory) - || result != GNOME_VFS_OK) { - directory_load_done (directory, result); - } - - nautilus_directory_unref (directory); -} - -/* This checks if there's a request for the metafile contents. */ -static gboolean -is_anyone_waiting_for_metafile (NautilusDirectory *directory) -{ - GList *node; - ReadyCallback *callback; - Monitor *monitor; - - for (node = directory->details->call_when_ready_list; node != NULL; node = node->next) { - callback = node->data; - if (callback->request.metafile) { - return TRUE; - } - } - - for (node = directory->details->monitor_list; node != NULL; node = node->next) { - monitor = node->data; - if (monitor->request.metafile) { - return TRUE; - } - } - - return FALSE; -} - -static void -update_metadata_monitors (NautilusDirectory *directory) -{ - gboolean is_metadata_monitored; - - is_metadata_monitored = is_anyone_waiting_for_metafile (directory); - - if (directory->details->metafile_monitor == NULL) { - if (is_metadata_monitored) { - nautilus_directory_register_metadata_monitor (directory); - } - } else { - if (!is_metadata_monitored) { - nautilus_directory_unregister_metadata_monitor (directory); - } - } -} - -void -nautilus_directory_monitor_remove_internal (NautilusDirectory *directory, - NautilusFile *file, - gconstpointer client) -{ - g_assert (NAUTILUS_IS_DIRECTORY (directory)); - g_assert (file == NULL || NAUTILUS_IS_FILE (file)); - g_assert (client != NULL); - - remove_monitor (directory, file, client); - - if (file == NULL) { - if (directory->details->monitor != NULL - && !find_any_monitor (directory, NULL)) { - nautilus_monitor_cancel (directory->details->monitor); - directory->details->monitor = NULL; - } - } else { - if (file->details->monitor != NULL - && !find_any_monitor (directory, file)) { - nautilus_monitor_cancel (file->details->monitor); - file->details->monitor = NULL; - } - } - - update_metadata_monitors (directory); - - nautilus_directory_async_state_changed (directory); -} - -FileMonitors * -nautilus_directory_remove_file_monitors (NautilusDirectory *directory, - NautilusFile *file) -{ - GList *result, **list, *node, *next; - Monitor *monitor; - - g_assert (NAUTILUS_IS_DIRECTORY (directory)); - g_assert (NAUTILUS_IS_FILE (file)); - g_assert (file->details->directory == directory); - - result = NULL; - - list = &directory->details->monitor_list; - for (node = directory->details->monitor_list; node != NULL; node = next) { - next = node->next; - monitor = node->data; - - if (monitor->file == file) { - *list = g_list_remove_link (*list, node); - result = g_list_concat (node, result); - } - } - - update_metadata_monitors (directory); - nautilus_directory_async_state_changed (directory); - - return (FileMonitors *) result; -} - -void -nautilus_directory_add_file_monitors (NautilusDirectory *directory, - NautilusFile *file, - FileMonitors *monitors) -{ - GList **list; - - g_assert (NAUTILUS_IS_DIRECTORY (directory)); - g_assert (NAUTILUS_IS_FILE (file)); - g_assert (file->details->directory == directory); - - if (monitors == NULL) { - return; - } - - list = &directory->details->monitor_list; - *list = g_list_concat (*list, (GList *) monitors); - - update_metadata_monitors (directory); - nautilus_directory_async_state_changed (directory); -} - -static int -ready_callback_key_compare (gconstpointer a, gconstpointer b) -{ - const ReadyCallback *callback_a, *callback_b; - - callback_a = a; - callback_b = b; - if (callback_a->file < callback_b->file) { - return -1; - } - if (callback_a->file > callback_b->file) { - return 1; - } - if (callback_a->file == NULL) { - if (callback_a->callback.directory < callback_b->callback.directory) { - return -1; - } - if (callback_a->callback.directory > callback_b->callback.directory) { - return 1; - } - } else { - if (callback_a->callback.file < callback_b->callback.file) { - return -1; - } - if (callback_a->callback.file > callback_b->callback.file) { - return 1; - } - } - if (callback_a->callback_data < callback_b->callback_data) { - return -1; - } - if (callback_a->callback_data > callback_b->callback_data) { - return 1; - } - return 0; -} - -static void -ready_callback_call (NautilusDirectory *directory, - const ReadyCallback *callback) -{ - GList *file_list; - - /* Call the callback. */ - if (callback->file != NULL) { - (* callback->callback.file) (callback->file, - callback->callback_data); - } else { - if (directory == NULL || !callback->request.file_list) { - file_list = NULL; - } else { - file_list = get_non_tentative_file_list (directory); - } - - /* Pass back the file list if the user was waiting for it. */ - (* callback->callback.directory) (directory, - file_list, - callback->callback_data); - - nautilus_file_list_free (file_list); - } -} - -void -nautilus_directory_call_when_ready_internal (NautilusDirectory *directory, - NautilusFile *file, - GList *file_attributes, - NautilusDirectoryCallback directory_callback, - NautilusFileCallback file_callback, - gpointer callback_data) -{ - ReadyCallback callback; - - g_assert (directory == NULL || NAUTILUS_IS_DIRECTORY (directory)); - g_assert (file == NULL || NAUTILUS_IS_FILE (file)); - g_assert (file != NULL || directory_callback != NULL); - g_assert (file == NULL || file_callback != NULL); - - /* Construct a callback object. */ - callback.file = file; - if (file == NULL) { - callback.callback.directory = directory_callback; - } else { - callback.callback.file = file_callback; - } - callback.callback_data = callback_data; - nautilus_directory_set_up_request (&callback.request, file_attributes); - callback.request.file_list = file == NULL && file_attributes != NULL; - - /* Handle the NULL case. */ - if (directory == NULL) { - ready_callback_call (NULL, &callback); - return; - } - - /* Check if the callback is already there. */ - if (g_list_find_custom (directory->details->call_when_ready_list, - &callback, - ready_callback_key_compare) != NULL) { - g_warning ("tried to add a new callback while an old one was pending"); - return; - } - - /* Add the new callback to the list. */ - directory->details->call_when_ready_list = g_list_prepend - (directory->details->call_when_ready_list, - g_memdup (&callback, sizeof (callback))); - - /* When we change the ready list we need to sync up metadata monitors. - * We could just call update_metadata_monitors here, but we can be smarter - * since we know what was just added. - */ - if (callback.request.metafile && directory->details->metafile_monitor == NULL) { - nautilus_directory_register_metadata_monitor (directory); - } - - nautilus_directory_async_state_changed (directory); -} - -gboolean -nautilus_directory_check_if_ready_internal (NautilusDirectory *directory, - NautilusFile *file, - GList *file_attributes) -{ - Request request; - - g_assert (NAUTILUS_IS_DIRECTORY (directory)); - - nautilus_directory_set_up_request (&request, file_attributes); - return request_is_satisfied (directory, file, &request); -} - -static void -remove_callback_link_keep_data (NautilusDirectory *directory, - GList *link) -{ - directory->details->call_when_ready_list = g_list_remove_link - (directory->details->call_when_ready_list, link); - g_list_free_1 (link); -} - -static void -remove_callback_link (NautilusDirectory *directory, - GList *link) -{ - g_free (link->data); - remove_callback_link_keep_data (directory, link); -} - -void -nautilus_directory_cancel_callback_internal (NautilusDirectory *directory, - NautilusFile *file, - NautilusDirectoryCallback directory_callback, - NautilusFileCallback file_callback, - gpointer callback_data) -{ - ReadyCallback callback; - GList *node; - - if (directory == NULL) { - return; - } - - g_assert (NAUTILUS_IS_DIRECTORY (directory)); - g_assert (file == NULL || NAUTILUS_IS_FILE (file)); - g_assert (file != NULL || directory_callback != NULL); - g_assert (file == NULL || file_callback != NULL); - - /* Construct a callback object. */ - callback.file = file; - if (file == NULL) { - callback.callback.directory = directory_callback; - } else { - callback.callback.file = file_callback; - } - callback.callback_data = callback_data; - - /* Remove queued callback from the list. */ - node = g_list_find_custom (directory->details->call_when_ready_list, - &callback, - ready_callback_key_compare); - if (node != NULL) { - remove_callback_link (directory, node); - /* When we change the ready list we need to sync up metadata monitors. */ - update_metadata_monitors (directory); - - nautilus_directory_async_state_changed (directory); - } -} - -static void -directory_count_callback (GnomeVFSAsyncHandle *handle, - GnomeVFSResult result, - GList *list, - guint entries_read, - gpointer callback_data) -{ - NautilusDirectory *directory; - NautilusFile *count_file; - - directory = NAUTILUS_DIRECTORY (callback_data); - - g_assert (directory->details->count_in_progress == handle); - count_file = directory->details->count_file; - g_assert (NAUTILUS_IS_FILE (count_file)); - - if (result == GNOME_VFS_OK) { - return; - } - - nautilus_directory_ref (directory); - - count_file->details->directory_count_is_up_to_date = TRUE; - - /* Record either a failure or success. */ - if (result != GNOME_VFS_ERROR_EOF) { - count_file->details->directory_count_failed = TRUE; - } else { - count_file->details->got_directory_count = TRUE; - count_file->details->directory_count = entries_read; - } - directory->details->count_file = NULL; - directory->details->count_in_progress = NULL; - - /* Send file-changed even if count failed, so interested parties can - * distinguish between unknowable and not-yet-known cases. - */ - nautilus_file_changed (count_file); - - /* Start up the next one. */ - async_job_end (directory, "directory count"); - nautilus_directory_async_state_changed (directory); - - nautilus_directory_unref (directory); -} - -static void -new_files_callback (GnomeVFSAsyncHandle *handle, - GList *results, - gpointer callback_data) -{ - GList **handles, *node; - NautilusDirectory *directory; - GnomeVFSGetFileInfoResult *result; - - directory = NAUTILUS_DIRECTORY (callback_data); - handles = &directory->details->get_file_infos_in_progress; - g_assert (handle == NULL || g_list_find (*handles, handle) != NULL); - - nautilus_directory_ref (directory); - - /* Note that this call is done. */ - *handles = g_list_remove (*handles, handle); - - /* Queue up the new files. */ - for (node = results; node != NULL; node = node->next) { - result = node->data; - - if (result->result == GNOME_VFS_OK) { - directory_load_one (directory, result->file_info); - } - } - - nautilus_directory_unref (directory); -} - -void -nautilus_directory_get_info_for_new_files (NautilusDirectory *directory, - GList *vfs_uri_list) -{ - GnomeVFSAsyncHandle *handle; - gnome_vfs_async_get_file_info - (&handle, - vfs_uri_list, - (GNOME_VFS_FILE_INFO_GET_MIME_TYPE - | GNOME_VFS_FILE_INFO_FOLLOW_LINKS), - new_files_callback, - directory); - - directory->details->get_file_infos_in_progress - = g_list_prepend (directory->details->get_file_infos_in_progress, - handle); -} - -void -nautilus_async_destroying_file (NautilusFile *file) -{ - NautilusDirectory *directory; - gboolean changed; - GList *node, *next; - ReadyCallback *callback; - Monitor *monitor; - - directory = file->details->directory; - changed = FALSE; - - /* Check for callbacks. */ - for (node = directory->details->call_when_ready_list; node != NULL; node = next) { - next = node->next; - callback = node->data; - - if (callback->file == file) { - /* Client should have cancelled callback. */ - g_warning ("destroyed file has call_when_ready pending"); - remove_callback_link (directory, node); - changed = TRUE; - } - } - - /* Check for monitors. */ - for (node = directory->details->monitor_list; node != NULL; node = next) { - next = node->next; - monitor = node->data; - - if (monitor->file == file) { - /* Client should have removed monitor earlier. */ - g_warning ("destroyed file still being monitored"); - remove_monitor_link (directory, node); - changed = TRUE; - } - } - - /* When we change the monitor or ready list we need to sync up metadata monitors */ - if (changed) { - update_metadata_monitors (directory); - } - - /* Check if it's a file that's currently being worked on. - * If so, make that NULL so it gets canceled right away. - */ - if (directory->details->count_file == file) { - directory->details->count_file = NULL; - changed = TRUE; - } - if (directory->details->deep_count_file == file) { - directory->details->deep_count_file = NULL; - changed = TRUE; - } - if (directory->details->mime_list_file == file) { - directory->details->mime_list_file = NULL; - changed = TRUE; - } - if (directory->details->get_info_file == file) { - directory->details->get_info_file = NULL; - changed = TRUE; - } - if (directory->details->top_left_read_state != NULL - && directory->details->top_left_read_state->file == 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; - changed = TRUE; - } - - /* Let the directory take care of the rest. */ - if (changed) { - nautilus_directory_async_state_changed (directory); - } -} - -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; -} - -static gboolean -should_get_directory_count_now (NautilusFile *file) -{ - return lacks_directory_count (file) - && !file->details->loading_directory; -} - -static gboolean -wants_directory_count (const Request *request) -{ - return request->directory_count; -} - -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; -} - -static gboolean -wants_top_left (const Request *request) -{ - return request->top_left_text; -} - -static gboolean -lacks_info (NautilusFile *file) -{ - return !file->details->file_info_is_up_to_date - && !file->details->is_gone; -} - -static gboolean -wants_info (const Request *request) -{ - return request->file_info; -} - -static gboolean -lacks_deep_count (NautilusFile *file) -{ - return nautilus_file_is_directory (file) - && file->details->deep_counts_status != NAUTILUS_REQUEST_DONE; -} - -static gboolean -wants_deep_count (const Request *request) -{ - return request->deep_count; -} - -static gboolean -lacks_mime_list (NautilusFile *file) -{ - return nautilus_file_is_directory (file) - && !file->details->mime_list_is_up_to_date; -} - -static gboolean -should_get_mime_list (NautilusFile *file) -{ - return lacks_mime_list (file) - && !file->details->loading_directory; -} - -static gboolean -wants_mime_list (const Request *request) -{ - return request->mime_list; -} - -static gboolean -lacks_activation_uri (NautilusFile *file) -{ - return file->details->info != NULL - && !file->details->activation_uri_is_up_to_date; -} - -static gboolean -wants_activation_uri (const Request *request) -{ - return request->activation_uri; -} - - -static gboolean -has_problem (NautilusDirectory *directory, NautilusFile *file, FileCheck problem) -{ - GList *node; - - if (file != NULL) { - return (* problem) (file); - } - - for (node = directory->details->file_list; node != NULL; node = node->next) { - if ((* problem) (node->data)) { - return TRUE; - } - } - - return FALSE; -} - -static gboolean -request_is_satisfied (NautilusDirectory *directory, - NautilusFile *file, - Request *request) -{ - if (request->metafile && !nautilus_directory_is_metadata_read (directory)) { - return FALSE; - } - - if (request->file_list && !(directory->details->directory_loaded && - directory->details->directory_loaded_sent_notification)) { - return FALSE; - } - - if (request->directory_count) { - if (has_problem (directory, file, lacks_directory_count)) { - return FALSE; - } - } - - if (request->file_info) { - if (has_problem (directory, file, lacks_info)) { - return FALSE; - } - } - - if (request->top_left_text) { - if (has_problem (directory, file, lacks_top_left)) { - return FALSE; - } - } - - if (request->deep_count) { - if (has_problem (directory, file, lacks_deep_count)) { - return FALSE; - } - } - - if (request->mime_list) { - if (has_problem (directory, file, lacks_mime_list)) { - return FALSE; - } - } - - if (request->activation_uri) { - if (has_problem (directory, file, lacks_activation_uri)) { - return FALSE; - } - } - - return TRUE; -} - -static gboolean -call_ready_callbacks (NautilusDirectory *directory) -{ - gboolean called_any; - GList *node, *next; - ReadyCallback *callback; - - callback = NULL; - called_any = FALSE; - while (1) { - /* Check if any callbacks are satisifed and call them if they are. */ - for (node = directory->details->call_when_ready_list; - node != NULL; node = next) { - next = node->next; - callback = node->data; - if (request_is_satisfied (directory, callback->file, &callback->request)) { - break; - } - } - if (node == NULL) { - if (called_any) { - /* When we change the ready list we need to sync up metadata monitors. */ - update_metadata_monitors (directory); - } - return called_any; - } - - /* Callbacks are one-shots, so remove it now. */ - remove_callback_link_keep_data (directory, node); - - /* Call the callback. */ - ready_callback_call (directory, callback); - g_free (callback); - called_any = TRUE; - } -} - -/* This checks if there's a request for monitoring the file list. */ -gboolean -nautilus_directory_is_anyone_monitoring_file_list (NautilusDirectory *directory) -{ - GList *node; - ReadyCallback *callback; - Monitor *monitor; - - for (node = directory->details->call_when_ready_list; - node != NULL; node = node->next) { - callback = node->data; - if (callback->request.file_list) { - return TRUE; - } - } - - for (node = directory->details->monitor_list; - node != NULL; node = node->next) { - monitor = node->data; - if (monitor->request.file_list) { - return TRUE; - } - } - - return FALSE; -} - -/* This checks if the file list being monitored. */ -gboolean -nautilus_directory_is_file_list_monitored (NautilusDirectory *directory) -{ - return directory->details->file_list_monitored; -} - -static void -mark_all_files_unconfirmed (NautilusDirectory *directory) -{ - GList *node; - NautilusFile *file; - - for (node = directory->details->file_list; node != NULL; node = node->next) { - file = node->data; - set_file_unconfirmed (file, TRUE); - } -} - -static gboolean -should_display_file_name (const char *name, - GnomeVFSDirectoryFilterOptions options) -{ - /* Note that the name is URI-encoded, but this should not - * affect the . or the ~. - */ - - if ((options & GNOME_VFS_DIRECTORY_FILTER_NODOTFILES) != 0 - && nautilus_file_name_matches_hidden_pattern (name)) { - return FALSE; - } - - if ((options & GNOME_VFS_DIRECTORY_FILTER_NOBACKUPFILES) != 0 - && nautilus_file_name_matches_backup_pattern (name)) { - return FALSE; - } - - /* Note that we don't bother to check for "." or ".." here, because - * this function is used only for search results, which never include - * those special files. If we later use this function more generally, - * we might have to change this. - */ - return TRUE; -} - -/* Filter search results based on user preferences. This must be done - * differently than filtering other files because the search results - * are encoded: the entire file path is encoded and stored as the file - * name. - */ -static gboolean -filter_search_uri (const GnomeVFSFileInfo *info, gpointer data) -{ - GnomeVFSDirectoryFilterOptions options; - char *real_file_uri; - gboolean result; - - options = GPOINTER_TO_INT (data); - - real_file_uri = nautilus_get_target_uri_from_search_result_name (info->name); - result = should_display_file_name (g_basename (real_file_uri), options); - g_free (real_file_uri); - - return result; -} - -static GnomeVFSDirectoryFilter * -get_file_count_filter (NautilusDirectory *directory) -{ - if (nautilus_is_search_uri (directory->details->uri)) { - return gnome_vfs_directory_filter_new_custom - (filter_search_uri, - GNOME_VFS_DIRECTORY_FILTER_NEEDS_NAME, - GINT_TO_POINTER (get_filter_options_for_directory_count ())); - } - - return gnome_vfs_directory_filter_new - (GNOME_VFS_DIRECTORY_FILTER_NONE, - get_filter_options_for_directory_count (), - NULL); -} - -/* Start monitoring the file list if it isn't already. */ -static void -start_monitoring_file_list (NautilusDirectory *directory) -{ - if (!directory->details->file_list_monitored) { - g_assert (directory->details->directory_load_in_progress == NULL); - directory->details->file_list_monitored = TRUE; - nautilus_file_list_ref (directory->details->file_list); - } - - if (directory->details->directory_loaded - || directory->details->directory_load_in_progress != NULL) { - return; - } - - if (!async_job_start (directory, "file list")) { - return; - } - - mark_all_files_unconfirmed (directory); - - g_assert (directory->details->uri != NULL); - directory->details->load_directory_file = - nautilus_directory_get_corresponding_file (directory); - - directory->details->load_directory_file->details->loading_directory = TRUE; - directory->details->load_file_count = 0; - directory->details->load_file_count_filter = get_file_count_filter (directory); - directory->details->load_mime_list_hash = istr_set_new (); -#ifdef DEBUG_LOAD_DIRECTORY - g_message ("load_directory called to monitor file list of %s", directory->details->uri); -#endif - gnome_vfs_async_load_directory - (&directory->details->directory_load_in_progress, /* handle */ - directory->details->uri, /* uri */ - (GNOME_VFS_FILE_INFO_GET_MIME_TYPE /* options */ - | GNOME_VFS_FILE_INFO_FOLLOW_LINKS), - GNOME_VFS_DIRECTORY_FILTER_NONE, /* filter_type */ - (GNOME_VFS_DIRECTORY_FILTER_NOSELFDIR /* filter_options */ - | GNOME_VFS_DIRECTORY_FILTER_NOPARENTDIR), - NULL, /* filter_pattern */ - DIRECTORY_LOAD_ITEMS_PER_CALLBACK, /* items_per_notification */ - directory_load_callback, /* callback */ - directory); -} - -/* Stop monitoring the file list if it is being monitored. */ -void -nautilus_directory_stop_monitoring_file_list (NautilusDirectory *directory) -{ - if (!directory->details->file_list_monitored) { - g_assert (directory->details->directory_load_in_progress == NULL); - return; - } - - directory->details->file_list_monitored = FALSE; - file_list_cancel (directory); - nautilus_file_list_unref (directory->details->file_list); - directory->details->directory_loaded = FALSE; -} - -static void -file_list_start (NautilusDirectory *directory) -{ - if (nautilus_directory_is_anyone_monitoring_file_list (directory)) { - start_monitoring_file_list (directory); - } else { - nautilus_directory_stop_monitoring_file_list (directory); - } -} - -/* Reset count and mime list. Invalidating deep counts is handled by - * itself elsewhere because it's a relatively heavyweight and - * special-purpose operation (see bug 5863). Also, the shallow count - * needs to be refreshed when filtering changes, but the deep count - * deliberately does not take filtering into account. - */ -void -nautilus_directory_invalidate_count_and_mime_list (NautilusDirectory *directory) -{ - NautilusFile *file; - NautilusDirectory *parent_directory; - - file = nautilus_directory_get_existing_corresponding_file (directory); - if (file != 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; - - nautilus_file_unref (file); - - nautilus_directory_async_state_changed (parent_directory); - } -} - -static void -nautilus_directory_invalidate_file_attributes (NautilusDirectory *directory, - GList *file_attributes) -{ - GList *node; - - cancel_loading_attributes (directory, file_attributes); - - for (node = directory->details->file_list; node != NULL; node = node->next) { - nautilus_file_invalidate_attributes_internal (NAUTILUS_FILE (node->data), - file_attributes); - } - - if (directory->details->as_file != NULL) { - nautilus_file_invalidate_attributes_internal (directory->details->as_file, - file_attributes); - } -} - -void -nautilus_directory_force_reload_internal (NautilusDirectory *directory, - GList *file_attributes) -{ - /* invalidate attributes that are getting reloaded for all files */ - nautilus_directory_invalidate_file_attributes (directory, file_attributes); - - /* Start a new directory load. */ - file_list_cancel (directory); - directory->details->directory_loaded = FALSE; - - /* Start a new directory count. */ - nautilus_directory_invalidate_count_and_mime_list (directory); - - nautilus_directory_async_state_changed (directory); -} - -static gboolean -monitor_includes_file (const Monitor *monitor, - NautilusFile *file) -{ - if (monitor->file == file) { - return TRUE; - } - if (monitor->file != NULL) { - return FALSE; - } - if (file == file->details->directory->details->as_file) { - return FALSE; - } - return nautilus_file_should_show (file, - monitor->monitor_hidden_files, - monitor->monitor_backup_files); -} - -static gboolean -is_needy (NautilusFile *file, - FileCheck check_missing, - RequestCheck check_wanted) -{ - NautilusDirectory *directory; - GList *node; - ReadyCallback *callback; - Monitor *monitor; - - g_assert (NAUTILUS_IS_FILE (file)); - - if (!(* check_missing) (file)) { - return FALSE; - } - - directory = file->details->directory; - for (node = directory->details->call_when_ready_list; - node != NULL; node = node->next) { - callback = node->data; - if ((* check_wanted) (&callback->request)) { - if (callback->file == file) { - return TRUE; - } - if (callback->file == NULL - && file != directory->details->as_file) { - return TRUE; - } - } - } - for (node = directory->details->monitor_list; - node != NULL; node = node->next) { - monitor = node->data; - if ((* check_wanted) (&monitor->request)) { - if (monitor_includes_file (monitor, file)) { - return TRUE; - } - } - } - 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) -{ - 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) { - g_assert (NAUTILUS_IS_FILE (file)); - g_assert (file->details->directory == directory); - if (is_needy (file, - should_get_directory_count_now, - wants_directory_count)) { - return; - } - } - - /* 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) { - return; - } - - if (!async_job_start (directory, "directory count")) { - return; - } - - /* Start counting. */ - directory->details->count_file = file; - uri = nautilus_file_get_uri (file); -#ifdef DEBUG_LOAD_DIRECTORY - g_message ("load_directory called to get shallow file count for %s", uri); -#endif - gnome_vfs_async_load_directory - (&directory->details->count_in_progress, - uri, - GNOME_VFS_FILE_INFO_DEFAULT, - GNOME_VFS_DIRECTORY_FILTER_NONE, - get_filter_options_for_directory_count (), - NULL, - G_MAXINT, - directory_count_callback, - directory); - g_free (uri); -} - -static void -deep_count_one (NautilusDirectory *directory, - GnomeVFSFileInfo *info) -{ - NautilusFile *file; - char *escaped_name, *uri; - - file = directory->details->deep_count_file; - - if ((info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_TYPE) != 0 - && info->type == GNOME_VFS_FILE_TYPE_DIRECTORY) { - /* Count the directory. */ - file->details->deep_directory_count += 1; - - /* Record the fact that we have to descend into this directory. */ - escaped_name = gnome_vfs_escape_string (info->name); - uri = nautilus_make_path (directory->details->deep_count_uri, escaped_name); - g_free (escaped_name); - directory->details->deep_count_subdirectories = g_list_prepend - (directory->details->deep_count_subdirectories, uri); - } else { - /* Even non-regular files count as files. */ - file->details->deep_file_count += 1; - } - - /* Count the size. */ - if ((info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) != 0) { - file->details->deep_size += info->size; - } -} - -static void -deep_count_callback (GnomeVFSAsyncHandle *handle, - GnomeVFSResult result, - GList *list, - guint entries_read, - gpointer callback_data) -{ - NautilusDirectory *directory; - NautilusFile *file; - GList *element; - char *uri; - gboolean done; - - directory = NAUTILUS_DIRECTORY (callback_data); - g_assert (directory->details->deep_count_in_progress == handle); - file = directory->details->deep_count_file; - g_assert (NAUTILUS_IS_FILE (file)); - - nautilus_directory_ref (directory); - - for (element = list; element != NULL; element = element->next) { - deep_count_one (directory, element->data); - } - - done = FALSE; - if (result != GNOME_VFS_OK) { - if (result != GNOME_VFS_ERROR_EOF) { - file->details->deep_unreadable_count += 1; - } - - directory->details->deep_count_in_progress = NULL; - g_free (directory->details->deep_count_uri); - directory->details->deep_count_uri = NULL; - - if (directory->details->deep_count_subdirectories != NULL) { - /* Work on a new directory. */ - uri = directory->details->deep_count_subdirectories->data; - directory->details->deep_count_subdirectories = g_list_remove - (directory->details->deep_count_subdirectories, uri); - deep_count_load (directory, uri); - g_free (uri); - } else { - file->details->deep_counts_status = NAUTILUS_REQUEST_DONE; - directory->details->deep_count_file = NULL; - done = TRUE; - } - } - - nautilus_file_updated_deep_count_in_progress (file); - - if (done) { - nautilus_file_changed (file); - async_job_end (directory, "deep count"); - nautilus_directory_async_state_changed (directory); - } - - nautilus_directory_unref (directory); -} - -static void -deep_count_load (NautilusDirectory *directory, const char *uri) -{ - g_assert (directory->details->deep_count_uri == NULL); - directory->details->deep_count_uri = g_strdup (uri); -#ifdef DEBUG_LOAD_DIRECTORY - g_message ("load_directory called to get deep file count for %s", uri); -#endif - gnome_vfs_async_load_directory - (&directory->details->deep_count_in_progress, - uri, - GNOME_VFS_FILE_INFO_DEFAULT, - GNOME_VFS_DIRECTORY_FILTER_NONE, - (GNOME_VFS_DIRECTORY_FILTER_NOSELFDIR - | GNOME_VFS_DIRECTORY_FILTER_NOPARENTDIR), - NULL, - G_MAXINT, - deep_count_callback, - directory); -} - -static void -deep_count_start (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) { - g_assert (NAUTILUS_IS_FILE (file)); - g_assert (file->details->directory == directory); - if (is_needy (file, - lacks_deep_count, - wants_deep_count)) { - return; - } - } - - /* 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) { - return; - } - - if (!async_job_start (directory, "deep count")) { - return; - } - - /* Start counting. */ - file->details->deep_counts_status = NAUTILUS_REQUEST_IN_PROGRESS; - file->details->deep_directory_count = 0; - file->details->deep_file_count = 0; - file->details->deep_unreadable_count = 0; - file->details->deep_size = 0; - directory->details->deep_count_file = file; - uri = nautilus_file_get_uri (file); - deep_count_load (directory, uri); - g_free (uri); -} - -static void -mime_list_one (NautilusDirectory *directory, - GnomeVFSFileInfo *info) -{ - if ((info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_MIME_TYPE) != 0) { - istr_set_insert (directory->details->mime_list_hash, info->mime_type); - } -} - -static void -mime_list_callback (GnomeVFSAsyncHandle *handle, - GnomeVFSResult result, - GList *list, - guint entries_read, - gpointer callback_data) -{ - NautilusDirectory *directory; - NautilusFile *file; - GList *element; - - directory = NAUTILUS_DIRECTORY (callback_data); - g_assert (directory->details->mime_list_in_progress == handle); - file = directory->details->mime_list_file; - g_assert (NAUTILUS_IS_FILE (file)); - - for (element = list; element != NULL; element = element->next) { - mime_list_one (directory, element->data); - } - - if (result == GNOME_VFS_OK) { - return; - } - - nautilus_directory_ref (directory); - - file->details->mime_list_is_up_to_date = TRUE; - - /* Record either a failure or success. */ - eel_g_list_free_deep (file->details->mime_list); - if (result != GNOME_VFS_ERROR_EOF) { - file->details->mime_list_failed = TRUE; - file->details->mime_list = NULL; - } else { - file->details->got_mime_list = TRUE; - file->details->mime_list = istr_set_get_as_list - (directory->details->mime_list_hash); - } - istr_set_destroy (directory->details->mime_list_hash); - - directory->details->mime_list_in_progress = NULL; - directory->details->mime_list_file = NULL; - directory->details->mime_list_hash = NULL; - - /* Send file-changed even if getting the item type list - * failed, so interested parties can distinguish between - * unknowable and not-yet-known cases. - */ - nautilus_file_changed (file); - - /* Start up the next one. */ - async_job_end (directory, "MIME list"); - nautilus_directory_async_state_changed (directory); - - nautilus_directory_unref (directory); -} - -static void -mime_list_load (NautilusDirectory *directory, const char *uri) -{ - directory->details->mime_list_hash = istr_set_new (); -#ifdef DEBUG_LOAD_DIRECTORY - g_message ("load_directory called to get MIME list of %s", uri); -#endif - gnome_vfs_async_load_directory - (&directory->details->mime_list_in_progress, - uri, - GNOME_VFS_FILE_INFO_GET_MIME_TYPE, - GNOME_VFS_DIRECTORY_FILTER_NONE, - (GNOME_VFS_DIRECTORY_FILTER_NOSELFDIR - | GNOME_VFS_DIRECTORY_FILTER_NOPARENTDIR), - NULL, - DIRECTORY_LOAD_ITEMS_PER_CALLBACK, - mime_list_callback, - directory); -} - -static void -mime_list_start (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) { - g_assert (NAUTILUS_IS_FILE (file)); - g_assert (file->details->directory == directory); - if (is_needy (file, - should_get_mime_list, - wants_mime_list)) { - return; - } - } - - /* The count is not wanted, so stop it. */ - mime_list_cancel (directory); - } - - /* 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) { - return; - } - - if (!async_job_start (directory, "MIME list")) { - return; - } - - directory->details->mime_list_file = file; - uri = nautilus_file_get_uri (file); - mime_list_load (directory, uri); - g_free (uri); -} - -static int -count_lines (const char *text, int length) -{ - int count, i; - - count = 0; - for (i = 0; i < length; i++) { - count += *text++ == '\n'; - } - return count; -} - -static void -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; - - async_job_end (directory, "top left"); - nautilus_directory_async_state_changed (directory); -} - -static void -top_left_read_callback (GnomeVFSResult result, - GnomeVFSFileSize bytes_read, - char *file_contents, - gpointer callback_data) -{ - NautilusDirectory *directory; - NautilusFile *changed_file; - - 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; - if (result == GNOME_VFS_OK) { - g_free (directory->details->top_left_read_state->file->details->top_left_text); - directory->details->top_left_read_state->file->details->top_left_text = - 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); - } - - top_left_read_done (directory); - - if (changed_file != NULL) { - nautilus_file_changed (changed_file); - nautilus_file_unref (changed_file); - } - - nautilus_directory_unref (directory); -} - -static gboolean -top_left_read_more_callback (GnomeVFSFileSize bytes_read, - const char *file_contents, - gpointer callback_data) -{ - g_assert (NAUTILUS_IS_DIRECTORY (callback_data)); - - /* Stop reading when we have enough. */ - return bytes_read < NAUTILUS_FILE_TOP_LEFT_TEXT_MAXIMUM_BYTES - && count_lines (file_contents, bytes_read) <= NAUTILUS_FILE_TOP_LEFT_TEXT_MAXIMUM_LINES; -} - -static void -top_left_start (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) { - g_assert (NAUTILUS_IS_FILE (file)); - g_assert (file->details->directory == directory); - if (is_needy (file, - lacks_top_left, - wants_top_left)) { - return; - } - } - - /* The top left is not wanted, so stop it. */ - top_left_cancel (directory); - } - - /* Figure out which file to read the top left for. */ - file = select_needy_file (directory, - lacks_top_left, - wants_top_left); - if (file == NULL) { - return; - } - - if (!async_job_start (directory, "top left")) { - return; - } - - /* Start reading. */ - directory->details->top_left_read_state = g_new0 (TopLeftTextReadState, 1); - directory->details->top_left_read_state->file = file; - uri = nautilus_file_get_uri (file); - directory->details->top_left_read_state->handle = eel_read_file_async - (uri, - top_left_read_callback, - top_left_read_more_callback, - directory); - g_free (uri); -} - -static void -get_info_callback (GnomeVFSAsyncHandle *handle, - GList *results, - gpointer callback_data) -{ - NautilusDirectory *directory; - NautilusFile *get_info_file; - GnomeVFSGetFileInfoResult *result; - - directory = NAUTILUS_DIRECTORY (callback_data); - g_assert (handle == NULL || handle == directory->details->get_info_in_progress); - g_assert (eel_g_list_exactly_one_item (results)); - get_info_file = directory->details->get_info_file; - g_assert (NAUTILUS_IS_FILE (get_info_file)); - - nautilus_directory_ref (directory); - - directory->details->get_info_file = NULL; - directory->details->get_info_in_progress = NULL; - - /* ref here because we might be removing the last ref when we - * mark the file gone below, but we need to keep a ref at - * least long enough to send the change notification. - */ - nautilus_file_ref (get_info_file); - - result = results->data; - - if (result->result != GNOME_VFS_OK) { - get_info_file->details->file_info_is_up_to_date = TRUE; - if (get_info_file->details->info != NULL) { - gnome_vfs_file_info_unref (get_info_file->details->info); - get_info_file->details->info = NULL; - } - get_info_file->details->get_info_failed = TRUE; - get_info_file->details->get_info_error = result->result; - if (result->result == GNOME_VFS_ERROR_NOT_FOUND) { - /* mark file as gone */ - - get_info_file->details->is_gone = TRUE; - if (get_info_file != directory->details->as_file) { - nautilus_directory_remove_file (directory, get_info_file); - } - } - } else { - nautilus_file_update_info (get_info_file, result->file_info); - } - - nautilus_file_changed (get_info_file); - nautilus_file_unref (get_info_file); - - async_job_end (directory, "file info"); - nautilus_directory_async_state_changed (directory); - - nautilus_directory_unref (directory); -} - -static void -file_info_start (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) { - g_assert (NAUTILUS_IS_FILE (file)); - g_assert (file->details->directory == directory); - if (is_needy (file, lacks_info, wants_info)) { - return; - } - } - - /* The info is not wanted, so stop it. */ - file_info_cancel (directory); - } - - /* 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); - - /* Found one we need to get the info for. */ - if (!async_job_start (directory, "file info")) { - return; - } - directory->details->get_info_file = file; - fake_list.data = vfs_uri; - fake_list.prev = NULL; - fake_list.next = NULL; - gnome_vfs_async_get_file_info - (&directory->details->get_info_in_progress, - &fake_list, - GNOME_VFS_FILE_INFO_GET_MIME_TYPE - | GNOME_VFS_FILE_INFO_FOLLOW_LINKS, - get_info_callback, - directory); - gnome_vfs_uri_unref (vfs_uri); -} - -static void -activation_uri_done (NautilusDirectory *directory, - NautilusFile *file, - const char *uri) -{ - file->details->activation_uri_is_up_to_date = TRUE; - - file->details->got_activation_uri = TRUE; - g_free (file->details->activation_uri); - file->details->activation_uri = g_strdup (uri); - - 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) -{ - 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; - - activation_uri_done (directory, file, uri); -} - -static void -activation_uri_nautilus_link_read_callback (GnomeVFSResult result, - GnomeVFSFileSize bytes_read, - char *file_contents, - gpointer callback_data) -{ - NautilusDirectory *directory; - char *buffer, *uri; - - directory = NAUTILUS_DIRECTORY (callback_data); - - nautilus_directory_ref (directory); - - /* Handle the case where we read the Nautilus link. */ - if (result != GNOME_VFS_OK) { - /* FIXME bugzilla.eazel.com 2433: We should report this error to the user. */ - g_free (file_contents); - uri = 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); - g_free (buffer); - } - - activation_uri_read_done (directory, uri); - g_free (uri); - - nautilus_directory_unref (directory); -} - -static void -activation_uri_gmc_link_read_callback (GnomeVFSResult result, - GnomeVFSFileSize bytes_read, - char *file_contents, - gpointer callback_data) -{ - NautilusDirectory *directory; - char *end_of_line, *uri; - - directory = NAUTILUS_DIRECTORY (callback_data); - - nautilus_directory_ref (directory); - - /* Handle the case where we read the GMC link. */ - if (result != GNOME_VFS_OK || !eel_str_has_prefix (file_contents, "URL: ")) { - /* FIXME bugzilla.eazel.com 2433: We should report this error to the user. */ - uri = NULL; - } else { - /* Make sure we don't run off the end of the buffer. */ - end_of_line = memchr (file_contents, '\n', bytes_read); - if (end_of_line != NULL) { - uri = g_strndup (file_contents, end_of_line - file_contents); - } else { - uri = g_strndup (file_contents, bytes_read); - } - } - - g_free (file_contents); - activation_uri_read_done (directory, uri ? uri + 5 : NULL); - g_free (uri); - - nautilus_directory_unref (directory); -} - -static gboolean -activation_uri_gmc_link_read_more_callback (GnomeVFSFileSize bytes_read, - const char *file_contents, - gpointer callback_data) -{ - g_assert (NAUTILUS_IS_DIRECTORY (callback_data)); - - /* We need the first 512 bytes to see if something is a gmc link. */ - return bytes_read < 512; -} - -static void -activation_uri_start (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 (file != NULL) { - g_assert (NAUTILUS_IS_FILE (file)); - g_assert (file->details->directory == directory); - if (is_needy (file, lacks_info, wants_info)) { - return; - } - } - - /* The count is not wanted, so stop it. */ - activation_uri_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) { - return; - } - - if (!async_job_start (directory, "activation URI")) { - 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); - nautilus_style_link = nautilus_file_is_nautilus_link (file); - - /* 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); - } 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 (gmc_style_link) { - directory->details->activation_uri_read_state->handle = eel_read_file_async - (uri, - activation_uri_gmc_link_read_callback, - activation_uri_gmc_link_read_more_callback, - directory); - } else { - directory->details->activation_uri_read_state->handle = eel_read_entire_file_async - (uri, - activation_uri_nautilus_link_read_callback, - directory); - } - g_free (uri); - } -} - -static void -start_or_stop_io (NautilusDirectory *directory) -{ - /* Start or stop getting file info. */ - file_info_start (directory); - - /* Start or stop reading files. */ - file_list_start (directory); - - /* Start or stop getting directory counts. */ - directory_count_start (directory); - deep_count_start (directory); - - /* Start or stop getting mime lists. */ - mime_list_start (directory); - - /* Start or stop getting top left pieces of files. */ - top_left_start (directory); - - /* 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, - * or when some I/O is completed. - */ -void -nautilus_directory_async_state_changed (NautilusDirectory *directory) -{ - /* Check if any callbacks are satisfied and call them if they - * are. Do this last so that any changes done in start or stop - * I/O functions immediately (not in callbacks) are taken into - * consideration. If any callbacks are called, consider the - * I/O state again so that we can release or cancel I/O that - * is not longer needed once the callbacks are satisfied. - */ - - if (GTK_OBJECT_DESTROYED (directory)) { - return; - } - if (directory->details->in_async_service_loop) { - directory->details->state_changed = TRUE; - return; - } - directory->details->in_async_service_loop = TRUE; - nautilus_directory_ref (directory); - do { - directory->details->state_changed = FALSE; - start_or_stop_io (directory); - if (call_ready_callbacks (directory)) { - directory->details->state_changed = TRUE; - } - } while (directory->details->state_changed); - directory->details->in_async_service_loop = FALSE; - nautilus_directory_unref (directory); - - /* Check if any directories should wake up. */ - async_job_wake_up (); -} - -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); - mime_list_cancel (directory); - top_left_cancel (directory); - - /* We aren't waiting for anything any more. */ - if (waiting_directories != NULL) { - g_hash_table_remove (waiting_directories, directory); - } - - /* Check if any directories should wake up. */ - async_job_wake_up (); -} - -static void -cancel_directory_count_for_file (NautilusDirectory *directory, - NautilusFile *file) -{ - if (directory->details->count_file == file) { - directory_count_cancel (directory); - } -} - -static void -cancel_deep_counts_for_file (NautilusDirectory *directory, - NautilusFile *file) -{ - if (directory->details->deep_count_file == file) { - deep_count_cancel (directory); - } -} - -static void -cancel_mime_list_for_file (NautilusDirectory *directory, - NautilusFile *file) -{ - if (directory->details->mime_list_file == file) { - mime_list_cancel (directory); - } -} - -static void -cancel_top_left_text_for_file (NautilusDirectory *directory, - NautilusFile *file) -{ - if (directory->details->top_left_read_state != NULL && - directory->details->top_left_read_state->file == file) { - top_left_cancel (directory); - } -} - -static void -cancel_file_info_for_file (NautilusDirectory *directory, - NautilusFile *file) -{ - if (directory->details->get_info_file == file) { - file_info_cancel (directory); - } -} - -static void -cancel_activation_uri_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); - } -} - -static void -cancel_loading_attributes (NautilusDirectory *directory, - GList *file_attributes) -{ - Request request; - - nautilus_directory_set_up_request (&request, - file_attributes); - - if (request.directory_count) { - directory_count_cancel (directory); - } - if (request.deep_count) { - deep_count_cancel (directory); - } - if (request.mime_list) { - mime_list_cancel (directory); - } - if (request.top_left_text) { - top_left_cancel (directory); - } - if (request.file_info) { - file_info_cancel (directory); - } - if (request.activation_uri) { - file_info_cancel (directory); - } - - /* FIXME bugzilla.eazel.com 5064: implement cancelling metadata when we - implement invalidating metadata */ - - nautilus_directory_async_state_changed (directory); -} - -void -nautilus_directory_cancel_loading_file_attributes (NautilusDirectory *directory, - NautilusFile *file, - GList *file_attributes) -{ - Request request; - - nautilus_directory_set_up_request (&request, - file_attributes); - - if (request.directory_count) { - cancel_directory_count_for_file (directory, file); - } - if (request.deep_count) { - cancel_deep_counts_for_file (directory, file); - } - if (request.mime_list) { - cancel_mime_list_for_file (directory, file); - } - if (request.top_left_text) { - cancel_top_left_text_for_file (directory, file); - } - if (request.file_info) { - cancel_file_info_for_file (directory, file); - } - if (request.activation_uri) { - cancel_activation_uri_for_file (directory, file); - } - - /* FIXME bugzilla.eazel.com 5064: implement cancelling metadata when we - implement invalidating metadata */ - - nautilus_directory_async_state_changed (directory); -} diff --git a/libnautilus-extensions/nautilus-directory-background.c b/libnautilus-extensions/nautilus-directory-background.c deleted file mode 100644 index e58356504..000000000 --- a/libnautilus-extensions/nautilus-directory-background.c +++ /dev/null @@ -1,1023 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */ - -/* - nautilus-directory-background.c: Helper for the background of a widget - that is viewing a particular location. - - 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. - - Author: Darin Adler <darin@eazel.com> -*/ - -#include <config.h> -#include "nautilus-directory-background.h" - -#include <eel/eel-gdk-extensions.h> -#include <eel/eel-background.h> -#include "nautilus-global-preferences.h" -#include "nautilus-metadata.h" -#include "nautilus-file-attributes.h" -#include <eel/eel-string.h> -#include "nautilus-theme.h" -#include <X11/Xatom.h> -#include <gdk/gdkx.h> -#include <gtk/gtkmain.h> -#include <gtk/gtksignal.h> -#include <libgnome/gnome-config.h> -#include <libgnome/gnome-util.h> -#include <libgnomevfs/gnome-vfs-utils.h> - -static void background_changed_callback (EelBackground *background, - NautilusFile *file); -static void background_reset_callback (EelBackground *background, - NautilusFile *file); - -static void saved_settings_changed_callback (NautilusFile *file, - EelBackground *background); - -static void nautilus_file_background_receive_root_window_changes (EelBackground *background); - -static void nautilus_file_update_desktop_pixmaps (EelBackground *background); - -static void nautilus_file_background_write_desktop_settings (char *color, - char *image, - EelBackgroundImagePlacement placement); - -static gboolean nautilus_file_background_matches_default_settings ( - const char* color, const char* default_color, - const char* image, const char* default_image, - EelBackgroundImagePlacement placement, EelBackgroundImagePlacement default_placement); - -static void -desktop_background_realized (NautilusIconContainer *icon_container, void *disconnect_signal) -{ - EelBackground *background; - - if ((gboolean) GPOINTER_TO_INT (disconnect_signal)) { - gtk_signal_disconnect_by_func (GTK_OBJECT (icon_container), - GTK_SIGNAL_FUNC (desktop_background_realized), - disconnect_signal); - } - - background = eel_get_widget_background (GTK_WIDGET (icon_container)); - - gtk_object_set_data (GTK_OBJECT (background), "icon_container", (gpointer) icon_container); - - nautilus_file_update_desktop_pixmaps (background); -} - -static const char *default_theme_source = "directory"; -static const char *desktop_theme_source = "desktop"; - -void -nautilus_connect_desktop_background_to_file_metadata (NautilusIconContainer *icon_container, - NautilusFile *file) -{ - EelBackground *background; - - background = eel_get_widget_background (GTK_WIDGET (icon_container)); - - gtk_object_set_data (GTK_OBJECT (background), "theme_source", (gpointer) desktop_theme_source); - - /* Strictly speaking, we don't need to know about metadata changes, since - * the desktop setting aren't stored there. But, hooking up to metadata - * changes is actually a small part of what this fn does, and we do need - * the other stuff (hooked up to background & theme changes, initialize - * the background). Being notified of metadata changes on the file is a - * waste, but won't hurt, so I don't think it's worth refactoring the fn - * at this point. - */ - nautilus_connect_background_to_file_metadata (GTK_WIDGET (icon_container), file); - - if (GTK_WIDGET_REALIZED (icon_container)) { - desktop_background_realized (icon_container, GINT_TO_POINTER (FALSE)); - } else { - gtk_signal_connect (GTK_OBJECT (icon_container), "realize", GTK_SIGNAL_FUNC (desktop_background_realized), GINT_TO_POINTER (TRUE)); - } - - nautilus_file_background_receive_root_window_changes (background); -} - -static gboolean -eel_background_is_desktop (EelBackground *background) -{ - /* == works because we're carful to always use the same string. - */ - return gtk_object_get_data (GTK_OBJECT (background), "theme_source") == desktop_theme_source; -} - -static const char *nautilus_file_background_peek_theme_source (EelBackground *background) -{ - char *theme_source; - - theme_source = gtk_object_get_data (GTK_OBJECT (background), "theme_source"); - - return theme_source != NULL ? theme_source : default_theme_source; -} - -static GdkWindow * -eel_background_get_desktop_background_window (EelBackground *background) -{ - gpointer layout; - - layout = gtk_object_get_data (GTK_OBJECT (background), "icon_container"); - return layout != NULL ? GTK_LAYOUT (layout)->bin_window : NULL; -} - -/* utility routine to handle mapping local image files in themes to a uri */ -static char* -theme_image_path_to_uri (char *image_file, const char *theme_name) -{ - char *image_path; - char *image_uri; - - if (image_file != NULL && !eel_istr_has_prefix (image_file, "file://")) { - - if (eel_str_has_prefix (image_file, "./")) { - image_path = nautilus_theme_get_image_path_from_theme (image_file + 2, theme_name); - } else { - image_path = g_strdup_printf ("%s/%s", NAUTILUS_DATADIR, image_file); - } - - if (image_path && g_file_exists (image_path)) { - image_uri = gnome_vfs_get_uri_from_local_path (image_path); - } else { - image_uri = NULL; - } - - g_free (image_path); - } else { - image_uri = g_strdup (image_file); - } - - return image_uri; -} - -static void -nautilus_file_background_get_default_settings_for_theme (const char* theme_name, - const char* theme_source, - char **color, - char **image, - EelBackgroundImagePlacement *placement) -{ - char *image_local_path; - - if (placement != NULL) { - *placement = EEL_BACKGROUND_TILED; - } - - if (color != NULL) { - *color = nautilus_theme_get_theme_data_from_theme (theme_source, NAUTILUS_METADATA_KEY_LOCATION_BACKGROUND_COLOR, theme_name); - } - - if (image != NULL) { - image_local_path = nautilus_theme_get_theme_data_from_theme (theme_source, NAUTILUS_METADATA_KEY_LOCATION_BACKGROUND_IMAGE, theme_name); - *image = theme_image_path_to_uri (image_local_path, theme_name); - g_free (image_local_path); - } -} - -static void -nautilus_file_background_get_default_settings (const char* theme_source, - char **color, - char **image, - EelBackgroundImagePlacement *placement) -{ - char *theme_name; - theme_name = nautilus_theme_get_theme (); - nautilus_file_background_get_default_settings_for_theme - (theme_name, theme_source, color, image, placement); - g_free (theme_name); -} - -static gboolean -eel_gnome_config_string_match_no_case_with_default (const char *path, const char *test_value, gboolean *was_default) -{ - char *value; - gboolean result; - value = gnome_config_get_string_with_default (path, was_default); - result = !eel_strcasecmp (value, test_value); - g_free (value); - return result; -} - -/* This enum is from gnome-source/control-center/capplets/background-properties/render-background.h */ -enum { - WALLPAPER_TILED, - WALLPAPER_CENTERED, - WALLPAPER_SCALED, - WALLPAPER_SCALED_KEEP, - WALLPAPER_EMBOSSED -}; - -static void -nautilus_file_background_read_desktop_settings (char **color, - char **image, - EelBackgroundImagePlacement *placement) -{ - int image_alignment; - char* image_local_path; - char* default_image_uri; - gboolean no_alignment_set; - gboolean no_image_set; - EelBackgroundImagePlacement default_placement; - - char *end_color; - char *start_color; - char *default_color; - gboolean use_gradient; - gboolean is_horizontal; - gboolean no_start_color_set; - gboolean no_end_color_set; - gboolean no_gradient_set; - gboolean no_gradient_orientation_set; - - char *theme_name; - char *cur_theme_name; - gboolean no_theme_name_set; - gboolean switch_to_cur_theme_default; - - theme_name = gnome_config_get_string_with_default ("/Background/Default/nautilus_theme", &no_theme_name_set); - - if (no_theme_name_set) { - nautilus_file_background_get_default_settings - (desktop_theme_source, &default_color, &default_image_uri, &default_placement); - } else { - nautilus_file_background_get_default_settings_for_theme - (theme_name, desktop_theme_source, &default_color, &default_image_uri, &default_placement); - } - - image_local_path = gnome_config_get_string_with_default ("/Background/Default/wallpaper", &no_image_set); - - if (no_image_set) { - *image = g_strdup (default_image_uri); - } else if (eel_strcasecmp (image_local_path, "none") != 0) { - *image = gnome_vfs_get_uri_from_local_path (image_local_path); - } else { - *image = NULL; - } - - g_free(image_local_path); - - image_alignment = gnome_config_get_int_with_default ("/Background/Default/wallpaperAlign", &no_alignment_set); - - if (no_alignment_set) { - *placement = default_placement; - } else { - switch (image_alignment) { - default: - g_assert_not_reached (); - case WALLPAPER_EMBOSSED: - /* FIXME bugzilla.eazel.com 2193: we don't support embossing. - * Just treat it as centered - ugh. - */ - case WALLPAPER_CENTERED: - *placement = EEL_BACKGROUND_CENTERED; - break; - case WALLPAPER_TILED: - *placement = EEL_BACKGROUND_TILED; - break; - case WALLPAPER_SCALED: - *placement = EEL_BACKGROUND_SCALED; - break; - case WALLPAPER_SCALED_KEEP: - *placement = EEL_BACKGROUND_SCALED_ASPECT; - break; - } - } - - end_color = gnome_config_get_string_with_default ("/Background/Default/color2", &no_end_color_set); - start_color = gnome_config_get_string_with_default ("/Background/Default/color1", &no_start_color_set); - use_gradient = !eel_gnome_config_string_match_no_case_with_default ("/Background/Default/simple", "solid", &no_gradient_set); - is_horizontal = !eel_gnome_config_string_match_no_case_with_default ("/Background/Default/gradient", "vertical", &no_gradient_orientation_set); - - if (no_gradient_set || no_gradient_orientation_set || no_start_color_set) { - *color = g_strdup (default_color); - } else if (use_gradient) { - if (no_end_color_set) { - *color = g_strdup (default_color); - } else { - *color = eel_gradient_new (start_color, end_color , is_horizontal); - } - } else { - *color = g_strdup (start_color); - } - - g_free(start_color); - g_free(end_color); - - /* Since we share our settings with the background-capplet, we can't - * write the default values specially (e.g. by removing them entirely). - * - * The best we can do is check to see if the settings match the default values - * for the theme name that's stored with them. If so, we assume it means use - * the default - i.e. the default from the current theme. - * - * - there must be a theme name stored with the settings - * - if the stored theme name matches the current theme, then - * we don't need to do anything since we're already using - * the current theme's default values. - * - */ - cur_theme_name = nautilus_theme_get_theme (); - - switch_to_cur_theme_default = !no_theme_name_set && - (eel_strcmp (theme_name, cur_theme_name) != 0) && - nautilus_file_background_matches_default_settings - (*color, default_color, - *image, default_image_uri, - *placement, default_placement); - - if (switch_to_cur_theme_default) { - g_free (*color); - g_free (*image); - nautilus_file_background_get_default_settings (desktop_theme_source, color, image, placement); - } - - if (switch_to_cur_theme_default || no_theme_name_set) { - /* Writing out the actual settings for the current theme so that the - * background capplet will show the right settings. - */ - nautilus_file_background_write_desktop_settings (*color, *image, *placement); - } - - g_free (theme_name); - g_free (cur_theme_name); - g_free(default_color); - g_free(default_image_uri); -} - -static void -nautilus_file_background_write_desktop_settings (char *color, char *image, EelBackgroundImagePlacement placement) -{ - char *end_color; - char *start_color; - char *image_local_path; - char *theme_name; - - int wallpaper_align; - - int i; - int wallpaper_count; - char *wallpaper_path_i; - char *wallpaper_config_path_i; - gboolean found_wallpaper; - - if (color != NULL) { - start_color = eel_gradient_get_start_color_spec (color); - gnome_config_set_string ("/Background/Default/color1", start_color); - g_free (start_color); - - /* if color is not a gradient, this ends up writing same as start_color */ - end_color = eel_gradient_get_end_color_spec (color); - gnome_config_set_string ("/Background/Default/color2", end_color); - g_free (end_color); - - gnome_config_set_string ("/Background/Default/simple", eel_gradient_is_gradient (color) ? "gradient" : "solid"); - gnome_config_set_string ("/Background/Default/gradient", eel_gradient_is_horizontal (color) ? "horizontal" : "vertical"); - } else { - /* We set it to white here because that's how backgrounds with a NULL color - * are drawn by Nautilus - due to usage of eel_gdk_color_parse_with_white_default. - */ - gnome_config_set_string ("/Background/Default/color1", "rgb:FFFF/FFFF/FFFF"); - gnome_config_set_string ("/Background/Default/color2", "rgb:FFFF/FFFF/FFFF"); - gnome_config_set_string ("/Background/Default/simple", "solid"); - gnome_config_set_string ("/Background/Default/gradient", "vertical"); - } - - if (image != NULL) { - image_local_path = gnome_vfs_get_local_path_from_uri (image); - gnome_config_set_string ("/Background/Default/wallpaper", image_local_path); - switch (placement) { - case EEL_BACKGROUND_TILED: - wallpaper_align = WALLPAPER_TILED; - break; - case EEL_BACKGROUND_CENTERED: - wallpaper_align = WALLPAPER_CENTERED; - break; - case EEL_BACKGROUND_SCALED: - wallpaper_align = WALLPAPER_SCALED; - break; - case EEL_BACKGROUND_SCALED_ASPECT: - wallpaper_align = WALLPAPER_SCALED_KEEP; - break; - default: - g_assert_not_reached (); - wallpaper_align = WALLPAPER_TILED; - break; - } - - gnome_config_set_int ("/Background/Default/wallpaperAlign", wallpaper_align); - - wallpaper_count = gnome_config_get_int ("/Background/Default/wallpapers=0"); - found_wallpaper = FALSE; - for (i = 1; i <= wallpaper_count && !found_wallpaper; ++i) { - wallpaper_config_path_i = g_strdup_printf ("/Background/Default/wallpaper%d", i); - wallpaper_path_i = gnome_config_get_string (wallpaper_config_path_i); - g_free (wallpaper_config_path_i); - if (eel_strcmp (wallpaper_path_i, image_local_path) == 0) { - found_wallpaper = TRUE; - } - - g_free (wallpaper_path_i); - } - - if (!found_wallpaper) { - gnome_config_set_int ("/Background/Default/wallpapers", wallpaper_count + 1); - gnome_config_set_string ("/Background/Default/wallpapers_dir", image_local_path); - wallpaper_config_path_i = g_strdup_printf ("/Background/Default/wallpaper%d", wallpaper_count + 1); - gnome_config_set_string (wallpaper_config_path_i, image_local_path); - g_free (wallpaper_config_path_i); - } - - g_free (image_local_path); - } else { - gnome_config_set_string ("/Background/Default/wallpaper", "none"); - } - - theme_name = nautilus_theme_get_theme (); - gnome_config_set_string ("/Background/Default/nautilus_theme", theme_name); - g_free (theme_name); - - gnome_config_sync (); -} - -static void -nautilus_file_background_write_desktop_default_settings () -{ - char *color; - char *image; - EelBackgroundImagePlacement placement; - nautilus_file_background_get_default_settings (desktop_theme_source, &color, &image, &placement); - nautilus_file_background_write_desktop_settings (color, image, placement); -} - -static int -call_settings_changed (EelBackground *background) -{ - NautilusFile *file; - file = gtk_object_get_data (GTK_OBJECT (background), "eel_background_file"); - if (file) { - saved_settings_changed_callback (file, background); - } - return FALSE; -} - -/* We don't want to respond to our own changes to the root pixmap. - * Since there's no way to determine the origin of the x-event (or mark it) - * we use this variable determine if we think the next PropertyNotify is - * due to us. - */ -static int set_root_pixmap_count = 0; - -static GdkFilterReturn -nautilus_file_background_event_filter (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data) -{ - XEvent *xevent; - EelBackground *background; - - xevent = (XEvent *) gdk_xevent; - - if (xevent->type == PropertyNotify && xevent->xproperty.atom == gdk_atom_intern("ESETROOT_PMAP_ID", TRUE)) { - - /* If we caused it, ignore it. - */ - if (set_root_pixmap_count > 0) { - --set_root_pixmap_count; - return GDK_FILTER_CONTINUE; - } - - background = EEL_BACKGROUND (data); - /* FIXME bugzilla.eazel.com 2220: - * We'd like to call saved_settings_changed_callback right here, directly. - * However, the current version of the property-background capplet saves - * the new setting in gnome_config AFTER setting the root window's property - - * i.e. after we get this event. How long afterwards is not knowable - we - * guess half a second. Fixing this requires changing the capplet. - */ - gtk_timeout_add (500, (GtkFunction) (call_settings_changed), background); - } - - return GDK_FILTER_CONTINUE; -} - -static void -desktop_background_destroyed_callback (EelBackground *background, void *georgeWBush) -{ - gdk_window_remove_filter (GDK_ROOT_PARENT(), nautilus_file_background_event_filter, background); -} - -static void -nautilus_file_background_receive_root_window_changes (EelBackground *background) -{ - XWindowAttributes attribs = { 0 }; - - /* set up a filter on the root window to get notified about property changes */ - gdk_window_add_filter (GDK_ROOT_PARENT(), nautilus_file_background_event_filter, background); - - gdk_error_trap_push (); - - /* select events, we need to trap the kde status thingies anyway */ - XGetWindowAttributes (GDK_DISPLAY (), GDK_ROOT_WINDOW (), &attribs); - XSelectInput (GDK_DISPLAY (), GDK_ROOT_WINDOW (), attribs.your_event_mask | PropertyChangeMask); - - gdk_flush (); - - gdk_error_trap_pop (); - - gtk_signal_connect (GTK_OBJECT (background), - "destroy", - GTK_SIGNAL_FUNC (desktop_background_destroyed_callback), - NULL); -} - -/* Create a persistant pixmap. We create a separate display - * and set the closedown mode on it to RetainPermanent - * (copied from gnome-source/control-panels/capplets/background-properties/render-background.c) - */ -static GdkPixmap * -make_root_pixmap (gint width, gint height) -{ - Display *display; - Pixmap result; - - gdk_flush (); - - display = XOpenDisplay (gdk_display_name); - - XSetCloseDownMode (display, RetainPermanent); - - result = XCreatePixmap (display, - DefaultRootWindow (display), - width, height, - DefaultDepthOfScreen (DefaultScreenOfDisplay (GDK_DISPLAY()))); - - XCloseDisplay (display); - - return gdk_pixmap_foreign_new (result); -} - -/* (copied from gnome-source/control-panels/capplets/background-properties/render-background.c) - */ -static void -dispose_root_pixmap (GdkPixmap *pixmap) -{ - /* Unrefing a foreign pixmap causes it to be destroyed - so we include - * this bad hack, that will work for GTK+-1.2 until the problem - * is fixed in the next release - */ - - GdkWindowPrivate *private = (GdkWindowPrivate *)pixmap; - - gdk_xid_table_remove (private->xwindow); - g_dataset_destroy (private); - g_free (private); - -} - -/* Set the root pixmap, and properties pointing to it. We - * do this atomically with XGrabServer to make sure that - * we won't leak the pixmap if somebody else it setting - * it at the same time. (This assumes that they follow the - * same conventions we do - * (copied from gnome-source/control-panels/capplets/background-properties/render-background.c) - */ -static void -set_root_pixmap (GdkPixmap *pixmap) -{ - int result; - gint format; - gulong nitems; - gulong bytes_after; - guchar *data_esetroot; - Pixmap pixmap_id; - GdkAtom type; - - data_esetroot = NULL; - - XGrabServer (GDK_DISPLAY()); - - result = XGetWindowProperty (GDK_DISPLAY(), GDK_ROOT_WINDOW(), - gdk_atom_intern("ESETROOT_PMAP_ID", FALSE), - 0L, 1L, False, XA_PIXMAP, - &type, &format, &nitems, &bytes_after, - &data_esetroot); - - if (result == Success && type == XA_PIXMAP && format == 32 && nitems == 1) { - XKillClient(GDK_DISPLAY(), *(Pixmap*)data_esetroot); - } - - if (data_esetroot != NULL) { - XFree (data_esetroot); - } - - ++set_root_pixmap_count; - - pixmap_id = GDK_WINDOW_XWINDOW (pixmap); - - XChangeProperty (GDK_DISPLAY(), GDK_ROOT_WINDOW(), - gdk_atom_intern("ESETROOT_PMAP_ID", FALSE), XA_PIXMAP, - 32, PropModeReplace, - (guchar *) &pixmap_id, 1); - XChangeProperty (GDK_DISPLAY(), GDK_ROOT_WINDOW(), - gdk_atom_intern("_XROOTPMAP_ID", FALSE), XA_PIXMAP, - 32, PropModeReplace, - (guchar *) &pixmap_id, 1); - - XSetWindowBackgroundPixmap (GDK_DISPLAY(), GDK_ROOT_WINDOW(), pixmap_id); - XClearWindow (GDK_DISPLAY (), GDK_ROOT_WINDOW ()); - - XUngrabServer (GDK_DISPLAY()); - - XFlush(GDK_DISPLAY()); -} - -static void -image_loading_done_callback (EelBackground *background, gboolean successful_load, void *disconnect_signal) -{ - int width; - int height; - GdkGC *gc; - GdkPixmap *pixmap; - GdkWindow *background_window; - - if ((gboolean) GPOINTER_TO_INT (disconnect_signal)) { - gtk_signal_disconnect_by_func (GTK_OBJECT (background), - GTK_SIGNAL_FUNC (image_loading_done_callback), - disconnect_signal); - } - - width = gdk_screen_width (); - height = gdk_screen_height (); - - pixmap = make_root_pixmap (width, height); - gc = gdk_gc_new (pixmap); - eel_background_draw_to_drawable (background, pixmap, gc, 0, 0, width, height, width, height); - gdk_gc_unref (gc); - - set_root_pixmap (pixmap); - - background_window = eel_background_get_desktop_background_window (background); - if (background_window != NULL) { - gdk_window_set_back_pixmap (background_window, pixmap, FALSE); - } - - /* We'd like to simply unref pixmap here, but due to a bug in gdk's handling of - * foreign pixmaps, we can't - it would free the X resource. - * - * gdk_window_set_back_pixmap does not need the gdk pixmap object to stick around. - * It simply uses X resource inside it. dispose_root_pixmap free's the gdk object - * and not the X resource. - */ - dispose_root_pixmap (pixmap); -} - -static void -nautilus_file_update_desktop_pixmaps (EelBackground *background) -{ - if (eel_background_is_loaded (background)) { - image_loading_done_callback (background, TRUE, GINT_TO_POINTER (FALSE)); - } else { - gtk_signal_connect (GTK_OBJECT (background), - "image_loading_done", - GTK_SIGNAL_FUNC (image_loading_done_callback), - GINT_TO_POINTER (TRUE)); - } -} - -static gboolean -nautilus_file_background_matches_default_settings ( - const char* color, const char* default_color, - const char* image, const char* default_image, - EelBackgroundImagePlacement placement, EelBackgroundImagePlacement default_placement) -{ - gboolean match_color; - gboolean match_image; - - /* A NULL default color or image is not considered when determining a match. - */ - - match_color = (default_color == NULL) || eel_strcmp (color, default_color) == 0; - - match_image = (default_image == NULL) || - ((eel_strcmp (image, default_image) == 0) && (placement == default_placement)); - return match_color && match_image; -} - -/* return true if the background is not in the default state */ -gboolean -nautilus_file_background_is_set (EelBackground *background) -{ - char *color; - char *image; - char *default_color; - char *default_image; - - gboolean matches; - - EelBackgroundImagePlacement placement; - EelBackgroundImagePlacement default_placement; - - color = eel_background_get_color (background); - image = eel_background_get_image_uri (background); - placement = eel_background_get_image_placement (background); - - nautilus_file_background_get_default_settings ( - nautilus_file_background_peek_theme_source (background), - &default_color, &default_image, &default_placement); - - matches = nautilus_file_background_matches_default_settings (color, default_color, - image, default_image, - placement, default_placement); - - g_free (color); - g_free (image); - g_free (default_color); - g_free (default_image); - - return !matches; -} - -/* handle the background changed signal */ -static void -background_changed_callback (EelBackground *background, - NautilusFile *file) -{ - char *color; - char *image; - - g_assert (EEL_IS_BACKGROUND (background)); - g_assert (NAUTILUS_IS_FILE (file)); - g_assert (gtk_object_get_data (GTK_OBJECT (background), "eel_background_file") == file); - - - color = eel_background_get_color (background); - image = eel_background_get_image_uri (background); - - if (eel_background_is_desktop (background)) { - nautilus_file_background_write_desktop_settings (color, image, eel_background_get_image_placement (background)); - } else { - /* Block the other handler while we are writing metadata so it doesn't - * try to change the background. - */ - gtk_signal_handler_block_by_func (GTK_OBJECT (file), - saved_settings_changed_callback, - background); - - nautilus_file_set_metadata (file, - NAUTILUS_METADATA_KEY_LOCATION_BACKGROUND_COLOR, - NULL, - color); - - nautilus_file_set_metadata (file, - NAUTILUS_METADATA_KEY_LOCATION_BACKGROUND_IMAGE, - NULL, - image); - - /* Unblock the handler. */ - gtk_signal_handler_unblock_by_func (GTK_OBJECT (file), - saved_settings_changed_callback, - background); - } - - g_free (color); - g_free (image); - - if (eel_background_is_desktop (background)) { - nautilus_file_update_desktop_pixmaps (background); - } -} - -static void -initialize_background_from_settings (NautilusFile *file, - EelBackground *background) -{ - char *color; - char *image; - EelBackgroundImagePlacement placement; - - g_assert (NAUTILUS_IS_FILE (file)); - g_assert (EEL_IS_BACKGROUND (background)); - g_assert (gtk_object_get_data (GTK_OBJECT (background), "eel_background_file") - == file); - - if (eel_background_is_desktop (background)) { - nautilus_file_background_read_desktop_settings (&color, &image, &placement); - } else { - color = nautilus_file_get_metadata (file, - NAUTILUS_METADATA_KEY_LOCATION_BACKGROUND_COLOR, - NULL); - image = nautilus_file_get_metadata (file, - NAUTILUS_METADATA_KEY_LOCATION_BACKGROUND_IMAGE, - NULL); - placement = EEL_BACKGROUND_TILED; /* non-tiled only avail for desktop, at least for now */ - - /* if there's none, read the default from the theme */ - if (color == NULL && image == NULL) { - nautilus_file_background_get_default_settings - (nautilus_file_background_peek_theme_source (background), - &color, &image, &placement); - } - } - - /* Block the other handler while we are responding to changes - * in the metadata so it doesn't try to change the metadata. - */ - gtk_signal_handler_block_by_func (GTK_OBJECT (background), - background_changed_callback, - file); - - eel_background_set_color (background, color); - eel_background_set_image_uri (background, image); - eel_background_set_image_placement (background, placement); - - /* Unblock the handler. */ - gtk_signal_handler_unblock_by_func (GTK_OBJECT (background), - background_changed_callback, - file); - - g_free (color); - g_free (image); -} - -/* handle the file changed signal */ -static void -saved_settings_changed_callback (NautilusFile *file, - EelBackground *background) -{ - initialize_background_from_settings (file, background); - - if (eel_background_is_desktop (background)) { - nautilus_file_update_desktop_pixmaps (background); - } -} - -/* handle the theme changing */ -static void -nautilus_file_background_theme_changed (gpointer user_data) -{ - NautilusFile *file; - EelBackground *background; - - background = EEL_BACKGROUND (user_data); - file = gtk_object_get_data (GTK_OBJECT (background), "eel_background_file"); - if (file) { - saved_settings_changed_callback (file, background); - } -} - -/* handle the background reset signal by setting values from the current theme */ -static void -background_reset_callback (EelBackground *background, - NautilusFile *file) -{ - if (eel_background_is_desktop (background)) { - nautilus_file_background_write_desktop_default_settings (); - } else { - /* Block the other handler while we are writing metadata so it doesn't - * try to change the background. - */ - gtk_signal_handler_block_by_func (GTK_OBJECT (file), - saved_settings_changed_callback, - background); - - /* reset the metadata */ - nautilus_file_set_metadata (file, - NAUTILUS_METADATA_KEY_LOCATION_BACKGROUND_COLOR, - NULL, - NULL); - - nautilus_file_set_metadata (file, - NAUTILUS_METADATA_KEY_LOCATION_BACKGROUND_IMAGE, - NULL, - NULL); - /* Unblock the handler. */ - gtk_signal_handler_unblock_by_func (GTK_OBJECT (file), - saved_settings_changed_callback, - background); - } - - saved_settings_changed_callback (file, background); -} - -/* handle the background destroyed signal */ -static void -background_destroyed_callback (EelBackground *background, - NautilusFile *file) -{ - gtk_signal_disconnect_by_func (GTK_OBJECT (file), - GTK_SIGNAL_FUNC (saved_settings_changed_callback), - background); - nautilus_file_monitor_remove (file, background); - nautilus_preferences_remove_callback (NAUTILUS_PREFERENCES_THEME, - nautilus_file_background_theme_changed, - background); -} - -/* key routine that hooks up a background and location */ -void -nautilus_connect_background_to_file_metadata (GtkWidget *widget, - NautilusFile *file) -{ - EelBackground *background; - gpointer old_file; - GList *attributes; - - /* Get at the background object we'll be connecting. */ - background = eel_get_widget_background (widget); - - /* Check if it is already connected. */ - old_file = gtk_object_get_data (GTK_OBJECT (background), "eel_background_file"); - if (old_file == file) { - return; - } - - /* Disconnect old signal handlers. */ - if (old_file != NULL) { - g_assert (NAUTILUS_IS_FILE (old_file)); - gtk_signal_disconnect_by_func (GTK_OBJECT (background), - GTK_SIGNAL_FUNC (background_changed_callback), - old_file); - gtk_signal_disconnect_by_func (GTK_OBJECT (background), - GTK_SIGNAL_FUNC (background_destroyed_callback), - old_file); - gtk_signal_disconnect_by_func (GTK_OBJECT (background), - GTK_SIGNAL_FUNC (background_reset_callback), - old_file); - gtk_signal_disconnect_by_func (GTK_OBJECT (old_file), - GTK_SIGNAL_FUNC (saved_settings_changed_callback), - background); - nautilus_file_monitor_remove (old_file, background); - nautilus_preferences_remove_callback (NAUTILUS_PREFERENCES_THEME, - nautilus_file_background_theme_changed, - background); - - } - - /* Attach the new directory. */ - nautilus_file_ref (file); - gtk_object_set_data_full (GTK_OBJECT (background), - "eel_background_file", - file, - (GtkDestroyNotify) nautilus_file_unref); - - /* Connect new signal handlers. */ - if (file != NULL) { - gtk_signal_connect (GTK_OBJECT (background), - "settings_changed", - GTK_SIGNAL_FUNC (background_changed_callback), - file); - gtk_signal_connect (GTK_OBJECT (background), - "destroy", - GTK_SIGNAL_FUNC (background_destroyed_callback), - file); - gtk_signal_connect (GTK_OBJECT (background), - "reset", - GTK_SIGNAL_FUNC (background_reset_callback), - file); - gtk_signal_connect (GTK_OBJECT (file), - "changed", - GTK_SIGNAL_FUNC (saved_settings_changed_callback), - background); - - /* arrange to receive file metadata */ - attributes = g_list_append (NULL, NAUTILUS_FILE_ATTRIBUTE_METADATA); - nautilus_file_monitor_add (file, - background, - attributes); - g_list_free (attributes); - - /* arrange for notification when the theme changes */ - nautilus_preferences_add_callback (NAUTILUS_PREFERENCES_THEME, - nautilus_file_background_theme_changed, background); - - } - - /* Update the background based on the file metadata. */ - initialize_background_from_settings (file, background); -} - -void -nautilus_connect_background_to_file_metadata_by_uri (GtkWidget *widget, - const char *uri) -{ - NautilusFile *file; - file = nautilus_file_get (uri); - nautilus_connect_background_to_file_metadata (widget, file); - nautilus_file_unref (file); -} diff --git a/libnautilus-extensions/nautilus-directory-background.h b/libnautilus-extensions/nautilus-directory-background.h deleted file mode 100644 index 31f376038..000000000 --- a/libnautilus-extensions/nautilus-directory-background.h +++ /dev/null @@ -1,39 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */ - -/* - nautilus-directory-background.h: Helper for the background of a widget - that is viewing a particular directory. - - 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. - - Author: Darin Adler <darin@eazel.com> -*/ - -#include <gtk/gtkwidget.h> -#include "nautilus-file.h" -#include <eel/eel-background.h> -#include "libnautilus-extensions/nautilus-icon-container.h" - -void nautilus_connect_background_to_file_metadata (GtkWidget *widget, - NautilusFile *file); -void nautilus_connect_desktop_background_to_file_metadata (NautilusIconContainer *icon_container, - NautilusFile *file); -void nautilus_connect_background_to_file_metadata_by_uri (GtkWidget *widget, - const char *uri); -gboolean nautilus_file_background_is_set (EelBackground *background); - diff --git a/libnautilus-extensions/nautilus-directory-metafile-monitor.c b/libnautilus-extensions/nautilus-directory-metafile-monitor.c deleted file mode 100644 index 27dd58d72..000000000 --- a/libnautilus-extensions/nautilus-directory-metafile-monitor.c +++ /dev/null @@ -1,135 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ - -/* nautilus-directory-metafile-monitor.c - * - * Copyright (C) 2001 Eazel, Inc. - * - * 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. - * - * This 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; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#include <config.h> -#include "nautilus-directory-metafile-monitor.h" - -#include "nautilus-directory-private.h" -#include "nautilus-file-private.h" - -#include <eel/eel-gtk-macros.h> -#include <eel/eel-glib-extensions.h> -#include <libnautilus-extensions/nautilus-bonobo-extensions.h> -#include <libnautilus/nautilus-bonobo-workarounds.h> - -struct NautilusMetafileMonitorDetails { - NautilusDirectory *directory; -}; - -static void nautilus_metafile_monitor_init (NautilusMetafileMonitor *monitor); -static void nautilus_metafile_monitor_class_init (NautilusMetafileMonitorClass *klass); - -static void destroy (GtkObject *monitor); - -static void corba_metafile_changed (PortableServer_Servant servant, - const Nautilus_FileNameList *file_names, - CORBA_Environment *ev); - -static void corba_metafile_ready (PortableServer_Servant servant, - CORBA_Environment *ev); - -NAUTILUS_BONOBO_X_BOILERPLATE (NautilusMetafileMonitor, Nautilus_MetafileMonitor, BONOBO_X_OBJECT_TYPE, nautilus_metafile_monitor) - -static void -nautilus_metafile_monitor_class_init (NautilusMetafileMonitorClass *klass) -{ - GTK_OBJECT_CLASS (klass)->destroy = destroy; - - klass->epv.metafile_changed = corba_metafile_changed; - klass->epv.metafile_ready = corba_metafile_ready; -} - -static void -nautilus_metafile_monitor_init (NautilusMetafileMonitor *monitor) -{ - monitor->details = g_new0 (NautilusMetafileMonitorDetails, 1); -} - -static void -destroy (GtkObject *object) -{ - NautilusMetafileMonitor *monitor; - - monitor = NAUTILUS_METAFILE_MONITOR (object); - g_free (monitor->details); - - EEL_CALL_PARENT (GTK_OBJECT_CLASS, destroy, (object)); -} - -NautilusMetafileMonitor * -nautilus_metafile_monitor_new (NautilusDirectory *directory) -{ - NautilusMetafileMonitor *monitor; - monitor = NAUTILUS_METAFILE_MONITOR (gtk_object_new (NAUTILUS_TYPE_METAFILE_MONITOR, NULL)); - monitor->details->directory = directory; - /* The monitor is owned by the directory, so we don't ref the directory. */ - return monitor; -} - -static void -corba_metafile_changed (PortableServer_Servant servant, - const Nautilus_FileNameList *file_names, - CORBA_Environment *ev) -{ - GList *file_list; - NautilusFile *file; - CORBA_unsigned_long buf_pos; - NautilusMetafileMonitor *monitor; - - monitor = NAUTILUS_METAFILE_MONITOR (bonobo_object_from_servant (servant)); - - file_list = NULL; - - for (buf_pos = 0; buf_pos < file_names->_length; ++buf_pos) { - file = nautilus_directory_find_file_by_internal_uri - (monitor->details->directory, file_names->_buffer [buf_pos]); - - if (file != NULL) { - if (nautilus_file_is_self_owned (file)) { - nautilus_file_emit_changed (file); - } else { - file_list = g_list_prepend (file_list, file); - } - } - } - - if (file_list != NULL) { - file_list = g_list_reverse (file_list); - nautilus_directory_emit_change_signals (monitor->details->directory, file_list); - g_list_free (file_list); - } -} - -static void -corba_metafile_ready (PortableServer_Servant servant, - CORBA_Environment *ev) -{ - NautilusMetafileMonitor *monitor; - - monitor = NAUTILUS_METAFILE_MONITOR (bonobo_object_from_servant (servant)); - emit_change_signals_for_all_files (monitor->details->directory); - nautilus_idle_queue_add (monitor->details->directory->details->idle_queue, - (GFunc) nautilus_directory_async_state_changed, - monitor->details->directory, - NULL, - NULL); -} diff --git a/libnautilus-extensions/nautilus-directory-metafile-monitor.h b/libnautilus-extensions/nautilus-directory-metafile-monitor.h deleted file mode 100644 index ef8e0ee22..000000000 --- a/libnautilus-extensions/nautilus-directory-metafile-monitor.h +++ /dev/null @@ -1,55 +0,0 @@ -/* -*- Mode: IDL; tab-width: 8; indent-tabs-mode: 8; c-basic-offset: 8 -*- */ - -/* nautilus-directory-metafile-monitor.h - * - * Copyright (C) 2001 Eazel, Inc. - * - * 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. - * - * This 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; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef NAUTILUS_METAFILE_MONITOR_H -#define NAUTILUS_METAFILE_MONITOR_H - -#include "nautilus-metafile-server.h" - -#include <bonobo/bonobo-object.h> -#include <bonobo/bonobo-xobject.h> -#include <libnautilus-extensions/nautilus-directory.h> - -#define NAUTILUS_TYPE_METAFILE_MONITOR (nautilus_metafile_monitor_get_type ()) -#define NAUTILUS_METAFILE_MONITOR(obj) (GTK_CHECK_CAST ((obj), NAUTILUS_TYPE_METAFILE_MONITOR, NautilusMetafileMonitor)) -#define NAUTILUS_METAFILE_MONITOR_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), NAUTILUS_TYPE_METAFILE_MONITOR, NautilusMetafileMonitorClass)) -#define NAUTILUS_IS_METAFILE_MONITOR(obj) (GTK_CHECK_TYPE ((obj), NAUTILUS_TYPE_METAFILE_MONITOR)) -#define NAUTILUS_IS_METAFILE_MONITOR_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), NAUTILUS_TYPE_METAFILE_MONITOR)) - -typedef struct NautilusMetafileMonitorDetails NautilusMetafileMonitorDetails; - -typedef struct { - BonoboXObject parent_slot; - NautilusMetafileMonitorDetails *details; -} NautilusMetafileMonitor; - -typedef struct { - BonoboXObjectClass parent_slot; - POA_Nautilus_MetafileMonitor__epv epv; -} NautilusMetafileMonitorClass; - -GtkType nautilus_metafile_monitor_get_type (void); - - -NautilusMetafileMonitor *nautilus_metafile_monitor_new (NautilusDirectory *directory); - -#endif /* NAUTILUS_METAFILE_MONITOR_H */ diff --git a/libnautilus-extensions/nautilus-directory-metafile.c b/libnautilus-extensions/nautilus-directory-metafile.c deleted file mode 100644 index 06038abd1..000000000 --- a/libnautilus-extensions/nautilus-directory-metafile.c +++ /dev/null @@ -1,518 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- - - nautilus-directory-metafile.c: Nautilus directory model. - - Copyright (C) 2000, 2001 Eazel, Inc. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public - License along with this program; if not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. - - Authors: Darin Adler <darin@eazel.com>, - Mike Engber <engber@eazel.com> -*/ - -#include <config.h> -#include "nautilus-directory-metafile.h" -#include "nautilus-directory-private.h" - -#include <libnautilus-extensions/nautilus-metafile-factory.h> -#include <libnautilus-extensions/nautilus-directory-metafile-monitor.h> -#include <libnautilus-extensions/nautilus-metafile-server.h> -#include <eel/eel-string.h> -#include <liboaf/liboaf.h> -#include <stdio.h> - -static Nautilus_MetafileFactory factory = CORBA_OBJECT_NIL; -static gboolean get_factory_from_oaf = TRUE; - -void -nautilus_directory_use_self_contained_metafile_factory (void) -{ - g_return_if_fail (factory == CORBA_OBJECT_NIL); - - get_factory_from_oaf = FALSE; -} - -static void -free_factory (void) -{ - bonobo_object_release_unref (factory, NULL); -} - -static Nautilus_MetafileFactory -get_factory (void) -{ - NautilusMetafileFactory *instance; - - if (factory == CORBA_OBJECT_NIL) { - if (get_factory_from_oaf) { - factory = oaf_activate_from_id (METAFILE_FACTORY_IID, 0, NULL, NULL); - } else { - instance = nautilus_metafile_factory_get_instance (); - factory = bonobo_object_dup_ref (bonobo_object_corba_objref (BONOBO_OBJECT (instance)), NULL); - bonobo_object_unref (BONOBO_OBJECT (instance)); - } - g_atexit (free_factory); - } - - return factory; -} - -static Nautilus_Metafile -get_metafile (NautilusDirectory *directory) -{ - char *uri; - CORBA_Environment ev; - - uri = nautilus_directory_get_uri (directory); - - CORBA_exception_init (&ev); - - if (directory->details->metafile_corba_object == CORBA_OBJECT_NIL) { - directory->details->metafile_corba_object = Nautilus_MetafileFactory_open (get_factory (), uri, &ev); - } - - /* FIXME bugzilla.eazel.com 6664: examine ev for errors */ - CORBA_exception_free (&ev); - - g_free (uri); - - return bonobo_object_dup_ref (directory->details->metafile_corba_object, NULL); -} - -gboolean -nautilus_directory_is_metadata_read (NautilusDirectory *directory) -{ - CORBA_Environment ev; - Nautilus_Metafile metafile; - - gboolean result; - - g_return_val_if_fail (NAUTILUS_IS_DIRECTORY (directory), FALSE); - - metafile = get_metafile (directory); - CORBA_exception_init (&ev); - - result = Nautilus_Metafile_is_read (metafile, &ev); - - /* FIXME bugzilla.eazel.com 6664: examine ev for errors */ - CORBA_exception_free (&ev); - bonobo_object_release_unref (metafile, NULL); - - return result; -} - -char * -nautilus_directory_get_file_metadata (NautilusDirectory *directory, - const char *file_name, - const char *key, - const char *default_metadata) -{ - CORBA_Environment ev; - Nautilus_Metafile metafile; - - char *result; - const char *non_null_default; - CORBA_char *corba_value; - - g_return_val_if_fail (NAUTILUS_IS_DIRECTORY (directory), NULL); - g_return_val_if_fail (!eel_str_is_empty (file_name), NULL); - g_return_val_if_fail (!eel_str_is_empty (key), NULL); - - /* We can't pass NULL as a CORBA_string - pass "" instead. */ - non_null_default = default_metadata != NULL ? default_metadata : ""; - - metafile = get_metafile (directory); - CORBA_exception_init (&ev); - - corba_value = Nautilus_Metafile_get (metafile, file_name, key, non_null_default, &ev); - - /* FIXME bugzilla.eazel.com 6664: examine ev for errors */ - CORBA_exception_free (&ev); - bonobo_object_release_unref (metafile, NULL); - - if (eel_str_is_empty (corba_value)) { - /* Even though in all other respects we treat "" as NULL, we want to - * make sure the caller gets back the same default that was passed in. - */ - result = g_strdup (default_metadata); - } else { - result = g_strdup (corba_value); - } - - CORBA_free (corba_value); - - return result; -} - -GList * -nautilus_directory_get_file_metadata_list (NautilusDirectory *directory, - const char *file_name, - const char *list_key, - const char *list_subkey) -{ - CORBA_Environment ev; - Nautilus_Metafile metafile; - - GList *result; - Nautilus_MetadataList *corba_value; - CORBA_unsigned_long buf_pos; - - g_return_val_if_fail (NAUTILUS_IS_DIRECTORY (directory), NULL); - g_return_val_if_fail (!eel_str_is_empty (file_name), NULL); - g_return_val_if_fail (!eel_str_is_empty (list_key), NULL); - g_return_val_if_fail (!eel_str_is_empty (list_subkey), NULL); - - metafile = get_metafile (directory); - CORBA_exception_init (&ev); - - corba_value = Nautilus_Metafile_get_list (metafile, file_name, list_key, list_subkey, &ev); - - /* FIXME bugzilla.eazel.com 6664: examine ev for errors */ - CORBA_exception_free (&ev); - bonobo_object_release_unref (metafile, NULL); - - result = NULL; - for (buf_pos = 0; buf_pos < corba_value->_length; ++buf_pos) { - result = g_list_prepend (result, g_strdup (corba_value->_buffer [buf_pos])); - } - result = g_list_reverse (result); - CORBA_free (corba_value); - - return result; -} - -void -nautilus_directory_set_file_metadata (NautilusDirectory *directory, - const char *file_name, - const char *key, - const char *default_metadata, - const char *metadata) -{ - CORBA_Environment ev; - Nautilus_Metafile metafile; - - g_return_if_fail (NAUTILUS_IS_DIRECTORY (directory)); - g_return_if_fail (!eel_str_is_empty (file_name)); - g_return_if_fail (!eel_str_is_empty (key)); - - /* We can't pass NULL as a CORBA_string - pass "" instead. - */ - if (default_metadata == NULL) { - default_metadata = ""; - } - if (metadata == NULL) { - metadata = ""; - } - - metafile = get_metafile (directory); - CORBA_exception_init (&ev); - - Nautilus_Metafile_set (metafile, file_name, key, default_metadata, metadata, &ev); - - /* FIXME bugzilla.eazel.com 6664: examine ev for errors */ - CORBA_exception_free (&ev); - bonobo_object_release_unref (metafile, NULL); -} - -void -nautilus_directory_set_file_metadata_list (NautilusDirectory *directory, - const char *file_name, - const char *list_key, - const char *list_subkey, - GList *list) -{ - CORBA_Environment ev; - Nautilus_Metafile metafile; - - Nautilus_MetadataList *corba_list; - int len; - int buf_pos; - GList *list_ptr; - - g_return_if_fail (NAUTILUS_IS_DIRECTORY (directory)); - g_return_if_fail (!eel_str_is_empty (file_name)); - g_return_if_fail (!eel_str_is_empty (list_key)); - g_return_if_fail (!eel_str_is_empty (list_subkey)); - - len = g_list_length (list); - - corba_list = Nautilus_MetadataList__alloc (); - corba_list->_maximum = len; - corba_list->_length = len; - corba_list->_buffer = CORBA_sequence_CORBA_string_allocbuf (len); - - /* We allocate our buffer with CORBA calls, so CORBA_free will clean it - * all up if we set release to TRUE. - */ - CORBA_sequence_set_release (corba_list, CORBA_TRUE); - - buf_pos = 0; - list_ptr = list; - while (list_ptr != NULL) { - corba_list->_buffer [buf_pos] = CORBA_string_dup (list_ptr->data); - list_ptr = g_list_next (list_ptr); - ++buf_pos; - } - - metafile = get_metafile (directory); - CORBA_exception_init (&ev); - - Nautilus_Metafile_set_list (metafile, file_name, list_key, list_subkey, corba_list, &ev); - - /* FIXME bugzilla.eazel.com 6664: examine ev for errors */ - CORBA_exception_free (&ev); - bonobo_object_release_unref (metafile, NULL); - - CORBA_free (corba_list); -} - -gboolean -nautilus_directory_get_boolean_file_metadata (NautilusDirectory *directory, - const char *file_name, - const char *key, - gboolean default_metadata) -{ - char *result_as_string; - gboolean result; - - result_as_string = nautilus_directory_get_file_metadata - (directory, file_name, key, - default_metadata ? "true" : "false"); - - g_strdown (result_as_string); - if (strcmp (result_as_string, "true") == 0) { - result = TRUE; - } else if (strcmp (result_as_string, "false") == 0) { - result = FALSE; - } else { - if (result_as_string != NULL) { - g_warning ("boolean metadata with value other than true or false"); - } - result = default_metadata; - } - - g_free (result_as_string); - return result; -} - -void -nautilus_directory_set_boolean_file_metadata (NautilusDirectory *directory, - const char *file_name, - const char *key, - gboolean default_metadata, - gboolean metadata) -{ - nautilus_directory_set_file_metadata - (directory, file_name, key, - default_metadata ? "true" : "false", - metadata ? "true" : "false"); -} - -int -nautilus_directory_get_integer_file_metadata (NautilusDirectory *directory, - const char *file_name, - const char *key, - int default_metadata) -{ - char *result_as_string; - char *default_as_string; - int result; - - default_as_string = g_strdup_printf ("%d", default_metadata); - result_as_string = nautilus_directory_get_file_metadata - (directory, file_name, key, default_as_string); - - /* Normally we can't get a a NULL, but we check for it here to - * handle the oddball case of a non-existent directory. - */ - if (result_as_string == NULL) { - result = default_metadata; - } else { - if (sscanf (result_as_string, " %d %*s", &result) != 1) { - result = default_metadata; - } - g_free (result_as_string); - } - - g_free (default_as_string); - return result; -} - -void -nautilus_directory_set_integer_file_metadata (NautilusDirectory *directory, - const char *file_name, - const char *key, - int default_metadata, - int metadata) -{ - char *value_as_string; - char *default_as_string; - - value_as_string = g_strdup_printf ("%d", metadata); - default_as_string = g_strdup_printf ("%d", default_metadata); - - nautilus_directory_set_file_metadata - (directory, file_name, key, - default_as_string, value_as_string); - - g_free (value_as_string); - g_free (default_as_string); -} - -void -nautilus_directory_copy_file_metadata (NautilusDirectory *source_directory, - const char *source_file_name, - NautilusDirectory *destination_directory, - const char *destination_file_name) -{ - CORBA_Environment ev; - Nautilus_Metafile source_metafile; - char* destination_uri; - - g_return_if_fail (NAUTILUS_IS_DIRECTORY (source_directory)); - g_return_if_fail (source_file_name != NULL); - g_return_if_fail (NAUTILUS_IS_DIRECTORY (destination_directory)); - g_return_if_fail (destination_file_name != NULL); - - destination_uri = nautilus_directory_get_uri (destination_directory); - - source_metafile = get_metafile (source_directory); - CORBA_exception_init (&ev); - - Nautilus_Metafile_copy (source_metafile, source_file_name, destination_uri, destination_file_name, &ev); - - /* FIXME bugzilla.eazel.com 6664: examine ev for errors */ - CORBA_exception_free (&ev); - bonobo_object_release_unref (source_metafile, NULL); - - g_free (destination_uri); -} - -void -nautilus_directory_remove_file_metadata (NautilusDirectory *directory, - const char *file_name) -{ - CORBA_Environment ev; - Nautilus_Metafile metafile; - - g_return_if_fail (NAUTILUS_IS_DIRECTORY (directory)); - g_return_if_fail (file_name != NULL); - - metafile = get_metafile (directory); - CORBA_exception_init (&ev); - - Nautilus_Metafile_remove (metafile, file_name, &ev); - - /* FIXME bugzilla.eazel.com 6664: examine ev for errors */ - CORBA_exception_free (&ev); - bonobo_object_release_unref (metafile, NULL); -} - -void -nautilus_directory_rename_file_metadata (NautilusDirectory *directory, - const char *old_file_name, - const char *new_file_name) -{ - CORBA_Environment ev; - Nautilus_Metafile metafile; - - g_return_if_fail (NAUTILUS_IS_DIRECTORY (directory)); - g_return_if_fail (old_file_name != NULL); - g_return_if_fail (new_file_name != NULL); - - metafile = get_metafile (directory); - CORBA_exception_init (&ev); - - Nautilus_Metafile_rename (metafile, old_file_name, new_file_name, &ev); - - /* FIXME bugzilla.eazel.com 6664: examine ev for errors */ - CORBA_exception_free (&ev); - bonobo_object_release_unref (metafile, &ev); -} - -void -nautilus_directory_rename_directory_metadata (NautilusDirectory *directory, - const char *new_directory_uri) -{ - CORBA_Environment ev; - Nautilus_Metafile metafile; - - g_return_if_fail (NAUTILUS_IS_DIRECTORY (directory)); - g_return_if_fail (new_directory_uri != NULL); - - metafile = get_metafile (directory); - CORBA_exception_init (&ev); - - Nautilus_Metafile_rename_directory (metafile, new_directory_uri, &ev); - - /* FIXME bugzilla.eazel.com 6664: examine ev for errors */ - CORBA_exception_free (&ev); - bonobo_object_release_unref (metafile, &ev); -} - -void -nautilus_directory_register_metadata_monitor (NautilusDirectory *directory) -{ - CORBA_Environment ev; - Nautilus_Metafile metafile; - - g_return_if_fail (NAUTILUS_IS_DIRECTORY (directory)); - - if (directory->details->metafile_monitor != NULL) { - /* If there's already a monitor, it's already registered. */ - return; - } - - directory->details->metafile_monitor = nautilus_metafile_monitor_new (directory); - - metafile = get_metafile (directory); - CORBA_exception_init (&ev); - - Nautilus_Metafile_register_monitor - (metafile, - bonobo_object_corba_objref (BONOBO_OBJECT (directory->details->metafile_monitor)), - &ev); - - /* FIXME bugzilla.eazel.com 6664: examine ev for errors */ - CORBA_exception_free (&ev); - bonobo_object_release_unref (metafile, NULL); -} - -void -nautilus_directory_unregister_metadata_monitor (NautilusDirectory *directory) -{ - CORBA_Environment ev; - Nautilus_Metafile metafile; - - g_return_if_fail (NAUTILUS_IS_DIRECTORY (directory)); - - g_return_if_fail (NAUTILUS_IS_METAFILE_MONITOR (directory->details->metafile_monitor)); - - metafile = get_metafile (directory); - CORBA_exception_init (&ev); - - Nautilus_Metafile_unregister_monitor - (metafile, - bonobo_object_corba_objref (BONOBO_OBJECT (directory->details->metafile_monitor)), - &ev); - - /* FIXME bugzilla.eazel.com 6664: examine ev for errors */ - CORBA_exception_free (&ev); - bonobo_object_release_unref (metafile, NULL); - - directory->details->metafile_monitor = NULL; -} - diff --git a/libnautilus-extensions/nautilus-directory-metafile.h b/libnautilus-extensions/nautilus-directory-metafile.h deleted file mode 100644 index ffe6eb4a5..000000000 --- a/libnautilus-extensions/nautilus-directory-metafile.h +++ /dev/null @@ -1,83 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- - - nautilus-directory-metafile.h: Nautilus directory model. - - 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. - - Author: Darin Adler <darin@eazel.com> -*/ - -#include "nautilus-directory.h" - -/* Interface for file metadata. */ -gboolean nautilus_directory_is_metadata_read (NautilusDirectory *directory); - -char * nautilus_directory_get_file_metadata (NautilusDirectory *directory, - const char *file_name, - const char *key, - const char *default_metadata); -GList * nautilus_directory_get_file_metadata_list (NautilusDirectory *directory, - const char *file_name, - const char *list_key, - const char *list_subkey); -gboolean nautilus_directory_get_boolean_file_metadata (NautilusDirectory *directory, - const char *file_name, - const char *key, - gboolean default_metadata); -int nautilus_directory_get_integer_file_metadata (NautilusDirectory *directory, - const char *file_name, - const char *key, - int default_metadata); - -void nautilus_directory_set_file_metadata (NautilusDirectory *directory, - const char *file_name, - const char *key, - const char *default_metadata, - const char *metadata); -void nautilus_directory_set_file_metadata_list (NautilusDirectory *directory, - const char *file_name, - const char *list_key, - const char *list_subkey, - GList *list); -void nautilus_directory_set_boolean_file_metadata (NautilusDirectory *directory, - const char *file_name, - const char *key, - gboolean default_metadata, - gboolean metadata); -void nautilus_directory_set_integer_file_metadata (NautilusDirectory *directory, - const char *file_name, - const char *key, - int default_metadata, - int metadata); - -void nautilus_directory_copy_file_metadata (NautilusDirectory *source_directory, - const char *source_file_name, - NautilusDirectory *destination_directory, - const char *destination_file_name); -void nautilus_directory_remove_file_metadata (NautilusDirectory *directory, - const char *file_name); -void nautilus_directory_rename_file_metadata (NautilusDirectory *directory, - const char *old_file_name, - const char *new_file_name); -void nautilus_directory_rename_directory_metadata (NautilusDirectory *directory, - const char *new_directory_uri); - -void nautilus_directory_register_metadata_monitor (NautilusDirectory *directory); -void nautilus_directory_unregister_metadata_monitor (NautilusDirectory *directory); - -void nautilus_directory_use_self_contained_metafile_factory (void); diff --git a/libnautilus-extensions/nautilus-directory-notify.h b/libnautilus-extensions/nautilus-directory-notify.h deleted file mode 100644 index 73c798c0f..000000000 --- a/libnautilus-extensions/nautilus-directory-notify.h +++ /dev/null @@ -1,55 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- - - nautilus-directory-notify.h: Nautilus directory notify calls. - - Copyright (C) 2000, 2001 Eazel, Inc. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public - License along with this program; if not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. - - Author: Darin Adler <darin@eazel.com> -*/ - -#include <glib.h> -#include <gdk/gdk.h> -#include <libnautilus-extensions/nautilus-file.h> - -typedef struct { - char *from_uri; - char *to_uri; -} URIPair; - -typedef struct { - char *uri; - gboolean set; - GdkPoint point; -} NautilusFileChangesQueuePosition; - -/* Almost-public change notification calls */ -void nautilus_directory_notify_files_added (GList *uris); -void nautilus_directory_notify_files_changed (GList *uris); -void nautilus_directory_notify_files_moved (GList *uri_pairs); -void nautilus_directory_notify_files_removed (GList *uris); -void nautilus_directory_schedule_metadata_copy (GList *uri_pairs); -void nautilus_directory_schedule_metadata_move (GList *uri_pairs); -void nautilus_directory_schedule_metadata_remove (GList *uris); -void nautilus_directory_schedule_position_set (GList *position_setting_list); - -/* Change notification hack. - * This is called when code modifies the file and it needs to trigger - * a notification. Eventually this should become private, but for now - * it needs to be used for code like the thumbnail generation. - */ -void nautilus_file_changed (NautilusFile *file); diff --git a/libnautilus-extensions/nautilus-directory-private.h b/libnautilus-extensions/nautilus-directory-private.h deleted file mode 100644 index 65ef808f5..000000000 --- a/libnautilus-extensions/nautilus-directory-private.h +++ /dev/null @@ -1,206 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- - - nautilus-directory-private.h: Nautilus directory model. - - Copyright (C) 1999, 2000, 2001 Eazel, Inc. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public - License along with this program; if not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. - - Author: Darin Adler <darin@eazel.com> -*/ - -#include "nautilus-directory-metafile-monitor.h" -#include "nautilus-directory.h" -#include "nautilus-file.h" -#include "nautilus-metafile-server.h" -#include "nautilus-monitor.h" -#include <eel/eel-vfs-extensions.h> -#include <gnome-xml/tree.h> -#include <libgnomevfs/gnome-vfs-file-info.h> -#include <libgnomevfs/gnome-vfs-types.h> -#include <libgnomevfs/gnome-vfs-uri.h> -#include <libnautilus/nautilus-idle-queue.h> - -typedef struct ActivationURIReadState ActivationURIReadState; -typedef struct TopLeftTextReadState TopLeftTextReadState; -typedef struct FileMonitors FileMonitors; - -struct NautilusDirectoryDetails -{ - /* The location. */ - char *uri; - GnomeVFSURI *vfs_uri; - - /* The file objects. */ - NautilusFile *as_file; - GList *file_list; - GHashTable *file_hash; - - /* These lists are going to be pretty short. If we think they - * are going to get big, we can use hash tables instead. - */ - GList *call_when_ready_list; - GList *monitor_list; - - NautilusMonitor *monitor; - - NautilusIdleQueue *idle_queue; - NautilusMetafileMonitor *metafile_monitor; - Nautilus_Metafile metafile_corba_object; - - gboolean in_async_service_loop; - gboolean state_changed; - - gboolean file_list_monitored; - gboolean directory_loaded; - gboolean directory_loaded_sent_notification; - GnomeVFSAsyncHandle *directory_load_in_progress; - - GList *pending_file_info; /* list of GnomeVFSFileInfo's that are pending */ - int confirmed_file_count; - guint dequeue_pending_idle_id; - - NautilusFile *load_directory_file; - int load_file_count; - GnomeVFSDirectoryFilter *load_file_count_filter; - GHashTable *load_mime_list_hash; - - GList *get_file_infos_in_progress; /* list of GnomeVFSAsyncHandle * */ - - NautilusFile *count_file; - GnomeVFSAsyncHandle *count_in_progress; - - NautilusFile *deep_count_file; - GnomeVFSAsyncHandle *deep_count_in_progress; - char *deep_count_uri; - GList *deep_count_subdirectories; - - NautilusFile *mime_list_file; - GnomeVFSAsyncHandle *mime_list_in_progress; - GHashTable *mime_list_hash; - - NautilusFile *get_info_file; - GnomeVFSAsyncHandle *get_info_in_progress; - - TopLeftTextReadState *top_left_read_state; - ActivationURIReadState *activation_uri_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 deep_count; - gboolean directory_count; - gboolean file_info; - gboolean file_list; /* always FALSE if file != NULL */ - gboolean metafile; - gboolean mime_list; - gboolean top_left_text; -} Request; - -NautilusDirectory *nautilus_directory_get_existing (const char *uri); - -/* async. interface */ -void nautilus_directory_async_state_changed (NautilusDirectory *directory); -void nautilus_directory_call_when_ready_internal (NautilusDirectory *directory, - NautilusFile *file, - GList *file_attributes, - NautilusDirectoryCallback directory_callback, - NautilusFileCallback file_callback, - gpointer callback_data); -gboolean nautilus_directory_check_if_ready_internal (NautilusDirectory *directory, - NautilusFile *file, - GList *file_attributes); -void nautilus_directory_cancel_callback_internal (NautilusDirectory *directory, - NautilusFile *file, - NautilusDirectoryCallback directory_callback, - NautilusFileCallback file_callback, - gpointer callback_data); -void nautilus_directory_monitor_add_internal (NautilusDirectory *directory, - NautilusFile *file, - gconstpointer client, - gboolean monitor_hidden_files, - gboolean monitor_backup_files, - GList *attributes); -void nautilus_directory_monitor_remove_internal (NautilusDirectory *directory, - NautilusFile *file, - gconstpointer client); -void nautilus_directory_get_info_for_new_files (NautilusDirectory *directory, - GList *vfs_uris); -NautilusFile * nautilus_directory_get_existing_corresponding_file (NautilusDirectory *directory); -void nautilus_directory_invalidate_count_and_mime_list (NautilusDirectory *directory); -gboolean nautilus_directory_is_file_list_monitored (NautilusDirectory *directory); -gboolean nautilus_directory_is_anyone_monitoring_file_list (NautilusDirectory *directory); -void nautilus_directory_remove_file_monitor_link (NautilusDirectory *directory, - GList *link); -void nautilus_directory_schedule_dequeue_pending (NautilusDirectory *directory); -void nautilus_directory_stop_monitoring_file_list (NautilusDirectory *directory); -void nautilus_directory_cancel (NautilusDirectory *directory); -void nautilus_async_destroying_file (NautilusFile *file); -void nautilus_directory_force_reload_internal (NautilusDirectory *directory, - GList *file_attributes); -void nautilus_directory_cancel_loading_file_attributes (NautilusDirectory *directory, - NautilusFile *file, - GList *file_attributes); - -/* Calls shared between directory, file, and async. code. */ -void nautilus_directory_emit_files_added (NautilusDirectory *directory, - GList *added_files); -void nautilus_directory_emit_files_changed (NautilusDirectory *directory, - GList *changed_files); -void nautilus_directory_emit_change_signals (NautilusDirectory *directory, - GList *changed_files); -void emit_change_signals_for_all_files (NautilusDirectory *directory); -void nautilus_directory_emit_done_loading (NautilusDirectory *directory); -void nautilus_directory_emit_load_error (NautilusDirectory *directory, - GnomeVFSResult error_result); -NautilusDirectory *nautilus_directory_get_internal (const char *uri, - gboolean create); -char * nautilus_directory_get_name_for_self_as_new_file (NautilusDirectory *directory); -void nautilus_directory_set_up_request (Request *request, - GList *file_attributes); - -/* Interface to the file list. */ -NautilusFile * nautilus_directory_find_file_by_name (NautilusDirectory *directory, - const char *relative_uri); -NautilusFile * nautilus_directory_find_file_by_relative_uri (NautilusDirectory *directory, - const char *relative_uri); -NautilusFile * nautilus_directory_find_file_by_internal_uri (NautilusDirectory *directory, - const char *relative_uri); - -void nautilus_directory_add_file (NautilusDirectory *directory, - NautilusFile *file); -void nautilus_directory_remove_file (NautilusDirectory *directory, - NautilusFile *file); -FileMonitors * nautilus_directory_remove_file_monitors (NautilusDirectory *directory, - NautilusFile *file); -void nautilus_directory_add_file_monitors (NautilusDirectory *directory, - NautilusFile *file, - FileMonitors *monitors); -void nautilus_directory_add_file (NautilusDirectory *directory, - NautilusFile *file); -GList * nautilus_directory_begin_file_name_change (NautilusDirectory *directory, - NautilusFile *file); -void nautilus_directory_end_file_name_change (NautilusDirectory *directory, - NautilusFile *file, - GList *node); -void nautilus_directory_moved (const char *from_uri, - const char *to_uri); - -/* debugging functions */ -int nautilus_directory_number_outstanding (void); diff --git a/libnautilus-extensions/nautilus-directory.c b/libnautilus-extensions/nautilus-directory.c deleted file mode 100644 index 7c9a25a81..000000000 --- a/libnautilus-extensions/nautilus-directory.c +++ /dev/null @@ -1,1664 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- - - nautilus-directory.c: Nautilus directory model. - - Copyright (C) 1999, 2000, 2001 Eazel, Inc. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public - License along with this program; if not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. - - Author: Darin Adler <darin@eazel.com> -*/ - -#include <config.h> -#include "nautilus-directory-private.h" - -#include "nautilus-directory-metafile.h" -#include "nautilus-directory-notify.h" -#include "nautilus-file-private.h" -#include "nautilus-file-utilities.h" -#include "nautilus-global-preferences.h" -#include "nautilus-lib-self-check-functions.h" -#include "nautilus-metadata.h" -#include "nautilus-metafile.h" -#include "nautilus-trash-directory.h" -#include "nautilus-vfs-directory.h" -#include <ctype.h> -#include <eel/eel-glib-extensions.h> -#include <eel/eel-gtk-macros.h> -#include <eel/eel-string.h> -#include <gtk/gtkmain.h> -#include <gtk/gtksignal.h> - -enum { - FILES_ADDED, - FILES_CHANGED, - DONE_LOADING, - LOAD_ERROR, - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL]; - -/* Specifications for parallel-directory metafile. */ -#define METAFILES_DIRECTORY_NAME "metafiles" -#define METAFILE_SUFFIX ".xml" -#define METAFILES_DIRECTORY_PERMISSIONS \ - (GNOME_VFS_PERM_USER_ALL \ - | GNOME_VFS_PERM_GROUP_ALL \ - | GNOME_VFS_PERM_OTHER_ALL) - -static GHashTable *directories; - -static void nautilus_directory_destroy (GtkObject *object); -static void nautilus_directory_initialize (gpointer object, - gpointer klass); -static void nautilus_directory_initialize_class (NautilusDirectoryClass *klass); -static NautilusDirectory *nautilus_directory_new (const char *uri); -static char * real_get_name_for_self_as_new_file (NautilusDirectory *directory); -static void set_directory_uri (NautilusDirectory *directory, - const char *new_uri); - -EEL_DEFINE_CLASS_BOILERPLATE (NautilusDirectory, - nautilus_directory, - GTK_TYPE_OBJECT) - -static void -nautilus_directory_initialize_class (NautilusDirectoryClass *klass) -{ - GtkObjectClass *object_class; - - object_class = GTK_OBJECT_CLASS (klass); - - object_class->destroy = nautilus_directory_destroy; - - signals[FILES_ADDED] = - gtk_signal_new ("files_added", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (NautilusDirectoryClass, files_added), - gtk_marshal_NONE__POINTER, - GTK_TYPE_NONE, 1, GTK_TYPE_POINTER); - signals[FILES_CHANGED] = - gtk_signal_new ("files_changed", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (NautilusDirectoryClass, files_changed), - gtk_marshal_NONE__POINTER, - GTK_TYPE_NONE, 1, GTK_TYPE_POINTER); - signals[DONE_LOADING] = - gtk_signal_new ("done_loading", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (NautilusDirectoryClass, done_loading), - gtk_marshal_NONE__NONE, - GTK_TYPE_NONE, 0); - signals[LOAD_ERROR] = - gtk_signal_new ("load_error", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (NautilusDirectoryClass, load_error), - gtk_marshal_NONE__INT, - GTK_TYPE_NONE, 1, GTK_TYPE_INT); - - gtk_object_class_add_signals (object_class, signals, LAST_SIGNAL); - - klass->get_name_for_self_as_new_file = real_get_name_for_self_as_new_file; -} - -static void -nautilus_directory_initialize (gpointer object, gpointer klass) -{ - NautilusDirectory *directory; - - directory = NAUTILUS_DIRECTORY(object); - - directory->details = g_new0 (NautilusDirectoryDetails, 1); - directory->details->file_hash = g_hash_table_new (g_str_hash, g_str_equal); - directory->details->idle_queue = nautilus_idle_queue_new (); -} - -void -nautilus_directory_ref (NautilusDirectory *directory) -{ - if (directory == NULL) { - return; - } - - g_return_if_fail (NAUTILUS_IS_DIRECTORY (directory)); - - gtk_object_ref (GTK_OBJECT (directory)); -} - -void -nautilus_directory_unref (NautilusDirectory *directory) -{ - if (directory == NULL) { - return; - } - - g_return_if_fail (NAUTILUS_IS_DIRECTORY (directory)); - - gtk_object_unref (GTK_OBJECT (directory)); -} - -static void -nautilus_directory_destroy (GtkObject *object) -{ - NautilusDirectory *directory; - - directory = NAUTILUS_DIRECTORY (object); - - nautilus_directory_cancel (directory); - g_assert (directory->details->count_in_progress == NULL); - g_assert (directory->details->top_left_read_state == NULL); - - if (directory->details->monitor_list != NULL) { - g_warning ("destroying a NautilusDirectory while it's being monitored"); - eel_g_list_free_deep (directory->details->monitor_list); - } - - if (directory->details->monitor != NULL) { - nautilus_monitor_cancel (directory->details->monitor); - } - - if (directory->details->metafile_monitor != NULL) { - nautilus_directory_unregister_metadata_monitor (directory); - } - - if (directory->details->metafile_corba_object != CORBA_OBJECT_NIL) { - bonobo_object_release_unref (directory->details->metafile_corba_object, NULL); - } - - g_hash_table_remove (directories, directory->details->uri); - - if (directory->details->dequeue_pending_idle_id != 0) { - gtk_idle_remove (directory->details->dequeue_pending_idle_id); - } - - g_free (directory->details->uri); - if (directory->details->vfs_uri != NULL) { - gnome_vfs_uri_unref (directory->details->vfs_uri); - } - g_assert (directory->details->file_list == NULL); - g_hash_table_destroy (directory->details->file_hash); - 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); - g_assert (directory->details->dequeue_pending_idle_id == 0); - gnome_vfs_file_info_list_unref (directory->details->pending_file_info); - - g_free (directory->details); - - EEL_CALL_PARENT (GTK_OBJECT_CLASS, destroy, (object)); -} - -static void -invalidate_one_count (gpointer key, gpointer value, gpointer user_data) -{ - NautilusDirectory *directory; - - g_assert (key != NULL); - g_assert (NAUTILUS_IS_DIRECTORY (value)); - g_assert (user_data == NULL); - - directory = NAUTILUS_DIRECTORY (value); - - nautilus_directory_invalidate_count_and_mime_list (directory); -} - -static void -filtering_changed_callback (gpointer callback_data) -{ - g_assert (callback_data == NULL); - - /* Preference about which items to show has changed, so we - * can't trust any of our precomputed directory counts. - */ - g_hash_table_foreach (directories, invalidate_one_count, NULL); -} - -void -emit_change_signals_for_all_files (NautilusDirectory *directory) -{ - GList *files; - - files = eel_g_list_copy (directory->details->file_list); - if (directory->details->as_file != NULL) { - files = g_list_prepend (files, directory->details->as_file); - } - - nautilus_directory_emit_change_signals (directory, files); - - g_list_free (files); -} - -static void -async_state_changed_one (gpointer key, gpointer value, gpointer user_data) -{ - NautilusDirectory *directory; - - g_assert (key != NULL); - g_assert (NAUTILUS_IS_DIRECTORY (value)); - g_assert (user_data == NULL); - - directory = NAUTILUS_DIRECTORY (value); - - nautilus_directory_async_state_changed (directory); - emit_change_signals_for_all_files (directory); -} - -static void -async_data_preference_changed_callback (gpointer callback_data) -{ - g_assert (callback_data == NULL); - - /* Preference involving fetched async data has changed, so - * we have to kick off refetching all async data, and tell - * each file that it (might have) changed. - */ - g_hash_table_foreach (directories, async_state_changed_one, NULL); -} - -static void -add_preferences_callbacks (void) -{ - nautilus_preferences_add_callback (NAUTILUS_PREFERENCES_SHOW_HIDDEN_FILES, - filtering_changed_callback, - NULL); - nautilus_preferences_add_callback (NAUTILUS_PREFERENCES_SHOW_BACKUP_FILES, - filtering_changed_callback, - NULL); - nautilus_preferences_add_callback (NAUTILUS_PREFERENCES_SHOW_TEXT_IN_ICONS, - async_data_preference_changed_callback, - NULL); - nautilus_preferences_add_callback (NAUTILUS_PREFERENCES_SHOW_DIRECTORY_ITEM_COUNTS, - async_data_preference_changed_callback, - NULL); - nautilus_preferences_add_callback (NAUTILUS_PREFERENCES_DEFAULT_SMOOTH_FONT, - async_data_preference_changed_callback, - NULL); -} - -char * -nautilus_directory_make_uri_canonical (const char *uri) -{ - char *canonical_maybe_trailing_slash; - char *canonical; - char *with_slashes; - size_t length; - - canonical_maybe_trailing_slash = eel_make_uri_canonical (uri); - - /* To NautilusDirectory, a uri with or without a trailing - * / is equivalent. This is necessary to prevent separate - * NautilusDirectories for the same location from being - * created. (See bugzilla.eazel.com 3322 for an example.) - */ - canonical = eel_str_strip_trailing_chr (canonical_maybe_trailing_slash, '/'); - if (strcmp (canonical, canonical_maybe_trailing_slash) != 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 - * that "file:///" still works as a URI. - */ - length = strlen (canonical); - if (length == 0 || canonical[length - 1] == ':') { - with_slashes = g_strconcat (canonical, "///", NULL); - g_free (canonical); - canonical = with_slashes; - } - } - - g_free (canonical_maybe_trailing_slash); - - return canonical; -} - - -/** - * nautilus_directory_get: - * @uri: URI of directory to get. - * - * Get a directory given a uri. - * Creates the appropriate subclass given the uri mappings. - * Returns a referenced object, not a floating one. Unref when finished. - * If two windows are viewing the same uri, the directory object is shared. - */ -NautilusDirectory * -nautilus_directory_get_internal (const char *uri, gboolean create) -{ - char *canonical_uri; - NautilusDirectory *directory; - - if (uri == NULL) { - return NULL; - } - - canonical_uri = nautilus_directory_make_uri_canonical (uri); - - /* Create the hash table first time through. */ - if (directories == NULL) { - directories = eel_g_hash_table_new_free_at_exit - (g_str_hash, g_str_equal, "nautilus-directory.c: directories"); - - add_preferences_callbacks (); - } - - /* If the object is already in the hash table, look it up. */ - - directory = g_hash_table_lookup (directories, - canonical_uri); - if (directory != NULL) { - nautilus_directory_ref (directory); - } else if (create) { - /* Create a new directory object instead. */ - directory = nautilus_directory_new (canonical_uri); - if (directory == NULL) { - return NULL; - } - - g_assert (strcmp (directory->details->uri, canonical_uri) == 0); - - /* Put it in the hash table. */ - g_hash_table_insert (directories, - directory->details->uri, - directory); - } - - g_free (canonical_uri); - - return directory; -} - -NautilusDirectory * -nautilus_directory_get (const char *uri) -{ - return nautilus_directory_get_internal (uri, TRUE); -} - -NautilusDirectory * -nautilus_directory_get_existing (const char *uri) -{ - return nautilus_directory_get_internal (uri, FALSE); -} - -/* Returns a reffed NautilusFile object for this directory. - */ -NautilusFile * -nautilus_directory_get_corresponding_file (NautilusDirectory *directory) -{ - NautilusFile *file; - - file = nautilus_directory_get_existing_corresponding_file (directory); - if (file == NULL) { - file = nautilus_file_get (directory->details->uri); - } - - return file; -} - -/* Returns a reffed NautilusFile object for this directory, but only if the - * NautilusFile object has already been created. - */ -NautilusFile * -nautilus_directory_get_existing_corresponding_file (NautilusDirectory *directory) -{ - NautilusFile *file; - - file = directory->details->as_file; - if (file != NULL) { - nautilus_file_ref (file); - return file; - } - - return nautilus_file_get_existing (directory->details->uri); -} - -/* nautilus_directory_get_name_for_self_as_new_file: - * - * Get a name to display for the file representing this - * directory. This is called only when there's no VFS - * directory for this NautilusDirectory. - */ -char * -nautilus_directory_get_name_for_self_as_new_file (NautilusDirectory *directory) -{ - g_return_val_if_fail (NAUTILUS_IS_DIRECTORY (directory), NULL); - - return EEL_CALL_METHOD_WITH_RETURN_VALUE - (NAUTILUS_DIRECTORY_CLASS, directory, - get_name_for_self_as_new_file, (directory)); -} - -static char * -real_get_name_for_self_as_new_file (NautilusDirectory *directory) -{ - const char *directory_uri; - char *name, *colon; - - directory_uri = directory->details->uri; - - colon = strchr (directory_uri, ':'); - if (colon == NULL || colon == directory_uri) { - name = g_strdup (directory_uri); - } else { - name = g_strndup (directory_uri, colon - directory_uri); - } - - return name; -} - -char * -nautilus_directory_get_uri (NautilusDirectory *directory) -{ - g_return_val_if_fail (NAUTILUS_IS_DIRECTORY (directory), NULL); - - return g_strdup (directory->details->uri); -} - - -static NautilusDirectory * -nautilus_directory_new (const char *uri) -{ - NautilusDirectory *directory; - - g_assert (uri != NULL); - - if (eel_uri_is_trash (uri)) { - directory = NAUTILUS_DIRECTORY (gtk_object_new (NAUTILUS_TYPE_TRASH_DIRECTORY, NULL)); - } else { - directory = NAUTILUS_DIRECTORY (gtk_object_new (NAUTILUS_TYPE_VFS_DIRECTORY, NULL)); - } - gtk_object_ref (GTK_OBJECT (directory)); - gtk_object_sink (GTK_OBJECT (directory)); - - set_directory_uri (directory, uri); - - return directory; -} - -gboolean -nautilus_directory_is_local (NautilusDirectory *directory) -{ - g_return_val_if_fail (NAUTILUS_IS_DIRECTORY (directory), FALSE); - - if (directory->details->vfs_uri == NULL) { - return TRUE; - } - return gnome_vfs_uri_is_local (directory->details->vfs_uri); -} - -gboolean -nautilus_directory_are_all_files_seen (NautilusDirectory *directory) -{ - g_return_val_if_fail (NAUTILUS_IS_DIRECTORY (directory), FALSE); - - return EEL_CALL_METHOD_WITH_RETURN_VALUE - (NAUTILUS_DIRECTORY_CLASS, directory, - are_all_files_seen, (directory)); -} - -static void -add_to_hash_table (NautilusDirectory *directory, NautilusFile *file, GList *node) -{ - g_assert (node != NULL); - g_assert (g_hash_table_lookup (directory->details->file_hash, - file->details->relative_uri) == NULL); - g_hash_table_insert (directory->details->file_hash, - file->details->relative_uri, node); -} - -static GList * -extract_from_hash_table (NautilusDirectory *directory, NautilusFile *file) -{ - char *relative_uri; - GList *node; - - relative_uri = file->details->relative_uri; - if (relative_uri == NULL) { - return NULL; - } - - /* Find the list node in the hash table. */ - node = g_hash_table_lookup (directory->details->file_hash, relative_uri); - g_hash_table_remove (directory->details->file_hash, relative_uri); - - return node; -} - -void -nautilus_directory_add_file (NautilusDirectory *directory, NautilusFile *file) -{ - GList *node; - - g_assert (NAUTILUS_IS_DIRECTORY (directory)); - g_assert (NAUTILUS_IS_FILE (file)); - g_assert (file->details->relative_uri != NULL); - - /* Add to list. */ - node = g_list_prepend (directory->details->file_list, file); - directory->details->file_list = node; - - /* Add to hash table. */ - add_to_hash_table (directory, file, node); - - directory->details->confirmed_file_count++; - - /* Ref if we are monitoring. */ - if (nautilus_directory_is_file_list_monitored (directory)) { - nautilus_file_ref (file); - } -} - -void -nautilus_directory_remove_file (NautilusDirectory *directory, NautilusFile *file) -{ - GList *node; - - g_assert (NAUTILUS_IS_DIRECTORY (directory)); - g_assert (NAUTILUS_IS_FILE (file)); - g_assert (file->details->relative_uri != NULL); - - /* Find the list node in the hash table. */ - node = extract_from_hash_table (directory, file); - g_assert (node != NULL); - g_assert (node->data == file); - - /* Remove the item from the list. */ - directory->details->file_list = g_list_remove_link - (directory->details->file_list, node); - g_list_free_1 (node); - - if (!file->details->unconfirmed) { - directory->details->confirmed_file_count--; - } - - /* Unref if we are monitoring. */ - if (nautilus_directory_is_file_list_monitored (directory)) { - nautilus_file_unref (file); - } -} - -gboolean -nautilus_directory_file_list_length_reached (NautilusDirectory *directory) -{ - return directory->details->confirmed_file_count >= NAUTILUS_DIRECTORY_FILE_LIST_HARD_LIMIT; -} - -GList * -nautilus_directory_begin_file_name_change (NautilusDirectory *directory, - NautilusFile *file) -{ - /* Find the list node in the hash table. */ - return extract_from_hash_table (directory, file); -} - -void -nautilus_directory_end_file_name_change (NautilusDirectory *directory, - NautilusFile *file, - GList *node) -{ - /* Add the list node to the hash table. */ - if (node != NULL) { - add_to_hash_table (directory, file, node); - } -} - -NautilusFile * -nautilus_directory_find_file_by_name (NautilusDirectory *directory, - const char *name) -{ - char *relative_uri; - NautilusFile *file; - - g_return_val_if_fail (NAUTILUS_IS_DIRECTORY (directory), NULL); - g_return_val_if_fail (name != NULL, NULL); - - relative_uri = gnome_vfs_escape_string (name); - file = nautilus_directory_find_file_by_relative_uri - (directory, relative_uri); - g_free (relative_uri); - return file; -} - -NautilusFile * -nautilus_directory_find_file_by_relative_uri (NautilusDirectory *directory, - const char *relative_uri) -{ - GList *node; - - g_return_val_if_fail (NAUTILUS_IS_DIRECTORY (directory), NULL); - g_return_val_if_fail (relative_uri != NULL, NULL); - - node = g_hash_table_lookup (directory->details->file_hash, - relative_uri); - return node == NULL ? NULL : NAUTILUS_FILE (node->data); -} - -NautilusFile * -nautilus_directory_find_file_by_internal_uri (NautilusDirectory *directory, - const char *relative_uri) -{ - NautilusFile *result; - - if (eel_strcmp (relative_uri, ".") == 0) { - result = nautilus_directory_get_existing_corresponding_file (directory); - if (result != NULL) { - nautilus_file_unref (result); - g_return_val_if_fail (!GTK_OBJECT_DESTROYED (result), NULL); - } - } else { - result = nautilus_directory_find_file_by_relative_uri (directory, relative_uri); - } - - return result; -} - -void -nautilus_directory_emit_files_added (NautilusDirectory *directory, - GList *added_files) -{ - if (added_files != NULL) { - gtk_signal_emit (GTK_OBJECT (directory), - signals[FILES_ADDED], - added_files); - } -} - -void -nautilus_directory_emit_files_changed (NautilusDirectory *directory, - GList *changed_files) -{ - if (changed_files != NULL) { - gtk_signal_emit (GTK_OBJECT (directory), - signals[FILES_CHANGED], - changed_files); - } -} - -void -nautilus_directory_emit_change_signals (NautilusDirectory *directory, - GList *changed_files) -{ - GList *p; - - for (p = changed_files; p != NULL; p = p->next) { - nautilus_file_emit_changed (p->data); - } - nautilus_directory_emit_files_changed (directory, changed_files); -} - -void -nautilus_directory_emit_done_loading (NautilusDirectory *directory) -{ - gtk_signal_emit (GTK_OBJECT (directory), - signals[DONE_LOADING]); -} - -void -nautilus_directory_emit_load_error (NautilusDirectory *directory, - GnomeVFSResult error_result) -{ - gtk_signal_emit (GTK_OBJECT (directory), - signals[LOAD_ERROR], - error_result); -} - - -static char * -uri_get_directory_part (const char *uri) -{ - GnomeVFSURI *vfs_uri, *directory_vfs_uri; - char *directory_uri; - - /* Make VFS version of URI. */ - vfs_uri = gnome_vfs_uri_new (uri); - if (vfs_uri == NULL) { - return NULL; - } - - /* Make VFS version of directory URI. */ - directory_vfs_uri = gnome_vfs_uri_get_parent (vfs_uri); - gnome_vfs_uri_unref (vfs_uri); - if (directory_vfs_uri == NULL) { - return NULL; - } - - /* Make text version of directory URI. */ - directory_uri = gnome_vfs_uri_to_string (directory_vfs_uri, - GNOME_VFS_URI_HIDE_NONE); - gnome_vfs_uri_unref (directory_vfs_uri); - - return directory_uri; -} - -/* Return a directory object for this one's parent. */ -static NautilusDirectory * -get_parent_directory (const char *uri) -{ - char *directory_uri; - NautilusDirectory *directory; - - directory_uri = uri_get_directory_part (uri); - directory = nautilus_directory_get (directory_uri); - g_free (directory_uri); - return directory; -} - -/* If a directory object exists for this one's parent, then - * return it, otherwise return NULL. - */ -static NautilusDirectory * -get_parent_directory_if_exists (const char *uri) -{ - char *directory_uri; - NautilusDirectory *directory; - - /* Make text version of directory URI. */ - directory_uri = uri_get_directory_part (uri); - directory = nautilus_directory_get_existing (directory_uri); - g_free (directory_uri); - return directory; -} - -static void -hash_table_list_prepend (GHashTable *table, gconstpointer key, gpointer data) -{ - GList *list; - - list = g_hash_table_lookup (table, key); - list = g_list_prepend (list, data); - g_hash_table_insert (table, (gpointer) key, list); -} - -static void -call_files_added_free_list (gpointer key, gpointer value, gpointer user_data) -{ - g_assert (NAUTILUS_IS_DIRECTORY (key)); - g_assert (value != NULL); - g_assert (user_data == NULL); - - gtk_signal_emit (GTK_OBJECT (key), - signals[FILES_ADDED], - value); - g_list_free (value); -} - -static void -call_files_changed_free_list (gpointer key, gpointer value, gpointer user_data) -{ - g_assert (NAUTILUS_IS_DIRECTORY (key)); - g_assert (value != NULL); - g_assert (user_data == NULL); - - nautilus_directory_emit_change_signals (key, value); - g_list_free (value); -} - -static void -call_files_changed_unref_free_list (gpointer key, gpointer value, gpointer user_data) -{ - g_assert (NAUTILUS_IS_DIRECTORY (key)); - g_assert (value != NULL); - g_assert (user_data == NULL); - - nautilus_directory_async_state_changed (key); - nautilus_directory_emit_change_signals (key, value); - nautilus_file_list_free (value); -} - -static void -call_get_file_info_free_list (gpointer key, gpointer value, gpointer user_data) -{ - g_assert (NAUTILUS_IS_DIRECTORY (key)); - g_assert (value != NULL); - g_assert (user_data == NULL); - - nautilus_directory_get_info_for_new_files (key, value); - gnome_vfs_uri_list_free (value); -} - -static void -invalidate_count_and_unref (gpointer key, gpointer value, gpointer user_data) -{ - g_assert (NAUTILUS_IS_DIRECTORY (key)); - g_assert (value == key); - g_assert (user_data == NULL); - - nautilus_directory_invalidate_count_and_mime_list (key); - nautilus_directory_unref (key); -} - -static void -collect_parent_directories (GHashTable *hash_table, NautilusDirectory *directory) -{ - g_assert (hash_table != NULL); - g_assert (NAUTILUS_IS_DIRECTORY (directory)); - - if (g_hash_table_lookup (hash_table, directory) == NULL) { - nautilus_directory_ref (directory); - g_hash_table_insert (hash_table, directory, directory); - } -} - -void -nautilus_directory_notify_files_added (GList *uris) -{ - GHashTable *added_lists; - GList *p; - NautilusDirectory *directory; - GHashTable *parent_directories; - const char *uri; - GnomeVFSURI *vfs_uri; - - /* Make a list of added files in each directory. */ - added_lists = g_hash_table_new (NULL, NULL); - - /* Make a list of parent directories that will need their counts updated. */ - parent_directories = g_hash_table_new (NULL, NULL); - - for (p = uris; p != NULL; p = p->next) { - uri = (const char *) p->data; - - /* See if the directory is already known. */ - directory = get_parent_directory_if_exists (uri); - if (directory == NULL) { - continue; - } - - collect_parent_directories (parent_directories, directory); - - /* If no one is monitoring files in the directory, nothing to do. */ - if (!nautilus_directory_is_file_list_monitored (directory)) { - nautilus_directory_unref (directory); - continue; - } - - /* Collect the URIs to use. */ - vfs_uri = gnome_vfs_uri_new (uri); - if (vfs_uri == NULL) { - nautilus_directory_unref (directory); - g_warning ("bad uri %s", uri); - continue; - } - hash_table_list_prepend (added_lists, directory, vfs_uri); - nautilus_directory_unref (directory); - } - - - /* Now get file info for the new files. This creates NautilusFile - * objects for the new files, and sends out a files_added signal. - */ - g_hash_table_foreach (added_lists, call_get_file_info_free_list, NULL); - g_hash_table_destroy (added_lists); - - /* Invalidate count for each parent directory. */ - g_hash_table_foreach (parent_directories, invalidate_count_and_unref, NULL); - g_hash_table_destroy (parent_directories); -} - -void -nautilus_directory_notify_files_changed (GList *uris) -{ - GHashTable *changed_lists; - GList *node; - const char *uri; - NautilusFile *file; - - /* Make a list of changed files in each directory. */ - changed_lists = g_hash_table_new (NULL, NULL); - - /* Go through all the notifications. */ - for (node = uris; node != NULL; node = node->next) { - uri = (const char *) node->data; - - /* Find the file. */ - file = nautilus_file_get_existing (uri); - if (file != NULL) { - /* Tell it to re-get info and emit a changed - * signal. - */ - file->details->file_info_is_up_to_date = FALSE; - hash_table_list_prepend (changed_lists, - file->details->directory, - file); - } - } - - /* Now send out the changed signals. */ - g_hash_table_foreach (changed_lists, call_files_changed_unref_free_list, NULL); - g_hash_table_destroy (changed_lists); -} - -void -nautilus_directory_notify_files_removed (GList *uris) -{ - GHashTable *changed_lists; - GList *p; - NautilusDirectory *directory; - GHashTable *parent_directories; - const char *uri; - NautilusFile *file; - - /* Make a list of changed files in each directory. */ - changed_lists = g_hash_table_new (NULL, NULL); - - /* Make a list of parent directories that will need their counts updated. */ - parent_directories = g_hash_table_new (NULL, NULL); - - /* Go through all the notifications. */ - for (p = uris; p != NULL; p = p->next) { - uri = (const char *) p->data; - - /* Update file count for parent directory if anyone might care. */ - directory = get_parent_directory_if_exists (uri); - if (directory != NULL) { - collect_parent_directories (parent_directories, directory); - nautilus_directory_unref (directory); - } - - /* Find the file. */ - file = nautilus_file_get_existing (uri); - if (file != NULL) { - /* Mark it gone and prepare to send the changed signal. */ - nautilus_file_mark_gone (file); - hash_table_list_prepend (changed_lists, - file->details->directory, - file); - } - } - - /* Now send out the changed signals. */ - g_hash_table_foreach (changed_lists, call_files_changed_unref_free_list, NULL); - g_hash_table_destroy (changed_lists); - - /* Invalidate count for each parent directory. */ - g_hash_table_foreach (parent_directories, invalidate_count_and_unref, NULL); - g_hash_table_destroy (parent_directories); -} - -static void -set_directory_uri (NautilusDirectory *directory, - const char *new_uri) -{ - GnomeVFSURI *new_vfs_uri; - - new_vfs_uri = gnome_vfs_uri_new (new_uri); - - g_free (directory->details->uri); - directory->details->uri = g_strdup (new_uri); - - if (directory->details->vfs_uri != NULL) { - gnome_vfs_uri_unref (directory->details->vfs_uri); - } - directory->details->vfs_uri = new_vfs_uri; -} - -static void -change_directory_uri (NautilusDirectory *directory, - const char *new_uri) -{ - /* I believe it's impossible for a self-owned file/directory - * to be moved. But if that did somehow happen, this function - * wouldn't do enough to handle it. - */ - g_return_if_fail (directory->details->as_file == NULL); - - g_hash_table_remove (directories, - directory->details->uri); - - set_directory_uri (directory, new_uri); - - g_hash_table_insert (directories, - directory->details->uri, - directory); - - nautilus_directory_rename_directory_metadata (directory, new_uri); -} - -typedef struct { - char *uri_prefix; - GList *directories; -} CollectData; - -static void -collect_directories_by_prefix (gpointer key, gpointer value, gpointer callback_data) -{ - const char *uri, *uri_suffix; - NautilusDirectory *directory; - CollectData *collect_data; - - uri = (const char *) key; - directory = NAUTILUS_DIRECTORY (value); - collect_data = (CollectData *) callback_data; - - if (eel_str_has_prefix (uri, collect_data->uri_prefix)) { - uri_suffix = &uri[strlen (collect_data->uri_prefix)]; - switch (uri_suffix[0]) { - case '\0': - case '/': - nautilus_directory_ref (directory); - collect_data->directories = - g_list_prepend (collect_data->directories, - directory); - break; - } - } -} - -static char * -str_replace_prefix (const char *str, - const char *old_prefix, - const char *new_prefix) -{ - const char *old_suffix; - - g_return_val_if_fail (eel_str_has_prefix (str, old_prefix), - g_strdup (str)); - - old_suffix = &str [strlen (old_prefix)]; - return g_strconcat (new_prefix, old_suffix, NULL); -} - -static GList * -nautilus_directory_moved_internal (const char *old_uri, - const char *new_uri) -{ - char *canonical_old_uri, *canonical_new_uri; - CollectData collection; - NautilusDirectory *directory; - char *new_directory_uri; - GList *node, *affected_files; - - canonical_old_uri = nautilus_directory_make_uri_canonical (old_uri); - canonical_new_uri = nautilus_directory_make_uri_canonical (new_uri); - - collection.uri_prefix = canonical_old_uri; - collection.directories = NULL; - - g_hash_table_foreach (directories, - collect_directories_by_prefix, - &collection); - - affected_files = NULL; - - for (node = collection.directories; node != NULL; node = node->next) { - directory = NAUTILUS_DIRECTORY (node->data); - - /* Change the URI in the directory object. */ - new_directory_uri = str_replace_prefix (directory->details->uri, - canonical_old_uri, - canonical_new_uri); - change_directory_uri (directory, - new_directory_uri); - g_free (new_directory_uri); - - /* Collect affected files. */ - if (directory->details->as_file != NULL) { - affected_files = g_list_prepend - (affected_files, - nautilus_file_ref (directory->details->as_file)); - } - affected_files = g_list_concat - (affected_files, - nautilus_file_list_copy (directory->details->file_list)); - - nautilus_directory_unref (directory); - } - - g_list_free (collection.directories); - - g_free (canonical_old_uri); - g_free (canonical_new_uri); - - return affected_files; -} - -void -nautilus_directory_moved (const char *old_uri, - const char *new_uri) -{ - GList *list, *node; - GHashTable *hash; - NautilusFile *file; - - hash = g_hash_table_new (NULL, NULL); - - list = nautilus_directory_moved_internal (old_uri, new_uri); - for (node = list; node != NULL; node = node->next) { - file = NAUTILUS_FILE (node->data); - hash_table_list_prepend (hash, - file->details->directory, - nautilus_file_ref (file)); - } - nautilus_file_list_free (list); - - g_hash_table_foreach (hash, call_files_changed_unref_free_list, NULL); - g_hash_table_destroy (hash); -} - -void -nautilus_directory_notify_files_moved (GList *uri_pairs) -{ - GList *p, *affected_files, *node; - URIPair *pair; - NautilusFile *file; - NautilusDirectory *old_directory, *new_directory; - GHashTable *parent_directories; - GList *new_files_list, *unref_list; - GHashTable *added_lists, *changed_lists; - char *name; - - /* Make a list of added and changed files in each directory. */ - new_files_list = NULL; - added_lists = g_hash_table_new (NULL, NULL); - changed_lists = g_hash_table_new (NULL, NULL); - unref_list = NULL; - - /* Make a list of parent directories that will need their counts updated. */ - parent_directories = g_hash_table_new (NULL, NULL); - - for (p = uri_pairs; p != NULL; p = p->next) { - pair = p->data; - - /* Handle overwriting a file. */ - file = nautilus_file_get_existing (pair->to_uri); - if (file != NULL) { - /* Mark it gone and prepare to send the changed signal. */ - nautilus_file_mark_gone (file); - new_directory = file->details->directory; - hash_table_list_prepend (changed_lists, - new_directory, - file); - collect_parent_directories (parent_directories, - new_directory); - } - - /* Update any directory objects that are affected. */ - affected_files = nautilus_directory_moved_internal (pair->from_uri, - pair->to_uri); - for (node = affected_files; node != NULL; node = node->next) { - file = NAUTILUS_FILE (node->data); - hash_table_list_prepend (changed_lists, - file->details->directory, - file); - } - unref_list = g_list_concat (unref_list, affected_files); - - /* Move an existing file. */ - file = nautilus_file_get_existing (pair->from_uri); - if (file == NULL) { - /* Handle this as if it was a new file. */ - new_files_list = g_list_prepend (new_files_list, - pair->to_uri); - } else { - /* Handle notification in the old directory. */ - old_directory = file->details->directory; - collect_parent_directories (parent_directories, old_directory); - - /* Locate the new directory. */ - new_directory = get_parent_directory (pair->to_uri); - collect_parent_directories (parent_directories, new_directory); - /* We can unref now -- new_directory is in the - * parent directories list so it will be - * around until the end of this function - * anyway. - */ - nautilus_directory_unref (new_directory); - - /* Update the file's name. */ - name = eel_uri_get_basename (pair->to_uri); - nautilus_file_update_name (file, name); - g_free (name); - - /* Update the file's directory. */ - nautilus_file_set_directory (file, new_directory); - - hash_table_list_prepend (changed_lists, - old_directory, - file); - if (old_directory != new_directory) { - hash_table_list_prepend (added_lists, - new_directory, - file); - } - - /* Unref each file once to balance out nautilus_file_get. */ - unref_list = g_list_prepend (unref_list, file); - } - } - - /* Now send out the changed and added signals for existing file objects. */ - g_hash_table_foreach (changed_lists, call_files_changed_free_list, NULL); - g_hash_table_destroy (changed_lists); - g_hash_table_foreach (added_lists, call_files_added_free_list, NULL); - g_hash_table_destroy (added_lists); - - /* Let the file objects go. */ - nautilus_file_list_free (unref_list); - - /* Invalidate count for each parent directory. */ - g_hash_table_foreach (parent_directories, invalidate_count_and_unref, NULL); - g_hash_table_destroy (parent_directories); - - /* Separate handling for brand new file objects. */ - nautilus_directory_notify_files_added (new_files_list); - g_list_free (new_files_list); -} - -void -nautilus_directory_schedule_metadata_copy (GList *uri_pairs) -{ - GList *p; - URIPair *pair; - NautilusDirectory *source_directory, *destination_directory; - const char *source_relative_uri, *destination_relative_uri; - - for (p = uri_pairs; p != NULL; p = p->next) { - pair = (URIPair *) p->data; - - source_directory = get_parent_directory (pair->from_uri); - destination_directory = get_parent_directory (pair->to_uri); - - source_relative_uri = g_basename (pair->from_uri); - destination_relative_uri = g_basename (pair->to_uri); - - nautilus_directory_copy_file_metadata (source_directory, - source_relative_uri, - destination_directory, - destination_relative_uri); - - nautilus_directory_unref (source_directory); - nautilus_directory_unref (destination_directory); - } -} - -void -nautilus_directory_schedule_metadata_move (GList *uri_pairs) -{ - GList *p; - URIPair *pair; - NautilusDirectory *source_directory, *destination_directory; - const char *source_relative_uri, *destination_relative_uri; - - for (p = uri_pairs; p != NULL; p = p->next) { - pair = (URIPair *) p->data; - - source_directory = get_parent_directory (pair->from_uri); - destination_directory = get_parent_directory (pair->to_uri); - - source_relative_uri = g_basename (pair->from_uri); - destination_relative_uri = g_basename (pair->to_uri); - - nautilus_directory_copy_file_metadata (source_directory, - source_relative_uri, - destination_directory, - destination_relative_uri); - nautilus_directory_remove_file_metadata (source_directory, - source_relative_uri); - - nautilus_directory_unref (source_directory); - nautilus_directory_unref (destination_directory); - } -} - -void -nautilus_directory_schedule_metadata_remove (GList *uris) -{ - GList *p; - const char *uri; - NautilusDirectory *directory; - const char *relative_uri; - - for (p = uris; p != NULL; p = p->next) { - uri = (const char *) p->data; - - directory = get_parent_directory (uri); - relative_uri = g_basename (uri); - - nautilus_directory_remove_file_metadata (directory, - relative_uri); - - nautilus_directory_unref (directory); - } -} - -void -nautilus_directory_schedule_position_set (GList *position_setting_list) -{ - GList *p; - const NautilusFileChangesQueuePosition *item; - NautilusFile *file; - char *position_string; - - for (p = position_setting_list; p != NULL; p = p->next) { - item = (NautilusFileChangesQueuePosition *) p->data; - - file = nautilus_file_get (item->uri); - - if (item->set) { - position_string = g_strdup_printf ("%d,%d", - item->point.x, item->point.y); - } else { - position_string = NULL; - } - nautilus_file_set_metadata - (file, - NAUTILUS_METADATA_KEY_ICON_POSITION, - NULL, - position_string); - g_free (position_string); - - nautilus_file_unref (file); - } -} - -gboolean -nautilus_directory_contains_file (NautilusDirectory *directory, - NautilusFile *file) -{ - g_return_val_if_fail (NAUTILUS_IS_DIRECTORY (directory), FALSE); - g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE); - - if (nautilus_file_is_gone (file)) { - return FALSE; - } - - return EEL_CALL_METHOD_WITH_RETURN_VALUE - (NAUTILUS_DIRECTORY_CLASS, directory, - contains_file, (directory, file)); -} - -char * -nautilus_directory_get_file_uri (NautilusDirectory *directory, - const char *file_name) -{ - GnomeVFSURI *directory_uri, *file_uri; - char *result; - - g_return_val_if_fail (NAUTILUS_IS_DIRECTORY (directory), NULL); - g_return_val_if_fail (file_name != NULL, NULL); - - result = NULL; - - directory_uri = gnome_vfs_uri_new (directory->details->uri); - - g_assert (directory_uri != NULL); - - file_uri = gnome_vfs_uri_append_string (directory_uri, file_name); - gnome_vfs_uri_unref (directory_uri); - - if (file_uri != NULL) { - result = gnome_vfs_uri_to_string (file_uri, GNOME_VFS_URI_HIDE_NONE); - gnome_vfs_uri_unref (file_uri); - } - - return result; -} - -void -nautilus_directory_call_when_ready (NautilusDirectory *directory, - GList *file_attributes, - NautilusDirectoryCallback callback, - gpointer callback_data) -{ - g_return_if_fail (NAUTILUS_IS_DIRECTORY (directory)); - g_return_if_fail (callback != NULL); - - EEL_CALL_METHOD - (NAUTILUS_DIRECTORY_CLASS, directory, - call_when_ready, (directory, file_attributes, - callback, callback_data)); -} - - -void -nautilus_directory_cancel_callback (NautilusDirectory *directory, - NautilusDirectoryCallback callback, - gpointer callback_data) -{ - g_return_if_fail (NAUTILUS_IS_DIRECTORY (directory)); - g_return_if_fail (callback != NULL); - - EEL_CALL_METHOD - (NAUTILUS_DIRECTORY_CLASS, directory, - cancel_callback, (directory, callback, callback_data)); -} - -void -nautilus_directory_file_monitor_add (NautilusDirectory *directory, - gconstpointer client, - gboolean monitor_hidden_files, - gboolean monitor_backup_files, - GList *file_attributes) -{ - g_return_if_fail (NAUTILUS_IS_DIRECTORY (directory)); - g_return_if_fail (client != NULL); - - EEL_CALL_METHOD - (NAUTILUS_DIRECTORY_CLASS, directory, - file_monitor_add, (directory, client, - monitor_hidden_files, - monitor_backup_files, - file_attributes)); -} - -void -nautilus_directory_file_monitor_remove (NautilusDirectory *directory, - gconstpointer client) -{ - g_return_if_fail (NAUTILUS_IS_DIRECTORY (directory)); - g_return_if_fail (client != NULL); - - EEL_CALL_METHOD - (NAUTILUS_DIRECTORY_CLASS, directory, - file_monitor_remove, (directory, client)); -} - -void -nautilus_directory_force_reload (NautilusDirectory *directory) -{ - g_return_if_fail (NAUTILUS_IS_DIRECTORY (directory)); - - EEL_CALL_METHOD - (NAUTILUS_DIRECTORY_CLASS, directory, - force_reload, (directory)); -} - -gboolean -nautilus_directory_is_not_empty (NautilusDirectory *directory) -{ - g_return_val_if_fail (NAUTILUS_IS_DIRECTORY (directory), FALSE); - - return EEL_CALL_METHOD_WITH_RETURN_VALUE - (NAUTILUS_DIRECTORY_CLASS, directory, - is_not_empty, (directory)); -} - -#if !defined (NAUTILUS_OMIT_SELF_CHECK) - -#include <eel/eel-debug.h> -#include "nautilus-file-attributes.h" - -static int data_dummy; -static gboolean got_metadata_flag; -static gboolean got_files_flag; - -static void -got_metadata_callback (NautilusDirectory *directory, GList *files, gpointer callback_data) -{ - g_assert (NAUTILUS_IS_DIRECTORY (directory)); - g_assert (callback_data == &data_dummy); - - got_metadata_flag = TRUE; -} - -static void -got_files_callback (NautilusDirectory *directory, GList *files, gpointer callback_data) -{ - g_assert (NAUTILUS_IS_DIRECTORY (directory)); - g_assert (g_list_length (files) > 10); - g_assert (callback_data == &data_dummy); - - got_files_flag = TRUE; -} - -/* Return the number of extant NautilusDirectories */ -int -nautilus_directory_number_outstanding (void) -{ - return directories ? g_hash_table_size (directories) : 0; -} - -void -nautilus_self_check_directory (void) -{ - NautilusDirectory *directory; - NautilusFile *file; - GList *attributes; - - directory = nautilus_directory_get ("file:///etc"); - file = nautilus_file_get ("file:///etc/passwd"); - - EEL_CHECK_INTEGER_RESULT (g_hash_table_size (directories), 1); - - nautilus_directory_file_monitor_add - (directory, &data_dummy, - TRUE, TRUE, NULL); - - got_metadata_flag = FALSE; - - attributes = g_list_append (NULL, NAUTILUS_FILE_ATTRIBUTE_METADATA); - nautilus_directory_call_when_ready (directory, attributes, - got_metadata_callback, &data_dummy); - g_list_free (attributes); - - while (!got_metadata_flag) { - gtk_main_iteration (); - } - - nautilus_file_set_metadata (file, "test", "default", "value"); - EEL_CHECK_STRING_RESULT (nautilus_file_get_metadata (file, "test", "default"), "value"); - - nautilus_file_set_boolean_metadata (file, "test_boolean", TRUE, TRUE); - EEL_CHECK_BOOLEAN_RESULT (nautilus_file_get_boolean_metadata (file, "test_boolean", TRUE), TRUE); - nautilus_file_set_boolean_metadata (file, "test_boolean", TRUE, FALSE); - EEL_CHECK_BOOLEAN_RESULT (nautilus_file_get_boolean_metadata (file, "test_boolean", TRUE), FALSE); - EEL_CHECK_BOOLEAN_RESULT (nautilus_file_get_boolean_metadata (NULL, "test_boolean", TRUE), TRUE); - - nautilus_file_set_integer_metadata (file, "test_integer", 0, 17); - EEL_CHECK_INTEGER_RESULT (nautilus_file_get_integer_metadata (file, "test_integer", 0), 17); - nautilus_file_set_integer_metadata (file, "test_integer", 0, -1); - EEL_CHECK_INTEGER_RESULT (nautilus_file_get_integer_metadata (file, "test_integer", 0), -1); - nautilus_file_set_integer_metadata (file, "test_integer", 42, 42); - EEL_CHECK_INTEGER_RESULT (nautilus_file_get_integer_metadata (file, "test_integer", 42), 42); - EEL_CHECK_INTEGER_RESULT (nautilus_file_get_integer_metadata (NULL, "test_integer", 42), 42); - EEL_CHECK_INTEGER_RESULT (nautilus_file_get_integer_metadata (file, "nonexistent_key", 42), 42); - - EEL_CHECK_BOOLEAN_RESULT (nautilus_directory_get ("file:///etc") == directory, TRUE); - nautilus_directory_unref (directory); - - EEL_CHECK_BOOLEAN_RESULT (nautilus_directory_get ("file:///etc/") == directory, TRUE); - nautilus_directory_unref (directory); - - EEL_CHECK_BOOLEAN_RESULT (nautilus_directory_get ("file:///etc////") == directory, TRUE); - nautilus_directory_unref (directory); - - nautilus_file_unref (file); - - nautilus_directory_file_monitor_remove (directory, &data_dummy); - - nautilus_directory_unref (directory); - - while (g_hash_table_size (directories) != 0) { - gtk_main_iteration (); - } - - EEL_CHECK_INTEGER_RESULT (g_hash_table_size (directories), 0); - - directory = nautilus_directory_get ("file:///etc"); - - got_metadata_flag = FALSE; - attributes = g_list_append (NULL, NAUTILUS_FILE_ATTRIBUTE_METADATA); - nautilus_directory_call_when_ready (directory, attributes, - got_metadata_callback, &data_dummy); - g_list_free (attributes); - - while (!got_metadata_flag) { - gtk_main_iteration (); - } - - EEL_CHECK_BOOLEAN_RESULT (nautilus_directory_is_metadata_read (directory), TRUE); - - got_files_flag = FALSE; - - attributes = g_list_prepend (NULL, NAUTILUS_FILE_ATTRIBUTE_MIME_TYPE); - attributes = g_list_prepend (attributes, NAUTILUS_FILE_ATTRIBUTE_DEEP_COUNTS); - nautilus_directory_call_when_ready (directory, attributes, - got_files_callback, &data_dummy); - g_list_free (attributes); - - while (!got_files_flag) { - gtk_main_iteration (); - } - - EEL_CHECK_BOOLEAN_RESULT (directory->details->file_list == NULL, TRUE); - - EEL_CHECK_INTEGER_RESULT (g_hash_table_size (directories), 1); - - file = nautilus_file_get ("file:///etc/passwd"); - - EEL_CHECK_STRING_RESULT (nautilus_file_get_metadata (file, "test", "default"), "value"); - - nautilus_file_unref (file); - - nautilus_directory_unref (directory); - - EEL_CHECK_INTEGER_RESULT (g_hash_table_size (directories), 0); - - /* escape_slashes: code is now in gnome-vfs, but lets keep the tests here for now */ - EEL_CHECK_STRING_RESULT (gnome_vfs_escape_slashes (""), ""); - EEL_CHECK_STRING_RESULT (gnome_vfs_escape_slashes ("a"), "a"); - EEL_CHECK_STRING_RESULT (gnome_vfs_escape_slashes ("/"), "%2F"); - EEL_CHECK_STRING_RESULT (gnome_vfs_escape_slashes ("%"), "%25"); - EEL_CHECK_STRING_RESULT (gnome_vfs_escape_slashes ("a/a"), "a%2Fa"); - EEL_CHECK_STRING_RESULT (gnome_vfs_escape_slashes ("a%a"), "a%25a"); - EEL_CHECK_STRING_RESULT (gnome_vfs_escape_slashes ("%25"), "%2525"); - EEL_CHECK_STRING_RESULT (gnome_vfs_escape_slashes ("%2F"), "%252F"); - - /* nautilus_directory_make_uri_canonical */ - EEL_CHECK_STRING_RESULT (nautilus_directory_make_uri_canonical (""), "file:///"); - EEL_CHECK_STRING_RESULT (nautilus_directory_make_uri_canonical ("file:/"), "file:///"); - EEL_CHECK_STRING_RESULT (nautilus_directory_make_uri_canonical ("file:///"), "file:///"); - EEL_CHECK_STRING_RESULT (nautilus_directory_make_uri_canonical ("TRASH:XXX"), EEL_TRASH_URI); - EEL_CHECK_STRING_RESULT (nautilus_directory_make_uri_canonical ("trash:xxx"), EEL_TRASH_URI); - EEL_CHECK_STRING_RESULT (nautilus_directory_make_uri_canonical ("GNOME-TRASH:XXX"), EEL_TRASH_URI); - EEL_CHECK_STRING_RESULT (nautilus_directory_make_uri_canonical ("gnome-trash:xxx"), EEL_TRASH_URI); - EEL_CHECK_STRING_RESULT (nautilus_directory_make_uri_canonical ("file:///home/mathieu/"), "file:///home/mathieu"); - EEL_CHECK_STRING_RESULT (nautilus_directory_make_uri_canonical ("file:///home/mathieu"), "file:///home/mathieu"); - EEL_CHECK_STRING_RESULT (nautilus_directory_make_uri_canonical ("ftp://mathieu:password@le-hackeur.org"), "ftp://mathieu:password@le-hackeur.org"); - EEL_CHECK_STRING_RESULT (nautilus_directory_make_uri_canonical ("ftp://mathieu:password@le-hackeur.org/"), "ftp://mathieu:password@le-hackeur.org"); - EEL_CHECK_STRING_RESULT (nautilus_directory_make_uri_canonical ("http://le-hackeur.org"), "http://le-hackeur.org"); - EEL_CHECK_STRING_RESULT (nautilus_directory_make_uri_canonical ("http://le-hackeur.org/"), "http://le-hackeur.org"); - EEL_CHECK_STRING_RESULT (nautilus_directory_make_uri_canonical ("http://le-hackeur.org/dir"), "http://le-hackeur.org/dir"); - EEL_CHECK_STRING_RESULT (nautilus_directory_make_uri_canonical ("http://le-hackeur.org/dir/"), "http://le-hackeur.org/dir"); - /* FIXME bugzilla.eazel.com 5068: the "nested" URI loses some characters here. Maybe that's OK because we escape them in practice? */ - EEL_CHECK_STRING_RESULT (nautilus_directory_make_uri_canonical ("search://[file://]file_name contains stuff"), "search://[file/]file_name contains stuff"); - EEL_CHECK_STRING_RESULT (nautilus_directory_make_uri_canonical ("eazel-services:/~turtle"), "eazel-services:///~turtle"); - EEL_CHECK_STRING_RESULT (nautilus_directory_make_uri_canonical ("eazel-services:///~turtle"), "eazel-services:///~turtle"); -} - -#endif /* !NAUTILUS_OMIT_SELF_CHECK */ diff --git a/libnautilus-extensions/nautilus-directory.h b/libnautilus-extensions/nautilus-directory.h deleted file mode 100644 index 7ec226dac..000000000 --- a/libnautilus-extensions/nautilus-directory.h +++ /dev/null @@ -1,207 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- - - nautilus-directory.h: Nautilus directory model. - - Copyright (C) 1999, 2000, 2001 Eazel, Inc. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public - License along with this program; if not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. - - Author: Darin Adler <darin@eazel.com> -*/ - -#ifndef NAUTILUS_DIRECTORY_H -#define NAUTILUS_DIRECTORY_H - -#include <gtk/gtkobject.h> -#include <libgnomevfs/gnome-vfs-types.h> - -/* NautilusDirectory is a class that manages the model for a directory, - real or virtual, for Nautilus, mainly the file-manager component. The directory is - responsible for managing both real data and cached metadata. On top of - the file system independence provided by gnome-vfs, the directory - object also provides: - - 1) A synchronization framework, which notifies via signals as the - set of known files changes. - 2) An abstract interface for getting attributes and performing - operations on files. -*/ - -#define NAUTILUS_TYPE_DIRECTORY \ - (nautilus_directory_get_type ()) -#define NAUTILUS_DIRECTORY(obj) \ - (GTK_CHECK_CAST ((obj), NAUTILUS_TYPE_DIRECTORY, NautilusDirectory)) -#define NAUTILUS_DIRECTORY_CLASS(klass) \ - (GTK_CHECK_CLASS_CAST ((klass), NAUTILUS_TYPE_DIRECTORY, NautilusDirectoryClass)) -#define NAUTILUS_IS_DIRECTORY(obj) \ - (GTK_CHECK_TYPE ((obj), NAUTILUS_TYPE_DIRECTORY)) -#define NAUTILUS_IS_DIRECTORY_CLASS(klass) \ - (GTK_CHECK_CLASS_TYPE ((klass), NAUTILUS_TYPE_DIRECTORY)) - -/* NautilusFile is defined both here and in nautilus-file.h. */ -#ifndef NAUTILUS_FILE_DEFINED -#define NAUTILUS_FILE_DEFINED -typedef struct NautilusFile NautilusFile; -#endif - -/* FIXME bugzilla.eazel.com 5382: - * Increase or remove this limit? - */ -/* FIXME bugzilla.eazel.com 5603: - * This limit is not actually "hard", which can lead to some minor UI problems. - */ -#define NAUTILUS_DIRECTORY_FILE_LIST_HARD_LIMIT 4000 - -typedef struct NautilusDirectoryDetails NautilusDirectoryDetails; - -typedef struct -{ - GtkObject object; - NautilusDirectoryDetails *details; -} NautilusDirectory; - -typedef void (*NautilusDirectoryCallback) (NautilusDirectory *directory, - GList *files, - gpointer callback_data); - -typedef struct -{ - GtkObjectClass parent_class; - - /*** Notification signals for clients to connect to. ***/ - - /* The files_added signal is emitted as the directory model - * discovers new files. - */ - void (* files_added) (NautilusDirectory *directory, - GList *added_files); - - /* The files_changed signal is emitted as changes occur to - * existing files that are noticed by the synchronization framework, - * including when an old file has been deleted. When an old file - * has been deleted, this is the last chance to forget about these - * file objects, which are about to be unref'd. Use a call to - * nautilus_file_is_gone () to test for this case. - */ - void (* files_changed) (NautilusDirectory *directory, - GList *changed_files); - - /* The done_loading signal is emitted when a directory load - * request completes. This is needed because, at least in the - * case where the directory is empty, the caller will receive - * no kind of notification at all when a directory load - * initiated by `nautilus_directory_file_monitor_add' completes. - */ - void (* done_loading) (NautilusDirectory *directory); - - void (* load_error) (NautilusDirectory *directory); - - /*** Virtual functions for subclasses to override. ***/ - gboolean (* contains_file) (NautilusDirectory *directory, - NautilusFile *file); - void (* call_when_ready) (NautilusDirectory *directory, - GList *file_attributes, - NautilusDirectoryCallback callback, - gpointer callback_data); - void (* cancel_callback) (NautilusDirectory *directory, - NautilusDirectoryCallback callback, - gpointer callback_data); - void (* file_monitor_add) (NautilusDirectory *directory, - gconstpointer client, - gboolean monitor_hidden_files, - gboolean monitor_backup_files, - GList *monitor_attributes); - void (* file_monitor_remove) (NautilusDirectory *directory, - gconstpointer client); - void (* force_reload) (NautilusDirectory *directory); - gboolean (* are_all_files_seen) (NautilusDirectory *directory); - gboolean (* is_not_empty) (NautilusDirectory *directory); - char * (* get_name_for_self_as_new_file) (NautilusDirectory *directory); -} NautilusDirectoryClass; - -/* Basic GtkObject requirements. */ -GtkType nautilus_directory_get_type (void); - -/* Get a directory given a uri. - * Creates the appropriate subclass given the uri mappings. - * Returns a referenced object, not a floating one. Unref when finished. - * If two windows are viewing the same uri, the directory object is shared. - */ -NautilusDirectory *nautilus_directory_get (const char *uri); - -/* Covers for gtk_object_ref and gtk_object_unref that provide two conveniences: - * 1) You don't have to cast to GtkObject *, so using these is type safe. - * 2) You are allowed to call these with NULL, - */ -void nautilus_directory_ref (NautilusDirectory *directory); -void nautilus_directory_unref (NautilusDirectory *directory); - -/* Access to a URI. */ -char * nautilus_directory_get_uri (NautilusDirectory *directory); - -/* Is this file still alive and in this directory? */ -gboolean nautilus_directory_contains_file (NautilusDirectory *directory, - NautilusFile *file); - -/* Get the uri of the file in the directory, NULL if not found */ -char * nautilus_directory_get_file_uri (NautilusDirectory *directory, - const char *file_name); - -/* Get (and ref) a NautilusFile object for this directory. */ -NautilusFile * nautilus_directory_get_corresponding_file (NautilusDirectory *directory); - - -/* Waiting for data that's read asynchronously. - * The file attribute and metadata keys are for files in the directory. - * If any file attributes or metadata keys are passed, it won't call - * until all the files are seen. - */ -void nautilus_directory_call_when_ready (NautilusDirectory *directory, - GList *file_attributes, - NautilusDirectoryCallback callback, - gpointer callback_data); -void nautilus_directory_cancel_callback (NautilusDirectory *directory, - NautilusDirectoryCallback callback, - gpointer callback_data); - - -/* Monitor the files in a directory. */ -void nautilus_directory_file_monitor_add (NautilusDirectory *directory, - gconstpointer client, - gboolean monitor_hidden_files, - gboolean monitor_backup_files, - GList *attributes); -void nautilus_directory_file_monitor_remove (NautilusDirectory *directory, - gconstpointer client); -void nautilus_directory_force_reload (NautilusDirectory *directory); - -/* Return true if the directory has information about all the files. - * This will be false until the directory has been read at least once. - */ -gboolean nautilus_directory_are_all_files_seen (NautilusDirectory *directory); - -/* Return true if the directory is local. */ -gboolean nautilus_directory_is_local (NautilusDirectory *directory); - -/* Return false if directory contains anything besides a Nautilus metafile. - * Only valid if directory is monitored. Used by the Trash monitor. - */ -gboolean nautilus_directory_is_not_empty (NautilusDirectory *directory); -gboolean nautilus_directory_file_list_length_reached (NautilusDirectory *directory); - -char * nautilus_directory_make_uri_canonical (const char *uri); - -#endif /* NAUTILUS_DIRECTORY_H */ diff --git a/libnautilus-extensions/nautilus-drag-window.c b/libnautilus-extensions/nautilus-drag-window.c deleted file mode 100644 index 0f039875e..000000000 --- a/libnautilus-extensions/nautilus-drag-window.c +++ /dev/null @@ -1,403 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */ - -/* - * Nautilus - * - * Copyright (C) 2001 Eazel, Inc. - * - * Nautilus 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. - * - * Nautilus 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Author: John Harper <jsh@eazel.com> - * - */ - -/* Registering that a window may be used as a drag 'n drop source */ - -#include <config.h> -#include "nautilus-drag-window.h" - -#include <eel/eel-gdk-extensions.h> -#include <gtk/gtk.h> -#include <X11/Xatom.h> -#include <gdk/gdkx.h> -#include <gdk/gdkprivate.h> - -/* State for handling focus/raise */ -typedef struct NautilusDragWindowDetails NautilusDragWindowDetails; -struct NautilusDragWindowDetails { - gboolean in_button_press; - gboolean pending_focus; - gboolean pending_raise; - - Time focus_timestamp; - - guint focus_timeout_tag; -}; - -/* Delay in milliseconds between receiving a TAKE_FOCUS or RAISE_WINDOW - * client message, and assuming that there's no following button-press - * event. This seems to be large enough to work, but small enough to be - * unnoticeable to the user. - */ -#define WINDOW_FOCUS_TIMEOUT 50 - -/* Key used to store a NautilusDragWindowDetails structure in each - * registered window's object data hash - */ -#define NAUTILUS_DRAG_WINDOW_DETAILS_KEY "nautilus-drag-window-details" - -static Atom sawfish_wm_raise_window = 0; - -/* Return the nearest ancestor of WIDGET that has type WIDGET_TYPE. But only - * if there's no widget between the two with type BLOCKING_TYPE. - */ -static GtkWidget * -get_ancestor_blocked_by (GtkWidget *widget, - GtkType widget_type, - GtkType blocking_type) -{ - g_return_val_if_fail (widget != NULL, NULL); - g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL); - - while (widget != NULL) - { - if (gtk_type_is_a (GTK_WIDGET_TYPE (widget), widget_type)) - return widget; - else if (gtk_type_is_a (GTK_WIDGET_TYPE (widget), blocking_type)) - return NULL; - widget = widget->parent; - } - - return NULL; -} - -/* Returns the details structure associated with WINDOW, or a null pointer - * if no such structure exists - */ -static NautilusDragWindowDetails * -get_details (GtkWindow *window) -{ - NautilusDragWindowDetails *details; - - details = gtk_object_get_data (GTK_OBJECT (window), - NAUTILUS_DRAG_WINDOW_DETAILS_KEY); - return details; -} - -/* Commit any pending focus/raise requests for WINDOW. */ -static void -execute_pending_requests (GtkWindow *window, - NautilusDragWindowDetails *details) -{ - if (GTK_WIDGET_REALIZED (window)) { - if (details->pending_focus) { - eel_gdk_window_focus (GTK_WIDGET (window)->window, - details->focus_timestamp); - details->pending_focus = FALSE; - } - if (details->pending_raise) { - gdk_window_raise (GTK_WIDGET (window)->window); - details->pending_raise = FALSE; - } - } -} - -/* Called when no button-press event arrived occurred shortly after - * receiving a TAKE_FOCUS or RAISE_WINDOW request. So just commit - * the pending requests. - */ -static gint -focus_timeout_callback (gpointer data) -{ - GtkWindow *window; - NautilusDragWindowDetails *details; - - window = GTK_WINDOW (data); - details = get_details (window); - - if (details != NULL) { - execute_pending_requests (window, details); - - details->focus_timeout_tag = 0; - } - - /* Only ever a one-shot timeout */ - return FALSE; -} - -static void -remove_focus_timeout (GtkWindow *window) -{ - NautilusDragWindowDetails *details; - - details = get_details (window); - - if (details != NULL && details->focus_timeout_tag != 0) { - gtk_timeout_remove (details->focus_timeout_tag); - details->focus_timeout_tag = 0; - } -} - -static void -set_focus_timeout (GtkWindow *window) -{ - NautilusDragWindowDetails *details; - - details = get_details (window); - - if (details != NULL) { - remove_focus_timeout (window); - details->focus_timeout_tag - = gtk_timeout_add (WINDOW_FOCUS_TIMEOUT, - focus_timeout_callback, window); - } -} - -/* Called for all button-press events; sets the `in_button_press' flag */ -static gboolean -button_press_emission_callback (GtkObject *object, guint signal_id, - guint n_params, GtkArg *params, - gpointer data) -{ - GtkWidget *window; - NautilusDragWindowDetails *details; - - /* This blocking is kind of a hack. But it seems necessary, - * otherwise we can get duped into counting unbalanced - * press/release events, which isn't healthy - */ - window = get_ancestor_blocked_by (GTK_WIDGET (object), - GTK_TYPE_WINDOW, - GTK_TYPE_MENU_SHELL); - if (window != NULL) { - details = get_details (GTK_WINDOW (window)); - if (details != NULL) { - remove_focus_timeout (GTK_WINDOW (window)); - - if (!details->in_button_press) { - details->in_button_press = TRUE; - } else { - /* We never got the last button - * release. Adapt. - */ - execute_pending_requests (GTK_WINDOW (window), - details); - details->in_button_press = FALSE; - } - } - } - - return TRUE; -} - -/* Called for button-release events; commits any pending focus/raise */ -static gboolean -button_release_emission_callback (GtkObject *object, guint signal_id, - guint n_params, GtkArg *params, - gpointer data) -{ - GtkWidget *window; - NautilusDragWindowDetails *details; - - window = get_ancestor_blocked_by (GTK_WIDGET (object), - GTK_TYPE_WINDOW, - GTK_TYPE_MENU_SHELL); - if (window != NULL) { - details = get_details (GTK_WINDOW (window)); - if (details != NULL) { - execute_pending_requests (GTK_WINDOW (window), - details); - details->in_button_press = FALSE; - } - } - - return TRUE; -} - -/* Called when a drag is started. If a drag-window is found above the - * widget emitting the signal, cancel any pending focus/raise requests - */ -static gboolean -drag_begin_emission_callback (GtkObject *object, guint signal_id, - guint n_params, GtkArg *params, - gpointer data) -{ - GtkWidget *window; - NautilusDragWindowDetails *details; - - window = gtk_widget_get_ancestor (GTK_WIDGET (object), - GTK_TYPE_WINDOW); - if (window != NULL) { - details = get_details (GTK_WINDOW (window)); - if (details != NULL) { - details->pending_focus = FALSE; - details->pending_raise = FALSE; - } - } - - return TRUE; -} - -/* The process-wide filter for WM_PROTOCOLS client messages */ -static GdkFilterReturn -wm_protocols_filter (GdkXEvent *xev, GdkEvent *event, gpointer data) -{ - XEvent *xevent; - GtkWindow *window; - NautilusDragWindowDetails *details; - - xevent = (XEvent *)xev; - - gdk_window_get_user_data (event->any.window, (gpointer *) &window); - if (window != NULL) { - details = get_details (window); - } else { - details = NULL; - } - - if ((Atom) xevent->xclient.data.l[0] == gdk_wm_delete_window) { - - /* (copied from gdkevents.c) */ - - /* The delete window request specifies a window - * to delete. We don't actually destroy the - * window because "it is only a request". (The - * window might contain vital data that the - * program does not want destroyed). Instead - * the event is passed along to the program, - * which should then destroy the window. - */ - - event->any.type = GDK_DELETE; - return GDK_FILTER_TRANSLATE; - - } else if ((Atom) xevent->xclient.data.l[0] == gdk_wm_take_focus) { - - if (details != NULL) { - details->pending_focus = TRUE; - details->focus_timestamp = xevent->xclient.data.l[1]; - - /* Wait to see if a button-press event - * is received in the near future. - */ - set_focus_timeout (window); - } - return GDK_FILTER_REMOVE; - - } else if ((Atom) xevent->xclient.data.l[0] == sawfish_wm_raise_window) { - - if (details != NULL) { - details->pending_raise = TRUE; - - /* Wait to see if a button-press event - * is received in the near future. - */ - set_focus_timeout (window); - } - return GDK_FILTER_REMOVE; - } - else { - return GDK_FILTER_CONTINUE; - } -} - -static void -nautilus_drag_window_destroy (GtkObject *object, gpointer data) -{ - NautilusDragWindowDetails *details; - - details = get_details (GTK_WINDOW (object)); - - remove_focus_timeout (GTK_WINDOW (object)); - - /* The `details' will be freed automatically */ -} - -static void -nautilus_drag_window_realize (GtkWidget *widget, gpointer data) -{ - GdkAtom protocols[3]; - - /* Tell the window manager _not_ to focus this window by itself */ - eel_gdk_window_set_wm_hints_input (widget->window, FALSE); - - /* Set WM_PROTOCOLS to the usual two atoms plus something that tells - * sawfish to send messages telling us when we might want to raise - * the window. (This won't work with other wm's, but it won't - * break anything either.) - */ - protocols[0] = gdk_wm_delete_window; - protocols[1] = gdk_wm_take_focus; - protocols[2] = sawfish_wm_raise_window; - eel_gdk_window_set_wm_protocols (widget->window, protocols, 3); -} - - -/* Public entry point */ - -/* initialize the instance's fields */ -void -nautilus_drag_window_register (GtkWindow *window) -{ - static gboolean initialized = FALSE; - - NautilusDragWindowDetails *details; - guint signal_id; - - if (!initialized) { - /* Add emission hooks for the signals we need to monitor - */ - signal_id = gtk_signal_lookup ("button_press_event", - GTK_TYPE_WIDGET); - gtk_signal_add_emission_hook (signal_id, - button_press_emission_callback, - NULL); - signal_id = gtk_signal_lookup ("button_release_event", - GTK_TYPE_WIDGET); - gtk_signal_add_emission_hook (signal_id, - button_release_emission_callback, - NULL); - signal_id = gtk_signal_lookup ("drag_begin", - GTK_TYPE_WIDGET); - gtk_signal_add_emission_hook (signal_id, - drag_begin_emission_callback, - NULL); - - /* Intern the necessary X atoms - */ - sawfish_wm_raise_window = XInternAtom (GDK_DISPLAY (), - "_SAWFISH_WM_RAISE_WINDOW", - False); - - /* Override the standard GTK filter for handling WM_PROTOCOLS - * client messages - */ - gdk_add_client_message_filter (gdk_wm_protocols, - wm_protocols_filter, NULL); - - initialized = TRUE; - } - - details = g_new0 (NautilusDragWindowDetails, 1); - - gtk_object_set_data_full (GTK_OBJECT (window), - NAUTILUS_DRAG_WINDOW_DETAILS_KEY, - details, g_free); - - gtk_signal_connect (GTK_OBJECT (window), "realize", - nautilus_drag_window_realize, NULL); - gtk_signal_connect (GTK_OBJECT (window), "destroy", - nautilus_drag_window_destroy, NULL); -} diff --git a/libnautilus-extensions/nautilus-drag-window.h b/libnautilus-extensions/nautilus-drag-window.h deleted file mode 100644 index 81e7a9c52..000000000 --- a/libnautilus-extensions/nautilus-drag-window.h +++ /dev/null @@ -1,40 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */ - -/* - * Nautilus - * - * Copyright (C) 2001 Eazel, Inc. - * - * Nautilus 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. - * - * Nautilus 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Author: John Harper <jsh@eazel.com> - * - */ - -#ifndef NAUTILUS_DRAG_WINDOW_H -#define NAUTILUS_DRAG_WINDOW_H - -#include <gtk/gtkwindow.h> - -/* Call this function before WINDOW has been realized. It will hook - * into the window so that it automatically supports the correct focus - * policy when dragging objects from within the window. (This policy is - * *not* to focus or raise the window when the activating click is used - * to drag something) - */ - -void nautilus_drag_window_register (GtkWindow *window); - -#endif /* NAUTILUS_DRAG_WINDOW_H */ diff --git a/libnautilus-extensions/nautilus-druid-page-eazel.c b/libnautilus-extensions/nautilus-druid-page-eazel.c deleted file mode 100644 index 51b9d8a53..000000000 --- a/libnautilus-extensions/nautilus-druid-page-eazel.c +++ /dev/null @@ -1,697 +0,0 @@ -/* gnome-druid-page-eazel.c - * Copyright (C) 1999 Red Hat, Inc. - * Copyright (C) 2000 Eazel, Inc. - * - * All rights reserved. - * - * 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. - * - * This 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; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ -/* - @NOTATION@ -*/ - -#include <config.h> - -#include "nautilus-druid-page-eazel.h" - -#include <eel/eel-gtk-macros.h> - -#include <libgnomeui/gnome-uidefs.h> -#include <libgnomeui/libgnomeui.h> -#include <libgnomeui/gnome-druid.h> -#include <libgnomeui/gnome-druid-page.h> - -#include <gdk-pixbuf/gnome-canvas-pixbuf.h> -#include "nautilus-druid.h" -#include <libgnome/gnome-i18n.h> - -#include <libnautilus-extensions/nautilus-file-utilities.h> - -struct NautilusDruidPageEazelDetails -{ - GnomeCanvasItem *background_item; - GnomeCanvasItem *background_image_item; - GnomeCanvasItem *topbar_image_item; - int topbar_image_width; - GnomeCanvasItem *topbar_image_stretch_item; - GnomeCanvasItem *title_item; - GtkWidget *title_label; - guint title_label_signal_id; - GnomeCanvasItem *text_item; - GnomeCanvasItem *sidebar_image_item; - GnomeCanvasItem *title_image_item; - GnomeCanvasItem *widget_item; -}; - -static void nautilus_druid_page_eazel_initialize (NautilusDruidPageEazel *druid_page_eazel); -static void nautilus_druid_page_eazel_initialize_class (NautilusDruidPageEazelClass *klass); -static void nautilus_druid_page_eazel_destroy (GtkObject *object); -static void nautilus_druid_page_eazel_finalize (GtkObject *object); -static void nautilus_druid_page_eazel_construct (NautilusDruidPageEazel *druid_page_eazel); -static void nautilus_druid_page_eazel_configure_size(NautilusDruidPageEazel *druid_page_eazel, - gint width, - gint height); -static void nautilus_druid_page_eazel_size_allocate (GtkWidget *widget, - GtkAllocation *allocation); -static void nautilus_druid_page_eazel_size_request (GtkWidget *widget, - GtkRequisition *requisition); -static void nautilus_druid_page_eazel_prepare (GnomeDruidPage *page, - GtkWidget *druid, - gpointer *data); - -#define TITLE_X 60.0 -#define TITLE_Y 60.0 -#define CONTENT_PADDING 15.0 -#define DEFAULT_CONTENT_X 34.0 -#define DRUID_PAGE_MIN_HEIGHT 322 -#define DRUID_PAGE_MIN_WIDTH 516 -#define DRUID_PAGE_BORDER 24 - -EEL_DEFINE_CLASS_BOILERPLATE (NautilusDruidPageEazel, nautilus_druid_page_eazel, GNOME_TYPE_DRUID_PAGE) - -static void -nautilus_druid_page_eazel_initialize_class (NautilusDruidPageEazelClass *klass) -{ - GtkObjectClass *object_class; - GtkWidgetClass *widget_class; - - object_class = (GtkObjectClass*) klass; - widget_class = (GtkWidgetClass*) klass; - - parent_class = gtk_type_class (gnome_druid_page_get_type ()); - - object_class->destroy = nautilus_druid_page_eazel_destroy; - object_class->finalize = nautilus_druid_page_eazel_finalize; - - widget_class->size_allocate = nautilus_druid_page_eazel_size_allocate; - widget_class->size_request = nautilus_druid_page_eazel_size_request; -} - -static void -nautilus_druid_page_eazel_initialize (NautilusDruidPageEazel *druid_page_eazel) -{ - druid_page_eazel->details = g_new0(NautilusDruidPageEazelDetails, 1); - - /* Set up the canvas */ - gtk_container_set_border_width (GTK_CONTAINER (druid_page_eazel), 0); - gtk_widget_push_visual (gdk_rgb_get_visual ()); - gtk_widget_push_colormap (gdk_rgb_get_cmap ()); - druid_page_eazel->canvas = gnome_canvas_new_aa (); - gtk_widget_pop_visual (); - gtk_widget_pop_colormap (); - gtk_widget_show (druid_page_eazel->canvas); - gtk_container_add (GTK_CONTAINER (druid_page_eazel), druid_page_eazel->canvas); - nautilus_druid_page_eazel_configure_size (druid_page_eazel, - DRUID_PAGE_MIN_WIDTH, - DRUID_PAGE_MIN_HEIGHT); -} - -static void -nautilus_druid_page_eazel_destroy(GtkObject *object) -{ - NautilusDruidPageEazel *druid_page_eazel = - NAUTILUS_DRUID_PAGE_EAZEL(object); - - druid_page_eazel->canvas = NULL; - druid_page_eazel->widget = NULL; - - g_free (druid_page_eazel->title); - druid_page_eazel->title = NULL; - g_free (druid_page_eazel->text); - druid_page_eazel->text = NULL; - - if (druid_page_eazel->title_image != NULL) - gdk_pixbuf_unref (druid_page_eazel->title_image); - druid_page_eazel->title_image = NULL; - if (druid_page_eazel->sidebar_image != NULL) - gdk_pixbuf_unref (druid_page_eazel->sidebar_image); - druid_page_eazel->sidebar_image = NULL; - - if (druid_page_eazel->widget != NULL) - gtk_widget_unref (druid_page_eazel->widget); - druid_page_eazel->widget = NULL; - - /* Chain destroy */ - EEL_CALL_PARENT (GTK_OBJECT_CLASS, destroy, (object)); -} - -static void -nautilus_druid_page_eazel_finalize (GtkObject *object) -{ - NautilusDruidPageEazel *druid_page_eazel = - NAUTILUS_DRUID_PAGE_EAZEL(object); - - g_free(druid_page_eazel->details); - druid_page_eazel->details = NULL; - - /* Chain finalize */ - EEL_CALL_PARENT (GTK_OBJECT_CLASS, finalize, (object)); -} - -static void -get_content_xy (NautilusDruidPageEazel *druid_page_eazel, - double *content_x, double *content_y) -{ - double title_height; - - if (druid_page_eazel->sidebar_image) { - *content_x = gdk_pixbuf_get_width (druid_page_eazel->sidebar_image); - } else { - *content_x = DEFAULT_CONTENT_X; - } - - if (druid_page_eazel->title_image) { - *content_y = gdk_pixbuf_get_height (druid_page_eazel->title_image) + TITLE_Y + CONTENT_PADDING; - } else { - *content_y = TITLE_Y; - } - - title_height = 0.0; - if (druid_page_eazel->title && druid_page_eazel->title[0] != '\0') { - gtk_object_get (GTK_OBJECT (druid_page_eazel->details->title_item), - "height", &title_height, - NULL); - title_height += CONTENT_PADDING; - } - - if (*content_y < title_height + TITLE_Y) { - *content_y = title_height + TITLE_Y; - } -} - - -static void -nautilus_druid_page_eazel_configure_size (NautilusDruidPageEazel *druid_page_eazel, gint width, gint height) -{ - double content_x; - double content_y; - - g_return_if_fail (druid_page_eazel != NULL); - g_return_if_fail (NAUTILUS_IS_DRUID_PAGE_EAZEL (druid_page_eazel)); - - get_content_xy (druid_page_eazel, &content_x, &content_y); - - gnome_canvas_set_scroll_region (GNOME_CANVAS (druid_page_eazel->canvas), - 0.0, 0.0, width, height); - - if (druid_page_eazel->details->background_item != NULL) { - gnome_canvas_item_set (druid_page_eazel->details->background_item, - "x1", 0.0, - "y1", 0.0, - "x2", (gfloat) width, - "y2", (gfloat) height, - NULL); - } - - if (druid_page_eazel->details->topbar_image_stretch_item != NULL) { - gnome_canvas_item_set (druid_page_eazel->details->topbar_image_stretch_item, - "width", (double) (width - druid_page_eazel->details->topbar_image_width), - "width_set", TRUE, - NULL); - } - - if (druid_page_eazel->details->widget_item != NULL) { - gnome_canvas_item_set (druid_page_eazel->details->widget_item, - "x", content_x, - "y", content_y, - NULL); - - /* Event boxes can handle not having the size set, and - * not doing so allows them to scale with their child - * widget. On the other hand, some other widgets require - * the size to be set, otherwise they won't appear on the - * canvas! - */ - if (druid_page_eazel->widget != NULL && !GTK_IS_EVENT_BOX (druid_page_eazel->widget)) { - gnome_canvas_item_set (druid_page_eazel->details->widget_item, - "width", (gfloat) width - content_x, - "height", (gfloat) height - content_y, - NULL); - } - } - - if (druid_page_eazel->details->text_item != NULL) { - gnome_canvas_item_set (druid_page_eazel->details->text_item, - "x", content_x, - "y", content_y, - NULL); - } -} - -static void -set_image (GnomeCanvasItem *item, const char *file, - int *width, int *height) -{ - char *fullname; - - if (width != NULL) - *width = 0; - if (height != NULL) - *height = 0; - - fullname = nautilus_pixmap_file (file); - if (fullname != NULL) { - GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file (fullname); - if (pixbuf != NULL) { - if (width != NULL) - *width = gdk_pixbuf_get_width (pixbuf); - if (height != NULL) - *height = gdk_pixbuf_get_height (pixbuf); - gnome_canvas_item_set (item, - "pixbuf", pixbuf, - NULL); - gdk_pixbuf_unref (pixbuf); - } - g_free (fullname); - } -} - -static void -title_label_size_allocated (GtkWidget *widget, GtkAllocation *allocation, gpointer data) -{ - NautilusDruidPageEazel *druid_page_eazel = NAUTILUS_DRUID_PAGE_EAZEL (data); - gnome_canvas_item_set (druid_page_eazel->details->title_item, - "size_pixels", TRUE, - "height", (double) allocation->height, - "width", (double) allocation->width, - NULL); -} - - -static void -nautilus_druid_page_eazel_construct (NautilusDruidPageEazel *druid_page_eazel) -{ - druid_page_eazel->details->background_item = - gnome_canvas_item_new (gnome_canvas_root (GNOME_CANVAS (druid_page_eazel->canvas)), - gnome_canvas_rect_get_type (), - "x1", 0.0, - "y1", 0.0, - "fill_color", "white", - NULL); - - druid_page_eazel->details->background_image_item = - gnome_canvas_item_new (gnome_canvas_root (GNOME_CANVAS (druid_page_eazel->canvas)), - gnome_canvas_pixbuf_get_type (), - "x", 0.0, - "y", 0.0, - "x_in_pixels", TRUE, - "y_in_pixels", TRUE, - NULL); - if (druid_page_eazel->background_image) - gnome_canvas_item_set (druid_page_eazel->details->background_image_item, - "pixbuf", druid_page_eazel->background_image, - NULL); - - druid_page_eazel->details->sidebar_image_item = - gnome_canvas_item_new (gnome_canvas_root (GNOME_CANVAS (druid_page_eazel->canvas)), - gnome_canvas_pixbuf_get_type (), - "x", 0.0, - "y", 0.0, - "x_in_pixels", TRUE, - "y_in_pixels", TRUE, - NULL); - if (druid_page_eazel->sidebar_image) - gnome_canvas_item_set (druid_page_eazel->details->sidebar_image_item, - "pixbuf", druid_page_eazel->sidebar_image, - NULL); - - druid_page_eazel->details->topbar_image_item = - gnome_canvas_item_new (gnome_canvas_root (GNOME_CANVAS (druid_page_eazel->canvas)), - gnome_canvas_pixbuf_get_type (), - "x", 0.0, - "y", 0.0, - "x_in_pixels", TRUE, - "y_in_pixels", TRUE, - NULL); - set_image (druid_page_eazel->details->topbar_image_item, - "druid_header.png", - &druid_page_eazel->details->topbar_image_width, - NULL); - - druid_page_eazel->details->topbar_image_stretch_item = - gnome_canvas_item_new (gnome_canvas_root (GNOME_CANVAS (druid_page_eazel->canvas)), - gnome_canvas_pixbuf_get_type (), - "x", (double)druid_page_eazel->details->topbar_image_width, - "y", 0.0, - "x_in_pixels", TRUE, - "y_in_pixels", TRUE, - NULL); - set_image (druid_page_eazel->details->topbar_image_stretch_item, - "druid_header_stretch.png", NULL, NULL); - - druid_page_eazel->details->title_image_item = - gnome_canvas_item_new (gnome_canvas_root (GNOME_CANVAS (druid_page_eazel->canvas)), - gnome_canvas_pixbuf_get_type (), - "x", TITLE_X, - "y", TITLE_Y, - "x_in_pixels", TRUE, - "y_in_pixels", TRUE, - NULL); - if (druid_page_eazel->title_image) - gnome_canvas_item_set (druid_page_eazel->details->title_image_item, - "pixbuf", druid_page_eazel->title_image, - NULL); - - druid_page_eazel->details->title_item = - gnome_canvas_item_new (gnome_canvas_root (GNOME_CANVAS (druid_page_eazel->canvas)), - gnome_canvas_widget_get_type (), - "x", TITLE_X, - "y", TITLE_Y, - NULL); - - druid_page_eazel->details->text_item = - gnome_canvas_item_new (gnome_canvas_root (GNOME_CANVAS (druid_page_eazel->canvas)), - gnome_canvas_text_get_type (), - "text", druid_page_eazel->text, - "fill_color", "black", - /* Note to localizers: this font is used for text items in Druid pages */ - "fontset", _("-adobe-helvetica-bold-r-normal-*-*-120-*-*-p-*-*-*,*-r-*"), - "anchor", GTK_ANCHOR_NW, - NULL); - - nautilus_druid_page_eazel_configure_size (druid_page_eazel, DRUID_PAGE_MIN_WIDTH, DRUID_PAGE_MIN_HEIGHT); - gtk_signal_connect (GTK_OBJECT (druid_page_eazel), - "prepare", - nautilus_druid_page_eazel_prepare, - NULL); -} - -static void -nautilus_druid_page_eazel_prepare (GnomeDruidPage *page, - GtkWidget *druid, - gpointer *data) -{ - switch (NAUTILUS_DRUID_PAGE_EAZEL (page)->position) { - case NAUTILUS_DRUID_PAGE_EAZEL_START: - gnome_druid_set_buttons_sensitive (GNOME_DRUID (druid), FALSE, TRUE, TRUE); - gnome_druid_set_show_finish (GNOME_DRUID (druid), FALSE); - gtk_widget_grab_default (GNOME_DRUID (druid)->next); - break; - case NAUTILUS_DRUID_PAGE_EAZEL_FINISH: - gnome_druid_set_buttons_sensitive (GNOME_DRUID (druid), TRUE, FALSE, TRUE); - gnome_druid_set_show_finish (GNOME_DRUID (druid), TRUE); - gtk_widget_grab_default (GNOME_DRUID (druid)->finish); - break; - case NAUTILUS_DRUID_PAGE_EAZEL_OTHER: - gnome_druid_set_buttons_sensitive (GNOME_DRUID (druid), TRUE, TRUE, TRUE); - gnome_druid_set_show_finish (GNOME_DRUID (druid), FALSE); - default: - break; - } -} - - -static void -nautilus_druid_page_eazel_size_allocate(GtkWidget *widget, - GtkAllocation *allocation) -{ - EEL_CALL_PARENT (GTK_WIDGET_CLASS, size_allocate, - (widget, allocation)); - - gnome_canvas_set_scroll_region (GNOME_CANVAS (NAUTILUS_DRUID_PAGE_EAZEL (widget)->canvas), - 0.0, 0.0, - allocation->width, - allocation->height); - - nautilus_druid_page_eazel_configure_size (NAUTILUS_DRUID_PAGE_EAZEL (widget), - allocation->width, - allocation->height); -} - -static void -nautilus_druid_page_eazel_size_request(GtkWidget *widget, - GtkRequisition *requisition) -{ - NautilusDruidPageEazel *druid_page_eazel; - - druid_page_eazel = NAUTILUS_DRUID_PAGE_EAZEL (widget); - - EEL_CALL_PARENT (GTK_WIDGET_CLASS, size_request, - (widget, requisition)); - - if (druid_page_eazel->widget) { - GtkRequisition child_requisition; - double x, y; - - g_assert (druid_page_eazel->details->widget_item != NULL); - - get_content_xy (druid_page_eazel, &x, &y); - - gtk_widget_get_child_requisition (druid_page_eazel->widget, - &child_requisition); - - if (child_requisition.width + x > requisition->width) { - requisition->width = child_requisition.width + x + DRUID_PAGE_BORDER; - } - if (child_requisition.height + y > requisition->height) { - requisition->height = child_requisition.height + y + DRUID_PAGE_BORDER; - } - } -} - - -/** - * nautilus_druid_page_eazel_new: - * - * Creates a new NautilusDruidPageEazel widget. - * - * Return value: Pointer to new NautilusDruidPageEazel - **/ -/* Public functions */ -GtkWidget * -nautilus_druid_page_eazel_new (NautilusDruidPageEazelPosition position) -{ - NautilusDruidPageEazel *page; - - page = NAUTILUS_DRUID_PAGE_EAZEL (gtk_widget_new (nautilus_druid_page_eazel_get_type (), NULL)); - - page->position = position; - page->title = g_strdup (""); - page->text = g_strdup (""); - page->title_image = NULL; - page->sidebar_image = NULL; - page->background_image = NULL; - nautilus_druid_page_eazel_construct (page); - - return GTK_WIDGET (page); -} -/** - * nautilus_druid_page_eazel_new_with_vals: - * @title: The title. - * @text: The introduction text. - * @logo: The logo in the upper right corner. - * @watermark: The watermark on the left. - * - * This will create a new GNOME Druid Eazel page, with the values - * given. It is acceptable for any of them to be %NULL. - * - * Return value: GtkWidget pointer to new NautilusDruidPageEazel. - **/ -GtkWidget * -nautilus_druid_page_eazel_new_with_vals (NautilusDruidPageEazelPosition position, - const gchar *title, - const gchar* text, - GdkPixbuf *title_image, - GdkPixbuf *sidebar_image, - GdkPixbuf *background_image) -{ - NautilusDruidPageEazel *page; - - page = NAUTILUS_DRUID_PAGE_EAZEL (gtk_widget_new (nautilus_druid_page_eazel_get_type (), NULL)); - - page->position = position; - page->title = g_strdup (title ? title : ""); - page->text = g_strdup (text ? text : ""); - - if (title_image) - gdk_pixbuf_ref (title_image); - page->title_image = title_image; - - if (sidebar_image) - gdk_pixbuf_ref (sidebar_image); - page->sidebar_image = sidebar_image; - - if (background_image) - gdk_pixbuf_ref (background_image); - page->background_image = background_image; - - nautilus_druid_page_eazel_construct (page); - - return GTK_WIDGET (page); -} - -void -nautilus_druid_page_eazel_set_text (NautilusDruidPageEazel *druid_page_eazel, - const gchar *text) -{ - g_return_if_fail (druid_page_eazel != NULL); - g_return_if_fail (NAUTILUS_IS_DRUID_PAGE_EAZEL (druid_page_eazel)); - - g_free (druid_page_eazel->text); - druid_page_eazel->text = g_strdup (text ? text : ""); - gnome_canvas_item_set (druid_page_eazel->details->text_item, - "text", druid_page_eazel->text, - NULL); -} - -static GtkWidget * -make_title_label (const char *text) -{ - GtkWidget *label; - GtkStyle *new_style; - GdkFont *font; - - label = gtk_label_new (text); - - /* Note to localizers: this font is used for page titles in Druid pages */ - font = gdk_fontset_load (_("-adobe-helvetica-bold-r-normal-*-*-180-*-*-p-*-*-*,*-r-*")); - if (font != NULL) { - new_style = gtk_style_copy (gtk_widget_get_style (label)); - gdk_font_unref (new_style->font); - new_style->font = font; - gtk_widget_set_style (label, new_style); - gtk_style_unref (new_style); - } - - return label; -} - -void -nautilus_druid_page_eazel_set_title (NautilusDruidPageEazel *druid_page_eazel, - const gchar *title) -{ - GtkWidget *label; - - g_return_if_fail (druid_page_eazel != NULL); - g_return_if_fail (NAUTILUS_IS_DRUID_PAGE_EAZEL (druid_page_eazel)); - - g_free (druid_page_eazel->title); - druid_page_eazel->title = g_strdup (title ? title : ""); - - if (druid_page_eazel->details->title_label == NULL) { - label = make_title_label (druid_page_eazel->title); - nautilus_druid_page_eazel_set_title_label (druid_page_eazel, GTK_LABEL (label)); - } else { - gtk_label_set_text (GTK_LABEL (druid_page_eazel->details->title_label), druid_page_eazel->title); - } -} - -void -nautilus_druid_page_eazel_set_title_label (NautilusDruidPageEazel *druid_page_eazel, - GtkLabel *label) -{ - g_return_if_fail (druid_page_eazel != NULL); - g_return_if_fail (NAUTILUS_IS_DRUID_PAGE_EAZEL (druid_page_eazel)); - g_return_if_fail (GTK_IS_LABEL (label)); - - if (druid_page_eazel->details->title_label != NULL) { - gtk_signal_disconnect (GTK_OBJECT (druid_page_eazel->details->title_label), - druid_page_eazel->details->title_label_signal_id); - } - - gtk_widget_show (GTK_WIDGET (label)); - gnome_canvas_item_set (druid_page_eazel->details->title_item, - "widget", label, - NULL); - druid_page_eazel->details->title_label = GTK_WIDGET (label); - druid_page_eazel->details->title_label_signal_id = - gtk_signal_connect (GTK_OBJECT (label), "size_allocate", - title_label_size_allocated, - druid_page_eazel); - - if (druid_page_eazel->title != NULL) { - g_free (druid_page_eazel->title); - } - druid_page_eazel->title = g_strdup (label->label); -} - -void -nautilus_druid_page_eazel_set_title_image (NautilusDruidPageEazel *druid_page_eazel, - GdkPixbuf *title_image) -{ - g_return_if_fail (druid_page_eazel != NULL); - g_return_if_fail (NAUTILUS_IS_DRUID_PAGE_EAZEL (druid_page_eazel)); - - if (druid_page_eazel->title_image) - gdk_pixbuf_unref (druid_page_eazel->title_image); - - druid_page_eazel->title_image = title_image; - if (title_image != NULL) - gdk_pixbuf_ref (title_image); - gnome_canvas_item_set (druid_page_eazel->details->title_image_item, - "pixbuf", druid_page_eazel->title_image, NULL); -} - -void -nautilus_druid_page_eazel_set_sidebar_image (NautilusDruidPageEazel *druid_page_eazel, - GdkPixbuf *sidebar_image) -{ - g_return_if_fail (druid_page_eazel != NULL); - g_return_if_fail (NAUTILUS_IS_DRUID_PAGE_EAZEL (druid_page_eazel)); - - if (druid_page_eazel->sidebar_image) - gdk_pixbuf_unref (druid_page_eazel->sidebar_image); - - druid_page_eazel->sidebar_image = sidebar_image; - if (sidebar_image != NULL) - gdk_pixbuf_ref (sidebar_image); - gnome_canvas_item_set (druid_page_eazel->details->sidebar_image_item, - "pixbuf", druid_page_eazel->sidebar_image, NULL); -} - -void -nautilus_druid_page_eazel_set_background_image (NautilusDruidPageEazel *druid_page_eazel, - GdkPixbuf *background_image) -{ - g_return_if_fail (druid_page_eazel != NULL); - g_return_if_fail (NAUTILUS_IS_DRUID_PAGE_EAZEL (druid_page_eazel)); - - if (druid_page_eazel->background_image) - gdk_pixbuf_unref (druid_page_eazel->background_image); - - druid_page_eazel->background_image = background_image; - if (background_image != NULL) - gdk_pixbuf_ref (background_image); - gnome_canvas_item_set (druid_page_eazel->details->background_image_item, - "pixbuf", druid_page_eazel->background_image, NULL); -} - -void -nautilus_druid_page_eazel_put_widget (NautilusDruidPageEazel *druid_page_eazel, - GtkWidget *widget) -{ - g_return_if_fail (druid_page_eazel != NULL); - g_return_if_fail (NAUTILUS_IS_DRUID_PAGE_EAZEL (druid_page_eazel)); - - if (druid_page_eazel->details->widget_item != NULL) { - gtk_object_destroy (GTK_OBJECT (druid_page_eazel->details->widget_item)); - } - if (druid_page_eazel->widget != NULL) { - gtk_widget_unref (druid_page_eazel->widget); - } - - druid_page_eazel->widget = widget; - if (widget != NULL) - gtk_widget_ref (widget); - - druid_page_eazel->details->widget_item = - gnome_canvas_item_new (gnome_canvas_root (GNOME_CANVAS (druid_page_eazel->canvas)), - gnome_canvas_widget_get_type (), - "widget", widget, - NULL); - - gtk_widget_queue_resize (GTK_WIDGET (druid_page_eazel)); -} diff --git a/libnautilus-extensions/nautilus-druid-page-eazel.h b/libnautilus-extensions/nautilus-druid-page-eazel.h deleted file mode 100644 index fb33e50ca..000000000 --- a/libnautilus-extensions/nautilus-druid-page-eazel.h +++ /dev/null @@ -1,100 +0,0 @@ -/* nautilus-druid-page-eazel.h - * Copyright (C) 1999 Red Hat, Inc. - * - * All rights reserved. - * - * 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. - * - * This 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; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ -/* - @NOTATION@ -*/ -#ifndef NAUTILUS_DRUID_PAGE_EAZEL_H -#define NAUTILUS_DRUID_PAGE_EAZEL_H - -#include <libgnomeui/gnome-canvas.h> -#include <libgnomeui/gnome-druid-page.h> -#include <gdk-pixbuf/gdk-pixbuf.h> - -BEGIN_GNOME_DECLS - -#define NAUTILUS_TYPE_DRUID_PAGE_EAZEL (nautilus_druid_page_eazel_get_type ()) -#define NAUTILUS_DRUID_PAGE_EAZEL(obj) (GTK_CHECK_CAST ((obj), NAUTILUS_TYPE_DRUID_PAGE_EAZEL, NautilusDruidPageEazel)) -#define NAUTILUS_DRUID_PAGE_EAZEL_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), NAUTILUS_TYPE_DRUID_PAGE_EAZEL, NautilusDruidPageEazelClass)) -#define NAUTILUS_IS_DRUID_PAGE_EAZEL(obj) (GTK_CHECK_TYPE ((obj), NAUTILUS_TYPE_DRUID_PAGE_EAZEL)) -#define NAUTILUS_IS_DRUID_PAGE_EAZEL_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), NAUTILUS_TYPE_DRUID_PAGE_EAZEL)) - -typedef enum { - /* update structure when adding enums */ - NAUTILUS_DRUID_PAGE_EAZEL_START, - NAUTILUS_DRUID_PAGE_EAZEL_FINISH, - NAUTILUS_DRUID_PAGE_EAZEL_OTHER -} NautilusDruidPageEazelPosition; - - -typedef struct NautilusDruidPageEazel NautilusDruidPageEazel; -typedef struct NautilusDruidPageEazelDetails NautilusDruidPageEazelDetails; -typedef struct NautilusDruidPageEazelClass NautilusDruidPageEazelClass; - -struct NautilusDruidPageEazel -{ - GnomeDruidPage parent; - - GtkWidget *canvas; - char *title; - char *text; - GdkPixbuf *title_image; - GdkPixbuf *sidebar_image; - GdkPixbuf *background_image; - - GtkWidget *widget; - - NautilusDruidPageEazelPosition position : 2; - - /*< private >*/ - NautilusDruidPageEazelDetails *details; -}; - -struct NautilusDruidPageEazelClass -{ - GnomeDruidPageClass parent_class; -}; - -GtkType nautilus_druid_page_eazel_get_type (void); -GtkWidget *nautilus_druid_page_eazel_new (NautilusDruidPageEazelPosition position); -GtkWidget *nautilus_druid_page_eazel_new_with_vals (NautilusDruidPageEazelPosition position, - const gchar *title, - const gchar *text, - GdkPixbuf *title_image, - GdkPixbuf *sidebar_image, - GdkPixbuf *background_image); -void nautilus_druid_page_eazel_put_widget (NautilusDruidPageEazel *druid_page_eazel, - GtkWidget *widget); -void nautilus_druid_page_eazel_set_text (NautilusDruidPageEazel *druid_page_eazel, - const gchar *text); -void nautilus_druid_page_eazel_set_title (NautilusDruidPageEazel *druid_page_eazel, - const gchar *title); -void nautilus_druid_page_eazel_set_title_label (NautilusDruidPageEazel *druid_page_eazel, - GtkLabel *label); -void nautilus_druid_page_eazel_set_title_image (NautilusDruidPageEazel *druid_page_eazel, - GdkPixbuf *title_image); -void nautilus_druid_page_eazel_set_sidebar_image (NautilusDruidPageEazel *druid_page_eazel, - GdkPixbuf *sidebar_image); -void nautilus_druid_page_eazel_set_background_image(NautilusDruidPageEazel *druid_page_eazel, - GdkPixbuf *background_image); - -END_GNOME_DECLS - -#endif /* NAUTILUS_DRUID_PAGE_EAZEL_H */ diff --git a/libnautilus-extensions/nautilus-druid.c b/libnautilus-extensions/nautilus-druid.c deleted file mode 100644 index 49eeff81d..000000000 --- a/libnautilus-extensions/nautilus-druid.c +++ /dev/null @@ -1,204 +0,0 @@ -/* gnome-druid.c - * Copyright (C) 1999 Red Hat, Inc. - * Copyright (C) 2000 Eazel, Inc. - * All rights reserved. - * - * 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. - * - * This 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; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ -/* - @NOTATION@ -*/ -#include <config.h> - -#include "nautilus-druid.h" -#include <libgnomeui/gnome-stock.h> -#include <libgnomeui/gnome-uidefs.h> -#include <libgnome/gnome-i18n.h> - -#include <eel/eel-gtk-macros.h> - -static void nautilus_druid_initialize (NautilusDruid *druid); -static void nautilus_druid_initialize_class(NautilusDruidClass *klass); -static void nautilus_druid_size_request (GtkWidget *widget, - GtkRequisition *requisition); -static void nautilus_druid_size_allocate(GtkWidget *widget, - GtkAllocation *allocation); - -EEL_DEFINE_CLASS_BOILERPLATE (NautilusDruid, nautilus_druid, GNOME_TYPE_DRUID) - -static void -nautilus_druid_initialize_class (NautilusDruidClass *klass) -{ - GtkWidgetClass *widget_class; - - widget_class = (GtkWidgetClass*) klass; - - parent_class = gtk_type_class (gtk_container_get_type ()); - - widget_class->size_request = nautilus_druid_size_request; - widget_class->size_allocate = nautilus_druid_size_allocate; -} - -static void -nautilus_druid_initialize (NautilusDruid *druid) -{ -} - -static void -nautilus_druid_size_request (GtkWidget *widget, - GtkRequisition *requisition) -{ - guint16 temp_width, temp_height; - GList *list; - GnomeDruid *druid; - GtkRequisition child_requisition; - GnomeDruidPage *child; - int border; - - g_return_if_fail (widget != NULL); - g_return_if_fail (NAUTILUS_IS_DRUID (widget)); - - border = GTK_CONTAINER(widget)->border_width; - - druid = GNOME_DRUID (widget); - temp_height = temp_width = 0; - - /* We find the maximum size of all children widgets */ - for (list = druid->children; list; list = list->next) { - child = GNOME_DRUID_PAGE (list->data); - if (GTK_WIDGET_VISIBLE (child)) { - gtk_widget_size_request (GTK_WIDGET (child), &child_requisition); - temp_width = MAX (temp_width, child_requisition.width); - temp_height = MAX (temp_height, child_requisition.height); - if (GTK_WIDGET_MAPPED (child) && child != druid->current) - gtk_widget_unmap (GTK_WIDGET(child)); - } - } - - requisition->width = temp_width + 2 * border; - requisition->height = temp_height + 2 * border; - - /* In an Attempt to show how the widgets are packed, - * here's a little diagram. - * - * [ Cancel ] ------------- [ Back ] [ Next ] - * | - * This part needs to be at least 1 button width. - * In addition, there is a GNOME_PAD_SMALL between Next and Back. - */ - /* our_button width is temp_width and temp_height */ - temp_height = 0; - temp_width = 0; - - gtk_widget_size_request (druid->back, &child_requisition); - temp_width = MAX (temp_width, child_requisition.width); - temp_height = MAX (temp_height, child_requisition.height); - - gtk_widget_size_request (druid->next, &child_requisition); - temp_width = MAX (temp_width, child_requisition.width); - temp_height = MAX (temp_height, child_requisition.height); - - gtk_widget_size_request (druid->cancel, &child_requisition); - temp_width = MAX (temp_width, child_requisition.width); - temp_height = MAX (temp_height, child_requisition.height); - - gtk_widget_size_request (druid->finish, &child_requisition); - temp_width = MAX (temp_width, child_requisition.width); - temp_height = MAX (temp_height, child_requisition.height); - - temp_width += border * 2; - temp_height += GNOME_PAD_SMALL; - temp_width = temp_width * 4 + GNOME_PAD_SMALL * 3; - - /* pick which is bigger, the buttons, or the NautilusDruidPages */ - requisition->width = MAX (temp_width, requisition->width); - requisition->height += temp_height; -} - -static void -nautilus_druid_size_allocate (GtkWidget *widget, - GtkAllocation *allocation) -{ - GnomeDruid *druid; - GtkAllocation child_allocation; - gint button_height; - GList *list; - int border; - - g_return_if_fail (widget != NULL); - g_return_if_fail (NAUTILUS_IS_DRUID (widget)); - - druid = GNOME_DRUID (widget); - widget->allocation = *allocation; - - /* deal with the buttons */ - child_allocation.width = child_allocation.height = 0; - child_allocation.width = druid->back->requisition.width; - child_allocation.height = druid->back->requisition.height; - child_allocation.width = MAX (child_allocation.width, - druid->next->requisition.width); - child_allocation.height = MAX (child_allocation.height, - druid->next->requisition.height); - child_allocation.width = MAX (child_allocation.width, - druid->cancel->requisition.width); - child_allocation.height = MAX (child_allocation.height, - druid->cancel->requisition.height); - - child_allocation.height += GNOME_PAD_SMALL; - button_height = child_allocation.height; - child_allocation.width += 2 * GNOME_PAD_SMALL; - child_allocation.y = allocation->y + allocation->height - - GNOME_PAD_SMALL - child_allocation.height; - - /* allocate cancel */ - child_allocation.x = allocation->x + GNOME_PAD_SMALL; - gtk_widget_size_allocate (druid->cancel, &child_allocation); - - - /* Allocate next/finish */ - child_allocation.x = allocation->x + allocation->width - - GNOME_PAD_SMALL - child_allocation.width; - gtk_widget_size_allocate (druid->next, &child_allocation); - gtk_widget_size_allocate (druid->finish, &child_allocation); - - /* Allocate back */ - child_allocation.x -= (GNOME_PAD_SMALL + child_allocation.width); - gtk_widget_size_allocate (druid->back, &child_allocation); - - border = GTK_CONTAINER (widget)->border_width; - - /* Put up the GnomeDruidPage */ - child_allocation.x = allocation->x + border; - child_allocation.y = allocation->y + border; - child_allocation.width = - ((allocation->width - 2 * border) > 0) ? - (allocation->width - 2 * border):0; - child_allocation.height = - ((allocation->height - 2 * border - GNOME_PAD_SMALL - button_height) > 0) ? - (allocation->height - 2 * border - GNOME_PAD_SMALL - button_height):0; - for (list = druid->children; list; list=list->next) { - if (GTK_WIDGET_VISIBLE (list->data)) { - gtk_widget_size_allocate (GTK_WIDGET (list->data), &child_allocation); - } - } -} - -/* Public methods */ -GtkWidget * -nautilus_druid_new (void) -{ - return gtk_widget_new (NAUTILUS_TYPE_DRUID, NULL); -} diff --git a/libnautilus-extensions/nautilus-druid.h b/libnautilus-extensions/nautilus-druid.h deleted file mode 100644 index a85c14194..000000000 --- a/libnautilus-extensions/nautilus-druid.h +++ /dev/null @@ -1,57 +0,0 @@ -/* nautilus-druid.h - * Copyright (C) 1999 Red Hat, Inc. - * Copyright (C) 2000 Eazel, Inc. - * All rights reserved. - * - * 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. - * - * This 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; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ -/* - @NOTATION@ -*/ -#ifndef NAUTILUS_DRUID_H -#define NAUTILUS_DRUID_H - -#include <libgnome/gnome-defs.h> -#include <libgnomeui/gnome-druid.h> - -BEGIN_GNOME_DECLS - -#define NAUTILUS_TYPE_DRUID (nautilus_druid_get_type ()) -#define NAUTILUS_DRUID(obj) (GTK_CHECK_CAST ((obj), NAUTILUS_TYPE_DRUID, NautilusDruid)) -#define NAUTILUS_DRUID_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), NAUTILUS_TYPE_DRUID, NautilusDruidClass)) -#define NAUTILUS_IS_DRUID(obj) (GTK_CHECK_TYPE ((obj), NAUTILUS_TYPE_DRUID)) -#define NAUTILUS_IS_DRUID_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), NAUTILUS_TYPE_DRUID)) - - -typedef struct NautilusDruid NautilusDruid; -typedef struct NautilusDruidClass NautilusDruidClass; - -struct NautilusDruid -{ - GnomeDruid gnome_druid; -}; -struct NautilusDruidClass -{ - GnomeDruidClass parent_class; -}; - - -GtkType nautilus_druid_get_type (void); -GtkWidget *nautilus_druid_new (void); - -END_GNOME_DECLS - -#endif /* NAUTILUS_DRUID_H */ diff --git a/libnautilus-extensions/nautilus-entry.c b/libnautilus-extensions/nautilus-entry.c deleted file mode 100644 index a465563b9..000000000 --- a/libnautilus-extensions/nautilus-entry.c +++ /dev/null @@ -1,460 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ - -/* NautilusEntry: one-line text editing widget. This consists of bug fixes - * and other improvements to GtkEntry, and all the changes could be rolled - * into GtkEntry some day. - * - * Copyright (C) 2000 Eazel, Inc. - * - * Author: John Sullivan <sullivan@eazel.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. - * - * This 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; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#include <config.h> -#include "nautilus-entry.h" - -#include <eel/eel-gtk-macros.h> -#include <gdk/gdkkeysyms.h> -#include <gtk/gtkmain.h> -#include <gtk/gtksignal.h> -#include <libgnome/gnome-i18n.h> -#include <eel/eel-gdk-extensions.h> -#include <libnautilus-extensions/nautilus-global-preferences.h> -#include <libnautilus-extensions/nautilus-undo-signal-handlers.h> -#include <orb/orbit.h> - -struct NautilusEntryDetails { - gboolean use_emacs_shortcuts; - gboolean user_edit; - gboolean special_tab_handling; - gboolean cursor_obscured; -}; - -enum { - USER_CHANGED, - SELECTION_CHANGED, - LAST_SIGNAL -}; -static guint signals[LAST_SIGNAL]; - -static void nautilus_entry_initialize (NautilusEntry *entry); -static void nautilus_entry_initialize_class (NautilusEntryClass *class); - -EEL_DEFINE_CLASS_BOILERPLATE (NautilusEntry, - nautilus_entry, - GTK_TYPE_ENTRY) - -static void -emacs_shortcuts_preference_changed_callback (gpointer callback_data) -{ - NautilusEntry *entry; - - entry = NAUTILUS_ENTRY (callback_data); - - entry->details->use_emacs_shortcuts = - nautilus_preferences_get_boolean (NAUTILUS_PREFERENCES_USE_EMACS_SHORTCUTS); -} - -static void -nautilus_entry_initialize (NautilusEntry *entry) -{ - GtkWidget *widget; - - widget = GTK_WIDGET (entry); - entry->details = g_new0 (NautilusEntryDetails, 1); - - entry->details->user_edit = TRUE; - - /* Allow pointer motion events so we can expose an obscured cursor if necessary */ - gtk_widget_set_events (widget, gtk_widget_get_events (widget) | GDK_POINTER_MOTION_MASK); - - nautilus_undo_set_up_nautilus_entry_for_undo (entry); - - nautilus_preferences_add_callback (NAUTILUS_PREFERENCES_USE_EMACS_SHORTCUTS, - emacs_shortcuts_preference_changed_callback, - entry); - emacs_shortcuts_preference_changed_callback (entry); -} - -GtkWidget * -nautilus_entry_new (void) -{ - return gtk_widget_new (NAUTILUS_TYPE_ENTRY, NULL); -} - -GtkWidget * -nautilus_entry_new_with_max_length (guint16 max) -{ - GtkWidget *widget; - - widget = gtk_widget_new (NAUTILUS_TYPE_ENTRY, NULL); - GTK_ENTRY (widget)->text_max_length = max; - - return widget; -} - -static void -nautilus_entry_destroy (GtkObject *object) -{ - NautilusEntry *entry; - - entry = NAUTILUS_ENTRY (object); - - nautilus_preferences_remove_callback (NAUTILUS_PREFERENCES_USE_EMACS_SHORTCUTS, - emacs_shortcuts_preference_changed_callback, - entry); - - g_free (entry->details); - - EEL_CALL_PARENT (GTK_OBJECT_CLASS, destroy, (object)); -} - -static void -obscure_cursor (NautilusEntry *entry) -{ - if (entry->details->cursor_obscured) { - return; - } - - entry->details->cursor_obscured = TRUE; - eel_gdk_window_set_invisible_cursor (GTK_ENTRY (entry)->text_area); -} - -static gboolean -nautilus_entry_key_press (GtkWidget *widget, GdkEventKey *event) -{ - NautilusEntry *entry; - GtkEditable *editable; - int position; - gboolean result; - - entry = NAUTILUS_ENTRY (widget); - editable = GTK_EDITABLE (widget); - - if (!editable->editable) { - return FALSE; - } - - switch (event->keyval) { - case GDK_Tab: - /* The location bar entry wants TAB to work kind of - * like it does in the shell for command completion, - * so if we get a tab and there's a selection, we - * should position the insertion point at the end of - * the selection. - */ - if (entry->details->special_tab_handling && editable->has_selection) { - position = strlen (gtk_entry_get_text (GTK_ENTRY (editable))); - gtk_entry_select_region (GTK_ENTRY (editable), position, position); - return TRUE; - } - break; - - case GDK_KP_Enter: - /* Work around bug in GtkEntry where keypad Enter key - * inserts a character rather than activating like the - * other Enter key. - */ - gtk_widget_activate (widget); - return TRUE; - - default: - break; - } - - if (!entry->details->use_emacs_shortcuts) { - /* Filter out the emacs-style keyboard shortcuts in - * GtkEntry for alt and control keys. They have - * numerous conflicts with menu keyboard shortcuts. - */ - if (event->state & GDK_CONTROL_MASK || event->state & GDK_MOD1_MASK) { - return FALSE; - } - } - - obscure_cursor (entry); - - result = EEL_CALL_PARENT_WITH_RETURN_VALUE - (GTK_WIDGET_CLASS, key_press_event, (widget, event)); - - if (result) { - gtk_signal_emit (GTK_OBJECT (widget), signals[SELECTION_CHANGED]); - } - - return result; - -} - -static gboolean -nautilus_entry_motion_notify (GtkWidget *widget, GdkEventMotion *event) -{ - int result; - guint old_start_pos, old_end_pos; - GdkCursor *cursor; - NautilusEntry *entry; - - /* Reset cursor to I-Beam */ - entry = NAUTILUS_ENTRY (widget); - if (entry->details->cursor_obscured) { - cursor = gdk_cursor_new (GDK_XTERM); - gdk_window_set_cursor (GTK_ENTRY (entry)->text_area, cursor); - gdk_cursor_destroy (cursor); - entry->details->cursor_obscured = FALSE; - } - - old_start_pos = GTK_EDITABLE (widget)->selection_start_pos; - old_end_pos = GTK_EDITABLE (widget)->selection_end_pos; - - result = EEL_CALL_PARENT_WITH_RETURN_VALUE - (GTK_WIDGET_CLASS, motion_notify_event, (widget, event)); - - if (result) { - gtk_signal_emit (GTK_OBJECT (widget), signals[SELECTION_CHANGED]); - } - - return result; -} - -/** - * nautilus_entry_select_all - * - * Select all text, leaving the text cursor position at the end. - * - * @entry: A NautilusEntry - **/ -void -nautilus_entry_select_all (NautilusEntry *entry) -{ - g_return_if_fail (NAUTILUS_IS_ENTRY (entry)); - - gtk_editable_set_position (GTK_EDITABLE (entry), -1); - gtk_editable_select_region (GTK_EDITABLE (entry), 0, -1); -} - -static gboolean -select_all_at_idle (gpointer callback_data) -{ - NautilusEntry *entry; - - entry = NAUTILUS_ENTRY (callback_data); - if (!GTK_OBJECT_DESTROYED (entry)) { - nautilus_entry_select_all (entry); - } - gtk_object_unref (GTK_OBJECT (entry)); - return FALSE; -} - -/** - * nautilus_entry_select_all_at_idle - * - * Select all text at the next idle, not immediately. - * This is useful when reacting to a key press, because - * changing the selection and the text cursor position doesn't - * work in a key_press signal handler. - * - * @entry: A NautilusEntry - **/ -void -nautilus_entry_select_all_at_idle (NautilusEntry *entry) -{ - g_return_if_fail (NAUTILUS_IS_ENTRY (entry)); - - /* If the text cursor position changes in this routine - * then gtk_entry_key_press will unselect (and we want - * to move the text cursor position to the end). - */ - gtk_object_ref (GTK_OBJECT (entry)); - gtk_idle_add (select_all_at_idle, entry); -} - -/** - * nautilus_entry_set_text - * - * This function wraps gtk_entry_set_text. It sets undo_registered - * to TRUE and preserves the old value for a later restore. This is - * done so the programmatic changes to the entry do not register - * with the undo manager. - * - * @entry: A NautilusEntry - * @test: The text to set - **/ - -void -nautilus_entry_set_text (NautilusEntry *entry, const gchar *text) -{ - g_return_if_fail (NAUTILUS_IS_ENTRY (entry)); - - entry->details->user_edit = FALSE; - gtk_entry_set_text (GTK_ENTRY (entry), text); - entry->details->user_edit = TRUE; - - gtk_signal_emit (GTK_OBJECT (entry), signals[SELECTION_CHANGED]); -} - -static void -nautilus_entry_set_selection (GtkEditable *editable, - int start_pos, - int end_pos) -{ - EEL_CALL_PARENT (GTK_EDITABLE_CLASS, set_selection, - (editable, start_pos, end_pos)); - - gtk_signal_emit (GTK_OBJECT (editable), signals[SELECTION_CHANGED]); -} - -static gboolean -nautilus_entry_button_press (GtkWidget *widget, - GdkEventButton *event) -{ - gboolean result; - - result = EEL_CALL_PARENT_WITH_RETURN_VALUE - (GTK_WIDGET_CLASS, button_press_event, (widget, event)); - - if (result) { - gtk_signal_emit (GTK_OBJECT (widget), signals[SELECTION_CHANGED]); - } - - return result; -} - -static gboolean -nautilus_entry_button_release (GtkWidget *widget, - GdkEventButton *event) -{ - gboolean result; - - result = EEL_CALL_PARENT_WITH_RETURN_VALUE - (GTK_WIDGET_CLASS, button_release_event, (widget, event)); - - if (result) { - gtk_signal_emit (GTK_OBJECT (widget), signals[SELECTION_CHANGED]); - } - - return result; -} - -static void -nautilus_entry_insert_text (GtkEditable *editable, const gchar *text, - int length, int *position) -{ - NautilusEntry *entry; - - entry = NAUTILUS_ENTRY(editable); - - /* Fire off user changed signals */ - if (entry->details->user_edit) { - gtk_signal_emit (GTK_OBJECT (editable), signals[USER_CHANGED]); - } - - EEL_CALL_PARENT (GTK_EDITABLE_CLASS, insert_text, - (editable, text, length, position)); - - gtk_signal_emit (GTK_OBJECT (editable), signals[SELECTION_CHANGED]); -} - -static void -nautilus_entry_delete_text (GtkEditable *editable, int start_pos, int end_pos) -{ - NautilusEntry *entry; - - entry = NAUTILUS_ENTRY (editable); - - /* Fire off user changed signals */ - if (entry->details->user_edit) { - gtk_signal_emit (GTK_OBJECT (editable), signals[USER_CHANGED]); - } - - EEL_CALL_PARENT (GTK_EDITABLE_CLASS, delete_text, - (editable, start_pos, end_pos)); - - gtk_signal_emit (GTK_OBJECT (editable), signals[SELECTION_CHANGED]); -} - -/* Overridden to work around GTK bug. The selection_clear_event is queued - * when the selection changes. Changing the selection to NULL and then - * back to the original selection owner still sends the event, so the - * selection owner then gets the selection ripped away from it. We ran into - * this with type-completion behavior in NautilusLocationBar (see bug 5313). - * There's a FIXME comment that seems to be about this same issue in - * gtk+/gtkselection.c, gtk_selection_clear. - */ -static gboolean -nautilus_entry_selection_clear (GtkWidget *widget, - GdkEventSelection *event) -{ - g_return_val_if_fail (NAUTILUS_IS_ENTRY (widget), FALSE); - - if (gdk_selection_owner_get (event->selection) == widget->window) { - return FALSE; - } - - return EEL_CALL_PARENT_WITH_RETURN_VALUE - (GTK_WIDGET_CLASS, selection_clear_event, (widget, event)); -} - -static void -nautilus_entry_initialize_class (NautilusEntryClass *class) -{ - GtkWidgetClass *widget_class; - GtkObjectClass *object_class; - GtkEditableClass *editable_class; - - widget_class = GTK_WIDGET_CLASS (class); - object_class = GTK_OBJECT_CLASS (class); - editable_class = GTK_EDITABLE_CLASS (class); - - widget_class->button_press_event = nautilus_entry_button_press; - widget_class->button_release_event = nautilus_entry_button_release; - widget_class->key_press_event = nautilus_entry_key_press; - widget_class->motion_notify_event = nautilus_entry_motion_notify; - widget_class->selection_clear_event = nautilus_entry_selection_clear; - - object_class->destroy = nautilus_entry_destroy; - - editable_class->insert_text = nautilus_entry_insert_text; - editable_class->delete_text = nautilus_entry_delete_text; - editable_class->set_selection = nautilus_entry_set_selection; - - /* Set up signals */ - signals[USER_CHANGED] = gtk_signal_new - ("user_changed", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (NautilusEntryClass, - user_changed), - gtk_marshal_NONE__NONE, - GTK_TYPE_NONE, 0); - signals[SELECTION_CHANGED] = gtk_signal_new - ("selection_changed", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (NautilusEntryClass, - selection_changed), - gtk_marshal_NONE__NONE, - GTK_TYPE_NONE, 0); - gtk_object_class_add_signals (object_class, signals, LAST_SIGNAL); -} - -void -nautilus_entry_set_special_tab_handling (NautilusEntry *entry, - gboolean special_tab_handling) -{ - g_return_if_fail (NAUTILUS_IS_ENTRY (entry)); - - entry->details->special_tab_handling = special_tab_handling; -} diff --git a/libnautilus-extensions/nautilus-entry.h b/libnautilus-extensions/nautilus-entry.h deleted file mode 100644 index dc94d2711..000000000 --- a/libnautilus-extensions/nautilus-entry.h +++ /dev/null @@ -1,72 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ - -/* NautilusEntry: one-line text editing widget. This consists of bug fixes - * and other improvements to GtkEntry, and all the changes could be rolled - * into GtkEntry some day. - * - * Copyright (C) 2000 Eazel, Inc. - * - * Author: John Sullivan <sullivan@eazel.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. - * - * This 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; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef NAUTILUS_ENTRY_H -#define NAUTILUS_ENTRY_H - -#include <libgnome/gnome-defs.h> -#include <gtk/gtkentry.h> - -BEGIN_GNOME_DECLS - -#define NAUTILUS_TYPE_ENTRY \ - (nautilus_entry_get_type ()) -#define NAUTILUS_ENTRY(obj) \ - (GTK_CHECK_CAST ((obj), NAUTILUS_TYPE_ENTRY, NautilusEntry)) -#define NAUTILUS_ENTRY_CLASS(klass) \ - (GTK_CHECK_CLASS_CAST ((klass), NAUTILUS_TYPE_ENTRY, NautilusEntryClass)) -#define NAUTILUS_IS_ENTRY(obj) \ - (GTK_CHECK_TYPE ((obj), NAUTILUS_TYPE_ENTRY)) -#define NAUTILUS_IS_ENTRY_CLASS(klass) \ - (GTK_CHECK_CLASS_TYPE ((klass), NAUTILUS_TYPE_ENTRY)) - -typedef struct NautilusEntryDetails NautilusEntryDetails; - -typedef struct { - GtkEntry parent; - NautilusEntryDetails *details; -} NautilusEntry; - -typedef struct { - GtkEntryClass parent_class; - - void (*user_changed) (NautilusEntry *entry); - void (*selection_changed) (NautilusEntry *entry); -} NautilusEntryClass; - -GtkType nautilus_entry_get_type (void); -GtkWidget *nautilus_entry_new (void); -GtkWidget *nautilus_entry_new_with_max_length (guint16 max); -void nautilus_entry_set_text (NautilusEntry *entry, - const char *text); -void nautilus_entry_select_all (NautilusEntry *entry); -void nautilus_entry_select_all_at_idle (NautilusEntry *entry); -void nautilus_entry_set_special_tab_handling (NautilusEntry *entry, - gboolean special_tab_handling); - -END_GNOME_DECLS - -#endif /* NAUTILUS_ENTRY_H */ diff --git a/libnautilus-extensions/nautilus-file-attributes.h b/libnautilus-extensions/nautilus-file-attributes.h deleted file mode 100644 index e4b3a8406..000000000 --- a/libnautilus-extensions/nautilus-file-attributes.h +++ /dev/null @@ -1,44 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- - - nautilus-file-attributes.h: #defines and other file-attribute-related info - - 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. - - Author: Darin Adler <darin@eazel.com> -*/ - -#ifndef NAUTILUS_FILE_ATTRIBUTES_H -#define NAUTILUS_FILE_ATTRIBUTES_H - -/* Names for NautilusFile attributes. These are used when registering - * 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" - -#endif /* NAUTILUS_FILE_ATTRIBUTES_H */ diff --git a/libnautilus-extensions/nautilus-file-changes-queue.c b/libnautilus-extensions/nautilus-file-changes-queue.c deleted file mode 100644 index 6af48e1db..000000000 --- a/libnautilus-extensions/nautilus-file-changes-queue.c +++ /dev/null @@ -1,543 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- - - Copyright (C) 1999, 2000, 2001 Eazel, Inc. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public - License along with this program; if not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. - - Author: Pavel Cisler <pavel@eazel.com> -*/ - -#include <config.h> -#include "nautilus-file-changes-queue.h" - -#include "nautilus-directory-notify.h" -#include <eel/eel-glib-extensions.h> - -#ifdef G_THREADS_ENABLED -#define MUTEX_LOCK(a) if ((a) != NULL) g_mutex_lock (a) -#define MUTEX_UNLOCK(a) if ((a) != NULL) g_mutex_unlock (a) -#else -#define MUTEX_LOCK(a) -#define MUTEX_UNLOCK(a) -#endif - -typedef enum { - CHANGE_FILE_INITIAL, - CHANGE_FILE_ADDED, - CHANGE_FILE_CHANGED, - CHANGE_FILE_REMOVED, - CHANGE_FILE_MOVED, - CHANGE_METADATA_COPIED, - CHANGE_METADATA_MOVED, - CHANGE_METADATA_REMOVED, - CHANGE_POSITION_SET, - CHANGE_POSITION_REMOVE -} NautilusFileChangeKind; - -typedef struct { - NautilusFileChangeKind kind; - char *from_uri; - char *to_uri; - GdkPoint point; -} NautilusFileChange; - -typedef struct { - GList *head; - GList *tail; -#ifdef G_THREADS_ENABLED - GMutex *mutex; -#endif -} NautilusFileChangesQueue; - -static NautilusFileChangesQueue * -nautilus_file_changes_queue_new (void) -{ - NautilusFileChangesQueue *result; - - result = g_new0 (NautilusFileChangesQueue, 1); - -#ifdef G_THREADS_ENABLED - result->mutex = g_mutex_new (); -#endif - return result; -} - -static NautilusFileChangesQueue * -nautilus_file_changes_queue_get (void) -{ - static NautilusFileChangesQueue *file_changes_queue; - - if (file_changes_queue == NULL) { - file_changes_queue = nautilus_file_changes_queue_new (); - } - - return file_changes_queue; -} - -#if 0 /* no public free call yet */ - -static void -nautilus_file_change_free (NautilusFileChange *change) -{ - g_free (change->from_uri); - g_free (change->to_uri); -} - -void -nautilus_file_changes_queue_free (NautilusFileChangesQueue *queue) -{ - GList *p; - if (queue == NULL) { - return; - } - -#ifdef G_THREADS_ENABLED - /* if lock on a defunct mutex were defined (returning a failure) - * we would lock here - */ -#endif - - for (p = queue->head; p != NULL; p = p->next) { - nautilus_file_change_free (p->data); - } - g_list_free (queue->head); - -#ifdef G_THREADS_ENABLED - g_mutex_free (queue->mutex); -#endif - g_free (queue); -} - -#endif /* no public free call yet */ - -static void -nautilus_file_changes_queue_add_common (NautilusFileChangesQueue *queue, - NautilusFileChange *new_item) -{ - /* enqueue the new queue item while locking down the list */ - MUTEX_LOCK (queue->mutex); - - queue->head = g_list_prepend (queue->head, new_item); - if (queue->tail == NULL) - queue->tail = queue->head; - - MUTEX_UNLOCK (queue->mutex); -} - -void -nautilus_file_changes_queue_file_added (const char *uri) -{ - NautilusFileChange *new_item; - NautilusFileChangesQueue *queue; - - queue = nautilus_file_changes_queue_get(); - - new_item = g_new0 (NautilusFileChange, 1); - new_item->kind = CHANGE_FILE_ADDED; - new_item->from_uri = g_strdup (uri); - nautilus_file_changes_queue_add_common (queue, new_item); -} - -void -nautilus_file_changes_queue_file_changed (const char *uri) -{ - NautilusFileChange *new_item; - NautilusFileChangesQueue *queue; - - queue = nautilus_file_changes_queue_get(); - - new_item = g_new0 (NautilusFileChange, 1); - new_item->kind = CHANGE_FILE_CHANGED; - new_item->from_uri = g_strdup (uri); - nautilus_file_changes_queue_add_common (queue, new_item); -} - -void -nautilus_file_changes_queue_file_removed (const char *uri) -{ - NautilusFileChange *new_item; - NautilusFileChangesQueue *queue; - - queue = nautilus_file_changes_queue_get(); - - new_item = g_new0 (NautilusFileChange, 1); - new_item->kind = CHANGE_FILE_REMOVED; - new_item->from_uri = g_strdup (uri); - nautilus_file_changes_queue_add_common (queue, new_item); -} - -void -nautilus_file_changes_queue_file_moved (const char *from, const char *to) -{ - NautilusFileChange *new_item; - NautilusFileChangesQueue *queue; - - queue = nautilus_file_changes_queue_get (); - - new_item = g_new (NautilusFileChange, 1); - new_item->kind = CHANGE_FILE_MOVED; - new_item->from_uri = g_strdup (from); - new_item->to_uri = g_strdup (to); - nautilus_file_changes_queue_add_common (queue, new_item); -} - -void -nautilus_file_changes_queue_schedule_metadata_copy (const char *from_uri, - const char *to_uri) -{ - NautilusFileChange *new_item; - NautilusFileChangesQueue *queue; - - queue = nautilus_file_changes_queue_get (); - - new_item = g_new (NautilusFileChange, 1); - new_item->kind = CHANGE_METADATA_COPIED; - new_item->from_uri = g_strdup (from_uri); - new_item->to_uri = g_strdup (to_uri); - nautilus_file_changes_queue_add_common (queue, new_item); -} - -void -nautilus_file_changes_queue_schedule_metadata_move (const char *from_uri, - const char *to_uri) -{ - NautilusFileChange *new_item; - NautilusFileChangesQueue *queue; - - queue = nautilus_file_changes_queue_get (); - - new_item = g_new (NautilusFileChange, 1); - new_item->kind = CHANGE_METADATA_MOVED; - new_item->from_uri = g_strdup (from_uri); - new_item->to_uri = g_strdup (to_uri); - nautilus_file_changes_queue_add_common (queue, new_item); -} - -void -nautilus_file_changes_queue_schedule_metadata_remove (const char *uri) -{ - NautilusFileChange *new_item; - NautilusFileChangesQueue *queue; - - queue = nautilus_file_changes_queue_get (); - - new_item = g_new (NautilusFileChange, 1); - new_item->kind = CHANGE_METADATA_REMOVED; - new_item->from_uri = g_strdup (uri); - nautilus_file_changes_queue_add_common (queue, new_item); -} - -void -nautilus_file_changes_queue_schedule_position_set (const char *uri, - GdkPoint point) -{ - NautilusFileChange *new_item; - NautilusFileChangesQueue *queue; - - queue = nautilus_file_changes_queue_get (); - - new_item = g_new (NautilusFileChange, 1); - new_item->kind = CHANGE_POSITION_SET; - new_item->from_uri = g_strdup (uri); - new_item->point = point; - nautilus_file_changes_queue_add_common (queue, new_item); -} - -void -nautilus_file_changes_queue_schedule_position_remove (const char *uri) -{ - NautilusFileChange *new_item; - NautilusFileChangesQueue *queue; - - queue = nautilus_file_changes_queue_get (); - - new_item = g_new (NautilusFileChange, 1); - new_item->kind = CHANGE_POSITION_REMOVE; - new_item->from_uri = g_strdup (uri); - nautilus_file_changes_queue_add_common (queue, new_item); -} - -static NautilusFileChange * -nautilus_file_changes_queue_get_change (NautilusFileChangesQueue *queue) -{ - GList *new_tail; - NautilusFileChange *result; - - g_assert (queue != NULL); - - /* dequeue the tail item while locking down the list */ - MUTEX_LOCK (queue->mutex); - - if (queue->tail == NULL) { - result = NULL; - } else { - new_tail = queue->tail->prev; - result = queue->tail->data; - queue->head = g_list_remove_link (queue->head, - queue->tail); - g_list_free_1 (queue->tail); - queue->tail = new_tail; - } - - MUTEX_UNLOCK (queue->mutex); - - return result; -} - -enum { - CONSUME_CHANGES_MAX_CHUNK = 20 -}; - -static void -pairs_list_free (GList *pairs) -{ - GList *p; - URIPair *pair; - - /* deep delete the list of pairs */ - - for (p = pairs; p != NULL; p = p->next) { - /* delete the strings in each pair */ - pair = p->data; - g_free (pair->from_uri); - g_free (pair->to_uri); - } - - /* delete the list and the now empty pair structs */ - eel_g_list_free_deep (pairs); -} - -static void -position_set_list_free (GList *list) -{ - GList *p; - NautilusFileChangesQueuePosition *item; - - for (p = list; p != NULL; p = p->next) { - item = p->data; - g_free (item->uri); - } - /* delete the list and the now empty structs */ - eel_g_list_free_deep (list); -} - -/* go through changes in the change queue, send ones with the same kind - * in a list to the different nautilus_directory_notify calls - */ -void -nautilus_file_changes_consume_changes (gboolean consume_all) -{ - NautilusFileChange *change; - GList *additions, *changes, *deletions, *moves; - GList *metadata_copy_requests, *metadata_move_requests, *metadata_remove_requests; - GList *position_set_requests; - URIPair *pair; - NautilusFileChangesQueuePosition *position_set; - guint chunk_count; - NautilusFileChangesQueue *queue; - gboolean flush_needed; - - - additions = NULL; - changes = NULL; - deletions = NULL; - moves = NULL; - metadata_copy_requests = NULL; - metadata_move_requests = NULL; - metadata_remove_requests = NULL; - position_set_requests = NULL; - - queue = nautilus_file_changes_queue_get(); - - /* Consume changes from the queue, stuffing them into one of three lists, - * keep doing it while the changes are of the same kind, then send them off. - * This is to ensure that the changes get sent off in the same order that they - * arrived. - */ - for (chunk_count = 0; ; chunk_count++) { - change = nautilus_file_changes_queue_get_change (queue); - - /* figure out if we need to flush the pending changes that we collected sofar */ - - if (change == NULL) { - flush_needed = TRUE; - /* no changes left, flush everything */ - } else { - flush_needed = additions != NULL - && change->kind != CHANGE_FILE_ADDED - && change->kind != CHANGE_METADATA_COPIED - && change->kind != CHANGE_POSITION_SET - && change->kind != CHANGE_POSITION_REMOVE; - - flush_needed |= changes != NULL - && change->kind != CHANGE_FILE_CHANGED; - - flush_needed |= moves != NULL - && change->kind != CHANGE_FILE_MOVED - && change->kind != CHANGE_METADATA_MOVED - && change->kind != CHANGE_POSITION_SET - && change->kind != CHANGE_POSITION_REMOVE; - - flush_needed |= deletions != NULL - && change->kind != CHANGE_FILE_REMOVED - && change->kind != CHANGE_METADATA_REMOVED; - - flush_needed |= metadata_copy_requests != NULL - && change->kind != CHANGE_FILE_ADDED - && change->kind != CHANGE_METADATA_COPIED - && change->kind != CHANGE_POSITION_SET - && change->kind != CHANGE_POSITION_REMOVE; - - flush_needed |= metadata_move_requests != NULL - && change->kind != CHANGE_FILE_MOVED - && change->kind != CHANGE_METADATA_MOVED - && change->kind != CHANGE_POSITION_SET - && change->kind != CHANGE_POSITION_REMOVE; - - flush_needed |= metadata_remove_requests != NULL - && change->kind != CHANGE_FILE_REMOVED - && change->kind != CHANGE_METADATA_REMOVED; - - flush_needed |= position_set_requests != NULL - && change->kind != CHANGE_POSITION_SET - && change->kind != CHANGE_POSITION_REMOVE - && change->kind != CHANGE_FILE_ADDED - && change->kind != CHANGE_FILE_MOVED - && change->kind != CHANGE_METADATA_COPIED - && change->kind != CHANGE_METADATA_MOVED; - - flush_needed |= !consume_all && chunk_count >= CONSUME_CHANGES_MAX_CHUNK; - /* we have reached the chunk maximum */ - } - - if (flush_needed) { - /* Send changes we collected off. - * At one time we may only have one of the lists - * contain changes. - */ - - if (deletions != NULL) { - nautilus_directory_notify_files_removed (deletions); - eel_g_list_free_deep (deletions); - deletions = NULL; - } - if (moves != NULL) { - nautilus_directory_notify_files_moved (moves); - pairs_list_free (moves); - moves = NULL; - } - if (additions != NULL) { - nautilus_directory_notify_files_added (additions); - eel_g_list_free_deep (additions); - additions = NULL; - } - if (changes != NULL) { - nautilus_directory_notify_files_changed (changes); - eel_g_list_free_deep (changes); - changes = NULL; - } - if (metadata_copy_requests != NULL) { - nautilus_directory_schedule_metadata_copy (metadata_copy_requests); - pairs_list_free (metadata_copy_requests); - metadata_copy_requests = NULL; - } - if (metadata_move_requests != NULL) { - nautilus_directory_schedule_metadata_move (metadata_move_requests); - pairs_list_free (metadata_move_requests); - metadata_move_requests = NULL; - } - if (metadata_remove_requests != NULL) { - nautilus_directory_schedule_metadata_remove (metadata_remove_requests); - eel_g_list_free_deep (metadata_remove_requests); - metadata_remove_requests = NULL; - } - if (position_set_requests != NULL) { - nautilus_directory_schedule_position_set (position_set_requests); - position_set_list_free (position_set_requests); - position_set_requests = NULL; - } - } - - if (change == NULL) { - /* we are done */ - return; - } - - /* add the new change to the list */ - switch (change->kind) { - case CHANGE_FILE_ADDED: - additions = g_list_append (additions, change->from_uri); - break; - - case CHANGE_FILE_CHANGED: - changes = g_list_append (changes, change->from_uri); - break; - - case CHANGE_FILE_REMOVED: - deletions = g_list_append (deletions, change->from_uri); - break; - - case CHANGE_FILE_MOVED: - pair = g_new (URIPair, 1); - pair->from_uri = change->from_uri; - pair->to_uri = change->to_uri; - moves = g_list_append (moves, pair); - break; - - case CHANGE_METADATA_COPIED: - pair = g_new (URIPair, 1); - pair->from_uri = change->from_uri; - pair->to_uri = change->to_uri; - metadata_copy_requests = g_list_append (metadata_copy_requests, pair); - break; - - case CHANGE_METADATA_MOVED: - pair = g_new (URIPair, 1); - pair->from_uri = change->from_uri; - pair->to_uri = change->to_uri; - metadata_move_requests = g_list_append (metadata_move_requests, pair); - break; - - case CHANGE_METADATA_REMOVED: - metadata_remove_requests = g_list_append (metadata_remove_requests, - change->from_uri); - break; - - case CHANGE_POSITION_SET: - position_set = g_new (NautilusFileChangesQueuePosition, 1); - position_set->uri = change->from_uri; - position_set->set = TRUE; - position_set->point = change->point; - position_set_requests = g_list_append (position_set_requests, - position_set); - break; - - case CHANGE_POSITION_REMOVE: - position_set = g_new (NautilusFileChangesQueuePosition, 1); - position_set->uri = change->from_uri; - position_set->set = FALSE; - position_set_requests = g_list_append (position_set_requests, - position_set); - break; - - default: - g_assert_not_reached (); - break; - } - change->from_uri = NULL; - change->to_uri = NULL; - } -} diff --git a/libnautilus-extensions/nautilus-file-changes-queue.h b/libnautilus-extensions/nautilus-file-changes-queue.h deleted file mode 100644 index d048072d4..000000000 --- a/libnautilus-extensions/nautilus-file-changes-queue.h +++ /dev/null @@ -1,44 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- - - Copyright (C) 1999, 2000, 2001 Eazel, Inc. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public - License along with this program; if not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. - - Author: Pavel Cisler <pavel@eazel.com> -*/ - -#ifndef NAUTILUS_FILE_CHANGES_QUEUE_H -#define NAUTILUS_FILE_CHANGES_QUEUE_H - -#include <gdk/gdktypes.h> - -void nautilus_file_changes_queue_file_added (const char *uri); -void nautilus_file_changes_queue_file_changed (const char *uri); -void nautilus_file_changes_queue_file_removed (const char *uri); -void nautilus_file_changes_queue_file_moved (const char *from_uri, - const char *to_uri); -void nautilus_file_changes_queue_schedule_metadata_copy (const char *from_uri, - const char *to_uri); -void nautilus_file_changes_queue_schedule_metadata_move (const char *from_uri, - const char *to_uri); -void nautilus_file_changes_queue_schedule_metadata_remove (const char *uri); -void nautilus_file_changes_queue_schedule_position_set (const char *uri, - GdkPoint point); -void nautilus_file_changes_queue_schedule_position_remove (const char *uri); - -void nautilus_file_changes_consume_changes (gboolean consume_all); - -#endif /* NAUTILUS_FILE_CHANGES_QUEUE_H */ diff --git a/libnautilus-extensions/nautilus-file-dnd.c b/libnautilus-extensions/nautilus-file-dnd.c deleted file mode 100644 index b7c12af26..000000000 --- a/libnautilus-extensions/nautilus-file-dnd.c +++ /dev/null @@ -1,109 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ - -/* nautilus-file-drag.c - Drag & drop handling code that operated on - NautilusFile objects. - - Copyright (C) 2000 Eazel, Inc. - - The Gnome 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 Gnome 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 the Gnome 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. - - Authors: Pavel Cisler <pavel@eazel.com>, -*/ - -#include <config.h> -#include "nautilus-file-dnd.h" - -#include <eel/eel-glib-extensions.h> -#include <eel/eel-string.h> - -gboolean -nautilus_drag_can_accept_item (NautilusFile *drop_target_item, - const char *item_uri) -{ - if (nautilus_file_matches_uri (drop_target_item, item_uri)) { - /* can't accept itself */ - return FALSE; - } - - if (nautilus_file_is_directory (drop_target_item)) { - /* target is a directory, accept anything */ - return TRUE; - } - - /* All Nautilus links are assumed to be links to directories. - * Therefore, they all can accept drags, like all other - * directories to. As with other directories, there can be - * errors when the actual copy is attempted due to - * permissions. - */ - if (nautilus_file_is_nautilus_link (drop_target_item)) { - return TRUE; - } - - return FALSE; -} - -gboolean -nautilus_drag_can_accept_items (NautilusFile *drop_target_item, - const GList *items) -{ - int max; - - if (drop_target_item == NULL) - return FALSE; - - g_assert (NAUTILUS_IS_FILE (drop_target_item)); - - /* Iterate through selection checking if item will get accepted by the - * drop target. If more than 100 items selected, return an over-optimisic - * result - */ - for (max = 100; items != NULL && max >= 0; items = items->next, max--) { - if (!nautilus_drag_can_accept_item (drop_target_item, - ((EelDragSelectionItem *)items->data)->uri)) { - return FALSE; - } - } - - return TRUE; -} - -void -nautilus_drag_file_receive_dropped_keyword (NautilusFile *file, char *keyword) -{ - GList *keywords, *word; - - g_return_if_fail (NAUTILUS_IS_FILE (file)); - g_return_if_fail (keyword != NULL); - - /* special case the erase emblem */ - if (strcmp (keyword, NAUTILUS_FILE_DND_ERASE_KEYWORD) == 0) { - keywords = NULL; - } else { - keywords = nautilus_file_get_keywords (file); - word = g_list_find_custom (keywords, keyword, (GCompareFunc) strcmp); - if (word == NULL) { - keywords = g_list_append (keywords, g_strdup (keyword)); - } else { - keywords = g_list_remove_link (keywords, word); - g_free (word->data); - g_list_free_1 (word); - } - } - - nautilus_file_set_keywords (file, keywords); - eel_g_list_free_deep (keywords); -} diff --git a/libnautilus-extensions/nautilus-file-dnd.h b/libnautilus-extensions/nautilus-file-dnd.h deleted file mode 100644 index 7ae75fd93..000000000 --- a/libnautilus-extensions/nautilus-file-dnd.h +++ /dev/null @@ -1,41 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ -/* nautilus-file-drag.h - Drag & drop handling code that operated on - NautilusFile objects. - - Copyright (C) 2000 Eazel, Inc. - - The Gnome 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 Gnome 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 the Gnome 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. - - Authors: Pavel Cisler <pavel@eazel.com>, -*/ - -#ifndef NAUTILUS_FILE_DND_H -#define NAUTILUS_FILE_DND_H - -#include <eel/eel-dnd.h> -#include <libnautilus-extensions/nautilus-file.h> - -#define NAUTILUS_FILE_DND_ERASE_KEYWORD "erase" - -gboolean nautilus_drag_can_accept_item (NautilusFile *drop_target_item, - const char *item_uri); -gboolean nautilus_drag_can_accept_items (NautilusFile *drop_target_item, - const GList *items); -void nautilus_drag_file_receive_dropped_keyword (NautilusFile *file, - char *keyword); - -#endif /* NAUTILUS_FILE_DND_H */ - diff --git a/libnautilus-extensions/nautilus-file-operations-progress.c b/libnautilus-extensions/nautilus-file-operations-progress.c deleted file mode 100644 index a72340a5c..000000000 --- a/libnautilus-extensions/nautilus-file-operations-progress.c +++ /dev/null @@ -1,446 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ - -/* dfos-xfer-progress-dialog.c - Progress dialog for transfer operations in the - GNOME Desktop File Operation Service. - - Copyright (C) 1999, 2000 Free Software Foundation - Copyright (C) 2000, 2001 Eazel Inc. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public - License along with this program; see the file COPYING. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. - - Authors: - Ettore Perazzoli <ettore@gnu.org> - Pavel Cisler <pavel@eazel.com> -*/ - -#include <config.h> -#include "nautilus-file-operations-progress.h" - -#include <eel/eel-ellipsizing-label.h> -#include <eel/eel-gdk-font-extensions.h> -#include <eel/eel-glib-extensions.h> -#include <eel/eel-gtk-extensions.h> -#include <eel/eel-gtk-macros.h> -#include <gtk/gtkhbox.h> -#include <gtk/gtkmain.h> -#include <gtk/gtkprogressbar.h> -#include <gtk/gtktable.h> -#include <libgnome/gnome-i18n.h> -#include <libgnomeui/gnome-stock.h> -#include <libgnomevfs/gnome-vfs-utils.h> - -/* The width of the progress bar determines the minimum width of the - * window. It will be wider only if the font is really huge and the - * fixed labels don't fit in the window otherwise. - */ -#define PROGRESS_BAR_WIDTH 350 - -#define OUTER_BORDER 5 -#define HORIZONTAL_SPACING 3 - -#define MINIMUM_TIME_UP 1000 - -static void nautilus_file_operations_progress_initialize_class (NautilusFileOperationsProgressClass *klass); -static void nautilus_file_operations_progress_initialize (NautilusFileOperationsProgress *dialog); - -EEL_DEFINE_CLASS_BOILERPLATE (NautilusFileOperationsProgress, - nautilus_file_operations_progress, - GNOME_TYPE_DIALOG); - -struct NautilusFileOperationsProgressDetails { - GtkWidget *progress_title_label; - GtkWidget *progress_count_label; - GtkWidget *operation_name_label; - GtkWidget *item_name; - GtkWidget *from_label; - GtkWidget *from_path_label; - GtkWidget *to_label; - GtkWidget *to_path_label; - - GtkWidget *progress_bar; - - const char *from_prefix; - const char *to_prefix; - - gulong bytes_copied; - gulong files_total; - gulong bytes_total; - - /* system time (microseconds) when dialog was mapped */ - gint64 start_time; - - guint delayed_close_timeout_id; -}; - -/* Private functions. */ - -static void -nautilus_file_operations_progress_update (NautilusFileOperationsProgress *progress) -{ - if (progress->details->bytes_total == 0) { - /* We haven't set up the file count yet, do not update - * the progress bar until we do. - */ - return; - } - - gtk_progress_configure (GTK_PROGRESS (progress->details->progress_bar), - progress->details->bytes_copied, - 0.0, - progress->details->bytes_total); -} - -static void -set_text_unescaped_trimmed (EelEllipsizingLabel *label, const char *text) -{ - char *unescaped_text; - - if (text == NULL || text[0] == '\0') { - eel_ellipsizing_label_set_text (label, ""); - return; - } - - unescaped_text = gnome_vfs_unescape_string_for_display (text); - eel_ellipsizing_label_set_text (label, unescaped_text); - g_free (unescaped_text); -} - -/* This is just to make sure the dialog is not closed without explicit - * intervention. - */ -static gboolean -close_callback (GnomeDialog *dialog) -{ - return FALSE; -} - -/* GtkObject methods. */ - -static void -nautilus_file_operations_progress_destroy (GtkObject *object) -{ - NautilusFileOperationsProgress *progress; - - progress = NAUTILUS_FILE_OPERATIONS_PROGRESS (object); - - if (progress->details->delayed_close_timeout_id != 0) { - g_source_remove (progress->details->delayed_close_timeout_id); - } - - g_free (progress->details); - - EEL_CALL_PARENT (GTK_OBJECT_CLASS, destroy, (object)); -} - -/* Initialization. */ - -static void -create_titled_label (GtkTable *table, int row, GtkWidget **title_widget, GtkWidget **label_text_widget) -{ - *title_widget = gtk_label_new (""); - eel_gtk_label_make_bold (GTK_LABEL (*title_widget)); - gtk_misc_set_alignment (GTK_MISC (*title_widget), 1, 0); - gtk_table_attach (table, *title_widget, - 0, 1, - row, row + 1, - GTK_FILL, 0, - 0, 0); - gtk_widget_show (*title_widget); - - *label_text_widget = eel_ellipsizing_label_new (""); - gtk_table_attach (table, *label_text_widget, - 1, 2, - row, row + 1, - GTK_FILL | GTK_EXPAND, 0, - 0, 0); - gtk_widget_show (*label_text_widget); - gtk_misc_set_alignment (GTK_MISC (*label_text_widget), 0, 0); -} - -static void -map_callback (GtkWidget *widget) -{ - NautilusFileOperationsProgress *progress; - - progress = NAUTILUS_FILE_OPERATIONS_PROGRESS (widget); - - EEL_CALL_PARENT (GTK_WIDGET_CLASS, map, (widget)); - - progress->details->start_time = eel_get_system_time (); -} - -static gboolean -delete_event_callback (GtkWidget *widget, - GdkEventAny *event) -{ - /* Do nothing -- we shouldn't be getting a close event because - * the dialog should not have a close box. - */ - return TRUE; -} - -static void -nautilus_file_operations_progress_initialize (NautilusFileOperationsProgress *progress) -{ - GtkBox *vbox; - GtkWidget *hbox; - GtkTable *titled_label_table; - - progress->details = g_new0 (NautilusFileOperationsProgressDetails, 1); - - vbox = GTK_BOX (GNOME_DIALOG (progress)->vbox); - - /* This is evil but makes the dialog look less cramped. */ - gtk_container_set_border_width (GTK_CONTAINER (vbox), OUTER_BORDER); - - hbox = gtk_hbox_new (FALSE, 0); - gtk_box_pack_start (vbox, hbox, TRUE, TRUE, HORIZONTAL_SPACING); - gtk_widget_show (hbox); - - /* label- */ - /* Files remaining to be copied: */ - progress->details->progress_title_label = gtk_label_new (""); - gtk_label_set_justify (GTK_LABEL (progress->details->progress_title_label), GTK_JUSTIFY_LEFT); - gtk_box_pack_start (GTK_BOX (hbox), progress->details->progress_title_label, FALSE, FALSE, 0); - gtk_widget_show (progress->details->progress_title_label); - eel_gtk_label_make_bold (GTK_LABEL (progress->details->progress_title_label)); - - - /* label -- */ - /* 24 of 30 */ - progress->details->progress_count_label = gtk_label_new (""); - gtk_label_set_justify (GTK_LABEL (progress->details->progress_count_label), GTK_JUSTIFY_RIGHT); - gtk_box_pack_end (GTK_BOX (hbox), progress->details->progress_count_label, FALSE, FALSE, 0); - gtk_widget_show (progress->details->progress_count_label); - eel_gtk_label_make_bold (GTK_LABEL (progress->details->progress_count_label)); - - /* progress bar */ - progress->details->progress_bar = gtk_progress_bar_new (); - gtk_progress_bar_set_bar_style (GTK_PROGRESS_BAR (progress->details->progress_bar), - GTK_PROGRESS_CONTINUOUS); - gtk_progress_bar_set_orientation (GTK_PROGRESS_BAR (progress->details->progress_bar), - GTK_PROGRESS_LEFT_TO_RIGHT); - gtk_widget_set_usize (progress->details->progress_bar, PROGRESS_BAR_WIDTH, -1); - gtk_box_pack_start (vbox, progress->details->progress_bar, FALSE, TRUE, 0); - gtk_widget_show (progress->details->progress_bar); - - titled_label_table = GTK_TABLE (gtk_table_new (3, 2, FALSE)); - gtk_table_set_row_spacings (titled_label_table, 4); - gtk_table_set_col_spacings (titled_label_table, 4); - gtk_widget_show (GTK_WIDGET (titled_label_table)); - - create_titled_label (titled_label_table, 0, - &progress->details->operation_name_label, - &progress->details->item_name); - create_titled_label (titled_label_table, 1, - &progress->details->from_label, - &progress->details->from_path_label); - create_titled_label (titled_label_table, 2, - &progress->details->to_label, - &progress->details->to_path_label); - - gtk_box_pack_start (vbox, GTK_WIDGET (titled_label_table), FALSE, FALSE, 0); -} - -static void -nautilus_file_operations_progress_initialize_class (NautilusFileOperationsProgressClass *klass) -{ - GtkObjectClass *object_class; - GtkWidgetClass *widget_class; - GnomeDialogClass *dialog_class; - - object_class = GTK_OBJECT_CLASS (klass); - widget_class = GTK_WIDGET_CLASS (klass); - dialog_class = GNOME_DIALOG_CLASS (klass); - - object_class->destroy = nautilus_file_operations_progress_destroy; - - /* The progress dialog should not have a title and a close box. - * Some broken window manager themes still show the window title. - * Make clicking the close box do nothing in that case to prevent - * a crash. - */ - widget_class->delete_event = delete_event_callback; - widget_class->map = map_callback; - - dialog_class->close = close_callback; -} - -NautilusFileOperationsProgress * -nautilus_file_operations_progress_new (const char *title, - const char *operation_string, - const char *from_prefix, - const char *to_prefix, - gulong total_files, - gulong total_bytes) -{ - GtkWidget *widget; - NautilusFileOperationsProgress *progress; - - widget = gtk_widget_new (nautilus_file_operations_progress_get_type (), NULL); - progress = NAUTILUS_FILE_OPERATIONS_PROGRESS (widget); - - nautilus_file_operations_progress_set_operation_string (progress, operation_string); - nautilus_file_operations_progress_set_total (progress, total_files, total_bytes); - - gtk_window_set_title (GTK_WINDOW (widget), title); - gtk_window_set_wmclass (GTK_WINDOW (widget), "file_progress", "Nautilus"); - - gnome_dialog_append_button (GNOME_DIALOG (widget), - GNOME_STOCK_BUTTON_CANCEL); - - progress->details->from_prefix = from_prefix; - progress->details->to_prefix = to_prefix; - - return progress; -} - -void -nautilus_file_operations_progress_set_total (NautilusFileOperationsProgress *progress, - gulong files_total, - gulong bytes_total) -{ - g_return_if_fail (NAUTILUS_IS_FILE_OPERATIONS_PROGRESS (progress)); - - progress->details->files_total = files_total; - progress->details->bytes_total = bytes_total; - - nautilus_file_operations_progress_update (progress); -} - -void -nautilus_file_operations_progress_set_operation_string (NautilusFileOperationsProgress *progress, - const char *operation_string) -{ - g_return_if_fail (NAUTILUS_IS_FILE_OPERATIONS_PROGRESS (progress)); - - gtk_label_set_text (GTK_LABEL (progress->details->progress_title_label), - operation_string); -} - -void -nautilus_file_operations_progress_new_file (NautilusFileOperationsProgress *progress, - const char *progress_verb, - const char *item_name, - const char *from_path, - const char *to_path, - const char *from_prefix, - const char *to_prefix, - gulong file_index, - gulong size) -{ - char *progress_count; - - g_return_if_fail (NAUTILUS_IS_FILE_OPERATIONS_PROGRESS (progress)); - g_return_if_fail (GTK_WIDGET_REALIZED (progress)); - - progress->details->from_prefix = from_prefix; - progress->details->to_prefix = to_prefix; - - if (progress->details->bytes_total > 0) { - /* we haven't set up the file count yet, do not update the progress - * count until we do - */ - gtk_label_set_text (GTK_LABEL (progress->details->operation_name_label), - progress_verb); - set_text_unescaped_trimmed - (EEL_ELLIPSIZING_LABEL (progress->details->item_name), - item_name); - - progress_count = g_strdup_printf (_("%ld of %ld"), - file_index, - progress->details->files_total); - gtk_label_set_text (GTK_LABEL (progress->details->progress_count_label), progress_count); - g_free (progress_count); - - gtk_label_set_text (GTK_LABEL (progress->details->from_label), from_prefix); - set_text_unescaped_trimmed - (EEL_ELLIPSIZING_LABEL (progress->details->from_path_label), from_path); - - if (progress->details->to_prefix != NULL && progress->details->to_path_label != NULL) { - gtk_label_set_text (GTK_LABEL (progress->details->to_label), to_prefix); - set_text_unescaped_trimmed - (EEL_ELLIPSIZING_LABEL (progress->details->to_path_label), to_path); - } - } - - nautilus_file_operations_progress_update (progress); -} - -void -nautilus_file_operations_progress_clear (NautilusFileOperationsProgress *progress) -{ - gtk_label_set_text (GTK_LABEL (progress->details->from_label), ""); - gtk_label_set_text (GTK_LABEL (progress->details->from_path_label), ""); - gtk_label_set_text (GTK_LABEL (progress->details->to_label), ""); - gtk_label_set_text (GTK_LABEL (progress->details->to_path_label), ""); - - progress->details->files_total = 0; - progress->details->bytes_total = 0; - - nautilus_file_operations_progress_update (progress); -} - -void -nautilus_file_operations_progress_update_sizes (NautilusFileOperationsProgress *progress, - gulong bytes_done_in_file, - gulong bytes_done) -{ - g_return_if_fail (NAUTILUS_IS_FILE_OPERATIONS_PROGRESS (progress)); - - progress->details->bytes_copied = bytes_done; - - nautilus_file_operations_progress_update (progress); -} - -static gboolean -delayed_close_callback (gpointer callback_data) -{ - NautilusFileOperationsProgress *progress; - - progress = NAUTILUS_FILE_OPERATIONS_PROGRESS (callback_data); - - progress->details->delayed_close_timeout_id = 0; - gtk_object_destroy (GTK_OBJECT (progress)); - return FALSE; -} - -void -nautilus_file_operations_progress_done (NautilusFileOperationsProgress *progress) -{ - guint time_up; - - if (!GTK_WIDGET_MAPPED (progress)) { - gtk_object_destroy (GTK_OBJECT (progress)); - return; - } - g_assert (progress->details->start_time != 0); - - /* compute time up in milliseconds */ - time_up = (eel_get_system_time () - progress->details->start_time) / 1000; - if (time_up >= MINIMUM_TIME_UP) { - gtk_object_destroy (GTK_OBJECT (progress)); - return; - } - - /* No cancel button once the operation is done. */ - gnome_dialog_set_sensitive (GNOME_DIALOG (progress), 0, FALSE); - - progress->details->delayed_close_timeout_id = gtk_timeout_add - (MINIMUM_TIME_UP - time_up, - delayed_close_callback, - progress); -} diff --git a/libnautilus-extensions/nautilus-file-operations-progress.h b/libnautilus-extensions/nautilus-file-operations-progress.h deleted file mode 100644 index 3ec3445d4..000000000 --- a/libnautilus-extensions/nautilus-file-operations-progress.h +++ /dev/null @@ -1,81 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ - -/* nautilus-file-operations-progress.h - Progress dialog for transfer - operations in the GNOME Desktop File Operation Service. - - Copyright (C) 1999, 2000 Free Software Foundation - Copyright (C) 2000, 2001 Eazel Inc. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - This program 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; see the file COPYING. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. - - Author: - Ettore Perazzoli <ettore@gnu.org> - Pavel Cisler <pavel@eazel.com> -*/ - -#ifndef NAUTILUS_FILE_OPERATIONS_PROGRESS_H -#define NAUTILUS_FILE_OPERATIONS_PROGRESS_H - -#include <libgnomeui/gnome-dialog.h> - -typedef struct NautilusFileOperationsProgressDetails NautilusFileOperationsProgressDetails; - -typedef struct { - GnomeDialog dialog; - NautilusFileOperationsProgressDetails *details; -} NautilusFileOperationsProgress; - -typedef struct { - GnomeDialogClass parent_class; -} NautilusFileOperationsProgressClass; - -#define NAUTILUS_FILE_OPERATIONS_PROGRESS(obj) \ - GTK_CHECK_CAST (obj, nautilus_file_operations_progress_get_type (), NautilusFileOperationsProgress) -#define NAUTILUS_FILE_OPERATIONS_PROGRESS_CLASS(klass) \ - GTK_CHECK_CLASS_CAST (klass, nautilus_file_operations_progress_get_type (), NautilusFileOperationsProgressClass) -#define NAUTILUS_IS_FILE_OPERATIONS_PROGRESS(obj) \ - GTK_CHECK_TYPE (obj, nautilus_file_operations_progress_get_type ()) - -guint nautilus_file_operations_progress_get_type (void); -NautilusFileOperationsProgress *nautilus_file_operations_progress_new (const char *title, - const char *operation_string, - const char *from_prefix, - const char *to_prefix, - gulong files_total, - gulong bytes_total); -void nautilus_file_operations_progress_done (NautilusFileOperationsProgress *dialog); -void nautilus_file_operations_progress_set_progress_title (NautilusFileOperationsProgress *dialog, - const char *progress_title); -void nautilus_file_operations_progress_set_total (NautilusFileOperationsProgress *dialog, - gulong files_total, - gulong bytes_total); -void nautilus_file_operations_progress_set_operation_string (NautilusFileOperationsProgress *dialog, - const char *operation_string); -void nautilus_file_operations_progress_clear (NautilusFileOperationsProgress *dialog); -void nautilus_file_operations_progress_new_file (NautilusFileOperationsProgress *dialog, - const char *progress_verb, - const char *item_name, - const char *from_path, - const char *to_path, - const char *from_prefix, - const char *to_prefix, - gulong file_index, - gulong size); -void nautilus_file_operations_progress_update_sizes (NautilusFileOperationsProgress *dialog, - gulong bytes_done_in_file, - gulong bytes_done); - -#endif /* NAUTILUS_FILE_OPERATIONS_PROGRESS_H */ diff --git a/libnautilus-extensions/nautilus-file-operations.c b/libnautilus-extensions/nautilus-file-operations.c deleted file mode 100644 index c6f0443e8..000000000 --- a/libnautilus-extensions/nautilus-file-operations.c +++ /dev/null @@ -1,2303 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ - -/* nautilus-file-operations.c - Nautilus file operations. - - Copyright (C) 1999, 2000 Free Software Foundation - Copyright (C) 2000, 2001 Eazel, Inc. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public - License along with this program; if not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. - - Authors: Ettore Perazzoli <ettore@gnu.org> - Pavel Cisler <pavel@eazel.com> - */ - -#include <config.h> -#include "nautilus-file-operations.h" - -#include "nautilus-file-operations-progress.h" -#include "nautilus-lib-self-check-functions.h" - -#include <eel/eel-gdk-font-extensions.h> -#include <eel/eel-glib-extensions.h> -#include <eel/eel-gtk-extensions.h> -#include <eel/eel-stock-dialogs.h> -#include <eel/eel-vfs-extensions.h> - -#include <gnome.h> -#include <gtk/gtklabel.h> -#include <libgnomevfs/gnome-vfs-async-ops.h> -#include <libgnomevfs/gnome-vfs-find-directory.h> -#include <libgnomevfs/gnome-vfs-ops.h> -#include <libgnomevfs/gnome-vfs-result.h> -#include <libgnomevfs/gnome-vfs-uri.h> -#include <libgnomevfs/gnome-vfs-utils.h> -#include <libnautilus-extensions/nautilus-file-changes-queue.h> -#include "nautilus-global-preferences.h" -#include "nautilus-link.h" -#include "nautilus-trash-monitor.h" - -typedef enum { - TRANSFER_MOVE, - TRANSFER_COPY, - TRANSFER_DUPLICATE, - TRANSFER_MOVE_TO_TRASH, - TRANSFER_EMPTY_TRASH, - TRANSFER_DELETE, - TRANSFER_LINK -} TransferKind; - -/* Copy engine callback state */ -typedef struct { - GnomeVFSAsyncHandle *handle; - NautilusFileOperationsProgress *progress_dialog; - const char *operation_title; /* "Copying files" */ - const char *action_label; /* "Files copied:" */ - const char *progress_verb; /* "Copying" */ - const char *preparation_name; /* "Preparing To Copy..." */ - const char *cleanup_name; /* "Finishing Move..." */ - GnomeVFSXferErrorMode error_mode; - GnomeVFSXferOverwriteMode overwrite_mode; - GtkWidget *parent_view; - TransferKind kind; - gboolean show_progress_dialog; - void (* done_callback) (GHashTable *debuting_uris, gpointer data); - gpointer done_callback_data; - GHashTable *debuting_uris; - gboolean cancelled; -} TransferInfo; - -static TransferInfo * -transfer_info_new (GtkWidget *parent_view) -{ - TransferInfo *result; - - result = g_new0 (TransferInfo, 1); - result->parent_view = parent_view; - - eel_nullify_when_destroyed (&result->parent_view); - - return result; -} - -static void -transfer_info_destroy (TransferInfo *transfer_info) -{ - eel_nullify_cancel (&transfer_info->parent_view); - - if (transfer_info->progress_dialog != NULL) { - nautilus_file_operations_progress_done (transfer_info->progress_dialog); - } - - if (transfer_info->debuting_uris != NULL) { - eel_g_hash_table_destroy_deep_custom - (transfer_info->debuting_uris, (GFunc) g_free, NULL, NULL, NULL); - } - - g_free (transfer_info); -} - -/* Struct used to control applying icon positions to - * top level items during a copy, drag, new folder creation and - * link creation - */ -typedef struct { - GdkPoint *icon_positions; - int last_icon_position_index; - GList *uris; - const GList *last_uri; -} IconPositionIterator; - -static IconPositionIterator * -icon_position_iterator_new (GArray *icon_positions, const GList *uris) -{ - IconPositionIterator *result; - guint index; - - g_assert (icon_positions->len == g_list_length ((GList *)uris)); - result = g_new (IconPositionIterator, 1); - - /* make our own copy of the icon locations */ - result->icon_positions = g_new (GdkPoint, icon_positions->len); - for (index = 0; index < icon_positions->len; index++) { - result->icon_positions[index] = g_array_index (icon_positions, GdkPoint, index); - } - result->last_icon_position_index = 0; - - result->uris = eel_g_str_list_copy ((GList *)uris); - result->last_uri = result->uris; - - return result; -} - -static void -icon_position_iterator_free (IconPositionIterator *position_iterator) -{ - if (position_iterator == NULL) { - return; - } - - g_free (position_iterator->icon_positions); - eel_g_list_free_deep (position_iterator->uris); - g_free (position_iterator); -} - -static gboolean -icon_position_iterator_get_next (IconPositionIterator *position_iterator, - const char *next_uri, - GdkPoint *point) -{ - if (position_iterator == NULL) { - return FALSE; - } - - for (;;) { - if (position_iterator->last_uri == NULL) { - /* we are done, no more points left */ - return FALSE; - } - - /* Scan for the next point that matches the source_name - * uri. - */ - if (strcmp ((const char *) position_iterator->last_uri->data, - next_uri) == 0) { - break; - } - - /* Didn't match -- a uri must have been skipped by the copy - * engine because of a name conflict. All we need to do is - * skip ahead too. - */ - position_iterator->last_uri = position_iterator->last_uri->next; - position_iterator->last_icon_position_index++; - } - - /* apply the location to the target file */ - *point = position_iterator->icon_positions - [position_iterator->last_icon_position_index]; - - /* advance to the next point for next time */ - position_iterator->last_uri = position_iterator->last_uri->next; - position_iterator->last_icon_position_index++; - - return TRUE; -} - -/* Hack to get the GdkFont used by a GtkLabel in an error dialog. - * We need to do this because the string truncation needs to be - * done before a dialog is instantiated. - * - * This is probably not super fast but it is not a problem in the - * context we are using it, truncating a string while displaying an - * error dialog. - */ -static GdkFont * -get_label_font (void) -{ - GtkWidget *label; - GtkStyle *style; - GdkFont *font; - - /* FIXME: Does this really pick up the correct font if the rc - * file has a special case for the particular dialog we are - * preparing? - */ - - label = gtk_label_new (""); - style = gtk_widget_get_style (label); - font = style->font; - gdk_font_ref (font); - gtk_object_sink (GTK_OBJECT (label)); - - return font; -} - -static char * -ellipsize_string_for_dialog (const char *str) -{ - GdkFont *font; - int maximum_width; - char *result; - - /* get a nice length to ellipsize to, based on the font */ - font = get_label_font (); - maximum_width = gdk_string_width (font, "MMMMMMMMMMMMMMMMMMMMMM"); - - result = eel_string_ellipsize (str, font, maximum_width, EEL_ELLIPSIZE_MIDDLE); - gdk_font_unref (font); - - return result; -} - -static char * -format_and_ellipsize_uri_for_dialog (const char *uri) -{ - char *unescaped, *result; - - unescaped = eel_format_uri_for_display (uri); - result = ellipsize_string_for_dialog (unescaped); - g_free (unescaped); - - return result; -} - -static char * -extract_and_ellipsize_file_name_for_dialog (const char *uri) -{ - const char *last_part; - char *unescaped, *result; - - last_part = g_basename (uri); - g_return_val_if_fail (last_part != NULL, NULL); - - unescaped = gnome_vfs_unescape_string_for_display (last_part); - result = ellipsize_string_for_dialog (unescaped); - g_free (unescaped); - - return result; -} - -static GtkWidget * -parent_for_error_dialog (TransferInfo *transfer_info) -{ - if (transfer_info->progress_dialog != NULL) { - return GTK_WIDGET (transfer_info->progress_dialog); - } - - return transfer_info->parent_view; -} - -static void -fit_rect_on_screen (GdkRectangle *rect) -{ - if (rect->x + rect->width > gdk_screen_width ()) { - rect->x = gdk_screen_width () - rect->width; - } - - if (rect->y + rect->height > gdk_screen_height ()) { - rect->y = gdk_screen_height () - rect->height; - } - - if (rect->x < 0) { - rect->x = 0; - } - - if (rect->y < 0) { - rect->y = 0; - } -} - -static void -center_dialog_over_rect (GtkWindow *window, GdkRectangle rect) -{ - g_return_if_fail (GTK_WINDOW (window) != NULL); - - fit_rect_on_screen (&rect); - - gtk_widget_set_uposition (GTK_WIDGET (window), - rect.x + rect.width / 2 - - GTK_WIDGET (window)->allocation.width / 2, - rect.y + rect.height / 2 - - GTK_WIDGET (window)->allocation.height / 2); -} - -static void -center_dialog_over_window (GtkWindow *window, GtkWindow *over) -{ - GdkRectangle rect; - int x, y, w, h; - - g_return_if_fail (GTK_WINDOW (window) != NULL); - g_return_if_fail (GTK_WINDOW (over) != NULL); - - gdk_window_get_root_origin (GTK_WIDGET (over)->window, &x, &y); - gdk_window_get_size (GTK_WIDGET (over)->window, &w, &h); - rect.x = x; - rect.y = y; - rect.width = w; - rect.height = h; - - center_dialog_over_rect (window, rect); -} - -static gboolean -handle_close_callback (GnomeDialog *dialog, TransferInfo *tranfer_info) -{ - tranfer_info->cancelled = TRUE; - return FALSE; -} - -static void -create_transfer_dialog (const GnomeVFSXferProgressInfo *progress_info, - TransferInfo *transfer_info) -{ - if (!transfer_info->show_progress_dialog) { - return; - } - - g_return_if_fail (transfer_info->progress_dialog == NULL); - - transfer_info->progress_dialog = nautilus_file_operations_progress_new - (transfer_info->operation_title, "", "", "", 0, 0); - - /* Treat clicking on the close box or use of the escape key - * the same as clicking cancel. - */ - gtk_signal_connect (GTK_OBJECT (transfer_info->progress_dialog), - "clicked", - GTK_SIGNAL_FUNC (gnome_dialog_close), - NULL); - gtk_signal_connect (GTK_OBJECT (transfer_info->progress_dialog), - "close", - GTK_SIGNAL_FUNC (handle_close_callback), - transfer_info); - - gtk_widget_show (GTK_WIDGET (transfer_info->progress_dialog)); - - /* Make the progress dialog show up over the window we are copying into */ - if (transfer_info->parent_view != NULL) { - center_dialog_over_window (GTK_WINDOW (transfer_info->progress_dialog), - GTK_WINDOW (gtk_widget_get_toplevel (transfer_info->parent_view))); - } -} - -static void -progress_dialog_set_to_from_item_text (NautilusFileOperationsProgress *dialog, - const char *progress_verb, - const char *from_uri, const char *to_uri, - gulong index, gulong size) -{ - char *item; - char *from_path; - char *to_path; - char *progress_label_text; - const char *from_prefix; - const char *to_prefix; - GnomeVFSURI *uri; - int length; - - item = NULL; - from_path = NULL; - to_path = NULL; - from_prefix = ""; - to_prefix = ""; - progress_label_text = NULL; - - if (from_uri != NULL) { - uri = gnome_vfs_uri_new (from_uri); - item = gnome_vfs_uri_extract_short_name (uri); - from_path = gnome_vfs_uri_extract_dirname (uri); - - /* remove the last '/' */ - length = strlen (from_path); - if (from_path [length - 1] == '/') { - from_path [length - 1] = '\0'; - } - - gnome_vfs_uri_unref (uri); - g_assert (progress_verb); - progress_label_text = g_strdup_printf ("%s:", progress_verb); - /* "From" dialog label, source path gets placed next to it in the dialog */ - from_prefix = _("From:"); - } - - if (to_uri != NULL) { - uri = gnome_vfs_uri_new (to_uri); - to_path = gnome_vfs_uri_extract_dirname (uri); - - /* remove the last '/' */ - length = strlen (to_path); - if (to_path [length - 1] == '/') { - to_path [length - 1] = '\0'; - } - - gnome_vfs_uri_unref (uri); - /* "To" dialog label, source path gets placed next to it in the dialog */ - to_prefix = _("To:"); - } - - nautilus_file_operations_progress_new_file - (dialog, - progress_label_text != NULL ? progress_label_text : "", - item != NULL ? item : "", - from_path != NULL ? from_path : "", - to_path != NULL ? to_path : "", - from_prefix, to_prefix, index, size); - - g_free (progress_label_text); - g_free (item); - g_free (from_path); - g_free (to_path); -} - -static int -handle_transfer_ok (const GnomeVFSXferProgressInfo *progress_info, - TransferInfo *transfer_info) -{ - if (transfer_info->cancelled - && progress_info->phase != GNOME_VFS_XFER_PHASE_COMPLETED) { - /* If cancelled, delete any partially copied files that are laying - * around and return. - */ - if (progress_info->bytes_total != progress_info->bytes_copied) { - GList *delete_me = NULL; - - delete_me = g_list_append (delete_me, progress_info->target_name); - - nautilus_file_operations_delete (delete_me, transfer_info->parent_view); - - g_list_free (delete_me); - } - - return 0; - } - - switch (progress_info->phase) { - case GNOME_VFS_XFER_PHASE_INITIAL: - create_transfer_dialog (progress_info, transfer_info); - return 1; - - case GNOME_VFS_XFER_PHASE_COLLECTING: - if (transfer_info->progress_dialog != NULL) { - nautilus_file_operations_progress_set_operation_string - (transfer_info->progress_dialog, - transfer_info->preparation_name); - } - return 1; - - case GNOME_VFS_XFER_PHASE_READYTOGO: - if (transfer_info->progress_dialog != NULL) { - nautilus_file_operations_progress_set_operation_string - (transfer_info->progress_dialog, - transfer_info->action_label); - nautilus_file_operations_progress_set_total - (transfer_info->progress_dialog, - progress_info->files_total, - progress_info->bytes_total); - } - return 1; - - case GNOME_VFS_XFER_PHASE_DELETESOURCE: - nautilus_file_changes_consume_changes (FALSE); - if (transfer_info->progress_dialog != NULL) { - progress_dialog_set_to_from_item_text - (transfer_info->progress_dialog, - transfer_info->progress_verb, - progress_info->source_name, - NULL, - progress_info->file_index, - progress_info->file_size); - - nautilus_file_operations_progress_update_sizes - (transfer_info->progress_dialog, - MIN (progress_info->bytes_copied, - progress_info->bytes_total), - MIN (progress_info->total_bytes_copied, - progress_info->bytes_total)); - } - return 1; - - case GNOME_VFS_XFER_PHASE_MOVING: - case GNOME_VFS_XFER_PHASE_OPENSOURCE: - case GNOME_VFS_XFER_PHASE_OPENTARGET: - /* fall through */ - case GNOME_VFS_XFER_PHASE_COPYING: - if (transfer_info->progress_dialog != NULL) { - if (progress_info->bytes_copied == 0) { - progress_dialog_set_to_from_item_text - (transfer_info->progress_dialog, - transfer_info->progress_verb, - progress_info->source_name, - progress_info->target_name, - progress_info->file_index, - progress_info->file_size); - } else { - nautilus_file_operations_progress_update_sizes - (transfer_info->progress_dialog, - MIN (progress_info->bytes_copied, - progress_info->bytes_total), - MIN (progress_info->total_bytes_copied, - progress_info->bytes_total)); - } - } - return 1; - - case GNOME_VFS_XFER_PHASE_CLEANUP: - if (transfer_info->progress_dialog != NULL) { - nautilus_file_operations_progress_clear - (transfer_info->progress_dialog); - nautilus_file_operations_progress_set_operation_string - (transfer_info->progress_dialog, - transfer_info->cleanup_name); - } - return 1; - - case GNOME_VFS_XFER_PHASE_COMPLETED: - nautilus_file_changes_consume_changes (TRUE); - if (transfer_info->done_callback != NULL) { - transfer_info->done_callback (transfer_info->debuting_uris, - transfer_info->done_callback_data); - /* done_callback now owns (will free) debuting_uris */ - transfer_info->debuting_uris = NULL; - } - - transfer_info_destroy (transfer_info); - return 1; - - default: - return 1; - } -} - -typedef enum { - ERROR_READ_ONLY, - ERROR_NOT_READABLE, - ERROR_NOT_WRITABLE, - ERROR_NOT_ENOUGH_PERMISSIONS, - ERROR_NO_SPACE, - ERROR_OTHER -} NautilusFileOperationsErrorKind; - -typedef enum { - ERROR_LOCATION_UNKNOWN, - ERROR_LOCATION_SOURCE, - ERROR_LOCATION_SOURCE_PARENT, - ERROR_LOCATION_SOURCE_OR_PARENT, - ERROR_LOCATION_TARGET -} NautilusFileOperationsErrorLocation; - - -static char * -build_error_string (const char *source_name, const char *target_name, - TransferKind operation_kind, - NautilusFileOperationsErrorKind error_kind, - NautilusFileOperationsErrorLocation error_location, - GnomeVFSResult error) -{ - /* Avoid clever message composing here, just use brute force and - * duplicate the different flavors of error messages for all the - * possible permutations. - * That way localizers have an easier time and can even rearrange the - * order of the words in the messages easily. - */ - - const char *error_string; - char *result; - - error_string = NULL; - result = NULL; - - if (error_location == ERROR_LOCATION_SOURCE_PARENT) { - - switch (operation_kind) { - case TRANSFER_MOVE: - case TRANSFER_MOVE_TO_TRASH: - if (error_kind == ERROR_READ_ONLY) { - error_string = _("Error while moving.\n\n" - "\"%s\" cannot be moved because it is on " - "a read-only disk."); - } - break; - - case TRANSFER_DELETE: - case TRANSFER_EMPTY_TRASH: - switch (error_kind) { - case ERROR_NOT_ENOUGH_PERMISSIONS: - case ERROR_NOT_WRITABLE: - error_string = _("Error while deleting.\n\n" - "\"%s\" cannot be deleted because you do not have " - "permissions to modify its parent folder."); - break; - - case ERROR_READ_ONLY: - error_string = _("Error while deleting.\n\n" - "\"%s\" cannot be deleted because it is on " - "a read-only disk."); - break; - - default: - break; - } - break; - - default: - g_assert_not_reached (); - break; - } - - if (error_string != NULL) { - g_assert (source_name != NULL); - result = g_strdup_printf (error_string, source_name); - } - - } else if (error_location == ERROR_LOCATION_SOURCE_OR_PARENT) { - - g_assert (source_name != NULL); - - /* FIXME: Would be better if we could distinguish source vs parent permissions - * better somehow. The GnomeVFS copy engine would have to do some snooping - * after the failure in this case. - */ - switch (operation_kind) { - case TRANSFER_MOVE: - if (error_kind == ERROR_NOT_ENOUGH_PERMISSIONS) { - error_string = _("Error while moving.\n\n" - "\"%s\" cannot be moved because you do not have " - "permissions to change it or its parent folder."); - } - break; - case TRANSFER_MOVE_TO_TRASH: - if (error_kind == ERROR_NOT_ENOUGH_PERMISSIONS) { - error_string = _("Error while moving.\n\n" - "\"%s\" cannot be moved to the Trash because you do not have " - "permissions to change it or its parent folder."); - } - break; - - default: - g_assert_not_reached (); - break; - } - - if (error_string != NULL) { - g_assert (source_name != NULL); - result = g_strdup_printf (error_string, source_name); - } - - } else if (error_location == ERROR_LOCATION_SOURCE) { - - g_assert (source_name != NULL); - - switch (operation_kind) { - case TRANSFER_COPY: - case TRANSFER_DUPLICATE: - if (error_kind == ERROR_NOT_READABLE) { - error_string = _("Error while copying.\n\n" - "\"%s\" cannot be copied because you do not have " - "permissions to read it."); - } - break; - - default: - g_assert_not_reached (); - break; - } - - if (error_string != NULL) { - g_assert (source_name != NULL); - result = g_strdup_printf (error_string, source_name); - } - - } else if (error_location == ERROR_LOCATION_TARGET) { - - if (error_kind == ERROR_NO_SPACE) { - switch (operation_kind) { - case TRANSFER_COPY: - case TRANSFER_DUPLICATE: - error_string = _("Error while copying to \"%s\".\n\n" - "There is not enough space on the destination."); - break; - case TRANSFER_MOVE_TO_TRASH: - case TRANSFER_MOVE: - error_string = _("Error while moving to \"%s\".\n\n" - "There is not enough space on the destination."); - break; - case TRANSFER_LINK: - error_string = _("Error while creating link in \"%s\".\n\n" - "There is not enough space on the destination."); - break; - default: - g_assert_not_reached (); - break; - } - } else { - switch (operation_kind) { - case TRANSFER_COPY: - case TRANSFER_DUPLICATE: - if (error_kind == ERROR_NOT_ENOUGH_PERMISSIONS) { - error_string = _("Error while copying to \"%s\".\n\n" - "You do not have permissions to write to " - "this folder."); - } else if (error_kind == ERROR_NOT_WRITABLE) { - error_string = _("Error while copying to \"%s\".\n\n" - "The destination disk is read-only."); - } - break; - case TRANSFER_MOVE: - case TRANSFER_MOVE_TO_TRASH: - if (error_kind == ERROR_NOT_ENOUGH_PERMISSIONS) { - error_string = _("Error while moving items to \"%s\".\n\n" - "You do not have permissions to write to " - "this folder."); - } else if (error_kind == ERROR_NOT_WRITABLE) { - error_string = _("Error while moving items to \"%s\".\n\n" - "The destination disk is read-only."); - } - - break; - case TRANSFER_LINK: - if (error_kind == ERROR_NOT_ENOUGH_PERMISSIONS) { - error_string = _("Error while creating links in \"%s\".\n\n" - "You do not have permissions to write to " - "this folder."); - } else if (error_kind == ERROR_NOT_WRITABLE) { - error_string = _("Error while creating links in \"%s\".\n\n" - "The destination disk is read-only."); - } - break; - default: - g_assert_not_reached (); - break; - } - } - if (error_string != NULL) { - g_assert (target_name != NULL); - result = g_strdup_printf (error_string, target_name); - } - } - - if (result == NULL) { - /* None of the specific error messages apply, use a catch-all - * generic error - */ - g_message ("Please tell pavel@eazel.com that you hit case %s while doing " - "a file operation.", gnome_vfs_result_to_string (error)); - - /* FIXMEs: we need to consider a single item - * move/copy and not offer to continue in that case - */ - if (source_name != NULL) { - switch (operation_kind) { - case TRANSFER_COPY: - case TRANSFER_DUPLICATE: - error_string = _("Error \"%s\" while copying \"%s\".\n\n" - "Would you like to continue?"); - break; - case TRANSFER_MOVE: - error_string = _("Error \"%s\" while moving \"%s\".\n\n" - "Would you like to continue?"); - break; - case TRANSFER_LINK: - error_string = _("Error \"%s\" while creating a link to \"%s\".\n\n" - "Would you like to continue?"); - break; - case TRANSFER_DELETE: - case TRANSFER_EMPTY_TRASH: - case TRANSFER_MOVE_TO_TRASH: - error_string = _("Error \"%s\" while deleting \"%s\".\n\n" - "Would you like to continue?"); - break; - default: - g_assert_not_reached (); - break; - } - - result = g_strdup_printf (error_string, - gnome_vfs_result_to_string (error), - source_name); - } else { - switch (operation_kind) { - case TRANSFER_COPY: - case TRANSFER_DUPLICATE: - error_string = _("Error \"%s\" while copying.\n\n" - "Would you like to continue?"); - break; - case TRANSFER_MOVE: - error_string = _("Error \"%s\" while moving.\n\n" - "Would you like to continue?"); - break; - case TRANSFER_LINK: - error_string = _("Error \"%s\" while linking.\n\n" - "Would you like to continue?"); - break; - case TRANSFER_DELETE: - case TRANSFER_EMPTY_TRASH: - case TRANSFER_MOVE_TO_TRASH: - error_string = _("Error \"%s\" while deleting.\n\n" - "Would you like to continue?"); - break; - default: - g_assert_not_reached (); - break; - } - - result = g_strdup_printf (error_string, - gnome_vfs_result_to_string (error)); - } - } - return result; -} - -static int -handle_transfer_vfs_error (const GnomeVFSXferProgressInfo *progress_info, - TransferInfo *transfer_info) -{ - /* Notice that the error mode in `transfer_info' is the one we have been - * requested, but the transfer is always performed in mode - * `GNOME_VFS_XFER_ERROR_MODE_QUERY'. - */ - - int error_dialog_button_pressed; - int error_dialog_result; - char *text; - char *formatted_source_name; - char *formatted_target_name; - const char *dialog_title; - NautilusFileOperationsErrorKind error_kind; - NautilusFileOperationsErrorLocation error_location; - - switch (transfer_info->error_mode) { - case GNOME_VFS_XFER_ERROR_MODE_QUERY: - - /* transfer error, prompt the user to continue or stop */ - - formatted_source_name = NULL; - formatted_target_name = NULL; - - if (progress_info->source_name != NULL) { - formatted_source_name = format_and_ellipsize_uri_for_dialog - (progress_info->source_name); - } - - if (progress_info->target_name != NULL) { - formatted_target_name = format_and_ellipsize_uri_for_dialog - (progress_info->target_name); - } - - error_kind = ERROR_OTHER; - error_location = ERROR_LOCATION_UNKNOWN; - - /* Single out a few common error conditions for which we have - * custom-taylored error messages. - */ - if ((progress_info->vfs_status == GNOME_VFS_ERROR_READ_ONLY_FILE_SYSTEM - || progress_info->vfs_status == GNOME_VFS_ERROR_READ_ONLY) - && (transfer_info->kind == TRANSFER_DELETE - || transfer_info->kind == TRANSFER_EMPTY_TRASH)) { - error_location = ERROR_LOCATION_SOURCE_PARENT; - error_kind = ERROR_READ_ONLY; - } else if (progress_info->vfs_status == GNOME_VFS_ERROR_ACCESS_DENIED - && (transfer_info->kind == TRANSFER_DELETE - || transfer_info->kind == TRANSFER_EMPTY_TRASH)) { - error_location = ERROR_LOCATION_SOURCE_PARENT; - error_kind = ERROR_NOT_ENOUGH_PERMISSIONS; - } else if ((progress_info->vfs_status == GNOME_VFS_ERROR_READ_ONLY_FILE_SYSTEM - || progress_info->vfs_status == GNOME_VFS_ERROR_READ_ONLY) - && (transfer_info->kind == TRANSFER_MOVE - || transfer_info->kind == TRANSFER_MOVE_TO_TRASH) - && progress_info->phase != GNOME_VFS_XFER_CHECKING_DESTINATION) { - error_location = ERROR_LOCATION_SOURCE_PARENT; - error_kind = ERROR_READ_ONLY; - } else if (progress_info->vfs_status == GNOME_VFS_ERROR_ACCESS_DENIED - && transfer_info->kind == TRANSFER_MOVE - && progress_info->phase == GNOME_VFS_XFER_PHASE_OPENTARGET) { - error_location = ERROR_LOCATION_TARGET; - error_kind = ERROR_NOT_ENOUGH_PERMISSIONS; - } else if (progress_info->vfs_status == GNOME_VFS_ERROR_ACCESS_DENIED - && (transfer_info->kind == TRANSFER_MOVE - || transfer_info->kind == TRANSFER_MOVE_TO_TRASH) - && progress_info->phase != GNOME_VFS_XFER_CHECKING_DESTINATION) { - error_location = ERROR_LOCATION_SOURCE_OR_PARENT; - error_kind = ERROR_NOT_ENOUGH_PERMISSIONS; - } else if (progress_info->vfs_status == GNOME_VFS_ERROR_ACCESS_DENIED - && (transfer_info->kind == TRANSFER_COPY - || transfer_info->kind == TRANSFER_DUPLICATE) - && (progress_info->phase == GNOME_VFS_XFER_PHASE_OPENSOURCE - || progress_info->phase == GNOME_VFS_XFER_PHASE_COLLECTING - || progress_info->phase == GNOME_VFS_XFER_PHASE_INITIAL)) { - error_location = ERROR_LOCATION_SOURCE; - error_kind = ERROR_NOT_READABLE; - } else if ((progress_info->vfs_status == GNOME_VFS_ERROR_READ_ONLY_FILE_SYSTEM - || progress_info->vfs_status == GNOME_VFS_ERROR_READ_ONLY) - && progress_info->phase == GNOME_VFS_XFER_CHECKING_DESTINATION) { - error_location = ERROR_LOCATION_TARGET; - error_kind = ERROR_NOT_WRITABLE; - } else if (progress_info->vfs_status == GNOME_VFS_ERROR_ACCESS_DENIED - && progress_info->phase == GNOME_VFS_XFER_CHECKING_DESTINATION) { - error_location = ERROR_LOCATION_TARGET; - error_kind = ERROR_NOT_ENOUGH_PERMISSIONS; - } else if (progress_info->vfs_status == GNOME_VFS_ERROR_NO_SPACE) { - error_location = ERROR_LOCATION_TARGET; - error_kind = ERROR_NO_SPACE; - } - - text = build_error_string (formatted_source_name, formatted_target_name, - transfer_info->kind, - error_kind, error_location, - progress_info->vfs_status); - - switch (transfer_info->kind) { - case TRANSFER_COPY: - case TRANSFER_DUPLICATE: - dialog_title = _("Error while copying."); - break; - case TRANSFER_MOVE: - dialog_title = _("Error while moving."); - break; - case TRANSFER_LINK: - dialog_title = _("Error while linking."); - break; - case TRANSFER_DELETE: - case TRANSFER_EMPTY_TRASH: - case TRANSFER_MOVE_TO_TRASH: - dialog_title = _("Error while deleting."); - break; - default: - dialog_title = NULL; - break; - } - - if (error_location == ERROR_LOCATION_TARGET) { - /* We can't continue, just tell the user. */ - eel_run_simple_dialog (parent_for_error_dialog (transfer_info), - TRUE, text, dialog_title, _("Stop"), NULL); - error_dialog_result = GNOME_VFS_XFER_ERROR_ACTION_ABORT; - - } else if ((error_location == ERROR_LOCATION_SOURCE - || error_location == ERROR_LOCATION_SOURCE_PARENT - || error_location == ERROR_LOCATION_SOURCE_OR_PARENT) - && (error_kind == ERROR_NOT_ENOUGH_PERMISSIONS - || error_kind == ERROR_NOT_READABLE)) { - /* The error could have happened on any of the files - * in the moved/copied/deleted hierarchy, we can probably - * continue. Allow the user to skip. - */ - error_dialog_button_pressed = eel_run_simple_dialog - (parent_for_error_dialog (transfer_info), TRUE, text, - dialog_title, - _("Skip"), _("Stop"), NULL); - - switch (error_dialog_button_pressed) { - case 0: - error_dialog_result = GNOME_VFS_XFER_ERROR_ACTION_SKIP; - break; - case 1: - error_dialog_result = GNOME_VFS_XFER_ERROR_ACTION_ABORT; - break; - default: - g_assert_not_reached (); - error_dialog_result = GNOME_VFS_XFER_ERROR_ACTION_ABORT; - } - - } else { - /* Generic error, offer to retry and skip. */ - error_dialog_button_pressed = eel_run_simple_dialog - (parent_for_error_dialog (transfer_info), TRUE, text, - dialog_title, - _("Skip"), _("Retry"), _("Stop"), NULL); - - switch (error_dialog_button_pressed) { - case 0: - error_dialog_result = GNOME_VFS_XFER_ERROR_ACTION_SKIP; - break; - case 1: - error_dialog_result = GNOME_VFS_XFER_ERROR_ACTION_RETRY; - break; - case 2: - error_dialog_result = GNOME_VFS_XFER_ERROR_ACTION_ABORT; - break; - default: - g_assert_not_reached (); - error_dialog_result = GNOME_VFS_XFER_ERROR_ACTION_ABORT; - } - } - - g_free (text); - g_free (formatted_source_name); - g_free (formatted_target_name); - - return error_dialog_result; - - case GNOME_VFS_XFER_ERROR_MODE_ABORT: - default: - if (transfer_info->progress_dialog != NULL) { - nautilus_file_operations_progress_done - (transfer_info->progress_dialog); - } - return GNOME_VFS_XFER_ERROR_ACTION_ABORT; - } -} - -/* is_special_link - * - * Check and see if file is one of our special links. - * A special link ould be one of the following: - * trash, home, volume - */ -static gboolean -is_special_link (const char *uri) -{ - char *local_path; - gboolean is_special; - - local_path = gnome_vfs_get_local_path_from_uri (uri); - - /* FIXME: This should use some API to check if the file is a - * link. Normally we use the MIME type. As things stand, this - * will read files and try to parse them as XML, which could - * result in a lot of output to the console, since the XML - * parser reports errors directly there. - */ - is_special = local_path != NULL - && nautilus_link_local_get_link_type (local_path) != NAUTILUS_LINK_GENERIC; - - g_free (local_path); - - return is_special; -} - -static int -handle_transfer_overwrite (const GnomeVFSXferProgressInfo *progress_info, - TransferInfo *transfer_info) -{ - int result; - char *text, *formatted_name; - - /* Handle special case files such as Trash, mount links and home directory */ - if (is_special_link (progress_info->target_name)) { - formatted_name = extract_and_ellipsize_file_name_for_dialog - (progress_info->target_name); - - if (transfer_info->kind == TRANSFER_MOVE) { - text = g_strdup_printf (_("\"%s\" could not be moved to the new location, " - "because its name is already used for a special item that " - "cannot be removed or replaced.\n\n" - "If you still want to move \"%s\", rename it and try again."), - formatted_name, formatted_name); - } else { - text = g_strdup_printf (_("\"%s\" could not be copied to the new location, " - "because its name is already used for a special item that " - "cannot be removed or replaced.\n\n" - "If you still want to copy \"%s\", rename it and try again."), - formatted_name, formatted_name); - } - - eel_run_simple_dialog (parent_for_error_dialog (transfer_info), TRUE, text, - _("Unable to replace file."), _("OK"), NULL, NULL); - - g_free (text); - g_free (formatted_name); - - return GNOME_VFS_XFER_OVERWRITE_ACTION_SKIP; - } - - /* transfer conflict, prompt the user to replace or skip */ - formatted_name = format_and_ellipsize_uri_for_dialog (progress_info->target_name); - text = g_strdup_printf (_("File \"%s\" already exists.\n\n" - "Would you like to replace it?"), - formatted_name); - g_free (formatted_name); - - if (progress_info->duplicate_count == 1) { - /* we are going to only get one duplicate alert, don't offer - * Replace All - */ - result = eel_run_simple_dialog - (parent_for_error_dialog (transfer_info), TRUE, text, - _("Conflict while copying"), - _("Replace"), _("Skip"), NULL); - switch (result) { - case 0: - return GNOME_VFS_XFER_OVERWRITE_ACTION_REPLACE; - default: - g_assert_not_reached (); - /* fall through */ - case 1: - return GNOME_VFS_XFER_OVERWRITE_ACTION_SKIP; - } - } else { - result = eel_run_simple_dialog - (parent_for_error_dialog (transfer_info), TRUE, text, - _("Conflict while copying"), - _("Replace All"), _("Replace"), _("Skip"), NULL); - - switch (result) { - case 0: - return GNOME_VFS_XFER_OVERWRITE_ACTION_REPLACE_ALL; - case 1: - return GNOME_VFS_XFER_OVERWRITE_ACTION_REPLACE; - default: - g_assert_not_reached (); - /* fall through */ - case 2: - return GNOME_VFS_XFER_OVERWRITE_ACTION_SKIP; - } - } -} - -/* Note that we have these two separate functions with separate format - * strings for ease of localization. - */ - -static char * -get_link_name (char *name, int count) -{ - char *result; - char *unescaped_name; - char *unescaped_result; - - const char *format; - - g_assert (name != NULL); - - unescaped_name = gnome_vfs_unescape_string (name, "/"); - g_free (name); - - if (count < 1) { - g_warning ("bad count in get_link_name"); - count = 1; - } - - if (count <= 2) { - /* Handle special cases for low numbers. - * Perhaps for some locales we will need to add more. - */ - switch (count) { - default: - g_assert_not_reached (); - /* fall through */ - case 1: - /* appended to new link file */ - format = _("link to %s"); - break; - case 2: - /* appended to new link file */ - format = _("another link to %s"); - break; - } - unescaped_result = g_strdup_printf (format, unescaped_name); - - } else { - /* Handle special cases for the first few numbers of each ten. - * For locales where getting this exactly right is difficult, - * these can just be made all the same as the general case below. - */ - switch (count % 10) { - case 1: - /* Localizers: Feel free to leave out the "st" suffix - * if there's no way to do that nicely for a - * particular language. - */ - format = _("%dst link to %s"); - break; - case 2: - /* appended to new link file */ - format = _("%dnd link to %s"); - break; - case 3: - /* appended to new link file */ - format = _("%drd link to %s"); - break; - default: - /* appended to new link file */ - format = _("%dth link to %s"); - break; - } - unescaped_result = g_strdup_printf (format, count, unescaped_name); - } - - result = gnome_vfs_escape_path_string (unescaped_result); - - g_free (unescaped_name); - g_free (unescaped_result); - - return result; -} - -/* Localizers: - * Feel free to leave out the st, nd, rd and th suffix or - * make some or all of them match. - */ - -/* localizers: tag used to detect the first copy of a file */ -static const char untranslated_copy_duplicate_tag[] = N_(" (copy)"); -/* localizers: tag used to detect the second copy of a file */ -static const char untranslated_another_copy_duplicate_tag[] = N_(" (another copy)"); -/* localizers: tag used to detect the x1st copy of a file */ -static const char untranslated_st_copy_duplicate_tag[] = N_("st copy)"); -/* localizers: tag used to detect the x2nd copy of a file */ -static const char untranslated_nd_copy_duplicate_tag[] = N_("nd copy)"); -/* localizers: tag used to detect the x3rd copy of a file */ -static const char untranslated_rd_copy_duplicate_tag[] = N_("rd copy)"); -/* localizers: tag used to detect the xxth copy of a file */ -static const char untranslated_th_copy_duplicate_tag[] = N_("th copy)"); - -#define COPY_DUPLICATE_TAG _(untranslated_copy_duplicate_tag) -#define ANOTHER_COPY_DUPLICATE_TAG _(untranslated_another_copy_duplicate_tag) -#define ST_COPY_DUPLICATE_TAG _(untranslated_st_copy_duplicate_tag) -#define ND_COPY_DUPLICATE_TAG _(untranslated_nd_copy_duplicate_tag) -#define RD_COPY_DUPLICATE_TAG _(untranslated_rd_copy_duplicate_tag) -#define TH_COPY_DUPLICATE_TAG _(untranslated_th_copy_duplicate_tag) - -/* localizers: appended to first file copy */ -static const char untranslated_first_copy_duplicate_format[] = N_("%s (copy)%s"); -/* localizers: appended to second file copy */ -static const char untranslated_second_copy_duplicate_format[] = N_("%s (another copy)%s"); -/* localizers: appended to x1st file copy */ -static const char untranslated_st_copy_duplicate_format[] = N_("%s (%dst copy)%s"); -/* localizers: appended to x2nd file copy */ -static const char untranslated_nd_copy_duplicate_format[] = N_("%s (%dnd copy)%s"); -/* localizers: appended to x3rd file copy */ -static const char untranslated_rd_copy_duplicate_format[] = N_("%s (%drd copy)%s"); -/* localizers: appended to xxth file copy */ -static const char untranslated_th_copy_duplicate_format[] = N_("%s (%dth copy)%s"); - -#define FIRST_COPY_DUPLICATE_FORMAT _(untranslated_first_copy_duplicate_format) -#define SECOND_COPY_DUPLICATE_FORMAT _(untranslated_second_copy_duplicate_format) -#define ST_COPY_DUPLICATE_FORMAT _(untranslated_st_copy_duplicate_format) -#define ND_COPY_DUPLICATE_FORMAT _(untranslated_nd_copy_duplicate_format) -#define RD_COPY_DUPLICATE_FORMAT _(untranslated_rd_copy_duplicate_format) -#define TH_COPY_DUPLICATE_FORMAT _(untranslated_th_copy_duplicate_format) - -static char * -extract_string_until (const char *original, const char *until_substring) -{ - char *result; - - g_assert ((int) strlen (original) >= until_substring - original); - g_assert (until_substring - original >= 0); - - result = g_malloc (until_substring - original + 1); - strncpy (result, original, until_substring - original); - result[until_substring - original] = '\0'; - - return result; -} - -/* Dismantle a file name, separating the base name, the file suffix and removing any - * (xxxcopy), etc. string. Figure out the count that corresponds to the given - * (xxxcopy) substring. - */ -static void -parse_previous_duplicate_name (const char *name, - char **name_base, - const char **suffix, - int *count) -{ - const char *tag; - - g_assert (name[0] != '\0'); - - *suffix = strrchr (name + 1, '.'); - if (*suffix == NULL || (*suffix)[1] == '\0') { - /* no suffix */ - *suffix = ""; - } - - tag = strstr (name, COPY_DUPLICATE_TAG); - if (tag != NULL) { - if (tag > *suffix) { - /* handle case "foo. (copy)" */ - *suffix = ""; - } - *name_base = extract_string_until (name, tag); - *count = 1; - return; - } - - - tag = strstr (name, ANOTHER_COPY_DUPLICATE_TAG); - if (tag != NULL) { - if (tag > *suffix) { - /* handle case "foo. (another copy)" */ - *suffix = ""; - } - *name_base = extract_string_until (name, tag); - *count = 2; - return; - } - - - /* Check to see if we got one of st, nd, rd, th. */ - - tag = strstr (name, ST_COPY_DUPLICATE_TAG); - if (tag == NULL) { - tag = strstr (name, ND_COPY_DUPLICATE_TAG); - } - if (tag == NULL) { - tag = strstr (name, RD_COPY_DUPLICATE_TAG); - } - if (tag == NULL) { - tag = strstr (name, TH_COPY_DUPLICATE_TAG); - } - - /* If we got one of st, nd, rd, th, fish out the duplicate number. */ - if (tag != NULL) { - /* localizers: opening parentheses to match the "th copy)" string */ - tag = strstr (name, _(" (")); - if (tag != NULL) { - if (tag > *suffix) { - /* handle case "foo. (22nd copy)" */ - *suffix = ""; - } - *name_base = extract_string_until (name, tag); - /* localizers: opening parentheses of the "th copy)" string */ - if (sscanf (tag, _(" (%d"), count) == 1) { - if (*count < 1 || *count > 1000000) { - /* keep the count within a reasonable range */ - *count = 0; - } - return; - } - *count = 0; - return; - } - } - - - *count = 0; - if (**suffix != '\0') { - *name_base = extract_string_until (name, *suffix); - } else { - *name_base = g_strdup (name); - } -} - -static char * -make_next_duplicate_name (const char *base, const char *suffix, int count) -{ - const char *format; - char *result; - - - if (count < 1) { - g_warning ("bad count %d in get_duplicate_name", count); - count = 1; - } - - if (count <= 2) { - /* Handle special cases for low numbers. - * Perhaps for some locales we will need to add more. - */ - switch (count) { - default: - g_assert_not_reached (); - /* fall through */ - case 1: - format = FIRST_COPY_DUPLICATE_FORMAT; - break; - case 2: - format = SECOND_COPY_DUPLICATE_FORMAT; - break; - - } - result = g_strdup_printf (format, base, suffix); - } else { - - /* Handle special cases for the first few numbers of each ten. - * For locales where getting this exactly right is difficult, - * these can just be made all the same as the general case below. - */ - switch (count % 10) { - case 1: - format = ST_COPY_DUPLICATE_FORMAT; - break; - case 2: - format = ND_COPY_DUPLICATE_FORMAT; - break; - case 3: - format = RD_COPY_DUPLICATE_FORMAT; - break; - default: - /* The general case. */ - format = TH_COPY_DUPLICATE_FORMAT; - break; - } - - result = g_strdup_printf (format, base, count, suffix); - } - - return result; -} - -static char * -get_duplicate_name (const char *name, int count_increment) -{ - char *result; - char *name_base; - const char *suffix; - int count; - - parse_previous_duplicate_name (name, &name_base, &suffix, &count); - result = make_next_duplicate_name (name_base, suffix, count + count_increment); - - g_free (name_base); - - return result; -} - -static char * -get_next_duplicate_name (char *name, int count_increment) -{ - char *unescaped_name; - char *unescaped_result; - char *result; - - unescaped_name = gnome_vfs_unescape_string (name, "/"); - g_free (name); - - unescaped_result = get_duplicate_name (unescaped_name, count_increment); - g_free (unescaped_name); - - result = gnome_vfs_escape_path_string (unescaped_result); - g_free (unescaped_result); - - return result; -} - -static int -handle_transfer_duplicate (GnomeVFSXferProgressInfo *progress_info, - TransferInfo *transfer_info) -{ - switch (transfer_info->kind) { - case TRANSFER_LINK: - progress_info->duplicate_name = get_link_name - (progress_info->duplicate_name, - progress_info->duplicate_count); - break; - - case TRANSFER_COPY: - case TRANSFER_MOVE_TO_TRASH: - progress_info->duplicate_name = get_next_duplicate_name - (progress_info->duplicate_name, - progress_info->duplicate_count); - break; - - default: - /* For all other cases we use the name as-is. */ - } - - return GNOME_VFS_XFER_ERROR_ACTION_SKIP; -} - -static int -update_transfer_callback (GnomeVFSAsyncHandle *handle, - GnomeVFSXferProgressInfo *progress_info, - gpointer data) -{ - TransferInfo *transfer_info; - - transfer_info = (TransferInfo *) data; - - switch (progress_info->status) { - case GNOME_VFS_XFER_PROGRESS_STATUS_OK: - return handle_transfer_ok (progress_info, transfer_info); - case GNOME_VFS_XFER_PROGRESS_STATUS_VFSERROR: - return handle_transfer_vfs_error (progress_info, transfer_info); - case GNOME_VFS_XFER_PROGRESS_STATUS_OVERWRITE: - return handle_transfer_overwrite (progress_info, transfer_info); - case GNOME_VFS_XFER_PROGRESS_STATUS_DUPLICATE: - return handle_transfer_duplicate (progress_info, transfer_info); - default: - g_warning (_("Unknown GnomeVFSXferProgressStatus %d"), - progress_info->status); - return 0; - } -} - -static void -apply_one_position (IconPositionIterator *position_iterator, - const char *source_name, - const char *target_name) -{ - GdkPoint point; - - if (icon_position_iterator_get_next (position_iterator, source_name, &point)) { - nautilus_file_changes_queue_schedule_position_set (target_name, point); - } else { - nautilus_file_changes_queue_schedule_position_remove (target_name); - } -} - -typedef struct { - GHashTable *debuting_uris; - IconPositionIterator *iterator; -} SyncTransferInfo; - -/* Low-level callback, called for every copy engine operation. - * Generates notifications about new, deleted and moved files. - */ -static int -sync_transfer_callback (GnomeVFSXferProgressInfo *progress_info, gpointer data) -{ - GHashTable *debuting_uris; - IconPositionIterator *position_iterator; - gboolean really_moved; - - if (data != NULL) { - debuting_uris = ((SyncTransferInfo *) data)->debuting_uris; - position_iterator = ((SyncTransferInfo *) data)->iterator; - } else { - debuting_uris = NULL; - position_iterator = NULL; - } - - if (progress_info->status == GNOME_VFS_XFER_PROGRESS_STATUS_OK) { - switch (progress_info->phase) { - case GNOME_VFS_XFER_PHASE_OPENTARGET: - if (progress_info->top_level_item) { - /* this is one of the selected copied or moved items -- we need - * to make sure it's metadata gets copied over - */ - if (progress_info->source_name == NULL) { - /* remove any old metadata */ - nautilus_file_changes_queue_schedule_metadata_remove - (progress_info->target_name); - } else { - nautilus_file_changes_queue_schedule_metadata_copy - (progress_info->source_name, progress_info->target_name); - - apply_one_position (position_iterator, - progress_info->source_name, - progress_info->target_name); - } - if (debuting_uris != NULL) { - g_hash_table_insert (debuting_uris, - g_strdup (progress_info->target_name), - GINT_TO_POINTER (TRUE)); - } - } - nautilus_file_changes_queue_file_added (progress_info->target_name); - break; - - case GNOME_VFS_XFER_PHASE_MOVING: - g_assert (progress_info->source_name != NULL); - - /* If the source and target are the same, that - * means we "moved" something in place. No - * actual change happened, so we really don't - * want to send out any change notification, - * but we do want to select the files as - * "newly moved here" so we put them into the - * debuting_uris set. - */ - really_moved = strcmp (progress_info->source_name, - progress_info->target_name) != 0; - - if (progress_info->top_level_item) { - if (really_moved) { - nautilus_file_changes_queue_schedule_metadata_move - (progress_info->source_name, progress_info->target_name); - - apply_one_position (position_iterator, - progress_info->source_name, - progress_info->target_name); - } - - if (debuting_uris != NULL) { - g_hash_table_insert (debuting_uris, - g_strdup (progress_info->target_name), - GINT_TO_POINTER (really_moved)); - } - } - if (really_moved) { - nautilus_file_changes_queue_file_moved (progress_info->source_name, - progress_info->target_name); - } - break; - - case GNOME_VFS_XFER_PHASE_DELETESOURCE: - g_assert (progress_info->source_name != NULL); - if (progress_info->top_level_item) { - nautilus_file_changes_queue_schedule_metadata_remove - (progress_info->source_name); - } - nautilus_file_changes_queue_file_removed (progress_info->source_name); - break; - - case GNOME_VFS_XFER_PHASE_COMPLETED: - /* done, clean up */ - icon_position_iterator_free (position_iterator); - /* SyncXferInfo doesn't own the debuting_uris hash table - don't free it here. - */ - g_free (data); - break; - - default: - break; - } - } - return 1; -} - -static gboolean -check_target_directory_is_or_in_trash (GnomeVFSURI *trash_dir_uri, GnomeVFSURI *target_dir_uri) -{ - g_assert (target_dir_uri != NULL); - - if (trash_dir_uri == NULL) { - return FALSE; - } - - return gnome_vfs_uri_equal (trash_dir_uri, target_dir_uri) - || gnome_vfs_uri_is_parent (trash_dir_uri, target_dir_uri, TRUE); -} - - -static GnomeVFSURI * -append_basename (const GnomeVFSURI *target_directory, - const GnomeVFSURI *source_directory) -{ - const char *file_name; - - file_name = gnome_vfs_uri_extract_short_name (source_directory); - if (file_name != NULL) { - return gnome_vfs_uri_append_file_name (target_directory, file_name); - } - - return gnome_vfs_uri_dup (target_directory); -} - -static gboolean -vfs_uri_is_special_link (GnomeVFSURI *vfs_uri) -{ - char *uri; - gboolean is_special; - - uri = gnome_vfs_uri_to_string (vfs_uri, GNOME_VFS_URI_HIDE_NONE); - is_special = is_special_link (uri); - g_free (uri); - - return is_special; -} - -void -nautilus_file_operations_copy_move (const GList *item_uris, - GArray *relative_item_points, - const char *target_dir, - GdkDragAction copy_action, - GtkWidget *parent_view, - void (*done_callback) (GHashTable *debuting_uris, gpointer data), - gpointer done_callback_data) -{ - const GList *p; - GnomeVFSXferOptions move_options; - GList *source_uri_list, *target_uri_list; - GnomeVFSURI *source_uri, *target_uri; - GnomeVFSURI *source_dir_uri, *target_dir_uri; - GnomeVFSURI *trash_dir_uri; - GnomeVFSURI *uri; - - TransferInfo *transfer_info; - SyncTransferInfo *sync_transfer_info; - GnomeVFSResult result; - gboolean target_is_trash; - gboolean is_desktop_trash_link; - gboolean duplicate; - gboolean all_local; - - IconPositionIterator *icon_position_iterator; - - g_assert (item_uris != NULL); - - target_dir_uri = NULL; - trash_dir_uri = NULL; - result = GNOME_VFS_OK; - - target_is_trash = FALSE; - if (target_dir != NULL) { - if (eel_uri_is_trash (target_dir)) { - target_is_trash = TRUE; - } else { - target_dir_uri = gnome_vfs_uri_new (target_dir); - } - } - - /* Build the source and target URI lists and figure out if all - * the files are on the same disk. - */ - source_uri_list = NULL; - target_uri_list = NULL; - all_local = TRUE; - duplicate = copy_action != GDK_ACTION_MOVE; - for (p = item_uris; p != NULL; p = p->next) { - /* Filter out special Nautilus link files */ - /* FIXME bugzilla.eazel.com 5295: - * This is surprising behavior -- the user drags the Trash icon (say) - * to a folder, releases it, and nothing whatsoever happens. Don't we want - * a dialog in this case? - */ - if (is_special_link ((const char *) p->data)) { - continue; - } - - source_uri = gnome_vfs_uri_new ((const char *) p->data); - source_dir_uri = gnome_vfs_uri_get_parent (source_uri); - target_uri = NULL; - if (target_dir != NULL) { - if (target_is_trash) { - gnome_vfs_find_directory (source_uri, GNOME_VFS_DIRECTORY_KIND_TRASH, - &target_dir_uri, FALSE, FALSE, 0777); - } - if (target_dir_uri != NULL) { - target_uri = append_basename (target_dir_uri, source_uri); - } - } else { - /* duplication */ - target_uri = gnome_vfs_uri_ref (source_uri); - if (target_dir_uri == NULL) { - target_dir_uri = gnome_vfs_uri_ref (source_dir_uri); - } - } - - if (target_uri != NULL) { - g_assert (target_dir_uri != NULL); - - target_uri_list = g_list_prepend (target_uri_list, target_uri); - source_uri_list = g_list_prepend (source_uri_list, source_uri); - - if (all_local && (!gnome_vfs_uri_is_local (source_uri) - || !gnome_vfs_uri_is_local (target_uri))) { - all_local = FALSE; - } - - if (duplicate - && !gnome_vfs_uri_equal (source_dir_uri, target_dir_uri)) { - duplicate = FALSE; - } - } - gnome_vfs_uri_unref (source_dir_uri); - } - - if (target_is_trash) { - /* Make sure new trash directories that we don't show yet get integrated. */ - nautilus_trash_monitor_add_new_trash_directories (); - } - - move_options = GNOME_VFS_XFER_RECURSIVE; - if (duplicate) { - /* Copy operation, parents match -> duplicate - * operation. Ask gnome-vfs to generate unique names - * for target files. - */ - move_options |= GNOME_VFS_XFER_USE_UNIQUE_NAMES; - } - - /* List may be NULL if we filtered all items out */ - if (source_uri_list == NULL) { - if (target_dir_uri != NULL) { - gnome_vfs_uri_unref (target_dir_uri); - } - if (target_uri_list != NULL) { - gnome_vfs_uri_list_free (target_uri_list); - } - return; - } - - source_uri_list = g_list_reverse (source_uri_list); - target_uri_list = g_list_reverse (target_uri_list); - - - if (copy_action == GDK_ACTION_MOVE) { - move_options |= GNOME_VFS_XFER_REMOVESOURCE; - } else if (copy_action == GDK_ACTION_LINK) { - move_options |= GNOME_VFS_XFER_LINK_ITEMS; - } - - /* set up the copy/move parameters */ - transfer_info = transfer_info_new (parent_view); - if (relative_item_points != NULL && relative_item_points->len > 0) { - /* FIXME: we probably don't need an icon_position_iterator - * here at all. - */ - icon_position_iterator = icon_position_iterator_new - (relative_item_points, item_uris); - } else { - icon_position_iterator = NULL; - } - - if (target_is_trash && (move_options & GNOME_VFS_XFER_REMOVESOURCE) != 0) { - /* when moving to trash, handle name conflicts automatically */ - move_options |= GNOME_VFS_XFER_USE_UNIQUE_NAMES; - /* localizers: progress dialog title */ - transfer_info->operation_title = _("Moving files to the Trash"); - /* localizers: label prepended to the progress count */ - transfer_info->action_label =_("Files thrown out:"); - /* localizers: label prepended to the name of the current file moved */ - transfer_info->progress_verb =_("Moving"); - transfer_info->preparation_name =_("Preparing to Move to Trash..."); - - transfer_info->kind = TRANSFER_MOVE_TO_TRASH; - - /* Do an arbitrary guess that an operation will take very little - * time and the progress shouldn't be shown. - */ - transfer_info->show_progress_dialog = - !all_local || g_list_length ((GList *) item_uris) > 20; - } else if ((move_options & GNOME_VFS_XFER_REMOVESOURCE) != 0) { - /* localizers: progress dialog title */ - transfer_info->operation_title = _("Moving files"); - /* localizers: label prepended to the progress count */ - transfer_info->action_label =_("Files moved:"); - /* localizers: label prepended to the name of the current file moved */ - transfer_info->progress_verb =_("Moving"); - transfer_info->preparation_name =_("Preparing To Move..."); - transfer_info->cleanup_name = _("Finishing Move..."); - - transfer_info->kind = TRANSFER_MOVE; - - /* Do an arbitrary guess that an operation will take very little - * time and the progress shouldn't be shown. - */ - transfer_info->show_progress_dialog = - !all_local || g_list_length ((GList *) item_uris) > 20; - } else if ((move_options & GNOME_VFS_XFER_LINK_ITEMS) != 0) { - /* when creating links, handle name conflicts automatically */ - move_options |= GNOME_VFS_XFER_USE_UNIQUE_NAMES; - /* localizers: progress dialog title */ - transfer_info->operation_title = _("Creating links to files"); - /* localizers: label prepended to the progress count */ - transfer_info->action_label =_("Files linked:"); - /* localizers: label prepended to the name of the current file linked */ - transfer_info->progress_verb =_("Linking"); - transfer_info->preparation_name = _("Preparing to Create Links..."); - transfer_info->cleanup_name = _("Finishing Creating Links..."); - - transfer_info->kind = TRANSFER_LINK; - transfer_info->show_progress_dialog = - g_list_length ((GList *)item_uris) > 20; - } else { - /* localizers: progress dialog title */ - transfer_info->operation_title = _("Copying files"); - /* localizers: label prepended to the progress count */ - transfer_info->action_label =_("Files copied:"); - /* localizers: label prepended to the name of the current file copied */ - transfer_info->progress_verb =_("Copying"); - transfer_info->preparation_name =_("Preparing To Copy..."); - transfer_info->cleanup_name = ""; - - transfer_info->kind = TRANSFER_COPY; - /* always show progress during copy */ - transfer_info->show_progress_dialog = TRUE; - } - - /* we'll need to check for copy into Trash and for moving/copying the Trash itself */ - gnome_vfs_find_directory (target_dir_uri, GNOME_VFS_DIRECTORY_KIND_TRASH, - &trash_dir_uri, FALSE, FALSE, 0777); - - if ((move_options & GNOME_VFS_XFER_REMOVESOURCE) == 0) { - /* don't allow copying into Trash */ - if (check_target_directory_is_or_in_trash (trash_dir_uri, target_dir_uri)) { - eel_run_simple_dialog - (parent_view, - FALSE, - _("You cannot copy items into the Trash."), - _("Can't Copy to Trash"), - GNOME_STOCK_BUTTON_OK, NULL, NULL); - result = GNOME_VFS_ERROR_NOT_PERMITTED; - } - } - - if (result == GNOME_VFS_OK) { - for (p = source_uri_list; p != NULL; p = p->next) { - uri = (GnomeVFSURI *)p->data; - - /* Check that a trash folder is not being moved/copied (link is OK). */ - if (trash_dir_uri != NULL - && ((move_options & GNOME_VFS_XFER_LINK_ITEMS) == 0) - && gnome_vfs_uri_equal (uri, trash_dir_uri)) { - /* Distinguish Trash file on desktop from other trash folders for - * message purposes. - */ - /* FIXME: is_special_link finds more than just trash links, - * so these messages are wrong. - */ - is_desktop_trash_link = vfs_uri_is_special_link (uri); - - eel_run_simple_dialog - (parent_view, - FALSE, - ((move_options & GNOME_VFS_XFER_REMOVESOURCE) != 0) - ? (is_desktop_trash_link - ? _("The Trash must remain on the desktop.") - : _("You cannot move this trash folder.")) - : (is_desktop_trash_link - ? _("You cannot copy the Trash.") - : _("You cannot copy this trash folder.")), - ((move_options & GNOME_VFS_XFER_REMOVESOURCE) != 0) - ? _("Can't Change Trash Location") - : _("Can't Copy Trash"), - GNOME_STOCK_BUTTON_OK, NULL, NULL); - - result = GNOME_VFS_ERROR_NOT_PERMITTED; - break; - } - - /* FIXME: - * We should not have the case where a folder containing trash is moved into - * the trash give a generic "cannot move into itself" message, rather, - * we should have a trash specific message here. - */ - - /* Don't allow recursive move/copy into itself. - * (We would get a file system error if we proceeded but it is nicer to - * detect and report it at this level) */ - if ((move_options & GNOME_VFS_XFER_LINK_ITEMS) == 0 - && (gnome_vfs_uri_equal (uri, target_dir_uri) - || gnome_vfs_uri_is_parent (uri, target_dir_uri, TRUE))) { - eel_run_simple_dialog - (parent_view, - FALSE, - ((move_options & GNOME_VFS_XFER_REMOVESOURCE) != 0) - ? _("You cannot move a folder into itself.") - : _("You cannot copy a folder into itself."), - ((move_options & GNOME_VFS_XFER_REMOVESOURCE) != 0) - ? _("Can't Move Into Self") - : _("Can't Copy Into Self"), - GNOME_STOCK_BUTTON_OK, NULL, NULL); - - result = GNOME_VFS_ERROR_NOT_PERMITTED; - break; - } - if ((move_options & GNOME_VFS_XFER_REMOVESOURCE) == 0 - && (move_options & GNOME_VFS_XFER_USE_UNIQUE_NAMES) == 0 - && gnome_vfs_uri_is_parent (target_dir_uri, uri, FALSE)) { - eel_run_simple_dialog - (parent_view, - FALSE, - _("You cannot copy a file over itself."), - _("Can't Copy Over Self"), - GNOME_STOCK_BUTTON_OK, NULL, NULL); - - result = GNOME_VFS_ERROR_NOT_PERMITTED; - break; - } - } - } - - transfer_info->error_mode = GNOME_VFS_XFER_ERROR_MODE_QUERY; - transfer_info->overwrite_mode = GNOME_VFS_XFER_OVERWRITE_MODE_QUERY; - transfer_info->done_callback = done_callback; - transfer_info->done_callback_data = done_callback_data; - transfer_info->debuting_uris = g_hash_table_new (g_str_hash, g_str_equal); - - sync_transfer_info = g_new (SyncTransferInfo, 1); - sync_transfer_info->iterator = icon_position_iterator; - sync_transfer_info->debuting_uris = transfer_info->debuting_uris; - - if (result == GNOME_VFS_OK) { - gnome_vfs_async_xfer (&transfer_info->handle, source_uri_list, target_uri_list, - move_options, GNOME_VFS_XFER_ERROR_MODE_QUERY, - GNOME_VFS_XFER_OVERWRITE_MODE_QUERY, - update_transfer_callback, transfer_info, - sync_transfer_callback, sync_transfer_info); - } - - gnome_vfs_uri_list_free (source_uri_list); - gnome_vfs_uri_list_free (target_uri_list); - if (trash_dir_uri != NULL) { - gnome_vfs_uri_unref (trash_dir_uri); - } - gnome_vfs_uri_unref (target_dir_uri); -} - -typedef struct { - GnomeVFSAsyncHandle *handle; - void (* done_callback)(const char *new_folder_uri, gpointer data); - gpointer data; - GtkWidget *parent_view; -} NewFolderTransferState; - -static int -handle_new_folder_vfs_error (const GnomeVFSXferProgressInfo *progress_info, NewFolderTransferState *state) -{ - const char *error_string; - char *error_string_to_free; - - error_string_to_free = NULL; - - if (progress_info->vfs_status == GNOME_VFS_ERROR_ACCESS_DENIED) { - error_string = _("Error creating new folder.\n\n" - "You do not have permissions to write to the destination."); - } else if (progress_info->vfs_status == GNOME_VFS_ERROR_NO_SPACE) { - error_string = _("Error creating new folder.\n\n" - "There is no space on the destination."); - } else { - error_string = g_strdup_printf (_("Error \"%s\" creating new folder."), - gnome_vfs_result_to_string(progress_info->vfs_status)); - } - - eel_show_error_dialog (error_string, _("Error creating new folder"), - GTK_WINDOW (state->parent_view)); - - g_free (error_string_to_free); - - return GNOME_VFS_XFER_ERROR_ACTION_ABORT; -} - -static int -new_folder_transfer_callback (GnomeVFSAsyncHandle *handle, - GnomeVFSXferProgressInfo *progress_info, - gpointer data) -{ - NewFolderTransferState *state; - char *temp_string; - - state = (NewFolderTransferState *) data; - - switch (progress_info->phase) { - - case GNOME_VFS_XFER_PHASE_COMPLETED: - eel_nullify_cancel (&state->parent_view); - g_free (state); - return 0; - - default: - switch (progress_info->status) { - case GNOME_VFS_XFER_PROGRESS_STATUS_OK: - nautilus_file_changes_consume_changes (TRUE); - (* state->done_callback) (progress_info->target_name, state->data); - return 0; - - case GNOME_VFS_XFER_PROGRESS_STATUS_DUPLICATE: - - temp_string = progress_info->duplicate_name; - - if (progress_info->vfs_status == GNOME_VFS_ERROR_NAME_TOO_LONG) { - /* special case an 8.3 file system */ - progress_info->duplicate_name = g_strndup (temp_string, 8); - progress_info->duplicate_name[8] = '\0'; - g_free (temp_string); - temp_string = progress_info->duplicate_name; - progress_info->duplicate_name = g_strdup_printf - ("%s.%d", - progress_info->duplicate_name, - progress_info->duplicate_count); - } else { - progress_info->duplicate_name = g_strdup_printf - ("%s%%20%d", - progress_info->duplicate_name, - progress_info->duplicate_count); - } - g_free (temp_string); - return GNOME_VFS_XFER_ERROR_ACTION_SKIP; - - case GNOME_VFS_XFER_PROGRESS_STATUS_VFSERROR: - return handle_new_folder_vfs_error (progress_info, state); - - - - default: - g_warning (_("Unknown GnomeVFSXferProgressStatus %d"), - progress_info->status); - return 0; - } - } -} - -void -nautilus_file_operations_new_folder (GtkWidget *parent_view, - const char *parent_dir, - void (*done_callback) (const char *, gpointer), - gpointer data) -{ - GList *target_uri_list; - GnomeVFSURI *uri, *parent_uri; - NewFolderTransferState *state; - - state = g_new (NewFolderTransferState, 1); - state->done_callback = done_callback; - state->data = data; - state->parent_view = parent_view; - eel_nullify_when_destroyed (&state->parent_view); - - /* pass in the target directory and the new folder name as a destination URI */ - parent_uri = gnome_vfs_uri_new (parent_dir); - /* localizers: the initial name of a new folder */ - uri = gnome_vfs_uri_append_file_name (parent_uri, _("untitled folder")); - target_uri_list = g_list_append (NULL, uri); - - gnome_vfs_async_xfer (&state->handle, NULL, target_uri_list, - GNOME_VFS_XFER_NEW_UNIQUE_DIRECTORY, - GNOME_VFS_XFER_ERROR_MODE_QUERY, - GNOME_VFS_XFER_OVERWRITE_MODE_QUERY, - new_folder_transfer_callback, state, - sync_transfer_callback, NULL); - - gnome_vfs_uri_list_free (target_uri_list); - gnome_vfs_uri_unref (parent_uri); -} - -void -nautilus_file_operations_delete (const GList *item_uris, - GtkWidget *parent_view) -{ - GList *uri_list; - const GList *p; - TransferInfo *transfer_info; - - uri_list = NULL; - for (p = item_uris; p != NULL; p = p->next) { - uri_list = g_list_prepend (uri_list, - gnome_vfs_uri_new ((const char *) p->data)); - } - uri_list = g_list_reverse (uri_list); - - transfer_info = transfer_info_new (parent_view); - transfer_info->show_progress_dialog = TRUE; - - /* localizers: progress dialog title */ - transfer_info->operation_title = _("Deleting files"); - /* localizers: label prepended to the progress count */ - transfer_info->action_label =_("Files deleted:"); - /* localizers: label prepended to the name of the current file deleted */ - transfer_info->progress_verb =_("Deleting"); - transfer_info->preparation_name =_("Preparing to Delete files..."); - transfer_info->cleanup_name =""; - - transfer_info->error_mode = GNOME_VFS_XFER_ERROR_MODE_QUERY; - transfer_info->overwrite_mode = GNOME_VFS_XFER_OVERWRITE_MODE_REPLACE; - transfer_info->kind = TRANSFER_DELETE; - - gnome_vfs_async_xfer (&transfer_info->handle, uri_list, NULL, - GNOME_VFS_XFER_DELETE_ITEMS | GNOME_VFS_XFER_RECURSIVE, - GNOME_VFS_XFER_ERROR_MODE_QUERY, - GNOME_VFS_XFER_OVERWRITE_MODE_REPLACE, - update_transfer_callback, transfer_info, - sync_transfer_callback, NULL); - - gnome_vfs_uri_list_free (uri_list); -} - -static void -do_empty_trash (GtkWidget *parent_view) -{ - TransferInfo *transfer_info; - GList *trash_dir_list; - - trash_dir_list = nautilus_trash_monitor_get_trash_directories (); - if (trash_dir_list != NULL) { - /* set up the move parameters */ - transfer_info = transfer_info_new (parent_view); - transfer_info->show_progress_dialog = TRUE; - - /* localizers: progress dialog title */ - transfer_info->operation_title = _("Emptying the Trash"); - /* localizers: label prepended to the progress count */ - transfer_info->action_label =_("Files deleted:"); - /* localizers: label prepended to the name of the current file deleted */ - transfer_info->progress_verb =_("Deleting"); - transfer_info->preparation_name =_("Preparing to Empty the Trash..."); - transfer_info->cleanup_name =""; - transfer_info->error_mode = GNOME_VFS_XFER_ERROR_MODE_QUERY; - transfer_info->overwrite_mode = GNOME_VFS_XFER_OVERWRITE_MODE_REPLACE; - transfer_info->kind = TRANSFER_EMPTY_TRASH; - - gnome_vfs_async_xfer (&transfer_info->handle, trash_dir_list, NULL, - GNOME_VFS_XFER_EMPTY_DIRECTORIES, - GNOME_VFS_XFER_ERROR_MODE_QUERY, - GNOME_VFS_XFER_OVERWRITE_MODE_REPLACE, - update_transfer_callback, transfer_info, - sync_transfer_callback, NULL); - } - - gnome_vfs_uri_list_free (trash_dir_list); -} - -static gboolean -confirm_empty_trash (GtkWidget *parent_view) -{ - GnomeDialog *dialog; - GtkWindow *parent_window; - - /* Just Say Yes if the preference says not to confirm. */ - if (!nautilus_preferences_get_boolean (NAUTILUS_PREFERENCES_CONFIRM_TRASH)) { - return TRUE; - } - - parent_window = GTK_WINDOW (gtk_widget_get_toplevel (parent_view)); - - dialog = eel_show_yes_no_dialog ( - _("Are you sure you want to permanently delete " - "all of the items in the Trash?"), - _("Delete Trash Contents?"), - _("Empty"), - GNOME_STOCK_BUTTON_CANCEL, - parent_window); - - gnome_dialog_set_default (dialog, GNOME_CANCEL); - - return gnome_dialog_run (dialog) == GNOME_OK; -} - -void -nautilus_file_operations_empty_trash (GtkWidget *parent_view) -{ - g_return_if_fail (parent_view != NULL); - - /* - * I chose to use a modal confirmation dialog here. - * If we used a modeless dialog, we'd have to do work to - * make sure that no more than one appears on screen at - * a time. That one probably couldn't be parented, because - * otherwise you'd get into weird layer-shifting problems - * selecting "Empty Trash" from one window when there was - * already a modeless "Empty Trash" dialog parented on a - * different window. And if the dialog were not parented, it - * might show up in some weird place since window manager - * placement is unreliable (i.e., sucks). So modal it is. - */ - if (confirm_empty_trash (parent_view)) { - do_empty_trash (parent_view); - } -} - -#if !defined (NAUTILUS_OMIT_SELF_CHECK) - -void -nautilus_self_check_file_operations (void) -{ - /* test the next duplicate name generator */ - EEL_CHECK_STRING_RESULT (get_duplicate_name (_(" (copy)"), 1), _(" (another copy)")); - EEL_CHECK_STRING_RESULT (get_duplicate_name (_("foo"), 1), _("foo (copy)")); - EEL_CHECK_STRING_RESULT (get_duplicate_name (_(".bashrc"), 1), _(".bashrc (copy)")); - EEL_CHECK_STRING_RESULT (get_duplicate_name (_(".foo.txt"), 1), _(".foo (copy).txt")); - EEL_CHECK_STRING_RESULT (get_duplicate_name (_("foo foo"), 1), _("foo foo (copy)")); - EEL_CHECK_STRING_RESULT (get_duplicate_name (_("foo.txt"), 1), _("foo (copy).txt")); - EEL_CHECK_STRING_RESULT (get_duplicate_name (_("foo foo.txt"), 1), _("foo foo (copy).txt")); - EEL_CHECK_STRING_RESULT (get_duplicate_name (_("foo foo.txt txt"), 1), _("foo foo (copy).txt txt")); - EEL_CHECK_STRING_RESULT (get_duplicate_name (_("foo...txt"), 1), _("foo.. (copy).txt")); - EEL_CHECK_STRING_RESULT (get_duplicate_name (_("foo..."), 1), _("foo... (copy)")); - EEL_CHECK_STRING_RESULT (get_duplicate_name (_("foo. (copy)"), 1), _("foo. (another copy)")); - EEL_CHECK_STRING_RESULT (get_duplicate_name (_("foo (copy)"), 1), _("foo (another copy)")); - EEL_CHECK_STRING_RESULT (get_duplicate_name (_("foo (copy).txt"), 1), _("foo (another copy).txt")); - EEL_CHECK_STRING_RESULT (get_duplicate_name (_("foo (another copy)"), 1), _("foo (3rd copy)")); - EEL_CHECK_STRING_RESULT (get_duplicate_name (_("foo (another copy).txt"), 1), _("foo (3rd copy).txt")); - EEL_CHECK_STRING_RESULT (get_duplicate_name (_("foo foo (another copy).txt"), 1), _("foo foo (3rd copy).txt")); - EEL_CHECK_STRING_RESULT (get_duplicate_name (_("foo (13th copy)"), 1), _("foo (14th copy)")); - EEL_CHECK_STRING_RESULT (get_duplicate_name (_("foo (13th copy).txt"), 1), _("foo (14th copy).txt")); - EEL_CHECK_STRING_RESULT (get_duplicate_name (_("foo (21st copy)"), 1), _("foo (22nd copy)")); - EEL_CHECK_STRING_RESULT (get_duplicate_name (_("foo (21st copy).txt"), 1), _("foo (22nd copy).txt")); - EEL_CHECK_STRING_RESULT (get_duplicate_name (_("foo (22nd copy)"), 1), _("foo (23rd copy)")); - EEL_CHECK_STRING_RESULT (get_duplicate_name (_("foo (22nd copy).txt"), 1), _("foo (23rd copy).txt")); - EEL_CHECK_STRING_RESULT (get_duplicate_name (_("foo (23rd copy)"), 1), _("foo (24th copy)")); - EEL_CHECK_STRING_RESULT (get_duplicate_name (_("foo (23rd copy).txt"), 1), _("foo (24th copy).txt")); - EEL_CHECK_STRING_RESULT (get_duplicate_name (_("foo (24th copy)"), 1), _("foo (25th copy)")); - EEL_CHECK_STRING_RESULT (get_duplicate_name (_("foo (24th copy).txt"), 1), _("foo (25th copy).txt")); - EEL_CHECK_STRING_RESULT (get_duplicate_name (_("foo foo (24th copy)"), 1), _("foo foo (25th copy)")); - EEL_CHECK_STRING_RESULT (get_duplicate_name (_("foo foo (24th copy).txt"), 1), _("foo foo (25th copy).txt")); - EEL_CHECK_STRING_RESULT (get_duplicate_name (_("foo foo (100000000000000th copy).txt"), 1), _("foo foo (copy).txt")); - - /* FIXME bugzilla.eazel.com 7701: These are wrong. */ - EEL_CHECK_STRING_RESULT (get_duplicate_name (_("foo (10th copy)"), 1), _("foo (11st copy)")); - EEL_CHECK_STRING_RESULT (get_duplicate_name (_("foo (10th copy).txt"), 1), _("foo (11st copy).txt")); - EEL_CHECK_STRING_RESULT (get_duplicate_name (_("foo (11th copy)"), 1), _("foo (12nd copy)")); - EEL_CHECK_STRING_RESULT (get_duplicate_name (_("foo (11th copy).txt"), 1), _("foo (12nd copy).txt")); - EEL_CHECK_STRING_RESULT (get_duplicate_name (_("foo (12th copy)"), 1), _("foo (13rd copy)")); - EEL_CHECK_STRING_RESULT (get_duplicate_name (_("foo (12th copy).txt"), 1), _("foo (13rd copy).txt")); -} - -#endif diff --git a/libnautilus-extensions/nautilus-file-operations.h b/libnautilus-extensions/nautilus-file-operations.h deleted file mode 100644 index 3fe6918ca..000000000 --- a/libnautilus-extensions/nautilus-file-operations.h +++ /dev/null @@ -1,55 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ - -/* nautilus-file-operations: execute file operations. - - Copyright (C) 1999, 2000 Free Software Foundation - Copyright (C) 2000, 2001 Eazel, Inc. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public - License along with this program; if not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. - - Authors: Ettore Perazzoli <ettore@gnu.org>, - Pavel Cisler <pavel@eazel.com> -*/ - -#ifndef NAUTILUS_FILE_OPERATIONS_H -#define NAUTILUS_FILE_OPERATIONS_H - -#include <gtk/gtkwidget.h> -#include <libgnomevfs/gnome-vfs-types.h> - -typedef void (* NautilusCopyCallback) (GHashTable *debuting_uris, - gpointer callback_data); -typedef void (* NautilusNewFolderCallback) (const char *new_folder_uri, - gpointer callback_data); - -/* FIXME: int copy_action should be an enum */ - -void nautilus_file_operations_copy_move (const GList *item_uris, - GArray *target_item_points, - const char *target_dir_uri, - GdkDragAction copy_action, - GtkWidget *parent_view, - NautilusCopyCallback done_callback, - gpointer done_callback_data); -void nautilus_file_operations_empty_trash (GtkWidget *parent_view); -void nautilus_file_operations_new_folder (GtkWidget *parent_view, - const char *parent_dir_uri, - NautilusNewFolderCallback done_callback, - gpointer done_callback_data); -void nautilus_file_operations_delete (const GList *item_uris, - GtkWidget *parent_view); - -#endif /* NAUTILUS_FILE_OPERATIONS_H */ diff --git a/libnautilus-extensions/nautilus-file-private.h b/libnautilus-extensions/nautilus-file-private.h deleted file mode 100644 index 13fb7dcda..000000000 --- a/libnautilus-extensions/nautilus-file-private.h +++ /dev/null @@ -1,149 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- - - nautilus-directory.c: Nautilus directory model. - - Copyright (C) 1999, 2000, 2001 Eazel, Inc. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public - License along with this program; if not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. - - Author: Darin Adler <darin@eazel.com> -*/ - -#include "nautilus-directory.h" -#include "nautilus-file.h" -#include "nautilus-monitor.h" -#include <eel/eel-glib-extensions.h> - -#define NAUTILUS_FILE_TOP_LEFT_TEXT_MAXIMUM_CHARACTERS_PER_LINE 80 -#define NAUTILUS_FILE_TOP_LEFT_TEXT_MAXIMUM_LINES 24 -#define NAUTILUS_FILE_TOP_LEFT_TEXT_MAXIMUM_BYTES 10000 - -/* These are in the typical sort order. Known things come first, then - * things where we can't know, finally things where we don't yet know. - */ -typedef enum { - KNOWN, - UNKNOWABLE, - UNKNOWN -} Knowledge; - -typedef struct { - int automatic_emblems_as_integer; - char emblem_keywords[1]; -} NautilusFileSortByEmblemCache; - -struct NautilusFileDetails -{ - NautilusDirectory *directory; - char *relative_uri; - - GnomeVFSFileInfo *info; - GnomeVFSResult get_info_error; - - NautilusMonitor *monitor; - - guint directory_count; - - guint deep_directory_count; - guint deep_file_count; - guint deep_unreadable_count; - GnomeVFSFileSize deep_size; - - GList *mime_list; /* If this is a directory, the list of MIME types in it. */ - char *top_left_text; - char *activation_uri; - - /* The following is for file operations in progress. Since - * there are normally only a few of these, we can move them to - * a separate hash table or something if required to keep the - * file objects small. - */ - GList *operations_in_progress; - - /* We use this to cache automatic emblems and emblem keywords - to speed up compare_by_emblems. */ - NautilusFileSortByEmblemCache *compare_by_emblem_cache; - - /* boolean fields: bitfield to save space, since there can be - many NautilusFile objects. */ - - eel_boolean_bit unconfirmed : 1; - eel_boolean_bit is_gone : 1; - /* Set by the NautilusDirectory while it's loading the file - * list so the file knows not to do redundant I/O. - */ - eel_boolean_bit loading_directory : 1; - /* got_info known from info field being non-NULL */ - eel_boolean_bit get_info_failed : 1; - eel_boolean_bit file_info_is_up_to_date : 1; - - eel_boolean_bit got_directory_count : 1; - eel_boolean_bit directory_count_failed : 1; - eel_boolean_bit directory_count_is_up_to_date : 1; - - NautilusRequestStatus deep_counts_status : 2; - /* no deep_counts_are_up_to_date field; since we expose - intermediate values for this attribute, we do actually - forget it rather than invalidating. */ - - eel_boolean_bit got_mime_list : 1; - eel_boolean_bit mime_list_failed : 1; - eel_boolean_bit mime_list_is_up_to_date : 1; - - 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; -}; - -NautilusFile *nautilus_file_new_from_info (NautilusDirectory *directory, - GnomeVFSFileInfo *info); -NautilusFile *nautilus_file_get_existing (const char *uri); -void nautilus_file_emit_changed (NautilusFile *file); -void nautilus_file_mark_gone (NautilusFile *file); -gboolean nautilus_file_info_missing (NautilusFile *file, - GnomeVFSFileInfoFields needed_mask); -char * nautilus_extract_top_left_text (const char *text, - int length); -void nautilus_file_set_directory (NautilusFile *file, - NautilusDirectory *directory); -gboolean nautilus_file_get_date (NautilusFile *file, - NautilusDateType date_type, - time_t *date); -void nautilus_file_updated_deep_count_in_progress (NautilusFile *file); - -/* Compare file's state with a fresh file info struct, return FALSE if - * no change, update file and return TRUE if the file info contains - * new state. */ -gboolean nautilus_file_update_info (NautilusFile *file, - GnomeVFSFileInfo *info); -gboolean nautilus_file_update_name (NautilusFile *file, - const char *name); - -/* Return true if the top lefts of files in this directory should be - * fetched, according to the preference settings. - */ -gboolean nautilus_file_should_get_top_left_text (NautilusFile *file); - -/* Mark specified attributes for this file out of date without canceling current - * I/O or kicking off new I/O. - */ -void nautilus_file_invalidate_attributes_internal (NautilusFile *file, - GList *file_attributes); -GList * nautilus_file_get_all_attributes (void); - -gboolean nautilus_file_is_self_owned (NautilusFile *file); diff --git a/libnautilus-extensions/nautilus-file-utilities.c b/libnautilus-extensions/nautilus-file-utilities.c deleted file mode 100644 index a741438cc..000000000 --- a/libnautilus-extensions/nautilus-file-utilities.c +++ /dev/null @@ -1,322 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ - -/* nautilus-file-utilities.c - implementation of file manipulation routines. - - Copyright (C) 1999, 2000, 2001 Eazel, Inc. - - The Gnome 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 Gnome 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 the Gnome 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. - - Authors: John Sullivan <sullivan@eazel.com> -*/ - -#include <config.h> -#include "nautilus-file-utilities.h" - -#include "nautilus-global-preferences.h" -#include "nautilus-lib-self-check-functions.h" -#include "nautilus-link-set.h" -#include "nautilus-metadata.h" -#include "nautilus-metafile.h" -#include <eel/eel-glib-extensions.h> -#include <eel/eel-string.h> -#include <libgnome/gnome-util.h> -#include <libgnomevfs/gnome-vfs-ops.h> -#include <libgnomevfs/gnome-vfs-uri.h> -#include <libgnomevfs/gnome-vfs-utils.h> - -#define NAUTILUS_USER_DIRECTORY_NAME ".nautilus" -#define DEFAULT_NAUTILUS_DIRECTORY_MODE (0755) - -#define DESKTOP_DIRECTORY_NAME ".gnome-desktop" -#define DEFAULT_DESKTOP_DIRECTORY_MODE (0755) - -#define NAUTILUS_USER_MAIN_DIRECTORY_NAME "Nautilus" - -gboolean -nautilus_file_name_matches_hidden_pattern (const char *name_or_relative_uri) -{ - g_return_val_if_fail (name_or_relative_uri != NULL, FALSE); - - return name_or_relative_uri[0] == '.'; -} - -gboolean -nautilus_file_name_matches_backup_pattern (const char *name_or_relative_uri) -{ - g_return_val_if_fail (name_or_relative_uri != NULL, FALSE); - - return eel_str_has_suffix (name_or_relative_uri, "~"); -} - -gboolean -nautilus_file_name_matches_metafile_pattern (const char *name_or_relative_uri) -{ - g_return_val_if_fail (name_or_relative_uri != NULL, FALSE); - - return eel_str_has_suffix (name_or_relative_uri, NAUTILUS_METAFILE_NAME_SUFFIX); -} - -/** - * nautilus_make_path: - * - * Make a path name from a base path and name. The base path - * can end with or without a separator character. - * - * Return value: the combined path name. - **/ -char * -nautilus_make_path (const char *path, const char* name) -{ - gboolean insert_separator; - int path_length; - char *result; - - path_length = strlen (path); - insert_separator = path_length > 0 && - name[0] != '\0' && - path[path_length - 1] != G_DIR_SEPARATOR; - - if (insert_separator) { - result = g_strconcat (path, G_DIR_SEPARATOR_S, name, NULL); - } else { - result = g_strconcat (path, name, NULL); - } - - return result; -} - -/** - * nautilus_get_user_directory: - * - * Get the path for the directory containing nautilus settings. - * - * Return value: the directory path. - **/ -char * -nautilus_get_user_directory (void) -{ - char *user_directory = NULL; - - user_directory = nautilus_make_path (g_get_home_dir (), - NAUTILUS_USER_DIRECTORY_NAME); - - if (!g_file_exists (user_directory)) { - mkdir (user_directory, DEFAULT_NAUTILUS_DIRECTORY_MODE); - /* FIXME bugzilla.eazel.com 1286: - * How should we handle the case where this mkdir fails? - * Note that nautilus_application_startup will refuse to launch if this - * directory doesn't get created, so that case is OK. But the directory - * could be deleted after Nautilus was launched, and perhaps - * there is some bad side-effect of not handling that case. - */ - } - - return user_directory; -} - -/** - * nautilus_get_desktop_directory: - * - * Get the path for the directory containing files on the desktop. - * - * Return value: the directory path. - **/ -char * -nautilus_get_desktop_directory (void) -{ - char *desktop_directory; - - if (nautilus_preferences_get_boolean (NAUTILUS_PREFERENCES_DESKTOP_IS_HOME_DIR)) { - desktop_directory = g_strdup (g_get_home_dir()); - } else { - desktop_directory = nautilus_make_path (g_get_home_dir (), DESKTOP_DIRECTORY_NAME); - } - - if (!g_file_exists (desktop_directory)) { - mkdir (desktop_directory, DEFAULT_DESKTOP_DIRECTORY_MODE); - /* FIXME bugzilla.eazel.com 1286: - * How should we handle the case where this mkdir fails? - * Note that nautilus_application_startup will refuse to launch if this - * directory doesn't get created, so that case is OK. But the directory - * could be deleted after Nautilus was launched, and perhaps - * there is some bad side-effect of not handling that case. - */ - } - - return desktop_directory; -} - -/** - * nautilus_user_main_directory_exists: - * - * returns true if the user directory exists. This must be called - * before nautilus_get_user_main_directory, which creates it if necessary - * - **/ -gboolean -nautilus_user_main_directory_exists(void) -{ - gboolean directory_exists; - char *main_directory; - - main_directory = g_strdup_printf ("%s/%s", - g_get_home_dir(), - NAUTILUS_USER_MAIN_DIRECTORY_NAME); - directory_exists = g_file_exists(main_directory); - g_free(main_directory); - return directory_exists; -} - - -/** - * nautilus_get_user_main_directory: - * - * Get the path for the user's main Nautilus directory. - * Usually ~/Nautilus - * - * Return value: the directory path. - **/ -char * -nautilus_get_user_main_directory (void) -{ - char *user_main_directory = NULL; - GnomeVFSResult result; - char *destination_directory_uri_text; - GnomeVFSURI *destination_directory_uri; - GnomeVFSURI *destination_uri; - - user_main_directory = g_strdup_printf ("%s/%s", - g_get_home_dir(), - NAUTILUS_USER_MAIN_DIRECTORY_NAME); - - if (!g_file_exists (user_main_directory)) { - destination_directory_uri_text = gnome_vfs_get_uri_from_local_path (g_get_home_dir()); - destination_directory_uri = gnome_vfs_uri_new (destination_directory_uri_text); - g_free (destination_directory_uri_text); - destination_uri = gnome_vfs_uri_append_file_name (destination_directory_uri, - NAUTILUS_USER_MAIN_DIRECTORY_NAME); - gnome_vfs_uri_unref (destination_directory_uri); - - result = gnome_vfs_make_directory_for_uri (destination_uri, - GNOME_VFS_PERM_USER_ALL - | GNOME_VFS_PERM_GROUP_ALL - | GNOME_VFS_PERM_OTHER_READ); - - /* FIXME bugzilla.eazel.com 1286: - * How should we handle error codes returned from gnome_vfs_xfer_uri? - * Note that nautilus_application_startup will refuse to launch if this - * directory doesn't get created, so that case is OK. But the directory - * could be deleted after Nautilus was launched, and perhaps - * there is some bad side-effect of not handling that case. - */ - gnome_vfs_uri_unref (destination_uri); - - /* If this fails to create the directory, nautilus_application_startup will - * notice and refuse to launch. - */ - - /* install the default link sets */ - nautilus_link_set_install (user_main_directory, "apps"); - nautilus_link_set_install (user_main_directory, "home"); - } - - return user_main_directory; -} - -/** - * nautilus_get_pixmap_directory - * - * Get the path for the directory containing Nautilus pixmaps. - * - * Return value: the directory path. - **/ -char * -nautilus_get_pixmap_directory (void) -{ - return g_strdup (DATADIR "/pixmaps/nautilus"); -} - -/* FIXME bugzilla.eazel.com 2423: - * Callers just use this and dereference so we core dump if - * pixmaps are missing. That is lame. - */ -char * -nautilus_pixmap_file (const char *partial_path) -{ - char *path; - - /* Look for a non-GPL Eazel logo version. */ - path = nautilus_make_path (DATADIR "/pixmaps/nautilus/eazel-logos", partial_path); - if (g_file_exists (path)) { - return path; - } - g_free (path); - - /* Look for a GPL version. */ - path = nautilus_make_path (DATADIR "/pixmaps/nautilus", partial_path); - if (g_file_exists (path)) { - return path; - } - g_free (path); - - return NULL; -} - -char * -nautilus_unique_temporary_file_name (void) -{ - const char *prefix = "/tmp/nautilus-temp-file"; - char *file_name; - static guint count = 1; - - file_name = g_strdup_printf ("%sXXXXXX", prefix); - - if (mktemp (file_name) != file_name) { - g_free (file_name); - file_name = g_strdup_printf ("%s-%d-%d", prefix, count++, getpid ()); - } - - return file_name; -} - -char * -nautilus_get_build_time_stamp (void) -{ -#ifdef EAZEL_BUILD_TIMESTAMP - return g_strdup (EAZEL_BUILD_TIMESTAMP); -#else - return NULL; -#endif -} - -char * -nautilus_get_build_message (void) -{ -#ifdef NAUTILUS_BUILD_MESSAGE - return g_strdup (NAUTILUS_BUILD_MESSAGE); -#else - return NULL; -#endif -} - -#if !defined (NAUTILUS_OMIT_SELF_CHECK) - -void -nautilus_self_check_file_utilities (void) -{ -} - -#endif /* !NAUTILUS_OMIT_SELF_CHECK */ diff --git a/libnautilus-extensions/nautilus-file-utilities.h b/libnautilus-extensions/nautilus-file-utilities.h deleted file mode 100644 index 79e39a295..000000000 --- a/libnautilus-extensions/nautilus-file-utilities.h +++ /dev/null @@ -1,81 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ - -/* nautilus-file-utilities.h - interface for file manipulation routines. - - Copyright (C) 1999, 2000, 2001 Eazel, Inc. - - The Gnome 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 Gnome 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 the Gnome 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. - - Authors: John Sullivan <sullivan@eazel.com> -*/ - -#ifndef NAUTILUS_FILE_UTILITIES_H -#define NAUTILUS_FILE_UTILITIES_H - -#include <libgnomevfs/gnome-vfs-types.h> - -/* Recognizing special file names. */ -gboolean nautilus_file_name_matches_hidden_pattern (const char *name_or_relative_uri); -gboolean nautilus_file_name_matches_backup_pattern (const char *name_or_relative_uri); -gboolean nautilus_file_name_matches_metafile_pattern (const char *name_or_relative_uri); - -/* FIXME bugzilla.eazel.com 2424: - * This is the same as gnome-libs g_concat_dir_and_file except - * for handling path == NULL. - */ -char * nautilus_make_path (const char *path, - const char *name); -/* These functions all return something something that needs to be - * freed with g_free, is not NULL, and is guaranteed to exist. - */ -char * nautilus_get_user_directory (void); -char * nautilus_get_user_main_directory (void); -char * nautilus_get_desktop_directory (void); -char * nautilus_get_pixmap_directory (void); - - -/* See if the user_main_directory exists. This should be called before - * nautilus_get_user_main_directory, which creates the directory. - */ -gboolean nautilus_user_main_directory_exists (void); - -/* A version of gnome's gnome_pixmap_file that works for the nautilus prefix. - * Otherwise similar to gnome_pixmap_file in that it checks to see if the file - * exists and returns NULL if it doesn't. - */ -/* FIXME bugzilla.eazel.com 2425: - * We might not need this once we get on gnome-libs 2.0 which handles - * gnome_pixmap_file better, using GNOME_PATH. - */ -char * nautilus_pixmap_file (const char *partial_path); - -/* Returns the build time stamp the Nautilus binary. - * This is useful to be able to tell builds apart. - * A return value of NULL means unknown time stamp. - */ -char * nautilus_get_build_time_stamp (void); - -/* Returns the "build message", which provides some information on build - * context. May return NULL. - */ -char * nautilus_get_build_message (void); - -/* Return an allocated file name that is guranteed to be unique. */ -char * nautilus_unique_temporary_file_name (void); -char * nautilus_find_file_in_gnome_path (char *file); -GList * nautilus_find_all_files_in_gnome_path (char *file); - -#endif /* NAUTILUS_FILE_UTILITIES_H */ diff --git a/libnautilus-extensions/nautilus-file.c b/libnautilus-extensions/nautilus-file.c deleted file mode 100644 index 56a9ae6a2..000000000 --- a/libnautilus-extensions/nautilus-file.c +++ /dev/null @@ -1,5190 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- - - nautilus-file.c: Nautilus file model. - - Copyright (C) 1999, 2000, 2001 Eazel, Inc. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public - License along with this program; if not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. - - Author: Darin Adler <darin@eazel.com> -*/ - -#include <config.h> -#include "nautilus-file.h" - -#include "nautilus-directory-metafile.h" -#include "nautilus-directory-notify.h" -#include "nautilus-directory-private.h" -#include "nautilus-file-attributes.h" -#include "nautilus-file-private.h" -#include "nautilus-file-utilities.h" -#include "nautilus-global-preferences.h" -#include "nautilus-lib-self-check-functions.h" -#include "nautilus-link.h" -#include "nautilus-metadata.h" -#include "nautilus-trash-directory.h" -#include "nautilus-trash-file.h" -#include "nautilus-vfs-file.h" -#include <ctype.h> -#include <eel/eel-glib-extensions.h> -#include <eel/eel-gtk-extensions.h> -#include <eel/eel-gtk-macros.h> -#include <eel/eel-string.h> -#include <gnome-xml/parser.h> -#include <grp.h> -#include <gtk/gtksignal.h> -#include <libgnome/gnome-defs.h> -#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> -#include <libgnomevfs/gnome-vfs-mime-info.h> -#include <libgnomevfs/gnome-vfs-mime.h> -#include <pwd.h> -#include <stdlib.h> -#include <unistd.h> - -#undef NAUTILUS_FILE_DEBUG_REF - -#ifdef NAUTILUS_FILE_DEBUG_REF -extern void eazel_dump_stack_trace (const char *print_prefix, - int num_levels); -/* from libleakcheck.so */ -#endif - -/* Files that start with these characters sort after files that don't. */ -#define SORT_LAST_CHARACTERS ".#" - -/* Name to use to tag metadata for the directory itself. */ -#define FILE_NAME_FOR_DIRECTORY_METADATA "." - -/* Name of Nautilus trash directories */ -#define TRASH_DIRECTORY_NAME ".Trash" - -typedef enum { - SHOW_HIDDEN = 1 << 0, - SHOW_BACKUP = 1 << 1 -} FilterOptions; - -typedef struct { - NautilusFile *file; - GnomeVFSAsyncHandle *handle; - NautilusFileOperationCallback callback; - gpointer callback_data; -} Operation; - -typedef GList * (* ModifyListFunction) (GList *list, NautilusFile *file); - -enum { - CHANGED, - UPDATED_DEEP_COUNT_IN_PROGRESS, - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL]; - -static GHashTable *symbolic_links; - -static void nautilus_file_initialize_class (NautilusFileClass *klass); -static void nautilus_file_initialize (NautilusFile *file); -static void destroy (GtkObject *object); -static char * nautilus_file_get_owner_as_string (NautilusFile *file, - gboolean include_real_name); -static char * nautilus_file_get_type_as_string (NautilusFile *file); -static gboolean update_info_and_name (NautilusFile *file, - GnomeVFSFileInfo *info); - -EEL_DEFINE_CLASS_BOILERPLATE (NautilusFile, nautilus_file, GTK_TYPE_OBJECT) - -static void -nautilus_file_initialize_class (NautilusFileClass *klass) -{ - GtkObjectClass *object_class; - - object_class = GTK_OBJECT_CLASS (klass); - - object_class->destroy = destroy; - - signals[CHANGED] = - gtk_signal_new ("changed", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (NautilusFileClass, changed), - gtk_marshal_NONE__NONE, - GTK_TYPE_NONE, 0); - - signals[UPDATED_DEEP_COUNT_IN_PROGRESS] = - gtk_signal_new ("updated_deep_count_in_progress", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (NautilusFileClass, updated_deep_count_in_progress), - gtk_marshal_NONE__NONE, - GTK_TYPE_NONE, 0); - - gtk_object_class_add_signals (object_class, signals, LAST_SIGNAL); -} - -static void -nautilus_file_initialize (NautilusFile *file) -{ - file->details = g_new0 (NautilusFileDetails, 1); -} - -static NautilusFile * -nautilus_file_new_from_relative_uri (NautilusDirectory *directory, - const char *relative_uri, - gboolean self_owned) -{ - NautilusFile *file; - - g_return_val_if_fail (NAUTILUS_IS_DIRECTORY (directory), NULL); - g_return_val_if_fail (relative_uri != NULL, NULL); - g_return_val_if_fail (relative_uri[0] != '\0', NULL); - - if (self_owned && NAUTILUS_IS_TRASH_DIRECTORY (directory)) { - file = NAUTILUS_FILE (gtk_object_new (NAUTILUS_TYPE_TRASH_FILE, NULL)); - } else { - file = NAUTILUS_FILE (gtk_object_new (NAUTILUS_TYPE_VFS_FILE, NULL)); - } - gtk_object_ref (GTK_OBJECT (file)); - gtk_object_sink (GTK_OBJECT (file)); - -#ifdef NAUTILUS_FILE_DEBUG_REF - printf("%10p ref'd\n", file); - eazel_dump_stack_trace ("\t", 10); -#endif - - nautilus_directory_ref (directory); - file->details->directory = directory; - - file->details->relative_uri = g_strdup (relative_uri); - - return file; -} - -gboolean -nautilus_file_info_missing (NautilusFile *file, GnomeVFSFileInfoFields needed_mask) -{ - GnomeVFSFileInfo *info; - - if (file == NULL) { - return TRUE; - } - g_return_val_if_fail (NAUTILUS_IS_FILE (file), TRUE); - info = file->details->info; - if (info == NULL) { - return TRUE; - } - return (info->valid_fields & needed_mask) != needed_mask; -} - -static void -modify_link_hash_table (NautilusFile *file, - ModifyListFunction modify_function) -{ - const char *symlink_name; - gboolean found; - gpointer original_key; - gpointer original_value; - GList *list; - - /* Check if there is a symlink name. If none, we are OK. */ - if (nautilus_file_info_missing (file, GNOME_VFS_FILE_INFO_FIELDS_SYMLINK_NAME)) { - return; - } - symlink_name = file->details->info->symlink_name; - if (symlink_name == NULL) { - return; - } - - /* Creat the hash table first time through. */ - if (symbolic_links == NULL) { - symbolic_links = eel_g_hash_table_new_free_at_exit - (g_str_hash, g_str_equal, "nautilus-file.c: symbolic_links"); - } - - /* Find the old contents of the hash table. */ - found = g_hash_table_lookup_extended - (symbolic_links, symlink_name, - &original_key, &original_value); - if (!found) { - list = NULL; - } else { - g_hash_table_remove (symbolic_links, symlink_name); - g_free (original_key); - list = original_value; - } - list = (* modify_function) (list, file); - if (list != NULL) { - g_hash_table_insert (symbolic_links, g_strdup (symlink_name), list); - } -} - -static GList * -add_to_link_hash_table_list (GList *list, NautilusFile *file) -{ - g_assert (g_list_find (list, file) == NULL); - return g_list_prepend (list, file); -} - -static void -add_to_link_hash_table (NautilusFile *file) -{ - modify_link_hash_table (file, add_to_link_hash_table_list); -} - -static GList * -remove_from_link_hash_table_list (GList *list, NautilusFile *file) -{ - g_assert (g_list_find (list, file) != NULL); - return g_list_remove (list, file); -} - -static void -remove_from_link_hash_table (NautilusFile *file) -{ - modify_link_hash_table (file, remove_from_link_hash_table_list); -} - -NautilusFile * -nautilus_file_new_from_info (NautilusDirectory *directory, - GnomeVFSFileInfo *info) -{ - NautilusFile *file; - - g_return_val_if_fail (NAUTILUS_IS_DIRECTORY (directory), NULL); - g_return_val_if_fail (info != NULL, NULL); - - file = NAUTILUS_FILE (gtk_object_new (NAUTILUS_TYPE_VFS_FILE, NULL)); - -#ifdef NAUTILUS_FILE_DEBUG_REF - printf("%10p ref'd\n", file); - eazel_dump_stack_trace ("\t", 10); -#endif - - gtk_object_ref (GTK_OBJECT (file)); - gtk_object_sink (GTK_OBJECT (file)); - - nautilus_directory_ref (directory); - file->details->directory = directory; - - update_info_and_name (file, info); - return file; -} - -/** - * nautilus_file_get_internal: - * @uri: URI of file to get. - * - * Get a file given a uri. - * Returns a referenced object. Unref when finished. - * If two windows are viewing the same uri, the file object is shared. - */ -static NautilusFile * -nautilus_file_get_internal (const char *uri, gboolean create) -{ - char *canonical_uri, *directory_uri, *relative_uri; - gboolean self_owned; - GnomeVFSURI *vfs_uri, *directory_vfs_uri; - NautilusDirectory *directory; - NautilusFile *file; - - g_return_val_if_fail (uri != NULL, NULL); - - /* Maybe we wouldn't need this if the gnome-vfs canonical - * stuff was strong enough. - */ - canonical_uri = eel_make_uri_canonical (uri); - - /* Make VFS version of URI. */ - vfs_uri = gnome_vfs_uri_new (canonical_uri); - relative_uri = NULL; - if (vfs_uri != NULL) { - relative_uri = gnome_vfs_uri_extract_short_path_name (vfs_uri); - - /* Couldn't parse a name out of the URI: the URI must be bogus, - * so we'll treat it like the case where gnome_vfs_uri couldn't - * even create a URI. - */ - if (eel_str_is_empty (relative_uri)) { - gnome_vfs_uri_unref (vfs_uri); - vfs_uri = NULL; - g_free (relative_uri); - relative_uri = NULL; - } - } - - /* Make VFS version of directory URI. */ - if (vfs_uri == NULL) { - directory_vfs_uri = NULL; - } else { - directory_vfs_uri = gnome_vfs_uri_get_parent (vfs_uri); - gnome_vfs_uri_unref (vfs_uri); - } - - self_owned = directory_vfs_uri == NULL; - if (self_owned) { - /* Use the item itself if we have no parent. */ - directory_uri = g_strdup (canonical_uri); - } else { - /* Make text version of directory URI. */ - directory_uri = gnome_vfs_uri_to_string - (directory_vfs_uri, - GNOME_VFS_URI_HIDE_NONE); - gnome_vfs_uri_unref (directory_vfs_uri); - } - - /* Get object that represents the directory. */ - directory = nautilus_directory_get_internal (directory_uri, create); - g_free (directory_uri); - - /* Get the name for the file. */ - if (vfs_uri == NULL) { - g_assert (self_owned); - if (directory != NULL) { - relative_uri = gnome_vfs_escape_string - (nautilus_directory_get_name_for_self_as_new_file (directory)); - } - } - - /* Check to see if it's a file that's already known. */ - if (directory == NULL) { - file = NULL; - } else if (self_owned) { - file = directory->details->as_file; - } else { - file = nautilus_directory_find_file_by_relative_uri (directory, relative_uri); - } - - /* Ref or create the file. */ - if (file != NULL) { - nautilus_file_ref (file); - } else if (create) { - file = nautilus_file_new_from_relative_uri (directory, relative_uri, self_owned); - if (self_owned) { - g_assert (directory->details->as_file == NULL); - directory->details->as_file = file; - } else { - nautilus_directory_add_file (directory, file); - } - } - - g_free (canonical_uri); - g_free (relative_uri); - nautilus_directory_unref (directory); - - return file; -} - -NautilusFile * -nautilus_file_get_existing (const char *uri) -{ - return nautilus_file_get_internal (uri, FALSE); -} - -NautilusFile * -nautilus_file_get (const char *uri) -{ - return nautilus_file_get_internal (uri, TRUE); -} - -gboolean -nautilus_file_is_self_owned (NautilusFile *file) -{ - return file->details->directory->details->as_file == file; -} - -static void -destroy (GtkObject *object) -{ - NautilusDirectory *directory; - NautilusFile *file; - - file = NAUTILUS_FILE (object); - - g_assert (file->details->operations_in_progress == NULL); - - if (file->details->monitor != NULL) { - nautilus_monitor_cancel (file->details->monitor); - } - - nautilus_async_destroying_file (file); - - remove_from_link_hash_table (file); - - directory = file->details->directory; - - if (nautilus_file_is_self_owned (file)) { - directory->details->as_file = NULL; - } else { - if (!file->details->is_gone) { - nautilus_directory_remove_file (directory, file); - } - } - - nautilus_directory_unref (directory); - g_free (file->details->relative_uri); - if (file->details->info != NULL) { - gnome_vfs_file_info_unref (file->details->info); - } - g_free (file->details->top_left_text); - g_free (file->details->activation_uri); - g_free (file->details->compare_by_emblem_cache); - - eel_g_list_free_deep (file->details->mime_list); - - g_free (file->details); - - EEL_CALL_PARENT (GTK_OBJECT_CLASS, destroy, (object)); -} - - -NautilusFile * -nautilus_file_ref (NautilusFile *file) -{ - if (file == NULL) { - return NULL; - } - g_return_val_if_fail (NAUTILUS_IS_FILE (file), NULL); - -#ifdef NAUTILUS_FILE_DEBUG_REF - printf("%10p ref'd\n", file); - eazel_dump_stack_trace ("\t", 10); -#endif - - gtk_object_ref (GTK_OBJECT (file)); - return file; -} - -void -nautilus_file_unref (NautilusFile *file) -{ - if (file == NULL) { - return; - } - - g_return_if_fail (NAUTILUS_IS_FILE (file)); - -#ifdef NAUTILUS_FILE_DEBUG_REF - printf("%10p unref'd\n", file); - eazel_dump_stack_trace ("\t", 10); -#endif - - gtk_object_unref (GTK_OBJECT (file)); -} - -/** - * nautilus_file_get_parent_uri_for_display: - * - * Get the uri for the parent directory. - * - * @file: The file in question. - * - * Return value: A string representing the parent's location, - * formatted for user display (including stripping "file://"). - * If the parent is NULL, returns the empty string. - */ -char * -nautilus_file_get_parent_uri_for_display (NautilusFile *file) -{ - char *raw_uri; - char *result; - - g_assert (NAUTILUS_IS_FILE (file)); - - raw_uri = nautilus_file_get_parent_uri (file); - result = eel_format_uri_for_display (raw_uri); - g_free (raw_uri); - - return result; -} - -/** - * nautilus_file_get_parent_uri: - * - * Get the uri for the parent directory. - * - * @file: The file in question. - * - * Return value: A string for the parent's location, in "raw URI" form. - * Use nautilus_file_get_parent_uri_for_display instead if the - * result is to be displayed on-screen. - * If the parent is NULL, returns the empty string. - */ -char * -nautilus_file_get_parent_uri (NautilusFile *file) -{ - g_assert (NAUTILUS_IS_FILE (file)); - - if (nautilus_file_is_self_owned (file)) { - /* Callers expect an empty string, not a NULL. */ - return g_strdup (""); - } - - return nautilus_directory_get_uri (file->details->directory); -} - -static NautilusFile * -get_file_for_parent_directory (NautilusFile *file) -{ - char *parent_uri; - NautilusFile *result; - - g_assert (NAUTILUS_IS_FILE (file)); - - if (nautilus_file_is_self_owned (file)) { - return NULL; - } - - parent_uri = nautilus_directory_get_uri (file->details->directory); - result = nautilus_file_get (parent_uri); - g_free (parent_uri); - - return result; -} - -/** - * nautilus_file_denies_access_permission: - * - * Check whether the current file does not have a given permission - * for the current user. The sense is negative because the function - * returns FALSE if permissions cannot be determined. - * - * @file: The file to check. - * @owner_permission: The USER version of the permission (e.g. GNOME_VFS_PERM_USER_READ). - * @group_permission: The GROUP version of the permission (e.g. GNOME_VFS_PERM_GROUP_READ). - * @other_permission: The OTHER version of the permission (e.g. GNOME_VFS_PERM_OTHER_READ). - * - * Return value: TRUE if the current user definitely does not have - * the specified permission. FALSE if the current user does have - * permission, or if the permissions themselves are not queryable. - */ -static gboolean -nautilus_file_denies_access_permission (NautilusFile *file, - GnomeVFSFilePermissions owner_permission, - GnomeVFSFilePermissions group_permission, - GnomeVFSFilePermissions other_permission) -{ - uid_t user_id; - struct passwd *password_info; - gid_t supplementary_groups[NGROUPS_MAX]; - int num_supplementary_groups; - int i; - - g_assert (NAUTILUS_IS_FILE (file)); - - /* Once the file is gone, you are denied permission to do anything. */ - if (nautilus_file_is_gone (file)) { - return TRUE; - } - - /* File system does not provide permission bits. - * Can't determine specific permissions, do not deny permission at all. - */ - if (!nautilus_file_can_get_permissions (file)) { - return FALSE; - } - - /* Check the user. */ - user_id = geteuid (); - - /* Root is not forbidden to do anything. */ - if (user_id == 0) { - return FALSE; - } - - /* File owner's access is governed by the owner bits. */ - /* FIXME bugzilla.eazel.com 644: - * Can we trust the uid in the file info? Might - * there be garbage there? What will it do for non-local files? - */ - if (user_id == file->details->info->uid) { - return (file->details->info->permissions & owner_permission) == 0; - } - - /* No need to free result of getpwuid. */ - password_info = getpwuid (user_id); - - /* Group member's access is governed by the group bits. */ - /* FIXME bugzilla.eazel.com 644: - * Can we trust the gid in the file info? Might - * there be garbage there? What will it do for non-local files? - */ - if (password_info != NULL - && password_info->pw_gid == file->details->info->gid) { - return (file->details->info->permissions & group_permission) == 0; - } - /* Check supplementary groups */ - num_supplementary_groups = getgroups (NGROUPS_MAX, supplementary_groups); - for (i = 0; i < num_supplementary_groups; i++) { - if (file->details->info->gid == supplementary_groups[i]) { - return (file->details->info->permissions & group_permission) == 0; - } - } - /* Other users' access is governed by the other bits. */ - return (file->details->info->permissions & other_permission) == 0; -} - -/** - * nautilus_file_can_read: - * - * Check whether the user is allowed to read the contents of this file. - * - * @file: The file to check. - * - * Return value: FALSE if the user is definitely not allowed to read - * the contents of the file. If the user has read permission, or - * the code can't tell whether the user has read permission, - * returns TRUE (so failures must always be handled). - */ -gboolean -nautilus_file_can_read (NautilusFile *file) -{ - g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE); - - return !nautilus_file_denies_access_permission - (file, - GNOME_VFS_PERM_USER_READ, - GNOME_VFS_PERM_GROUP_READ, - GNOME_VFS_PERM_OTHER_READ); -} - -/** - * nautilus_file_can_write: - * - * Check whether the user is allowed to write to this file. - * - * @file: The file to check. - * - * Return value: FALSE if the user is definitely not allowed to write - * to the file. If the user has write permission, or - * the code can't tell whether the user has write permission, - * returns TRUE (so failures must always be handled). - */ -gboolean -nautilus_file_can_write (NautilusFile *file) -{ - g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE); - - return !nautilus_file_denies_access_permission - (file, - GNOME_VFS_PERM_USER_WRITE, - GNOME_VFS_PERM_GROUP_WRITE, - GNOME_VFS_PERM_OTHER_WRITE); -} - -/** - * nautilus_file_can_execute: - * - * Check whether the user is allowed to execute this file. - * - * @file: The file to check. - * - * Return value: FALSE if the user is definitely not allowed to execute - * the file. If the user has execute permission, or - * the code can't tell whether the user has execute permission, - * returns TRUE (so failures must always be handled). - */ -gboolean -nautilus_file_can_execute (NautilusFile *file) -{ - g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE); - - return !nautilus_file_denies_access_permission - (file, - GNOME_VFS_PERM_USER_EXEC, - GNOME_VFS_PERM_GROUP_EXEC, - GNOME_VFS_PERM_OTHER_EXEC); -} - -/** - * nautilus_file_can_rename: - * - * Check whether the user is allowed to change the name of the file. - * - * @file: The file to check. - * - * Return value: FALSE if the user is definitely not allowed to change - * the name of the file. If the user is allowed to change the name, or - * the code can't tell whether the user is allowed to change the name, - * returns TRUE (so rename failures must always be handled). - */ -gboolean -nautilus_file_can_rename (NautilusFile *file) -{ - NautilusFile *parent; - gboolean can_rename; - char *uri, *path; - - g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE); - - /* Nonexistent files can't be renamed. */ - if (nautilus_file_is_gone (file)) { - return FALSE; - } - - /* Self-owned files can't be renamed */ - if (nautilus_file_is_self_owned (file)) { - return FALSE; - } - - if (nautilus_file_is_mime_type (file, "application/x-gnome-app-info")) { - return FALSE; - } - - can_rename = TRUE; - uri = nautilus_file_get_uri (file); - path = gnome_vfs_get_local_path_from_uri (uri); - - /* Certain types of links can't be renamed */ - if (path != NULL && nautilus_file_is_nautilus_link (file)) { - /* FIXME: This reads the link file every time -- seems - * bad to do that even though it's known to be local. - */ - switch (nautilus_link_local_get_link_type (path)) { - case NAUTILUS_LINK_TRASH: - case NAUTILUS_LINK_MOUNT: - can_rename = FALSE; - break; - - case NAUTILUS_LINK_HOME: - case NAUTILUS_LINK_GENERIC: - break; - } - } - - /* Nautilus trash directories cannot be renamed */ - if (eel_uri_is_trash_folder (uri)) { - can_rename = FALSE; - } - - g_free (uri); - g_free (path); - - if (!can_rename) { - return FALSE; - } - - /* User must have write permissions for the parent directory. */ - parent = get_file_for_parent_directory (file); - - /* No parent directory for some reason (at root level?). - * Can't tell whether this file is renameable, so return TRUE. - */ - if (parent == NULL) { - return TRUE; - } - - can_rename = nautilus_file_can_write (parent); - - nautilus_file_unref (parent); - - return can_rename; -} - -static GnomeVFSURI * -nautilus_file_get_gnome_vfs_uri (NautilusFile *file) -{ - GnomeVFSURI *vfs_uri; - - vfs_uri = file->details->directory->details->vfs_uri; - if (vfs_uri == NULL) { - return NULL; - } - - if (nautilus_file_is_self_owned (file)) { - gnome_vfs_uri_ref (vfs_uri); - return vfs_uri; - } - - return gnome_vfs_uri_append_string - (vfs_uri, file->details->relative_uri); -} - -static Operation * -operation_new (NautilusFile *file, - NautilusFileOperationCallback callback, - gpointer callback_data) -{ - Operation *op; - - nautilus_file_ref (file); - - op = g_new0 (Operation, 1); - op->file = file; - op->callback = callback; - op->callback_data = callback_data; - - op->file->details->operations_in_progress = g_list_prepend - (op->file->details->operations_in_progress, op); - - return op; -} - -static void -operation_remove (Operation *op) -{ - op->file->details->operations_in_progress = g_list_remove - (op->file->details->operations_in_progress, op); - -} - -static void -operation_free (Operation *op) -{ - operation_remove (op); - nautilus_file_unref (op->file); - g_free (op); -} - -static void -operation_complete (Operation *op, - GnomeVFSResult result) -{ - /* Claim that something changed even if the operation failed. - * This makes it easier for some clients who see the "reverting" - * as "changing back". - */ - operation_remove (op); - nautilus_file_changed (op->file); - (* op->callback) (op->file, result, op->callback_data); - operation_free (op); -} - -static void -operation_cancel (Operation *op) -{ - /* Cancel the operation if it's still in progress. */ - g_assert (op->handle != NULL); - gnome_vfs_async_cancel (op->handle); - - /* Claim that something changed even though the operation was - * canceled in case some work was partly done, but don't call - * the callback. - */ - nautilus_file_changed (op->file); - operation_free (op); -} - -static void -rename_callback (GnomeVFSAsyncHandle *handle, - GnomeVFSResult result, - GnomeVFSFileInfo *new_info, - gpointer callback_data) -{ - Operation *op; - NautilusDirectory *directory; - NautilusFile *existing_file; - char *old_relative_uri; - char *old_uri; - char *new_uri; - - op = callback_data; - g_assert (handle == op->handle); - - if (result == GNOME_VFS_OK && new_info != NULL) { - directory = op->file->details->directory; - - /* If there was another file by the same name in this - * directory, mark it gone. - */ - existing_file = nautilus_directory_find_file_by_name (directory, new_info->name); - if (existing_file != NULL) { - nautilus_file_mark_gone (existing_file); - nautilus_file_changed (existing_file); - } - - old_uri = nautilus_file_get_uri (op->file); - old_relative_uri = g_strdup (op->file->details->relative_uri); - update_info_and_name (op->file, new_info); - - /* Self-owned files store their metadata under the - * hard-code name "." so there's no need to rename - * their metadata when they are renamed. - */ - if (!nautilus_file_is_self_owned (op->file)) { - nautilus_directory_rename_file_metadata - (directory, old_relative_uri, op->file->details->relative_uri); - } - - new_uri = nautilus_file_get_uri (op->file); - nautilus_directory_moved (old_uri, new_uri); - g_free (new_uri); - g_free (old_uri); - } - operation_complete (op, result); -} - -static gboolean -name_is (NautilusFile *file, const char *new_name) -{ - char *old_name; - gboolean equal; - - old_name = nautilus_file_get_name (file); - equal = strcmp (new_name, old_name) == 0; - g_free (old_name); - return equal; -} - -void -nautilus_file_rename (NautilusFile *file, - const char *new_name, - NautilusFileOperationCallback callback, - gpointer callback_data) -{ - Operation *op; - GnomeVFSFileInfo *partial_file_info; - GnomeVFSURI *vfs_uri; - char *uri, *path; - - g_return_if_fail (NAUTILUS_IS_FILE (file)); - g_return_if_fail (new_name != NULL); - g_return_if_fail (callback != NULL); - - /* FIXME: Rename GMC URLs on the local file system by setting - * their metadata only. This leaves no way to rename them for - * real. - */ - if (nautilus_file_is_gmc_url (file)) { - uri = nautilus_file_get_uri (file); - path = gnome_vfs_get_local_path_from_uri (uri); - g_free (uri); - - if (path != NULL) { - gnome_metadata_set (path, "icon-caption", strlen (new_name) + 1, new_name); - g_free (path); - - (* callback) (file, GNOME_VFS_OK, callback_data); - nautilus_file_changed (file); - return; - } - } - - /* Make return an error for incoming names containing path separators. */ - if (strstr (new_name, "/") != NULL) { - (* callback) (file, GNOME_VFS_ERROR_NOT_PERMITTED, callback_data); - return; - } - - /* Can't rename a file that's already gone. - * We need to check this here because there may be a new - * file with the same name. - */ - if (nautilus_file_is_gone (file)) { - /* Claim that something changed even if the rename - * failed. This makes it easier for some clients who - * see the "reverting" to the old name as "changing - * back". - */ - nautilus_file_changed (file); - (* callback) (file, GNOME_VFS_ERROR_NOT_FOUND, callback_data); - return; - } - - /* Test the name-hasn't-changed case explicitly, for two reasons. - * (1) gnome_vfs_async_xfer returns an error if new & old are same. - * (2) We don't want to send file-changed signal if nothing changed. - */ - if (name_is (file, new_name)) { - (* callback) (file, GNOME_VFS_OK, callback_data); - return; - } - - /* Self-owned files can't be renamed. Test the name-not-actually-changing - * case before this case. - */ - if (nautilus_file_is_self_owned (file)) { - /* Claim that something changed even if the rename - * failed. This makes it easier for some clients who - * see the "reverting" to the old name as "changing - * back". - */ - nautilus_file_changed (file); - (* callback) (file, GNOME_VFS_ERROR_NOT_SUPPORTED, callback_data); - return; - } - - /* Set up a renaming operation. */ - op = operation_new (file, callback, callback_data); - - /* Do the renaming. */ - partial_file_info = gnome_vfs_file_info_new (); - partial_file_info->name = g_strdup (new_name); - vfs_uri = nautilus_file_get_gnome_vfs_uri (file); - gnome_vfs_async_set_file_info (&op->handle, - vfs_uri, partial_file_info, - GNOME_VFS_SET_FILE_INFO_NAME, - (GNOME_VFS_FILE_INFO_GET_MIME_TYPE - | GNOME_VFS_FILE_INFO_FOLLOW_LINKS), - rename_callback, op); - gnome_vfs_file_info_unref (partial_file_info); - gnome_vfs_uri_unref (vfs_uri); -} - -void -nautilus_file_cancel (NautilusFile *file, - NautilusFileOperationCallback callback, - gpointer callback_data) -{ - GList *p, *next; - Operation *op; - - for (p = file->details->operations_in_progress; p != NULL; p = next) { - next = p->next; - op = p->data; - - g_assert (op->file == file); - if (op->callback == callback - && op->callback_data == callback_data) { - operation_cancel (op); - } - } -} - -gboolean -nautilus_file_matches_uri (NautilusFile *file, const char *match_uri) -{ - GnomeVFSURI *match_vfs_uri, *file_vfs_uri; - char *file_uri; - gboolean result; - - g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE); - g_return_val_if_fail (match_uri != NULL, FALSE); - - match_vfs_uri = gnome_vfs_uri_new (match_uri); - file_vfs_uri = nautilus_file_get_gnome_vfs_uri (file); - - if (match_vfs_uri == NULL || file_vfs_uri == NULL) { - file_uri = nautilus_file_get_uri (file); - result = strcmp (match_uri, file_uri) == 0; - } else { - result = gnome_vfs_uri_equal (file_vfs_uri, match_vfs_uri); - } - - if (file_vfs_uri != NULL) { - gnome_vfs_uri_unref (file_vfs_uri); - } - if (match_vfs_uri != NULL) { - gnome_vfs_uri_unref (match_vfs_uri); - } - - return result; -} - -gboolean -nautilus_file_is_local (NautilusFile *file) -{ - g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE); - - return nautilus_directory_is_local (file->details->directory); -} - -static void -update_link (NautilusFile *link_file, NautilusFile *target_file) -{ - g_assert (NAUTILUS_IS_FILE (link_file)); - g_assert (NAUTILUS_IS_FILE (target_file)); - g_assert (!nautilus_file_info_missing (link_file, GNOME_VFS_FILE_INFO_FIELDS_SYMLINK_NAME)); - - /* FIXME bugzilla.eazel.com 2044: If we don't put any code - * here then the hash table is a waste of time. - */ -} - -static GList * -get_link_files (NautilusFile *target_file) -{ - char *uri; - GList *link_files; - - if (symbolic_links == NULL) { - link_files = NULL; - } else { - uri = nautilus_file_get_uri (target_file); - link_files = g_hash_table_lookup (symbolic_links, uri); - g_free (uri); - } - return nautilus_file_list_copy (link_files); -} - -static void -update_links_if_target (NautilusFile *target_file) -{ - GList *link_files, *p; - - link_files = get_link_files (target_file); - for (p = link_files; p != NULL; p = p->next) { - update_link (NAUTILUS_FILE (p->data), target_file); - } - nautilus_file_list_free (link_files); -} - -static gboolean -update_info_internal (NautilusFile *file, - GnomeVFSFileInfo *info, - gboolean update_name) -{ - GList *node; - GnomeVFSFileInfo *info_copy; - char *new_relative_uri; - - if (file->details->is_gone) { - return FALSE; - } - - if (info == NULL) { - nautilus_file_mark_gone (file); - return TRUE; - } - - file->details->file_info_is_up_to_date = TRUE; - - if (file->details->info != NULL - && gnome_vfs_file_info_matches (file->details->info, info)) { - return FALSE; - } - - /* FIXME bugzilla.eazel.com 2044: Need to let links that - * point to the old name know that the file has been renamed. - */ - - remove_from_link_hash_table (file); - - info_copy = gnome_vfs_file_info_dup (info); - if (file->details->info != NULL) { - gnome_vfs_file_info_unref (file->details->info); - } - file->details->info = info_copy; - - if (update_name) { - new_relative_uri = gnome_vfs_escape_string (info->name); - if (file->details->relative_uri != NULL - && strcmp (file->details->relative_uri, new_relative_uri) == 0) { - g_free (new_relative_uri); - } else { - node = nautilus_directory_begin_file_name_change - (file->details->directory, file); - g_free (file->details->relative_uri); - file->details->relative_uri = new_relative_uri; - nautilus_directory_end_file_name_change - (file->details->directory, file, node); - } - } - - add_to_link_hash_table (file); - - update_links_if_target (file); - - return TRUE; -} - -static gboolean -update_info_and_name (NautilusFile *file, - GnomeVFSFileInfo *info) -{ - return update_info_internal (file, info, TRUE); -} - -gboolean -nautilus_file_update_info (NautilusFile *file, - GnomeVFSFileInfo *info) -{ - return update_info_internal (file, info, FALSE); -} - -gboolean -nautilus_file_update_name (NautilusFile *file, const char *name) -{ - GnomeVFSFileInfo *info; - GList *node; - - g_assert (name != NULL); - - if (file->details->is_gone) { - return FALSE; - } - - if (name_is (file, name)) { - return FALSE; - } - - if (file->details->info == NULL) { - node = nautilus_directory_begin_file_name_change - (file->details->directory, file); - g_free (file->details->relative_uri); - file->details->relative_uri = gnome_vfs_escape_string (name); - nautilus_directory_end_file_name_change - (file->details->directory, file, node); - } else { - /* Make a copy and update the file name in the copy. */ - info = gnome_vfs_file_info_new (); - gnome_vfs_file_info_copy (info, file->details->info); - g_free (info->name); - info->name = g_strdup (name); - update_info_and_name (file, info); - gnome_vfs_file_info_unref (info); - } - - return TRUE; -} - -void -nautilus_file_set_directory (NautilusFile *file, - NautilusDirectory *new_directory) -{ - NautilusDirectory *old_directory; - FileMonitors *monitors; - - g_return_if_fail (NAUTILUS_IS_FILE (file)); - g_return_if_fail (NAUTILUS_IS_DIRECTORY (file->details->directory)); - g_return_if_fail (!file->details->is_gone); - g_return_if_fail (!nautilus_file_is_self_owned (file)); - g_return_if_fail (NAUTILUS_IS_DIRECTORY (new_directory)); - - old_directory = file->details->directory; - if (old_directory == new_directory) { - return; - } - - nautilus_file_ref (file); - - /* FIXME bugzilla.eazel.com 2044: Need to let links that - * point to the old name know that the file has been moved. - */ - - remove_from_link_hash_table (file); - - monitors = nautilus_directory_remove_file_monitors (old_directory, file); - nautilus_directory_remove_file (old_directory, file); - - nautilus_directory_ref (new_directory); - file->details->directory = new_directory; - nautilus_directory_unref (old_directory); - - nautilus_directory_add_file (new_directory, file); - nautilus_directory_add_file_monitors (new_directory, file, monitors); - - add_to_link_hash_table (file); - - update_links_if_target (file); - - nautilus_file_unref (file); -} - -static Knowledge -get_item_count (NautilusFile *file, - guint *count) -{ - gboolean known, unreadable; - - known = nautilus_file_get_directory_item_count - (file, count, &unreadable); - if (!known) { - return UNKNOWN; - } - if (unreadable) { - return UNKNOWABLE; - } - return KNOWN; -} - -static Knowledge -get_size (NautilusFile *file, - GnomeVFSFileSize *size) -{ - /* If we tried and failed, then treat it like there is no size - * to know. - */ - if (file->details->get_info_failed) { - return UNKNOWABLE; - } - - /* If the info is NULL that means we haven't even tried yet, - * so it's just unknown, not unknowable. - */ - if (file->details->info == NULL) { - return UNKNOWN; - } - - /* If we got info with no size in it, it means there is no - * such thing as a size as far as gnome-vfs is concerned, - * so "unknowable". - */ - if ((file->details->info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) == 0) { - return UNKNOWABLE; - } - - /* We have a size! */ - *size = file->details->info->size; - return KNOWN; -} - -static Knowledge -get_modification_time (NautilusFile *file, - time_t *modification_time) -{ - /* If we tried and failed, then treat it like there is no size - * to know. - */ - if (file->details->get_info_failed) { - return UNKNOWABLE; - } - - /* If the info is NULL that means we haven't even tried yet, - * so it's just unknown, not unknowable. - */ - if (file->details->info == NULL) { - return UNKNOWN; - } - - /* If we got info with no modification time in it, it means - * there is no such thing as a modification time as far as - * gnome-vfs is concerned, so "unknowable". - */ - if ((file->details->info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_MTIME) == 0) { - return UNKNOWABLE; - } - - /* We have a modification time. */ - *modification_time = file->details->info->mtime; - return KNOWN; -} - -static int -compare_directories_by_count (NautilusFile *file_1, NautilusFile *file_2) -{ - /* Sort order: - * Directories with n items - * Directories with 0 items - * Directories with "unknowable" # of items - * Directories with unknown # of items - */ - - Knowledge count_known_1, count_known_2; - guint count_1, count_2; - - count_known_1 = get_item_count (file_1, &count_1); - count_known_2 = get_item_count (file_2, &count_2); - - if (count_known_1 < count_known_2) { - return -1; - } - if (count_known_1 > count_known_2) { - return +1; - } - - if (count_1 > count_2) { - return -1; - } - if (count_1 < count_2) { - return +1; - } - - return 0; -} - -static int -compare_files_by_size (NautilusFile *file_1, NautilusFile *file_2) -{ - /* Sort order: - * Files with large sizes. - * Files with smaller sizes. - * Files with "unknowable" size. - * Files with unknown size. - */ - - Knowledge size_known_1, size_known_2; - GnomeVFSFileSize size_1, size_2; - - size_known_1 = get_size (file_1, &size_1); - size_known_2 = get_size (file_2, &size_2); - - if (size_known_1 < size_known_2) { - return -1; - } - if (size_known_1 > size_known_2) { - return +1; - } - - if (size_1 > size_2) { - return -1; - } - if (size_1 < size_2) { - return +1; - } - - return 0; -} - -static int -compare_by_size (NautilusFile *file_1, NautilusFile *file_2) -{ - /* Sort order: - * Directories with n items - * Directories with 0 items - * Directories with "unknowable" # of items - * Directories with unknown # of items - * Files with large sizes. - * Files with smaller sizes. - * Files with "unknowable" size. - * Files with unknown size. - */ - - gboolean is_directory_1, is_directory_2; - - is_directory_1 = nautilus_file_is_directory (file_1); - is_directory_2 = nautilus_file_is_directory (file_2); - - if (is_directory_1 && !is_directory_2) { - return -1; - } - if (is_directory_2 && !is_directory_1) { - return +1; - } - - if (is_directory_1) { - return compare_directories_by_count (file_1, file_2); - } else { - return compare_files_by_size (file_1, file_2); - } -} - -static int -compare_by_name (NautilusFile *file_1, NautilusFile *file_2) -{ - char *name_1, *name_2; - gboolean sort_last_1, sort_last_2; - int compare; - - name_1 = nautilus_file_get_name (file_1); - name_2 = nautilus_file_get_name (file_2); - - sort_last_1 = strchr (SORT_LAST_CHARACTERS, name_1[0]) != NULL; - sort_last_2 = strchr (SORT_LAST_CHARACTERS, name_2[0]) != NULL; - - if (sort_last_1 && !sort_last_2) { - compare = +1; - } else if (!sort_last_1 && sort_last_2) { - compare = -1; - } else { - compare = eel_strcoll (name_1, name_2); - } - - g_free (name_1); - g_free (name_2); - - return compare; -} - -static int -compare_by_directory_name (NautilusFile *file_1, NautilusFile *file_2) -{ - char *directory_1, *directory_2; - int compare; - - if (file_1->details->directory == file_2->details->directory) { - return 0; - } - - directory_1 = nautilus_file_get_parent_uri_for_display (file_1); - directory_2 = nautilus_file_get_parent_uri_for_display (file_2); - - compare = eel_strcoll (directory_1, directory_2); - - g_free (directory_1); - g_free (directory_2); - - return compare; -} - -static int -get_automatic_emblems_as_integer (NautilusFile *file) -{ - int integer; - - /* Keep in proper order for sorting. */ - - integer = nautilus_file_is_symbolic_link (file); - integer <<= 1; - integer |= !nautilus_file_can_read (file); - integer <<= 1; - integer |= !nautilus_file_can_write (file); - integer <<= 1; - integer |= nautilus_file_is_in_trash (file); - - return integer; -} - -static GList * -prepend_automatic_emblem_names (NautilusFile *file, - GList *names) -{ - /* Prepend in reverse order. */ - - if (nautilus_file_is_in_trash (file)) { - names = g_list_prepend - (names, g_strdup (NAUTILUS_FILE_EMBLEM_NAME_TRASH)); - } - if (!nautilus_file_can_write (file)) { - names = g_list_prepend - (names, g_strdup (NAUTILUS_FILE_EMBLEM_NAME_CANT_WRITE)); - } - if (!nautilus_file_can_read (file)) { - names = g_list_prepend - (names, g_strdup (NAUTILUS_FILE_EMBLEM_NAME_CANT_READ)); - } - if (nautilus_file_is_symbolic_link (file)) { - names = g_list_prepend - (names, g_strdup (NAUTILUS_FILE_EMBLEM_NAME_SYMBOLIC_LINK)); - } - - return names; -} - -static void -fill_emblem_cache_if_needed (NautilusFile *file) -{ - GList *node, *keywords; - char *scanner; - size_t length; - - if (file->details->compare_by_emblem_cache != NULL) { - /* Got a cache already. */ - return; - } - - keywords = nautilus_file_get_keywords (file); - - /* Add up the keyword string lengths */ - length = 1; - for (node = keywords; node != NULL; node = node->next) { - length += strlen ((const char *) node->data) + 1; - } - - /* Now that we know how large the cache struct needs to be, allocate it. */ - file->details->compare_by_emblem_cache = g_malloc (sizeof(NautilusFileSortByEmblemCache) + length); - - /* Copy them into the cache. */ - scanner = file->details->compare_by_emblem_cache->emblem_keywords; - for (node = keywords; node != NULL; node = node->next) { - length = strlen ((const char *) node->data) + 1; - memcpy (scanner, (const char *) node->data, length); - scanner += length; - } - - /* Zero-terminate so we can tell where the list ends. */ - *scanner = 0; - - eel_g_list_free_deep (keywords); - - /* Chache the values of the automatic emblems. */ - file->details->compare_by_emblem_cache->automatic_emblems_as_integer - = get_automatic_emblems_as_integer (file); -} - -static int -compare_by_emblems (NautilusFile *file_1, NautilusFile *file_2) -{ - const char *keyword_cache_1, *keyword_cache_2; - size_t length; - int compare_result; - - - fill_emblem_cache_if_needed (file_1); - fill_emblem_cache_if_needed (file_2); - - /* Compare automatic emblems. */ - if (file_1->details->compare_by_emblem_cache->automatic_emblems_as_integer < - file_2->details->compare_by_emblem_cache->automatic_emblems_as_integer) { - return +1; - } else if (file_1->details->compare_by_emblem_cache->automatic_emblems_as_integer > - file_2->details->compare_by_emblem_cache->automatic_emblems_as_integer) { - return -1; - } - - /* Compare each keyword. */ - compare_result = 0; - keyword_cache_1 = file_1->details->compare_by_emblem_cache->emblem_keywords; - keyword_cache_2 = file_2->details->compare_by_emblem_cache->emblem_keywords; - for (; *keyword_cache_1 != '\0' && *keyword_cache_2 != '\0';) { - compare_result = eel_strcoll (keyword_cache_1, keyword_cache_2); - if (compare_result != 0) { - return compare_result; - } - - /* Advance to the next keyword */ - length = strlen (keyword_cache_1); - keyword_cache_1 += length + 1; - keyword_cache_2 += length + 1; - } - - - /* One or both is now NULL. */ - if (*keyword_cache_1 != '\0') { - g_assert (*keyword_cache_2 == '\0'); - return -1; - } else if (*keyword_cache_2 != '\0') { - return +1; - } - - return 0; -} - -static int -compare_by_type (NautilusFile *file_1, NautilusFile *file_2) -{ - gboolean is_directory_1; - gboolean is_directory_2; - char *type_string_1; - char *type_string_2; - int result; - - /* Directories go first. Then, if mime types are identical, - * don't bother getting strings (for speed). This assumes - * that the string is dependent entirely on the mime type, - * which is true now but might not be later. - */ - is_directory_1 = nautilus_file_is_directory (file_1); - is_directory_2 = nautilus_file_is_directory (file_2); - - if (is_directory_1 && is_directory_2) { - return 0; - } - - if (is_directory_1) { - return -1; - } - - if (is_directory_2) { - return +1; - } - - if (file_1->details->info != NULL - && file_2->details->info != NULL - && eel_strcmp (file_1->details->info->mime_type, - file_2->details->info->mime_type) == 0) { - return 0; - } - - type_string_1 = nautilus_file_get_type_as_string (file_1); - type_string_2 = nautilus_file_get_type_as_string (file_2); - - result = eel_strcoll (type_string_1, type_string_2); - - g_free (type_string_1); - g_free (type_string_2); - - return result; -} - -static int -compare_by_modification_time (NautilusFile *file_1, NautilusFile *file_2) -{ - /* Sort order: - * Files with newer times. - * Files with older times. - * Files with "unknowable" times. - * Files with unknown times. - */ - - Knowledge time_known_1, time_known_2; - time_t time_1, time_2; - - time_known_1 = get_modification_time (file_1, &time_1); - time_known_2 = get_modification_time (file_2, &time_2); - - if (time_known_1 < time_known_2) { - return -1; - } - if (time_known_1 > time_known_2) { - return +1; - } - - if (time_1 > time_2) { - return -1; - } - if (time_1 < time_2) { - return +1; - } - - return 0; -} - -static int -compare_by_full_path (NautilusFile *file_1, NautilusFile *file_2) -{ - int compare; - - compare = compare_by_directory_name (file_1, file_2); - if (compare != 0) { - return compare; - } - return compare_by_name (file_1, file_2); -} - -static int -nautilus_file_compare_for_sort_internal (NautilusFile *file_1, - NautilusFile *file_2, - NautilusFileSortType sort_type) -{ - int compare; - - g_return_val_if_fail (NAUTILUS_IS_FILE (file_1), 0); - g_return_val_if_fail (NAUTILUS_IS_FILE (file_2), 0); - - switch (sort_type) { - case NAUTILUS_FILE_SORT_BY_NAME: - compare = compare_by_name (file_1, file_2); - if (compare != 0) { - return compare; - } - return compare_by_directory_name (file_1, file_2); - case NAUTILUS_FILE_SORT_BY_DIRECTORY: - return compare_by_full_path (file_1, file_2); - case NAUTILUS_FILE_SORT_BY_SIZE: - /* Compare directory sizes ourselves, then if necessary - * use GnomeVFS to compare file sizes. - */ - compare = compare_by_size (file_1, file_2); - if (compare != 0) { - return compare; - } - return compare_by_full_path (file_1, file_2); - case NAUTILUS_FILE_SORT_BY_TYPE: - /* GnomeVFS doesn't know about our special text for certain - * mime types, so we handle the mime-type sorting ourselves. - */ - compare = compare_by_type (file_1, file_2); - if (compare != 0) { - return compare; - } - return compare_by_full_path (file_1, file_2); - case NAUTILUS_FILE_SORT_BY_MTIME: - compare = compare_by_modification_time (file_1, file_2); - if (compare != 0) { - return compare; - } - return compare_by_full_path (file_1, file_2); - case NAUTILUS_FILE_SORT_BY_EMBLEMS: - /* GnomeVFS doesn't know squat about our emblems, so - * we handle comparing them here, before falling back - * to tie-breakers. - */ - compare = compare_by_emblems (file_1, file_2); - if (compare != 0) { - return compare; - } - return compare_by_full_path (file_1, file_2); - default: - g_return_val_if_fail (FALSE, 0); - } -} - -/** - * nautilus_file_compare_for_sort: - * @file_1: A file object - * @file_2: Another file object - * @sort_type: Sort criterion - * @directories_first: Put all directories before any non-directories - * @reversed: Reverse the order of the items, except that - * the directories_first flag is still respected. - * - * Return value: int < 0 if @file_1 should come before file_2 in a - * sorted list; int > 0 if @file_2 should come before file_1 in a - * sorted list; 0 if @file_1 and @file_2 are equal for this sort criterion. Note - * that each named sort type may actually break ties several ways, with the name - * of the sort criterion being the primary but not only differentiator. - **/ -int -nautilus_file_compare_for_sort (NautilusFile *file_1, - NautilusFile *file_2, - NautilusFileSortType sort_type, - gboolean directories_first, - gboolean reversed) -{ - int result; - gboolean is_directory_1, is_directory_2; - - if (directories_first) { - is_directory_1 = nautilus_file_is_directory (file_1); - is_directory_2 = nautilus_file_is_directory (file_2); - - if (is_directory_1 && !is_directory_2) { - return -1; - } - - if (is_directory_2 && !is_directory_1) { - return +1; - } - } - - result = nautilus_file_compare_for_sort_internal (file_1, file_2, sort_type); - - if (reversed) { - result = -result; - } - - return result; -} - -/** - * nautilus_file_compare_name: - * @file: A file object - * @pattern: A string we are comparing it with - * - * Return value: result of a comparison of the file name and the given pattern, - * using the same sorting order as sort by name. - **/ -int -nautilus_file_compare_name (NautilusFile *file, - const char *pattern) -{ - char *name; - int result; - - g_return_val_if_fail (pattern != NULL, -1); - - name = nautilus_file_get_name (file); - result = eel_strcoll (name, pattern); - g_free (name); - return result; -} - -gboolean -nautilus_file_is_hidden_file (NautilusFile *file) -{ - return nautilus_file_name_matches_hidden_pattern - (file->details->relative_uri); -} - -gboolean -nautilus_file_is_backup_file (NautilusFile *file) -{ - return nautilus_file_name_matches_backup_pattern - (file->details->relative_uri); -} - -gboolean -nautilus_file_is_metafile (NautilusFile *file) -{ - return nautilus_file_name_matches_metafile_pattern - (file->details->relative_uri); -} - -static gboolean -is_special_desktop_gmc_file (NautilusFile *file) -{ - static char *home_dir; - static int home_dir_len; - char buffer [1024]; - char *uri, *path; - int s; - - if (!nautilus_file_is_local (file)) { - return FALSE; - } - - if (strcmp (file->details->relative_uri, "Trash.gmc") == 0) { - return TRUE; - } - - if (nautilus_file_is_symbolic_link (file)) { - /* You would think that - * nautilus_file_get_symbolic_link_target_path would - * be useful here, but you would be wrong. The - * information kept around by NautilusFile is not - * available right now, and I have no clue how to fix - * this. On top of that, inode/device are not stored, - * so it is not possible to see if a link is a symlink - * to the home directory. sigh. -Miguel - */ - uri = nautilus_file_get_uri (file); - path = gnome_vfs_get_local_path_from_uri (uri); - if (path != NULL){ - s = readlink (path, buffer, sizeof (buffer)-1); - g_free (path); - } else { - s = -1; - } - g_free (uri); - - if (s == -1) { - return FALSE; - } - - buffer [s] = 0; - - if (home_dir == NULL) { - home_dir = g_strdup (g_get_home_dir ()); - home_dir_len = strlen (home_dir); - - if (home_dir != NULL && home_dir [home_dir_len-1] == '/') { - home_dir [home_dir_len-1] = 0; - home_dir_len--; - } - - } - if (home_dir != NULL) { - if (strcmp (home_dir, buffer) == 0) - return TRUE; - } - } - return FALSE; -} - -gboolean -nautilus_file_should_show (NautilusFile *file, - gboolean show_hidden, - gboolean show_backup) -{ - if (nautilus_file_is_in_desktop (file) && is_special_desktop_gmc_file (file)) { - return FALSE; - } - return (show_hidden || ! nautilus_file_is_hidden_file (file)) && - (show_backup || ! nautilus_file_is_backup_file (file)); -} - -gboolean -nautilus_file_is_in_desktop (NautilusFile *file) -{ - /* This handles visiting other people's desktops, but it can arguably - * be said that this might break and that we should lookup the passwd table. - */ - return strstr (file->details->directory->details->uri, "/.gnome-desktop") != NULL; -} - -static gboolean -filter_hidden_and_backup_partition_callback (gpointer data, - gpointer callback_data) -{ - NautilusFile *file; - FilterOptions options; - - file = NAUTILUS_FILE (data); - options = GPOINTER_TO_INT (callback_data); - - return nautilus_file_should_show (file, - options & SHOW_HIDDEN, - options & SHOW_BACKUP); -} - -GList * -nautilus_file_list_filter_hidden_and_backup (GList *files, - gboolean show_hidden, - gboolean show_backup) -{ - GList *filtered_files; - GList *removed_files; - - /* FIXME bugzilla.eazel.com 653: - * Eventually this should become a generic filtering thingy. - */ - - filtered_files = nautilus_file_list_copy (files); - filtered_files = eel_g_list_partition (filtered_files, - filter_hidden_and_backup_partition_callback, - GINT_TO_POINTER ((show_hidden ? SHOW_HIDDEN : 0) | - (show_backup ? SHOW_BACKUP : 0)), - &removed_files); - nautilus_file_list_free (removed_files); - - return filtered_files; -} - - - - -/* We use the file's URI for the metadata for files in a directory, - * but we use a hard-coded string for the metadata for the directory - * itself. - */ -static const char * -get_metadata_name (NautilusFile *file) -{ - if (nautilus_file_is_self_owned (file)) { - return FILE_NAME_FOR_DIRECTORY_METADATA; - } - return file->details->relative_uri; -} - -char * -nautilus_file_get_metadata (NautilusFile *file, - const char *key, - const char *default_metadata) -{ - g_return_val_if_fail (key != NULL, g_strdup (default_metadata)); - g_return_val_if_fail (key[0] != '\0', g_strdup (default_metadata)); - if (file == NULL) { - return g_strdup (default_metadata); - } - g_return_val_if_fail (NAUTILUS_IS_FILE (file), g_strdup (default_metadata)); - - return nautilus_directory_get_file_metadata - (file->details->directory, - get_metadata_name (file), - key, - default_metadata); -} - -GList * -nautilus_file_get_metadata_list (NautilusFile *file, - const char *list_key, - const char *list_subkey) -{ - g_return_val_if_fail (list_key != NULL, NULL); - g_return_val_if_fail (list_key[0] != '\0', NULL); - g_return_val_if_fail (list_subkey != NULL, NULL); - g_return_val_if_fail (list_subkey[0] != '\0', NULL); - if (file == NULL) { - return NULL; - } - g_return_val_if_fail (NAUTILUS_IS_FILE (file), NULL); - - return nautilus_directory_get_file_metadata_list - (file->details->directory, - get_metadata_name (file), - list_key, - list_subkey); -} - -void -nautilus_file_set_metadata (NautilusFile *file, - const char *key, - const char *default_metadata, - const char *metadata) -{ - char *icon_path; - char *local_path; - char *local_uri; - - g_return_if_fail (NAUTILUS_IS_FILE (file)); - g_return_if_fail (key != NULL); - g_return_if_fail (key[0] != '\0'); - - if (strcmp (key, NAUTILUS_METADATA_KEY_CUSTOM_ICON) == 0) { - if (nautilus_file_is_in_desktop (file) - && nautilus_file_is_local (file)) { - - local_uri = nautilus_file_get_uri (file); - local_path = gnome_vfs_get_local_path_from_uri (local_uri); - icon_path = gnome_vfs_get_local_path_from_uri (metadata); - - if (local_path != NULL && icon_path != NULL) { - gnome_metadata_set (local_path, "icon-filename", strlen (icon_path)+1, icon_path); - } - - g_free (icon_path); - g_free (local_path); - g_free (local_uri); - } - } - - nautilus_directory_set_file_metadata - (file->details->directory, - get_metadata_name (file), - key, - default_metadata, - metadata); -} - -void -nautilus_file_set_metadata_list (NautilusFile *file, - const char *list_key, - const char *list_subkey, - GList *list) -{ - g_return_if_fail (NAUTILUS_IS_FILE (file)); - g_return_if_fail (list_key != NULL); - g_return_if_fail (list_key[0] != '\0'); - g_return_if_fail (list_subkey != NULL); - g_return_if_fail (list_subkey[0] != '\0'); - - nautilus_directory_set_file_metadata_list - (file->details->directory, - get_metadata_name (file), - list_key, - list_subkey, - list); -} - - -gboolean -nautilus_file_get_boolean_metadata (NautilusFile *file, - const char *key, - gboolean default_metadata) -{ - g_return_val_if_fail (key != NULL, default_metadata); - g_return_val_if_fail (key[0] != '\0', default_metadata); - if (file == NULL) { - return default_metadata; - } - g_return_val_if_fail (NAUTILUS_IS_FILE (file), default_metadata); - - return nautilus_directory_get_boolean_file_metadata - (file->details->directory, - get_metadata_name (file), - key, - default_metadata); -} - -int -nautilus_file_get_integer_metadata (NautilusFile *file, - const char *key, - int default_metadata) -{ - g_return_val_if_fail (key != NULL, default_metadata); - g_return_val_if_fail (key[0] != '\0', default_metadata); - if (file == NULL) { - return default_metadata; - } - g_return_val_if_fail (NAUTILUS_IS_FILE (file), default_metadata); - - return nautilus_directory_get_integer_file_metadata - (file->details->directory, - get_metadata_name (file), - key, - default_metadata); -} - - -void -nautilus_file_set_boolean_metadata (NautilusFile *file, - const char *key, - gboolean default_metadata, - gboolean metadata) -{ - g_return_if_fail (NAUTILUS_IS_FILE (file)); - g_return_if_fail (key != NULL); - g_return_if_fail (key[0] != '\0'); - - nautilus_directory_set_boolean_file_metadata - (file->details->directory, - get_metadata_name (file), - key, - default_metadata, - metadata); -} - -void -nautilus_file_set_integer_metadata (NautilusFile *file, - const char *key, - int default_metadata, - int metadata) -{ - g_return_if_fail (NAUTILUS_IS_FILE (file)); - g_return_if_fail (key != NULL); - g_return_if_fail (key[0] != '\0'); - - nautilus_directory_set_integer_file_metadata - (file->details->directory, - get_metadata_name (file), - key, - default_metadata, - 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); - - 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; - } - } - - /* 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; - } - } - - name = gnome_vfs_unescape_string (file->details->relative_uri, "/"); - if (name != NULL) { - return name; - } - - /* Fall back to the escaped form if the unescaped form is no - * good. This is dangerous for people who code with the name, - * but convenient for people who just want to display it. - */ - return g_strdup (file->details->relative_uri); -} - -void -nautilus_file_monitor_add (NautilusFile *file, - gconstpointer client, - GList *attributes) -{ - g_return_if_fail (NAUTILUS_IS_FILE (file)); - g_return_if_fail (client != NULL); - - EEL_CALL_METHOD - (NAUTILUS_FILE_CLASS, file, - monitor_add, (file, client, attributes)); -} - -void -nautilus_file_monitor_remove (NautilusFile *file, - gconstpointer client) -{ - g_return_if_fail (NAUTILUS_IS_FILE (file)); - g_return_if_fail (client != NULL); - - EEL_CALL_METHOD - (NAUTILUS_FILE_CLASS, file, - monitor_remove, (file, client)); -} - - -/* Return the uri associated with the passed-in file, which may not be - * the actual uri if the file is an old-style gmc link or a nautilus - * xml link file. - */ -char * -nautilus_file_get_activation_uri (NautilusFile *file) -{ - g_return_val_if_fail (NAUTILUS_IS_FILE (file), NULL); - - if (!file->details->got_activation_uri) { - return NULL; - } - return file->details->activation_uri == NULL - ? nautilus_file_get_uri (file) - : g_strdup (file->details->activation_uri); -} - -/* Return the actual uri associated with the passed-in file. */ -char * -nautilus_file_get_uri (NautilusFile *file) -{ - GnomeVFSURI *vfs_uri; - char *uri; - - g_return_val_if_fail (NAUTILUS_IS_FILE (file), NULL); - - if (nautilus_file_is_self_owned (file)) { - return g_strdup (file->details->directory->details->uri); - } - - vfs_uri = nautilus_file_get_gnome_vfs_uri (file); - if (vfs_uri != NULL) { - uri = gnome_vfs_uri_to_string (vfs_uri, GNOME_VFS_URI_HIDE_NONE); - gnome_vfs_uri_unref (vfs_uri); - return uri; - } - - return g_strconcat (file->details->directory->details->uri, - "/", - file->details->relative_uri, - NULL); -} - -char * -nautilus_file_get_uri_scheme (NautilusFile *file) -{ - - g_return_val_if_fail (NAUTILUS_IS_FILE (file), NULL); - - if (file->details->directory == NULL || - file->details->directory->details->uri == NULL) { - return NULL; - } - - return eel_uri_get_scheme (file->details->directory->details->uri); -} - -gboolean -nautilus_file_get_date (NautilusFile *file, - NautilusDateType date_type, - time_t *date) -{ - if (date != NULL) { - *date = 0; - } - - g_return_val_if_fail (date_type == NAUTILUS_DATE_TYPE_CHANGED - || date_type == NAUTILUS_DATE_TYPE_ACCESSED - || date_type == NAUTILUS_DATE_TYPE_MODIFIED - || date_type == NAUTILUS_DATE_TYPE_PERMISSIONS_CHANGED, FALSE); - - if (file == NULL) { - return FALSE; - } - - g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE); - - return EEL_CALL_METHOD_WITH_RETURN_VALUE - (NAUTILUS_FILE_CLASS, file, - get_date, (file, date_type, date)); -} - -static char * -nautilus_file_get_where_string (NautilusFile *file) -{ - if (file == NULL) { - return NULL; - } - - g_return_val_if_fail (NAUTILUS_IS_FILE (file), NULL); - - return EEL_CALL_METHOD_WITH_RETURN_VALUE - (NAUTILUS_FILE_CLASS, file, - get_where_string, (file)); -} - -const char *TODAY_TIME_FORMATS [] = { - /* Today, use special word. - * strftime patterns preceeded with the widest - * possible resulting string for that pattern. - * - * Note to localizers: You can look at man strftime - * for details on the format, but you should only use - * the specifiers from the C standard, not extensions. - * These include "%" followed by one of - * "aAbBcdHIjmMpSUwWxXyYZ". There are two extensions - * in the Nautilus version of strftime that can be - * used (and match GNU extensions). Putting a "-" - * between the "%" and any numeric directive will turn - * off zero padding, and putting a "_" there will use - * space padding instead of zero padding. - */ - N_("today at 00:00:00 PM"), - N_("today at %-I:%M:%S %p"), - - N_("today at 00:00 PM"), - N_("today at %-I:%M %p"), - - N_("today, 00:00 PM"), - N_("today, %-I:%M %p"), - - N_("today"), - N_("today"), - - NULL -}; - -const char *YESTERDAY_TIME_FORMATS [] = { - /* Yesterday, use special word. - * Note to localizers: Same issues as "today" string. - */ - N_("yesterday at 00:00:00 PM"), - N_("yesterday at %-I:%M:%S %p"), - - N_("yesterday at 00:00 PM"), - N_("yesterday at %-I:%M %p"), - - N_("yesterday, 00:00 PM"), - N_("yesterday, %-I:%M %p"), - - N_("yesterday"), - N_("yesterday"), - - NULL -}; - -const char *CURRENT_WEEK_TIME_FORMATS [] = { - /* Current week, include day of week. - * Note to localizers: Same issues as "today" string. - * The width measurement templates correspond to - * the day/month name with the most letters. - */ - N_("Wednesday, September 00 0000 at 00:00:00 PM"), - N_("%A, %B %-d %Y at %-I:%M:%S %p"), - - N_("Mon, Oct 00 0000 at 00:00:00 PM"), - N_("%a, %b %-d %Y at %-I:%M:%S %p"), - - N_("Mon, Oct 00 0000 at 00:00 PM"), - N_("%a, %b %-d %Y at %-I:%M %p"), - - N_("Oct 00 0000 at 00:00 PM"), - N_("%b %-d %Y at %-I:%M %p"), - - N_("Oct 00 0000, 00:00 PM"), - N_("%b %-d %Y, %-I:%M %p"), - - N_("00/00/00, 00:00 PM"), - N_("%m/%-d/%y, %-I:%M %p"), - - N_("00/00/00"), - N_("%m/%d/%y"), - - NULL -}; - -static char * -nautilus_file_fit_date_as_string (NautilusFile *file, - NautilusDateType date_type, - int width, - NautilusWidthMeasureCallback measure_callback, - NautilusTruncateCallback truncate_callback, - void *measure_context) -{ - time_t file_time_raw; - struct tm *file_time; - const char **formats; - const char *width_template; - const char *format; - char *date_string; - char *result; - GDate *today; - GDate *file_date; - guint32 file_date_age; - int i; - - if (!nautilus_file_get_date (file, date_type, &file_time_raw)) { - return NULL; - } - - file_time = localtime (&file_time_raw); - file_date = eel_g_date_new_tm (file_time); - - today = g_date_new (); - g_date_set_time (today, time (NULL)); - - /* Overflow results in a large number; fine for our purposes. */ - file_date_age = g_date_julian (today) - g_date_julian (file_date); - - g_date_free (file_date); - g_date_free (today); - - /* Format varies depending on how old the date is. This minimizes - * the length (and thus clutter & complication) of typical dates - * while providing sufficient detail for recent dates to make - * them maximally understandable at a glance. Keep all format - * strings separate rather than combining bits & pieces for - * internationalization's sake. - */ - - if (file_date_age == 0) { - formats = TODAY_TIME_FORMATS; - } else if (file_date_age == 1) { - formats = YESTERDAY_TIME_FORMATS; - } else if (file_date_age < 7) { - formats = CURRENT_WEEK_TIME_FORMATS; - } else { - formats = CURRENT_WEEK_TIME_FORMATS; - } - - /* Find the date format that just fits the required width. Instead of measuring - * the resulting string width directly, measure the width of a template that represents - * the widest possible version of a date in a given format. This is done by using M, m - * and 0 for the variable letters/digits respectively. - */ - format = NULL; - - for (i = 0; ; i += 2) { - width_template = formats [i]; - if (width_template == NULL) { - /* no more formats left */ - g_assert (format != NULL); - - /* Can't fit even the shortest format -- return an ellipsized form in the - * shortest format - */ - - date_string = eel_strdup_strftime (format, file_time); - - if (truncate_callback == NULL) { - return date_string; - } - - result = (* truncate_callback) (date_string, width, measure_context); - g_free (date_string); - return result; - } - - format = formats [i + 1]; - - if (measure_callback == NULL) { - /* don't care about fitting the width */ - break; - } - - if ((* measure_callback) (width_template, measure_context) <= width) { - /* The template fits, this is the format we can fit. */ - break; - } - } - - return eel_strdup_strftime (format, file_time); - -} - -/** - * nautilus_file_fit_modified_date_as_string: - * - * Get a user-displayable string representing a file modification date, - * truncated to @width using the measuring and truncating callbacks. - * @file: NautilusFile representing the file in question. - * @width: The desired resulting string width. - * @measure_callback: The callback used to measure the string width. - * @truncate_callback: The callback used to truncate the string to a desired width. - * @measure_context: Data neede when measuring and truncating. - * - * Returns: Newly allocated string ready to display to the user. - * - **/ -char * -nautilus_file_fit_modified_date_as_string (NautilusFile *file, - int width, - NautilusWidthMeasureCallback measure_callback, - NautilusTruncateCallback truncate_callback, - void *measure_context) -{ - return nautilus_file_fit_date_as_string (file, NAUTILUS_DATE_TYPE_MODIFIED, - width, measure_callback, truncate_callback, measure_context); -} - -/** - * nautilus_file_get_date_as_string: - * - * Get a user-displayable string representing a file modification date. - * The caller is responsible for g_free-ing this string. - * @file: NautilusFile representing the file in question. - * - * Returns: Newly allocated string ready to display to the user. - * - **/ -static char * -nautilus_file_get_date_as_string (NautilusFile *file, NautilusDateType date_type) -{ - return nautilus_file_fit_date_as_string (file, date_type, - 0, NULL, NULL, NULL); -} - -static NautilusSpeedTradeoffValue show_directory_item_count; -static NautilusSpeedTradeoffValue show_text_in_icons; - -static void -show_text_in_icons_changed_callback (gpointer callback_data) -{ - show_text_in_icons = nautilus_preferences_get_integer (NAUTILUS_PREFERENCES_SHOW_TEXT_IN_ICONS); -} - -static void -show_directory_item_count_changed_callback (gpointer callback_data) -{ - show_directory_item_count = nautilus_preferences_get_integer (NAUTILUS_PREFERENCES_SHOW_DIRECTORY_ITEM_COUNTS); -} - -static gboolean -get_speed_tradeoff_preference_for_file (NautilusFile *file, NautilusSpeedTradeoffValue value) -{ - g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE); - - if (value == NAUTILUS_SPEED_TRADEOFF_ALWAYS) { - return TRUE; - } - - if (value == NAUTILUS_SPEED_TRADEOFF_NEVER) { - return FALSE; - } - - g_assert (value == NAUTILUS_SPEED_TRADEOFF_LOCAL_ONLY); - return nautilus_file_is_local (file); -} - -gboolean -nautilus_file_should_show_directory_item_count (NautilusFile *file) -{ - static gboolean show_directory_item_count_callback_added = FALSE; - - g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE); - - /* Add the callback once for the life of our process */ - if (!show_directory_item_count_callback_added) { - nautilus_preferences_add_callback (NAUTILUS_PREFERENCES_SHOW_DIRECTORY_ITEM_COUNTS, - show_directory_item_count_changed_callback, - NULL); - show_directory_item_count_callback_added = TRUE; - - /* Peek for the first time */ - show_directory_item_count_changed_callback (NULL); - } - - return get_speed_tradeoff_preference_for_file (file, show_directory_item_count); -} - -gboolean -nautilus_file_should_get_top_left_text (NautilusFile *file) -{ - static gboolean show_text_in_icons_callback_added = FALSE; - - g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE); - - /* Add the callback once for the life of our process */ - if (!show_text_in_icons_callback_added) { - nautilus_preferences_add_callback (NAUTILUS_PREFERENCES_SHOW_TEXT_IN_ICONS, - show_text_in_icons_changed_callback, - NULL); - show_text_in_icons_callback_added = TRUE; - - /* Peek for the first time */ - show_text_in_icons_changed_callback (NULL); - } - - if (show_text_in_icons == NAUTILUS_SPEED_TRADEOFF_ALWAYS) { - return TRUE; - } - - if (show_text_in_icons == NAUTILUS_SPEED_TRADEOFF_NEVER) { - return FALSE; - } - - return get_speed_tradeoff_preference_for_file (file, show_text_in_icons); -} - -/** - * nautilus_file_get_directory_item_count - * - * Get the number of items in a directory. - * @file: NautilusFile representing a directory. - * @count: Place to put count. - * @count_unreadable: Set to TRUE (if non-NULL) if permissions prevent - * the item count from being read on this directory. Otherwise set to FALSE. - * - * Returns: TRUE if count is available. - * - **/ -gboolean -nautilus_file_get_directory_item_count (NautilusFile *file, - guint *count, - gboolean *count_unreadable) -{ - if (count != NULL) { - *count = 0; - } - if (count_unreadable != NULL) { - *count_unreadable = FALSE; - } - - g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE); - - if (!nautilus_file_is_directory (file)) { - return FALSE; - } - - if (!nautilus_file_should_show_directory_item_count (file)) { - return FALSE; - } - - return EEL_CALL_METHOD_WITH_RETURN_VALUE - (NAUTILUS_FILE_CLASS, file, - get_item_count, (file, count, count_unreadable)); -} - -/** - * nautilus_file_get_deep_counts - * - * Get the statistics about items inside a directory. - * @file: NautilusFile representing a directory or file. - * @directory_count: Place to put count of directories inside. - * @files_count: Place to put count of files inside. - * @unreadable_directory_count: Number of directories encountered - * that were unreadable. - * @total_size: Total size of all files and directories visited. - * - * Returns: Status to indicate whether sizes are available. - * - **/ -NautilusRequestStatus -nautilus_file_get_deep_counts (NautilusFile *file, - guint *directory_count, - guint *file_count, - guint *unreadable_directory_count, - GnomeVFSFileSize *total_size) -{ - if (directory_count != NULL) { - *directory_count = 0; - } - if (file_count != NULL) { - *file_count = 0; - } - if (unreadable_directory_count != NULL) { - *unreadable_directory_count = 0; - } - if (total_size != NULL) { - *total_size = 0; - } - - g_return_val_if_fail (NAUTILUS_IS_FILE (file), NAUTILUS_REQUEST_DONE); - - if (!nautilus_file_should_show_directory_item_count (file)) { - /* Set field so an existing value isn't treated as up-to-date - * when preference changes later. - */ - file->details->deep_counts_status = NAUTILUS_REQUEST_NOT_STARTED; - return file->details->deep_counts_status; - } - - return EEL_CALL_METHOD_WITH_RETURN_VALUE - (NAUTILUS_FILE_CLASS, file, - get_deep_counts, (file, - directory_count, - file_count, - unreadable_directory_count, - total_size)); -} - -void -nautilus_file_recompute_deep_counts (NautilusFile *file) -{ - if (file->details->deep_counts_status != NAUTILUS_REQUEST_IN_PROGRESS) { - file->details->deep_counts_status = NAUTILUS_REQUEST_NOT_STARTED; - if (file->details->directory != NULL) { - nautilus_directory_async_state_changed (file->details->directory); - } - } -} - -/** - * nautilus_file_get_directory_item_mime_types - * - * Get the list of mime-types present in a directory. - * @file: NautilusFile representing a directory. It is an error to - * call this function on a file that is not a directory. - * @mime_list: Place to put the list of mime-types. - * - * Returns: TRUE if mime-type list is available. - * - **/ -gboolean -nautilus_file_get_directory_item_mime_types (NautilusFile *file, - GList **mime_list) -{ - g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE); - g_return_val_if_fail (mime_list != NULL, FALSE); - - if (!nautilus_file_is_directory (file) - || !file->details->got_mime_list) { - *mime_list = NULL; - return FALSE; - } - - *mime_list = eel_g_str_list_copy (file->details->mime_list); - return TRUE; -} - -/** - * nautilus_file_get_size - * - * Get the file size. - * @file: NautilusFile representing the file in question. - * - * Returns: Size in bytes. - * - **/ -GnomeVFSFileSize -nautilus_file_get_size (NautilusFile *file) -{ - /* Before we have info on the file, we don't know the size. */ - return nautilus_file_info_missing (file, GNOME_VFS_FILE_INFO_FIELDS_SIZE) - ? 0 : file->details->info->size; -} - -/** - * nautilus_file_can_get_permissions: - * - * Check whether the permissions for a file are determinable. - * This might not be the case for files on non-UNIX file systems. - * - * @file: The file in question. - * - * Return value: TRUE if the permissions are valid. - */ -gboolean -nautilus_file_can_get_permissions (NautilusFile *file) -{ - return !nautilus_file_info_missing (file, GNOME_VFS_FILE_INFO_FIELDS_PERMISSIONS); -} - -/** - * nautilus_file_can_set_permissions: - * - * Check whether the current user is allowed to change - * the permissions of a file. - * - * @file: The file in question. - * - * Return value: TRUE if the current user can change the - * permissions of @file, FALSE otherwise. It's always possible - * that when you actually try to do it, you will fail. - */ -gboolean -nautilus_file_can_set_permissions (NautilusFile *file) -{ - uid_t user_id; - - /* Not allowed to set the permissions if we can't - * even read them. This can happen on non-UNIX file - * systems. - */ - if (!nautilus_file_can_get_permissions (file)) { - return FALSE; - } - - /* Check the user. */ - user_id = geteuid(); - - /* Owner is allowed to set permissions. */ - if (user_id == file->details->info->uid) { - return TRUE; - } - - /* Root is also allowed to set permissions. */ - if (user_id == 0) { - return TRUE; - } - - /* Nobody else is allowed. */ - return FALSE; -} - -GnomeVFSFilePermissions -nautilus_file_get_permissions (NautilusFile *file) -{ - g_return_val_if_fail (nautilus_file_can_get_permissions (file), 0); - - return file->details->info->permissions; -} - -static void -set_permissions_callback (GnomeVFSAsyncHandle *handle, - GnomeVFSResult result, - GnomeVFSFileInfo *new_info, - gpointer callback_data) -{ - Operation *op; - - op = callback_data; - g_assert (handle == op->handle); - - if (result == GNOME_VFS_OK && new_info != NULL) { - nautilus_file_update_info (op->file, new_info); - } - operation_complete (op, result); -} - -/** - * nautilus_file_set_permissions: - * - * Change a file's permissions. This should only be called if - * nautilus_file_can_set_permissions returned TRUE. - * - * @file: NautilusFile representing the file in question. - * @new_permissions: New permissions value. This is the whole - * set of permissions, not a delta. - **/ -void -nautilus_file_set_permissions (NautilusFile *file, - GnomeVFSFilePermissions new_permissions, - NautilusFileOperationCallback callback, - gpointer callback_data) -{ - Operation *op; - GnomeVFSURI *vfs_uri; - GnomeVFSFileInfo *partial_file_info; - - if (!nautilus_file_can_set_permissions (file)) { - /* Claim that something changed even if the permission change failed. - * This makes it easier for some clients who see the "reverting" - * to the old permissions as "changing back". - */ - nautilus_file_changed (file); - (* callback) (file, GNOME_VFS_ERROR_ACCESS_DENIED, callback_data); - return; - } - - /* Test the permissions-haven't-changed case explicitly - * because we don't want to send the file-changed signal if - * nothing changed. - */ - if (new_permissions == file->details->info->permissions) { - (* callback) (file, GNOME_VFS_OK, callback_data); - return; - } - - /* Set up a permission change operation. */ - op = operation_new (file, callback, callback_data); - - /* Change the file-on-disk permissions. */ - partial_file_info = gnome_vfs_file_info_new (); - partial_file_info->permissions = new_permissions; - vfs_uri = nautilus_file_get_gnome_vfs_uri (file); - gnome_vfs_async_set_file_info (&op->handle, - vfs_uri, partial_file_info, - GNOME_VFS_SET_FILE_INFO_PERMISSIONS, - (GNOME_VFS_FILE_INFO_GET_MIME_TYPE - | GNOME_VFS_FILE_INFO_FOLLOW_LINKS), - set_permissions_callback, op); - gnome_vfs_file_info_unref (partial_file_info); - gnome_vfs_uri_unref (vfs_uri); -} - -static char * -get_user_name_from_id (uid_t uid) -{ - struct passwd *password_info; - - /* No need to free result of getpwuid */ - password_info = getpwuid (uid); - - if (password_info == NULL) { - return NULL; - } - - return g_strdup (password_info->pw_name); -} - -static char * -get_real_name (struct passwd *user) -{ - char *part_before_comma, *capitalized_login_name, *real_name; - - if (user->pw_gecos == NULL) { - return NULL; - } - - part_before_comma = eel_str_strip_substring_and_after (user->pw_gecos, ","); - - capitalized_login_name = eel_str_capitalize (user->pw_name); - - if (capitalized_login_name == NULL) { - real_name = part_before_comma; - } else { - real_name = eel_str_replace_substring - (part_before_comma, "&", capitalized_login_name); - g_free (part_before_comma); - } - - - if (eel_str_is_empty (real_name) - || eel_strcmp (user->pw_name, real_name) == 0 - || eel_strcmp (capitalized_login_name, real_name) == 0) { - g_free (real_name); - real_name = NULL; - } - - g_free (capitalized_login_name); - - return real_name; -} - -static char * -get_user_and_real_name_from_id (uid_t uid) -{ - char *real_name, *user_and_real_name; - struct passwd *password_info; - - /* No need to free result of getpwuid */ - password_info = getpwuid (uid); - - if (password_info == NULL) { - return NULL; - } - - real_name = get_real_name (password_info); - if (real_name != NULL) { - user_and_real_name = g_strdup_printf - ("%s - %s", password_info->pw_name, real_name); - } else { - user_and_real_name = g_strdup (password_info->pw_name); - } - g_free (real_name); - - return user_and_real_name; -} - -static gboolean -get_group_id_from_group_name (const char *group_name, uid_t *gid) -{ - struct group *group; - - g_assert (gid != NULL); - - group = getgrnam (group_name); - - if (group == NULL) { - return FALSE; - } - - *gid = group->gr_gid; - - return TRUE; -} - -static gboolean -get_ids_from_user_name (const char *user_name, uid_t *uid, uid_t *gid) -{ - struct passwd *password_info; - - g_assert (uid != NULL || gid != NULL); - - password_info = getpwnam (user_name); - - if (password_info == NULL) { - return FALSE; - } - - if (uid != NULL) { - *uid = password_info->pw_uid; - } - - if (gid != NULL) { - *gid = password_info->pw_gid; - } - - return TRUE; -} - -static gboolean -get_user_id_from_user_name (const char *user_name, uid_t *id) -{ - return get_ids_from_user_name (user_name, id, NULL); -} - -static gboolean -get_group_id_from_user_name (const char *user_name, uid_t *id) -{ - return get_ids_from_user_name (user_name, NULL, id); -} - -static gboolean -get_id_from_digit_string (const char *digit_string, uid_t *id) -{ - long scanned_id; - - g_assert (id != NULL); - - /* Only accept string if it has one integer with nothing - * afterwards. - */ - if (sscanf (digit_string, "%ld%*s", &scanned_id) != 1) { - return FALSE; - } - *id = scanned_id; - return TRUE; -} - -/** - * nautilus_file_can_get_owner: - * - * Check whether the owner a file is determinable. - * This might not be the case for files on non-UNIX file systems. - * - * @file: The file in question. - * - * Return value: TRUE if the owner is valid. - */ -gboolean -nautilus_file_can_get_owner (NautilusFile *file) -{ - /* Before we have info on a file, the owner is unknown. */ - /* FIXME bugzilla.eazel.com 644: - * Can we trust the uid in the file info? Might - * there be garbage there? What will it do for non-local files? - */ - return !nautilus_file_info_missing (file, 0 /* FIXME bugzilla.eazel.com 644: GNOME_VFS_FILE_INFO_FIELDS_UID */); -} - -/** - * nautilus_file_get_owner_name: - * - * Get the user name of the file's owner. If the owner has no - * name, returns the userid as a string. The caller is responsible - * for g_free-ing this string. - * - * @file: The file in question. - * - * Return value: A newly-allocated string. - */ -char * -nautilus_file_get_owner_name (NautilusFile *file) -{ - return nautilus_file_get_owner_as_string (file, FALSE); -} - -/** - * nautilus_file_can_set_owner: - * - * Check whether the current user is allowed to change - * the owner of a file. - * - * @file: The file in question. - * - * Return value: TRUE if the current user can change the - * owner of @file, FALSE otherwise. It's always possible - * that when you actually try to do it, you will fail. - */ -gboolean -nautilus_file_can_set_owner (NautilusFile *file) -{ - /* Not allowed to set the owner if we can't - * even read it. This can happen on non-UNIX file - * systems. - */ - if (!nautilus_file_can_get_owner (file)) { - return FALSE; - } - - /* Only root is also allowed to set the owner. */ - return geteuid() == 0; -} - -static void -set_owner_and_group_callback (GnomeVFSAsyncHandle *handle, - GnomeVFSResult result, - GnomeVFSFileInfo *new_info, - gpointer callback_data) -{ - Operation *op; - - op = callback_data; - g_assert (handle == op->handle); - - if (result == GNOME_VFS_OK && new_info != NULL) { - nautilus_file_update_info (op->file, new_info); - } - operation_complete (op, result); -} - -static void -set_owner_and_group (NautilusFile *file, - uid_t owner, - uid_t group, - NautilusFileOperationCallback callback, - gpointer callback_data) -{ - Operation *op; - GnomeVFSURI *uri; - GnomeVFSFileInfo *partial_file_info; - - /* Set up a owner-change operation. */ - op = operation_new (file, callback, callback_data); - - /* Change the file-on-disk owner. */ - partial_file_info = gnome_vfs_file_info_new (); - partial_file_info->uid = owner; - partial_file_info->gid = group; - - uri = nautilus_file_get_gnome_vfs_uri (file); - gnome_vfs_async_set_file_info (&op->handle, - uri, partial_file_info, - GNOME_VFS_SET_FILE_INFO_OWNER, - (GNOME_VFS_FILE_INFO_GET_MIME_TYPE - | GNOME_VFS_FILE_INFO_FOLLOW_LINKS), - set_owner_and_group_callback, op); - gnome_vfs_file_info_unref (partial_file_info); - gnome_vfs_uri_unref (uri); -} - -/** - * nautilus_file_set_owner: - * - * Set the owner of a file. This will only have any effect if - * nautilus_file_can_set_owner returns TRUE. - * - * @file: The file in question. - * @user_name_or_id: The user name to set the owner to. - * If the string does not match any user name, and the - * string is an integer, the owner will be set to the - * userid represented by that integer. - * @callback: Function called when asynch owner change succeeds or fails. - * @callback_data: Parameter passed back with callback function. - */ -void -nautilus_file_set_owner (NautilusFile *file, - const char *user_name_or_id, - NautilusFileOperationCallback callback, - gpointer callback_data) -{ - uid_t new_id; - - if (!nautilus_file_can_set_owner (file)) { - /* Claim that something changed even if the permission - * change failed. This makes it easier for some - * clients who see the "reverting" to the old owner as - * "changing back". - */ - nautilus_file_changed (file); - (* callback) (file, GNOME_VFS_ERROR_ACCESS_DENIED, callback_data); - return; - } - - /* If no match treating user_name_or_id as name, try treating - * it as id. - */ - if (!get_user_id_from_user_name (user_name_or_id, &new_id) - && !get_id_from_digit_string (user_name_or_id, &new_id)) { - /* Claim that something changed even if the permission - * change failed. This makes it easier for some - * clients who see the "reverting" to the old owner as - * "changing back". - */ - nautilus_file_changed (file); - (* callback) (file, GNOME_VFS_ERROR_BAD_PARAMETERS, callback_data); - return; - } - - /* Test the owner-hasn't-changed case explicitly because we - * don't want to send the file-changed signal if nothing - * changed. - */ - if (new_id == file->details->info->uid) { - (* callback) (file, GNOME_VFS_OK, callback_data); - return; - } - - /* FIXME bugzilla.eazel.com 2427: - * We can't assume that the gid is already good/read, - * can we? Maybe we have to precede the set_file_info with a - * get_file_info to fix this? - */ - set_owner_and_group (file, - new_id, - file->details->info->gid, - callback, callback_data); -} - -/** - * nautilus_get_user_names: - * - * Get a list of user names. For users with a different associated - * "real name", the real name follows the standard user name, separated - * by a carriage return. The caller is responsible for freeing this list - * and its contents. - */ -GList * -nautilus_get_user_names (void) -{ - GList *list; - char *real_name, *name; - struct passwd *user; - - list = NULL; - - setpwent (); - - while ((user = getpwent ()) != NULL) { - real_name = get_real_name (user); - if (real_name != NULL) { - name = g_strconcat (user->pw_name, "\n", real_name, NULL); - } else { - name = g_strdup (user->pw_name); - } - g_free (real_name); - list = g_list_prepend (list, name); - } - - endpwent (); - - return eel_g_str_list_alphabetize (list); -} - -/** - * nautilus_file_can_get_group: - * - * Check whether the group a file is determinable. - * This might not be the case for files on non-UNIX file systems. - * - * @file: The file in question. - * - * Return value: TRUE if the group is valid. - */ -gboolean -nautilus_file_can_get_group (NautilusFile *file) -{ - /* Before we have info on a file, the group is unknown. */ - /* FIXME bugzilla.eazel.com 644: - * Can we trust the gid in the file info? Might - * there be garbage there? What will it do for non-local files? - */ - return !nautilus_file_info_missing (file, 0 /* FIXME bugzilla.eazel.com 644: GNOME_VFS_FILE_INFO_FIELDS_GID */); -} - -/** - * nautilus_file_get_group_name: - * - * Get the name of the file's group. If the group has no - * name, returns the groupid as a string. The caller is responsible - * for g_free-ing this string. - * - * @file: The file in question. - * - * Return value: A newly-allocated string. - **/ -char * -nautilus_file_get_group_name (NautilusFile *file) -{ - struct group *group_info; - - /* Before we have info on a file, the owner is unknown. */ - if (nautilus_file_info_missing (file, 0 /* FIXME bugzilla.eazel.com 644: GNOME_VFS_FILE_INFO_FIELDS_GID */)) { - return NULL; - } - - /* FIXME bugzilla.eazel.com 644: - * Can we trust the gid in the file info? Might - * there be garbage there? What will it do for non-local files? - */ - /* No need to free result of getgrgid */ - group_info = getgrgid (file->details->info->gid); - - if (group_info != NULL) { - return g_strdup (group_info->gr_name); - } - - /* In the oddball case that the group name has been set to an id for which - * there is no defined group, return the id in string form. - */ - return g_strdup_printf ("%d", file->details->info->gid); -} - -/** - * nautilus_file_can_set_group: - * - * Check whether the current user is allowed to change - * the group of a file. - * - * @file: The file in question. - * - * Return value: TRUE if the current user can change the - * group of @file, FALSE otherwise. It's always possible - * that when you actually try to do it, you will fail. - */ -gboolean -nautilus_file_can_set_group (NautilusFile *file) -{ - uid_t user_id; - - /* Not allowed to set the permissions if we can't - * even read them. This can happen on non-UNIX file - * systems. - */ - if (!nautilus_file_can_get_group (file)) { - return FALSE; - } - - /* Check the user. */ - user_id = geteuid(); - - /* Owner is allowed to set group (with restrictions). */ - if (user_id == file->details->info->uid) { - return TRUE; - } - - /* Root is also allowed to set group. */ - if (user_id == 0) { - return TRUE; - } - - /* Nobody else is allowed. */ - return FALSE; -} - -static gboolean -group_includes_user (struct group *group, const char *username) -{ - char *member; - int member_index; - uid_t user_gid; - - /* Check whether user is in group. Check not only member list, - * but also group id of username, since user is not explicitly - * listed in member list of own group. - */ - if (get_group_id_from_user_name (username, &user_gid)) { - if (user_gid == (uid_t) group->gr_gid) { - return TRUE; - } - } - - member_index = 0; - while ((member = (group->gr_mem [member_index++])) != NULL) { - if (strcmp (member, username) == 0) { - return TRUE; - } - } - - return FALSE; -} - -/* Get a list of group names, filtered to only the ones - * that contain the given username. If the username is - * NULL, returns a list of all group names. - */ -static GList * -nautilus_get_group_names_including (const char *username) -{ - GList *list; - struct group *group; - - list = NULL; - - setgrent (); - - while ((group = getgrent ()) != NULL) { - if (username != NULL && !group_includes_user (group, username)) { - continue; - } - - list = g_list_prepend (list, g_strdup (group->gr_name)); - } - - endgrent (); - - return eel_g_str_list_alphabetize (list); -} - -/** - * nautilus_get_group_names: - * - * Get a list of all group names. - */ -GList * -nautilus_get_group_names (void) -{ - return nautilus_get_group_names_including (NULL); -} - -/** - * nautilus_file_get_settable_group_names: - * - * Get a list of all group names that the current user - * can set the group of a specific file to. - * - * @file: The NautilusFile in question. - */ -GList * -nautilus_file_get_settable_group_names (NautilusFile *file) -{ - uid_t user_id; - char *user_name_string; - GList *result; - - if (!nautilus_file_can_set_group (file)) { - return NULL; - } - - /* Check the user. */ - user_id = geteuid(); - - if (user_id == 0) { - /* Root is allowed to set group to anything. */ - result = nautilus_get_group_names_including (NULL); - } else if (user_id == file->details->info->uid) { - /* Owner is allowed to set group to any that owner is member of. */ - user_name_string = get_user_name_from_id (user_id); - result = nautilus_get_group_names_including (user_name_string); - g_free (user_name_string); - } else { - g_warning ("unhandled case in nautilus_get_settable_group_names"); - result = NULL; - } - - return result; -} - -/** - * nautilus_file_set_group: - * - * Set the group of a file. This will only have any effect if - * nautilus_file_can_set_group returns TRUE. - * - * @file: The file in question. - * @group_name_or_id: The group name to set the owner to. - * If the string does not match any group name, and the - * string is an integer, the group will be set to the - * group id represented by that integer. - * @callback: Function called when asynch group change succeeds or fails. - * @callback_data: Parameter passed back with callback function. - */ -void -nautilus_file_set_group (NautilusFile *file, - const char *group_name_or_id, - NautilusFileOperationCallback callback, - gpointer callback_data) -{ - uid_t new_id; - - if (!nautilus_file_can_set_group (file)) { - /* Claim that something changed even if the group - * change failed. This makes it easier for some - * clients who see the "reverting" to the old group as - * "changing back". - */ - nautilus_file_changed (file); - (* callback) (file, GNOME_VFS_ERROR_ACCESS_DENIED, callback_data); - return; - } - - /* If no match treating group_name_or_id as name, try treating - * it as id. - */ - if (!get_group_id_from_group_name (group_name_or_id, &new_id) - && !get_id_from_digit_string (group_name_or_id, &new_id)) { - /* Claim that something changed even if the group - * change failed. This makes it easier for some - * clients who see the "reverting" to the old group as - * "changing back". - */ - nautilus_file_changed (file); - (* callback) (file, GNOME_VFS_ERROR_BAD_PARAMETERS, callback_data); - return; - } - - if (new_id == file->details->info->gid) { - (* callback) (file, GNOME_VFS_OK, callback_data); - return; - } - - /* FIXME bugzilla.eazel.com 2427: We can't assume that the gid is already good/read, - * can we? Maybe we have to precede the set_file_info with a - * get_file_info to fix this? - */ - set_owner_and_group (file, - file->details->info->uid, - new_id, - callback, callback_data); -} - -/** - * nautilus_file_get_octal_permissions_as_string: - * - * Get a user-displayable string representing a file's permissions - * as an octal number. The caller - * is responsible for g_free-ing this string. - * @file: NautilusFile representing the file in question. - * - * Returns: Newly allocated string ready to display to the user. - * - **/ -static char * -nautilus_file_get_octal_permissions_as_string (NautilusFile *file) -{ - GnomeVFSFilePermissions permissions; - - g_return_val_if_fail (NAUTILUS_IS_FILE (file), NULL); - - if (!nautilus_file_can_get_permissions (file)) { - return NULL; - } - - permissions = file->details->info->permissions; - return g_strdup_printf ("%03o", permissions); -} - -/** - * nautilus_file_get_permissions_as_string: - * - * Get a user-displayable string representing a file's permissions. The caller - * is responsible for g_free-ing this string. - * @file: NautilusFile representing the file in question. - * - * Returns: Newly allocated string ready to display to the user. - * - **/ -static char * -nautilus_file_get_permissions_as_string (NautilusFile *file) -{ - GnomeVFSFilePermissions permissions; - gboolean is_directory; - gboolean is_link; - gboolean suid, sgid, sticky; - - if (!nautilus_file_can_get_permissions (file)) { - return NULL; - } - - g_return_val_if_fail (NAUTILUS_IS_FILE (file), NULL); - - permissions = file->details->info->permissions; - is_directory = nautilus_file_is_directory (file); - is_link = nautilus_file_is_symbolic_link (file); - - /* We use ls conventions for displaying these three obscure flags */ - suid = permissions & GNOME_VFS_PERM_SUID; - sgid = permissions & GNOME_VFS_PERM_SGID; - sticky = permissions & GNOME_VFS_PERM_STICKY; - - return g_strdup_printf ("%c%c%c%c%c%c%c%c%c%c", - is_link ? 'l' : is_directory ? 'd' : '-', - permissions & GNOME_VFS_PERM_USER_READ ? 'r' : '-', - permissions & GNOME_VFS_PERM_USER_WRITE ? 'w' : '-', - permissions & GNOME_VFS_PERM_USER_EXEC - ? (suid ? 's' : 'x') - : (suid ? 'S' : '-'), - permissions & GNOME_VFS_PERM_GROUP_READ ? 'r' : '-', - permissions & GNOME_VFS_PERM_GROUP_WRITE ? 'w' : '-', - permissions & GNOME_VFS_PERM_GROUP_EXEC - ? (sgid ? 's' : 'x') - : (sgid ? 'S' : '-'), - permissions & GNOME_VFS_PERM_OTHER_READ ? 'r' : '-', - permissions & GNOME_VFS_PERM_OTHER_WRITE ? 'w' : '-', - permissions & GNOME_VFS_PERM_OTHER_EXEC - ? (sticky ? 't' : 'x') - : (sticky ? 'T' : '-')); -} - -/** - * nautilus_file_get_owner_as_string: - * - * Get a user-displayable string representing a file's owner. The caller - * is responsible for g_free-ing this string. - * @file: NautilusFile representing the file in question. - * @include_real_name: Whether or not to append the real name (if any) - * for this user after the user name. - * - * Returns: Newly allocated string ready to display to the user. - * - **/ -static char * -nautilus_file_get_owner_as_string (NautilusFile *file, gboolean include_real_name) -{ - char *user_name; - - /* Before we have info on a file, the owner is unknown. */ - /* FIXME bugzilla.eazel.com 644: - * Can we trust the uid in the file info? Might - * there be garbage there? What will it do for non-local files? - */ - if (nautilus_file_info_missing (file, 0 /* FIXME bugzilla.eazel.com 644: GNOME_VFS_FILE_INFO_FIELDS_UID */)) { - return NULL; - } - - if (include_real_name) { - user_name = get_user_and_real_name_from_id (file->details->info->uid); - } else { - user_name = get_user_name_from_id (file->details->info->uid); - } - - if (user_name != NULL) { - return user_name; - } - - /* In the oddball case that the user name has been set to an id for which - * there is no defined user, return the id in string form. - */ - return g_strdup_printf ("%d", file->details->info->uid); -} - -static char * -format_item_count_for_display (guint item_count, - gboolean includes_directories, - gboolean includes_files) -{ - g_return_val_if_fail (includes_directories || includes_files, NULL); - - if (item_count == 0) { - return g_strdup (includes_directories - ? (includes_files ? _("0 items") : _("0 folders")) - : _("0 files")); - } - if (item_count == 1) { - return g_strdup (includes_directories - ? (includes_files ? _("1 item") : _("1 folder")) - : _("1 file")); - } - return g_strdup_printf (includes_directories - ? (includes_files ? _("%u items") : _("%u folders")) - : _("%u files"), item_count); -} - -/** - * nautilus_file_get_size_as_string: - * - * Get a user-displayable string representing a file size. The caller - * is responsible for g_free-ing this string. The string is an item - * count for directories. - * @file: NautilusFile representing the file in question. - * - * Returns: Newly allocated string ready to display to the user. - * - **/ -static char * -nautilus_file_get_size_as_string (NautilusFile *file) -{ - guint item_count; - gboolean count_unreadable; - - if (file == NULL) { - return NULL; - } - - g_return_val_if_fail (NAUTILUS_IS_FILE (file), NULL); - - if (nautilus_file_is_directory (file)) { - if (!nautilus_file_get_directory_item_count (file, &item_count, &count_unreadable)) { - return NULL; - } - - return format_item_count_for_display (item_count, TRUE, TRUE); - } - - if (nautilus_file_info_missing (file, GNOME_VFS_FILE_INFO_FIELDS_SIZE)) { - return NULL; - } - return gnome_vfs_format_file_size_for_display (file->details->info->size); -} - -static char * -nautilus_file_get_deep_count_as_string_internal (NautilusFile *file, - gboolean report_size, - gboolean report_directory_count, - gboolean report_file_count) -{ - NautilusRequestStatus status; - guint directory_count; - guint file_count; - guint unreadable_count; - guint total_count; - GnomeVFSFileSize total_size; - - /* Must ask for size or some kind of count, but not both. */ - g_return_val_if_fail (!report_size || (!report_directory_count && !report_file_count), NULL); - g_return_val_if_fail (report_size || report_directory_count || report_file_count, NULL); - - if (file == NULL) { - return NULL; - } - - g_return_val_if_fail (NAUTILUS_IS_FILE (file), NULL); - g_return_val_if_fail (nautilus_file_is_directory (file), NULL); - - status = nautilus_file_get_deep_counts - (file, &directory_count, &file_count, &unreadable_count, &total_size); - - /* Check whether any info is available. */ - if (status == NAUTILUS_REQUEST_NOT_STARTED) { - return NULL; - } - - total_count = file_count + directory_count; - - if (total_count == 0) { - switch (status) { - case NAUTILUS_REQUEST_IN_PROGRESS: - /* Don't return confident "zero" until we're finished looking, - * because of next case. - */ - return NULL; - case NAUTILUS_REQUEST_DONE: - /* Don't return "zero" if we there were contents but we couldn't read them. */ - if (unreadable_count != 0) { - return NULL; - } - default: break; - } - } - - /* Note that we don't distinguish the "everything was readable" case - * from the "some things but not everything was readable" case here. - * Callers can distinguish them using nautilus_file_get_deep_counts - * directly if desired. - */ - if (report_size) { - return gnome_vfs_format_file_size_for_display (total_size); - } - - return format_item_count_for_display (report_directory_count - ? (report_file_count ? total_count : directory_count) - : file_count, - report_directory_count, report_file_count); -} - -/** - * nautilus_file_get_deep_size_as_string: - * - * Get a user-displayable string representing the size of all contained - * items (only makes sense for directories). The caller - * is responsible for g_free-ing this string. - * @file: NautilusFile representing the file in question. - * - * Returns: Newly allocated string ready to display to the user. - * - **/ -static char * -nautilus_file_get_deep_size_as_string (NautilusFile *file) -{ - return nautilus_file_get_deep_count_as_string_internal (file, TRUE, FALSE, FALSE); -} - -/** - * nautilus_file_get_deep_total_count_as_string: - * - * Get a user-displayable string representing the count of all contained - * items (only makes sense for directories). The caller - * is responsible for g_free-ing this string. - * @file: NautilusFile representing the file in question. - * - * Returns: Newly allocated string ready to display to the user. - * - **/ -static char * -nautilus_file_get_deep_total_count_as_string (NautilusFile *file) -{ - return nautilus_file_get_deep_count_as_string_internal (file, FALSE, TRUE, TRUE); -} - -/** - * nautilus_file_get_deep_file_count_as_string: - * - * Get a user-displayable string representing the count of all contained - * items, not including directories. It only makes sense to call this - * function on a directory. The caller - * is responsible for g_free-ing this string. - * @file: NautilusFile representing the file in question. - * - * Returns: Newly allocated string ready to display to the user. - * - **/ -static char * -nautilus_file_get_deep_file_count_as_string (NautilusFile *file) -{ - return nautilus_file_get_deep_count_as_string_internal (file, FALSE, FALSE, TRUE); -} - -/** - * nautilus_file_get_deep_directory_count_as_string: - * - * Get a user-displayable string representing the count of all contained - * directories. It only makes sense to call this - * function on a directory. The caller - * is responsible for g_free-ing this string. - * @file: NautilusFile representing the file in question. - * - * Returns: Newly allocated string ready to display to the user. - * - **/ -static char * -nautilus_file_get_deep_directory_count_as_string (NautilusFile *file) -{ - return nautilus_file_get_deep_count_as_string_internal (file, FALSE, TRUE, FALSE); -} - -/** - * nautilus_file_get_string_attribute: - * - * Get a user-displayable string from a named attribute. Use g_free to - * free this string. If the value is unknown, returns NULL. You can call - * nautilus_file_get_string_attribute_with_default if you want a non-NULL - * default. - * - * @file: NautilusFile representing the file in question. - * @attribute_name: The name of the desired attribute. The currently supported - * set includes "name", "type", "mime_type", "size", "deep_size", "deep_directory_count", - * "deep_file_count", "deep_total_count", "date_modified", "date_changed", "date_accessed", - * "date_permissions", "owner", "group", "permissions", "octal_permissions", "uri", "where", - * "link_target". - * - * Returns: Newly allocated string ready to display to the user, or NULL - * if the value is unknown or @attribute_name is not supported. - * - **/ -char * -nautilus_file_get_string_attribute (NautilusFile *file, const char *attribute_name) -{ - /* FIXME bugzilla.eazel.com 646: - * Use hash table and switch statement or function pointers for speed? - */ - - if (strcmp (attribute_name, "name") == 0) { - return nautilus_file_get_name (file); - } - if (strcmp (attribute_name, "type") == 0) { - return nautilus_file_get_type_as_string (file); - } - if (strcmp (attribute_name, "mime_type") == 0) { - return nautilus_file_get_mime_type (file); - } - if (strcmp (attribute_name, "size") == 0) { - return nautilus_file_get_size_as_string (file); - } - if (strcmp (attribute_name, "deep_size") == 0) { - return nautilus_file_get_deep_size_as_string (file); - } - if (strcmp (attribute_name, "deep_file_count") == 0) { - return nautilus_file_get_deep_file_count_as_string (file); - } - if (strcmp (attribute_name, "deep_directory_count") == 0) { - return nautilus_file_get_deep_directory_count_as_string (file); - } - if (strcmp (attribute_name, "deep_total_count") == 0) { - return nautilus_file_get_deep_total_count_as_string (file); - } - if (strcmp (attribute_name, "date_modified") == 0) { - return nautilus_file_get_date_as_string (file, - NAUTILUS_DATE_TYPE_MODIFIED); - } - if (strcmp (attribute_name, "date_changed") == 0) { - return nautilus_file_get_date_as_string (file, - NAUTILUS_DATE_TYPE_CHANGED); - } - if (strcmp (attribute_name, "date_accessed") == 0) { - return nautilus_file_get_date_as_string (file, - NAUTILUS_DATE_TYPE_ACCESSED); - } - if (strcmp (attribute_name, "date_permissions") == 0) { - return nautilus_file_get_date_as_string (file, - NAUTILUS_DATE_TYPE_PERMISSIONS_CHANGED); - } - if (strcmp (attribute_name, "permissions") == 0) { - return nautilus_file_get_permissions_as_string (file); - } - if (strcmp (attribute_name, "octal_permissions") == 0) { - return nautilus_file_get_octal_permissions_as_string (file); - } - if (strcmp (attribute_name, "owner") == 0) { - return nautilus_file_get_owner_as_string (file, TRUE); - } - if (strcmp (attribute_name, "group") == 0) { - return nautilus_file_get_group_name (file); - } - if (strcmp (attribute_name, "uri") == 0) { - return nautilus_file_get_uri (file); - } - if (strcmp (attribute_name, "where") == 0) { - return nautilus_file_get_where_string (file); - } - if (strcmp (attribute_name, "link_target") == 0) { - return nautilus_file_get_symbolic_link_target_path (file); - } - - return NULL; -} - -/** - * nautilus_file_get_string_attribute_with_default: - * - * Get a user-displayable string from a named attribute. Use g_free to - * free this string. If the value is unknown, returns a string representing - * the unknown value, which varies with attribute. You can call - * nautilus_file_get_string_attribute if you want NULL instead of a default - * result. - * - * @file: NautilusFile representing the file in question. - * @attribute_name: The name of the desired attribute. See the description of - * nautilus_file_get_string for the set of available attributes. - * - * Returns: Newly allocated string ready to display to the user, or a string - * such as "unknown" if the value is unknown or @attribute_name is not supported. - * - **/ -char * -nautilus_file_get_string_attribute_with_default (NautilusFile *file, const char *attribute_name) -{ - char *result; - guint item_count; - gboolean count_unreadable; - NautilusRequestStatus status; - - result = nautilus_file_get_string_attribute (file, attribute_name); - - if (result == NULL) { - /* Supply default values for the ones we know about. */ - /* FIXME bugzilla.eazel.com 646: - * Use hash table and switch statement or function pointers for speed? - */ - if (strcmp (attribute_name, "size") == 0) { - if (!nautilus_file_should_show_directory_item_count (file)) { - result = g_strdup ("--"); - } else { - count_unreadable = FALSE; - if (nautilus_file_is_directory (file)) { - nautilus_file_get_directory_item_count (file, &item_count, &count_unreadable); - } - - result = g_strdup (count_unreadable ? _("? items") : "..."); - } - } else if (strcmp (attribute_name, "deep_size") == 0) { - status = nautilus_file_get_deep_counts (file, NULL, NULL, NULL, NULL); - if (status == NAUTILUS_REQUEST_DONE) { - /* This means no contents at all were readable */ - return g_strdup (_("? bytes")); - } - return g_strdup ("..."); - } else if (strcmp (attribute_name, "deep_file_count") == 0 - || strcmp (attribute_name, "deep_directory_count") == 0 - || strcmp (attribute_name, "deep_total_count") == 0) { - status = nautilus_file_get_deep_counts (file, NULL, NULL, NULL, NULL); - if (status == NAUTILUS_REQUEST_DONE) { - /* This means no contents at all were readable */ - return g_strdup (_("? items")); - } - return g_strdup ("..."); - } else if (strcmp (attribute_name, "type") == 0) { - result = g_strdup (_("unknown type")); - } else if (strcmp (attribute_name, "mime_type") == 0) { - result = g_strdup (_("unknown MIME type")); - } else { - /* Fallback, use for both unknown attributes and attributes - * for which we have no more appropriate default. - */ - result = g_strdup (_("unknown")); - } - } - - return result; -} - -/** - * get_description: - * - * Get a user-displayable string representing a file type. The caller - * is responsible for g_free-ing this string. - * @file: NautilusFile representing the file in question. - * - * Returns: Newly allocated string ready to display to the user. - * - **/ - -static const char * -get_description (NautilusFile *file) -{ - const char *mime_type, *description; - - g_assert (NAUTILUS_IS_FILE (file)); - - if (file->details->info == NULL) { - return NULL; - } - - mime_type = file->details->info->mime_type; - if (eel_str_is_empty (mime_type)) { - return NULL; - } - - if (g_strcasecmp (mime_type, GNOME_VFS_MIME_TYPE_UNKNOWN) == 0 - && nautilus_file_is_executable (file)) { - return _("program"); - } - - description = gnome_vfs_mime_get_description (mime_type); - if (!eel_str_is_empty (description)) { - return description; - } - - /* We want to update gnome-vfs/data/mime/gnome-vfs.keys to include - * English (& localizable) versions of every mime type anyone ever sees. - */ - if (g_strcasecmp (mime_type, "x-directory/normal") == 0) { - g_warning (_("Can't find description even for \"x-directory/normal\". This " - "probably means that your gnome-vfs.keys file is in the wrong place " - "or isn't being found for some other reason.")); - } else { - g_warning (_("No description found for mime type \"%s\" (file is \"%s\"), " - "tell aaron@eazel.com"), - mime_type, - file->details->relative_uri); - } - return mime_type; -} - -static char * -update_description_for_link (NautilusFile *file, const char *string) -{ - if (nautilus_file_is_symbolic_link (file)) { - g_assert (!nautilus_file_is_broken_symbolic_link (file)); - if (string == NULL) { - return g_strdup (_("link")); - } - /* Note to localizers: convert file type string for file - * (e.g. "folder", "plain text") to file type for symbolic link - * to that kind of file (e.g. "link to folder"). - */ - return g_strdup_printf (_("link to %s"), string); - } - - return g_strdup (string); -} - -static char * -nautilus_file_get_type_as_string (NautilusFile *file) -{ - if (file == NULL) { - return NULL; - } - - if (nautilus_file_is_broken_symbolic_link (file)) { - return g_strdup (_("link (broken)")); - } - - return update_description_for_link (file, get_description (file)); -} - -/** - * nautilus_file_get_file_type - * - * Return this file's type. - * @file: NautilusFile representing the file in question. - * - * Returns: The type. - * - **/ -GnomeVFSFileType -nautilus_file_get_file_type (NautilusFile *file) -{ - if (file == NULL) { - return GNOME_VFS_FILE_TYPE_UNKNOWN; - } - return EEL_CALL_METHOD_WITH_RETURN_VALUE - (NAUTILUS_FILE_CLASS, file, get_file_type, (file)); -} - -/** - * nautilus_file_get_mime_type - * - * Return this file's default mime type. - * @file: NautilusFile representing the file in question. - * - * Returns: The mime type. - * - **/ -char * -nautilus_file_get_mime_type (NautilusFile *file) -{ - if (file != NULL) { - g_return_val_if_fail (NAUTILUS_IS_FILE (file), NULL); - if (file->details->info != NULL - && file->details->info->mime_type != NULL) { - return g_strdup (file->details->info->mime_type); - } - } - return g_strdup (GNOME_VFS_MIME_TYPE_UNKNOWN); -} - -/** - * nautilus_file_is_mime_type - * - * Check whether a file is of a particular MIME type. - * @file: NautilusFile representing the file in question. - * @mime_type: The MIME-type string to test (e.g. "text/plain") - * - * Return value: TRUE if @mime_type exactly matches the - * file's MIME type. - * - **/ -gboolean -nautilus_file_is_mime_type (NautilusFile *file, const char *mime_type) -{ - g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE); - g_return_val_if_fail (mime_type != NULL, FALSE); - - if (file->details->info == NULL) { - return FALSE; - } - return eel_strcasecmp (file->details->info->mime_type, - mime_type) == 0; -} - -/** - * nautilus_file_get_emblem_names - * - * Return the list of names of emblems that this file should display, - * in canonical order. - * @file: NautilusFile representing the file in question. - * - * Returns: A list of emblem names. - * - **/ -GList * -nautilus_file_get_emblem_names (NautilusFile *file) -{ - if (file == NULL) { - return NULL; - } - - g_return_val_if_fail (NAUTILUS_IS_FILE (file), NULL); - - return prepend_automatic_emblem_names - (file, nautilus_file_get_keywords (file)); -} - -static GList * -sort_keyword_list_and_remove_duplicates (GList *keywords) -{ - GList *p; - GList *duplicate_link; - - if (keywords != NULL) { - keywords = eel_g_str_list_alphabetize (keywords); - - p = keywords; - while (p->next != NULL) { - if (strcmp ((const char *) p->data, (const char *) p->next->data) == 0) { - duplicate_link = p->next; - keywords = g_list_remove_link (keywords, duplicate_link); - eel_g_list_free_deep (duplicate_link); - } else { - p = p->next; - } - } - } - - return keywords; -} - -/** - * nautilus_file_get_keywords - * - * Return this file's keywords. - * @file: NautilusFile representing the file in question. - * - * Returns: A list of keywords. - * - **/ -GList * -nautilus_file_get_keywords (NautilusFile *file) -{ - GList *keywords; - - if (file == NULL) { - return NULL; - } - - g_return_val_if_fail (NAUTILUS_IS_FILE (file), NULL); - - /* Put all the keywords into a list. */ - keywords = nautilus_file_get_metadata_list - (file, "keyword", "name"); - - return sort_keyword_list_and_remove_duplicates (keywords); -} - -/** - * nautilus_file_set_keywords - * - * Change this file's keywords. - * @file: NautilusFile representing the file in question. - * @keywords: New set of keywords (a GList of strings). - * - **/ -void -nautilus_file_set_keywords (NautilusFile *file, GList *keywords) -{ - GList *canonical_keywords; - - /* Invalidate the emblem compare cache */ - g_free (file->details->compare_by_emblem_cache); - file->details->compare_by_emblem_cache = NULL; - - g_return_if_fail (NAUTILUS_IS_FILE (file)); - - canonical_keywords = sort_keyword_list_and_remove_duplicates - (g_list_copy (keywords)); - nautilus_file_set_metadata_list - (file, "keyword", "name", canonical_keywords); - g_list_free (canonical_keywords); -} - -/** - * nautilus_file_is_symbolic_link - * - * Check if this file is a symbolic link. - * @file: NautilusFile representing the file in question. - * - * Returns: True if the file is a symbolic link. - * - **/ -gboolean -nautilus_file_is_symbolic_link (NautilusFile *file) -{ - return nautilus_file_info_missing (file, GNOME_VFS_FILE_INFO_FIELDS_FLAGS) - ? FALSE : (file->details->info->flags & GNOME_VFS_FILE_FLAGS_SYMLINK); -} - -/** - * nautilus_file_is_broken_symbolic_link - * - * Check if this file is a symbolic link with a missing target. - * @file: NautilusFile representing the file in question. - * - * Returns: True if the file is a symbolic link with a missing target. - * - **/ -gboolean -nautilus_file_is_broken_symbolic_link (NautilusFile *file) -{ - if (file == NULL) { - return FALSE; - } - - g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE); - - /* Non-broken symbolic links return the target's type for get_file_type. */ - return nautilus_file_get_file_type (file) == GNOME_VFS_FILE_TYPE_SYMBOLIC_LINK; -} - -/** - * nautilus_file_get_symbolic_link_target_path - * - * Get the file path of the target of a symbolic link. It is an error - * to call this function on a file that isn't a symbolic link. - * @file: NautilusFile representing the symbolic link in question. - * - * Returns: newly-allocated copy of the file path of the target of the symbolic link. - */ -char * -nautilus_file_get_symbolic_link_target_path (NautilusFile *file) -{ - g_return_val_if_fail (nautilus_file_is_symbolic_link (file), NULL); - - return nautilus_file_info_missing (file, GNOME_VFS_FILE_INFO_FIELDS_SYMLINK_NAME) - ? NULL - : g_strdup (file->details->info->symlink_name); -} - -/** - * nautilus_file_is_nautilus_link - * - * Check if this file is a nautilus link. - * @file: NautilusFile representing the file in question. - * - * Returns: True if the file is a nautilus link. - * - **/ -gboolean -nautilus_file_is_nautilus_link (NautilusFile *file) -{ - return nautilus_file_is_mime_type (file, "application/x-nautilus-link"); -} - -/** - * nautilus_file_is_gmc_url - * - * Check if this file is a gmc url - * @file: NautilusFile representing the file in question. - * - * Returns: True if the file is a gmc url - * - **/ -gboolean -nautilus_file_is_gmc_url (NautilusFile *file) -{ - return strncmp (file->details->relative_uri, "url", 3) == 0 - && nautilus_file_is_in_desktop (file); -} - -/** - * nautilus_file_is_directory - * - * Check if this file is a directory. - * @file: NautilusFile representing the file in question. - * - * Returns: TRUE if @file is a directory. - * - **/ -gboolean -nautilus_file_is_directory (NautilusFile *file) -{ - return nautilus_file_get_file_type (file) == GNOME_VFS_FILE_TYPE_DIRECTORY; -} - -/** - * nautilus_file_is_in_trash - * - * Check if this file is a file in trash. - * @file: NautilusFile representing the file in question. - * - * Returns: TRUE if @file is in a trash. - * - **/ -gboolean -nautilus_file_is_in_trash (NautilusFile *file) -{ - g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE); - - return eel_uri_is_in_trash (file->details->directory->details->uri); -} - -GnomeVFSResult -nautilus_file_get_file_info_result (NautilusFile *file) -{ - if (!file->details->get_info_failed) { - return GNOME_VFS_OK; - } - - return file->details->get_info_error; -} - -/** - * nautilus_file_contains_text - * - * Check if this file contains text. - * This is private and is used to decide whether or not to read the top left text. - * @file: NautilusFile representing the file in question. - * - * Returns: TRUE if @file has a text MIME type. - * - **/ -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; -} - -/** - * nautilus_file_is_executable - * - * Check if this file is executable at all. - * @file: NautilusFile representing the file in question. - * - * Returns: TRUE if any of the execute bits are set. FALSE if - * not, or if the permissions are unknown. - * - **/ -gboolean -nautilus_file_is_executable (NautilusFile *file) -{ - if (!nautilus_file_can_get_permissions (file)) { - /* File's permissions field is not valid. - * Can't access specific permissions, so return FALSE. - */ - return FALSE; - } - - return (file->details->info->permissions - & (GNOME_VFS_PERM_USER_EXEC - | GNOME_VFS_PERM_GROUP_EXEC - | GNOME_VFS_PERM_OTHER_EXEC)) != 0; -} - -/** - * nautilus_file_get_top_left_text - * - * Get the text from the top left of the file. - * @file: NautilusFile representing the file in question. - * - * Returns: NULL if there is no text readable, otherwise, the text. - * - **/ -char * -nautilus_file_get_top_left_text (NautilusFile *file) -{ - g_return_val_if_fail (NAUTILUS_IS_FILE (file), NULL); - - if (!nautilus_file_should_get_top_left_text (file)) { - return NULL; - } - - /* Show " ..." in the file until we read the contents in. */ - if (!file->details->got_top_left_text) { - if (nautilus_file_contains_text (file)) { - return g_strdup (" ..."); - } - return NULL; - } - - /* Show what we read in. */ - return g_strdup (file->details->top_left_text); -} - -void -nautilus_file_mark_gone (NautilusFile *file) -{ - NautilusDirectory *directory; - - g_return_if_fail (!file->details->is_gone); - - file->details->is_gone = TRUE; - - update_links_if_target (file); - - /* Let the directory know it's gone. */ - directory = file->details->directory; - if (!nautilus_file_is_self_owned (file)) { - nautilus_directory_remove_file (directory, file); - } - - /* Drop away all the old file information. */ - if (file->details->info != NULL) { - gnome_vfs_file_info_unref (file->details->info); - file->details->info = NULL; - } - - /* FIXME bugzilla.eazel.com 2429: - * Maybe we can get rid of the name too eventually, but - * for now that would probably require too many if statements - * everywhere anyone deals with the name. Maybe we can give it - * a hard-coded "<deleted>" name or something. - */ -} - -/** - * nautilus_file_changed - * - * Notify the user that this file has changed. - * @file: NautilusFile representing the file in question. - **/ -void -nautilus_file_changed (NautilusFile *file) -{ - GList fake_list; - - g_return_if_fail (NAUTILUS_IS_FILE (file)); - - if (nautilus_file_is_self_owned (file)) { - nautilus_file_emit_changed (file); - } else { - fake_list.data = file; - fake_list.next = NULL; - fake_list.prev = NULL; - nautilus_directory_emit_change_signals - (file->details->directory, &fake_list); - } -} - -/** - * nautilus_file_updated_deep_count_in_progress - * - * Notify clients that a newer deep count is available for - * the directory in question. - */ -void -nautilus_file_updated_deep_count_in_progress (NautilusFile *file) { - GList *link_files, *node; - - g_assert (NAUTILUS_IS_FILE (file)); - g_assert (nautilus_file_is_directory (file)); - - /* Send out a signal. */ - gtk_signal_emit (GTK_OBJECT (file), signals[UPDATED_DEEP_COUNT_IN_PROGRESS], file); - - /* Tell link files pointing to this object about the change. */ - link_files = get_link_files (file); - for (node = link_files; node != NULL; node = node->next) { - nautilus_file_updated_deep_count_in_progress (NAUTILUS_FILE (node->data)); - } - nautilus_file_list_free (link_files); -} - -/** - * nautilus_file_emit_changed - * - * Emit a file changed signal. - * This can only be called by the directory, since the directory - * also has to emit a files_changed signal. - * - * @file: NautilusFile representing the file in question. - **/ -void -nautilus_file_emit_changed (NautilusFile *file) -{ - GList *link_files, *p; - - g_assert (NAUTILUS_IS_FILE (file)); - - - /* Invalidate the emblem compare cache. -- This is not the cleanest - * place to do it but it is the one guaranteed bottleneck through - * which all change notifications pass. - */ - g_free (file->details->compare_by_emblem_cache); - file->details->compare_by_emblem_cache = NULL; - - /* Send out a signal. */ - gtk_signal_emit (GTK_OBJECT (file), signals[CHANGED], file); - - /* Tell link files pointing to this object about the change. */ - link_files = get_link_files (file); - for (p = link_files; p != NULL; p = p->next) { - nautilus_file_changed (NAUTILUS_FILE (p->data)); - } - nautilus_file_list_free (link_files); -} - -/** - * nautilus_file_is_gone - * - * Check if a file has already been deleted. - * @file: NautilusFile representing the file in question. - * - * Returns: TRUE if the file is already gone. - **/ -gboolean -nautilus_file_is_gone (NautilusFile *file) -{ - g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE); - - return file->details->is_gone; -} - -/** - * nautilus_file_is_not_yet_confirmed - * - * Check if we're in a state where we don't know if a file really - * exists or not, before the initial I/O is complete. - * @file: NautilusFile representing the file in question. - * - * Returns: TRUE if the file is already gone. - **/ -gboolean -nautilus_file_is_not_yet_confirmed (NautilusFile *file) -{ - g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE); - - return file->details->info == NULL; -} - -/** - * nautilus_file_check_if_ready - * - * Check whether the values for a set of file attributes are - * currently available, without doing any additional work. This - * is useful for callers that want to reflect updated information - * when it is ready but don't want to force the work required to - * obtain the information, which might be slow network calls, e.g. - * - * @file: The file being queried. - * @file_attributes: A GList of the desired information. - * - * Return value: TRUE if all of the specified attributes are currently readable. - */ -gboolean -nautilus_file_check_if_ready (NautilusFile *file, - GList *file_attributes) -{ - /* To be parallel with call_when_ready, return - * TRUE for NULL file. - */ - if (file == NULL) { - return TRUE; - } - - g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE); - - return EEL_CALL_METHOD_WITH_RETURN_VALUE - (NAUTILUS_FILE_CLASS, file, - check_if_ready, (file, file_attributes)); -} - -void -nautilus_file_call_when_ready (NautilusFile *file, - GList *file_attributes, - NautilusFileCallback callback, - gpointer callback_data) - -{ - g_return_if_fail (callback != NULL); - - if (file == NULL) { - (* callback) (file, callback_data); - return; - } - - g_return_if_fail (NAUTILUS_IS_FILE (file)); - - EEL_CALL_METHOD - (NAUTILUS_FILE_CLASS, file, - call_when_ready, (file, file_attributes, - callback, callback_data)); -} - -void -nautilus_file_cancel_call_when_ready (NautilusFile *file, - NautilusFileCallback callback, - gpointer callback_data) -{ - g_return_if_fail (callback != NULL); - - if (file == NULL) { - return; - } - - g_return_if_fail (NAUTILUS_IS_FILE (file)); - - EEL_CALL_METHOD - (NAUTILUS_FILE_CLASS, file, - cancel_call_when_ready, (file, callback, callback_data)); -} - -static void -invalidate_directory_count (NautilusFile *file) -{ - file->details->directory_count_is_up_to_date = FALSE; -} - - -static void -invalidate_deep_counts (NautilusFile *file) -{ - file->details->deep_counts_status = NAUTILUS_REQUEST_NOT_STARTED; -} - -static void -invalidate_mime_list (NautilusFile *file) -{ - file->details->mime_list_is_up_to_date = FALSE; -} - -static void -invalidate_top_left_text (NautilusFile *file) -{ - file->details->top_left_text_is_up_to_date = FALSE; -} - -static void -invalidate_file_info (NautilusFile *file) -{ - file->details->file_info_is_up_to_date = FALSE; -} - -static void -invalidate_activation_uri (NautilusFile *file) -{ - file->details->activation_uri_is_up_to_date = FALSE; -} - - -void -nautilus_file_invalidate_attributes_internal (NautilusFile *file, - GList *file_attributes) -{ - Request request; - - if (file == NULL) { - return; - } - - nautilus_directory_set_up_request (&request, file_attributes); - - if (request.directory_count) { - invalidate_directory_count (file); - } - if (request.deep_count) { - invalidate_deep_counts (file); - } - if (request.mime_list) { - invalidate_mime_list (file); - } - if (request.file_info) { - invalidate_file_info (file); - } - if (request.top_left_text) { - invalidate_top_left_text (file); - } - if (request.activation_uri) { - invalidate_activation_uri (file); - } - - /* FIXME bugzilla.eazel.com 5075: implement invalidating metadata */ -} - - -/** - * nautilus_file_invalidate_attributes - * - * Invalidate the specified attributes and force a reload. - * @file: NautilusFile representing the file in question. - * @file_attributes: attributes to froget. - **/ - -void -nautilus_file_invalidate_attributes (NautilusFile *file, - GList *file_attributes) -{ - /* Cancel possible in-progress loads of any of these attributes */ - nautilus_directory_cancel_loading_file_attributes (file->details->directory, - file, - file_attributes); - - /* Actually invalidate the values */ - nautilus_file_invalidate_attributes_internal (file, file_attributes); - - /* Kick off I/O if necessary */ - nautilus_directory_async_state_changed (file->details->directory); -} - -GList * -nautilus_file_get_all_attributes (void) -{ - GList *attributes; - - attributes = NULL; - - attributes = g_list_prepend (attributes, NAUTILUS_FILE_ATTRIBUTE_ACTIVATION_URI); - attributes = g_list_prepend (attributes, NAUTILUS_FILE_ATTRIBUTE_CAPABILITIES); - attributes = g_list_prepend (attributes, NAUTILUS_FILE_ATTRIBUTE_CUSTOM_ICON); - attributes = g_list_prepend (attributes, NAUTILUS_FILE_ATTRIBUTE_DEEP_COUNTS); - attributes = g_list_prepend (attributes, NAUTILUS_FILE_ATTRIBUTE_DIRECTORY_ITEM_COUNT); - attributes = g_list_prepend (attributes, NAUTILUS_FILE_ATTRIBUTE_DIRECTORY_ITEM_MIME_TYPES); - attributes = g_list_prepend (attributes, NAUTILUS_FILE_ATTRIBUTE_FILE_TYPE); - attributes = g_list_prepend (attributes, NAUTILUS_FILE_ATTRIBUTE_IS_DIRECTORY); - 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); - - return attributes; -} - -void -nautilus_file_invalidate_all_attributes (NautilusFile *file) -{ - GList *all_attributes; - - all_attributes = nautilus_file_get_all_attributes (); - nautilus_file_invalidate_attributes (file, all_attributes); - g_list_free (all_attributes); -} - - -/** - * nautilus_file_dump - * - * Debugging call, prints out the contents of the file - * fields. - * - * @file: file to dump. - **/ -void -nautilus_file_dump (NautilusFile *file) -{ - long size = file->details->deep_size; - char *uri; - const char *file_kind; - - uri = nautilus_file_get_uri (file); - g_print ("uri: %s \n", uri); - if (file->details->info == NULL) { - g_print ("no file info \n"); - } else if (file->details->get_info_failed) { - g_print ("failed to get file info \n"); - } else { - g_print ("size: %ld \n", size); - switch (file->details->info->type) { - case GNOME_VFS_FILE_TYPE_REGULAR: - file_kind = "regular file"; - break; - case GNOME_VFS_FILE_TYPE_DIRECTORY: - file_kind = "folder"; - break; - case GNOME_VFS_FILE_TYPE_FIFO: - file_kind = "fifo"; - break; - case GNOME_VFS_FILE_TYPE_SOCKET: - file_kind = "socket"; - break; - case GNOME_VFS_FILE_TYPE_CHARACTER_DEVICE: - file_kind = "character device"; - break; - case GNOME_VFS_FILE_TYPE_BLOCK_DEVICE: - file_kind = "block device"; - break; - case GNOME_VFS_FILE_TYPE_SYMBOLIC_LINK: - file_kind = "symbolic link"; - break; - case GNOME_VFS_FILE_TYPE_UNKNOWN: - default: - file_kind = "unknown"; - break; - } - g_print ("kind: %s \n", file_kind); - if (file->details->info->type == GNOME_VFS_FILE_TYPE_SYMBOLIC_LINK) { - g_print ("link to %s \n", file->details->info->symlink_name); - /* FIXME bugzilla.eazel.com 2430: add following of symlinks here */ - } - /* FIXME bugzilla.eazel.com 2431: add permissions and other useful stuff here */ - } - g_free (uri); -} - -/** - * nautilus_file_list_ref - * - * Ref all the files in a list. - * @list: GList of files. - **/ -GList * -nautilus_file_list_ref (GList *list) -{ - g_list_foreach (list, (GFunc) nautilus_file_ref, NULL); - return list; -} - -/** - * nautilus_file_list_unref - * - * Unref all the files in a list. - * @list: GList of files. - **/ -void -nautilus_file_list_unref (GList *list) -{ - eel_g_list_safe_for_each (list, (GFunc) nautilus_file_unref, NULL); -} - -/** - * nautilus_file_list_free - * - * Free a list of files after unrefing them. - * @list: GList of files. - **/ -void -nautilus_file_list_free (GList *list) -{ - nautilus_file_list_unref (list); - g_list_free (list); -} - -/** - * nautilus_file_list_copy - * - * Copy the list of files, making a new ref of each, - * @list: GList of files. - **/ -GList * -nautilus_file_list_copy (GList *list) -{ - return g_list_copy (nautilus_file_list_ref (list)); -} - -static int -compare_by_name_cover (gconstpointer a, gconstpointer b) -{ - return compare_by_name (NAUTILUS_FILE (a), NAUTILUS_FILE (b)); -} - -/** - * nautilus_file_list_sort_by_name - * - * Sort the list of files by file name. - * @list: GList of files. - **/ -GList * -nautilus_file_list_sort_by_name (GList *list) -{ - return g_list_sort (list, compare_by_name_cover); -} - -/* Extract the top left part of the read-in text. */ -char * -nautilus_extract_top_left_text (const char *text, - int length) -{ - char buffer[(NAUTILUS_FILE_TOP_LEFT_TEXT_MAXIMUM_CHARACTERS_PER_LINE + 1) - * NAUTILUS_FILE_TOP_LEFT_TEXT_MAXIMUM_LINES + 1]; - const char *in, *end; - char *out; - int line, i; - - if (length == 0) { - return NULL; - } - - in = text; - end = text + length; - out = buffer; - - for (line = 0; line < NAUTILUS_FILE_TOP_LEFT_TEXT_MAXIMUM_LINES; line++) { - /* Extract one line. */ - for (i = 0; i < NAUTILUS_FILE_TOP_LEFT_TEXT_MAXIMUM_CHARACTERS_PER_LINE; ) { - if (*in == '\n') { - break; - } - if (isprint (*in)) { - *out++ = *in; - i++; - } - if (++in == end) { - goto done; - } - } - - /* Skip the rest of the line. */ - while (*in != '\n') { - if (++in == end) { - goto done; - } - } - if (++in == end) { - goto done; - } - - /* Put a new-line separator in. */ - *out++ = '\n'; - } - - done: - /* Omit any trailing new-lines. */ - while (out != buffer && out[-1] == '\n') { - out--; - } - - /* Check again for special case of empty string. */ - if (out == buffer) { - return NULL; - } - - /* Allocate a copy to keep. */ - *out = '\0'; - return g_strdup (buffer); -} - -#if !defined (NAUTILUS_OMIT_SELF_CHECK) - -void -nautilus_self_check_file (void) -{ - NautilusFile *file_1; - NautilusFile *file_2; - GList *list; - - /* refcount checks */ - - EEL_CHECK_INTEGER_RESULT (nautilus_directory_number_outstanding (), 0); - - file_1 = nautilus_file_get ("file:///home/"); - - EEL_CHECK_INTEGER_RESULT (GTK_OBJECT (file_1)->ref_count, 1); - EEL_CHECK_INTEGER_RESULT (GTK_OBJECT (file_1->details->directory)->ref_count, 1); - EEL_CHECK_INTEGER_RESULT (nautilus_directory_number_outstanding (), 1); - - nautilus_file_unref (file_1); - - EEL_CHECK_INTEGER_RESULT (nautilus_directory_number_outstanding (), 0); - - file_1 = nautilus_file_get ("file:///etc"); - file_2 = nautilus_file_get ("file:///usr"); - - list = NULL; - list = g_list_append (list, file_1); - list = g_list_append (list, file_2); - - nautilus_file_list_ref (list); - - EEL_CHECK_INTEGER_RESULT (GTK_OBJECT (file_1)->ref_count, 2); - EEL_CHECK_INTEGER_RESULT (GTK_OBJECT (file_2)->ref_count, 2); - - nautilus_file_list_unref (list); - - EEL_CHECK_INTEGER_RESULT (GTK_OBJECT (file_1)->ref_count, 1); - EEL_CHECK_INTEGER_RESULT (GTK_OBJECT (file_2)->ref_count, 1); - - nautilus_file_list_free (list); - - EEL_CHECK_INTEGER_RESULT (nautilus_directory_number_outstanding (), 0); - - - /* name checks */ - file_1 = nautilus_file_get ("file:///home/"); - - EEL_CHECK_STRING_RESULT (nautilus_file_get_name (file_1), "home"); - - EEL_CHECK_BOOLEAN_RESULT (nautilus_file_get ("file:///home/") == file_1, TRUE); - nautilus_file_unref (file_1); - - EEL_CHECK_BOOLEAN_RESULT (nautilus_file_get ("file:///home") == file_1, TRUE); - nautilus_file_unref (file_1); - - nautilus_file_unref (file_1); - - file_1 = nautilus_file_get ("file:///home"); - EEL_CHECK_STRING_RESULT (nautilus_file_get_name (file_1), "home"); - nautilus_file_unref (file_1); - - file_1 = nautilus_file_get (":"); - EEL_CHECK_STRING_RESULT (nautilus_file_get_name (file_1), ":"); - nautilus_file_unref (file_1); - - file_1 = nautilus_file_get ("eazel:"); - EEL_CHECK_STRING_RESULT (nautilus_file_get_name (file_1), "eazel"); - nautilus_file_unref (file_1); - - file_1 = nautilus_file_get (EEL_TRASH_URI); - EEL_CHECK_STRING_RESULT (nautilus_file_get_name (file_1), _("Trash")); - nautilus_file_unref (file_1); - - /* sorting */ - file_1 = nautilus_file_get ("file:///etc"); - file_2 = nautilus_file_get ("file:///usr"); - - EEL_CHECK_INTEGER_RESULT (GTK_OBJECT (file_1)->ref_count, 1); - EEL_CHECK_INTEGER_RESULT (GTK_OBJECT (file_2)->ref_count, 1); - - EEL_CHECK_BOOLEAN_RESULT (nautilus_file_compare_for_sort (file_1, file_2, NAUTILUS_FILE_SORT_BY_NAME, FALSE, FALSE) < 0, TRUE); - EEL_CHECK_BOOLEAN_RESULT (nautilus_file_compare_for_sort (file_1, file_2, NAUTILUS_FILE_SORT_BY_NAME, FALSE, TRUE) > 0, TRUE); - EEL_CHECK_BOOLEAN_RESULT (nautilus_file_compare_for_sort (file_1, file_1, NAUTILUS_FILE_SORT_BY_NAME, FALSE, FALSE) == 0, TRUE); - EEL_CHECK_BOOLEAN_RESULT (nautilus_file_compare_for_sort (file_1, file_1, NAUTILUS_FILE_SORT_BY_NAME, TRUE, FALSE) == 0, TRUE); - EEL_CHECK_BOOLEAN_RESULT (nautilus_file_compare_for_sort (file_1, file_1, NAUTILUS_FILE_SORT_BY_NAME, FALSE, TRUE) == 0, TRUE); - EEL_CHECK_BOOLEAN_RESULT (nautilus_file_compare_for_sort (file_1, file_1, NAUTILUS_FILE_SORT_BY_NAME, TRUE, TRUE) == 0, TRUE); - - nautilus_file_unref (file_1); - nautilus_file_unref (file_2); -} - -#endif /* !NAUTILUS_OMIT_SELF_CHECK */ diff --git a/libnautilus-extensions/nautilus-file.h b/libnautilus-extensions/nautilus-file.h deleted file mode 100644 index c82cd5c7d..000000000 --- a/libnautilus-extensions/nautilus-file.h +++ /dev/null @@ -1,361 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- - - nautilus-file.h: Nautilus file model. - - Copyright (C) 1999, 2000, 2001 Eazel, Inc. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public - License along with this program; if not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. - - Author: Darin Adler <darin@eazel.com> -*/ - -#ifndef NAUTILUS_FILE_H -#define NAUTILUS_FILE_H - -#include <gtk/gtkobject.h> -#include <libgnomevfs/gnome-vfs-types.h> - -/* NautilusFile is an object used to represent a single element of a - * NautilusDirectory. It's lightweight and relies on NautilusDirectory - * to do most of the work. - */ - -/* NautilusFile is defined both here and in nautilus-directory.h. */ -#ifndef NAUTILUS_FILE_DEFINED -#define NAUTILUS_FILE_DEFINED -typedef struct NautilusFile NautilusFile; -#endif - -#define NAUTILUS_TYPE_FILE \ - (nautilus_file_get_type ()) -#define NAUTILUS_FILE(obj) \ - (GTK_CHECK_CAST ((obj), NAUTILUS_TYPE_FILE, NautilusFile)) -#define NAUTILUS_FILE_CLASS(klass) \ - (GTK_CHECK_CLASS_CAST ((klass), NAUTILUS_TYPE_FILE, NautilusFileClass)) -#define NAUTILUS_IS_FILE(obj) \ - (GTK_CHECK_TYPE ((obj), NAUTILUS_TYPE_FILE)) -#define NAUTILUS_IS_FILE_CLASS(klass) \ - (GTK_CHECK_CLASS_TYPE ((klass), NAUTILUS_TYPE_FILE)) - -typedef enum { - NAUTILUS_FILE_SORT_NONE, - NAUTILUS_FILE_SORT_BY_NAME, - NAUTILUS_FILE_SORT_BY_DIRECTORY, - NAUTILUS_FILE_SORT_BY_SIZE, - NAUTILUS_FILE_SORT_BY_TYPE, - NAUTILUS_FILE_SORT_BY_MTIME, - NAUTILUS_FILE_SORT_BY_EMBLEMS -} NautilusFileSortType; - -typedef enum { - NAUTILUS_REQUEST_NOT_STARTED, - NAUTILUS_REQUEST_IN_PROGRESS, - NAUTILUS_REQUEST_DONE -} NautilusRequestStatus; - -/* Emblems sometimes displayed for NautilusFiles. Do not localize. */ -#define NAUTILUS_FILE_EMBLEM_NAME_SYMBOLIC_LINK "symbolic-link" -#define NAUTILUS_FILE_EMBLEM_NAME_CANT_READ "noread" -#define NAUTILUS_FILE_EMBLEM_NAME_CANT_WRITE "nowrite" -#define NAUTILUS_FILE_EMBLEM_NAME_TRASH "trash" - -typedef void (*NautilusFileCallback) (NautilusFile *file, - gpointer callback_data); -typedef void (*NautilusFileOperationCallback) (NautilusFile *file, - GnomeVFSResult result, - gpointer callback_data); -typedef int (*NautilusWidthMeasureCallback) (const char *string, - void *context); -typedef char * (*NautilusTruncateCallback) (const char *string, - int width, - void *context); - -/* GtkObject requirements. */ -GtkType nautilus_file_get_type (void); - -/* Getting at a single file. */ -NautilusFile * nautilus_file_get (const char *uri); - -/* Covers for gtk_object_ref and gtk_object_unref that provide two conveniences: - * 1) You don't have to cast to GtkObject *, so using these is type safe. - * 2) You are allowed to call these with NULL, - */ -NautilusFile * nautilus_file_ref (NautilusFile *file); -void nautilus_file_unref (NautilusFile *file); - -/* Monitor the file. */ -void nautilus_file_monitor_add (NautilusFile *file, - gconstpointer client, - GList *attributes); -void nautilus_file_monitor_remove (NautilusFile *file, - gconstpointer client); - -/* Waiting for data that's read asynchronously. - * This interface currently works only for metadata, but could be expanded - * to other attributes as well. - */ -void nautilus_file_call_when_ready (NautilusFile *file, - GList *attributes, - NautilusFileCallback callback, - gpointer callback_data); -void nautilus_file_cancel_call_when_ready (NautilusFile *file, - NautilusFileCallback callback, - gpointer callback_data); -gboolean nautilus_file_check_if_ready (NautilusFile *file, - GList *attributes); -void nautilus_file_invalidate_attributes (NautilusFile *file, - GList *attributes); -void nautilus_file_invalidate_all_attributes (NautilusFile *file); - -/* Basic attributes for file objects. */ -gboolean nautilus_file_contains_text (NautilusFile *file); -char * nautilus_file_get_name (NautilusFile *file); -char * nautilus_file_get_uri (NautilusFile *file); -char * nautilus_file_get_uri_scheme (NautilusFile *file); -char * nautilus_file_get_parent_uri (NautilusFile *file); -char * nautilus_file_get_parent_uri_for_display (NautilusFile *file); -GnomeVFSFileSize nautilus_file_get_size (NautilusFile *file); -GnomeVFSFileType nautilus_file_get_file_type (NautilusFile *file); -char * nautilus_file_get_mime_type (NautilusFile *file); -gboolean nautilus_file_is_mime_type (NautilusFile *file, - const char *mime_type); -gboolean nautilus_file_is_symbolic_link (NautilusFile *file); -char * nautilus_file_get_symbolic_link_target_path (NautilusFile *file); -gboolean nautilus_file_is_broken_symbolic_link (NautilusFile *file); -gboolean nautilus_file_is_nautilus_link (NautilusFile *file); -gboolean nautilus_file_is_gmc_url (NautilusFile *file); -gboolean nautilus_file_is_executable (NautilusFile *file); -gboolean nautilus_file_is_directory (NautilusFile *file); -gboolean nautilus_file_is_in_trash (NautilusFile *file); -gboolean nautilus_file_is_in_desktop (NautilusFile *file); -GnomeVFSResult nautilus_file_get_file_info_result (NautilusFile *file); -gboolean nautilus_file_get_directory_item_count (NautilusFile *file, - guint *count, - gboolean *count_unreadable); -void nautilus_file_recompute_deep_counts (NautilusFile *file); -NautilusRequestStatus nautilus_file_get_deep_counts (NautilusFile *file, - guint *directory_count, - guint *file_count, - guint *unreadable_directory_count, - GnomeVFSFileSize *total_size); -gboolean nautilus_file_should_show_directory_item_count (NautilusFile *file); -GList * nautilus_file_get_keywords (NautilusFile *file); -void nautilus_file_set_keywords (NautilusFile *file, - GList *keywords); -GList * nautilus_file_get_emblem_names (NautilusFile *file); -char * nautilus_file_get_top_left_text (NautilusFile *file); -gboolean nautilus_file_get_directory_item_mime_types (NautilusFile *file, - GList **mime_list); - -/* Permissions. */ -gboolean nautilus_file_can_get_permissions (NautilusFile *file); -gboolean nautilus_file_can_set_permissions (NautilusFile *file); -GnomeVFSFilePermissions nautilus_file_get_permissions (NautilusFile *file); -gboolean nautilus_file_can_get_owner (NautilusFile *file); -gboolean nautilus_file_can_set_owner (NautilusFile *file); -gboolean nautilus_file_can_get_group (NautilusFile *file); -gboolean nautilus_file_can_set_group (NautilusFile *file); -char * nautilus_file_get_owner_name (NautilusFile *file); -char * nautilus_file_get_group_name (NautilusFile *file); -GList * nautilus_get_user_names (void); -GList * nautilus_get_group_names (void); -GList * nautilus_file_get_settable_group_names (NautilusFile *file); - -/* "Capabilities". */ -gboolean nautilus_file_can_read (NautilusFile *file); -gboolean nautilus_file_can_write (NautilusFile *file); -gboolean nautilus_file_can_execute (NautilusFile *file); -gboolean nautilus_file_can_rename (NautilusFile *file); - -/* Basic operations for file objects. */ -void nautilus_file_set_owner (NautilusFile *file, - const char *user_name_or_id, - NautilusFileOperationCallback callback, - gpointer callback_data); -void nautilus_file_set_group (NautilusFile *file, - const char *group_name_or_id, - NautilusFileOperationCallback callback, - gpointer callback_data); -void nautilus_file_set_permissions (NautilusFile *file, - GnomeVFSFilePermissions permissions, - NautilusFileOperationCallback callback, - gpointer callback_data); -void nautilus_file_rename (NautilusFile *file, - const char *new_name, - NautilusFileOperationCallback callback, - gpointer callback_data); -void nautilus_file_cancel (NautilusFile *file, - NautilusFileOperationCallback callback, - gpointer callback_data); - -/* Return true if this file has already been deleted. - * This object will be unref'd after sending the files_removed signal, - * but it could hang around longer if someone ref'd it. - */ -gboolean nautilus_file_is_gone (NautilusFile *file); - -/* Return true if this file is not confirmed to have ever really - * existed. This is true when the NautilusFile object has been created, but no I/O - * has yet confirmed the existence of a file by that name. - */ -gboolean nautilus_file_is_not_yet_confirmed (NautilusFile *file); - -/* Simple getting and setting top-level metadata. */ -char * nautilus_file_get_metadata (NautilusFile *file, - const char *key, - const char *default_metadata); -GList * nautilus_file_get_metadata_list (NautilusFile *file, - const char *list_key, - const char *list_subkey); -void nautilus_file_set_metadata (NautilusFile *file, - const char *key, - const char *default_metadata, - const char *metadata); -void nautilus_file_set_metadata_list (NautilusFile *file, - const char *list_key, - const char *list_subkey, - GList *list); - -/* Covers for common data types. */ -gboolean nautilus_file_get_boolean_metadata (NautilusFile *file, - const char *key, - gboolean default_metadata); -void nautilus_file_set_boolean_metadata (NautilusFile *file, - const char *key, - gboolean default_metadata, - gboolean metadata); -int nautilus_file_get_integer_metadata (NautilusFile *file, - const char *key, - int default_metadata); -void nautilus_file_set_integer_metadata (NautilusFile *file, - const char *key, - int default_metadata, - int metadata); - - -/* Attributes for file objects as user-displayable strings. */ -char * nautilus_file_get_string_attribute (NautilusFile *file, - const char *attribute_name); -char * nautilus_file_get_string_attribute_with_default (NautilusFile *file, - const char *attribute_name); -char * nautilus_file_fit_modified_date_as_string (NautilusFile *file, - int width, - NautilusWidthMeasureCallback measure_callback, - NautilusTruncateCallback truncate_callback, - void *measure_truncate_context); - -/* Matching with another URI. */ -gboolean nautilus_file_matches_uri (NautilusFile *file, - const char *uri); - -/* Is the file local? */ -gboolean nautilus_file_is_local (NautilusFile *file); - -/* Comparing two file objects for sorting */ -int nautilus_file_compare_for_sort (NautilusFile *file_1, - NautilusFile *file_2, - NautilusFileSortType sort_type, - gboolean directories_first, - gboolean reversed); -int nautilus_file_compare_name (NautilusFile *file_1, - const char *pattern); - -/* filtering functions for use by various directory views */ -gboolean nautilus_file_is_hidden_file (NautilusFile *file); -gboolean nautilus_file_is_backup_file (NautilusFile *file); -gboolean nautilus_file_is_metafile (NautilusFile *file); -gboolean nautilus_file_should_show (NautilusFile *file, - gboolean show_hidden, - gboolean show_backup); -GList *nautilus_file_list_filter_hidden_and_backup (GList *files, - gboolean show_hidden, - gboolean show_backup); - - -/* Get the URI that's used when activating the file. - * Getting this can require reading the contents of the file. - */ -char * nautilus_file_get_activation_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 *. - */ -GList * nautilus_file_list_ref (GList *file_list); -void nautilus_file_list_unref (GList *file_list); -void nautilus_file_list_free (GList *file_list); -GList * nautilus_file_list_copy (GList *file_list); -GList * nautilus_file_list_sort_by_name (GList *file_list); - -/* Debugging */ -void nautilus_file_dump (NautilusFile *file); - -typedef struct NautilusFileDetails NautilusFileDetails; - -struct NautilusFile { - GtkObject parent_slot; - NautilusFileDetails *details; -}; - -/* This is actually a "protected" type, but it must be here so we can - * compile the get_date function pointer declaration below. - */ -typedef enum { - NAUTILUS_DATE_TYPE_MODIFIED, - NAUTILUS_DATE_TYPE_CHANGED, - NAUTILUS_DATE_TYPE_ACCESSED, - NAUTILUS_DATE_TYPE_PERMISSIONS_CHANGED -} NautilusDateType; - -typedef struct { - GtkObjectClass parent_slot; - - /* Called when the file notices any change. */ - void (* changed) (NautilusFile *file); - - /* Called periodically while directory deep count is being computed. */ - void (* updated_deep_count_in_progress) (NautilusFile *file); - - /* Virtual functions (mainly used for trash directory). */ - void (* monitor_add) (NautilusFile *file, - gconstpointer client, - GList *attributes); - void (* monitor_remove) (NautilusFile *file, - gconstpointer client); - void (* call_when_ready) (NautilusFile *file, - GList *attributes, - NautilusFileCallback callback, - gpointer callback_data); - void (* cancel_call_when_ready) (NautilusFile *file, - NautilusFileCallback callback, - gpointer callback_data); - gboolean (* check_if_ready) (NautilusFile *file, - GList *attributes); - GnomeVFSFileType (* get_file_type) (NautilusFile *file); - gboolean (* get_item_count) (NautilusFile *file, - guint *count, - gboolean *count_unreadable); - NautilusRequestStatus (* get_deep_counts) (NautilusFile *file, - guint *directory_count, - guint *file_count, - guint *unreadable_directory_count, - GnomeVFSFileSize *total_size); - gboolean (* get_date) (NautilusFile *file, - NautilusDateType type, - time_t *date); - char * (* get_where_string) (NautilusFile *file); -} NautilusFileClass; - -#endif /* NAUTILUS_FILE_H */ diff --git a/libnautilus-extensions/nautilus-font-factory.c b/libnautilus-extensions/nautilus-font-factory.c deleted file mode 100644 index 89fed7b62..000000000 --- a/libnautilus-extensions/nautilus-font-factory.c +++ /dev/null @@ -1,292 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- - - nautilus-font-factory.c: Class for obtaining fonts. - - 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: Ramiro Estrugo <ramiro@eazel.com> -*/ - -#include <config.h> -#include "nautilus-font-factory.h" - -#include "nautilus-global-preferences.h" -#include <eel/eel-gtk-macros.h> -#include <eel/eel-string.h> -#include <eel/eel-gdk-font-extensions.h> -#include <eel/eel-gtk-extensions.h> -#include <pthread.h> -#include <unistd.h> - -#include <libgnome/gnome-i18n.h> - -#define NAUTILUS_TYPE_FONT_FACTORY \ - (nautilus_font_factory_get_type ()) -#define NAUTILUS_FONT_FACTORY(obj) \ - (GTK_CHECK_CAST ((obj), NAUTILUS_TYPE_FONT_FACTORY, NautilusFontFactory)) -#define NAUTILUS_FONT_FACTORY_CLASS(klass) \ - (GTK_CHECK_CLASS_CAST ((klass), NAUTILUS_TYPE_FONT_FACTORY, NautilusFontFactoryClass)) -#define NAUTILUS_IS_FONT_FACTORY(obj) \ - (GTK_CHECK_TYPE ((obj), NAUTILUS_TYPE_FONT_FACTORY)) -#define NAUTILUS_IS_FONT_FACTORY_CLASS(klass) \ - (GTK_CHECK_CLASS_TYPE ((klass), NAUTILUS_TYPE_FONT_FACTORY)) - -/* The font factory */ -typedef struct { - GtkObject object; - - GHashTable *fonts; -} NautilusFontFactory; - -typedef struct { - GtkObjectClass parent_class; -} NautilusFontFactoryClass; - -/* FontHashNode */ -typedef struct { - char *name; - GdkFont *font; -} FontHashNode; - -static NautilusFontFactory *global_font_factory = NULL; - -static GtkType nautilus_font_factory_get_type (void); -static void nautilus_font_factory_initialize_class (NautilusFontFactoryClass *class); -static void nautilus_font_factory_initialize (NautilusFontFactory *factory); -static void destroy (GtkObject *object); - -EEL_DEFINE_CLASS_BOILERPLATE (NautilusFontFactory, - nautilus_font_factory, - GTK_TYPE_OBJECT) - -static void -unref_global_font_factory (void) -{ - gtk_object_unref (GTK_OBJECT (global_font_factory)); -} - -/* Return a pointer to the single global font factory. */ -static NautilusFontFactory * -nautilus_get_current_font_factory (void) -{ - if (global_font_factory == NULL) { - global_font_factory = NAUTILUS_FONT_FACTORY (gtk_object_new (nautilus_font_factory_get_type (), NULL)); - gtk_object_ref (GTK_OBJECT (global_font_factory)); - gtk_object_sink (GTK_OBJECT (global_font_factory)); - g_atexit (unref_global_font_factory); - } - - return global_font_factory; -} - -GtkObject * -nautilus_font_factory_get (void) -{ - return GTK_OBJECT (nautilus_get_current_font_factory ()); -} - -static void -nautilus_font_factory_initialize (NautilusFontFactory *factory) -{ - factory->fonts = g_hash_table_new (g_str_hash, g_str_equal); -} - -static void -nautilus_font_factory_initialize_class (NautilusFontFactoryClass *class) -{ - GtkObjectClass *object_class; - - object_class = GTK_OBJECT_CLASS (class); - object_class->destroy = destroy; -} - -static FontHashNode * -font_hash_node_alloc (const char *name) -{ - FontHashNode *node; - - g_assert (name != NULL); - - node = g_new0 (FontHashNode, 1); - node->name = g_strdup (name); - - return node; -} - -static void -font_hash_node_free (FontHashNode *node) -{ - g_assert (node != NULL); - - g_free (node->name); - gdk_font_unref (node->font); - - g_free (node); -} - -static void -free_one_hash_node (gpointer key, gpointer value, gpointer callback_data) -{ - FontHashNode *node; - - g_assert (key != NULL); - g_assert (value != NULL); - g_assert (callback_data == NULL); - - node = value; - - g_assert (node->name == key); - - font_hash_node_free (node); -} - -static void -destroy (GtkObject *object) -{ - NautilusFontFactory *factory; - - factory = NAUTILUS_FONT_FACTORY (object); - - g_hash_table_foreach (factory->fonts, free_one_hash_node, NULL); - g_hash_table_destroy (factory->fonts); - - EEL_CALL_PARENT (GTK_OBJECT_CLASS, destroy, (object)); -} - -static FontHashNode * -font_hash_node_lookup (const char *name) -{ - NautilusFontFactory *factory; - - g_assert (name != NULL); - - factory = nautilus_get_current_font_factory (); - return (FontHashNode *) g_hash_table_lookup (factory->fonts, name); -} - -static FontHashNode * -font_hash_node_lookup_with_insertion (const char *name) -{ - NautilusFontFactory *factory; - FontHashNode *node; - GdkFont *font; - - g_assert (name != NULL); - - factory = nautilus_get_current_font_factory (); - node = font_hash_node_lookup (name); - - if (node == NULL) { - font = gdk_fontset_load (name); - - if (font != NULL) { - node = font_hash_node_alloc (name); - node->font = font; - g_hash_table_insert (factory->fonts, node->name, node); - } - } - - return node; -} - -/* Public functions */ -GdkFont * -nautilus_font_factory_get_font_by_family (const char *family, - guint size_in_pixels) -{ - NautilusFontFactory *factory; - GdkFont *font; - FontHashNode *node; - char *font_name; - char **fontset; - char **iter; - - g_return_val_if_fail (family != NULL, NULL); - g_return_val_if_fail (size_in_pixels > 0, NULL); - - /* FIXME bugzilla.eazel.com 7907: - * The "GTK System Font" string is hard coded in many places. - */ - if (eel_str_is_equal (family, "GTK System Font")) { - return eel_gtk_get_system_font (); - } - - fontset = g_strsplit (family, ",", 5); - iter = fontset; - - factory = nautilus_get_current_font_factory (); - while (*iter) { - /* FIXME bugzilla.eazel.com 7347: - * Its a hack that we check for "-" prefixes in font names. - * We do this in order not to break transalted font families. - */ - if (!eel_str_has_prefix (*iter, "-")) { - font_name = eel_gdk_font_xlfd_string_new ("*", - *iter, - "medium", - "r", - "normal", - "*", - size_in_pixels); - } else { - font_name = g_strdup (*iter); - } - - g_free (*iter); - *iter = font_name; - iter++; - } - - font_name = g_strjoinv (",", fontset); - g_strfreev (fontset); - - node = font_hash_node_lookup_with_insertion (font_name); - - if (node != NULL) { - g_assert (node->font != NULL); - font = node->font; - gdk_font_ref (font); - } else { - font = eel_gdk_font_get_fixed (); - } - - g_free (font_name); - - return font; -} - -GdkFont * -nautilus_font_factory_get_font_from_preferences (guint size_in_pixels) -{ - static gboolean icon_view_font_auto_value_registered; - static const char *icon_view_font_auto_value; - - /* Can't initialize this in initialize_class, because no font factory - * instance may yet exist when this is called. - */ - if (!icon_view_font_auto_value_registered) { - nautilus_preferences_add_auto_string (NAUTILUS_PREFERENCES_ICON_VIEW_FONT, - &icon_view_font_auto_value); - icon_view_font_auto_value_registered = TRUE; - } - - /* FIXME: We hardwire icon view font here, but some callers probably - * expect default font instead. - */ - return nautilus_font_factory_get_font_by_family (icon_view_font_auto_value, size_in_pixels); -} diff --git a/libnautilus-extensions/nautilus-font-factory.h b/libnautilus-extensions/nautilus-font-factory.h deleted file mode 100644 index 52f93a9de..000000000 --- a/libnautilus-extensions/nautilus-font-factory.h +++ /dev/null @@ -1,43 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- - - nautilus-font-factory.h: Class for obtaining fonts. - - 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: Ramiro Estrugo <ramiro@eazel.com> -*/ - -#ifndef NAUTILUS_FONT_FACTORY_H -#define NAUTILUS_FONT_FACTORY_H - -#include <gdk/gdk.h> -#include <gtk/gtkobject.h> - -/* A There's a single NautilusFontFactory object. */ -GtkObject *nautilus_font_factory_get (void); - - -/* Get a font by familiy. */ -GdkFont * nautilus_font_factory_get_font_by_family (const char *family, - guint size_in_pixels); - - -/* Get a font according to the family set in preferences. */ -GdkFont * nautilus_font_factory_get_font_from_preferences (guint size_in_pixels); - -#endif /* NAUTILUS_FONT_FACTORY_H */ diff --git a/libnautilus-extensions/nautilus-gconf-extensions.c b/libnautilus-extensions/nautilus-gconf-extensions.c deleted file mode 100644 index 3995bed02..000000000 --- a/libnautilus-extensions/nautilus-gconf-extensions.c +++ /dev/null @@ -1,515 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ - -/* nautilus-gconf-extensions.c - Stuff to make GConf easier to use in Nautilus. - - Copyright (C) 2000, 2001 Eazel, Inc. - - The Gnome 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 Gnome 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 the Gnome 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. - - Authors: Ramiro Estrugo <ramiro@eazel.com> -*/ - -#include <config.h> -#include "nautilus-gconf-extensions.h" - -#include <eel/eel-glib-extensions.h> -#include <eel/eel-stock-dialogs.h> -#include <eel/eel-string.h> - -#include <gconf/gconf-client.h> -#include <gconf/gconf.h> -#include <libgnome/gnome-i18n.h> - -static GConfClient *global_gconf_client = NULL; - -static void -global_client_free (void) -{ - if (global_gconf_client == NULL) { - return; - } - - gtk_object_unref (GTK_OBJECT (global_gconf_client)); - global_gconf_client = NULL; -} - -/* Public */ -GConfClient * -nautilus_gconf_client_get_global (void) -{ - /* Initialize gconf if needed */ - if (!gconf_is_initialized ()) { - char *argv[] = { "nautilus-preferences", NULL }; - GError *error = NULL; - - if (!gconf_init (1, argv, &error)) { - if (nautilus_gconf_handle_error (&error)) { - return NULL; - } - } - } - - if (global_gconf_client == NULL) { - global_gconf_client = gconf_client_get_default (); - g_atexit (global_client_free); - } - - return global_gconf_client; -} - -gboolean -nautilus_gconf_handle_error (GError **error) -{ - char *message; - static gboolean shown_dialog = FALSE; - - g_return_val_if_fail (error != NULL, FALSE); - - if (*error != NULL) { - g_warning (_("GConf error:\n %s"), (*error)->message); - if (! shown_dialog) { - shown_dialog = TRUE; - - message = g_strdup_printf (_("GConf error:\n %s\n" - "All further errors shown " - "only on terminal"), - (*error)->message); - eel_show_error_dialog (message, _("GConf Error"), NULL); - g_free (message); - } - g_error_free (*error); - *error = NULL; - - return TRUE; - } - - return FALSE; -} - -void -nautilus_gconf_set_boolean (const char *key, - gboolean boolean_value) -{ - GConfClient *client; - GError *error = NULL; - - g_return_if_fail (key != NULL); - - client = nautilus_gconf_client_get_global (); - g_return_if_fail (client != NULL); - - gconf_client_set_bool (client, key, boolean_value, &error); - nautilus_gconf_handle_error (&error); -} - -gboolean -nautilus_gconf_get_boolean (const char *key) -{ - gboolean result; - GConfClient *client; - GError *error = NULL; - - g_return_val_if_fail (key != NULL, FALSE); - - client = nautilus_gconf_client_get_global (); - g_return_val_if_fail (client != NULL, FALSE); - - result = gconf_client_get_bool (client, key, &error); - - if (nautilus_gconf_handle_error (&error)) { - result = FALSE; - } - - return result; -} - -void -nautilus_gconf_set_integer (const char *key, - int int_value) -{ - GConfClient *client; - GError *error = NULL; - - g_return_if_fail (key != NULL); - - client = nautilus_gconf_client_get_global (); - g_return_if_fail (client != NULL); - - gconf_client_set_int (client, key, int_value, &error); - nautilus_gconf_handle_error (&error); -} - -int -nautilus_gconf_get_integer (const char *key) -{ - int result; - GConfClient *client; - GError *error = NULL; - - g_return_val_if_fail (key != NULL, 0); - - client = nautilus_gconf_client_get_global (); - g_return_val_if_fail (client != NULL, 0); - - result = gconf_client_get_int (client, key, &error); - - if (nautilus_gconf_handle_error (&error)) { - result = 0; - } - - return result; -} - -void -nautilus_gconf_set_string (const char *key, - const char *string_value) -{ - GConfClient *client; - GError *error = NULL; - - g_return_if_fail (key != NULL); - - client = nautilus_gconf_client_get_global (); - g_return_if_fail (client != NULL); - - gconf_client_set_string (client, key, string_value, &error); - nautilus_gconf_handle_error (&error); -} - -char * -nautilus_gconf_get_string (const char *key) -{ - char *result; - GConfClient *client; - GError *error = NULL; - - g_return_val_if_fail (key != NULL, NULL); - - client = nautilus_gconf_client_get_global (); - g_return_val_if_fail (client != NULL, NULL); - - result = gconf_client_get_string (client, key, &error); - - if (nautilus_gconf_handle_error (&error)) { - result = g_strdup (""); - } - - return result; -} - -void -nautilus_gconf_set_string_list (const char *key, - const GSList *slist) -{ - GConfClient *client; - GError *error; - - g_return_if_fail (key != NULL); - - client = nautilus_gconf_client_get_global (); - g_return_if_fail (client != NULL); - - error = NULL; - gconf_client_set_list (client, key, GCONF_VALUE_STRING, - /* Need cast cause of GConf api bug */ - (GSList *) slist, - &error); - nautilus_gconf_handle_error (&error); -} - -GSList * -nautilus_gconf_get_string_list (const char *key) -{ - GSList *slist; - GConfClient *client; - GError *error; - - g_return_val_if_fail (key != NULL, NULL); - - client = nautilus_gconf_client_get_global (); - g_return_val_if_fail (client != NULL, NULL); - - error = NULL; - slist = gconf_client_get_list (client, key, GCONF_VALUE_STRING, &error); - if (nautilus_gconf_handle_error (&error)) { - slist = NULL; - } - - return slist; -} - -gboolean -nautilus_gconf_is_default (const char *key) -{ - gboolean result; - GConfValue *value; - GError *error = NULL; - - g_return_val_if_fail (key != NULL, FALSE); - - value = gconf_client_get_without_default (nautilus_gconf_client_get_global (), key, &error); - - if (nautilus_gconf_handle_error (&error)) { - if (value != NULL) { - gconf_value_free (value); - } - return FALSE; - } - - result = (value == NULL); - - if (value != NULL) { - gconf_value_free (value); - } - - - return result; -} - -gboolean -nautilus_gconf_monitor_add (const char *directory) -{ - GError *error = NULL; - GConfClient *client; - - g_return_val_if_fail (directory != NULL, FALSE); - - client = gconf_client_get_default (); - g_return_val_if_fail (client != NULL, FALSE); - - gconf_client_add_dir (client, - directory, - GCONF_CLIENT_PRELOAD_NONE, - &error); - - if (nautilus_gconf_handle_error (&error)) { - return FALSE; - } - - return TRUE; -} - -gboolean -nautilus_gconf_monitor_remove (const char *directory) -{ - GError *error = NULL; - GConfClient *client; - - if (directory == NULL) { - return FALSE; - } - - client = gconf_client_get_default (); - g_return_val_if_fail (client != NULL, FALSE); - - gconf_client_remove_dir (client, - directory, - &error); - - if (nautilus_gconf_handle_error (&error)) { - return FALSE; - } - - return TRUE; -} - -void -nautilus_gconf_suggest_sync (void) -{ - GConfClient *client; - GError *error = NULL; - - client = nautilus_gconf_client_get_global (); - g_return_if_fail (client != NULL); - - gconf_client_suggest_sync (client, &error); - nautilus_gconf_handle_error (&error); -} - -GConfValue* -nautilus_gconf_get_value (const char *key) -{ - GConfValue *value = NULL; - GConfClient *client; - GError *error = NULL; - - g_return_val_if_fail (key != NULL, NULL); - - client = nautilus_gconf_client_get_global (); - g_return_val_if_fail (client != NULL, NULL); - - value = gconf_client_get (client, key, &error); - - if (nautilus_gconf_handle_error (&error)) { - if (value != NULL) { - gconf_value_free (value); - value = NULL; - } - } - - return value; -} - -static gboolean -simple_value_is_equal (const GConfValue *a, - const GConfValue *b) -{ - g_return_val_if_fail (a != NULL, FALSE); - g_return_val_if_fail (b != NULL, FALSE); - - switch (a->type) { - case GCONF_VALUE_STRING: - return eel_str_is_equal (a->d.string_data, b->d.string_data); - break; - - case GCONF_VALUE_INT: - return a->d.int_data == b->d.int_data; - break; - - case GCONF_VALUE_FLOAT: - return a->d.float_data == b->d.float_data; - break; - - case GCONF_VALUE_BOOL: - return a->d.bool_data == b->d.bool_data; - break; - default: - g_assert_not_reached (); - } - - return FALSE; -} - -gboolean -nautilus_gconf_value_is_equal (const GConfValue *a, - const GConfValue *b) -{ - GSList *node_a; - GSList *node_b; - - if (a == NULL && b == NULL) { - return TRUE; - } - - if (a == NULL || b == NULL) { - return FALSE; - } - - if (a->type != b->type) { - return FALSE; - } - - switch (a->type) { - case GCONF_VALUE_STRING: - case GCONF_VALUE_INT: - case GCONF_VALUE_FLOAT: - case GCONF_VALUE_BOOL: - return simple_value_is_equal (a, b); - break; - - case GCONF_VALUE_LIST: - if (a->d.list_data.type != b->d.list_data.type) { - return FALSE; - } - - if (a->d.list_data.list == NULL && b->d.list_data.list == NULL) { - return TRUE; - } - - if (a->d.list_data.list != NULL || b->d.list_data.list != NULL) { - return FALSE; - } - - if (g_slist_length (a->d.list_data.list) != g_slist_length (b->d.list_data.list)) { - return FALSE; - } - - for (node_a = a->d.list_data.list,node_b = b->d.list_data.list; - node_a != NULL && node_b != NULL; - node_a = node_a->next, node_b = node_b->next) { - g_assert (node_a->data != NULL); - g_assert (node_b->data != NULL); - if (!simple_value_is_equal (node_a->data, node_b->data)) { - return FALSE; - } - } - - return TRUE; - default: - /* FIXME: pair ? */ - g_assert (0); - } - - g_assert_not_reached (); - return FALSE; -} - -void -nautilus_gconf_value_free (GConfValue *value) -{ - if (value == NULL) { - return; - } - - gconf_value_free (value); -} - -guint -nautilus_gconf_notification_add (const char *key, - GConfClientNotifyFunc notification_callback, - gpointer callback_data) -{ - guint notification_id; - GConfClient *client; - GError *error = NULL; - - g_return_val_if_fail (key != NULL, NAUTILUS_GCONF_UNDEFINED_CONNECTION); - g_return_val_if_fail (notification_callback != NULL, NAUTILUS_GCONF_UNDEFINED_CONNECTION); - - client = nautilus_gconf_client_get_global (); - g_return_val_if_fail (client != NULL, NAUTILUS_GCONF_UNDEFINED_CONNECTION); - - notification_id = gconf_client_notify_add (client, - key, - notification_callback, - callback_data, - NULL, - &error); - - if (nautilus_gconf_handle_error (&error)) { - if (notification_id != NAUTILUS_GCONF_UNDEFINED_CONNECTION) { - gconf_client_notify_remove (client, notification_id); - notification_id = NAUTILUS_GCONF_UNDEFINED_CONNECTION; - } - } - - return notification_id; -} - -void -nautilus_gconf_notification_remove (guint notification_id) -{ - GConfClient *client; - - if (notification_id == NAUTILUS_GCONF_UNDEFINED_CONNECTION) { - return; - } - - client = nautilus_gconf_client_get_global (); - g_return_if_fail (client != NULL); - - gconf_client_notify_remove (client, notification_id); -} diff --git a/libnautilus-extensions/nautilus-gconf-extensions.h b/libnautilus-extensions/nautilus-gconf-extensions.h deleted file mode 100644 index 0200c05aa..000000000 --- a/libnautilus-extensions/nautilus-gconf-extensions.h +++ /dev/null @@ -1,65 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ - -/* nautilus-gconf-extensions.h - Stuff to make GConf easier to use in Nautilus. - - Copyright (C) 2000, 2001 Eazel, Inc. - - The Gnome 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 Gnome 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 the Gnome 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. - - Authors: Ramiro Estrugo <ramiro@eazel.com> -*/ - -#ifndef NAUTILUS_GCONF_EXTENSIONS_H -#define NAUTILUS_GCONF_EXTENSIONS_H - -#include <gconf/gconf.h> -#include <gconf/gconf-client.h> -#include <libgnome/gnome-defs.h> - -BEGIN_GNOME_DECLS - -#define NAUTILUS_GCONF_UNDEFINED_CONNECTION 0 - -GConfClient *nautilus_gconf_client_get_global (void); -gboolean nautilus_gconf_handle_error (GError **error); -void nautilus_gconf_set_boolean (const char *key, - gboolean boolean_value); -gboolean nautilus_gconf_get_boolean (const char *key); -int nautilus_gconf_get_integer (const char *key); -void nautilus_gconf_set_integer (const char *key, - int int_value); -char * nautilus_gconf_get_string (const char *key); -void nautilus_gconf_set_string (const char *key, - const char *string_value); -GSList * nautilus_gconf_get_string_list (const char *key); -void nautilus_gconf_set_string_list (const char *key, - const GSList *string_list_value); -gboolean nautilus_gconf_is_default (const char *key); -gboolean nautilus_gconf_monitor_add (const char *directory); -gboolean nautilus_gconf_monitor_remove (const char *directory); -void nautilus_gconf_suggest_sync (void); -GConfValue* nautilus_gconf_get_value (const char *key); -gboolean nautilus_gconf_value_is_equal (const GConfValue *a, - const GConfValue *b); -void nautilus_gconf_value_free (GConfValue *value); -guint nautilus_gconf_notification_add (const char *key, - GConfClientNotifyFunc notification_callback, - gpointer callback_data); -void nautilus_gconf_notification_remove (guint notification_id); - -END_GNOME_DECLS - -#endif /* NAUTILUS_GCONF_EXTENSIONS_H */ diff --git a/libnautilus-extensions/nautilus-generous-bin.c b/libnautilus-extensions/nautilus-generous-bin.c deleted file mode 100644 index e845b4452..000000000 --- a/libnautilus-extensions/nautilus-generous-bin.c +++ /dev/null @@ -1,87 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ - -/* nautilus-generous-bin.c: Subclass of GtkVBox that clips off - items that don't fit, except the last one. - - Copyright (C) 2000 Eazel, Inc. - - The Gnome 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 Gnome 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 the Gnome 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. - - Author: John Sullivan <sullivan@eazel.com>, - */ - -#include <config.h> -#include "nautilus-generous-bin.h" - -#include <eel/eel-gtk-macros.h> - -static void nautilus_generous_bin_initialize_class (NautilusGenerousBinClass *class); -static void nautilus_generous_bin_initialize (NautilusGenerousBin *box); -static void nautilus_generous_bin_size_request (GtkWidget *widget, - GtkRequisition *requisition); -static void nautilus_generous_bin_size_allocate (GtkWidget *widget, - GtkAllocation *allocation); - -EEL_DEFINE_CLASS_BOILERPLATE (NautilusGenerousBin, nautilus_generous_bin, GTK_TYPE_BIN) - -static void -nautilus_generous_bin_initialize_class (NautilusGenerousBinClass *klass) -{ - GTK_WIDGET_CLASS (klass)->size_request = nautilus_generous_bin_size_request; - GTK_WIDGET_CLASS (klass)->size_allocate = nautilus_generous_bin_size_allocate; -} - -static void -nautilus_generous_bin_initialize (NautilusGenerousBin *bin) -{ -} - -static void -nautilus_generous_bin_size_request (GtkWidget *widget, - GtkRequisition *requisition) -{ - GtkBin *bin; - GtkRequisition child_requisition; - - bin = GTK_BIN (widget); - - requisition->width = 0; - requisition->height = 0; - - if (bin->child != NULL && GTK_WIDGET_VISIBLE (bin->child)) { - gtk_widget_size_request (bin->child, &child_requisition); - - requisition->width += child_requisition.width; - requisition->height += child_requisition.height; - } -} - -static void -nautilus_generous_bin_size_allocate (GtkWidget *widget, - GtkAllocation *allocation) -{ - GtkBin *bin; - GtkAllocation child_allocation; - - bin = GTK_BIN (widget); - - widget->allocation = *allocation; - - if (bin->child != NULL && GTK_WIDGET_VISIBLE (bin->child)) { - child_allocation = *allocation; - gtk_widget_size_allocate (bin->child, &child_allocation); - } -} diff --git a/libnautilus-extensions/nautilus-generous-bin.h b/libnautilus-extensions/nautilus-generous-bin.h deleted file mode 100644 index decf64956..000000000 --- a/libnautilus-extensions/nautilus-generous-bin.h +++ /dev/null @@ -1,50 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ - -/* nautilus-generous-bin.h: Subclass of GtkBin that gives all of its - allocation to its child. - - Copyright (C) 2000 Eazel, Inc. - - The Gnome 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 Gnome 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 the Gnome 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. - - Author: Darin Adler <darin@eazel.com> - */ - -#ifndef NAUTILUS_GENEROUS_BIN_H -#define NAUTILUS_GENEROUS_BIN_H - -#include <gtk/gtkbin.h> - -#define NAUTILUS_TYPE_GENEROUS_BIN (nautilus_generous_bin_get_type ()) -#define NAUTILUS_GENEROUS_BIN(obj) (GTK_CHECK_CAST ((obj), NAUTILUS_TYPE_GENEROUS_BIN, NautilusGenerousBin)) -#define NAUTILUS_GENEROUS_BIN_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), NAUTILUS_TYPE_GENEROUS_BIN, NautilusGenerousBinClass)) -#define NAUTILUS_IS_GENEROUS_BIN(obj) (GTK_CHECK_TYPE ((obj), NAUTILUS_TYPE_GENEROUS_BIN)) -#define NAUTILUS_IS_GENEROUS_BIN_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), NAUTILUS_TYPE_GENEROUS_BIN)) - -typedef struct NautilusGenerousBin NautilusGenerousBin; -typedef struct NautilusGenerousBinClass NautilusGenerousBinClass; - -struct NautilusGenerousBin { - GtkBin parent_slot; -}; - -struct NautilusGenerousBinClass { - GtkBinClass parent_slot; -}; - -GtkType nautilus_generous_bin_get_type (void); - -#endif /* NAUTILUS_GENEROUS_BIN_H */ diff --git a/libnautilus-extensions/nautilus-global-preferences.c b/libnautilus-extensions/nautilus-global-preferences.c deleted file mode 100644 index 91b65e11e..000000000 --- a/libnautilus-extensions/nautilus-global-preferences.c +++ /dev/null @@ -1,1115 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ - -/* nautilus-prefs-dialog.c - Implementation for preferences dialog. - - Copyright (C) 1999, 2000, 2001 Eazel, Inc. - - The Gnome 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 Gnome 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 the Gnome 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. - - Authors: Ramiro Estrugo <ramiro@eazel.com> -*/ - -#include <config.h> -#include "nautilus-global-preferences.h" - -#include "nautilus-file-utilities.h" -#include "nautilus-file.h" -#include "nautilus-icon-factory.h" -#include "nautilus-sidebar-functions.h" -#include <eel/eel-enumeration.h> -#include <eel/eel-font-manager.h> -#include <eel/eel-glib-extensions.h> -#include <eel/eel-gtk-extensions.h> -#include <eel/eel-scalable-font.h> -#include <eel/eel-smooth-widget.h> -#include <eel/eel-stock-dialogs.h> -#include <eel/eel-string.h> -#include <libgnome/gnome-i18n.h> -#include <libgnome/gnome-util.h> -#include <libgnomevfs/gnome-vfs-mime-handlers.h> -#include <libgnomevfs/gnome-vfs-utils.h> - -/* Constants */ -#define STRING_LIST_DEFAULT_TOKENS_DELIMETER "," -#define PREFERENCES_SORT_ORDER_MANUALLY 100 - -/* base path for NAUTILUS_PREFERENCES_HTTP_* */ -static const char SYSTEM_GNOME_VFS_PATH[] = "/system/gnome-vfs"; - -/* Forward declarations */ -static void global_preferences_install_defaults (void); -static void global_preferences_register_enumerations (void); -static gpointer default_font_callback (int user_level); -static gpointer default_smooth_font_callback (int user_level); -static gpointer default_home_location_callback (int user_level); -static gpointer default_default_folder_viewer_callback (int user_level); - -static const char *default_smooth_font_auto_value; -static const char *icon_view_smooth_font_auto_value; - -/* An enumeration used for installing type specific preferences defaults. */ -typedef enum -{ - PREFERENCE_BOOLEAN = 1, - PREFERENCE_INTEGER, - PREFERENCE_STRING, - PREFERENCE_STRING_LIST -} PreferenceType; - -/* Enumerations used to qualify some INTEGER preferences */ -static EelEnumerationEntry speed_tradeoff_enum_entries[] = { - { "always", N_("Always"), NAUTILUS_SPEED_TRADEOFF_ALWAYS }, - { "local_only", N_("Local Files Only"), NAUTILUS_SPEED_TRADEOFF_LOCAL_ONLY }, - { "never", N_("Never"), NAUTILUS_SPEED_TRADEOFF_NEVER }, - { NULL } -}; - -static EelEnumerationEntry default_zoom_level_enum_entries[] = { - { "smallest", N_("25%"), NAUTILUS_ZOOM_LEVEL_SMALLEST }, - { "smaller", N_("50%"), NAUTILUS_ZOOM_LEVEL_SMALLER }, - { "small", N_("75%"), NAUTILUS_ZOOM_LEVEL_SMALL }, - { "standard", N_("100%"), NAUTILUS_ZOOM_LEVEL_STANDARD }, - { "large", N_("150%"), NAUTILUS_ZOOM_LEVEL_LARGE }, - { "larger", N_("200%"), NAUTILUS_ZOOM_LEVEL_LARGER }, - { "largest", N_("400%"), NAUTILUS_ZOOM_LEVEL_LARGEST }, - { NULL } -}; - -static EelEnumerationEntry file_size_enum_entries[] = { - { "102400", N_("100 K"), 102400 }, - { "512000", N_("500 K"), 512000 }, - { "1048576", N_("1 MB"), 1048576 }, - { "3145728", N_("3 MB"), 3145728 }, - { "5242880", N_("5 MB"), 5242880 }, - { "10485760", N_("10 MB"), 10485760 }, - { "104857600", N_("100 MB"), 104857600 }, - { NULL } -}; - -static EelEnumerationEntry click_policy_enum_entries[] = { - { "single", - N_("Activate items with a single click"), - NAUTILUS_CLICK_POLICY_SINGLE - }, - { "double", - N_("Activate items with a double click"), - NAUTILUS_CLICK_POLICY_DOUBLE - }, - { NULL } -}; - -static EelEnumerationEntry executable_text_activation_enum_entries[] = { - { "launch", - N_("Execute files when they are clicked"), - NAUTILUS_EXECUTABLE_TEXT_LAUNCH - }, - { "display", - N_("Display files when they are clicked"), - NAUTILUS_EXECUTABLE_TEXT_DISPLAY - }, - { "ask", - N_("Ask each time"), - NAUTILUS_EXECUTABLE_TEXT_ASK - }, - { NULL } -}; - -static EelEnumerationEntry search_bar_type_enum_entries[] = { - { N_("search by text"), - N_("Search for files by file name only"), - NAUTILUS_SIMPLE_SEARCH_BAR - }, - { N_("search by text and properties"), - N_("Search for files by file name and file properties"), - NAUTILUS_COMPLEX_SEARCH_BAR - }, - { NULL } -}; - -static EelEnumerationEntry default_folder_viewer_enum_entries[] = { - { "icon_view", N_("Icon View"), NAUTILUS_DEFAULT_FOLDER_VIEWER_ICON_VIEW }, - { "list_view", N_("List View"), NAUTILUS_DEFAULT_FOLDER_VIEWER_LIST_VIEW }, - { NULL } -}; - -static EelEnumerationEntry default_icon_view_sort_order_enum_entries[] = { - { "manually", N_("Manually"), PREFERENCES_SORT_ORDER_MANUALLY }, - { "--------", "--------" }, - { "name", N_("By Name"), NAUTILUS_FILE_SORT_BY_NAME }, - { "size", N_("By Size"), NAUTILUS_FILE_SORT_BY_SIZE }, - { "type", N_("By Type"), NAUTILUS_FILE_SORT_BY_TYPE }, - { "modification_date", N_("By Modification Date"), NAUTILUS_FILE_SORT_BY_MTIME }, - { "emblems", N_("By Emblems"), NAUTILUS_FILE_SORT_BY_EMBLEMS }, - { NULL } -}; - -static EelEnumerationEntry default_list_view_sort_order_enum_entries[] = { - { "name", N_("By Name"), NAUTILUS_FILE_SORT_BY_NAME }, - { "size", N_("By Size"), NAUTILUS_FILE_SORT_BY_SIZE }, - { "type", N_("By Type"), NAUTILUS_FILE_SORT_BY_TYPE }, - { "modification_date", N_("By Modification Date"), NAUTILUS_FILE_SORT_BY_MTIME }, - { "emblems", N_("By Emblems"), NAUTILUS_FILE_SORT_BY_EMBLEMS }, - { NULL } -}; - -static EelEnumerationEntry standard_font_size_entries[] = { - { "8", N_("8"), 8 }, - { "10", N_("10"), 10 }, - { "12", N_("12"), 12 }, - { "14", N_("14"), 14 }, - { "16", N_("16"), 16 }, - { "18", N_("18"), 18 }, - { "20", N_("20"), 20 }, - { "22", N_("22"), 22 }, - { "24", N_("24"), 24 }, - { NULL } -}; - -static EelEnumerationEntry icon_captions_enum_entries[] = { - { "size", N_("size"), 0 }, - { "type", N_("type"), 1 }, - { "date_modified", N_("date modified"), 2 }, - { "date_changed", N_("date changed"), 3 }, - { "date_accessed", N_("date accessed"), 4 }, - { "owner", N_("owner"), 5 }, - { "group", N_("group"), 6 }, - { "permissions", N_("permissions"), 7 }, - { "octal_permissions", N_("octal permissions"), 8 }, - { "mime_type", N_("MIME type"), 9 }, - { "none", N_("none"), 10 }, - { NULL } -}; - -/* These enumerations are used in the preferences dialog to - * populate widgets and route preferences changes between the - * storage (GConf) and the displayed values. - */ -static EelEnumerationInfo enumerations[] = { - { "click_policy", click_policy_enum_entries }, - { "default_folder_viewer", default_folder_viewer_enum_entries }, - { "default_icon_view_sort_order", default_icon_view_sort_order_enum_entries }, - { "default_list_view_sort_order", default_list_view_sort_order_enum_entries }, - { "default_zoom_level", default_zoom_level_enum_entries }, - { "executable_text_activation", executable_text_activation_enum_entries }, - { "file_size", file_size_enum_entries }, - { "icon_captions", icon_captions_enum_entries }, - { "search_bar_type", search_bar_type_enum_entries }, - { "speed_tradeoff", speed_tradeoff_enum_entries }, - { "standard_font_size", standard_font_size_entries }, - { NULL } -}; - -/* - * A callback which can be used to fetch dynamic default values. - * For example, values that are dependent on the environment (such as user name) - * cannot be specified as constants. - */ -typedef gpointer (*PreferencesDefaultValueCallback) (int user_level); - -/* A structure that pairs a default value with a specific user level. */ -typedef struct -{ - int user_level; - const gpointer value; - PreferencesDefaultValueCallback callback; - GFreeFunc callback_result_free_function; -} PreferenceUserLevelDefault; - -#define USER_LEVEL_NONE -1 - -/* A structure that describes a single preference including defaults and visibility. */ -typedef struct -{ - const char *name; - PreferenceType type; - int visible_user_level; - const PreferenceUserLevelDefault default1; - const PreferenceUserLevelDefault default2; - const char *enumeration_id; -} PreferenceDefault; - -/* The following table defines the default values and user level visibilities of - * Nautilus preferences. Each of these preferences does not necessarily need to - * have a UI item in the preferences dialog. To add an item to the preferences - * dialog, see the NautilusPreferencesItemDescription tables later in this file. - * - * Field definitions: - * - * 1. name - * - * The name of the preference. Usually defined in - * nautilus-global-preferences.h - * - * 2. type - * The preference type. One of: - * - * PREFERENCE_BOOLEAN - * PREFERENCE_INTEGER - * PREFERENCE_STRING - * PREFERENCE_STRING_LIST - * - * 3. visible_user_level - * The visible user level is the first user level at which the - * preference is visible. By default all preferences have a visibility of 0. - * - * A preference with a visible_user_level greater than 0, will be "visible" - * only at that level or higher. Any getters that ask for that preference at - * lower user levels will always receive the default value. Also, if the - * preference has an entry in the preferences dialog, it will not be shown - * unless the current user level is greater than or equal to the preference's - * visible user level. - * - * 4. default1 - * A pair of a user_level and a value (PreferenceUserLevelDefault). For the - * left hand side user_level, the preference will have the right hand side - * default value. - * - * This pair does not need to be given. It can be { USER_LEVEL_NONE }, in - * which case the preference defaults to 0 at all user levels. - * - * 5. default2 - * A pair of a user_level and a value (PreferenceUserLevelDefault). For the - * left hand side user_level, the preference will have the right hand side - * default value. - * - * This pair does not need to be given. It can be { USER_LEVEL_NONE }, in - * which case the preference defaults to 0 at all user levels. - * - * Notes: - * - * Define defaults only for preferences that need something other than 0 (integer) - * FALSE (boolean) or "" (string) as their defaults. - * - * Its possible to have different defaults for different user levels Its not - * required to have defaults for EACH user level. If there is no default - * installed for a high user level, the next lowest user level with a valid - * default is used. - * - * 6. enumeration_id - * An an enumeration id is a unique string that identifies an enumeration. - * If given, an enumeration id can be used to qualify a INTEGER preference. - * The preferences dialog widgetry will use this enumeration id to find out - * what choices and descriptions of choices to present to the user. - */ -static const PreferenceDefault preference_defaults[] = { - { NAUTILUS_PREFERENCES_SHOW_HIDDEN_FILES, - PREFERENCE_BOOLEAN, - NAUTILUS_USER_LEVEL_INTERMEDIATE, - { NAUTILUS_USER_LEVEL_NOVICE, GINT_TO_POINTER (FALSE) }, - { USER_LEVEL_NONE } - }, - { NAUTILUS_PREFERENCES_SHOW_BACKUP_FILES, - PREFERENCE_BOOLEAN, - NAUTILUS_USER_LEVEL_INTERMEDIATE, - { NAUTILUS_USER_LEVEL_NOVICE, GINT_TO_POINTER (FALSE) }, - { USER_LEVEL_NONE } - }, - { NAUTILUS_PREFERENCES_CONFIRM_TRASH, - PREFERENCE_BOOLEAN, - NAUTILUS_USER_LEVEL_ADVANCED, - { NAUTILUS_USER_LEVEL_NOVICE, GINT_TO_POINTER (TRUE) }, - { USER_LEVEL_NONE } - }, - { NAUTILUS_PREFERENCES_ENABLE_DELETE, - PREFERENCE_BOOLEAN, - NAUTILUS_USER_LEVEL_ADVANCED, - { NAUTILUS_USER_LEVEL_NOVICE, GINT_TO_POINTER (FALSE) }, - { USER_LEVEL_NONE } - }, - { NAUTILUS_PREFERENCES_SHOW_TEXT_IN_ICONS, - PREFERENCE_INTEGER, - NAUTILUS_USER_LEVEL_INTERMEDIATE, - { NAUTILUS_USER_LEVEL_NOVICE, GINT_TO_POINTER (NAUTILUS_SPEED_TRADEOFF_LOCAL_ONLY) }, - { USER_LEVEL_NONE }, - "speed_tradeoff" - }, - /* Don't show remote directory item counts for Beginner users because computing them - * can be annoyingly slow, especially for FTP. If we make this fast enough for FTP in - * particular, we should change this default to ALWAYS. - */ - { NAUTILUS_PREFERENCES_SHOW_DIRECTORY_ITEM_COUNTS, - PREFERENCE_INTEGER, - NAUTILUS_USER_LEVEL_INTERMEDIATE, - { NAUTILUS_USER_LEVEL_NOVICE, GINT_TO_POINTER (NAUTILUS_SPEED_TRADEOFF_LOCAL_ONLY) }, - { NAUTILUS_USER_LEVEL_INTERMEDIATE, GINT_TO_POINTER (NAUTILUS_SPEED_TRADEOFF_ALWAYS) }, - "speed_tradeoff" - }, - { NAUTILUS_PREFERENCES_CLICK_POLICY, - PREFERENCE_INTEGER, - NAUTILUS_USER_LEVEL_INTERMEDIATE, - { NAUTILUS_USER_LEVEL_NOVICE, GINT_TO_POINTER (NAUTILUS_SPEED_TRADEOFF_LOCAL_ONLY) }, - { USER_LEVEL_NONE }, - "click_policy" - }, - { NAUTILUS_PREFERENCES_EXECUTABLE_TEXT_ACTIVATION, - PREFERENCE_INTEGER, - NAUTILUS_USER_LEVEL_ADVANCED, - { NAUTILUS_USER_LEVEL_NOVICE, GINT_TO_POINTER (NAUTILUS_EXECUTABLE_TEXT_ASK) }, - { USER_LEVEL_NONE }, - "executable_text_activation" - }, - { NAUTILUS_PREFERENCES_THEME, - PREFERENCE_STRING, - NAUTILUS_USER_LEVEL_NOVICE, - { NAUTILUS_USER_LEVEL_NOVICE, "default" }, - { USER_LEVEL_NONE } - }, - { NAUTILUS_PREFERENCES_SHOW_IMAGE_FILE_THUMBNAILS, - PREFERENCE_INTEGER, - NAUTILUS_USER_LEVEL_INTERMEDIATE, - { NAUTILUS_USER_LEVEL_NOVICE, GINT_TO_POINTER (NAUTILUS_SPEED_TRADEOFF_LOCAL_ONLY) }, - { USER_LEVEL_NONE }, - "speed_tradeoff" - }, - { NAUTILUS_PREFERENCES_IMAGE_FILE_THUMBNAIL_LIMIT, - PREFERENCE_INTEGER, - NAUTILUS_USER_LEVEL_ADVANCED, - { NAUTILUS_USER_LEVEL_NOVICE, GINT_TO_POINTER (3145728) }, - { USER_LEVEL_NONE }, - "file_size" - }, - { NAUTILUS_PREFERENCES_USE_PUBLIC_METADATA, - PREFERENCE_INTEGER, - NAUTILUS_USER_LEVEL_ADVANCED, - { NAUTILUS_USER_LEVEL_NOVICE, GINT_TO_POINTER (NAUTILUS_SPEED_TRADEOFF_LOCAL_ONLY) }, - { USER_LEVEL_NONE }, - "speed_tradeoff" - }, - { NAUTILUS_PREFERENCES_SMOOTH_GRAPHICS_MODE, - PREFERENCE_BOOLEAN, - NAUTILUS_USER_LEVEL_INTERMEDIATE, - { NAUTILUS_USER_LEVEL_NOVICE, GINT_TO_POINTER (TRUE) }, - { USER_LEVEL_NONE } - }, - { NAUTILUS_PREFERENCES_PREVIEW_SOUND, - PREFERENCE_INTEGER, - NAUTILUS_USER_LEVEL_INTERMEDIATE, - { NAUTILUS_USER_LEVEL_NOVICE, GINT_TO_POINTER (NAUTILUS_SPEED_TRADEOFF_LOCAL_ONLY) }, - { USER_LEVEL_NONE }, - "speed_tradeoff" - }, - { NAUTILUS_PREFERENCES_SHOW_SPECIAL_FLAGS, - PREFERENCE_BOOLEAN, - NAUTILUS_USER_LEVEL_ADVANCED, - { NAUTILUS_USER_LEVEL_NOVICE, GINT_TO_POINTER (FALSE) }, - { NAUTILUS_USER_LEVEL_ADVANCED, GINT_TO_POINTER (TRUE) } - }, - { NAUTILUS_PREFERENCES_SORT_DIRECTORIES_FIRST, - PREFERENCE_BOOLEAN, - NAUTILUS_USER_LEVEL_INTERMEDIATE, - { NAUTILUS_USER_LEVEL_NOVICE, GINT_TO_POINTER (FALSE) }, - { USER_LEVEL_NONE } - }, - { NAUTILUS_PREFERENCES_SHOW_DESKTOP, - PREFERENCE_BOOLEAN, - NAUTILUS_USER_LEVEL_INTERMEDIATE, - { NAUTILUS_USER_LEVEL_NOVICE, GINT_TO_POINTER (TRUE) }, - { USER_LEVEL_NONE } - }, - { NAUTILUS_PREFERENCES_DESKTOP_IS_HOME_DIR, - PREFERENCE_BOOLEAN, - NAUTILUS_USER_LEVEL_ADVANCED, - { NAUTILUS_USER_LEVEL_NOVICE, GINT_TO_POINTER (FALSE) }, - { USER_LEVEL_NONE } - }, - { NAUTILUS_PREFERENCES_CAN_ADD_CONTENT, - PREFERENCE_BOOLEAN, - NAUTILUS_USER_LEVEL_NOVICE, - { NAUTILUS_USER_LEVEL_NOVICE, GINT_TO_POINTER (FALSE) }, - { NAUTILUS_USER_LEVEL_INTERMEDIATE, GINT_TO_POINTER (TRUE) } - }, - { NAUTILUS_PREFERENCES_SEARCH_BAR_TYPE, - PREFERENCE_INTEGER, - NAUTILUS_USER_LEVEL_INTERMEDIATE, - { NAUTILUS_USER_LEVEL_NOVICE, GINT_TO_POINTER (NAUTILUS_SIMPLE_SEARCH_BAR) }, - { NAUTILUS_USER_LEVEL_INTERMEDIATE, GINT_TO_POINTER (NAUTILUS_COMPLEX_SEARCH_BAR) }, - "search_bar_type" - }, - { NAUTILUS_PREFERENCES_WINDOW_ALWAYS_NEW, - PREFERENCE_BOOLEAN, - NAUTILUS_USER_LEVEL_NOVICE, - { NAUTILUS_USER_LEVEL_NOVICE, GINT_TO_POINTER (FALSE) }, - { USER_LEVEL_NONE } - }, - { NAUTILUS_PREFERENCES_ICON_VIEW_CAPTIONS, - PREFERENCE_STRING_LIST, - NAUTILUS_USER_LEVEL_NOVICE, - { NAUTILUS_USER_LEVEL_NOVICE, "size,date_modified,type", }, - { USER_LEVEL_NONE }, - "icon_captions" - }, - { NAUTILUS_PREFERENCES_HIDE_BUILT_IN_BOOKMARKS, - PREFERENCE_BOOLEAN, - NAUTILUS_USER_LEVEL_INTERMEDIATE, - { NAUTILUS_USER_LEVEL_NOVICE, GINT_TO_POINTER (FALSE) }, - { USER_LEVEL_NONE } - }, - { NAUTILUS_PREFERENCES_USE_EMACS_SHORTCUTS, - PREFERENCE_BOOLEAN, - NAUTILUS_USER_LEVEL_ADVANCED, - { NAUTILUS_USER_LEVEL_NOVICE, GINT_TO_POINTER (FALSE) }, - { USER_LEVEL_NONE } - }, - /* FIXME bugzilla.eazel.com 1245: Saved in pixels instead of in %? */ - { NAUTILUS_PREFERENCES_SIDEBAR_WIDTH, - PREFERENCE_INTEGER, - NAUTILUS_USER_LEVEL_NOVICE, - { NAUTILUS_USER_LEVEL_NOVICE, GINT_TO_POINTER (148) }, - { USER_LEVEL_NONE } - }, - { NAUTILUS_PREFERENCES_SEARCH_WEB_URI, - PREFERENCE_STRING, - NAUTILUS_USER_LEVEL_INTERMEDIATE, - { NAUTILUS_USER_LEVEL_NOVICE, "http://www.eazel.com/websearch" }, - { USER_LEVEL_NONE } - }, - { NAUTILUS_PREFERENCES_START_WITH_TOOLBAR, - PREFERENCE_BOOLEAN, - NAUTILUS_USER_LEVEL_INTERMEDIATE, - { NAUTILUS_USER_LEVEL_NOVICE, GINT_TO_POINTER (TRUE) }, - { USER_LEVEL_NONE } - }, - { NAUTILUS_PREFERENCES_START_WITH_LOCATION_BAR, - PREFERENCE_BOOLEAN, - NAUTILUS_USER_LEVEL_INTERMEDIATE, - { NAUTILUS_USER_LEVEL_NOVICE, GINT_TO_POINTER (TRUE) }, - { USER_LEVEL_NONE } - }, - { NAUTILUS_PREFERENCES_START_WITH_STATUS_BAR, - PREFERENCE_BOOLEAN, - NAUTILUS_USER_LEVEL_INTERMEDIATE, - { NAUTILUS_USER_LEVEL_NOVICE, GINT_TO_POINTER (TRUE) }, - { USER_LEVEL_NONE } - }, - { NAUTILUS_PREFERENCES_START_WITH_SIDEBAR, - PREFERENCE_BOOLEAN, - NAUTILUS_USER_LEVEL_INTERMEDIATE, - { NAUTILUS_USER_LEVEL_NOVICE, GINT_TO_POINTER (TRUE) }, - { USER_LEVEL_NONE } - }, - { NAUTILUS_PREFERENCES_TREE_SHOW_ONLY_DIRECTORIES, - PREFERENCE_BOOLEAN, - NAUTILUS_USER_LEVEL_INTERMEDIATE, - { NAUTILUS_USER_LEVEL_NOVICE, GINT_TO_POINTER (FALSE) }, - { USER_LEVEL_NONE } - }, - - /* Proxy defaults */ - { NAUTILUS_PREFERENCES_HTTP_USE_PROXY, - PREFERENCE_BOOLEAN, - NAUTILUS_USER_LEVEL_NOVICE, - { NAUTILUS_USER_LEVEL_NOVICE, GINT_TO_POINTER (FALSE) }, - { USER_LEVEL_NONE } - }, - { NAUTILUS_PREFERENCES_HTTP_PROXY_PORT, - PREFERENCE_INTEGER, - NAUTILUS_USER_LEVEL_NOVICE, - { NAUTILUS_USER_LEVEL_NOVICE, GINT_TO_POINTER (8080) }, - { USER_LEVEL_NONE } - }, - { NAUTILUS_PREFERENCES_HTTP_PROXY_USE_AUTH, - PREFERENCE_BOOLEAN, - NAUTILUS_USER_LEVEL_NOVICE, - { NAUTILUS_USER_LEVEL_NOVICE, GINT_TO_POINTER (FALSE) }, - { USER_LEVEL_NONE } - }, - - /* Home URI */ - { NAUTILUS_PREFERENCES_HOME_URI, - PREFERENCE_STRING, - NAUTILUS_USER_LEVEL_INTERMEDIATE, - { NAUTILUS_USER_LEVEL_NOVICE, NULL, default_home_location_callback, g_free }, - { NAUTILUS_USER_LEVEL_INTERMEDIATE, NULL, default_home_location_callback, g_free }, - }, - - /* Default fonts */ - { NAUTILUS_PREFERENCES_DEFAULT_FONT, - PREFERENCE_STRING, - NAUTILUS_USER_LEVEL_NOVICE, - { NAUTILUS_USER_LEVEL_NOVICE, NULL, default_font_callback, g_free }, - { USER_LEVEL_NONE } - }, - { NAUTILUS_PREFERENCES_DEFAULT_SMOOTH_FONT, - PREFERENCE_STRING, - NAUTILUS_USER_LEVEL_NOVICE, - { NAUTILUS_USER_LEVEL_NOVICE, NULL, default_smooth_font_callback, g_free }, - { USER_LEVEL_NONE } - }, - { NAUTILUS_PREFERENCES_DEFAULT_FONT_SIZE, - PREFERENCE_INTEGER, - NAUTILUS_USER_LEVEL_NOVICE, - { NAUTILUS_USER_LEVEL_NOVICE, GINT_TO_POINTER (12) }, - { USER_LEVEL_NONE }, - "standard_font_size" - }, - - /* View Preferences */ - { NAUTILUS_PREFERENCES_DEFAULT_FOLDER_VIEWER, - PREFERENCE_INTEGER, - NAUTILUS_USER_LEVEL_NOVICE, - { NAUTILUS_USER_LEVEL_NOVICE, NULL, default_default_folder_viewer_callback, NULL }, - { USER_LEVEL_NONE }, - "default_folder_viewer" - }, - - /* Icon View Default Preferences */ - { NAUTILUS_PREFERENCES_ICON_VIEW_SMOOTH_FONT, - PREFERENCE_STRING, - NAUTILUS_USER_LEVEL_NOVICE, - { NAUTILUS_USER_LEVEL_NOVICE, NULL, default_smooth_font_callback, g_free }, - { USER_LEVEL_NONE } - }, - { NAUTILUS_PREFERENCES_ICON_VIEW_FONT, - PREFERENCE_STRING, - NAUTILUS_USER_LEVEL_NOVICE, - { NAUTILUS_USER_LEVEL_NOVICE, NULL, default_font_callback, g_free }, - { USER_LEVEL_NONE } - }, - { NAUTILUS_PREFERENCES_ICON_VIEW_DEFAULT_ZOOM_LEVEL_FONT_SIZE, - PREFERENCE_INTEGER, - NAUTILUS_USER_LEVEL_NOVICE, - { NAUTILUS_USER_LEVEL_NOVICE, GINT_TO_POINTER (12) }, - { USER_LEVEL_NONE }, - "standard_font_size" - }, - { NAUTILUS_PREFERENCES_ICON_VIEW_DEFAULT_SORT_ORDER, - PREFERENCE_INTEGER, - NAUTILUS_USER_LEVEL_NOVICE, - { NAUTILUS_USER_LEVEL_NOVICE, GINT_TO_POINTER (NAUTILUS_FILE_SORT_BY_NAME) }, - { USER_LEVEL_NONE }, - "default_icon_view_sort_order" - }, - { NAUTILUS_PREFERENCES_ICON_VIEW_DEFAULT_SORT_ORDER_OR_MANUAL_LAYOUT, - PREFERENCE_INTEGER, - NAUTILUS_USER_LEVEL_NOVICE, - { NAUTILUS_USER_LEVEL_NOVICE, GINT_TO_POINTER (NAUTILUS_FILE_SORT_BY_NAME) }, - { USER_LEVEL_NONE }, - "default_icon_view_sort_order" - }, - { NAUTILUS_PREFERENCES_ICON_VIEW_DEFAULT_SORT_IN_REVERSE_ORDER, - PREFERENCE_BOOLEAN, - NAUTILUS_USER_LEVEL_NOVICE, - { NAUTILUS_USER_LEVEL_NOVICE, GINT_TO_POINTER (FALSE) }, - { USER_LEVEL_NONE } - }, - { NAUTILUS_PREFERENCES_ICON_VIEW_DEFAULT_USE_TIGHTER_LAYOUT, - PREFERENCE_BOOLEAN, - NAUTILUS_USER_LEVEL_NOVICE, - { NAUTILUS_USER_LEVEL_NOVICE, GINT_TO_POINTER (FALSE) }, - { USER_LEVEL_NONE } - }, - { NAUTILUS_PREFERENCES_ICON_VIEW_DEFAULT_USE_MANUAL_LAYOUT, - PREFERENCE_BOOLEAN, - NAUTILUS_USER_LEVEL_NOVICE, - { NAUTILUS_USER_LEVEL_NOVICE, GINT_TO_POINTER (FALSE) }, - { USER_LEVEL_NONE } - }, - { NAUTILUS_PREFERENCES_ICON_VIEW_DEFAULT_ZOOM_LEVEL, - PREFERENCE_INTEGER, - NAUTILUS_USER_LEVEL_NOVICE, - { NAUTILUS_USER_LEVEL_NOVICE, GINT_TO_POINTER (NAUTILUS_ZOOM_LEVEL_STANDARD) }, - { USER_LEVEL_NONE }, - "default_zoom_level" - }, - - /* List View Default Preferences */ - { NAUTILUS_PREFERENCES_LIST_VIEW_FONT, - PREFERENCE_STRING, - NAUTILUS_USER_LEVEL_NOVICE, - { NAUTILUS_USER_LEVEL_NOVICE, NULL, default_font_callback, g_free }, - { USER_LEVEL_NONE } - }, - { NAUTILUS_PREFERENCES_LIST_VIEW_DEFAULT_ZOOM_LEVEL_FONT_SIZE, - PREFERENCE_INTEGER, - NAUTILUS_USER_LEVEL_NOVICE, - { NAUTILUS_USER_LEVEL_NOVICE, GINT_TO_POINTER (12) }, - { USER_LEVEL_NONE }, - "standard_font_size" - }, - { NAUTILUS_PREFERENCES_LIST_VIEW_DEFAULT_SORT_ORDER, - PREFERENCE_INTEGER, - NAUTILUS_USER_LEVEL_NOVICE, - { NAUTILUS_USER_LEVEL_NOVICE, GINT_TO_POINTER (NAUTILUS_FILE_SORT_BY_NAME) }, - { USER_LEVEL_NONE }, - "default_list_view_sort_order" - }, - { NAUTILUS_PREFERENCES_LIST_VIEW_DEFAULT_SORT_IN_REVERSE_ORDER, - PREFERENCE_BOOLEAN, - NAUTILUS_USER_LEVEL_NOVICE, - { NAUTILUS_USER_LEVEL_NOVICE, GINT_TO_POINTER (FALSE) }, - { USER_LEVEL_NONE } - }, - { NAUTILUS_PREFERENCES_LIST_VIEW_DEFAULT_ZOOM_LEVEL, - PREFERENCE_INTEGER, - NAUTILUS_USER_LEVEL_NOVICE, - { NAUTILUS_USER_LEVEL_NOVICE, GINT_TO_POINTER (NAUTILUS_ZOOM_LEVEL_SMALLER) }, - { USER_LEVEL_NONE }, - "default_zoom_level" - }, - - /* Sidebar panel default */ - { nautilus_sidebar_news_enabled_preference_name, - PREFERENCE_BOOLEAN, - NAUTILUS_USER_LEVEL_INTERMEDIATE, - { NAUTILUS_USER_LEVEL_NOVICE, GINT_TO_POINTER (TRUE) }, - { USER_LEVEL_NONE } - }, - { nautilus_sidebar_notes_enabled_preference_name, - PREFERENCE_BOOLEAN, - NAUTILUS_USER_LEVEL_INTERMEDIATE, - { NAUTILUS_USER_LEVEL_NOVICE, GINT_TO_POINTER (TRUE) }, - { USER_LEVEL_NONE } - }, - { nautilus_sidebar_help_enabled_preference_name, - PREFERENCE_BOOLEAN, - NAUTILUS_USER_LEVEL_INTERMEDIATE, - { NAUTILUS_USER_LEVEL_NOVICE, GINT_TO_POINTER (TRUE) }, - { USER_LEVEL_NONE } - }, - { nautilus_sidebar_history_enabled_preference_name, - PREFERENCE_BOOLEAN, - NAUTILUS_USER_LEVEL_INTERMEDIATE, - { NAUTILUS_USER_LEVEL_NOVICE, GINT_TO_POINTER (TRUE) }, - { USER_LEVEL_NONE } - }, - { nautilus_sidebar_tree_enabled_preference_name, - PREFERENCE_BOOLEAN, - NAUTILUS_USER_LEVEL_INTERMEDIATE, - { NAUTILUS_USER_LEVEL_NOVICE, GINT_TO_POINTER (FALSE) }, - { NAUTILUS_USER_LEVEL_INTERMEDIATE, GINT_TO_POINTER (TRUE) } - }, - /* news panel preferences */ - { NAUTILUS_PREFERENCES_NEWS_MAX_ITEMS, - PREFERENCE_INTEGER, - NAUTILUS_USER_LEVEL_NOVICE, - { NAUTILUS_USER_LEVEL_NOVICE, GINT_TO_POINTER (6) }, - { USER_LEVEL_NONE } - }, - { NAUTILUS_PREFERENCES_NEWS_UPDATE_INTERVAL, - PREFERENCE_INTEGER, - NAUTILUS_USER_LEVEL_NOVICE, - { NAUTILUS_USER_LEVEL_NOVICE, GINT_TO_POINTER (5) }, - { USER_LEVEL_NONE } - }, - - { NULL } -}; - -/** - * global_preferences_register_enumerations - * - * Register enumerations for INTEGER preferences that need them. - * - * This function needs to be called before the preferences dialog - * panes are populated, as they use the registered information to - * create enumeration item widgets. - */ -static void -global_preferences_register_enumerations (void) -{ - guint i; - - /* Register the enumerations */ - eel_enumeration_register (enumerations); - - /* Set the enumeration ids for preferences that need them */ - for (i = 0; preference_defaults[i].name != NULL; i++) { - if (eel_strlen (preference_defaults[i].enumeration_id) > 0) { - g_assert (preference_defaults[i].type == PREFERENCE_INTEGER - || preference_defaults[i].type == PREFERENCE_STRING_LIST); - nautilus_preferences_set_enumeration_id (preference_defaults[i].name, - preference_defaults[i].enumeration_id); - } - } -} - -static void -global_preferences_install_one_default (const char *preference_name, - PreferenceType preference_type, - const PreferenceUserLevelDefault *user_level_default) -{ - gpointer value = NULL; - EelStringList *string_list_value; - - g_return_if_fail (preference_name != NULL); - g_return_if_fail (preference_type >= PREFERENCE_BOOLEAN); - g_return_if_fail (preference_type <= PREFERENCE_STRING_LIST); - g_return_if_fail (user_level_default != NULL); - - if (user_level_default->user_level == USER_LEVEL_NONE) { - return; - } - - /* If a callback is given, use that to fetch the default value */ - if (user_level_default->callback != NULL) { - value = (* user_level_default->callback) (user_level_default->user_level); - } else { - value = user_level_default->value; - } - - switch (preference_type) { - case PREFERENCE_BOOLEAN: - nautilus_preferences_default_set_boolean (preference_name, - user_level_default->user_level, - GPOINTER_TO_INT (value)); - break; - - case PREFERENCE_INTEGER: - nautilus_preferences_default_set_integer (preference_name, - user_level_default->user_level, - GPOINTER_TO_INT (value)); - break; - - case PREFERENCE_STRING: - nautilus_preferences_default_set_string (preference_name, - user_level_default->user_level, - value); - break; - - case PREFERENCE_STRING_LIST: - string_list_value = eel_string_list_new_from_tokens (value, - STRING_LIST_DEFAULT_TOKENS_DELIMETER, - TRUE); - nautilus_preferences_default_set_string_list (preference_name, - user_level_default->user_level, - string_list_value); - eel_string_list_free (string_list_value); - break; - - default: - g_assert_not_reached (); - } - - /* Free the dynamic default value if needed */ - if (user_level_default->callback != NULL - && user_level_default->callback_result_free_function != NULL) { - (* user_level_default->callback_result_free_function) (value); - } -} - -/** - * global_preferences_install_defaults - * - * Install defaults and visibilities. - * - * Most of the defaults come from the preference_defaults table above. - * - * Many preferences require their defaults to be computed, and so there - * are special functions to install those. - */ -static void -global_preferences_install_defaults (void) -{ - guint i; - - for (i = 0; preference_defaults[i].name != NULL; i++) { - global_preferences_install_one_default (preference_defaults[i].name, - preference_defaults[i].type, - &preference_defaults[i].default1); - - global_preferences_install_one_default (preference_defaults[i].name, - preference_defaults[i].type, - &preference_defaults[i].default2); - - nautilus_preferences_set_visible_user_level (preference_defaults[i].name, - preference_defaults[i].visible_user_level); - } -} - -static gpointer -default_font_callback (int user_level) -{ - g_return_val_if_fail (nautilus_preferences_user_level_is_valid (user_level), NULL); - - if (eel_dumb_down_for_multi_byte_locale_hack ()) { - return g_strdup ("fixed"); - } - - return g_strdup ("helvetica"); -} - -static gpointer -default_smooth_font_callback (int user_level) -{ - g_return_val_if_fail (nautilus_preferences_user_level_is_valid (user_level), NULL); - return eel_font_manager_get_default_font (); -} - -static int -get_default_folder_viewer_preference_from_iid (const char *iid) -{ - g_return_val_if_fail (iid != NULL, NAUTILUS_DEFAULT_FOLDER_VIEWER_ICON_VIEW); - - if (strcmp (iid, NAUTILUS_LIST_VIEW_IID) == 0) { - return NAUTILUS_DEFAULT_FOLDER_VIEWER_LIST_VIEW; - } else if (strcmp (iid, NAUTILUS_ICON_VIEW_IID) == 0) { - return NAUTILUS_DEFAULT_FOLDER_VIEWER_ICON_VIEW; - } - - return NAUTILUS_DEFAULT_FOLDER_VIEWER_OTHER; -} - -static gpointer -default_default_folder_viewer_callback (int user_level) -{ - OAF_ServerInfo *oaf_info; - int result; - - oaf_info = gnome_vfs_mime_get_default_component ("x-directory/normal"); - if (oaf_info == NULL) { - result = NAUTILUS_DEFAULT_FOLDER_VIEWER_ICON_VIEW; - } else { - result = get_default_folder_viewer_preference_from_iid (oaf_info->iid); - if (result == NAUTILUS_DEFAULT_FOLDER_VIEWER_OTHER) { - result = NAUTILUS_DEFAULT_FOLDER_VIEWER_ICON_VIEW; - } - CORBA_free (oaf_info); - } - - return GINT_TO_POINTER (result); -} - -static gpointer -default_home_location_callback (int user_level) -{ - char *default_home_location; - char *user_main_directory; - - g_return_val_if_fail (nautilus_preferences_user_level_is_valid (user_level), NULL); - - if (user_level == NAUTILUS_USER_LEVEL_NOVICE) { - user_main_directory = nautilus_get_user_main_directory (); - default_home_location = gnome_vfs_get_uri_from_local_path (user_main_directory); - g_free (user_main_directory); - return default_home_location; - } - - if (user_level == NAUTILUS_USER_LEVEL_INTERMEDIATE) { - return gnome_vfs_get_uri_from_local_path (g_get_home_dir ()); - } - - return NULL; -} - -/* - * Public functions - */ -static EelScalableFont * -global_preferences_get_smooth_font (const char *smooth_font_file_name) -{ - EelScalableFont *smooth_font; - - smooth_font = (smooth_font_file_name != NULL && g_file_exists (smooth_font_file_name)) ? - eel_scalable_font_new (smooth_font_file_name) : - eel_scalable_font_get_default_font (); - - g_assert (EEL_IS_SCALABLE_FONT (smooth_font)); - return smooth_font; -} - -static EelScalableFont * -global_preferences_get_smooth_bold_font (const char *file_name) -{ - EelScalableFont *plain_font; - EelScalableFont *bold_font; - - plain_font = global_preferences_get_smooth_font (file_name); - g_assert (EEL_IS_SCALABLE_FONT (plain_font)); - - bold_font = eel_scalable_font_make_bold (plain_font); - - if (bold_font == NULL) { - bold_font = plain_font; - } else { - gtk_object_unref (GTK_OBJECT (plain_font)); - } - - g_assert (EEL_IS_SCALABLE_FONT (bold_font)); - return bold_font; -} - -/** - * nautilus_global_preferences_get_icon_view_smooth_font - * - * Return value: The user's smooth font for icon file names. Need to - * unref the returned GtkObject when done with it. - */ -EelScalableFont * -nautilus_global_preferences_get_icon_view_smooth_font (void) -{ - return global_preferences_get_smooth_font (icon_view_smooth_font_auto_value); -} - -/** - * nautilus_global_preferences_get_default_smooth_font - * - * Return value: The user's smooth font for default text. - * Need to unref the returned GtkObject when done with it. - */ -EelScalableFont * -nautilus_global_preferences_get_default_smooth_font (void) -{ - return global_preferences_get_smooth_font (default_smooth_font_auto_value); -} - -/** - * nautilus_global_preferences_get_default_smooth_bold_font - * - * Return value: A bold flavor on the user's default text font. If - * no bold font is found, then the plain preffered font is - * used. Need to unref the returned GtkObject when done - * with it. - */ -EelScalableFont * -nautilus_global_preferences_get_default_smooth_bold_font (void) -{ - return global_preferences_get_smooth_bold_font (default_smooth_font_auto_value); -} - -/* Let the smooth widget machinery know about smoothness changes */ -static void -smooth_graphics_mode_changed_callback (gpointer callback_data) -{ - gboolean is_smooth; - - is_smooth = nautilus_preferences_get_boolean (NAUTILUS_PREFERENCES_SMOOTH_GRAPHICS_MODE); - - eel_smooth_widget_global_set_is_smooth (is_smooth); -} - -static void -set_default_folder_viewer_in_gnome_vfs (const char *iid) -{ - gnome_vfs_mime_set_default_action_type ("x-directory/normal", GNOME_VFS_MIME_ACTION_TYPE_COMPONENT); - gnome_vfs_mime_set_default_component ("x-directory/normal", iid); -} - -/* Convert between gnome-vfs and gconf ways of storing this information. */ -static void -default_folder_viewer_changed_callback (gpointer callback_data) -{ - int preference_value; - const char *viewer_iid; - - g_assert (callback_data == NULL); - - preference_value = - nautilus_preferences_get_integer (NAUTILUS_PREFERENCES_DEFAULT_FOLDER_VIEWER); - - if (preference_value == NAUTILUS_DEFAULT_FOLDER_VIEWER_LIST_VIEW) { - viewer_iid = NAUTILUS_LIST_VIEW_IID; - } else { - g_return_if_fail (preference_value == NAUTILUS_DEFAULT_FOLDER_VIEWER_ICON_VIEW); - viewer_iid = NAUTILUS_ICON_VIEW_IID; - } - - set_default_folder_viewer_in_gnome_vfs (viewer_iid); -} - -void -nautilus_global_preferences_set_default_folder_viewer (const char *iid) -{ - int viewer_preference; - - set_default_folder_viewer_in_gnome_vfs (iid); - - viewer_preference = get_default_folder_viewer_preference_from_iid (iid); - - /* If viewer is set to one that the Preferences dialog doesn't know about, - * just change the underlying gnome-vfs setting but leave the Preferences dialog alone. - */ - if (viewer_preference == NAUTILUS_DEFAULT_FOLDER_VIEWER_OTHER) { - return; - } - - nautilus_preferences_set_integer (NAUTILUS_PREFERENCES_DEFAULT_FOLDER_VIEWER, - viewer_preference); -} - -/* The icon view uses 2 variables to store the sort order and - * whether to use manual layout. However, the UI for these - * preferences presensts them as single option menu. So we - * use the following preference as a proxy for the other two. - * In nautilus-global-preferences.c we install callbacks for - * the proxy preference and update the other 2 when it changes - */ -static void -default_icon_view_sort_order_or_manual_layout_changed_callback (gpointer callback_data) -{ - int default_sort_order_or_manual_layout; - int default_sort_order; - - default_sort_order_or_manual_layout = - nautilus_preferences_get_integer (NAUTILUS_PREFERENCES_ICON_VIEW_DEFAULT_SORT_ORDER_OR_MANUAL_LAYOUT); - - nautilus_preferences_set_boolean (NAUTILUS_PREFERENCES_ICON_VIEW_DEFAULT_USE_MANUAL_LAYOUT, - default_sort_order_or_manual_layout == PREFERENCES_SORT_ORDER_MANUALLY); - - if (default_sort_order_or_manual_layout != PREFERENCES_SORT_ORDER_MANUALLY) { - default_sort_order = default_sort_order_or_manual_layout; - - g_return_if_fail (default_sort_order >= NAUTILUS_FILE_SORT_BY_NAME); - g_return_if_fail (default_sort_order <= NAUTILUS_FILE_SORT_BY_EMBLEMS); - - nautilus_preferences_set_integer (NAUTILUS_PREFERENCES_ICON_VIEW_DEFAULT_SORT_ORDER, - default_sort_order); - } -} - -void -nautilus_global_preferences_initialize (void) -{ - static gboolean initialized = FALSE; - - if (initialized) { - return; - } - - initialized = TRUE; - - nautilus_preferences_initialize ("/apps/nautilus"); - - /* Install defaults */ - global_preferences_install_defaults (); - - global_preferences_register_enumerations (); - - /* Add the gnome-vfs path to the list of monitored directories - for proxy settings */ - nautilus_preferences_monitor_directory (SYSTEM_GNOME_VFS_PATH); - - /* Set up storage for values accessed in this file */ - nautilus_preferences_add_auto_string (NAUTILUS_PREFERENCES_ICON_VIEW_SMOOTH_FONT, - &icon_view_smooth_font_auto_value); - nautilus_preferences_add_auto_string (NAUTILUS_PREFERENCES_DEFAULT_SMOOTH_FONT, - &default_smooth_font_auto_value); - - nautilus_preferences_add_callback (NAUTILUS_PREFERENCES_SMOOTH_GRAPHICS_MODE, - smooth_graphics_mode_changed_callback, - NULL); - - nautilus_preferences_add_callback (NAUTILUS_PREFERENCES_DEFAULT_FOLDER_VIEWER, - default_folder_viewer_changed_callback, - NULL); - - nautilus_preferences_add_callback (NAUTILUS_PREFERENCES_ICON_VIEW_DEFAULT_SORT_ORDER_OR_MANUAL_LAYOUT, - default_icon_view_sort_order_or_manual_layout_changed_callback, - NULL); - - /* Keep track of smooth graphics mode changes in order to notify the smooth - * widget machinery. - */ - smooth_graphics_mode_changed_callback (NULL); -} diff --git a/libnautilus-extensions/nautilus-global-preferences.h b/libnautilus-extensions/nautilus-global-preferences.h deleted file mode 100644 index 1e9080ec5..000000000 --- a/libnautilus-extensions/nautilus-global-preferences.h +++ /dev/null @@ -1,204 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ - -/* nautilus-global-prefs.h - Nautilus main preferences api. - - 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 Library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this program; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. - - Authors: Ramiro Estrugo <ramiro@eazel.com> -*/ - -#ifndef NAUTILUS_PREFS_GLOBAL_H -#define NAUTILUS_PREFS_GLOBAL_H - -#include <libnautilus-extensions/nautilus-preferences.h> - -BEGIN_GNOME_DECLS - -/* Which theme is active */ -#define NAUTILUS_PREFERENCES_THEME "preferences/theme" - -/* How wide the sidebar is (or how wide it will be when expanded) */ -#define NAUTILUS_PREFERENCES_SIDEBAR_WIDTH "preferences/sidebar_width" - -/* Text fields */ -#define NAUTILUS_PREFERENCES_USE_EMACS_SHORTCUTS "preferences/use_emacs_shortcuts" - -/* Window options */ -#define NAUTILUS_PREFERENCES_WINDOW_ALWAYS_NEW "preferences/window_always_new" - -/* Trash options */ -#define NAUTILUS_PREFERENCES_CONFIRM_TRASH "preferences/confirm_trash" -#define NAUTILUS_PREFERENCES_ENABLE_DELETE "preferences/enable_delete" - -/* Desktop options */ -#define NAUTILUS_PREFERENCES_SHOW_DESKTOP "preferences/show_desktop" -#define NAUTILUS_PREFERENCES_DESKTOP_IS_HOME_DIR "preferences/desktop_is_home_dir" - -/* Display */ -#define NAUTILUS_PREFERENCES_SHOW_HIDDEN_FILES "preferences/show_hidden_files" -#define NAUTILUS_PREFERENCES_SHOW_BACKUP_FILES "preferences/show_backup_files" -#define NAUTILUS_PREFERENCES_SHOW_SPECIAL_FLAGS "preferences/show_special_flags" - -/* Sidebar panels */ -#define NAUTILUS_PREFERENCES_TREE_SHOW_ONLY_DIRECTORIES "sidebar-panels/tree/show_only_directories" - -/* Navigation */ -#define NAUTILUS_PREFERENCES_HOME_URI "preferences/home_uri" -#define NAUTILUS_PREFERENCES_HIDE_BUILT_IN_BOOKMARKS "preferences/hide_built_in_bookmarks" - -/* Proxy */ -#define NAUTILUS_PREFERENCES_HTTP_USE_PROXY "/system/gnome-vfs/use-http-proxy" -#define NAUTILUS_PREFERENCES_HTTP_PROXY_HOST "/system/gnome-vfs/http-proxy-host" -#define NAUTILUS_PREFERENCES_HTTP_PROXY_PORT "/system/gnome-vfs/http-proxy-port" - -/* HTTP Proxy Authentication */ -#define NAUTILUS_PREFERENCES_HTTP_PROXY_USE_AUTH "/system/gnome-vfs/use-http-proxy-authorization" -#define NAUTILUS_PREFERENCES_HTTP_PROXY_AUTH_USERNAME "/system/gnome-vfs/http-proxy-authorization-user" -#define NAUTILUS_PREFERENCES_HTTP_USE_AUTH_PASSWORD "/system/gnome-vfs/http-proxy-authorization-password" - -/* adding/removing from property browser */ -#define NAUTILUS_PREFERENCES_CAN_ADD_CONTENT "preferences/can_add_content" - -/* Content fonts */ -#define NAUTILUS_PREFERENCES_DEFAULT_FONT "preferences/default_font" -#define NAUTILUS_PREFERENCES_DEFAULT_SMOOTH_FONT "preferences/default_smooth_font" -#define NAUTILUS_PREFERENCES_DEFAULT_FONT_SIZE "preferences/default_font_size" - -/* Single/Double click preference */ -#define NAUTILUS_PREFERENCES_CLICK_POLICY "preferences/click_policy" - -/* Activating executable text files */ -#define NAUTILUS_PREFERENCES_EXECUTABLE_TEXT_ACTIVATION "preferences/executable_text_activation" - -/* Smooth graphics mode (smoother but slower) */ -#define NAUTILUS_PREFERENCES_SMOOTH_GRAPHICS_MODE "preferences/smooth_graphics_mode" - -/* Which views should be displayed for new windows */ -#define NAUTILUS_PREFERENCES_START_WITH_TOOLBAR "preferences/start_with_toolbar" -#define NAUTILUS_PREFERENCES_START_WITH_LOCATION_BAR "preferences/start_with_location_bar" -#define NAUTILUS_PREFERENCES_START_WITH_STATUS_BAR "preferences/start_with_status_bar" -#define NAUTILUS_PREFERENCES_START_WITH_SIDEBAR "preferences/start_with_sidebar" - -/* Sorting order */ -#define NAUTILUS_PREFERENCES_SORT_DIRECTORIES_FIRST "preferences/sort_directories_first" - -/* The default folder viewer - one of the two enums below */ -#define NAUTILUS_PREFERENCES_DEFAULT_FOLDER_VIEWER "preferences/default_folder_viewer" - -enum -{ - NAUTILUS_DEFAULT_FOLDER_VIEWER_ICON_VIEW, - NAUTILUS_DEFAULT_FOLDER_VIEWER_LIST_VIEW, - NAUTILUS_DEFAULT_FOLDER_VIEWER_OTHER -}; - -/* These IIDs are used by the preferences code and in nautilus-application.c */ -#define NAUTILUS_ICON_VIEW_IID "OAFIID:nautilus_file_manager_icon_view:42681b21-d5ca-4837-87d2-394d88ecc058" -#define NAUTILUS_LIST_VIEW_IID "OAFIID:nautilus_file_manager_list_view:521e489d-0662-4ad7-ac3a-832deabe111c" - - -/* Icon View */ -#define NAUTILUS_PREFERENCES_ICON_VIEW_DEFAULT_SORT_IN_REVERSE_ORDER "icon-view/default_sort_in_reverse_order" -#define NAUTILUS_PREFERENCES_ICON_VIEW_DEFAULT_SORT_ORDER "icon-view/default_sort_order" -#define NAUTILUS_PREFERENCES_ICON_VIEW_DEFAULT_USE_TIGHTER_LAYOUT "icon-view/default_use_tighter_layout" -#define NAUTILUS_PREFERENCES_ICON_VIEW_DEFAULT_ZOOM_LEVEL "icon-view/default_zoom_level" -#define NAUTILUS_PREFERENCES_ICON_VIEW_DEFAULT_ZOOM_LEVEL_FONT_SIZE "icon-view/default_zoom_level_font_size" -#define NAUTILUS_PREFERENCES_ICON_VIEW_DEFAULT_USE_MANUAL_LAYOUT "icon-view/default_use_manual_layout" -#define NAUTILUS_PREFERENCES_ICON_VIEW_FONT "icon-view/font" -#define NAUTILUS_PREFERENCES_ICON_VIEW_SMOOTH_FONT "icon-view/smooth_font" - -/* The icon view uses 2 variables to store the sort order and - * whether to use manual layout. However, the UI for these - * preferences presensts them as single option menu. So we - * use the following preference as a proxy for the other two. - * In nautilus-global-preferences.c we install callbacks for - * the proxy preference and update the other 2 when it changes - */ -#define NAUTILUS_PREFERENCES_ICON_VIEW_DEFAULT_SORT_ORDER_OR_MANUAL_LAYOUT "icon-view/default_sort_order_or_manual_layout" - -/* Which text attributes appear beneath icon names */ -#define NAUTILUS_PREFERENCES_ICON_VIEW_CAPTIONS "icon-view/captions" - -/* List View */ -#define NAUTILUS_PREFERENCES_LIST_VIEW_DEFAULT_SORT_IN_REVERSE_ORDER "list-view/default_sort_in_reverse_order" -#define NAUTILUS_PREFERENCES_LIST_VIEW_DEFAULT_SORT_ORDER "list-view/default_sort_order" -#define NAUTILUS_PREFERENCES_LIST_VIEW_DEFAULT_ZOOM_LEVEL "list-view/default_zoom_level" -#define NAUTILUS_PREFERENCES_LIST_VIEW_DEFAULT_ZOOM_LEVEL_FONT_SIZE "list-view/default_zoom_level_font_size" -#define NAUTILUS_PREFERENCES_LIST_VIEW_FONT "list-view/font" - -/* News panel */ -#define NAUTILUS_PREFERENCES_NEWS_MAX_ITEMS "news/max_items" -#define NAUTILUS_PREFERENCES_NEWS_UPDATE_INTERVAL "news/update_interval" - -/* File Indexing */ -#define NAUTILUS_PREFERENCES_SEARCH_BAR_TYPE "preferences/search_bar_type" - -/* searching */ -#define NAUTILUS_PREFERENCES_SEARCH_WEB_URI "preferences/search_web_uri" - - - -enum -{ - NAUTILUS_CLICK_POLICY_SINGLE, - NAUTILUS_CLICK_POLICY_DOUBLE -}; - -enum -{ - NAUTILUS_EXECUTABLE_TEXT_LAUNCH, - NAUTILUS_EXECUTABLE_TEXT_DISPLAY, - NAUTILUS_EXECUTABLE_TEXT_ASK -}; - -typedef enum -{ - NAUTILUS_SPEED_TRADEOFF_ALWAYS, - NAUTILUS_SPEED_TRADEOFF_LOCAL_ONLY, - NAUTILUS_SPEED_TRADEOFF_NEVER -} NautilusSpeedTradeoffValue; - -#define NAUTILUS_PREFERENCES_SHOW_TEXT_IN_ICONS "preferences/show_icon_text" -#define NAUTILUS_PREFERENCES_SHOW_DIRECTORY_ITEM_COUNTS "preferences/show_directory_item_counts" -#define NAUTILUS_PREFERENCES_SHOW_IMAGE_FILE_THUMBNAILS "preferences/show_image_thumbnails" -#define NAUTILUS_PREFERENCES_IMAGE_FILE_THUMBNAIL_LIMIT "preferences/thumbnail_limit" -#define NAUTILUS_PREFERENCES_USE_PUBLIC_METADATA "preferences/use_public_metadata" -#define NAUTILUS_PREFERENCES_PREVIEW_SOUND "preferences/preview_sound" - -typedef enum -{ - NAUTILUS_COMPLEX_SEARCH_BAR, - NAUTILUS_SIMPLE_SEARCH_BAR -} NautilusSearchBarMode; - -/* Gnome session management */ -#define NAUTILUS_PREFERENCES_ADD_TO_SESSION "preferences/add_to_session" - -void nautilus_global_preferences_initialize (void); - -/* Sidebar */ -struct EelScalableFont *nautilus_global_preferences_get_icon_view_smooth_font (void); -struct EelScalableFont *nautilus_global_preferences_get_default_smooth_font (void); -struct EelScalableFont *nautilus_global_preferences_get_default_smooth_bold_font (void); - -void nautilus_global_preferences_set_default_folder_viewer (const char *iid); - - -END_GNOME_DECLS - -#endif /* NAUTILUS_PREFS_GLOBAL_H */ diff --git a/libnautilus-extensions/nautilus-horizontal-splitter.c b/libnautilus-extensions/nautilus-horizontal-splitter.c deleted file mode 100644 index 615b46102..000000000 --- a/libnautilus-extensions/nautilus-horizontal-splitter.c +++ /dev/null @@ -1,447 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ - -/* nautilus-horizontal-splitter.c - A horizontal splitter with a semi gradient look - - Copyright (C) 1999, 2000 Eazel, Inc. - - The Gnome 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 Gnome 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 the Gnome 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. - - Authors: Ramiro Estrugo <ramiro@eazel.com> -*/ - -#include <config.h> -#include "nautilus-horizontal-splitter.h" - -#include <eel/eel-gtk-macros.h> - -#include <stdlib.h> - -struct NautilusHorizontalSplitterDetails { - gboolean down; - double down_position; - guint32 down_time; - int saved_size; -}; - -/* Bar width currently hardcoded to 7 */ -#define BAR_WIDTH 7 -#define CLOSED_THRESHOLD 4 -#define NOMINAL_SIZE 148 -#define SPLITTER_CLICK_SLOP 1 -#define SPLITTER_CLICK_TIMEOUT 400 - -/* NautilusHorizontalSplitterClass methods */ -static void nautilus_horizontal_splitter_initialize_class (NautilusHorizontalSplitterClass *horizontal_splitter_class); -static void nautilus_horizontal_splitter_initialize (NautilusHorizontalSplitter *horizontal_splitter); -static gboolean nautilus_horizontal_splitter_button_press (GtkWidget *widget, - GdkEventButton *event); -static gboolean nautilus_horizontal_splitter_button_release (GtkWidget *widget, - GdkEventButton *event); -static gboolean nautilus_horizontal_splitter_motion (GtkWidget *widget, - GdkEventMotion *event); - -/* GtkObjectClass methods */ -static void nautilus_horizontal_splitter_destroy (GtkObject *object); - -/* GtkWidgetClass methods */ -static void nautilus_horizontal_splitter_draw (GtkWidget *widget, - GdkRectangle *area); - -EEL_DEFINE_CLASS_BOILERPLATE (NautilusHorizontalSplitter, - nautilus_horizontal_splitter, - E_TYPE_HPANED) - -/* GtkObjectClass methods */ -static void -nautilus_horizontal_splitter_initialize_class (NautilusHorizontalSplitterClass *horizontal_splitter_class) -{ - GtkObjectClass *object_class; - GtkWidgetClass *widget_class; - - object_class = GTK_OBJECT_CLASS (horizontal_splitter_class); - widget_class = GTK_WIDGET_CLASS (horizontal_splitter_class); - - /* GtkObjectClass */ - object_class->destroy = nautilus_horizontal_splitter_destroy; - - /* GtkWidgetClass */ - widget_class->draw = nautilus_horizontal_splitter_draw; - widget_class->button_press_event = nautilus_horizontal_splitter_button_press; - widget_class->button_release_event = nautilus_horizontal_splitter_button_release; - widget_class->motion_notify_event = nautilus_horizontal_splitter_motion; - -} - -static void -nautilus_horizontal_splitter_initialize (NautilusHorizontalSplitter *horizontal_splitter) -{ - horizontal_splitter->details = g_new0 (NautilusHorizontalSplitterDetails, 1); - e_paned_set_handle_size (E_PANED (horizontal_splitter), BAR_WIDTH); -} - -/* GtkObjectClass methods */ -static void -nautilus_horizontal_splitter_destroy (GtkObject *object) -{ - NautilusHorizontalSplitter *horizontal_splitter; - - horizontal_splitter = NAUTILUS_HORIZONTAL_SPLITTER (object); - - g_free (horizontal_splitter->details); - - /* Chain */ - EEL_CALL_PARENT (GTK_OBJECT_CLASS, destroy, (object)); -} - -static void -draw_resize_bar (GtkWidget *widget, - GdkWindow *window, - const GdkRectangle *area) -{ - GtkStyle *style; - GdkGC *gcs[BAR_WIDTH]; - guint i; - - g_assert (widget != NULL); - g_assert (window != NULL); - g_assert (area != NULL); - g_assert (area->width == BAR_WIDTH); - - style = widget->style; - - g_assert (style != NULL); - - gcs[0] = style->fg_gc[GTK_STATE_NORMAL]; - gcs[1] = style->fg_gc[GTK_STATE_SELECTED]; - gcs[2] = style->light_gc[GTK_STATE_ACTIVE]; - gcs[3] = style->bg_gc[GTK_STATE_NORMAL]; - gcs[4] = style->mid_gc[GTK_STATE_ACTIVE]; - gcs[5] = style->dark_gc[GTK_STATE_NORMAL]; - gcs[6] = style->fg_gc[GTK_STATE_NORMAL]; - - for (i = 0; i < BAR_WIDTH; i++) - { - gdk_draw_line (window, - gcs[i], - area->x + i, - area->y, - area->x + i, - area->y + area->height - 1); - } -} - -/* Number of ridges in the thumb currently hardcoded to 8 */ -#define NUM_RIDGES 8 - -/* These control the layout of the ridges */ -#define RIDGE_HEIGHT 2 -#define RIDGE_EDGE_OFFSET 2 -#define BETWEEN_RIDGE_OFFSET 1 - -static void -draw_resize_bar_thumb (GtkWidget *widget, - GdkWindow *window, - const GdkRectangle *area) -{ - EPaned *paned; - GtkStyle *style; - GdkGC *light_gc; - GdkGC *dark_gc; - guint total_thumb_height; - - g_assert (widget != NULL); - g_assert (window != NULL); - g_assert (area != NULL); - g_assert (area->width == BAR_WIDTH); - - style = widget->style; - g_assert (style != NULL); - - paned = E_PANED (widget); - - light_gc = style->light_gc[GTK_STATE_ACTIVE]; - dark_gc = style->dark_gc[GTK_STATE_NORMAL]; - - total_thumb_height = (NUM_RIDGES * RIDGE_HEIGHT) + ((NUM_RIDGES - 1) * BETWEEN_RIDGE_OFFSET); - - /* Make sure the thumb aint bigger than the handle */ - if (total_thumb_height > paned->handle_height) - { - total_thumb_height = paned->handle_height; - } - - /* Draw the thumb only if we have enough space for at least one ridge */ - if (total_thumb_height > RIDGE_HEIGHT) - { - gint y = paned->handle_ypos + (paned->handle_height - total_thumb_height) / 2; - guint i; - - for (i = 0; i < NUM_RIDGES; i++) - { - gint x1 = area->x + RIDGE_EDGE_OFFSET; - gint x2 = area->x + BAR_WIDTH - RIDGE_EDGE_OFFSET; - - gdk_draw_line (window, - dark_gc, - x1, - y, - x2, - y); - - y += BETWEEN_RIDGE_OFFSET; - - gdk_draw_line (window, - light_gc, - x1, - y, - x2, - y); - - y += RIDGE_HEIGHT; - } - } -} - -/* GtkWidgetClass methods */ -static void -nautilus_horizontal_splitter_draw (GtkWidget *widget, - GdkRectangle *area) -{ - EPaned *paned; - GdkRectangle handle_area, child_area; - guint16 border_width; - - g_return_if_fail (widget != NULL); - g_return_if_fail (E_IS_PANED (widget)); - - if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_MAPPED (widget)) { - paned = E_PANED (widget); - border_width = GTK_CONTAINER (paned)->border_width; - - gdk_window_clear_area (widget->window, - area->x, area->y, area->width, - area->height); - - if (e_paned_handle_shown(paned)) { - handle_area.x = paned->handle_xpos; - handle_area.y = paned->handle_ypos; - handle_area.width = paned->handle_size; - handle_area.height = paned->handle_height; - - if (gdk_rectangle_intersect (&handle_area, area, &child_area)) { - child_area.x -= paned->handle_xpos; - child_area.y -= paned->handle_ypos; - - /* Simply things by always drawing the full width of the bar. */ - child_area.x = 0; - child_area.width = BAR_WIDTH; - - draw_resize_bar (widget, paned->handle, &child_area); - draw_resize_bar_thumb (widget, paned->handle, &child_area); - } - } - - /* Redraw the children - */ - if (paned->child1 && gtk_widget_intersect (paned->child1, area, &child_area)) { - gtk_widget_draw (paned->child1, &child_area); - } - - if (paned->child2 && gtk_widget_intersect (paned->child2, area, &child_area)) { - gtk_widget_draw (paned->child2, &child_area); - } - } -} - -void -nautilus_horizontal_splitter_expand (NautilusHorizontalSplitter *splitter) -{ - int position; - - g_return_if_fail (NAUTILUS_IS_HORIZONTAL_SPLITTER (splitter)); - - position = e_paned_get_position (E_PANED (splitter)); - - if (position >= CLOSED_THRESHOLD) { - return; - } - - position = splitter->details->saved_size; - if (position < CLOSED_THRESHOLD) { - position = NOMINAL_SIZE; - } - - e_paned_set_position (E_PANED (splitter), position); -} - -void -nautilus_horizontal_splitter_collapse (NautilusHorizontalSplitter *splitter) -{ - int position; - - g_return_if_fail (NAUTILUS_IS_HORIZONTAL_SPLITTER (splitter)); - - position = e_paned_get_position (E_PANED (splitter)); - - if (position < CLOSED_THRESHOLD) { - return; - } - - splitter->details->saved_size = position; - e_paned_set_position (E_PANED (splitter), 0); -} - -/* routine to toggle the open/closed state of the splitter */ -void -nautilus_horizontal_splitter_toggle_position (NautilusHorizontalSplitter *splitter) -{ - g_return_if_fail (NAUTILUS_IS_HORIZONTAL_SPLITTER (splitter)); - - if (e_paned_get_position (E_PANED (splitter)) >= CLOSED_THRESHOLD) { - nautilus_horizontal_splitter_collapse (splitter); - } else { - nautilus_horizontal_splitter_expand (splitter); - } -} - -/* NautilusHorizontalSplitter public methods */ -GtkWidget * -nautilus_horizontal_splitter_new (void) -{ - return gtk_widget_new (nautilus_horizontal_splitter_get_type (), NULL); -} - -/* handle mouse downs by remembering the position and the time */ -static gboolean -nautilus_horizontal_splitter_button_press (GtkWidget *widget, GdkEventButton *event) -{ - NautilusHorizontalSplitter *splitter; - - splitter = NAUTILUS_HORIZONTAL_SPLITTER (widget); - - if (event->window != E_PANED (widget)->handle) { - splitter->details->down = FALSE; - } else { - splitter->details->down = TRUE; - splitter->details->down_position = event->x; - splitter->details->down_time = event->time; - } - - return EEL_CALL_PARENT_WITH_RETURN_VALUE - (GTK_WIDGET_CLASS, button_press_event, (widget, event)); -} - - -static void -splitter_xor_line (EPaned *paned) -{ - GtkWidget *widget; - GdkGCValues values; - guint16 xpos, half_width; - gint8 dash_list[2]; - - widget = GTK_WIDGET(paned); - - if (!paned->xor_gc) { - values.function = GDK_INVERT; - values.subwindow_mode = GDK_INCLUDE_INFERIORS; - paned->xor_gc = gdk_gc_new_with_values (widget->window, &values, - GDK_GC_FUNCTION | GDK_GC_SUBWINDOW); - } - - gdk_gc_set_line_attributes (paned->xor_gc, 1, GDK_LINE_ON_OFF_DASH, - GDK_CAP_NOT_LAST, GDK_JOIN_BEVEL); - - /* Make line appear as every other pixel dash */ - dash_list[0] = 1; - dash_list[1] = 1; - gdk_gc_set_dashes (paned->xor_gc, 1, dash_list, 2); - - xpos = paned->child1_size + GTK_CONTAINER (paned)->border_width + paned->handle_size / 2; - half_width = paned->handle_size / 2; - - gdk_draw_line (widget->window, paned->xor_gc, xpos - half_width, 0, xpos - half_width, - widget->allocation.height - 1); - - gdk_draw_line (widget->window, paned->xor_gc, xpos + half_width, 0, xpos + half_width, - widget->allocation.height - 1); - -} - - -/* handle mouse ups by seeing if it was a tap and toggling the open state accordingly */ -static gboolean -nautilus_horizontal_splitter_button_release (GtkWidget *widget, GdkEventButton *event) -{ - NautilusHorizontalSplitter *splitter; - int delta, delta_time; - EPaned *paned; - - splitter = NAUTILUS_HORIZONTAL_SPLITTER (widget); - - if (event->window == E_PANED (widget)->handle - && splitter->details->down) { - delta = abs (event->x - splitter->details->down_position); - delta_time = abs (splitter->details->down_time - event->time); - if (delta < SPLITTER_CLICK_SLOP && delta_time < SPLITTER_CLICK_TIMEOUT) { - nautilus_horizontal_splitter_toggle_position (splitter); - } - } - - splitter->details->down = FALSE; - - - paned = E_PANED (widget); - - if (paned->in_drag && (event->button == 1)) { - splitter_xor_line (paned); - paned->in_drag = FALSE; - paned->position_set = TRUE; - gdk_pointer_ungrab (event->time); - gtk_widget_queue_resize (GTK_WIDGET (paned)); - return TRUE; - } - - return FALSE; -} - -static gboolean -nautilus_horizontal_splitter_motion (GtkWidget *widget, GdkEventMotion *event) -{ - EPaned *paned; - gint x; - - g_return_val_if_fail (widget != NULL, FALSE); - g_return_val_if_fail (E_IS_PANED (widget), FALSE); - - paned = E_PANED (widget); - - if (event->is_hint || event->window != widget->window) { - gtk_widget_get_pointer(widget, &x, NULL); - } else { - x = event->x; - } - - if (paned->in_drag) { - gint size = x - GTK_CONTAINER (paned)->border_width - paned->handle_size / 2; - splitter_xor_line (paned); - paned->child1_size = CLAMP (e_paned_quantized_size (paned, size), paned->min_position, paned->max_position); - splitter_xor_line (paned); - } - - return TRUE; -} - diff --git a/libnautilus-extensions/nautilus-horizontal-splitter.h b/libnautilus-extensions/nautilus-horizontal-splitter.h deleted file mode 100644 index f44107b35..000000000 --- a/libnautilus-extensions/nautilus-horizontal-splitter.h +++ /dev/null @@ -1,60 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ - -/* nautilus-horizontal-splitter.h - A horizontal splitter with a semi gradient look - - Copyright (C) 1999, 2000 Eazel, Inc. - - The Gnome 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 Gnome 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 the Gnome 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. - - Authors: Ramiro Estrugo <ramiro@eazel.com> -*/ - -#ifndef NAUTILUS_HORIZONTAL_SPLITTER_H -#define NAUTILUS_HORIZONTAL_SPLITTER_H - -#include <libgnome/gnome-defs.h> -#include <widgets/e-paned/e-hpaned.h> - -BEGIN_GNOME_DECLS - -#define NAUTILUS_TYPE_HORIZONTAL_SPLITTER (nautilus_horizontal_splitter_get_type ()) -#define NAUTILUS_HORIZONTAL_SPLITTER(obj) (GTK_CHECK_CAST ((obj), NAUTILUS_TYPE_HORIZONTAL_SPLITTER, NautilusHorizontalSplitter)) -#define NAUTILUS_HORIZONTAL_SPLITTER_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), NAUTILUS_TYPE_HORIZONTAL_SPLITTER, NautilusHorizontalSplitterClass)) -#define NAUTILUS_IS_HORIZONTAL_SPLITTER(obj) (GTK_CHECK_TYPE ((obj), NAUTILUS_TYPE_HORIZONTAL_SPLITTER)) -#define NAUTILUS_IS_HORIZONTAL_SPLITTER_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), NAUTILUS_TYPE_HORIZONTAL_SPLITTER)) - -typedef struct NautilusHorizontalSplitterDetails NautilusHorizontalSplitterDetails; - -typedef struct { - EHPaned parent_slot; - NautilusHorizontalSplitterDetails *details; -} NautilusHorizontalSplitter; - -typedef struct { - EHPanedClass parent_slot; -} NautilusHorizontalSplitterClass; - -/* NautilusHorizontalSplitter public methods */ -GtkType nautilus_horizontal_splitter_get_type (void); -GtkWidget *nautilus_horizontal_splitter_new (void); - -void nautilus_horizontal_splitter_collapse (NautilusHorizontalSplitter *splitter); -void nautilus_horizontal_splitter_expand (NautilusHorizontalSplitter *splitter); -void nautilus_horizontal_splitter_toggle_position (NautilusHorizontalSplitter *splitter); - -END_GNOME_DECLS - -#endif /* NAUTILUS_HORIZONTAL_SPLITTER_H */ diff --git a/libnautilus-extensions/nautilus-icon-canvas-item.c b/libnautilus-extensions/nautilus-icon-canvas-item.c deleted file mode 100644 index 6d7c18d0f..000000000 --- a/libnautilus-extensions/nautilus-icon-canvas-item.c +++ /dev/null @@ -1,2224 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ - -/* Nautilus - Icon canvas item class for icon container. - * - * Copyright (C) 2000 Eazel, Inc - * - * Author: Andy Hertzfeld <andy@eazel.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. - * - * This 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; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#include <config.h> -#include "nautilus-icon-canvas-item.h" - -#include <math.h> -#include <string.h> -#include <stdio.h> -#include <gtk/gtksignal.h> -#include <gdk-pixbuf/gdk-pixbuf.h> -#include <libgnome/gnome-i18n.h> -#include <libgnomeui/gnome-canvas-util.h> -#include <libgnomeui/gnome-icon-text.h> -#include <libart_lgpl/art_rgb.h> -#include <libart_lgpl/art_rgb_affine.h> -#include <libart_lgpl/art_rgb_rgba_affine.h> -#include <libart_lgpl/art_svp_vpath.h> -#include "nautilus-icon-private.h" -#include <eel/eel-string.h> -#include <eel/eel-art-extensions.h> -#include <eel/eel-glib-extensions.h> -#include <eel/eel-gdk-extensions.h> -#include <eel/eel-gdk-font-extensions.h> -#include <eel/eel-gdk-pixbuf-extensions.h> -#include "nautilus-global-preferences.h" -#include <eel/eel-gtk-macros.h> -#include <eel/eel-gnome-extensions.h> -#include <eel/eel-graphic-effects.h> -#include "nautilus-file-utilities.h" -#include "nautilus-icon-factory.h" -#include "nautilus-theme.h" -#include <eel/eel-smooth-text-layout.h> -#include <eel/eel-smooth-text-layout-cache.h> - -/* Comment this out if the new smooth fonts code give you problems - * This isnt meant to be permanent. Its just a precaution. - */ -#define EMBLEM_SPACING 2 - -/* gap between bottom of icon and start of text box */ -#define LABEL_OFFSET 1 -#define LABEL_LINE_SPACING 0 - -#define MAX_TEXT_WIDTH_STANDARD 135 -#define MAX_TEXT_WIDTH_TIGHTER 80 - -/* The list of characters that cause line breaks can be localized. */ -static const char untranslated_line_break_characters[] = N_(" -_,;.?/&"); -#define LINE_BREAK_CHARACTERS _(untranslated_line_break_characters) - -/* Private part of the NautilusIconCanvasItem structure. */ -struct NautilusIconCanvasItemDetails { - /* The image, text, font. */ - GdkPixbuf *pixbuf; - GdkPixbuf *rendered_pixbuf; - GList *emblem_pixbufs; - char *editable_text; /* Text that can be modified by a renaming function */ - char *additional_text; /* Text that cannot be modifed, such as file size, etc. */ - GdkFont *font; - NautilusEmblemAttachPoints *attach_points; - - /* Size of the text at current font. */ - int text_width; - int text_height; - - /* preview state */ - guint is_active : 1; - - /* Highlight state. */ - guint is_highlighted_for_selection : 1; - guint is_highlighted_as_keyboard_focus: 1; - guint is_highlighted_for_drop : 1; - guint show_stretch_handles : 1; - guint is_prelit : 1; - - guint rendered_is_active : 1; - guint rendered_is_highlighted_for_selection : 1; - guint rendered_is_highlighted_for_drop : 1; - guint rendered_is_prelit : 1; - - gboolean is_renaming; - - /* Font stuff whilst in smooth mode */ - int smooth_font_size; - EelScalableFont *smooth_font; - - /* Cached rectangle in canvas coordinates */ - ArtIRect canvas_rect; - ArtIRect text_rect; - ArtIRect emblem_rect; -}; - -/* Object argument IDs. */ -enum { - ARG_0, - ARG_EDITABLE_TEXT, - ARG_ADDITIONAL_TEXT, - ARG_FONT, - ARG_HIGHLIGHTED_FOR_SELECTION, - ARG_HIGHLIGHTED_AS_KEYBOARD_FOCUS, - ARG_HIGHLIGHTED_FOR_DROP, - ARG_MODIFIER, - ARG_SMOOTH_FONT_SIZE, - ARG_SMOOTH_FONT -}; - -typedef enum { - RIGHT_SIDE, - BOTTOM_SIDE, - LEFT_SIDE, - TOP_SIDE -} RectangleSide; - -typedef struct { - NautilusIconCanvasItem *icon_item; - ArtIRect icon_rect; - RectangleSide side; - int position; - int index; - GList *emblem; -} EmblemLayout; - -enum { - BOUNDS_CHANGED, - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL]; - -static guint32 highlight_background_color = EEL_RGBA_COLOR_PACK (0x00, 0x00, 0x00, 0xFF); -static guint32 highlight_text_color = EEL_RGBA_COLOR_PACK (0xFF, 0xFF, 0xFF, 0xFF); -static guint32 highlight_text_info_color = EEL_RGBA_COLOR_PACK (0xCC, 0xCC, 0xCC, 0xFF); - -static int click_policy_auto_value; - -/* GtkObject */ -static void nautilus_icon_canvas_item_initialize_class (NautilusIconCanvasItemClass *class); -static void nautilus_icon_canvas_item_initialize (NautilusIconCanvasItem *item); -static void nautilus_icon_canvas_item_destroy (GtkObject *object); -static int nautilus_icon_canvas_item_event (GnomeCanvasItem *item, - GdkEvent *event); -static void nautilus_icon_canvas_item_set_arg (GtkObject *object, - GtkArg *arg, - guint arg_id); -static void nautilus_icon_canvas_item_get_arg (GtkObject *object, - GtkArg *arg, - guint arg_id); - -/* GnomeCanvasItem */ -static void nautilus_icon_canvas_item_update (GnomeCanvasItem *item, - double *affine, - ArtSVP *clip_path, - int flags); -static void nautilus_icon_canvas_item_draw (GnomeCanvasItem *item, - GdkDrawable *drawable, - int x, - int y, - int width, - int height); -static void nautilus_icon_canvas_item_render (GnomeCanvasItem *item, - GnomeCanvasBuf *buffer); -static double nautilus_icon_canvas_item_point (GnomeCanvasItem *item, - double x, - double y, - int cx, - int cy, - GnomeCanvasItem **actual_item); -static void nautilus_icon_canvas_item_bounds (GnomeCanvasItem *item, - double *x1, - double *y1, - double *x2, - double *y2); - -/* private */ -static void draw_or_measure_label_text (NautilusIconCanvasItem *item, - GdkDrawable *drawable, - int icon_left, - int icon_bottom); -static void draw_or_measure_label_text_aa (NautilusIconCanvasItem *item, - GdkPixbuf *destination_pixbuf, - int icon_left, - int icon_bottom); -static void draw_label_text (NautilusIconCanvasItem *item, - GdkDrawable *drawable, - int icon_left, - int icon_bottom); -static void measure_label_text (NautilusIconCanvasItem *item); -static void get_icon_canvas_rectangle (NautilusIconCanvasItem *item, - ArtIRect *rect); -static void emblem_layout_reset (EmblemLayout *layout, - NautilusIconCanvasItem *icon_item, - ArtIRect icon_rect); -static gboolean emblem_layout_next (EmblemLayout *layout, - GdkPixbuf **emblem_pixbuf, - ArtIRect *emblem_rect); -static void draw_pixbuf (GdkPixbuf *pixbuf, - GdkDrawable *drawable, - int x, - int y); -static gboolean hit_test_stretch_handle (NautilusIconCanvasItem *item, - ArtIRect canvas_rect); -static gboolean icon_canvas_item_is_smooth (const NautilusIconCanvasItem *icon_item); - -EEL_DEFINE_CLASS_BOILERPLATE (NautilusIconCanvasItem, nautilus_icon_canvas_item, GNOME_TYPE_CANVAS_ITEM) - -static EelSmoothTextLayoutCache *layout_cache; - -static void -free_layout_cache (void) -{ - gtk_object_unref (GTK_OBJECT (layout_cache)); -} - -/* Class initialization function for the icon canvas item. */ -static void -nautilus_icon_canvas_item_initialize_class (NautilusIconCanvasItemClass *class) -{ - GtkObjectClass *object_class; - GnomeCanvasItemClass *item_class; - - if (layout_cache == NULL) { - layout_cache = eel_smooth_text_layout_cache_new (); - g_atexit (free_layout_cache); - } - - object_class = GTK_OBJECT_CLASS (class); - item_class = GNOME_CANVAS_ITEM_CLASS (class); - - gtk_object_add_arg_type ("NautilusIconCanvasItem::editable_text", - GTK_TYPE_STRING, GTK_ARG_READWRITE, ARG_EDITABLE_TEXT); - gtk_object_add_arg_type ("NautilusIconCanvasItem::additional_text", - GTK_TYPE_STRING, GTK_ARG_READWRITE, ARG_ADDITIONAL_TEXT); - gtk_object_add_arg_type ("NautilusIconCanvasItem::font", - GTK_TYPE_BOXED, GTK_ARG_READWRITE, ARG_FONT); - gtk_object_add_arg_type ("NautilusIconCanvasItem::highlighted_for_selection", - GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_HIGHLIGHTED_FOR_SELECTION); - gtk_object_add_arg_type ("NautilusIconCanvasItem::highlighted_as_keyboard_focus", - GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_HIGHLIGHTED_AS_KEYBOARD_FOCUS); - gtk_object_add_arg_type ("NautilusIconCanvasItem::highlighted_for_drop", - GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_HIGHLIGHTED_FOR_DROP); - gtk_object_add_arg_type ("NautilusIconCanvasItem::smooth_font_size", - GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_SMOOTH_FONT_SIZE); - gtk_object_add_arg_type ("NautilusIconCanvasItem::smooth_font", - GTK_TYPE_OBJECT, GTK_ARG_READWRITE, ARG_SMOOTH_FONT); - - object_class->destroy = nautilus_icon_canvas_item_destroy; - object_class->set_arg = nautilus_icon_canvas_item_set_arg; - object_class->get_arg = nautilus_icon_canvas_item_get_arg; - - signals[BOUNDS_CHANGED] - = gtk_signal_new ("bounds_changed", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (NautilusIconCanvasItemClass, - bounds_changed), - gtk_marshal_NONE__NONE, - GTK_TYPE_NONE, 0); - - gtk_object_class_add_signals (object_class, signals, LAST_SIGNAL); - - item_class->update = nautilus_icon_canvas_item_update; - item_class->draw = nautilus_icon_canvas_item_draw; - item_class->render = nautilus_icon_canvas_item_render; - item_class->point = nautilus_icon_canvas_item_point; - item_class->bounds = nautilus_icon_canvas_item_bounds; - item_class->event = nautilus_icon_canvas_item_event; - - nautilus_preferences_add_auto_integer (NAUTILUS_PREFERENCES_CLICK_POLICY, - &click_policy_auto_value); -} - -/* Object initialization function for the icon item. */ -static void -nautilus_icon_canvas_item_initialize (NautilusIconCanvasItem *icon_item) -{ - NautilusIconCanvasItemDetails *details; - - details = g_new0 (NautilusIconCanvasItemDetails, 1); - - icon_item->details = details; - - icon_item->details->is_renaming = FALSE; - - /* invalidate cached text dimensions initially */ - nautilus_icon_canvas_item_invalidate_label_size (icon_item); - - /* set up the default font and size */ - icon_item->details->smooth_font_size = 12; - icon_item->details->smooth_font = eel_scalable_font_get_default_font (); -} - -/* Destroy handler for the icon canvas item. */ -static void -nautilus_icon_canvas_item_destroy (GtkObject *object) -{ - GnomeCanvasItem *item; - NautilusIconCanvasItem *icon_item; - NautilusIconCanvasItemDetails *details; - - g_return_if_fail (NAUTILUS_IS_ICON_CANVAS_ITEM (object)); - - item = GNOME_CANVAS_ITEM (object); - icon_item = (NAUTILUS_ICON_CANVAS_ITEM (object)); - details = icon_item->details; - - gnome_canvas_request_redraw (item->canvas, item->x1, item->y1, item->x2, item->y2); - - if (details->pixbuf != NULL) { - gdk_pixbuf_unref (details->pixbuf); - } - eel_gdk_pixbuf_list_free (details->emblem_pixbufs); - g_free (details->editable_text); - g_free (details->additional_text); - g_free (details->attach_points); - - if (details->font != NULL) { - gdk_font_unref (details->font); - } - - gtk_object_unref (GTK_OBJECT (icon_item->details->smooth_font)); - icon_item->details->smooth_font = NULL; - - if (details->rendered_pixbuf != NULL) { - gdk_pixbuf_unref (details->rendered_pixbuf); - } - - g_free (details); - - EEL_CALL_PARENT (GTK_OBJECT_CLASS, destroy, (object)); -} - -/* Currently we require pixbufs in this format (for hit testing). - * Perhaps gdk-pixbuf will be changed so it can do the hit testing - * and we won't have this requirement any more. - */ -static gboolean -pixbuf_is_acceptable (GdkPixbuf *pixbuf) -{ - return gdk_pixbuf_get_colorspace (pixbuf) == GDK_COLORSPACE_RGB - && ((!gdk_pixbuf_get_has_alpha (pixbuf) - && gdk_pixbuf_get_n_channels (pixbuf) == 3) - || (gdk_pixbuf_get_has_alpha (pixbuf) - && gdk_pixbuf_get_n_channels (pixbuf) == 4)) - && gdk_pixbuf_get_bits_per_sample (pixbuf) == 8; -} - -/* invalidate the text width and height cached in the item details. */ -void -nautilus_icon_canvas_item_invalidate_label_size (NautilusIconCanvasItem *item) -{ - item->details->text_width = -1; - item->details->text_height = -1; -} - -/* Set_arg handler for the icon item. */ -static void -nautilus_icon_canvas_item_set_arg (GtkObject *object, GtkArg *arg, guint arg_id) -{ - NautilusIconCanvasItem *item; - NautilusIconCanvasItemDetails *details; - GdkFont *font; - - item = NAUTILUS_ICON_CANVAS_ITEM (object); - details = item->details; - - switch (arg_id) { - - case ARG_EDITABLE_TEXT: - if (eel_strcmp (details->editable_text, GTK_VALUE_STRING (*arg)) == 0) { - return; - } - - g_free (details->editable_text); - details->editable_text = g_strdup (GTK_VALUE_STRING (*arg)); - - nautilus_icon_canvas_item_invalidate_label_size (item); - break; - - case ARG_ADDITIONAL_TEXT: - if (eel_strcmp (details->additional_text, GTK_VALUE_STRING (*arg)) == 0) { - return; - } - - g_free (details->additional_text); - details->additional_text = g_strdup (GTK_VALUE_STRING (*arg)); - - nautilus_icon_canvas_item_invalidate_label_size (item); - break; - - case ARG_FONT: - font = GTK_VALUE_BOXED (*arg); - if (eel_gdk_font_equal (font, details->font)) { - return; - } - - if (font != NULL) { - gdk_font_ref (font); - } - if (details->font != NULL) { - gdk_font_unref (details->font); - } - details->font = font; - - nautilus_icon_canvas_item_invalidate_label_size (item); - break; - - case ARG_HIGHLIGHTED_FOR_SELECTION: - if (!details->is_highlighted_for_selection == !GTK_VALUE_BOOL (*arg)) { - return; - } - details->is_highlighted_for_selection = GTK_VALUE_BOOL (*arg); - break; - - case ARG_HIGHLIGHTED_AS_KEYBOARD_FOCUS: - if (!details->is_highlighted_as_keyboard_focus == !GTK_VALUE_BOOL (*arg)) { - return; - } - details->is_highlighted_as_keyboard_focus = GTK_VALUE_BOOL (*arg); - break; - - case ARG_HIGHLIGHTED_FOR_DROP: - if (!details->is_highlighted_for_drop == !GTK_VALUE_BOOL (*arg)) { - return; - } - details->is_highlighted_for_drop = GTK_VALUE_BOOL (*arg); - break; - - case ARG_SMOOTH_FONT: - nautilus_icon_canvas_item_set_smooth_font (NAUTILUS_ICON_CANVAS_ITEM (object), - EEL_SCALABLE_FONT (GTK_VALUE_OBJECT (*arg))); - nautilus_icon_canvas_item_invalidate_label_size (item); - break; - - case ARG_SMOOTH_FONT_SIZE: - nautilus_icon_canvas_item_set_smooth_font_size (NAUTILUS_ICON_CANVAS_ITEM (object), - GTK_VALUE_INT (*arg)); - break; - - default: - g_warning ("nautilus_icons_view_item_item_set_arg on unknown argument"); - return; - } - - gnome_canvas_item_request_update (GNOME_CANVAS_ITEM (object)); -} - -/* Get_arg handler for the icon item */ -static void -nautilus_icon_canvas_item_get_arg (GtkObject *object, GtkArg *arg, guint arg_id) -{ - NautilusIconCanvasItemDetails *details; - - details = NAUTILUS_ICON_CANVAS_ITEM (object)->details; - - switch (arg_id) { - - case ARG_EDITABLE_TEXT: - GTK_VALUE_STRING (*arg) = g_strdup (details->editable_text); - break; - - case ARG_ADDITIONAL_TEXT: - GTK_VALUE_STRING (*arg) = g_strdup (details->additional_text); - break; - - case ARG_FONT: - GTK_VALUE_BOXED (*arg) = details->font; - break; - - case ARG_HIGHLIGHTED_FOR_SELECTION: - GTK_VALUE_BOOL (*arg) = details->is_highlighted_for_selection; - break; - - case ARG_HIGHLIGHTED_AS_KEYBOARD_FOCUS: - GTK_VALUE_BOOL (*arg) = details->is_highlighted_as_keyboard_focus; - break; - - case ARG_HIGHLIGHTED_FOR_DROP: - GTK_VALUE_BOOL (*arg) = details->is_highlighted_for_drop; - break; - - case ARG_SMOOTH_FONT: - gtk_object_ref (GTK_OBJECT (details->smooth_font)); - GTK_VALUE_OBJECT (*arg) = GTK_OBJECT (details->smooth_font); - break; - - case ARG_SMOOTH_FONT_SIZE: - GTK_VALUE_INT (*arg) = details->smooth_font_size; - break; - - default: - arg->type = GTK_TYPE_INVALID; - break; - } -} - -GdkPixbuf * -nautilus_icon_canvas_item_get_image (NautilusIconCanvasItem *item) -{ - NautilusIconCanvasItemDetails *details; - - g_return_val_if_fail (NAUTILUS_IS_ICON_CANVAS_ITEM (item), NULL); - - details = item->details; - - return details->pixbuf; -} - -void -nautilus_icon_canvas_item_set_image (NautilusIconCanvasItem *item, - GdkPixbuf *image) -{ - NautilusIconCanvasItemDetails *details; - - g_return_if_fail (NAUTILUS_IS_ICON_CANVAS_ITEM (item)); - g_return_if_fail (image == NULL || pixbuf_is_acceptable (image)); - - details = item->details; - if (details->pixbuf == image) { - return; - } - - if (image != NULL) { - gdk_pixbuf_ref (image); - } - if (details->pixbuf != NULL) { - gdk_pixbuf_unref (details->pixbuf); - } - if (details->rendered_pixbuf != NULL) { - gdk_pixbuf_unref (details->rendered_pixbuf); - details->rendered_pixbuf = NULL; - } - - details->pixbuf = image; - - gnome_canvas_item_request_update (GNOME_CANVAS_ITEM (item)); -} - -void -nautilus_icon_canvas_item_set_emblems (NautilusIconCanvasItem *item, - GList *emblem_pixbufs) -{ - GList *p; - - g_return_if_fail (NAUTILUS_IS_ICON_CANVAS_ITEM (item)); - - g_assert (item->details->emblem_pixbufs != emblem_pixbufs || emblem_pixbufs == NULL); - - /* The case where the emblems are identical is fairly common, - * so lets take the time to check for it. - */ - if (eel_g_list_equal (item->details->emblem_pixbufs, emblem_pixbufs)) { - return; - } - - /* Check if they are acceptable. */ - for (p = emblem_pixbufs; p != NULL; p = p->next) { - g_return_if_fail (pixbuf_is_acceptable (p->data)); - } - - /* Take in the new list of emblems. */ - eel_gdk_pixbuf_list_ref (emblem_pixbufs); - eel_gdk_pixbuf_list_free (item->details->emblem_pixbufs); - item->details->emblem_pixbufs = g_list_copy (emblem_pixbufs); - gnome_canvas_item_request_update (GNOME_CANVAS_ITEM (item)); -} - -void -nautilus_icon_canvas_item_set_attach_points (NautilusIconCanvasItem *item, - NautilusEmblemAttachPoints *attach_points) -{ - g_free (item->details->attach_points); - item->details->attach_points = NULL; - - if (attach_points != NULL && attach_points->num_points != 0) { - item->details->attach_points = g_new (NautilusEmblemAttachPoints, 1); - *item->details->attach_points = *attach_points; - } -} - -/* Recomputes the bounding box of a icon canvas item. - * This is a generic implementation that could be used for any canvas item - * class, it has no assumptions about how the item is used. - */ -static void -recompute_bounding_box (NautilusIconCanvasItem *icon_item) -{ - /* The bounds stored in the item is the same as what get_bounds - * returns, except it's in canvas coordinates instead of the item's - * parent's coordinates. - */ - - GnomeCanvasItem *item; - ArtPoint top_left, bottom_right; - double i2c[6]; - - item = GNOME_CANVAS_ITEM (icon_item); - - gnome_canvas_item_get_bounds (item, - &top_left.x, &top_left.y, - &bottom_right.x, &bottom_right.y); - - gnome_canvas_item_i2c_affine (item->parent, i2c); - - art_affine_point (&top_left, &top_left, i2c); - art_affine_point (&bottom_right, &bottom_right, i2c); - - item->x1 = top_left.x; - item->y1 = top_left.y; - item->x2 = bottom_right.x; - item->y2 = bottom_right.y; -} - -static ArtIRect -compute_text_rectangle (NautilusIconCanvasItem *item, - ArtIRect icon_rectangle) -{ - ArtIRect text_rectangle; - - /* Compute text rectangle. */ - text_rectangle.x0 = (icon_rectangle.x0 + icon_rectangle.x1) / 2 - item->details->text_width / 2; - text_rectangle.y0 = icon_rectangle.y1 + LABEL_OFFSET; - text_rectangle.x1 = text_rectangle.x0 + item->details->text_width; - text_rectangle.y1 = text_rectangle.y0 + item->details->text_height; - - return text_rectangle; -} - -void -nautilus_icon_canvas_item_update_bounds (NautilusIconCanvasItem *item) -{ - ArtIRect before, after, emblem_rect; - EmblemLayout emblem_layout; - GdkPixbuf *emblem_pixbuf; - - /* Compute new bounds. */ - before = eel_gnome_canvas_item_get_current_canvas_bounds - (GNOME_CANVAS_ITEM (item)); - recompute_bounding_box (item); - after = eel_gnome_canvas_item_get_current_canvas_bounds - (GNOME_CANVAS_ITEM (item)); - - /* If the bounds didn't change, we are done. */ - if (eel_art_irect_equal (before, after)) { - return; - } - - /* Update canvas and text rect cache */ - get_icon_canvas_rectangle (item, &item->details->canvas_rect); - item->details->text_rect = compute_text_rectangle (item, item->details->canvas_rect); - - /* Update emblem rect cache */ - item->details->emblem_rect.x0 = 0; - item->details->emblem_rect.x1 = 0; - item->details->emblem_rect.y0 = 0; - item->details->emblem_rect.y1 = 0; - emblem_layout_reset (&emblem_layout, item, item->details->canvas_rect); - while (emblem_layout_next (&emblem_layout, &emblem_pixbuf, &emblem_rect)) { - art_irect_union (&item->details->emblem_rect, &item->details->emblem_rect, &emblem_rect); - } - - /* Send out the bounds_changed signal and queue a redraw. */ - eel_gnome_canvas_request_redraw_rectangle - (GNOME_CANVAS_ITEM (item)->canvas, before); - gtk_signal_emit (GTK_OBJECT (item), - signals[BOUNDS_CHANGED]); - eel_gnome_canvas_item_request_redraw - (GNOME_CANVAS_ITEM (item)); -} - -/* Update handler for the icon canvas item. */ -static void -nautilus_icon_canvas_item_update (GnomeCanvasItem *item, - double *affine, - ArtSVP *clip_path, - int flags) -{ - nautilus_icon_canvas_item_update_bounds (NAUTILUS_ICON_CANVAS_ITEM (item)); - eel_gnome_canvas_item_request_redraw (item); - EEL_CALL_PARENT (GNOME_CANVAS_ITEM_CLASS, update, - (item, affine, clip_path, flags)); -} - -/* Rendering */ - -/* routine to underline the text in a gnome_icon_text structure */ - -static void -gnome_icon_underline_text (GnomeIconTextInfo *text_info, - GdkDrawable *drawable, - GdkGC *gc, - int x, int y) -{ - GList *item; - int text_width; - GnomeIconTextInfoRow *row; - int xpos; - - y += text_info->font->ascent; - - for (item = text_info->rows; item; item = item->next) { - if (item->data) { - row = item->data; - xpos = (text_info->width - row->width) / 2; - text_width = gdk_text_width_wc(text_info->font, row->text_wc, row->text_length); - gdk_draw_line(drawable, gc, x + xpos, y + 1, x + xpos + text_width, y + 1); - - y += text_info->baseline_skip; - } else - y += text_info->baseline_skip / 2; - } -} - -static gboolean -in_single_click_mode () -{ - return click_policy_auto_value == NAUTILUS_CLICK_POLICY_SINGLE; -} - -/* Keep these for a bit while we work on performance of draw_or_measure_label_text. */ - -/* - #define PERFORMANCE_TEST_DRAW_DISABLE - #define PERFORMANCE_TEST_MEASURE_DISABLE -*/ - -/* Draw the text in a box, using gnomelib routines. */ -static void -draw_or_measure_label_text (NautilusIconCanvasItem *item, - GdkDrawable *drawable, - int icon_left, - int icon_bottom) -{ - NautilusIconCanvasItemDetails *details; - guint width_so_far, height_so_far; - GdkGC* gc; - GdkGCValues save_gc; - guint32 label_color; - GnomeCanvasItem *canvas_item; - int max_text_width; - int icon_width, text_left, box_left; - GnomeIconTextInfo *icon_text_info; - char **pieces; - const char *text_piece; - int i; - char *combined_text; - gboolean have_editable, have_additional, needs_highlight; - - gc = NULL; - icon_width = 0; - - details = item->details; - needs_highlight = details->is_highlighted_for_selection || details->is_highlighted_for_drop; - - have_editable = details->editable_text != NULL - && details->editable_text[0] != '\0'; - have_additional = details->additional_text != NULL - && details->additional_text[0] != '\0'; - - - /* No font or no text, then do no work. */ - if (details->font == NULL || (!have_editable && !have_additional)) { - details->text_height = 0; - details->text_width = 0; - return; - } - -#if (defined PERFORMANCE_TEST_MEASURE_DISABLE && defined PERFORMANCE_TEST_DRAW_DISABLE) - /* don't do any drawing and fake out the width */ - details->text_width = 80; - details->text_height = 20; - return; -#endif - -#ifdef PERFORMANCE_TEST_MEASURE_DISABLE - if (drawable == NULL) { - /* fake out the width */ - details->text_width = 80; - details->text_height = 20; - return; - } -#endif - -#ifdef PERFORMANCE_TEST_DRAW_DISABLE - if (drawable != NULL) { - return; - } -#endif - - /* Combine editable and additional text for processing */ - combined_text = g_strconcat - (have_editable ? details->editable_text : "", - (have_editable && have_additional) ? "\n" : "", - have_additional ? details->additional_text : "", - NULL); - - width_so_far = 0; - height_so_far = 0; - - canvas_item = GNOME_CANVAS_ITEM (item); - if (drawable != NULL) { - icon_width = details->pixbuf == NULL ? 0 : gdk_pixbuf_get_width (details->pixbuf); - gc = gdk_gc_new (canvas_item->canvas->layout.bin_window); - gdk_gc_get_values (gc, &save_gc); - } - - max_text_width = floor (nautilus_icon_canvas_item_get_max_text_width (item)); - - /* if the icon is highlighted, do some set-up */ - if (needs_highlight && drawable != NULL && !details->is_renaming) { - gdk_rgb_gc_set_foreground (gc, highlight_background_color); - - gdk_draw_rectangle - (drawable, gc, TRUE, - icon_left + (icon_width - details->text_width) / 2, - icon_bottom, - details->text_width, details->text_height); - - gdk_rgb_gc_set_foreground (gc, highlight_text_color); - } - - if (!needs_highlight && drawable != NULL) { - label_color = nautilus_icon_container_get_label_color (NAUTILUS_ICON_CONTAINER (canvas_item->canvas), TRUE); - gdk_rgb_gc_set_foreground (gc, label_color); - } - - pieces = g_strsplit (combined_text, "\n", 0); - - for (i = 0; (text_piece = pieces[i]) != NULL; i++) { - /* Replace empty string with space for measurement and drawing. - * This makes empty lines appear, instead of being collapsed out. - */ - if (text_piece[0] == '\0') { - text_piece = " "; - } - - icon_text_info = gnome_icon_layout_text - (details->font, text_piece, - LINE_BREAK_CHARACTERS, - max_text_width, TRUE); - - /* Draw text if we are not in user rename mode */ - if (drawable != NULL && !details->is_renaming) { - text_left = icon_left + (icon_width - icon_text_info->width) / 2; - - gnome_icon_paint_text - (icon_text_info, drawable, gc, - text_left, icon_bottom + height_so_far, - GTK_JUSTIFY_CENTER); - - /* if it's highlighted, embolden by drawing twice */ - if (needs_highlight) { - gnome_icon_paint_text - (icon_text_info, drawable, gc, - text_left + 1, icon_bottom + height_so_far, - GTK_JUSTIFY_CENTER); - } - - /* if it's prelit, and we're in click-to-activate mode, underline the text */ - if (details->is_prelit && in_single_click_mode ()) { - gnome_icon_underline_text - (icon_text_info, drawable, gc, - text_left + 1, icon_bottom + height_so_far); - } - } - - if (drawable != NULL && i == 0) { - if (needs_highlight) { - gdk_rgb_gc_set_foreground (gc, highlight_text_info_color); - } else { - label_color = nautilus_icon_container_get_label_color (NAUTILUS_ICON_CONTAINER (canvas_item->canvas), FALSE); - gdk_rgb_gc_set_foreground (gc, label_color); - } - } - - width_so_far = MAX (width_so_far, (guint) icon_text_info->width); - height_so_far += icon_text_info->height; - - gnome_icon_text_info_free (icon_text_info); - } - g_strfreev (pieces); - - /* add slop used for highlighting, even if we're not highlighting now */ - width_so_far += 4; - - if (drawable != NULL) { - /* Current calculations should match what we measured before drawing. - * This assumes that we will always make a separate call to measure - * before the call to draw. We might later decide to use this function - * differently and change these asserts. - */ -#if (defined PERFORMANCE_TEST_MEASURE_DISABLE || defined PERFORMANCE_TEST_DRAW_DISABLE) - g_assert ((int) height_so_far == details->text_height); - g_assert ((int) width_so_far == details->text_width); -#endif - - gdk_gc_set_foreground (gc, &save_gc.foreground); - - box_left = icon_left + (icon_width - width_so_far) / 2; - - /* indicate keyboard selection by framing the text with a gray-stippled rectangle */ - if (details->is_highlighted_as_keyboard_focus) { - gdk_gc_set_stipple (gc, eel_stipple_bitmap ()); - gdk_gc_set_fill (gc, GDK_STIPPLED); - gdk_draw_rectangle - (drawable, gc, FALSE, - box_left, icon_bottom - 2, - width_so_far, 2 + height_so_far); - } - - gdk_gc_unref (gc); - } else { - /* If measuring, remember the width & height. */ - details->text_width = width_so_far; - details->text_height = height_so_far; - } - - g_free (combined_text); -} - -static void -measure_label_text (NautilusIconCanvasItem *item) -{ - /* check to see if the cached values are still valid; if so, there's - * no work necessary - */ - - if (item->details->text_width >= 0 && item->details->text_height >= 0) { - return; - } - - if (icon_canvas_item_is_smooth (item)) { - draw_or_measure_label_text_aa (item, NULL, 0, 0); - } - else { - draw_or_measure_label_text (item, NULL, 0, 0); - } -} - -static void -draw_label_text (NautilusIconCanvasItem *item, GdkDrawable *drawable, - int icon_left, int icon_bottom) -{ - draw_or_measure_label_text (item, drawable, icon_left, icon_bottom + LABEL_OFFSET); -} - -static void -draw_stretch_handles (NautilusIconCanvasItem *item, GdkDrawable *drawable, - const ArtIRect *rect) -{ - GdkGC *gc; - char *knob_filename; - GdkPixbuf *knob_pixbuf; - int knob_width, knob_height; - - if (!item->details->show_stretch_handles) { - return; - } - - gc = gdk_gc_new (drawable); - - knob_filename = nautilus_theme_get_image_path ("knob.png"); - knob_pixbuf = gdk_pixbuf_new_from_file (knob_filename); - knob_width = gdk_pixbuf_get_width (knob_pixbuf); - knob_height = gdk_pixbuf_get_height (knob_pixbuf); - - /* first draw the box */ - gdk_gc_set_stipple (gc, eel_stipple_bitmap ()); - gdk_gc_set_fill (gc, GDK_STIPPLED); - gdk_draw_rectangle - (drawable, gc, FALSE, - rect->x0, - rect->y0, - rect->x1 - rect->x0 - 1, - rect->y1 - rect->y0 - 1); - - /* draw the stretch handles themselves */ - - draw_pixbuf (knob_pixbuf, drawable, rect->x0, rect->y0); - draw_pixbuf (knob_pixbuf, drawable, rect->x0, rect->y1 - knob_height); - draw_pixbuf (knob_pixbuf, drawable, rect->x1 - knob_width, rect->y0); - draw_pixbuf (knob_pixbuf, drawable, rect->x1 - knob_width, rect->y1 - knob_height); - - g_free(knob_filename); - gdk_pixbuf_unref(knob_pixbuf); - - gdk_gc_unref (gc); -} - -/* utility routine that uses libart to draw an outlined rectangle */ -static void -draw_outline_rectangle_aa (GnomeCanvasBuf *buf, int x0, int y0, int x1, int y1, guint outline_color) -{ - ArtVpath vpath[12]; - ArtSVP *path; - int halfwidth; - - halfwidth = 1.0; - - vpath[0].code = ART_MOVETO; - vpath[0].x = x0 - halfwidth; - vpath[0].y = y0 - halfwidth; - - vpath[1].code = ART_LINETO; - vpath[1].x = x0 - halfwidth; - vpath[1].y = y1 + halfwidth; - - vpath[2].code = ART_LINETO; - vpath[2].x = x1 + halfwidth; - vpath[2].y = y1 + halfwidth; - - vpath[3].code = ART_LINETO; - vpath[3].x = x1 + halfwidth; - vpath[3].y = y0 - halfwidth; - - vpath[4].code = ART_LINETO; - vpath[4].x = x0 - halfwidth; - vpath[4].y = y0 - halfwidth; - - vpath[5].code = ART_MOVETO; - vpath[5].x = x0 + halfwidth; - vpath[5].y = y0 + halfwidth; - - vpath[6].code = ART_LINETO; - vpath[6].x = x1 - halfwidth; - vpath[6].y = y0 + halfwidth; - - vpath[7].code = ART_LINETO; - vpath[7].x = x1 - halfwidth; - vpath[7].y = y1 - halfwidth; - - vpath[8].code = ART_LINETO; - vpath[8].x = x0 + halfwidth; - vpath[8].y = y1 - halfwidth; - - vpath[9].code = ART_LINETO; - vpath[9].x = x0 + halfwidth; - vpath[9].y = y0 + halfwidth; - - vpath[10].code = ART_END; - vpath[10].x = 0; - vpath[10].y = 0; - - path = art_svp_from_vpath(vpath); - gnome_canvas_render_svp(buf, path, outline_color); - art_svp_free(path); -} - -/* draw the stretch handles in the anti-aliased canvas */ -static void -draw_stretch_handles_aa (NautilusIconCanvasItem *item, GnomeCanvasBuf *buf, - const ArtIRect *rect) -{ - int knob_width, knob_height; - GnomeCanvasItem *canvas_item; - char *knob_filename; - GdkPixbuf *knob_pixbuf; - - if (!item->details->show_stretch_handles) { - return; - } - - canvas_item = GNOME_CANVAS_ITEM (item); - - knob_filename = nautilus_theme_get_image_path ("knob.png"); - knob_pixbuf = gdk_pixbuf_new_from_file (knob_filename); - knob_width = gdk_pixbuf_get_width (knob_pixbuf); - knob_height = gdk_pixbuf_get_height (knob_pixbuf); - - /* draw a box to connect the dots */ - draw_outline_rectangle_aa (buf, rect->x0 + 1, rect->y0 + 1, - rect->x1 - 1, rect->y1 - 1, - EEL_RGBA_COLOR_PACK (153, 153, 153, 127)); - - /* now draw the stretch handles themselves */ - eel_gnome_canvas_draw_pixbuf (buf, knob_pixbuf, rect->x0, rect->y0); - eel_gnome_canvas_draw_pixbuf (buf, knob_pixbuf, rect->x0, rect->y1 - knob_height); - eel_gnome_canvas_draw_pixbuf (buf, knob_pixbuf, rect->x1 - knob_width, rect->y0); - eel_gnome_canvas_draw_pixbuf (buf, knob_pixbuf, rect->x1 - knob_width, rect->y1 - knob_height); - - g_free(knob_filename); - gdk_pixbuf_unref(knob_pixbuf); -} - -static void -emblem_layout_reset (EmblemLayout *layout, NautilusIconCanvasItem *icon_item, ArtIRect icon_rect) -{ - layout->icon_item = icon_item; - layout->icon_rect = icon_rect; - layout->side = RIGHT_SIDE; - layout->position = 0; - layout->index = 0; - layout->emblem = icon_item->details->emblem_pixbufs; -} - -static gboolean -emblem_layout_next (EmblemLayout *layout, - GdkPixbuf **emblem_pixbuf, - ArtIRect *emblem_rect) -{ - GdkPixbuf *pixbuf; - int width, height, x, y; - NautilusEmblemAttachPoints *attach_points; - - /* Check if we have layed out all of the pixbufs. */ - if (layout->emblem == NULL) { - return FALSE; - } - - /* Get the pixbuf. */ - pixbuf = layout->emblem->data; - width = gdk_pixbuf_get_width (pixbuf); - height = gdk_pixbuf_get_height (pixbuf); - - - /* Advance to the next emblem. */ - layout->emblem = layout->emblem->next; - - attach_points = layout->icon_item->details->attach_points; - if (attach_points != NULL) { - if (layout->index >= attach_points->num_points) { - return FALSE; - } - - x = layout->icon_rect.x0 + attach_points->points[layout->index].x; - y = layout->icon_rect.y0 + attach_points->points[layout->index].y; - - layout->index += 1; - - /* Return the rectangle and pixbuf. */ - *emblem_pixbuf = pixbuf; - emblem_rect->x0 = x - width / 2; - emblem_rect->y0 = y - height / 2; - emblem_rect->x1 = emblem_rect->x0 + width; - emblem_rect->y1 = emblem_rect->y0 + height; - - return TRUE; - - } - - for (;;) { - - /* Find the side to lay out along. */ - switch (layout->side) { - case RIGHT_SIDE: - x = layout->icon_rect.x1; - y = layout->icon_rect.y0; - break; - case BOTTOM_SIDE: - x = layout->icon_rect.x1; - y = layout->icon_rect.y1; - break; - case LEFT_SIDE: - x = layout->icon_rect.x0; - y = layout->icon_rect.y1; - break; - case TOP_SIDE: - x = layout->icon_rect.x0; - y = layout->icon_rect.y0; - break; - default: - g_assert_not_reached (); - x = 0; - y = 0; - break; - } - if (layout->position != 0) { - switch (layout->side) { - case RIGHT_SIDE: - y += layout->position + height / 2; - break; - case BOTTOM_SIDE: - x -= layout->position + width / 2; - break; - case LEFT_SIDE: - y -= layout->position + height / 2; - break; - case TOP_SIDE: - x += layout->position + width / 2; - break; - } - } - - /* Check to see if emblem fits in current side. */ - if (x >= layout->icon_rect.x0 && x <= layout->icon_rect.x1 - && y >= layout->icon_rect.y0 && y <= layout->icon_rect.y1) { - - /* It fits. */ - - /* Advance along the side. */ - switch (layout->side) { - case RIGHT_SIDE: - case LEFT_SIDE: - layout->position += height + EMBLEM_SPACING; - break; - case BOTTOM_SIDE: - case TOP_SIDE: - layout->position += width + EMBLEM_SPACING; - break; - } - - /* Return the rectangle and pixbuf. */ - *emblem_pixbuf = pixbuf; - emblem_rect->x0 = x - width / 2; - emblem_rect->y0 = y - height / 2; - emblem_rect->x1 = emblem_rect->x0 + width; - emblem_rect->y1 = emblem_rect->y0 + height; - - return TRUE; - } - - /* It doesn't fit, so move to the next side. */ - switch (layout->side) { - case RIGHT_SIDE: - layout->side = BOTTOM_SIDE; - break; - case BOTTOM_SIDE: - layout->side = LEFT_SIDE; - break; - case LEFT_SIDE: - layout->side = TOP_SIDE; - break; - case TOP_SIDE: - default: - return FALSE; - } - layout->position = 0; - } -} - -static void -draw_pixbuf (GdkPixbuf *pixbuf, GdkDrawable *drawable, int x, int y) -{ - /* FIXME bugzilla.eazel.com 703: - * Dither would be better if we passed dither values. - */ - gdk_pixbuf_render_to_drawable_alpha (pixbuf, drawable, 0, 0, x, y, - gdk_pixbuf_get_width (pixbuf), - gdk_pixbuf_get_height (pixbuf), - GDK_PIXBUF_ALPHA_BILEVEL, 128, GDK_RGB_DITHER_MAX, - 0, 0); -} - -/* shared code to highlight or dim the passed-in pixbuf */ -static GdkPixbuf * -real_map_pixbuf (NautilusIconCanvasItem *icon_item) -{ - GnomeCanvas *canvas; - char *audio_filename; - GdkPixbuf *temp_pixbuf, *old_pixbuf, *audio_pixbuf; - - temp_pixbuf = icon_item->details->pixbuf; - canvas = GNOME_CANVAS_ITEM(icon_item)->canvas; - - gdk_pixbuf_ref (temp_pixbuf); - - if (icon_item->details->is_prelit) { - old_pixbuf = temp_pixbuf; - temp_pixbuf = eel_create_spotlight_pixbuf (temp_pixbuf); - gdk_pixbuf_unref (old_pixbuf); - - /* FIXME bugzilla.eazel.com 2471: This hard-wired image is inappropriate to - * this level of code, which shouldn't know that the - * preview is audio, nor should it have an icon - * hard-wired in. - */ - - /* if the icon is currently being previewed, superimpose an image to indicate that */ - /* audio is the only kind of previewing right now, so this code isn't as general as it could be */ - if (icon_item->details->is_active) { - /* Load the audio symbol. */ - audio_filename = nautilus_pixmap_file ("audio.png"); - if (audio_filename != NULL) { - audio_pixbuf = gdk_pixbuf_new_from_file (audio_filename); - } else { - audio_pixbuf = NULL; - } - - /* Composite it onto the icon. */ - if (audio_pixbuf != NULL) { - gdk_pixbuf_composite - (audio_pixbuf, - temp_pixbuf, - 0, 0, - gdk_pixbuf_get_width (temp_pixbuf), - gdk_pixbuf_get_height(temp_pixbuf), - 0, 0, - canvas->pixels_per_unit, - canvas->pixels_per_unit, - GDK_INTERP_BILINEAR, 0xFF); - - gdk_pixbuf_unref (audio_pixbuf); - } - - g_free (audio_filename); - } - } - - if (icon_item->details->is_highlighted_for_selection - || icon_item->details->is_highlighted_for_drop) { - old_pixbuf = temp_pixbuf; - temp_pixbuf = eel_create_darkened_pixbuf (temp_pixbuf, - 0.8 * 255, - 0.8 * 255); - gdk_pixbuf_unref (old_pixbuf); - } - - return temp_pixbuf; -} - -static GdkPixbuf * -map_pixbuf (NautilusIconCanvasItem *icon_item) -{ - if (!(icon_item->details->rendered_pixbuf != NULL - && icon_item->details->rendered_is_active == icon_item->details->is_active - && icon_item->details->rendered_is_prelit == icon_item->details->is_prelit - && icon_item->details->rendered_is_highlighted_for_selection == icon_item->details->is_highlighted_for_selection - && icon_item->details->rendered_is_highlighted_for_drop == icon_item->details->is_highlighted_for_drop)) { - if (icon_item->details->rendered_pixbuf != NULL) { - gdk_pixbuf_unref (icon_item->details->rendered_pixbuf); - } - icon_item->details->rendered_pixbuf = real_map_pixbuf (icon_item); - icon_item->details->rendered_is_active = icon_item->details->is_active; - icon_item->details->rendered_is_prelit = icon_item->details->is_prelit; - icon_item->details->rendered_is_highlighted_for_selection = icon_item->details->is_highlighted_for_selection; - icon_item->details->rendered_is_highlighted_for_drop = icon_item->details->is_highlighted_for_drop; - } - - gdk_pixbuf_ref (icon_item->details->rendered_pixbuf); - - return icon_item->details->rendered_pixbuf; -} - -/* Draw the icon item for non-anti-aliased mode. */ -static void -nautilus_icon_canvas_item_draw (GnomeCanvasItem *item, GdkDrawable *drawable, - int x, int y, int width, int height) -{ - NautilusIconCanvasItem *icon_item; - NautilusIconCanvasItemDetails *details; - ArtIRect icon_rect, emblem_rect; - EmblemLayout emblem_layout; - GdkPixbuf *emblem_pixbuf, *temp_pixbuf; - - icon_item = NAUTILUS_ICON_CANVAS_ITEM (item); - details = icon_item->details; - - /* Draw the pixbuf. */ - if (details->pixbuf == NULL) { - return; - } - - /* Compute icon rectangle in drawable coordinates. */ - icon_rect = icon_item->details->canvas_rect; - icon_rect.x0 -= x; - icon_rect.y0 -= y; - icon_rect.x1 -= x; - icon_rect.y1 -= y; - - /* if the pre-lit or selection flag is set, make a pre-lit or darkened pixbuf and draw that instead */ - temp_pixbuf = map_pixbuf (icon_item); - draw_pixbuf (temp_pixbuf, drawable, icon_rect.x0, icon_rect.y0); - gdk_pixbuf_unref (temp_pixbuf); - - /* Draw the emblem pixbufs. */ - emblem_layout_reset (&emblem_layout, icon_item, icon_rect); - while (emblem_layout_next (&emblem_layout, &emblem_pixbuf, &emblem_rect)) { - draw_pixbuf (emblem_pixbuf, drawable, emblem_rect.x0, emblem_rect.y0); - } - - /* Draw stretching handles (if necessary). */ - draw_stretch_handles (icon_item, drawable, &icon_rect); - - /* Draw the label text. */ - draw_label_text (icon_item, drawable, icon_rect.x0, icon_rect.y1); -} - -static void -draw_or_measure_label_text_aa (NautilusIconCanvasItem *item, - GdkPixbuf *destination_pixbuf, - int icon_left, - int icon_bottom) -{ - NautilusIconCanvasItemDetails *details; - guint width_so_far, height_so_far; - guint32 label_name_color; - guint32 label_info_color; - GnomeCanvasItem *canvas_item; - int max_text_width; - int icon_width, text_left, box_left; - const EelSmoothTextLayout *smooth_text_layout; - char **pieces; - const char *text_piece; - int i; - char *combined_text; - gboolean have_editable, have_additional, needs_highlight; - - details = item->details; - needs_highlight = details->is_highlighted_for_selection || details->is_highlighted_for_drop; - - have_editable = details->editable_text != NULL && details->editable_text[0] != '\0'; - have_additional = details->additional_text != NULL && details->additional_text[0] != '\0'; - - /* No font or no text, then do no work. */ - if (!have_editable && !have_additional) { - details->text_height = 0; - details->text_width = 0; - return; - } - -#if (defined PERFORMANCE_TEST_MEASURE_DISABLE && defined PERFORMANCE_TEST_DRAW_DISABLE) - /* don't do any drawing and fake out the width */ - details->text_width = 80; - details->text_height = 20; - return; -#endif - -#ifdef PERFORMANCE_TEST_MEASURE_DISABLE - if (destination_pixbuf == NULL) { - /* fake out the width */ - details->text_width = 80; - details->text_height = 20; - return; - } -#endif - -#ifdef PERFORMANCE_TEST_DRAW_DISABLE - if (destination_pixbuf != NULL) { - return; - } -#endif - - /* Combine editable and additional text for processing */ - combined_text = g_strconcat - (have_editable ? details->editable_text : "", - (have_editable && have_additional) ? "\n" : "", - have_additional ? details->additional_text : "", - NULL); - - width_so_far = 0; - height_so_far = 0; - - canvas_item = GNOME_CANVAS_ITEM (item); - if (destination_pixbuf == NULL ) { - icon_width = 0; - } else { - icon_width = details->pixbuf == NULL ? 0 : gdk_pixbuf_get_width (details->pixbuf); - } - - max_text_width = floor (nautilus_icon_canvas_item_get_max_text_width (item)); - - label_name_color = nautilus_icon_container_get_label_color (NAUTILUS_ICON_CONTAINER (canvas_item->canvas), TRUE); - label_info_color = nautilus_icon_container_get_label_color (NAUTILUS_ICON_CONTAINER (canvas_item->canvas), FALSE); - - pieces = g_strsplit (combined_text, "\n", 0); - - for (i = 0; (text_piece = pieces[i]) != NULL; i++) { - guint32 label_color; - - if (needs_highlight) { - if (i == 0) { - label_color = highlight_text_color; - } - else { - label_color = highlight_text_info_color; - } - } else { - if (i == 0) { - label_color = label_name_color; - } - else { - label_color = label_info_color; - } - } - - /* Replace empty string with space for measurement and drawing. - * This makes empty lines appear, instead of being collapsed out. - */ - if (text_piece[0] == '\0') { - text_piece = " "; - } - - smooth_text_layout = eel_smooth_text_layout_cache_render (layout_cache, - text_piece, - strlen (text_piece), - details->smooth_font, - details->smooth_font_size, - TRUE, LABEL_LINE_SPACING, - max_text_width); - - /* Draw text if we are not in user rename mode */ - if (destination_pixbuf != NULL && !details->is_renaming) { - gboolean underlined; - ArtIRect destination_area; - - text_left = icon_left + (icon_width - eel_smooth_text_layout_get_width (smooth_text_layout)) / 2; - - /* if it's prelit, and we're in click-to-activate mode, underline the text */ - underlined = (details->is_prelit && in_single_click_mode ()); - - /* draw the shadow in black */ - if (needs_highlight) { - icon_bottom += 1; /* leave some space for selection frame */ - text_left -= 1; - - destination_area.x0 = text_left + 2; - destination_area.y0 = icon_bottom + height_so_far + 1; - destination_area.x1 = destination_area.x0 + eel_smooth_text_layout_get_width (smooth_text_layout); - destination_area.y1 = destination_area.y0 + eel_smooth_text_layout_get_height (smooth_text_layout); - eel_smooth_text_layout_draw_to_pixbuf (smooth_text_layout, - destination_pixbuf, - 0, - 0, - destination_area, - GTK_JUSTIFY_CENTER, - underlined, - EEL_RGB_COLOR_BLACK, - 0xff); - } - - destination_area.x0 = text_left; - destination_area.y0 = icon_bottom + height_so_far; - destination_area.x1 = destination_area.x0 + eel_smooth_text_layout_get_width (smooth_text_layout); - destination_area.y1 = destination_area.y0 + eel_smooth_text_layout_get_height (smooth_text_layout); - eel_smooth_text_layout_draw_to_pixbuf (smooth_text_layout, - destination_pixbuf, - 0, - 0, - destination_area, - GTK_JUSTIFY_CENTER, - underlined, - label_color, - 0xff); - - /* if it's highlighted, embolden by drawing twice */ - if (needs_highlight) { - destination_area.x0 = text_left + 1; - destination_area.y0 = icon_bottom + height_so_far; - destination_area.x1 = destination_area.x0 + eel_smooth_text_layout_get_width (smooth_text_layout); - destination_area.y1 = destination_area.y0 + eel_smooth_text_layout_get_height (smooth_text_layout); - eel_smooth_text_layout_draw_to_pixbuf (smooth_text_layout, - destination_pixbuf, - 0, - 0, - destination_area, - GTK_JUSTIFY_CENTER, - underlined, - label_color, - 0xff); - } - - } - - width_so_far = MAX (width_so_far, (guint) eel_smooth_text_layout_get_width (smooth_text_layout)); - height_so_far += eel_smooth_text_layout_get_height (smooth_text_layout) + LABEL_LINE_SPACING; - - gtk_object_unref (GTK_OBJECT (smooth_text_layout)); - } - g_strfreev (pieces); - - /* add some extra space for highlighting, even when we don't highlight so things wont move */ - height_so_far += 2; /* extra slop for nicer highlighting */ - width_so_far += 8; /* account for emboldening, plus extra to make it look nicer */ - - if (destination_pixbuf != NULL) { - /* Current calculations should match what we measured before drawing. - * This assumes that we will always make a separate call to measure - * before the call to draw. We might later decide to use this function - * differently and change these asserts. - */ -#if (defined PERFORMANCE_TEST_MEASURE_DISABLE || defined PERFORMANCE_TEST_DRAW_DISABLE) - g_assert ((int) height_so_far == details->text_height); - g_assert ((int) width_so_far == details->text_width); -#endif - - box_left = icon_left + (icon_width - width_so_far) / 2; - - } else { - /* If measuring, remember the width & height. */ - details->text_width = width_so_far; - details->text_height = height_so_far; - } - - g_free (combined_text); -} - -/* clear the corners of the selection pixbuf by copying the corners of the passed-in pixbuf */ -static void -clear_rounded_corners (GdkPixbuf *destination_pixbuf, GdkPixbuf *corner_pixbuf, int corner_size) -{ - int dest_width, dest_height, src_width, src_height; - - dest_width = gdk_pixbuf_get_width (destination_pixbuf); - dest_height = gdk_pixbuf_get_height (destination_pixbuf); - - src_width = gdk_pixbuf_get_width (corner_pixbuf); - src_height = gdk_pixbuf_get_height (corner_pixbuf); - - /* draw top left corner */ - gdk_pixbuf_copy_area (corner_pixbuf, - 0, 0, - corner_size, corner_size, - destination_pixbuf, - 0, 0); - - /* draw top right corner */ - gdk_pixbuf_copy_area (corner_pixbuf, - src_width - corner_size, 0, - corner_size, corner_size, - destination_pixbuf, - dest_width - corner_size, 0); - - /* draw bottom left corner */ - gdk_pixbuf_copy_area (corner_pixbuf, - 0, src_height - corner_size, - corner_size, corner_size, - destination_pixbuf, - 0, dest_height - corner_size); - - /* draw bottom right corner */ - gdk_pixbuf_copy_area (corner_pixbuf, - src_width - corner_size, src_height - corner_size, - corner_size, corner_size, - destination_pixbuf, - dest_width - corner_size, dest_height - corner_size); -} - -static void -draw_label_text_aa (NautilusIconCanvasItem *icon_item, GnomeCanvasBuf *buf, int x, int y, int x_delta) -{ - GdkPixbuf *text_pixbuf; - NautilusIconContainer *container; - - gboolean needs_highlight; - gboolean have_editable; - gboolean have_additional; - - /* make sure this is really necessary */ - have_editable = icon_item->details->editable_text != NULL - && icon_item->details->editable_text[0] != '\0'; - have_additional = icon_item->details->additional_text != NULL - && icon_item->details->additional_text[0] != '\0'; - - /* No font or no text, then do no work. */ - if (icon_item->details->smooth_font == NULL - || (!have_editable && !have_additional)) { - icon_item->details->text_height = 0; - icon_item->details->text_width = 0; - return; - } - - if (icon_item->details->is_renaming) { - /* Exit if we are renaming. We don't need to set the text - * width and height to 0 because there is text, it just is not - * drawn to the canvas while the renaming widget is dispalyed. - */ - return; - } - - /* Set up the background. */ - needs_highlight = icon_item->details->is_highlighted_for_selection - || icon_item->details->is_highlighted_for_drop; - - /* Optimizing out the allocation of this pixbuf on every call is a - * measureable speed improvement, but only by around 5%. - * draw_or_measure_label_text_aa accounts for about 90% of the time. - */ - text_pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, - TRUE, - 8, - icon_item->details->text_width, - icon_item->details->text_height); - if (needs_highlight) { - container = NAUTILUS_ICON_CONTAINER (GNOME_CANVAS_ITEM (icon_item)->canvas); - eel_gdk_pixbuf_fill_rectangle_with_color (text_pixbuf, - eel_gdk_pixbuf_whole_pixbuf, - container->details->highlight_color); - clear_rounded_corners (text_pixbuf, container->details->highlight_frame, 5); - - } else { - eel_gdk_pixbuf_fill_rectangle_with_color (text_pixbuf, - eel_gdk_pixbuf_whole_pixbuf, - EEL_RGBA_COLOR_PACK (0, 0, 0, 0)); - } - - draw_or_measure_label_text_aa (icon_item, text_pixbuf, x_delta, 0); - - /* Draw the pixbuf containing the label. */ - - eel_gnome_canvas_draw_pixbuf (buf, text_pixbuf, x - x_delta, y + LABEL_OFFSET); - - gdk_pixbuf_unref (text_pixbuf); - - /* draw the keyboard selection focus indicator if necessary */ - if (icon_item->details->is_highlighted_as_keyboard_focus) { - draw_outline_rectangle_aa (buf, x - x_delta + 1, y + 1, - x - x_delta + icon_item->details->text_width, - y + icon_item->details->text_height, - EEL_RGBA_COLOR_PACK (153, 153, 153, 127)); - } -} - -/* draw the item for anti-aliased mode */ -static void -nautilus_icon_canvas_item_render (GnomeCanvasItem *item, GnomeCanvasBuf *buf) -{ - ArtIRect icon_rect, emblem_rect; - EmblemLayout emblem_layout; - GdkPixbuf *emblem_pixbuf, *temp_pixbuf; - NautilusIconCanvasItem *icon_item; - int x_delta; - - icon_item = NAUTILUS_ICON_CANVAS_ITEM (item); - - /* map the pixbuf for selection or other effects */ - temp_pixbuf = map_pixbuf (icon_item); - - icon_rect = icon_item->details->canvas_rect; - - if (buf->is_bg) { - gnome_canvas_buf_ensure_buf (buf); - buf->is_bg = FALSE; - } - - /* draw the icon */ - eel_gnome_canvas_draw_pixbuf (buf, temp_pixbuf, icon_rect.x0, icon_rect.y0); - - gdk_pixbuf_unref (temp_pixbuf); - - /* draw the emblems */ - emblem_layout_reset (&emblem_layout, icon_item, icon_rect); - while (emblem_layout_next (&emblem_layout, &emblem_pixbuf, &emblem_rect)) { - eel_gnome_canvas_draw_pixbuf (buf, emblem_pixbuf, emblem_rect.x0, emblem_rect.y0); - } - - /* draw the stretch handles */ - draw_stretch_handles_aa (icon_item, buf, &icon_rect); - - /* draw the text */ - x_delta = (icon_item->details->text_width - (icon_rect.x1 - icon_rect.x0)) / 2; - draw_label_text_aa (icon_item, buf, icon_rect.x0, icon_rect.y1, x_delta); -} - - -/* handle events */ - -static int -nautilus_icon_canvas_item_event (GnomeCanvasItem *item, GdkEvent *event) -{ - NautilusIconCanvasItem *icon_item; - - icon_item = NAUTILUS_ICON_CANVAS_ITEM (item); - - switch (event->type) { - case GDK_ENTER_NOTIFY: - if (!icon_item->details->is_prelit) { - icon_item->details->is_prelit = TRUE; - gnome_canvas_item_request_update (item); - /* FIXME bugzilla.eazel.com 2473: - * We should emit our own signal here, - * not one from the container; it could hook - * up to that signal and emit one of its - * own. Doing it this way hard-codes what - * "user_data" is. Also, the two signals - * should be separate. The "unpreview" signal - * does not have a return value. - */ - icon_item->details->is_active = nautilus_icon_container_emit_preview_signal - (NAUTILUS_ICON_CONTAINER (item->canvas), - NAUTILUS_ICON_CANVAS_ITEM (item)->user_data, - TRUE); - } - return TRUE; - - case GDK_LEAVE_NOTIFY: - if (icon_item->details->is_prelit - || icon_item->details->is_highlighted_for_drop) { - /* When leaving, turn of the prelight state and the - * higlighted for drop. The latter gets turned on - * by the drag&drop motion callback. - */ - /* FIXME bugzilla.eazel.com 2473: - * We should emit our own signal here, - * not one from the containe; it could hook up - * to that signal and emit one of its - * ownr. Doing it this way hard-codes what - * "user_data" is. Also, the two signals - * should be separate. The "unpreview" signal - * does not have a return value. - */ - nautilus_icon_container_emit_preview_signal - (NAUTILUS_ICON_CONTAINER (item->canvas), - NAUTILUS_ICON_CANVAS_ITEM (item)->user_data, - FALSE); - icon_item->details->is_prelit = FALSE; - icon_item->details->is_active = 0; - icon_item->details->is_highlighted_for_drop = FALSE; - gnome_canvas_item_request_update (item); - } - return TRUE; - - default: - /* Don't eat up other events; icon container might use them. */ - return FALSE; - } -} - -static gboolean -hit_test_pixbuf (GdkPixbuf *pixbuf, ArtIRect pixbuf_location, ArtIRect probe_rect) -{ - ArtIRect relative_rect, pixbuf_rect; - int x, y; - guint8 *pixel; - - /* You can get here without a pixbuf in some strange cases. */ - if (pixbuf == NULL) { - return FALSE; - } - - /* Check to see if it's within the rectangle at all. */ - relative_rect.x0 = probe_rect.x0 - pixbuf_location.x0; - relative_rect.y0 = probe_rect.y0 - pixbuf_location.y0; - relative_rect.x1 = probe_rect.x1 - pixbuf_location.x0; - relative_rect.y1 = probe_rect.y1 - pixbuf_location.y0; - pixbuf_rect.x0 = 0; - pixbuf_rect.y0 = 0; - pixbuf_rect.x1 = gdk_pixbuf_get_width (pixbuf); - pixbuf_rect.y1 = gdk_pixbuf_get_height (pixbuf); - art_irect_intersect (&relative_rect, &relative_rect, &pixbuf_rect); - if (art_irect_empty (&relative_rect)) { - return FALSE; - } - - /* If there's no alpha channel, it's opaque and we have a hit. */ - if (!gdk_pixbuf_get_has_alpha (pixbuf)) { - return TRUE; - } - g_assert (gdk_pixbuf_get_n_channels (pixbuf) == 4); - - /* Check the alpha channel of the pixel to see if we have a hit. */ - for (x = relative_rect.x0; x < relative_rect.x1; x++) { - for (y = relative_rect.y0; y < relative_rect.y1; y++) { - pixel = gdk_pixbuf_get_pixels (pixbuf) - + y * gdk_pixbuf_get_rowstride (pixbuf) - + x * 4; - if (pixel[3] > 1) { - return TRUE; - } - } - } - return FALSE; -} - -static gboolean -hit_test (NautilusIconCanvasItem *icon_item, ArtIRect canvas_rect) -{ - NautilusIconCanvasItemDetails *details; - ArtIRect emblem_rect; - EmblemLayout emblem_layout; - GdkPixbuf *emblem_pixbuf; - - details = icon_item->details; - - /* Quick check to see if the rect hits the icon, text or emblems at all. */ - if (!eel_art_irect_hits_irect (icon_item->details->canvas_rect, canvas_rect) - && (!eel_art_irect_hits_irect (details->text_rect, canvas_rect)) - && (!eel_art_irect_hits_irect (details->emblem_rect, canvas_rect))) { - return FALSE; - } - - /* Check for hits in the stretch handles. */ - if (hit_test_stretch_handle (icon_item, canvas_rect)) { - return TRUE; - } - - /* Check for hit in the icon. If we're highlighted for dropping, anywhere in the rect is OK */ - if (icon_item->details->is_highlighted_for_drop) { - if (eel_art_irect_hits_irect (icon_item->details->canvas_rect, canvas_rect)) { - return TRUE; - } - } else { - if (hit_test_pixbuf (details->pixbuf, icon_item->details->canvas_rect, canvas_rect)) { - return TRUE; - } - } - - /* Check for hit in the text. */ - if (eel_art_irect_hits_irect (details->text_rect, canvas_rect) - && !icon_item->details->is_renaming) { - return TRUE; - } - - /* Check for hit in the emblem pixbufs. */ - emblem_layout_reset (&emblem_layout, icon_item, icon_item->details->canvas_rect); - while (emblem_layout_next (&emblem_layout, &emblem_pixbuf, &emblem_rect)) { - if (hit_test_pixbuf (emblem_pixbuf, emblem_rect, canvas_rect)) { - return TRUE; - } - } - - return FALSE; -} - -/* Point handler for the icon canvas item. */ -static double -nautilus_icon_canvas_item_point (GnomeCanvasItem *item, double x, double y, int cx, int cy, - GnomeCanvasItem **actual_item) -{ - ArtIRect canvas_rect; - - *actual_item = item; - canvas_rect.x0 = cx; - canvas_rect.y0 = cy; - canvas_rect.x1 = cx + 1; - canvas_rect.y1 = cy + 1; - if (hit_test (NAUTILUS_ICON_CANVAS_ITEM (item), canvas_rect)) { - return 0.0; - } else { - /* This value means not hit. - * It's kind of arbitrary. Can we do better? - */ - return item->canvas->pixels_per_unit * 2 + 10; - } -} - -/* Bounds handler for the icon canvas item. */ -static void -nautilus_icon_canvas_item_bounds (GnomeCanvasItem *item, - double *x1, double *y1, double *x2, double *y2) -{ - NautilusIconCanvasItem *icon_item; - NautilusIconCanvasItemDetails *details; - ArtIRect icon_rect, text_rect, total_rect, emblem_rect; - double pixels_per_unit; - EmblemLayout emblem_layout; - GdkPixbuf *emblem_pixbuf; - - g_assert (x1 != NULL); - g_assert (y1 != NULL); - g_assert (x2 != NULL); - g_assert (y2 != NULL); - - icon_item = NAUTILUS_ICON_CANVAS_ITEM (item); - details = icon_item->details; - - measure_label_text (icon_item); - - /* Compute icon rectangle. */ - icon_rect.x0 = 0; - icon_rect.y0 = 0; - if (details->pixbuf == NULL) { - icon_rect.x1 = 0; - icon_rect.y1 = 0; - } else { - icon_rect.x1 = gdk_pixbuf_get_width (details->pixbuf); - icon_rect.y1 = gdk_pixbuf_get_height (details->pixbuf); - } - - /* Compute text rectangle. */ - text_rect = compute_text_rectangle (icon_item, icon_rect); - - /* Compute total rectangle, adding in emblem rectangles. */ - art_irect_union (&total_rect, &icon_rect, &text_rect); - emblem_layout_reset (&emblem_layout, icon_item, icon_rect); - while (emblem_layout_next (&emblem_layout, &emblem_pixbuf, &emblem_rect)) { - art_irect_union (&total_rect, &total_rect, &emblem_rect); - } - - /* Return the result. */ - pixels_per_unit = item->canvas->pixels_per_unit; - *x1 = total_rect.x0 / pixels_per_unit; - *y1 = total_rect.y0 / pixels_per_unit; - *x2 = total_rect.x1 / pixels_per_unit; - *y2 = total_rect.y1 / pixels_per_unit; -} - -/* Get the rectangle of the icon only, in world coordinates. */ -ArtDRect -nautilus_icon_canvas_item_get_icon_rectangle (const NautilusIconCanvasItem *item) -{ - ArtDRect rectangle; - double i2w[6]; - ArtPoint art_point; - double pixels_per_unit; - GdkPixbuf *pixbuf; - - g_return_val_if_fail (NAUTILUS_IS_ICON_CANVAS_ITEM (item), eel_art_drect_empty); - - gnome_canvas_item_i2w_affine (GNOME_CANVAS_ITEM (item), i2w); - - art_point.x = 0; - art_point.y = 0; - art_affine_point (&art_point, &art_point, i2w); - - rectangle.x0 = art_point.x; - rectangle.y0 = art_point.y; - - pixbuf = item->details->pixbuf; - pixels_per_unit = GNOME_CANVAS_ITEM (item)->canvas->pixels_per_unit; - - rectangle.x1 = rectangle.x0 + (pixbuf == NULL ? 0 : gdk_pixbuf_get_width (pixbuf)) / pixels_per_unit; - rectangle.y1 = rectangle.y0 + (pixbuf == NULL ? 0 : gdk_pixbuf_get_height (pixbuf)) / pixels_per_unit; - - return rectangle; -} - -/* Get the rectangle of the icon only, in canvas coordinates. */ -static void -get_icon_canvas_rectangle (NautilusIconCanvasItem *item, - ArtIRect *rect) -{ - double i2c[6]; - ArtPoint art_point; - GdkPixbuf *pixbuf; - - g_return_if_fail (NAUTILUS_IS_ICON_CANVAS_ITEM (item)); - g_return_if_fail (rect != NULL); - - gnome_canvas_item_i2c_affine (GNOME_CANVAS_ITEM (item), i2c); - - art_point.x = 0; - art_point.y = 0; - art_affine_point (&art_point, &art_point, i2c); - - rect->x0 = floor (art_point.x); - rect->y0 = floor (art_point.y); - - pixbuf = item->details->pixbuf; - - rect->x1 = rect->x0 + (pixbuf == NULL ? 0 : gdk_pixbuf_get_width (pixbuf)); - rect->y1 = rect->y0 + (pixbuf == NULL ? 0 : gdk_pixbuf_get_height (pixbuf)); -} - -void -nautilus_icon_canvas_item_set_show_stretch_handles (NautilusIconCanvasItem *item, - gboolean show_stretch_handles) -{ - g_return_if_fail (NAUTILUS_IS_ICON_CANVAS_ITEM (item)); - g_return_if_fail (show_stretch_handles == FALSE || show_stretch_handles == TRUE); - - if (!item->details->show_stretch_handles == !show_stretch_handles) { - return; - } - - item->details->show_stretch_handles = show_stretch_handles; - gnome_canvas_item_request_update (GNOME_CANVAS_ITEM (item)); -} - -/* Check whether the item is in smooth mode */ -static gboolean -icon_canvas_item_is_smooth (const NautilusIconCanvasItem *icon_item) -{ - GnomeCanvas *parent_canvas; - - g_return_val_if_fail (NAUTILUS_IS_ICON_CANVAS_ITEM (icon_item), FALSE); - - parent_canvas = GNOME_CANVAS (GNOME_CANVAS_ITEM (icon_item)->canvas); - - return parent_canvas->aa; -} - -/* Check if one of the stretch handles was hit. */ -static gboolean -hit_test_stretch_handle (NautilusIconCanvasItem *item, - ArtIRect probe_canvas_rect) -{ - ArtIRect icon_rect; - char *knob_filename; - GdkPixbuf *knob_pixbuf; - int knob_width, knob_height; - - g_return_val_if_fail (NAUTILUS_IS_ICON_CANVAS_ITEM (item), FALSE); - - /* Make sure there are handles to hit. */ - if (!item->details->show_stretch_handles) { - return FALSE; - } - - /* Quick check to see if the rect hits the icon at all. */ - icon_rect = item->details->canvas_rect; - if (!eel_art_irect_hits_irect (probe_canvas_rect, icon_rect)) { - return FALSE; - } - - knob_filename = nautilus_theme_get_image_path ("knob.png"); - knob_pixbuf = gdk_pixbuf_new_from_file (knob_filename); - knob_width = gdk_pixbuf_get_width (knob_pixbuf); - knob_height = gdk_pixbuf_get_height (knob_pixbuf); - - g_free(knob_filename); - gdk_pixbuf_unref(knob_pixbuf); - - /* Check for hits in the stretch handles. */ - return (probe_canvas_rect.x0 < icon_rect.x0 + knob_width - || probe_canvas_rect.x1 >= icon_rect.x1 - knob_width) - && (probe_canvas_rect.y0 < icon_rect.y0 + knob_height - || probe_canvas_rect.y1 >= icon_rect.y1 - knob_height); -} - -gboolean -nautilus_icon_canvas_item_hit_test_stretch_handles (NautilusIconCanvasItem *item, - ArtPoint world_point) -{ - ArtIRect canvas_rect; - - g_return_val_if_fail (NAUTILUS_IS_ICON_CANVAS_ITEM (item), FALSE); - - gnome_canvas_w2c (GNOME_CANVAS_ITEM (item)->canvas, - world_point.x, - world_point.y, - &canvas_rect.x0, - &canvas_rect.y0); - canvas_rect.x1 = canvas_rect.x0 + 1; - canvas_rect.y1 = canvas_rect.y0 + 1; - return hit_test_stretch_handle (item, canvas_rect); -} - -/* nautilus_icon_canvas_item_hit_test_rectangle - * - * Check and see if there is an intersection between the item and the - * canvas rect. - */ -gboolean -nautilus_icon_canvas_item_hit_test_rectangle (NautilusIconCanvasItem *item, ArtIRect canvas_rect) -{ - g_return_val_if_fail (NAUTILUS_IS_ICON_CANVAS_ITEM (item), FALSE); - - return hit_test (item, canvas_rect); -} - -const char * -nautilus_icon_canvas_item_get_editable_text (NautilusIconCanvasItem *icon_item) -{ - g_return_val_if_fail (NAUTILUS_IS_ICON_CANVAS_ITEM (icon_item), NULL); - - return icon_item->details->editable_text; -} - -void -nautilus_icon_canvas_item_set_renaming (NautilusIconCanvasItem *item, gboolean state) -{ - g_return_if_fail (NAUTILUS_IS_ICON_CANVAS_ITEM (item)); - g_return_if_fail (state == FALSE || state == TRUE); - - if (item->details->is_renaming == state) { - return; - } - - item->details->is_renaming = state; - gnome_canvas_item_request_update (GNOME_CANVAS_ITEM (item)); -} - -double -nautilus_icon_canvas_item_get_max_text_width (NautilusIconCanvasItem *item) -{ - GnomeCanvasItem *canvas_item; - - canvas_item = GNOME_CANVAS_ITEM (item); - if (nautilus_icon_container_is_tighter_layout (NAUTILUS_ICON_CONTAINER (canvas_item->canvas))) { - return MAX_TEXT_WIDTH_TIGHTER * canvas_item->canvas->pixels_per_unit; - } else { - return MAX_TEXT_WIDTH_STANDARD * canvas_item->canvas->pixels_per_unit; - } - -} - -void -nautilus_icon_canvas_item_set_smooth_font (NautilusIconCanvasItem *icon_item, - EelScalableFont *font) -{ - g_return_if_fail (NAUTILUS_IS_ICON_CANVAS_ITEM (icon_item)); - g_return_if_fail (EEL_IS_SCALABLE_FONT (font)); - - gtk_object_unref (GTK_OBJECT (icon_item->details->smooth_font)); - - gtk_object_ref (GTK_OBJECT (font)); - - icon_item->details->smooth_font = font; - - /* Only need to update if in smooth mode */ - if (icon_canvas_item_is_smooth (icon_item)) { - gnome_canvas_item_request_update (GNOME_CANVAS_ITEM (icon_item)); - } -} - -void -nautilus_icon_canvas_item_set_smooth_font_size (NautilusIconCanvasItem *icon_item, - int font_size) -{ - g_return_if_fail (NAUTILUS_IS_ICON_CANVAS_ITEM (icon_item)); - g_return_if_fail (font_size > 0); - - if (icon_item->details->smooth_font_size == font_size) { - return; - } - - icon_item->details->smooth_font_size = font_size; - - /* Only need to update if in smooth mode */ - if (icon_canvas_item_is_smooth (icon_item)) { - gnome_canvas_item_request_update (GNOME_CANVAS_ITEM (icon_item)); - } -} diff --git a/libnautilus-extensions/nautilus-icon-canvas-item.h b/libnautilus-extensions/nautilus-icon-canvas-item.h deleted file mode 100644 index 35b1cc6d5..000000000 --- a/libnautilus-extensions/nautilus-icon-canvas-item.h +++ /dev/null @@ -1,98 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ - -/* Nautilus - Icon canvas item class for icon container. - * - * Copyright (C) 2000 Eazel, Inc. - * - * Author: Andy Hertzfeld <andy@eazel.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. - * - * This 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; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef NAUTILUS_ICON_CANVAS_ITEM_H -#define NAUTILUS_ICON_CANVAS_ITEM_H - -#include <libgnome/gnome-defs.h> -#include <libgnomeui/gnome-canvas.h> -#include <gdk-pixbuf/gdk-pixbuf.h> -#include "nautilus-icon-factory.h" -#include <eel/eel-scalable-font.h> - -BEGIN_GNOME_DECLS - -#define NAUTILUS_TYPE_ICON_CANVAS_ITEM \ - (nautilus_icon_canvas_item_get_type ()) -#define NAUTILUS_ICON_CANVAS_ITEM(obj) \ - (GTK_CHECK_CAST ((obj), NAUTILUS_TYPE_ICON_CANVAS_ITEM, NautilusIconCanvasItem)) -#define NAUTILUS_ICON_CANVAS_ITEM_CLASS(klass) \ - (GTK_CHECK_CLASS_CAST ((klass), NAUTILUS_TYPE_ICON_CANVAS_ITEM, NautilusIconCanvasItemClass)) -#define NAUTILUS_IS_ICON_CANVAS_ITEM(obj) \ - (GTK_CHECK_TYPE ((obj), NAUTILUS_TYPE_ICON_CANVAS_ITEM)) -#define NAUTILUS_IS_ICON_CANVAS_ITEM_CLASS(klass) \ - (GTK_CHECK_CLASS_TYPE ((klass), NAUTILUS_TYPE_ICON_CANVAS_ITEM)) - -typedef struct NautilusIconCanvasItem NautilusIconCanvasItem; -typedef struct NautilusIconCanvasItemClass NautilusIconCanvasItemClass; -typedef struct NautilusIconCanvasItemDetails NautilusIconCanvasItemDetails; - -struct NautilusIconCanvasItem { - GnomeCanvasItem item; - NautilusIconCanvasItemDetails *details; - gpointer user_data; -}; - -struct NautilusIconCanvasItemClass { - GnomeCanvasItemClass parent_class; - - void (* bounds_changed) (NautilusIconCanvasItem *item, - const ArtDRect *old_world_bounds); -}; - -/* GtkObject */ -GtkType nautilus_icon_canvas_item_get_type (void); - -/* attributes */ -void nautilus_icon_canvas_item_set_image (NautilusIconCanvasItem *item, - GdkPixbuf *image); -GdkPixbuf * nautilus_icon_canvas_item_get_image (NautilusIconCanvasItem *item); -void nautilus_icon_canvas_item_set_emblems (NautilusIconCanvasItem *item, - GList *emblem_pixbufs); -void nautilus_icon_canvas_item_set_show_stretch_handles (NautilusIconCanvasItem *item, - gboolean show_stretch_handles); -void nautilus_icon_canvas_item_set_attach_points (NautilusIconCanvasItem *item, - NautilusEmblemAttachPoints *attach_points); -double nautilus_icon_canvas_item_get_max_text_width (NautilusIconCanvasItem *item); -const char *nautilus_icon_canvas_item_get_editable_text (NautilusIconCanvasItem *icon_item); -void nautilus_icon_canvas_item_set_renaming (NautilusIconCanvasItem *icon_item, - gboolean state); - - -/* geometry and hit testing */ -gboolean nautilus_icon_canvas_item_hit_test_rectangle (NautilusIconCanvasItem *item, - ArtIRect canvas_rect); -gboolean nautilus_icon_canvas_item_hit_test_stretch_handles (NautilusIconCanvasItem *item, - ArtPoint world_point); -void nautilus_icon_canvas_item_invalidate_label_size (NautilusIconCanvasItem *item); -ArtDRect nautilus_icon_canvas_item_get_icon_rectangle (const NautilusIconCanvasItem *item); -void nautilus_icon_canvas_item_update_bounds (NautilusIconCanvasItem *item); -void nautilus_icon_canvas_item_set_smooth_font (NautilusIconCanvasItem *item, - EelScalableFont *font); -void nautilus_icon_canvas_item_set_smooth_font_size (NautilusIconCanvasItem *item, - int font_size); - -END_GNOME_DECLS - -#endif /* NAUTILUS_ICON_CANVAS_ITEM_H */ diff --git a/libnautilus-extensions/nautilus-icon-container.c b/libnautilus-extensions/nautilus-icon-container.c deleted file mode 100644 index fbfce2692..000000000 --- a/libnautilus-extensions/nautilus-icon-container.c +++ /dev/null @@ -1,5194 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ - -/* nautilus-icon-container.c - Icon container widget. - - Copyright (C) 1999, 2000 Free Software Foundation - Copyright (C) 2000, 2001 Eazel, Inc. - - The Gnome 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 Gnome 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 the Gnome 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. - - Authors: Ettore Perazzoli <ettore@gnu.org>, - Darin Adler <darin@eazel.com> -*/ - -#include <config.h> -#include "nautilus-icon-container.h" - -#include "nautilus-font-factory.h" -#include "nautilus-global-preferences.h" -#include "nautilus-icon-private.h" -#include "nautilus-icon-text-item.h" -#include "nautilus-lib-self-check-functions.h" -#include "nautilus-theme.h" -#include <ctype.h> -#include <eel/eel-background.h> -#include <eel/eel-canvas-rect.h> -#include <eel/eel-gdk-pixbuf-extensions.h> -#include <eel/eel-glib-extensions.h> -#include <eel/eel-gnome-extensions.h> -#include <eel/eel-gtk-extensions.h> -#include <eel/eel-gtk-macros.h> -#include <eel/eel-string.h> -#include <gdk-pixbuf/gnome-canvas-pixbuf.h> -#include <gdk/gdkkeysyms.h> -#include <gtk/gtklayout.h> -#include <gtk/gtkmain.h> -#include <gtk/gtksignal.h> -#include <libgnome/gnome-i18n.h> -#include <libnautilus/nautilus-clipboard.h> -#include <math.h> -#include <stdio.h> -#include <string.h> - -/* Interval for updating the rubberband selection, in milliseconds. */ -#define RUBBERBAND_TIMEOUT_INTERVAL 10 - -/* Internal double click time constant */ -#define DOUBLE_CLICK_TIME 500000 - -/* Initial unpositioned icon value */ -#define ICON_UNPOSITIONED_VALUE -1 - -/* Timeout for making the icon currently selected for keyboard operation visible. - * If this is 0, you can get into trouble with extra scrolling after holding - * down the arrow key for awhile when there are many items. - */ -#define KEYBOARD_ICON_REVEAL_TIMEOUT 10 - -#define CONTEXT_MENU_TIMEOUT_INTERVAL 500 - -/* Maximum amount of milliseconds the mouse button is allowed to stay down - * and still be considered a click. - */ -#define MAX_CLICK_TIME 1500 - -/* Distance you have to move before it becomes a drag. */ -#define SNAP_RESISTANCE 2 /* GMC has this set to 3, but it's too much for Ettore's taste. */ - -/* Button assignments. */ -#define DRAG_BUTTON 1 -#define RUBBERBAND_BUTTON 1 -#define MIDDLE_BUTTON 2 -#define CONTEXTUAL_MENU_BUTTON 3 - -/* Maximum size (pixels) allowed for icons at the standard zoom level. */ -#define MINIMUM_IMAGE_SIZE 24 -#define MAXIMUM_IMAGE_SIZE 96 -#define MAXIMUM_EMBLEM_SIZE 48 - -#define ICON_PAD_LEFT 4 -#define ICON_PAD_RIGHT 4 -#define ICON_BASE_WIDTH 96 - -#define ICON_PAD_TOP 4 -#define ICON_PAD_BOTTOM 4 - -#define CONTAINER_PAD_LEFT 4 -#define CONTAINER_PAD_RIGHT 4 -#define CONTAINER_PAD_TOP 4 -#define CONTAINER_PAD_BOTTOM 4 - -#define STANDARD_ICON_GRID_WIDTH 145 - -/* Desktop layout mode defines */ -#define DESKTOP_PAD_HORIZONTAL 30 -#define DESKTOP_PAD_VERTICAL 10 -#define CELL_SIZE 20 - -/* Value used to protect against icons being dragged outside of the desktop bounds */ -#define DESKTOP_ICON_SAFETY_PAD 10 - -enum { - NAUTILUS_TYPESELECT_FLUSH_DELAY = 1000000 - /* After this time the current typeselect buffer will be - * thrown away and the new pressed character will be made - * the the start of a new pattern. - */ -}; - -static void activate_selected_items (NautilusIconContainer *container); -static void nautilus_icon_container_initialize_class (NautilusIconContainerClass *class); -static void nautilus_icon_container_initialize (NautilusIconContainer *container); -static void nautilus_icon_container_theme_changed (gpointer user_data); - -static void compute_stretch (StretchState *start, - StretchState *current); -static NautilusIcon *get_first_selected_icon (NautilusIconContainer *container); -static NautilusIcon *get_nth_selected_icon (NautilusIconContainer *container, - int index); -static gboolean has_multiple_selection (NautilusIconContainer *container); -static void icon_destroy (NautilusIconContainer *container, - NautilusIcon *icon); -static void end_renaming_mode (NautilusIconContainer *container, - gboolean commit); -static NautilusIcon *get_icon_being_renamed (NautilusIconContainer *container); -static void finish_adding_new_icons (NautilusIconContainer *container); -static void update_label_color (EelBackground *background, - NautilusIconContainer *icon_container); -static void icon_get_bounding_box (NautilusIcon *icon, - int *x1_return, - int *y1_return, - int *x2_return, - int *y2_return); -static gboolean is_renaming (NautilusIconContainer *container); -static gboolean is_renaming_pending (NautilusIconContainer *container); -static void process_pending_icon_to_rename (NautilusIconContainer *container); - -static int click_policy_auto_value; - -EEL_DEFINE_CLASS_BOILERPLATE (NautilusIconContainer, - nautilus_icon_container, - GNOME_TYPE_CANVAS) - -/* The NautilusIconContainer signals. */ -enum { - ACTIVATE, - BAND_SELECT_STARTED, - BAND_SELECT_ENDED, - BUTTON_PRESS, - CAN_ACCEPT_ITEM, - COMPARE_ICONS, - COMPARE_ICONS_BY_NAME, - CONTEXT_CLICK_BACKGROUND, - CONTEXT_CLICK_SELECTION, - MIDDLE_CLICK, - GET_CONTAINER_URI, - GET_ICON_IMAGES, - GET_ICON_TEXT, - GET_ICON_URI, - GET_ICON_DROP_TARGET_URI, - GET_STORED_ICON_POSITION, - ICON_POSITION_CHANGED, - ICON_TEXT_CHANGED, - ICON_STRETCH_STARTED, - ICON_STRETCH_ENDED, - RENAMING_ICON, - LAYOUT_CHANGED, - MOVE_COPY_ITEMS, - HANDLE_URI_LIST, - PREVIEW, - SELECTION_CHANGED, - LAST_SIGNAL -}; -static guint signals[LAST_SIGNAL]; - -/* Bitmap for stippled selection rectangles. */ -static GdkBitmap *stipple; -static char stipple_bits[] = { 0x02, 0x01 }; - -/* Functions dealing with NautilusIcons. */ - -static void -icon_free (NautilusIcon *icon) -{ - /* Destroy this canvas item; the parent will unref it. */ - gtk_object_destroy (GTK_OBJECT (icon->item)); - g_free (icon); -} - -static gboolean -icon_is_positioned (const NautilusIcon *icon) -{ - return icon->x != ICON_UNPOSITIONED_VALUE && icon->y != ICON_UNPOSITIONED_VALUE; -} - -static void -icon_set_position (NautilusIcon *icon, - double x, double y) -{ - NautilusIconContainer *container; - - int left, top, right, bottom; - int width, height; - int x1, y1, x2, y2; - - if (icon->x == x && icon->y == y) { - return; - } - - container = NAUTILUS_ICON_CONTAINER (GNOME_CANVAS_ITEM (icon->item)->canvas); - - if (icon == get_icon_being_renamed (container)) { - end_renaming_mode (container, TRUE); - } - - if (nautilus_icon_container_get_is_fixed_size (container)) { - /* Clip the position of the icon within our desktop bounds */ - left = GTK_WIDGET (container)->allocation.x; - top = GTK_WIDGET (container)->allocation.y; - right = left + GTK_WIDGET (container)->allocation.width; - bottom = top + GTK_WIDGET (container)->allocation.height; - - icon_get_bounding_box (icon, &x1, &y1, &x2, &y2); - width = x2 - x1; - height = y2 - y1; - - if (x > right - DESKTOP_ICON_SAFETY_PAD) { - x = right - DESKTOP_ICON_SAFETY_PAD; - } - - if (x < left) { - x = left; - } - if (y > bottom - DESKTOP_ICON_SAFETY_PAD) { - y = bottom - DESKTOP_ICON_SAFETY_PAD; - } - if (y < top) { - y = top; - } - } - - gnome_canvas_item_move (GNOME_CANVAS_ITEM (icon->item), - x - icon->x, - y - icon->y); - - icon->x = x; - icon->y = y; -} - -static void -icon_get_size (NautilusIconContainer *container, - NautilusIcon *icon, - guint *size_x, guint *size_y) -{ - if (size_x != NULL) { - *size_x = MAX (nautilus_get_icon_size_for_zoom_level (container->details->zoom_level) - * icon->scale_x, NAUTILUS_ICON_SIZE_SMALLEST); - } - if (size_y != NULL) { - *size_y = MAX (nautilus_get_icon_size_for_zoom_level (container->details->zoom_level) - * icon->scale_y, NAUTILUS_ICON_SIZE_SMALLEST); - } -} - -/* The icon_set_size function is used by the stretching user - * interface, which currently stretches in a way that keeps the aspect - * ratio. Later we might have a stretching interface that stretches Y - * separate from X and we will change this around. - */ -static void -icon_set_size (NautilusIconContainer *container, - NautilusIcon *icon, - guint icon_size, - gboolean update_position) -{ - guint old_size_x, old_size_y; - double scale; - - icon_get_size (container, icon, &old_size_x, &old_size_y); - if (icon_size == old_size_x && icon_size == old_size_y) { - return; - } - - scale = (double) icon_size / - nautilus_get_icon_size_for_zoom_level - (container->details->zoom_level); - nautilus_icon_container_move_icon (container, icon, - icon->x, icon->y, - scale, scale, - FALSE, update_position); -} - -static void -icon_raise (NautilusIcon *icon) -{ - gnome_canvas_item_raise_to_top (GNOME_CANVAS_ITEM (icon->item)); -} - -static void -emit_stretch_started (NautilusIconContainer *container, NautilusIcon *icon) -{ - gtk_signal_emit (GTK_OBJECT (container), - signals[ICON_STRETCH_STARTED], - icon->data); -} - -static void -emit_stretch_ended (NautilusIconContainer *container, NautilusIcon *icon) -{ - gtk_signal_emit (GTK_OBJECT (container), - signals[ICON_STRETCH_ENDED], - icon->data); -} - -static void -icon_toggle_selected (NautilusIconContainer *container, - NautilusIcon *icon) -{ - end_renaming_mode (container, TRUE); - - icon->is_selected = !icon->is_selected; - gnome_canvas_item_set (GNOME_CANVAS_ITEM (icon->item), - "highlighted_for_selection", (gboolean) icon->is_selected, - NULL); - - /* If the icon is deselected, then get rid of the stretch handles. - * No harm in doing the same if the item is newly selected. - */ - if (icon == container->details->stretch_icon) { - container->details->stretch_icon = NULL; - nautilus_icon_canvas_item_set_show_stretch_handles (icon->item, FALSE); - emit_stretch_ended (container, icon); - } - - /* Raise each newly-selected icon to the front as it is selected. */ - if (icon->is_selected) { - icon_raise (icon); - } - -} - -/* Select an icon. Return TRUE if selection has changed. */ -static gboolean -icon_set_selected (NautilusIconContainer *container, - NautilusIcon *icon, - gboolean select) -{ - g_assert (select == FALSE || select == TRUE); - g_assert (icon->is_selected == FALSE || icon->is_selected == TRUE); - - if (select == icon->is_selected) { - return FALSE; - } - - icon_toggle_selected (container, icon); - g_assert (select == icon->is_selected); - return TRUE; -} - -static void -icon_get_bounding_box (NautilusIcon *icon, - int *x1_return, int *y1_return, - int *x2_return, int *y2_return) -{ - double x1, y1, x2, y2; - - gnome_canvas_item_get_bounds (GNOME_CANVAS_ITEM (icon->item), - &x1, &y1, &x2, &y2); - - *x1_return = x1; - *y1_return = y1; - *x2_return = x2; - *y2_return = y2; -} - -/* Utility functions for NautilusIconContainer. */ - -gboolean -nautilus_icon_container_scroll (NautilusIconContainer *container, - int delta_x, int delta_y) -{ - GtkAdjustment *hadj, *vadj; - int old_h_value, old_v_value; - - hadj = gtk_layout_get_hadjustment (GTK_LAYOUT (container)); - vadj = gtk_layout_get_vadjustment (GTK_LAYOUT (container)); - - /* Store the old ajustment values so we can tell if we - * ended up actually scrolling. We may not have in a case - * where the resulting value got pinned to the adjustment - * min or max. - */ - old_h_value = hadj->value; - old_v_value = vadj->value; - - eel_gtk_adjustment_set_value (hadj, hadj->value + delta_x); - eel_gtk_adjustment_set_value (vadj, vadj->value + delta_y); - - /* return TRUE if we did scroll */ - return hadj->value != old_h_value || vadj->value != old_v_value; -} - -static void -pending_icon_to_reveal_destroy_callback (NautilusIconCanvasItem *item, - NautilusIconContainer *container) -{ - g_assert (NAUTILUS_IS_ICON_CONTAINER (container)); - g_assert (container->details->pending_icon_to_reveal != NULL); - g_assert (container->details->pending_icon_to_reveal->item == item); - - container->details->pending_icon_to_reveal = NULL; -} - -static NautilusIcon* -get_pending_icon_to_reveal (NautilusIconContainer *container) -{ - return container->details->pending_icon_to_reveal; -} - -static void -set_pending_icon_to_reveal (NautilusIconContainer *container, NautilusIcon *icon) -{ - NautilusIcon *cur_pending; - - cur_pending = container->details->pending_icon_to_reveal; - - if (icon == cur_pending) { - return; - } - - if (cur_pending != NULL) { - gtk_signal_disconnect_by_func (GTK_OBJECT (cur_pending->item), - pending_icon_to_reveal_destroy_callback, - container); - } - - if (icon != NULL) { - gtk_signal_connect (GTK_OBJECT (icon->item), "destroy", - pending_icon_to_reveal_destroy_callback, container); - } - - container->details->pending_icon_to_reveal = icon; -} - -static void -reveal_icon (NautilusIconContainer *container, - NautilusIcon *icon) -{ - NautilusIconContainerDetails *details; - GtkAllocation *allocation; - GtkAdjustment *hadj, *vadj; - ArtIRect bounds; - - if (!icon_is_positioned (icon)) { - set_pending_icon_to_reveal (container, icon); - return; - } - - set_pending_icon_to_reveal (container, NULL); - - details = container->details; - allocation = >K_WIDGET (container)->allocation; - - hadj = gtk_layout_get_hadjustment (GTK_LAYOUT (container)); - vadj = gtk_layout_get_vadjustment (GTK_LAYOUT (container)); - - bounds = eel_gnome_canvas_item_get_canvas_bounds - (GNOME_CANVAS_ITEM (icon->item)); - - if (bounds.y0 < vadj->value) { - eel_gtk_adjustment_set_value (vadj, bounds.y0); - } else if (bounds.y1 > vadj->value + allocation->height) { - eel_gtk_adjustment_set_value - (vadj, bounds.y1 - allocation->height); - } - - if (bounds.x0 < hadj->value) { - eel_gtk_adjustment_set_value (hadj, bounds.x0); - } else if (bounds.x1 > hadj->value + allocation->width) { - eel_gtk_adjustment_set_value - (hadj, bounds.x1 - allocation->width); - } -} - -static void -process_pending_icon_to_reveal (NautilusIconContainer *container) -{ - NautilusIcon *pending_icon_to_reveal; - - pending_icon_to_reveal = get_pending_icon_to_reveal (container); - - if (pending_icon_to_reveal != NULL) { - reveal_icon (container, pending_icon_to_reveal); - } -} - -static gboolean -keyboard_icon_reveal_timeout_callback (gpointer data) -{ - NautilusIconContainer *container; - NautilusIcon *icon; - - container = NAUTILUS_ICON_CONTAINER (data); - icon = container->details->keyboard_icon_to_reveal; - - g_assert (icon != NULL); - - /* Only reveal the icon if it's still the keyboard focus or if - * it's still selected. Someone originally thought we should - * cancel this reveal if the user manages to sneak a direct - * scroll in before the timeout fires, but we later realized - * this wouldn't actually be an improvement - * (see bugzilla.eazel.com 612). - */ - if (icon == container->details->keyboard_focus - || icon->is_selected) { - reveal_icon (container, icon); - } - container->details->keyboard_icon_reveal_timer_id = 0; - - return FALSE; -} - -static void -unschedule_keyboard_icon_reveal (NautilusIconContainer *container) -{ - NautilusIconContainerDetails *details; - - details = container->details; - - if (details->keyboard_icon_reveal_timer_id != 0) { - gtk_timeout_remove (details->keyboard_icon_reveal_timer_id); - } -} - -static void -schedule_keyboard_icon_reveal (NautilusIconContainer *container, - NautilusIcon *icon) -{ - NautilusIconContainerDetails *details; - - details = container->details; - - unschedule_keyboard_icon_reveal (container); - - details->keyboard_icon_to_reveal = icon; - details->keyboard_icon_reveal_timer_id - = gtk_timeout_add (KEYBOARD_ICON_REVEAL_TIMEOUT, - keyboard_icon_reveal_timeout_callback, - container); -} - -static void -clear_keyboard_focus (NautilusIconContainer *container) -{ - if (container->details->keyboard_focus != NULL) { - gnome_canvas_item_set (GNOME_CANVAS_ITEM (container->details->keyboard_focus->item), - "highlighted_as_keyboard_focus", 0, - NULL); - } - - container->details->keyboard_focus = NULL; -} - -/* Set @icon as the icon currently selected for keyboard operations. */ -static void -set_keyboard_focus (NautilusIconContainer *container, - NautilusIcon *icon) -{ - g_assert (icon != NULL); - - if (icon == container->details->keyboard_focus) { - return; - } - - clear_keyboard_focus (container); - - container->details->keyboard_focus = icon; - - gnome_canvas_item_set (GNOME_CANVAS_ITEM (container->details->keyboard_focus->item), - "highlighted_as_keyboard_focus", 1, - NULL); -} - -static void -get_all_icon_bounds (NautilusIconContainer *container, - double *x1, double *y1, - double *x2, double *y2) -{ - /* FIXME bugzilla.eazel.com 2477: Do we have to do something about the rubberband - * here? Any other non-icon items? - */ - gnome_canvas_item_get_bounds - (GNOME_CANVAS (container)->root, - x1, y1, x2, y2); -} - -/* Don't preserve visible white space the next time the scroll region - * is recomputed when the container is not empty. */ -void -nautilus_icon_container_reset_scroll_region (NautilusIconContainer *container) -{ - container->details->reset_scroll_region_trigger = TRUE; -} - -void -nautilus_icon_container_update_scroll_region (NautilusIconContainer *container) -{ - double x1, y1, x2, y2; - GtkAdjustment *hadj, *vadj; - float step_increment; - GtkAllocation *allocation; - gboolean reset_scroll_region; - - if (nautilus_icon_container_get_is_fixed_size (container)) { - /* Set the scroll region to the size of the container allocation */ - allocation = >K_WIDGET (container)->allocation; - eel_gnome_canvas_set_scroll_region_left_justify - (GNOME_CANVAS (container), - (double) - container->details->left_margin, - (double) - container->details->top_margin, - (double) allocation->width - 1 - - container->details->left_margin - - container->details->right_margin, - (double) allocation->height - 1 - - container->details->top_margin - - container->details->bottom_margin); - return; - } - - get_all_icon_bounds (container, &x1, &y1, &x2, &y2); - - reset_scroll_region = container->details->reset_scroll_region_trigger - || nautilus_icon_container_is_empty (container) - || nautilus_icon_container_is_auto_layout (container); - - /* The trigger is only cleared when container is non-empty, so - * callers can reliably reset the scroll region when an item - * is added even if extraneous relayouts are called when the - * window is still empty. - */ - if (!nautilus_icon_container_is_empty (container)) { - container->details->reset_scroll_region_trigger = FALSE; - } - - if (reset_scroll_region) { - eel_gnome_canvas_set_scroll_region_left_justify - (GNOME_CANVAS (container), - x1 - CONTAINER_PAD_LEFT, - y1 - CONTAINER_PAD_TOP, - x2 + CONTAINER_PAD_RIGHT, - y2 + CONTAINER_PAD_BOTTOM); - } else { - eel_gnome_canvas_set_scroll_region_include_visible_area - (GNOME_CANVAS (container), - x1 - CONTAINER_PAD_LEFT, - y1 - CONTAINER_PAD_TOP, - x2 + CONTAINER_PAD_RIGHT, - y2 + CONTAINER_PAD_BOTTOM); - } - - hadj = gtk_layout_get_hadjustment (GTK_LAYOUT (container)); - vadj = gtk_layout_get_vadjustment (GTK_LAYOUT (container)); - - /* Scroll by 1/4 icon each time you click. */ - step_increment = nautilus_get_icon_size_for_zoom_level - (container->details->zoom_level) / 4; - if (hadj->step_increment != step_increment) { - hadj->step_increment = step_increment; - gtk_adjustment_changed (hadj); - } - if (vadj->step_increment != step_increment) { - vadj->step_increment = step_increment; - gtk_adjustment_changed (vadj); - } - - /* Now that we have a new scroll region, clamp the - * adjustments so we are within the valid scroll area. - */ - eel_gtk_adjustment_clamp_value (hadj); - eel_gtk_adjustment_clamp_value (vadj); -} - -static NautilusIconContainer *sort_hack_container; - -static int -compare_icons (gconstpointer a, gconstpointer b) -{ - const NautilusIcon *icon_a, *icon_b; - int result; - - icon_a = a; - icon_b = b; - - result = 0; - gtk_signal_emit (GTK_OBJECT (sort_hack_container), - signals[COMPARE_ICONS], - icon_a->data, - icon_b->data, - &result); - return result; -} - -static void -sort_icons (NautilusIconContainer *container, - GList **icons) -{ - sort_hack_container = container; - *icons = g_list_sort (*icons, compare_icons); -} - -static int -compare_icons_by_name (gconstpointer a, gconstpointer b) -{ - const NautilusIcon *icon_a, *icon_b; - int result; - - icon_a = a; - icon_b = b; - - result = 0; - gtk_signal_emit (GTK_OBJECT (sort_hack_container), - signals[COMPARE_ICONS_BY_NAME], - icon_a->data, - icon_b->data, - &result); - return result; -} - -static void -sort_icons_by_name (NautilusIconContainer *container, - GList **icons) -{ - sort_hack_container = container; - *icons = g_list_sort (*icons, compare_icons_by_name); -} - - -static void -resort (NautilusIconContainer *container) -{ - sort_icons (container, &container->details->icons); -} - -/* Given an icon's bounds, compute the width of the space it should be - * placed in. - */ -static int -get_icon_space_width (NautilusIconContainer *container, const ArtDRect *bounds) -{ - double world_width; - - world_width = ICON_PAD_LEFT + (bounds->x1 - bounds->x0) + ICON_PAD_RIGHT; - if (container->details->tighter_layout) { - return world_width + 8; /* 8 pixels extra for fancy selection box */ - } - - if (world_width > STANDARD_ICON_GRID_WIDTH) - return world_width; - - return STANDARD_ICON_GRID_WIDTH; -} - -static void -lay_down_one_line (NautilusIconContainer *container, - GList *line_start, - GList *line_end, - double *y) -{ - GList *p; - double max_height_above, max_height_below; - NautilusIcon *icon; - ArtDRect bounds, icon_bounds; - double height_above, height_below, x, width; - - g_assert (NAUTILUS_IS_ICON_CONTAINER (container)); - g_assert (line_end == NULL || g_list_first (line_start) == g_list_first (line_end)); - g_assert (y != NULL); - - /* Compute the total height above and below the baseline. */ - max_height_above = 0; - max_height_below = 0; - for (p = line_start; p != line_end; p = p->next) { - icon = p->data; - - bounds = eel_gnome_canvas_item_get_world_bounds - (GNOME_CANVAS_ITEM (icon->item)); - icon_bounds = nautilus_icon_canvas_item_get_icon_rectangle (icon->item); - height_above = icon_bounds.y1 - bounds.y0; - height_below = bounds.y1 - icon_bounds.y1; - - if (height_above > max_height_above) { - max_height_above = height_above; - } - if (height_below > max_height_below) { - max_height_below = height_below; - } - } - - /* Advance to the baseline. */ - *y += ICON_PAD_TOP + max_height_above; - - /* Lay out the icons along the baseline. */ - x = 0; - for (p = line_start; p != line_end; p = p->next) { - icon = p->data; - - bounds = eel_gnome_canvas_item_get_world_bounds - (GNOME_CANVAS_ITEM (icon->item)); - icon_bounds = nautilus_icon_canvas_item_get_icon_rectangle (icon->item); - width = get_icon_space_width (container, &bounds); - - icon_set_position - (icon, - x + (width - (icon_bounds.x1 - icon_bounds.x0)) / 2, - *y - (icon_bounds.y1 - icon_bounds.y0)); - - x += width; - } - - /* Advance to next line. */ - *y += max_height_below + ICON_PAD_BOTTOM; -} - - -static void -lay_down_icons_horizontal (NautilusIconContainer *container, - GList *icons, - double start_y) -{ - GList *p, *line_start; - NautilusIcon *icon; - ArtDRect bounds; - double canvas_width, line_width, space_width, y; - - /* Lay out icons a line at a time. */ - canvas_width = (GTK_WIDGET (container)->allocation.width - - container->details->left_margin - - container->details->right_margin) - / GNOME_CANVAS (container)->pixels_per_unit; - line_width = 0; - line_start = icons; - y = start_y; - for (p = icons; p != NULL; p = p->next) { - icon = p->data; - - /* Get the width of the icon. */ - bounds = eel_gnome_canvas_item_get_world_bounds - (GNOME_CANVAS_ITEM (icon->item)); - space_width = get_icon_space_width (container, &bounds); - - /* If this icon doesn't fit, it's time to lay out the line that's queued up. */ - - /* FIXME: why don't we want to guarantee a small white space to the right of - * the last column just like we guarantee a small white space to the left of - * the first column? - */ - if (line_start != p && line_width + space_width - ICON_PAD_RIGHT > canvas_width) { - lay_down_one_line (container, line_start, p, &y); - line_width = 0; - line_start = p; - } - - /* Add this icon. */ - line_width += space_width; - } - - /* Lay down that last line of icons. */ - if (line_start != NULL) { - lay_down_one_line (container, line_start, NULL, &y); - } -} - -/* Search for available space at location */ -static gboolean -find_open_grid_space (NautilusIcon *icon, int **icon_grid, int num_rows, - int num_columns, int row, int column) -{ - int row_index, column_index; - int x1, x2, y1, y2; - double width, height; - int qwidth, qheight; - - /* Get icon dimensions */ - icon_get_bounding_box (icon, &x1, &y1, &x2, &y2); - width = x2 - x1; - height = y2 - y1; - - /* Convert to grid coordinates */ - qwidth = ceil (width / CELL_SIZE); - qheight = ceil (height / CELL_SIZE); - - if (row + qwidth > num_rows) { - qwidth = num_rows; - } else { - qwidth += row; - } - if (column + qheight > num_columns) { - qheight = num_columns; - } else { - qheight += column; - } - - for (row_index = row; row_index < qwidth; row_index++) { - for (column_index = column; column_index < qheight; column_index++) { - if (icon_grid [row_index] [column_index] == 1) { - return FALSE; - } - } - } - return TRUE; -} - - -static void -get_best_empty_grid_location (NautilusIcon *icon, int **icon_grid, int num_rows, - int num_columns, int *x, int *y) -{ - gboolean found_space; - int row, column; - - g_assert (icon_grid != NULL); - g_assert (x != NULL); - g_assert (y != NULL); - - found_space = FALSE; - - /* Set up default fallback position */ - *x = num_columns * CELL_SIZE; - *y = num_rows * CELL_SIZE; - - /* Find best empty location */ - for (row = 0; row < num_rows; row++) { - for (column = 0; column < num_columns; column++) { - found_space = find_open_grid_space (icon, icon_grid, num_rows, - num_columns, row, column); - if (found_space) { - *x = row * CELL_SIZE; - *y = column * CELL_SIZE; - - /* Correct for padding */ - if (*x < DESKTOP_PAD_HORIZONTAL) { - *x = DESKTOP_PAD_HORIZONTAL; - } - if (*y < DESKTOP_PAD_VERTICAL) { - *y = DESKTOP_PAD_VERTICAL; - } - return; - } - } - } -} - -static void -mark_icon_location_in_grid (NautilusIcon *icon, int **icon_grid, int num_rows, int num_columns) -{ - int x1, x2, y1, y2; - double width, height; - int qx, qy, qwidth, qheight, qy_index; - int grid_width, grid_height; - - icon_get_bounding_box (icon, &x1, &y1, &x2, &y2); - width = x2 - x1; - height = y2 - y1; - - /* Convert x and y to our quantized grid value */ - qx = icon->x / CELL_SIZE; - qy = icon->y / CELL_SIZE; - qwidth = ceil (width / CELL_SIZE); - qheight = ceil (height / CELL_SIZE); - - /* Check and correct for edge conditions */ - grid_width = num_rows; - grid_height = num_columns; - - if ((qx + qwidth) > grid_width) { - qwidth = grid_width; - } else { - qwidth = qx + qwidth; - } - if ((qy + qheight) > grid_height) { - qheight = grid_height; - } else { - qheight = qy + qheight; - } - - /* Mark location */ - for (; qx < qwidth; qx++) { - for (qy_index = qy; qy_index < qheight; qy_index++) { - icon_grid [qx] [qy_index] = 1; - } - } -} - -static void -mark_icon_locations_in_grid (GList *icon_list, int **icon_grid, int num_rows, int num_columns) -{ - GList *p; - NautilusIcon *icon; - - /* Mark filled grid locations */ - for (p = icon_list; p != NULL; p = p->next) { - icon = p->data; - mark_icon_location_in_grid (icon, icon_grid, num_rows, num_columns); - } -} - -static void -lay_down_icons_tblr (NautilusIconContainer *container, GList *icons) -{ - GList *p, *placed_icons, *unplaced_icons; - int index, total, new_length, placed; - NautilusIcon *icon; - int width, height, max_width, icon_width, icon_height; - int x, y, x1, x2, y1, y2; - int *grid_memory; - int **icon_grid; - int num_rows, num_columns; - int row, column; - - /* Get container dimensions */ - width = GTK_WIDGET (container)->allocation.width - - container->details->left_margin - - container->details->right_margin; - height = GTK_WIDGET (container)->allocation.height - - container->details->top_margin - - container->details->bottom_margin; - - /* Determine which icons have and have not been placed */ - placed_icons = NULL; - unplaced_icons = NULL; - - total = g_list_length (container->details->icons); - new_length = g_list_length (icons); - placed = total - new_length; - if (placed > 0) { - /* Add only placed icons in list */ - for (p = container->details->icons; p != NULL; p = p->next) { - icon = p->data; - if (icon_is_positioned (icon)) { - placed_icons = g_list_append (placed_icons, icon); - } else { - icon->x = 0; - icon->y = 0; - unplaced_icons = g_list_append (unplaced_icons, icon); - } - } - - /* Allocate grid array */ - num_rows = width / CELL_SIZE; - num_columns = height / CELL_SIZE; - - /* Allocate array memory */ - grid_memory = malloc (num_rows * num_columns * sizeof (int *)); - g_assert (grid_memory); - - /* Allocate room for the pointers to the rows */ - icon_grid = malloc (num_rows * sizeof (int)); - g_assert (icon_grid); - - /* Point to array pointers */ - for (index = 0; index < num_rows; index++) { - icon_grid[index] = grid_memory + (index * num_columns); - } - - /* Set all grid values to unfilled */ - for (row = 0; row < num_rows; row++) { - for (column = 0; column < num_columns; column++) { - icon_grid [row] [column] = 0; - } - } - - /* Mark filled grid locations */ - mark_icon_locations_in_grid (placed_icons, icon_grid, num_rows, num_columns); - - /* Place unplaced icons in the best locations */ - for (p = unplaced_icons; p != NULL; p = p->next) { - icon = p->data; - get_best_empty_grid_location (icon, icon_grid, num_rows, num_columns, - &x, &y); - icon_set_position (icon, x, y); - /* Add newly placed icon to grid */ - mark_icon_location_in_grid (icon, icon_grid, num_rows, num_columns); - } - - /* Clean up */ - free (icon_grid); - free (grid_memory); - g_list_free (placed_icons); - g_list_free (unplaced_icons); - } else { - /* There are no placed icons. Just lay them down using our rules */ - x = DESKTOP_PAD_HORIZONTAL; - y = DESKTOP_PAD_VERTICAL; - max_width = 0; - - for (p = icons; p != NULL; p = p->next) { - icon = p->data; - icon_get_bounding_box (icon, &x1, &y1, &x2, &y2); - icon_set_position (icon, x, y); - - icon_width = x2 - x1; - icon_height = y2 - y1; - y += icon_height + 10; - - /* Check for increase in column width */ - if (max_width < icon_width) { - max_width = icon_width; - } - - /* Check and see if we need to move to a new column */ - if (y > height - icon_height) { - x += max_width + DESKTOP_PAD_VERTICAL; - y = DESKTOP_PAD_VERTICAL; - } - } - } - - /* These modes are special. We freeze all of our positions - * after we do the layout. - */ - /* FIXME bugzilla.eazel.com 2478: - * This should not be tied to the direction of layout. - * It should be a separate switch. - */ - nautilus_icon_container_freeze_icon_positions (container); -} - - -static void -lay_down_icons (NautilusIconContainer *container, GList *icons, double start_y) -{ - switch (container->details->layout_mode) - { - case NAUTILUS_ICON_LAYOUT_L_R_T_B: - lay_down_icons_horizontal (container, icons, start_y); - break; - - case NAUTILUS_ICON_LAYOUT_T_B_L_R: - case NAUTILUS_ICON_LAYOUT_T_B_R_L: - /* FIXME bugzilla.eazel.com 2479: - * Need to handle T_B_R_L differently. */ - lay_down_icons_tblr (container, icons); - break; - - default: - g_assert_not_reached (); - } -} - -static void -redo_layout_internal (NautilusIconContainer *container) -{ - finish_adding_new_icons (container); - - /* Don't do any re-laying-out during stretching. Later we - * might add smart logic that does this and leaves room for - * the stretched icon, but if we do it we want it to be fast - * and only re-lay-out when it's really needed. - */ - if (container->details->auto_layout - && container->details->drag_state != DRAG_STATE_STRETCH) { - resort (container); - lay_down_icons (container, container->details->icons, 0); - } - - nautilus_icon_container_update_scroll_region (container); - - process_pending_icon_to_reveal (container); - process_pending_icon_to_rename (container); -} - -static gboolean -redo_layout_callback (gpointer callback_data) -{ - NautilusIconContainer *container; - - container = NAUTILUS_ICON_CONTAINER (callback_data); - redo_layout_internal (container); - container->details->idle_id = 0; - - return FALSE; -} - -static void -unschedule_redo_layout (NautilusIconContainer *container) -{ - if (container->details->idle_id != 0) { - gtk_idle_remove (container->details->idle_id); - container->details->idle_id = 0; - } -} - -static void -schedule_redo_layout (NautilusIconContainer *container) -{ - if (container->details->idle_id == 0 - && container->details->has_been_allocated) { - container->details->idle_id = gtk_idle_add - (redo_layout_callback, container); - } -} - -static void -redo_layout (NautilusIconContainer *container) -{ - unschedule_redo_layout (container); - redo_layout_internal (container); -} - -static void -reload_icon_positions (NautilusIconContainer *container) -{ - GList *p, *no_position_icons; - NautilusIcon *icon; - gboolean have_stored_position; - NautilusIconPosition position; - ArtDRect bounds; - double bottom; - - g_assert (!container->details->auto_layout); - - resort (container); - - no_position_icons = NULL; - - /* Place all the icons with positions. */ - bottom = 0; - for (p = container->details->icons; p != NULL; p = p->next) { - icon = p->data; - - have_stored_position = FALSE; - gtk_signal_emit (GTK_OBJECT (container), - signals[GET_STORED_ICON_POSITION], - icon->data, - &position, - &have_stored_position); - if (have_stored_position) { - icon_set_position (icon, position.x, position.y); - bounds = eel_gnome_canvas_item_get_world_bounds - (GNOME_CANVAS_ITEM (icon->item)); - if (bounds.y1 > bottom) { - bottom = bounds.y1; - } - } else { - no_position_icons = g_list_prepend (no_position_icons, icon); - } - } - no_position_icons = g_list_reverse (no_position_icons); - - /* Place all the other icons. */ - lay_down_icons (container, no_position_icons, bottom + ICON_PAD_BOTTOM); - g_list_free (no_position_icons); -} - -/* Container-level icon handling functions. */ - -static gboolean -button_event_modifies_selection (GdkEventButton *event) -{ - return (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK)) != 0; -} - -/* invalidate the cached label sizes for all the icons */ -static void -invalidate_label_sizes (NautilusIconContainer *container) -{ - GList *p; - NautilusIcon *icon; - - for (p = container->details->icons; p != NULL; p = p->next) { - icon = p->data; - - nautilus_icon_canvas_item_invalidate_label_size (icon->item); - } -} - -static gboolean -select_one_unselect_others (NautilusIconContainer *container, - NautilusIcon *icon_to_select) -{ - gboolean selection_changed; - GList *p; - NautilusIcon *icon; - - selection_changed = FALSE; - - for (p = container->details->icons; p != NULL; p = p->next) { - icon = p->data; - - selection_changed |= icon_set_selected - (container, icon, icon == icon_to_select); - } - - return selection_changed; -} - -static gboolean -unselect_all (NautilusIconContainer *container) -{ - return select_one_unselect_others (container, NULL); -} - -void -nautilus_icon_container_move_icon (NautilusIconContainer *container, - NautilusIcon *icon, - int x, int y, - double scale_x, double scale_y, - gboolean raise, - gboolean update_position) -{ - NautilusIconContainerDetails *details; - gboolean emit_signal; - NautilusIconPosition position; - - details = container->details; - - emit_signal = FALSE; - - if (icon == get_icon_being_renamed (container)) { - end_renaming_mode (container, TRUE); - } - - if (!details->auto_layout) { - if (x != icon->x || y != icon->y) { - icon_set_position (icon, x, y); - emit_signal = update_position; - } - } - - if (scale_x != icon->scale_x || scale_y != icon->scale_y) { - icon->scale_x = scale_x; - icon->scale_y = scale_y; - nautilus_icon_container_update_icon (container, icon); - if (update_position) { - redo_layout (container); - emit_signal = TRUE; - } - - } - - if (emit_signal) { - position.x = icon->x; - position.y = icon->y; - position.scale_x = scale_x; - position.scale_y = scale_y; - gtk_signal_emit (GTK_OBJECT (container), - signals[ICON_POSITION_CHANGED], - icon->data, &position); - } - - if (raise) { - icon_raise (icon); - } - - /* FIXME bugzilla.eazel.com 2474: - * Handling of the scroll region is inconsistent here. In - * the scale-changing case, redo_layout is called, which updates the - * scroll region appropriately. In other cases, it's up to the - * caller to make sure the scroll region is updated. This could - * lead to hard-to-track-down bugs. - */ -} - -/* Implementation of rubberband selection. */ -static void -rubberband_select (NautilusIconContainer *container, - const ArtDRect *previous_rect, - const ArtDRect *current_rect) -{ - GList *p; - gboolean selection_changed, is_in, canvas_rect_calculated; - NautilusIcon *icon; - ArtIRect canvas_rect; - - selection_changed = FALSE; - canvas_rect_calculated = FALSE; - - for (p = container->details->icons; p != NULL; p = p->next) { - icon = p->data; - - if (!canvas_rect_calculated) { - /* Only do this calculation once, since all the canvas items - * we are interating are in the same coordinate space - */ - canvas_rect = eel_gnome_canvas_world_to_canvas_rectangle - (GNOME_CANVAS_ITEM (icon->item)->canvas, *current_rect); - canvas_rect_calculated = TRUE; - } - - is_in = nautilus_icon_canvas_item_hit_test_rectangle (icon->item, canvas_rect); - - g_assert (icon->was_selected_before_rubberband == FALSE - || icon->was_selected_before_rubberband == TRUE); - selection_changed |= icon_set_selected - (container, icon, - is_in ^ icon->was_selected_before_rubberband); - } - - if (selection_changed) { - gtk_signal_emit (GTK_OBJECT (container), - signals[SELECTION_CHANGED]); - } -} - -static int -rubberband_timeout_callback (gpointer data) -{ - NautilusIconContainer *container; - GtkWidget *widget; - NautilusIconRubberbandInfo *band_info; - int x, y; - double x1, y1, x2, y2; - double world_x, world_y; - int x_scroll, y_scroll; - ArtDRect selection_rect; - - widget = GTK_WIDGET (data); - container = NAUTILUS_ICON_CONTAINER (data); - band_info = &container->details->rubberband_info; - - g_assert (band_info->timer_id != 0); - g_assert (GNOME_IS_CANVAS_RECT (band_info->selection_rectangle)); - - gdk_window_get_pointer (widget->window, &x, &y, NULL); - - if (x < 0) { - x_scroll = x; - x = 0; - } else if (x >= widget->allocation.width) { - x_scroll = x - widget->allocation.width + 1; - x = widget->allocation.width - 1; - } else { - x_scroll = 0; - } - - if (y < 0) { - y_scroll = y; - y = 0; - } else if (y >= widget->allocation.height) { - y_scroll = y - widget->allocation.height + 1; - y = widget->allocation.height - 1; - } else { - y_scroll = 0; - } - - if (y_scroll == 0 && x_scroll == 0 - && (int) band_info->prev_x == x && (int) band_info->prev_y == y) { - return TRUE; - } - - nautilus_icon_container_scroll (container, x_scroll, y_scroll); - - gnome_canvas_window_to_world (GNOME_CANVAS (container), - x, y, &world_x, &world_y); - - if (world_x < band_info->start_x) { - x1 = world_x; - x2 = band_info->start_x; - } else { - x1 = band_info->start_x; - x2 = world_x; - } - - if (world_y < band_info->start_y) { - y1 = world_y; - y2 = band_info->start_y; - } else { - y1 = band_info->start_y; - y2 = world_y; - } - - /* Don't let the area of the selection rectangle be empty. - * Aside from the fact that it would be funny when the rectangle disappears, - * this also works around a crash in libart that happens sometimes when a - * zero height rectangle is passed. - */ - x2 = MAX (x1 + 1, x2); - y2 = MAX (y1 + 1, y2); - - gnome_canvas_item_set - (band_info->selection_rectangle, - "x1", x1, "y1", y1, - "x2", x2, "y2", y2, - NULL); - - selection_rect.x0 = x1; - selection_rect.y0 = y1; - selection_rect.x1 = x2; - selection_rect.y1 = y2; - - rubberband_select (container, - &band_info->prev_rect, - &selection_rect); - - gnome_canvas_item_raise_to_top (band_info->selection_rectangle); - - - band_info->prev_x = x; - band_info->prev_y = y; - - band_info->prev_rect = selection_rect; - - return TRUE; -} - -static void -start_rubberbanding (NautilusIconContainer *container, - GdkEventButton *event) -{ - NautilusIconContainerDetails *details; - NautilusIconRubberbandInfo *band_info; - uint fill_color, outline_color; - char *fill_color_str; - GList *p; - - details = container->details; - band_info = &details->rubberband_info; - - gtk_signal_emit (GTK_OBJECT (container), - signals[BAND_SELECT_STARTED]); - - for (p = details->icons; p != NULL; p = p->next) { - NautilusIcon *icon; - - icon = p->data; - icon->was_selected_before_rubberband = icon->is_selected; - } - - gnome_canvas_window_to_world - (GNOME_CANVAS (container), - event->x, event->y, - &band_info->start_x, &band_info->start_y); - - /* FIXME: The code to extract colors from the theme should be in FMDirectoryView, not here. - * The NautilusIconContainer class should simply provide calls to set the colors. - */ - if (GNOME_CANVAS(container)->aa) { - /* FIXME: Should use some standard format, not just a 32-bit integer. */ - fill_color_str = nautilus_theme_get_theme_data ("directory", "selection_box_color_rgba"); - if (fill_color_str == NULL) { - fill_color = 0x77BBDD40; - } else { - fill_color = strtoul (fill_color_str, NULL, 0); - /* FIXME: Need error handling here. */ - g_free (fill_color_str); - } - - outline_color = fill_color | 255; - - band_info->selection_rectangle = gnome_canvas_item_new - (gnome_canvas_root - (GNOME_CANVAS (container)), - eel_canvas_rect_get_type (), - "x1", band_info->start_x, - "y1", band_info->start_y, - "x2", band_info->start_x, - "y2", band_info->start_y, - "fill_color_rgba", fill_color, - "outline_color_rgba", outline_color, - "width_pixels", 1, - NULL); - - } else { - fill_color_str = nautilus_theme_get_theme_data ("directory", "selection_box_color"); - if (fill_color_str == NULL) { - fill_color_str = g_strdup ("rgb:7777/BBBB/DDDD"); - } - - band_info->selection_rectangle = gnome_canvas_item_new - (gnome_canvas_root - (GNOME_CANVAS (container)), - eel_canvas_rect_get_type (), - "x1", band_info->start_x, - "y1", band_info->start_y, - "x2", band_info->start_x, - "y2", band_info->start_y, - "fill_color", fill_color_str, - "fill_stipple", stipple, - "outline_color", fill_color_str, - "width_pixels", 1, - NULL); - g_free (fill_color_str); - } - - band_info->prev_x = event->x; - band_info->prev_y = event->y; - - band_info->active = TRUE; - - if (band_info->timer_id == 0) { - band_info->timer_id = gtk_timeout_add - (RUBBERBAND_TIMEOUT_INTERVAL, - rubberband_timeout_callback, - container); - } - - gnome_canvas_item_grab (band_info->selection_rectangle, - (GDK_POINTER_MOTION_MASK - | GDK_BUTTON_RELEASE_MASK), - NULL, event->time); -} - -static void -stop_rubberbanding (NautilusIconContainer *container, - GdkEventButton *event) -{ - NautilusIconRubberbandInfo *band_info; - - band_info = &container->details->rubberband_info; - - g_assert (band_info->timer_id != 0); - gtk_timeout_remove (band_info->timer_id); - band_info->timer_id = 0; - - band_info->active = FALSE; - - /* Destroy this canvas item; the parent will unref it. */ - gnome_canvas_item_ungrab (band_info->selection_rectangle, event->time); - gtk_object_destroy (GTK_OBJECT (band_info->selection_rectangle)); - band_info->selection_rectangle = NULL; - - - gtk_signal_emit (GTK_OBJECT (container), - signals[BAND_SELECT_ENDED]); -} - -/* Keyboard navigation. */ - -typedef gboolean (* IsBetterIconFunction) (NautilusIconContainer *container, - NautilusIcon *start_icon, - NautilusIcon *best_so_far, - NautilusIcon *candidate, - void *data); - -static NautilusIcon * -find_best_icon (NautilusIconContainer *container, - NautilusIcon *start_icon, - IsBetterIconFunction function, - void *data) -{ - GList *p; - NautilusIcon *best, *candidate; - - best = NULL; - for (p = container->details->icons; p != NULL; p = p->next) { - candidate = p->data; - - if (candidate != start_icon) { - if ((* function) (container, start_icon, best, candidate, data)) { - best = candidate; - } - } - } - return best; -} - -static NautilusIcon * -find_best_selected_icon (NautilusIconContainer *container, - NautilusIcon *start_icon, - IsBetterIconFunction function, - void *data) -{ - GList *p; - NautilusIcon *best, *candidate; - - best = NULL; - for (p = container->details->icons; p != NULL; p = p->next) { - candidate = p->data; - - if (candidate != start_icon && candidate->is_selected) { - if ((* function) (container, start_icon, best, candidate, data)) { - best = candidate; - } - } - } - return best; -} - -static int -compare_icons_by_uri (NautilusIconContainer *container, - NautilusIcon *icon_a, - NautilusIcon *icon_b) -{ - char *uri_a, *uri_b; - int result; - - g_assert (NAUTILUS_IS_ICON_CONTAINER (container)); - g_assert (icon_a != NULL); - g_assert (icon_b != NULL); - g_assert (icon_a != icon_b); - - uri_a = nautilus_icon_container_get_icon_uri (container, icon_a); - uri_b = nautilus_icon_container_get_icon_uri (container, icon_b); - result = strcmp (uri_a, uri_b); - g_assert (result != 0); - g_free (uri_a); - g_free (uri_b); - - return result; -} - -static int -compare_icons_horizontal_first (NautilusIconContainer *container, - NautilusIcon *icon_a, - NautilusIcon *icon_b) -{ - if (icon_a->x < icon_b->x) { - return -1; - } - if (icon_a->x > icon_b->x) { - return +1; - } - if (icon_a->y < icon_b->y) { - return -1; - } - if (icon_a->y > icon_b->y) { - return +1; - } - return compare_icons_by_uri (container, icon_a, icon_b); -} - -static int -compare_icons_vertical_first (NautilusIconContainer *container, - NautilusIcon *icon_a, - NautilusIcon *icon_b) -{ - if (icon_a->y < icon_b->y) { - return -1; - } - if (icon_a->y > icon_b->y) { - return +1; - } - if (icon_a->x < icon_b->x) { - return -1; - } - if (icon_a->x > icon_b->x) { - return +1; - } - return compare_icons_by_uri (container, icon_a, icon_b); -} - -static gboolean -leftmost_in_top_row (NautilusIconContainer *container, - NautilusIcon *start_icon, - NautilusIcon *best_so_far, - NautilusIcon *candidate, - void *data) -{ - if (best_so_far == NULL) { - return TRUE; - } - return compare_icons_vertical_first (container, best_so_far, candidate) > 0; -} - -static gboolean -rightmost_in_bottom_row (NautilusIconContainer *container, - NautilusIcon *start_icon, - NautilusIcon *best_so_far, - NautilusIcon *candidate, - void *data) -{ - if (best_so_far == NULL) { - return TRUE; - } - return compare_icons_vertical_first (container, best_so_far, candidate) < 0; -} - -static int -compare_with_start_row (NautilusIconContainer *container, - NautilusIcon *icon) -{ - ArtIRect bounds; - - bounds = eel_gnome_canvas_item_get_current_canvas_bounds (GNOME_CANVAS_ITEM (icon->item)); - if (container->details->arrow_key_start < bounds.y0) { - return -1; - } - if (container->details->arrow_key_start > bounds.y1) { - return +1; - } - return 0; -} - -static int -compare_with_start_column (NautilusIconContainer *container, - NautilusIcon *icon) -{ - ArtIRect bounds; - - bounds = eel_gnome_canvas_item_get_current_canvas_bounds (GNOME_CANVAS_ITEM (icon->item)); - if (container->details->arrow_key_start < bounds.x0) { - return -1; - } - if (container->details->arrow_key_start > bounds.x1) { - return +1; - } - return 0; -} - -static gboolean -same_row_right_side_leftmost (NautilusIconContainer *container, - NautilusIcon *start_icon, - NautilusIcon *best_so_far, - NautilusIcon *candidate, - void *data) -{ - /* Candidates not on the start row do not qualify. */ - if (compare_with_start_row (container, candidate) != 0) { - return FALSE; - } - - /* Candidates that are farther right lose out. */ - if (best_so_far != NULL) { - if (compare_icons_horizontal_first (container, - best_so_far, - candidate) < 0) { - return FALSE; - } - } - - /* Candidate to the left of the start do not qualify. */ - if (compare_icons_horizontal_first (container, - candidate, - start_icon) <= 0) { - return FALSE; - } - - return TRUE; -} - -static gboolean -same_row_left_side_rightmost (NautilusIconContainer *container, - NautilusIcon *start_icon, - NautilusIcon *best_so_far, - NautilusIcon *candidate, - void *data) -{ - /* Candidates not on the start row do not qualify. */ - if (compare_with_start_row (container, candidate) != 0) { - return FALSE; - } - - /* Candidates that are farther left lose out. */ - if (best_so_far != NULL) { - if (compare_icons_horizontal_first (container, - best_so_far, - candidate) > 0) { - return FALSE; - } - } - - /* Candidate to the right of the start do not qualify. */ - if (compare_icons_horizontal_first (container, - candidate, - start_icon) >= 0) { - return FALSE; - } - - return TRUE; -} - -static gboolean -same_column_above_lowest (NautilusIconContainer *container, - NautilusIcon *start_icon, - NautilusIcon *best_so_far, - NautilusIcon *candidate, - void *data) -{ - /* Candidates not on the start column do not qualify. */ - if (compare_with_start_column (container, candidate) != 0) { - return FALSE; - } - - /* Candidates that are higher lose out. */ - if (best_so_far != NULL) { - if (compare_icons_vertical_first (container, - best_so_far, - candidate) > 0) { - return FALSE; - } - } - - /* Candidates below the start do not qualify. */ - if (compare_icons_vertical_first (container, - candidate, - start_icon) >= 0) { - return FALSE; - } - - return TRUE; -} - -static gboolean -same_column_below_highest (NautilusIconContainer *container, - NautilusIcon *start_icon, - NautilusIcon *best_so_far, - NautilusIcon *candidate, - void *data) -{ - /* Candidates not on the start column do not qualify. */ - if (compare_with_start_column (container, candidate) != 0) { - return FALSE; - } - - /* Candidates that are lower lose out. */ - if (best_so_far != NULL) { - if (compare_icons_vertical_first (container, - best_so_far, - candidate) < 0) { - return FALSE; - } - } - - /* Candidate above the start do not qualify. */ - if (compare_icons_vertical_first (container, - candidate, - start_icon) <= 0) { - return FALSE; - } - - return TRUE; -} - -static void -keyboard_move_to (NautilusIconContainer *container, - NautilusIcon *icon, - GdkEventKey *event) -{ - if (icon == NULL) { - return; - } - - if ((event->state & GDK_MOD1_MASK) != 0) { - /* Move the keyboard focus. Use Alt modifier - * rather than Control to avoid Sawfish conflict. - */ - set_keyboard_focus (container, icon); - } else { - /* Select icons and get rid of the special keyboard focus. */ - clear_keyboard_focus (container); - if (select_one_unselect_others (container, icon)) { - gtk_signal_emit (GTK_OBJECT (container), - signals[SELECTION_CHANGED]); - } - } - schedule_keyboard_icon_reveal (container, icon); -} - -static void -keyboard_home (NautilusIconContainer *container, - GdkEventKey *event) -{ - /* Home selects the first icon. - * Control-Home sets the keyboard focus to the first icon. - */ - container->details->arrow_key_axis = AXIS_NONE; - keyboard_move_to (container, - find_best_icon (container, - NULL, - leftmost_in_top_row, - NULL), - event); -} - -static void -keyboard_end (NautilusIconContainer *container, - GdkEventKey *event) -{ - /* End selects the last icon. - * Control-End sets the keyboard focus to the last icon. - */ - container->details->arrow_key_axis = AXIS_NONE; - keyboard_move_to (container, - find_best_icon (container, - NULL, - rightmost_in_bottom_row, - NULL), - event); -} - -static void -record_arrow_key_start (NautilusIconContainer *container, - NautilusIcon *icon, - Axis arrow_key_axis) -{ - ArtDRect world_rect; - - if (container->details->arrow_key_axis == arrow_key_axis) { - return; - } - - world_rect = nautilus_icon_canvas_item_get_icon_rectangle (icon->item); - gnome_canvas_w2c - (GNOME_CANVAS (container), - (world_rect.x0 + world_rect.x1) / 2, - (world_rect.y0 + world_rect.y1) / 2, - arrow_key_axis == AXIS_VERTICAL - ? &container->details->arrow_key_start : NULL, - arrow_key_axis == AXIS_HORIZONTAL - ? &container->details->arrow_key_start : NULL); - container->details->arrow_key_axis = arrow_key_axis; -} - -static void -keyboard_arrow_key (NautilusIconContainer *container, - GdkEventKey *event, - Axis axis, - IsBetterIconFunction better_start, - IsBetterIconFunction empty_start, - IsBetterIconFunction better_destination) -{ - NautilusIcon *icon; - - /* Chose the icon to start with. - * If we have a keyboard focus, start with it. - * Otherwise, use the single selected icon. - * If there's multiple selection, use the icon farthest toward the end. - */ - icon = container->details->keyboard_focus; - if (icon == NULL) { - if (has_multiple_selection (container)) { - icon = find_best_selected_icon - (container, NULL, - better_start, NULL); - } else { - icon = get_first_selected_icon (container); - } - } - - /* If there's no icon, select the icon farthest toward the end. - * If there is an icon, select the next icon based on the arrow direction. - */ - if (icon == NULL) { - container->details->arrow_key_axis = AXIS_NONE; - icon = find_best_icon - (container, NULL, - empty_start, NULL); - } else { - record_arrow_key_start (container, icon, axis); - icon = find_best_icon - (container, icon, - better_destination, NULL); - } - - keyboard_move_to (container, icon, event); -} - -static void -keyboard_right (NautilusIconContainer *container, - GdkEventKey *event) -{ - /* Right selects the next icon in the same row. - * Control-Right sets the keyboard focus to the next icon in the same row. - */ - keyboard_arrow_key (container, - event, - AXIS_HORIZONTAL, - rightmost_in_bottom_row, - leftmost_in_top_row, - same_row_right_side_leftmost); -} - -static void -keyboard_left (NautilusIconContainer *container, - GdkEventKey *event) -{ - /* Left selects the next icon in the same row. - * Control-Left sets the keyboard focus to the next icon in the same row. - */ - keyboard_arrow_key (container, - event, - AXIS_HORIZONTAL, - leftmost_in_top_row, - rightmost_in_bottom_row, - same_row_left_side_rightmost); -} - -static void -keyboard_down (NautilusIconContainer *container, - GdkEventKey *event) -{ - /* Down selects the next icon in the same column. - * Control-Down sets the keyboard focus to the next icon in the same column. - */ - keyboard_arrow_key (container, - event, - AXIS_VERTICAL, - rightmost_in_bottom_row, - leftmost_in_top_row, - same_column_below_highest); -} - -static void -keyboard_up (NautilusIconContainer *container, - GdkEventKey *event) -{ - /* Up selects the next icon in the same column. - * Control-Up sets the keyboard focus to the next icon in the same column. - */ - keyboard_arrow_key (container, - event, - AXIS_VERTICAL, - leftmost_in_top_row, - rightmost_in_bottom_row, - same_column_above_lowest); -} - -static void -keyboard_space (NautilusIconContainer *container, - GdkEventKey *event) -{ - /* Alt-space toggles the selection state of the current icon. */ - if (container->details->keyboard_focus != NULL && - (event->state & GDK_MOD1_MASK) != 0) { - icon_toggle_selected (container, container->details->keyboard_focus); - gtk_signal_emit (GTK_OBJECT (container), signals[SELECTION_CHANGED]); - } -} - -/* look for the first icon that matches the longest part of a given - * search pattern - */ -typedef struct { - char *name; - int last_match_length; -} BestNameMatch; - -static gboolean -match_best_name (NautilusIconContainer *container, - NautilusIcon *start_icon, - NautilusIcon *best_so_far, - NautilusIcon *candidate, - void *data) -{ - BestNameMatch *match_state; - const char *name; - int match_length; - - match_state = (BestNameMatch *) data; - - name = nautilus_icon_canvas_item_get_editable_text (candidate->item); - - /* This can happen if a key event is handled really early while loading - * the icon container, before the items have all been updated once. - */ - if (name == NULL) { - return FALSE; - } - - for (match_length = 0; ; match_length++) { - if (name[match_length] == '\0' - || match_state->name[match_length] == '\0') { - break; - } - - /* Require the match pattern to already be lowercase. */ - g_assert (tolower ((guchar) match_state->name[match_length]) - == match_state->name[match_length]); - - if (tolower ((guchar) name[match_length]) != match_state->name[match_length]) { - break; - } - } - - if (match_length > match_state->last_match_length) { - /* This is the longest pattern match sofar, remember the - * length and return with a candidate. - */ - match_state->last_match_length = match_length; - return TRUE; - } - - return FALSE; -} - -static void -select_matching_name (NautilusIconContainer *container, - const char *match_name) -{ - int index; - NautilusIcon *icon; - BestNameMatch match_state; - - match_state.name = g_strdup (match_name); - match_state.last_match_length = 0; - - /* a little optimization for case-insensitive match - convert the - * pattern to lowercase ahead of time - */ - for (index = 0; ; index++) { - if (match_state.name[index] == '\0') - break; - match_state.name[index] = tolower ((guchar) match_state.name[index]); - } - - icon = find_best_icon (container, - NULL, - match_best_name, - &match_state); - if (icon == NULL) { - return; - } - - /* Select icons and get rid of the special keyboard focus. */ - clear_keyboard_focus (container); - if (select_one_unselect_others (container, icon)) { - gtk_signal_emit (GTK_OBJECT (container), - signals[SELECTION_CHANGED]); - } - schedule_keyboard_icon_reveal (container, icon); - - g_free (match_state.name); -} - -static GList * -build_icon_list_sorted_by_name (NautilusIconContainer *container) -{ - GList *result; - - if (container->details->icons == NULL) { - return NULL; - } - - result = eel_g_list_copy (container->details->icons); - sort_icons_by_name (container, &result); - - return result; -} - -static void -select_previous_or_next_name (NautilusIconContainer *container, - gboolean next, - GdkEventKey *event) -{ - NautilusIcon *icon; - GList *list; - const GList *item; - - item = NULL; - /* Chose the icon to start with. - * If we have a keyboard focus, start with it. - * Otherwise, use the single selected icon. - */ - icon = container->details->keyboard_focus; - if (icon == NULL) { - icon = get_first_selected_icon (container); - } - - list = build_icon_list_sorted_by_name (container); - - if (icon != NULL) { - /* must have at least @icon in the list */ - g_assert (list != NULL); - item = g_list_find (list, icon); - g_assert (item != NULL); - - item = next ? item->next : item->prev; - } else if (list != NULL) { - /* no selection yet, pick the first or last item to select */ - item = next ? g_list_first (list) : g_list_last (list); - } - - icon = (item != NULL) ? item->data : NULL; - - if (icon != NULL) { - keyboard_move_to (container, icon, event); - } - - g_list_free (list); -} - -/* GtkObject methods. */ - -static void -destroy (GtkObject *object) -{ - NautilusIconContainer *container; - guint i; - - container = NAUTILUS_ICON_CONTAINER (object); - - nautilus_icon_dnd_fini (container); - nautilus_icon_container_clear (container); - - unschedule_keyboard_icon_reveal (container); - - if (container->details->rubberband_info.timer_id != 0) { - gtk_timeout_remove (container->details->rubberband_info.timer_id); - } - if (container->details->rubberband_info.selection_rectangle != NULL) { - /* Destroy this canvas item; the parent will unref it. */ - gtk_object_destroy (GTK_OBJECT (container->details->rubberband_info.selection_rectangle)); - } - - if (container->details->idle_id != 0) { - gtk_idle_remove (container->details->idle_id); - } - - if (container->details->stretch_idle_id != 0) { - gtk_idle_remove (container->details->stretch_idle_id); - } - - for (i = 0; i < EEL_N_ELEMENTS (container->details->label_font); i++) { - if (container->details->label_font[i] != NULL) - gdk_font_unref (container->details->label_font[i]); - } - - if (container->details->smooth_label_font != NULL) { - gtk_object_unref (GTK_OBJECT (container->details->smooth_label_font)); - } - - if (container->details->highlight_frame != NULL) { - gdk_pixbuf_unref (container->details->highlight_frame); - } - - if (container->details->rename_widget != NULL) { - gtk_object_destroy (GTK_OBJECT (container->details->rename_widget)); - } - - /* FIXME: The code to extract colors from the theme should be in FMDirectoryView, not here. - * The NautilusIconContainer class should simply provide calls to set the colors. - */ - nautilus_preferences_remove_callback (NAUTILUS_PREFERENCES_THEME, - nautilus_icon_container_theme_changed, - container); - - nautilus_icon_container_flush_typeselect_state (container); - - g_free (container->details); - - EEL_CALL_PARENT (GTK_OBJECT_CLASS, destroy, (object)); -} - -/* GtkWidget methods. */ - -static void -size_request (GtkWidget *widget, - GtkRequisition *requisition) -{ - requisition->width = 1; - requisition->height = 1; -} - -static void -size_allocate (GtkWidget *widget, - GtkAllocation *allocation) -{ - NautilusIconContainer *container; - gboolean need_layout_redone; - - container = NAUTILUS_ICON_CONTAINER (widget); - - need_layout_redone = !container->details->has_been_allocated; - - /* FIXME bugzilla.eazel.com 7219: - * We shouldn't have to redo the layout when x, y, or height - * changes, only when width changes. However, just removing these - * tests causes a problem when you're vertically stretching a window - * taller than the size needed to display all contents (the whole - * batch of contents start moving down, centered in the extra space). - */ - if (allocation->x != widget->allocation.x - || allocation->width != widget->allocation.width - || allocation->y != widget->allocation.y - || allocation->height != widget->allocation.height) { - need_layout_redone = TRUE; - } - - EEL_CALL_PARENT (GTK_WIDGET_CLASS, size_allocate, (widget, allocation)); - - container->details->has_been_allocated = TRUE; - - if (need_layout_redone) { - redo_layout (NAUTILUS_ICON_CONTAINER (widget)); - } -} - -static void -realize (GtkWidget *widget) -{ - GtkStyle *style; - GtkWindow *window; - - EEL_CALL_PARENT (GTK_WIDGET_CLASS, realize, (widget)); - - style = gtk_style_copy (gtk_widget_get_style (widget)); - style->bg[GTK_STATE_NORMAL] = style->base[GTK_STATE_NORMAL]; - gtk_widget_set_style (widget, style); - - gdk_window_set_background - (GTK_LAYOUT (widget)->bin_window, - &widget->style->bg[GTK_STATE_NORMAL]); - - /* reduce flicker when scrolling by setting the back pixmap to NULL */ - gdk_window_set_back_pixmap (GTK_LAYOUT (widget)->bin_window, - NULL, FALSE); - - /* make us the focused widget */ - g_assert (GTK_IS_WINDOW (gtk_widget_get_toplevel (widget))); - window = GTK_WINDOW (gtk_widget_get_toplevel (widget)); - gtk_window_set_focus (window, widget); -} - -static void -unrealize (GtkWidget *widget) -{ - GtkWindow *window; - g_assert (GTK_IS_WINDOW (gtk_widget_get_toplevel (widget))); - window = GTK_WINDOW (gtk_widget_get_toplevel (widget)); - gtk_window_set_focus (window, NULL); - - EEL_CALL_PARENT (GTK_WIDGET_CLASS, unrealize, (widget)); -} - -static gboolean -button_press_event (GtkWidget *widget, - GdkEventButton *event) -{ - NautilusIconContainer *container; - gboolean selection_changed; - gboolean return_value; - gboolean clicked_on_icon; - gint64 current_time; - static gint64 last_click_time = 0; - static gint click_count = 0; - - /* Determine click count */ - current_time = eel_get_system_time (); - if (current_time - last_click_time < DOUBLE_CLICK_TIME) { - click_count++; - } else { - click_count = 0; - } - - /* Stash time for next compare */ - last_click_time = current_time; - - /* Ignore double click if we are in single click mode */ - if (click_policy_auto_value == NAUTILUS_CLICK_POLICY_SINGLE && click_count >= 2) { - return TRUE; - } - - container = NAUTILUS_ICON_CONTAINER (widget); - container->details->button_down_time = event->time; - - /* Forget about the old keyboard selection now that we've started mousing. */ - clear_keyboard_focus (container); - - /* Forget about where we began with the arrow keys now that we're mousing. */ - container->details->arrow_key_axis = AXIS_NONE; - - /* Forget the typeahead state. */ - nautilus_icon_container_flush_typeselect_state (container); - - /* Invoke the canvas event handler and see if an item picks up the event. */ - clicked_on_icon = EEL_CALL_PARENT_WITH_RETURN_VALUE - (GTK_WIDGET_CLASS, button_press_event, (widget, event)); - - /* Move focus to icon container, unless we're still renaming (to avoid exiting - * renaming mode) - */ - if (!GTK_WIDGET_HAS_FOCUS (widget) && !(is_renaming (container) || is_renaming_pending (container))) { - gtk_widget_grab_focus (widget); - } - - if (clicked_on_icon) { - return TRUE; - } - - - /* An item didn't take the press, so it's a background press. - * We ignore double clicks on the desktop for now. - */ - if (event->type == GDK_2BUTTON_PRESS || event->type == GDK_3BUTTON_PRESS) { - return TRUE; - } - - /* Button 1 does rubber banding. */ - if (event->button == RUBBERBAND_BUTTON) { - if (! button_event_modifies_selection (event)) { - selection_changed = unselect_all (container); - if (selection_changed) { - gtk_signal_emit (GTK_OBJECT (container), - signals[SELECTION_CHANGED]); - } - } - - start_rubberbanding (container, event); - return TRUE; - } - - /* Prevent multi-button weirdness such as bug 6181 */ - if (container->details->rubberband_info.active) { - return TRUE; - } - - /* Button 2 may be passed to the window manager. */ - if (event->button == MIDDLE_BUTTON) { - gtk_signal_emit (GTK_OBJECT (widget), signals[MIDDLE_CLICK], event); - return TRUE; - } - - /* Button 3 does a contextual menu. */ - if (event->button == CONTEXTUAL_MENU_BUTTON) { - end_renaming_mode (container, TRUE); - gtk_signal_emit (GTK_OBJECT (widget), signals[CONTEXT_CLICK_BACKGROUND], event); - return TRUE; - } - - /* Otherwise, we emit a button_press message. */ - gtk_signal_emit (GTK_OBJECT (widget), - signals[BUTTON_PRESS], event, - &return_value); - return return_value; -} - -static void -nautilus_icon_container_did_not_drag (NautilusIconContainer *container, - GdkEventButton *event) -{ - NautilusIconContainerDetails *details; - details = container->details; - - if (!button_event_modifies_selection (event) && !details->drag_icon->is_selected) { - gboolean selection_changed; - - selection_changed = select_one_unselect_others - (container, details->drag_icon); - - if (selection_changed) { - gtk_signal_emit (GTK_OBJECT (container), - signals[SELECTION_CHANGED]); - } - } - - if (details->drag_icon != NULL) { - /* If single-click mode, activate the selected icons, unless modifying - * the selection or pressing for a very long time. - */ - if (details->single_click_mode - && event->time - details->button_down_time < MAX_CLICK_TIME - && ! button_event_modifies_selection (event)) { - - /* It's a tricky UI issue whether this should activate - * just the clicked item (as if it were a link), or all - * the selected items (as if you were issuing an "activate - * selection" command). For now, we're trying the activate - * entire selection version to see how it feels. Note that - * NautilusList goes the other way because its "links" seem - * much more link-like. - */ - activate_selected_items (container); - } - } -} - -static void -clear_drag_state (NautilusIconContainer *container) -{ - container->details->drag_icon = NULL; - container->details->drag_state = DRAG_STATE_INITIAL; - if (container->details->context_menu_timeout_id != 0) { - gtk_timeout_remove (container->details->context_menu_timeout_id); - container->details->context_menu_timeout_id = 0; - } -} - -static gboolean -start_stretching (NautilusIconContainer *container) -{ - NautilusIconContainerDetails *details; - NautilusIcon *icon; - ArtPoint world_point; - GtkWidget *toplevel; - - details = container->details; - icon = details->stretch_icon; - - /* Check if we hit the stretch handles. */ - world_point.x = details->drag_x; - world_point.y = details->drag_y; - if (!nautilus_icon_canvas_item_hit_test_stretch_handles - (icon->item, world_point)) { - return FALSE; - } - - /* Set up the dragging. */ - details->drag_state = DRAG_STATE_STRETCH; - gnome_canvas_w2c (GNOME_CANVAS (container), - details->drag_x, - details->drag_y, - &details->stretch_start.pointer_x, - &details->stretch_start.pointer_y); - gnome_canvas_w2c (GNOME_CANVAS (container), - icon->x, icon->y, - &details->stretch_start.icon_x, - &details->stretch_start.icon_y); - icon_get_size (container, icon, - &details->stretch_start.icon_size, NULL); - - gnome_canvas_item_grab (GNOME_CANVAS_ITEM (icon->item), - (GDK_POINTER_MOTION_MASK - | GDK_BUTTON_RELEASE_MASK), - NULL, - GDK_CURRENT_TIME); - - /* Ensure the window itself is focused.. */ - toplevel = gtk_widget_get_toplevel (GTK_WIDGET (container)); - if (toplevel != NULL && GTK_WIDGET_REALIZED (toplevel)) { - eel_gdk_window_focus (toplevel->window, GDK_CURRENT_TIME); - } - - return TRUE; -} - -static gboolean -update_stretch_at_idle (NautilusIconContainer *container) -{ - NautilusIconContainerDetails *details; - NautilusIcon *icon; - double world_x, world_y; - StretchState stretch_state; - - details = container->details; - icon = details->stretch_icon; - - if (icon == NULL) { - container->details->stretch_idle_id = 0; - return FALSE; - } - - gnome_canvas_window_to_world (GNOME_CANVAS (container), - details->window_x, details->window_y, - &world_x, &world_y); - gnome_canvas_w2c (GNOME_CANVAS (container), - world_x, world_y, - &stretch_state.pointer_x, &stretch_state.pointer_y); - - compute_stretch (&details->stretch_start, - &stretch_state); - - gnome_canvas_c2w (GNOME_CANVAS (container), - stretch_state.icon_x, stretch_state.icon_y, - &world_x, &world_y); - - icon_set_position (icon, world_x, world_y); - icon_set_size (container, icon, stretch_state.icon_size, FALSE); - - container->details->stretch_idle_id = 0; - - return FALSE; -} - -static void -continue_stretching (NautilusIconContainer *container, - int window_x, int window_y) -{ - - g_return_if_fail (NAUTILUS_IS_ICON_CONTAINER (container)); - - container->details->window_x = window_x; - container->details->window_y = window_y; - - if (container->details->stretch_idle_id == 0) { - container->details->stretch_idle_id = gtk_idle_add ((GtkFunction) update_stretch_at_idle, container); - } -} - -static void -ungrab_stretch_icon (NautilusIconContainer *container) -{ - gnome_canvas_item_ungrab (GNOME_CANVAS_ITEM (container->details->stretch_icon->item), - GDK_CURRENT_TIME); -} - -static void -end_stretching (NautilusIconContainer *container, - int window_x, int window_y) -{ - NautilusIconPosition position; - NautilusIcon *icon; - - continue_stretching (container, window_x, window_y); - ungrab_stretch_icon (container); - - /* now that we're done stretching, update the icon's position */ - icon = container->details->drag_icon; - position.x = icon->x; - position.y = icon->y; - position.scale_x = icon->scale_x; - position.scale_y = icon->scale_y; - gtk_signal_emit (GTK_OBJECT (container), - signals[ICON_POSITION_CHANGED], - icon->data, &position); - - clear_drag_state (container); - redo_layout (container); -} - -static void -undo_stretching (NautilusIconContainer *container) -{ - NautilusIcon *stretched_icon; - - stretched_icon = container->details->stretch_icon; - - if (stretched_icon == NULL) { - return; - } - - if (container->details->drag_state == DRAG_STATE_STRETCH) { - ungrab_stretch_icon (container); - clear_drag_state (container); - } - nautilus_icon_canvas_item_set_show_stretch_handles - (stretched_icon->item, FALSE); - - icon_set_position (stretched_icon, - container->details->stretch_initial_x, - container->details->stretch_initial_y); - icon_set_size (container, - stretched_icon, - container->details->stretch_initial_size, - TRUE); - - container->details->stretch_icon = NULL; - emit_stretch_ended (container, stretched_icon); - redo_layout (container); -} - -static gboolean -button_release_event (GtkWidget *widget, - GdkEventButton *event) -{ - NautilusIconContainer *container; - NautilusIconContainerDetails *details; - - container = NAUTILUS_ICON_CONTAINER (widget); - details = container->details; - - if (event->button == RUBBERBAND_BUTTON && details->rubberband_info.active) { - stop_rubberbanding (container, event); - return TRUE; - } - - if (event->button == details->drag_button) { - details->drag_button = 0; - - switch (details->drag_state) { - case DRAG_STATE_MOVE_COPY_OR_MENU: - if (!details->drag_started) { - /* Right click, drag did not start, - * show context menu. - */ - clear_drag_state (container); - gtk_signal_emit (GTK_OBJECT (container), - signals[CONTEXT_CLICK_SELECTION], - event); - break; - } - /* fall through */ - - case DRAG_STATE_MOVE_OR_COPY: - if (!details->drag_started) { - nautilus_icon_container_did_not_drag (container, event); - } else { - nautilus_icon_dnd_end_drag (container); - } - break; - case DRAG_STATE_STRETCH: - end_stretching (container, event->x, event->y); - break; - default: - break; - } - - clear_drag_state (container); - return TRUE; - } - - return EEL_CALL_PARENT_WITH_RETURN_VALUE - (GTK_WIDGET_CLASS, button_release_event, (widget, event)); -} - -static int -motion_notify_event (GtkWidget *widget, - GdkEventMotion *event) -{ - NautilusIconContainer *container; - NautilusIconContainerDetails *details; - double world_x, world_y; - - container = NAUTILUS_ICON_CONTAINER (widget); - details = container->details; - - if (details->drag_button != 0) { - switch (details->drag_state) { - case DRAG_STATE_MOVE_COPY_OR_MENU: - if (details->drag_started) { - break; - } - gtk_timeout_remove (details->context_menu_timeout_id); - /* fall through */ - - case DRAG_STATE_MOVE_OR_COPY: - if (details->drag_started) { - break; - } - - gnome_canvas_window_to_world - (GNOME_CANVAS (container), - event->x, event->y, - &world_x, &world_y); - - if (abs (details->drag_x - world_x) >= SNAP_RESISTANCE - || abs (details->drag_y - world_y) >= SNAP_RESISTANCE) { - details->drag_started = TRUE; - - end_renaming_mode (container, TRUE); - - /* KLUDGE ALERT: Poke the starting values into the motion - * structure so that dragging behaves as expected. - */ - event->x = details->drag_x; - event->y = details->drag_y; - - nautilus_icon_dnd_begin_drag (container, - details->drag_state == DRAG_STATE_MOVE_OR_COPY - ? (GDK_ACTION_MOVE - | GDK_ACTION_COPY - | GDK_ACTION_LINK - | GDK_ACTION_ASK) - : GDK_ACTION_ASK, - details->drag_button, - event); - details->drag_state = DRAG_STATE_MOVE_OR_COPY; - } - break; - case DRAG_STATE_STRETCH: - continue_stretching (container, event->x, event->y); - break; - default: - break; - } - } - - return EEL_CALL_PARENT_WITH_RETURN_VALUE - (GTK_WIDGET_CLASS, motion_notify_event, (widget, event)); -} - -void -nautilus_icon_container_flush_typeselect_state (NautilusIconContainer *container) -{ - if (container->details->type_select_state == NULL) { - return; - } - - g_free (container->details->type_select_state->type_select_pattern); - g_free (container->details->type_select_state); - container->details->type_select_state = NULL; -} - -static gboolean -handle_typeahead (NautilusIconContainer *container, const char *key_string) -{ - char *new_pattern; - gint64 now; - gint64 time_delta; - int key_string_length; - int index; - - g_assert (key_string != NULL); - g_assert (strlen (key_string) < 5); - - key_string_length = strlen (key_string); - - if (key_string_length == 0) { - /* can be an empty string if the modifier was held down, etc. */ - return FALSE; - } - - /* only handle if printable keys typed */ - for (index = 0; index < key_string_length; index++) { - if (!isprint ((guchar) key_string[index])) { - return FALSE; - } - } - - /* lazily allocate the typeahead state */ - if (container->details->type_select_state == NULL) { - container->details->type_select_state = g_new0 (TypeSelectState, 1); - } - - /* find out how long since last character was typed */ - now = eel_get_system_time (); - time_delta = now - container->details->type_select_state->last_typeselect_time; - if (time_delta < 0 || time_delta > NAUTILUS_TYPESELECT_FLUSH_DELAY) { - /* the typeselect state is too old, start with a fresh one */ - g_free (container->details->type_select_state->type_select_pattern); - container->details->type_select_state->type_select_pattern = NULL; - } - - if (container->details->type_select_state->type_select_pattern != NULL) { - new_pattern = g_strconcat - (container->details->type_select_state->type_select_pattern, - key_string, NULL); - g_free (container->details->type_select_state->type_select_pattern); - } else { - new_pattern = g_strdup (key_string); - } - - container->details->type_select_state->type_select_pattern = new_pattern; - container->details->type_select_state->last_typeselect_time = now; - - select_matching_name (container, new_pattern); - - return TRUE; -} - -static int -key_press_event (GtkWidget *widget, - GdkEventKey *event) -{ - NautilusIconContainer *container; - gboolean handled; - gboolean flush_typeahead; - - container = NAUTILUS_ICON_CONTAINER (widget); - handled = FALSE; - flush_typeahead = TRUE; - - if (is_renaming (container) || is_renaming_pending (container)) { - switch (event->keyval) { - case GDK_Return: - case GDK_KP_Enter: - end_renaming_mode (container, TRUE); - handled = TRUE; - break; - case GDK_Escape: - end_renaming_mode (container, FALSE); - handled = TRUE; - break; - default: - break; - } - } else { - switch (event->keyval) { - case GDK_Home: - keyboard_home (container, event); - handled = TRUE; - break; - case GDK_End: - keyboard_end (container, event); - handled = TRUE; - break; - case GDK_Left: - keyboard_left (container, event); - handled = TRUE; - break; - case GDK_Up: - keyboard_up (container, event); - handled = TRUE; - break; - case GDK_Right: - keyboard_right (container, event); - handled = TRUE; - break; - case GDK_Down: - keyboard_down (container, event); - handled = TRUE; - break; - case GDK_space: - keyboard_space (container, event); - handled = TRUE; - break; - case GDK_Tab: - case GDK_ISO_Left_Tab: - select_previous_or_next_name (container, - (event->state & GDK_SHIFT_MASK) == 0, event); - handled = TRUE; - break; - case GDK_Return: - case GDK_KP_Enter: - activate_selected_items (container); - handled = TRUE; - break; - case GDK_Escape: - undo_stretching (container); - handled = TRUE; - break; - default: - /* Don't use Control or Alt keys for type-selecting, because they - * might be used for menus. - */ - handled = (event->state & (GDK_CONTROL_MASK | GDK_MOD1_MASK)) == 0 && - handle_typeahead (container, event->string); - flush_typeahead = !handled; - break; - } - } - - if (flush_typeahead) { - /* any non-ascii key will force the typeahead state to be forgotten */ - nautilus_icon_container_flush_typeselect_state (container); - } - - if (!handled) { - handled = EEL_CALL_PARENT_WITH_RETURN_VALUE - (GTK_WIDGET_CLASS, key_press_event, (widget, event)); - } - - return handled; -} - -/* Initialization. */ - -static void -nautilus_icon_container_initialize_class (NautilusIconContainerClass *class) -{ - GtkObjectClass *object_class; - GtkWidgetClass *widget_class; - - /* NautilusIconContainer class. */ - - class->button_press = NULL; - - /* GtkObject class. */ - - object_class = GTK_OBJECT_CLASS (class); - object_class->destroy = destroy; - - /* Signals. */ - - signals[SELECTION_CHANGED] - = gtk_signal_new ("selection_changed", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (NautilusIconContainerClass, - selection_changed), - gtk_marshal_NONE__NONE, - GTK_TYPE_NONE, 0); - signals[BUTTON_PRESS] - = gtk_signal_new ("button_press", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (NautilusIconContainerClass, - button_press), - gtk_marshal_BOOL__POINTER, - GTK_TYPE_BOOL, 1, - GTK_TYPE_GDK_EVENT); - signals[ACTIVATE] - = gtk_signal_new ("activate", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (NautilusIconContainerClass, - activate), - gtk_marshal_NONE__POINTER, - GTK_TYPE_NONE, 1, - GTK_TYPE_POINTER); - signals[CONTEXT_CLICK_SELECTION] - = gtk_signal_new ("context_click_selection", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (NautilusIconContainerClass, - context_click_selection), - gtk_marshal_NONE__POINTER, - GTK_TYPE_NONE, 1, - GTK_TYPE_POINTER); - signals[CONTEXT_CLICK_BACKGROUND] - = gtk_signal_new ("context_click_background", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (NautilusIconContainerClass, - context_click_background), - gtk_marshal_NONE__POINTER, - GTK_TYPE_NONE, 1, - GTK_TYPE_POINTER); - signals[MIDDLE_CLICK] - = gtk_signal_new ("middle_click", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (NautilusIconContainerClass, - middle_click), - gtk_marshal_NONE__POINTER, - GTK_TYPE_NONE, 1, - GTK_TYPE_POINTER); - signals[ICON_POSITION_CHANGED] - = gtk_signal_new ("icon_position_changed", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (NautilusIconContainerClass, - icon_position_changed), - gtk_marshal_NONE__POINTER_POINTER, - GTK_TYPE_NONE, 2, - GTK_TYPE_POINTER, - GTK_TYPE_POINTER); - signals[ICON_TEXT_CHANGED] - = gtk_signal_new ("icon_text_changed", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (NautilusIconContainerClass, - icon_text_changed), - gtk_marshal_NONE__POINTER_POINTER, - GTK_TYPE_NONE, 2, - GTK_TYPE_POINTER, - GTK_TYPE_STRING); - signals[ICON_STRETCH_STARTED] - = gtk_signal_new ("icon_stretch_started", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (NautilusIconContainerClass, - icon_stretch_started), - gtk_marshal_NONE__POINTER, - GTK_TYPE_NONE, 1, - GTK_TYPE_POINTER); - signals[ICON_STRETCH_ENDED] - = gtk_signal_new ("icon_stretch_ended", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (NautilusIconContainerClass, - icon_stretch_ended), - gtk_marshal_NONE__POINTER, - GTK_TYPE_NONE, 1, - GTK_TYPE_POINTER); - signals[RENAMING_ICON] - = gtk_signal_new ("renaming_icon", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (NautilusIconContainerClass, - renaming_icon), - gtk_marshal_NONE__POINTER, - GTK_TYPE_NONE, 1, - GTK_TYPE_POINTER); - signals[GET_ICON_IMAGES] - = gtk_signal_new ("get_icon_images", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (NautilusIconContainerClass, - get_icon_images), - eel_gtk_marshal_POINTER__POINTER_STRING_POINTER, - GTK_TYPE_POINTER, 3, - GTK_TYPE_POINTER, - GTK_TYPE_STRING, - GTK_TYPE_POINTER); - signals[GET_ICON_TEXT] - = gtk_signal_new ("get_icon_text", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (NautilusIconContainerClass, - get_icon_text), - eel_gtk_marshal_NONE__POINTER_STRING_STRING, - GTK_TYPE_NONE, 3, - GTK_TYPE_POINTER, - GTK_TYPE_STRING, - GTK_TYPE_STRING); - signals[GET_ICON_URI] - = gtk_signal_new ("get_icon_uri", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (NautilusIconContainerClass, - get_icon_uri), - eel_gtk_marshal_STRING__POINTER, - GTK_TYPE_STRING, 1, - GTK_TYPE_POINTER); - signals[GET_ICON_DROP_TARGET_URI] - = gtk_signal_new ("get_icon_drop_target_uri", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (NautilusIconContainerClass, - get_icon_drop_target_uri), - eel_gtk_marshal_STRING__POINTER, - GTK_TYPE_STRING, 1, - GTK_TYPE_POINTER); - signals[COMPARE_ICONS] - = gtk_signal_new ("compare_icons", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (NautilusIconContainerClass, - compare_icons), - eel_gtk_marshal_INT__POINTER_POINTER, - GTK_TYPE_INT, 2, - GTK_TYPE_POINTER, - GTK_TYPE_POINTER); - signals[COMPARE_ICONS_BY_NAME] - = gtk_signal_new ("compare_icons_by_name", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (NautilusIconContainerClass, - compare_icons_by_name), - eel_gtk_marshal_INT__POINTER_POINTER, - GTK_TYPE_INT, 2, - GTK_TYPE_POINTER, - GTK_TYPE_POINTER); - signals[MOVE_COPY_ITEMS] - = gtk_signal_new ("move_copy_items", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (NautilusIconContainerClass, - move_copy_items), - eel_gtk_marshal_NONE__POINTER_POINTER_POINTER_INT_INT_INT, - GTK_TYPE_NONE, 6, - GTK_TYPE_POINTER, - GTK_TYPE_POINTER, - GTK_TYPE_POINTER, - GTK_TYPE_INT, - GTK_TYPE_INT, - GTK_TYPE_INT); - signals[HANDLE_URI_LIST] - = gtk_signal_new ("handle_uri_list", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (NautilusIconContainerClass, - handle_uri_list), - gtk_marshal_NONE__POINTER_INT_INT, - GTK_TYPE_NONE, 3, - GTK_TYPE_POINTER, - GTK_TYPE_INT, - GTK_TYPE_INT); - - signals[GET_CONTAINER_URI] - = gtk_signal_new ("get_container_uri", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (NautilusIconContainerClass, - get_container_uri), - eel_gtk_marshal_STRING__NONE, - GTK_TYPE_STRING, 0); - signals[CAN_ACCEPT_ITEM] - = gtk_signal_new ("can_accept_item", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (NautilusIconContainerClass, - can_accept_item), - eel_gtk_marshal_INT__POINTER_STRING, - GTK_TYPE_INT, 2, - GTK_TYPE_POINTER, - GTK_TYPE_STRING); - signals[GET_STORED_ICON_POSITION] - = gtk_signal_new ("get_stored_icon_position", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (NautilusIconContainerClass, - get_stored_icon_position), - eel_gtk_marshal_BOOL__POINTER_POINTER, - GTK_TYPE_BOOL, 2, - GTK_TYPE_POINTER, - GTK_TYPE_POINTER); - signals[LAYOUT_CHANGED] - = gtk_signal_new ("layout_changed", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (NautilusIconContainerClass, - layout_changed), - gtk_marshal_NONE__NONE, - GTK_TYPE_NONE, 0); - signals[PREVIEW] - = gtk_signal_new ("preview", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (NautilusIconContainerClass, - preview), - eel_gtk_marshal_INT__POINTER_INT, - GTK_TYPE_INT, 2, - GTK_TYPE_POINTER, - GTK_TYPE_BOOL); - signals[BAND_SELECT_STARTED] - = gtk_signal_new ("band_select_started", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (NautilusIconContainerClass, - band_select_started), - gtk_marshal_NONE__NONE, - GTK_TYPE_NONE, 0); - signals[BAND_SELECT_ENDED] - = gtk_signal_new ("band_select_ended", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (NautilusIconContainerClass, - band_select_ended), - gtk_marshal_NONE__NONE, - GTK_TYPE_NONE, 0); - - gtk_object_class_add_signals (object_class, signals, LAST_SIGNAL); - - /* GtkWidget class. */ - - widget_class = GTK_WIDGET_CLASS (class); - widget_class->size_request = size_request; - widget_class->size_allocate = size_allocate; - widget_class->realize = realize; - widget_class->unrealize = unrealize; - widget_class->button_press_event = button_press_event; - widget_class->button_release_event = button_release_event; - widget_class->motion_notify_event = motion_notify_event; - widget_class->key_press_event = key_press_event; - - /* Initialize the stipple bitmap. */ - - stipple = gdk_bitmap_create_from_data (NULL, stipple_bits, 2, 2); - - nautilus_preferences_add_auto_integer (NAUTILUS_PREFERENCES_CLICK_POLICY, - &click_policy_auto_value); -} - -static void -handle_focus_out_event (GtkWidget *widget, GdkEventFocus *event, gpointer user_data) -{ - /* End renaming and commit change. */ - end_renaming_mode (NAUTILUS_ICON_CONTAINER (widget), TRUE); -} - -static void -nautilus_icon_container_initialize (NautilusIconContainer *container) -{ - NautilusIconContainerDetails *details; - EelBackground *background; - - details = g_new0 (NautilusIconContainerDetails, 1); - - details->zoom_level = NAUTILUS_ZOOM_LEVEL_STANDARD; - - /* font table - this isn't exactly proportional, but it looks better than computed */ - /* FIXME bugzilla.eazel.com 5093: Font name is hard-coded here. */ - /* FIXME bugzilla.eazel.com 5101: Font size is hard-coded here. */ - - details->label_font[NAUTILUS_ZOOM_LEVEL_SMALLEST] = nautilus_font_factory_get_font_by_family ("helvetica", 8); - details->label_font[NAUTILUS_ZOOM_LEVEL_SMALLER] = nautilus_font_factory_get_font_by_family ("helvetica", 8); - details->label_font[NAUTILUS_ZOOM_LEVEL_SMALL] = nautilus_font_factory_get_font_by_family ("helvetica", 10); - details->label_font[NAUTILUS_ZOOM_LEVEL_STANDARD] = nautilus_font_factory_get_font_by_family ("helvetica", 12); - details->label_font[NAUTILUS_ZOOM_LEVEL_LARGE] = nautilus_font_factory_get_font_by_family ("helvetica", 14); - details->label_font[NAUTILUS_ZOOM_LEVEL_LARGER] = nautilus_font_factory_get_font_by_family ("helvetica", 18); - details->label_font[NAUTILUS_ZOOM_LEVEL_LARGEST] = nautilus_font_factory_get_font_by_family ("helvetica", 18); - - details->smooth_label_font = eel_scalable_font_get_default_font (); - - /* These are the default font sizes. The font sizes are configurable via - * nautilus_icon_container_set_font_size_table() - */ - details->font_size_table[NAUTILUS_ZOOM_LEVEL_SMALLEST] = 8; - details->font_size_table[NAUTILUS_ZOOM_LEVEL_SMALLER] = 8; - details->font_size_table[NAUTILUS_ZOOM_LEVEL_SMALL] = 10; - details->font_size_table[NAUTILUS_ZOOM_LEVEL_STANDARD] = 12; - details->font_size_table[NAUTILUS_ZOOM_LEVEL_LARGE] = 14; - details->font_size_table[NAUTILUS_ZOOM_LEVEL_LARGER] = 18; - details->font_size_table[NAUTILUS_ZOOM_LEVEL_LARGEST] = 18; - - container->details = details; - - /* Set up DnD. */ - nautilus_icon_dnd_init (container, stipple); - - /* Make sure that we find out if the icons change. */ - gtk_signal_connect_object_while_alive - (nautilus_icon_factory_get (), - "icons_changed", - nautilus_icon_container_request_update_all, - GTK_OBJECT (container)); - - /* when the background changes, we must set up the label text color */ - background = eel_get_widget_background (GTK_WIDGET (container)); - - gtk_signal_connect - (GTK_OBJECT(background), - "appearance_changed", - update_label_color, - GTK_OBJECT (container)); - - - gtk_signal_connect (GTK_OBJECT (container), "focus-out-event", handle_focus_out_event, NULL); - - /* FIXME: The code to extract colors from the theme should be in FMDirectoryView, not here. - * The NautilusIconContainer class should simply provide calls to set the colors. - */ - /* read in theme-dependent data */ - nautilus_icon_container_theme_changed (container); - nautilus_preferences_add_callback (NAUTILUS_PREFERENCES_THEME, nautilus_icon_container_theme_changed, container); -} - -typedef struct { - NautilusIconContainer *container; - GdkEventButton *event; -} ContextMenuParameters; - -static ContextMenuParameters * -context_menu_parameters_new (NautilusIconContainer *container, - GdkEventButton *event) -{ - ContextMenuParameters *parameters; - - parameters = g_new (ContextMenuParameters, 1); - parameters->container = container; - parameters->event = (GdkEventButton *)(gdk_event_copy ((GdkEvent *)event)); - - return parameters; -} - -static void -context_menu_parameters_free (ContextMenuParameters *parameters) -{ - gdk_event_free ((GdkEvent *)parameters->event); - g_free (parameters); -} - -static gboolean -show_context_menu_callback (void *cast_to_parameters) -{ - ContextMenuParameters *parameters; - - parameters = (ContextMenuParameters *)cast_to_parameters; - - g_assert (NAUTILUS_IS_ICON_CONTAINER (parameters->container)); - - if (parameters->container->details->drag_state == DRAG_STATE_MOVE_COPY_OR_MENU) { - clear_drag_state (parameters->container); - - /* Context menu applies to all selected items. The only - * odd case is if this click deselected the icon under - * the mouse, but at least the behavior is consistent. - */ - gtk_signal_emit (GTK_OBJECT (parameters->container), - signals[CONTEXT_CLICK_SELECTION], - parameters->event); - } - - context_menu_parameters_free (parameters); - - return TRUE; -} - -/* NautilusIcon event handling. */ - -/* Conceptually, pressing button 1 together with CTRL or SHIFT toggles - * selection of a single icon without affecting the other icons; - * without CTRL or SHIFT, it selects a single icon and un-selects all - * the other icons. But in this latter case, the de-selection should - * only happen when the button is released if the icon is already - * selected, because the user might select multiple icons and drag all - * of them by doing a simple click-drag. -*/ - -static gboolean -handle_icon_button_press (NautilusIconContainer *container, - NautilusIcon *icon, - GdkEventButton *event) -{ - NautilusIconContainerDetails *details; - - if (event->button != DRAG_BUTTON - && event->button != CONTEXTUAL_MENU_BUTTON) { - return TRUE; - } - - details = container->details; - - if (event->button == DRAG_BUTTON - || event->button == CONTEXTUAL_MENU_BUTTON) { - details->drag_button = event->button; - details->drag_icon = icon; - details->drag_x = event->x; - details->drag_y = event->y; - details->drag_state = event->button == DRAG_BUTTON - ? DRAG_STATE_MOVE_OR_COPY : DRAG_STATE_MOVE_COPY_OR_MENU; - details->drag_started = FALSE; - - /* Check to see if this is a click on the stretch handles. - * If so, it won't modify the selection. - */ - if (icon == container->details->stretch_icon) { - if (start_stretching (container)) { - return TRUE; - } - } - - if (event->button == CONTEXTUAL_MENU_BUTTON) { - /* after a timeout we will decide if this is a - * context menu click or a drag start. - */ - if (details->context_menu_timeout_id == 0) { - details->context_menu_timeout_id = gtk_timeout_add ( - CONTEXT_MENU_TIMEOUT_INTERVAL, - show_context_menu_callback, - context_menu_parameters_new (container, event)); - } - } - } - - /* Modify the selection as appropriate. Selection is modified - * the same way for contextual menu as it would be without. - */ - if (button_event_modifies_selection (event)) { - icon_toggle_selected (container, icon); - gtk_signal_emit (GTK_OBJECT (container), - signals[SELECTION_CHANGED]); - } else if (!icon->is_selected) { - unselect_all (container); - icon_set_selected (container, icon, TRUE); - gtk_signal_emit (GTK_OBJECT (container), - signals[SELECTION_CHANGED]); - } - - if (event->type == GDK_2BUTTON_PRESS && event->button == DRAG_BUTTON) { - /* Double clicking does not trigger a D&D action. */ - details->drag_button = 0; - details->drag_icon = NULL; - - activate_selected_items (container); - } - - return TRUE; -} - -static int -item_event_callback (GnomeCanvasItem *item, - GdkEvent *event, - gpointer data) -{ - NautilusIconContainer *container; - NautilusIconContainerDetails *details; - NautilusIcon *icon; - - container = NAUTILUS_ICON_CONTAINER (data); - details = container->details; - - icon = NAUTILUS_ICON_CANVAS_ITEM (item)->user_data; - g_return_val_if_fail (icon != NULL, FALSE); - - switch (event->type) { - case GDK_BUTTON_PRESS: - case GDK_2BUTTON_PRESS: - if (handle_icon_button_press (container, icon, &event->button)) { - /* Stop the event from being passed along further. Returning - * TRUE ain't enough. - */ - gtk_signal_emit_stop_by_name (GTK_OBJECT (item), "event"); - return TRUE; - } - return FALSE; - default: - return FALSE; - } -} - -GtkWidget * -nautilus_icon_container_new (void) -{ - GtkWidget *container; - - gtk_widget_push_visual (gdk_rgb_get_visual ()); - gtk_widget_push_colormap (gdk_rgb_get_cmap ()); - - container = gtk_widget_new (nautilus_icon_container_get_type (), NULL); - - gtk_widget_pop_visual (); - gtk_widget_pop_colormap (); - - return container; -} - -/* Clear all of the icons in the container. */ -void -nautilus_icon_container_clear (NautilusIconContainer *container) -{ - NautilusIconContainerDetails *details; - GList *p; - - g_return_if_fail (NAUTILUS_IS_ICON_CONTAINER (container)); - - details = container->details; - - end_renaming_mode (container, TRUE); - - clear_keyboard_focus (container); - details->stretch_icon = NULL; - - for (p = details->icons; p != NULL; p = p->next) { - icon_free (p->data); - } - g_list_free (details->icons); - details->icons = NULL; - g_list_free (details->new_icons); - details->new_icons = NULL; - - nautilus_icon_container_update_scroll_region (container); -} - -gboolean -nautilus_icon_container_is_empty (NautilusIconContainer *container) -{ - return container->details->icons == NULL; -} - -/* Call a function for all the icons. */ -typedef struct { - NautilusIconCallback callback; - gpointer callback_data; -} CallbackAndData; - -static void -call_icon_callback (gpointer data, gpointer callback_data) -{ - NautilusIcon *icon; - CallbackAndData *callback_and_data; - - icon = data; - callback_and_data = callback_data; - (* callback_and_data->callback) (icon->data, callback_and_data->callback_data); -} - -void -nautilus_icon_container_for_each (NautilusIconContainer *container, - NautilusIconCallback callback, - gpointer callback_data) -{ - CallbackAndData callback_and_data; - - g_return_if_fail (NAUTILUS_IS_ICON_CONTAINER (container)); - - callback_and_data.callback = callback; - callback_and_data.callback_data = callback_data; - - g_list_foreach (container->details->icons, - call_icon_callback, &callback_and_data); -} - -/* utility routine to remove a single icon from the container */ - -static void -icon_destroy (NautilusIconContainer *container, - NautilusIcon *icon) -{ - NautilusIconContainerDetails *details; - gboolean was_selected; - - details = container->details; - - details->icons = g_list_remove (details->icons, icon); - details->new_icons = g_list_remove (details->new_icons, icon); - - was_selected = icon->is_selected; - - if (details->keyboard_focus == icon) { - clear_keyboard_focus (container); - } - if (details->keyboard_icon_to_reveal == icon) { - unschedule_keyboard_icon_reveal (container); - } - if (details->drop_target == icon) { - details->drop_target = NULL; - } - - icon_free (icon); - - if (was_selected) { - gtk_signal_emit (GTK_OBJECT (container), - signals[SELECTION_CHANGED]); - } -} - -/* activate any selected items in the container */ -static void -activate_selected_items (NautilusIconContainer *container) -{ - GList *selection; - - g_return_if_fail (NAUTILUS_IS_ICON_CONTAINER (container)); - - selection = nautilus_icon_container_get_selection (container); - if (selection != NULL) { - gtk_signal_emit (GTK_OBJECT (container), - signals[ACTIVATE], - selection); - } - g_list_free (selection); -} - -static NautilusIcon * -get_icon_being_renamed (NautilusIconContainer *container) -{ - NautilusIcon *rename_icon; - - if (!is_renaming (container)) { - return NULL; - } - - g_assert (!has_multiple_selection (container)); - - rename_icon = get_first_selected_icon (container); - g_assert (rename_icon != NULL); - - return rename_icon; -} - -void -nautilus_icon_container_update_icon (NautilusIconContainer *container, - NautilusIcon *icon) -{ - NautilusIconContainerDetails *details; - guint icon_size_x, icon_size_y; - guint min_image_size, max_image_size; - guint width, height, scaled_width, scaled_height; - double scale_factor; - NautilusScalableIcon *scalable_icon; - NautilusEmblemAttachPoints attach_points; - GdkPixbuf *pixbuf, *emblem_pixbuf, *saved_pixbuf; - GList *emblem_scalable_icons, *emblem_pixbufs, *p; - char *editable_text, *additional_text; - GdkFont *font; - int smooth_font_size; - - if (icon == NULL) { - return; - } - - details = container->details; - - /* Get the icons. */ - gtk_signal_emit (GTK_OBJECT (container), - signals[GET_ICON_IMAGES], - icon->data, - (icon == details->drop_target) ? "accept" : "", - &emblem_scalable_icons, - &scalable_icon); - - /* compute the maximum size based on the scale factor */ - min_image_size = MINIMUM_IMAGE_SIZE * GNOME_CANVAS (container)->pixels_per_unit; - max_image_size = MAXIMUM_IMAGE_SIZE * GNOME_CANVAS (container)->pixels_per_unit; - - /* Get the appropriate images for the file. */ - icon_get_size (container, icon, &icon_size_x, &icon_size_y); - pixbuf = nautilus_icon_factory_get_pixbuf_for_icon - (scalable_icon, - icon_size_x, - icon_size_y, - max_image_size * icon->scale_x, - max_image_size * icon->scale_y, - nautilus_icon_container_get_anti_aliased_mode (container), - &attach_points, - TRUE); - - nautilus_scalable_icon_unref (scalable_icon); - - /* in the rare case an image is too small, scale it up */ - - width = gdk_pixbuf_get_width (pixbuf); - height = gdk_pixbuf_get_height (pixbuf); - if (width < min_image_size || height < min_image_size) { - scale_factor = MAX (min_image_size / (double) width, min_image_size / (double) height); - /* don't let it exceed the maximum width in the other dimension */ - scale_factor = MIN (scale_factor, max_image_size / width); - scale_factor = MIN (scale_factor, max_image_size / height); - - scaled_width = floor (width * scale_factor + .5); - scaled_height = floor (height * scale_factor + .5); - saved_pixbuf = pixbuf; - pixbuf = gdk_pixbuf_scale_simple (pixbuf, scaled_width, scaled_height, GDK_INTERP_BILINEAR); - gdk_pixbuf_unref (saved_pixbuf); - } - - emblem_pixbufs = NULL; - - icon_size_x = MAX (nautilus_get_icon_size_for_zoom_level (container->details->zoom_level) - * icon->scale_x, NAUTILUS_ICON_SIZE_SMALLEST); - icon_size_y = MAX (nautilus_get_icon_size_for_zoom_level (container->details->zoom_level) - * icon->scale_y, NAUTILUS_ICON_SIZE_SMALLEST); - for (p = emblem_scalable_icons; p != NULL; p = p->next) { - emblem_pixbuf = nautilus_icon_factory_get_pixbuf_for_icon - (p->data, - icon_size_x, - icon_size_y, - MAXIMUM_EMBLEM_SIZE, - MAXIMUM_EMBLEM_SIZE, - nautilus_icon_container_get_anti_aliased_mode (container), - NULL, - FALSE); - if (emblem_pixbuf != NULL) { - emblem_pixbufs = g_list_prepend - (emblem_pixbufs, emblem_pixbuf); - } - } - emblem_pixbufs = g_list_reverse (emblem_pixbufs); - nautilus_scalable_icon_list_free (emblem_scalable_icons); - - /* Get both editable and non-editable icon text */ - gtk_signal_emit (GTK_OBJECT (container), - signals[GET_ICON_TEXT], - icon->data, - &editable_text, - &additional_text); - - /* If name of icon being renamed was changed from elsewhere, end renaming mode. - * Alternatively, we could replace the characters in the editable text widget - * with the new name, but that could cause timing problems if the user just - * happened to be typing at that moment. - */ - if (icon == get_icon_being_renamed (container) && - eel_strcmp (editable_text, - nautilus_icon_canvas_item_get_editable_text (icon->item)) != 0) { - end_renaming_mode (container, FALSE); - } - - font = details->label_font[details->zoom_level]; - - smooth_font_size = details->font_size_table[details->zoom_level]; - - gnome_canvas_item_set (GNOME_CANVAS_ITEM (icon->item), - "editable_text", editable_text, - "additional_text", additional_text, - "font", font, - "highlighted_for_drop", icon == details->drop_target, - "smooth_font_size", smooth_font_size, - "smooth_font", details->smooth_label_font, - NULL); - - nautilus_icon_canvas_item_set_image (icon->item, pixbuf); - nautilus_icon_canvas_item_set_attach_points (icon->item, &attach_points); - nautilus_icon_canvas_item_set_emblems (icon->item, emblem_pixbufs); - - /* Let the pixbufs go. */ - gdk_pixbuf_unref (pixbuf); - eel_gdk_pixbuf_list_free (emblem_pixbufs); - - g_free (editable_text); - g_free (additional_text); -} - -static gboolean -assign_icon_position (NautilusIconContainer *container, - NautilusIcon *icon) -{ - gboolean have_stored_position; - NautilusIconPosition position; - - /* Get the stored position. */ - have_stored_position = FALSE; - position.scale_x = 1.0; - position.scale_y = 1.0; - gtk_signal_emit (GTK_OBJECT (container), - signals[GET_STORED_ICON_POSITION], - icon->data, - &position, - &have_stored_position); - icon->scale_x = position.scale_x; - icon->scale_y = position.scale_y; - if (!container->details->auto_layout) { - if (have_stored_position) { - icon_set_position (icon, position.x, position.y); - } else { - return FALSE; - } - } - return TRUE; -} - -static void -finish_adding_icon (NautilusIconContainer *container, - NautilusIcon *icon) -{ - nautilus_icon_container_update_icon (container, icon); - gnome_canvas_item_show (GNOME_CANVAS_ITEM (icon->item)); - - gtk_signal_connect (GTK_OBJECT (icon->item), "event", - GTK_SIGNAL_FUNC (item_event_callback), container); -} - -static void -finish_adding_new_icons (NautilusIconContainer *container) -{ - GList *p, *new_icons, *no_position_icons; - NautilusIcon *icon; - double bottom; - - new_icons = container->details->new_icons; - container->details->new_icons = NULL; - - /* Position most icons (not unpositioned manual-layout icons). */ - new_icons = g_list_reverse (new_icons); - no_position_icons = NULL; - for (p = new_icons; p != NULL; p = p->next) { - icon = p->data; - if (!assign_icon_position (container, icon)) { - no_position_icons = g_list_prepend (no_position_icons, icon); - } - finish_adding_icon (container, icon); - } - g_list_free (new_icons); - - /* Position the unpositioned manual layout icons. */ - if (no_position_icons != NULL) { - g_assert (!container->details->auto_layout); - - sort_icons (container, &no_position_icons); - get_all_icon_bounds (container, NULL, NULL, NULL, &bottom); - lay_down_icons (container, no_position_icons, bottom + ICON_PAD_BOTTOM); - g_list_free (no_position_icons); - } -} - -/** - * nautilus_icon_container_add: - * @container: A NautilusIconContainer - * @data: Icon data. - * - * Add icon to represent @data to container. - * Returns FALSE if there was already such an icon. - **/ -gboolean -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); - g_return_val_if_fail (data != NULL, FALSE); - - details = container->details; - - /* FIXME bugzilla.eazel.com 1288: - * 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; - } - } - - /* Create the new icon, including the canvas item. */ - icon = g_new0 (NautilusIcon, 1); - icon->data = data; - icon->x = ICON_UNPOSITIONED_VALUE; - icon->y = ICON_UNPOSITIONED_VALUE; - icon->scale_x = 1.0; - icon->scale_y = 1.0; - icon->item = NAUTILUS_ICON_CANVAS_ITEM - (gnome_canvas_item_new (GNOME_CANVAS_GROUP (GNOME_CANVAS (container)->root), - nautilus_icon_canvas_item_get_type (), - NULL)); - gnome_canvas_item_hide (GNOME_CANVAS_ITEM (icon->item)); - icon->item->user_data = icon; - - /* Put it on both lists. */ - details->icons = g_list_prepend (details->icons, icon); - details->new_icons = g_list_prepend (details->new_icons, icon); - - /* Run an idle function to add the icons. */ - schedule_redo_layout (container); - - return TRUE; -} - -/** - * nautilus_icon_container_remove: - * @container: A NautilusIconContainer. - * @data: Icon data. - * - * Remove the icon with this data. - **/ -gboolean -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.eazel.com 1288: - * 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; - } - } - - return FALSE; -} - -/** - * nautilus_icon_container_request_update: - * @container: A NautilusIconContainer. - * @data: Icon data. - * - * Update the icon with this data. - **/ -void -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; - } - } -} - -/* zooming */ - -NautilusZoomLevel -nautilus_icon_container_get_zoom_level (NautilusIconContainer *container) -{ - return container->details->zoom_level; -} - -void -nautilus_icon_container_set_zoom_level (NautilusIconContainer *container, int new_level) -{ - NautilusIconContainerDetails *details; - int pinned_level; - double pixels_per_unit; - - details = container->details; - - end_renaming_mode (container, TRUE); - - pinned_level = new_level; - if (pinned_level < NAUTILUS_ZOOM_LEVEL_SMALLEST) { - pinned_level = NAUTILUS_ZOOM_LEVEL_SMALLEST; - } else if (pinned_level > NAUTILUS_ZOOM_LEVEL_LARGEST) { - pinned_level = NAUTILUS_ZOOM_LEVEL_LARGEST; - } - - if (pinned_level == details->zoom_level) { - return; - } - - details->zoom_level = pinned_level; - - pixels_per_unit = (double) nautilus_get_icon_size_for_zoom_level (pinned_level) - / NAUTILUS_ICON_SIZE_STANDARD; - gnome_canvas_set_pixels_per_unit (GNOME_CANVAS (container), pixels_per_unit); - - nautilus_icon_container_request_update_all (container); -} - -/** - * nautilus_icon_container_request_update_all: - * For each icon, synchronizes the displayed information (image, text) with the - * information from the model. - * - * @container: An icon container. - **/ -void -nautilus_icon_container_request_update_all (NautilusIconContainer *container) -{ - GList *p; - - g_return_if_fail (NAUTILUS_IS_ICON_CONTAINER (container)); - - for (p = container->details->icons; p != NULL; p = p->next) { - nautilus_icon_container_update_icon (container, p->data); - } - redo_layout (container); -} - -/** - * nautilus_icon_container_reveal: - * Change scroll position as necessary to reveal the specified item. - */ -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.eazel.com 1288: - * 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); - } - } -} - -/** - * nautilus_icon_container_get_anti_aliased_mode: - * get the state of the anti_aliased boolean - * - **/ - -gboolean -nautilus_icon_container_get_anti_aliased_mode (NautilusIconContainer *container) -{ - GnomeCanvas *canvas; - - canvas = GNOME_CANVAS (container); - return canvas->aa; -} - -/** - * nautilus_icon_container_set_anti_aliased_mode: - * Change the anti-aliased mode and redraw everything - * - **/ - -void -nautilus_icon_container_set_anti_aliased_mode (NautilusIconContainer *container, gboolean anti_aliased_mode) -{ - GnomeCanvas *canvas; - - canvas = GNOME_CANVAS (container); - if (canvas->aa != anti_aliased_mode) { - canvas->aa = anti_aliased_mode; - - invalidate_label_sizes (container); - nautilus_icon_container_request_update_all (container); - } -} - -/** - * nautilus_icon_container_get_selection: - * @container: An icon container. - * - * Get a list of the icons currently selected in @container. - * - * Return value: A GList of the programmer-specified data associated to each - * selected icon, or NULL if no icon is selected. The caller is expected to - * free the list when it is not needed anymore. - **/ -GList * -nautilus_icon_container_get_selection (NautilusIconContainer *container) -{ - GList *list, *p; - - g_return_val_if_fail (NAUTILUS_IS_ICON_CONTAINER (container), FALSE); - - list = NULL; - for (p = container->details->icons; p != NULL; p = p->next) { - NautilusIcon *icon; - - icon = p->data; - if (icon->is_selected) { - list = g_list_prepend (list, icon->data); - } - } - - return list; -} - -/* Returns an array of GdkPoints of locations of the icons. */ -static GArray * -nautilus_icon_container_get_icon_locations (NautilusIconContainer *container, - GList *icons) -{ - GArray *result; - GList *node; - int index; - - result = g_array_new (FALSE, TRUE, sizeof (GdkPoint)); - result = g_array_set_size (result, g_list_length (icons)); - - for (index = 0, node = icons; node != NULL; index++, node = node->next) { - g_array_index (result, GdkPoint, index).x = - ((NautilusIcon *)node->data)->x; - g_array_index (result, GdkPoint, index).y = - ((NautilusIcon *)node->data)->y; - } - - return result; -} - -/** - * nautilus_icon_container_get_selected_icon_locations: - * @container: An icon container widget. - * - * Returns an array of GdkPoints of locations of the selected icons. - **/ -GArray * -nautilus_icon_container_get_selected_icon_locations (NautilusIconContainer *container) -{ - GArray *result; - GList *icons, *node; - - g_return_val_if_fail (NAUTILUS_IS_ICON_CONTAINER (container), NULL); - - icons = NULL; - for (node = container->details->icons; node != NULL; node = node->next) { - NautilusIcon *icon; - - icon = node->data; - if (icon->is_selected) { - icons = g_list_prepend (icons, icon); - } - } - - result = nautilus_icon_container_get_icon_locations (container, icons); - g_list_free (icons); - - return result; -} - -/** - * nautilus_icon_container_select_all: - * @container: An icon container widget. - * - * Select all the icons in @container at once. - **/ -void -nautilus_icon_container_select_all (NautilusIconContainer *container) -{ - gboolean selection_changed; - GList *p; - NautilusIcon *icon; - - g_return_if_fail (NAUTILUS_IS_ICON_CONTAINER (container)); - - selection_changed = FALSE; - - for (p = container->details->icons; p != NULL; p = p->next) { - icon = p->data; - - selection_changed |= icon_set_selected (container, icon, TRUE); - } - - if (selection_changed) { - gtk_signal_emit (GTK_OBJECT (container), - signals[SELECTION_CHANGED]); - } -} - -/** - * nautilus_icon_container_set_selection: - * @container: An icon container widget. - * @selection: A list of NautilusIconData *. - * - * Set the selection to exactly the icons in @container which have - * programmer data matching one of the items in @selection. - **/ -void -nautilus_icon_container_set_selection (NautilusIconContainer *container, - GList *selection) -{ - gboolean selection_changed; - GHashTable *hash; - GList *p; - NautilusIcon *icon; - - g_return_if_fail (NAUTILUS_IS_ICON_CONTAINER (container)); - - selection_changed = FALSE; - - hash = g_hash_table_new (NULL, NULL); - for (p = selection; p != NULL; p = p->next) { - g_hash_table_insert (hash, p->data, p->data); - } - for (p = container->details->icons; p != NULL; p = p->next) { - icon = p->data; - - selection_changed |= icon_set_selected - (container, icon, - g_hash_table_lookup (hash, icon->data) != NULL); - } - g_hash_table_destroy (hash); - - if (selection_changed) { - gtk_signal_emit (GTK_OBJECT (container), - signals[SELECTION_CHANGED]); - } -} - -/** - * nautilus_icon_container_select_list_unselect_others. - * @container: An icon container widget. - * @selection: A list of NautilusIcon *. - * - * Set the selection to exactly the icons in @selection. - **/ -void -nautilus_icon_container_select_list_unselect_others (NautilusIconContainer *container, - GList *selection) -{ - gboolean selection_changed; - GHashTable *hash; - GList *p; - NautilusIcon *icon; - - g_return_if_fail (NAUTILUS_IS_ICON_CONTAINER (container)); - - selection_changed = FALSE; - - hash = g_hash_table_new (NULL, NULL); - for (p = selection; p != NULL; p = p->next) { - g_hash_table_insert (hash, p->data, p->data); - } - for (p = container->details->icons; p != NULL; p = p->next) { - icon = p->data; - - selection_changed |= icon_set_selected - (container, icon, - g_hash_table_lookup (hash, icon) != NULL); - } - g_hash_table_destroy (hash); - - if (selection_changed) { - gtk_signal_emit (GTK_OBJECT (container), - signals[SELECTION_CHANGED]); - } -} - -/** - * nautilus_icon_container_unselect_all: - * @container: An icon container widget. - * - * Deselect all the icons in @container. - **/ -void -nautilus_icon_container_unselect_all (NautilusIconContainer *container) -{ - if (unselect_all (container)) { - gtk_signal_emit (GTK_OBJECT (container), - signals[SELECTION_CHANGED]); - } -} - -/** - * nautilus_icon_container_get_icon_by_uri: - * @container: An icon container widget. - * @uri: The uri of an icon to find. - * - * Locate an icon, given the URI. The URI must match exactly. - * Later we may have to have some way of figuring out if the - * URI specifies the same object that does not require an exact match. - **/ -NautilusIcon * -nautilus_icon_container_get_icon_by_uri (NautilusIconContainer *container, - const char *uri) -{ - NautilusIconContainerDetails *details; - GList *p; - - /* Eventually, we must avoid searching the entire icon list, - but it's OK for now. - A hash table mapping uri to icon is one possibility. - */ - - details = container->details; - - for (p = details->icons; p != NULL; p = p->next) { - NautilusIcon *icon; - char *icon_uri; - gboolean is_match; - - icon = p->data; - - icon_uri = nautilus_icon_container_get_icon_uri - (container, icon); - is_match = strcmp (uri, icon_uri) == 0; - g_free (icon_uri); - - if (is_match) { - return icon; - } - } - - return NULL; -} - -static NautilusIcon * -get_nth_selected_icon (NautilusIconContainer *container, int index) -{ - GList *p; - NautilusIcon *icon; - int selection_count; - - g_return_val_if_fail (index > 0, NULL); - - /* Find the nth selected icon. */ - selection_count = 0; - for (p = container->details->icons; p != NULL; p = p->next) { - icon = p->data; - if (icon->is_selected) { - if (++selection_count == index) { - return icon; - } - } - } - return NULL; -} - -static NautilusIcon * -get_first_selected_icon (NautilusIconContainer *container) -{ - return get_nth_selected_icon (container, 1); -} - -static gboolean -has_multiple_selection (NautilusIconContainer *container) -{ - return get_nth_selected_icon (container, 2) != NULL; -} - -/** - * nautilus_icon_container_show_stretch_handles: - * @container: An icon container widget. - * - * Makes stretch handles visible on the first selected icon. - **/ -void -nautilus_icon_container_show_stretch_handles (NautilusIconContainer *container) -{ - NautilusIconContainerDetails *details; - NautilusIcon *icon; - int initial_size_x, initial_size_y; - - icon = get_first_selected_icon (container); - if (icon == NULL) { - return; - } - - /* Check if it already has stretch handles. */ - details = container->details; - if (details->stretch_icon == icon) { - return; - } - - /* Get rid of the existing stretch handles and put them on the new icon. */ - if (details->stretch_icon != NULL) { - nautilus_icon_canvas_item_set_show_stretch_handles - (details->stretch_icon->item, FALSE); - ungrab_stretch_icon (container); - emit_stretch_ended (container, details->stretch_icon); - } - nautilus_icon_canvas_item_set_show_stretch_handles (icon->item, TRUE); - details->stretch_icon = icon; - - icon_get_size (container, icon, &initial_size_x, &initial_size_y); - - /* only need to keep size in one dimension, since they are constrained to be the same */ - container->details->stretch_initial_x = icon->x; - container->details->stretch_initial_y = icon->y; - container->details->stretch_initial_size = initial_size_x; - - emit_stretch_started (container, icon); -} - -/** - * nautilus_icon_container_has_stretch_handles - * @container: An icon container widget. - * - * Returns true if the first selected item has stretch handles. - **/ -gboolean -nautilus_icon_container_has_stretch_handles (NautilusIconContainer *container) -{ - NautilusIcon *icon; - - icon = get_first_selected_icon (container); - if (icon == NULL) { - return FALSE; - } - - return icon == container->details->stretch_icon; -} - -/** - * nautilus_icon_container_is_stretched - * @container: An icon container widget. - * - * Returns true if the any selected item is stretched to a size other than 1.0. - **/ -gboolean -nautilus_icon_container_is_stretched (NautilusIconContainer *container) -{ - GList *p; - NautilusIcon *icon; - - for (p = container->details->icons; p != NULL; p = p->next) { - icon = p->data; - if (icon->is_selected && (icon->scale_x != 1.0 || icon->scale_y != 1.0)) { - return TRUE; - } - } - return FALSE; -} - -/** - * nautilus_icon_container_unstretch - * @container: An icon container widget. - * - * Gets rid of any icon stretching. - **/ -void -nautilus_icon_container_unstretch (NautilusIconContainer *container) -{ - GList *p; - NautilusIcon *icon; - - for (p = container->details->icons; p != NULL; p = p->next) { - icon = p->data; - if (icon->is_selected) { - nautilus_icon_container_move_icon (container, icon, - icon->x, icon->y, - 1.0, 1.0, - FALSE, TRUE); - } - } -} - -static void -compute_stretch (StretchState *start, - StretchState *current) -{ - gboolean right, bottom; - int x_stretch, y_stretch; - - /* FIXME bugzilla.eazel.com 5390: This doesn't correspond to - * the way the handles are drawn. - */ - /* Figure out which handle we are dragging. */ - right = start->pointer_x > start->icon_x + (int) start->icon_size / 2; - bottom = start->pointer_y > start->icon_y + (int) start->icon_size / 2; - - /* Figure out how big we should stretch. */ - x_stretch = start->pointer_x - current->pointer_x; - y_stretch = start->pointer_y - current->pointer_y; - if (right) { - x_stretch = - x_stretch; - } - if (bottom) { - y_stretch = - y_stretch; - } - current->icon_size = MAX ((int) start->icon_size + MIN (x_stretch, y_stretch), - (int) NAUTILUS_ICON_SIZE_SMALLEST); - - /* Figure out where the corner of the icon should be. */ - current->icon_x = start->icon_x; - if (!right) { - current->icon_x += start->icon_size - current->icon_size; - } - current->icon_y = start->icon_y; - if (!bottom) { - current->icon_y += start->icon_size - current->icon_size; - } -} - -char * -nautilus_icon_container_get_icon_uri (NautilusIconContainer *container, - NautilusIcon *icon) -{ - char *uri; - - uri = NULL; - gtk_signal_emit (GTK_OBJECT (container), - signals[GET_ICON_URI], - icon->data, - &uri); - return uri; -} - -char * -nautilus_icon_container_get_icon_drop_target_uri (NautilusIconContainer *container, - NautilusIcon *icon) -{ - char *uri; - - uri = NULL; - gtk_signal_emit (GTK_OBJECT (container), - signals[GET_ICON_DROP_TARGET_URI], - icon->data, - &uri); - return uri; -} - -/* Call to reset the scroll region only if the container is not empty, - * to avoid having the flag linger until the next file is added. - */ -static void -reset_scroll_region_if_not_empty (NautilusIconContainer *container) -{ - if (!nautilus_icon_container_is_empty (container)) { - nautilus_icon_container_reset_scroll_region (container); - } -} - -/* Switch from automatic layout to manual or vice versa. - * If we switch to manual layout, we restore the icon positions from the - * last manual layout. - */ -void -nautilus_icon_container_set_auto_layout (NautilusIconContainer *container, - gboolean auto_layout) -{ - g_return_if_fail (NAUTILUS_IS_ICON_CONTAINER (container)); - g_return_if_fail (auto_layout == FALSE || auto_layout == TRUE); - - if (container->details->auto_layout == auto_layout) { - return; - } - - reset_scroll_region_if_not_empty (container); - container->details->auto_layout = auto_layout; - - if (!auto_layout) { - reload_icon_positions (container); - nautilus_icon_container_freeze_icon_positions (container); - } - - redo_layout (container); - - gtk_signal_emit (GTK_OBJECT (container), signals[LAYOUT_CHANGED]); -} - - -/* Toggle the tighter layout boolean. */ -void -nautilus_icon_container_set_tighter_layout (NautilusIconContainer *container, - gboolean tighter_layout) -{ - g_return_if_fail (NAUTILUS_IS_ICON_CONTAINER (container)); - g_return_if_fail (tighter_layout == FALSE || tighter_layout == TRUE); - - if (container->details->tighter_layout == tighter_layout) { - return; - } - - container->details->tighter_layout = tighter_layout; - - if (container->details->auto_layout) { - invalidate_label_sizes (container); - redo_layout (container); - - gtk_signal_emit (GTK_OBJECT (container), signals[LAYOUT_CHANGED]); - } else { - /* in manual layout, label sizes still change, even though - * the icons don't move. - */ - invalidate_label_sizes (container); - nautilus_icon_container_request_update_all (container); - } -} - - -void -nautilus_icon_container_set_layout_mode (NautilusIconContainer *container, - NautilusIconLayoutMode mode) -{ - g_return_if_fail (NAUTILUS_IS_ICON_CONTAINER (container)); - - container->details->layout_mode = mode; - - redo_layout (container); - - gtk_signal_emit (GTK_OBJECT (container), signals[LAYOUT_CHANGED]); -} - - -/* Switch from automatic to manual layout, freezing all the icons in their - * current positions instead of restoring icon positions from the last manual - * layout as set_auto_layout does. - */ -void -nautilus_icon_container_freeze_icon_positions (NautilusIconContainer *container) -{ - gboolean changed; - GList *p; - NautilusIcon *icon; - NautilusIconPosition position; - - changed = container->details->auto_layout; - container->details->auto_layout = FALSE; - - for (p = container->details->icons; p != NULL; p = p->next) { - icon = p->data; - - position.x = icon->x; - position.y = icon->y; - position.scale_x = icon->scale_x; - position.scale_y = icon->scale_y; - gtk_signal_emit (GTK_OBJECT (container), signals[ICON_POSITION_CHANGED], - icon->data, &position); - } - - if (changed) { - gtk_signal_emit (GTK_OBJECT (container), signals[LAYOUT_CHANGED]); - } -} - -/* Re-sort, switching to automatic layout if it was in manual layout. */ -void -nautilus_icon_container_sort (NautilusIconContainer *container) -{ - gboolean changed; - - changed = !container->details->auto_layout; - container->details->auto_layout = TRUE; - - reset_scroll_region_if_not_empty (container); - redo_layout (container); - - if (changed) { - gtk_signal_emit (GTK_OBJECT (container), signals[LAYOUT_CHANGED]); - } -} - -gboolean -nautilus_icon_container_is_auto_layout (NautilusIconContainer *container) -{ - g_return_val_if_fail (NAUTILUS_IS_ICON_CONTAINER (container), FALSE); - - return container->details->auto_layout; -} - -gboolean -nautilus_icon_container_is_tighter_layout (NautilusIconContainer *container) -{ - g_return_val_if_fail (NAUTILUS_IS_ICON_CONTAINER (container), FALSE); - - return container->details->tighter_layout; -} - -static void -pending_icon_to_rename_destroy_callback (NautilusIconCanvasItem *item, NautilusIconContainer *container) -{ - g_assert (container->details->pending_icon_to_rename != NULL); - g_assert (container->details->pending_icon_to_rename->item == item); - container->details->pending_icon_to_rename = NULL; -} - -static NautilusIcon* -get_pending_icon_to_rename (NautilusIconContainer *container) -{ - return container->details->pending_icon_to_rename; -} - -static void -set_pending_icon_to_rename (NautilusIconContainer *container, NautilusIcon *icon) -{ - NautilusIcon *cur_pending; - - cur_pending = container->details->pending_icon_to_rename; - - if (icon == cur_pending) { - return; - } - - if (cur_pending != NULL) { - gtk_signal_disconnect_by_func (GTK_OBJECT (cur_pending->item), - &pending_icon_to_rename_destroy_callback, - container); - } - - if (icon != NULL) { - gtk_signal_connect (GTK_OBJECT (icon->item), "destroy", &pending_icon_to_rename_destroy_callback, container); - } - - container->details->pending_icon_to_rename = icon; -} - -static void -process_pending_icon_to_rename (NautilusIconContainer *container) -{ - NautilusIcon *pending_icon_to_rename; - - pending_icon_to_rename = get_pending_icon_to_rename (container); - - if (pending_icon_to_rename != NULL) { - if (pending_icon_to_rename->is_selected && !has_multiple_selection (container)) { - nautilus_icon_container_start_renaming_selected_item (container); - } else { - set_pending_icon_to_rename (container, NULL); - } - } -} - -gboolean -is_renaming_pending (NautilusIconContainer *container) -{ - return get_pending_icon_to_rename (container) != NULL; -} - -gboolean -is_renaming (NautilusIconContainer *container) -{ - return container->details->renaming; -} - -/** - * nautilus_icon_container_start_renaming_selected_item - * @container: An icon container widget. - * - * Displays the edit name widget on the first selected icon - **/ -void -nautilus_icon_container_start_renaming_selected_item (NautilusIconContainer *container) -{ - NautilusIconContainerDetails *details; - NautilusIcon *icon; - ArtDRect icon_rect; - const char *editable_text; - - /* Check if it already in renaming mode. */ - details = container->details; - if (details->renaming) { - return; - } - - /* Find selected icon */ - icon = get_first_selected_icon (container); - if (icon == NULL) { - return; - } - - g_assert (!has_multiple_selection (container)); - - - if (!icon_is_positioned (icon)) { - set_pending_icon_to_rename (container, icon); - return; - } - - set_pending_icon_to_rename (container, NULL); - - /* Make a copy of the original editable text for a later compare */ - editable_text = nautilus_icon_canvas_item_get_editable_text (icon->item); - - /* This could conceivably be NULL if a rename was triggered really early. */ - if (editable_text == NULL) { - return; - } - - details->original_text = g_strdup (editable_text); - - /* Create text renaming widget, if it hasn't been created already. - * We deal with the broken icon text item widget by keeping it around - * so its contents can still be cut and pasted as part of the clipboard - */ - if (details->rename_widget == NULL) { - details->rename_widget = NAUTILUS_ICON_TEXT_ITEM - (gnome_canvas_item_new (gnome_canvas_root (GNOME_CANVAS (container)), - nautilus_icon_text_item_get_type (), - NULL)); - } else { - gnome_canvas_item_show (GNOME_CANVAS_ITEM (details->rename_widget)); - } - - icon_rect = nautilus_icon_canvas_item_get_icon_rectangle (icon->item); - gnome_canvas_item_w2i (GNOME_CANVAS_ITEM (details->rename_widget), &icon_rect.x0, &icon_rect.y0); - gnome_canvas_item_w2i (GNOME_CANVAS_ITEM (details->rename_widget), &icon_rect.x1, &icon_rect.y1); - - nautilus_icon_text_item_configure - (details->rename_widget, - (icon_rect.x0 + icon_rect.x1) / 2, /* x_center */ - icon_rect.y1, /* y_top */ - nautilus_icon_canvas_item_get_max_text_width (icon->item), /* max_text_width */ - details->label_font[details->zoom_level], /* font */ - editable_text, /* text */ - FALSE); /* allocate local copy */ - - nautilus_icon_text_item_start_editing (details->rename_widget); - - gtk_signal_emit (GTK_OBJECT (container), - signals[RENAMING_ICON], - nautilus_icon_text_item_get_renaming_editable (details->rename_widget)); - - nautilus_icon_container_update_icon (container, icon); - - /* We are in renaming mode */ - details->renaming = TRUE; - nautilus_icon_canvas_item_set_renaming (icon->item, TRUE); -} - -static void -end_renaming_mode (NautilusIconContainer *container, gboolean commit) -{ - NautilusIcon *icon; - const char *changed_text; - - set_pending_icon_to_rename (container, NULL); - - icon = get_icon_being_renamed (container); - if (icon == NULL) { - return; - } - - if (commit) { - /* Verify that text has been modified before signalling change. */ - changed_text = nautilus_icon_text_item_get_text (container->details->rename_widget); - if (strcmp (container->details->original_text, changed_text) != 0) { - gtk_signal_emit (GTK_OBJECT (container), - signals[ICON_TEXT_CHANGED], - icon->data, - changed_text); - } - } - - nautilus_icon_text_item_stop_editing (container->details->rename_widget, TRUE); - - gnome_canvas_item_hide (GNOME_CANVAS_ITEM (container->details->rename_widget)); - - g_free (container->details->original_text); - - /* We are not in renaming mode */ - container->details->renaming = FALSE; - nautilus_icon_canvas_item_set_renaming (icon->item, FALSE); -} - -/* emit preview signal, called by the canvas item */ -gboolean -nautilus_icon_container_emit_preview_signal (NautilusIconContainer *icon_container, - NautilusIcon *icon, - gboolean start_flag) -{ - gboolean result; - - g_return_val_if_fail (NAUTILUS_IS_ICON_CONTAINER (icon_container), FALSE); - g_return_val_if_fail (icon != NULL, FALSE); - g_return_val_if_fail (start_flag == FALSE || start_flag == TRUE, FALSE); - - result = FALSE; - gtk_signal_emit (GTK_OBJECT (icon_container), - signals[PREVIEW], - icon->data, - start_flag, - &result); - - return result; -} - -gboolean -nautilus_icon_container_has_stored_icon_positions (NautilusIconContainer *container) -{ - GList *p; - NautilusIcon *icon; - gboolean have_stored_position; - NautilusIconPosition position; - - for (p = container->details->icons; p != NULL; p = p->next) { - icon = p->data; - - have_stored_position = FALSE; - gtk_signal_emit (GTK_OBJECT (container), - signals[GET_STORED_ICON_POSITION], - icon->data, - &position, - &have_stored_position); - if (have_stored_position) { - return TRUE; - } - } - return FALSE; -} - -void -nautilus_icon_container_set_label_font_for_zoom_level (NautilusIconContainer *container, - int zoom_level, - GdkFont *font) -{ - g_return_if_fail (NAUTILUS_IS_ICON_CONTAINER (container)); - g_return_if_fail (font != NULL); - g_return_if_fail (zoom_level >= NAUTILUS_ZOOM_LEVEL_SMALLEST); - g_return_if_fail (zoom_level <= NAUTILUS_ZOOM_LEVEL_LARGEST); - - if (container->details->label_font[zoom_level] != NULL) { - gdk_font_unref (container->details->label_font[zoom_level]); - } - - gdk_font_ref (font); - - container->details->label_font[zoom_level] = font; -} - -void -nautilus_icon_container_set_smooth_label_font (NautilusIconContainer *container, - EelScalableFont *font) -{ - g_return_if_fail (NAUTILUS_IS_ICON_CONTAINER (container)); - g_return_if_fail (EEL_IS_SCALABLE_FONT (font)); - - gtk_object_ref (GTK_OBJECT (font)); - gtk_object_unref (GTK_OBJECT (container->details->smooth_label_font)); - - container->details->smooth_label_font = font; -} - -void -nautilus_icon_container_set_single_click_mode (NautilusIconContainer *container, - gboolean single_click_mode) -{ - g_return_if_fail (NAUTILUS_IS_ICON_CONTAINER (container)); - - container->details->single_click_mode = single_click_mode; -} - - -/* update the label color when the background changes */ - -guint32 -nautilus_icon_container_get_label_color (NautilusIconContainer *container, - gboolean is_name) -{ - g_return_val_if_fail (NAUTILUS_IS_ICON_CONTAINER (container), 0); - - if (is_name) { - return container->details->label_color; - } else { - return container->details->label_info_color; - } - -} - -static void -update_label_color (EelBackground *background, - NautilusIconContainer *container) -{ - char *light_info_color, *dark_info_color; - uint light_info_value, dark_info_value; - - g_assert (EEL_IS_BACKGROUND (background)); - g_assert (NAUTILUS_IS_ICON_CONTAINER (container)); - - /* FIXME: The code to extract colors from the theme should be in FMDirectoryView, not here. - * The NautilusIconContainer class should simply provide calls to set the colors. - */ - /* read the info colors from the current theme; use a reasonable default if undefined */ - light_info_color = nautilus_theme_get_theme_data ("directory", "light_info_color"); - if (light_info_color == NULL) { - light_info_value = 0xAAAAFD; - } else { - light_info_value = strtoul (light_info_color, NULL, 0); - g_free (light_info_color); - } - - dark_info_color = nautilus_theme_get_theme_data ("directory", "dark_info_color"); - if (dark_info_color == NULL) { - dark_info_value = 0x33337F; - } else { - dark_info_value = strtoul (dark_info_color, NULL, 0); - g_free (dark_info_color); - } - - if (eel_background_is_dark (background)) { - container->details->label_color = 0xEFEFEF; - container->details->label_info_color = light_info_value; - } else { - container->details->label_color = 0x000000; - container->details->label_info_color = dark_info_value; - } -} - - -/* Return if the icon container is a fixed size */ -gboolean -nautilus_icon_container_get_is_fixed_size (NautilusIconContainer *container) -{ - g_return_val_if_fail (NAUTILUS_IS_ICON_CONTAINER (container), FALSE); - - return container->details->is_fixed_size; -} - -/* Set the icon container to be a fixed size */ -void -nautilus_icon_container_set_is_fixed_size (NautilusIconContainer *container, - gboolean is_fixed_size) -{ - g_return_if_fail (NAUTILUS_IS_ICON_CONTAINER (container)); - - container->details->is_fixed_size = is_fixed_size; -} - -void -nautilus_icon_container_set_margins (NautilusIconContainer *container, - int left_margin, - int right_margin, - int top_margin, - int bottom_margin) -{ - g_return_if_fail (NAUTILUS_IS_ICON_CONTAINER (container)); - - container->details->left_margin = left_margin; - container->details->right_margin = right_margin; - container->details->top_margin = top_margin; - container->details->bottom_margin = bottom_margin; - - /* redo layout of icons as the margins have changed */ - schedule_redo_layout (container); -} - -/* handle theme changes */ - -/* FIXME: The code to extract colors from the theme should be in FMDirectoryView, not here. - * The NautilusIconContainer class should simply provide calls to set the colors. - */ -static void -nautilus_icon_container_theme_changed (gpointer user_data) -{ - NautilusIconContainer *container; - char *text_frame_path, *highlight_color_str; - - container = NAUTILUS_ICON_CONTAINER (user_data); - - /* load the highlight frame */ - text_frame_path = nautilus_theme_get_image_path ("text-selection-frame-aa.png"); - if (container->details->highlight_frame) { - gdk_pixbuf_unref (container->details->highlight_frame); - } - - container->details->highlight_frame = gdk_pixbuf_new_from_file (text_frame_path); - g_free (text_frame_path); - - /* load the highlight color */ - highlight_color_str = nautilus_theme_get_theme_data ("directory", "highlight_color_rgba"); - - if (highlight_color_str == NULL) { - container->details->highlight_color = EEL_RGBA_COLOR_PACK (0, 0, 0, 102); - } else { - container->details->highlight_color = strtoul (highlight_color_str, NULL, 0); - g_free (highlight_color_str); - } -} - -void -nautilus_icon_container_set_font_size_table (NautilusIconContainer *container, - const int font_size_table[NAUTILUS_ZOOM_LEVEL_LARGEST + 1]) -{ - int i; - - g_return_if_fail (NAUTILUS_IS_ICON_CONTAINER (container)); - g_return_if_fail (font_size_table != NULL); - - for (i = 0; i <= NAUTILUS_ZOOM_LEVEL_LARGEST; i++) { - container->details->font_size_table[i] = font_size_table[i]; - } -} - -#if ! defined (NAUTILUS_OMIT_SELF_CHECK) - -static char * -check_compute_stretch (int icon_x, int icon_y, int icon_size, - int start_pointer_x, int start_pointer_y, - int end_pointer_x, int end_pointer_y) -{ - StretchState start, current; - - start.icon_x = icon_x; - start.icon_y = icon_y; - start.icon_size = icon_size; - start.pointer_x = start_pointer_x; - start.pointer_y = start_pointer_y; - current.pointer_x = end_pointer_x; - current.pointer_y = end_pointer_y; - - compute_stretch (&start, ¤t); - - return g_strdup_printf ("%d,%d:%d", - current.icon_x, - current.icon_y, - current.icon_size); -} - -void -nautilus_self_check_icon_container (void) -{ - EEL_CHECK_STRING_RESULT (check_compute_stretch (0, 0, 12, 0, 0, 0, 0), "0,0:12"); - EEL_CHECK_STRING_RESULT (check_compute_stretch (0, 0, 12, 12, 12, 13, 13), "0,0:13"); - EEL_CHECK_STRING_RESULT (check_compute_stretch (0, 0, 12, 12, 12, 13, 12), "0,0:12"); - EEL_CHECK_STRING_RESULT (check_compute_stretch (100, 100, 64, 105, 105, 40, 40), "35,35:129"); -} - -#endif /* ! NAUTILUS_OMIT_SELF_CHECK */ diff --git a/libnautilus-extensions/nautilus-icon-container.h b/libnautilus-extensions/nautilus-icon-container.h deleted file mode 100644 index 30382a19e..000000000 --- a/libnautilus-extensions/nautilus-icon-container.h +++ /dev/null @@ -1,232 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ - -/* gnome-icon-container.h - Icon container widget. - - Copyright (C) 1999, 2000 Free Software Foundation - Copyright (C) 2000 Eazel, Inc. - - The Gnome 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 Gnome 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 the Gnome 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. - - Authors: Ettore Perazzoli <ettore@gnu.org>, Darin Adler <darin@eazel.com> -*/ - -#ifndef NAUTILUS_ICON_CONTAINER_H -#define NAUTILUS_ICON_CONTAINER_H - -#include <libgnomeui/gnome-canvas.h> -#include "nautilus-icon-factory.h" -#include <eel/eel-scalable-font.h> - -#define NAUTILUS_ICON_CONTAINER(obj) \ - GTK_CHECK_CAST (obj, nautilus_icon_container_get_type (), NautilusIconContainer) -#define NAUTILUS_ICON_CONTAINER_CLASS(k) \ - GTK_CHECK_CLASS_CAST (k, nautilus_icon_container_get_type (), NautilusIconContainerClass) -#define NAUTILUS_IS_ICON_CONTAINER(obj) \ - GTK_CHECK_TYPE (obj, nautilus_icon_container_get_type ()) - -#define NAUTILUS_ICON_CONTAINER_ICON_DATA(pointer) \ - ((NautilusIconData *) (pointer)) - -typedef struct NautilusIconData NautilusIconData; - -typedef void (* NautilusIconCallback) (NautilusIconData *icon_data, - gpointer callback_data); - -typedef struct { - int x; - int y; - double scale_x; - double scale_y; -} NautilusIconPosition; - -typedef enum { - NAUTILUS_ICON_LAYOUT_L_R_T_B, - NAUTILUS_ICON_LAYOUT_T_B_L_R, - NAUTILUS_ICON_LAYOUT_T_B_R_L -} NautilusIconLayoutMode; - -typedef struct NautilusIconContainerDetails NautilusIconContainerDetails; - -typedef struct { - GnomeCanvas canvas; - NautilusIconContainerDetails *details; -} NautilusIconContainer; - -typedef struct { - GnomeCanvasClass parent_slot; - - /* Operations on the container. */ - int (* button_press) (NautilusIconContainer *container, - GdkEventButton *event); - void (* context_click_background) (NautilusIconContainer *container, - GdkEventButton *event); - void (* middle_click) (NautilusIconContainer *container, - GdkEventButton *event); - - /* Operations on icons. */ - void (* activate) (NautilusIconContainer *container, - NautilusIconData *data); - void (* context_click_selection) (NautilusIconContainer *container, - GdkEventButton *event); - void (* move_copy_items) (NautilusIconContainer *container, - GList *item_uris, - GdkPoint *relative_item_points, - const char *target_uri, - int copy_action, - int x, - int y); - void (* handle_uri_list) (NautilusIconContainer *container, - GList *item_uris, - int x, - int y); - - /* Queries on the container for subclass/client. - * These must be implemented. The default "do nothing" is not good enough. - */ - char * (* get_container_uri) (NautilusIconContainer *container); - - /* Queries on icons for subclass/client. - * These must be implemented. The default "do nothing" is not good enough. - */ - gboolean (* can_accept_item) (NautilusIconContainer *container, - NautilusIconData *target, - const char *item_uri); - gboolean (* get_stored_icon_position) (NautilusIconContainer *container, - NautilusIconData *data, - NautilusIconPosition *position); - NautilusScalableIcon * - (* get_icon_images) (NautilusIconContainer *container, - NautilusIconData *data, - const char *modifier, - GList **emblem_icons); - void (* get_icon_text) (NautilusIconContainer *container, - NautilusIconData *data, - char **editable_text, - char **additional_text); - char * (* get_icon_uri) (NautilusIconContainer *container, - NautilusIconData *data); - char * (* get_icon_drop_target_uri) (NautilusIconContainer *container, - NautilusIconData *data); - int (* compare_icons) (NautilusIconContainer *container, - NautilusIconData *icon_a, - NautilusIconData *icon_b); - int (* compare_icons_by_name) (NautilusIconContainer *container, - NautilusIconData *icon_a, - NautilusIconData *icon_b); - - /* Notifications for the whole container. */ - void (* band_select_started) (NautilusIconContainer *container); - void (* band_select_ended) (NautilusIconContainer *container); - void (* selection_changed) (NautilusIconContainer *container); - void (* layout_changed) (NautilusIconContainer *container); - - /* Notifications for icons. */ - void (* icon_position_changed) (NautilusIconContainer *container, - NautilusIconData *data, - const NautilusIconPosition *position); - void (* icon_text_changed) (NautilusIconContainer *container, - NautilusIconData *data, - const char *text); - void (* renaming_icon) (NautilusIconContainer *container, - GtkWidget *renaming_widget); - void (* icon_stretch_started) (NautilusIconContainer *container, - NautilusIconData *data); - void (* icon_stretch_ended) (NautilusIconContainer *container, - NautilusIconData *data); - int (* preview) (NautilusIconContainer *container, - NautilusIconData *data, - gboolean start_flag); -} NautilusIconContainerClass; - -/* GtkObject */ -guint nautilus_icon_container_get_type (void); -GtkWidget * nautilus_icon_container_new (void); - - -/* adding, removing, and managing icons */ -void nautilus_icon_container_clear (NautilusIconContainer *view); -gboolean nautilus_icon_container_add (NautilusIconContainer *view, - NautilusIconData *data); -gboolean nautilus_icon_container_remove (NautilusIconContainer *view, - NautilusIconData *data); -void nautilus_icon_container_for_each (NautilusIconContainer *view, - NautilusIconCallback callback, - gpointer callback_data); -void nautilus_icon_container_request_update (NautilusIconContainer *view, - NautilusIconData *data); -void nautilus_icon_container_request_update_all (NautilusIconContainer *container); -void nautilus_icon_container_reveal (NautilusIconContainer *container, - NautilusIconData *data); -gboolean nautilus_icon_container_is_empty (NautilusIconContainer *container); - -/* control the layout */ -gboolean nautilus_icon_container_is_auto_layout (NautilusIconContainer *container); -void nautilus_icon_container_set_auto_layout (NautilusIconContainer *container, - gboolean auto_layout); -gboolean nautilus_icon_container_is_tighter_layout (NautilusIconContainer *container); -void nautilus_icon_container_set_tighter_layout (NautilusIconContainer *container, - gboolean tighter_layout); -void nautilus_icon_container_set_layout_mode (NautilusIconContainer *container, - NautilusIconLayoutMode mode); -void nautilus_icon_container_sort (NautilusIconContainer *container); -void nautilus_icon_container_freeze_icon_positions (NautilusIconContainer *container); - - -/* operations on all icons */ -void nautilus_icon_container_unselect_all (NautilusIconContainer *view); -void nautilus_icon_container_select_all (NautilusIconContainer *view); - - -/* operations on the selection */ -GList * nautilus_icon_container_get_selection (NautilusIconContainer *view); -void nautilus_icon_container_set_selection (NautilusIconContainer *view, - GList *selection); -GArray * nautilus_icon_container_get_selected_icon_locations (NautilusIconContainer *view); -gboolean nautilus_icon_container_has_stretch_handles (NautilusIconContainer *container); -gboolean nautilus_icon_container_is_stretched (NautilusIconContainer *container); -void nautilus_icon_container_show_stretch_handles (NautilusIconContainer *container); -void nautilus_icon_container_unstretch (NautilusIconContainer *container); -void nautilus_icon_container_start_renaming_selected_item (NautilusIconContainer *container); - -/* options */ -NautilusZoomLevel nautilus_icon_container_get_zoom_level (NautilusIconContainer *view); -void nautilus_icon_container_set_zoom_level (NautilusIconContainer *view, - int new_zoom_level); -void nautilus_icon_container_set_single_click_mode (NautilusIconContainer *container, - gboolean single_click_mode); -void nautilus_icon_container_enable_linger_selection (NautilusIconContainer *view, - gboolean enable); -gboolean nautilus_icon_container_get_anti_aliased_mode (NautilusIconContainer *view); -void nautilus_icon_container_set_anti_aliased_mode (NautilusIconContainer *view, - gboolean anti_aliased_mode); -void nautilus_icon_container_set_label_font_for_zoom_level (NautilusIconContainer *container, - int zoom_level, - GdkFont *font); -void nautilus_icon_container_set_smooth_label_font (NautilusIconContainer *container, - EelScalableFont *font); -gboolean nautilus_icon_container_get_is_fixed_size (NautilusIconContainer *container); -void nautilus_icon_container_set_is_fixed_size (NautilusIconContainer *container, - gboolean is_fixed_size); -void nautilus_icon_container_reset_scroll_region (NautilusIconContainer *container); -void nautilus_icon_container_set_font_size_table (NautilusIconContainer *container, - const int font_size_table[NAUTILUS_ZOOM_LEVEL_LARGEST + 1]); -void nautilus_icon_container_set_margins (NautilusIconContainer *container, - int left_margin, - int right_margin, - int top_margin, - int bottom_margin); - -#endif /* NAUTILUS_ICON_CONTAINER_H */ diff --git a/libnautilus-extensions/nautilus-icon-dnd.c b/libnautilus-extensions/nautilus-icon-dnd.c deleted file mode 100644 index 02a997bcc..000000000 --- a/libnautilus-extensions/nautilus-icon-dnd.c +++ /dev/null @@ -1,1366 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ - -/* nautilus-icon-dnd.c - Drag & drop handling for the icon container widget. - - Copyright (C) 1999, 2000 Free Software Foundation - Copyright (C) 2000 Eazel, Inc. - - The Gnome 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 Gnome 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 the Gnome 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. - - Authors: Ettore Perazzoli <ettore@gnu.org>, - Darin Adler <darin@eazel.com>, - Andy Hertzfeld <andy@eazel.com> - Pavel Cisler <pavel@eazel.com> -*/ - - -#include <config.h> -#include "nautilus-icon-dnd.h" - -#include "nautilus-file-dnd.h" -#include "nautilus-icon-private.h" -#include "nautilus-link.h" -#include <eel/eel-background.h> -#include <eel/eel-gdk-pixbuf-extensions.h> -#include <eel/eel-glib-extensions.h> -#include <eel/eel-gnome-extensions.h> -#include <eel/eel-graphic-effects.h> -#include <eel/eel-gtk-extensions.h> -#include <eel/eel-gtk-macros.h> -#include <eel/eel-stock-dialogs.h> -#include <eel/eel-string.h> -#include <eel/eel-vfs-extensions.h> -#include <gdk/gdkkeysyms.h> -#include <gdk/gdkx.h> -#include <gtk/gtkmain.h> -#include <gtk/gtksignal.h> -#include <libgnome/gnome-i18n.h> -#include <libgnomeui/gnome-canvas-rect-ellipse.h> -#include <libgnomeui/gnome-stock.h> -#include <libgnomeui/gnome-uidefs.h> -#include <libgnomevfs/gnome-vfs-uri.h> -#include <libgnomevfs/gnome-vfs-utils.h> -#include <math.h> -#include <stdio.h> -#include <string.h> - -static gboolean drag_drop_callback (GtkWidget *widget, - GdkDragContext *context, - int x, - int y, - guint32 time, - gpointer data); -static void nautilus_icon_dnd_update_drop_target (NautilusIconContainer *container, - GdkDragContext *context, - int x, - int y); -static gboolean drag_motion_callback (GtkWidget *widget, - GdkDragContext *context, - int x, - int y, - guint32 time); - -static void nautilus_icon_container_receive_dropped_icons (NautilusIconContainer *container, - GdkDragContext *context, - int x, int y); -static void receive_dropped_tile_image (NautilusIconContainer *container, - GtkSelectionData *data); -static void receive_dropped_keyword (NautilusIconContainer *container, - char* keyword, - int x, - int y); -static void receive_dropped_uri_list (NautilusIconContainer *container, - char* keyword, - int x, - int y); -static void nautilus_icon_container_free_drag_data (NautilusIconContainer *container); -static void set_drop_target (NautilusIconContainer *container, - NautilusIcon *icon); - - -static GtkTargetEntry drag_types [] = { - { EEL_ICON_DND_GNOME_ICON_LIST_TYPE, 0, EEL_ICON_DND_GNOME_ICON_LIST }, - { EEL_ICON_DND_URI_LIST_TYPE, 0, EEL_ICON_DND_URI_LIST }, - { EEL_ICON_DND_URL_TYPE, 0, EEL_ICON_DND_URL }, - { EEL_ICON_DND_TEXT_TYPE, 0, EEL_ICON_DND_TEXT } -}; - -static GtkTargetEntry drop_types [] = { - { EEL_ICON_DND_GNOME_ICON_LIST_TYPE, 0, EEL_ICON_DND_GNOME_ICON_LIST }, - { EEL_ICON_DND_URI_LIST_TYPE, 0, EEL_ICON_DND_URI_LIST }, - { EEL_ICON_DND_URL_TYPE, 0, EEL_ICON_DND_URL }, - { EEL_ICON_DND_COLOR_TYPE, 0, EEL_ICON_DND_COLOR }, - { EEL_ICON_DND_BGIMAGE_TYPE, 0, EEL_ICON_DND_BGIMAGE }, - { EEL_ICON_DND_KEYWORD_TYPE, 0, EEL_ICON_DND_KEYWORD } -}; - -static GtkTargetList *drop_types_list = NULL; - - -static GnomeCanvasItem * -create_selection_shadow (NautilusIconContainer *container, - GList *list) -{ - GnomeCanvasGroup *group; - GnomeCanvas *canvas; - GdkBitmap *stipple; - int max_x, max_y; - int min_x, min_y; - GList *p; - - if (list == NULL) { - return NULL; - } - - /* if we're only dragging a single item, don't worry about the shadow */ - if (list->next == NULL) { - return NULL; - } - - stipple = container->details->dnd_info->drag_info.stipple; - g_return_val_if_fail (stipple != NULL, NULL); - - canvas = GNOME_CANVAS (container); - - /* Creating a big set of rectangles in the canvas can be expensive, so - we try to be smart and only create the maximum number of rectangles - that we will need, in the vertical/horizontal directions. */ - - max_x = GTK_WIDGET (container)->allocation.width; - min_x = -max_x; - - max_y = GTK_WIDGET (container)->allocation.height; - min_y = -max_y; - - /* Create a group, so that it's easier to move all the items around at - once. */ - group = GNOME_CANVAS_GROUP - (gnome_canvas_item_new (GNOME_CANVAS_GROUP (canvas->root), - gnome_canvas_group_get_type (), - NULL)); - - for (p = list; p != NULL; p = p->next) { - EelDragSelectionItem *item; - int x1, y1, x2, y2; - - item = p->data; - - if (!item->got_icon_position) { - continue; - } - - x1 = item->icon_x; - y1 = item->icon_y; - x2 = x1 + item->icon_width; - y2 = y1 + item->icon_height; - - if (x2 >= min_x && x1 <= max_x && y2 >= min_y && y1 <= max_y) - gnome_canvas_item_new - (group, - gnome_canvas_rect_get_type (), - "x1", (double) x1, - "y1", (double) y1, - "x2", (double) x2, - "y2", (double) y2, - "outline_color", "black", - "outline_stipple", stipple, - "width_pixels", 1, - NULL); - } - - return GNOME_CANVAS_ITEM (group); -} - -/* Set the affine instead of the x and y position. - * Simple, and setting x and y was broken at one point. - */ -static void -set_shadow_position (GnomeCanvasItem *shadow, - double x, double y) -{ - double affine[6]; - - affine[0] = 1.0; - affine[1] = 0.0; - affine[2] = 0.0; - affine[3] = 1.0; - affine[4] = x; - affine[5] = y; - - gnome_canvas_item_affine_absolute (shadow, affine); -} - - -/* Source-side handling of the drag. */ - -/* iteration glue struct */ -typedef struct { - gpointer iterator_context; - EelDragEachSelectedItemDataGet iteratee; - gpointer iteratee_data; -} IconGetDataBinderContext; - -static gboolean -icon_get_data_binder (NautilusIcon *icon, gpointer data) -{ - IconGetDataBinderContext *context; - ArtDRect world_rect; - ArtIRect window_rect; - char *uri; - NautilusIconContainer *container; - - context = (IconGetDataBinderContext *)data; - - g_assert (NAUTILUS_IS_ICON_CONTAINER (context->iterator_context)); - - container = NAUTILUS_ICON_CONTAINER (context->iterator_context); - - world_rect = nautilus_icon_canvas_item_get_icon_rectangle (icon->item); - window_rect = eel_gnome_canvas_world_to_window_rectangle - (GNOME_CANVAS (container), world_rect); - - uri = nautilus_icon_container_get_icon_uri (container, icon); - if (uri == NULL) { - g_warning ("no URI for one of the iterated icons"); - return TRUE; - } - - window_rect = eel_art_irect_offset_by (window_rect, - - container->details->dnd_info->drag_info.start_x, - - container->details->dnd_info->drag_info.start_y); - - window_rect = eel_art_irect_scale_by (window_rect, - 1 / GNOME_CANVAS (container)->pixels_per_unit); - - /* pass the uri, mouse-relative x/y and icon width/height */ - context->iteratee (uri, - (int) window_rect.x0, - (int) window_rect.y0, - window_rect.x1 - window_rect.x0, - window_rect.y1 - window_rect.y0, - context->iteratee_data); - - g_free (uri); - - return TRUE; -} - -/* Iterate over each selected icon in a NautilusIconContainer, - * calling each_function on each. - */ -static void -nautilus_icon_container_each_selected_icon (NautilusIconContainer *container, - gboolean (*each_function) (NautilusIcon *, gpointer), gpointer data) -{ - GList *p; - NautilusIcon *icon; - - for (p = container->details->icons; p != NULL; p = p->next) { - icon = p->data; - if (!icon->is_selected) { - continue; - } - if (!each_function (icon, data)) { - return; - } - } -} - -/* Adaptor function used with nautilus_icon_container_each_selected_icon - * to help iterate over all selected items, passing uris, x, y, w and h - * values to the iteratee - */ -static void -each_icon_get_data_binder (EelDragEachSelectedItemDataGet iteratee, - gpointer iterator_context, gpointer data) -{ - IconGetDataBinderContext context; - NautilusIconContainer *container; - - g_assert (NAUTILUS_IS_ICON_CONTAINER (iterator_context)); - container = NAUTILUS_ICON_CONTAINER (iterator_context); - - context.iterator_context = iterator_context; - context.iteratee = iteratee; - context.iteratee_data = data; - nautilus_icon_container_each_selected_icon (container, icon_get_data_binder, &context); -} - -/* Called when the data for drag&drop is needed */ -static void -drag_data_get_callback (GtkWidget *widget, - GdkDragContext *context, - GtkSelectionData *selection_data, - guint info, - guint32 time, - gpointer data) -{ - g_assert (widget != NULL); - g_assert (NAUTILUS_IS_ICON_CONTAINER (widget)); - g_return_if_fail (context != NULL); - - /* Call common function from nautilus-drag that set's up - * the selection data in the right format. Pass it means to - * iterate all the selected icons. - */ - eel_drag_drag_data_get (widget, context, selection_data, - info, time, widget, each_icon_get_data_binder); -} - - -/* Target-side handling of the drag. */ - -static void -nautilus_icon_container_position_shadow (NautilusIconContainer *container, - int x, int y) -{ - GnomeCanvasItem *shadow; - double world_x, world_y; - - shadow = container->details->dnd_info->shadow; - if (shadow == NULL) { - return; - } - gnome_canvas_window_to_world (GNOME_CANVAS (container), - x, y, &world_x, &world_y); - - set_shadow_position (shadow, world_x, world_y); - gnome_canvas_item_show (shadow); -} - -static void -nautilus_icon_container_dropped_icon_feedback (GtkWidget *widget, - GtkSelectionData *data, - int x, int y) -{ - NautilusIconContainer *container; - NautilusIconDndInfo *dnd_info; - - container = NAUTILUS_ICON_CONTAINER (widget); - dnd_info = container->details->dnd_info; - - /* Delete old selection list. */ - eel_drag_destroy_selection_list (dnd_info->drag_info.selection_list); - dnd_info->drag_info.selection_list = NULL; - - /* Delete old shadow if any. */ - if (dnd_info->shadow != NULL) { - /* FIXME bugzilla.eazel.com 2484: - * Is a destroy really sufficient here? Who does the unref? */ - gtk_object_destroy (GTK_OBJECT (dnd_info->shadow)); - } - - /* Build the selection list and the shadow. */ - dnd_info->drag_info.selection_list = eel_drag_build_selection_list (data); - dnd_info->shadow = create_selection_shadow (container, dnd_info->drag_info.selection_list); - nautilus_icon_container_position_shadow (container, x, y); -} - -/** this callback is called in 2 cases. - It is called upon drag_motion events to get the actual data - In that case, it just makes sure it gets the data. - It is called upon drop_drop events to execute the actual - actions on the received action. In that case, it actually first makes sure - that we have got the data then processes it. -*/ - -static void -drag_data_received_callback (GtkWidget *widget, - GdkDragContext *context, - int x, - int y, - GtkSelectionData *data, - guint info, - guint32 time, - gpointer user_data) -{ - EelDragInfo *drag_info; - - drag_info = &(NAUTILUS_ICON_CONTAINER (widget)->details->dnd_info->drag_info); - - drag_info->got_drop_data_type = TRUE; - drag_info->data_type = info; - - switch (info) { - case EEL_ICON_DND_GNOME_ICON_LIST: - nautilus_icon_container_dropped_icon_feedback (widget, data, x, y); - break; - case EEL_ICON_DND_COLOR: - case EEL_ICON_DND_BGIMAGE: - case EEL_ICON_DND_KEYWORD: - case EEL_ICON_DND_URI_LIST: - /* Save the data so we can do the actual work on drop. */ - g_assert (drag_info->selection_data == NULL); - drag_info->selection_data = eel_gtk_selection_data_copy_deep (data); - break; - - /* Netscape keeps sending us the data, even though we accept the first drag */ - case EEL_ICON_DND_URL: - if (drag_info->selection_data != NULL) { - eel_gtk_selection_data_free_deep (drag_info->selection_data); - drag_info->selection_data = eel_gtk_selection_data_copy_deep (data); - } - break; - - default: - g_message ("drag_data_received_callback unknown"); - break; - } - - - /* this is the second use case of this callback. - * we have to do the actual work for the drop. - */ - if (drag_info->drop_occured) { - - switch (info) { - case EEL_ICON_DND_GNOME_ICON_LIST: - nautilus_icon_container_receive_dropped_icons - (NAUTILUS_ICON_CONTAINER (widget), - context, x, y); - gtk_drag_finish (context, TRUE, FALSE, time); - break; - case EEL_ICON_DND_COLOR: - eel_background_receive_dropped_color - (eel_get_widget_background (widget), - widget, x, y, data); - gtk_drag_finish (context, TRUE, FALSE, time); - break; - case EEL_ICON_DND_BGIMAGE: - receive_dropped_tile_image - (NAUTILUS_ICON_CONTAINER (widget), - data); - gtk_drag_finish (context, FALSE, FALSE, time); - break; - case EEL_ICON_DND_KEYWORD: - receive_dropped_keyword - (NAUTILUS_ICON_CONTAINER (widget), - (char*) data->data, x, y); - gtk_drag_finish (context, FALSE, FALSE, time); - break; - case EEL_ICON_DND_URI_LIST: - case EEL_ICON_DND_URL: - receive_dropped_uri_list - (NAUTILUS_ICON_CONTAINER (widget), - (char*) data->data, x, y); - gtk_drag_finish (context, TRUE, FALSE, time); - break; - - default: - gtk_drag_finish (context, FALSE, FALSE, time); - } - - nautilus_icon_container_free_drag_data (NAUTILUS_ICON_CONTAINER (widget)); - - set_drop_target (NAUTILUS_ICON_CONTAINER (widget), NULL); - - /* reinitialise it for the next dnd */ - drag_info->drop_occured = FALSE; - } - -} - -/* FIXME bugzilla.eazel.com 7445: Needs to become a shared function */ -static void -get_data_on_first_target_we_support (GtkWidget *widget, GdkDragContext *context, guint32 time) -{ - GList *target; - - if (drop_types_list == NULL) - drop_types_list = gtk_target_list_new (drop_types, - EEL_N_ELEMENTS (drop_types)); - - for (target = context->targets; target != NULL; target = target->next) { - guint dummy_info; - GdkAtom target_atom = GPOINTER_TO_UINT (target->data); - - if (gtk_target_list_find (drop_types_list, - target_atom, - &dummy_info)) { - gtk_drag_get_data (GTK_WIDGET (widget), context, - target_atom, - time); - break; - } - } -} - -static void -nautilus_icon_container_ensure_drag_data (NautilusIconContainer *container, - GdkDragContext *context, - guint32 time) -{ - NautilusIconDndInfo *dnd_info; - - dnd_info = container->details->dnd_info; - - if (!dnd_info->drag_info.got_drop_data_type) { - get_data_on_first_target_we_support (GTK_WIDGET (container), context, time); - } -} - -static void -drag_end_callback (GtkWidget *widget, - GdkDragContext *context, - gpointer data) -{ - NautilusIconContainer *container; - NautilusIconDndInfo *dnd_info; - - container = NAUTILUS_ICON_CONTAINER (widget); - dnd_info = container->details->dnd_info; - - eel_drag_destroy_selection_list (dnd_info->drag_info.selection_list); - dnd_info->drag_info.selection_list = NULL; -} - -static NautilusIcon * -nautilus_icon_container_item_at (NautilusIconContainer *container, - int x, int y) -{ - GList *p; - int size; - ArtDRect point; - ArtIRect canvas_point; - - /* build the hit-test rectangle. Base the size on the scale factor to ensure that it is - * non-empty even at the smallest scale factor - */ - - size = MAX (1, 1 + (1 / GNOME_CANVAS (container)->pixels_per_unit)); - point.x0 = x; - point.y0 = y; - point.x1 = x + size; - point.y1 = y + size; - - for (p = container->details->icons; p != NULL; p = p->next) { - NautilusIcon *icon; - icon = p->data; - - canvas_point = eel_gnome_canvas_world_to_canvas_rectangle (GNOME_CANVAS_ITEM (icon->item)->canvas, - point); - if (nautilus_icon_canvas_item_hit_test_rectangle (icon->item, canvas_point)) { - return icon; - } - } - - return NULL; -} - -static char * -get_container_uri (const NautilusIconContainer *container) -{ - char *uri; - - /* get the URI associated with the container */ - uri = NULL; - gtk_signal_emit_by_name (GTK_OBJECT (container), "get_container_uri", &uri); - return uri; -} - -static gboolean -nautilus_icon_container_selection_items_local (const NautilusIconContainer *container, - const GList *items) -{ - char *container_uri_string; - gboolean result; - - /* must have at least one item */ - g_assert (items); - - result = FALSE; - - /* get the URI associated with the container */ - container_uri_string = get_container_uri (container); - - if (eel_uri_is_trash (container_uri_string)) { - /* Special-case "trash:" because the eel_drag_items_local - * would not work for it. - */ - result = eel_drag_items_in_trash (items); - } else { - result = eel_drag_items_local (container_uri_string, items); - } - g_free (container_uri_string); - - return result; -} - -/* handle dropped tile images */ -static void -receive_dropped_tile_image (NautilusIconContainer *container, GtkSelectionData *data) -{ - g_assert (data != NULL); - eel_background_receive_dropped_background_image - (eel_get_widget_background (GTK_WIDGET (container)), data->data); -} - -/* handle dropped keywords */ -static void -receive_dropped_keyword (NautilusIconContainer *container, char* keyword, int x, int y) -{ - char *uri; - double world_x, world_y; - - NautilusIcon *drop_target_icon; - NautilusFile *file; - - g_assert (keyword != NULL); - - /* find the item we hit with our drop, if any */ - gnome_canvas_window_to_world (GNOME_CANVAS (container), x, y, &world_x, &world_y); - drop_target_icon = nautilus_icon_container_item_at (container, world_x, world_y); - if (drop_target_icon == NULL) { - return; - } - - /* FIXME bugzilla.eazel.com 2485: - * This does not belong in the icon code. - * It has to be in the file manager. - * The icon code has no right to deal with the file directly. - * But luckily there's no issue of not getting a file object, - * so we don't have to worry about async. issues here. - */ - uri = nautilus_icon_container_get_icon_uri (container, drop_target_icon); - file = nautilus_file_get (uri); - g_free (uri); - - nautilus_drag_file_receive_dropped_keyword (file, keyword); - - nautilus_file_unref (file); - nautilus_icon_container_update_icon (container, drop_target_icon); -} - -/* handle dropped uri list */ -static void -receive_dropped_uri_list (NautilusIconContainer *container, char *uri_list, int x, int y) -{ - if (uri_list == NULL) { - return; - } - - gtk_signal_emit_by_name (GTK_OBJECT (container), "handle_uri_list", - uri_list, - x, y); -} - -static int -auto_scroll_timeout_callback (gpointer data) -{ - NautilusIconContainer *container; - GtkWidget *widget; - float x_scroll_delta, y_scroll_delta; - GdkRectangle exposed_area; - - g_assert (NAUTILUS_IS_ICON_CONTAINER (data)); - widget = GTK_WIDGET (data); - container = NAUTILUS_ICON_CONTAINER (widget); - - if (container->details->dnd_info->drag_info.waiting_to_autoscroll - && container->details->dnd_info->drag_info.start_auto_scroll_in > eel_get_system_time()) { - /* not yet */ - return TRUE; - } - - container->details->dnd_info->drag_info.waiting_to_autoscroll = FALSE; - - eel_drag_autoscroll_calculate_delta (widget, &x_scroll_delta, &y_scroll_delta); - if (x_scroll_delta == 0 && y_scroll_delta == 0) { - /* no work */ - return TRUE; - } - - if (!nautilus_icon_container_scroll (container, (int)x_scroll_delta, (int)y_scroll_delta)) { - /* the scroll value got pinned to a min or max adjustment value, - * we ended up not scrolling - */ - return TRUE; - } - - /* update cached drag start offsets */ - container->details->dnd_info->drag_info.start_x -= x_scroll_delta; - container->details->dnd_info->drag_info.start_y -= y_scroll_delta; - - /* Due to a glitch in GtkLayout, whe need to do an explicit draw of the exposed - * area. - * Calculate the size of the area we need to draw - */ - exposed_area.x = widget->allocation.x; - exposed_area.y = widget->allocation.y; - exposed_area.width = widget->allocation.width; - exposed_area.height = widget->allocation.height; - - if (x_scroll_delta > 0) { - exposed_area.x = exposed_area.width - x_scroll_delta; - } else if (x_scroll_delta < 0) { - exposed_area.width = -x_scroll_delta; - } - - if (y_scroll_delta > 0) { - exposed_area.y = exposed_area.height - y_scroll_delta; - } else if (y_scroll_delta < 0) { - exposed_area.height = -y_scroll_delta; - } - - /* offset it to 0, 0 */ - exposed_area.x -= widget->allocation.x; - exposed_area.y -= widget->allocation.y; - - gtk_widget_draw (widget, &exposed_area); - - return TRUE; -} - -static void -set_up_auto_scroll_if_needed (NautilusIconContainer *container) -{ - eel_drag_autoscroll_start (&container->details->dnd_info->drag_info, - GTK_WIDGET (container), - auto_scroll_timeout_callback, - container); -} - -static void -stop_auto_scroll (NautilusIconContainer *container) -{ - eel_drag_autoscroll_stop (&container->details->dnd_info->drag_info); -} - -static gboolean -confirm_switch_to_manual_layout (NautilusIconContainer *container) -{ - const char *message; - GnomeDialog *dialog; - - /* FIXME bugzilla.eazel.com 915: Use of the word "directory" - * makes this FMIconView specific. Move these messages into - * FMIconView so NautilusIconContainer can be used for things - * that are not directories? - */ - if (nautilus_icon_container_has_stored_icon_positions (container)) { - if (eel_g_list_exactly_one_item (container->details->dnd_info->drag_info.selection_list)) { - message = _("This folder uses automatic layout. " - "Do you want to switch to manual layout and leave this item where you dropped it? " - "This will clobber the stored manual layout."); - } else { - message = _("This folder uses automatic layout. " - "Do you want to switch to manual layout and leave these items where you dropped them? " - "This will clobber the stored manual layout."); - } - } else { - if (eel_g_list_exactly_one_item (container->details->dnd_info->drag_info.selection_list)) { - message = _("This folder uses automatic layout. " - "Do you want to switch to manual layout and leave this item where you dropped it?"); - } else { - message = _("This folder uses automatic layout. " - "Do you want to switch to manual layout and leave these items where you dropped them?"); - } - } - - dialog = eel_show_yes_no_dialog (message, _("Switch to Manual Layout?"), - _("Switch"), GNOME_STOCK_BUTTON_CANCEL, - GTK_WINDOW (gtk_widget_get_ancestor - (GTK_WIDGET (container), GTK_TYPE_WINDOW))); - - return gnome_dialog_run (dialog) == GNOME_OK; -} - -static void -handle_local_move (NautilusIconContainer *container, - double world_x, double world_y) -{ - GList *moved_icons, *p; - EelDragSelectionItem *item; - NautilusIcon *icon; - - if (container->details->auto_layout) { - if (!confirm_switch_to_manual_layout (container)) { - return; - } - nautilus_icon_container_freeze_icon_positions (container); - } - - /* Move and select the icons. */ - moved_icons = NULL; - for (p = container->details->dnd_info->drag_info.selection_list; p != NULL; p = p->next) { - item = p->data; - - icon = nautilus_icon_container_get_icon_by_uri - (container, item->uri); - - if (item->got_icon_position) { - nautilus_icon_container_move_icon - (container, icon, - world_x + item->icon_x, world_y + item->icon_y, - icon->scale_x, icon->scale_y, - TRUE, TRUE); - } - moved_icons = g_list_prepend (moved_icons, icon); - } - nautilus_icon_container_select_list_unselect_others - (container, moved_icons); - /* Might have been moved in a way that requires adjusting scroll region. */ - nautilus_icon_container_update_scroll_region (container); - g_list_free (moved_icons); -} - -static void -handle_nonlocal_move (NautilusIconContainer *container, - GdkDragContext *context, - int x, int y, - const char *target_uri, - gboolean icon_hit) -{ - GList *source_uris, *p; - GArray *source_item_locations; - int index; - - if (container->details->dnd_info->drag_info.selection_list == NULL) { - return; - } - - source_uris = NULL; - for (p = container->details->dnd_info->drag_info.selection_list; p != NULL; p = p->next) { - /* do a shallow copy of all the uri strings of the copied files */ - source_uris = g_list_prepend (source_uris, ((EelDragSelectionItem *)p->data)->uri); - } - source_uris = g_list_reverse (source_uris); - - source_item_locations = g_array_new (FALSE, TRUE, sizeof (GdkPoint)); - if (!icon_hit) { - /* Drop onto a container. Pass along the item points to allow placing - * the items in their same relative positions in the new container. - */ - source_item_locations = g_array_set_size (source_item_locations, - g_list_length (container->details->dnd_info->drag_info.selection_list)); - - for (index = 0, p = container->details->dnd_info->drag_info.selection_list; - p != NULL; index++, p = p->next) { - g_array_index (source_item_locations, GdkPoint, index).x = - ((EelDragSelectionItem *)p->data)->icon_x; - g_array_index (source_item_locations, GdkPoint, index).y = - ((EelDragSelectionItem *)p->data)->icon_y; - } - } - - /* start the copy */ - gtk_signal_emit_by_name (GTK_OBJECT (container), "move_copy_items", - source_uris, - source_item_locations, - target_uri, - context->action, - x, y); - - g_list_free (source_uris); - g_array_free (source_item_locations, TRUE); -} - -static char * -nautilus_icon_container_find_drop_target (NautilusIconContainer *container, - GdkDragContext *context, - int x, int y, - gboolean *icon_hit) -{ - NautilusIcon *drop_target_icon; - double world_x, world_y; - NautilusFile *file; - char *icon_uri; - - *icon_hit = FALSE; - if (container->details->dnd_info->drag_info.selection_list == NULL) { - return NULL; - } - - gnome_canvas_window_to_world (GNOME_CANVAS (container), - x, y, &world_x, &world_y); - - /* FIXME bugzilla.eazel.com 2485: - * These "can_accept_items" tests need to be done by - * the icon view, not here. This file is not supposed to know - * that the target is a file. - */ - - /* Find the item we hit with our drop, if any */ - drop_target_icon = nautilus_icon_container_item_at (container, world_x, world_y); - if (drop_target_icon != NULL) { - icon_uri = nautilus_icon_container_get_icon_uri (container, drop_target_icon); - if (icon_uri != NULL) { - file = nautilus_file_get (icon_uri); - - if (!nautilus_drag_can_accept_items (file, - container->details->dnd_info->drag_info.selection_list)) { - /* the item we dropped our selection on cannot accept the items, - * do the same thing as if we just dropped the items on the canvas - */ - drop_target_icon = NULL; - } - - g_free (icon_uri); - nautilus_file_unref (file); - } - } - - if (drop_target_icon == NULL) { - *icon_hit = FALSE; - return get_container_uri (container); - } - - *icon_hit = TRUE; - return nautilus_icon_container_get_icon_drop_target_uri (container, drop_target_icon); -} - -/* FIXME bugzilla.eazel.com 2485: This belongs in FMDirectoryView, not here. */ -static gboolean -selection_includes_special_link (GList *selection_list) -{ - GList *node; - char *uri, *local_path; - gboolean link_in_selection; - - link_in_selection = FALSE; - - for (node = selection_list; node != NULL; node = node->next) { - uri = ((EelDragSelectionItem *) node->data)->uri; - - /* FIXME bugzilla.eazel.com 3020: This does sync. I/O and works only locally. */ - local_path = gnome_vfs_get_local_path_from_uri (uri); - link_in_selection = local_path != NULL - && (nautilus_link_local_is_trash_link (local_path) || nautilus_link_local_is_home_link (local_path) || - nautilus_link_local_is_volume_link (local_path)); - g_free (local_path); - - if (link_in_selection) { - break; - } - } - - return link_in_selection; -} - -static void -nautilus_icon_container_receive_dropped_icons (NautilusIconContainer *container, - GdkDragContext *context, - int x, int y) -{ - char *drop_target; - gboolean local_move_only; - double world_x, world_y; - gboolean icon_hit; - GdkDragAction action; - - drop_target = NULL; - - if (container->details->dnd_info->drag_info.selection_list == NULL) { - return; - } - - if (context->action == GDK_ACTION_ASK) { - /* FIXME bugzilla.eazel.com 2485: This belongs in FMDirectoryView, not here. */ - /* Check for special case items in selection list */ - if (selection_includes_special_link (container->details->dnd_info->drag_info.selection_list)) { - /* We only want to move the trash */ - action = GDK_ACTION_MOVE; - } else { - action = GDK_ACTION_MOVE | GDK_ACTION_COPY | GDK_ACTION_LINK; - } - context->action = eel_drag_drop_action_ask (action); - } - - if (context->action > 0) { - gnome_canvas_window_to_world (GNOME_CANVAS (container), - x, y, &world_x, &world_y); - - drop_target = nautilus_icon_container_find_drop_target (container, - context, x, y, &icon_hit); - - local_move_only = FALSE; - if (!icon_hit && context->action == GDK_ACTION_MOVE) { - /* we can just move the icon positions if the move ended up in - * the item's parent container - */ - local_move_only = nautilus_icon_container_selection_items_local - (container, container->details->dnd_info->drag_info.selection_list); - } - - if (local_move_only) { - handle_local_move (container, world_x, world_y); - } else { - handle_nonlocal_move (container, context, world_x, world_y, drop_target, icon_hit); - } - } - - g_free (drop_target); - eel_drag_destroy_selection_list (container->details->dnd_info->drag_info.selection_list); - container->details->dnd_info->drag_info.selection_list = NULL; -} - -static void -nautilus_icon_container_get_drop_action (NautilusIconContainer *container, - GdkDragContext *context, - int x, int y, - int *default_action, - int *non_default_action) -{ - char *drop_target; - gboolean icon_hit; - NautilusIcon *icon; - double world_x, world_y; - - icon_hit = FALSE; - if (!container->details->dnd_info->drag_info.got_drop_data_type) { - /* drag_data_received_callback didn't get called yet */ - return; - } - - /* find out if we're over an icon */ - gnome_canvas_window_to_world (GNOME_CANVAS (container), - x, y, &world_x, &world_y); - - icon = nautilus_icon_container_item_at (container, world_x, world_y); - - /* case out on the type of object being dragged */ - switch (container->details->dnd_info->drag_info.data_type) { - case EEL_ICON_DND_GNOME_ICON_LIST: - if (container->details->dnd_info->drag_info.selection_list == NULL) { - *default_action = 0; - *non_default_action = 0; - return; - } - drop_target = nautilus_icon_container_find_drop_target (container, - context, x, y, &icon_hit); - if (!drop_target) { - *default_action = 0; - *non_default_action = 0; - return; - } - eel_drag_default_drop_action_for_icons (context, drop_target, - container->details->dnd_info->drag_info.selection_list, - default_action, non_default_action); - g_free (drop_target); - break; - - /* handle emblems by setting the action if we're over an object */ - case EEL_ICON_DND_KEYWORD: - if (icon == NULL) { - *default_action = 0; - *non_default_action = 0; - } else { - *default_action = context->suggested_action; - *non_default_action = context->suggested_action; - } - - break; - - /* handle colors and backgrounds by setting the action if we're over the background */ - case EEL_ICON_DND_COLOR: - case EEL_ICON_DND_BGIMAGE: - if (icon == NULL) { - *default_action = context->suggested_action; - *non_default_action = context->suggested_action; - } else { - *default_action = 0; - *non_default_action = 0; - } - - break; - - case EEL_ICON_DND_URI_LIST: - case EEL_ICON_DND_URL: - *default_action = context->suggested_action; - *non_default_action = context->suggested_action; - break; - - default: - } - -} - -static void -set_drop_target (NautilusIconContainer *container, - NautilusIcon *icon) -{ - NautilusIcon *old_icon; - - /* Check if current drop target changed, update icon drop - * higlight if needed. - */ - old_icon = container->details->drop_target; - if (icon == old_icon) { - return; - } - - /* Remember the new drop target for the next round. */ - container->details->drop_target = icon; - nautilus_icon_container_update_icon (container, old_icon); - nautilus_icon_container_update_icon (container, icon); -} - -static void -nautilus_icon_dnd_update_drop_target (NautilusIconContainer *container, - GdkDragContext *context, - int x, int y) -{ - NautilusIcon *icon; - double world_x, world_y; - - g_assert (NAUTILUS_IS_ICON_CONTAINER (container)); - if ((container->details->dnd_info->drag_info.selection_list == NULL) - && (container->details->dnd_info->drag_info.data_type != EEL_ICON_DND_KEYWORD)) { - return; - } - - gnome_canvas_window_to_world (GNOME_CANVAS (container), - x, y, &world_x, &world_y); - - /* Find the item we hit with our drop, if any. */ - icon = nautilus_icon_container_item_at (container, world_x, world_y); - - /* FIXME bugzilla.eazel.com 2485: - * These "can_accept_items" tests need to be done by - * the icon view, not here. This file is not supposed to know - * that the target is a file. - */ - - /* Find if target icon accepts our drop. */ - if (icon != NULL - && (container->details->dnd_info->drag_info.data_type != EEL_ICON_DND_KEYWORD) - && !nautilus_drag_can_accept_items - (nautilus_file_get ( - nautilus_icon_container_get_icon_uri (container, icon)), - container->details->dnd_info->drag_info.selection_list)) { - icon = NULL; - } - - set_drop_target (container, icon); -} - -static void -nautilus_icon_container_free_drag_data (NautilusIconContainer *container) -{ - NautilusIconDndInfo *dnd_info; - - dnd_info = container->details->dnd_info; - - dnd_info->drag_info.got_drop_data_type = FALSE; - - if (dnd_info->shadow != NULL) { - gtk_object_destroy (GTK_OBJECT (dnd_info->shadow)); - dnd_info->shadow = NULL; - } - - if (dnd_info->drag_info.selection_data != NULL) { - eel_gtk_selection_data_free_deep (dnd_info->drag_info.selection_data); - dnd_info->drag_info.selection_data = NULL; - } -} - -static void -drag_leave_callback (GtkWidget *widget, - GdkDragContext *context, - guint32 time, - gpointer data) -{ - NautilusIconDndInfo *dnd_info; - - dnd_info = NAUTILUS_ICON_CONTAINER (widget)->details->dnd_info; - - if (dnd_info->shadow != NULL) - gnome_canvas_item_hide (dnd_info->shadow); - - stop_auto_scroll (NAUTILUS_ICON_CONTAINER (widget)); - nautilus_icon_container_free_drag_data(NAUTILUS_ICON_CONTAINER (widget)); -} - -void -nautilus_icon_dnd_init (NautilusIconContainer *container, - GdkBitmap *stipple) -{ - g_return_if_fail (container != NULL); - g_return_if_fail (NAUTILUS_IS_ICON_CONTAINER (container)); - - - container->details->dnd_info = g_new0 (NautilusIconDndInfo, 1); - eel_drag_init (&container->details->dnd_info->drag_info, - drag_types, EEL_N_ELEMENTS (drag_types), stipple); - - /* Set up the widget as a drag destination. - * (But not a source, as drags starting from this widget will be - * implemented by dealing with events manually.) - */ - gtk_drag_dest_set (GTK_WIDGET (container), - 0, - drop_types, EEL_N_ELEMENTS (drop_types), - GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK - | GDK_ACTION_ASK); - - /* Messages for outgoing drag. */ - gtk_signal_connect (GTK_OBJECT (container), "drag_data_get", - GTK_SIGNAL_FUNC (drag_data_get_callback), NULL); - gtk_signal_connect (GTK_OBJECT (container), "drag_end", - GTK_SIGNAL_FUNC (drag_end_callback), NULL); - - /* Messages for incoming drag. */ - gtk_signal_connect (GTK_OBJECT (container), "drag_data_received", - GTK_SIGNAL_FUNC (drag_data_received_callback), NULL); - gtk_signal_connect (GTK_OBJECT (container), "drag_motion", - GTK_SIGNAL_FUNC (drag_motion_callback), NULL); - gtk_signal_connect (GTK_OBJECT (container), "drag_drop", - GTK_SIGNAL_FUNC (drag_drop_callback), NULL); - gtk_signal_connect (GTK_OBJECT (container), "drag_leave", - GTK_SIGNAL_FUNC (drag_leave_callback), NULL); - -} - -void -nautilus_icon_dnd_fini (NautilusIconContainer *container) -{ - g_return_if_fail (container != NULL); - g_return_if_fail (NAUTILUS_IS_ICON_CONTAINER (container)); - g_return_if_fail (container->details->dnd_info != NULL); - - stop_auto_scroll (container); - if (container->details->dnd_info->shadow != NULL) { - /* FIXME bugzilla.eazel.com 2484: - * Is a destroy really sufficient here? Who does the unref? */ - gtk_object_destroy (GTK_OBJECT (container->details->dnd_info->shadow)); - } - - eel_drag_finalize (&container->details->dnd_info->drag_info); -} - -void -nautilus_icon_dnd_begin_drag (NautilusIconContainer *container, - GdkDragAction actions, - int button, - GdkEventMotion *event) -{ - NautilusIconDndInfo *dnd_info; - GnomeCanvas *canvas; - GdkDragContext *context; - GdkPixbuf *pixbuf; - int x_offset, y_offset; - ArtDRect world_rect; - ArtIRect window_rect; - - g_return_if_fail (NAUTILUS_IS_ICON_CONTAINER (container)); - g_return_if_fail (event != NULL); - - dnd_info = container->details->dnd_info; - g_return_if_fail (dnd_info != NULL); - - /* Notice that the event is in world coordinates, because of - the way the canvas handles events. - */ - canvas = GNOME_CANVAS (container); - gnome_canvas_world_to_window (canvas, - event->x, event->y, - &dnd_info->drag_info.start_x, &dnd_info->drag_info.start_y); - - /* start the drag */ - context = gtk_drag_begin (GTK_WIDGET (container), - dnd_info->drag_info.target_list, - actions, - button, - (GdkEvent *) event); - - - /* create a pixmap and mask to drag with */ - pixbuf = nautilus_icon_canvas_item_get_image (container->details->drag_icon->item); - - /* we want to drag semi-transparent pixbufs, but X is too slow dealing with - stippled masks, so we had to remove the code; this comment is left as a memorial - to it, with the hope that we get it back someday as X Windows improves */ - - /* compute the image's offset */ - world_rect = nautilus_icon_canvas_item_get_icon_rectangle ( - container->details->drag_icon->item); - window_rect = eel_gnome_canvas_world_to_window_rectangle - (canvas, world_rect); - x_offset = dnd_info->drag_info.start_x - window_rect.x0; - y_offset = dnd_info->drag_info.start_y - window_rect.y0; - - /* set the icon for dragging */ - eel_drag_set_icon_pixbuf (context, pixbuf, x_offset, y_offset); -} - -static gboolean -drag_motion_callback (GtkWidget *widget, - GdkDragContext *context, - int x, int y, - guint32 time) -{ - int default_action, non_default_action; - int resulting_action; - - nautilus_icon_container_ensure_drag_data (NAUTILUS_ICON_CONTAINER (widget), context, time); - nautilus_icon_container_position_shadow (NAUTILUS_ICON_CONTAINER (widget), x, y); - nautilus_icon_dnd_update_drop_target (NAUTILUS_ICON_CONTAINER (widget), context, x, y); - set_up_auto_scroll_if_needed (NAUTILUS_ICON_CONTAINER (widget)); - /* Find out what the drop actions are based on our drag selection and - * the drop target. - */ - nautilus_icon_container_get_drop_action (NAUTILUS_ICON_CONTAINER (widget), context, x, y, - &default_action, &non_default_action); - - /* set the right drop action, choose based on modifier key state - */ - resulting_action = eel_drag_modifier_based_action (default_action, - non_default_action); - gdk_drag_status (context, resulting_action, time); - - return TRUE; -} - -static gboolean -drag_drop_callback (GtkWidget *widget, - GdkDragContext *context, - int x, - int y, - guint32 time, - gpointer data) -{ - NautilusIconDndInfo *dnd_info; - - dnd_info = NAUTILUS_ICON_CONTAINER (widget)->details->dnd_info; - - - /* tell the drag_data_received callback that - the drop occured and that it can actually - process the actions. - make sure it is going to be called at least once. - */ - dnd_info->drag_info.drop_occured = TRUE; - - get_data_on_first_target_we_support (widget, context, time); - - return FALSE; -} - -void -nautilus_icon_dnd_end_drag (NautilusIconContainer *container) -{ - NautilusIconDndInfo *dnd_info; - - g_return_if_fail (NAUTILUS_IS_ICON_CONTAINER (container)); - - dnd_info = container->details->dnd_info; - g_return_if_fail (dnd_info != NULL); - stop_auto_scroll (container); - /* Do nothing. - * Can that possibly be right? - */ -} - diff --git a/libnautilus-extensions/nautilus-icon-dnd.h b/libnautilus-extensions/nautilus-icon-dnd.h deleted file mode 100644 index 5dd83cc44..000000000 --- a/libnautilus-extensions/nautilus-icon-dnd.h +++ /dev/null @@ -1,53 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ - -/* nautilus-icon-dnd.h - Drag & drop handling for the icon container widget. - - Copyright (C) 1999, 2000 Free Software Foundation - Copyright (C) 2000 Eazel, Inc. - - The Gnome 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 Gnome 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 the Gnome 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. - - Authors: Ettore Perazzoli <ettore@gnu.org>, - Darin Adler <darin@eazel.com>, - Andy Hertzfeld <andy@eazel.com> -*/ - -#ifndef NAUTILUS_ICON_DND_H -#define NAUTILUS_ICON_DND_H - -#include "nautilus-icon-container.h" -#include <eel/eel-dnd.h> - -/* DnD-related information. */ -typedef struct { - /* inherited drag info context */ - EelDragInfo drag_info; - - /* Shadow for the icons being dragged. */ - GnomeCanvasItem *shadow; -} NautilusIconDndInfo; - - -void nautilus_icon_dnd_init (NautilusIconContainer *container, - GdkBitmap *stipple); -void nautilus_icon_dnd_fini (NautilusIconContainer *container); -void nautilus_icon_dnd_begin_drag (NautilusIconContainer *container, - GdkDragAction actions, - gint button, - GdkEventMotion *event); -void nautilus_icon_dnd_end_drag (NautilusIconContainer *container); - -#endif /* NAUTILUS_ICON_DND_H */ diff --git a/libnautilus-extensions/nautilus-icon-factory-private.h b/libnautilus-extensions/nautilus-icon-factory-private.h deleted file mode 100644 index 5b57b12e2..000000000 --- a/libnautilus-extensions/nautilus-icon-factory-private.h +++ /dev/null @@ -1,39 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- - - nautilus-icon-factory-private.h: Private interface for use within - the icon factory code. - - 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. - - Author: Darin Adler <darin@eazel.com> -*/ - -#ifndef NAUTILUS_ICON_FACTORY_PRIVATE_H -#define NAUTILUS_ICON_FACTORY_PRIVATE_H - -#include "nautilus-icon-factory.h" - -/* For now, images are used themselves as thumbnails when they are - * below this threshold size. Later we might have to have a more - * complex rule about when to use an image for itself. - */ -#define SELF_THUMBNAIL_SIZE_THRESHOLD 16384 - -void nautilus_icon_factory_remove_by_uri (const char *uri); - -#endif /* NAUTILUS_ICON_FACTORY_PRIVATE_H */ diff --git a/libnautilus-extensions/nautilus-icon-factory.c b/libnautilus-extensions/nautilus-icon-factory.c deleted file mode 100644 index fbc6c6e53..000000000 --- a/libnautilus-extensions/nautilus-icon-factory.c +++ /dev/null @@ -1,2787 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- - - nautilus-icon-factory.c: Class for obtaining icons for files and other objects. - - Copyright (C) 1999, 2000 Red Hat Inc. - Copyright (C) 1999, 2000, 2001 Eazel, Inc. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public - License along with this program; if not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. - - Authors: John Sullivan <sullivan@eazel.com>, - Darin Adler <darin@eazel.com>, - Andy Hertzfeld <andy@eazel.com> -*/ - -#include <config.h> -#include "nautilus-icon-factory.h" - -#include "nautilus-default-file-icon.h" -#include "nautilus-file-attributes.h" -#include "nautilus-file-utilities.h" -#include "nautilus-global-preferences.h" -#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" -#include <eel/eel-gdk-extensions.h> -#include <eel/eel-gdk-pixbuf-extensions.h> -#include <eel/eel-gdk-pixbuf-extensions.h> -#include <eel/eel-glib-extensions.h> -#include <eel/eel-gtk-macros.h> -#include <eel/eel-scalable-font.h> -#include <eel/eel-smooth-text-layout.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 <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-handlers.h> -#include <libgnomevfs/gnome-vfs-mime-info.h> -#include <libgnomevfs/gnome-vfs-mime-monitor.h> -#include <libgnomevfs/gnome-vfs-types.h> -#include <librsvg/rsvg.h> -#include <stdio.h> -#include <string.h> - -/* List of suffixes to search when looking for an icon file. */ -static const char *icon_file_name_suffixes[] = -{ - ".svg", - ".SVG", - ".png", - ".PNG", - ".gif", - ".GIF", - ".jpg", - ".JPG", - ".xpm", - ".XPM" -}; - -#define ICON_NAME_BLOCK_DEVICE "i-blockdev" -#define ICON_NAME_BROKEN_SYMBOLIC_LINK "i-symlink" -#define ICON_NAME_CHARACTER_DEVICE "i-chardev" -#define ICON_NAME_DIRECTORY "i-directory" -#define ICON_NAME_EXECUTABLE "i-executable" -#define ICON_NAME_FIFO "i-fifo" -#define ICON_NAME_INSTALL "services-rpm" -#define ICON_NAME_REGULAR "i-regular" -#define ICON_NAME_SEARCH_RESULTS "i-search" -#define ICON_NAME_SOCKET "i-sock" -#define ICON_NAME_THUMBNAIL_LOADING "loading" -#define ICON_NAME_TRASH_EMPTY "trash-empty" -#define ICON_NAME_TRASH_NOT_EMPTY "trash-full" -#define ICON_NAME_WEB "i-web" - -#define EMBLEM_NAME_PREFIX "emblem-" -#define EMBLEM_SCALE_FACTOR 0.75 - -/* This used to be called ICON_CACHE_MAX_ENTRIES, but it's misleading - * to call it that, since we can have any number of entries in the - * cache if the caller keeps the pixbuf around (we only get rid of - * items from the cache after the caller unref's them). -*/ -#define ICON_CACHE_COUNT 20 - -/* This is the number of milliseconds we wait before sweeping out - * items from the cache. - */ -#define ICON_CACHE_SWEEP_TIMEOUT (10 * 1000) - -/* Images are used themselves as thumbnails when they are below this - * threshold size. - */ -/* FIXME bugzilla.eazel.com 5081: Later we might have to have a more - * complex rule about when to use an image for itself. - */ -#define SELF_THUMBNAIL_SIZE_THRESHOLD 16384 - -/* Maximum size for either dimension at the standard zoom level. */ -#define MAXIMUM_ICON_SIZE 96 - -/* Embedded text font size and text line settings */ - -/* FIXME; Hard coded font size */ -#define EMBEDDED_TEXT_FONT_SIZE 9 -#define EMBEDDED_TEXT_LINE_SPACING 1 -#define EMBEDDED_TEXT_EMPTY_LINE_HEIGHT 4 - -#define MINIMUM_EMBEDDED_TEXT_RECT_WIDTH 20 -#define MINIMUM_EMBEDDED_TEXT_RECT_HEIGHT 20 - -/* This circular doubly-linked list structure is used to keep a list - * of the most recently used items in the cache. - */ -typedef struct CircularList CircularList; -struct CircularList { - CircularList *next; - CircularList *prev; -}; - -/* The icon factory. - * These are just globals, but they're in an object so we can - * connect signals and have multiple icon factories some day - * if we want to. - */ -typedef struct { - GtkObject object; - - /* name of current theme */ - char *theme_name; - gboolean theme_is_in_user_directory; - - /* name of default theme, so it can be delegated */ - char *default_theme_name; - gboolean default_theme_is_in_user_directory; - - /* A hash table so we pass out the same scalable icon pointer - * every time someone asks for the same icon. Scalable icons - * are removed from this hash table when they are destroyed. - */ - GHashTable *scalable_icons; - - /* A hash table so we can find a cached icon's data structure - * from the pixbuf. - */ - GHashTable *cache_icons; - - /* A hash table that contains the icons. A circular list of - * the most recently used icons is kept around, and we don't - * let them go when we sweep the cache. - */ - GHashTable *icon_cache; - CircularList recently_used_dummy_head; - guint recently_used_count; - guint sweep_timer; -} NautilusIconFactory; - -#define NAUTILUS_ICON_FACTORY(obj) \ - GTK_CHECK_CAST (obj, nautilus_icon_factory_get_type (), NautilusIconFactory) - -typedef struct { - GtkObjectClass parent_class; -} NautilusIconFactoryClass; - -enum { - ICONS_CHANGED, - LAST_SIGNAL -}; -static guint signals[LAST_SIGNAL]; - -/* A scalable icon, which is basically the name and path of an icon, - * before we load the actual pixels of the icons's pixbuf. - */ -struct NautilusScalableIcon { - guint ref_count; - - char *uri; - char *mime_type; - char *name; - char *modifier; - char *embedded_text; -}; - -typedef enum { - REQUEST_NORMAL, - REQUEST_PICKY_CUSTOM_ONLY, - REQUEST_PICKY_BY_NAME_FIRST_CHOICE, - REQUEST_PICKY_BY_NAME_SECOND_CHOICE -} IconRequest; - -/* A request for an icon of a particular size. */ -typedef struct { - guint nominal_width; - guint nominal_height; - guint maximum_width; - guint maximum_height; - gboolean optimized_for_aa; -} IconSizeRequest; - -typedef struct { - ArtIRect text_rect; - NautilusEmblemAttachPoints attach_points; -} IconDetails; - -/* The key to a hash table that holds the scaled icons as pixbufs. */ -typedef struct { - NautilusScalableIcon *scalable_icon; - IconSizeRequest size; -} CacheKey; - -/* The value in the same table. */ -typedef struct { - GdkPixbuf *pixbuf; - IconDetails details; - - /* If true, outside clients have refs to the pixbuf. */ - gboolean outstanding; - - /* Number of internal clients with refs to the pixbuf. */ - guint internal_ref_count; - - /* Used to decide when to kick icons out of the cache. */ - CircularList recently_used_node; - - /* Used to know when to make a new thumbnail. */ - time_t cache_time; - - /* Type of icon. */ - IconRequest request; - gboolean scaled; - gboolean is_fallback; -} CacheIcon; - -static CacheIcon *fallback_icon; -static int cached_thumbnail_limit; - -/* forward declarations */ - -static guint nautilus_icon_factory_get_type (void); -static void nautilus_icon_factory_initialize_class (NautilusIconFactoryClass *class); -static void nautilus_icon_factory_initialize (NautilusIconFactory *factory); -static void nautilus_icon_factory_destroy (GtkObject *object); -static void icon_theme_changed_callback (gpointer user_data); -static void thumbnail_limit_changed_callback (gpointer user_data); -static void mime_type_data_changed_callback (GnomeVFSMIMEMonitor *monitor, - gpointer user_data); -static guint nautilus_scalable_icon_hash (gconstpointer p); -static gboolean nautilus_scalable_icon_equal (gconstpointer a, - gconstpointer b); -static guint cache_key_hash (gconstpointer p); -static gboolean cache_key_equal (gconstpointer a, - gconstpointer b); -static CacheIcon *get_icon_from_cache (NautilusScalableIcon *scalable_icon, - const IconSizeRequest *size, - IconRequest type); -static CacheIcon *load_icon_with_embedded_text (NautilusScalableIcon *scalable_icon, - const IconSizeRequest *size); - -EEL_DEFINE_CLASS_BOILERPLATE (NautilusIconFactory, - nautilus_icon_factory, - GTK_TYPE_OBJECT) - - static NautilusIconFactory *global_icon_factory = NULL; - - static void - destroy_icon_factory (void) -{ - nautilus_preferences_remove_callback (NAUTILUS_PREFERENCES_THEME, - icon_theme_changed_callback, - NULL); - nautilus_preferences_remove_callback (NAUTILUS_PREFERENCES_IMAGE_FILE_THUMBNAIL_LIMIT, - thumbnail_limit_changed_callback, - NULL); - gtk_object_unref (GTK_OBJECT (global_icon_factory)); -} - -/* Return a pointer to the single global icon factory. */ -static NautilusIconFactory * -get_icon_factory (void) -{ - if (global_icon_factory == NULL) { - global_icon_factory = NAUTILUS_ICON_FACTORY - (gtk_object_new (nautilus_icon_factory_get_type (), NULL)); - gtk_object_ref (GTK_OBJECT (global_icon_factory)); - gtk_object_sink (GTK_OBJECT (global_icon_factory)); - - icon_theme_changed_callback (NULL); - nautilus_preferences_add_callback (NAUTILUS_PREFERENCES_THEME, - icon_theme_changed_callback, - NULL); - - thumbnail_limit_changed_callback (NULL); - nautilus_preferences_add_callback (NAUTILUS_PREFERENCES_IMAGE_FILE_THUMBNAIL_LIMIT, - thumbnail_limit_changed_callback, - NULL); - - gtk_signal_connect (GTK_OBJECT (gnome_vfs_mime_monitor_get ()), - "data_changed", - mime_type_data_changed_callback, - NULL); - - g_atexit (destroy_icon_factory); - } - return global_icon_factory; -} - -GtkObject * -nautilus_icon_factory_get (void) -{ - return GTK_OBJECT (get_icon_factory ()); -} - -static void -check_recently_used_list (void) -{ - NautilusIconFactory *factory; - CircularList *head, *node, *next; - guint count; - - factory = get_icon_factory (); - - head = &factory->recently_used_dummy_head; - - count = 0; - - node = head; - while (1) { - next = node->next; - g_assert (next != NULL); - g_assert (next->prev == node); - - if (next == head) { - break; - } - - count += 1; - - node = next; - } - - g_assert (count == factory->recently_used_count); -} - -static void -nautilus_icon_factory_initialize (NautilusIconFactory *factory) -{ - factory->scalable_icons = g_hash_table_new (nautilus_scalable_icon_hash, - nautilus_scalable_icon_equal); - factory->cache_icons = g_hash_table_new (NULL, NULL); - factory->icon_cache = g_hash_table_new (cache_key_hash, - cache_key_equal); - - /* Empty out the recently-used list. */ - factory->recently_used_dummy_head.next = &factory->recently_used_dummy_head; - factory->recently_used_dummy_head.prev = &factory->recently_used_dummy_head; -} - -static void -nautilus_icon_factory_initialize_class (NautilusIconFactoryClass *class) -{ - GtkObjectClass *object_class; - - object_class = GTK_OBJECT_CLASS (class); - - signals[ICONS_CHANGED] - = gtk_signal_new ("icons_changed", - GTK_RUN_LAST, - object_class->type, - 0, - gtk_marshal_NONE__NONE, - GTK_TYPE_NONE, 0); - - gtk_object_class_add_signals (object_class, signals, LAST_SIGNAL); - - object_class->destroy = nautilus_icon_factory_destroy; -} - -static void -cache_key_destroy (CacheKey *key) -{ - nautilus_scalable_icon_unref (key->scalable_icon); - g_free (key); -} - -static void -mark_icon_not_outstanding (GdkPixbuf *pixbuf, gpointer callback_data) -{ - NautilusIconFactory *factory; - CacheIcon *icon; - - g_assert (callback_data == NULL); - - factory = get_icon_factory (); - - icon = g_hash_table_lookup (factory->cache_icons, pixbuf); - g_return_if_fail (icon != NULL); - g_return_if_fail (icon->pixbuf == pixbuf); - g_return_if_fail (icon->outstanding); - - icon->outstanding = FALSE; -} - -static CacheIcon * -cache_icon_new (GdkPixbuf *pixbuf, - IconRequest request, - gboolean scaled, - const IconDetails *details) -{ - NautilusIconFactory *factory; - CacheIcon *icon; - - factory = get_icon_factory (); - - /* Just a check to see this is not reusing a pixbuf. */ - g_assert (g_hash_table_lookup (factory->cache_icons, pixbuf) == NULL); - - /* Grab the pixbuf since we are keeping it. */ - gdk_pixbuf_ref (pixbuf); - gdk_pixbuf_set_last_unref_handler - (pixbuf, mark_icon_not_outstanding, NULL); - - /* Make the icon. */ - icon = g_new0 (CacheIcon, 1); - icon->pixbuf = pixbuf; - icon->internal_ref_count = 1; - icon->request = request; - icon->scaled = scaled; - icon->is_fallback = FALSE; - - if (details != NULL) { - icon->details = *details; - } - - /* Put it into the hash table. */ - g_hash_table_insert (factory->cache_icons, pixbuf, icon); - return icon; -} - -static void -cache_icon_ref (CacheIcon *icon) -{ - NautilusIconFactory *factory; - - factory = get_icon_factory (); - - g_assert (icon != NULL); - g_assert (icon->internal_ref_count >= 1 - || (icon->internal_ref_count == 0 && icon == fallback_icon)); - g_assert (g_hash_table_lookup (factory->cache_icons, icon->pixbuf) == icon); - - icon->internal_ref_count++; -} - -static void -cache_icon_unref (CacheIcon *icon) -{ - NautilusIconFactory *factory; - CircularList *node; - - factory = get_icon_factory (); - - g_assert (icon != NULL); - g_assert (icon->internal_ref_count >= 1); - g_assert (g_hash_table_lookup (factory->cache_icons, icon->pixbuf) == icon); - - if (icon->internal_ref_count > 1) { - icon->internal_ref_count--; - return; - } - icon->internal_ref_count = 0; - - check_recently_used_list (); - - /* If it's in the recently used list, free it from there */ - node = &icon->recently_used_node; - if (node->next != NULL) { - g_assert (factory->recently_used_count >= 1); - - g_assert (node->next->prev == node); - g_assert (node->prev->next == node); - g_assert (node->next != node); - g_assert (node->prev != node); - - node->next->prev = node->prev; - node->prev->next = node->next; - - node->next = NULL; - node->prev = NULL; - - factory->recently_used_count -= 1; - } - - check_recently_used_list (); - - /* The fallback icon has life after death. */ - if (icon == fallback_icon) { - return; - } - - /* Remove from the cache icons table. */ - g_hash_table_remove (factory->cache_icons, icon->pixbuf); - - /* Since it's no longer in the cache, we don't need to notice the last unref. */ - gdk_pixbuf_set_last_unref_handler (icon->pixbuf, NULL, NULL); - - /* Let go of the pixbuf if we were holding a reference to it. - * If it was still outstanding, we didn't have a reference to it, - * and we were counting on the unref handler to catch it. - */ - if (!icon->outstanding) { - gdk_pixbuf_unref (icon->pixbuf); - } - - g_free (icon); -} - -/* Destroy one pixbuf in the cache. */ -static gboolean -nautilus_icon_factory_destroy_cached_icon (gpointer key, gpointer value, gpointer user_data) -{ - cache_key_destroy (key); - cache_icon_unref (value); - - /* Tell the caller to remove the hash table entry. */ - return TRUE; -} - -/* Reset the cache to the default state. */ -static void -nautilus_icon_factory_clear (void) -{ - NautilusIconFactory *factory; - CircularList *head; - - factory = get_icon_factory (); - - g_hash_table_foreach_remove (factory->icon_cache, - nautilus_icon_factory_destroy_cached_icon, - NULL); - - /* Empty out the recently-used list. */ - head = &factory->recently_used_dummy_head; - g_assert (factory->recently_used_count == 0); - g_assert (head->next == head); - g_assert (head->prev == head); -} - -static void -nautilus_icon_factory_destroy (GtkObject *object) -{ - NautilusIconFactory *factory; - - factory = NAUTILUS_ICON_FACTORY (object); - - nautilus_icon_factory_clear (); - - if (g_hash_table_size (factory->scalable_icons) != 0) { - g_warning ("%d scalable icons still left when destroying icon factory", - g_hash_table_size (factory->scalable_icons)); - } - if (g_hash_table_size (factory->icon_cache) != 0) { - g_warning ("%d icon cache entries still left when destroying icon factory", - g_hash_table_size (factory->icon_cache)); - } - - g_hash_table_destroy (factory->scalable_icons); - g_hash_table_destroy (factory->icon_cache); - - g_free (factory->theme_name); - g_free (factory->default_theme_name); - - EEL_CALL_PARENT (GTK_OBJECT_CLASS, destroy, (object)); -} - -static gboolean -nautilus_icon_factory_possibly_free_cached_icon (gpointer key, - gpointer value, - gpointer user_data) -{ - CacheIcon *icon; - - icon = value; - - /* Don't free a cache entry that is in the recently used list. */ - if (icon->recently_used_node.next != NULL) { - return FALSE; - } - - /* Don't free a cache entry if the pixbuf is still in use. */ - if (icon->outstanding) { - return FALSE; - } - - /* Free the item. */ - return nautilus_icon_factory_destroy_cached_icon (key, value, NULL); -} - -/* Remove icons whose URI field matches the passed-in URI. */ -static gboolean -nautilus_icon_factory_remove_if_uri_matches (gpointer key, - gpointer value, - gpointer user_data) -{ - char *image_uri; - CacheKey *cache_key; - CacheIcon *icon; - - cache_key = key; - icon = value; - image_uri = user_data; - - /* See if the the uri's match - if not, just return. */ - if (cache_key->scalable_icon->uri != NULL - && strcmp (cache_key->scalable_icon->uri, image_uri)) { - return FALSE; - } - - /* Free the item. */ - return nautilus_icon_factory_destroy_cached_icon (key, value, NULL); -} - -/* Sweep the cache, freeing any icons that are not in use and are - * also not recently used. - */ -static gboolean -nautilus_icon_factory_sweep (gpointer user_data) -{ - NautilusIconFactory *factory; - - factory = user_data; - - g_hash_table_foreach_remove (factory->icon_cache, - nautilus_icon_factory_possibly_free_cached_icon, - NULL); - - factory->sweep_timer = 0; - - return FALSE; -} - -/* Schedule a timer to do a sweep. */ -static void -nautilus_icon_factory_schedule_sweep (void) -{ - NautilusIconFactory *factory; - - factory = get_icon_factory (); - - if (factory->sweep_timer != 0) { - return; - } - - factory->sweep_timer = g_timeout_add (ICON_CACHE_SWEEP_TIMEOUT, - nautilus_icon_factory_sweep, - factory); -} - -/* Clear a specific icon from the cache. */ -void -nautilus_icon_factory_remove_by_uri (const char *image_uri) -{ - NautilusIconFactory *factory; - - /* build the key and look it up in the icon cache */ - - factory = get_icon_factory (); - g_hash_table_foreach_remove (factory->icon_cache, - nautilus_icon_factory_remove_if_uri_matches, - (gpointer) image_uri); -} - -/* utility to check if a theme is in user directory or not */ -static gboolean -is_theme_in_user_directory (const char *theme_name) -{ - char *user_directory, *themes_directory, *this_theme_directory; - gboolean result; - - if (theme_name == NULL) { - return FALSE; - } - - user_directory = nautilus_get_user_directory (); - themes_directory = nautilus_make_path (user_directory, "themes"); - this_theme_directory = nautilus_make_path (themes_directory, theme_name); - - result = g_file_exists (this_theme_directory); - - g_free (user_directory); - g_free (themes_directory); - g_free (this_theme_directory); - - return result; -} - -/* Change the theme. */ -static void -set_theme (const char *theme_name) -{ - NautilusIconFactory *factory; - - factory = get_icon_factory (); - - if (eel_strcmp (theme_name, factory->theme_name) == 0) { - return; - } - - nautilus_icon_factory_clear (); - - g_free (factory->theme_name); - factory->theme_name = g_strdup (theme_name); - factory->theme_is_in_user_directory = is_theme_in_user_directory (theme_name); - - /* now set up the default theme */ - g_free (factory->default_theme_name); - factory->default_theme_name = nautilus_theme_get_theme_data ("icon-images", "default_theme"); - factory->default_theme_is_in_user_directory = is_theme_in_user_directory - (factory->default_theme_name); - - /* we changed the theme, so emit the icons_changed signal */ - gtk_signal_emit (GTK_OBJECT (factory), - signals[ICONS_CHANGED]); -} - -static char * -remove_icon_name_suffix (const char *icon_name) -{ - guint i; - const char *suffix; - - for (i = 0; i < EEL_N_ELEMENTS (icon_file_name_suffixes); i++) { - suffix = icon_file_name_suffixes[i]; - if (eel_str_has_suffix (icon_name, suffix)) { - return eel_str_strip_trailing_str (icon_name, suffix); - } - } - return g_strdup (icon_name); -} - -static char * -get_mime_type_icon_without_suffix (const char *mime_type) -{ - return remove_icon_name_suffix (gnome_vfs_mime_get_icon (mime_type)); -} - -static char * -make_icon_name_from_mime_type (const char *mime_type) -{ - char *mime_type_without_slashes, *icon_name; - - if (mime_type == NULL) { - return NULL; - } - - mime_type_without_slashes = eel_str_replace_substring - (mime_type, "/", "-"); - icon_name = g_strconcat ("gnome-", mime_type_without_slashes, NULL); - g_free (mime_type_without_slashes); - return icon_name; -} - -/* Use the MIME type to get the icon name. */ -static char * -get_icon_name_for_regular_file (NautilusFile *file) -{ - const char *icon_name; - char *mime_type, *uri; - - mime_type = nautilus_file_get_mime_type (file); - uri = nautilus_file_get_uri (file); - - /* Special-case icons based on the uri scheme. Eventually we - * should generalize this or at least have a way for others to - * extend it. - */ - if (eel_istr_has_prefix (uri, "http:") - && eel_strcmp (mime_type, "text/html") == 0) { - icon_name = ICON_NAME_WEB; - } else if (eel_istr_has_prefix (uri, "eazel-install:")) { - icon_name = ICON_NAME_INSTALL; - } else { - if (nautilus_file_is_executable (file) - && eel_strcasecmp (mime_type, "text/plain") != 0) { - icon_name = ICON_NAME_EXECUTABLE; - } else { - icon_name = ICON_NAME_REGULAR; - } - } - - g_free (uri); - g_free (mime_type); - - return g_strdup (icon_name); -} - -/* Use the MIME type to get the icon name. */ -static char * -get_icon_name_for_directory (NautilusFile *file) -{ - const char *icon_name; - char *mime_type; - - mime_type = nautilus_file_get_mime_type (file); - - if (eel_strcasecmp (mime_type, "x-directory/search") == 0) { - icon_name = ICON_NAME_SEARCH_RESULTS; - } else { - icon_name = ICON_NAME_DIRECTORY; - } - - g_free (mime_type); - - return g_strdup (icon_name); -} - - -/* Get the icon name for a file. */ -static char * -get_icon_name_for_file (NautilusFile *file) -{ - char *uri; - - uri = nautilus_file_get_uri (file); - if (strcmp (uri, EEL_TRASH_URI) == 0) { - g_free (uri); - return g_strdup (nautilus_trash_monitor_is_empty () - ? ICON_NAME_TRASH_EMPTY : ICON_NAME_TRASH_NOT_EMPTY); - } - g_free (uri); - - /* Get an icon name based on the file's type. */ - switch (nautilus_file_get_file_type (file)) { - case GNOME_VFS_FILE_TYPE_DIRECTORY: - return get_icon_name_for_directory (file); - case GNOME_VFS_FILE_TYPE_FIFO: - return g_strdup (ICON_NAME_FIFO); - case GNOME_VFS_FILE_TYPE_SOCKET: - return g_strdup (ICON_NAME_SOCKET); - case GNOME_VFS_FILE_TYPE_CHARACTER_DEVICE: - return g_strdup (ICON_NAME_CHARACTER_DEVICE); - case GNOME_VFS_FILE_TYPE_BLOCK_DEVICE: - return g_strdup (ICON_NAME_BLOCK_DEVICE); - case GNOME_VFS_FILE_TYPE_SYMBOLIC_LINK: - /* Non-broken symbolic links return the target's type. */ - return g_strdup (ICON_NAME_BROKEN_SYMBOLIC_LINK); - case GNOME_VFS_FILE_TYPE_REGULAR: - case GNOME_VFS_FILE_TYPE_UNKNOWN: - default: - return get_icon_name_for_regular_file (file); - } -} - -static char * -make_full_icon_path (const char *path, - const char *suffix, - gboolean theme_is_in_user_directory) -{ - char *partial_path, *full_path; - char *user_directory, *themes_directory; - - partial_path = g_strconcat (path, suffix, NULL); - - if (path[0] == '/') { - return partial_path; - } - - /* Build a path for this icon, depending on the theme_is_in_user_directory boolean. */ - if (theme_is_in_user_directory) { - user_directory = nautilus_get_user_directory (); - themes_directory = nautilus_make_path (user_directory, "themes"); - full_path = nautilus_make_path (themes_directory, partial_path); - g_free (user_directory); - g_free (themes_directory); - if (!g_file_exists (full_path)) { - g_free (full_path); - full_path = NULL; - } - } else { - full_path = nautilus_pixmap_file (partial_path); - } - - if (full_path == NULL) { - full_path = gnome_vfs_icon_path_from_filename (partial_path); - } - - g_free (partial_path); - return full_path; -} - -/* utility routine to parse the attach points string to set up the array in icon_info */ -static void -parse_attach_points (NautilusEmblemAttachPoints *attach_points, const char *attach_point_string) -{ - char **point_array; - int i, x_offset, y_offset; - - attach_points->num_points = 0; - if (attach_point_string == NULL) { - return; - } - - /* Split the attach point string into a string array, then process - * each point with sscanf in a loop. - */ - point_array = g_strsplit (attach_point_string, "|", MAX_ATTACH_POINTS); - - for (i = 0; point_array[i] != NULL; i++) { - if (sscanf (point_array[i], " %d , %d , %*s", &x_offset, &y_offset) == 2) { - attach_points->points[attach_points->num_points].x = x_offset; - attach_points->points[attach_points->num_points].y = y_offset; - attach_points->num_points++; - } else { - g_warning ("bad attach point specification: %s", point_array[i]); - } - } - - g_strfreev (point_array); -} - -/* Pick a particular icon to use, trying all the various suffixes. - * Return the path of the icon or NULL if no icon is found. - */ -static char * -get_themed_icon_file_path (const char *theme_name, - gboolean theme_is_in_user_directory, - const char *icon_name, - guint icon_size, - gboolean optimized_for_aa, - IconDetails *details) -{ - guint i; - gboolean include_size; - char *themed_icon_name, *partial_path, *path, *aa_path, *xml_path; - xmlDocPtr doc; - xmlNodePtr node; - char *size_as_string, *property; - ArtIRect parsed_rect; - NautilusIconFactory *factory; - char *user_directory; - - g_assert (icon_name != NULL); - - if (theme_name == NULL || icon_name[0] == '/') { - themed_icon_name = g_strdup (icon_name); - } else { - themed_icon_name = g_strconcat (theme_name, "/", icon_name, NULL); - } - - include_size = icon_size != NAUTILUS_ICON_SIZE_STANDARD; - factory = get_icon_factory (); - - /* Try each suffix. */ - for (i = 0; i < EEL_N_ELEMENTS (icon_file_name_suffixes); i++) { - if (include_size && strcasecmp (icon_file_name_suffixes[i], ".svg") != 0) { - /* Build a path for this icon. */ - partial_path = g_strdup_printf ("%s-%u", - themed_icon_name, - icon_size); - } else { - partial_path = g_strdup (themed_icon_name); - } - - /* if we're in anti-aliased mode, try for an optimized one first */ - if (optimized_for_aa) { - aa_path = g_strconcat (partial_path, "-aa", NULL); - path = make_full_icon_path (aa_path, - icon_file_name_suffixes[i], - theme_is_in_user_directory); - g_free (aa_path); - - /* Return the path if the file exists. */ - if (path != NULL) { - break; - } - - g_free (path); - path = NULL; - } - - path = make_full_icon_path (partial_path, - icon_file_name_suffixes[i], - theme_is_in_user_directory); - g_free (partial_path); - - /* Return the path if the file exists. */ - if (path != NULL) { - break; - } - - g_free (path); - path = NULL; - } - - /* Open the XML file to get the text rectangle and emblem attach points */ - if (path != NULL && details != NULL) { - memset (&details->text_rect, 0, sizeof (details->text_rect)); - - xml_path = make_full_icon_path (themed_icon_name, - ".xml", - theme_is_in_user_directory); - - doc = xmlParseFile (xml_path); - g_free (xml_path); - - size_as_string = g_strdup_printf ("%u", icon_size); - node = eel_xml_get_root_child_by_name_and_property - (doc, "icon", "size", size_as_string); - g_free (size_as_string); - - property = NULL; - if (optimized_for_aa) { - property = xmlGetProp (node, "embedded_text_rectangle_aa"); - } - if (property == NULL) { - property = xmlGetProp (node, "embedded_text_rectangle"); - } - - if (property != NULL) { - if (sscanf (property, - " %d , %d , %d , %d %*s", - &parsed_rect.x0, - &parsed_rect.y0, - &parsed_rect.x1, - &parsed_rect.y1) == 4) { - details->text_rect = parsed_rect; - } - xmlFree (property); - } - - property = NULL; - if (optimized_for_aa) { - property = xmlGetProp (node, "attach_points_aa"); - } - if (property == NULL) { - property = xmlGetProp (node, "attach_points"); - } - - parse_attach_points (&details->attach_points, property); - xmlFree (property); - - xmlFreeDoc (doc); - } - - /* If we still haven't found anything, and we're looking for an emblem, - * check out the user's home directory, since it might be an emblem - * that they've added there. - */ - if (path == NULL - && icon_size == NAUTILUS_ICON_SIZE_STANDARD - && eel_str_has_prefix (icon_name, EMBLEM_NAME_PREFIX)) { - for (i = 0; i < EEL_N_ELEMENTS (icon_file_name_suffixes); i++) { - user_directory = nautilus_get_user_directory (); - path = g_strdup_printf ("%s/emblems/%s%s", - user_directory, - icon_name + 7, - icon_file_name_suffixes[i]); - g_free (user_directory); - - if (g_file_exists (path)) { - break; - } - - g_free (path); - path = NULL; - } - } - g_free (themed_icon_name); - - return path; -} - -/* Choose the file name to load, taking into account theme - * vs. non-theme icons. Also fill in info in the icon structure based - * on what's found in the XML file. - */ -static char * -get_icon_file_path (const char *name, - const char *modifier, - guint size_in_pixels, - gboolean optimized_for_aa, - IconDetails *details) -{ - NautilusIconFactory *factory; - const char *theme_to_use; - gboolean theme_is_in_user_directory; - char *path; - char *name_with_modifier; - - if (name == NULL) { - return NULL; - } - - factory = get_icon_factory (); - theme_to_use = NULL; - theme_is_in_user_directory = FALSE; - - /* Check and see if there is a theme icon to use. - * If there's a default theme specified, try it, too. - * This decision must be based on whether there's a non-size- - * specific theme icon. - */ - if (factory->theme_name != NULL) { - path = get_themed_icon_file_path (factory->theme_name, - factory->theme_is_in_user_directory, - name, - NAUTILUS_ICON_SIZE_STANDARD, - optimized_for_aa, - details); - if (path != NULL) { - theme_to_use = factory->theme_name; - theme_is_in_user_directory = factory->theme_is_in_user_directory; - g_free (path); - } else if (factory->default_theme_name != NULL) { - path = get_themed_icon_file_path (factory->default_theme_name, - factory->default_theme_is_in_user_directory, - name, - NAUTILUS_ICON_SIZE_STANDARD, - optimized_for_aa, - details); - if (path != NULL) { - theme_to_use = factory->default_theme_name; - theme_is_in_user_directory = factory->default_theme_is_in_user_directory; - g_free (path); - } - } - } - - /* Now we know whether or not to use the theme. */ - - /* If there's a modifier, try the modified icon first. */ - if (modifier && modifier[0] != '\0') { - name_with_modifier = g_strconcat (name, "-", modifier, NULL); - path = get_themed_icon_file_path (theme_to_use, - theme_is_in_user_directory, - name_with_modifier, - size_in_pixels, - optimized_for_aa, - details); - g_free (name_with_modifier); - if (path != NULL) { - return path; - } - } - - return get_themed_icon_file_path (theme_to_use, - theme_is_in_user_directory, - name, - size_in_pixels, - optimized_for_aa, - details); -} - -static void -icon_theme_changed_callback (gpointer user_data) -{ - char *theme_preference, *icon_theme; - - /* Consult the user preference and the Nautilus theme. In the - * long run, we sould just get rid of the user preference. - */ - theme_preference = nautilus_preferences_get (NAUTILUS_PREFERENCES_THEME); - icon_theme = nautilus_theme_get_theme_data ("icons", "icon_theme"); - - set_theme (icon_theme == NULL ? theme_preference : icon_theme); - - g_free (theme_preference); - g_free (icon_theme); -} - -static void -thumbnail_limit_changed_callback (gpointer user_data) -{ - cached_thumbnail_limit = nautilus_preferences_get_integer (NAUTILUS_PREFERENCES_IMAGE_FILE_THUMBNAIL_LIMIT); - - /* Tell the world that icons might have changed. We could invent a narrower-scope - * signal to mean only "thumbnails might have changed" if this ends up being slow - * for some reason. - */ - gtk_signal_emit (GTK_OBJECT (global_icon_factory), - signals[ICONS_CHANGED]); -} - -static void -mime_type_data_changed_callback (GnomeVFSMIMEMonitor *monitor, gpointer user_data) -{ - g_assert (monitor != NULL); - g_assert (user_data == NULL); - - /* We don't know which data changed, so we have to assume that - * any or all icons might have changed. - */ - gtk_signal_emit (GTK_OBJECT (get_icon_factory ()), - signals[ICONS_CHANGED]); -} - -/* Decompose a scalable icon into its text pieces. */ -void -nautilus_scalable_icon_get_text_pieces (NautilusScalableIcon *icon, - char **uri_return, - char **mime_type_return, - char **name_return, - char **modifier_return, - char **embedded_text_return) -{ - g_return_if_fail (icon != NULL); - - if (uri_return != NULL) { - *uri_return = g_strdup (icon->uri); - } - if (mime_type_return != NULL) { - *mime_type_return = g_strdup (icon->mime_type); - } - if (name_return != NULL) { - *name_return = g_strdup (icon->name); - } - if (modifier_return != NULL) { - *modifier_return = g_strdup (icon->modifier); - } - if (embedded_text_return != NULL) { - *embedded_text_return = g_strdup (icon->embedded_text); - } -} - -/* Get or create a scalable icon from text pieces. */ -NautilusScalableIcon * -nautilus_scalable_icon_new_from_text_pieces (const char *uri, - const char *mime_type, - const char *name, - const char *modifier, - const char *embedded_text) -{ - GHashTable *hash_table; - NautilusScalableIcon cache_key, *icon; - NautilusIconFactory *factory; - - factory = get_icon_factory (); - /* Make empty strings canonical. */ - if (uri != NULL && uri[0] == '\0') { - uri = NULL; - } - if (mime_type != NULL && mime_type[0] == '\0') { - mime_type = NULL; - } - if (name != NULL && name[0] == '\0') { - name = NULL; - } - if (modifier != NULL && modifier[0] == '\0') { - modifier = NULL; - } - if (embedded_text != NULL && embedded_text[0] == '\0') { - embedded_text = NULL; - } - - /* Get at the hash table. */ - hash_table = factory->scalable_icons; - - /* Check to see if it's already in the table. */ - cache_key.uri = (char *) uri; - cache_key.mime_type = (char *) mime_type; - cache_key.name = (char *) name; - cache_key.modifier = (char *) modifier; - cache_key.embedded_text = (char *) embedded_text; - - icon = g_hash_table_lookup (hash_table, &cache_key); - if (icon == NULL) { - /* Not in the table, so create it and put it in. */ - icon = g_new0 (NautilusScalableIcon, 1); - icon->uri = g_strdup (uri); - icon->mime_type = g_strdup (mime_type); - icon->name = g_strdup (name); - icon->modifier = g_strdup (modifier); - icon->embedded_text = g_strdup (embedded_text); - g_hash_table_insert (hash_table, icon, icon); - } - - /* Grab a reference and return it. */ - nautilus_scalable_icon_ref (icon); - return icon; -} - -void -nautilus_scalable_icon_ref (NautilusScalableIcon *icon) -{ - g_return_if_fail (icon != NULL); - - icon->ref_count++; -} - -void -nautilus_scalable_icon_unref (NautilusScalableIcon *icon) -{ - GHashTable *hash_table; - - g_return_if_fail (icon != NULL); - g_return_if_fail (icon->ref_count != 0); - - if (--icon->ref_count != 0) { - return; - } - - hash_table = get_icon_factory ()->scalable_icons; - g_hash_table_remove (hash_table, icon); - - g_free (icon->uri); - g_free (icon->mime_type); - g_free (icon->name); - g_free (icon->modifier); - g_free (icon->embedded_text); - g_free (icon); -} - -static guint -nautilus_scalable_icon_hash (gconstpointer p) -{ - const NautilusScalableIcon *icon; - guint hash; - - icon = p; - hash = 0; - - if (icon->uri != NULL) { - hash = g_str_hash (icon->uri); - } - - hash <<= 4; - if (icon->mime_type != NULL) { - hash ^= g_str_hash (icon->mime_type); - } - - hash <<= 4; - if (icon->name != NULL) { - hash ^= g_str_hash (icon->name); - } - - hash <<= 4; - if (icon->modifier != NULL) { - hash ^= g_str_hash (icon->modifier); - } - - hash <<= 4; - if (icon->embedded_text != NULL) { - hash ^= g_str_hash (icon->embedded_text); - } - - return hash; -} - -static gboolean -nautilus_scalable_icon_equal (gconstpointer a, - gconstpointer b) -{ - const NautilusScalableIcon *icon_a, *icon_b; - - icon_a = a; - icon_b = b; - - return eel_strcmp (icon_a->uri, icon_b->uri) == 0 - && eel_strcmp (icon_a->mime_type, icon_b->mime_type) == 0 - && eel_strcmp (icon_a->name, icon_b->name) == 0 - && eel_strcmp (icon_a->modifier, icon_b->modifier) == 0 - && eel_strcmp (icon_a->embedded_text, icon_b->embedded_text) == 0; -} - -static gboolean -should_display_image_file_as_itself (NautilusFile *file, gboolean optimized_for_aa) -{ - static int show_thumbnails_auto_value; - static gboolean show_thumbnail_auto_value_registered; - - if (!show_thumbnail_auto_value_registered) { - nautilus_preferences_add_auto_integer (NAUTILUS_PREFERENCES_SHOW_IMAGE_FILE_THUMBNAILS, - &show_thumbnails_auto_value); - show_thumbnail_auto_value_registered = TRUE; - } - - /* see if there's a proxy thumbnail to indicate that thumbnailing - * failed, in which case we shouldn't use the thumbnail. - */ - if (nautilus_thumbnail_has_invalid_thumbnail (file, optimized_for_aa)) { - return FALSE; - } - - /* if we don't have read permissions for the file, don't show as itself for security reasons */ - if (!nautilus_file_can_read (file)) { - return FALSE; - } - - if (show_thumbnails_auto_value == NAUTILUS_SPEED_TRADEOFF_ALWAYS) { - return TRUE; - } - - if (show_thumbnails_auto_value == NAUTILUS_SPEED_TRADEOFF_NEVER) { - return FALSE; - } - - g_assert (show_thumbnails_auto_value == NAUTILUS_SPEED_TRADEOFF_LOCAL_ONLY); - return nautilus_file_is_local (file); -} - -/* return TRUE if the passed-in mime-type is one that we can thumbnail. It's - * used to exclude ones that we know will generate errors if we tried them. - */ -static gboolean -is_supported_mime_type (const char *mime_type) -{ - /* exclude xfig images, since we can't handle them */ - if (eel_strcmp (mime_type, "image/x-xfig") == 0) { - return FALSE; - } - return TRUE; -} - -/* 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; - gboolean is_local; - int file_size, size, res; - NautilusScalableIcon *scalable_icon; - char *directory_uri; - GnomeDesktopEntry *entry; - - if (file == NULL) { - return NULL; - } - - icon_name = NULL; - - /* 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); - - /* if the file is an image, either use the image itself as the icon if it's small enough, - 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_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 (desktop_directory); - } - - /* also, dont make thumbnails for images in the thumbnails directory */ - if (uri == NULL) { - file_size = nautilus_file_get_size (file); - - /* FIXME: This has to be done later, when we know - * whether anti-aliasing is needed or not. - */ - if (eel_istr_has_prefix (mime_type, "image/") - && is_supported_mime_type (mime_type) - && should_display_image_file_as_itself (file, TRUE)) { - if (file_size < SELF_THUMBNAIL_SIZE_THRESHOLD && is_local) { - uri = nautilus_file_get_uri (file); - } else if (strstr (file_uri, "/.thumbnails/") == NULL - && file_size < cached_thumbnail_limit) { - uri = nautilus_get_thumbnail_uri (file, TRUE); - if (uri == NULL) { - icon_name = g_strdup (ICON_NAME_THUMBNAIL_LOADING); - } - } - } - } - - /* Handle nautilus link xml files, which may specify their own image */ - if (nautilus_file_is_nautilus_link (file)) { - /* FIXME bugzilla.eazel.com 2563: 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.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); - } - 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.eazel.com 2563: 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")) { - uri = g_strdup (file_uri); - } - - /* Get the generic icon set for this file. */ - g_free (file_uri); - if (icon_name == NULL) { - icon_name = get_icon_name_for_file (file); - } - - top_left_text = nautilus_file_get_top_left_text (file); - - /* 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); - g_free (top_left_text); - - return scalable_icon; -} - -/** - * 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 = g_list_prepend (NULL, NAUTILUS_FILE_ATTRIBUTE_CUSTOM_ICON); - attributes = g_list_prepend (attributes, - NAUTILUS_FILE_ATTRIBUTE_MIME_TYPE); - attributes = g_list_prepend (attributes, - NAUTILUS_FILE_ATTRIBUTE_TOP_LEFT_TEXT); - - return attributes; -} - -/** - * nautilus_icon_factory_is_icon_ready_for_file - * - * Check whether a NautilusFile has enough information to report - * what its icon should be. - * - * @file: The NautilusFile in question. - */ -gboolean -nautilus_icon_factory_is_icon_ready_for_file (NautilusFile *file) -{ - GList *attributes; - gboolean result; - - attributes = nautilus_icon_factory_get_required_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) -{ - NautilusScalableIcon *scalable_icon; - char *name_with_prefix; - - name_with_prefix = g_strconcat (EMBLEM_NAME_PREFIX, emblem_name, NULL); - scalable_icon = nautilus_scalable_icon_new_from_text_pieces - (NULL, NULL, name_with_prefix, NULL, NULL); - g_free (name_with_prefix); - - return scalable_icon; -} - -GList * -nautilus_icon_factory_get_emblem_icons_for_file (NautilusFile *file, - EelStringList *exclude) -{ - GList *icons, *emblem_names, *node; - char *uri, *name; - NautilusScalableIcon *icon; - gboolean file_is_trash; - - /* Leave out the trash emblem for the trash itself, since - * putting a trash emblem on a trash icon is gilding the - * lily. - */ - uri = nautilus_file_get_uri (file); - file_is_trash = strcmp (uri, EEL_TRASH_URI) == 0; - g_free (uri); - - icons = NULL; - - emblem_names = nautilus_file_get_emblem_names (file); - for (node = emblem_names; node != NULL; node = node->next) { - name = node->data; - if (file_is_trash && strcmp (name, NAUTILUS_FILE_EMBLEM_NAME_TRASH) == 0) { - continue; - } - if (eel_string_list_contains (exclude, name)) { - continue; - } - icon = nautilus_icon_factory_get_emblem_icon_by_name (name); - icons = g_list_prepend (icons, icon); - } - eel_g_list_free_deep (emblem_names); - - return g_list_reverse (icons); -} - -static guint -get_larger_icon_size (guint size) -{ - if (size < NAUTILUS_ICON_SIZE_SMALLEST) { - return NAUTILUS_ICON_SIZE_SMALLEST; - } - if (size < NAUTILUS_ICON_SIZE_FOR_MENUS) { - return NAUTILUS_ICON_SIZE_FOR_MENUS; - } - if (size < NAUTILUS_ICON_SIZE_SMALLER) { - return NAUTILUS_ICON_SIZE_SMALLER; - } - if (size < NAUTILUS_ICON_SIZE_SMALL) { - return NAUTILUS_ICON_SIZE_SMALL; - } - if (size < NAUTILUS_ICON_SIZE_STANDARD) { - return NAUTILUS_ICON_SIZE_STANDARD; - } - if (size < NAUTILUS_ICON_SIZE_LARGE) { - return NAUTILUS_ICON_SIZE_LARGE; - } - if (size < NAUTILUS_ICON_SIZE_LARGER) { - return NAUTILUS_ICON_SIZE_LARGER; - } - return NAUTILUS_ICON_SIZE_LARGEST; -} - -static guint -get_smaller_icon_size (guint size) -{ - if (size > NAUTILUS_ICON_SIZE_LARGEST) { - return NAUTILUS_ICON_SIZE_LARGEST; - } - if (size > NAUTILUS_ICON_SIZE_LARGER) { - return NAUTILUS_ICON_SIZE_LARGER; - } - if (size > NAUTILUS_ICON_SIZE_LARGE) { - return NAUTILUS_ICON_SIZE_LARGE; - } - if (size > NAUTILUS_ICON_SIZE_STANDARD) { - return NAUTILUS_ICON_SIZE_STANDARD; - } - if (size > NAUTILUS_ICON_SIZE_SMALL) { - return NAUTILUS_ICON_SIZE_SMALL; - } - if (size > NAUTILUS_ICON_SIZE_SMALLER) { - return NAUTILUS_ICON_SIZE_SMALLER; - } - if (size > NAUTILUS_ICON_SIZE_FOR_MENUS) { - return NAUTILUS_ICON_SIZE_FOR_MENUS; - } - return NAUTILUS_ICON_SIZE_SMALLEST; -} - -/* Return true if there is another size to try. - * Set the size pointed to by @current_size to 0 to start. - */ -static gboolean -get_next_icon_size_to_try (guint target_size, guint *current_size) -{ - guint size; - - /* Get next larger size. */ - size = *current_size; - if (size == 0 || size >= target_size) { - if (size == 0 && target_size != 0) { - size = target_size - 1; - } - if (size < NAUTILUS_ICON_SIZE_LARGEST) { - *current_size = get_larger_icon_size (size); - return TRUE; - } - size = target_size; - } - - /* Already hit the largest size, get the next smaller size instead. */ - if (size > NAUTILUS_ICON_SIZE_SMALLEST) { - *current_size = get_smaller_icon_size (size); - return TRUE; - } - - /* Tried them all. */ - return FALSE; -} - -/* This loads an SVG image, scaling it to the appropriate size. */ -static GdkPixbuf * -load_pixbuf_svg (const char *path, guint size_in_pixels, gboolean is_emblem) -{ - FILE *f; - GdkPixbuf *pixbuf; - double actual_size_in_pixels; - - f = fopen (path, "rb"); - if (f == NULL) { - return NULL; - } - - /* FIXME: the nominal size of .svg emblems is too large, so we scale it - * down here if the file is an emblem. This code should be removed - * when we scale all the emblems properly. - */ - if (is_emblem) { - actual_size_in_pixels = size_in_pixels * EMBLEM_SCALE_FACTOR; - } else { - actual_size_in_pixels = size_in_pixels; - } - - pixbuf = rsvg_render_file (f, (double) (actual_size_in_pixels / NAUTILUS_ICON_SIZE_STANDARD)); - fclose (f); - - return pixbuf; -} - -static gboolean -path_represents_svg_image (const char *path) -{ - char *uri; - GnomeVFSFileInfo *file_info; - gboolean is_svg; - - /* Sync. file I/O is OK here because this is used only for installed - * icons, not for the general case which could include icons on devices - * other than the local hard disk. - */ - - uri = gnome_vfs_get_uri_from_local_path (path); - file_info = gnome_vfs_file_info_new (); - gnome_vfs_get_file_info (uri, file_info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE); - g_free (uri); - is_svg = eel_strcmp (file_info->mime_type, "image/svg") == 0; - gnome_vfs_file_info_unref (file_info); - - return is_svg; -} - -/* Returns GNOME_VFS_ERROR_NOT_SUPPORTED for icons that are not files. */ -static GnomeVFSResult -get_cache_time (const char *file_uri, time_t *cache_time) -{ - GnomeVFSURI *vfs_uri; - GnomeVFSFileInfo *file_info; - GnomeVFSResult result; - gboolean is_local; - - /* If there's no specific file, simply return. */ - if (file_uri == NULL) { - return GNOME_VFS_ERROR_NOT_SUPPORTED; - } - - /* FIXME bugzilla.eazel.com 2566: if the URI is remote, assume - * it's valid to match logic below. - */ - vfs_uri = gnome_vfs_uri_new (file_uri); - is_local = gnome_vfs_uri_is_local (vfs_uri); - gnome_vfs_uri_unref (vfs_uri); - if (!is_local) { - return GNOME_VFS_ERROR_NOT_SUPPORTED; - } - - /* Gather the info and then compare modification times. */ - file_info = gnome_vfs_file_info_new (); - result = gnome_vfs_get_file_info (file_uri, file_info, GNOME_VFS_FILE_INFO_DEFAULT); - if (result == GNOME_VFS_OK) { - *cache_time = file_info->mtime; - } - gnome_vfs_file_info_unref (file_info); - - return result; -} - -static GdkPixbuf * -load_icon_from_path (const char *path, - guint size_in_pixels, - gboolean custom, - gboolean is_emblem) /* for emblem scaling hack only */ -{ - /* Get the icon. */ - if (path == NULL) { - return NULL; - } - if (path_represents_svg_image (path)) { - return load_pixbuf_svg (path, size_in_pixels, is_emblem); - } - /* Custom non-svg icons exist at one size. - * Non-custom icons have their size encoded in their path. - */ - if (custom && size_in_pixels != NAUTILUS_ICON_SIZE_STANDARD) { - return NULL; - } - return gdk_pixbuf_new_from_file (path); -} - -static GdkPixbuf * -load_named_icon (const char *name, - const char *modifier, - guint size_in_pixels, - gboolean optimized_for_aa, - IconDetails *details) -{ - char *path; - GdkPixbuf *pixbuf; - - 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)); - g_free (path); - - if (pixbuf == NULL) { - memset (&details, 0, sizeof (details)); - } - return pixbuf; -} - -static gboolean -is_generic_icon_name (const char *name) -{ - return eel_strcmp (name, ICON_NAME_EXECUTABLE) == 0 - || eel_strcmp (name, ICON_NAME_REGULAR) == 0; -} - -/* This load function returns NULL if the icon is not available at - * this size. - */ -static CacheIcon * -load_specific_icon (NautilusScalableIcon *scalable_icon, - guint size_in_pixels, - gboolean optimized_for_aa, - IconRequest type) -{ - IconDetails details; - GdkPixbuf *pixbuf; - char *mime_type_icon_name, *path; - const char *first_choice_name, *second_choice_name; - CacheIcon *icon; - - memset (&details, 0, sizeof (details)); - pixbuf = NULL; - - /* Get the path. */ - if (type == REQUEST_PICKY_CUSTOM_ONLY) { - /* We don't support custom icons that are not local here. */ - path = gnome_vfs_get_local_path_from_uri (scalable_icon->uri); - pixbuf = load_icon_from_path (path, size_in_pixels, TRUE, FALSE); - g_free (path); - } else { - mime_type_icon_name = get_mime_type_icon_without_suffix (scalable_icon->mime_type); - if (mime_type_icon_name == NULL) { - mime_type_icon_name = make_icon_name_from_mime_type (scalable_icon->mime_type); - } - if (is_generic_icon_name (scalable_icon->name)) { - first_choice_name = mime_type_icon_name; - second_choice_name = scalable_icon->name; - } else { - first_choice_name = scalable_icon->name; - second_choice_name = mime_type_icon_name; - } - pixbuf = load_named_icon - ((type == REQUEST_PICKY_BY_NAME_FIRST_CHOICE) - ? first_choice_name : second_choice_name, - scalable_icon->modifier, - size_in_pixels, - optimized_for_aa, &details); - g_free (mime_type_icon_name); - } - - if (pixbuf == NULL) { - return NULL; - } - - /* Since we got something, we can create a cache icon. */ - icon = cache_icon_new (pixbuf, type, FALSE, &details); - get_cache_time (scalable_icon->uri, &icon->cache_time); - gdk_pixbuf_unref (pixbuf); - - return icon; -} - -static void -destroy_fallback_icon (void) -{ - CacheIcon *icon; - - icon = fallback_icon; - g_assert (icon->internal_ref_count == 0); - cache_icon_ref (icon); - fallback_icon = NULL; - cache_icon_unref (icon); -} - -/* This load function is not allowed to return NULL. */ -static CacheIcon * -load_icon_for_scaling (NautilusScalableIcon *scalable_icon, - guint requested_size, - gboolean optimized_for_aa, - guint *actual_size_result) -{ - CacheIcon *icon; - guint actual_size; - IconSizeRequest size_request; - GdkPixbuf *pixbuf; - guint i; - const IconRequest requests[] = { - REQUEST_PICKY_CUSTOM_ONLY, - REQUEST_PICKY_BY_NAME_FIRST_CHOICE, - REQUEST_PICKY_BY_NAME_SECOND_CHOICE - }; - - size_request.maximum_width = MAXIMUM_ICON_SIZE * requested_size / NAUTILUS_ZOOM_LEVEL_STANDARD; - size_request.maximum_height = size_request.maximum_width; - size_request.optimized_for_aa = optimized_for_aa; - - for (i = 0; i < EEL_N_ELEMENTS (requests); i++) { - actual_size = 0; - while (get_next_icon_size_to_try (requested_size, &actual_size)) { - size_request.nominal_width = actual_size; - size_request.nominal_height = actual_size; - - icon = get_icon_from_cache (scalable_icon, &size_request, requests[i]); - if (icon != NULL) { - *actual_size_result = actual_size; - return icon; - } - } - } - - /* Fall back on the hard-coded image. */ - if (fallback_icon != NULL) { - cache_icon_ref (fallback_icon); - } else { - pixbuf = gdk_pixbuf_new_from_data - (nautilus_default_file_icon, - GDK_COLORSPACE_RGB, - TRUE, - 8, - nautilus_default_file_icon_width, - nautilus_default_file_icon_height, - nautilus_default_file_icon_width * 4, /* stride */ - NULL, /* don't destroy data */ - NULL); - fallback_icon = cache_icon_new (pixbuf, FALSE, FALSE, NULL); - fallback_icon->is_fallback = TRUE; - g_atexit (destroy_fallback_icon); - } - - *actual_size_result = NAUTILUS_ICON_SIZE_STANDARD; - return fallback_icon; -} - -/* Consumes the icon and returns a scaled one if the pixbuf is too big. - * Note that this does an unref on the icon and returns a new one. - */ -static CacheIcon * -scale_icon (CacheIcon *icon, - double scale_x, - double scale_y) -{ - int width, height; - int rect_width, rect_height; - int i, num_points; - GdkPixbuf *scaled_pixbuf; - IconDetails scaled_details; - CacheIcon *scaled_icon; - - g_assert (!icon->scaled); - - width = gdk_pixbuf_get_width (icon->pixbuf); - height = gdk_pixbuf_get_height (icon->pixbuf); - - /* Check for no-scaling case. */ - if ((int) (width * scale_x) == width - && (int) (height * scale_y) == height) { - return NULL; - } - - width *= scale_x; - if (width < 1) { - width = 1; - } - height *= scale_y; - if (height < 1) { - height = 1; - } - - scaled_pixbuf = gdk_pixbuf_scale_simple - (icon->pixbuf, width, height, GDK_INTERP_BILINEAR); - - rect_width = (icon->details.text_rect.x1 - icon->details.text_rect.x0) * scale_x; - rect_height = (icon->details.text_rect.y1 - icon->details.text_rect.y0) * scale_y; - - scaled_details.text_rect.x0 = icon->details.text_rect.x0 * scale_x; - scaled_details.text_rect.y0 = icon->details.text_rect.x0 * scale_y; - scaled_details.text_rect.x1 = scaled_details.text_rect.x0 + rect_width; - scaled_details.text_rect.y1 = scaled_details.text_rect.y0 + rect_height; - - num_points = icon->details.attach_points.num_points; - scaled_details.attach_points.num_points = num_points; - for (i = 0; i < num_points; i++) { - scaled_details.attach_points.points[i].x = icon->details.attach_points.points[i].x * scale_x; - scaled_details.attach_points.points[i].y = icon->details.attach_points.points[i].y * scale_y; - } - - scaled_icon = cache_icon_new (scaled_pixbuf, - icon->request, - TRUE, - &scaled_details); - scaled_icon->is_fallback = icon->is_fallback; - scaled_icon->cache_time = icon->cache_time; - gdk_pixbuf_unref (scaled_pixbuf); - return scaled_icon; -} - -static void -revise_scale_factors_if_too_big (GdkPixbuf *pixbuf, - const IconSizeRequest *size, - double *scale_x, - double *scale_y) -{ - guint width, height; - double y_distortion; - - width = gdk_pixbuf_get_width (pixbuf); - height = gdk_pixbuf_get_height (pixbuf); - - if ((int) (width * *scale_x) <= (int) size->maximum_width - && (int) (height * *scale_y) <= (int) size->maximum_height) { - return; - } - - y_distortion = *scale_y / *scale_x; - - *scale_x = MIN ((double) size->maximum_width / width, - (double) size->maximum_height / (height / y_distortion)); - *scale_y = *scale_x * y_distortion; -} - -/* Returns a scaled icon if this one is too big. */ -static CacheIcon * -scale_down_if_too_big (CacheIcon *icon, - const IconSizeRequest *size) -{ - double scale_x, scale_y; - - scale_x = 1.0; - scale_y = 1.0; - revise_scale_factors_if_too_big (icon->pixbuf, size, &scale_x, &scale_y); - return scale_icon (icon, scale_x, scale_y); -} - -/* This load function is not allowed to return NULL. */ -static CacheIcon * -load_icon_scale_if_necessary (NautilusScalableIcon *scalable_icon, - const IconSizeRequest *size) -{ - CacheIcon *icon, *scaled_icon; - guint nominal_actual_size; - double scale_x, scale_y; - - /* Load the icon that's closest in size to what we want. */ - icon = load_icon_for_scaling (scalable_icon, - size->nominal_width, - size->optimized_for_aa, - &nominal_actual_size); - - /* Scale the pixbuf to the size we want. */ - scale_x = (double) size->nominal_width / nominal_actual_size; - scale_y = (double) size->nominal_height / nominal_actual_size; - revise_scale_factors_if_too_big (icon->pixbuf, size, &scale_x, &scale_y); - scaled_icon = scale_icon (icon, scale_x, scale_y); - if (scaled_icon == NULL) { - return icon; - } - - /* Mark this icon as scaled, too. */ - cache_icon_unref (icon); - g_assert (scaled_icon->scaled); - return scaled_icon; -} - -/* Move this item to the head of the recently-used list, - * bumping the last item off that list if necessary. - */ -static void -mark_recently_used (CircularList *node) -{ - NautilusIconFactory *factory; - CircularList *head, *last_node; - - check_recently_used_list (); - - factory = get_icon_factory (); - head = &factory->recently_used_dummy_head; - - /* Move the node to the start of the list. */ - if (node->prev != head) { - if (node->next != NULL) { - /* Remove the node from its current position in the list. */ - node->next->prev = node->prev; - node->prev->next = node->next; - } else { - /* Node was not already in the list, so add it. - * If the list is already full, remove the last node. - */ - if (factory->recently_used_count < ICON_CACHE_COUNT) { - factory->recently_used_count += 1; - } else { - /* Remove the last node. */ - last_node = head->prev; - - g_assert (last_node != head); - g_assert (last_node != node); - - head->prev = last_node->prev; - last_node->prev->next = head; - - last_node->prev = NULL; - last_node->next = NULL; - } - } - - /* Insert the node at the head of the list. */ - node->prev = head; - node->next = head->next; - node->next->prev = node; - head->next = node; - } - - check_recently_used_list (); -} - -/* Utility routine that checks if a cached thumbnail-type icon has - * changed since it was cached. Returns TRUE after removing the icon - * from the cache if the icon has changed. - */ -static gboolean -remove_icons_if_file_changed (const char *file_uri, time_t cached_time) -{ - GnomeVFSResult result; - time_t new_time; - - /* Get the time from the file. */ - result = get_cache_time (file_uri, &new_time); - - /* Do nothing for cases where a time doesn't apply. */ - if (result == GNOME_VFS_ERROR_NOT_SUPPORTED) { - return FALSE; - } - - /* Do nothing if the file is still the same as before. */ - if (result == GNOME_VFS_OK && new_time == cached_time) { - return FALSE; - } - - /* Remove the icon from the cache and inform the caller. */ - nautilus_icon_factory_remove_by_uri (file_uri); - return TRUE; -} - -/* Get the icon, handling the caching. - * If @picky is true, then only an unscaled icon is acceptable. - * Also, if @picky is true, the icon must be a custom icon if - * @custom is true or a standard icon is @custom is false. - */ -static CacheIcon * -get_icon_from_cache (NautilusScalableIcon *scalable_icon, - const IconSizeRequest *size, - IconRequest type) -{ - NautilusIconFactory *factory; - GHashTable *hash_table; - CacheKey lookup_key, *key; - CacheIcon *icon, *scaled_icon; - gpointer key_in_table, value; - - g_return_val_if_fail (scalable_icon != NULL, NULL); - - key = NULL; - icon = NULL; - - factory = get_icon_factory (); - hash_table = factory->icon_cache; - - /* Check to see if it's already in the table. */ - lookup_key.scalable_icon = scalable_icon; - lookup_key.size = *size; - - if (g_hash_table_lookup_extended (hash_table, &lookup_key, - &key_in_table, &value)) { - /* Found it in the table. */ - g_assert (key_in_table != NULL); - g_assert (value != NULL); - key = key_in_table; - icon = value; - - /* If we're going to be picky, then don't accept anything - * other than exactly what we are looking for. - */ - if (type != REQUEST_NORMAL - && (icon->scaled || type != icon->request)) { - return NULL; - } - - /* Check if the cached image is good before using it. */ - if (remove_icons_if_file_changed (scalable_icon->uri, - icon->cache_time)) { - icon = NULL; - } - } - - if (icon == NULL) { - /* Not in the table, so load the image. */ - /* If we're picky, then we want the image only if this exact - * nominal size is available. - */ - if (type != REQUEST_NORMAL) { - g_assert (scalable_icon->embedded_text == NULL); - - /* Actual icons have nominal sizes that are square! */ - if (size->nominal_width != size->nominal_height) { - return NULL; - } - - /* Get the image. */ - icon = load_specific_icon (scalable_icon, - size->nominal_width, - size->optimized_for_aa, - type); - if (icon == NULL) { - return NULL; - } - - /* Now we have the image, but is it bigger - * than the maximum size? If so we scale it, - * but we don't call it "scaled" for caching - * purposese. - */ - scaled_icon = scale_down_if_too_big (icon, size); - if (scaled_icon != NULL) { - scaled_icon->scaled = FALSE; - cache_icon_unref (icon); - icon = scaled_icon; - } - } else { - if (scalable_icon->embedded_text != NULL) { - icon = load_icon_with_embedded_text (scalable_icon, size); - } else { - icon = load_icon_scale_if_necessary (scalable_icon, size); - } - g_assert (icon != NULL); - } - - /* Create the key and icon for the hash table. */ - key = g_new (CacheKey, 1); - nautilus_scalable_icon_ref (scalable_icon); - key->scalable_icon = scalable_icon; - key->size = *size; - - /* Add the item to the hash table. */ - g_assert (g_hash_table_lookup (hash_table, key) == NULL); - g_hash_table_insert (hash_table, key, icon); - } - - /* Hand back a ref to the caller. */ - cache_icon_ref (icon); - - /* Since this item was used, keep it in the cache longer. */ - mark_recently_used (&icon->recently_used_node); - - /* Come back later and sweep the cache. */ - nautilus_icon_factory_schedule_sweep (); - - return icon; -} - -GdkPixbuf * -nautilus_icon_factory_get_pixbuf_for_icon (NautilusScalableIcon *scalable_icon, - guint nominal_width, - guint nominal_height, - guint maximum_width, - guint maximum_height, - gboolean optimized_for_aa, - NautilusEmblemAttachPoints *attach_points, - gboolean wants_default) -{ - IconSizeRequest size; - CacheIcon *icon; - GdkPixbuf *pixbuf; - - size.nominal_width = nominal_width; - size.nominal_height = nominal_width; - size.maximum_width = maximum_width; - size.maximum_height = maximum_height; - size.optimized_for_aa = optimized_for_aa; - icon = get_icon_from_cache (scalable_icon, &size, REQUEST_NORMAL); - - if (attach_points != NULL) { - *attach_points = icon->details.attach_points; - } - - /* if we don't want a default icon and one is returned, return NULL instead */ - if (!wants_default && icon->is_fallback) { - cache_icon_unref (icon); - return NULL; - } - - /* The first time we hand out an icon we just leave it with a - * single ref (we'll get called back for the unref), but - * subsequent times we add additional refs. - */ - pixbuf = icon->pixbuf; - if (!icon->outstanding) { - icon->outstanding = TRUE; - } else { - gdk_pixbuf_ref (pixbuf); - } - cache_icon_unref (icon); - - return pixbuf; -} - -static guint -cache_key_hash (gconstpointer p) -{ - const CacheKey *key; - - key = p; - return (((((((((GPOINTER_TO_UINT (key->scalable_icon) << 4) - ^ key->size.nominal_width) << 4) - ^ key->size.nominal_height) << 4) - ^ key->size.maximum_width) << 4) - ^ key->size.maximum_height) << 1) - | key->size.optimized_for_aa; -} - -static gboolean -cache_key_equal (gconstpointer a, gconstpointer b) -{ - const CacheKey *key_a, *key_b; - - key_a = a; - key_b = b; - - return key_a->scalable_icon == key_b->scalable_icon - && key_a->size.nominal_width == key_b->size.nominal_width - && key_a->size.nominal_height == key_b->size.nominal_height - && key_a->size.maximum_width == key_b->size.maximum_width - && key_a->size.maximum_height == key_b->size.maximum_height - && key_a->size.optimized_for_aa == key_b->size.optimized_for_aa; -} - -/* Return nominal icon size for given zoom level. - * @zoom_level: zoom level for which to find matching icon size. - * - * Return value: icon size between NAUTILUS_ICON_SIZE_SMALLEST and - * NAUTILUS_ICON_SIZE_LARGEST, inclusive. - */ -guint -nautilus_get_icon_size_for_zoom_level (NautilusZoomLevel zoom_level) -{ - switch (zoom_level) { - case NAUTILUS_ZOOM_LEVEL_SMALLEST: - return NAUTILUS_ICON_SIZE_SMALLEST; - case NAUTILUS_ZOOM_LEVEL_SMALLER: - return NAUTILUS_ICON_SIZE_SMALLER; - case NAUTILUS_ZOOM_LEVEL_SMALL: - return NAUTILUS_ICON_SIZE_SMALL; - case NAUTILUS_ZOOM_LEVEL_STANDARD: - return NAUTILUS_ICON_SIZE_STANDARD; - case NAUTILUS_ZOOM_LEVEL_LARGE: - return NAUTILUS_ICON_SIZE_LARGE; - case NAUTILUS_ZOOM_LEVEL_LARGER: - return NAUTILUS_ICON_SIZE_LARGER; - case NAUTILUS_ZOOM_LEVEL_LARGEST: - return NAUTILUS_ICON_SIZE_LARGEST; - } - g_return_val_if_fail (FALSE, NAUTILUS_ICON_SIZE_STANDARD); -} - -/* Convenience cover for nautilus_icon_factory_get_icon_for_file - * and nautilus_icon_factory_get_pixbuf_for_icon. - */ -GdkPixbuf * -nautilus_icon_factory_get_pixbuf_for_file (NautilusFile *file, - const char *modifer, - guint size_in_pixels, - gboolean optimized_for_aa) -{ - NautilusScalableIcon *icon; - GdkPixbuf *pixbuf; - - /* Get the pixbuf for this file. */ - icon = nautilus_icon_factory_get_icon_for_file (file, modifer); - if (icon == NULL) { - return NULL; - } - pixbuf = nautilus_icon_factory_get_pixbuf_for_icon - (icon, - size_in_pixels, size_in_pixels, - size_in_pixels, size_in_pixels, - optimized_for_aa, - NULL, TRUE); - nautilus_scalable_icon_unref (icon); - - return pixbuf; -} - -/* Convenience cover for nautilus_icon_factory_get_icon_for_file, - * nautilus_icon_factory_get_pixbuf_for_icon, - * and gdk_pixbuf_render_pixmap_and_mask. - */ -void -nautilus_icon_factory_get_pixmap_and_mask_for_file (NautilusFile *file, - const char *modifer, - guint size_in_pixels, - GdkPixmap **pixmap, - GdkBitmap **mask) -{ - GdkPixbuf *pixbuf; - - g_return_if_fail (pixmap != NULL); - g_return_if_fail (mask != NULL); - - *pixmap = NULL; - *mask = NULL; - - pixbuf = nautilus_icon_factory_get_pixbuf_for_file (file, modifer, size_in_pixels, FALSE); - if (pixbuf == NULL) { - return; - } - gdk_pixbuf_render_pixmap_and_mask (pixbuf, pixmap, mask, EEL_STANDARD_ALPHA_THRESHHOLD); - gdk_pixbuf_unref (pixbuf); -} - -/* Convenience routine for getting a pixbuf from an icon name. */ -GdkPixbuf * -nautilus_icon_factory_get_pixbuf_from_name (const char *icon_name, - const char *modifier, - guint size_in_pixels, - gboolean optimized_for_aa) -{ - GdkPixbuf *pixbuf; - NautilusScalableIcon *icon; - - icon = nautilus_scalable_icon_new_from_text_pieces (NULL, NULL, icon_name, modifier, NULL); - pixbuf = nautilus_icon_factory_get_pixbuf_for_icon (icon, - size_in_pixels, size_in_pixels, - size_in_pixels, size_in_pixels, - optimized_for_aa, - NULL, TRUE); - nautilus_scalable_icon_unref (icon); - return pixbuf; -} - - -static gboolean -embedded_text_rect_usable (ArtIRect embedded_text_rect) -{ - if (art_irect_empty (&embedded_text_rect)) { - return FALSE; - } - - if (embedded_text_rect.x1 - embedded_text_rect.x0 - < MINIMUM_EMBEDDED_TEXT_RECT_WIDTH || - embedded_text_rect.y1 - embedded_text_rect.y0 - < MINIMUM_EMBEDDED_TEXT_RECT_HEIGHT) { - return FALSE; - } - - return TRUE; -} - -static gboolean embedded_text_preferences_callbacks_added = FALSE; -static EelScalableFont *embedded_text_font = NULL; - -static void -embedded_text_font_changed_callback (gpointer callback_data) -{ - gboolean clear_cache = GPOINTER_TO_INT (callback_data); - - embedded_text_font = nautilus_global_preferences_get_default_smooth_font (); - - if (clear_cache) { - nautilus_icon_factory_clear (); - } -} - -static void -embedded_text_font_free (void) -{ - if (embedded_text_font == NULL) { - return; - } - - gtk_object_unref (GTK_OBJECT (embedded_text_font)); - embedded_text_font = NULL; -} - -static GdkPixbuf * -embed_text (GdkPixbuf *pixbuf_without_text, - ArtIRect embedded_text_rect, - const char *text) -{ - EelSmoothTextLayout *smooth_text_layout; - GdkPixbuf *pixbuf_with_text; - - g_return_val_if_fail (pixbuf_without_text != NULL, NULL); - - /* Quick out for the case where there's no place to embed the - * text or the place is too small or there's no text. - */ - if (!embedded_text_rect_usable (embedded_text_rect) || eel_strlen (text) == 0) { - return NULL; - } - - /* Listen for changes in embedded text (icon text preview) font preferences */ - if (embedded_text_preferences_callbacks_added == FALSE) { - embedded_text_preferences_callbacks_added = TRUE; - - nautilus_preferences_add_callback (NAUTILUS_PREFERENCES_DEFAULT_SMOOTH_FONT, - embedded_text_font_changed_callback, - GINT_TO_POINTER (TRUE)); - embedded_text_font_changed_callback (GINT_TO_POINTER (FALSE)); - - g_atexit (embedded_text_font_free); - } - - g_return_val_if_fail (EEL_IS_SCALABLE_FONT (embedded_text_font), NULL); - - smooth_text_layout = eel_smooth_text_layout_new (text, - eel_strlen (text), - embedded_text_font, - EMBEDDED_TEXT_FONT_SIZE, - FALSE); - g_return_val_if_fail (EEL_IS_SMOOTH_TEXT_LAYOUT (smooth_text_layout), NULL); - eel_smooth_text_layout_set_line_spacing (smooth_text_layout, EMBEDDED_TEXT_LINE_SPACING); - eel_smooth_text_layout_set_empty_line_height (smooth_text_layout, EMBEDDED_TEXT_EMPTY_LINE_HEIGHT); - - pixbuf_with_text = gdk_pixbuf_copy (pixbuf_without_text); - - eel_smooth_text_layout_draw_to_pixbuf (smooth_text_layout, - pixbuf_with_text, - 0, - 0, - embedded_text_rect, - GTK_JUSTIFY_LEFT, - FALSE, - EEL_RGB_COLOR_BLACK, - EEL_OPACITY_FULLY_OPAQUE); - - gtk_object_unref (GTK_OBJECT (smooth_text_layout)); - - return pixbuf_with_text; -} - -static CacheIcon * -load_icon_with_embedded_text (NautilusScalableIcon *scalable_icon, - const IconSizeRequest *size) -{ - NautilusScalableIcon *scalable_icon_without_text; - CacheIcon *icon_without_text, *icon_with_text; - GdkPixbuf *pixbuf_with_text; - IconDetails details; - - g_assert (scalable_icon->embedded_text != NULL); - - /* Get the icon without text. */ - scalable_icon_without_text = nautilus_scalable_icon_new_from_text_pieces - (scalable_icon->uri, - scalable_icon->mime_type, - scalable_icon->name, - scalable_icon->modifier, - NULL); - icon_without_text = get_icon_from_cache - (scalable_icon_without_text, size, REQUEST_NORMAL); - nautilus_scalable_icon_unref (scalable_icon_without_text); - - /* Create a pixbuf with the text in it. */ - pixbuf_with_text = embed_text (icon_without_text->pixbuf, - icon_without_text->details.text_rect, - scalable_icon->embedded_text); - if (pixbuf_with_text == NULL) { - return icon_without_text; - } - - /* Create an icon from the new pixbuf. */ - details = icon_without_text->details; - memset (&details.text_rect, 0, sizeof (details.text_rect)); - icon_with_text = cache_icon_new (pixbuf_with_text, - icon_without_text->request, - icon_without_text->scaled, - &details); - icon_with_text->cache_time = icon_without_text->cache_time; - cache_icon_unref (icon_without_text); - gdk_pixbuf_unref (pixbuf_with_text); - - return icon_with_text; -} - -/* Convenience function for unrefing and then freeing an entire list. */ -void -nautilus_scalable_icon_list_free (GList *icon_list) -{ - eel_g_list_free_deep_custom - (icon_list, (GFunc) nautilus_scalable_icon_unref, NULL); -} - -#if ! defined (NAUTILUS_OMIT_SELF_CHECK) - -static char * -self_test_next_icon_size_to_try (guint start_size, guint current_size) -{ - gboolean got_next_size; - - got_next_size = get_next_icon_size_to_try (start_size, ¤t_size); - return g_strdup_printf ("%s,%d", got_next_size ? "TRUE" : "FALSE", current_size); -} - -void -nautilus_self_check_icon_factory (void) -{ - EEL_CHECK_INTEGER_RESULT (nautilus_get_icon_size_for_zoom_level (0), 12); - EEL_CHECK_INTEGER_RESULT (nautilus_get_icon_size_for_zoom_level (1), 24); - EEL_CHECK_INTEGER_RESULT (nautilus_get_icon_size_for_zoom_level (2), 36); - EEL_CHECK_INTEGER_RESULT (nautilus_get_icon_size_for_zoom_level (3), 48); - EEL_CHECK_INTEGER_RESULT (nautilus_get_icon_size_for_zoom_level (4), 72); - EEL_CHECK_INTEGER_RESULT (nautilus_get_icon_size_for_zoom_level (5), 96); - EEL_CHECK_INTEGER_RESULT (nautilus_get_icon_size_for_zoom_level (6), 192); - - EEL_CHECK_INTEGER_RESULT (get_larger_icon_size (0), 12); - EEL_CHECK_INTEGER_RESULT (get_larger_icon_size (1), 12); - EEL_CHECK_INTEGER_RESULT (get_larger_icon_size (11), 12); - EEL_CHECK_INTEGER_RESULT (get_larger_icon_size (12), 20); - EEL_CHECK_INTEGER_RESULT (get_larger_icon_size (19), 20); - EEL_CHECK_INTEGER_RESULT (get_larger_icon_size (20), 24); - EEL_CHECK_INTEGER_RESULT (get_larger_icon_size (23), 24); - EEL_CHECK_INTEGER_RESULT (get_larger_icon_size (24), 36); - EEL_CHECK_INTEGER_RESULT (get_larger_icon_size (35), 36); - EEL_CHECK_INTEGER_RESULT (get_larger_icon_size (36), 48); - EEL_CHECK_INTEGER_RESULT (get_larger_icon_size (47), 48); - EEL_CHECK_INTEGER_RESULT (get_larger_icon_size (48), 72); - EEL_CHECK_INTEGER_RESULT (get_larger_icon_size (71), 72); - EEL_CHECK_INTEGER_RESULT (get_larger_icon_size (72), 96); - EEL_CHECK_INTEGER_RESULT (get_larger_icon_size (95), 96); - EEL_CHECK_INTEGER_RESULT (get_larger_icon_size (96), 192); - EEL_CHECK_INTEGER_RESULT (get_larger_icon_size (191), 192); - EEL_CHECK_INTEGER_RESULT (get_larger_icon_size (192), 192); - EEL_CHECK_INTEGER_RESULT (get_larger_icon_size (0xFFFFFFFF), 192); - - EEL_CHECK_INTEGER_RESULT (get_smaller_icon_size (0), 12); - EEL_CHECK_INTEGER_RESULT (get_smaller_icon_size (1), 12); - EEL_CHECK_INTEGER_RESULT (get_smaller_icon_size (11), 12); - EEL_CHECK_INTEGER_RESULT (get_smaller_icon_size (12), 12); - EEL_CHECK_INTEGER_RESULT (get_smaller_icon_size (20), 12); - EEL_CHECK_INTEGER_RESULT (get_smaller_icon_size (21), 20); - EEL_CHECK_INTEGER_RESULT (get_smaller_icon_size (24), 20); - EEL_CHECK_INTEGER_RESULT (get_smaller_icon_size (25), 24); - EEL_CHECK_INTEGER_RESULT (get_smaller_icon_size (36), 24); - EEL_CHECK_INTEGER_RESULT (get_smaller_icon_size (37), 36); - EEL_CHECK_INTEGER_RESULT (get_smaller_icon_size (48), 36); - EEL_CHECK_INTEGER_RESULT (get_smaller_icon_size (49), 48); - EEL_CHECK_INTEGER_RESULT (get_smaller_icon_size (72), 48); - EEL_CHECK_INTEGER_RESULT (get_smaller_icon_size (73), 72); - EEL_CHECK_INTEGER_RESULT (get_smaller_icon_size (96), 72); - EEL_CHECK_INTEGER_RESULT (get_smaller_icon_size (97), 96); - EEL_CHECK_INTEGER_RESULT (get_smaller_icon_size (192), 96); - EEL_CHECK_INTEGER_RESULT (get_smaller_icon_size (193), 192); - EEL_CHECK_INTEGER_RESULT (get_smaller_icon_size (0xFFFFFFFF), 192); - - EEL_CHECK_STRING_RESULT (self_test_next_icon_size_to_try (0, 0), "TRUE,12"); - EEL_CHECK_STRING_RESULT (self_test_next_icon_size_to_try (0, 12), "TRUE,20"); - EEL_CHECK_STRING_RESULT (self_test_next_icon_size_to_try (0, 20), "TRUE,24"); - EEL_CHECK_STRING_RESULT (self_test_next_icon_size_to_try (0, 24), "TRUE,36"); - EEL_CHECK_STRING_RESULT (self_test_next_icon_size_to_try (0, 36), "TRUE,48"); - EEL_CHECK_STRING_RESULT (self_test_next_icon_size_to_try (0, 48), "TRUE,72"); - EEL_CHECK_STRING_RESULT (self_test_next_icon_size_to_try (0, 72), "TRUE,96"); - EEL_CHECK_STRING_RESULT (self_test_next_icon_size_to_try (0, 96), "TRUE,192"); - EEL_CHECK_STRING_RESULT (self_test_next_icon_size_to_try (0, 192), "FALSE,192"); - - EEL_CHECK_STRING_RESULT (self_test_next_icon_size_to_try (36, 0), "TRUE,36"); - EEL_CHECK_STRING_RESULT (self_test_next_icon_size_to_try (36, 36), "TRUE,48"); - EEL_CHECK_STRING_RESULT (self_test_next_icon_size_to_try (36, 48), "TRUE,72"); - EEL_CHECK_STRING_RESULT (self_test_next_icon_size_to_try (36, 72), "TRUE,96"); - EEL_CHECK_STRING_RESULT (self_test_next_icon_size_to_try (36, 96), "TRUE,192"); - EEL_CHECK_STRING_RESULT (self_test_next_icon_size_to_try (36, 192), "TRUE,24"); - EEL_CHECK_STRING_RESULT (self_test_next_icon_size_to_try (36, 24), "TRUE,20"); - EEL_CHECK_STRING_RESULT (self_test_next_icon_size_to_try (36, 20), "TRUE,12"); - EEL_CHECK_STRING_RESULT (self_test_next_icon_size_to_try (36, 12), "FALSE,12"); - - EEL_CHECK_STRING_RESULT (self_test_next_icon_size_to_try (37, 0), "TRUE,48"); - EEL_CHECK_STRING_RESULT (self_test_next_icon_size_to_try (37, 48), "TRUE,72"); - EEL_CHECK_STRING_RESULT (self_test_next_icon_size_to_try (37, 72), "TRUE,96"); - EEL_CHECK_STRING_RESULT (self_test_next_icon_size_to_try (37, 96), "TRUE,192"); - EEL_CHECK_STRING_RESULT (self_test_next_icon_size_to_try (37, 192), "TRUE,36"); - EEL_CHECK_STRING_RESULT (self_test_next_icon_size_to_try (37, 36), "TRUE,24"); - EEL_CHECK_STRING_RESULT (self_test_next_icon_size_to_try (37, 24), "TRUE,20"); - EEL_CHECK_STRING_RESULT (self_test_next_icon_size_to_try (37, 20), "TRUE,12"); - EEL_CHECK_STRING_RESULT (self_test_next_icon_size_to_try (37, 12), "FALSE,12"); - - EEL_CHECK_STRING_RESULT (self_test_next_icon_size_to_try (0xFFFFFFFF, 0), "TRUE,192"); - EEL_CHECK_STRING_RESULT (self_test_next_icon_size_to_try (0xFFFFFFFF, 192), "TRUE,96"); - EEL_CHECK_STRING_RESULT (self_test_next_icon_size_to_try (0xFFFFFFFF, 96), "TRUE,72"); - EEL_CHECK_STRING_RESULT (self_test_next_icon_size_to_try (0xFFFFFFFF, 72), "TRUE,48"); - EEL_CHECK_STRING_RESULT (self_test_next_icon_size_to_try (0xFFFFFFFF, 48), "TRUE,36"); - EEL_CHECK_STRING_RESULT (self_test_next_icon_size_to_try (0xFFFFFFFF, 36), "TRUE,24"); - EEL_CHECK_STRING_RESULT (self_test_next_icon_size_to_try (0xFFFFFFFF, 24), "TRUE,20"); - EEL_CHECK_STRING_RESULT (self_test_next_icon_size_to_try (0xFFFFFFFF, 20), "TRUE,12"); - EEL_CHECK_STRING_RESULT (self_test_next_icon_size_to_try (0xFFFFFFFF, 12), "FALSE,12"); -} - -#endif /* ! NAUTILUS_OMIT_SELF_CHECK */ diff --git a/libnautilus-extensions/nautilus-icon-factory.h b/libnautilus-extensions/nautilus-icon-factory.h deleted file mode 100644 index 8c10173d6..000000000 --- a/libnautilus-extensions/nautilus-icon-factory.h +++ /dev/null @@ -1,183 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- - - nautilus-icon-factory.h: Class for obtaining icons for files and other objects. - - Copyright (C) 1999, 2000 Red Hat Inc. - Copyright (C) 1999, 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. - - Author: John Sullivan <sullivan@eazel.com> -*/ - -#ifndef NAUTILUS_ICON_FACTORY_H -#define NAUTILUS_ICON_FACTORY_H - -#include <gdk-pixbuf/gdk-pixbuf.h> -#include <libnautilus-extensions/nautilus-file.h> -#include <eel/eel-string-list.h> -#include <gtk/gtkobject.h> - -/* NautilusIconFactory is a class that knows how to hand out icons to be - * used for representing files and some other objects. It was designed - * specifically to be useful for the Nautilus file browser, but could be - * used by any program that wants to display the standard icon for a - * file. - * - * The most common usage is to get a NautilusIconFactory object with - * nautilus_get_current_icon_factory, then ask for an icon for a specific - * file with nautilus_icon_factory_get_icon_for_file. The caller can ask - * for any size icon, but normally will use one of the defined - * NAUTILUS_ICON_SIZE macros. - */ - -/* Names for Nautilus's different zoom levels, from tiniest items to largest items */ -typedef enum { - NAUTILUS_ZOOM_LEVEL_SMALLEST, - NAUTILUS_ZOOM_LEVEL_SMALLER, - NAUTILUS_ZOOM_LEVEL_SMALL, - NAUTILUS_ZOOM_LEVEL_STANDARD, - NAUTILUS_ZOOM_LEVEL_LARGE, - NAUTILUS_ZOOM_LEVEL_LARGER, - NAUTILUS_ZOOM_LEVEL_LARGEST -} NautilusZoomLevel; - -/* Nominal icon sizes for each Nautilus zoom level. - * This scheme assumes that icons are designed to - * fit in a square space, though each image needn't - * be square. Since individual icons can be stretched, - * each icon is not constrained to this nominal size. - */ -#define NAUTILUS_ICON_SIZE_SMALLEST 12 -#define NAUTILUS_ICON_SIZE_SMALLER 24 -#define NAUTILUS_ICON_SIZE_SMALL 36 -#define NAUTILUS_ICON_SIZE_STANDARD 48 -#define NAUTILUS_ICON_SIZE_LARGE 72 -#define NAUTILUS_ICON_SIZE_LARGER 96 -#define NAUTILUS_ICON_SIZE_LARGEST 192 - -/* Icon size to use for menus. NAUTILUS_ICON_SIZE_SMALLEST - * is a little too small and NAUTILUS_ICON_SIZE_SMALLER is - * a little too big. - */ -#define NAUTILUS_ICON_SIZE_FOR_MENUS 20 - -typedef struct NautilusScalableIcon NautilusScalableIcon; - -/* here's a structure to hold the emblem attach points */ - -#define MAX_ATTACH_POINTS 8 - -typedef struct { - int num_points; - GdkPoint points[MAX_ATTACH_POINTS]; -} NautilusEmblemAttachPoints; - -/* Instead of a class declaration here, I will just document - * the signals. - * - * "icons_changed", no parameters - */ - -/* There's a single NautilusIconFactory object. - * The only thing you need it for is to connect to its signals. - */ -GtkObject * nautilus_icon_factory_get (void); - -/* Relationship between zoom levels and icons sizes. */ -guint nautilus_get_icon_size_for_zoom_level (NautilusZoomLevel zoom_level); - -/* Choose the appropriate icon, but don't render it yet. */ -NautilusScalableIcon *nautilus_icon_factory_get_icon_for_file (NautilusFile *file, - const char *modifier); -gboolean nautilus_icon_factory_is_icon_ready_for_file (NautilusFile *file); -GList * nautilus_icon_factory_get_required_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); - -/* Render an icon to a particular size. - * Ownership of a ref. count in this pixbuf comes with the deal. - * This allows scaling in both dimensions. All other calls assume - * that X and Y scaling are the same. Optionally, we also pass - * back an array of emblem attach points, if the pointer is non-null - * If the wants_default boolean is set, return a default icon instead - * of NULL if we can't find anything - */ -GdkPixbuf * nautilus_icon_factory_get_pixbuf_for_icon (NautilusScalableIcon *scalable_icon, - guint nominal_size_in_pixels_x, - guint nominal_size_in_pixels_y, - guint maximum_size_in_pixels_x, - guint maximum_size_in_pixels_y, - gboolean optimized_for_anti_aliasing, - NautilusEmblemAttachPoints *attach_points, - gboolean wants_default); - -/* Convenience functions for the common case where you want to choose - * and render the icon into a pixbuf all at once. - */ -GdkPixbuf * nautilus_icon_factory_get_pixbuf_for_file (NautilusFile *file, - const char *modifer, - guint size_in_pixels, - gboolean optimized_for_anti_aliasing); - -/* Convenience functions for legacy interfaces that require a pixmap and - * bitmap. Maybe we can get rid of these one day. - */ -void nautilus_icon_factory_get_pixmap_and_mask_for_file (NautilusFile *file, - const char *modifer, - guint size_in_pixels, - GdkPixmap **pixmap, - GdkBitmap **mask); -/* Convenience routine for getting a pixbuf from an icon name - */ -GdkPixbuf * nautilus_icon_factory_get_pixbuf_from_name (const char *icon_name, - const char *modifer, - guint size_in_pixels, - gboolean optimized_for_anti_aliasing); -/* Manage a scalable icon. - * Since the factory always passes out references to the same scalable - * icon, you can compare two scalable icons to see if they are the same - * with ==. - */ -void nautilus_scalable_icon_ref (NautilusScalableIcon *scalable_icon); -void nautilus_scalable_icon_unref (NautilusScalableIcon *scalable_icon); - -/* A scalable icon can be decomposed into text and reconstituted later - * using nautilus_scalable_icon_new_from_text_pieces. This is the way - * to store scalable icons in metadata or other files. - */ -void nautilus_scalable_icon_get_text_pieces (NautilusScalableIcon *scalable_icon, - char **uri_return, - char **mime_type_return, - char **name_return, - char **modifier_return, - char **embedded_text_return); -/* Get a scalable icon using the earlier results of - * nautilus_scalable_icon_get_text_pieces. - */ -NautilusScalableIcon *nautilus_scalable_icon_new_from_text_pieces (const char *uri, - const char *mime_type, - const char *name, - const char *modifier, - const char *embedded_text); - -/* Convenience function for freeing a list of scalable icons. - * Unrefs all the icons before freeing the list. - */ -void nautilus_scalable_icon_list_free (GList *scalable_icon_list); - -#endif /* NAUTILUS_ICON_FACTORY_H */ diff --git a/libnautilus-extensions/nautilus-icon-private.h b/libnautilus-extensions/nautilus-icon-private.h deleted file mode 100644 index b1b73c147..000000000 --- a/libnautilus-extensions/nautilus-icon-private.h +++ /dev/null @@ -1,257 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ -/* gnome-icon-container-private.h - - Copyright (C) 1999, 2000 Free Software Foundation - Copyright (C) 2000 Eazel, Inc. - - The Gnome 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 Gnome 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 the Gnome 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. - - Author: Ettore Perazzoli <ettore@gnu.org> -*/ - -#ifndef NAUTILUS_ICON_CONTAINER_PRIVATE_H -#define NAUTILUS_ICON_CONTAINER_PRIVATE_H - -#include "nautilus-entry.h" -#include <eel/eel-glib-extensions.h> -#include "nautilus-icon-container.h" -#include "nautilus-icon-dnd.h" -#include "nautilus-icon-factory.h" -#include "nautilus-icon-canvas-item.h" -#include "nautilus-icon-text-item.h" - -/* An Icon. */ - -typedef struct { - /* Object represented by this icon. */ - NautilusIconData *data; - - /* Canvas item for the icon. */ - NautilusIconCanvasItem *item; - - /* X/Y coordinates. */ - double x, y; - - /* Scale factor (stretches icon). */ - double scale_x, scale_y; - - /* Whether this item is selected. */ - eel_boolean_bit is_selected : 1; - - /* Whether this item was selected before rubberbanding. */ - eel_boolean_bit was_selected_before_rubberband : 1; -} NautilusIcon; - - -/* Private NautilusIconContainer members. */ - -typedef struct { - gboolean active; - - double start_x, start_y; - - GnomeCanvasItem *selection_rectangle; - - guint timer_id; - - guint prev_x, prev_y; - ArtDRect prev_rect; -} NautilusIconRubberbandInfo; - -typedef enum { - DRAG_STATE_INITIAL, - DRAG_STATE_MOVE_OR_COPY, - DRAG_STATE_MOVE_COPY_OR_MENU, - DRAG_STATE_STRETCH -} DragState; - -typedef struct { - /* Pointer position in canvas coordinates. */ - int pointer_x, pointer_y; - - /* Icon top, left, and size in canvas coordinates. */ - int icon_x, icon_y; - guint icon_size; -} StretchState; - -typedef enum { - AXIS_NONE, - AXIS_HORIZONTAL, - AXIS_VERTICAL -} Axis; - -typedef struct { - char *type_select_pattern; - guint64 last_typeselect_time; -} TypeSelectState; - -struct NautilusIconContainerDetails { - /* List of icons. */ - GList *icons; - GList *new_icons; - - /* Current icon for keyboard navigation. */ - NautilusIcon *keyboard_focus; - - /* Current icon with stretch handles, so we have only one. */ - NautilusIcon *stretch_icon; - double stretch_initial_x, stretch_initial_y; - guint stretch_initial_size; - - /* Last highlighted drop target. */ - NautilusIcon *drop_target; - - /* Rubberbanding status. */ - NautilusIconRubberbandInfo rubberband_info; - - /* Timeout used to make a selected icon fully visible after a short - * period of time. (The timeout is needed to make sure - * double-clicking still works.) - */ - guint keyboard_icon_reveal_timer_id; - NautilusIcon *keyboard_icon_to_reveal; - - /* If a request is made to reveal an unpositioned icon we remember - * it and reveal it once it gets positioned (in relayout). - */ - NautilusIcon *pending_icon_to_reveal; - - /* If a request is made to rename an unpositioned icon we remember - * it and start renaming it once it gets positioned (in relayout). - */ - NautilusIcon *pending_icon_to_rename; - - /* Remembered information about the start of the current event. */ - guint32 button_down_time; - - /* Drag state. Valid only if drag_button is non-zero. */ - guint drag_button; - NautilusIcon *drag_icon; - int drag_x, drag_y; - DragState drag_state; - gboolean drag_started; - StretchState stretch_start; - int context_menu_timeout_id; - - /* Renaming Details */ - gboolean renaming; - NautilusIconTextItem *rename_widget; /* Editable text item */ - char *original_text; /* Copy of editable text for later compare */ - - /* typeahead selection state */ - TypeSelectState *type_select_state; - - /* Idle ID. */ - guint idle_id; - - /* Idle handler for stretch code */ - guint stretch_idle_id; - - /* Timeout for selection in browser mode. */ - guint linger_selection_mode_timer_id; - - /* Icon to be selected at timeout in browser mode. */ - NautilusIcon *linger_selection_mode_icon; - - /* DnD info. */ - NautilusIconDndInfo *dnd_info; - - /* zoom level */ - int zoom_level; - - /* fonts used to draw labels in regular mode */ - GdkFont *label_font[NAUTILUS_ZOOM_LEVEL_LARGEST + 1]; - - /* font used to draw labels in smooth mode */ - EelScalableFont *smooth_label_font; - int font_size_table[NAUTILUS_ZOOM_LEVEL_LARGEST + 1]; - - /* pixbuf and color for label highlighting */ - GdkPixbuf *highlight_frame; - guint32 highlight_color; - - /* color for text labels */ - guint32 label_color; - guint32 label_info_color; - - /* State used so arrow keys don't wander if icons aren't lined up. - * Keeps track of last axis arrow key was used on. - */ - Axis arrow_key_axis; - int arrow_key_start; - - /* Mode settings. */ - gboolean single_click_mode; - gboolean auto_layout; - gboolean tighter_layout; - - /* Layout mode */ - NautilusIconLayoutMode layout_mode; - - /* Set to TRUE after first allocation has been done */ - gboolean has_been_allocated; - - /* Is the container fixed or resizable */ - gboolean is_fixed_size; - - /* Ignore the visible area the next time the scroll region is recomputed */ - gboolean reset_scroll_region_trigger; - - /* The position we are scaling to on stretch */ - int window_x; - int window_y; - - /* margins to follow, used for the desktop panel avoidance */ - int left_margin; - int right_margin; - int top_margin; - int bottom_margin; -}; - -/* Private functions shared by mutiple files. */ -NautilusIcon *nautilus_icon_container_get_icon_by_uri (NautilusIconContainer *container, - const char *uri); -void nautilus_icon_container_move_icon (NautilusIconContainer *container, - NautilusIcon *icon, - int x, - int y, - double scale_x, - double scale_y, - gboolean raise, - gboolean update_position); -void nautilus_icon_container_select_list_unselect_others (NautilusIconContainer *container, - GList *icons); -char * nautilus_icon_container_get_icon_uri (NautilusIconContainer *container, - NautilusIcon *icon); -char * nautilus_icon_container_get_icon_drop_target_uri (NautilusIconContainer *container, - NautilusIcon *icon); -void nautilus_icon_container_update_icon (NautilusIconContainer *container, - NautilusIcon *icon); -void nautilus_icon_container_flush_typeselect_state (NautilusIconContainer *container); -gboolean nautilus_icon_container_has_stored_icon_positions (NautilusIconContainer *container); -gboolean nautilus_icon_container_emit_preview_signal (NautilusIconContainer *view, - NautilusIcon *icon, - gboolean start_flag); -gboolean nautilus_icon_container_scroll (NautilusIconContainer *container, - int delta_x, - int delta_y); -void nautilus_icon_container_update_scroll_region (NautilusIconContainer *container); - -/* label color for items */ -guint32 nautilus_icon_container_get_label_color (NautilusIconContainer *container, - gboolean first_line); - -#endif /* NAUTILUS_ICON_CONTAINER_PRIVATE_H */ diff --git a/libnautilus-extensions/nautilus-icon-text-item.c b/libnautilus-extensions/nautilus-icon-text-item.c deleted file mode 100644 index af72de11d..000000000 --- a/libnautilus-extensions/nautilus-icon-text-item.c +++ /dev/null @@ -1,1614 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ - -/* nautilus-icon-text-item: an editable text block with word wrapping for the - * GNOME canvas. - * - * Copyright (C) 1998, 1999 The Free Software Foundation - * - * Authors: Miguel de Icaza <miguel@gnu.org> - * Federico Mena <federico@gimp.org> - * - */ - -#include <config.h> -#include "nautilus-icon-text-item.h" - -#include "nautilus-entry.h" -#include "nautilus-theme.h" - -#include <libnautilus/nautilus-undo.h> -#include <eel/eel-gdk-extensions.h> -#include <eel/eel-glib-extensions.h> - -#include <math.h> -#include <stdio.h> -#include <gdk/gdkkeysyms.h> -#include <gtk/gtkmain.h> -#include <gtk/gtksignal.h> -#include <gtk/gtkwindow.h> -#include <libgnome/gnome-i18n.h> -#include <libart_lgpl/art_rgb_affine.h> -#include <libart_lgpl/art_rgb_rgba_affine.h> -#include <gdk-pixbuf/gdk-pixbuf.h> - -/* Margins used to display the information */ -#define MARGIN_X 2 -#define MARGIN_Y 2 - -/* Default fontset to be used if the user specified fontset is not found */ -#define DEFAULT_FONT_NAME "-adobe-helvetica-medium-r-normal--*-100-*-*-*-*-*-*," \ - "-*-*-medium-r-normal--10-*-*-*-*-*-*-*,*" - -/* Separators for text layout */ -#define DEFAULT_SEPARATORS " \t-.[]#" - -/* Aliases to minimize screen use in my laptop */ -#define ITI(x) NAUTILUS_ICON_TEXT_ITEM (x) -#define ITI_CLASS(x) NAUTILUS_ICON_TEXT_ITEM_CLASS (x) -#define IS_ITI(x) NAUTILUS_IS_ICON_TEXT_ITEM (x) - -typedef NautilusIconTextItem Iti; - -/* Signal callbacks */ -static void register_rename_undo (NautilusIconTextItem *item); -static void restore_from_undo_snapshot_callback (GtkObject *target, gpointer callback_data); - -/* Private part of the NautilusIconTextItem structure */ -typedef struct { - /* Font */ - GdkFont *font; - - /* Create an offscreen window and place an entry inside it */ - NautilusEntry *entry; - GtkWidget *entry_top; - - /* Store min width and height. These are used when the text entry is empty. */ - int min_width; - int min_height; - - gboolean undo_registered; - -} ItiPrivate; - - -static GnomeCanvasItemClass *parent_class; - -enum { - ARG_0, -}; - -enum { - TEXT_CHANGED, - TEXT_EDITED, - HEIGHT_CHANGED, - WIDTH_CHANGED, - EDITING_STARTED, - EDITING_STOPPED, - SELECTION_STARTED, - SELECTION_STOPPED, - LAST_SIGNAL -}; -static guint iti_signals [LAST_SIGNAL] = { 0 }; - -static void -send_focus_event (Iti *iti, gboolean in) -{ - ItiPrivate *priv; - GtkWidget *widget; - gboolean has_focus; - GdkEvent fake_event; - - g_assert (in == FALSE || in == TRUE); - - priv = iti->priv; - if (priv->entry == NULL) { - g_assert (!in); - return; - } - - widget = GTK_WIDGET (priv->entry); - has_focus = GTK_WIDGET_HAS_FOCUS (widget); - if (has_focus == in) { - return; - } - - memset (&fake_event, 0, sizeof (fake_event)); - fake_event.focus_change.type = GDK_FOCUS_CHANGE; - fake_event.focus_change.window = widget->window; - fake_event.focus_change.in = in; - gtk_widget_event (widget, &fake_event); - g_assert (GTK_WIDGET_HAS_FOCUS (widget) == in); -} - -/* Stops the editing state of an icon text item */ -static void -iti_stop_editing (Iti *iti) -{ - ItiPrivate *priv; - - priv = iti->priv; - - iti->editing = FALSE; - - send_focus_event (iti, FALSE); - - gnome_canvas_item_request_update (GNOME_CANVAS_ITEM (iti)); - - gtk_signal_emit (GTK_OBJECT (iti), iti_signals[EDITING_STOPPED]); -} - -/* Lays out the text in an icon item */ -static void -layout_text (Iti *iti) -{ - ItiPrivate *priv; - char *text; - int old_width, old_height; - int width, height; - - priv = iti->priv; - - /* Save old size */ - if (iti->ti) { - old_width = iti->ti->width + 2 * MARGIN_X; - old_height = iti->ti->height + 2 * MARGIN_Y; - - gnome_icon_text_info_free (iti->ti); - } else { - old_width = 2 * MARGIN_X; - old_height = 2 * MARGIN_Y; - } - - /* Change the text layout */ - if (iti->editing) { - text = gtk_entry_get_text (GTK_ENTRY(priv->entry)); - } else { - text = iti->text; - } - - iti->ti = gnome_icon_layout_text (priv->font, - text, - DEFAULT_SEPARATORS, - iti->max_text_width - 2 * MARGIN_X, - TRUE); - - /* Check the sizes and see if we need to emit any signals */ - width = iti->ti->width + 2 * MARGIN_X; - height = iti->ti->height + 2 * MARGIN_Y; - - if (width != old_width) - gtk_signal_emit (GTK_OBJECT (iti), iti_signals[WIDTH_CHANGED]); - - if (height != old_height) - gtk_signal_emit (GTK_OBJECT (iti), iti_signals[HEIGHT_CHANGED]); - - gtk_signal_emit (GTK_OBJECT (iti), iti_signals [TEXT_EDITED]); -} - -/* Accepts the text in the off-screen entry of an icon text item */ -static void -iti_edition_accept (Iti *iti) -{ - ItiPrivate *priv; - gboolean accept; - - priv = iti->priv; - accept = TRUE; - - gtk_signal_emit (GTK_OBJECT (iti), iti_signals [TEXT_CHANGED], &accept); - - if (iti->editing){ - if (accept) { - if (iti->is_text_allocated) - g_free (iti->text); - - iti->text = g_strdup (gtk_entry_get_text (GTK_ENTRY(priv->entry))); - iti->is_text_allocated = 1; - } - - iti_stop_editing (iti); - } - layout_text (iti); - - gnome_canvas_item_request_update (GNOME_CANVAS_ITEM (iti)); -} - - -static void -iti_entry_text_changed_by_clipboard (GtkObject *widget, - gpointer data) -{ - Iti *iti; - GnomeCanvasItem *item; - ItiPrivate *priv; - - /* Update text item to reflect changes */ - iti = NAUTILUS_ICON_TEXT_ITEM (data); - layout_text (iti); - priv = iti->priv; - - item = GNOME_CANVAS_ITEM (iti); - gnome_canvas_item_request_update (item); - -} - - -/* Callback used when the off-screen entry of an icon text item is activated. - * When this happens, we have to accept edition. - */ -static void -iti_entry_activate (GtkWidget *entry, Iti *iti) -{ - iti_edition_accept (iti); -} - -/* Starts the editing state of an icon text item */ -static void -iti_start_editing (Iti *iti) -{ - ItiPrivate *priv; - - priv = iti->priv; - - if (iti->editing) { - return; - } - - /* Trick: The actual edition of the entry takes place in a NautilusEntry - * which is placed offscreen. That way we get all of the advantages - * from NautilusEntry without duplicating code. Yes, this is a hack. - */ - - if (priv->entry_top == NULL) { - priv->entry = (NautilusEntry *) nautilus_entry_new (); - gtk_signal_connect (GTK_OBJECT (priv->entry), "activate", - GTK_SIGNAL_FUNC (iti_entry_activate), iti); - /* Make clipboard functions cause an update the appearance of - the icon text item itself, since the clipboard functions - will change the offscreen entry */ - gtk_signal_connect_after (GTK_OBJECT (priv->entry), "changed", - GTK_SIGNAL_FUNC (iti_entry_text_changed_by_clipboard), iti); - - priv->entry_top = gtk_window_new (GTK_WINDOW_POPUP); - gtk_container_add (GTK_CONTAINER (priv->entry_top), GTK_WIDGET (priv->entry)); - gtk_widget_set_uposition (priv->entry_top, 20000, 20000); - gtk_widget_show_all (priv->entry_top); - } - - gtk_entry_set_text (GTK_ENTRY(priv->entry), iti->text); - - gtk_editable_select_region (GTK_EDITABLE (priv->entry), 0, -1); - - iti->editing = TRUE; - - send_focus_event (iti, TRUE); - - gnome_canvas_item_request_update (GNOME_CANVAS_ITEM (iti)); - - gtk_signal_emit (GTK_OBJECT (iti), iti_signals[EDITING_STARTED]); -} - -/* Destroy method handler for the icon text item */ -static void -iti_destroy (GtkObject *object) -{ - Iti *iti; - ItiPrivate *priv; - GnomeCanvasItem *item; - - g_return_if_fail (object != NULL); - g_return_if_fail (IS_ITI (object)); - - iti = ITI (object); - priv = iti->priv; - item = GNOME_CANVAS_ITEM (object); - - /* Queue redraw of bounding box */ - gnome_canvas_request_redraw (item->canvas, - eel_round (item->x1), - eel_round (item->y1), - eel_round (item->x2), - eel_round (item->y2)); - - /* Free everything */ - if (iti->font) - gdk_font_unref (iti->font); - - if (iti->text && iti->is_text_allocated) - g_free (iti->text); - - if (iti->ti) - gnome_icon_text_info_free (iti->ti); - - if (priv->font) - gdk_font_unref (priv->font); - - if (priv->entry_top) { - gtk_widget_destroy (priv->entry_top); - } - - g_free (priv); - - if (GTK_OBJECT_CLASS (parent_class)->destroy) - (* GTK_OBJECT_CLASS (parent_class)->destroy) (object); -} - -/* set_arg handler for the icon text item */ -static void -iti_set_arg (GtkObject *object, GtkArg *arg, guint arg_id) -{ - Iti *iti; - ItiPrivate *priv; - - iti = ITI (object); - priv = iti->priv; - - switch (arg_id) { - default: - break; - } -} - -/* Recomputes the bounding box of an icon text item */ -static void -recompute_bounding_box (Iti *iti) -{ - GnomeCanvasItem *item; - int width_c, height_c; - double width_w, height_w; - double x1, y1, x2, y2; - ItiPrivate *priv; - - item = GNOME_CANVAS_ITEM (iti); - - priv = iti->priv; - - /* Compute width, height - scaled to world coords - */ - width_c = iti->ti->width + 2 * MARGIN_X; - height_c = iti->ti->height + 2 * MARGIN_Y; - - /* Verify we are not smaller than default settings - */ - if (width_c < priv->min_width) { - width_c = priv->min_width; - } - if (height_c < priv->min_height) { - height_c = priv->min_height; - } - - width_w = width_c / item->canvas->pixels_per_unit; - height_w = height_c / item->canvas->pixels_per_unit; - - /* start with item coords - */ - x1 = iti->x_center; - y1 = iti->y_top; - - /* do computations in world coords - */ - gnome_canvas_item_i2w (item, &x1, &y1); - x1 -= width_w / 2; - y1 -= MARGIN_Y / item->canvas->pixels_per_unit; - x2 = x1 + width_w; - y2 = y1 + height_w; - - /* store canvas coords in item - */ - gnome_canvas_w2c_d (item->canvas, x1, y1, &item->x1, &item->y1); - gnome_canvas_w2c_d (item->canvas, x2, y2, &item->x2, &item->y2); -} - -/* Update method for the icon text item */ -static void -iti_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags) -{ - Iti *iti; - - iti = ITI (item); - - if (parent_class->update) - (* parent_class->update) (item, affine, clip_path, flags); - - gnome_canvas_request_redraw (item->canvas, - eel_round (item->x1), - eel_round (item->y1), - eel_round (item->x2), - eel_round (item->y2)); - recompute_bounding_box (iti); - gnome_canvas_request_redraw (item->canvas, - eel_round (item->x1), - eel_round (item->y1), - eel_round (item->x2), - eel_round (item->y2)); -} - -/* utility to fetch a color from a theme */ -static void -fetch_themed_color (const char *property_name, GdkColor *color) -{ - char *color_string; - - color_string = nautilus_theme_get_theme_data ("icon", property_name); - if (color_string == NULL) { - color_string = g_strdup ("rgb:FFFF/FFFF/FFFF"); - } - gdk_color_parse (color_string, color); - g_free (color_string); -} - -/* Draw the icon text item's text when it is being edited */ -static void -iti_paint_text (Iti *iti, GdkDrawable *drawable, int x, int y) -{ - ItiPrivate *priv; - GnomeIconTextInfoRow *row; - GnomeIconTextInfo *ti; - GtkStyle *style; - GdkGC *fg_gc, *bg_gc; - GdkGC *gc, *bgc, *sgc, *bsgc; - GList *item; - GdkGCValues save_gc; - GdkColor highlight_background_color, highlight_text_color, fill_color; - int xpos, len; - int cursor, offset, i; - GnomeCanvasItem *canvas_item; - - xpos = 0; - offset = 0; - priv = iti->priv; - style = GTK_WIDGET (GNOME_CANVAS_ITEM (iti)->canvas)->style; - - ti = iti->ti; - len = 0; - y += ti->font->ascent; - - cursor = 0; - i = -1; - - /* - * Pointers to all of the GCs we use - */ - gc = style->fg_gc [GTK_STATE_NORMAL]; - bgc = style->bg_gc [GTK_STATE_NORMAL]; - sgc = style->fg_gc [GTK_STATE_SELECTED]; - bsgc = style->bg_gc [GTK_STATE_SELECTED]; - - /* fetch the colors from the theme */ - fetch_themed_color ("highlight_background_color", &highlight_background_color); - fetch_themed_color ("highlight_text_color", &highlight_text_color); - fetch_themed_color ("text_fill_color", &fill_color); - - /* Set up user defined colors */ - canvas_item = GNOME_CANVAS_ITEM (iti); - gdk_colormap_alloc_color - (gtk_widget_get_colormap (GTK_WIDGET (canvas_item->canvas)), - &highlight_background_color, FALSE, TRUE); - gdk_colormap_alloc_color - (gtk_widget_get_colormap (GTK_WIDGET (canvas_item->canvas)), - &highlight_text_color, FALSE, TRUE); - gdk_colormap_alloc_color - (gtk_widget_get_colormap (GTK_WIDGET (canvas_item->canvas)), - &fill_color, FALSE, TRUE); - - for (item = ti->rows; item; item = item->next, len += (row ? row->text_length : 0)) { - GdkWChar *text_wc; - int text_length; - int sel_start, sel_end; - - row = item->data; - - if (!row) { - y += ti->baseline_skip / 2; - continue; - } - - text_wc = row->text_wc; - text_length = row->text_length; - - xpos = (ti->width - row->width) / 2; - - sel_start = GTK_EDITABLE (priv->entry)->selection_start_pos - len; - sel_end = GTK_EDITABLE (priv->entry)->selection_end_pos - len; - offset = 0; - cursor = GTK_EDITABLE (priv->entry)->current_pos - len; - - for (i = 0; *text_wc; text_wc++, i++) { - int size, px; - - size = gdk_text_width_wc (ti->font, text_wc, 1); - px = x + xpos + offset; - - if (i >= sel_start && i < sel_end) { - /* Draw selection */ - fg_gc = sgc; - bg_gc = bsgc; - - gdk_gc_get_values (bg_gc, &save_gc); - - gdk_gc_set_foreground (bg_gc, &highlight_background_color); - gdk_draw_rectangle (drawable, - bg_gc, - TRUE, - px, - y - ti->font->ascent, - size, ti->baseline_skip); - - gdk_gc_set_foreground (bg_gc, &highlight_text_color); - gdk_draw_text_wc (drawable, - ti->font, - fg_gc, - px, y, - text_wc, 1); - } else { - /* Draw unselected area */ - fg_gc = gc; - bg_gc = bgc; - gdk_gc_get_values (bg_gc, &save_gc); - - gdk_gc_set_foreground (bg_gc, &fill_color); - gdk_draw_rectangle (drawable, - bg_gc, - TRUE, - px, - y - ti->font->ascent, - size, ti->baseline_skip); - - gdk_draw_text_wc (drawable, - ti->font, - fg_gc, - px, y, - text_wc, 1); - } - - if (cursor == i) { - gdk_draw_line (drawable, - gc, - px, - y - ti->font->ascent, - px, - y + ti->font->descent - 1); - } - offset += size; - - /* Restore colors */ - gdk_gc_set_foreground(bg_gc, &save_gc.foreground); - gdk_gc_set_background(bg_gc, &save_gc.background); - } - - y += ti->baseline_skip; - } - - /* The i-beam should only be drawn at the end of a line of text if that line is the - * only or last line of text in a label. We subtract one from the x position - * so the i-beam is not visually jammed against the edge of the bounding rect. */ - if (cursor == i) { - int px = x + xpos + offset; - y -= ti->baseline_skip; - - gdk_draw_line (drawable, - gc, - px - 1, - y - ti->font->ascent, - px - 1, - y + ti->font->descent - 1); - } - -} - -/* Draw method handler for the icon text item */ -static void -iti_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int update_width, int update_height) -{ - Iti *iti; - GtkStyle *style; - int width, height; - int xofs, yofs; - - iti = ITI (item); - - width = eel_round (item->x2 - item->x1); - height = eel_round (item->y2 - item->y1); - - xofs = eel_round (item->x1) - x; - yofs = eel_round (item->y1) - y; - - style = GTK_WIDGET (item->canvas)->style; - - if (iti->editing) { - /* Draw outline around text */ - gdk_draw_rectangle (drawable, - style->fg_gc[GTK_STATE_NORMAL], - FALSE, - xofs, yofs, - width - 1, height - 1); - - iti_paint_text (iti, drawable, xofs + MARGIN_X, yofs + MARGIN_Y); - } else { - g_message ("Drawing, but not editing!!!!"); - if (iti->selected) { - gdk_draw_rectangle (drawable, - style->bg_gc[GTK_STATE_SELECTED], - TRUE, - xofs, yofs, - width, height); - } - gnome_icon_paint_text (iti->ti, - drawable, - style->fg_gc[(iti->selected - ? GTK_STATE_SELECTED - : GTK_STATE_NORMAL)], - xofs + MARGIN_X, - yofs + MARGIN_Y, - GTK_JUSTIFY_CENTER); - } -} - -/* utility to draw a pixbuf to the anti-aliased canvas */ - -static void -draw_pixbuf_aa (GdkPixbuf *pixbuf, GnomeCanvasBuf *buf, double affine[6], int x_offset, int y_offset) -{ - void (* affine_function) - (art_u8 *dst, int x0, int y0, int x1, int y1, int dst_rowstride, - const art_u8 *src, int src_width, int src_height, int src_rowstride, - const double affine[6], - ArtFilterLevel level, - ArtAlphaGamma *alpha_gamma); - - affine[4] += x_offset; - affine[5] += y_offset; - - affine_function = gdk_pixbuf_get_has_alpha (pixbuf) - ? art_rgb_rgba_affine - : art_rgb_affine; - - (* affine_function) - (buf->buf, - buf->rect.x0, buf->rect.y0, - buf->rect.x1, buf->rect.y1, - buf->buf_rowstride, - gdk_pixbuf_get_pixels (pixbuf), - gdk_pixbuf_get_width (pixbuf), - gdk_pixbuf_get_height (pixbuf), - gdk_pixbuf_get_rowstride (pixbuf), - affine, - ART_FILTER_NEAREST, - NULL); - - affine[4] -= x_offset; - affine[5] -= y_offset; -} - -static void -iti_render (GnomeCanvasItem *item, GnomeCanvasBuf *buffer) -{ - GdkVisual *visual; - GdkGC *gc; - GdkColormap *colormap; - GdkPixmap *pixmap; - GdkPixbuf *text_pixbuf; - double affine[6]; - int width, height; - - visual = gdk_visual_get_system (); - art_affine_identity(affine); - width = eel_round (item->x2 - item->x1); - height = eel_round (item->y2 - item->y1); - - /* allocate a pixmap to draw the text into, and clear it to white */ - pixmap = gdk_pixmap_new (NULL, width, height, visual->depth); - - gc = gdk_gc_new (pixmap); - - gdk_rgb_gc_set_foreground (gc, EEL_RGB_COLOR_WHITE); - gdk_draw_rectangle (pixmap, gc, TRUE, - 0, 0, - width, - height); - gdk_gc_unref (gc); - - /* use a common routine to draw the label into the pixmap */ - iti_draw (item, pixmap, eel_round (item->x1), eel_round (item->y1), width, height); - - /* turn it into a pixbuf */ - colormap = gdk_colormap_new (visual, FALSE); - text_pixbuf = gdk_pixbuf_get_from_drawable - (NULL, pixmap, colormap, - 0, 0, - 0, 0, - width, - height); - - gdk_colormap_unref (colormap); - gdk_pixmap_unref (pixmap); - - /* draw the pixbuf containing the label */ - draw_pixbuf_aa (text_pixbuf, buffer, affine, eel_round (item->x1), eel_round (item->y1)); - gdk_pixbuf_unref (text_pixbuf); - - buffer->is_bg = FALSE; - buffer->is_buf = TRUE; -} - - -/* Point method handler for the icon text item */ -static double -iti_point (GnomeCanvasItem *item, double x, double y, int cx, int cy, GnomeCanvasItem **actual_item) -{ - double dx, dy; - double cx_d, cy_d; - - *actual_item = item; - - gnome_canvas_w2c_d (item->canvas, x, y, &cx_d, &cy_d); - - if (cx_d < item->x1) { - dx = item->x1 - cx_d; - } else if (cx_d > item->x2) { - dx = cx_d - item->x2; - } else { - dx = 0.0; - } - - if (cy_d < item->y1) { - dy = item->y1 - cy_d; - } else if (cy_d > item->y2) { - dy = cy_d - item->y2; - } else { - dy = 0.0; - } - - return sqrt (dx * dx + dy * dy); -} - -/* Given X, Y, a mouse position, return a valid index inside the edited text */ -static int -iti_idx_from_x_y (Iti *iti, int x, int y) -{ - ItiPrivate *priv; - GnomeIconTextInfoRow *row; - int lines; - int line, col, i, idx; - GList *l; - - priv = iti->priv; - - if (iti->ti->rows == NULL) - return 0; - - lines = g_list_length (iti->ti->rows); - line = y / iti->ti->baseline_skip; - - if (line < 0) - line = 0; - else if (lines < line + 1) - line = lines - 1; - - /* Compute the base index for this line */ - for (l = iti->ti->rows, idx = i = 0; i < line; l = l->next, i++) { - row = l->data; - idx += row->text_length; - } - - row = g_list_nth (iti->ti->rows, line)->data; - col = 0; - if (row != NULL) { - int first_char; - int last_char; - - first_char = (iti->ti->width - row->width) / 2; - last_char = first_char + row->width; - - if (x < first_char) { - /* nothing */ - } else if (x > last_char) { - col = row->text_length; - } else { - GdkWChar *s = row->text_wc; - int pos = first_char; - - while (pos < last_char) { - pos += gdk_text_width_wc (iti->ti->font, s, 1); - if (pos > x) - break; - col++; - s++; - } - } - } - - idx += col; - - g_assert (idx <= GTK_ENTRY(priv->entry)->text_size); - - return idx; -} - -/* Starts the selection state in the icon text item */ -static void -iti_start_selecting (Iti *iti, int idx, guint32 event_time) -{ - ItiPrivate *priv; - GtkEditable *e; - GdkCursor *ibeam; - - priv = iti->priv; - e = GTK_EDITABLE (priv->entry); - - gtk_editable_select_region (e, idx, idx); - gtk_editable_set_position (e, idx); - ibeam = gdk_cursor_new (GDK_XTERM); - gnome_canvas_item_grab (GNOME_CANVAS_ITEM (iti), - GDK_BUTTON_RELEASE_MASK | - GDK_POINTER_MOTION_MASK, - ibeam, event_time); - gdk_cursor_destroy (ibeam); - - gtk_editable_select_region (e, idx, idx); - e->current_pos = e->selection_start_pos; - e->has_selection = TRUE; - iti->selecting = TRUE; - - gnome_canvas_item_request_update (GNOME_CANVAS_ITEM (iti)); - - gtk_signal_emit (GTK_OBJECT (iti), iti_signals[SELECTION_STARTED]); -} - -/* Stops the selection state in the icon text item */ -static void -iti_stop_selecting (Iti *iti, guint32 event_time) -{ - ItiPrivate *priv; - GnomeCanvasItem *item; - GtkEditable *e; - - priv = iti->priv; - item = GNOME_CANVAS_ITEM (iti); - e = GTK_EDITABLE (priv->entry); - - gnome_canvas_item_ungrab (item, event_time); - e->has_selection = FALSE; - iti->selecting = FALSE; - - gnome_canvas_item_request_update (GNOME_CANVAS_ITEM (iti)); - gtk_signal_emit (GTK_OBJECT (iti), iti_signals[SELECTION_STOPPED]); - /* Hack, since the real nautilus entry can't get this information */ - gtk_signal_emit_by_name (GTK_OBJECT (priv->entry), "selection_changed"); -} - -/* Handles selection range changes on the icon text item */ -static void -iti_selection_motion (Iti *iti, int idx) -{ - ItiPrivate *priv; - GtkEditable *e; - - g_assert (idx >= 0); - - priv = iti->priv; - e = GTK_EDITABLE (priv->entry); - - if (idx < (int) e->current_pos) { - e->selection_start_pos = idx; - e->selection_end_pos = e->current_pos; - } else { - e->selection_start_pos = e->current_pos; - e->selection_end_pos = idx; - } - - gnome_canvas_item_request_update (GNOME_CANVAS_ITEM (iti)); -} - -/* Ensure the item gets focused (both globally, and local to Gtk) */ -static void -iti_ensure_focus (GnomeCanvasItem *item) -{ - GtkWidget *toplevel; - - /* gnome_canvas_item_grab_focus still generates focus out/in - * events when focused_item == item - */ - if (GNOME_CANVAS_ITEM (item)->canvas->focused_item != item) { - gnome_canvas_item_grab_focus (GNOME_CANVAS_ITEM (item)); - } - - toplevel = gtk_widget_get_toplevel (GTK_WIDGET (item->canvas)); - if (toplevel != NULL && GTK_WIDGET_REALIZED (toplevel)) { - eel_gdk_window_focus (toplevel->window, GDK_CURRENT_TIME); - } -} - -/* Position insertion point based on arrow key event */ -static void -iti_handle_arrow_key_event (NautilusIconTextItem *iti, GdkEvent *event) -{ - ItiPrivate *priv; - GnomeIconTextInfoRow *row; - GList *list; - GtkEditable *editable; - int index, lines, line; - int position, pos_count, new_position; - int cur_count, prev_count, next_count; - float scale; - - /* Get number of lines. Do nothing if we have only one line */ - lines = g_list_length (iti->ti->rows); - if (lines <= 1) { - return; - } - - /* Figure out which line the current insertion point is on */ - priv = iti->priv; - editable = GTK_EDITABLE (priv->entry); - pos_count = position = gtk_editable_get_position (editable); - for (list = iti->ti->rows, line = -1, index = 1; index <= lines; index++) { - if (list != NULL) { - row = list->data; - if (pos_count > row->text_length) { - list = list->next; - pos_count -= row->text_length; - } - else { - line = index; - break; - } - } - } - - /* Calculate new position of insertion point */ - switch (event->key.keyval) { - - case GDK_Up: - /* Try to set insertion point to previous line */ - if (line > 1) { - list = g_list_nth(iti->ti->rows, line - 1); - row = list->data; - cur_count = row->text_length; - list = g_list_nth(iti->ti->rows, line - 2); - row = list->data; - prev_count = row->text_length; - scale = (float)prev_count / (float)cur_count; - new_position = pos_count * scale; - position -= prev_count + pos_count; - position += new_position; - gtk_editable_set_position (editable, position); - } - break; - - case GDK_Down: - /* Try to set insertion point to next line */ - if (line < lines) { - int new_position; - list = g_list_nth(iti->ti->rows, line - 1); - row = list->data; - cur_count = row->text_length; - list = g_list_nth(iti->ti->rows, line); - row = list->data; - next_count = row->text_length; - scale = (float)next_count / (float)cur_count; - new_position = pos_count * scale; - new_position += (position + (cur_count - pos_count)); - gtk_editable_set_position (editable, new_position); - } - break; - - default: - break; - - } - -} - -/* Event handler for icon text items */ -static gint -iti_event (GnomeCanvasItem *item, GdkEvent *event) -{ - Iti *iti; - ItiPrivate *priv; - int idx; - double cx, cy; - - iti = ITI (item); - priv = iti->priv; - - switch (event->type) { - case GDK_KEY_PRESS: - if (!iti->editing) { - break; - } - - switch(event->key.keyval) { - - /* Pass these events back to parent */ - case GDK_Escape: - case GDK_Return: - case GDK_KP_Enter: - return FALSE; - - /* Handle up and down arrow keys. GdkEntry does not know - * how to handle multi line items */ - case GDK_Up: - case GDK_Down: - iti_handle_arrow_key_event(iti, event); - break; - - default: - /* Check for control key operations */ - if (event->key.state & GDK_CONTROL_MASK) { - return FALSE; - } - - /* Register undo transaction if neccessary */ - if (!priv->undo_registered) { - priv->undo_registered = TRUE; - register_rename_undo (iti); - } - - /* Handle any events that reach us */ - gtk_widget_event (GTK_WIDGET (priv->entry), event); - break; - } - - /* Update text item to reflect changes */ - layout_text (iti); - gnome_canvas_item_request_update (item); - return TRUE; - - case GDK_BUTTON_PRESS: - if (!iti->editing) { - break; - } - - if (event->button.button == 1) { - gnome_canvas_w2c_d (item->canvas, event->button.x, event->button.y, &cx, &cy); - idx = iti_idx_from_x_y (iti, - eel_round (cx - (item->x1 + MARGIN_X)), - eel_round (cy - (item->y1 + MARGIN_Y))); - iti_start_selecting (iti, idx, event->button.time); - } - return TRUE; - - case GDK_MOTION_NOTIFY: - if (!iti->selecting) - break; - - gtk_widget_event (GTK_WIDGET (priv->entry), event); - gnome_canvas_w2c_d (item->canvas, event->button.x, event->button.y, &cx, &cy); - idx = iti_idx_from_x_y (iti, - eel_round (cx - (item->x1 + MARGIN_X)), - eel_round (cy - (item->y1 + MARGIN_Y))); - iti_selection_motion (iti, idx); - return TRUE; - - case GDK_BUTTON_RELEASE: - if (iti->selecting && event->button.button == 1) - iti_stop_selecting (iti, event->button.time); - else - break; - - return TRUE; - - case GDK_FOCUS_CHANGE: - /* FIXME bugzilla.eazel.com 5484: - * Working around bug in the GnomeCanvas widget's focus_in/focus_out - * methods. They (all widgets) should be setting/usetting these flags. - * GnomeCanvas doesn't. We need it set so the GtkWindow passes us all - * focus out events. Once GnomeCanvas is fixed, this can be removed. - */ - if (event->focus_change.in) { - GTK_WIDGET_SET_FLAGS (item->canvas, GTK_HAS_FOCUS); - } else { - GTK_WIDGET_UNSET_FLAGS (item->canvas, GTK_HAS_FOCUS); - } - - if (iti->editing) { - gtk_widget_event (GTK_WIDGET (priv->entry), event); - - if (!event->focus_change.in) { - iti_edition_accept (iti); - } - } - return TRUE; - - default: - break; - } - - return FALSE; -} - -/* Bounds method handler for the icon text item */ -static void -iti_bounds (GnomeCanvasItem *item, double *x1, double *y1, double *x2, double *y2) -{ - Iti *iti; - int width_c, height_c; - double width_w, height_w; - - iti = ITI (item); - - if (iti->ti) { - width_c = iti->ti->width + 2 * MARGIN_X; - height_c = iti->ti->height + 2 * MARGIN_Y; - } else { - width_c = 2 * MARGIN_X; - height_c = 2 * MARGIN_Y; - } - - width_w = width_c / item->canvas->pixels_per_unit; - height_w = height_c / item->canvas->pixels_per_unit; - - /* start with item coords - */ - *x1 = iti->x_center; - *y1 = iti->y_top; - - /* do computations in world coords - */ - gnome_canvas_item_i2w (item, x1, y1); - *x1 -= width_w / 2; - *y1 -= MARGIN_Y / item->canvas->pixels_per_unit; - *x2 = *x1 + width_w; - *y2 = *y1 + height_w; - - /* convert back to item coords - */ - gnome_canvas_item_w2i (item, x1, y1); - gnome_canvas_item_w2i (item, x2, y2); -} - -/* Class initialization function for the icon text item */ -static void -iti_class_init (NautilusIconTextItemClass *text_item_class) -{ - GtkObjectClass *object_class; - GnomeCanvasItemClass *item_class; - - object_class = (GtkObjectClass *) text_item_class; - item_class = (GnomeCanvasItemClass *) text_item_class; - - parent_class = gtk_type_class (gnome_canvas_item_get_type ()); - - iti_signals [TEXT_CHANGED] = gtk_signal_new - ("text_changed", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (NautilusIconTextItemClass, text_changed), - gtk_marshal_BOOL__NONE, - GTK_TYPE_BOOL, 0); - - iti_signals [TEXT_EDITED] = gtk_signal_new - ("text_edited", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (NautilusIconTextItemClass, text_edited), - gtk_marshal_NONE__NONE, - GTK_TYPE_NONE, 0); - - iti_signals [HEIGHT_CHANGED] = gtk_signal_new - ("height_changed", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (NautilusIconTextItemClass, height_changed), - gtk_marshal_NONE__NONE, - GTK_TYPE_NONE, 0); - - iti_signals [WIDTH_CHANGED] = gtk_signal_new - ("width_changed", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (NautilusIconTextItemClass, width_changed), - gtk_marshal_NONE__NONE, - GTK_TYPE_NONE, 0); - - iti_signals[EDITING_STARTED] = gtk_signal_new - ("editing_started", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (NautilusIconTextItemClass, editing_started), - gtk_marshal_NONE__NONE, - GTK_TYPE_NONE, 0); - - iti_signals[EDITING_STOPPED] = gtk_signal_new - ("editing_stopped", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (NautilusIconTextItemClass, editing_stopped), - gtk_marshal_NONE__NONE, - GTK_TYPE_NONE, 0); - - iti_signals[SELECTION_STARTED] = gtk_signal_new - ("selection_started", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (NautilusIconTextItemClass, selection_started), - gtk_marshal_NONE__NONE, - GTK_TYPE_NONE, 0); - - iti_signals[SELECTION_STOPPED] = gtk_signal_new - ("selection_stopped", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (NautilusIconTextItemClass, selection_stopped), - gtk_marshal_NONE__NONE, - GTK_TYPE_NONE, 0); - - gtk_object_class_add_signals (object_class, iti_signals, LAST_SIGNAL); - - object_class->destroy = iti_destroy; - object_class->set_arg = iti_set_arg; - - item_class->update = iti_update; - item_class->draw = iti_draw; - item_class->render = iti_render; - item_class->point = iti_point; - item_class->bounds = iti_bounds; - item_class->event = iti_event; -} - -/* Object initialization function for the icon text item */ -static void -iti_init (NautilusIconTextItem *iti) -{ - ItiPrivate *priv; - - priv = g_new0 (ItiPrivate, 1); - iti->priv = priv; -} - - - - -/** - * nautilus_icon_text_item_configure: - * @iti: An icon text item. - * @x_center: X position of item's center - item coords. - * @y_top: Y position of item's top - item coords. - * @width: Maximum width allowed for this item, to be used for word wrapping. - * @font: Name of the fontset that should be used to display the text. - * @text: Text that is going to be displayed. - * @is_editable: Deprecated. - * @is_static: Whether @text points to a static string or not. - * - * This routine is used to configure a &NautilusIconTextItem. - * - * @x and @y specify the cordinates where the item is placed inside the canvas. - * The @x coordinate should be the leftmost position that the icon text item can - * assume at any one time, that is, the left margin of the column in which the - * icon is to be placed. The @y coordinate specifies the top of the icon text - * item. - * - * @width is the maximum width allowed for this icon text item. The coordinates - * define the upper-left corner of an icon text item with maximum width; this may - * actually be outside the bounding box of the item if the text is narrower than - * the maximum width. - * - * If @is_static is true, it means that there is no need for the item to - * allocate memory for the string (it is a guarantee that the text is allocated - * by the caller and it will not be deallocated during the lifetime of this - * item). This is an optimization to reduce memory usage for large icon sets. - */ -void -nautilus_icon_text_item_configure (NautilusIconTextItem *iti, double x_center, double y_top, - int max_text_width, GdkFont *font, - const char *text, gboolean is_static) -{ - ItiPrivate *priv; - GnomeIconTextInfo *min_text_info; - - g_return_if_fail (iti != NULL); - g_return_if_fail (IS_ITI (iti)); - g_return_if_fail (max_text_width > 2 * MARGIN_X); - g_return_if_fail (text != NULL); - - priv = iti->priv; - - iti->x_center = x_center; - iti->y_top = y_top; - iti->max_text_width = max_text_width; - - if (iti->text && iti->is_text_allocated) - g_free (iti->text); - - iti->is_text_allocated = !is_static; - - /* This cast is to shut up the compiler */ - if (is_static) - iti->text = (char *) text; - else - iti->text = g_strdup (text); - - if (iti->font) - gdk_font_unref (iti->font); - - iti->font = gdk_font_ref (font); - - if (priv->font) - gdk_font_unref (priv->font); - - priv->font = NULL; - if (font) - priv->font = gdk_font_ref (iti->font); - if (!priv->font) - priv->font = gdk_fontset_load (DEFAULT_FONT_NAME); - - layout_text (iti); - - /* Calculate and store min and max dimensions */ - min_text_info = gnome_icon_layout_text (priv->font, - " ", - DEFAULT_SEPARATORS, - iti->max_text_width - 2 * MARGIN_X, - TRUE); - - priv->min_width = min_text_info->width + 2 * MARGIN_X; - priv->min_height = min_text_info->height + 2 * MARGIN_Y; - gnome_icon_text_info_free(min_text_info); - - priv->undo_registered = FALSE; - - /* Request update */ - gnome_canvas_item_request_update (GNOME_CANVAS_ITEM (iti)); -} - -/** - * nautilus_icon_text_item_setxy: - * @iti: An icon text item. - * @x_center: X position of item's center - item coords. - * @y_top: Y position of item's top - item coords. - * - * Sets the coordinates at which the icon text item should be placed. - * - * See also: nautilus_icon_text_item_configure(). - */ -void -nautilus_icon_text_item_setxy (NautilusIconTextItem *iti, double x_center, double y_top) -{ - ItiPrivate *priv; - - g_return_if_fail (iti != NULL); - g_return_if_fail (IS_ITI (iti)); - - priv = iti->priv; - - iti->x_center = x_center; - iti->y_top = y_top; - - gnome_canvas_item_request_update (GNOME_CANVAS_ITEM (iti)); -} - -/** - * nautilus_icon_text_item_select: - * @iti: An icon text item - * @sel: Whether the icon text item should be displayed as selected. - * - * This function is used to control whether an icon text item is displayed as - * selected or not. Mouse events are ignored by the item when it is unselected; - * when the user clicks on a selected icon text item, it will start the text - * editing process. - */ -void -nautilus_icon_text_item_select (NautilusIconTextItem *iti, int sel) -{ - ItiPrivate *priv; - - g_return_if_fail (iti != NULL); - g_return_if_fail (IS_ITI (iti)); - - priv = iti->priv; - - if (!iti->selected == !sel) - return; - - iti->selected = sel ? TRUE : FALSE; - - if (!iti->selected && iti->editing) { - iti_edition_accept (iti); - } - - gnome_canvas_item_request_update (GNOME_CANVAS_ITEM (iti)); -} - -/** - * nautilus_icon_text_item_set_text: - * @iti: An icon text item. - * - * Returns the current text string in an icon text item. The client should not - * free this string, as it is internal to the icon text item. - */ -void -nautilus_icon_text_item_set_text (NautilusIconTextItem *iti, const char *text) -{ - ItiPrivate *priv; - - g_return_if_fail (iti != NULL); - g_return_if_fail (IS_ITI (iti)); - - priv = iti->priv; - - gtk_entry_set_text (GTK_ENTRY(priv->entry), text); - gtk_editable_select_region (GTK_EDITABLE (priv->entry), 0, -1); - - layout_text (iti); - - gnome_canvas_item_request_update (GNOME_CANVAS_ITEM (iti)); -} - -/** - * nautilus_icon_text_item_get_text: - * @iti: An icon text item. - * - * Returns the current text string in an icon text item. The client should not - * free this string, as it is internal to the icon text item. - */ -const char * -nautilus_icon_text_item_get_text (NautilusIconTextItem *iti) -{ - ItiPrivate *priv; - - g_return_val_if_fail (iti != NULL, NULL); - g_return_val_if_fail (IS_ITI (iti), NULL); - - priv = iti->priv; - - if (iti->editing) { - return gtk_entry_get_text (GTK_ENTRY(priv->entry)); - } else { - return iti->text; - } -} - - -/** - * nautilus_icon_text_item_start_editing: - * @iti: An icon text item. - * - * Starts the editing state of an icon text item. - **/ -void -nautilus_icon_text_item_start_editing (NautilusIconTextItem *iti) -{ - ItiPrivate *priv; - - g_return_if_fail (iti != NULL); - g_return_if_fail (IS_ITI (iti)); - - priv = iti->priv; - - if (iti->editing) { - return; - } - - iti->selected = TRUE; /* Ensure that we are selected */ - iti_ensure_focus (GNOME_CANVAS_ITEM (iti)); - iti_start_editing (iti); -} - -/** - * nautilus_icon_text_item_stop_editing: - * @iti: An icon text item. - * @accept: Whether to accept the current text or to discard it. - * - * Terminates the editing state of an icon text item. The @accept argument - * controls whether the item's current text should be accepted or discarded. If - * it is discarded, then the icon's original text will be restored. - **/ -void -nautilus_icon_text_item_stop_editing (NautilusIconTextItem *iti, - gboolean accept) -{ - ItiPrivate *priv; - - g_return_if_fail (iti != NULL); - g_return_if_fail (IS_ITI (iti)); - - priv = iti->priv; - - if (!iti->editing) { - return; - } - - if (accept) { - iti_edition_accept (iti); - } else { - iti_stop_editing (iti); - } -} - - -/** - * nautilus_icon_text_item_get_type: - * @void: - * - * Registers the &NautilusIconTextItem class if necessary, and returns the type ID - * associated to it. - * - * Return value: the type ID of the &NautilusIconTextItem class. - **/ -GtkType -nautilus_icon_text_item_get_type (void) -{ - static GtkType iti_type = 0; - - if (!iti_type) { - static const GtkTypeInfo iti_info = { - "NautilusIconTextItem", - sizeof (NautilusIconTextItem), - sizeof (NautilusIconTextItemClass), - (GtkClassInitFunc) iti_class_init, - (GtkObjectInitFunc) iti_init, - NULL, /* reserved_1 */ - NULL, /* reserved_2 */ - (GtkClassInitFunc) NULL - }; - - iti_type = gtk_type_unique (gnome_canvas_item_get_type (), &iti_info); - } - - return iti_type; -} - -/** - * nautilus_icon_text_item_get_renaming_editable - * @GtkEditable * - * Return the editable widget doing the renaming - **/ -GtkEditable * -nautilus_icon_text_item_get_renaming_editable (NautilusIconTextItem *item) -{ - ItiPrivate *priv; - - priv = item->priv; - return GTK_EDITABLE (priv->entry); -} - - - -/* register_undo - * - * Get text at start of edit operation and store in undo data as - * string with a key of "undo_text". - */ -static void -register_rename_undo (NautilusIconTextItem *item) -{ - ItiPrivate *priv; - - priv = item->priv; - nautilus_undo_register - (GTK_OBJECT (item), - restore_from_undo_snapshot_callback, - g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->entry))), - (GDestroyNotify) g_free, - _("Rename"), - _("Undo Typing"), - _("Restore the old name"), - _("Redo Typing"), - _("Restore the changed name")); -} - - -/* restore_from_undo_snapshot_callback - * - * Restore edited text to data stored in undoable. Data is stored as - * a string with a key of "undo_text". - */ -static void -restore_from_undo_snapshot_callback (GtkObject *target, gpointer callback_data) -{ - NautilusIconTextItem *item; - ItiPrivate *priv; - - item = NAUTILUS_ICON_TEXT_ITEM (target); - priv = item->priv; - - /* Register a new undo transaction for redo. */ - register_rename_undo (item); - - /* Restore the text. */ - nautilus_icon_text_item_set_text (item, callback_data); - - /* Reset the registered flag so we get a new item for future editing. */ - priv->undo_registered = FALSE; -} diff --git a/libnautilus-extensions/nautilus-icon-text-item.h b/libnautilus-extensions/nautilus-icon-text-item.h deleted file mode 100644 index e895acaed..000000000 --- a/libnautilus-extensions/nautilus-icon-text-item.h +++ /dev/null @@ -1,95 +0,0 @@ -/* nautilus-icon-text-item: an editable text block with word wrapping for the - * GNOME canvas. - * - * Copyright (C) 1998, 1999 The Free Software Foundation - * - * Authors: Miguel de Icaza <miguel@gnu.org> - * Federico Mena <federico@gimp.org> - */ - -#ifndef NAUTILUS_ICON_TEXT_ITEM_H -#define NAUTILUS_ICON_TEXT_ITEM_H - -#include <gtk/gtkeditable.h> -#include <libgnome/gnome-defs.h> -#include <libgnomeui/gnome-canvas.h> -#include <libgnomeui/gnome-icon-text.h> - -#define NAUTILUS_ICON_TEXT_ITEM(obj) (GTK_CHECK_CAST((obj), \ - nautilus_icon_text_item_get_type (), NautilusIconTextItem)) -#define NAUTILUS_ICON_TEXT_ITEM_CLASS(k) (GTK_CHECK_CLASS_CAST ((k),\ - nautilus_icon_text_item_get_type ())) -#define NAUTILUS_IS_ICON_TEXT_ITEM(o) (GTK_CHECK_TYPE((o), \ - nautilus_icon_text_item_get_type ())) - -/* This structure has been converted to use public and private parts. */ -typedef struct { - GnomeCanvasItem canvas_item; - - double x_center; /* center of text, item coords */ - double y_top; /* top of text, item coords */ - - int max_text_width; /* max width of text - canvas coords */ - - /* Font */ - GdkFont *font; - - /* Private data */ - gpointer priv; /* was GtkEntry *entry */ - - /* Actual text */ - char *text; - - /* Text layout information */ - GnomeIconTextInfo *ti; - - /* Whether the text is being edited */ - unsigned int editing : 1; - - /* Whether the text item is selected */ - unsigned int selected : 1; - - /* Whether the user is select-dragging a block of text */ - unsigned int selecting : 1; - - /* Whether the text is allocated by us (FALSE if allocated by the client) */ - unsigned int is_text_allocated : 1; - -} NautilusIconTextItem; - -typedef struct { - GnomeCanvasItemClass parent_class; - - /* Signals we emit */ - int (* text_changed) (NautilusIconTextItem *item); - void (* text_edited) (NautilusIconTextItem *item); - void (* height_changed) (NautilusIconTextItem *item); - void (* width_changed) (NautilusIconTextItem *item); - void (* editing_started) (NautilusIconTextItem *item); - void (* editing_stopped) (NautilusIconTextItem *item); - void (* selection_started) (NautilusIconTextItem *item); - void (* selection_stopped) (NautilusIconTextItem *item); -} NautilusIconTextItemClass; - -GtkType nautilus_icon_text_item_get_type (void); -void nautilus_icon_text_item_configure (NautilusIconTextItem *item, - double x_center, - double y_top, - int max_text_width, - GdkFont *font, - const char *text, - gboolean is_static); -void nautilus_icon_text_item_setxy (NautilusIconTextItem *item, - double x_center, - double y_top); -void nautilus_icon_text_item_select (NautilusIconTextItem *item, - int sel); -void nautilus_icon_text_item_set_text (NautilusIconTextItem *item, - const char *text); -const char * nautilus_icon_text_item_get_text (NautilusIconTextItem *item); -void nautilus_icon_text_item_start_editing (NautilusIconTextItem *item); -void nautilus_icon_text_item_stop_editing (NautilusIconTextItem *item, - gboolean accept); -GtkEditable *nautilus_icon_text_item_get_renaming_editable (NautilusIconTextItem *item); - -#endif /* NAUTILUS_ICON_TEXT_ITEM_H */ diff --git a/libnautilus-extensions/nautilus-iso9660.h b/libnautilus-extensions/nautilus-iso9660.h deleted file mode 100644 index ad68b15fa..000000000 --- a/libnautilus-extensions/nautilus-iso9660.h +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Header file iso9660.h - assorted structure definitions and typecasts. - * specific to iso9660 filesystem. - - Written by Eric Youngdale (1993). - - Copyright 1993 Yggdrasil Computing, Incorporated - - 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ - -#ifndef _ISOFS_FS_H -#define _ISOFS_FS_H - -/* - * The isofs filesystem constants/structures - */ - -#define ISODCL(from, to) (to - from + 1) - -struct iso_volume_descriptor { - char type[ISODCL(1,1)]; /* 711 */ - char id[ISODCL(2,6)]; - char version[ISODCL(7,7)]; - char data[ISODCL(8,2048)]; -}; - -/* volume descriptor types */ -#define ISO_VD_PRIMARY 1 -#define ISO_VD_END 255 - -#define ISO_STANDARD_ID "CD001" - -struct iso_primary_descriptor { - char type [ISODCL ( 1, 1)]; /* 711 */ - char id [ISODCL ( 2, 6)]; - char version [ISODCL ( 7, 7)]; /* 711 */ - char unused1 [ISODCL ( 8, 8)]; - char system_id [ISODCL ( 9, 40)]; /* achars */ - char volume_id [ISODCL ( 41, 72)]; /* dchars */ - char unused2 [ISODCL ( 73, 80)]; - char volume_space_size [ISODCL ( 81, 88)]; /* 733 */ - char unused3 [ISODCL ( 89, 120)]; - char volume_set_size [ISODCL (121, 124)]; /* 723 */ - char volume_sequence_number [ISODCL (125, 128)]; /* 723 */ - char logical_block_size [ISODCL (129, 132)]; /* 723 */ - char path_table_size [ISODCL (133, 140)]; /* 733 */ - char type_l_path_table [ISODCL (141, 144)]; /* 731 */ - char opt_type_l_path_table [ISODCL (145, 148)]; /* 731 */ - char type_m_path_table [ISODCL (149, 152)]; /* 732 */ - char opt_type_m_path_table [ISODCL (153, 156)]; /* 732 */ - char root_directory_record [ISODCL (157, 190)]; /* 9.1 */ - char volume_set_id [ISODCL (191, 318)]; /* dchars */ - char publisher_id [ISODCL (319, 446)]; /* achars */ - char preparer_id [ISODCL (447, 574)]; /* achars */ - char application_id [ISODCL (575, 702)]; /* achars */ - char copyright_file_id [ISODCL (703, 739)]; /* 7.5 dchars */ - char abstract_file_id [ISODCL (740, 776)]; /* 7.5 dchars */ - char bibliographic_file_id [ISODCL (777, 813)]; /* 7.5 dchars */ - char creation_date [ISODCL (814, 830)]; /* 8.4.26.1 */ - char modification_date [ISODCL (831, 847)]; /* 8.4.26.1 */ - char expiration_date [ISODCL (848, 864)]; /* 8.4.26.1 */ - char effective_date [ISODCL (865, 881)]; /* 8.4.26.1 */ - char file_structure_version [ISODCL (882, 882)]; /* 711 */ - char unused4 [ISODCL (883, 883)]; - char application_data [ISODCL (884, 1395)]; - char unused5 [ISODCL (1396, 2048)]; -}; - -/* We use this to help us look up the parent inode numbers. */ - -struct iso_path_table{ - unsigned char name_len[2]; /* 721 */ - char extent[4]; /* 731 */ - char parent[2]; /* 721 */ - char name[1]; -}; - -struct iso_directory_record { - unsigned char length [ISODCL (1, 1)]; /* 711 */ - char ext_attr_length [ISODCL (2, 2)]; /* 711 */ - char extent [ISODCL (3, 10)]; /* 733 */ - char size [ISODCL (11, 18)]; /* 733 */ - char date [ISODCL (19, 25)]; /* 7 by 711 */ - char flags [ISODCL (26, 26)]; - char file_unit_size [ISODCL (27, 27)]; /* 711 */ - char interleave [ISODCL (28, 28)]; /* 711 */ - char volume_sequence_number [ISODCL (29, 32)]; /* 723 */ - unsigned char name_len [ISODCL (33, 33)]; /* 711 */ - char name [34]; /* Not really, but we need something here */ -}; -#endif - - - diff --git a/libnautilus-extensions/nautilus-keep-last-vertical-box.c b/libnautilus-extensions/nautilus-keep-last-vertical-box.c deleted file mode 100644 index a9036895b..000000000 --- a/libnautilus-extensions/nautilus-keep-last-vertical-box.c +++ /dev/null @@ -1,159 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ - -/* nautilus-keep-last-vertical-box.c: Subclass of GtkVBox that clips off - items that don't fit, except the last one. - - Copyright (C) 2000 Eazel, Inc. - - The Gnome 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 Gnome 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 the Gnome 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. - - Author: John Sullivan <sullivan@eazel.com>, - */ - -#include <config.h> -#include "nautilus-keep-last-vertical-box.h" - -#include <eel/eel-gtk-macros.h> - -static void nautilus_keep_last_vertical_box_initialize_class (NautilusKeepLastVerticalBoxClass *class); -static void nautilus_keep_last_vertical_box_initialize (NautilusKeepLastVerticalBox *box); -static void nautilus_keep_last_vertical_box_size_allocate (GtkWidget *widget, - GtkAllocation *allocation); - -EEL_DEFINE_CLASS_BOILERPLATE (NautilusKeepLastVerticalBox, nautilus_keep_last_vertical_box, GTK_TYPE_VBOX) - -/* Standard class initialization function */ -static void -nautilus_keep_last_vertical_box_initialize_class (NautilusKeepLastVerticalBoxClass *klass) -{ - GtkWidgetClass *widget_class; - - widget_class = (GtkWidgetClass *) klass; - - widget_class->size_allocate = nautilus_keep_last_vertical_box_size_allocate; -} - -/* Standard object initialization function */ -static void -nautilus_keep_last_vertical_box_initialize (NautilusKeepLastVerticalBox *box) -{ -} - - -/* nautilus_keep_last_vertical_box_new: - * - * Create a new vertical box that clips off items from the end that don't - * fit, except the last item, which is always kept. When packing this widget - * into another vbox, use TRUE for expand and TRUE for fill or this class's - * special clipping magic won't work because this widget's allocation might - * be larger than the available space. - * - * @spacing: Vertical space between items. - * - * Return value: A new NautilusKeepLastVerticalBox - */ -GtkWidget * -nautilus_keep_last_vertical_box_new (gint spacing) -{ - NautilusKeepLastVerticalBox *box; - - box = NAUTILUS_KEEP_LAST_VERTICAL_BOX (gtk_widget_new (nautilus_keep_last_vertical_box_get_type (), NULL)); - - GTK_BOX (box)->spacing = spacing; - - /* If homogeneous is TRUE and there are too many items to fit - * naturally, they will be squashed together to fit in the space. - * We want the ones that don't fit to be not shown at all, so - * we set homogeneous to FALSE. - */ - GTK_BOX (box)->homogeneous = FALSE; - - return GTK_WIDGET (box); -} - -static void -nautilus_keep_last_vertical_box_size_allocate (GtkWidget *widget, - GtkAllocation *allocation) -{ - GtkBox *box; - GtkBoxChild *last_child, *child; - GList *children; - GtkAllocation last_child_allocation, child_allocation, tiny_allocation; - - g_return_if_fail (NAUTILUS_IS_KEEP_LAST_VERTICAL_BOX (widget)); - g_return_if_fail (allocation != NULL); - - EEL_CALL_PARENT (GTK_WIDGET_CLASS, size_allocate, (widget, allocation)); - - box = GTK_BOX (widget); - children = g_list_last (box->children); - - if (children != NULL) { - last_child = children->data; - children = children->prev; - - last_child_allocation = last_child->widget->allocation; - - /* If last child doesn't fit vertically, prune items from the end of the - * list one at a time until it does. - */ - if (last_child_allocation.y + last_child_allocation.height > - allocation->y + allocation->height) { - - while (children != NULL) { - child = children->data; - children = children->prev; - - child_allocation = child->widget->allocation; - - /* Reallocate this child's position so that it does not appear. - * Setting the width & height to 0 is not enough, as - * one pixel is still drawn. Must also move it outside - * visible range. For the cases I've seen, -1, -1 works fine. - * This might not work in all future cases. Alternatively, the - * items that don't fit could be hidden, but that would interfere - * with having other hidden children. - * - * Note that these children are having their size allocated twice, - * once by gtk_vbox_size_allocate and then again here. I don't - * know of any problems with this, but holler if you do. - */ - tiny_allocation.x = tiny_allocation.y = -1; - tiny_allocation.height = tiny_allocation.width = 0; - gtk_widget_size_allocate (child->widget, &tiny_allocation); - - /* We're done if the special last item fits now. */ - if (child_allocation.y + last_child_allocation.height <= - allocation->y + allocation->height) { - last_child_allocation.y = child_allocation.y; - gtk_widget_size_allocate (last_child->widget, &last_child_allocation); - break; - } - - /* If the special last item still doesn't fit, but we've - * run out of earlier items, then the special last item is - * just too darn tall. Let's squash it down to fit in the box's - * allocation. - */ - if (children == NULL) { - last_child_allocation.y = allocation->y; - last_child_allocation.height = allocation->height; - gtk_widget_size_allocate (last_child->widget, &last_child_allocation); - } - } - } - } -} diff --git a/libnautilus-extensions/nautilus-keep-last-vertical-box.h b/libnautilus-extensions/nautilus-keep-last-vertical-box.h deleted file mode 100644 index 6fe1d48cd..000000000 --- a/libnautilus-extensions/nautilus-keep-last-vertical-box.h +++ /dev/null @@ -1,51 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ - -/* nautilus-keep-last-vertical-box.h: Subclass of GtkVBox that clips off - items that don't fit, except the last one. - - Copyright (C) 2000 Eazel, Inc. - - The Gnome 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 Gnome 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 the Gnome 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. - - Author: John Sullivan <sullivan@eazel.com>, - */ - -#ifndef NAUTILUS_KEEP_LAST_VERTICAL_BOX_H -#define NAUTILUS_KEEP_LAST_VERTICAL_BOX_H - -#include <gtk/gtkvbox.h> - -#define NAUTILUS_TYPE_KEEP_LAST_VERTICAL_BOX (nautilus_keep_last_vertical_box_get_type ()) -#define NAUTILUS_KEEP_LAST_VERTICAL_BOX(obj) (GTK_CHECK_CAST ((obj), NAUTILUS_TYPE_KEEP_LAST_VERTICAL_BOX, NautilusKeepLastVerticalBox)) -#define NAUTILUS_KEEP_LAST_VERTICAL_BOX_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), NAUTILUS_TYPE_KEEP_LAST_VERTICAL_BOX, NautilusKeepLastVerticalBoxClass)) -#define NAUTILUS_IS_KEEP_LAST_VERTICAL_BOX(obj) (GTK_CHECK_TYPE ((obj), NAUTILUS_TYPE_KEEP_LAST_VERTICAL_BOX)) -#define NAUTILUS_IS_KEEP_LAST_VERTICAL_BOX_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), NAUTILUS_TYPE_KEEP_LAST_VERTICAL_BOX)) - -typedef struct NautilusKeepLastVerticalBox NautilusKeepLastVerticalBox; -typedef struct NautilusKeepLastVerticalBoxClass NautilusKeepLastVerticalBoxClass; - -struct NautilusKeepLastVerticalBox { - GtkVBox vbox; -}; - -struct NautilusKeepLastVerticalBoxClass { - GtkVBoxClass parent_class; -}; - -GtkType nautilus_keep_last_vertical_box_get_type (void); -GtkWidget *nautilus_keep_last_vertical_box_new (gint spacing); - -#endif /* NAUTILUS_KEEP_LAST_VERTICAL_BOX_H */ diff --git a/libnautilus-extensions/nautilus-lib-self-check-functions.c b/libnautilus-extensions/nautilus-lib-self-check-functions.c deleted file mode 100644 index 50156c1c0..000000000 --- a/libnautilus-extensions/nautilus-lib-self-check-functions.c +++ /dev/null @@ -1,38 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- - - nautilus-lib-self-check-functions.c: Wrapper for all self check functions - in Nautilus proper. - - 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. - - Author: Darin Adler <darin@eazel.com> -*/ - -#include <config.h> - -#if ! defined (NAUTILUS_OMIT_SELF_CHECK) - -#include "nautilus-lib-self-check-functions.h" - -void -nautilus_run_lib_self_checks (void) -{ - NAUTILUS_LIB_FOR_EACH_SELF_CHECK_FUNCTION (EEL_CALL_SELF_CHECK_FUNCTION) -} - -#endif /* ! NAUTILUS_OMIT_SELF_CHECK */ diff --git a/libnautilus-extensions/nautilus-lib-self-check-functions.h b/libnautilus-extensions/nautilus-lib-self-check-functions.h deleted file mode 100644 index fcc53e5df..000000000 --- a/libnautilus-extensions/nautilus-lib-self-check-functions.h +++ /dev/null @@ -1,53 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- - - nautilus-lib-self-check-functions.h: Wrapper and prototypes for all - self-check functions in libnautilus. - - 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. - - Author: Darin Adler <darin@eazel.com> -*/ - -#include <eel/eel-self-checks.h> - -void nautilus_run_lib_self_checks (void); - -/* Putting the prototypes for these self-check functions in each - header file for the files they are defined in would make compiling - the self-check framework take way too long (since one file would - have to include everything). - - So we put the list of functions here instead. - - Instead of just putting prototypes here, we put this macro that - can be used to do operations on the whole list of functions. -*/ - -#define NAUTILUS_LIB_FOR_EACH_SELF_CHECK_FUNCTION(macro) \ - macro (nautilus_self_check_preferences) \ - macro (nautilus_self_check_search_uri) \ - macro (nautilus_self_check_file_utilities) \ - macro (nautilus_self_check_file_operations) \ - macro (nautilus_self_check_directory) \ - macro (nautilus_self_check_file) \ - macro (nautilus_self_check_icon_container) \ - macro (nautilus_self_check_icon_factory) \ -/* Add new self-check functions to the list above this line. */ - -/* Generate prototypes for all the functions. */ -NAUTILUS_LIB_FOR_EACH_SELF_CHECK_FUNCTION (EEL_SELF_CHECK_FUNCTION_PROTOTYPE) diff --git a/libnautilus-extensions/nautilus-link-set.c b/libnautilus-extensions/nautilus-link-set.c deleted file mode 100644 index 1edb038af..000000000 --- a/libnautilus-extensions/nautilus-link-set.c +++ /dev/null @@ -1,213 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- - - nautilus-link-set.c: xml-based link file sets. - - 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. - - Author: Andy Hertzfeld <andy@eazel.com> -*/ - -#include <config.h> -#include "nautilus-link-set.h" - -#include "nautilus-file-utilities.h" -#include "nautilus-file.h" -#include <eel/eel-glib-extensions.h> -#include "nautilus-global-preferences.h" -#include "nautilus-link.h" -#include "nautilus-metadata.h" -#include "nautilus-preferences.h" -#include <eel/eel-string.h> -#include <eel/eel-xml-extensions.h> -#include <gnome-xml/parser.h> -#include <gnome-xml/xmlmemory.h> -#include <gtk/gtktogglebutton.h> -#include <gtk/gtkwindow.h> -#include <libgnome/gnome-util.h> -#include <libgnomevfs/gnome-vfs.h> -#include <stdlib.h> -#include <unistd.h> - -/* routine to create a new link file in the specified directory */ -static gboolean -create_new_link (const char *directory_path, const char *name, const char *image, const char *uri) -{ - xmlDocPtr output_document; - xmlNodePtr root_node; - char *file_name; - int result; - - /* 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 has no meaning. */ - xmlSetProp (root_node, "nautilus_link", "Nautilus Link"); - - /* Add link and custom icon tags */ - xmlSetProp (root_node, "custom_icon", image); - xmlSetProp (root_node, "link", uri); - - /* all done, so save the xml document as a link file */ - file_name = nautilus_make_path (directory_path, name); - result = xmlSaveFile (file_name, output_document); - g_free (file_name); - - xmlFreeDoc (output_document); - - return result > 0; -} - -/* utility to return link set path */ - -static xmlDocPtr -get_link_set_document(const char *link_set_name) -{ - char *link_set_path; - xmlDocPtr document; - - link_set_path = g_strdup_printf ("%s/linksets/%s.xml", - NAUTILUS_DATADIR, - link_set_name); - document = xmlParseFile (link_set_path); - g_free (link_set_path); - - return document; -} - -/* install a link set into the specified directory */ - -gboolean -nautilus_link_set_install (const char *directory_path, const char *link_set_name) -{ - xmlDocPtr document; - xmlNodePtr node; - char *link_name, *image_name, *uri, *full_uri; - gboolean created; - - /* load and parse the link set document */ - document = get_link_set_document (link_set_name); - if (document == NULL) { - g_warning ("could not load %s", link_set_name); - return FALSE; - } - - /* loop through the entries, generating link files */ - for (node = eel_xml_get_children (xmlDocGetRootElement (document)); - node != NULL; node = node->next) { - if (strcmp (node->name, "link") == 0) { - link_name = eel_xml_get_property_translated (node, "name"); - image_name = xmlGetProp (node, "image"); - uri = xmlGetProp (node, "uri"); - - /* Expand special URIs */ - full_uri = gnome_vfs_expand_initial_tilde (uri); - - /* create the link file */ - created = create_new_link (directory_path, link_name, - image_name, full_uri); - - xmlFree (link_name); - xmlFree (image_name); - xmlFree (uri); - g_free (full_uri); - - if (!created) { - xmlFreeDoc (document); - return FALSE; - } - } - } - - xmlFreeDoc (document); - return TRUE; -} - -/* test to see if a link set is installed. Return TRUE if all of the members are installed, false otherwise */ - -gboolean -nautilus_link_set_is_installed (const char *directory_path, const char *link_set_name) -{ - xmlDocPtr document; - xmlNodePtr node; - char *link_name, *file_name; - - /* load and parse the link set document */ - document = get_link_set_document (link_set_name); - if (document == NULL) { - g_warning ("could not load %s", link_set_name); - return FALSE; - } - - /* loop through the entries, testing to see if any are present */ - for (node = eel_xml_get_children (xmlDocGetRootElement (document)); - node != NULL; node = node->next) { - if (strcmp (node->name, "link") == 0) { - link_name = eel_xml_get_property_translated (node, "name"); - file_name = nautilus_make_path (directory_path, link_name); - xmlFree (link_name); - - if (!g_file_exists (file_name)) { - g_free (file_name); - xmlFreeDoc (document); - return FALSE; - } - g_free (file_name); - } - } - - xmlFreeDoc (document); - return TRUE; -} - -/* remove a link set from the specified directory */ -void -nautilus_link_set_remove (const char *directory_path, const char *link_set_name) -{ - xmlDocPtr document; - xmlNodePtr node; - char *link_name, *file_name; - - document = get_link_set_document(link_set_name); - if (document == NULL) { - g_message ("could not load %s", link_set_name); - return; - } - - /* loop through the entries in the xml file, formulating the names of the link files and - deleting them or decrementing their reference count */ - for (node = eel_xml_get_children (xmlDocGetRootElement (document)); - node != NULL; node = node->next) { - if (strcmp (node->name, "link") == 0) { - /* formulate the link file path name */ - link_name = eel_xml_get_property_translated (node, "name"); - file_name = nautilus_make_path (directory_path, link_name); - xmlFree (link_name); - - /* delete the file */ - unlink (file_name); - g_free (link_name); - } - } - - xmlFreeDoc (document); -} diff --git a/libnautilus-extensions/nautilus-link-set.h b/libnautilus-extensions/nautilus-link-set.h deleted file mode 100644 index 64bb00f4a..000000000 --- a/libnautilus-extensions/nautilus-link-set.h +++ /dev/null @@ -1,38 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- - - nautilus-link-set.h: xml-based sets of link files - - 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_SET_H -#define NAUTILUS_LINK_SET_H - -#include <glib.h> -#include <gtk/gtkwindow.h> - -gboolean nautilus_link_set_install (const char *directory_path, - const char *link_set_name); -void nautilus_link_set_remove (const char *directory_path, - const char *link_set_name); -gboolean nautilus_link_set_is_installed (const char *directory_path, - const char *link_set_name); - -#endif /* NAUTILUS_LINK_SET_H */ diff --git a/libnautilus-extensions/nautilus-link.c b/libnautilus-extensions/nautilus-link.c deleted file mode 100644 index 545fe493b..000000000 --- a/libnautilus-extensions/nautilus-link.c +++ /dev/null @@ -1,552 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- - - nautilus-link.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 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: Andy Hertzfeld <andy@eazel.com> -*/ - -#include <config.h> -#include "nautilus-link.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> - -/* 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" - -#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) -{ - 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_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 *path, - const char *key, - const char *value, - NautilusFileFunction extra_notify) -{ - xmlDocPtr document; - xmlNodePtr root; - const char *old_value; - char *uri; - NautilusFile *file; - - 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); - return TRUE; - } - - /* 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; -} - -/* 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) -{ - return local_set_root_property (path, - NAUTILUS_METADATA_KEY_CUSTOM_ICON, - icon_name, - NULL); -} - - -static void -forget_file_activation_uri (NautilusFile *file) -{ - GList *attributes; - - attributes = g_list_prepend (NULL, NAUTILUS_FILE_ATTRIBUTE_ACTIVATION_URI); - nautilus_file_invalidate_attributes (file, attributes); - 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); -} - -gboolean -nautilus_link_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_local_get_additional_text (const char *path) -{ - return local_get_root_property - (path, NAUTILUS_METADATA_KEY_EXTRA_TEXT); -} - -/* 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); - - return local_file_path; -} - -/* utility to free the icon notification info */ - -static void -free_icon_notification_info (NautilusLinkIconNotificationInfo *info) -{ - g_free (info->link_uri); - g_free (info->file_path); - g_free (info); -} - -/* 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) -{ - int size; - FILE* outfile; - NautilusFile *file; - NautilusLinkIconNotificationInfo *info; - - info = (NautilusLinkIconNotificationInfo *) callback_data; - - if (result != GNOME_VFS_OK) { - g_assert (file_contents == NULL); - free_icon_notification_info (info); - return; - } - - /* 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); - - /* 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); - } - - /* free up the notification info */ - free_icon_notification_info (info); -} - -/* returns the image associated with a link file */ -char * -nautilus_link_local_get_image_uri (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); - - if (icon_uri == NULL) { - return NULL; - } - - /* 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 = g_strdup (local_path); - eel_read_entire_file_async (icon_uri, icon_read_done_callback, info); - - g_free (icon_uri); - g_free (local_path); - return NULL; /* return NULL since the icon is still loading - it will get correctly set by the callback */ - } - - return icon_uri; -} - -/* Returns the link uri associated with a link file. */ -char * -nautilus_link_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_local_get_link_type (const char *path) -{ - return get_link_type (local_get_root_property (path, "nautilus_link")); -} - -/* FIXME bugzilla.eazel.com 2495: - * 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, - 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; -} - -gboolean -nautilus_link_local_is_volume_link (const char *path) -{ - return nautilus_link_local_get_link_type (path) == NAUTILUS_LINK_MOUNT; -} - -gboolean -nautilus_link_local_is_home_link (const char *path) -{ - return nautilus_link_local_get_link_type (path) == NAUTILUS_LINK_HOME; -} - -gboolean -nautilus_link_local_is_trash_link (const char *path) -{ - return nautilus_link_local_get_link_type (path) == NAUTILUS_LINK_TRASH; -} - - -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); -} diff --git a/libnautilus-extensions/nautilus-link.h b/libnautilus-extensions/nautilus-link.h deleted file mode 100644 index 88882ccb5..000000000 --- a/libnautilus-extensions/nautilus-link.h +++ /dev/null @@ -1,123 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- - - nautilus-link.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_H -#define NAUTILUS_LINK_H - -#include "nautilus-file.h" -#include <gdk/gdk.h> -#include <libgnome/gnome-defs.h> -#include <libgnome/gnome-dentry.h> - -/* Link types */ -typedef enum { - NAUTILUS_LINK_GENERIC, - NAUTILUS_LINK_TRASH, - NAUTILUS_LINK_MOUNT, - NAUTILUS_LINK_HOME -} NautilusLinkType; - -/* Create a new link file. Takes a path, works locally, and uses sync. I/O. - * Returns TRUE if it succeeds, FALSE if it fails. - */ -gboolean nautilus_link_local_create (const char *directory_path, - const char *name, - const char *image, - const char *target_uri, - const GdkPoint *point, - NautilusLinkType type); - -/* Change the icon of an existing link file. Takes a path, works - * locally, and uses sync. I/O. Returns TRUE if it succeeds, FALSE if - * it fails. Does not check and see if it is a link file. - */ -gboolean nautilus_link_local_set_icon (const char *path, - const char *icon_name); - -/* Specify the type of link that is represented - * Takes a path, works locally, and uses sync. I/O. - * Returns TRUE if it succeeds, FALSE if - * it fails. Does not check and see if it is a link file. - */ -gboolean nautilus_link_local_set_type (const char *path, - NautilusLinkType type); - -/* Specify the link uri of link that is represented - * Takes a path, works locally, and uses sync. I/O. - * Returns TRUE if it succeeds, FALSE if - * it fails. Does not check and see if it is a link file. - */ -gboolean nautilus_link_local_set_link_uri (const char *path, - const char *uri); - -/* Returns additional text to display under the name, NULL if - * none. Despite the fact that it takes a URI parameter, works only if - * the file is local and does sync. I/O. - */ -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 - */ -NautilusLinkType nautilus_link_local_get_link_type (const char *path); - - -/* Returns if a link is a mount link. - * Works only if the file is local and does sync. I/O - */ -gboolean nautilus_link_local_is_volume_link (const char *path); - -/* Returns if a link is a home link. - * Works only if the file is local and does sync. I/O - */ -gboolean nautilus_link_local_is_home_link (const char *path); - -/* Returns if a link is a trash link. - * Works only if the file is local and does sync. I/O - */ -gboolean nautilus_link_local_is_trash_link (const char *path); - - -/* Returns the link uri associated with a link file. The first version - * works only if the file is local and does sync. I/O, despite the - * fact that it takes a URI parameter. The second version takes the - * contents of a file already in memory. - */ -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); - -#endif /* NAUTILUS_LINK_H */ diff --git a/libnautilus-extensions/nautilus-medusa-support.c b/libnautilus-extensions/nautilus-medusa-support.c deleted file mode 100644 index 0af87810e..000000000 --- a/libnautilus-extensions/nautilus-medusa-support.c +++ /dev/null @@ -1,146 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ - -/* nautilus-medusa-support.c - Covers for access to medusa - from nautilus - - Copyright (C) 2001 Eazel, Inc. - - The Gnome 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 Gnome 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 the Gnome 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. - - Authors: Ramiro Estrugo <ramiro@eazel.com> - Rebecca Schulman <rebecka@eazel.com> -*/ - -#include <config.h> -#include "nautilus-medusa-support.h" -#include <libgnome/gnome-defs.h> -#include <libgnome/gnome-i18n.h> - -#include <eel/eel-glib-extensions.h> -#include <eel/eel-string.h> -#include <dirent.h> -#include <stdio.h> -#include <sys/types.h> - -#ifdef HAVE_MEDUSA -#include <libmedusa/medusa-system-state.h> -#endif - -gboolean -nautilus_medusa_services_are_enabled (void) -{ -#ifdef HAVE_MEDUSA - return medusa_system_services_are_enabled (); -#else - return FALSE; -#endif -} - - -NautilusCronStatus -nautilus_medusa_check_cron_is_enabled (void) -{ - DIR *proc_directory; - struct dirent *file; - char *stat_file_name; - FILE *stat_file; - char stat_file_data[128]; - const char *stat_file_process_name; - int process_number, bytes_read; - NautilusCronStatus status; - - /* We figure out whether cron is running by reading the proc - directory, and checking for a process named or ending with - "crond" */ - - proc_directory = opendir ("/proc"); - if (proc_directory == NULL) { - return NAUTILUS_CRON_STATUS_UNKNOWN; - } - - status = NAUTILUS_CRON_STATUS_UNKNOWN; - - while ((file = readdir (proc_directory)) != NULL) { - /* Process files have numbers */ - if (!eel_str_to_int (file->d_name, &process_number)) { - continue; - } - - /* Since we've seen at least one process file, we can change our state - * from "unknown" to "presumed off until proved otherwise". - */ - status = NAUTILUS_CRON_STATUS_OFF; - - stat_file_name = g_strdup_printf ("/proc/%d/stat", process_number); - stat_file = fopen (stat_file_name, "r"); - g_free (stat_file_name); - - if (stat_file == NULL) { - continue; - } - - bytes_read = fread (stat_file_data, 1, sizeof (stat_file_data) - 1, stat_file); - fclose (stat_file); - stat_file_data[bytes_read] = '\0'; - - stat_file_process_name = strchr (stat_file_data, ' '); - - if (eel_str_has_prefix (stat_file_process_name, " (crond)") || - eel_str_has_prefix (stat_file_process_name, " (cron)")) { - status = NAUTILUS_CRON_STATUS_ON; - break; - } - } - - closedir (proc_directory); - return status; -} - -#ifdef HAVE_MEDUSA -static const char * -nautilus_medusa_get_configuration_file_path (void) -{ - return medusa_get_configuration_file_path (); -} -#endif - -char * -nautilus_medusa_get_explanation_of_enabling (void) -{ -#ifdef HAVE_MEDUSA - return g_strdup_printf (_("If you would like to enable fast searches, you can " - "edit the file %s as root. " - "Setting the enabled flag to \"yes\" will turn medusa " - "services on.\n" - "To start indexing and search services right away, you " - "should also run the following commands as root:\n" - "\n" - "medusa-indexd\n" - "medusa-searchd\n" - "\n" - "Fast searches will not be available until an initial " - "index of your files has been created. This may take " - "a long time."), - nautilus_medusa_get_configuration_file_path ()); -#else - return g_strdup_printf (_("Medusa, the application that performs searches, cannot be found on " - "your system. If you have compiled nautilus yourself, " - "you will need to install a copy of medusa and recompile nautilus. " - "(A copy of Medusa may be available at ftp://ftp.gnome.org)\n" - "If you are using a packaged version of Nautilus, fast searching is " - "not available.\n")); -#endif -} diff --git a/libnautilus-extensions/nautilus-medusa-support.h b/libnautilus-extensions/nautilus-medusa-support.h deleted file mode 100644 index bc64e338d..000000000 --- a/libnautilus-extensions/nautilus-medusa-support.h +++ /dev/null @@ -1,47 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ - -/* nautilus-medusa-support.h - Covers for access to medusa - from nautilus - - - Copyright (C) 2001 Eazel, Inc. - - The Gnome 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 Gnome 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 the Gnome 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. - - Authors: Ramiro Estrugo <ramiro@eazel.com> - Rebecca Schulman <rebecka@eazel.com> -*/ - -#ifndef NAUTILUS_MEDUSA_SUPPORT_H -#define NAUTILUS_MEDUSA_SUPPORT_H - -#include <glib.h> - -typedef void (* NautilusMedusaChangedCallback) (gpointer data); - -typedef enum { - NAUTILUS_CRON_STATUS_ON, - NAUTILUS_CRON_STATUS_OFF, - NAUTILUS_CRON_STATUS_UNKNOWN -} NautilusCronStatus; - - -gboolean nautilus_medusa_services_are_enabled (void); -NautilusCronStatus nautilus_medusa_check_cron_is_enabled (void); -char * nautilus_medusa_get_explanation_of_enabling (void); - -#endif /* NAUTILUS_MEDUSA_SUPPORT_H */ - diff --git a/libnautilus-extensions/nautilus-merged-directory.c b/libnautilus-extensions/nautilus-merged-directory.c deleted file mode 100644 index 0101938ab..000000000 --- a/libnautilus-extensions/nautilus-merged-directory.c +++ /dev/null @@ -1,641 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- - - nautilus-merged-directory.c: Subclass of NautilusDirectory to implement the - virtual merged directory. - - Copyright (C) 1999, 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. - - Author: Darin Adler <darin@eazel.com> -*/ - -#include <config.h> -#include "nautilus-merged-directory.h" - -#include "nautilus-directory-private.h" -#include "nautilus-file.h" -#include <eel/eel-glib-extensions.h> -#include <eel/eel-gtk-macros.h> -#include <gtk/gtksignal.h> - -struct NautilusMergedDirectoryDetails { - GList *directories; - GList *directories_not_done_loading; - GHashTable *callbacks; - GHashTable *monitors; -}; - -typedef struct { - /* Basic configuration. */ - NautilusMergedDirectory *merged; - NautilusDirectoryCallback callback; - gpointer callback_data; - - GList *wait_for_attributes; - - GList *non_ready_directories; - GList *merged_file_list; -} MergedCallback; - -typedef struct { - NautilusMergedDirectory *merged; - - gboolean monitor_hidden_files; - gboolean monitor_backup_files; - GList *monitor_attributes; -} MergedMonitor; - -enum { - ADD_REAL_DIRECTORY, - REMOVE_REAL_DIRECTORY, - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL]; - -static void nautilus_merged_directory_initialize (gpointer object, - gpointer klass); -static void nautilus_merged_directory_initialize_class (gpointer klass); -static void remove_all_real_directories (NautilusMergedDirectory *merged); -static guint merged_callback_hash (gconstpointer merged_callback); -static gboolean merged_callback_equal (gconstpointer merged_callback, - gconstpointer merged_callback_2); - -EEL_DEFINE_CLASS_BOILERPLATE (NautilusMergedDirectory, - nautilus_merged_directory, - NAUTILUS_TYPE_DIRECTORY) - -static void -nautilus_merged_directory_initialize (gpointer object, gpointer klass) -{ - NautilusMergedDirectory *merged; - - merged = NAUTILUS_MERGED_DIRECTORY (object); - - merged->details = g_new0 (NautilusMergedDirectoryDetails, 1); - merged->details->callbacks = g_hash_table_new - (merged_callback_hash, merged_callback_equal); - merged->details->monitors = g_hash_table_new (NULL, NULL); -} - -static void -merged_destroy (GtkObject *object) -{ - NautilusMergedDirectory *merged; - - merged = NAUTILUS_MERGED_DIRECTORY (object); - - remove_all_real_directories (merged); - - if (g_hash_table_size (merged->details->callbacks) != 0) { - g_warning ("call_when_ready still pending when merged virtual directory is destroyed"); - } - if (g_hash_table_size (merged->details->monitors) != 0) { - g_warning ("file monitor still active when merged virtual directory is destroyed"); - } - - g_hash_table_destroy (merged->details->callbacks); - g_hash_table_destroy (merged->details->monitors); - g_free (merged->details); - - EEL_CALL_PARENT (GTK_OBJECT_CLASS, destroy, (object)); -} - -static guint -merged_callback_hash (gconstpointer merged_callback_as_pointer) -{ - const MergedCallback *merged_callback; - - merged_callback = merged_callback_as_pointer; - return GPOINTER_TO_UINT (merged_callback->callback) - ^ GPOINTER_TO_UINT (merged_callback->callback_data); -} - -static gboolean -merged_callback_equal (gconstpointer merged_callback_as_pointer, - gconstpointer merged_callback_as_pointer_2) -{ - const MergedCallback *merged_callback, *merged_callback_2; - - merged_callback = merged_callback_as_pointer; - merged_callback_2 = merged_callback_as_pointer_2; - - return merged_callback->callback == merged_callback_2->callback - && merged_callback->callback_data == merged_callback_2->callback_data; -} - -static void -merged_callback_destroy (MergedCallback *merged_callback) -{ - g_assert (merged_callback != NULL); - g_assert (NAUTILUS_IS_MERGED_DIRECTORY (merged_callback->merged)); - - eel_g_list_free_deep (merged_callback->wait_for_attributes); - g_list_free (merged_callback->non_ready_directories); - nautilus_file_list_free (merged_callback->merged_file_list); - g_free (merged_callback); -} - -static void -merged_callback_check_done (MergedCallback *merged_callback) -{ - /* Check if we are ready. */ - if (merged_callback->non_ready_directories != NULL) { - return; - } - - /* Remove from the hash table before sending it. */ - g_hash_table_remove (merged_callback->merged->details->callbacks, merged_callback); - - /* We are ready, so do the real callback. */ - (* merged_callback->callback) (NAUTILUS_DIRECTORY (merged_callback->merged), - merged_callback->merged_file_list, - merged_callback->callback_data); - - /* And we are done. */ - merged_callback_destroy (merged_callback); -} - -static void -merged_callback_remove_directory (MergedCallback *merged_callback, - NautilusDirectory *directory) -{ - merged_callback->non_ready_directories = g_list_remove - (merged_callback->non_ready_directories, - directory); - merged_callback_check_done (merged_callback); -} - -static void -directory_ready_callback (NautilusDirectory *directory, - GList *files, - gpointer callback_data) -{ - MergedCallback *merged_callback; - - g_assert (NAUTILUS_IS_DIRECTORY (directory)); - g_assert (callback_data != NULL); - - merged_callback = callback_data; - g_assert (g_list_find (merged_callback->non_ready_directories, directory) != NULL); - - /* Update based on this call. */ - merged_callback->merged_file_list = g_list_concat - (merged_callback->merged_file_list, - nautilus_file_list_copy (files)); - - /* Check if we are ready. */ - merged_callback_remove_directory (merged_callback, directory); -} - -static void -merged_call_when_ready (NautilusDirectory *directory, - GList *file_attributes, - NautilusDirectoryCallback callback, - gpointer callback_data) -{ - NautilusMergedDirectory *merged; - MergedCallback search_key, *merged_callback; - GList *node; - - merged = NAUTILUS_MERGED_DIRECTORY (directory); - - /* Check to be sure we aren't overwriting. */ - search_key.callback = callback; - search_key.callback_data = callback_data; - if (g_hash_table_lookup (merged->details->callbacks, &search_key) != NULL) { - g_warning ("tried to add a new callback while an old one was pending"); - return; - } - - /* Create a merged_callback record. */ - merged_callback = g_new0 (MergedCallback, 1); - merged_callback->merged = merged; - merged_callback->callback = callback; - merged_callback->callback_data = callback_data; - merged_callback->wait_for_attributes = eel_g_str_list_copy (file_attributes); - for (node = merged->details->directories; node != NULL; node = node->next) { - merged_callback->non_ready_directories = g_list_prepend - (merged_callback->non_ready_directories, node->data); - } - - /* Put it in the hash table. */ - g_hash_table_insert (merged->details->callbacks, - merged_callback, merged_callback); - - /* Handle the pathological case where there are no directories. */ - if (merged->details->directories == NULL) { - merged_callback_check_done (merged_callback); - } - - /* Now tell all the directories about it. */ - for (node = merged->details->directories; node != NULL; node = node->next) { - nautilus_directory_call_when_ready - (node->data, - merged_callback->wait_for_attributes, - directory_ready_callback, merged_callback); - } -} - -static void -merged_cancel_callback (NautilusDirectory *directory, - NautilusDirectoryCallback callback, - gpointer callback_data) -{ - NautilusMergedDirectory *merged; - MergedCallback search_key, *merged_callback; - GList *node; - - merged = NAUTILUS_MERGED_DIRECTORY (directory); - - /* Find the entry in the table. */ - search_key.callback = callback; - search_key.callback_data = callback_data; - merged_callback = g_hash_table_lookup (merged->details->callbacks, &search_key); - if (merged_callback == NULL) { - return; - } - - /* Remove from the hash table before working with it. */ - g_hash_table_remove (merged_callback->merged->details->callbacks, merged_callback); - - /* Tell all the directories to cancel the call. */ - for (node = merged_callback->non_ready_directories; node != NULL; node = node->next) { - nautilus_directory_cancel_callback - (node->data, - directory_ready_callback, merged_callback); - } - merged_callback_destroy (merged_callback); -} - -/* Create a monitor on each of the directories in the list. */ -static void -merged_file_monitor_add (NautilusDirectory *directory, - gconstpointer client, - gboolean monitor_hidden_files, - gboolean monitor_backup_files, - GList *file_attributes) -{ - NautilusMergedDirectory *merged; - MergedMonitor *monitor; - GList *node; - - merged = NAUTILUS_MERGED_DIRECTORY (directory); - - /* Map the client to a unique value so this doesn't interfere - * with direct monitoring of the directory by the same client. - */ - monitor = g_hash_table_lookup (merged->details->monitors, client); - if (monitor != NULL) { - g_assert (monitor->merged == merged); - eel_g_list_free_deep (monitor->monitor_attributes); - } else { - monitor = g_new0 (MergedMonitor, 1); - monitor->merged = merged; - g_hash_table_insert (merged->details->monitors, - (gpointer) client, monitor); - } - monitor->monitor_hidden_files = monitor_hidden_files; - monitor->monitor_backup_files = monitor_backup_files; - monitor->monitor_attributes = eel_g_str_list_copy (file_attributes); - - /* Call through to the real directory add calls. */ - for (node = merged->details->directories; node != NULL; node = node->next) { - nautilus_directory_file_monitor_add - (node->data, monitor, - monitor_hidden_files, monitor_backup_files, - file_attributes); - } -} - -/* Remove the monitor from each of the directories in the list. */ -static void -merged_file_monitor_remove (NautilusDirectory *directory, - gconstpointer client) -{ - NautilusMergedDirectory *merged; - MergedMonitor *monitor; - GList *node; - - merged = NAUTILUS_MERGED_DIRECTORY (directory); - - /* Map the client to the value used by the earlier add call. */ - monitor = g_hash_table_lookup (merged->details->monitors, client); - if (monitor == NULL) { - return; - } - g_hash_table_remove (merged->details->monitors, client); - - /* Call through to the real directory remove calls. */ - for (node = merged->details->directories; node != NULL; node = node->next) { - nautilus_directory_file_monitor_remove - (node->data, monitor); - } - - eel_g_list_free_deep (monitor->monitor_attributes); - g_free (monitor); -} - -static void -merged_force_reload (NautilusDirectory *directory) -{ - NautilusMergedDirectory *merged; - GList *node; - - merged = NAUTILUS_MERGED_DIRECTORY (directory); - - /* Call through to the real force_reload calls. */ - for (node = merged->details->directories; node != NULL; node = node->next) { - nautilus_directory_force_reload (node->data); - } -} - -/* Return true if any directory in the list does. */ -static gboolean -merged_contains_file (NautilusDirectory *directory, - NautilusFile *file) -{ - NautilusMergedDirectory *merged; - GList *node; - - merged = NAUTILUS_MERGED_DIRECTORY (directory); - - for (node = merged->details->directories; node != NULL; node = node->next) { - if (nautilus_directory_contains_file (node->data, file)) { - return TRUE; - } - } - return FALSE; -} - -/* Return true only if all directories in the list do. */ -static gboolean -merged_are_all_files_seen (NautilusDirectory *directory) -{ - NautilusMergedDirectory *merged; - GList *node; - - merged = NAUTILUS_MERGED_DIRECTORY (directory); - - for (node = merged->details->directories; node != NULL; node = node->next) { - if (!nautilus_directory_are_all_files_seen (node->data)) { - return FALSE; - } - } - return TRUE; -} - -/* Return true if any directory in the list does. */ -static gboolean -merged_is_not_empty (NautilusDirectory *directory) -{ - NautilusMergedDirectory *merged; - GList *node; - - merged = NAUTILUS_MERGED_DIRECTORY (directory); - - for (node = merged->details->directories; node != NULL; node = node->next) { - if (nautilus_directory_is_not_empty (node->data)) { - return TRUE; - } - } - return FALSE; -} - -static void -forward_files_added_cover (NautilusDirectory *real_directory, - GList *files, - NautilusMergedDirectory *merged) -{ - nautilus_directory_emit_files_added (NAUTILUS_DIRECTORY (merged), files); -} - -static void -forward_files_changed_cover (NautilusDirectory *real_directory, - GList *files, - NautilusMergedDirectory *merged) -{ - nautilus_directory_emit_files_changed (NAUTILUS_DIRECTORY (merged), files); -} - -static void -done_loading_callback (NautilusDirectory *real_directory, - NautilusMergedDirectory *merged) -{ - merged->details->directories_not_done_loading = g_list_remove - (merged->details->directories_not_done_loading, real_directory); - if (merged->details->directories_not_done_loading == NULL) { - nautilus_directory_emit_done_loading (NAUTILUS_DIRECTORY (merged)); - } -} - -static void -monitor_add_directory (gpointer key, - gpointer value, - gpointer callback_data) -{ - MergedMonitor *monitor; - - monitor = value; - nautilus_directory_file_monitor_add - (NAUTILUS_DIRECTORY (callback_data), monitor, - monitor->monitor_hidden_files, - monitor->monitor_backup_files, - monitor->monitor_attributes); -} - -static void -merged_add_real_directory (NautilusMergedDirectory *merged, - NautilusDirectory *real_directory) -{ - g_return_if_fail (NAUTILUS_IS_MERGED_DIRECTORY (merged)); - g_return_if_fail (NAUTILUS_IS_DIRECTORY (real_directory)); - g_return_if_fail (!NAUTILUS_IS_MERGED_DIRECTORY (real_directory)); - g_return_if_fail (g_list_find (merged->details->directories, real_directory) == NULL); - - /* Add to our list of directories. */ - nautilus_directory_ref (real_directory); - merged->details->directories = g_list_prepend - (merged->details->directories, real_directory); - merged->details->directories_not_done_loading = g_list_prepend - (merged->details->directories_not_done_loading, real_directory); - - /* Connect signals. */ - gtk_signal_connect (GTK_OBJECT (real_directory), - "files_added", - forward_files_added_cover, - merged); - gtk_signal_connect (GTK_OBJECT (real_directory), - "files_changed", - forward_files_changed_cover, - merged); - gtk_signal_connect (GTK_OBJECT (real_directory), - "done_loading", - done_loading_callback, - merged); - - /* FIXME bugzilla.eazel.com 5084: The done_loading part won't work for the case where - * we have no directories in our list. - */ - - /* Add the directory to any extant monitors. */ - g_hash_table_foreach (merged->details->monitors, - monitor_add_directory, - real_directory); - /* FIXME bugzilla.eazel.com 2541: Do we need to add the directory to callbacks too? */ -} - -void -nautilus_merged_directory_add_real_directory (NautilusMergedDirectory *merged, - NautilusDirectory *real_directory) -{ - g_return_if_fail (NAUTILUS_IS_MERGED_DIRECTORY (merged)); - g_return_if_fail (NAUTILUS_IS_DIRECTORY (real_directory)); - g_return_if_fail (!NAUTILUS_IS_MERGED_DIRECTORY (real_directory)); - - /* Quietly do nothing if asked to add something that's already there. */ - if (g_list_find (merged->details->directories, real_directory) != NULL) { - return; - } - - gtk_signal_emit (GTK_OBJECT (merged), - signals[ADD_REAL_DIRECTORY], - real_directory); -} - -GList * -nautilus_merged_directory_get_real_directories (NautilusMergedDirectory *merged) -{ - return g_list_copy (merged->details->directories); -} - -static void -merged_callback_remove_directory_cover (gpointer key, - gpointer value, - gpointer callback_data) -{ - merged_callback_remove_directory - (value, NAUTILUS_DIRECTORY (callback_data)); -} - -static void -monitor_remove_directory (gpointer key, - gpointer value, - gpointer callback_data) -{ - nautilus_directory_file_monitor_remove - (NAUTILUS_DIRECTORY (callback_data), value); -} - -static void -merged_remove_real_directory (NautilusMergedDirectory *merged, - NautilusDirectory *real_directory) -{ - g_return_if_fail (NAUTILUS_IS_MERGED_DIRECTORY (merged)); - g_return_if_fail (NAUTILUS_IS_DIRECTORY (real_directory)); - g_return_if_fail (g_list_find (merged->details->directories, real_directory) != NULL); - - /* Remove this directory from callbacks and monitors. */ - eel_g_hash_table_safe_for_each - (merged->details->callbacks, - merged_callback_remove_directory_cover, - real_directory); - g_hash_table_foreach - (merged->details->monitors, - monitor_remove_directory, - real_directory); - - /* Disconnect all the signals. */ - gtk_signal_disconnect_by_data (GTK_OBJECT (real_directory), merged); - - /* Remove from our list of directories. */ - merged->details->directories = g_list_remove - (merged->details->directories, real_directory); - merged->details->directories_not_done_loading = g_list_remove - (merged->details->directories_not_done_loading, real_directory); - nautilus_directory_unref (real_directory); -} - -void -nautilus_merged_directory_remove_real_directory (NautilusMergedDirectory *merged, - NautilusDirectory *real_directory) -{ - g_return_if_fail (NAUTILUS_IS_MERGED_DIRECTORY (merged)); - - /* Quietly do nothing if asked to remove something that's not there. */ - if (g_list_find (merged->details->directories, real_directory) == NULL) { - return; - } - - gtk_signal_emit (GTK_OBJECT (merged), - signals[REMOVE_REAL_DIRECTORY], - real_directory); -} - -static void -remove_all_real_directories (NautilusMergedDirectory *merged) -{ - while (merged->details->directories != NULL) { - nautilus_merged_directory_remove_real_directory - (merged, merged->details->directories->data); - } -} - -static void -nautilus_merged_directory_initialize_class (gpointer klass) -{ - GtkObjectClass *object_class; - NautilusDirectoryClass *directory_class; - NautilusMergedDirectoryClass *merged_directory_class; - - object_class = GTK_OBJECT_CLASS (klass); - directory_class = NAUTILUS_DIRECTORY_CLASS (klass); - merged_directory_class = NAUTILUS_MERGED_DIRECTORY_CLASS (klass); - - object_class->destroy = merged_destroy; - - directory_class->contains_file = merged_contains_file; - directory_class->call_when_ready = merged_call_when_ready; - directory_class->cancel_callback = merged_cancel_callback; - directory_class->file_monitor_add = merged_file_monitor_add; - directory_class->file_monitor_remove = merged_file_monitor_remove; - directory_class->force_reload = merged_force_reload; - directory_class->are_all_files_seen = merged_are_all_files_seen; - directory_class->is_not_empty = merged_is_not_empty; - - merged_directory_class->add_real_directory = merged_add_real_directory; - merged_directory_class->remove_real_directory = merged_remove_real_directory; - - signals[ADD_REAL_DIRECTORY] - = gtk_signal_new ("add_real_directory", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (NautilusMergedDirectoryClass, - add_real_directory), - gtk_marshal_NONE__POINTER, - GTK_TYPE_NONE, 1, GTK_TYPE_POINTER); - signals[REMOVE_REAL_DIRECTORY] - = gtk_signal_new ("remove_real_directory", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (NautilusMergedDirectoryClass, - remove_real_directory), - gtk_marshal_NONE__POINTER, - GTK_TYPE_NONE, 1, GTK_TYPE_POINTER); - - gtk_object_class_add_signals (object_class, signals, LAST_SIGNAL); -} diff --git a/libnautilus-extensions/nautilus-merged-directory.h b/libnautilus-extensions/nautilus-merged-directory.h deleted file mode 100644 index ac8db0bd5..000000000 --- a/libnautilus-extensions/nautilus-merged-directory.h +++ /dev/null @@ -1,66 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- - - nautilus-merged-directory.h: Subclass of NautilusDirectory to implement - a virtual directory consisting of the merged contents of some real - directories. - - Copyright (C) 1999, 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. - - Author: Darin Adler <darin@eazel.com> -*/ - -#ifndef NAUTILUS_MERGED_DIRECTORY_H -#define NAUTILUS_MERGED_DIRECTORY_H - -#include "nautilus-directory.h" - -#define NAUTILUS_TYPE_MERGED_DIRECTORY \ - (nautilus_merged_directory_get_type ()) -#define NAUTILUS_MERGED_DIRECTORY(obj) \ - (GTK_CHECK_CAST ((obj), NAUTILUS_TYPE_MERGED_DIRECTORY, NautilusMergedDirectory)) -#define NAUTILUS_MERGED_DIRECTORY_CLASS(klass) \ - (GTK_CHECK_CLASS_CAST ((klass), NAUTILUS_TYPE_MERGED_DIRECTORY, NautilusMergedDirectoryClass)) -#define NAUTILUS_IS_MERGED_DIRECTORY(obj) \ - (GTK_CHECK_TYPE ((obj), NAUTILUS_TYPE_MERGED_DIRECTORY)) -#define NAUTILUS_IS_MERGED_DIRECTORY_CLASS(klass) \ - (GTK_CHECK_CLASS_TYPE ((klass), NAUTILUS_TYPE_MERGED_DIRECTORY)) - -typedef struct NautilusMergedDirectoryDetails NautilusMergedDirectoryDetails; - -typedef struct { - NautilusDirectory parent_slot; - NautilusMergedDirectoryDetails *details; -} NautilusMergedDirectory; - -typedef struct { - NautilusDirectoryClass parent_slot; - - void (* add_real_directory) (NautilusMergedDirectory *merged_directory, - NautilusDirectory *real_directory); - void (* remove_real_directory) (NautilusMergedDirectory *merged_directory, - NautilusDirectory *real_directory); -} NautilusMergedDirectoryClass; - -GtkType nautilus_merged_directory_get_type (void); -void nautilus_merged_directory_add_real_directory (NautilusMergedDirectory *merged_directory, - NautilusDirectory *real_directory); -void nautilus_merged_directory_remove_real_directory (NautilusMergedDirectory *merged_directory, - NautilusDirectory *real_directory); -GList * nautilus_merged_directory_get_real_directories (NautilusMergedDirectory *merged_directory); - -#endif /* NAUTILUS_MERGED_DIRECTORY_H */ diff --git a/libnautilus-extensions/nautilus-metadata.h b/libnautilus-extensions/nautilus-metadata.h deleted file mode 100644 index 00f96a2da..000000000 --- a/libnautilus-extensions/nautilus-metadata.h +++ /dev/null @@ -1,79 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- - - nautilus-metadata.h: #defines and other metadata-related info - - 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. - - Author: John Sullivan <sullivan@eazel.com> -*/ - -#ifndef NAUTILUS_METADATA_H -#define NAUTILUS_METADATA_H - -/* Keys for getting/setting Nautilus metadata. All metadata used in Nautilus - * should define its key here, so we can keep track of the whole set easily. - */ - -/* Per-file */ - -#define NAUTILUS_METADATA_KEY_CONTENT_VIEWS "content_views" - -#define NAUTILUS_METADATA_KEY_DEFAULT_ACTION_TYPE "default_action_type" -#define NAUTILUS_METADATA_KEY_DEFAULT_APPLICATION "default_application" -#define NAUTILUS_METADATA_KEY_DEFAULT_COMPONENT "default_component" -#define NAUTILUS_METADATA_KEY_SHORT_LIST_APPLICATION_ADD "short_list_application_add" -#define NAUTILUS_METADATA_KEY_SHORT_LIST_APPLICATION_REMOVE "short_list_application_remove" -#define NAUTILUS_METADATA_KEY_EXPLICIT_APPLICATION "application" -#define NAUTILUS_METADATA_SUBKEY_APPLICATION_ID "id" -#define NAUTILUS_METADATA_KEY_SHORT_LIST_COMPONENT_ADD "short_list_component_add" -#define NAUTILUS_METADATA_KEY_SHORT_LIST_COMPONENT_REMOVE "short_list_component_remove" -#define NAUTILUS_METADATA_KEY_EXPLICIT_COMPONENT "explicit_content_view" -#define NAUTILUS_METADATA_SUBKEY_COMPONENT_IID "iid" - -#define NAUTILUS_METADATA_KEY_LOCATION_BACKGROUND_COLOR "background_color" -#define NAUTILUS_METADATA_KEY_LOCATION_BACKGROUND_IMAGE "background_tile_image" - -#define NAUTILUS_METADATA_KEY_ICON_VIEW_ZOOM_LEVEL "icon_view_zoom_level" -#define NAUTILUS_METADATA_KEY_ICON_VIEW_AUTO_LAYOUT "icon_view_auto_layout" -#define NAUTILUS_METADATA_KEY_ICON_VIEW_TIGHTER_LAYOUT "icon_view_tighter_layout" -#define NAUTILUS_METADATA_KEY_ICON_VIEW_SORT_BY "icon_view_sort_by" -#define NAUTILUS_METADATA_KEY_ICON_VIEW_SORT_REVERSED "icon_view_sort_reversed" - -#define NAUTILUS_METADATA_KEY_LIST_VIEW_ZOOM_LEVEL "list_view_zoom_level" -#define NAUTILUS_METADATA_KEY_LIST_VIEW_SORT_COLUMN "list_view_sort_column" -#define NAUTILUS_METADATA_KEY_LIST_VIEW_SORT_REVERSED "list_view_sort_reversed" - -#define NAUTILUS_METADATA_KEY_WINDOW_GEOMETRY "window_geometry" - -#define NAUTILUS_METADATA_KEY_SIDEBAR_BACKGROUND_COLOR "sidebar_background_color" -#define NAUTILUS_METADATA_KEY_SIDEBAR_BACKGROUND_IMAGE "sidebar_background_tile_image" -#define NAUTILUS_METADATA_KEY_SIDEBAR_BUTTONS "sidebar_buttons" -#define NAUTILUS_METADATA_KEY_SIDEBAR_TAB_COLOR "sidebar_tab_color" -#define NAUTILUS_METADATA_KEY_SIDEBAR_TITLE_TAB_COLOR "sidebar_title_tab_color" - -#define NAUTILUS_METADATA_KEY_NOTES "notes" -#define NAUTILUS_METADATA_KEY_ANNOTATION "annotation" -#define NAUTILUS_METADATA_KEY_ICON_POSITION "icon_position" -#define NAUTILUS_METADATA_KEY_ICON_SCALE "icon_scale" -#define NAUTILUS_METADATA_KEY_CUSTOM_ICON "custom_icon" - -/* per link file */ - -#define NAUTILUS_METADATA_KEY_EXTRA_TEXT "extra_text" - -#endif /* NAUTILUS_METADATA_H */ diff --git a/libnautilus-extensions/nautilus-metafile-factory.c b/libnautilus-extensions/nautilus-metafile-factory.c deleted file mode 100644 index 046b167b9..000000000 --- a/libnautilus-extensions/nautilus-metafile-factory.c +++ /dev/null @@ -1,108 +0,0 @@ -/* -*- Mode: IDL; tab-width: 8; indent-tabs-mode: 8; c-basic-offset: 8 -*- */ - -/* nautilus-metafile.c - server side of Nautilus::MetafileFactory - * - * Copyright (C) 2001 Eazel, Inc. - * - * 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. - * - * This 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; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#include <config.h> -#include "nautilus-metafile-factory.h" -#include "nautilus-metafile.h" - -#include <eel/eel-gtk-macros.h> -#include <libnautilus-extensions/nautilus-bonobo-extensions.h> -#include <libnautilus/nautilus-bonobo-workarounds.h> - -struct NautilusMetafileFactoryDetails { -}; - -static void nautilus_metafile_factory_init (NautilusMetafileFactory *factory); -static void nautilus_metafile_factory_class_init (NautilusMetafileFactoryClass *klass); - -static void destroy (GtkObject *factory); - -static Nautilus_Metafile corba_open (PortableServer_Servant servant, - const Nautilus_URI directory, - CORBA_Environment *ev); - -NAUTILUS_BONOBO_X_BOILERPLATE (NautilusMetafileFactory, Nautilus_MetafileFactory, BONOBO_X_OBJECT_TYPE, nautilus_metafile_factory) - -static void -nautilus_metafile_factory_class_init (NautilusMetafileFactoryClass *klass) -{ - GTK_OBJECT_CLASS (klass)->destroy = destroy; - - klass->epv.open = corba_open; -} - -static void -nautilus_metafile_factory_init (NautilusMetafileFactory *factory) -{ - factory->details = g_new0 (NautilusMetafileFactoryDetails, 1); -} - -static void -destroy (GtkObject *object) -{ - NautilusMetafileFactory *factory; - - factory = NAUTILUS_METAFILE_FACTORY (object); - g_free (factory->details); - - EEL_CALL_PARENT (GTK_OBJECT_CLASS, destroy, (object)); -} - -static NautilusMetafileFactory * -nautilus_metafile_factory_new (void) -{ - NautilusMetafileFactory *metafile_factory; - metafile_factory = NAUTILUS_METAFILE_FACTORY (gtk_object_new (NAUTILUS_TYPE_METAFILE_FACTORY, NULL)); - return metafile_factory; -} - -static NautilusMetafileFactory *the_factory; - -static void -free_factory_instance (void) -{ - bonobo_object_unref (BONOBO_OBJECT (the_factory)); - the_factory = NULL; -} - -NautilusMetafileFactory * -nautilus_metafile_factory_get_instance (void) -{ - if (the_factory == NULL) { - the_factory = nautilus_metafile_factory_new (); - g_atexit (free_factory_instance); - } - - bonobo_object_ref (BONOBO_OBJECT (the_factory)); - - return the_factory; -} - -static Nautilus_Metafile -corba_open (PortableServer_Servant servant, - const Nautilus_URI directory, - CORBA_Environment *ev) -{ - BonoboObject *object; - object = BONOBO_OBJECT (nautilus_metafile_get (directory)); - return CORBA_Object_duplicate (bonobo_object_corba_objref (object), ev); -} diff --git a/libnautilus-extensions/nautilus-metafile-factory.h b/libnautilus-extensions/nautilus-metafile-factory.h deleted file mode 100644 index 91654f25d..000000000 --- a/libnautilus-extensions/nautilus-metafile-factory.h +++ /dev/null @@ -1,56 +0,0 @@ -/* -*- Mode: IDL; tab-width: 8; indent-tabs-mode: 8; c-basic-offset: 8 -*- */ - -/* nautilus-metafile.h - server side of Nautilus::MetafileFactory - * - * Copyright (C) 2001 Eazel, Inc. - * - * 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. - * - * This 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; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef NAUTILUS_METAFILE_FACTORY_H -#define NAUTILUS_METAFILE_FACTORY_H - -#include <libnautilus-extensions/nautilus-metafile-server.h> - -#include <bonobo/bonobo-object.h> -#include <bonobo/bonobo-xobject.h> - -#define NAUTILUS_TYPE_METAFILE_FACTORY (nautilus_metafile_factory_get_type ()) -#define NAUTILUS_METAFILE_FACTORY(obj) (GTK_CHECK_CAST ((obj), NAUTILUS_TYPE_METAFILE_FACTORY, NautilusMetafileFactory)) -#define NAUTILUS_METAFILE_FACTORY_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), NAUTILUS_TYPE_METAFILE_FACTORY, NautilusMetafileFactoryClass)) -#define NAUTILUS_IS_METAFILE_FACTORY(obj) (GTK_CHECK_TYPE ((obj), NAUTILUS_TYPE_METAFILE_FACTORY)) -#define NAUTILUS_IS_METAFILE_FACTORY_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), NAUTILUS_TYPE_METAFILE_FACTORY)) - -typedef struct NautilusMetafileFactoryDetails NautilusMetafileFactoryDetails; - -typedef struct { - BonoboXObject parent_slot; - NautilusMetafileFactoryDetails *details; -} NautilusMetafileFactory; - -typedef struct { - BonoboXObjectClass parent_slot; - POA_Nautilus_MetafileFactory__epv epv; -} NautilusMetafileFactoryClass; - -GtkType nautilus_metafile_factory_get_type (void); - - -#define METAFILE_FACTORY_IID "OAFIID:nautilus_metafile_factory:bc318c01-4106-4622-8d6c-b419ec89e4c6" - -NautilusMetafileFactory *nautilus_metafile_factory_get_instance (void); - -#endif /* NAUTILUS_METAFILE_FACTORY_H */ diff --git a/libnautilus-extensions/nautilus-metafile-server.idl b/libnautilus-extensions/nautilus-metafile-server.idl deleted file mode 100644 index afa1a6617..000000000 --- a/libnautilus-extensions/nautilus-metafile-server.idl +++ /dev/null @@ -1,92 +0,0 @@ -/* -*- Mode: IDL; tab-width: 8; indent-tabs-mode: 8; c-basic-offset: 8 -*- */ - -/* nautilus-metafile-server.idl - Interface for components to access Nautilus metadata - * - * Copyright (C) 2001 Eazel, Inc. - * - * 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. - * - * This 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; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef NAUTILUS_METAFILE_SERVER_IDL_INCLUDED -#define NAUTILUS_METAFILE_SERVER_IDL_INCLUDED - -#include <Bonobo.idl> -#include <libnautilus/nautilus-view-component.idl> - -module Nautilus { - - typedef sequence<string> FileNameList; - - /* NautilusFiles creates (and registers) MetafileMonitors in order - * to get notified of metafile changes. - */ - interface MetafileMonitor : ::Bonobo::Unknown { - void metafile_changed (in FileNameList file_names); - void metafile_ready (); - }; - - typedef sequence<string> MetadataList; - - /* A Metafile provides access to the metadata for the files - * in a directory. - * - * Note: file names within the directory are specified, by - * strings whose special characters have been URI encoded. - */ - interface Metafile : ::Bonobo::Unknown { - - /* returns whether the metadata has been read in yet */ - boolean is_read (); - - /* getters for a file's metadata */ - string get (in string file_name, - in string key, - in string default_value); - MetadataList get_list (in string file_name, - in string list_key, - in string list_subkey); - - /* setters for a file's metadata */ - void set (in string file_name, - in string key, - in string default_value, - in string metadata); - void set_list (in string file_name, - in string list_key, - in string list_subkey, - in MetadataList list); - - /* calls to keep metadata in sync with file operations */ - void copy (in string source_file_name, - in URI destination_directory_uri, - in string destination_file_name); - void remove (in string file_name); - void rename (in string old_file_name, - in string new_file_name); - void rename_directory (in string new_directory_uri); - - /* calls for registering a MetafileMonitor with a Metafile */ - void register_monitor (in MetafileMonitor monitor); - void unregister_monitor (in MetafileMonitor monitor); - }; - - /* Components use the MetafileFactory to get a Metafile for a directory. */ - interface MetafileFactory : ::Bonobo::Unknown { - Metafile open (in URI directory); - }; -}; - -#endif /* NAUTILUS_METAFILE_SERVER_IDL_INCLUDED */ diff --git a/libnautilus-extensions/nautilus-metafile.c b/libnautilus-extensions/nautilus-metafile.c deleted file mode 100644 index eac730a09..000000000 --- a/libnautilus-extensions/nautilus-metafile.c +++ /dev/null @@ -1,2127 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-*/ - -/* nautilus-metafile.c - server side of Nautilus::Metafile - * - * Copyright (C) 2001 Eazel, Inc. - * - * 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. - * - * This 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; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#include <config.h> -#include "nautilus-metafile.h" - -#include "nautilus-bonobo-extensions.h" -#include "nautilus-directory.h" -#include "nautilus-directory.h" -#include "nautilus-file-private.h" -#include "nautilus-global-preferences.h" -#include "nautilus-metadata.h" -#include "nautilus-search-uri.h" -#include "nautilus-thumbnails.h" -#include <eel/eel-glib-extensions.h> -#include <eel/eel-gtk-macros.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 <gtk/gtkmain.h> -#include <libgnomevfs/gnome-vfs-file-info.h> -#include <libgnomevfs/gnome-vfs-types.h> -#include <libgnomevfs/gnome-vfs-uri.h> -#include <libnautilus/nautilus-bonobo-workarounds.h> -#include <stdlib.h> - -#define METAFILE_XML_VERSION "1.0" - -#define METAFILE_PERMISSIONS (GNOME_VFS_PERM_USER_READ | GNOME_VFS_PERM_USER_WRITE \ - | GNOME_VFS_PERM_GROUP_READ | GNOME_VFS_PERM_GROUP_WRITE \ - | GNOME_VFS_PERM_OTHER_READ | GNOME_VFS_PERM_OTHER_WRITE) - -#define METAFILES_DIRECTORY_NAME "metafiles" - -#define METAFILES_DIRECTORY_PERMISSIONS \ - (GNOME_VFS_PERM_USER_ALL \ - | GNOME_VFS_PERM_GROUP_ALL \ - | GNOME_VFS_PERM_OTHER_ALL) - -static void nautilus_metafile_init (NautilusMetafile *metafile); -static void nautilus_metafile_class_init (NautilusMetafileClass *klass); - -static void destroy (GtkObject *metafile); - -static CORBA_boolean corba_is_read (PortableServer_Servant servant, - CORBA_Environment *ev); - -static CORBA_char *corba_get (PortableServer_Servant servant, - const CORBA_char *file_name, - const CORBA_char *key, - const CORBA_char *default_value, - CORBA_Environment *ev); -static Nautilus_MetadataList *corba_get_list (PortableServer_Servant servant, - const CORBA_char *file_name, - const CORBA_char *list_key, - const CORBA_char *list_subkey, - CORBA_Environment *ev); - -static void corba_set (PortableServer_Servant servant, - const CORBA_char *file_name, - const CORBA_char *key, - const CORBA_char *default_value, - const CORBA_char *metadata, - CORBA_Environment *ev); -static void corba_set_list (PortableServer_Servant servant, - const CORBA_char *file_name, - const CORBA_char *list_key, - const CORBA_char *list_subkey, - const Nautilus_MetadataList *list, - CORBA_Environment *ev); - -static void corba_copy (PortableServer_Servant servant, - const CORBA_char *source_file_name, - const Nautilus_URI destination_directory_uri, - const CORBA_char *destination_file_name, - CORBA_Environment *ev); -static void corba_remove (PortableServer_Servant servant, - const CORBA_char *file_name, - CORBA_Environment *ev); -static void corba_rename (PortableServer_Servant servant, - const CORBA_char *old_file_name, - const CORBA_char *new_file_name, - CORBA_Environment *ev); -static void corba_rename_directory (PortableServer_Servant servant, - const CORBA_char *new_directory_uri, - CORBA_Environment *ev); - -static void corba_register_monitor (PortableServer_Servant servant, - const Nautilus_MetafileMonitor monitor, - CORBA_Environment *ev); -static void corba_unregister_monitor (PortableServer_Servant servant, - const Nautilus_MetafileMonitor monitor, - CORBA_Environment *ev); - -static char *get_file_metadata (NautilusMetafile *metafile, - const char *file_name, - const char *key, - const char *default_metadata); -static GList *get_file_metadata_list (NautilusMetafile *metafile, - const char *file_name, - const char *list_key, - const char *list_subkey); -static gboolean set_file_metadata (NautilusMetafile *metafile, - const char *file_name, - const char *key, - const char *default_metadata, - const char *metadata); -static gboolean set_file_metadata_list (NautilusMetafile *metafile, - const char *file_name, - const char *list_key, - const char *list_subkey, - GList *list); - -static void rename_file_metadata (NautilusMetafile *metafile, - const char *old_file_name, - const char *new_file_name); -static void copy_file_metadata (NautilusMetafile *source_metafile, - const char *source_file_name, - NautilusMetafile *destination_metafile, - const char *destination_file_name); -static void remove_file_metadata (NautilusMetafile *metafile, - const char *file_name); - -static void call_metafile_changed_for_one_file (NautilusMetafile *metafile, - const CORBA_char *file_name); - -static void metafile_read_restart (NautilusMetafile *metafile); -static void metafile_read_start (NautilusMetafile *metafile); -static void metafile_write_start (NautilusMetafile *metafile); -static void directory_request_write_metafile (NautilusMetafile *metafile); -static void metafile_free_metadata (NautilusMetafile *metafile); -static void metafile_read_cancel (NautilusMetafile *metafile); -static void async_read_cancel (NautilusMetafile *metafile); - -static void nautilus_metafile_set_metafile_contents (NautilusMetafile *metafile, - xmlDocPtr metafile_contents); - -NAUTILUS_BONOBO_X_BOILERPLATE (NautilusMetafile, Nautilus_Metafile, BONOBO_X_OBJECT_TYPE, nautilus_metafile) - -typedef struct MetafileReadState { - gboolean use_public_metafile; - EelReadFileHandle *handle; - GnomeVFSAsyncHandle *get_file_info_handle; -} MetafileReadState; - -typedef struct MetafileWriteState { - gboolean use_public_metafile; - GnomeVFSAsyncHandle *handle; - xmlChar *buffer; - GnomeVFSFileSize size; - gboolean write_again; -} MetafileWriteState; - -struct NautilusMetafileDetails { - gboolean is_read; - - xmlDoc *xml; - GHashTable *node_hash; - GHashTable *changes; - - /* State for reading and writing metadata. */ - MetafileReadState *read_state; - guint write_idle_id; - MetafileWriteState *write_state; - - GList *monitors; - - GnomeVFSURI *private_vfs_uri; - GnomeVFSURI *public_vfs_uri; - - char *directory_uri; - GnomeVFSURI *directory_vfs_uri; -}; - -static GHashTable *metafiles; - -static void -nautilus_metafile_class_init (NautilusMetafileClass *klass) -{ - GTK_OBJECT_CLASS (klass)->destroy = destroy; - - klass->epv.is_read = corba_is_read; - klass->epv.get = corba_get; - klass->epv.get_list = corba_get_list; - klass->epv.set = corba_set; - klass->epv.set_list = corba_set_list; - klass->epv.copy = corba_copy; - klass->epv.remove = corba_remove; - klass->epv.rename = corba_rename; - klass->epv.rename_directory = corba_rename_directory; - klass->epv.register_monitor = corba_register_monitor; - klass->epv.unregister_monitor = corba_unregister_monitor; -} - -static void -nautilus_metafile_init (NautilusMetafile *metafile) -{ - metafile->details = g_new0 (NautilusMetafileDetails, 1); - - metafile->details->node_hash = g_hash_table_new (g_str_hash, g_str_equal); - -} - -static void -destroy (GtkObject *object) -{ - NautilusMetafile *metafile; - - metafile = NAUTILUS_METAFILE (object); - - g_assert (metafile->details->write_state == NULL); - async_read_cancel (metafile); - g_assert (metafile->details->read_state == NULL); - - if (metafile->details->public_vfs_uri != NULL) { - gnome_vfs_uri_unref (metafile->details->public_vfs_uri); - } - if (metafile->details->private_vfs_uri != NULL) { - gnome_vfs_uri_unref (metafile->details->private_vfs_uri); - } - - g_hash_table_remove (metafiles, metafile->details->directory_uri); - - metafile_free_metadata (metafile); - g_hash_table_destroy (metafile->details->node_hash); - - g_assert (metafile->details->write_idle_id == 0); - - g_free (metafile->details); - - EEL_CALL_PARENT (GTK_OBJECT_CLASS, destroy, (object)); -} - -static GnomeVFSURI * -construct_private_metafile_vfs_uri (const char *uri) -{ - GnomeVFSResult result; - char *user_directory; - GnomeVFSURI *user_directory_uri, *metafiles_directory_uri, *alternate_uri; - char *escaped_uri, *file_name; - - /* Ensure that the metafiles directory exists. */ - user_directory = nautilus_get_user_directory (); - user_directory_uri = gnome_vfs_uri_new (user_directory); - g_free (user_directory); - - metafiles_directory_uri = gnome_vfs_uri_append_file_name (user_directory_uri, - METAFILES_DIRECTORY_NAME); - gnome_vfs_uri_unref (user_directory_uri); - result = eel_make_directory_and_parents (metafiles_directory_uri, - METAFILES_DIRECTORY_PERMISSIONS); - if (result != GNOME_VFS_OK && result != GNOME_VFS_ERROR_FILE_EXISTS) { - gnome_vfs_uri_unref (metafiles_directory_uri); - return NULL; - } - - /* Construct a file name from the URI. */ - escaped_uri = gnome_vfs_escape_slashes (uri); - file_name = g_strconcat (escaped_uri, ".xml", NULL); - g_free (escaped_uri); - - /* Construct a URI for something in the "metafiles" directory. */ - alternate_uri = gnome_vfs_uri_append_file_name (metafiles_directory_uri, file_name); - gnome_vfs_uri_unref (metafiles_directory_uri); - g_free (file_name); - - return alternate_uri; -} - -static void -nautilus_metafile_set_directory_uri (NautilusMetafile *metafile, const char *directory_uri) -{ - GnomeVFSURI *new_vfs_uri; - - if (eel_strcmp (metafile->details->directory_uri, directory_uri) == 0) { - return; - } - - g_free (metafile->details->directory_uri); - metafile->details->directory_uri = g_strdup (directory_uri); - - new_vfs_uri = gnome_vfs_uri_new (directory_uri); - - if (metafile->details->directory_vfs_uri != NULL) { - gnome_vfs_uri_unref (metafile->details->directory_vfs_uri); - } - metafile->details->directory_vfs_uri = new_vfs_uri; - - if (metafile->details->public_vfs_uri != NULL) { - gnome_vfs_uri_unref (metafile->details->public_vfs_uri); - } - metafile->details->public_vfs_uri = new_vfs_uri == NULL ? NULL - : gnome_vfs_uri_append_file_name (new_vfs_uri, NAUTILUS_METAFILE_NAME_SUFFIX); - - if (metafile->details->private_vfs_uri != NULL) { - gnome_vfs_uri_unref (metafile->details->private_vfs_uri); - } - metafile->details->private_vfs_uri - = construct_private_metafile_vfs_uri (directory_uri); - -} - -static NautilusMetafile * -nautilus_metafile_new (const char *directory_uri) -{ - NautilusMetafile *metafile; - - metafile = NAUTILUS_METAFILE (gtk_object_new (NAUTILUS_TYPE_METAFILE, NULL)); - - nautilus_metafile_set_directory_uri (metafile, directory_uri); - - return metafile; -} - -NautilusMetafile * -nautilus_metafile_get (const char *directory_uri) -{ - NautilusMetafile *metafile; - char *canonical_uri; - - g_return_val_if_fail (directory_uri != NULL, NULL); - - if (metafiles == NULL) { - metafiles = eel_g_hash_table_new_free_at_exit - (g_str_hash, g_str_equal, __FILE__ ": metafiles"); - } - - canonical_uri = nautilus_directory_make_uri_canonical (directory_uri); - - metafile = g_hash_table_lookup (metafiles, canonical_uri); - - if (metafile != NULL) { - bonobo_object_ref (BONOBO_OBJECT (metafile)); - } else { - metafile = nautilus_metafile_new (canonical_uri); - - g_assert (strcmp (metafile->details->directory_uri, canonical_uri) == 0); - - g_hash_table_insert (metafiles, - metafile->details->directory_uri, - metafile); - } - - g_free (canonical_uri); - - return metafile; -} - -/* FIXME - * Right now we only limit the number of conccurrent reads. - * We may want to consider limiting writes as well. - */ - -int num_reads_in_progress; -GList *pending_reads; - -#if 0 -#define DEBUG_METADATA_IO -#endif - -static void -schedule_next_read () -{ - const int kMaxAsyncReads = 10; - - GList* node; - -#ifdef DEBUG_METADATA_IO - g_message ("schedule_next_read: %d pending reads, %d reads in progress", - g_list_length (pending_reads), num_reads_in_progress); -#endif - - if (pending_reads != NULL && num_reads_in_progress <= kMaxAsyncReads) { - node = pending_reads; - pending_reads = g_list_remove_link (pending_reads, node); -#ifdef DEBUG_METADATA_IO - g_message ("schedule_next_read: %s", NAUTILUS_METAFILE (node->data)->details->directory_uri); -#endif - metafile_read_start (node->data); - g_list_free_1 (node); - ++num_reads_in_progress; - } -} - -static void -async_read_start (NautilusMetafile *metafile) -{ - if (metafile->details->is_read - || metafile->details->read_state != NULL) { - return; - } -#ifdef DEBUG_METADATA_IO - g_message ("async_read_start: %s", metafile->details->directory_uri); -#endif - pending_reads = g_list_prepend (pending_reads, metafile); - schedule_next_read (); -} - -static void -async_read_done (NautilusMetafile *metafile) -{ -#ifdef DEBUG_METADATA_IO - g_message ("async_read_done: %s", metafile->details->directory_uri); -#endif - --num_reads_in_progress; - schedule_next_read (); -} - -static void -async_read_cancel (NautilusMetafile *metafile) -{ - GList* node; - -#ifdef DEBUG_METADATA_IO - g_message ("async_read_cancel: %s", metafile->details->directory_uri); -#endif - node = g_list_find (pending_reads, metafile); - - if (node != NULL) { - pending_reads = g_list_remove_link (pending_reads, node); - g_list_free_1 (node); - } - - if (metafile->details->read_state != NULL) { - metafile_read_cancel (metafile); - async_read_done (metafile); - } - -} - -static CORBA_boolean -corba_is_read (PortableServer_Servant servant, - CORBA_Environment *ev) -{ - NautilusMetafile *metafile; - - metafile = NAUTILUS_METAFILE (bonobo_object_from_servant (servant)); - return metafile->details->is_read ? CORBA_TRUE : CORBA_FALSE; -} - -static CORBA_char * -corba_get (PortableServer_Servant servant, - const CORBA_char *file_name, - const CORBA_char *key, - const CORBA_char *default_value, - CORBA_Environment *ev) -{ - NautilusMetafile *metafile; - - char *metadata; - CORBA_char *result; - - metafile = NAUTILUS_METAFILE (bonobo_object_from_servant (servant)); - - metadata = get_file_metadata (metafile, file_name, key, default_value); - - result = CORBA_string_dup (metadata != NULL ? metadata : ""); - - g_free (metadata); - - return result; -} - -static Nautilus_MetadataList * -corba_get_list (PortableServer_Servant servant, - const CORBA_char *file_name, - const CORBA_char *list_key, - const CORBA_char *list_subkey, - CORBA_Environment *ev) -{ - NautilusMetafile *metafile; - - GList *metadata_list; - Nautilus_MetadataList *result; - int len; - int buf_pos; - GList *list_ptr; - - metafile = NAUTILUS_METAFILE (bonobo_object_from_servant (servant)); - - metadata_list = get_file_metadata_list (metafile, file_name, list_key, list_subkey); - - len = g_list_length (metadata_list); - result = Nautilus_MetadataList__alloc (); - result->_maximum = len; - result->_length = len; - result->_buffer = CORBA_sequence_CORBA_string_allocbuf (len); - - /* We allocate our buffer with CORBA calls, so the caller will clean it - * all up if we set release to TRUE. - */ - CORBA_sequence_set_release (result, CORBA_TRUE); - - buf_pos = 0; - list_ptr = metadata_list; - while (list_ptr != NULL) { - result->_buffer [buf_pos] = CORBA_string_dup (list_ptr->data); - list_ptr = g_list_next (list_ptr); - ++buf_pos; - } - - eel_g_list_free_deep (metadata_list); - - return result; -} - -static void -corba_set (PortableServer_Servant servant, - const CORBA_char *file_name, - const CORBA_char *key, - const CORBA_char *default_value, - const CORBA_char *metadata, - CORBA_Environment *ev) -{ - NautilusMetafile *metafile; - - if (eel_str_is_empty (default_value)) { - default_value = NULL; - } - if (eel_str_is_empty (metadata)) { - metadata = NULL; - } - - metafile = NAUTILUS_METAFILE (bonobo_object_from_servant (servant)); - - if (set_file_metadata (metafile, file_name, key, default_value, metadata)) { - call_metafile_changed_for_one_file (metafile, file_name); - } -} - -static void -corba_set_list (PortableServer_Servant servant, - const CORBA_char *file_name, - const CORBA_char *list_key, - const CORBA_char *list_subkey, - const Nautilus_MetadataList *list, - CORBA_Environment *ev) -{ - NautilusMetafile *metafile; - - GList *metadata_list; - CORBA_unsigned_long buf_pos; - - metafile = NAUTILUS_METAFILE (bonobo_object_from_servant (servant)); - - metadata_list = NULL; - for (buf_pos = 0; buf_pos < list->_length; ++buf_pos) { - metadata_list = g_list_prepend (metadata_list, list->_buffer [buf_pos]); - } - metadata_list = g_list_reverse (metadata_list); - - if (set_file_metadata_list (metafile, file_name, list_key, list_subkey, metadata_list)) { - call_metafile_changed_for_one_file (metafile, file_name); - } - - g_list_free (metadata_list); -} - -static void -corba_copy (PortableServer_Servant servant, - const CORBA_char *source_file_name, - const Nautilus_URI destination_directory_uri, - const CORBA_char *destination_file_name, - CORBA_Environment *ev) -{ - NautilusMetafile *source_metafile; - NautilusMetafile *destination_metafile; - - source_metafile = NAUTILUS_METAFILE (bonobo_object_from_servant (servant)); - - destination_metafile = nautilus_metafile_get (destination_directory_uri); - - copy_file_metadata (source_metafile, source_file_name, - destination_metafile, destination_file_name); - - bonobo_object_unref (BONOBO_OBJECT (destination_metafile)); -} - -static void -corba_remove (PortableServer_Servant servant, - const CORBA_char *file_name, - CORBA_Environment *ev) -{ - NautilusMetafile *metafile; - - metafile = NAUTILUS_METAFILE (bonobo_object_from_servant (servant)); - - remove_file_metadata (metafile, file_name); -} - -static void -corba_rename (PortableServer_Servant servant, - const CORBA_char *old_file_name, - const CORBA_char *new_file_name, - CORBA_Environment *ev) -{ - NautilusMetafile *metafile; - - metafile = NAUTILUS_METAFILE (bonobo_object_from_servant (servant)); - - rename_file_metadata (metafile, old_file_name, new_file_name); -} - -static void -corba_rename_directory (PortableServer_Servant servant, - const CORBA_char *new_directory_uri, - CORBA_Environment *ev) -{ - NautilusMetafile *metafile; - - metafile = NAUTILUS_METAFILE (bonobo_object_from_servant (servant)); - - nautilus_metafile_set_directory_uri (metafile, new_directory_uri); -} - -static GList * -find_monitor_node (GList *monitors, const Nautilus_MetafileMonitor monitor) -{ - GList *node; - CORBA_Environment ev; - Nautilus_MetafileMonitor cur_monitor; - - CORBA_exception_init (&ev); - - for (node = monitors; node != NULL; node = node->next) { - cur_monitor = node->data; - if (CORBA_Object_is_equivalent (cur_monitor, monitor, &ev)) { - break; - } - } - - /* FIXME bugzilla.eazel.com 6664: examine ev for errors */ - - CORBA_exception_free (&ev); - - return node; -} - -static void -corba_register_monitor (PortableServer_Servant servant, - const Nautilus_MetafileMonitor monitor, - CORBA_Environment *ev) -{ - NautilusMetafile *metafile; - - metafile = NAUTILUS_METAFILE (bonobo_object_from_servant (servant)); - - g_return_if_fail (find_monitor_node (metafile->details->monitors, monitor) == NULL); - - metafile->details->monitors = g_list_prepend (metafile->details->monitors, (gpointer) CORBA_Object_duplicate (monitor, ev)); - - async_read_start (metafile); -} - -static void -corba_unregister_monitor (PortableServer_Servant servant, - const Nautilus_MetafileMonitor monitor, - CORBA_Environment *ev) -{ - NautilusMetafile *metafile; - GList *node; - - metafile = NAUTILUS_METAFILE (bonobo_object_from_servant (servant)); - - node = find_monitor_node (metafile->details->monitors, monitor); - - g_return_if_fail (node != NULL); - - metafile->details->monitors = g_list_remove_link (metafile->details->monitors, node); - - CORBA_Object_release (node->data, ev); - g_list_free_1 (node); -} - -static void -nautilus_metafile_notify_metafile_ready (NautilusMetafile *metafile) -{ - GList *node; - CORBA_Environment ev; - Nautilus_MetafileMonitor monitor; - - CORBA_exception_init (&ev); - - for (node = metafile->details->monitors; node != NULL; node = node->next) { - monitor = node->data; - Nautilus_MetafileMonitor_metafile_ready (monitor, &ev); - /* FIXME bugzilla.eazel.com 6664: examine ev for errors */ - } - - CORBA_exception_free (&ev); -} - -static void -call_metafile_changed (NautilusMetafile *metafile, - const Nautilus_FileNameList *file_names) -{ - GList *node; - CORBA_Environment ev; - Nautilus_MetafileMonitor monitor; - - CORBA_exception_init (&ev); - - for (node = metafile->details->monitors; node != NULL; node = node->next) { - monitor = node->data; - Nautilus_MetafileMonitor_metafile_changed (monitor, file_names, &ev); - /* FIXME bugzilla.eazel.com 6664: examine ev for errors */ - } - - CORBA_exception_free (&ev); -} -#if 0 - -static void -file_list_filler_ghfunc (gpointer key, - gpointer value, - gpointer user_data) -{ - Nautilus_FileNameList *file_names; - - file_names = user_data; - - file_names->_buffer [file_names->_length] = key; - - ++file_names->_length; -} - -void -call_metafile_changed_for_all_files_mentioned_in_metafile (NautilusMetafile *metafile) -{ - CORBA_unsigned_long len; - Nautilus_FileNameList file_names; - - len = g_hash_table_size (metafile->details->node_hash); - - if (len > 0) { - file_names._maximum = len; - file_names._length = 0; - file_names._buffer = g_new (CORBA_char *, len); - - g_hash_table_foreach (metafile->details->node_hash, - file_list_filler_ghfunc, - &file_names); - - call_metafile_changed (metafile, &file_names); - - g_free (file_names._buffer); - } -} -#endif - -static void -call_metafile_changed_for_one_file (NautilusMetafile *metafile, - const CORBA_char *file_name) -{ - Nautilus_FileNameList file_names = {0}; - - file_names._maximum = 1; - file_names._length = 1; - file_names._buffer = (CORBA_char **) &file_name; - - call_metafile_changed (metafile, &file_names); -} - -typedef struct { - gboolean is_list; - union { - char *string; - GList *string_list; - } value; - char *default_value; -} MetadataValue; - -static char * -get_metadata_from_node (xmlNode *node, - const char *key, - const char *default_metadata) -{ - xmlChar *property; - char *result; - - g_return_val_if_fail (key != NULL, NULL); - g_return_val_if_fail (key[0] != '\0', NULL); - - property = xmlGetProp (node, key); - if (property == NULL) { - result = g_strdup (default_metadata); - } else { - result = g_strdup (property); - } - xmlFree (property); - - return result; -} - -static GList * -get_metadata_list_from_node (xmlNode *node, - const char *list_key, - const char *list_subkey) -{ - return eel_xml_get_property_for_children - (node, list_key, list_subkey); -} - -static xmlNode * -create_metafile_root (NautilusMetafile *metafile) -{ - xmlNode *root; - - if (metafile->details->xml == NULL) { - nautilus_metafile_set_metafile_contents (metafile, xmlNewDoc (METAFILE_XML_VERSION)); - } - root = xmlDocGetRootElement (metafile->details->xml); - if (root == NULL) { - root = xmlNewDocNode (metafile->details->xml, NULL, "directory", NULL); - xmlDocSetRootElement (metafile->details->xml, root); - } - - return root; -} - -static xmlNode * -get_file_node (NautilusMetafile *metafile, - const char *file_name, - gboolean create) -{ - GHashTable *hash; - xmlNode *root, *node; - - g_assert (NAUTILUS_IS_METAFILE (metafile)); - - hash = metafile->details->node_hash; - node = g_hash_table_lookup (hash, file_name); - if (node != NULL) { - return node; - } - - if (create) { - root = create_metafile_root (metafile); - node = xmlNewChild (root, NULL, "file", NULL); - xmlSetProp (node, "name", file_name); - g_hash_table_insert (hash, xmlMemStrdup (file_name), node); - return node; - } - - return NULL; -} - -static char * -get_metadata_string_from_metafile (NautilusMetafile *metafile, - const char *file_name, - const char *key, - const char *default_metadata) -{ - xmlNode *node; - - node = get_file_node (metafile, file_name, FALSE); - return get_metadata_from_node (node, key, default_metadata); -} - -static GList * -get_metadata_list_from_metafile (NautilusMetafile *metafile, - const char *file_name, - const char *list_key, - const char *list_subkey) -{ - xmlNode *node; - - node = get_file_node (metafile, file_name, FALSE); - return get_metadata_list_from_node (node, list_key, list_subkey); -} - -static gboolean -set_metadata_string_in_metafile (NautilusMetafile *metafile, - const char *file_name, - const char *key, - const char *default_metadata, - const char *metadata) -{ - char *old_metadata; - gboolean old_metadata_matches; - const char *value; - xmlNode *node; - xmlAttr *property_node; - - /* If the data in the metafile is already correct, do nothing. */ - old_metadata = get_file_metadata - (metafile, file_name, key, default_metadata); - - old_metadata_matches = eel_strcmp (old_metadata, metadata) == 0; - g_free (old_metadata); - if (old_metadata_matches) { - return FALSE; - } - - /* Data that matches the default is represented in the tree by - * the lack of an attribute. - */ - if (eel_strcmp (default_metadata, metadata) == 0) { - value = NULL; - } else { - value = metadata; - } - - /* Get or create the node. */ - node = get_file_node (metafile, file_name, value != NULL); - - /* Add or remove a property node. */ - if (node != NULL) { - property_node = xmlSetProp (node, key, value); - if (value == NULL) { - xmlRemoveProp (property_node); - } - } - - /* Since we changed the tree, arrange for it to be written. */ - directory_request_write_metafile (metafile); - return TRUE; -} - -static gboolean -set_metadata_list_in_metafile (NautilusMetafile *metafile, - const char *file_name, - const char *list_key, - const char *list_subkey, - GList *list) -{ - xmlNode *node, *child, *next; - gboolean changed; - GList *p; - xmlChar *property; - - /* Get or create the node. */ - node = get_file_node (metafile, file_name, list != NULL); - - /* Work with the list. */ - changed = FALSE; - if (node == NULL) { - g_assert (list == NULL); - } else { - p = list; - - /* Remove any nodes except the ones we expect. */ - for (child = eel_xml_get_children (node); - child != NULL; - child = next) { - - next = child->next; - if (strcmp (child->name, list_key) == 0) { - property = xmlGetProp (child, list_subkey); - if (property != NULL && p != NULL - && strcmp (property, (char *) p->data) == 0) { - p = p->next; - } else { - xmlUnlinkNode (child); - xmlFreeNode (child); - changed = TRUE; - } - xmlFree (property); - } - } - - /* Add any additional nodes needed. */ - for (; p != NULL; p = p->next) { - child = xmlNewChild (node, NULL, list_key, NULL); - xmlSetProp (child, list_subkey, p->data); - changed = TRUE; - } - } - - if (!changed) { - return FALSE; - } - - directory_request_write_metafile (metafile); - return TRUE; -} - -static MetadataValue * -metadata_value_new (const char *default_metadata, const char *metadata) -{ - MetadataValue *value; - - value = g_new0 (MetadataValue, 1); - - value->default_value = g_strdup (default_metadata); - value->value.string = g_strdup (metadata); - - return value; -} - -static MetadataValue * -metadata_value_new_list (GList *metadata) -{ - MetadataValue *value; - - value = g_new0 (MetadataValue, 1); - - value->is_list = TRUE; - value->value.string_list = eel_g_str_list_copy (metadata); - - return value; -} - -static void -metadata_value_destroy (MetadataValue *value) -{ - if (value == NULL) { - return; - } - - if (!value->is_list) { - g_free (value->value.string); - } else { - eel_g_list_free_deep (value->value.string_list); - } - g_free (value->default_value); - g_free (value); -} - -static gboolean -metadata_value_equal (const MetadataValue *value_a, - const MetadataValue *value_b) -{ - if (value_a->is_list != value_b->is_list) { - return FALSE; - } - - if (!value_a->is_list) { - return eel_strcmp (value_a->value.string, - value_b->value.string) == 0 - && eel_strcmp (value_a->default_value, - value_b->default_value) == 0; - } else { - g_assert (value_a->default_value == NULL); - g_assert (value_b->default_value == NULL); - - return eel_g_str_list_equal - (value_a->value.string_list, - value_b->value.string_list); - } -} - -static gboolean -set_metadata_in_metafile (NautilusMetafile *metafile, - const char *file_name, - const char *key, - const char *subkey, - const MetadataValue *value) -{ - gboolean changed; - - if (!value->is_list) { - g_assert (subkey == NULL); - changed = set_metadata_string_in_metafile - (metafile, file_name, key, - value->default_value, - value->value.string); - } else { - g_assert (value->default_value == NULL); - changed = set_metadata_list_in_metafile - (metafile, file_name, key, subkey, - value->value.string_list); - } - - return changed; -} - -static char * -get_metadata_string_from_table (NautilusMetafile *metafile, - const char *file_name, - const char *key, - const char *default_metadata) -{ - GHashTable *directory_table, *file_table; - MetadataValue *value; - - /* Get the value from the hash table. */ - directory_table = metafile->details->changes; - file_table = directory_table == NULL ? NULL - : g_hash_table_lookup (directory_table, file_name); - value = file_table == NULL ? NULL - : g_hash_table_lookup (file_table, key); - if (value == NULL) { - return g_strdup (default_metadata); - } - - /* Convert it to a string. */ - g_assert (!value->is_list); - if (eel_strcmp (value->value.string, value->default_value) == 0) { - return g_strdup (default_metadata); - } - return g_strdup (value->value.string); -} - -static GList * -get_metadata_list_from_table (NautilusMetafile *metafile, - const char *file_name, - const char *key, - const char *subkey) -{ - GHashTable *directory_table, *file_table; - char *combined_key; - MetadataValue *value; - - /* Get the value from the hash table. */ - directory_table = metafile->details->changes; - file_table = directory_table == NULL ? NULL - : g_hash_table_lookup (directory_table, file_name); - if (file_table == NULL) { - return NULL; - } - combined_key = g_strconcat (key, "/", subkey, NULL); - value = g_hash_table_lookup (file_table, combined_key); - g_free (combined_key); - if (value == NULL) { - return NULL; - } - - /* Copy the list and return it. */ - g_assert (value->is_list); - return eel_g_str_list_copy (value->value.string_list); -} - -static guint -str_or_null_hash (gconstpointer str) -{ - return str == NULL ? 0 : g_str_hash (str); -} - -static gboolean -str_or_null_equal (gconstpointer str_a, gconstpointer str_b) -{ - if (str_a == NULL) { - return str_b == NULL; - } - if (str_b == NULL) { - return FALSE; - } - return g_str_equal (str_a, str_b); -} - -static gboolean -set_metadata_eat_value (NautilusMetafile *metafile, - const char *file_name, - const char *key, - const char *subkey, - MetadataValue *value) -{ - GHashTable *directory_table, *file_table; - gboolean changed; - char *combined_key; - MetadataValue *old_value; - - if (metafile->details->is_read) { - changed = set_metadata_in_metafile - (metafile, file_name, key, subkey, value); - metadata_value_destroy (value); - } else { - /* Create hash table only when we need it. - * We'll destroy it when we finish reading the metafile. - */ - directory_table = metafile->details->changes; - if (directory_table == NULL) { - directory_table = g_hash_table_new - (str_or_null_hash, str_or_null_equal); - metafile->details->changes = directory_table; - } - file_table = g_hash_table_lookup (directory_table, file_name); - if (file_table == NULL) { - file_table = g_hash_table_new (g_str_hash, g_str_equal); - g_hash_table_insert (directory_table, - g_strdup (file_name), file_table); - } - - /* Find the entry in the hash table. */ - if (subkey == NULL) { - combined_key = g_strdup (key); - } else { - combined_key = g_strconcat (key, "/", subkey, NULL); - } - old_value = g_hash_table_lookup (file_table, combined_key); - - /* Put the change into the hash. Delete the old change. */ - changed = old_value == NULL || !metadata_value_equal (old_value, value); - if (changed) { - g_hash_table_insert (file_table, combined_key, value); - if (old_value != NULL) { - /* The hash table keeps the old key. */ - g_free (combined_key); - metadata_value_destroy (old_value); - } - } else { - g_free (combined_key); - metadata_value_destroy (value); - } - } - - return changed; -} - -static void -free_file_table_entry (gpointer key, gpointer value, gpointer user_data) -{ - g_assert (user_data == NULL); - - g_free (key); - metadata_value_destroy (value); -} - -static void -free_directory_table_entry (gpointer key, gpointer value, gpointer user_data) -{ - g_assert (user_data == NULL); - g_assert (value != NULL); - - g_free (key); - g_hash_table_foreach (value, free_file_table_entry, NULL); - g_hash_table_destroy (value); -} - -static void -destroy_metadata_changes_hash_table (GHashTable *directory_table) -{ - if (directory_table == NULL) { - return; - } - g_hash_table_foreach (directory_table, free_directory_table_entry, NULL); - g_hash_table_destroy (directory_table); -} - -static void -destroy_xml_string_key (gpointer key, gpointer value, gpointer user_data) -{ - g_assert (key != NULL); - g_assert (user_data == NULL); - g_assert (value != NULL); - - xmlFree (key); -} - -static void -metafile_free_metadata (NautilusMetafile *metafile) -{ - g_return_if_fail (NAUTILUS_IS_METAFILE (metafile)); - - g_hash_table_foreach (metafile->details->node_hash, - destroy_xml_string_key, NULL); - xmlFreeDoc (metafile->details->xml); - destroy_metadata_changes_hash_table (metafile->details->changes); -} - -static char * -get_file_metadata (NautilusMetafile *metafile, - const char *file_name, - const char *key, - const char *default_metadata) -{ - g_return_val_if_fail (NAUTILUS_IS_METAFILE (metafile), NULL); - g_return_val_if_fail (!eel_str_is_empty (file_name), NULL); - g_return_val_if_fail (!eel_str_is_empty (key), NULL); - - if (metafile->details->is_read) { - return get_metadata_string_from_metafile - (metafile, file_name, key, default_metadata); - } else { - return get_metadata_string_from_table - (metafile, file_name, key, default_metadata); - } -} - -static GList * -get_file_metadata_list (NautilusMetafile *metafile, - const char *file_name, - const char *list_key, - const char *list_subkey) -{ - g_return_val_if_fail (NAUTILUS_IS_METAFILE (metafile), NULL); - g_return_val_if_fail (!eel_str_is_empty (file_name), NULL); - g_return_val_if_fail (!eel_str_is_empty (list_key), NULL); - g_return_val_if_fail (!eel_str_is_empty (list_subkey), NULL); - - if (metafile->details->is_read) { - return get_metadata_list_from_metafile - (metafile, file_name, list_key, list_subkey); - } else { - return get_metadata_list_from_table - (metafile, file_name, list_key, list_subkey); - } -} - -static gboolean -set_file_metadata (NautilusMetafile *metafile, - const char *file_name, - const char *key, - const char *default_metadata, - const char *metadata) -{ - MetadataValue *value; - - g_return_val_if_fail (NAUTILUS_IS_METAFILE (metafile), FALSE); - g_return_val_if_fail (!eel_str_is_empty (file_name), FALSE); - g_return_val_if_fail (!eel_str_is_empty (key), FALSE); - - if (metafile->details->is_read) { - return set_metadata_string_in_metafile (metafile, file_name, key, - default_metadata, metadata); - } else { - value = metadata_value_new (default_metadata, metadata); - return set_metadata_eat_value (metafile, file_name, - key, NULL, value); - } -} - -static gboolean -set_file_metadata_list (NautilusMetafile *metafile, - const char *file_name, - const char *list_key, - const char *list_subkey, - GList *list) -{ - MetadataValue *value; - - g_return_val_if_fail (NAUTILUS_IS_METAFILE (metafile), FALSE); - g_return_val_if_fail (!eel_str_is_empty (file_name), FALSE); - g_return_val_if_fail (!eel_str_is_empty (list_key), FALSE); - g_return_val_if_fail (!eel_str_is_empty (list_subkey), FALSE); - - if (metafile->details->is_read) { - return set_metadata_list_in_metafile (metafile, file_name, - list_key, list_subkey, list); - } else { - value = metadata_value_new_list (list); - return set_metadata_eat_value (metafile, file_name, - list_key, list_subkey, value); - } -} - -static char * -metafile_get_file_uri (NautilusMetafile *metafile, - const char *file_name) -{ - GnomeVFSURI *file_uri; - char *result; - - g_return_val_if_fail (NAUTILUS_IS_METAFILE (metafile), NULL); - g_return_val_if_fail (file_name != NULL, NULL); - - result = NULL; - - g_assert (metafile->details->directory_vfs_uri != NULL); - - file_uri = gnome_vfs_uri_append_string (metafile->details->directory_vfs_uri, file_name); - - if (file_uri != NULL) { - result = gnome_vfs_uri_to_string (file_uri, GNOME_VFS_URI_HIDE_NONE); - gnome_vfs_uri_unref (file_uri); - } - - return result; -} - -static void -rename_file_metadata (NautilusMetafile *metafile, - const char *old_file_name, - const char *new_file_name) -{ - gboolean found; - gpointer key, value; - xmlNode *file_node; - GHashTable *hash; - char *old_file_uri, *new_file_uri; - - g_return_if_fail (NAUTILUS_IS_METAFILE (metafile)); - g_return_if_fail (old_file_name != NULL); - g_return_if_fail (new_file_name != NULL); - - remove_file_metadata (metafile, new_file_name); - - if (metafile->details->is_read) { - /* Move data in XML document if present. */ - hash = metafile->details->node_hash; - found = g_hash_table_lookup_extended - (hash, old_file_name, &key, &value); - if (found) { - g_assert (strcmp ((const char *) key, old_file_name) == 0); - file_node = value; - g_hash_table_remove (hash, - old_file_name); - xmlFree (key); - g_hash_table_insert (hash, - xmlMemStrdup (new_file_name), value); - xmlSetProp (file_node, "name", new_file_name); - directory_request_write_metafile (metafile); - } - } else { - /* Move data in hash table. */ - /* FIXME: If there's data for this file in the - * metafile on disk, this doesn't arrange for that - * data to be moved to the new name. - */ - hash = metafile->details->changes; - found = g_hash_table_lookup_extended - (hash, old_file_name, &key, &value); - if (found) { - g_hash_table_remove (hash, old_file_name); - g_free (key); - g_hash_table_insert (hash, g_strdup (new_file_name), value); - } - } - - /* Rename the thumbnails for the file, if any. */ - old_file_uri = metafile_get_file_uri (metafile, old_file_name); - new_file_uri = metafile_get_file_uri (metafile, new_file_name); - nautilus_update_thumbnail_file_renamed (old_file_uri, new_file_uri); - g_free (old_file_uri); - g_free (new_file_uri); -} - -typedef struct { - NautilusMetafile *metafile; - const char *file_name; -} ChangeContext; - -static void -apply_one_change (gpointer key, gpointer value, gpointer callback_data) -{ - ChangeContext *context; - const char *hash_table_key, *separator, *metadata_key, *subkey; - char *key_prefix; - - g_assert (key != NULL); - g_assert (value != NULL); - g_assert (callback_data != NULL); - - context = callback_data; - - /* Break the key in half. */ - hash_table_key = key; - separator = strchr (hash_table_key, '/'); - if (separator == NULL) { - key_prefix = NULL; - metadata_key = hash_table_key; - subkey = NULL; - } else { - key_prefix = g_strndup (hash_table_key, separator - hash_table_key); - metadata_key = key_prefix; - subkey = separator + 1; - } - - /* Set the metadata. */ - set_metadata_in_metafile (context->metafile, context->file_name, - metadata_key, subkey, value); - g_free (key_prefix); -} - -static void -apply_file_changes (NautilusMetafile *metafile, - const char *file_name, - GHashTable *changes) -{ - ChangeContext context; - - g_assert (NAUTILUS_IS_METAFILE (metafile)); - g_assert (file_name != NULL); - g_assert (changes != NULL); - - context.metafile = metafile; - context.file_name = file_name; - - g_hash_table_foreach (changes, apply_one_change, &context); -} - -static void -apply_one_file_changes (gpointer key, gpointer value, gpointer callback_data) -{ - apply_file_changes (callback_data, key, value); - g_hash_table_destroy (value); -} - -static void -nautilus_metafile_apply_pending_changes (NautilusMetafile *metafile) -{ - if (metafile->details->changes == NULL) { - return; - } - g_hash_table_foreach (metafile->details->changes, - apply_one_file_changes, metafile); - g_hash_table_destroy (metafile->details->changes); - metafile->details->changes = NULL; -} - -static void -copy_file_metadata (NautilusMetafile *source_metafile, - const char *source_file_name, - NautilusMetafile *destination_metafile, - const char *destination_file_name) -{ - xmlNodePtr source_node, node, root; - GHashTable *hash, *changes; - - g_return_if_fail (NAUTILUS_IS_METAFILE (source_metafile)); - g_return_if_fail (source_file_name != NULL); - g_return_if_fail (NAUTILUS_IS_METAFILE (destination_metafile)); - g_return_if_fail (destination_file_name != NULL); - - /* FIXME bugzilla.eazel.com 3343: This does not properly - * handle the case where we don't have the source metadata yet - * since it's not read in. - */ - - remove_file_metadata - (destination_metafile, destination_file_name); - g_assert (get_file_node (destination_metafile, destination_file_name, FALSE) == NULL); - - source_node = get_file_node (source_metafile, source_file_name, FALSE); - if (source_node != NULL) { - if (destination_metafile->details->is_read) { - node = xmlCopyNode (source_node, TRUE); - root = create_metafile_root (destination_metafile); - xmlAddChild (root, node); - xmlSetProp (node, "name", destination_file_name); - g_hash_table_insert (destination_metafile->details->node_hash, - xmlMemStrdup (destination_file_name), node); - } else { - /* FIXME bugzilla.eazel.com 6526: Copying data into a destination - * where the metafile was not yet read is not implemented. - */ - g_warning ("not copying metadata"); - } - } - - hash = source_metafile->details->changes; - if (hash != NULL) { - changes = g_hash_table_lookup (hash, source_file_name); - if (changes != NULL) { - apply_file_changes (destination_metafile, - destination_file_name, - changes); - } - } - - /* FIXME: Do we want to copy the thumbnail here like in the - * rename and remove cases? - */ -} - -static void -remove_file_metadata (NautilusMetafile *metafile, - const char *file_name) -{ - gboolean found; - gpointer key, value; - xmlNode *file_node; - GHashTable *hash; - char *file_uri; - - g_return_if_fail (NAUTILUS_IS_METAFILE (metafile)); - g_return_if_fail (file_name != NULL); - - if (metafile->details->is_read) { - /* Remove data in XML document if present. */ - hash = metafile->details->node_hash; - found = g_hash_table_lookup_extended - (hash, file_name, &key, &value); - if (found) { - g_assert (strcmp ((const char *) key, file_name) == 0); - file_node = value; - g_hash_table_remove (hash, - file_name); - xmlFree (key); - eel_xml_remove_node (file_node); - xmlFreeNode (file_node); - directory_request_write_metafile (metafile); - } - } else { - /* Remove data from hash table. */ - /* FIXME: If there's data for this file on the - * metafile on disk, this does not arrange for it to - * be removed when the metafile is later read. - */ - hash = metafile->details->changes; - if (hash != NULL) { - found = g_hash_table_lookup_extended - (hash, file_name, &key, &value); - if (found) { - g_hash_table_remove (hash, file_name); - g_free (key); - metadata_value_destroy (value); - } - } - } - - /* Delete the thumbnails for the file, if any. */ - file_uri = metafile_get_file_uri (metafile, file_name); - nautilus_remove_thumbnail_for_file (file_uri); - g_free (file_uri); -} - -static void -nautilus_metafile_set_metafile_contents (NautilusMetafile *metafile, - xmlDocPtr metafile_contents) -{ - GHashTable *hash; - xmlNodePtr node; - xmlChar *name; - - g_return_if_fail (NAUTILUS_IS_METAFILE (metafile)); - g_return_if_fail (metafile->details->xml == NULL); - - if (metafile_contents == NULL) { - return; - } - - metafile->details->xml = metafile_contents; - - /* Populate the node hash table. */ - hash = metafile->details->node_hash; - for (node = eel_xml_get_root_children (metafile_contents); - node != NULL; node = node->next) { - if (strcmp (node->name, "file") == 0) { - name = xmlGetProp (node, "name"); - if (g_hash_table_lookup (hash, name) != NULL) { - xmlFree (name); - /* FIXME: Should we delete duplicate nodes as we discover them? */ - } else { - g_hash_table_insert (hash, name, node); - } - } - } -} - - -static void -metafile_read_cancel (NautilusMetafile *metafile) -{ - if (metafile->details->read_state != NULL) { - if (metafile->details->read_state->handle != NULL) { - eel_read_file_cancel (metafile->details->read_state->handle); - } - if (metafile->details->read_state->get_file_info_handle != NULL) { - gnome_vfs_async_cancel (metafile->details->read_state->get_file_info_handle); - } - g_free (metafile->details->read_state); - metafile->details->read_state = NULL; - } -} - -static gboolean -can_use_public_metafile (NautilusMetafile *metafile) -{ - NautilusSpeedTradeoffValue preference_value; - - g_return_val_if_fail (NAUTILUS_IS_METAFILE (metafile), FALSE); - - if (metafile->details->public_vfs_uri == NULL) { - return FALSE; - } - - preference_value = nautilus_preferences_get_integer (NAUTILUS_PREFERENCES_USE_PUBLIC_METADATA); - - if (preference_value == NAUTILUS_SPEED_TRADEOFF_ALWAYS) { - return TRUE; - } - - if (preference_value == NAUTILUS_SPEED_TRADEOFF_NEVER) { - return FALSE; - } - - g_assert (preference_value == NAUTILUS_SPEED_TRADEOFF_LOCAL_ONLY); - - return metafile->details->directory_vfs_uri == NULL || - gnome_vfs_uri_is_local (metafile->details->directory_vfs_uri); -} - -static void -metafile_read_mark_done (NautilusMetafile *metafile) -{ - g_free (metafile->details->read_state); - metafile->details->read_state = NULL; - - metafile->details->is_read = TRUE; - - /* Move over the changes to the metafile that were in the hash table. */ - nautilus_metafile_apply_pending_changes (metafile); - - /* Tell change-watchers that we have update information. */ - nautilus_metafile_notify_metafile_ready (metafile); - - async_read_done (metafile); -} - -static void -metafile_read_done (NautilusMetafile *metafile) -{ - metafile_read_mark_done (metafile); -} - -static void -metafile_read_try_public_metafile (NautilusMetafile *metafile) -{ - metafile->details->read_state->use_public_metafile = TRUE; - metafile_read_restart (metafile); -} - -static void -metafile_read_check_for_directory_callback (GnomeVFSAsyncHandle *handle, - GList *results, - gpointer callback_data) -{ - NautilusMetafile *metafile; - GnomeVFSGetFileInfoResult *result; - - metafile = NAUTILUS_METAFILE (callback_data); - - g_assert (metafile->details->read_state->get_file_info_handle == handle); - g_assert (eel_g_list_exactly_one_item (results)); - - metafile->details->read_state->get_file_info_handle = NULL; - - result = results->data; - - if (result->result == GNOME_VFS_OK - && ((result->file_info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_TYPE) != 0) - && result->file_info->type == GNOME_VFS_FILE_TYPE_DIRECTORY) { - /* Is a directory. */ - metafile_read_try_public_metafile (metafile); - } else { - /* Not a directory. */ - metafile_read_done (metafile); - } -} - -static void -metafile_read_check_for_directory (NautilusMetafile *metafile) -{ - GList fake_list; - - /* We only get here if the public metafile is in question, - * which in turn only happens if the URI is one that gnome-vfs - * can handle. - */ - g_assert (metafile->details->directory_vfs_uri != NULL); - - /* We have to do a get_info call to check if this a directory. */ - fake_list.data = metafile->details->directory_vfs_uri; - fake_list.next = NULL; - fake_list.prev = NULL; - gnome_vfs_async_get_file_info - (&metafile->details->read_state->get_file_info_handle, - &fake_list, - GNOME_VFS_FILE_INFO_DEFAULT, - metafile_read_check_for_directory_callback, - metafile); -} - -static void -metafile_read_failed (NautilusMetafile *metafile) -{ - NautilusFile *file; - gboolean need_directory_check, is_directory; - - g_assert (NAUTILUS_IS_METAFILE (metafile)); - - metafile->details->read_state->handle = NULL; - - if (!metafile->details->read_state->use_public_metafile - && can_use_public_metafile (metafile)) { - /* The goal here is to read the real metafile, but - * only if the directory is actually a directory. - */ - - /* First, check if we already know if it a directory. */ - file = nautilus_file_get (metafile->details->directory_uri); - if (file == NULL || file->details->is_gone) { - need_directory_check = FALSE; - is_directory = FALSE; - } else if (file->details->info == NULL) { - need_directory_check = TRUE; - is_directory = TRUE; - } else { - need_directory_check = FALSE; - is_directory = nautilus_file_is_directory (file); - } - nautilus_file_unref (file); - - /* Do the directory check if we don't know. */ - if (need_directory_check) { - metafile_read_check_for_directory (metafile); - return; - } - - /* Try for the public metafile if it is a directory. */ - if (is_directory) { - metafile_read_try_public_metafile (metafile); - return; - } - } - - metafile_read_done (metafile); -} - -static void -metafile_read_done_callback (GnomeVFSResult result, - GnomeVFSFileSize file_size, - char *file_contents, - gpointer callback_data) -{ - NautilusMetafile *metafile; - int size; - char *buffer; - - metafile = NAUTILUS_METAFILE (callback_data); - g_assert (metafile->details->xml == NULL); - - if (result != GNOME_VFS_OK) { - g_assert (file_contents == NULL); - metafile_read_failed (metafile); - return; - } - - size = file_size; - if ((GnomeVFSFileSize) size != file_size) { - g_free (file_contents); - metafile_read_failed (metafile); - return; - } - - /* The gnome-xml parser requires a zero-terminated array. */ - buffer = g_realloc (file_contents, size + 1); - buffer[size] = '\0'; - nautilus_metafile_set_metafile_contents (metafile, - xmlParseMemory (buffer, size)); - g_free (buffer); - - metafile_read_done (metafile); -} - -static void -metafile_read_restart (NautilusMetafile *metafile) -{ - char *text_uri; - - text_uri = gnome_vfs_uri_to_string - (metafile->details->read_state->use_public_metafile - ? metafile->details->public_vfs_uri - : metafile->details->private_vfs_uri, - GNOME_VFS_URI_HIDE_NONE); - - metafile->details->read_state->handle = eel_read_entire_file_async - (text_uri, metafile_read_done_callback, metafile); - - g_free (text_uri); -} - -static gboolean -allow_metafile (NautilusMetafile *metafile) -{ - const char *uri; - - g_assert (NAUTILUS_IS_METAFILE (metafile)); - - /* Note that this inhibits both reading and writing metadata - * completely. In the future we may want to inhibit writing to - * the real directory while allowing parallel-directory - * metadata. - */ - - /* For now, hard-code these schemes. Perhaps we should - * hardcode the schemes that are good for metadata instead of - * the schemes that are bad for it. - */ - /* FIXME bugzilla.eazel.com 2434: - * We need to handle this in a better way. Perhaps a - * better way can wait until we have support for metadata - * access inside gnome-vfs. - */ - uri = metafile->details->directory_uri; - if (nautilus_is_search_uri (uri) - || eel_istr_has_prefix (uri, "ghelp:") - || eel_istr_has_prefix (uri, "gnome-help:") - || eel_istr_has_prefix (uri, "help:") - || eel_istr_has_prefix (uri, "info:") - || eel_istr_has_prefix (uri, "man:") - || eel_istr_has_prefix (uri, "pipe:") - ) { - return FALSE; - } - - return TRUE; -} - -static void -metafile_read_start (NautilusMetafile *metafile) -{ - g_assert (NAUTILUS_IS_METAFILE (metafile)); - - if (metafile->details->is_read - || metafile->details->read_state != NULL) { - return; - } - - if (!allow_metafile (metafile)) { - metafile_read_mark_done (metafile); - } else { - metafile->details->read_state = g_new0 (MetafileReadState, 1); - metafile_read_restart (metafile); - } -} - -static void -metafile_write_done (NautilusMetafile *metafile) -{ - if (metafile->details->write_state->write_again) { - metafile_write_start (metafile); - return; - } - - xmlFree (metafile->details->write_state->buffer); - g_free (metafile->details->write_state); - metafile->details->write_state = NULL; - bonobo_object_unref (BONOBO_OBJECT (metafile)); -} - -static void -metafile_write_failed (NautilusMetafile *metafile) -{ - if (metafile->details->write_state->use_public_metafile) { - metafile->details->write_state->use_public_metafile = FALSE; - metafile_write_start (metafile); - return; - } - - metafile_write_done (metafile); -} - -static void -metafile_write_failure_close_callback (GnomeVFSAsyncHandle *handle, - GnomeVFSResult result, - gpointer callback_data) -{ - NautilusMetafile *metafile; - - metafile = NAUTILUS_METAFILE (callback_data); - - metafile_write_failed (metafile); -} - -static void -metafile_write_success_close_callback (GnomeVFSAsyncHandle *handle, - GnomeVFSResult result, - gpointer callback_data) -{ - NautilusMetafile *metafile; - - metafile = NAUTILUS_METAFILE (callback_data); - g_assert (metafile->details->write_state->handle == NULL); - - if (result != GNOME_VFS_OK) { - metafile_write_failed (metafile); - return; - } - - /* Now that we have finished writing, it is time to delete the - * private file if we wrote the public one. - */ - if (metafile->details->write_state->use_public_metafile) { - /* A synchronous unlink is OK here because the private - * metafiles are local, so an unlink is very fast. - */ - gnome_vfs_unlink_from_uri (metafile->details->private_vfs_uri); - } - - metafile_write_done (metafile); -} - -static void -metafile_write_callback (GnomeVFSAsyncHandle *handle, - GnomeVFSResult result, - gconstpointer buffer, - GnomeVFSFileSize bytes_requested, - GnomeVFSFileSize bytes_read, - gpointer callback_data) -{ - NautilusMetafile *metafile; - - metafile = NAUTILUS_METAFILE (callback_data); - g_assert (metafile->details->write_state->handle == handle); - g_assert (metafile->details->write_state->buffer == buffer); - g_assert (metafile->details->write_state->size == bytes_requested); - - g_assert (metafile->details->write_state->handle != NULL); - gnome_vfs_async_close (metafile->details->write_state->handle, - result == GNOME_VFS_OK - ? metafile_write_success_close_callback - : metafile_write_failure_close_callback, - metafile); - metafile->details->write_state->handle = NULL; -} - -static void -metafile_write_create_callback (GnomeVFSAsyncHandle *handle, - GnomeVFSResult result, - gpointer callback_data) -{ - NautilusMetafile *metafile; - - metafile = NAUTILUS_METAFILE (callback_data); - g_assert (metafile->details->write_state->handle == handle); - - if (result != GNOME_VFS_OK) { - metafile_write_failed (metafile); - return; - } - - gnome_vfs_async_write (metafile->details->write_state->handle, - metafile->details->write_state->buffer, - metafile->details->write_state->size, - metafile_write_callback, - metafile); -} - -static void -metafile_write_start (NautilusMetafile *metafile) -{ - g_assert (NAUTILUS_IS_METAFILE (metafile)); - - metafile->details->write_state->write_again = FALSE; - - /* Open the file. */ - gnome_vfs_async_create_uri - (&metafile->details->write_state->handle, - metafile->details->write_state->use_public_metafile - ? metafile->details->public_vfs_uri - : metafile->details->private_vfs_uri, - GNOME_VFS_OPEN_WRITE, FALSE, METAFILE_PERMISSIONS, - metafile_write_create_callback, metafile); -} - -static void -metafile_write (NautilusMetafile *metafile) -{ - int xml_doc_size; - - g_assert (NAUTILUS_IS_METAFILE (metafile)); - - bonobo_object_ref (BONOBO_OBJECT (metafile)); - - /* If we are already writing, then just remember to do it again. */ - if (metafile->details->write_state != NULL) { - bonobo_object_unref (BONOBO_OBJECT (metafile)); - metafile->details->write_state->write_again = TRUE; - return; - } - - /* Don't write anything if there's nothing to write. - * At some point, we might want to change this to actually delete - * the metafile in this case. - */ - if (metafile->details->xml == NULL) { - bonobo_object_unref (BONOBO_OBJECT (metafile)); - return; - } - - /* Create the write state. */ - metafile->details->write_state = g_new0 (MetafileWriteState, 1); - metafile->details->write_state->use_public_metafile - = can_use_public_metafile (metafile); - xmlDocDumpMemory (metafile->details->xml, - &metafile->details->write_state->buffer, - &xml_doc_size); - metafile->details->write_state->size = xml_doc_size; - metafile_write_start (metafile); -} - -static gboolean -metafile_write_idle_callback (gpointer callback_data) -{ - NautilusMetafile *metafile; - - metafile = NAUTILUS_METAFILE (callback_data); - - metafile->details->write_idle_id = 0; - metafile_write (metafile); - - bonobo_object_unref (BONOBO_OBJECT (metafile)); - - return FALSE; -} - -static void -directory_request_write_metafile (NautilusMetafile *metafile) -{ - g_assert (NAUTILUS_IS_METAFILE (metafile)); - - if (!allow_metafile (metafile)) { - return; - } - - /* Set up an idle task that will write the metafile. */ - if (metafile->details->write_idle_id == 0) { - bonobo_object_ref (BONOBO_OBJECT (metafile)); - metafile->details->write_idle_id = - gtk_idle_add (metafile_write_idle_callback, - metafile); - } -} diff --git a/libnautilus-extensions/nautilus-metafile.h b/libnautilus-extensions/nautilus-metafile.h deleted file mode 100644 index 7e22486b6..000000000 --- a/libnautilus-extensions/nautilus-metafile.h +++ /dev/null @@ -1,60 +0,0 @@ -/* -*- Mode: IDL; tab-width: 8; indent-tabs-mode: 8; c-basic-offset: 8 -*- */ - -/* nautilus-metafile.h - server side of Nautilus::Metafile - * - * Copyright (C) 2001 Eazel, Inc. - * - * 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. - * - * This 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; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef NAUTILUS_METAFILE_H -#define NAUTILUS_METAFILE_H - -#include "nautilus-metafile-server.h" - -#include <bonobo/bonobo-object.h> -#include <bonobo/bonobo-xobject.h> -#include <gnome-xml/tree.h> - -#include "nautilus-directory.h" -#include "nautilus-file-utilities.h" - -#define NAUTILUS_TYPE_METAFILE (nautilus_metafile_get_type ()) -#define NAUTILUS_METAFILE(obj) (GTK_CHECK_CAST ((obj), NAUTILUS_TYPE_METAFILE, NautilusMetafile)) -#define NAUTILUS_METAFILE_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), NAUTILUS_TYPE_METAFILE, NautilusMetafileClass)) -#define NAUTILUS_IS_METAFILE(obj) (GTK_CHECK_TYPE ((obj), NAUTILUS_TYPE_METAFILE)) -#define NAUTILUS_IS_METAFILE_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), NAUTILUS_TYPE_METAFILE)) - -typedef struct NautilusMetafileDetails NautilusMetafileDetails; - -typedef struct { - BonoboXObject parent_slot; - NautilusMetafileDetails *details; -} NautilusMetafile; - -typedef struct { - BonoboXObjectClass parent_slot; - POA_Nautilus_Metafile__epv epv; -} NautilusMetafileClass; - -GtkType nautilus_metafile_get_type (void); - -NautilusMetafile *nautilus_metafile_get (const char *directory_uri); - -/* Specifications for in-directory metafile. */ -#define NAUTILUS_METAFILE_NAME_SUFFIX ".nautilus-metafile.xml" - -#endif /* NAUTILUS_METAFILE_H */ diff --git a/libnautilus-extensions/nautilus-mime-actions.c b/libnautilus-extensions/nautilus-mime-actions.c deleted file mode 100644 index bcd18e027..000000000 --- a/libnautilus-extensions/nautilus-mime-actions.c +++ /dev/null @@ -1,1720 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ - -/* nautilus-mime-actions.h - uri-specific versions of mime action functions - - Copyright (C) 2000, 2001 Eazel, Inc. - - The Gnome 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 Gnome 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 the Gnome 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. - - Authors: Maciej Stachowiak <mjs@eazel.com> -*/ - -#include <config.h> -#include "nautilus-mime-actions.h" - -#include "nautilus-file-attributes.h" -#include "nautilus-file.h" -#include <eel/eel-glib-extensions.h> -#include "nautilus-metadata.h" -#include <eel/eel-string.h> -#include <libgnomevfs/gnome-vfs-application-registry.h> -#include <libgnomevfs/gnome-vfs-mime-info.h> -#include <libgnomevfs/gnome-vfs-mime.h> -#include <libgnomevfs/gnome-vfs.h> -#include <stdio.h> - -static int gnome_vfs_mime_application_has_id (GnomeVFSMimeApplication *application, - const char *id); -static int gnome_vfs_mime_id_matches_application (const char *id, - GnomeVFSMimeApplication *application); -static gboolean gnome_vfs_mime_application_has_id_not_in_list (GnomeVFSMimeApplication *application, - GList *ids); -static gboolean string_not_in_list (const char *str, - GList *list); -static char *mime_type_get_supertype (const char *mime_type); -static GList *get_explicit_content_view_iids_from_metafile (NautilusFile *file); -static gboolean server_has_content_requirements (OAF_ServerInfo *server); -static gboolean application_supports_uri_scheme (gpointer data, - gpointer uri_scheme); -static GList *nautilus_do_component_query (const char *mime_type, - const char *uri_scheme, - GList *content_mime_types, - gboolean ignore_content_mime_types, - GList *explicit_iids, - char **extra_sort_criteria, - char *extra_requirements, - CORBA_Environment *ev); -static GList *str_list_difference (GList *a, - GList *b); -static char **strv_concat (char **a, - char **b); - -static gboolean -is_known_mime_type (const char *mime_type) -{ - if (mime_type == NULL) { - return FALSE; - } - - if (strcasecmp (mime_type, "GNOME_VFS_MIME_TYPE_UNKNOWN") == 0) { - return FALSE; - } - - return TRUE; -} - -static gboolean -nautilus_mime_actions_check_if_minimum_attributes_ready (NautilusFile *file) -{ - GList *attributes; - gboolean ready; - - attributes = nautilus_mime_actions_get_minimum_file_attributes (); - ready = nautilus_file_check_if_ready (file, attributes); - g_list_free (attributes); - - return ready; -} - -static gboolean -nautilus_mime_actions_check_if_full_attributes_ready (NautilusFile *file) -{ - GList *attributes; - gboolean ready; - - attributes = nautilus_mime_actions_get_full_file_attributes (); - ready = nautilus_file_check_if_ready (file, attributes); - g_list_free (attributes); - - return ready; -} - - -GList * -nautilus_mime_actions_get_minimum_file_attributes (void) -{ - GList *attributes; - - attributes = NULL; - attributes = g_list_prepend (attributes, NAUTILUS_FILE_ATTRIBUTE_ACTIVATION_URI); - attributes = g_list_prepend (attributes, NAUTILUS_FILE_ATTRIBUTE_METADATA); - attributes = g_list_prepend (attributes, NAUTILUS_FILE_ATTRIBUTE_MIME_TYPE); - - return attributes; -} - - -GList * -nautilus_mime_actions_get_full_file_attributes (void) -{ - GList *attributes; - - attributes = nautilus_mime_actions_get_minimum_file_attributes (); - attributes = g_list_prepend (attributes, NAUTILUS_FILE_ATTRIBUTE_DIRECTORY_ITEM_MIME_TYPES); - - return attributes; -} - - - -GnomeVFSMimeActionType -nautilus_mime_get_default_action_type_for_file (NautilusFile *file) -{ - char *mime_type; - char *action_type_string; - GnomeVFSMimeActionType action_type; - - if (!nautilus_mime_actions_check_if_minimum_attributes_ready (file)) { - return GNOME_VFS_MIME_ACTION_TYPE_NONE; - } - - action_type_string = nautilus_file_get_metadata - (file, NAUTILUS_METADATA_KEY_DEFAULT_ACTION_TYPE, NULL); - - if (action_type_string == NULL) { - mime_type = nautilus_file_get_mime_type (file); - action_type = gnome_vfs_mime_get_default_action_type (mime_type); - g_free (mime_type); - return action_type; - } else { - if (strcasecmp (action_type_string, "application") == 0) { - return GNOME_VFS_MIME_ACTION_TYPE_APPLICATION; - } else if (strcasecmp (action_type_string, "component") == 0) { - return GNOME_VFS_MIME_ACTION_TYPE_COMPONENT; - } else { - return GNOME_VFS_MIME_ACTION_TYPE_NONE; - } - } -} - -GnomeVFSMimeAction * -nautilus_mime_get_default_action_for_file (NautilusFile *file) -{ - GnomeVFSMimeAction *action; - - if (!nautilus_mime_actions_check_if_minimum_attributes_ready (file)) { - return NULL; - } - - action = g_new0 (GnomeVFSMimeAction, 1); - - action->action_type = nautilus_mime_get_default_action_type_for_file (file); - - switch (action->action_type) { - case GNOME_VFS_MIME_ACTION_TYPE_APPLICATION: - action->action.application = - nautilus_mime_get_default_application_for_file (file); - if (action->action.application == NULL) { - g_free (action); - action = NULL; - } - break; - case GNOME_VFS_MIME_ACTION_TYPE_COMPONENT: - action->action.component = - nautilus_mime_get_default_component_for_file (file); - if (action->action.component == NULL) { - g_free (action); - action = NULL; - } - case GNOME_VFS_MIME_ACTION_TYPE_NONE: - g_free (action); - action = NULL; - break; - default: - g_assert_not_reached (); - } - - return action; -} - - -static GnomeVFSMimeApplication * -nautilus_mime_get_default_application_for_file_internal (NautilusFile *file, - gboolean *user_chosen) -{ - char *mime_type; - GnomeVFSMimeApplication *result; - char *default_application_string; - gboolean used_user_chosen_info; - - if (!nautilus_mime_actions_check_if_minimum_attributes_ready (file)) { - return NULL; - } - - used_user_chosen_info = TRUE; - - default_application_string = nautilus_file_get_metadata - (file, NAUTILUS_METADATA_KEY_DEFAULT_APPLICATION, NULL); - - /* FIXME bugzilla.eazel.com 5085: should fall back to normal default - if user-specified default is bogus */ - - if (default_application_string == NULL) { - mime_type = nautilus_file_get_mime_type (file); - result = gnome_vfs_mime_get_default_application (mime_type); - g_free (mime_type); - used_user_chosen_info = FALSE; - } else { - result = gnome_vfs_application_registry_get_mime_application (default_application_string); - } - - if (user_chosen != NULL) { - *user_chosen = used_user_chosen_info; - } - - return result; -} - -GnomeVFSMimeApplication * -nautilus_mime_get_default_application_for_file (NautilusFile *file) -{ - return nautilus_mime_get_default_application_for_file_internal (file, NULL); -} - -gboolean -nautilus_mime_is_default_application_for_file_user_chosen (NautilusFile *file) -{ - GnomeVFSMimeApplication *application; - gboolean user_chosen; - - application = nautilus_mime_get_default_application_for_file_internal (file, &user_chosen); - - /* Doesn't count as user chosen if the user-specified data is bogus and doesn't - * result in an actual application. - */ - if (application == NULL) { - return FALSE; - } - - gnome_vfs_mime_application_free (application); - - return user_chosen; -} - - -static char ** -nautilus_mime_get_default_component_sort_conditions (NautilusFile *file, char *default_component_string) -{ - char **sort_conditions; - char *supertype; - char *mime_type; - GList *short_list; - GList *p; - char *prev; - - sort_conditions = g_new0 (char *, 5); - - mime_type = nautilus_file_get_mime_type (file); - - supertype = mime_type_get_supertype (mime_type); - - /* prefer the exact right IID */ - if (default_component_string != NULL) { - sort_conditions[0] = g_strconcat ("iid == '", default_component_string, "'", NULL); - } else { - sort_conditions[0] = g_strdup ("true"); - } - - /* Prefer something from the short list */ - - short_list = nautilus_mime_get_short_list_components_for_file (file); - if (short_list != NULL) { - sort_conditions[1] = g_strdup ("prefer_by_list_order (iid, ['"); - - for (p = short_list; p != NULL; p = p->next) { - prev = sort_conditions[1]; - - if (p->next != NULL) { - sort_conditions[1] = g_strconcat (prev, ((OAF_ServerInfo *) (p->data))->iid, - "','", NULL); - } else { - sort_conditions[1] = g_strconcat (prev, ((OAF_ServerInfo *) (p->data))->iid, - "'])", NULL); - } - g_free (prev); - } - } else { - sort_conditions[1] = g_strdup ("true"); - } - - gnome_vfs_mime_component_list_free (short_list); - - /* Prefer something that matches the exact type to something - that matches the supertype */ - if (is_known_mime_type (mime_type)) { - sort_conditions[2] = g_strconcat ("bonobo:supported_mime_types.has ('",mime_type,"')", NULL); - } else { - sort_conditions[2] = g_strdup ("true"); - } - - /* Prefer something that matches the supertype to something that matches `*' */ - if (is_known_mime_type (mime_type) && supertype != NULL) { - sort_conditions[3] = g_strconcat ("bonobo:supported_mime_types.has ('",supertype,"')", NULL); - } else { - sort_conditions[3] = g_strdup ("true"); - } - - sort_conditions[4] = NULL; - - g_free (mime_type); - g_free (supertype); - - return sort_conditions; -} - -static OAF_ServerInfo * -nautilus_mime_get_default_component_for_file_internal (NautilusFile *file, - gboolean *user_chosen) -{ - GList *info_list; - OAF_ServerInfo *mime_default; - char *default_component_string; - char *mime_type; - char *uri_scheme; - GList *item_mime_types; - GList *explicit_iids; - CORBA_Environment ev; - OAF_ServerInfo *server; - char **sort_conditions; - char *extra_requirements; - gboolean used_user_chosen_info; - gboolean metadata_default; - - if (!nautilus_mime_actions_check_if_minimum_attributes_ready (file)) { - return NULL; - } - - used_user_chosen_info = TRUE; - - info_list = NULL; - - CORBA_exception_init (&ev); - - mime_type = nautilus_file_get_mime_type (file); - - uri_scheme = nautilus_file_get_uri_scheme (file); - - explicit_iids = get_explicit_content_view_iids_from_metafile (file); - - if (!nautilus_mime_actions_check_if_full_attributes_ready (file) || - !nautilus_file_get_directory_item_mime_types (file, &item_mime_types)) { - item_mime_types = NULL; - } - - default_component_string = nautilus_file_get_metadata - (file, NAUTILUS_METADATA_KEY_DEFAULT_COMPONENT, NULL); - - if (default_component_string == NULL) { - metadata_default = FALSE; - - if (is_known_mime_type (mime_type)) { - mime_default = gnome_vfs_mime_get_default_component (mime_type); - if (mime_default != NULL) { - default_component_string = g_strdup (mime_default->iid); - if (default_component_string != NULL) { - /* Default component chosen based only on type. */ - used_user_chosen_info = FALSE; - } - CORBA_free (mime_default); - } - } - } else { - metadata_default = TRUE; - } - - sort_conditions = nautilus_mime_get_default_component_sort_conditions (file, default_component_string); - - /* If the default is specified in the per-uri metadata, - respect the setting regardless of content type requirements */ - if (metadata_default) { - extra_requirements = g_strconcat ("iid == '", default_component_string, "'", NULL); - info_list = nautilus_do_component_query (mime_type, uri_scheme, item_mime_types, TRUE, - explicit_iids, sort_conditions, extra_requirements, &ev); - g_free (extra_requirements); - } - - if (info_list == NULL) { - info_list = nautilus_do_component_query (mime_type, uri_scheme, item_mime_types, FALSE, - explicit_iids, sort_conditions, NULL, &ev); - } - - if (info_list != NULL) { - server = OAF_ServerInfo_duplicate (info_list->data); - gnome_vfs_mime_component_list_free (info_list); - - if (default_component_string != NULL && strcmp (server->iid, default_component_string) == 0) { - used_user_chosen_info = TRUE; /* Default component chosen based on user-stored . */ - } - } else { - server = NULL; - } - - eel_g_list_free_deep (item_mime_types); - g_strfreev (sort_conditions); - - g_free (uri_scheme); - g_free (mime_type); - g_free (default_component_string); - - CORBA_exception_free (&ev); - - if (user_chosen != NULL) { - *user_chosen = used_user_chosen_info; - } - - return server; -} - - -OAF_ServerInfo * -nautilus_mime_get_default_component_for_file (NautilusFile *file) -{ - return nautilus_mime_get_default_component_for_file_internal (file, NULL); -} - -gboolean -nautilus_mime_is_default_component_for_file_user_chosen (NautilusFile *file) -{ - OAF_ServerInfo *component; - gboolean user_chosen; - - component = nautilus_mime_get_default_component_for_file_internal (file, &user_chosen); - - /* Doesn't count as user chosen if the user-specified data is bogus and doesn't - * result in an actual component. - */ - if (component == NULL) { - return FALSE; - } - - CORBA_free (component); - - return user_chosen; -} - - -GList * -nautilus_mime_get_short_list_applications_for_file (NautilusFile *file) -{ - char *mime_type; - char *uri_scheme; - GList *result; - GList *removed; - GList *metadata_application_add_ids; - GList *metadata_application_remove_ids; - GList *p; - GnomeVFSMimeApplication *application; - CORBA_Environment ev; - - if (!nautilus_mime_actions_check_if_minimum_attributes_ready (file)) { - return NULL; - } - - mime_type = nautilus_file_get_mime_type (file); - result = gnome_vfs_mime_get_short_list_applications (mime_type); - g_free (mime_type); - - /* First remove applications that cannot support this location */ - uri_scheme = nautilus_file_get_uri_scheme (file); - g_assert (uri_scheme != NULL); - result = eel_g_list_partition (result, application_supports_uri_scheme, - uri_scheme, &removed); - gnome_vfs_mime_application_list_free (removed); - - CORBA_exception_init (&ev); - - metadata_application_add_ids = nautilus_file_get_metadata_list - (file, - NAUTILUS_METADATA_KEY_SHORT_LIST_APPLICATION_ADD, - NAUTILUS_METADATA_SUBKEY_APPLICATION_ID); - metadata_application_remove_ids = nautilus_file_get_metadata_list - (file, - NAUTILUS_METADATA_KEY_SHORT_LIST_APPLICATION_REMOVE, - NAUTILUS_METADATA_SUBKEY_APPLICATION_ID); - - - result = eel_g_list_partition (result, (EelPredicateFunction) gnome_vfs_mime_application_has_id_not_in_list, - metadata_application_remove_ids, &removed); - - gnome_vfs_mime_application_list_free (removed); - - for (p = metadata_application_add_ids; p != NULL; p = p->next) { - if (g_list_find_custom (result, - p->data, - (GCompareFunc) gnome_vfs_mime_application_has_id) == NULL && - g_list_find_custom (metadata_application_remove_ids, - p->data, - (GCompareFunc) strcmp) == NULL) { - application = gnome_vfs_application_registry_get_mime_application (p->data); - - if (application != NULL) { - result = g_list_prepend (result, application); - } - } - } - - CORBA_exception_free (&ev); - - return result; -} - -GList * -nautilus_mime_get_short_list_components_for_file (NautilusFile *file) -{ - char *mime_type; - char *uri_scheme; - GList *item_mime_types; - GList *servers; - GList *iids; - GList *result; - GList *removed; - GList *metadata_component_add_ids; - GList *metadata_component_remove_ids; - GList *p; - OAF_ServerInfo *component; - GList *explicit_iids; - CORBA_Environment ev; - char *extra_requirements; - char *prev; - - if (!nautilus_mime_actions_check_if_minimum_attributes_ready (file)) { - return NULL; - } - - CORBA_exception_init (&ev); - - uri_scheme = nautilus_file_get_uri_scheme (file); - - explicit_iids = get_explicit_content_view_iids_from_metafile (file); - - if (!nautilus_mime_actions_check_if_full_attributes_ready (file) || - !nautilus_file_get_directory_item_mime_types (file, &item_mime_types)) { - item_mime_types = NULL; - } - - metadata_component_add_ids = nautilus_file_get_metadata_list - (file, - NAUTILUS_METADATA_KEY_SHORT_LIST_COMPONENT_ADD, - NAUTILUS_METADATA_SUBKEY_COMPONENT_IID); - metadata_component_remove_ids = nautilus_file_get_metadata_list - (file, - NAUTILUS_METADATA_KEY_SHORT_LIST_COMPONENT_REMOVE, - NAUTILUS_METADATA_SUBKEY_COMPONENT_IID); - - mime_type = nautilus_file_get_mime_type (file); - servers = gnome_vfs_mime_get_short_list_components (mime_type); - iids = NULL; - - for (p = servers; p != NULL; p = p->next) { - component = (OAF_ServerInfo *) p->data; - - iids = g_list_prepend (iids, component->iid); - } - - iids = eel_g_list_partition - (iids, (EelPredicateFunction) string_not_in_list, - metadata_component_remove_ids, &removed); - - g_list_free (removed); - - for (p = metadata_component_add_ids; p != NULL; p = p->next) { - if (g_list_find_custom (iids, - p->data, - (GCompareFunc) strcmp) == NULL && - g_list_find_custom (metadata_component_remove_ids, - p->data, - (GCompareFunc) strcmp) == NULL) { - iids = g_list_prepend (iids, p->data); - } - } - - /* By copying the iids using g_list_prepend, we've reversed the short - list order. We need to use the order to determine the first available - component, so reverse it now to maintain original ordering */ - iids = g_list_reverse (iids); - result = NULL; - - if (iids != NULL) { - extra_requirements = g_strdup ("has (['"); - for (p = iids; p != NULL; p = p->next) { - prev = extra_requirements; - - if (p->next != NULL) { - extra_requirements = g_strconcat (prev, p->data, "','", NULL); - } else { - extra_requirements = g_strconcat (prev, p->data, "'], iid)", NULL); - } - g_free (prev); - } - - result = nautilus_do_component_query (mime_type, uri_scheme, item_mime_types, FALSE, - explicit_iids, NULL, extra_requirements, &ev); - g_free (extra_requirements); - } - - eel_g_list_free_deep (item_mime_types); - gnome_vfs_mime_component_list_free (servers); - g_list_free (iids); - g_free (uri_scheme); - g_free (mime_type); - - return result; -} - -GList * -nautilus_mime_get_all_applications_for_file (NautilusFile *file) -{ - char *mime_type; - GList *result; - GList *metadata_application_ids; - GList *p; - GnomeVFSMimeApplication *application; - - if (!nautilus_mime_actions_check_if_minimum_attributes_ready (file)) { - return NULL; - } - - metadata_application_ids = nautilus_file_get_metadata_list - (file, - NAUTILUS_METADATA_KEY_EXPLICIT_APPLICATION, - NAUTILUS_METADATA_SUBKEY_APPLICATION_ID); - - mime_type = nautilus_file_get_mime_type (file); - - result = gnome_vfs_mime_get_all_applications (mime_type); - - for (p = metadata_application_ids; p != NULL; p = p->next) { - if (!g_list_find_custom (result, - p->data, - (GCompareFunc) gnome_vfs_mime_application_has_id)) { - application = gnome_vfs_application_registry_get_mime_application (p->data); - - if (application != NULL) { - result = g_list_prepend (result, application); - } - } - } - - g_free (mime_type); - return result; -} - -static int -application_supports_uri_scheme_strcmp_style (gconstpointer application_data, - gconstpointer uri_scheme) -{ - return application_supports_uri_scheme - ((gpointer) application_data, - (gpointer) uri_scheme) ? 0 : 1; -} - -gboolean -nautilus_mime_has_any_applications_for_file (NautilusFile *file) -{ - GList *all_applications_for_mime_type, *application_that_can_access_uri; - char *uri_scheme; - gboolean result; - - all_applications_for_mime_type = nautilus_mime_get_all_applications_for_file (file); - - uri_scheme = nautilus_file_get_uri_scheme (file); - application_that_can_access_uri = g_list_find_custom - (all_applications_for_mime_type, - uri_scheme, - application_supports_uri_scheme_strcmp_style); - g_free (uri_scheme); - - result = application_that_can_access_uri != NULL; - gnome_vfs_mime_application_list_free (all_applications_for_mime_type); - - return result; -} - -gboolean -nautilus_mime_has_any_applications_for_file_type (NautilusFile *file) -{ - GList *applications; - gboolean result; - - applications = nautilus_mime_get_all_applications_for_file (file); - - result = applications != NULL; - gnome_vfs_mime_application_list_free (applications); - - return result; -} - -gboolean -nautilus_mime_actions_file_needs_full_file_attributes (NautilusFile *file) -{ - char *mime_type; - char *uri_scheme; - GList *info_list; - GList *explicit_iids; - GList *p; - CORBA_Environment ev; - gboolean needs_full_attributes; - - g_return_val_if_fail (nautilus_mime_actions_check_if_minimum_attributes_ready (file), - FALSE); - - if (!nautilus_file_is_directory (file)) { - return FALSE; - } - - CORBA_exception_init (&ev); - - uri_scheme = nautilus_file_get_uri_scheme (file); - - mime_type = nautilus_file_get_mime_type (file); - - explicit_iids = get_explicit_content_view_iids_from_metafile (file); - - info_list = nautilus_do_component_query (mime_type, uri_scheme, NULL, TRUE, - explicit_iids, NULL, NULL, &ev); - - needs_full_attributes = FALSE; - - for (p = info_list; p != NULL; p = p->next) { - needs_full_attributes |= server_has_content_requirements ((OAF_ServerInfo *) (p->data)); - } - - gnome_vfs_mime_component_list_free (info_list); - eel_g_list_free_deep (explicit_iids); - g_free (uri_scheme); - g_free (mime_type); - CORBA_exception_free (&ev); - - return needs_full_attributes; -} - - -GList * -nautilus_mime_get_all_components_for_file (NautilusFile *file) -{ - char *mime_type; - char *uri_scheme; - GList *item_mime_types; - GList *info_list; - GList *explicit_iids; - CORBA_Environment ev; - - if (!nautilus_mime_actions_check_if_minimum_attributes_ready (file)) { - return NULL; - } - - CORBA_exception_init (&ev); - - uri_scheme = nautilus_file_get_uri_scheme (file); - - mime_type = nautilus_file_get_mime_type (file); - explicit_iids = get_explicit_content_view_iids_from_metafile (file); - - if (!nautilus_mime_actions_check_if_full_attributes_ready (file) || - !nautilus_file_get_directory_item_mime_types (file, &item_mime_types)) { - item_mime_types = NULL; - } - - info_list = nautilus_do_component_query (mime_type, uri_scheme, item_mime_types, FALSE, - explicit_iids, NULL, NULL, &ev); - - eel_g_list_free_deep (explicit_iids); - eel_g_list_free_deep (item_mime_types); - - g_free (uri_scheme); - g_free (mime_type); - CORBA_exception_free (&ev); - - return info_list; -} - -gboolean -nautilus_mime_has_any_components_for_file (NautilusFile *file) -{ - GList *list; - gboolean result; - - list = nautilus_mime_get_all_components_for_file (file); - result = list != NULL; - gnome_vfs_mime_component_list_free (list); - - return result; -} - - -static GList * -mime_get_all_components_for_uri_scheme (const char *uri_scheme) -{ - GList *info_list; - CORBA_Environment ev; - - g_return_val_if_fail (eel_strlen (uri_scheme) > 0, NULL); - - CORBA_exception_init (&ev); - - info_list = nautilus_do_component_query (NULL, - uri_scheme, - NULL, - TRUE, - NULL, - NULL, - NULL, - &ev); - - CORBA_exception_free (&ev); - - return info_list; -} - -gboolean -nautilus_mime_has_any_components_for_uri_scheme (const char *uri_scheme) -{ - GList *list; - gboolean result; - - g_return_val_if_fail (eel_strlen (uri_scheme) > 0, FALSE); - - list = mime_get_all_components_for_uri_scheme (uri_scheme); - result = list != NULL; - gnome_vfs_mime_component_list_free (list); - - return result; -} - -GnomeVFSResult -nautilus_mime_set_default_action_type_for_file (NautilusFile *file, - GnomeVFSMimeActionType action_type) -{ - const char *action_string; - - switch (action_type) { - case GNOME_VFS_MIME_ACTION_TYPE_APPLICATION: - action_string = "application"; - break; - case GNOME_VFS_MIME_ACTION_TYPE_COMPONENT: - action_string = "component"; - break; - case GNOME_VFS_MIME_ACTION_TYPE_NONE: - default: - action_string = "none"; - } - - nautilus_file_set_metadata - (file, NAUTILUS_METADATA_KEY_DEFAULT_ACTION_TYPE, NULL, action_string); - - return GNOME_VFS_OK; -} - -GnomeVFSResult -nautilus_mime_set_default_application_for_file (NautilusFile *file, - const char *application_id) -{ - g_return_val_if_fail (nautilus_mime_actions_check_if_minimum_attributes_ready (file), - GNOME_VFS_ERROR_GENERIC); - - nautilus_file_set_metadata - (file, NAUTILUS_METADATA_KEY_DEFAULT_APPLICATION, NULL, application_id); - - /* If there's no default action type, set it to match this. */ - if (application_id != NULL && - nautilus_mime_get_default_action_type_for_file (file) == GNOME_VFS_MIME_ACTION_TYPE_NONE) { - return nautilus_mime_set_default_action_type_for_file (file, GNOME_VFS_MIME_ACTION_TYPE_APPLICATION); - } - - return GNOME_VFS_OK; -} - -GnomeVFSResult -nautilus_mime_set_default_component_for_file (NautilusFile *file, - const char *component_iid) -{ - g_return_val_if_fail (nautilus_mime_actions_check_if_minimum_attributes_ready (file), - GNOME_VFS_ERROR_GENERIC); - - nautilus_file_set_metadata - (file, NAUTILUS_METADATA_KEY_DEFAULT_COMPONENT, NULL, component_iid); - - /* If there's no default action type, set it to match this. */ - if (component_iid != NULL && - nautilus_mime_get_default_action_type_for_file (file) == GNOME_VFS_MIME_ACTION_TYPE_NONE) { - return nautilus_mime_set_default_action_type_for_file (file, GNOME_VFS_MIME_ACTION_TYPE_COMPONENT); - } - - return GNOME_VFS_OK; -} - -GnomeVFSResult -nautilus_mime_set_short_list_applications_for_file (NautilusFile *file, - GList *applications) -{ - GList *add_list; - GList *remove_list; - GList *normal_short_list; - GList *normal_short_list_ids; - GList *p; - char *mime_type; - - g_return_val_if_fail (nautilus_mime_actions_check_if_minimum_attributes_ready (file), - GNOME_VFS_ERROR_GENERIC); - - /* get per-mime short list */ - - mime_type = nautilus_file_get_mime_type (file); - normal_short_list = gnome_vfs_mime_get_short_list_applications (mime_type); - g_free (mime_type); - - normal_short_list_ids = NULL; - for (p = normal_short_list; p != NULL; p = p->next) { - normal_short_list_ids = g_list_prepend (normal_short_list_ids, ((GnomeVFSMimeApplication *) p->data)->id); - } - - /* compute delta */ - - add_list = str_list_difference (applications, normal_short_list_ids); - remove_list = str_list_difference (normal_short_list_ids, applications); - - nautilus_file_set_metadata_list - (file, - NAUTILUS_METADATA_KEY_SHORT_LIST_APPLICATION_ADD, - NAUTILUS_METADATA_SUBKEY_APPLICATION_ID, - add_list); - nautilus_file_set_metadata_list - (file, - NAUTILUS_METADATA_KEY_SHORT_LIST_APPLICATION_REMOVE, - NAUTILUS_METADATA_SUBKEY_APPLICATION_ID, - remove_list); - - /* FIXME bugzilla.eazel.com 1269: - * need to free normal_short_list, normal_short_list_ids, add_list, remove_list - */ - - return GNOME_VFS_OK; -} - -GnomeVFSResult -nautilus_mime_set_short_list_components_for_file (NautilusFile *file, - GList *components) -{ - GList *add_list; - GList *remove_list; - GList *normal_short_list; - GList *normal_short_list_ids; - GList *p; - char *mime_type; - - g_return_val_if_fail (nautilus_mime_actions_check_if_minimum_attributes_ready (file), - GNOME_VFS_ERROR_GENERIC); - - /* get per-mime short list */ - mime_type = nautilus_file_get_mime_type (file); - normal_short_list = gnome_vfs_mime_get_short_list_components (mime_type); - g_free (mime_type); - - normal_short_list_ids = NULL; - for (p = normal_short_list; p != NULL; p = p->next) { - normal_short_list_ids = g_list_prepend (normal_short_list_ids, ((OAF_ServerInfo *) p->data)->iid); - } - - /* compute delta */ - - add_list = str_list_difference (components, normal_short_list_ids); - remove_list = str_list_difference (normal_short_list_ids, components); - - nautilus_file_set_metadata_list - (file, - NAUTILUS_METADATA_KEY_SHORT_LIST_COMPONENT_ADD, - NAUTILUS_METADATA_SUBKEY_COMPONENT_IID, - add_list); - nautilus_file_set_metadata_list - (file, - NAUTILUS_METADATA_KEY_SHORT_LIST_COMPONENT_REMOVE, - NAUTILUS_METADATA_SUBKEY_COMPONENT_IID, - remove_list); - - /* FIXME bugzilla.eazel.com 1269: - * need to free normal_short_list, normal_short_list_ids, add_list, remove_list - */ - - return GNOME_VFS_OK; -} - -GnomeVFSResult -nautilus_mime_add_application_to_short_list_for_file (NautilusFile *file, - const char *application_id) -{ - GList *old_list, *new_list; - GnomeVFSResult result; - - g_return_val_if_fail (nautilus_mime_actions_check_if_minimum_attributes_ready (file), - GNOME_VFS_ERROR_GENERIC); - - result = GNOME_VFS_OK; - - old_list = nautilus_mime_get_short_list_applications_for_file (file); - - if (!gnome_vfs_mime_id_in_application_list (application_id, old_list)) { - new_list = g_list_append (gnome_vfs_mime_id_list_from_application_list (old_list), - g_strdup (application_id)); - result = nautilus_mime_set_short_list_applications_for_file (file, new_list); - eel_g_list_free_deep (new_list); - } - - gnome_vfs_mime_application_list_free (old_list); - - return result; -} - -GnomeVFSResult -nautilus_mime_remove_application_from_short_list_for_file (NautilusFile *file, - const char *application_id) -{ - GList *old_list, *new_list; - gboolean was_in_list; - GnomeVFSResult result; - - g_return_val_if_fail (nautilus_mime_actions_check_if_minimum_attributes_ready (file), - GNOME_VFS_ERROR_GENERIC); - - old_list = nautilus_mime_get_short_list_applications_for_file (file); - old_list = gnome_vfs_mime_remove_application_from_list - (old_list, application_id, &was_in_list); - - if (!was_in_list) { - result = GNOME_VFS_OK; - } else { - new_list = gnome_vfs_mime_id_list_from_application_list (old_list); - result = nautilus_mime_set_short_list_applications_for_file (file, new_list); - eel_g_list_free_deep (new_list); - } - - gnome_vfs_mime_application_list_free (old_list); - - return result; -} - -GnomeVFSResult -nautilus_mime_add_component_to_short_list_for_file (NautilusFile *file, - const char *iid) -{ - GList *old_list, *new_list; - GnomeVFSResult result; - - g_return_val_if_fail (nautilus_mime_actions_check_if_minimum_attributes_ready (file), - GNOME_VFS_ERROR_GENERIC); - - old_list = nautilus_mime_get_short_list_components_for_file (file); - - if (gnome_vfs_mime_id_in_component_list (iid, old_list)) { - result = GNOME_VFS_OK; - } else { - new_list = g_list_append (gnome_vfs_mime_id_list_from_component_list (old_list), - g_strdup (iid)); - result = nautilus_mime_set_short_list_components_for_file (file, new_list); - eel_g_list_free_deep (new_list); - } - - gnome_vfs_mime_component_list_free (old_list); - - return result; -} - -GnomeVFSResult -nautilus_mime_remove_component_from_short_list_for_file (NautilusFile *file, - const char *iid) -{ - GList *old_list, *new_list; - gboolean was_in_list; - GnomeVFSResult result; - - g_return_val_if_fail (nautilus_mime_actions_check_if_minimum_attributes_ready (file), - GNOME_VFS_ERROR_GENERIC); - - old_list = nautilus_mime_get_short_list_components_for_file (file); - old_list = gnome_vfs_mime_remove_component_from_list - (old_list, iid, &was_in_list); - - if (!was_in_list) { - result = GNOME_VFS_OK; - } else { - new_list = gnome_vfs_mime_id_list_from_component_list (old_list); - result = nautilus_mime_set_short_list_components_for_file (file, new_list); - eel_g_list_free_deep (new_list); - } - - gnome_vfs_mime_component_list_free (old_list); - - return result; -} - -GnomeVFSResult -nautilus_mime_extend_all_applications_for_file (NautilusFile *file, - GList *applications) -{ - GList *metadata_application_ids; - GList *extras; - GList *final_applications; - - g_return_val_if_fail (nautilus_mime_actions_check_if_minimum_attributes_ready (file), - GNOME_VFS_ERROR_GENERIC); - - metadata_application_ids = nautilus_file_get_metadata_list - (file, - NAUTILUS_METADATA_KEY_EXPLICIT_APPLICATION, - NAUTILUS_METADATA_SUBKEY_APPLICATION_ID); - - extras = str_list_difference (applications, metadata_application_ids); - - final_applications = g_list_concat (g_list_copy (metadata_application_ids), extras); - - nautilus_file_set_metadata_list - (file, - NAUTILUS_METADATA_KEY_EXPLICIT_APPLICATION, - NAUTILUS_METADATA_SUBKEY_APPLICATION_ID, - final_applications); - - return GNOME_VFS_OK; -} - -GnomeVFSResult -nautilus_mime_remove_from_all_applications_for_file (NautilusFile *file, - GList *applications) -{ - GList *metadata_application_ids; - GList *final_applications; - - g_return_val_if_fail (nautilus_mime_actions_check_if_minimum_attributes_ready (file), - GNOME_VFS_ERROR_GENERIC); - - metadata_application_ids = nautilus_file_get_metadata_list - (file, - NAUTILUS_METADATA_KEY_EXPLICIT_APPLICATION, - NAUTILUS_METADATA_SUBKEY_APPLICATION_ID); - - final_applications = str_list_difference (metadata_application_ids, applications); - - nautilus_file_set_metadata_list - (file, - NAUTILUS_METADATA_KEY_EXPLICIT_APPLICATION, - NAUTILUS_METADATA_SUBKEY_APPLICATION_ID, - final_applications); - - return GNOME_VFS_OK; -} - -static int -gnome_vfs_mime_application_has_id (GnomeVFSMimeApplication *application, - const char *id) -{ - return strcmp (application->id, id); -} - -static int -gnome_vfs_mime_id_matches_application (const char *id, - GnomeVFSMimeApplication *application) -{ - return gnome_vfs_mime_application_has_id (application, id); -} - -static gboolean -gnome_vfs_mime_application_has_id_not_in_list (GnomeVFSMimeApplication *application, - GList *ids) -{ - return g_list_find_custom (ids, application, - (GCompareFunc) gnome_vfs_mime_id_matches_application) == NULL; -} - -static gboolean -string_not_in_list (const char *str, - GList *list) -{ - return g_list_find_custom (list, (gpointer) str, (GCompareFunc) strcmp) == NULL; -} - -static char * -extract_prefix_add_suffix (const char *string, - const char *separator, - const char *suffix) -{ - const char *separator_position; - int prefix_length; - char *result; - - separator_position = strstr (string, separator); - prefix_length = separator_position == NULL - ? (int) strlen (string) - : separator_position - string; - - result = g_malloc (prefix_length + strlen(suffix) + 1); - - strncpy (result, string, prefix_length); - result[prefix_length] = '\0'; - - strcat (result, suffix); - - return result; -} - -static char * -mime_type_get_supertype (const char *mime_type) -{ - if (mime_type == NULL || mime_type == '\0') { - return g_strdup (mime_type); - } - return extract_prefix_add_suffix (mime_type, "/", "/*"); -} - - -/* - * The following routine uses metadata associated with the current url - * to add content view components specified in the metadata. The - * content views are specified in the string as <EXPLICIT_CONTENT_VIEW - * IID="iid"/> elements inside the appropriate <FILE> element. - */ - -static GList * -get_explicit_content_view_iids_from_metafile (NautilusFile *file) -{ - if (file != NULL) { - return nautilus_file_get_metadata_list - (file, - NAUTILUS_METADATA_KEY_EXPLICIT_COMPONENT, - NAUTILUS_METADATA_SUBKEY_COMPONENT_IID); - } else { - return NULL; - } -} - -static char * -make_oaf_query_for_explicit_content_view_iids (GList *view_iids) -{ - GList *p; - char *iid; - char *query; - char *old_query; - - query = NULL; - - for (p = view_iids; p != NULL; p = p->next) { - iid = (char *) p->data; - if (query != NULL) { - old_query = query; - query = g_strconcat (query, " OR ", NULL); - g_free (old_query); - } else { - query = g_strdup ("("); - } - - old_query = query; - query = g_strdup_printf ("%s iid=='%s'", old_query, iid); - g_free (old_query); - } - - - if (query != NULL) { - old_query = query; - query = g_strconcat (old_query, ")", NULL); - g_free (old_query); - } else { - query = g_strdup ("false"); - } - - return query; -} - -static char * -make_oaf_query_with_known_mime_type (const char *mime_type, - const char *uri_scheme, - GList *explicit_iids, - const char *extra_requirements) -{ - char *mime_supertype; - char *result; - char *explicit_iid_query; - - mime_supertype = mime_type_get_supertype (mime_type); - - explicit_iid_query = make_oaf_query_for_explicit_content_view_iids (explicit_iids); - - result = g_strdup_printf - ( - /* Check if the component has the interfaces we need. - * We can work with either a Nautilus View, or - * with a Bonobo Control or Embeddable that supports - * one of the three persistence interfaces: - * PersistStream, ProgressiveDataSink, or - * PersistFile. - */ - "(((repo_ids.has_all (['IDL:Bonobo/Control:1.0'," - "'IDL:Nautilus/View:1.0'])" - "OR (repo_ids.has_one (['IDL:Bonobo/Control:1.0'," - "'IDL:Bonobo/Embeddable:1.0'])" - "AND repo_ids.has_one (['IDL:Bonobo/PersistStream:1.0'," - "'IDL:Bonobo/ProgressiveDataSink:1.0'," - "'IDL:Bonobo/PersistFile:1.0'])))" - - /* Check that the component either has a specific - * MIME type or URI scheme. If neither is specified, - * then we don't trust that to mean "all MIME types - * and all schemes". For that, you have to do a - * wildcard for the MIME type or for the scheme. - */ - "AND (bonobo:supported_mime_types.defined ()" - "OR bonobo:supported_uri_schemes.defined ()" - "OR bonobo:additional_uri_schemes.defined ())" - - /* One of two possibilties */ - - /* FIXME bugzilla.eazel.com 2542: this comment is not very clear. */ - /* 1 The mime type and URI scheme match the supported - attributes. */ - - "AND (" - - /* Check that the supported MIME types include the - * URI's MIME type or its supertype. - */ - "((NOT bonobo:supported_mime_types.defined ()" - "OR bonobo:supported_mime_types.has ('%s')" - "OR bonobo:supported_mime_types.has ('%s')" - "OR bonobo:supported_mime_types.has ('*/*'))" - - /* Check that the supported URI schemes include the - * URI's scheme. - */ - "AND (NOT bonobo:supported_uri_schemes.defined ()" - "OR bonobo:supported_uri_schemes.has ('%s')" - "OR bonobo:supported_uri_schemes.has ('*')))" - - /* 2 OR The additional URI schemes include this URI's - scheme; if that is the case, this view applies - whether or not the mime type is supported. */ - - "OR (bonobo:additional_uri_schemes.has ('%s')" - "OR bonobo:additional_uri_schemes.has ('*')))" - - /* Check that the component makes it clear that it's - * intended for Nautilus by providing a "view_as" - * name. We could instead support a default, but - * that would make components that are untested with - * Nautilus appear. */ - "AND nautilus:view_as_name.defined ())" - - /* Also select iids that were specifically requested - for this location, even if they do not otherwise - meet the requirements. */ - "OR %s)" - - /* Make it possible to add extra requirements */ - " AND (%s)" - - /* The MIME type, MIME supertype, and URI scheme for - * the %s above. - */ - , mime_type, mime_supertype, uri_scheme, uri_scheme - - /* The explicit metafile iid query for the %s above. */ - , explicit_iid_query - - /* extra requirements */ - , extra_requirements != NULL ? extra_requirements : "true"); - - g_free (mime_supertype); - g_free (explicit_iid_query); - return result; -} - -static char * -make_oaf_query_with_uri_scheme_only (const char *uri_scheme, - GList *explicit_iids, - const char *extra_requirements) -{ - char *result; - char *explicit_iid_query; - - explicit_iid_query = make_oaf_query_for_explicit_content_view_iids (explicit_iids); - - result = g_strdup_printf - ( - /* Check if the component has the interfaces we need. - * We can work with either a Nautilus tView, or - * with a Bonobo Control or Embeddable that works on - * a file, which is indicated by Bonobo PersistFile. - */ - "(((repo_ids.has_all(['IDL:Bonobo/Control:1.0'," - "'IDL:Nautilus/View:1.0'])" - "OR (repo_ids.has_one(['IDL:Bonobo/Control:1.0'," - "'IDL:Bonobo/Embeddable:1.0'])" - "AND repo_ids.has('IDL:Bonobo/PersistFile:1.0')))" - - - /* Check if the component supports this particular - * URI scheme. - */ - "AND (((bonobo:supported_uri_schemes.has ('%s')" - "OR bonobo:supported_uri_schemes.has ('*'))" - - /* Check that the component doesn't require - * particular MIME types. Note that even saying you support "all" - */ - "AND (NOT bonobo:supported_mime_types.defined ()))" - - /* FIXME bugzilla.eazel.com 2542: improve the comment explaining this. */ - - /* This attribute allows uri schemes to be supported - even for unsupported mime types or no mime type. */ - "OR (bonobo:additional_uri_schemes.has ('%s')" - "OR bonobo:additional_uri_schemes.has ('*')))" - - - /* Check that the component makes it clear that it's - * intended for Nautilus by providing a "view_as" - * name. We could instead support a default, but - * that would make components that are untested with - * Nautilus appear. */ - "AND nautilus:view_as_name.defined ())" - - /* Also select iids that were specifically requested - for this location, even if they do not otherwise - meet the requirements. */ - - "OR %s)" - - /* Make it possible to add extra requirements */ - " AND (%s)" - - /* The URI scheme for the %s above. */ - , uri_scheme, uri_scheme - - /* The explicit metafile iid query for the %s above. */ - , explicit_iid_query, - extra_requirements != NULL ? extra_requirements : "true"); - - return result; -} - - - -static GHashTable * -mime_type_list_to_hash_table (GList *types) -{ - GHashTable *result; - GList *p; - char *mime_type; - - result = g_hash_table_new (g_str_hash, g_str_equal); - - for (p = types; p != NULL; p = p->next) { - if (p->data != NULL) { - mime_type = (char *) (p->data); - - if (g_hash_table_lookup (result, mime_type) == NULL) { -#ifdef DEBUG_MJS - printf ("XXX content mime type: %s\n", mime_type); -#endif - g_hash_table_insert (result, g_strdup (mime_type), mime_type); - } - } - } - - return result; -} - -static void -free_key (gpointer key, - gpointer value, - gpointer user_data) -{ - g_free (key); -} - -static void -mime_type_hash_table_destroy (GHashTable *table) -{ - g_hash_table_foreach (table, free_key, NULL); - g_hash_table_destroy (table); -} - - - -static gboolean -server_has_content_requirements (OAF_ServerInfo *server) -{ - OAF_Property *prop; - - prop = oaf_server_info_prop_find (server, "nautilus:required_directory_content_mime_types"); - - if (prop == NULL || prop->v._d != OAF_P_STRINGV) { - return FALSE; - } else { - return TRUE; - } -} - -static gboolean -server_matches_content_requirements (OAF_ServerInfo *server, - GHashTable *type_table, - GList *explicit_iids) -{ - OAF_Property *prop; - GNOME_stringlist types; - guint i; - - /* Components explicitly requested in the metafile are not capability tested. */ - if (g_list_find_custom (explicit_iids, (gpointer) server->iid, (GCompareFunc) strcmp) != NULL) { - return TRUE; - } - - if (!server_has_content_requirements (server)) { - return TRUE; - } else { - prop = oaf_server_info_prop_find (server, "nautilus:required_directory_content_mime_types"); - - types = prop->v._u.value_stringv; - - for (i = 0; i < types._length; i++) { - if (g_hash_table_lookup (type_table, types._buffer[i]) != NULL) { - return TRUE; - } - } - } - - return FALSE; -} - - -static char *nautilus_sort_criteria[] = { - /* Prefer anything else over the loser view. */ - "iid != 'OAFIID:nautilus_content_loser:95901458-c68b-43aa-aaca-870ced11062d'", - /* Prefer anything else over the sample view. */ - "iid != 'OAFIID:nautilus_sample_content_view:45c746bc-7d64-4346-90d5-6410463b43ae'", - /* Sort alphabetically */ - "name", - NULL}; - - - -static GList * -nautilus_do_component_query (const char *mime_type, - const char *uri_scheme, - GList *item_mime_types, - gboolean ignore_content_mime_types, - GList *explicit_iids, - char **extra_sort_criteria, - char *extra_requirements, - CORBA_Environment *ev) -{ - OAF_ServerInfoList *oaf_result; - char *query; - GList *retval; - char **all_sort_criteria; - - oaf_result = NULL; - query = NULL; - - if (is_known_mime_type (mime_type)) { - query = make_oaf_query_with_known_mime_type (mime_type, uri_scheme, explicit_iids, extra_requirements); - } else { - query = make_oaf_query_with_uri_scheme_only (uri_scheme, explicit_iids, extra_requirements); - } - -#ifdef DEBUG_MJS - printf ("query: \"%s\"\n", query); -#endif - - all_sort_criteria = strv_concat (extra_sort_criteria, nautilus_sort_criteria);; - - oaf_result = oaf_query (query, all_sort_criteria, ev); - - g_free (all_sort_criteria); - g_free (query); - - retval = NULL; - - if (ev->_major == CORBA_NO_EXCEPTION && oaf_result != NULL && oaf_result->_length > 0) { - GHashTable *content_types; - guint i; - - content_types = mime_type_list_to_hash_table (item_mime_types); - - for (i = 0; i < oaf_result->_length; i++) { - OAF_ServerInfo *server; - - server = &oaf_result->_buffer[i]; - - if (ignore_content_mime_types || - server_matches_content_requirements (server, content_types, explicit_iids)) { - /* Hack to suppress the Bonobo_Sample_Text component, since the Nautilus text - * view is a superset and it's confusing for the user to be presented with both - */ - if (server->iid != NULL && strcmp (server->iid, "OAFIID:Bonobo_Sample_Text") != 0) { - retval = g_list_append - (retval, - OAF_ServerInfo_duplicate (server)); - } - } - } - - mime_type_hash_table_destroy (content_types); - } - - CORBA_free (oaf_result); - - return retval; -} - - -static GList * -str_list_difference (GList *a, - GList *b) -{ - GList *p; - GList *retval; - - retval = NULL; - - for (p = a; p != NULL; p = p->next) { - if (g_list_find_custom (b, p->data, (GCompareFunc) strcmp) == NULL) { - retval = g_list_prepend (retval, p->data); - } - } - - retval = g_list_reverse (retval); - return retval; -} - - -static int -strv_length (char **a) -{ - int i; - - for (i = 0; a != NULL && a[i] != NULL; i++) { - } - - return i; -} - -static char ** -strv_concat (char **a, - char **b) -{ - int a_length; - int b_length; - int i; - int j; - - char **result; - - a_length = strv_length (a); - b_length = strv_length (b); - - result = g_new0 (char *, a_length + b_length + 1); - - j = 0; - - for (i = 0; a != NULL && a[i] != NULL; i++) { - result[j] = a[i]; - j++; - } - - for (i = 0; b != NULL && b[i] != NULL; i++) { - result[j] = b[i]; - j++; - } - - result[j] = NULL; - - return result; -} - -static gboolean -application_supports_uri_scheme (gpointer data, - gpointer uri_scheme) -{ - GnomeVFSMimeApplication *application; - - g_assert (data != NULL); - application = (GnomeVFSMimeApplication *) data; - - /* The default supported uri scheme is "file" */ - if (application->supported_uri_schemes == NULL - && strcasecmp ((const char *) uri_scheme, "file") == 0) { - return TRUE; - } - return g_list_find_custom (application->supported_uri_schemes, - uri_scheme, - eel_strcasecmp_compare_func) != NULL; -} diff --git a/libnautilus-extensions/nautilus-mime-actions.h b/libnautilus-extensions/nautilus-mime-actions.h deleted file mode 100644 index 0c0b38d3d..000000000 --- a/libnautilus-extensions/nautilus-mime-actions.h +++ /dev/null @@ -1,80 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ - -/* nautilus-mime-actions.h - uri-specific versions of mime action functions - - Copyright (C) 2000 Eazel, Inc. - - The Gnome 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 Gnome 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 the Gnome 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. - - Authors: Maciej Stachowiak <mjs@eazel.com> -*/ - -#ifndef NAUTILUS_MIME_ACTIONS_H -#define NAUTILUS_MIME_ACTIONS_H - -#include <libgnomevfs/gnome-vfs-mime-handlers.h> - -#include <libnautilus-extensions/nautilus-file.h> - - -GList *nautilus_mime_actions_get_minimum_file_attributes (void); -GList *nautilus_mime_actions_get_full_file_attributes (void); -gboolean nautilus_mime_actions_file_needs_full_file_attributes (NautilusFile *file); -GnomeVFSMimeActionType nautilus_mime_get_default_action_type_for_file (NautilusFile *file); -GnomeVFSMimeAction * nautilus_mime_get_default_action_for_file (NautilusFile *file); -GnomeVFSMimeApplication *nautilus_mime_get_default_application_for_file (NautilusFile *file); -gboolean nautilus_mime_is_default_application_for_file_user_chosen (NautilusFile *file); -OAF_ServerInfo * nautilus_mime_get_default_component_for_file (NautilusFile *file); -gboolean nautilus_mime_is_default_component_for_file_user_chosen (NautilusFile *file); -GList * nautilus_mime_get_short_list_applications_for_file (NautilusFile *file); -GList * nautilus_mime_get_short_list_components_for_file (NautilusFile *file); -GList * nautilus_mime_get_all_applications_for_file (NautilusFile *file); -GList * nautilus_mime_get_all_components_for_file (NautilusFile *file); -gboolean nautilus_mime_has_any_components_for_file (NautilusFile *file); -gboolean nautilus_mime_has_any_applications_for_file (NautilusFile *file); -gboolean nautilus_mime_has_any_applications_for_file_type (NautilusFile *file); -GnomeVFSResult nautilus_mime_set_default_action_type_for_file (NautilusFile *file, - GnomeVFSMimeActionType action_type); -GnomeVFSResult nautilus_mime_set_default_application_for_file (NautilusFile *file, - const char *application_id); -GnomeVFSResult nautilus_mime_set_default_component_for_file (NautilusFile *file, - const char *component_iid); -/* Stored as delta to current user level */ -GnomeVFSResult nautilus_mime_set_short_list_applications_for_file (NautilusFile *file, - GList *components); -GnomeVFSResult nautilus_mime_add_application_to_short_list_for_file (NautilusFile *file, - const char *application_id); -GnomeVFSResult nautilus_mime_remove_application_from_short_list_for_file (NautilusFile *file, - const char *application_id); -GnomeVFSResult nautilus_mime_set_short_list_components_for_file (NautilusFile *file, - GList *components); -GnomeVFSResult nautilus_mime_add_component_to_short_list_for_file (NautilusFile *file, - const char *iid); -GnomeVFSResult nautilus_mime_remove_component_from_short_list_for_file (NautilusFile *file, - const char *iid); - -/* No way to override system list; can only add. */ -GnomeVFSResult nautilus_mime_extend_all_applications_for_file (NautilusFile *file, - GList *applications); -/* Only "user" entries may be removed. */ -GnomeVFSResult nautilus_mime_remove_from_all_applications_for_file (NautilusFile *file, - GList *applications); -gboolean nautilus_mime_has_any_components_for_uri_scheme (const char *uri_scheme); - - -/* No way to add to all components; oafinfo database assumed trusted in this regard. */ - -#endif /* NAUTILUS_MIME_ACTIONS_H */ diff --git a/libnautilus-extensions/nautilus-monitor.c b/libnautilus-extensions/nautilus-monitor.c deleted file mode 100644 index b90b3ab66..000000000 --- a/libnautilus-extensions/nautilus-monitor.c +++ /dev/null @@ -1,395 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- - - nautilus-monitor.c: file and directory change monitoring for nautilus - - Copyright (C) 2000, 2001 Eazel, Inc. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public - License along with this program; if not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. - - Authors: Seth Nickell <seth@eazel.com> - Darin Adler <darin@eazel.com> -*/ - -#include <config.h> -#include "nautilus-monitor.h" - -#include <eel/eel-glib-extensions.h> - -#ifdef HAVE_FAM_H - -#include "nautilus-file-changes-queue.h" -#include <fam.h> -#include <gdk/gdk.h> -#include <gmodule.h> -#include <libgnome/gnome-defs.h> -#include <libgnome/gnome-util.h> -#include <libgnomevfs/gnome-vfs-utils.h> - -/* Turn off this to make FAM calls the normal way rather than using - * GModule. This can be useful to check that the parameters to all the - * functions are still correct, but it won't link without configure - * and makefile changes. - */ -#define USE_FAM_AS_MODULE - -#ifndef USE_FAM_AS_MODULE - -#define CALL_FAM(f) FAM##f - -#else /* USE_FAM_AS_MODULE */ - -typedef struct { - const char *name; - gpointer *function; -} ModuleSymbolPair; - -static int (* pointer_FAMCancelMonitor) (FAMConnection *fc, - const FAMRequest *fr); -static int (* pointer_FAMClose) (FAMConnection *fc); -static int (* pointer_FAMMonitorDirectory) (FAMConnection *fc, - const char *filename, - FAMRequest *fr, - void *user_data); -static int (* pointer_FAMMonitorFile) (FAMConnection *fc, - const char *filename, - FAMRequest *fr, - void *user_data); -static int (* pointer_FAMOpen2) (FAMConnection *connection, - const char *name); -static int (* pointer_FAMNextEvent) (FAMConnection *fc, - FAMEvent *fe); -static int (* pointer_FAMPending) (FAMConnection *fc); - -static const ModuleSymbolPair fam_symbols[] = { -#define IMPORT_FAM(f) { "FAM" #f, (gpointer *) &pointer_FAM##f }, - IMPORT_FAM (CancelMonitor) - IMPORT_FAM (Close) - IMPORT_FAM (MonitorDirectory) - IMPORT_FAM (MonitorFile) - IMPORT_FAM (NextEvent) - IMPORT_FAM (Open2) - IMPORT_FAM (Pending) -#undef IMPORT_FAM -}; - -#define CALL_FAM(f) (* pointer_FAM##f) - -#endif /* USE_FAM_AS_MODULE */ - -struct NautilusMonitor { - FAMRequest request; -}; - -static gboolean got_connection; - -static void process_fam_notifications (gpointer callback_data, - int fd, - GdkInputCondition condition); - -/* singleton object, instantiate and connect if it doesn't already exist */ -static FAMConnection * -get_fam_connection (void) -{ - static gboolean tried_connection; - static FAMConnection connection; -#ifdef USE_FAM_AS_MODULE - char *path; - GModule *module; - guint i; -#endif - - /* Only try once. */ - if (tried_connection) { - if (!got_connection) { - return NULL; - } - } else { - tried_connection = TRUE; -#ifdef USE_FAM_AS_MODULE - path = g_module_build_path (NULL, "fam"); - module = g_module_open (path, 0); - g_free (path); - if (module == NULL) { - return NULL; - } - for (i = 0; i < EEL_N_ELEMENTS (fam_symbols); i++) { - if (!g_module_symbol (module, - fam_symbols[i].name, - fam_symbols[i].function)) { - return NULL; - } - } -#endif - if (CALL_FAM (Open2) (&connection, "Nautilus") != 0) { - return NULL; - } - - /* Make the main loop's select function watch the FAM - * connection's file descriptor for us. - */ - gdk_input_add (FAMCONNECTION_GETFD (&connection), - GDK_INPUT_READ, - process_fam_notifications, - NULL); - - got_connection = TRUE; - } - return &connection; -} - -static GHashTable * -get_request_hash_table (void) -{ - static GHashTable *table; - - if (table == NULL) { - table = eel_g_hash_table_new_free_at_exit - (NULL, NULL, "nautilus-monitor.c: FAM requests"); - } - return table; -} - -static char * -get_event_uri (const FAMEvent *event) -{ - const char *base_path; - char *path, *uri; - - /* FAM doesn't tell us when something is a full path and when - * it's just partial so we have to look and see if it starts - * with a /. - */ - if (event->filename[0] == '/') { - return gnome_vfs_get_uri_from_local_path (event->filename); - } - - /* Look up the directory registry that was used for this file - * notification and tack that on. - */ - base_path = g_hash_table_lookup (get_request_hash_table (), - GINT_TO_POINTER (FAMREQUEST_GETREQNUM (&event->fr))); - g_return_val_if_fail (base_path != NULL, NULL); - path = g_concat_dir_and_file (base_path, event->filename); - uri = gnome_vfs_get_uri_from_local_path (path); - g_free (path); - return uri; -} - -static void -process_fam_notifications (gpointer callback_data, int fd, GdkInputCondition condition) -{ - FAMConnection *connection; - FAMEvent event; - char *uri; - - connection = get_fam_connection (); - g_return_if_fail (connection != NULL); - - /* Process all the pending events right now. */ - - while (CALL_FAM (Pending) (connection)) { - if (CALL_FAM (NextEvent) (connection, &event) != 1) { - g_warning ("connection to FAM died"); - gdk_input_remove (fd); - CALL_FAM (Close) (connection); - got_connection = FALSE; - return; - } - - switch (event.code) { - case FAMChanged: - uri = get_event_uri (&event); - if (uri == NULL) { - break; - } - nautilus_file_changes_queue_file_changed (uri); - g_free (uri); - break; - - case FAMDeleted: - uri = get_event_uri (&event); - if (uri == NULL) { - break; - } - nautilus_file_changes_queue_file_removed (uri); - g_free (uri); - break; - - case FAMCreated: - uri = get_event_uri (&event); - if (uri == NULL) { - break; - } - nautilus_file_changes_queue_file_added (uri); - g_free (uri); - break; - - case FAMStartExecuting: - /* Emitted when a file you are monitoring is - * executed. This should work for both - * binaries and shell scripts. Nautilus is not - * doing anything with this yet. - */ - break; - - case FAMStopExecuting: - /* Emitted when a file you are monitoring - * ceases execution. Nautilus is not doing - * anything with this yet. - */ - break; - - case FAMAcknowledge: - /* Called in response to a successful - * CancelMonitor. We don't need to do anything - * with this information. - */ - break; - - case FAMExists: - /* Emitted when you start monitoring a - * directory. It tells you what's in the - * directory. Unhandled because Nautilus - * already handles this by calling - * gnome_vfs_directory_load, which gives us - * more information than merely the file name. - */ - break; - - case FAMEndExist: - /* Emitted at the end of a FAMExists stream. */ - break; - - case FAMMoved: - /* FAMMoved doesn't need to be handled because - * FAM never seems to generate this event on - * Linux systems (w/ or w/o IMON). Instead it - * generates a FAMDeleted followed by a - * FAMCreated. - */ - g_warning ("unexpected FAMMoved notification"); - break; - } - } - - nautilus_file_changes_consume_changes (TRUE); -} - -#endif /* HAVE_FAM_H */ - -gboolean -nautilus_monitor_active (void) -{ -#ifndef HAVE_FAM_H - return FALSE; -#else - return get_fam_connection () != NULL; -#endif -} - -NautilusMonitor * -nautilus_monitor_file (const char *uri) -{ -#ifndef HAVE_FAM_H - return NULL; -#else - FAMConnection *connection; - char *path; - NautilusMonitor *monitor; - - connection = get_fam_connection (); - if (connection == NULL) { - return NULL; - } - - path = gnome_vfs_get_local_path_from_uri (uri); - if (path == NULL) { - return NULL; - } - - monitor = g_new0 (NautilusMonitor, 1); - CALL_FAM (MonitorFile) (connection, path, &monitor->request, NULL); - - g_free (path); - - return monitor; -#endif -} - - - -NautilusMonitor * -nautilus_monitor_directory (const char *uri) -{ -#ifndef HAVE_FAM_H - return NULL; -#else - FAMConnection *connection; - char *path; - NautilusMonitor *monitor; - - connection = get_fam_connection (); - if (connection == NULL) { - return NULL; - } - - path = gnome_vfs_get_local_path_from_uri (uri); - if (path == NULL) { - return NULL; - } - - monitor = g_new0 (NautilusMonitor, 1); - CALL_FAM (MonitorDirectory) (connection, path, &monitor->request, NULL); - - g_assert (g_hash_table_lookup (get_request_hash_table (), - GINT_TO_POINTER (FAMREQUEST_GETREQNUM (&monitor->request))) == NULL); - - g_hash_table_insert (get_request_hash_table (), - GINT_TO_POINTER (FAMREQUEST_GETREQNUM (&monitor->request)), - path); - - return monitor; -#endif -} - -void -nautilus_monitor_cancel (NautilusMonitor *monitor) -{ -#ifndef HAVE_FAM_H - g_return_if_fail (monitor == NULL); -#else - FAMConnection *connection; - int reqnum; - char *path; - - if (monitor == NULL) { - return; - } - - reqnum = FAMREQUEST_GETREQNUM (&monitor->request); - path = g_hash_table_lookup (get_request_hash_table (), - GINT_TO_POINTER (reqnum)); - g_hash_table_remove (get_request_hash_table (), - GINT_TO_POINTER (reqnum)); - g_free (path); - - connection = get_fam_connection (); - g_return_if_fail (connection != NULL); - - CALL_FAM (CancelMonitor) (connection, &monitor->request); - g_free (monitor); -#endif -} diff --git a/libnautilus-extensions/nautilus-monitor.h b/libnautilus-extensions/nautilus-monitor.h deleted file mode 100644 index 35d990323..000000000 --- a/libnautilus-extensions/nautilus-monitor.h +++ /dev/null @@ -1,38 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- - - nautilus-monitor.h: file and directory change monitoring for nautilus - - Copyright (C) 2000, 2001 Eazel, Inc. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public - License along with this program; if not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. - - Authors: Seth Nickell <seth@eazel.com> - Darin Adler <darin@eazel.com> -*/ - -#ifndef NAUTILUS_MONITOR_H -#define NAUTILUS_MONITOR_H - -#include <glib.h> - -typedef struct NautilusMonitor NautilusMonitor; - -gboolean nautilus_monitor_active (void); -NautilusMonitor *nautilus_monitor_file (const char *uri); -NautilusMonitor *nautilus_monitor_directory (const char *uri); -void nautilus_monitor_cancel (NautilusMonitor *monitor); - -#endif /* NAUTILUS_MONITOR_H */ diff --git a/libnautilus-extensions/nautilus-preferences-box.c b/libnautilus-extensions/nautilus-preferences-box.c deleted file mode 100644 index 18d96e00c..000000000 --- a/libnautilus-extensions/nautilus-preferences-box.c +++ /dev/null @@ -1,573 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ - -/* nautilus-prefs-box.h - Implementation for preferences box component. - - Copyright (C) 1999, 2000, 2001 Eazel, Inc. - - The Gnome 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 Gnome 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 the Gnome 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. - - Authors: Ramiro Estrugo <ramiro@eazel.com> -*/ - - -#include <config.h> -#include "nautilus-preferences-box.h" - -#include <eel/eel-gtk-macros.h> -#include <eel/eel-string.h> -#include <gtk/gtkclist.h> -#include <gtk/gtknotebook.h> -#include <eel/eel-gtk-extensions.h> -#include <libgnome/gnome-i18n.h> -#include <libgnome/gnome-util.h> -#include <libgnomeui/gnome-stock.h> - -#define NUM_CATEGORY_COLUMNS 1 -#define CATEGORY_COLUMN 0 -#define SPACING_BETWEEN_CATEGORIES_AND_PANES 4 -#define STRING_LIST_DEFAULT_TOKENS_DELIMETER "," - -typedef struct -{ - char *pane_name; - NautilusPreferencesPane *pane_widget; -} PaneInfo; - -struct NautilusPreferencesBoxDetails -{ - GtkWidget *category_list; - GtkWidget *pane_notebook; - GList *panes; - char *selected_pane; - guint select_row_signal_id; -}; - -/* NautilusPreferencesBoxClass methods */ -static void nautilus_preferences_box_initialize_class (NautilusPreferencesBoxClass *preferences_box_class); -static void nautilus_preferences_box_initialize (NautilusPreferencesBox *preferences_box); - - - -/* GtkObjectClass methods */ -static void nautilus_preferences_box_destroy (GtkObject *object); - -/* Misc private stuff */ -static void preferences_box_category_list_recreate (NautilusPreferencesBox *preferences_box); -static void preferences_box_select_pane (NautilusPreferencesBox *preferences_box, - const char *name); - -/* PaneInfo functions */ -static PaneInfo *pane_info_new (const char *pane_name); -static void pane_info_free (PaneInfo *info); - -/* Category list callbacks */ -static void category_list_select_row_callback (GtkCList *clist, - int row, - int column, - GdkEventButton *event, - gpointer user_data); - -/* Convience functions */ -static int preferences_box_find_row (GtkCList *clist, - char *pane_name); -static void user_level_changed_callback (gpointer callback_data); - -EEL_DEFINE_CLASS_BOILERPLATE (NautilusPreferencesBox, nautilus_preferences_box, GTK_TYPE_HBOX) - -/* - * NautilusPreferencesBoxClass methods - */ -static void -nautilus_preferences_box_initialize_class (NautilusPreferencesBoxClass *preferences_box_class) -{ - GtkObjectClass *object_class; - - object_class = GTK_OBJECT_CLASS (preferences_box_class); - - /* GtkObjectClass */ - object_class->destroy = nautilus_preferences_box_destroy; -} - -static void -nautilus_preferences_box_initialize (NautilusPreferencesBox *preferences_box) -{ - preferences_box->details = g_new0 (NautilusPreferencesBoxDetails, 1); - - nautilus_preferences_add_callback_while_alive ("user_level", - user_level_changed_callback, - preferences_box, - GTK_OBJECT (preferences_box)); -} - -/* - * GtkObjectClass methods - */ -static void -nautilus_preferences_box_destroy (GtkObject *object) -{ - NautilusPreferencesBox *preferences_box; - - g_return_if_fail (NAUTILUS_IS_PREFERENCES_BOX (object)); - - preferences_box = NAUTILUS_PREFERENCES_BOX (object); - - if (preferences_box->details->panes) { - GList *panes; - - panes = preferences_box->details->panes; - - while (panes) { - PaneInfo * info = panes->data; - - g_assert (info != NULL); - pane_info_free (info); - panes = panes->next; - } - - g_list_free (preferences_box->details->panes); - } - - g_free (preferences_box->details->selected_pane); - g_free (preferences_box->details); - - /* Chain destroy */ - EEL_CALL_PARENT (GTK_OBJECT_CLASS, destroy, (object)); -} - -/* - * Misc private stuff - */ -static void -preferences_box_select_pane (NautilusPreferencesBox *preferences_box, - const char *pane_name) -{ - GList *pane_iterator; - - g_return_if_fail (NAUTILUS_IS_PREFERENCES_BOX (preferences_box)); - g_return_if_fail (preferences_box->details != NULL); - g_return_if_fail (preferences_box->details->panes != NULL); - g_return_if_fail (pane_name != NULL); - - /* Show only the corresponding pane widget */ - pane_iterator = preferences_box->details->panes; - - while (pane_iterator) { - PaneInfo *info = pane_iterator->data; - - g_assert (info != NULL); - - if (eel_str_is_equal (pane_name, info->pane_name)) { - gtk_widget_show (GTK_WIDGET (info->pane_widget)); - gtk_notebook_set_page (GTK_NOTEBOOK (preferences_box->details->pane_notebook), - g_list_position (preferences_box->details->panes, pane_iterator)); - - g_free (preferences_box->details->selected_pane); - preferences_box->details->selected_pane = g_strdup (pane_name); - return; - } - - pane_iterator = pane_iterator->next; - } - - g_warning ("Pane '%s' could not be found.", pane_name); -} - -static int -preferences_box_find_row (GtkCList *clist, char *pane_name) -{ - int i; - char *pane = NULL; - - for (i=0; i < GTK_CLIST (clist)->rows; i++) { - gtk_clist_get_text (GTK_CLIST (clist), i, 0, &pane); - - if (eel_str_is_equal (pane, pane_name)) { - return i; - } - } - - return -1; -} - -static void -preferences_box_category_list_recreate (NautilusPreferencesBox *preferences_box) -{ - GList *iterator; - int row = 0; - - g_return_if_fail (NAUTILUS_IS_PREFERENCES_BOX (preferences_box)); - g_return_if_fail (GTK_IS_CLIST (preferences_box->details->category_list)); - - /* Block the select_row signal so that the 1st item doesnt get selected. - * Otherwise, we lose the selected_pane. - */ - g_assert (preferences_box->details->select_row_signal_id != 0); - gtk_signal_handler_block (GTK_OBJECT (preferences_box->details->category_list), - preferences_box->details->select_row_signal_id); - - gtk_clist_clear (GTK_CLIST (preferences_box->details->category_list)); - - for (iterator = preferences_box->details->panes; iterator != NULL; iterator = iterator->next) { - PaneInfo *info = iterator->data; - - g_assert (NAUTILUS_IS_PREFERENCES_PANE (info->pane_widget)); - - if (nautilus_preferences_pane_get_num_visible_groups (info->pane_widget) > 0) { - char *text_array[NUM_CATEGORY_COLUMNS]; - - text_array[CATEGORY_COLUMN] = info->pane_name; - gtk_clist_append (GTK_CLIST (preferences_box->details->category_list), text_array); - - if (eel_str_is_equal (info->pane_name, preferences_box->details->selected_pane)) { - row = preferences_box_find_row (GTK_CLIST (preferences_box->details->category_list), - info->pane_name); - - if (row == -1) { - row = 0; - } - } - } - } - - gtk_signal_handler_unblock (GTK_OBJECT (preferences_box->details->category_list), - preferences_box->details->select_row_signal_id); - - /* You have to do this to get the highlighted row in the clist to change for some reason */ - gtk_clist_select_row (GTK_CLIST (preferences_box->details->category_list), row, 0); - - category_list_select_row_callback (GTK_CLIST (preferences_box->details->category_list), - row, - 0, - NULL, - preferences_box); -} - -/* - * PaneInfo functions - */ -static PaneInfo * -pane_info_new (const char *pane_name) -{ - PaneInfo * info; - - g_assert (pane_name != NULL); - - info = g_new0 (PaneInfo, 1); - - info->pane_name = g_strdup (pane_name); - - return info; -} - -static void -pane_info_free (PaneInfo *info) -{ - g_assert (info != NULL); - - g_free (info->pane_name); - g_free (info); -} - -/* - * Category list callbacks - */ -static void -category_list_select_row_callback (GtkCList *clist, - int row, - int column, - GdkEventButton *event, - gpointer callback_data) -{ - const char *pane_name = NULL; - - g_return_if_fail (NAUTILUS_IS_PREFERENCES_BOX (callback_data)); - - /* The cast here is needed because of the broken gtk_clist api */ - if (gtk_clist_get_text (clist, row, CATEGORY_COLUMN, (char **) &pane_name) != 1) { - return; - } - - g_return_if_fail (pane_name != NULL); - - preferences_box_select_pane (NAUTILUS_PREFERENCES_BOX (callback_data), pane_name); -} - -/* - * NautilusPreferencesBox public methods - */ -GtkWidget* -nautilus_preferences_box_new (void) -{ - NautilusPreferencesBox *preferences_box; - - preferences_box = NAUTILUS_PREFERENCES_BOX - (gtk_widget_new (nautilus_preferences_box_get_type (), NULL)); - - /* Configure ourselves */ - gtk_box_set_homogeneous (GTK_BOX (preferences_box), FALSE); - gtk_box_set_spacing (GTK_BOX (preferences_box), SPACING_BETWEEN_CATEGORIES_AND_PANES); - - /* The category list */ - preferences_box->details->category_list = gtk_clist_new (NUM_CATEGORY_COLUMNS); - - preferences_box->details->select_row_signal_id = - gtk_signal_connect (GTK_OBJECT (preferences_box->details->category_list), - "select_row", - GTK_SIGNAL_FUNC (category_list_select_row_callback), - preferences_box); - - gtk_clist_set_selection_mode (GTK_CLIST (preferences_box->details->category_list), - GTK_SELECTION_BROWSE); - - gtk_clist_set_column_auto_resize (GTK_CLIST (preferences_box->details->category_list), - CATEGORY_COLUMN, - TRUE); - - gtk_box_pack_start (GTK_BOX (preferences_box), - preferences_box->details->category_list, - FALSE, - TRUE, - 0); - - /* The gtk notebook that the panes go into. */ - preferences_box->details->pane_notebook = gtk_notebook_new (); - - gtk_notebook_set_show_tabs (GTK_NOTEBOOK (preferences_box->details->pane_notebook), FALSE); - gtk_notebook_set_show_border (GTK_NOTEBOOK (preferences_box->details->pane_notebook), FALSE); - - gtk_box_pack_start (GTK_BOX (preferences_box), - preferences_box->details->pane_notebook, - TRUE, - TRUE, - 0); - - gtk_widget_show (preferences_box->details->category_list); - gtk_widget_show (preferences_box->details->pane_notebook); - - return GTK_WIDGET (preferences_box); -} - -static NautilusPreferencesPane * -preferences_box_add_pane (NautilusPreferencesBox *preferences_box, - const char *pane_title) -{ - PaneInfo *info; - - g_return_val_if_fail (NAUTILUS_IS_PREFERENCES_BOX (preferences_box), NULL); - g_return_val_if_fail (pane_title != NULL, NULL); - - info = pane_info_new (pane_title); - - preferences_box->details->panes = g_list_append (preferences_box->details->panes, info); - - info->pane_widget = NAUTILUS_PREFERENCES_PANE (nautilus_preferences_pane_new ()); - - gtk_notebook_append_page (GTK_NOTEBOOK (preferences_box->details->pane_notebook), - GTK_WIDGET (info->pane_widget), - NULL); - - return info->pane_widget; -} - -void -nautilus_preferences_box_update (NautilusPreferencesBox *preferences_box) -{ - GList *iterator; - - g_return_if_fail (NAUTILUS_IS_PREFERENCES_BOX (preferences_box)); - - for (iterator = preferences_box->details->panes; iterator != NULL; iterator = iterator->next) { - PaneInfo *info = iterator->data; - - g_assert (NAUTILUS_IS_PREFERENCES_PANE (info->pane_widget)); - - nautilus_preferences_pane_update (info->pane_widget); - } - - preferences_box_category_list_recreate (preferences_box); -} - -static NautilusPreferencesPane * -preferences_box_find_pane (const NautilusPreferencesBox *preferences_box, - const char *pane_name) -{ - GList *node; - PaneInfo *info; - - g_return_val_if_fail (NAUTILUS_IS_PREFERENCES_BOX (preferences_box), FALSE); - - for (node = preferences_box->details->panes; node != NULL; node = node->next) { - g_assert (node->data != NULL); - info = node->data; - if (eel_str_is_equal (info->pane_name, pane_name)) { - return info->pane_widget; - } - } - - return NULL; -} - -static void -preferences_box_populate_pane (NautilusPreferencesBox *preferences_box, - const char *pane_name, - const NautilusPreferencesItemDescription *items) -{ - NautilusPreferencesPane *pane; - NautilusPreferencesGroup *group; - NautilusPreferencesItem *item; - EelStringList *group_names; - const char *translated_group_name; - guint i; - - g_return_if_fail (NAUTILUS_IS_PREFERENCES_BOX (preferences_box)); - g_return_if_fail (pane_name != NULL); - g_return_if_fail (items != NULL); - - /* Create the pane if needed */ - pane = preferences_box_find_pane (preferences_box, pane_name); - if (pane == NULL) { - pane = NAUTILUS_PREFERENCES_PANE (preferences_box_add_pane (preferences_box, pane_name)); - } - - group_names = eel_string_list_new (TRUE); - - for (i = 0; items[i].group_name != NULL; i++) { - translated_group_name = _(items[i].group_name); - if (!eel_string_list_contains (group_names, translated_group_name)) { - eel_string_list_insert (group_names, translated_group_name); - nautilus_preferences_pane_add_group (pane, - translated_group_name); - } - } - - for (i = 0; items[i].group_name != NULL; i++) { - group = NAUTILUS_PREFERENCES_GROUP (nautilus_preferences_pane_find_group (pane, - _(items[i].group_name))); - g_return_if_fail (NAUTILUS_IS_PREFERENCES_GROUP (group)); - - if (items[i].preference_name != NULL) { - if (items[i].preference_description != NULL) { - nautilus_preferences_set_description (items[i].preference_name, - _(items[i].preference_description)); - } - - item = NAUTILUS_PREFERENCES_ITEM (nautilus_preferences_group_add_item (group, - items[i].preference_name, - items[i].item_type, - items[i].column)); - - /* Install a control preference if needed */ - if (items[i].control_preference_name != NULL) { - nautilus_preferences_item_set_control_preference (item, - items[i].control_preference_name); - nautilus_preferences_item_set_control_action (item, - items[i].control_action); - nautilus_preferences_pane_add_control_preference (pane, - items[i].control_preference_name); - } - - /* Install exceptions to enum lists uniqueness rule */ - if (items[i].enumeration_list_unique_exceptions != NULL) { - g_assert (items[i].item_type == NAUTILUS_PREFERENCE_ITEM_ENUMERATION_LIST_VERTICAL - || items[i].item_type == NAUTILUS_PREFERENCE_ITEM_ENUMERATION_LIST_HORIZONTAL); - nautilus_preferences_item_enumeration_list_set_unique_exceptions (item, - items[i].enumeration_list_unique_exceptions, - STRING_LIST_DEFAULT_TOKENS_DELIMETER); - } - } - - if (items[i].populate_function != NULL) { - (* items[i].populate_function) (group); - } - } - - eel_string_list_free (group_names); -} - -void -nautilus_preferences_box_populate (NautilusPreferencesBox *preferences_box, - const NautilusPreferencesPaneDescription *panes) -{ - guint i; - - g_return_if_fail (NAUTILUS_IS_PREFERENCES_BOX (preferences_box)); - g_return_if_fail (panes != NULL); - - for (i = 0; panes[i].pane_name != NULL; i++) { - preferences_box_populate_pane (preferences_box, - _(panes[i].pane_name), - panes[i].items); - } - - nautilus_preferences_box_update (preferences_box); -} - -static void -user_level_changed_callback (gpointer callback_data) -{ - g_return_if_fail (NAUTILUS_IS_PREFERENCES_BOX (callback_data)); - - nautilus_preferences_box_update (NAUTILUS_PREFERENCES_BOX (callback_data)); -} - -GtkWidget * -nautilus_preferences_dialog_new (const char *title, - const NautilusPreferencesPaneDescription *panes) -{ - static const char *stock_buttons[] = { - GNOME_STOCK_BUTTON_OK, - NULL - }; - GtkWidget *dialog; - GtkWidget *preference_box; - GtkWidget *vbox; - - g_return_val_if_fail (title != NULL, NULL); - g_return_val_if_fail (panes != NULL, NULL); - - dialog = gnome_dialog_newv (title, stock_buttons); - - /* Setup the dialog */ - gtk_window_set_policy (GTK_WINDOW (dialog), - FALSE, /* allow_shrink */ - TRUE, /* allow_grow */ - FALSE); /* auto_shrink */ - - gtk_container_set_border_width (GTK_CONTAINER (dialog), 0); - - gnome_dialog_set_default (GNOME_DIALOG(dialog), 0); - - eel_gtk_window_set_up_close_accelerator (GTK_WINDOW (dialog)); - - preference_box = nautilus_preferences_box_new (); - - vbox = GNOME_DIALOG (dialog)->vbox; - - gtk_box_set_spacing (GTK_BOX (vbox), 10); - - gtk_box_pack_start (GTK_BOX (vbox), - preference_box, - TRUE, /* expand */ - TRUE, /* fill */ - 0); /* padding */ - - gtk_widget_show (preference_box); - - nautilus_preferences_box_populate (NAUTILUS_PREFERENCES_BOX (preference_box), - panes); - - return dialog; -} diff --git a/libnautilus-extensions/nautilus-preferences-box.h b/libnautilus-extensions/nautilus-preferences-box.h deleted file mode 100644 index cf373d65a..000000000 --- a/libnautilus-extensions/nautilus-preferences-box.h +++ /dev/null @@ -1,180 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ - -/* nautilus-prefs-box.h - Interface for preferences box component. - - Copyright (C) 1999, 2000 Eazel, Inc. - - The Gnome 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 Gnome 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 the Gnome 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. - - Authors: Ramiro Estrugo <ramiro@eazel.com> -*/ - -#ifndef NAUTILUS_PREFERENCES_BOX_H -#define NAUTILUS_PREFERENCES_BOX_H - -#include <libgnomeui/gnome-dialog.h> -#include <gtk/gtkhbox.h> -#include <libnautilus-extensions/nautilus-preferences-pane.h> - -BEGIN_GNOME_DECLS - -#define NAUTILUS_TYPE_PREFERENCES_BOX (nautilus_preferences_box_get_type ()) -#define NAUTILUS_PREFERENCES_BOX(obj) (GTK_CHECK_CAST ((obj), NAUTILUS_TYPE_PREFERENCES_BOX, NautilusPreferencesBox)) -#define NAUTILUS_PREFERENCES_BOX_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), NAUTILUS_TYPE_PREFERENCES_BOX, NautilusPreferencesBoxClass)) -#define NAUTILUS_IS_PREFERENCES_BOX(obj) (GTK_CHECK_TYPE ((obj), NAUTILUS_TYPE_PREFERENCES_BOX)) -#define NAUTILUS_IS_PREFERENCES_BOX_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), NAUTILUS_TYPE_PREFERENCES_BOX)) - -typedef struct NautilusPreferencesBox NautilusPreferencesBox; -typedef struct NautilusPreferencesBoxClass NautilusPreferencesBoxClass; -typedef struct NautilusPreferencesBoxDetails NautilusPreferencesBoxDetails; - -struct NautilusPreferencesBox -{ - /* Super Class */ - GtkHBox hbox; - - /* Private stuff */ - NautilusPreferencesBoxDetails *details; -}; - -struct NautilusPreferencesBoxClass -{ - GtkHBoxClass parent_class; -}; - -/* - * A callback which you can register to to be notified when a particular - * preference changes. - */ -typedef void (*NautilusPreferencesGroupPopulateFunction) (NautilusPreferencesGroup *group); - -/* A structure that describes a single preferences dialog ui item. */ -typedef struct -{ - const char *group_name; - const char *preference_name; - const char *preference_description; - NautilusPreferencesItemType item_type; - const char *control_preference_name; - NautilusPreferencesItemControlAction control_action; - int column; - NautilusPreferencesGroupPopulateFunction populate_function; - const char *enumeration_list_unique_exceptions; -} NautilusPreferencesItemDescription; - -typedef struct -{ - const char *pane_name; - const NautilusPreferencesItemDescription *items; -} NautilusPreferencesPaneDescription; - -/* The following tables define preference items for the preferences dialog. - * Each item corresponds to one preference. - * - * Field definitions: - * - * 1. group_name - * - * The group under which the preference is placed. Each unique group will - * be framed and titled with the group_name. - * - * Many items can have the same group_name. Groups will be created as needed - * while populating the items. - * - * This field needs to be non NULL. - * - * 2. preference_name - * - * The name of the preference - * - * This field needs to be non NULL. - * - * 3. preference_description - * - * A user visible description of the preference. Not all items use the - * description. In particular, enumeration items use the descriptions from - * an enumeration structure. See field XX below. - * - * This field needs to be non NULL for items other than: - * - * NAUTILUS_PREFERENCE_ITEM_ENUMERATION_VERTICAL_RADIO or - * NAUTILUS_PREFERENCE_ITEM_ENUMERATION_HORIZONTAL_RADIO - * - * 4. item_type - * - * The type of the item. Needs to be one of the valid values of - * NautilusPreferencesItemType. See nautilus-preference-item.h. - * - * This field needs to be one of the valid item types. - * - * 5. control_preference_name - * - * A second preference that "controls" this preference. Can only - * be a boolean preference. - * - * This field can be NULL, in which case field 6 is ignored. - * - * 6. control_action - * - * The action to take when the control preference in field 5 changes. - * There are only 2 possible actions: - * - * NAUTILUS_PREFERENCE_ITEM_SHOW - If the control preference is TRUE - * the show this item. - * - * NAUTILUS_PREFERENCE_ITEM_HIDE - If the control preference is FALSE - * the hide this item. - * - * 7. column - * - * A preference pane is composed of groups. Each group is bounded by - * a frame. Each of these groups can have 0 or 1 columns of preference - * item widgets. This field controls which column the preference item - * widgets appear in. - * - * 8. populate_function: - * - * Something. - * - * 9. enumeration_list_unique_exceptions - * If the item type is one of: - * - * NAUTILUS_PREFERENCE_ITEM_ENUMERATION_LIST_HORIZONTAL - * NAUTILUS_PREFERENCE_ITEM_ENUMERATION_LIST_VERTICAL - * - * The this field can be a string of exceptions to the rule that enumeration - * list items must always not allow duplicate choices. For example, if there - * are 3 string pickers in the item, then each one cannot select and item - * which is already selected in one of the other two. The preferences item - * widget enforces this rule by making such items insensitive. - * - * The enumeration_list_unique_exceptions allows a way to bypass this rule - * for certain choices. - */ - -GtkType nautilus_preferences_box_get_type (void); -GtkWidget* nautilus_preferences_box_new (void); -void nautilus_preferences_box_update (NautilusPreferencesBox *preferences_box); -void nautilus_preferences_box_populate (NautilusPreferencesBox *preferences_box, - const NautilusPreferencesPaneDescription *panes); -GtkWidget *nautilus_preferences_dialog_new (const char *title, - const NautilusPreferencesPaneDescription *panes); - -END_GNOME_DECLS - -#endif /* NAUTILUS_PREFERENCES_BOX_H */ - - diff --git a/libnautilus-extensions/nautilus-preferences-group.c b/libnautilus-extensions/nautilus-preferences-group.c deleted file mode 100644 index 02b4ab6ab..000000000 --- a/libnautilus-extensions/nautilus-preferences-group.c +++ /dev/null @@ -1,302 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ - -/* nautilus-preferences-group.c - A group of preferences items bounded by a frame. - - Copyright (C) 1999, 2000 Eazel, Inc. - - The Gnome 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 Gnome 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 the Gnome 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. - - Authors: Ramiro Estrugo <ramiro@eazel.com> -*/ - -#include <config.h> -#include "nautilus-preferences-group.h" - -#include <eel/eel-gtk-extensions.h> -#include <eel/eel-gtk-macros.h> -#include <gnome.h> - -struct NautilusPreferencesGroupDetails -{ - GtkWidget *main_box; - GtkWidget *columns[2]; - GList *items[2]; -}; - -/* NautilusPreferencesGroupClass methods */ -static void nautilus_preferences_group_initialize_class (NautilusPreferencesGroupClass *klass); -static void nautilus_preferences_group_initialize (NautilusPreferencesGroup *preferences_group); - -/* GtkObjectClass methods */ -static void nautilus_preferences_group_destroy (GtkObject *object); - -EEL_DEFINE_CLASS_BOILERPLATE (NautilusPreferencesGroup, - nautilus_preferences_group, - GTK_TYPE_FRAME); - -/* - * NautilusPreferencesGroupClass methods - */ -static void -nautilus_preferences_group_initialize_class (NautilusPreferencesGroupClass *preferences_group_class) -{ - GtkObjectClass *object_class; - - object_class = GTK_OBJECT_CLASS (preferences_group_class); - - /* GtkObjectClass */ - object_class->destroy = nautilus_preferences_group_destroy; -} - -static void -nautilus_preferences_group_initialize (NautilusPreferencesGroup *group) -{ - group->details = g_new0 (NautilusPreferencesGroupDetails, 1); -} - -/* - * GtkObjectClass methods - */ -static void -nautilus_preferences_group_destroy (GtkObject *object) -{ - NautilusPreferencesGroup *group; - - g_return_if_fail (NAUTILUS_IS_PREFERENCES_GROUP (object)); - - group = NAUTILUS_PREFERENCES_GROUP (object); - - g_list_free (group->details->items[0]); - g_list_free (group->details->items[1]); - g_free (group->details); - - /* Chain destroy */ - EEL_CALL_PARENT (GTK_OBJECT_CLASS, destroy, (object)); -} - -/* - * NautilusPreferencesGroup public methods - */ -GtkWidget * -nautilus_preferences_group_new (const gchar *title) -{ - NautilusPreferencesGroup *group; - - g_return_val_if_fail (title != NULL, NULL); - - group = NAUTILUS_PREFERENCES_GROUP - (gtk_widget_new (nautilus_preferences_group_get_type (), NULL)); - - /* Ourselves */ - gtk_frame_set_shadow_type (GTK_FRAME (group), GTK_SHADOW_ETCHED_IN); - - gtk_frame_set_label (GTK_FRAME (group), title); - - /* Main box */ - group->details->main_box = gtk_hbox_new (FALSE, 20); - gtk_container_add (GTK_CONTAINER (group), group->details->main_box); - - /* Column 1 */ - group->details->columns[0] = gtk_vbox_new (TRUE, 0); - gtk_box_pack_start (GTK_BOX (group->details->main_box), - group->details->columns[0], - TRUE, - TRUE, - 0); - - /* Column 2 */ - group->details->columns[1] = gtk_vbox_new (TRUE, 0); - gtk_box_pack_start (GTK_BOX (group->details->main_box), - group->details->columns[1], - TRUE, - TRUE, - 0); - - gtk_container_set_border_width (GTK_CONTAINER (group->details->columns[0]), 6); - - gtk_widget_show (group->details->columns[0]); - gtk_widget_show (group->details->columns[1]); - gtk_widget_show (group->details->main_box); - - return GTK_WIDGET (group); -} - -GtkWidget * -nautilus_preferences_group_add_item (NautilusPreferencesGroup *group, - const char *preference_name, - NautilusPreferencesItemType item_type, - int column) -{ - GtkWidget *item; - - g_return_val_if_fail (NAUTILUS_IS_PREFERENCES_GROUP (group), NULL); - g_return_val_if_fail (preference_name != NULL, NULL); - g_return_val_if_fail (column >= 0, NULL); - g_return_val_if_fail (column <= 1, NULL); - - item = nautilus_preferences_item_new (preference_name, item_type); - - group->details->items[column] = g_list_append (group->details->items[column], - item); - - gtk_box_pack_start (GTK_BOX (group->details->columns[column]), - item, - FALSE, - FALSE, - 0); - - gtk_widget_show (item); - - return item; -} - -GtkWidget * -nautilus_preferences_group_add_custom_item (NautilusPreferencesGroup *group, - const char *preference_name, - GtkWidget *child, - const char *signal_name, - int column) -{ - GtkWidget *item; - - g_return_val_if_fail (NAUTILUS_IS_PREFERENCES_GROUP (group), NULL); - g_return_val_if_fail (preference_name != NULL, NULL); - g_return_val_if_fail (GTK_IS_WIDGET (child), NULL); - g_return_val_if_fail (signal_name != NULL, NULL); - g_return_val_if_fail (column >= 0, NULL); - g_return_val_if_fail (column <= 1, NULL); - - item = nautilus_preferences_item_new_custom (preference_name, - child, - signal_name); - - group->details->items[column] = g_list_append (group->details->items[column], - item); - - gtk_box_pack_start (GTK_BOX (group->details->columns[column]), - item, - FALSE, - FALSE, - 0); - - gtk_widget_show (item); - - return item; -} - -void -nautilus_preferences_group_update (NautilusPreferencesGroup *group) -{ - GList *node; - - g_return_if_fail (NAUTILUS_IS_PREFERENCES_GROUP (group)); - - for (node = group->details->items[0]; node != NULL; node = node->next) { - g_assert (NAUTILUS_IS_PREFERENCES_ITEM (node->data)); - nautilus_preferences_item_update_showing (NAUTILUS_PREFERENCES_ITEM (node->data)); - } - - for (node = group->details->items[1]; node != NULL; node = node->next) { - g_assert (NAUTILUS_IS_PREFERENCES_ITEM (node->data)); - nautilus_preferences_item_update_showing (NAUTILUS_PREFERENCES_ITEM (node->data)); - } -} - -guint -nautilus_preferences_group_get_num_visible_items (const NautilusPreferencesGroup *group) -{ - guint n = 0; - GList *node; - - g_return_val_if_fail (NAUTILUS_IS_PREFERENCES_GROUP (group), 0); - - for (node = group->details->items[0]; node != NULL; node = node->next) { - if (nautilus_preferences_item_is_showing (NAUTILUS_PREFERENCES_ITEM (node->data))) { - n++; - } - } - - for (node = group->details->items[1]; node != NULL; node = node->next) { - if (nautilus_preferences_item_is_showing (NAUTILUS_PREFERENCES_ITEM (node->data))) { - n++; - } - } - - return n; -} - -char * -nautilus_preferences_group_get_title_label (const NautilusPreferencesGroup *group) -{ - g_return_val_if_fail (NAUTILUS_IS_PREFERENCES_GROUP (group), NULL); - - return g_strdup (GTK_FRAME (group)->label); -} - -int -nautilus_preferences_group_get_max_caption_width (const NautilusPreferencesGroup *group, - int column) -{ - GList *node; - NautilusPreferencesItem *item; - int max_caption_width = 0; - - g_return_val_if_fail (NAUTILUS_IS_PREFERENCES_GROUP (group), 0); - g_return_val_if_fail (column >= 0, 0); - g_return_val_if_fail (column <= 1, 0); - - for (node = group->details->items[column]; node != NULL; node = node->next) { - g_assert (NAUTILUS_IS_PREFERENCES_ITEM (node->data)); - item = NAUTILUS_PREFERENCES_ITEM (node->data); - - if (nautilus_preferences_item_is_showing (item) - && nautilus_preferences_item_child_is_caption (item)) { - max_caption_width = MAX (max_caption_width, - nautilus_preferences_item_get_child_width (item)); - } - } - - return max_caption_width; -} - -void -nautilus_preferences_group_align_captions (NautilusPreferencesGroup *group, - int max_caption_width, - int column) -{ - GList *node; - NautilusPreferencesItem *item; - int width; - - g_return_if_fail (NAUTILUS_IS_PREFERENCES_GROUP (group)); - g_return_if_fail (max_caption_width > 0); - g_return_if_fail (column >= 0); - g_return_if_fail (column <= 1); - - /* Set the spacing on all the captions */ - for (node = group->details->items[column]; node != NULL; node = node->next) { - g_assert (NAUTILUS_IS_PREFERENCES_ITEM (node->data)); - item = NAUTILUS_PREFERENCES_ITEM (node->data); - - if (nautilus_preferences_item_is_showing (item) - && nautilus_preferences_item_child_is_caption (item)) { - width = nautilus_preferences_item_get_child_width (item); - g_assert (width <= max_caption_width); - nautilus_preferences_item_set_caption_extra_spacing (item, max_caption_width - width); - } - } -} - diff --git a/libnautilus-extensions/nautilus-preferences-group.h b/libnautilus-extensions/nautilus-preferences-group.h deleted file mode 100644 index 76152aa7f..000000000 --- a/libnautilus-extensions/nautilus-preferences-group.h +++ /dev/null @@ -1,83 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ - -/* nautilus-preferences-group.h - A group of preferences items bounded by a frame. - - Copyright (C) 1999, 2000 Eazel, Inc. - - The Gnome 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 Gnome 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 the Gnome 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. - - Authors: Ramiro Estrugo <ramiro@eazel.com> -*/ - -#ifndef NAUTILUS_PREFERENCES_GROUP_H -#define NAUTILUS_PREFERENCES_GROUP_H - -#include <gtk/gtkframe.h> - -#include <libnautilus-extensions/nautilus-preferences.h> -#include <libnautilus-extensions/nautilus-preferences-item.h> - -BEGIN_GNOME_DECLS - -#define NAUTILUS_TYPE_PREFERENCES_GROUP (nautilus_preferences_group_get_type ()) -#define NAUTILUS_PREFERENCES_GROUP(obj) (GTK_CHECK_CAST ((obj), NAUTILUS_TYPE_PREFERENCES_GROUP, NautilusPreferencesGroup)) -#define NAUTILUS_PREFERENCES_GROUP_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), NAUTILUS_TYPE_PREFERENCES_GROUP, NautilusPreferencesGroupClass)) -#define NAUTILUS_IS_PREFERENCES_GROUP(obj) (GTK_CHECK_TYPE ((obj), NAUTILUS_TYPE_PREFERENCES_GROUP)) -#define NAUTILUS_IS_PREFERENCES_GROUP_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), NAUTILUS_TYPE_PREFERENCES_GROUP)) - -typedef struct NautilusPreferencesGroup NautilusPreferencesGroup; -typedef struct NautilusPreferencesGroupClass NautilusPreferencesGroupClass; -typedef struct NautilusPreferencesGroupDetails NautilusPreferencesGroupDetails; - -struct NautilusPreferencesGroup -{ - /* Super Class */ - GtkFrame frame; - - /* Private stuff */ - NautilusPreferencesGroupDetails *details; -}; - -struct NautilusPreferencesGroupClass -{ - GtkFrameClass parent_class; -}; - -GtkType nautilus_preferences_group_get_type (void); -GtkWidget* nautilus_preferences_group_new (const gchar *title); -GtkWidget* nautilus_preferences_group_add_item (NautilusPreferencesGroup *group, - const char *preference_name, - NautilusPreferencesItemType item_type, - int column); -GtkWidget* nautilus_preferences_group_add_custom_item (NautilusPreferencesGroup *group, - const char *preference_name, - GtkWidget *child, - const char *signal_name, - int column); -void nautilus_preferences_group_update (NautilusPreferencesGroup *group); -guint nautilus_preferences_group_get_num_visible_items (const NautilusPreferencesGroup *group); -char * nautilus_preferences_group_get_title_label (const NautilusPreferencesGroup *group); -int nautilus_preferences_group_get_max_caption_width (const NautilusPreferencesGroup *group, - int column); -void nautilus_preferences_group_align_captions (NautilusPreferencesGroup *group, - int max_caption_width, - int column); - -END_GNOME_DECLS - -#endif /* NAUTILUS_PREFERENCES_GROUP_H */ - - diff --git a/libnautilus-extensions/nautilus-preferences-item.c b/libnautilus-extensions/nautilus-preferences-item.c deleted file mode 100644 index 7fb0b3fd0..000000000 --- a/libnautilus-extensions/nautilus-preferences-item.c +++ /dev/null @@ -1,1448 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ - -/* nautilus-preferences-item.c - Implementation for an individual prefs item. - - Copyright (C) 1999, 2000 Eazel, Inc. - - The Gnome 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 Gnome 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 the Gnome 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. - - Authors: Ramiro Estrugo <ramiro@eazel.com> -*/ - -#include <config.h> -#include "nautilus-preferences-item.h" - -#include "nautilus-global-preferences.h" -#include "nautilus-preferences.h" -#include <eel/eel-art-gtk-extensions.h> -#include <eel/eel-enumeration.h> -#include <eel/eel-font-picker.h> -#include <eel/eel-glib-extensions.h> -#include <eel/eel-gtk-extensions.h> -#include <eel/eel-gtk-macros.h> -#include <eel/eel-radio-button-group.h> -#include <eel/eel-string-picker.h> -#include <eel/eel-string.h> -#include <eel/eel-text-caption.h> -#include <gtk/gtkcheckbutton.h> -#include <gtk/gtklabel.h> -#include <gtk/gtkmain.h> -#include <gtk/gtksignal.h> - -#define PREFERENCES_ITEM_UNDEFINED_ITEM -1U - -static gboolean text_idle_handler = FALSE; -static gboolean integer_idle_handler = FALSE; - -typedef struct -{ - GtkWidget *widget; - guint signal_id; -} PreferencesItemConnection; - -struct NautilusPreferencesItemDetails -{ - char *preference_name; - NautilusPreferencesItemType item_type; - GtkWidget *main_child; - GSList *change_signal_connections; - char *control_preference_name; - NautilusPreferencesItemControlAction control_action; - EelStringList *enumeration_list_unique_exceptions; -}; - -/* Signals */ -typedef enum -{ - CUSTOM_UPDATE_DISPLAYED_VALUE, - LAST_SIGNAL -} EelStringListSignals; - -static guint preferences_item_signals[LAST_SIGNAL]; - -/* GtkObjectClass methods */ -static void nautilus_preferences_item_initialize_class (NautilusPreferencesItemClass *preferences_item_class); -static void nautilus_preferences_item_initialize (NautilusPreferencesItem *preferences_item); -static void preferences_item_destroy (GtkObject *object); - -/* Private stuff */ -static void preferences_item_create_boolean (NautilusPreferencesItem *item); -static void preferences_item_create_editable_integer (NautilusPreferencesItem *item); -static void preferences_item_create_editable_string (NautilusPreferencesItem *item); -static void preferences_item_create_enumeration_menu (NautilusPreferencesItem *item); -static void preferences_item_create_enumeration_radio (NautilusPreferencesItem *item, - gboolean horizontal); -static void preferences_item_create_enumeration_list (NautilusPreferencesItem *item, - gboolean horizontal); -static void preferences_item_create_font (NautilusPreferencesItem *item); -static void preferences_item_create_font (NautilusPreferencesItem *item); -static void preferences_item_create_padding (NautilusPreferencesItem *item); -static void preferences_item_create_smooth_font (NautilusPreferencesItem *item); -static void preferences_item_update_displayed_value (NautilusPreferencesItem *preferences_item); -static void preferences_item_update_editable_integer_settings_at_idle (NautilusPreferencesItem *preferences_item); -static void preferences_item_update_text_settings_at_idle (NautilusPreferencesItem *preferences_item); - -/* User triggered item changed callbacks */ -static void enumeration_radio_changed_callback (EelRadioButtonGroup *radio_button_group, - gpointer callback_data); -static void boolean_button_toggled_callback (GtkWidget *button_group, - gpointer user_data); -static void editable_string_changed_callback (GtkWidget *caption, - gpointer user_data); -static void editable_integer_changed_callback (GtkWidget *caption, - gpointer user_data); -static void enumeration_menu_changed_callback (EelStringPicker *string_picker, - NautilusPreferencesItem *item); -static void font_changed_callback (GtkWidget *caption, - gpointer user_data); -static void enumeration_list_changed_callback (EelStringPicker *string_picker, - NautilusPreferencesItem *item); -static void smooth_font_changed_callback (EelFontPicker *font_picker, - gpointer callback_data); -static void custom_changed_callback (GtkWidget *custom, - gpointer user_data); - -EEL_DEFINE_CLASS_BOILERPLATE (NautilusPreferencesItem, nautilus_preferences_item, GTK_TYPE_VBOX) - -/* NautilusPreferencesItemClass methods */ -static void -nautilus_preferences_item_initialize_class (NautilusPreferencesItemClass *preferences_item_class) -{ - GtkObjectClass *object_class; - - object_class = GTK_OBJECT_CLASS (preferences_item_class); - - /* GtkObjectClass */ - object_class->destroy = preferences_item_destroy; - - /* Signals */ - preferences_item_signals[CUSTOM_UPDATE_DISPLAYED_VALUE] = - gtk_signal_new ("custom_update_displayed_value", - GTK_RUN_LAST, - object_class->type, - 0, - gtk_marshal_NONE__NONE, - GTK_TYPE_NONE, - 0); - - gtk_object_class_add_signals (object_class, preferences_item_signals, LAST_SIGNAL); -} - -static void -nautilus_preferences_item_initialize (NautilusPreferencesItem *item) -{ - item->details = g_new0 (NautilusPreferencesItemDetails, 1); - item->details->item_type = PREFERENCES_ITEM_UNDEFINED_ITEM; - item->details->enumeration_list_unique_exceptions = eel_string_list_new (TRUE); -} - -/* GtkObjectClass methods */ -static void -preferences_item_destroy (GtkObject *object) -{ - NautilusPreferencesItem * item; - - g_return_if_fail (NAUTILUS_IS_PREFERENCES_ITEM (object)); - - item = NAUTILUS_PREFERENCES_ITEM (object); - - g_free (item->details->preference_name); - g_free (item->details->control_preference_name); - eel_g_slist_free_deep (item->details->change_signal_connections); - eel_string_list_free (item->details->enumeration_list_unique_exceptions); - g_free (item->details); - - /* Chain destroy */ - EEL_CALL_PARENT (GTK_OBJECT_CLASS, destroy, (object)); -} - -/* - * Private stuff - */ -static void -preferences_item_update_enumeration_radio (NautilusPreferencesItem *item) -{ - int value; - char *enumeration_id; - guint i; - - g_return_if_fail (NAUTILUS_IS_PREFERENCES_ITEM (item)); - g_return_if_fail (item->details->item_type == NAUTILUS_PREFERENCE_ITEM_ENUMERATION_VERTICAL_RADIO - || item->details->item_type == NAUTILUS_PREFERENCE_ITEM_ENUMERATION_HORIZONTAL_RADIO); - - value = nautilus_preferences_get_integer (item->details->preference_name); - - enumeration_id = nautilus_preferences_get_enumeration_id (item->details->preference_name); - g_return_if_fail (eel_strlen (enumeration_id) > 0); - g_return_if_fail (eel_enumeration_id_get_length (enumeration_id) > 0); - - /* Set the active button */ - for (i = 0; i < eel_enumeration_id_get_length (enumeration_id); i++) { - if (value == eel_enumeration_id_get_nth_value (enumeration_id, i)) { - eel_radio_button_group_set_active_index (EEL_RADIO_BUTTON_GROUP (item->details->main_child), i); - } - } - - g_free (enumeration_id); -} - -/* Make sure the string pickers are wired such that duplicate choices cannot be - * made by the user. We do this by making items that would result in duplicates - * insensitive. Its possible to bypass this rule for some items. We use the - * use the enumeration_list_unique_exceptions for that. - */ -static void -preferences_item_update_enumeration_list_uniqueness (NautilusPreferencesItem *item) -{ - const GSList *node; - guint i; - guint j; - const PreferencesItemConnection *connection; - guint num_pickers; - EelStringList **insensitive_lists; - char *selected_string; - - g_return_if_fail (item->details->item_type == NAUTILUS_PREFERENCE_ITEM_ENUMERATION_LIST_VERTICAL - || item->details->item_type == NAUTILUS_PREFERENCE_ITEM_ENUMERATION_LIST_HORIZONTAL); - - num_pickers = g_slist_length (item->details->change_signal_connections); - - g_return_if_fail (num_pickers > 0); - - /* Allocate as many insensitive lists as we have string pickers */ - insensitive_lists = g_new (EelStringList *, num_pickers); - for (j = 0; j < num_pickers; j++) { - insensitive_lists[j] = eel_string_list_new (TRUE); - } - - /* Populate the insensitive lists with the selected strings of all the - * other lists. - */ - for (node = item->details->change_signal_connections, i = 0; node != NULL; node = node->next, i++) { - g_assert (node->data != NULL); - - connection = node->data; - g_assert (EEL_IS_STRING_PICKER (connection->widget)); - - selected_string = eel_string_picker_get_selected_string (EEL_STRING_PICKER (connection->widget)); - - for (j = 0; j < num_pickers; j++) { - if (j != i && !eel_string_list_contains (item->details->enumeration_list_unique_exceptions, - selected_string)) { - eel_string_list_insert (insensitive_lists[j], - selected_string); - } - } - g_free (selected_string); - } - - /* Install the insensitive lists on the string pickers */ - for (node = item->details->change_signal_connections, i = 0; node != NULL; node = node->next, i++) { - g_assert (node->data != NULL); - - connection = node->data; - g_assert (EEL_IS_STRING_PICKER (connection->widget)); - - eel_string_picker_set_insensitive_list (EEL_STRING_PICKER (connection->widget), - insensitive_lists[i]); - } - - /* Free the insensitive lists */ - for (j = 0; j < num_pickers; j++) { - eel_string_list_free (insensitive_lists[j]); - } - g_free (insensitive_lists); -} - -static void -preferences_item_update_enumeration_list (NautilusPreferencesItem *item) -{ - char *enumeration_id; - const GSList *node; - EelStringList *value; - char *nth_value_name; - char *nth_value_description; - guint i; - int position; - const PreferencesItemConnection *connection; - - g_return_if_fail (item->details->item_type == NAUTILUS_PREFERENCE_ITEM_ENUMERATION_LIST_VERTICAL - || item->details->item_type == NAUTILUS_PREFERENCE_ITEM_ENUMERATION_LIST_HORIZONTAL); - - enumeration_id = nautilus_preferences_get_enumeration_id (item->details->preference_name); - g_return_if_fail (eel_strlen (enumeration_id) > 0); - g_return_if_fail (eel_enumeration_id_get_length (enumeration_id) > 0); - - value = nautilus_preferences_get_string_list (item->details->preference_name); - - g_return_if_fail (eel_string_list_get_length (value) - == g_slist_length (item->details->change_signal_connections)); - - for (node = item->details->change_signal_connections, i = 0; node != NULL; node = node->next, i++) { - g_assert (node->data != NULL); - - connection = node->data; - g_assert (EEL_IS_STRING_PICKER (connection->widget)); - - nth_value_name = eel_string_list_nth (value, i); - - position = eel_enumeration_id_get_name_position (enumeration_id, - nth_value_name); - - nth_value_description = eel_enumeration_id_get_nth_description_translated (enumeration_id, - position); - - eel_string_picker_set_selected_string (EEL_STRING_PICKER (connection->widget), - nth_value_description); - - g_free (nth_value_name); - g_free (nth_value_description); - } - - eel_string_list_free (value); - g_free (enumeration_id); - - preferences_item_update_enumeration_list_uniqueness (item); -} - -static void -preferences_item_update_custom (NautilusPreferencesItem *item) -{ - g_return_if_fail (NAUTILUS_IS_PREFERENCES_ITEM (item)); - - gtk_signal_emit (GTK_OBJECT (item), - preferences_item_signals[CUSTOM_UPDATE_DISPLAYED_VALUE]); - -} - -/* This callback is called whenever the preference value changes, so that we can - * update the item widgets accordingly. - */ -static void -preferences_item_value_changed_callback (gpointer callback_data) -{ - g_return_if_fail (NAUTILUS_IS_PREFERENCES_ITEM (callback_data)); - - preferences_item_update_displayed_value (NAUTILUS_PREFERENCES_ITEM (callback_data)); -} - -static void -preferences_item_set_main_child (NautilusPreferencesItem *item, - GtkWidget *child) -{ - g_return_if_fail (NAUTILUS_IS_PREFERENCES_ITEM (item)); - g_return_if_fail (eel_strlen (item->details->preference_name) > 0); - g_return_if_fail (GTK_IS_WIDGET (child)); - g_return_if_fail (item->details->main_child == NULL); - - if (item->details->item_type != NAUTILUS_PREFERENCE_ITEM_PADDING) { - nautilus_preferences_add_callback_while_alive (item->details->preference_name, - preferences_item_value_changed_callback, - item, - GTK_OBJECT (item)); - } - - gtk_box_pack_start (GTK_BOX (item), - child, - FALSE, - FALSE, - 0); - - gtk_widget_show (child); - - item->details->main_child = child; -} - -static void -preferences_item_add_connection_child (NautilusPreferencesItem *item, - GtkWidget *child, - const char *signal_name, - GtkSignalFunc signal) -{ - PreferencesItemConnection *connection; - - g_return_if_fail (NAUTILUS_IS_PREFERENCES_ITEM (item)); - g_return_if_fail (GTK_IS_WIDGET (child)); - g_return_if_fail (eel_strlen (signal_name) > 0); - g_return_if_fail (signal != NULL); - - connection = g_new0 (PreferencesItemConnection, 1); - connection->widget = child; - connection->signal_id = gtk_signal_connect (GTK_OBJECT (child), - signal_name, - signal, - item); - - item->details->change_signal_connections = g_slist_append ( - item->details->change_signal_connections, connection); -} - -static void -preferences_item_create_enumeration_radio (NautilusPreferencesItem *item, - gboolean horizontal) -{ - guint i; - char *enumeration_id; - char *description; - GtkWidget *child; - - g_return_if_fail (NAUTILUS_IS_PREFERENCES_ITEM (item)); - g_return_if_fail (eel_strlen (item->details->preference_name) > 0); - - enumeration_id = nautilus_preferences_get_enumeration_id (item->details->preference_name); - g_return_if_fail (eel_strlen (enumeration_id) > 0); - g_return_if_fail (eel_enumeration_id_get_length (enumeration_id) > 0); - - child = eel_radio_button_group_new (horizontal); - - /* Populate the radio group */ - for (i = 0; i < eel_enumeration_id_get_length (enumeration_id); i++) { - description = eel_enumeration_id_get_nth_description_translated (enumeration_id, i); - g_assert (description != NULL); - - eel_radio_button_group_insert (EEL_RADIO_BUTTON_GROUP (child), - description); - g_free (description); - } - g_free (enumeration_id); - - preferences_item_add_connection_child (item, - child, - "changed", - GTK_SIGNAL_FUNC (enumeration_radio_changed_callback)); - - preferences_item_set_main_child (item, child); -} - -static void -preferences_item_create_enumeration_list (NautilusPreferencesItem *item, - gboolean horizontal) -{ - guint i; - guint j; - char *enumeration_id; - char *description; - char *enum_description; - EelStringList *default_value; - guint num_pickers; - GtkWidget *string_picker; - GtkWidget *picker_box; - GtkWidget *title; - GtkWidget *child; - - g_return_if_fail (NAUTILUS_IS_PREFERENCES_ITEM (item)); - g_return_if_fail (eel_strlen (item->details->preference_name) > 0); - - description = nautilus_preferences_get_description (item->details->preference_name); - g_return_if_fail (eel_strlen (description) > 0); - - enumeration_id = nautilus_preferences_get_enumeration_id (item->details->preference_name); - g_return_if_fail (eel_strlen (enumeration_id) > 0); - g_return_if_fail (eel_enumeration_id_get_length (enumeration_id) > 0); - - /* FIXME: Hard coded user level */ - default_value = nautilus_preferences_default_get_string_list (item->details->preference_name, 0); - - num_pickers = eel_string_list_get_length (default_value); - g_return_if_fail (num_pickers > 0); - - child = gtk_vbox_new (FALSE, 4); - picker_box = horizontal ? gtk_hbox_new (FALSE, 4): gtk_vbox_new (FALSE, 4); - - title = gtk_label_new (description); - gtk_misc_set_alignment (GTK_MISC (title), 0.0, 0.5); - gtk_label_set_justify (GTK_LABEL (title), GTK_JUSTIFY_LEFT); - - gtk_box_pack_start (GTK_BOX (child), - title, - FALSE, - FALSE, - 0); - - gtk_box_pack_start (GTK_BOX (child), - picker_box, - TRUE, - TRUE, - 0); - - gtk_widget_show (title); - gtk_widget_show (picker_box); - - /* Populate the string pickers */ - for (j = 0; j < num_pickers; j++) { - string_picker = eel_string_picker_new (); - eel_caption_set_show_title (EEL_CAPTION (string_picker), FALSE); - - for (i = 0; i < eel_enumeration_id_get_length (enumeration_id); i++) { - enum_description = eel_enumeration_id_get_nth_description_translated (enumeration_id, i); - g_assert (enum_description != NULL); - - if (enum_description[0] == '-') { - eel_string_picker_insert_separator (EEL_STRING_PICKER (string_picker)); - } else { - eel_string_picker_insert_string (EEL_STRING_PICKER (string_picker), enum_description); - } - g_free (enum_description); - } - - gtk_box_pack_start (GTK_BOX (picker_box), - string_picker, - FALSE, - FALSE, - 0); - - gtk_widget_show (string_picker); - - preferences_item_add_connection_child (item, - string_picker, - "changed", - GTK_SIGNAL_FUNC (enumeration_list_changed_callback)); - } - g_free (enumeration_id); - - preferences_item_set_main_child (item, child); -} - -static void -preferences_item_update_boolean (NautilusPreferencesItem *item) -{ - gboolean value; - - g_return_if_fail (NAUTILUS_IS_PREFERENCES_ITEM (item)); - g_return_if_fail (item->details->item_type == NAUTILUS_PREFERENCE_ITEM_BOOLEAN); - - value = nautilus_preferences_get_boolean (item->details->preference_name); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (item->details->main_child), value); -} - -static void -preferences_item_create_boolean (NautilusPreferencesItem *item) -{ - char *description; - GtkWidget *child; - - g_return_if_fail (NAUTILUS_IS_PREFERENCES_ITEM (item)); - g_return_if_fail (eel_strlen (item->details->preference_name) > 0); - - description = nautilus_preferences_get_description (item->details->preference_name); - g_return_if_fail (eel_strlen (description) > 0); - - child = gtk_check_button_new_with_label (description); - gtk_label_set_justify (GTK_LABEL (GTK_BIN (child)->child), GTK_JUSTIFY_LEFT); - g_free (description); - - preferences_item_add_connection_child (item, - child, - "toggled", - GTK_SIGNAL_FUNC (boolean_button_toggled_callback)); - - preferences_item_set_main_child (item, child); -} - -static void -preferences_item_update_editable_string (NautilusPreferencesItem *item) -{ - char *current_value; - - g_return_if_fail (NAUTILUS_IS_PREFERENCES_ITEM (item)); - g_return_if_fail (item->details->item_type == NAUTILUS_PREFERENCE_ITEM_EDITABLE_STRING); - - current_value = nautilus_preferences_get (item->details->preference_name); - - g_assert (current_value != NULL); - eel_text_caption_set_text (EEL_TEXT_CAPTION (item->details->main_child), current_value); - g_free (current_value); -} - -static void -preferences_item_create_editable_string (NautilusPreferencesItem *item) -{ - char *description; - GtkWidget *child; - - g_return_if_fail (NAUTILUS_IS_PREFERENCES_ITEM (item)); - g_return_if_fail (eel_strlen (item->details->preference_name) > 0); - - description = nautilus_preferences_get_description (item->details->preference_name); - g_assert (description != NULL); - - child = eel_text_caption_new (); - - /* FIXME This is a special case for the home uri preference, - in the future this should be generalized. */ - if (g_strcasecmp (item->details->preference_name, NAUTILUS_PREFERENCES_HOME_URI) == 0) - { - eel_text_caption_set_expand_tilde (EEL_TEXT_CAPTION (child), TRUE); - } - - eel_caption_set_title_label (EEL_CAPTION (child), description); - - g_free (description); - - preferences_item_add_connection_child (item, - child, - "changed", - GTK_SIGNAL_FUNC (editable_string_changed_callback)); - - preferences_item_set_main_child (item, child); -} - -static void -preferences_item_update_editable_integer (NautilusPreferencesItem *item) -{ - char *current_value; - - g_return_if_fail (NAUTILUS_IS_PREFERENCES_ITEM (item)); - g_return_if_fail (item->details->item_type == NAUTILUS_PREFERENCE_ITEM_EDITABLE_INTEGER); - - current_value = g_strdup_printf ("%d", nautilus_preferences_get_integer (item->details->preference_name)); - - g_assert (current_value != NULL); - eel_text_caption_set_text (EEL_TEXT_CAPTION (item->details->main_child), current_value); - g_free (current_value); -} - -static void -preferences_item_create_editable_integer (NautilusPreferencesItem *item) -{ - char *description; - GtkWidget *child; - - g_return_if_fail (NAUTILUS_IS_PREFERENCES_ITEM (item)); - g_return_if_fail (eel_strlen (item->details->preference_name) > 0); - - description = nautilus_preferences_get_description (item->details->preference_name); - - g_assert (description != NULL); - - child = eel_text_caption_new (); - - eel_caption_set_title_label (EEL_CAPTION (child), description); - - g_free (description); - - preferences_item_add_connection_child (item, - child, - "changed", - GTK_SIGNAL_FUNC (editable_integer_changed_callback)); - - preferences_item_set_main_child (item, child); -} - -static void -preferences_item_update_enumeration_menu (NautilusPreferencesItem *item) -{ - char *current_label; - int current_value; - int position; - char *enumeration_id; - - g_return_if_fail (NAUTILUS_IS_PREFERENCES_ITEM (item)); - g_return_if_fail (item->details->item_type == NAUTILUS_PREFERENCE_ITEM_ENUMERATION_MENU); - - enumeration_id = nautilus_preferences_get_enumeration_id (item->details->preference_name); - - g_return_if_fail (eel_strlen (enumeration_id) > 0); - g_return_if_fail (eel_enumeration_id_get_length (enumeration_id) > 0); - - current_value = nautilus_preferences_get_integer (item->details->preference_name); - - position = eel_enumeration_id_get_value_position (enumeration_id, - current_value); - g_return_if_fail (position != EEL_STRING_LIST_NOT_FOUND); - - current_label = eel_enumeration_id_get_nth_description_translated (enumeration_id, - position); - - if (eel_string_picker_contains (EEL_STRING_PICKER (item->details->main_child), current_label)) { - eel_string_picker_set_selected_string (EEL_STRING_PICKER (item->details->main_child), - current_label); - } else { - g_warning ("Value string for %s is %s, which isn't in the expected set of values", - item->details->preference_name, - current_label); - } - - g_free (enumeration_id); - g_free (current_label); -} - -static void -preferences_item_create_enumeration_menu (NautilusPreferencesItem *item) -{ - guint i; - char *enumeration_id; - char *description; - GtkWidget *child; - - g_return_if_fail (NAUTILUS_IS_PREFERENCES_ITEM (item)); - g_return_if_fail (eel_strlen (item->details->preference_name) > 0); - - description = nautilus_preferences_get_description (item->details->preference_name); - g_return_if_fail (description != NULL); - - child = eel_string_picker_new (); - eel_caption_set_title_label (EEL_CAPTION (child), description); - g_free (description); - - enumeration_id = nautilus_preferences_get_enumeration_id (item->details->preference_name); - g_return_if_fail (eel_strlen (enumeration_id) > 0); - g_return_if_fail (eel_enumeration_id_get_length (enumeration_id) > 0); - - /* Populate the string picker */ - for (i = 0; i < eel_enumeration_id_get_length (enumeration_id); i++) { - description = eel_enumeration_id_get_nth_description_translated (enumeration_id, i); - g_assert (description != NULL); - - if (description[0] == '-') { - eel_string_picker_insert_separator (EEL_STRING_PICKER (child)); - } else { - eel_string_picker_insert_string (EEL_STRING_PICKER (child), description); - } - - g_free (description); - } - g_free (enumeration_id); - - preferences_item_add_connection_child (item, - child, - "changed", - GTK_SIGNAL_FUNC (enumeration_menu_changed_callback)); - - preferences_item_set_main_child (item, child); -} - -static void -preferences_item_update_font (NautilusPreferencesItem *item) -{ - char *current_value; - - g_return_if_fail (NAUTILUS_IS_PREFERENCES_ITEM (item)); - g_return_if_fail (item->details->item_type == NAUTILUS_PREFERENCE_ITEM_FONT); - - current_value = nautilus_preferences_get (item->details->preference_name); - g_assert (current_value != NULL); - - /* The value of the gconf preference can be anything. In theory garbage could - * be used for the preference using a third party tool. So we make sure that - * it is one of the choice before trying to select it, otherwise we would get - * assertions. - */ - if (eel_string_picker_contains (EEL_STRING_PICKER (item->details->main_child), current_value)) { - eel_string_picker_set_selected_string (EEL_STRING_PICKER (item->details->main_child), - current_value); - } - - g_free (current_value); -} - -static void -preferences_item_create_font (NautilusPreferencesItem *item) -{ - char *description; - EelStringList *font_list; - GtkWidget *child; - - g_return_if_fail (NAUTILUS_IS_PREFERENCES_ITEM (item)); - g_return_if_fail (eel_strlen (item->details->preference_name) > 0); - - description = nautilus_preferences_get_description (item->details->preference_name); - g_return_if_fail (description != NULL); - - child = eel_string_picker_new (); - eel_caption_set_title_label (EEL_CAPTION (child), description); - - g_free (description); - - /* FIXME bugzilla.eazel.com 1274: Need to query system for available fonts */ - font_list = eel_string_list_new (TRUE); - - /* Once upon a time we had a bug in Nautilus that caused crashes with the "fixed" - * font. That bug (2256) was fixed by removing the "fixed" choice from this menu - * below. Subsequently we fixed many font bugs in nautilus (such hard coded font sizes) - * that would cause both crashes and ugliness. Bug 2256 seems to have been fixed by - * these changes as well. - * - * Anyhow, the "fixed" font choice is not very interesting because the other fonts - * look much better. However, in multi byte locales, the fixed font is usually the - * only one that is available at the right encoding. - */ - - /* FIXME bugzilla.eazel.com 7907: - * The "GTK System Font" string is hard coded in many places. - */ - eel_string_list_insert (font_list, "GTK System Font"); - eel_string_list_insert (font_list, "fixed"); - eel_string_list_insert (font_list, "helvetica"); - eel_string_list_insert (font_list, "times"); - eel_string_list_insert (font_list, "courier"); - eel_string_list_insert (font_list, "lucida"); - - eel_string_picker_set_string_list (EEL_STRING_PICKER (child), font_list); - eel_string_list_free (font_list); - - preferences_item_add_connection_child (item, - child, - "changed", - GTK_SIGNAL_FUNC (font_changed_callback)); - - preferences_item_set_main_child (item, child); -} - -static void -preferences_item_create_padding (NautilusPreferencesItem *item) -{ - g_return_if_fail (NAUTILUS_IS_PREFERENCES_ITEM (item)); - - preferences_item_set_main_child (item, gtk_label_new ("")); -} - -static void -preferences_item_update_smooth_font (NautilusPreferencesItem *item) -{ - char *current_value; - - g_return_if_fail (NAUTILUS_IS_PREFERENCES_ITEM (item)); - g_return_if_fail (item->details->item_type == NAUTILUS_PREFERENCE_ITEM_SMOOTH_FONT); - - current_value = nautilus_preferences_get (item->details->preference_name); - g_assert (current_value != NULL); - - eel_font_picker_set_selected_font (EEL_FONT_PICKER (item->details->main_child), - current_value); - g_free (current_value); -} - -static void -smooth_font_changed_callback (EelFontPicker *font_picker, - gpointer callback_data) -{ - NautilusPreferencesItem *item; - char *new_value; - - g_return_if_fail (EEL_IS_FONT_PICKER (font_picker)); - g_return_if_fail (NAUTILUS_IS_PREFERENCES_ITEM (callback_data)); - - item = NAUTILUS_PREFERENCES_ITEM (callback_data); - new_value = eel_font_picker_get_selected_font (EEL_FONT_PICKER (item->details->main_child)); - g_assert (new_value != NULL); - nautilus_preferences_set (item->details->preference_name, new_value); - g_free (new_value); -} - -static void -preferences_item_create_smooth_font (NautilusPreferencesItem *item) -{ - char *description = NULL; - GtkWidget *child; - - g_return_if_fail (NAUTILUS_IS_PREFERENCES_ITEM (item)); - g_return_if_fail (eel_strlen (item->details->preference_name) > 0); - - description = nautilus_preferences_get_description (item->details->preference_name); - g_return_if_fail (description != NULL); - - child = eel_font_picker_new (); - eel_caption_set_title_label (EEL_CAPTION (child), description); - g_free (description); - - preferences_item_add_connection_child (item, - child, - "changed", - GTK_SIGNAL_FUNC (smooth_font_changed_callback)); - - preferences_item_set_main_child (item, child); -} - -static void -custom_changed_callback (GtkWidget *widget, - gpointer callback_data) -{ - g_return_if_fail (GTK_IS_WIDGET (widget)); -} - -/* NautilusPreferencesItem public methods */ -GtkWidget * -nautilus_preferences_item_new (const char *preference_name, - NautilusPreferencesItemType item_type) -{ - NautilusPreferencesItem *item; - - g_return_val_if_fail (eel_strlen (preference_name) > 0, NULL); - g_return_val_if_fail (item_type >= NAUTILUS_PREFERENCE_ITEM_BOOLEAN, FALSE); - g_return_val_if_fail (item_type <= NAUTILUS_PREFERENCE_ITEM_SMOOTH_FONT, FALSE); - - item = NAUTILUS_PREFERENCES_ITEM - (gtk_widget_new (nautilus_preferences_item_get_type (), NULL)); - - item->details->preference_name = g_strdup (preference_name); - item->details->item_type = item_type; - - /* Create the child widget according to the item type */ - switch (item_type) - { - case NAUTILUS_PREFERENCE_ITEM_BOOLEAN: - preferences_item_create_boolean (item); - break; - - case NAUTILUS_PREFERENCE_ITEM_ENUMERATION_VERTICAL_RADIO: - preferences_item_create_enumeration_radio (item, FALSE); - break; - - case NAUTILUS_PREFERENCE_ITEM_ENUMERATION_HORIZONTAL_RADIO: - preferences_item_create_enumeration_radio (item, TRUE); - break; - - case NAUTILUS_PREFERENCE_ITEM_ENUMERATION_LIST_VERTICAL: - preferences_item_create_enumeration_list (item, FALSE); - break; - - case NAUTILUS_PREFERENCE_ITEM_ENUMERATION_LIST_HORIZONTAL: - preferences_item_create_enumeration_list (item, TRUE); - break; - - case NAUTILUS_PREFERENCE_ITEM_FONT: - preferences_item_create_font (item); - break; - - case NAUTILUS_PREFERENCE_ITEM_SMOOTH_FONT: - preferences_item_create_smooth_font (item); - break; - - case NAUTILUS_PREFERENCE_ITEM_EDITABLE_STRING: - preferences_item_create_editable_string (item); - break; - - case NAUTILUS_PREFERENCE_ITEM_EDITABLE_INTEGER: - preferences_item_create_editable_integer (item); - break; - - case NAUTILUS_PREFERENCE_ITEM_ENUMERATION_MENU: - preferences_item_create_enumeration_menu (item); - break; - - case NAUTILUS_PREFERENCE_ITEM_PADDING: - preferences_item_create_padding (item); - break; - - case NAUTILUS_PREFERENCE_ITEM_CUSTOM: - g_assert_not_reached (); - break; - } - - g_return_val_if_fail (GTK_IS_WIDGET (item->details->main_child), NULL); - - preferences_item_update_displayed_value (item); - - return GTK_WIDGET (item); -} - -GtkWidget* -nautilus_preferences_item_new_custom (const char *preference_name, - GtkWidget *child, - const char *signal_name) -{ - NautilusPreferencesItem *item; - - g_return_val_if_fail (eel_strlen (preference_name) > 0, NULL); - g_return_val_if_fail (GTK_IS_WIDGET (child), NULL); - g_return_val_if_fail (eel_strlen (signal_name) > 0, NULL); - - item = NAUTILUS_PREFERENCES_ITEM - (gtk_widget_new (nautilus_preferences_item_get_type (), NULL)); - - item->details->preference_name = g_strdup (preference_name); - item->details->item_type = NAUTILUS_PREFERENCE_ITEM_CUSTOM; - - preferences_item_add_connection_child (item, - child, - signal_name, - GTK_SIGNAL_FUNC (custom_changed_callback)); - - preferences_item_set_main_child (item, child); - - return GTK_WIDGET (item); -} - -static void -enumeration_radio_changed_callback (EelRadioButtonGroup *radio_button_group, - gpointer callback_data) -{ - NautilusPreferencesItem *item; - int i; - char *enumeration_id; - - g_return_if_fail (EEL_IS_RADIO_BUTTON_GROUP (radio_button_group)); - g_return_if_fail (NAUTILUS_IS_PREFERENCES_ITEM (callback_data)); - - item = NAUTILUS_PREFERENCES_ITEM (callback_data); - - g_assert (item->details->preference_name != NULL); - - i = eel_radio_button_group_get_active_index (radio_button_group); - - enumeration_id = nautilus_preferences_get_enumeration_id (item->details->preference_name); - g_return_if_fail (eel_strlen (enumeration_id) > 0); - g_return_if_fail ((guint)i < eel_enumeration_id_get_length (enumeration_id)); - - nautilus_preferences_set_integer (item->details->preference_name, - eel_enumeration_id_get_nth_value (enumeration_id, i)); - g_free (enumeration_id); -} - -static void -boolean_button_toggled_callback (GtkWidget *button, gpointer user_data) -{ - NautilusPreferencesItem *item; - gboolean active_state; - - g_assert (user_data != NULL); - g_assert (NAUTILUS_IS_PREFERENCES_ITEM (user_data)); - - item = NAUTILUS_PREFERENCES_ITEM (user_data); - - active_state = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)); - - nautilus_preferences_set_boolean (item->details->preference_name, active_state); -} - -static void -font_changed_callback (GtkWidget *string_picker, gpointer user_data) -{ - NautilusPreferencesItem *item; - char *selected_string; - - g_return_if_fail (EEL_IS_STRING_PICKER (string_picker)); - g_return_if_fail (NAUTILUS_IS_PREFERENCES_ITEM (user_data)); - - item = NAUTILUS_PREFERENCES_ITEM (user_data); - - g_return_if_fail (item->details->preference_name != NULL); - - selected_string = eel_string_picker_get_selected_string (EEL_STRING_PICKER (string_picker)); - g_return_if_fail (selected_string != NULL); - - nautilus_preferences_set (item->details->preference_name, selected_string); - - g_free (selected_string); -} - -static void -editable_string_changed_callback (GtkWidget *button, gpointer user_data) -{ - NautilusPreferencesItem *item; - - g_assert (user_data != NULL); - g_assert (NAUTILUS_IS_PREFERENCES_ITEM (user_data)); - - item = NAUTILUS_PREFERENCES_ITEM (user_data); - - g_assert (item->details->main_child != NULL); - g_assert (EEL_IS_TEXT_CAPTION (item->details->main_child)); - - preferences_item_update_text_settings_at_idle (item); -} - -static void -editable_integer_changed_callback (GtkWidget *button, gpointer user_data) -{ - NautilusPreferencesItem *item; - - g_assert (user_data != NULL); - g_assert (NAUTILUS_IS_PREFERENCES_ITEM (user_data)); - - item = NAUTILUS_PREFERENCES_ITEM (user_data); - - g_assert (item->details->main_child != NULL); - g_assert (EEL_IS_TEXT_CAPTION (item->details->main_child)); - - preferences_item_update_editable_integer_settings_at_idle (item); -} - -static void -enumeration_menu_changed_callback (EelStringPicker *string_picker, - NautilusPreferencesItem *item) -{ - char *selected_label; - int position; - int new_value; - char *enumeration_id; - - g_return_if_fail (EEL_IS_STRING_PICKER (string_picker)); - g_return_if_fail (NAUTILUS_IS_PREFERENCES_ITEM (item)); - - enumeration_id = nautilus_preferences_get_enumeration_id (item->details->preference_name); - g_return_if_fail (eel_strlen (enumeration_id) > 0); - g_return_if_fail (eel_enumeration_id_get_length (enumeration_id) > 0); - - selected_label = eel_string_picker_get_selected_string (string_picker); - g_return_if_fail (selected_label != NULL); - - position = eel_enumeration_id_get_description_position (enumeration_id, - selected_label); - g_free (selected_label); - g_return_if_fail (position != EEL_STRING_LIST_NOT_FOUND); - - new_value = eel_enumeration_id_get_nth_value (enumeration_id, - position); - - nautilus_preferences_set_integer (item->details->preference_name, new_value); - - g_free (enumeration_id); -} - -static void -enumeration_list_changed_callback (EelStringPicker *string_picker, - NautilusPreferencesItem *item) -{ - const GSList *node; - const PreferencesItemConnection *connection; - char *selected_label; - char *enumeration_id; - int position; - char *new_value_nth_name; - EelStringList *new_value; - - g_return_if_fail (EEL_IS_STRING_PICKER (string_picker)); - g_return_if_fail (NAUTILUS_IS_PREFERENCES_ITEM (item)); - - enumeration_id = nautilus_preferences_get_enumeration_id (item->details->preference_name); - g_return_if_fail (eel_strlen (enumeration_id) > 0); - g_return_if_fail (eel_enumeration_id_get_length (enumeration_id) > 0); - - new_value = eel_string_list_new (TRUE); - - for (node = item->details->change_signal_connections; node != NULL; node = node->next) { - g_assert (node->data != NULL); - connection = node->data; - g_assert (EEL_IS_STRING_PICKER (connection->widget)); - - selected_label = eel_string_picker_get_selected_string (EEL_STRING_PICKER (connection->widget)); - g_return_if_fail (selected_label != NULL); - - position = eel_enumeration_id_get_description_position (enumeration_id, - selected_label); - g_free (selected_label); - g_return_if_fail (position != EEL_STRING_LIST_NOT_FOUND); - - new_value_nth_name = eel_enumeration_id_get_nth_name (enumeration_id, - position); - - eel_string_list_insert (new_value, new_value_nth_name); - - g_free (new_value_nth_name); - } - - g_return_if_fail (eel_string_list_get_length (new_value) - == g_slist_length (item->details->change_signal_connections)); - - nautilus_preferences_set_string_list (item->details->preference_name, new_value); - - eel_string_list_free (new_value); - - g_free (enumeration_id); - - preferences_item_update_enumeration_list_uniqueness (item); -} - -char * -nautilus_preferences_item_get_name (const NautilusPreferencesItem *preferences_item) -{ - g_return_val_if_fail (NAUTILUS_IS_PREFERENCES_ITEM (preferences_item), NULL); - - return g_strdup (preferences_item->details->preference_name); -} - -static void -preferences_item_update_displayed_value (NautilusPreferencesItem *item) -{ - NautilusPreferencesItemType item_type; - const GSList *node; - const PreferencesItemConnection *connection; - - g_return_if_fail (NAUTILUS_IS_PREFERENCES_ITEM (item)); - - item_type = item->details->item_type; - - g_return_if_fail (item->details->item_type != PREFERENCES_ITEM_UNDEFINED_ITEM); - - /* Block the change signals while we update the widget to match the preference */ - for (node = item->details->change_signal_connections; node != NULL; node = node->next) { - g_assert (node->data != NULL); - connection = node->data; - g_assert (GTK_IS_WIDGET (connection->widget)); - - gtk_signal_handler_block (GTK_OBJECT (connection->widget), - connection->signal_id); - } - - /* Update the child widget according to the item type */ - switch (item_type) - { - case NAUTILUS_PREFERENCE_ITEM_BOOLEAN: - preferences_item_update_boolean (item); - break; - - case NAUTILUS_PREFERENCE_ITEM_ENUMERATION_VERTICAL_RADIO: - case NAUTILUS_PREFERENCE_ITEM_ENUMERATION_HORIZONTAL_RADIO: - preferences_item_update_enumeration_radio (item); - break; - - case NAUTILUS_PREFERENCE_ITEM_ENUMERATION_LIST_VERTICAL: - case NAUTILUS_PREFERENCE_ITEM_ENUMERATION_LIST_HORIZONTAL: - preferences_item_update_enumeration_list (item); - break; - - case NAUTILUS_PREFERENCE_ITEM_FONT: - preferences_item_update_font (item); - break; - - case NAUTILUS_PREFERENCE_ITEM_SMOOTH_FONT: - preferences_item_update_smooth_font (item); - break; - - case NAUTILUS_PREFERENCE_ITEM_EDITABLE_STRING: - preferences_item_update_editable_string (item); - break; - - case NAUTILUS_PREFERENCE_ITEM_EDITABLE_INTEGER: - preferences_item_update_editable_integer (item); - break; - - case NAUTILUS_PREFERENCE_ITEM_ENUMERATION_MENU: - preferences_item_update_enumeration_menu (item); - break; - - case NAUTILUS_PREFERENCE_ITEM_PADDING: - break; - - case NAUTILUS_PREFERENCE_ITEM_CUSTOM: - preferences_item_update_custom (item); - break; - default: - g_assert_not_reached (); - } - - for (node = item->details->change_signal_connections; node != NULL; node = node->next) { - g_assert (node->data != NULL); - connection = node->data; - g_assert (GTK_IS_WIDGET (connection->widget)); - - gtk_signal_handler_unblock (GTK_OBJECT (connection->widget), - connection->signal_id); - } -} - -static gboolean -update_text_settings_at_idle (NautilusPreferencesItem *preferences_item) -{ - char *text; - - text = eel_text_caption_get_text (EEL_TEXT_CAPTION (preferences_item->details->main_child)); - - if (text != NULL) { - nautilus_preferences_set (preferences_item->details->preference_name, text); - g_free (text); - } - - text_idle_handler = FALSE; - - return FALSE; -} - -static void -preferences_item_update_text_settings_at_idle (NautilusPreferencesItem *preferences_item) -{ - g_return_if_fail (NAUTILUS_IS_PREFERENCES_ITEM (preferences_item)); - - if (text_idle_handler == FALSE) { - gtk_idle_add ((GtkFunction) update_text_settings_at_idle, preferences_item); - text_idle_handler = TRUE; - } -} - -static gboolean -update_integer_settings_at_idle (NautilusPreferencesItem *preferences_item) -{ - int value = 0; - char *text; - - text = eel_text_caption_get_text (EEL_TEXT_CAPTION (preferences_item->details->main_child)); - - if (text != NULL) { - eel_eat_str_to_int (text, &value); - } - - nautilus_preferences_set_integer (preferences_item->details->preference_name, value); - - integer_idle_handler = FALSE; - - return FALSE; -} - -static void -preferences_item_update_editable_integer_settings_at_idle (NautilusPreferencesItem *preferences_item) -{ - g_return_if_fail (NAUTILUS_IS_PREFERENCES_ITEM (preferences_item)); - - if (integer_idle_handler == FALSE) { - gtk_idle_add ((GtkFunction) update_integer_settings_at_idle, preferences_item); - integer_idle_handler = TRUE; - } -} - -void -nautilus_preferences_item_set_control_preference (NautilusPreferencesItem *preferences_item, - const char *control_preference_name) -{ - g_return_if_fail (NAUTILUS_IS_PREFERENCES_ITEM (preferences_item)); - - if (eel_str_is_equal (preferences_item->details->control_preference_name, - control_preference_name)) { - return; - } - - g_free (preferences_item->details->control_preference_name); - preferences_item->details->control_preference_name = g_strdup (control_preference_name); -} - -void -nautilus_preferences_item_set_control_action (NautilusPreferencesItem *preferences_item, - NautilusPreferencesItemControlAction control_action) -{ - g_return_if_fail (NAUTILUS_IS_PREFERENCES_ITEM (preferences_item)); - g_return_if_fail (control_action >= NAUTILUS_PREFERENCE_ITEM_SHOW); - g_return_if_fail (control_action <= NAUTILUS_PREFERENCE_ITEM_HIDE); - - if (preferences_item->details->control_action == control_action) { - return; - } - - preferences_item->details->control_action = control_action; -} - -static gboolean -preferences_item_get_control_showing (const NautilusPreferencesItem *preferences_item) -{ - gboolean value; - - g_return_val_if_fail (NAUTILUS_IS_PREFERENCES_ITEM (preferences_item), FALSE); - - if (preferences_item->details->control_preference_name == NULL) { - return TRUE; - } - - value = nautilus_preferences_get_boolean (preferences_item->details->control_preference_name); - - if (preferences_item->details->control_action == NAUTILUS_PREFERENCE_ITEM_SHOW) { - return value; - } - - if (preferences_item->details->control_action == NAUTILUS_PREFERENCE_ITEM_HIDE) { - return !value; - } - - return !value; -} - -gboolean -nautilus_preferences_item_child_is_caption (const NautilusPreferencesItem *item) -{ - g_return_val_if_fail (NAUTILUS_IS_PREFERENCES_ITEM (item), FALSE); - - return EEL_IS_CAPTION (item->details->main_child); -} - -int -nautilus_preferences_item_get_child_width (const NautilusPreferencesItem *item) -{ - EelDimensions child_dimensions; - - g_return_val_if_fail (NAUTILUS_IS_PREFERENCES_ITEM (item), 0); - - if (item->details->main_child == NULL) { - return 0; - } - - child_dimensions = eel_gtk_widget_get_preferred_dimensions (item->details->main_child); - - return child_dimensions.width; -} - -void -nautilus_preferences_item_set_caption_extra_spacing (NautilusPreferencesItem *item, - int extra_spacing) -{ - g_return_if_fail (NAUTILUS_IS_PREFERENCES_ITEM (item)); - g_return_if_fail (extra_spacing >= 0); - - if (!nautilus_preferences_item_child_is_caption (item)) { - return; - } - - eel_caption_set_extra_spacing (EEL_CAPTION (item->details->main_child), - extra_spacing); -} - -gboolean -nautilus_preferences_item_is_showing (const NautilusPreferencesItem *item) -{ - g_return_val_if_fail (NAUTILUS_IS_PREFERENCES_ITEM (item), FALSE); - - if (item->details->item_type == NAUTILUS_PREFERENCE_ITEM_PADDING) { - return TRUE; - } else if (nautilus_preferences_is_visible (item->details->preference_name)) { - return preferences_item_get_control_showing (item); - } - - return FALSE; -} - -void -nautilus_preferences_item_update_showing (NautilusPreferencesItem *item) -{ - g_return_if_fail (NAUTILUS_IS_PREFERENCES_ITEM (item)); - - eel_gtk_widget_set_shown (GTK_WIDGET (item), - nautilus_preferences_item_is_showing (item)); -} - -void -nautilus_preferences_item_enumeration_list_set_unique_exceptions (NautilusPreferencesItem *item, - const char *exceptions, - const char *exceptions_delimeter) -{ - EelStringList *new_exceptions; - - g_return_if_fail (NAUTILUS_IS_PREFERENCES_ITEM (item)); - g_return_if_fail (item->details->item_type == NAUTILUS_PREFERENCE_ITEM_ENUMERATION_LIST_VERTICAL - || item->details->item_type == NAUTILUS_PREFERENCE_ITEM_ENUMERATION_LIST_HORIZONTAL); - g_return_if_fail (eel_strlen (exceptions_delimeter) > 0); - - new_exceptions = eel_string_list_new_from_tokens (exceptions, - exceptions_delimeter, - TRUE); - - if (eel_string_list_equals (new_exceptions, item->details->enumeration_list_unique_exceptions)) { - eel_string_list_free (new_exceptions); - return; - } - - eel_string_list_free (item->details->enumeration_list_unique_exceptions); - item->details->enumeration_list_unique_exceptions = new_exceptions; - - preferences_item_update_enumeration_list_uniqueness (item); -} diff --git a/libnautilus-extensions/nautilus-preferences-item.h b/libnautilus-extensions/nautilus-preferences-item.h deleted file mode 100644 index 227f0c1a0..000000000 --- a/libnautilus-extensions/nautilus-preferences-item.h +++ /dev/null @@ -1,112 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ - -/* nautilus-preferences-item.h - Interface for an individual prefs item. - - Copyright (C) 1999, 2000 Eazel, Inc. - - The Gnome 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 Gnome 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 the Gnome 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. - - Authors: Ramiro Estrugo <ramiro@eazel.com> -*/ - -#ifndef NAUTILUS_PREFERENCES_ITEM_H -#define NAUTILUS_PREFERENCES_ITEM_H - -#include <gtk/gtkvbox.h> -#include <libnautilus-extensions/nautilus-preferences.h> -#include <eel/eel-enumeration.h> - -BEGIN_GNOME_DECLS - -#define NAUTILUS_TYPE_PREFERENCES_ITEM (nautilus_preferences_item_get_type ()) -#define NAUTILUS_PREFERENCES_ITEM(obj) (GTK_CHECK_CAST ((obj), NAUTILUS_TYPE_PREFERENCES_ITEM, NautilusPreferencesItem)) -#define NAUTILUS_PREFERENCES_ITEM_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), NAUTILUS_TYPE_PREFERENCES_ITEM, NautilusPreferencesItemClass)) -#define NAUTILUS_IS_PREFERENCES_ITEM(obj) (GTK_CHECK_TYPE ((obj), NAUTILUS_TYPE_PREFERENCES_ITEM)) -#define NAUTILUS_IS_PREFERENCES_ITEM_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), NAUTILUS_TYPE_PREFERENCES_ITEM)) - -typedef struct NautilusPreferencesItem NautilusPreferencesItem; -typedef struct NautilusPreferencesItemClass NautilusPreferencesItemClass; -typedef struct NautilusPreferencesItemDetails NautilusPreferencesItemDetails; - -struct NautilusPreferencesItem -{ - /* Super Class */ - GtkVBox vbox; - - /* Private stuff */ - NautilusPreferencesItemDetails *details; -}; - -struct NautilusPreferencesItemClass -{ - GtkVBoxClass vbox_class; -}; - -/* - * NautilusPreferencesItemType: - * - * The types of supported preferences that also have a corresponding ui in the - * preferences dialog. Note that this is different than NautilusPreferencesType - * because it is possible to have a prefernce that is not exposed in the ui. - */ -typedef enum -{ - NAUTILUS_PREFERENCE_ITEM_BOOLEAN, - NAUTILUS_PREFERENCE_ITEM_CUSTOM, - NAUTILUS_PREFERENCE_ITEM_EDITABLE_INTEGER, - NAUTILUS_PREFERENCE_ITEM_EDITABLE_STRING, - NAUTILUS_PREFERENCE_ITEM_ENUMERATION_HORIZONTAL_RADIO, - NAUTILUS_PREFERENCE_ITEM_ENUMERATION_LIST_HORIZONTAL, - NAUTILUS_PREFERENCE_ITEM_ENUMERATION_LIST_VERTICAL, - NAUTILUS_PREFERENCE_ITEM_ENUMERATION_MENU, - NAUTILUS_PREFERENCE_ITEM_ENUMERATION_VERTICAL_RADIO, - NAUTILUS_PREFERENCE_ITEM_FONT, - NAUTILUS_PREFERENCE_ITEM_PADDING, - NAUTILUS_PREFERENCE_ITEM_SMOOTH_FONT -} NautilusPreferencesItemType; - -typedef enum -{ - NAUTILUS_PREFERENCE_ITEM_SHOW, - NAUTILUS_PREFERENCE_ITEM_HIDE -} NautilusPreferencesItemControlAction; - -GtkType nautilus_preferences_item_get_type (void); -GtkWidget* nautilus_preferences_item_new (const char *preference_name, - NautilusPreferencesItemType item_type); -GtkWidget* nautilus_preferences_item_new_custom (const char *preference_name, - GtkWidget *child, - const char *signal_name); -char * nautilus_preferences_item_get_name (const NautilusPreferencesItem *preferences_item); -void nautilus_preferences_item_set_control_preference (NautilusPreferencesItem *preferences_item, - const char *control_preference_name); -void nautilus_preferences_item_set_control_action (NautilusPreferencesItem *preferences_item, - NautilusPreferencesItemControlAction control_action); -gboolean nautilus_preferences_item_child_is_caption (const NautilusPreferencesItem *preferences_item); -int nautilus_preferences_item_get_child_width (const NautilusPreferencesItem *item); -void nautilus_preferences_item_set_caption_extra_spacing (NautilusPreferencesItem *item, - int extra_spacing); -void nautilus_preferences_item_update_showing (NautilusPreferencesItem *item); -gboolean nautilus_preferences_item_is_showing (const NautilusPreferencesItem *item); -void nautilus_preferences_item_enumeration_list_set_unique_exceptions (NautilusPreferencesItem *item, - const char *exceptions, - const char *exceptions_delimeter); - -END_GNOME_DECLS - -#endif /* NAUTILUS_PREFERENCES_ITEM_H */ - - diff --git a/libnautilus-extensions/nautilus-preferences-pane.c b/libnautilus-extensions/nautilus-preferences-pane.c deleted file mode 100644 index 0153c0e21..000000000 --- a/libnautilus-extensions/nautilus-preferences-pane.c +++ /dev/null @@ -1,298 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ - -/* nautilus-preferences-pane.h - Interface for a prefs pane superclass. - - Copyright (C) 1999, 2000 Eazel, Inc. - - The Gnome 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 Gnome 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 the Gnome 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. - - Authors: Ramiro Estrugo <ramiro@eazel.com> -*/ - - -#include <config.h> -#include "nautilus-preferences-pane.h" -#include <eel/eel-gtk-macros.h> -#include <eel/eel-gtk-extensions.h> -#include <eel/eel-string.h> -#include <eel/eel-string-list.h> - -#include <gtk/gtkhbox.h> - -static const guint GROUPS_BOX_TOP_OFFSET = 0; -static const guint IN_BETWEEN_OFFSET = 4; - -struct NautilusPreferencesPaneDetails -{ - GtkWidget *groups_box; - GList *groups; - EelStringList *control_preference_list; -}; - -/* NautilusPreferencesPaneClass methods */ -static void nautilus_preferences_pane_initialize_class (NautilusPreferencesPaneClass *preferences_pane_class); -static void nautilus_preferences_pane_initialize (NautilusPreferencesPane *preferences_pane); - -/* GtkObjectClass methods */ -static void nautilus_preferences_pane_destroy (GtkObject *object); - -EEL_DEFINE_CLASS_BOILERPLATE (NautilusPreferencesPane, nautilus_preferences_pane, GTK_TYPE_VBOX) - -/* - * NautilusPreferencesPaneClass methods - */ -static void -nautilus_preferences_pane_initialize_class (NautilusPreferencesPaneClass *preferences_pane_class) -{ - GtkObjectClass *object_class; - - object_class = GTK_OBJECT_CLASS (preferences_pane_class); - - /* GtkObjectClass */ - object_class->destroy = nautilus_preferences_pane_destroy; -} - -static void -preferences_pane_update_and_resize_callback (gpointer callback_data) -{ - g_return_if_fail (NAUTILUS_IS_PREFERENCES_PANE (callback_data)); - - nautilus_preferences_pane_update (NAUTILUS_PREFERENCES_PANE (callback_data)); - - gtk_widget_queue_resize (GTK_WIDGET (callback_data)); -} - -static void -nautilus_preferences_pane_initialize (NautilusPreferencesPane *preferences_pane) -{ - preferences_pane->details = g_new0 (NautilusPreferencesPaneDetails, 1); - - nautilus_preferences_add_callback_while_alive ("user_level", - preferences_pane_update_and_resize_callback, - preferences_pane, - GTK_OBJECT (preferences_pane)); -} - -/* GtkObjectClass methods */ -static void -nautilus_preferences_pane_destroy (GtkObject* object) -{ - NautilusPreferencesPane *preferences_pane; - - g_return_if_fail (NAUTILUS_IS_PREFERENCES_PANE (object)); - - preferences_pane = NAUTILUS_PREFERENCES_PANE (object); - - g_list_free (preferences_pane->details->groups); - eel_string_list_free (preferences_pane->details->control_preference_list); - g_free (preferences_pane->details); - - /* Chain destroy */ - EEL_CALL_PARENT (GTK_OBJECT_CLASS, destroy, (object)); -} - -/* - * NautilusPreferencesPane public methods - */ -GtkWidget * -nautilus_preferences_pane_new (void) -{ - NautilusPreferencesPane *preferences_pane; - - preferences_pane = NAUTILUS_PREFERENCES_PANE - (gtk_widget_new (nautilus_preferences_pane_get_type (), NULL)); - - /* Groups box */ - preferences_pane->details->groups_box = gtk_vbox_new (FALSE, 0); - - /* Add groups box to ourselves */ - gtk_box_pack_start (GTK_BOX (preferences_pane), - preferences_pane->details->groups_box, - FALSE, - FALSE, - GROUPS_BOX_TOP_OFFSET); - - gtk_widget_show (preferences_pane->details->groups_box); - gtk_widget_show (GTK_WIDGET (preferences_pane)); - - return GTK_WIDGET (preferences_pane); -} - -GtkWidget * -nautilus_preferences_pane_add_group (NautilusPreferencesPane *preferences_pane, - const char *group_title) -{ - GtkWidget *group; - - g_return_val_if_fail (NAUTILUS_IS_PREFERENCES_PANE (preferences_pane), NULL); - g_return_val_if_fail (group_title != NULL, NULL); - - group = nautilus_preferences_group_new (group_title); - - preferences_pane->details->groups = g_list_append (preferences_pane->details->groups, - group); - - gtk_box_pack_start (GTK_BOX (preferences_pane->details->groups_box), - group, - TRUE, - TRUE, - IN_BETWEEN_OFFSET); - - gtk_widget_show (group); - - return group; -} - -static int -preferences_pane_get_max_caption_width (const NautilusPreferencesPane *preferences_pane, - int column) -{ - NautilusPreferencesGroup *group; - GList *node; - int max_caption_width = 0; - - g_return_val_if_fail (NAUTILUS_IS_PREFERENCES_PANE (preferences_pane), 0); - g_return_val_if_fail (column >= 0, 0); - g_return_val_if_fail (column <= 1, 0); - - for (node = preferences_pane->details->groups; node != NULL; node = node->next) { - g_assert (NAUTILUS_IS_PREFERENCES_GROUP (node->data)); - group = NAUTILUS_PREFERENCES_GROUP (node->data); - - if (GTK_WIDGET_VISIBLE (group)) { - max_caption_width = MAX (max_caption_width, - nautilus_preferences_group_get_max_caption_width (group, column)); - } - } - - return max_caption_width; -} - -void -nautilus_preferences_pane_update (NautilusPreferencesPane *preferences_pane) -{ - GList *node; - int max_caption_widths[2]; - NautilusPreferencesGroup *group; - - g_return_if_fail (NAUTILUS_IS_PREFERENCES_PANE (preferences_pane)); - - for (node = preferences_pane->details->groups; node != NULL; node = node->next) { - g_assert (NAUTILUS_IS_PREFERENCES_GROUP (node->data)); - group = NAUTILUS_PREFERENCES_GROUP (node->data); - nautilus_preferences_group_update (group); - eel_gtk_widget_set_shown (GTK_WIDGET (group), - nautilus_preferences_group_get_num_visible_items (group) > 0); - } - - max_caption_widths[0] = preferences_pane_get_max_caption_width (preferences_pane, 0); - max_caption_widths[1] = preferences_pane_get_max_caption_width (preferences_pane, 1); - - for (node = preferences_pane->details->groups; node != NULL; node = node->next) { - g_assert (NAUTILUS_IS_PREFERENCES_GROUP (node->data)); - group = NAUTILUS_PREFERENCES_GROUP (node->data); - - if (GTK_WIDGET_VISIBLE (group)) { - if (max_caption_widths[0] > 0) { - nautilus_preferences_group_align_captions (group, - max_caption_widths[0], - 0); - } - - if (max_caption_widths[1] > 0) { - nautilus_preferences_group_align_captions (group, - max_caption_widths[1], - 1); - } - } - } -} - -guint -nautilus_preferences_pane_get_num_visible_groups (const NautilusPreferencesPane *pane) -{ - guint n = 0; - GList *node; - - g_return_val_if_fail (NAUTILUS_IS_PREFERENCES_PANE (pane), 0); - - for (node = pane->details->groups; node != NULL; node = node->next) { - NautilusPreferencesGroup *group = NAUTILUS_PREFERENCES_GROUP (node->data); - - if (GTK_WIDGET_VISIBLE (group)) { - n++; - } - } - - return n; -} - -guint -nautilus_preferences_pane_get_num_groups (const NautilusPreferencesPane *pane) -{ - g_return_val_if_fail (NAUTILUS_IS_PREFERENCES_PANE (pane), 0); - - return g_list_length (pane->details->groups); -} - -GtkWidget * -nautilus_preferences_pane_find_group (const NautilusPreferencesPane *pane, - const char *group_title) -{ - GList *node; - char *title; - - g_return_val_if_fail (NAUTILUS_IS_PREFERENCES_PANE (pane), 0); - - for (node = pane->details->groups; node != NULL; node = node->next) { - g_assert (NAUTILUS_IS_PREFERENCES_GROUP (node->data)); - - title = nautilus_preferences_group_get_title_label (NAUTILUS_PREFERENCES_GROUP (node->data)); - if (eel_str_is_equal (title, group_title)) { - g_free (title); - return node->data; - } - - g_free (title); - } - - return NULL; -} - -void -nautilus_preferences_pane_add_control_preference (NautilusPreferencesPane *pane, - const char *control_preference_name) -{ - g_return_if_fail (NAUTILUS_IS_PREFERENCES_PANE (pane)); - g_return_if_fail (control_preference_name != NULL); - - if (eel_string_list_contains (pane->details->control_preference_list, - control_preference_name)) { - return; - } - - if (pane->details->control_preference_list == NULL) { - pane->details->control_preference_list = eel_string_list_new (TRUE); - } - - eel_string_list_insert (pane->details->control_preference_list, - control_preference_name); - - nautilus_preferences_add_callback_while_alive (control_preference_name, - preferences_pane_update_and_resize_callback, - pane, - GTK_OBJECT (pane)); -} diff --git a/libnautilus-extensions/nautilus-preferences-pane.h b/libnautilus-extensions/nautilus-preferences-pane.h deleted file mode 100644 index 93aa2de15..000000000 --- a/libnautilus-extensions/nautilus-preferences-pane.h +++ /dev/null @@ -1,72 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ - -/* nautilus-preferences-pane.h - Interface for a prefs pane superclass. - - Copyright (C) 1999, 2000 Eazel, Inc. - - The Gnome 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 Gnome 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 the Gnome 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. - - Authors: Ramiro Estrugo <ramiro@eazel.com> -*/ - -#ifndef NAUTILUS_PREFERENCES_PANE_H -#define NAUTILUS_PREFERENCES_PANE_H - -#include <libgnomeui/gnome-dialog.h> -#include <gtk/gtkvbox.h> -#include <libnautilus-extensions/nautilus-preferences-group.h> - -BEGIN_GNOME_DECLS - -#define NAUTILUS_TYPE_PREFERENCES_PANE (nautilus_preferences_pane_get_type ()) -#define NAUTILUS_PREFERENCES_PANE(obj) (GTK_CHECK_CAST ((obj), NAUTILUS_TYPE_PREFERENCES_PANE, NautilusPreferencesPane)) -#define NAUTILUS_PREFERENCES_PANE_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), NAUTILUS_TYPE_PREFERENCES_PANE, NautilusPreferencesPaneClass)) -#define NAUTILUS_IS_PREFERENCES_PANE(obj) (GTK_CHECK_TYPE ((obj), NAUTILUS_TYPE_PREFERENCES_PANE)) -#define NAUTILUS_IS_PREFERENCES_PANE_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), NAUTILUS_TYPE_PREFERENCES_PANE)) - -typedef struct NautilusPreferencesPane NautilusPreferencesPane; -typedef struct NautilusPreferencesPaneClass NautilusPreferencesPaneClass; -typedef struct NautilusPreferencesPaneDetails NautilusPreferencesPaneDetails; - -struct NautilusPreferencesPane -{ - /* Super Class */ - GtkVBox vbox; - - /* Private stuff */ - NautilusPreferencesPaneDetails *details; -}; - -struct NautilusPreferencesPaneClass -{ - GtkVBoxClass parent_class; -}; - -GtkType nautilus_preferences_pane_get_type (void); -GtkWidget* nautilus_preferences_pane_new (void); -GtkWidget *nautilus_preferences_pane_add_group (NautilusPreferencesPane *preferences_pane, - const char *group_title); -void nautilus_preferences_pane_update (NautilusPreferencesPane *preferences_pane); -guint nautilus_preferences_pane_get_num_groups (const NautilusPreferencesPane *pane); -guint nautilus_preferences_pane_get_num_visible_groups (const NautilusPreferencesPane *pane); -GtkWidget* nautilus_preferences_pane_find_group (const NautilusPreferencesPane *preferences_pane, - const char *group_title); -void nautilus_preferences_pane_add_control_preference (NautilusPreferencesPane *preferences_pane, - const char *control_preference_name); - -END_GNOME_DECLS - -#endif /* NAUTILUS_PREFERENCES_PANE_H */ diff --git a/libnautilus-extensions/nautilus-preferences.c b/libnautilus-extensions/nautilus-preferences.c deleted file mode 100644 index 1dde99348..000000000 --- a/libnautilus-extensions/nautilus-preferences.c +++ /dev/null @@ -1,1858 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ - -/* nautilus-preferences.c - Preference peek/poke/notify implementation. - - Copyright (C) 1999, 2000 Eazel, Inc. - - The Gnome 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 Gnome 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 the Gnome 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. - - Authors: Ramiro Estrugo <ramiro@eazel.com> -*/ - -#include <config.h> -#include "nautilus-preferences.h" - -#include "nautilus-gconf-extensions.h" -#include "nautilus-lib-self-check-functions.h" -#include <eel/eel-enumeration.h> -#include <eel/eel-glib-extensions.h> -#include <eel/eel-string-list.h> -#include <eel/eel-string.h> -#include <gconf/gconf-client.h> -#include <gconf/gconf.h> -#include <gtk/gtksignal.h> -#include <libgnome/gnome-defs.h> -#include <libgnome/gnome-i18n.h> -#include <libgnomeui/gnome-dialog.h> -#include <libgnomeui/gnome-dialog-util.h> - -#define DEFAULT_USER_LEVEL NAUTILUS_USER_LEVEL_INTERMEDIATE -#define USER_LEVEL_KEY "/apps/nautilus/user_level" - -/* An enumeration used for updating auto-storage variables in a type-specific way. - * FIXME: there is another enumeration like this in nautilus-global-preferences.c, - * used for different purposes but in a related way. Should we combine them? - */ -typedef enum -{ - PREFERENCE_BOOLEAN = 1, - PREFERENCE_INTEGER, - PREFERENCE_STRING, - PREFERENCE_STRING_LIST -} PreferenceType; - -/* - * PreferencesEntry: - * - * A structure to manage preference hash table nodes. - * Preferences are hash tables. The hash key is the preference name - * (a string). The hash value is a pointer of the following struct: - */ -typedef struct { - char *name; - char *description; - PreferenceType type; - gboolean invisible; - GList *callback_list; - gboolean callbacks_blocked; - GList *auto_storage_list; - int gconf_connection_id; - char *enumeration_id; - GConfValue *cached_value; -} PreferencesEntry; - -/* - * PreferencesCallbackEntry: - * - * A structure to manage callback lists. A callback list is a GList. - * The callback_data in each list node is a pointer to the following - * struct: - */ -typedef struct { - NautilusPreferencesCallback callback; - gpointer callback_data; -} PreferencesCallbackEntry; - -static const char *user_level_names_for_display[] = -{ - N_("Beginner"), - N_("Intermediate"), - N_("Advanced") -}; - -static const char *user_level_names_for_storage[] = -{ - "novice", - "intermediate", - "advanced" -}; - -static const char * preferences_peek_storage_path (void); -static const char * preferences_peek_defaults_path (void); -static const char * preferences_peek_visibility_path (void); -static gboolean preferences_preference_is_internal (const char *name); -static gboolean preferences_preference_is_user_level (const char *name); -static gboolean preferences_preference_is_default (const char *name); -static char * preferences_key_make (const char *name); -static char * preferences_key_make_for_getter (const char *name); -static char * preferences_key_make_for_default (const char *name, - int user_level); -static char * preferences_key_make_for_default_getter (const char *name, - int user_level); -static char * preferences_key_make_for_visibility (const char *name); -static void preferences_user_level_changed_notice (GConfClient *client, - guint connection_id, - GConfEntry *gconf_entry, - gpointer user_data); -static void preferences_something_changed_notice (GConfClient *client, - guint connection_id, - GConfEntry *gconf_entry, - gpointer user_data); -static void preferences_global_table_check_changes_function (gpointer key, - gpointer value, - gpointer callback_data); -static GHashTable *preferences_global_table_get_global (void); -static void preferences_callback_entry_free (PreferencesCallbackEntry *callback_entry); -static void preferences_entry_update_auto_storage (PreferencesEntry *entry); -static void preferences_global_table_free (void); -static const char * preferences_peek_user_level_name_for_storage (int user_level); -static PreferencesEntry * preferences_global_table_lookup_or_insert (const char *name); - -static guint user_level_changed_connection_id = NAUTILUS_GCONF_UNDEFINED_CONNECTION; -static GHashTable *global_table = NULL; -static char *storage_path = NULL; -static char *defaults_path = NULL; -static char *visiblity_path = NULL; -static gboolean initialized = FALSE; - -static const char * -preferences_peek_storage_path (void) -{ - g_return_val_if_fail (storage_path != NULL, NULL); - - return storage_path; -} - -static void -preferences_set_storage_path (const char *new_storage_path) -{ - g_return_if_fail (eel_strlen (new_storage_path) > 0); - - /* Make sure the path is indeed different */ - if (eel_str_is_equal (new_storage_path, storage_path)) { - return; - } - - /* Free the preference hash table */ - preferences_global_table_free (); - - /* Stop monitoring the old path */ - nautilus_gconf_monitor_remove (storage_path); - - g_free (storage_path); - storage_path = g_strdup (new_storage_path); - - /* Start monitoring the new path */ - nautilus_gconf_monitor_add (storage_path); -} - -static gboolean -preferences_is_initialized (void) -{ - return initialized; -} - -static const char * -preferences_peek_defaults_path (void) -{ - if (defaults_path == NULL) { - defaults_path = g_strdup_printf ("%s/defaults", preferences_peek_storage_path ()); - } - - return defaults_path; -} - -static const char * -preferences_peek_visibility_path (void) -{ - if (visiblity_path == NULL) { - visiblity_path = g_strdup_printf ("%s/visibility", preferences_peek_storage_path ()); - } - - return visiblity_path; -} - -static const char * -preferences_peek_user_level_name_for_storage (int user_level) -{ - user_level = nautilus_preferences_user_level_clamp (user_level); - - return user_level_names_for_storage[user_level]; -} - -/* If the preference name begind with a "/", we interpret - * it as a straight gconf key. */ -static gboolean -preferences_preference_is_internal (const char *name) -{ - g_return_val_if_fail (name != NULL, FALSE); - - if (eel_str_has_prefix (name, "/")) { - return FALSE; - } - - return TRUE; -} - -static gboolean -preferences_preference_is_user_level (const char *name) -{ - g_return_val_if_fail (name != NULL, FALSE); - - return eel_str_is_equal (name, USER_LEVEL_KEY) - || eel_str_is_equal (name, "user_level"); -} - -static char * -preferences_key_make (const char *name) -{ - g_return_val_if_fail (name != NULL, NULL); - - if (!preferences_preference_is_internal (name)) { - return g_strdup (name); - } - - /* Otherwise, we prefix it with the path */ - return g_strdup_printf ("%s/%s", preferences_peek_storage_path (), name); -} - -static char * -preferences_key_make_for_default (const char *name, - int user_level) -{ - char *key; - char *default_key = NULL; - - g_return_val_if_fail (name != NULL, NULL); - - user_level = nautilus_preferences_user_level_clamp (user_level); - key = preferences_key_make (name); - default_key = g_strdup_printf ("%s/%s%s", - preferences_peek_defaults_path (), - preferences_peek_user_level_name_for_storage (user_level), - key); - g_free (key); - - return default_key; -} - -static char * -preferences_key_make_for_default_getter (const char *name, - int user_level) -{ - char *default_key_for_getter = NULL; - gboolean done; - - g_return_val_if_fail (name != NULL, NULL); - - user_level = nautilus_preferences_user_level_clamp (user_level); - - done = FALSE; - while (!done) { - default_key_for_getter = preferences_key_make_for_default (name, user_level); - - done = (user_level == 0) || (!nautilus_gconf_is_default (default_key_for_getter)); - - if (!done) { - g_free (default_key_for_getter); - user_level--; - } - } - - return default_key_for_getter; -} - -static char * -preferences_key_make_for_visibility (const char *name) -{ - char *default_key; - char *key; - - g_return_val_if_fail (name != NULL, NULL); - - key = preferences_key_make (name); - default_key = g_strdup_printf ("%s%s", preferences_peek_visibility_path (), key); - g_free (key); - - return default_key; -} - -static gboolean -preferences_preference_is_default (const char *name) -{ - gboolean result; - char *key; - - g_return_val_if_fail (name != NULL, FALSE); - - key = preferences_key_make (name); - result = nautilus_gconf_is_default (key); - g_free (key); - - return result; -} - -static char * -preferences_make_user_level_filtered_key (const char *name) -{ - char *key; - - g_return_val_if_fail (name != NULL, NULL); - - if (nautilus_preferences_visible_in_current_user_level (name)) { - key = preferences_key_make (name); - } else { - key = preferences_key_make_for_default (name, nautilus_preferences_get_user_level ()); - } - - return key; -} - -static void -preferences_block_callbacks (const char *name) -{ - PreferencesEntry *entry; - - g_return_if_fail (name != NULL); - g_return_if_fail (preferences_is_initialized ()); - - entry = preferences_global_table_lookup_or_insert (name); - g_assert (entry != NULL); - - entry->callbacks_blocked = TRUE; -} - -static void -preferences_unblock_callbacks (const char *name) -{ - PreferencesEntry *entry; - - g_return_if_fail (name != NULL); - g_return_if_fail (preferences_is_initialized ()); - - entry = preferences_global_table_lookup_or_insert (name); - g_assert (entry != NULL); - - entry->callbacks_blocked = FALSE; -} - -/* Public preferences functions */ -int -nautilus_preferences_get_visible_user_level (const char *name) -{ - int result; - char *visible_key; - - g_return_val_if_fail (name != NULL, FALSE); - g_return_val_if_fail (preferences_is_initialized (), FALSE); - - visible_key = preferences_key_make_for_visibility (name); - result = nautilus_gconf_get_integer (visible_key); - g_free (visible_key); - - return result; -} - -void -nautilus_preferences_set_visible_user_level (const char *name, - int visible_user_level) -{ - char *visible_key; - - g_return_if_fail (name != NULL); - g_return_if_fail (preferences_is_initialized ()); - - visible_key = preferences_key_make_for_visibility (name); - nautilus_gconf_set_integer (visible_key, visible_user_level); - g_free (visible_key); -} - -gboolean -nautilus_preferences_get_is_invisible (const char *name) -{ - g_return_val_if_fail (name != NULL, FALSE); - g_return_val_if_fail (preferences_is_initialized (), FALSE); - - return preferences_global_table_lookup_or_insert (name)->invisible; -} - -void -nautilus_preferences_set_is_invisible (const char *name, - gboolean is_invisible) -{ - g_return_if_fail (name != NULL); - g_return_if_fail (preferences_is_initialized ()); - - preferences_global_table_lookup_or_insert (name)->invisible = is_invisible; -} - -void -nautilus_preferences_set_boolean (const char *name, - gboolean boolean_value) -{ - char *key; - - g_return_if_fail (name != NULL); - g_return_if_fail (preferences_is_initialized ()); - - key = preferences_key_make (name); - nautilus_gconf_set_boolean (key, boolean_value); - g_free (key); - - nautilus_gconf_suggest_sync (); -} - -static char * -preferences_key_make_for_getter (const char *name) -{ - char *key; - - g_return_val_if_fail (name != NULL, NULL); - g_return_val_if_fail (preferences_is_initialized (), NULL); - - if (preferences_preference_is_default (name) || !nautilus_preferences_visible_in_current_user_level (name)) { - key = preferences_key_make_for_default_getter (name, nautilus_preferences_get_user_level ()); - } else { - key = preferences_make_user_level_filtered_key (name); - } - - return key; -} - -gboolean -nautilus_preferences_get_boolean (const char *name) -{ - gboolean result; - char *key; - - g_return_val_if_fail (name != NULL, FALSE); - g_return_val_if_fail (preferences_is_initialized (), FALSE); - - key = preferences_key_make_for_getter (name); - result = nautilus_gconf_get_boolean (key); - g_free (key); - - return result; -} - -void -nautilus_preferences_set_integer (const char *name, - int int_value) -{ - char *key; - int old_value; - - g_return_if_fail (name != NULL); - g_return_if_fail (preferences_is_initialized ()); - - key = preferences_key_make (name); - old_value = nautilus_preferences_get_integer (name); - - if (int_value != old_value) { - nautilus_gconf_set_integer (key, int_value); - nautilus_gconf_suggest_sync (); - } - g_free (key); -} - -int -nautilus_preferences_get_integer (const char *name) -{ - int result; - char *key; - - g_return_val_if_fail (name != NULL, 0); - g_return_val_if_fail (preferences_is_initialized (), 0); - - key = preferences_key_make_for_getter (name); - result = nautilus_gconf_get_integer (key); - g_free (key); - - return result; -} - -void -nautilus_preferences_set (const char *name, - const char *string_value) -{ - char *key; - char *old_value; - - g_return_if_fail (name != NULL); - g_return_if_fail (preferences_is_initialized ()); - - key = preferences_key_make (name); - old_value = nautilus_preferences_get (name); - - if (strcmp (string_value, old_value) != 0) { - nautilus_gconf_set_string (key, string_value); - - nautilus_gconf_suggest_sync (); - } - g_free (key); -} - -char * -nautilus_preferences_get (const char *name) -{ - char *result; - char *key; - - g_return_val_if_fail (name != NULL, NULL); - g_return_val_if_fail (preferences_is_initialized (), NULL); - - key = preferences_key_make_for_getter (name); - result = nautilus_gconf_get_string (key); - g_free (key); - - if (result == NULL) { - result = g_strdup (""); - } - - return result; -} - -void -nautilus_preferences_set_string_list (const char *name, - const EelStringList *string_list_value) -{ - char *key; - GSList *slist; - - g_return_if_fail (name != NULL); - g_return_if_fail (preferences_is_initialized ()); - - slist = eel_string_list_as_g_slist (string_list_value); - - key = preferences_key_make (name); - nautilus_gconf_set_string_list (key, slist); - g_free (key); - - eel_g_slist_free_deep (slist); - - nautilus_gconf_suggest_sync (); -} - -static gboolean -string_list_is_valid (const EelStringList *string_list, - const char *enumeration_id) -{ - guint i; - char *nth; - gboolean bad; - - g_return_val_if_fail (string_list != NULL, FALSE); - g_return_val_if_fail (enumeration_id != NULL, FALSE); - - bad = FALSE; - for (i = 0; i < eel_string_list_get_length (string_list) && !bad; i++) { - nth = eel_string_list_nth (string_list, i); - bad = !eel_enumeration_id_contains_name (enumeration_id, nth); - g_free (nth); - } - - return !bad; -} - -EelStringList * -nautilus_preferences_get_string_list (const char *name) -{ - EelStringList *result; - char *key; - GSList *slist; - PreferencesEntry *entry; - char *default_key; - - g_return_val_if_fail (name != NULL, NULL); - g_return_val_if_fail (preferences_is_initialized (), NULL); - - key = preferences_key_make_for_getter (name); - slist = nautilus_gconf_get_string_list (key); - g_free (key); - - result = eel_string_list_new_from_g_slist (slist, TRUE); - eel_g_slist_free_deep (slist); - - entry = preferences_global_table_lookup_or_insert (name); - g_assert (entry != NULL); - - /* No enumeration_id so we're done */ - if (entry->enumeration_id == NULL) { - return result; - } - - /* Do a sanity check on the validity of the values */ - if (string_list_is_valid (result, entry->enumeration_id)) { - return result; - } - - /* Forget the bad value and use the default instead */ - eel_string_list_free (result); - default_key = preferences_key_make_for_default_getter (name, - nautilus_preferences_get_user_level ()); - slist = nautilus_gconf_get_string_list (default_key); - g_free (default_key); - - result = eel_string_list_new_from_g_slist (slist, TRUE); - eel_g_slist_free_deep (slist); - - /* Go the extra mile and fix the problem for the user */ - preferences_block_callbacks (name); - nautilus_preferences_set_string_list (name, result); - preferences_unblock_callbacks (name); - - return result; -} - -int -nautilus_preferences_get_user_level (void) -{ - char *user_level; - int result; - - g_return_val_if_fail (preferences_is_initialized (), 0); - - user_level = nautilus_gconf_get_string (USER_LEVEL_KEY); - - if (eel_str_is_equal (user_level, "advanced")) { - result = NAUTILUS_USER_LEVEL_ADVANCED; - } else if (eel_str_is_equal (user_level, "intermediate")) { - result = NAUTILUS_USER_LEVEL_INTERMEDIATE; - } else if (eel_str_is_equal (user_level, "novice")) { - result = NAUTILUS_USER_LEVEL_NOVICE; - } else { - result = DEFAULT_USER_LEVEL; - } - - g_free (user_level); - return result; -} - -void -nautilus_preferences_set_user_level (int user_level) -{ - g_return_if_fail (preferences_is_initialized ()); - g_return_if_fail (nautilus_preferences_user_level_is_valid (user_level)); - - user_level = nautilus_preferences_user_level_clamp (user_level); - - nautilus_gconf_set_string (USER_LEVEL_KEY, user_level_names_for_storage[user_level]); - - nautilus_gconf_suggest_sync (); -} - -void -nautilus_preferences_default_set_integer (const char *name, - int user_level, - int int_value) -{ - char *default_key; - - g_return_if_fail (name != NULL); - g_return_if_fail (preferences_is_initialized ()); - - default_key = preferences_key_make_for_default (name, user_level); - nautilus_gconf_set_integer (default_key, int_value); - g_free (default_key); -} - -int -nautilus_preferences_default_get_integer (const char *name, - int user_level) -{ - int result; - char *default_key; - - g_return_val_if_fail (name != NULL, 0); - g_return_val_if_fail (preferences_is_initialized (), 0); - - default_key = preferences_key_make_for_default (name, user_level); - result = nautilus_gconf_get_integer (default_key); - g_free (default_key); - - return result; -} - -void -nautilus_preferences_default_set_boolean (const char *name, - int user_level, - gboolean boolean_value) -{ - char *default_key; - - g_return_if_fail (name != NULL); - g_return_if_fail (preferences_is_initialized ()); - - default_key = preferences_key_make_for_default (name, user_level); - nautilus_gconf_set_boolean (default_key, boolean_value); - g_free (default_key); -} - -gboolean -nautilus_preferences_default_get_boolean (const char *name, - int user_level) -{ - gboolean result; - char *default_key; - - g_return_val_if_fail (name != NULL, FALSE); - g_return_val_if_fail (preferences_is_initialized (), FALSE); - - default_key = preferences_key_make_for_default (name, user_level); - result = nautilus_gconf_get_boolean (default_key); - g_free (default_key); - - return result; -} - -void -nautilus_preferences_default_set_string (const char *name, - int user_level, - const char *string_value) -{ - char *default_key; - - g_return_if_fail (name != NULL); - g_return_if_fail (preferences_is_initialized ()); - - default_key = preferences_key_make_for_default (name, user_level); - nautilus_gconf_set_string (default_key, string_value); - g_free (default_key); -} - -char * -nautilus_preferences_default_get_string (const char *name, - int user_level) -{ - char *result; - char *default_key; - - g_return_val_if_fail (name != NULL, NULL); - g_return_val_if_fail (preferences_is_initialized (), NULL); - - default_key = preferences_key_make_for_default (name, user_level); - result = nautilus_gconf_get_string (default_key); - g_free (default_key); - - return result; -} - -void -nautilus_preferences_default_set_string_list (const char *name, - int user_level, - const EelStringList *string_list_value) -{ - char *default_key; - GSList *slist; - - g_return_if_fail (name != NULL); - g_return_if_fail (preferences_is_initialized ()); - - slist = eel_string_list_as_g_slist (string_list_value); - - default_key = preferences_key_make_for_default (name, user_level); - nautilus_gconf_set_string_list (default_key, slist); - g_free (default_key); - - eel_g_slist_free_deep (slist); -} - -EelStringList * -nautilus_preferences_default_get_string_list (const char *name, - int user_level) -{ - EelStringList *result; - char *default_key; - GSList *slist; - - g_return_val_if_fail (name != NULL, NULL); - g_return_val_if_fail (preferences_is_initialized (), NULL); - - default_key = preferences_key_make_for_default (name, user_level); - slist = nautilus_gconf_get_string_list (default_key); - g_free (default_key); - - result = eel_string_list_new_from_g_slist (slist, TRUE); - eel_g_slist_free_deep (slist); - - return result; -} - -/** - * preferences_callback_entry_invoke_function - * - * A function that invokes a callback from the given struct. It is meant to be fed to - * g_list_foreach () - * @data: The list data privately maintained by the GList. - * @callback_data: The callback_data privately maintained by the GList. - **/ -static void -preferences_callback_entry_invoke_function (gpointer data, - gpointer callback_data) -{ - PreferencesCallbackEntry *callback_entry; - - g_return_if_fail (data != NULL); - - callback_entry = data; - - (* callback_entry->callback) (callback_entry->callback_data); -} - -/** - * preferences_entry_invoke_callbacks_if_needed - * - * @entry: A PreferencesEntry - * - * This function checks the cached value in the entry with the current - * value of the preference. If the value has changed, then callbacks - * are invoked and auto storage updated. - * - * We need this check because even though the GConf value of a preference - * could indeed have changed, its representation on the Nautilus side - * of things could still be the same. The best example of this is - * user level changes, where the value of the preference on the Nautilus - * end of things is determined by visibility. - **/ -static void -preferences_entry_invoke_callbacks_if_needed (PreferencesEntry *entry) -{ - GConfValue *new_value; - char *getter_key; - - g_return_if_fail (entry != NULL); - - getter_key = preferences_key_make_for_getter (entry->name); - new_value = nautilus_gconf_get_value (getter_key); - g_free (getter_key); - - /* If the values are the same, then we dont need to invoke any callbacks */ - if (nautilus_gconf_value_is_equal (entry->cached_value, new_value)) { - nautilus_gconf_value_free (new_value); - return; - } - - /* Update the auto storage preferences */ - if (entry->auto_storage_list != NULL) { - preferences_entry_update_auto_storage (entry); - } - - /* Store the new cached value */ - nautilus_gconf_value_free (entry->cached_value); - entry->cached_value = new_value; - - /* Dont invoke callbacks if the entry is blocked */ - if (entry->callbacks_blocked) { - return; - } - - /* Invoke callbacks for this entry if any */ - if (entry->callback_list != NULL) { - g_list_foreach (entry->callback_list, - preferences_callback_entry_invoke_function, - NULL); - } -} - -static void -update_auto_string (gpointer data, gpointer callback_data) -{ - char **storage; - const char *value; - - g_return_if_fail (data != NULL); - g_return_if_fail (callback_data != NULL); - - storage = (char **)data; - value = (const char *)callback_data; - - g_free (*storage); - *(char **)storage = g_strdup (value); -} - -static void -update_auto_string_list (gpointer data, gpointer callback_data) -{ - EelStringList **storage; - const EelStringList *value; - - g_return_if_fail (data != NULL); - g_return_if_fail (callback_data != NULL); - - storage = (EelStringList **)data; - value = (const EelStringList *)callback_data; - - eel_string_list_free (*storage); - *(EelStringList **)storage = eel_string_list_copy (value); -} - -static void -update_auto_integer_or_boolean (gpointer data, gpointer callback_data) -{ - g_return_if_fail (data != NULL); - - *(int *)data = GPOINTER_TO_INT (callback_data); -} - -static void -preferences_entry_update_auto_storage (PreferencesEntry *entry) -{ - char *new_string_value; - EelStringList *new_string_list_value; - int new_int_value; - gboolean new_boolean_value; - - switch (entry->type) { - case PREFERENCE_STRING: - new_string_value = nautilus_preferences_get (entry->name); - g_list_foreach (entry->auto_storage_list, - update_auto_string, - new_string_value); - g_free (new_string_value); - break; - case PREFERENCE_STRING_LIST: - new_string_list_value = nautilus_preferences_get_string_list (entry->name); - g_list_foreach (entry->auto_storage_list, - update_auto_string_list, - new_string_list_value); - eel_string_list_free (new_string_list_value); - break; - case PREFERENCE_INTEGER: - new_int_value = nautilus_preferences_get_integer (entry->name); - g_list_foreach (entry->auto_storage_list, - update_auto_integer_or_boolean, - GINT_TO_POINTER (new_int_value)); - break; - case PREFERENCE_BOOLEAN: - new_boolean_value = nautilus_preferences_get_boolean (entry->name); - g_list_foreach (entry->auto_storage_list, - update_auto_integer_or_boolean, - GINT_TO_POINTER (new_boolean_value)); - break; - default: - g_warning ("unexpected preferences type %d in preferences_entry_update_auto_storage", entry->type); - } -} - -static void -preferences_something_changed_notice (GConfClient *client, - guint connection_id, - GConfEntry *entry, - gpointer notice_data) -{ - g_return_if_fail (entry != NULL); - g_return_if_fail (entry->key != NULL); - g_return_if_fail (notice_data != NULL); - - preferences_entry_invoke_callbacks_if_needed (notice_data); -} - -static void -preferences_global_table_check_changes_function (gpointer key, - gpointer value, - gpointer user_data) -{ - PreferencesEntry *entry; - - g_return_if_fail (key != NULL); - g_return_if_fail (value != NULL); - - entry = value; - - g_return_if_fail (entry->name != NULL); - - /* We dont worry about the 'user_level' itself for recursive reasons */ - if (preferences_preference_is_user_level (entry->name)) { - return; - } - - preferences_entry_invoke_callbacks_if_needed (entry); -} - -static void -preferences_entry_update_cached_value (PreferencesEntry *entry) -{ - char *getter_key; - - g_return_if_fail (entry != NULL); - - nautilus_gconf_value_free (entry->cached_value); - - getter_key = preferences_key_make_for_getter (entry->name); - entry->cached_value = nautilus_gconf_get_value (getter_key); - g_free (getter_key); -} - -static void -preferences_user_level_changed_notice (GConfClient *client, - guint connection_id, - GConfEntry *gconf_entry, - gpointer user_data) -{ - g_return_if_fail (gconf_entry != NULL); - g_return_if_fail (gconf_entry->key != NULL); - g_return_if_fail (eel_str_has_suffix (gconf_entry->key, "user_level")); - - g_hash_table_foreach (preferences_global_table_get_global (), - preferences_global_table_check_changes_function, - NULL); -} - -static void -preferences_entry_ensure_gconf_connection (PreferencesEntry *entry) -{ - char *key; - - /* - * We install only one gconf notification for each preference entry. - * Otherwise, we would invoke the installed callbacks more than once - * per registered callback. - */ - if (entry->gconf_connection_id != NAUTILUS_GCONF_UNDEFINED_CONNECTION) { - return; - } - - g_return_if_fail (entry->name != NULL); - - key = preferences_key_make (entry->name); - - entry->gconf_connection_id = nautilus_gconf_notification_add (key, - preferences_something_changed_notice, - entry); - g_free (key); - - g_return_if_fail (entry->gconf_connection_id != NAUTILUS_GCONF_UNDEFINED_CONNECTION); - - /* Update the cached value. - * From now onwards the cached value will be updated - * each time preferences_something_changed_notice() triggers - * so that it can be later compared with new values to - * determine if the gconf value is different from the - * Nautilus value. - */ - preferences_entry_update_cached_value (entry); -} - -/** - * preferences_entry_add_callback - * - * Add a callback to a pref node. Callbacks are fired whenever - * the pref value changes. - * @preferences_entry: The hash node. - * @callback: The user-supplied callback. - * @callback_data: The user-supplied closure. - **/ -static void -preferences_entry_add_callback (PreferencesEntry *entry, - NautilusPreferencesCallback callback, - gpointer callback_data) -{ - PreferencesCallbackEntry *callback_entry; - - g_return_if_fail (entry != NULL); - g_return_if_fail (callback != NULL); - - callback_entry = g_new0 (PreferencesCallbackEntry, 1); - callback_entry->callback = callback; - callback_entry->callback_data = callback_data; - - g_return_if_fail (callback_entry != NULL); - - entry->callback_list = g_list_append (entry->callback_list, callback_entry); - - preferences_entry_ensure_gconf_connection (entry); -} - -/** - * preferences_entry_add_auto_storage - * - * Add an auto-storage variable to a pref node. The variable will - * be updated to match the pref value whenever the pref - * the pref value changes. - * @preferences_entry: The hash node. - * @storage: The user-supplied location at which to store the value. - * @type: Which type of variable this is. - **/ -static void -preferences_entry_add_auto_storage (PreferencesEntry *entry, - gpointer storage, - PreferenceType type) -{ - g_return_if_fail (entry != NULL); - g_return_if_fail (storage != NULL); - g_return_if_fail (entry->type == 0 || entry->type == type); - g_return_if_fail (g_list_find (entry->auto_storage_list, storage) == NULL); - - entry->type = type; - - entry->auto_storage_list = g_list_append (entry->auto_storage_list, storage); - - preferences_entry_ensure_gconf_connection (entry); -} - -static void -preferences_entry_check_remove_connection (PreferencesEntry *entry) -{ - /* - * If there are no callbacks or auto-storage variables left in the entry, - * remove the gconf notification. - */ - if (entry->callback_list != NULL || entry->auto_storage_list != NULL) { - return; - } - - nautilus_gconf_notification_remove (entry->gconf_connection_id); - entry->gconf_connection_id = NAUTILUS_GCONF_UNDEFINED_CONNECTION; -} - -/** - * preferences_entry_remove_callback - * - * remove a callback from a pref entry. Both the callback and the callback_data must - * match in order for a callback to be removed from the entry. - * @preferences_entry: The hash entry. - * @callback: The user-supplied callback. - * @callback_data: The user-supplied closure. - **/ -static void -preferences_entry_remove_callback (PreferencesEntry *entry, - NautilusPreferencesCallback callback, - gpointer callback_data) -{ - GList *new_list; - const GList *node; - - g_return_if_fail (entry != NULL); - g_return_if_fail (callback != NULL); - g_return_if_fail (entry->callback_list != NULL); - - new_list = g_list_copy (entry->callback_list); - - for (node = new_list; node != NULL; node = node->next) { - PreferencesCallbackEntry *callback_entry = node->data; - - g_return_if_fail (callback_entry != NULL); - - if (callback_entry->callback == callback && - callback_entry->callback_data == callback_data) { - entry->callback_list = g_list_remove (entry->callback_list, - callback_entry); - - preferences_callback_entry_free (callback_entry); - } - } - - g_list_free (new_list); - - preferences_entry_check_remove_connection (entry); -} - -/** - * preferences_entry_remove_auto_storage - * - * remove an auto-storage variable from a pref entry. - * @preferences_entry: The hash entry. - * @storage: The user-supplied location. - **/ -static void -preferences_entry_remove_auto_storage (PreferencesEntry *entry, - gpointer storage) -{ - GList *new_list; - const GList *node; - gpointer storage_in_entry; - - g_return_if_fail (entry != NULL); - g_return_if_fail (storage != NULL); - g_return_if_fail (entry->auto_storage_list != NULL); - - new_list = g_list_copy (entry->auto_storage_list); - - for (node = new_list; node != NULL; node = node->next) { - storage_in_entry = node->data; - - g_return_if_fail (storage_in_entry != NULL); - - if (storage_in_entry == storage) { - entry->auto_storage_list = g_list_remove (entry->auto_storage_list, - storage); - - switch (entry->type) { - case PREFERENCE_STRING: - update_auto_string (storage, NULL); - break; - case PREFERENCE_STRING_LIST: - update_auto_string_list (storage, NULL); - break; - case PREFERENCE_BOOLEAN: - case PREFERENCE_INTEGER: - update_auto_integer_or_boolean (storage, 0); - break; - default: - g_warning ("unexpected preference type %d in preferences_entry_remove_auto_storage", entry->type); - } - } - } - - g_list_free (new_list); - - preferences_entry_check_remove_connection (entry); -} - -/** - * preferences_callback_entry_free - * - * Free a callback info struct. - * @preferences_callback_entry: The struct to free. - **/ -static void -preferences_callback_entry_free (PreferencesCallbackEntry *callback_entry) -{ - g_return_if_fail (callback_entry != NULL); - - callback_entry->callback = NULL; - callback_entry->callback_data = NULL; - - g_free (callback_entry); -} - -/** - * preferences_callback_entry_free_func - * - * A function that frees a callback info struct. It is meant to be fed to - * g_list_foreach () - * @data: The list data privately maintained by the GList. - * @callback_data: The callback_data privately maintained by the GList. - **/ -static void -preferences_callback_entry_free_func (gpointer data, - gpointer callback_data) -{ - g_return_if_fail (data != NULL); - - preferences_callback_entry_free (data); -} - -/** - * preferences_entry_free - * - * Free a preference hash node's members along with the node itself. - * @preferences_hash_node: The node to free. - **/ -static void -preferences_entry_free (PreferencesEntry *entry) -{ - g_return_if_fail (entry != NULL); - - nautilus_gconf_notification_remove (entry->gconf_connection_id); - entry->gconf_connection_id = NAUTILUS_GCONF_UNDEFINED_CONNECTION; - - g_list_free (entry->auto_storage_list); - eel_g_list_free_deep_custom (entry->callback_list, - preferences_callback_entry_free_func, - NULL); - - entry->auto_storage_list = NULL; - entry->callback_list = NULL; - - g_free (entry->name); - g_free (entry->description); - g_free (entry->enumeration_id); - - nautilus_gconf_value_free (entry->cached_value); - - g_free (entry); -} - -/** - * preferences_entry_free_func - * - * A function that frees a pref hash node. It is meant to be fed to - * g_hash_table_foreach () - * @key: The hash key privately maintained by the GHashTable. - * @value: The hash value privately maintained by the GHashTable. - * @callback_data: The callback_data privately maintained by the GHashTable. - **/ -static void -preferences_entry_free_func (gpointer key, - gpointer value, - gpointer callback_data) -{ - g_assert (value != NULL); - - preferences_entry_free (value); -} - -static void -preferences_global_table_free (void) -{ - if (global_table == NULL) { - return; - } - - g_hash_table_foreach (global_table, preferences_entry_free_func, NULL); - g_hash_table_destroy (global_table); - global_table = NULL; - - g_free (storage_path); - storage_path = NULL; - g_free (defaults_path); - defaults_path = NULL; - g_free (visiblity_path); - visiblity_path = NULL; -} - -static GHashTable * -preferences_global_table_get_global (void) -{ - static gboolean at_exit_handler_added = FALSE; - - if (global_table == NULL) { - global_table = g_hash_table_new (g_str_hash, g_str_equal); - - if (!at_exit_handler_added) { - at_exit_handler_added = TRUE; - g_atexit (preferences_global_table_free); - } - } - - return global_table; -} - -static PreferencesEntry * -preferences_global_table_lookup (const char *name) -{ - g_return_val_if_fail (name != NULL, NULL); - g_return_val_if_fail (preferences_global_table_get_global () != NULL, NULL); - - return g_hash_table_lookup (preferences_global_table_get_global (), name); -} - -static PreferencesEntry * -preferences_global_table_insert (const char *name) -{ - PreferencesEntry *entry; - - g_return_val_if_fail (name != NULL, NULL); - g_return_val_if_fail (preferences_global_table_get_global () != NULL, NULL); - g_return_val_if_fail (preferences_global_table_lookup (name) == NULL, NULL); - - entry = g_new0 (PreferencesEntry, 1); - entry->name = g_strdup (name); - - g_hash_table_insert (preferences_global_table_get_global (), entry->name, entry); - - g_return_val_if_fail (entry == preferences_global_table_lookup (name), NULL); - - /* Update the cached value for the first time. - * - * We need to do this because checks for value changes - * happen not only as a result of callbacks triggering, but - * also as a result of user_level changes. When a user level - * changes, all the preferences entries are iterated to invoke - * callbacks for those that changed as a result. - * - * See preferences_global_table_check_changes_function(). - */ - preferences_entry_update_cached_value (entry); - - return entry; -} - -static PreferencesEntry * -preferences_global_table_lookup_or_insert (const char *name) -{ - PreferencesEntry *entry; - - g_return_val_if_fail (name != NULL, NULL); - - entry = preferences_global_table_lookup (name); - - if (entry != NULL) { - return entry; - } - - entry = preferences_global_table_insert (name); - g_assert (entry != NULL); - - return entry; -} - -void -nautilus_preferences_add_callback (const char *name, - NautilusPreferencesCallback callback, - gpointer callback_data) -{ - PreferencesEntry *entry; - - g_return_if_fail (name != NULL); - g_return_if_fail (callback != NULL); - g_return_if_fail (preferences_is_initialized ()); - - entry = preferences_global_table_lookup_or_insert (name); - g_assert (entry != NULL); - - preferences_entry_add_callback (entry, callback, callback_data); -} - -void -nautilus_preferences_add_auto_string (const char *name, - const char **storage) -{ - PreferencesEntry *entry; - char *value; - - g_return_if_fail (name != NULL); - g_return_if_fail (storage != NULL); - g_return_if_fail (preferences_is_initialized ()); - - entry = preferences_global_table_lookup_or_insert (name); - g_assert (entry != NULL); - - preferences_entry_add_auto_storage (entry, storage, PREFERENCE_STRING); - - value = nautilus_preferences_get (entry->name); - update_auto_string (storage, value); - g_free (value); -} - -void -nautilus_preferences_add_auto_string_list (const char *name, - const EelStringList **storage) -{ - PreferencesEntry *entry; - EelStringList *value; - - g_return_if_fail (name != NULL); - g_return_if_fail (storage != NULL); - g_return_if_fail (preferences_is_initialized ()); - - entry = preferences_global_table_lookup_or_insert (name); - g_assert (entry != NULL); - - preferences_entry_add_auto_storage (entry, storage, PREFERENCE_STRING_LIST); - - value = nautilus_preferences_get_string_list (entry->name); - update_auto_string_list (storage, value); - eel_string_list_free (value); -} - -void -nautilus_preferences_add_auto_integer (const char *name, - int *storage) -{ - PreferencesEntry *entry; - int value; - - g_return_if_fail (name != NULL); - g_return_if_fail (storage != NULL); - g_return_if_fail (preferences_is_initialized ()); - - entry = preferences_global_table_lookup_or_insert (name); - g_assert (entry != NULL); - - preferences_entry_add_auto_storage (entry, storage, PREFERENCE_INTEGER); - - value = nautilus_preferences_get_integer (entry->name); - update_auto_integer_or_boolean (storage, GINT_TO_POINTER (value)); -} - -void -nautilus_preferences_add_auto_boolean (const char *name, - gboolean *storage) -{ - PreferencesEntry *entry; - gboolean value; - - g_return_if_fail (name != NULL); - g_return_if_fail (storage != NULL); - g_return_if_fail (preferences_is_initialized ()); - - entry = preferences_global_table_lookup_or_insert (name); - g_assert (entry != NULL); - - preferences_entry_add_auto_storage (entry, storage, PREFERENCE_BOOLEAN); - - value = nautilus_preferences_get_boolean (entry->name); - update_auto_integer_or_boolean (storage, GINT_TO_POINTER (value)); -} - -void -nautilus_preferences_remove_auto_string (const char *name, - const char **storage) -{ - PreferencesEntry *entry; - - g_return_if_fail (name != NULL); - g_return_if_fail (storage != NULL); - g_return_if_fail (preferences_is_initialized ()); - - entry = preferences_global_table_lookup (name); - if (entry == NULL) { - g_warning ("Trying to remove auto-string for %s without adding it first.", name); - return; - } - - preferences_entry_remove_auto_storage (entry, storage); -} - -void -nautilus_preferences_remove_auto_string_list (const char *name, - const EelStringList **storage) -{ - PreferencesEntry *entry; - - g_return_if_fail (name != NULL); - g_return_if_fail (storage != NULL); - g_return_if_fail (preferences_is_initialized ()); - - entry = preferences_global_table_lookup (name); - if (entry == NULL) { - g_warning ("Trying to remove auto-string for %s without adding it first.", name); - return; - } - - preferences_entry_remove_auto_storage (entry, storage); -} - -void -nautilus_preferences_remove_auto_integer (const char *name, - int *storage) -{ - PreferencesEntry *entry; - - g_return_if_fail (name != NULL); - g_return_if_fail (storage != NULL); - g_return_if_fail (preferences_is_initialized ()); - - entry = preferences_global_table_lookup (name); - if (entry == NULL) { - g_warning ("Trying to remove auto-integer for %s without adding it first.", name); - return; - } - - preferences_entry_remove_auto_storage (entry, storage); -} - -void -nautilus_preferences_remove_auto_boolean (const char *name, - gboolean *storage) -{ - PreferencesEntry *entry; - - g_return_if_fail (name != NULL); - g_return_if_fail (storage != NULL); - g_return_if_fail (preferences_is_initialized ()); - - entry = preferences_global_table_lookup (name); - if (entry == NULL) { - g_warning ("Trying to remove auto-boolean for %s without adding it first.", name); - return; - } - - preferences_entry_remove_auto_storage (entry, storage); -} - -typedef struct -{ - char *name; - NautilusPreferencesCallback callback; - gpointer callback_data; -} WhileAliveData; - -static void -preferences_while_alive_disconnector (GtkObject *object, gpointer callback_data) -{ - WhileAliveData *data; - - g_return_if_fail (GTK_IS_OBJECT (object)); - g_return_if_fail (callback_data != NULL); - - data = callback_data; - - nautilus_preferences_remove_callback (data->name, - data->callback, - data->callback_data); - - g_free (data->name); - g_free (data); -} - -void -nautilus_preferences_add_callback_while_alive (const char *name, - NautilusPreferencesCallback callback, - gpointer callback_data, - GtkObject *alive_object) -{ - WhileAliveData *data; - - g_return_if_fail (name != NULL); - g_return_if_fail (callback != NULL); - g_return_if_fail (GTK_IS_OBJECT (alive_object)); - g_return_if_fail (preferences_is_initialized ()); - - data = g_new (WhileAliveData, 1); - data->name = g_strdup (name); - data->callback = callback; - data->callback_data = callback_data; - - nautilus_preferences_add_callback (name, callback, callback_data); - - gtk_signal_connect (alive_object, - "destroy", - GTK_SIGNAL_FUNC (preferences_while_alive_disconnector), - data); -} - -void -nautilus_preferences_remove_callback (const char *name, - NautilusPreferencesCallback callback, - gpointer callback_data) -{ - PreferencesEntry *entry; - - g_return_if_fail (name != NULL); - g_return_if_fail (callback != NULL); - g_return_if_fail (preferences_is_initialized ()); - - entry = preferences_global_table_lookup (name); - - if (entry == NULL) { - g_warning ("Trying to remove a callback for %s without adding it first.", name); - return; - } - - preferences_entry_remove_callback (entry, callback, callback_data); -} - -void -nautilus_preferences_set_description (const char *name, - const char *description) -{ - PreferencesEntry *entry; - - g_return_if_fail (name != NULL); - g_return_if_fail (description != NULL); - g_return_if_fail (preferences_is_initialized ()); - - entry = preferences_global_table_lookup_or_insert (name); - g_assert (entry != NULL); - - g_free (entry->description); - entry->description = g_strdup (description); -} - -char * -nautilus_preferences_get_description (const char *name) -{ - PreferencesEntry *entry; - - g_return_val_if_fail (name != NULL, NULL); - g_return_val_if_fail (preferences_is_initialized (), NULL); - - entry = preferences_global_table_lookup_or_insert (name); - - return g_strdup (entry->description ? entry->description : ""); -} - -void -nautilus_preferences_set_enumeration_id (const char *name, - const char *enumeration_id) -{ - PreferencesEntry *entry; - - g_return_if_fail (name != NULL); - g_return_if_fail (enumeration_id != NULL); - g_return_if_fail (preferences_is_initialized ()); - - entry = preferences_global_table_lookup_or_insert (name); - g_assert (entry != NULL); - - g_free (entry->enumeration_id); - entry->enumeration_id = g_strdup (enumeration_id); -} - -char * -nautilus_preferences_get_enumeration_id (const char *name) -{ - PreferencesEntry *entry; - - g_return_val_if_fail (name != NULL, NULL); - g_return_val_if_fail (preferences_is_initialized (), NULL); - - entry = preferences_global_table_lookup_or_insert (name); - - return entry->enumeration_id ? g_strdup (entry->enumeration_id) : NULL; -} - -char * -nautilus_preferences_get_user_level_name_for_display (int user_level) -{ - g_return_val_if_fail (preferences_is_initialized (), NULL); - - user_level = nautilus_preferences_user_level_clamp (user_level); - - return g_strdup (gettext (user_level_names_for_display[user_level])); -} - -char * -nautilus_preferences_get_user_level_name_for_storage (int user_level) -{ - g_return_val_if_fail (preferences_is_initialized (), NULL); - - return g_strdup (preferences_peek_user_level_name_for_storage (user_level)); -} - -int -nautilus_preferences_user_level_clamp (int user_level) -{ - g_return_val_if_fail (preferences_is_initialized (), 0); - - return CLAMP (user_level, NAUTILUS_USER_LEVEL_NOVICE, NAUTILUS_USER_LEVEL_ADVANCED); -} - -gboolean -nautilus_preferences_user_level_is_valid (int user_level) -{ - g_return_val_if_fail (preferences_is_initialized (), FALSE); - - return user_level == nautilus_preferences_user_level_clamp (user_level); -} - -gboolean -nautilus_preferences_monitor_directory (const char *directory) -{ - g_return_val_if_fail (preferences_is_initialized (), FALSE); - - return nautilus_gconf_monitor_add (directory); -} - -gboolean -nautilus_preferences_visible_in_current_user_level (const char *name) -{ - int user_level; - int visible_user_level; - - g_return_val_if_fail (name != NULL, FALSE); - g_return_val_if_fail (preferences_is_initialized (), FALSE); - - user_level = nautilus_preferences_get_user_level (); - visible_user_level = nautilus_preferences_get_visible_user_level (name); - - return visible_user_level <= user_level; -} - -gboolean -nautilus_preferences_is_visible (const char *name) -{ - g_return_val_if_fail (name != NULL, FALSE); - g_return_val_if_fail (preferences_is_initialized (), FALSE); - - if (!nautilus_preferences_visible_in_current_user_level (name)) { - return FALSE; - } - - return !preferences_global_table_lookup_or_insert (name)->invisible; -} - -static void -preferences_remove_user_level_notice (void) -{ - nautilus_gconf_notification_remove (user_level_changed_connection_id); - user_level_changed_connection_id = NAUTILUS_GCONF_UNDEFINED_CONNECTION; -} - -void -nautilus_preferences_initialize (const char *path) -{ - g_return_if_fail (eel_strlen (path) > 0); - - if (initialized) { - return; - } - - initialized = TRUE; - - user_level_changed_connection_id = nautilus_gconf_notification_add (USER_LEVEL_KEY, - preferences_user_level_changed_notice, - NULL); - - g_atexit (preferences_remove_user_level_notice); - - preferences_set_storage_path (path); -} - -#if !defined (NAUTILUS_OMIT_SELF_CHECK) - -#define CHECK_BOOLEAN(name__, value__) \ -G_STMT_START { \ - nautilus_preferences_set_boolean ((name__), (value__)); \ - EEL_CHECK_BOOLEAN_RESULT (nautilus_preferences_get_boolean (name__), (value__)); \ -} G_STMT_END - -#define CHECK_INTEGER(name__, value__) \ -G_STMT_START { \ - nautilus_preferences_set_integer ((name__), (value__)); \ - EEL_CHECK_INTEGER_RESULT (nautilus_preferences_get_integer (name__), (value__)); \ -} G_STMT_END - -#define CHECK_STRING(name__, value__) \ -G_STMT_START { \ - nautilus_preferences_set ((name__), (value__)); \ - EEL_CHECK_STRING_RESULT (nautilus_preferences_get (name__), (value__)); \ -} G_STMT_END - -void -nautilus_self_check_preferences (void) -{ - /* Disabled until I can debug why these seemingly harmless tests - * dont work. -re - */ -#if 0 - int original_user_level; - - original_user_level = nautilus_preferences_get_user_level (); - - EEL_CHECK_INTEGER_RESULT (nautilus_preferences_get_integer ("self-check/neverset/i"), 0); - EEL_CHECK_STRING_RESULT (nautilus_preferences_get ("self-check/neverset/s"), ""); - EEL_CHECK_BOOLEAN_RESULT (nautilus_preferences_get_boolean ("self-check/neverset/b"), FALSE); - - nautilus_preferences_set_user_level (0); - - /* FIXME: Fails if you add the commented-out lines. */ - /* CHECK_INTEGER ("self-check/i", 0); */ - CHECK_INTEGER ("self-check/i", 666); - /* CHECK_BOOLEAN ("self-check/b", FALSE); */ - CHECK_BOOLEAN ("self-check/b", TRUE); - /* CHECK_STRING ("self-check/s", ""); */ - CHECK_STRING ("self-check/s", "foo"); - - /* Restore the original user level */ - nautilus_preferences_set_user_level (original_user_level); -#endif -} - -#endif /* !NAUTILUS_OMIT_SELF_CHECK */ diff --git a/libnautilus-extensions/nautilus-preferences.h b/libnautilus-extensions/nautilus-preferences.h deleted file mode 100644 index 2c4de5c7a..000000000 --- a/libnautilus-extensions/nautilus-preferences.h +++ /dev/null @@ -1,142 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ - -/* nautilus-preferences.c - Preference peek/poke/notify interface. - - Copyright (C) 1999, 2000, 2001 Eazel, Inc. - - The Gnome 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 Gnome 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 the Gnome 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. - - Authors: Ramiro Estrugo <ramiro@eazel.com> -*/ - -#ifndef NAUTILUS_PREFERENCES_H -#define NAUTILUS_PREFERENCES_H - -#include <gtk/gtkobject.h> -#include <libgnome/gnome-defs.h> -#include <eel/eel-string-list.h> - -BEGIN_GNOME_DECLS - -/* - * A callback which you can register to to be notified when a particular - * preference changes. - */ -typedef void (*NautilusPreferencesCallback) (gpointer callback_data); - -/* User level */ - -/* Note that there's a function to get the number of user levels, but there's - * a lot of code elsewhere that assumes three levels. Publicizing the numbers - * of these levels lets that other code be coherent and less error-prone. - */ -#define NAUTILUS_USER_LEVEL_NOVICE 0 -#define NAUTILUS_USER_LEVEL_INTERMEDIATE 1 -#define NAUTILUS_USER_LEVEL_ADVANCED 2 - -char * nautilus_preferences_get_user_level_name_for_display (int user_level); -char * nautilus_preferences_get_user_level_name_for_storage (int user_level); -int nautilus_preferences_get_user_level (void); -void nautilus_preferences_set_user_level (int user_level); -int nautilus_preferences_user_level_clamp (int user_level); -gboolean nautilus_preferences_user_level_is_valid (int user_level); - -/* Preferences getters and setters */ -gboolean nautilus_preferences_get_boolean (const char *name); -void nautilus_preferences_set_boolean (const char *name, - gboolean boolean_value); -int nautilus_preferences_get_integer (const char *name); -void nautilus_preferences_set_integer (const char *name, - int int_value); -char * nautilus_preferences_get (const char *name); -void nautilus_preferences_set (const char *name, - const char *string_value); -EelStringList *nautilus_preferences_get_string_list (const char *name); -void nautilus_preferences_set_string_list (const char *name, - const EelStringList *string_list_value); - -/* Default values getters and setters */ -gboolean nautilus_preferences_default_get_boolean (const char *name, - int user_level); -void nautilus_preferences_default_set_boolean (const char *name, - int user_level, - gboolean boolean_value); -int nautilus_preferences_default_get_integer (const char *name, - int user_level); -void nautilus_preferences_default_set_integer (const char *name, - int user_level, - int int_value); -char * nautilus_preferences_default_get_string (const char *name, - int user_level); -void nautilus_preferences_default_set_string (const char *name, - int user_level, - const char *string_value); -EelStringList *nautilus_preferences_default_get_string_list (const char *name, - int user_level); -void nautilus_preferences_default_set_string_list (const char *name, - int user_level, - const EelStringList *string_list_value); -/* Callbacks */ -void nautilus_preferences_add_callback (const char *name, - NautilusPreferencesCallback callback, - gpointer callback_data); -void nautilus_preferences_add_callback_while_alive (const char *name, - NautilusPreferencesCallback callback, - gpointer callback_data, - GtkObject *alive_object); -void nautilus_preferences_remove_callback (const char *name, - NautilusPreferencesCallback callback, - gpointer callback_data); - -/* Variables that are automatically updated (lightweight "callbacks") */ -void nautilus_preferences_add_auto_string (const char *name, - const char **storage); -void nautilus_preferences_add_auto_string_list (const char *name, - const EelStringList **storage); -void nautilus_preferences_add_auto_integer (const char *name, - int *storage); -void nautilus_preferences_add_auto_boolean (const char *name, - gboolean *storage); -void nautilus_preferences_remove_auto_string (const char *name, - const char **storage); -void nautilus_preferences_remove_auto_string_list (const char *name, - const EelStringList **storage); -void nautilus_preferences_remove_auto_integer (const char *name, - int *storage); -void nautilus_preferences_remove_auto_boolean (const char *name, - int *storage); - -/* Preferences attributes */ -int nautilus_preferences_get_visible_user_level (const char *name); -void nautilus_preferences_set_visible_user_level (const char *name, - int visible_user_level); -gboolean nautilus_preferences_get_is_invisible (const char *name); -void nautilus_preferences_set_is_invisible (const char *name, - gboolean invisible); -char * nautilus_preferences_get_description (const char *name); -void nautilus_preferences_set_description (const char *name, - const char *description); -char * nautilus_preferences_get_enumeration_id (const char *name); -void nautilus_preferences_set_enumeration_id (const char *name, - const char *enumeration_id); -gboolean nautilus_preferences_monitor_directory (const char *directory); -gboolean nautilus_preferences_visible_in_current_user_level (const char *name); -gboolean nautilus_preferences_is_visible (const char *name); -void nautilus_preferences_initialize (const char *storage_path); - -END_GNOME_DECLS - -#endif /* NAUTILUS_PREFERENCES_H */ diff --git a/libnautilus-extensions/nautilus-program-chooser.c b/libnautilus-extensions/nautilus-program-chooser.c deleted file mode 100644 index 71895d14c..000000000 --- a/libnautilus-extensions/nautilus-program-chooser.c +++ /dev/null @@ -1,1517 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ - -/* nautilus-program-chooser.c - implementation for window that lets user choose - a program from a list - - Copyright (C) 2000, 2001 Eazel, Inc. - - The Gnome 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 Gnome 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 the Gnome 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. - - Author: John Sullivan <sullivan@eazel.com> -*/ - -#include <config.h> -#include "nautilus-program-chooser.h" - -#include <eel/eel-gnome-extensions.h> -#include <eel/eel-gtk-extensions.h> -#include "nautilus-global-preferences.h" -#include "nautilus-mime-actions.h" -#include "nautilus-program-choosing.h" -#include <eel/eel-stock-dialogs.h> -#include <eel/eel-string.h> -#include "nautilus-view-identifier.h" -#include <gtk/gtkclist.h> -#include <gtk/gtkframe.h> -#include <gtk/gtkhbox.h> -#include <gtk/gtklabel.h> -#include <gtk/gtkmain.h> -#include <gtk/gtkradiobutton.h> -#include <gtk/gtkscrolledwindow.h> -#include <gtk/gtkvbox.h> -#include <libgnome/gnome-defs.h> -#include <libgnome/gnome-i18n.h> -#include <libgnomeui/gnome-stock.h> -#include <libgnomeui/gnome-uidefs.h> - -enum { - PROGRAM_LIST_NAME_COLUMN, - PROGRAM_LIST_STATUS_COLUMN, - PROGRAM_LIST_COLUMN_COUNT -}; - -typedef enum { - PROGRAM_STATUS_UNKNOWN, - PROGRAM_NOT_IN_PREFERRED_LIST, - PROGRAM_IN_PREFERRED_LIST_FOR_SUPERTYPE, - PROGRAM_IN_PREFERRED_LIST_FOR_TYPE, - PROGRAM_IN_PREFERRED_LIST_FOR_FILE, - PROGRAM_DEFAULT_FOR_SUPERTYPE, - PROGRAM_DEFAULT_FOR_TYPE, - PROGRAM_DEFAULT_FOR_FILE, -} ProgramFileStatus; - -typedef struct { - NautilusViewIdentifier *view_identifier; - GnomeVFSMimeApplication *application; - GnomeVFSMimeActionType action_type; - NautilusFile *file; - ProgramFileStatus status; -} ProgramFilePair; - -/* gtk_window_set_default_width (and some other functions) use a - * magic undocumented number of -2 to mean "ignore this parameter". - */ -#define NO_DEFAULT_MAGIC_NUMBER -2 - -/* Scrolling list has no idea how tall to make itself. Its - * "natural height" is just enough to draw the scroll bar controls. - * Hardwire an initial window size here, but let user resize - * bigger or smaller. - */ -#define PROGRAM_CHOOSER_DEFAULT_HEIGHT 374 - -/* If we let the automatic column sizing code run, it - * makes the Status column much wider than the Name column, - * which looks bad. Since there's no way to say "give each - * column the same amount of space", we'll hardwire a width. - */ -#define NAME_COLUMN_INITIAL_WIDTH 200 - -/* Program name of the mime type capplet */ -#define FILE_TYPES_CAPPLET_NAME "file-types-capplet" - -/* This number controls a maximum character count for a file name that is - * displayed as part of a dialog (beyond this it will be truncated). - * It's fairly arbitrary -- big enough to allow most "normal" names to display - * in full, but small enough to prevent the dialog from getting insanely wide. - */ -#define MAX_DISPLAYED_FILE_NAME_LENGTH 40 - -/* Forward declarations as needed */ -static gboolean program_file_pair_is_default_for_file_type (ProgramFilePair *pair); -static gboolean program_file_pair_is_default_for_file (ProgramFilePair *pair); -static gboolean program_file_pair_is_in_short_list_for_file_type (ProgramFilePair *pair); -static gboolean program_file_pair_is_in_short_list_for_file (ProgramFilePair *pair); - -static gboolean -program_file_pair_compute_status (ProgramFilePair *pair) -{ - ProgramFileStatus new_status; - - /* FIXME bugzilla.eazel.com 1459: Need to check whether it's the default or in short list for the supertype */ - if (program_file_pair_is_default_for_file_type (pair)) { - new_status = PROGRAM_DEFAULT_FOR_TYPE; - } else if (program_file_pair_is_default_for_file (pair)) { - new_status = PROGRAM_DEFAULT_FOR_FILE; - } else if (program_file_pair_is_in_short_list_for_file_type (pair)) { - new_status = PROGRAM_IN_PREFERRED_LIST_FOR_TYPE; - } else if (program_file_pair_is_in_short_list_for_file (pair)) { - new_status = PROGRAM_IN_PREFERRED_LIST_FOR_FILE; - } else { - new_status = PROGRAM_NOT_IN_PREFERRED_LIST; - } - - if (new_status == pair->status) { - return FALSE; - } - - pair->status = new_status; - return TRUE; -} - -static void -program_file_pair_set_file (ProgramFilePair *pair, NautilusFile *file) -{ - if (pair->file == file) { - return; - } - nautilus_file_unref (pair->file); - nautilus_file_ref (file); - pair->file = file; - program_file_pair_compute_status (pair); -} - -static ProgramFilePair * -program_file_pair_new_from_content_view (OAF_ServerInfo *content_view, NautilusFile *file) -{ - ProgramFilePair *new_pair; - - new_pair = g_new0 (ProgramFilePair, 1); - new_pair->view_identifier = nautilus_view_identifier_new_from_content_view (content_view); - new_pair->action_type = GNOME_VFS_MIME_ACTION_TYPE_COMPONENT; - - program_file_pair_set_file (new_pair, file); - - return new_pair; -} - -static ProgramFilePair * -program_file_pair_new_from_application (GnomeVFSMimeApplication *application, NautilusFile *file) -{ - ProgramFilePair *new_pair; - - new_pair = g_new0 (ProgramFilePair, 1); - new_pair->application = gnome_vfs_mime_application_copy (application); - new_pair->action_type = GNOME_VFS_MIME_ACTION_TYPE_APPLICATION; - - program_file_pair_set_file (new_pair, file); - - return new_pair; -} - -static void -program_file_pair_free (ProgramFilePair *pair) -{ - nautilus_view_identifier_free (pair->view_identifier); - gnome_vfs_mime_application_free (pair->application); - nautilus_file_unref (pair->file); - - g_free (pair); -} - -static char * -program_file_pair_get_program_name_for_display (ProgramFilePair *pair) -{ - g_assert (pair->action_type == GNOME_VFS_MIME_ACTION_TYPE_APPLICATION - || pair->action_type == GNOME_VFS_MIME_ACTION_TYPE_COMPONENT); - g_assert (pair->action_type != GNOME_VFS_MIME_ACTION_TYPE_APPLICATION - || pair->application != NULL); - g_assert (pair->action_type != GNOME_VFS_MIME_ACTION_TYPE_COMPONENT - || pair->view_identifier != NULL); - - if (pair->action_type == GNOME_VFS_MIME_ACTION_TYPE_COMPONENT) { - return g_strdup (_(pair->view_identifier->view_as_label)); - } - - return g_strdup (_(pair->application->name)); -} - -static char * -get_supertype_from_file (NautilusFile *file) -{ - /* FIXME bugzilla.eazel.com 1459: Needs implementation */ - return nautilus_file_get_string_attribute (file, "type"); -} - -static char * -program_file_pair_get_short_status_text (ProgramFilePair *pair) -{ - char *file_type; - char *supertype; - char *result; - - file_type = nautilus_file_get_string_attribute_with_default (pair->file, "type"); - supertype = get_supertype_from_file (pair->file); - - switch (pair->status) { - default: - case PROGRAM_STATUS_UNKNOWN: - g_assert_not_reached (); - result = "error"; - break; - case PROGRAM_NOT_IN_PREFERRED_LIST: - result = g_strdup (_("not in menu")); - break; - case PROGRAM_IN_PREFERRED_LIST_FOR_FILE: - result = g_strdup (_("in menu for this file")); - break; - case PROGRAM_IN_PREFERRED_LIST_FOR_TYPE: - result = g_strdup_printf (_("in menu for \"%s\""), file_type); - break; - case PROGRAM_IN_PREFERRED_LIST_FOR_SUPERTYPE: - result = g_strdup_printf (_("in menu for \"%s\""), supertype); - break; - case PROGRAM_DEFAULT_FOR_FILE: - result = g_strdup (_("default for this file")); - break; - case PROGRAM_DEFAULT_FOR_TYPE: - result = g_strdup_printf (_("default for \"%s\""), file_type); - break; - case PROGRAM_DEFAULT_FOR_SUPERTYPE: - result = g_strdup_printf (_("default for \"%s\""), supertype); - break; - } - - g_free (file_type); - g_free (supertype); - - return result; -} - -static char * -get_file_name_for_display (NautilusFile *file) -{ - char *full_name; - char *truncated_name; - - g_assert (NAUTILUS_IS_FILE (file)); - - full_name = nautilus_file_get_name (file); - truncated_name = eel_str_middle_truncate - (full_name, MAX_DISPLAYED_FILE_NAME_LENGTH); - g_free (full_name); - - return truncated_name; -} - -static char * -program_file_pair_get_long_status_text (ProgramFilePair *pair) -{ - char *file_type; - char *file_name; - char *supertype; - char *result; - - file_type = nautilus_file_get_string_attribute_with_default (pair->file, "type"); - supertype = get_supertype_from_file (pair->file); - file_name = get_file_name_for_display (pair->file); - - switch (pair->status) { - default: - case PROGRAM_STATUS_UNKNOWN: - g_assert_not_reached (); - result = "error"; - break; - case PROGRAM_NOT_IN_PREFERRED_LIST: - result = g_strdup_printf (_("Is not in the menu for \"%s\" items."), file_type); - break; - case PROGRAM_IN_PREFERRED_LIST_FOR_FILE: - result = g_strdup_printf (_("Is in the menu for \"%s\"."), file_name); - break; - case PROGRAM_IN_PREFERRED_LIST_FOR_TYPE: - result = g_strdup_printf (_("Is in the menu for \"%s\" items."), file_type); - break; - case PROGRAM_IN_PREFERRED_LIST_FOR_SUPERTYPE: - result = g_strdup_printf (_("Is in the menu for all \"%s\" items."), supertype); - break; - case PROGRAM_DEFAULT_FOR_FILE: - result = g_strdup_printf (_("Is the default for \"%s\"."), file_name); - break; - case PROGRAM_DEFAULT_FOR_TYPE: - result = g_strdup_printf (_("Is the default for \"%s\" items."), file_type); - break; - case PROGRAM_DEFAULT_FOR_SUPERTYPE: - result = g_strdup_printf (_("Is the default for all \"%s\" items."), supertype); - break; - } - - g_free (file_type); - g_free (file_name); - g_free (supertype); - - return result; -} - -static GnomeVFSMimeActionType -nautilus_program_chooser_get_type (GnomeDialog *program_chooser) -{ - GnomeVFSMimeActionType type; - - type = GPOINTER_TO_INT (gtk_object_get_data (GTK_OBJECT (program_chooser), "type")); - - g_assert (type == GNOME_VFS_MIME_ACTION_TYPE_COMPONENT || - type == GNOME_VFS_MIME_ACTION_TYPE_APPLICATION); - - return type; -} - -static void -repopulate_program_list (GnomeDialog *program_chooser, - NautilusFile *file, - GtkCList *clist) -{ - char **text; - GList *programs, *program; - ProgramFilePair *pair; - int new_row; - GnomeVFSMimeActionType type; - - type = nautilus_program_chooser_get_type (program_chooser); - - g_assert (type == GNOME_VFS_MIME_ACTION_TYPE_COMPONENT - || type == GNOME_VFS_MIME_ACTION_TYPE_APPLICATION); - - - programs = type == GNOME_VFS_MIME_ACTION_TYPE_COMPONENT - ? nautilus_mime_get_all_components_for_file (file) - : nautilus_mime_get_all_applications_for_file (file); - - gtk_clist_clear (clist); - - for (program = programs; program != NULL; program = program->next) { - /* One extra slot so it's NULL-terminated */ - text = g_new0 (char *, PROGRAM_LIST_COLUMN_COUNT+1); - - if (type == GNOME_VFS_MIME_ACTION_TYPE_COMPONENT) { - pair = program_file_pair_new_from_content_view - ((OAF_ServerInfo *)program->data, file); - } else { - pair = program_file_pair_new_from_application - ((GnomeVFSMimeApplication *)program->data, file); - } - - text[PROGRAM_LIST_NAME_COLUMN] = - program_file_pair_get_program_name_for_display (pair); - text[PROGRAM_LIST_STATUS_COLUMN] = - program_file_pair_get_short_status_text (pair); - - new_row = gtk_clist_append (clist, text); - - gtk_clist_set_row_data_full - (clist, new_row, pair, - (GtkDestroyNotify)program_file_pair_free); - - g_strfreev (text); - } - - if (type == GNOME_VFS_MIME_ACTION_TYPE_COMPONENT) { - gnome_vfs_mime_component_list_free (programs); - } else { - gnome_vfs_mime_application_list_free (programs); - } - - gtk_clist_sort (clist); - - /* Start with first item selected, rather than some arbitrary item */ - gtk_clist_select_row (clist, 0, 0); -} - -static NautilusFile * -nautilus_program_chooser_get_file (GnomeDialog *chooser) -{ - return NAUTILUS_FILE (gtk_object_get_data (GTK_OBJECT (chooser), "file")); -} - -static GtkCList * -nautilus_program_chooser_get_clist (GnomeDialog *chooser) -{ - return GTK_CLIST (gtk_object_get_data (GTK_OBJECT (chooser), "clist")); -} - -static GtkFrame * -nautilus_program_chooser_get_frame (GnomeDialog *chooser) -{ - return GTK_FRAME (gtk_object_get_data (GTK_OBJECT (chooser), "frame")); -} - -static GtkLabel * -nautilus_program_chooser_get_status_label (GnomeDialog *chooser) -{ - return GTK_LABEL (gtk_object_get_data (GTK_OBJECT (chooser), "status_label")); -} - -static void -nautilus_program_chooser_set_is_cancellable (GnomeDialog *chooser, gboolean cancellable) -{ - GtkButton *done_button, *cancel_button; - - cancel_button = eel_gnome_dialog_get_button_by_index - (chooser, GNOME_CANCEL); - done_button = eel_gnome_dialog_get_button_by_index - (chooser, GNOME_CANCEL+1); - - if (cancellable) { - gtk_widget_hide (GTK_WIDGET (done_button)); - gtk_widget_show (GTK_WIDGET (cancel_button)); - } else { - gtk_widget_hide (GTK_WIDGET (cancel_button)); - gtk_widget_show (GTK_WIDGET (done_button)); - } -} - -static void -nautilus_program_chooser_set_file (GnomeDialog *chooser, NautilusFile *file) -{ - nautilus_file_ref (file); - gtk_object_set_data_full (GTK_OBJECT (chooser), - "file", - file, - (GtkDestroyNotify)nautilus_file_unref); -} - -static void -nautilus_program_chooser_set_clist (GnomeDialog *chooser, GtkCList *clist) -{ - gtk_object_set_data (GTK_OBJECT (chooser), "clist", clist); -} - -static void -nautilus_program_chooser_set_frame (GnomeDialog *chooser, GtkFrame *frame) -{ - gtk_object_set_data (GTK_OBJECT (chooser), "frame", frame); -} - -static void -nautilus_program_chooser_set_status_label (GnomeDialog *chooser, GtkLabel *status_label) -{ - gtk_object_set_data (GTK_OBJECT (chooser), "status_label", status_label); -} - -static gint -compare_mime_applications (GnomeVFSMimeApplication *app_1, GnomeVFSMimeApplication *app_2) -{ - return strcmp (app_1->id, app_2->id); -} - -static gint -compare_component_with_view (OAF_ServerInfo *info, NautilusViewIdentifier *identifier) -{ - return strcmp (info->iid, identifier->iid); -} - -static gboolean -is_application_default_for_type (GnomeVFSMimeApplication *application, const char *mime_type) -{ - GnomeVFSMimeApplication *default_application; - gboolean result; - - g_assert (application != NULL); - - default_application = gnome_vfs_mime_get_default_application (mime_type); - result = (default_application != NULL && strcmp (default_application->id, application->id) == 0); - - gnome_vfs_mime_application_free (default_application); - - return result; -} - -static gboolean -is_component_default_for_type (NautilusViewIdentifier *identifier, const char *mime_type) -{ - OAF_ServerInfo *default_component; - gboolean result; - - g_assert (identifier != NULL); - - default_component = gnome_vfs_mime_get_default_component (mime_type); - result = (default_component != NULL && strcmp (default_component->iid, identifier->iid) == 0); - - CORBA_free (default_component); - - return result; -} - -static gboolean -is_application_default_for_file (GnomeVFSMimeApplication *application, - NautilusFile *file) -{ - GnomeVFSMimeApplication *default_application; - gboolean result; - - g_assert (application != NULL); - - default_application = nautilus_mime_get_default_application_for_file (file); - result = (default_application != NULL && strcmp (default_application->id, application->id) == 0); - - gnome_vfs_mime_application_free (default_application); - - return result; -} - -static gboolean -is_component_default_for_file (NautilusViewIdentifier *identifier, NautilusFile *file) -{ - OAF_ServerInfo *default_component; - gboolean result; - - g_assert (identifier != NULL); - - default_component = nautilus_mime_get_default_component_for_file (file); - result = (default_component != NULL && strcmp (default_component->iid, identifier->iid) == 0); - - CORBA_free (default_component); - - return result; -} - -static gboolean -is_component_in_short_list (NautilusViewIdentifier *identifier, const char *mime_type) -{ - GList *list; - gboolean result; - - list = gnome_vfs_mime_get_short_list_components (mime_type); - result = g_list_find_custom (list, - identifier, - (GCompareFunc)compare_component_with_view) - != NULL; - gnome_vfs_mime_component_list_free (list); - - return result; -} - -static gboolean -is_component_in_short_list_for_file (NautilusViewIdentifier *identifier, - NautilusFile *file) -{ - GList *list; - gboolean result; - - list = nautilus_mime_get_short_list_components_for_file (file); - result = g_list_find_custom (list, - identifier, - (GCompareFunc)compare_component_with_view) - != NULL; - gnome_vfs_mime_component_list_free (list); - - return result; -} - -static gboolean -is_application_in_short_list (GnomeVFSMimeApplication *application, const char *mime_type) -{ - GList *list; - gboolean result; - - list = gnome_vfs_mime_get_short_list_applications (mime_type); - result = g_list_find_custom (list, - application, - (GCompareFunc)compare_mime_applications) - != NULL; - gnome_vfs_mime_application_list_free (list); - - return result; -} - -static gboolean -is_application_in_short_list_for_file (GnomeVFSMimeApplication *application, NautilusFile *file) -{ - GList *list; - gboolean result; - - list = nautilus_mime_get_short_list_applications_for_file (file); - result = g_list_find_custom (list, - application, - (GCompareFunc)compare_mime_applications) - != NULL; - gnome_vfs_mime_application_list_free (list); - - return result; -} - -static gboolean -program_file_pair_is_default_for_file_type (ProgramFilePair *pair) -{ - char *mime_type; - gboolean result; - - g_assert (pair != NULL); - g_assert (NAUTILUS_IS_FILE (pair->file)); - - mime_type = nautilus_file_get_mime_type (pair->file); - - if (pair->action_type != gnome_vfs_mime_get_default_action_type (mime_type)) { - return FALSE; - } - - if (pair->action_type == GNOME_VFS_MIME_ACTION_TYPE_COMPONENT) { - result = is_component_default_for_type (pair->view_identifier, mime_type); - } else { - result = is_application_default_for_type (pair->application, mime_type); - } - - g_free (mime_type); - - return result; -} - -static gboolean -program_file_pair_is_default_for_file (ProgramFilePair *pair) -{ - gboolean result; - - g_assert (pair != NULL); - g_assert (NAUTILUS_IS_FILE (pair->file)); - - if (pair->action_type != nautilus_mime_get_default_action_type_for_file (pair->file)) { - return FALSE; - } - - if (pair->action_type == GNOME_VFS_MIME_ACTION_TYPE_COMPONENT) { - result = is_component_default_for_file (pair->view_identifier, pair->file); - } else { - result = is_application_default_for_file (pair->application, pair->file); - } - - return result; -} - -static gboolean -program_file_pair_is_in_short_list_for_file_type (ProgramFilePair *pair) -{ - char *mime_type; - gboolean result; - - g_assert (pair != NULL); - g_assert (NAUTILUS_IS_FILE (pair->file)); - - mime_type = nautilus_file_get_mime_type (pair->file); - - if (pair->action_type == GNOME_VFS_MIME_ACTION_TYPE_COMPONENT) { - result = is_component_in_short_list (pair->view_identifier, mime_type); - } else { - result = is_application_in_short_list (pair->application, mime_type); - } - - g_free (mime_type); - - return result; -} - -static gboolean -program_file_pair_is_in_short_list_for_file (ProgramFilePair *pair) -{ - gboolean result; - - g_assert (pair != NULL); - g_assert (NAUTILUS_IS_FILE (pair->file)); - - if (pair->action_type == GNOME_VFS_MIME_ACTION_TYPE_COMPONENT) { - result = is_component_in_short_list_for_file (pair->view_identifier, pair->file); - } else { - result = is_application_in_short_list_for_file (pair->application, pair->file); - } - - return result; -} - -static ProgramFilePair * -get_program_file_pair_from_row_data (GtkCList *clist, int row) -{ - g_assert (row < clist->rows); - return (ProgramFilePair *)gtk_clist_get_row_data (clist, row); -} - -static ProgramFilePair * -get_selected_program_file_pair (GnomeDialog *dialog) -{ - GtkCList *clist; - int selected_row; - - clist = nautilus_program_chooser_get_clist (dialog); - selected_row = eel_gtk_clist_get_first_selected_row (clist); - - if (selected_row < 0) { - return NULL; - } - - return get_program_file_pair_from_row_data (clist, selected_row); -} - -static void -update_selected_item_details (GnomeDialog *dialog) -{ - GtkFrame *frame; - GtkLabel *status_label; - char *frame_label_text, *status_label_text; - ProgramFilePair *pair; - - frame = nautilus_program_chooser_get_frame (dialog); - status_label = nautilus_program_chooser_get_status_label (dialog); - - pair = get_selected_program_file_pair (dialog); - - if (pair != NULL) { - frame_label_text = program_file_pair_get_program_name_for_display (pair); - status_label_text = program_file_pair_get_long_status_text (pair); - } else { - frame_label_text = NULL; - status_label_text = NULL; - } - - gtk_frame_set_label (frame, frame_label_text); - gtk_label_set_text (status_label, status_label_text); - - g_free (frame_label_text); - g_free (status_label_text); -} - -static void -update_all_status (GnomeDialog *dialog) -{ - GtkCList *clist; - ProgramFilePair *pair; - char *status_text; - int row; - gboolean anything_changed; - - clist = nautilus_program_chooser_get_clist (dialog); - anything_changed = FALSE; - for (row = 0; row < clist->rows; ++row) { - pair = get_program_file_pair_from_row_data (clist, row); - if (program_file_pair_compute_status (pair)) { - /* Status has changed, update text in list */ - anything_changed = TRUE; - status_text = program_file_pair_get_short_status_text (pair); - gtk_clist_set_text (clist, row, PROGRAM_LIST_STATUS_COLUMN, status_text); - g_free (status_text); - } - } - - if (anything_changed) { - gtk_clist_sort (clist); - } -} - -static void -program_list_selection_changed_callback (GtkCList *clist, - gint row, - gint column, - GdkEventButton *event, - gpointer user_data) -{ - g_assert (GTK_IS_CLIST (clist)); - g_assert (GNOME_IS_DIALOG (user_data)); - - update_selected_item_details (GNOME_DIALOG (user_data)); -} - -static GtkRadioButton * -pack_radio_button (GtkBox *box, const char *label_text, GtkRadioButton *group) -{ - GtkWidget *radio_button; - - radio_button = gtk_radio_button_new_with_label_from_widget (group, label_text); - gtk_widget_show (radio_button); - gtk_box_pack_start_defaults (box, radio_button); - - return GTK_RADIO_BUTTON (radio_button); -} - -static void -add_to_short_list_for_file (ProgramFilePair *pair) -{ - if (pair->action_type == GNOME_VFS_MIME_ACTION_TYPE_APPLICATION) { - nautilus_mime_add_application_to_short_list_for_file (pair->file, pair->application->id); - } else { - nautilus_mime_add_component_to_short_list_for_file (pair->file, pair->view_identifier->iid); - } -} - -static void -remove_from_short_list_for_file (ProgramFilePair *pair) -{ - if (pair->action_type == GNOME_VFS_MIME_ACTION_TYPE_APPLICATION) { - nautilus_mime_remove_application_from_short_list_for_file (pair->file, pair->application->id); - } else { - nautilus_mime_remove_component_from_short_list_for_file (pair->file, pair->view_identifier->iid); - } -} - -static void -add_to_short_list_for_type (ProgramFilePair *pair) -{ - char *mime_type; - - mime_type = nautilus_file_get_mime_type (pair->file); - - if (pair->action_type == GNOME_VFS_MIME_ACTION_TYPE_APPLICATION) { - gnome_vfs_mime_add_application_to_short_list (mime_type, pair->application->id); - } else { - gnome_vfs_mime_add_component_to_short_list (mime_type, pair->view_identifier->iid); - } - - g_free (mime_type); -} - -static void -remove_from_short_list_for_type (ProgramFilePair *pair) -{ - char *mime_type; - - mime_type = nautilus_file_get_mime_type (pair->file); - - if (pair->action_type == GNOME_VFS_MIME_ACTION_TYPE_APPLICATION) { - gnome_vfs_mime_remove_application_from_short_list (mime_type, pair->application->id); - } else { - gnome_vfs_mime_remove_component_from_short_list (mime_type, pair->view_identifier->iid); - } - - g_free (mime_type); -} - -static void -remove_default_for_type (ProgramFilePair *pair) -{ - char *mime_type; - - mime_type = nautilus_file_get_mime_type (pair->file); - - if (pair->action_type == GNOME_VFS_MIME_ACTION_TYPE_APPLICATION) { - if (is_application_default_for_type (pair->application, mime_type)) { - gnome_vfs_mime_set_default_application (mime_type, NULL); - } - } else { - if (is_component_default_for_type (pair->view_identifier, mime_type)) { - gnome_vfs_mime_set_default_component (mime_type, NULL); - } - } - - g_free (mime_type); -} - -static void -remove_default_for_item (ProgramFilePair *pair) -{ - if (pair->action_type == GNOME_VFS_MIME_ACTION_TYPE_APPLICATION) { - /* If the default is just falling through to the default for this type, - * don't do anything here. - */ - if (nautilus_mime_is_default_application_for_file_user_chosen (pair->file)) { - if (is_application_default_for_file (pair->application, pair->file)) { - nautilus_mime_set_default_application_for_file (pair->file, NULL); - } - } - } else { - /* If the default is just falling through to the default for this type, - * don't do anything here. - */ - if (nautilus_mime_is_default_component_for_file_user_chosen (pair->file)) { - if (is_component_default_for_file (pair->view_identifier, pair->file)) { - nautilus_mime_set_default_component_for_file (pair->file, NULL); - } - } - } -} - -static void -set_default_for_type (ProgramFilePair *pair) -{ - char *mime_type; - - mime_type = nautilus_file_get_mime_type (pair->file); - - if (pair->action_type == GNOME_VFS_MIME_ACTION_TYPE_APPLICATION) { - gnome_vfs_mime_set_default_application (mime_type, pair->application->id); - } else { - if (g_strcasecmp (mime_type, "x-directory/normal") == 0) { - nautilus_global_preferences_set_default_folder_viewer (pair->view_identifier->iid); - } else { - gnome_vfs_mime_set_default_component (mime_type, pair->view_identifier->iid); - } - } - - gnome_vfs_mime_set_default_action_type (mime_type, pair->action_type); - - g_free (mime_type); -} - -static void -set_default_for_item (ProgramFilePair *pair) -{ - if (pair->action_type == GNOME_VFS_MIME_ACTION_TYPE_APPLICATION) { - nautilus_mime_set_default_application_for_file (pair->file, pair->application->id); - } else { - nautilus_mime_set_default_component_for_file (pair->file, pair->view_identifier->iid); - } - - nautilus_mime_set_default_action_type_for_file (pair->file, pair->action_type); -} - -static void -launch_mime_capplet (GtkWidget *button, gpointer callback_data) -{ - char *command; - - g_assert (GTK_IS_WIDGET (button)); - - command = g_strdup_printf ("%s %s", FILE_TYPES_CAPPLET_NAME, (char *)callback_data); - - nautilus_launch_application_from_command (FILE_TYPES_CAPPLET_NAME, command, NULL, FALSE); - - g_free (command); -} - -static void -launch_mime_capplet_and_close_dialog (GtkWidget *button, gpointer callback_data) -{ - ProgramFilePair *file_pair; - char *mime_type; - - g_assert (GTK_IS_WIDGET (button)); - g_assert (GNOME_IS_DIALOG (callback_data)); - - file_pair = get_selected_program_file_pair (GNOME_DIALOG (callback_data)); - - mime_type = nautilus_file_get_mime_type (file_pair->file); - - launch_mime_capplet (button, mime_type); - - /* Don't leave a nested modal dialogs in the wake of switching - * user's attention to the capplet. - */ - gnome_dialog_close (GNOME_DIALOG (callback_data)); - - g_free (mime_type); -} - -static void -run_program_configurator_callback (GtkWidget *button, gpointer callback_data) -{ - GnomeDialog *program_chooser; - NautilusFile *file; - GtkCList *clist; - GtkWidget *dialog; - GtkWidget *radio_buttons_frame, *framed_vbox; - GtkRadioButton *type_radio_button, *type_default_radio_button, *item_radio_button, *item_default_radio_button, *none_radio_button; - GtkRadioButton *old_active_button; - char *radio_button_text; - char *file_type, *file_name; - char *program_display_name; - char *title; - ProgramFilePair *pair; - - g_assert (GNOME_IS_DIALOG (callback_data)); - - program_chooser = GNOME_DIALOG (callback_data); - - file = nautilus_program_chooser_get_file (program_chooser); - clist = nautilus_program_chooser_get_clist (program_chooser); - - file_type = nautilus_file_get_string_attribute_with_default (file, "type"); - file_name = get_file_name_for_display (file); - - pair = get_selected_program_file_pair (program_chooser); - if (pair == NULL) { - /* No valid selected item, don't do anything. The UI - * should prevent this. - */ - return; - } - - program_display_name = program_file_pair_get_program_name_for_display (pair); - - title = g_strdup_printf (_("Modify \"%s\""), program_display_name); - - dialog = gnome_dialog_new (title, - GNOME_STOCK_BUTTON_OK, - GNOME_STOCK_BUTTON_CANCEL, - NULL); - g_free (title); - gtk_window_set_wmclass (GTK_WINDOW (dialog), "program_chooser", "Nautilus"); - - /* Labeled frame to avoid repeating text in each radio button, - * and to look nice. - */ - radio_buttons_frame = gtk_frame_new (program_display_name); - gtk_widget_show (radio_buttons_frame); - gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (dialog)->vbox), radio_buttons_frame, FALSE, FALSE, 0); - - g_free (program_display_name); - - framed_vbox = gtk_vbox_new (FALSE, GNOME_PAD); - gtk_widget_show (framed_vbox); - gtk_container_add (GTK_CONTAINER (radio_buttons_frame), framed_vbox); - gtk_container_set_border_width (GTK_CONTAINER (framed_vbox), GNOME_PAD); - - - /* Radio button for adding to short list for file type. */ - radio_button_text = g_strdup_printf (_("Include in the menu for \"%s\" items"), - file_type); - type_radio_button = pack_radio_button (GTK_BOX (framed_vbox), radio_button_text, NULL); - g_free (radio_button_text); - - - /* Radio button for setting default for file type. */ - radio_button_text = g_strdup_printf (_("Use as default for \"%s\" items"), - file_type); - type_default_radio_button = pack_radio_button (GTK_BOX (framed_vbox), radio_button_text, type_radio_button); - g_free (radio_button_text); - - - /* Radio button for adding to short list for specific file. */ - radio_button_text = g_strdup_printf (_("Include in the menu just for \"%s\""), - file_name); - item_radio_button = pack_radio_button (GTK_BOX (framed_vbox), radio_button_text, type_radio_button); - g_free (radio_button_text); - - /* Radio button for setting default for specific file. */ - radio_button_text = g_strdup_printf (_("Use as default just for \"%s\""), - file_name); - item_default_radio_button = pack_radio_button (GTK_BOX (framed_vbox), radio_button_text, type_radio_button); - g_free (radio_button_text); - - - /* Radio button for not including program in short list for type or file. */ - radio_button_text = g_strdup_printf (_("Don't include in the menu for \"%s\" items"), - file_type); - none_radio_button = pack_radio_button (GTK_BOX (framed_vbox), radio_button_text, type_radio_button); - g_free (radio_button_text); - - g_free (file_type); - g_free (file_name); - - /* Activate the correct radio button. */ - switch (pair->status) { - case PROGRAM_DEFAULT_FOR_TYPE: - old_active_button = type_default_radio_button; - break; - case PROGRAM_DEFAULT_FOR_FILE: - old_active_button = item_default_radio_button; - break; - case PROGRAM_IN_PREFERRED_LIST_FOR_TYPE: - old_active_button = type_radio_button; - break; - case PROGRAM_IN_PREFERRED_LIST_FOR_FILE: - old_active_button = item_radio_button; - break; - default: - g_warning ("unhandled program status %d", pair->status); - case PROGRAM_NOT_IN_PREFERRED_LIST: - old_active_button = none_radio_button; - break; - } - - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (old_active_button), TRUE); - - /* Buttons close this dialog. */ - gnome_dialog_set_close (GNOME_DIALOG (dialog), TRUE); - - /* Make OK button the default. */ - gnome_dialog_set_default (GNOME_DIALOG (dialog), GNOME_OK); - - gnome_dialog_set_parent (GNOME_DIALOG (dialog), GTK_WINDOW (program_chooser)); - - /* Don't destroy on close because callers will need - * to extract some information from the dialog after - * it closes. - */ - gnome_dialog_close_hides (GNOME_DIALOG (dialog), TRUE); - - if (gnome_dialog_run (GNOME_DIALOG (dialog)) == GNOME_OK) { - if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (old_active_button))) { - /* Selected button has changed, update stuff as necessary. - * Rather than keep track of a whole bunch of transitions, we - * start by removing this program from everything and then - * add it back in as appropriate based on the new setting. - */ - if (old_active_button == item_radio_button) { - remove_from_short_list_for_type (pair); - remove_from_short_list_for_file (pair); - } else if (old_active_button == item_default_radio_button) { - remove_from_short_list_for_type (pair); - remove_from_short_list_for_file (pair); - remove_default_for_item (pair); - } else if (old_active_button == type_radio_button) { - remove_from_short_list_for_type (pair); - } else if (old_active_button == type_default_radio_button) { - remove_from_short_list_for_type (pair); - remove_default_for_type (pair); - } else { - g_assert (old_active_button == none_radio_button); - /* Nothing to remove anywhere for this case. */ - } - - if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (item_radio_button))) { - add_to_short_list_for_file (pair); - } else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (item_default_radio_button))) { - add_to_short_list_for_file (pair); - set_default_for_item (pair); - } else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (type_radio_button))) { - add_to_short_list_for_type (pair); - /* To remove it from the "removed" list if necessary. */ - add_to_short_list_for_file (pair); - } else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (type_default_radio_button))) { - add_to_short_list_for_type (pair); - /* To remove it from the "removed" list if necessary. */ - add_to_short_list_for_type (pair); - set_default_for_type (pair); - } else { - g_assert (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (none_radio_button))); - /* Nothing to add anywhere for this case. */ - } - - /* Change made in sub-dialog; now the main dialog can't be "cancel"ed, - * it can only be closed with no further changes. - */ - nautilus_program_chooser_set_is_cancellable (program_chooser, FALSE); - - /* Update displayed text about selected program. */ - update_selected_item_details (program_chooser); - - /* Update text in list too, since a changed item might change - * other items as side-effect (like changing the default). - */ - update_all_status (program_chooser); - } - } - - gtk_widget_destroy (dialog); -} - -static int -compare_program_file_pairs (GtkCList *clist, gconstpointer ptr1, gconstpointer ptr2) -{ - GtkCListRow *row1, *row2; - ProgramFilePair *pair1, *pair2; - char *name1, *name2; - gint result; - - g_assert (GTK_IS_CLIST (clist)); - - row1 = (GtkCListRow *) ptr1; - row2 = (GtkCListRow *) ptr2; - - pair1 = (ProgramFilePair *) row1->data; - pair2 = (ProgramFilePair *) row2->data; - - switch (clist->sort_column) { - case PROGRAM_LIST_STATUS_COLUMN: - if (pair1->status > pair2->status) { - result = -1; - } else if (pair1->status < pair2->status) { - result = +1; - } else { - result = 0; - } - break; - case PROGRAM_LIST_NAME_COLUMN: - name1 = program_file_pair_get_program_name_for_display (pair1); - name2 = program_file_pair_get_program_name_for_display (pair2); - result = strcmp (name1, name2); - g_free (name1); - g_free (name2); - break; - default: - g_warning ("unhandled sort column %d", clist->sort_column); - result = 0; - break; - } - - return result; -} - -static void -switch_sort_column (GtkCList *clist, gint column, gpointer user_data) -{ - g_assert (GTK_IS_CLIST (clist)); - - gtk_clist_set_sort_column (clist, column); - gtk_clist_sort (clist); -} - -static GtkWidget * -create_program_clist () -{ - GtkCList *clist; - - clist = GTK_CLIST (gtk_clist_new (PROGRAM_LIST_COLUMN_COUNT)); - - gtk_clist_set_column_title (clist, PROGRAM_LIST_NAME_COLUMN, _("Name")); - gtk_clist_set_column_width (clist, PROGRAM_LIST_NAME_COLUMN, NAME_COLUMN_INITIAL_WIDTH); - - gtk_clist_set_column_title (clist, PROGRAM_LIST_STATUS_COLUMN, _("Status")); - /* This column will get all the rest of the width */ - - gtk_clist_set_selection_mode (clist, GTK_SELECTION_BROWSE); - gtk_clist_column_titles_show (clist); - gtk_widget_show (GTK_WIDGET (clist)); - - gtk_clist_set_sort_column (clist, PROGRAM_LIST_NAME_COLUMN); - /* Do not use autosort. The list changes only at well-defined times - * that we control, and autosort has that nasty bug where you can't - * use row data in the compare function because the row is sorted - * on insert before the row data has been added. - */ - gtk_clist_set_compare_func (clist, compare_program_file_pairs); - - gtk_signal_connect (GTK_OBJECT (clist), - "click_column", - switch_sort_column, - NULL); - - - return GTK_WIDGET (clist); -} - -GnomeDialog * -nautilus_program_chooser_new (GnomeVFSMimeActionType action_type, - NautilusFile *file) -{ - GtkWidget *window; - GtkWidget *dialog_vbox; - GtkWidget *prompt_label; - GtkWidget *list_scroller, *clist; - GtkWidget *frame; - GtkWidget *framed_hbox; - GtkWidget *status_label; - GtkWidget *change_button_holder; - GtkWidget *change_button; - GtkWidget *capplet_button_frame, *capplet_hbox; - GtkWidget *capplet_button, *capption, *capplet_button_vbox; - char *file_name, *prompt; - const char *title; - - g_return_val_if_fail (NAUTILUS_IS_FILE (file), NULL); - - file_name = get_file_name_for_display (file); - - switch (action_type) { - case GNOME_VFS_MIME_ACTION_TYPE_APPLICATION: - title = _("Open with Other"); - prompt = g_strdup_printf (_("Choose an application with which to open \"%s\"."), file_name); - break; - case GNOME_VFS_MIME_ACTION_TYPE_COMPONENT: - default: - title = _("View as Other"); - prompt = g_strdup_printf (_("Choose a view for \"%s\"."), file_name); - break; - } - - g_free (file_name); - - window = gnome_dialog_new (title, - _("Choose"), - GNOME_STOCK_BUTTON_CANCEL, - _("Done"), - NULL); - - nautilus_program_chooser_set_is_cancellable (GNOME_DIALOG (window), TRUE); - - gtk_container_set_border_width (GTK_CONTAINER (window), GNOME_PAD); - gtk_window_set_policy (GTK_WINDOW (window), FALSE, TRUE, FALSE); - gtk_window_set_default_size (GTK_WINDOW (window), - NO_DEFAULT_MAGIC_NUMBER, - PROGRAM_CHOOSER_DEFAULT_HEIGHT); - gtk_window_set_wmclass (GTK_WINDOW (window), "program_chooser", "Nautilus"); - - gtk_object_set_data (GTK_OBJECT (window), "type", GINT_TO_POINTER (action_type)); - - dialog_vbox = GNOME_DIALOG (window)->vbox; - - /* Prompt at top of dialog. */ - prompt_label = gtk_label_new (prompt); - gtk_widget_show (prompt_label); - /* Move prompt to left edge */ - gtk_misc_set_alignment (GTK_MISC (prompt_label), 0, 0.5); - g_free (prompt); - - gtk_box_pack_start (GTK_BOX (dialog_vbox), prompt_label, FALSE, FALSE, 0); - - /* Scrolling list to hold choices. */ - list_scroller = gtk_scrolled_window_new (NULL, NULL); - gtk_widget_show (list_scroller); - gtk_box_pack_start_defaults (GTK_BOX (GNOME_DIALOG (window)->vbox), list_scroller); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (list_scroller), - GTK_POLICY_NEVER, - GTK_POLICY_AUTOMATIC); - - clist = create_program_clist (); - - gtk_container_add (GTK_CONTAINER (list_scroller), clist); - eel_gtk_clist_set_double_click_button - (GTK_CLIST (clist), - eel_gnome_dialog_get_button_by_index - (GNOME_DIALOG (window), GNOME_OK)); - gtk_object_set_data (GTK_OBJECT (window), "list", clist); - - repopulate_program_list (GNOME_DIALOG (window), file, GTK_CLIST (clist)); - - /* Framed area with selection-specific details */ - frame = gtk_frame_new (NULL); - gtk_widget_show (frame); - gtk_box_pack_start (GTK_BOX (dialog_vbox), frame, FALSE, FALSE, 0); - - framed_hbox = gtk_hbox_new (FALSE, GNOME_PAD); - gtk_widget_show (framed_hbox); - gtk_container_add (GTK_CONTAINER (frame), framed_hbox); - gtk_container_set_border_width (GTK_CONTAINER (framed_hbox), GNOME_PAD); - - status_label = gtk_label_new (NULL); - gtk_label_set_justify (GTK_LABEL (status_label), GTK_JUSTIFY_LEFT); - gtk_widget_show (status_label); - gtk_box_pack_start (GTK_BOX (framed_hbox), status_label, FALSE, FALSE, 0); - - change_button_holder = gtk_vbox_new (FALSE, 0); - gtk_widget_show (change_button_holder); - gtk_box_pack_end (GTK_BOX (framed_hbox), change_button_holder, FALSE, FALSE, 0); - - change_button = gtk_button_new_with_label(_("Modify...")); - eel_gtk_button_set_standard_padding (GTK_BUTTON (change_button)); - gtk_widget_show (change_button); - gtk_box_pack_end (GTK_BOX (change_button_holder), change_button, TRUE, FALSE, 0); - - gtk_signal_connect (GTK_OBJECT (change_button), - "clicked", - run_program_configurator_callback, - window); - - /* Framed area with button to launch mime type editing capplet. */ - capplet_button_frame = gtk_frame_new (_("File Types and Programs")); - gtk_widget_show (capplet_button_frame); - gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (window)->vbox), capplet_button_frame, FALSE, FALSE, 0); - - capplet_hbox = gtk_hbox_new (FALSE, GNOME_PAD_BIG); - gtk_widget_show (capplet_hbox); - gtk_container_add (GTK_CONTAINER (capplet_button_frame), capplet_hbox); - gtk_container_set_border_width (GTK_CONTAINER (capplet_hbox), GNOME_PAD); - - capplet_button_vbox = gtk_vbox_new (FALSE, 0); - gtk_widget_show (capplet_button_vbox); - gtk_box_pack_end (GTK_BOX (capplet_hbox), capplet_button_vbox, FALSE, FALSE, 0); - capplet_button = gtk_button_new_with_label (_("Go There")); - eel_gtk_button_set_standard_padding (GTK_BUTTON (capplet_button)); - gtk_signal_connect (GTK_OBJECT (capplet_button), - "clicked", - launch_mime_capplet_and_close_dialog, - window); - gtk_widget_show (capplet_button); - gtk_box_pack_start (GTK_BOX (capplet_button_vbox), capplet_button, TRUE, FALSE, 0); - - capption = gtk_label_new (_("You can configure which programs are offered " - "for which file types in the GNOME Control Center.")); - gtk_widget_show (capption); - gtk_label_set_line_wrap (GTK_LABEL (capption), TRUE); - gtk_box_pack_start (GTK_BOX (capplet_hbox), capption, FALSE, FALSE, 0); - - /* Buttons close this dialog. */ - gnome_dialog_set_close (GNOME_DIALOG (window), TRUE); - - /* Make confirmation button the default. */ - gnome_dialog_set_default (GNOME_DIALOG (window), GNOME_OK); - - - /* Load up the dialog object with info other functions will need. */ - nautilus_program_chooser_set_file (GNOME_DIALOG (window), file); - nautilus_program_chooser_set_clist (GNOME_DIALOG (window), GTK_CLIST (clist)); - nautilus_program_chooser_set_frame (GNOME_DIALOG (window), GTK_FRAME (frame)); - nautilus_program_chooser_set_status_label (GNOME_DIALOG (window), GTK_LABEL (status_label)); - - /* Fill in initial info about the selected item. */ - update_selected_item_details (GNOME_DIALOG (window)); - - /* Update selected item info whenever selection changes. */ - gtk_signal_connect (GTK_OBJECT (clist), - "select_row", - program_list_selection_changed_callback, - window); - - return GNOME_DIALOG (window); -} - -/** - * nautilus_program_chooser_get_application: - * - * Get the currently-chosen application in the program-choosing dialog. - * Usually used after the dialog has been closed (but not yet destroyed) - * to get the user's final choice. The returned value is the actual one - * stored in the dialog, and thus cannot be accessed after the dialog - * has been destroyed. - * - * @program_chooser: The result of calling nautilus_program_chooser_new - * with type GNOME_VFS_MIME_ACTION_TYPE_APPLICATION. - * - * Return value: a GnomeVFSMimeApplication specifying a component. The caller - * should make a copy if they want to use it after the dialog has been - * destroyed. - */ -GnomeVFSMimeApplication * -nautilus_program_chooser_get_application (GnomeDialog *program_chooser) -{ - ProgramFilePair *pair; - - g_return_val_if_fail (GNOME_IS_DIALOG (program_chooser), NULL); - - g_return_val_if_fail (nautilus_program_chooser_get_type (program_chooser) - == GNOME_VFS_MIME_ACTION_TYPE_APPLICATION, - NULL); - - pair = get_selected_program_file_pair (program_chooser); - if (pair == NULL) { - return NULL; - } - - return pair->application; -} - -/** - * nautilus_program_chooser_get_component: - * - * Get the currently-chosen component in the program-choosing dialog. - * Usually used after the dialog has been closed (but not yet destroyed) - * to get the user's final choice. The returned value is the actual one - * stored in the dialog, and thus cannot be accessed after the dialog - * has been destroyed. - * - * @program_chooser: The result of calling nautilus_program_chooser_new - * with type GNOME_VFS_MIME_ACTION_TYPE_COMPONENT. - * - * Return value: a NautilusViewIdentifier specifying a component. The caller - * should make a copy if they want to use it after the dialog has been - * destroyed. - */ -NautilusViewIdentifier * -nautilus_program_chooser_get_component (GnomeDialog *program_chooser) -{ - ProgramFilePair *pair; - - g_return_val_if_fail (GNOME_IS_DIALOG (program_chooser), NULL); - - g_return_val_if_fail (nautilus_program_chooser_get_type (program_chooser) - == GNOME_VFS_MIME_ACTION_TYPE_COMPONENT, - NULL); - - pair = get_selected_program_file_pair (program_chooser); - if (pair == NULL) { - return NULL; - } - - return pair->view_identifier; -} - -void -nautilus_program_chooser_show_no_choices_message (GnomeVFSMimeActionType action_type, - NautilusFile *file, - GtkWindow *parent_window) -{ - char *prompt; - char *unavailable_message; - char *file_name; - char *dialog_title; - GnomeDialog *dialog; - - file_name = get_file_name_for_display (file); - - if (action_type == GNOME_VFS_MIME_ACTION_TYPE_COMPONENT) { - unavailable_message = g_strdup_printf (_("No viewers are available for \"%s\"."), file_name); - dialog_title = g_strdup (_("No Viewers Available")); - } else { - g_assert (action_type == GNOME_VFS_MIME_ACTION_TYPE_APPLICATION); - unavailable_message = g_strdup_printf (_("No applications are available for \"%s\"."), file_name); - dialog_title = g_strdup (_("No Applications Available")); - } - - /* Note: This might be misleading in the components case, since the - * user can't add components to the complete list even from the capplet. - * (They can add applications though.) - */ - prompt = g_strdup_printf (_("%s\n\n" - "You can configure which programs are offered " - "for which file types with the \"File Types and " - "Programs\" part of the GNOME Control Center. Do " - "you want to go there now?"), - unavailable_message); - dialog = eel_show_yes_no_dialog - (prompt, dialog_title, GNOME_STOCK_BUTTON_OK, GNOME_STOCK_BUTTON_CANCEL, parent_window); - - gnome_dialog_button_connect (dialog, GNOME_OK, launch_mime_capplet, nautilus_file_get_mime_type (file)); - - g_free (unavailable_message); - g_free (file_name); - g_free (prompt); - g_free (dialog_title); -} diff --git a/libnautilus-extensions/nautilus-program-chooser.h b/libnautilus-extensions/nautilus-program-chooser.h deleted file mode 100644 index 3ca16ceb0..000000000 --- a/libnautilus-extensions/nautilus-program-chooser.h +++ /dev/null @@ -1,46 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ - -/* nautilus-program-chooser.h - interface for window that lets user choose - a program from a list - - Copyright (C) 2000 Eazel, Inc. - - The Gnome 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 Gnome 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 the Gnome 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. - - Author: John Sullivan <sullivan@eazel.com> -*/ - -#ifndef NAUTILUS_PROGRAM_CHOOSER_H -#define NAUTILUS_PROGRAM_CHOOSER_H - -#include <gtk/gtkwindow.h> -#include <libgnomeui/gnome-dialog.h> -#include <libgnomevfs/gnome-vfs-mime-handlers.h> - -#include "nautilus-file.h" -#include "nautilus-view-identifier.h" - -GnomeDialog *nautilus_program_chooser_new (GnomeVFSMimeActionType type, - NautilusFile *file); - -GnomeVFSMimeApplication *nautilus_program_chooser_get_application (GnomeDialog *program_chooser); -NautilusViewIdentifier *nautilus_program_chooser_get_component (GnomeDialog *program_chooser); - -void nautilus_program_chooser_show_no_choices_message (GnomeVFSMimeActionType action_type, - NautilusFile *file, - GtkWindow *parent_window); - -#endif /* NAUTILUS_PROGRAM_CHOOSER_H */ diff --git a/libnautilus-extensions/nautilus-program-choosing.c b/libnautilus-extensions/nautilus-program-choosing.c deleted file mode 100644 index c4c9e22b8..000000000 --- a/libnautilus-extensions/nautilus-program-choosing.c +++ /dev/null @@ -1,693 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ - -/* nautilus-program-choosing.c - functions for selecting and activating - programs for opening/viewing particular files. - - Copyright (C) 2000 Eazel, Inc. - - The Gnome 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 Gnome 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 the Gnome 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. - - Author: John Sullivan <sullivan@eazel.com> -*/ - -#include <config.h> -#include "nautilus-program-choosing.h" - -#include "nautilus-mime-actions.h" -#include "nautilus-program-chooser.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 <gtk/gtk.h> -#include <libgnome/gnome-config.h> -#include <libgnome/gnome-i18n.h> -#include <libgnome/gnome-util.h> -#include <libgnomeui/gnome-uidefs.h> -#include <libgnomevfs/gnome-vfs-mime-handlers.h> -#include <libgnomevfs/gnome-vfs-utils.h> -#include <stdlib.h> - -typedef struct { - NautilusFile *file; - GtkWindow *parent_window; - NautilusApplicationChoiceCallback callback; - gpointer callback_data; -} ChooseApplicationCallbackData; - -typedef struct { - NautilusFile *file; - GtkWindow *parent_window; - NautilusComponentChoiceCallback callback; - gpointer callback_data; -} ChooseComponentCallbackData; - -static GHashTable *choose_application_hash_table, *choose_component_hash_table; - -static guint -choose_application_hash (gconstpointer p) -{ - const ChooseApplicationCallbackData *data; - - data = p; - return GPOINTER_TO_UINT (data->file) - ^ GPOINTER_TO_UINT (data->callback) - ^ GPOINTER_TO_UINT (data->callback_data); -} - -static gboolean -choose_application_equal (gconstpointer a, - gconstpointer b) -{ - const ChooseApplicationCallbackData *data_a, *data_b; - - data_a = a; - data_b = a; - return data_a->file == data_b->file - && data_a->callback == data_b->callback - && data_a->callback_data == data_b->callback_data; -} - -static void -choose_application_destroy (ChooseApplicationCallbackData *choose_data) -{ - nautilus_file_unref (choose_data->file); - if (choose_data->parent_window != NULL) { - gtk_object_unref (GTK_OBJECT (choose_data->parent_window)); - } - g_free (choose_data); -} - -static guint -choose_component_hash (gconstpointer p) -{ - const ChooseApplicationCallbackData *data; - - data = p; - return GPOINTER_TO_UINT (data->file) - ^ GPOINTER_TO_UINT (data->callback) - ^ GPOINTER_TO_UINT (data->callback_data); -} - -static gboolean -choose_component_equal (gconstpointer a, - gconstpointer b) -{ - const ChooseApplicationCallbackData *data_a, *data_b; - - data_a = a; - data_b = a; - return data_a->file == data_b->file - && data_a->callback == data_b->callback - && data_a->callback_data == data_b->callback_data; -} - -static void -choose_component_destroy (ChooseComponentCallbackData *choose_data) -{ - nautilus_file_unref (choose_data->file); - if (choose_data->parent_window != NULL) { - gtk_object_unref (GTK_OBJECT (choose_data->parent_window)); - } - g_free (choose_data); -} - -/** - * set_up_program_chooser: - * - * Create but don't yet run a program-choosing dialog. - * The caller should run the dialog and destroy it. - * - * @file: Which NautilusFile programs are being chosen for. - * @type: Which type of program is being chosen. - * @parent: Optional window to parent the dialog on. - * - * Return value: The program-choosing dialog, ready to be run. - */ -static GnomeDialog * -set_up_program_chooser (NautilusFile *file, - GnomeVFSMimeActionType type, - GtkWindow *parent) -{ - GnomeDialog *dialog; - - g_assert (NAUTILUS_IS_FILE (file)); - - dialog = nautilus_program_chooser_new (type, file); - if (parent != NULL) { - gnome_dialog_set_parent (dialog, parent); - } - - /* Don't destroy on close because callers will need - * to extract some information from the dialog after - * it closes. - */ - gnome_dialog_close_hides (dialog, TRUE); - - return dialog; -} - -/** - * nautilus_choose_component_for_file: - * - * Lets user choose a component with which to view a given file. - * - * @file: The NautilusFile to be viewed. - * @parent_window: If supplied, the component-choosing dialog is parented - * on this window. - * @callback: Callback called when choice has been made. - * @callback_data: Parameter passed back when callback is called. - */ - -static void -choose_component_callback (NautilusFile *file, - gpointer callback_data) -{ - ChooseComponentCallbackData *choose_data; - NautilusViewIdentifier *identifier; - GnomeDialog *dialog; - - choose_data = callback_data; - - /* Remove from the hash table. */ - g_assert (g_hash_table_lookup (choose_component_hash_table, - choose_data) == choose_data); - g_hash_table_remove (choose_component_hash_table, - choose_data); - - /* The API uses a callback so we can do this non-modally in the future, - * but for now we just use a modal dialog. - */ - - identifier = NULL; - dialog = NULL; - if (nautilus_mime_has_any_components_for_file (file)) { - dialog = set_up_program_chooser (file, GNOME_VFS_MIME_ACTION_TYPE_COMPONENT, - choose_data->parent_window); - if (gnome_dialog_run (dialog) == GNOME_OK) { - identifier = nautilus_program_chooser_get_component (dialog); - } - } else { - nautilus_program_chooser_show_no_choices_message (GNOME_VFS_MIME_ACTION_TYPE_COMPONENT, - file, - choose_data->parent_window); - } - - /* Call callback even if identifier is NULL, so caller can - * free callback_data if necessary and present some cancel UI - * if desired. - */ - (* choose_data->callback) (identifier, choose_data->callback_data); - - if (dialog != NULL) { - /* Destroy only after callback, since view identifier will - * be destroyed too. - */ - gtk_widget_destroy (GTK_WIDGET (dialog)); - } - - choose_component_destroy (choose_data); -} - -void -nautilus_choose_component_for_file (NautilusFile *file, - GtkWindow *parent_window, - NautilusComponentChoiceCallback callback, - gpointer callback_data) -{ - ChooseComponentCallbackData *choose_data; - GList *attributes; - - g_return_if_fail (NAUTILUS_IS_FILE (file)); - g_return_if_fail (parent_window == NULL || GTK_IS_WINDOW (parent_window)); - g_return_if_fail (callback != NULL); - - /* Grab refs to the objects so they will still be around at - * callback time. - */ - nautilus_file_ref (file); - if (parent_window != NULL) { - gtk_object_ref (GTK_OBJECT (parent_window)); - } - - /* Create data to pass through. */ - choose_data = g_new (ChooseComponentCallbackData, 1); - choose_data->file = file; - choose_data->parent_window = parent_window; - choose_data->callback = callback; - choose_data->callback_data = callback_data; - - /* Put pending entry into choose hash table. */ - if (choose_component_hash_table == NULL) { - choose_component_hash_table = eel_g_hash_table_new_free_at_exit - (choose_component_hash, - choose_component_equal, - "choose component"); - } - g_hash_table_insert (choose_component_hash_table, - choose_data, choose_data); - - /* Do the rest of the work when the attributes are ready. */ - attributes = nautilus_mime_actions_get_full_file_attributes (); - nautilus_file_call_when_ready (file, - attributes, - choose_component_callback, - choose_data); - g_list_free (attributes); -} - -void -nautilus_cancel_choose_component_for_file (NautilusFile *file, - NautilusComponentChoiceCallback callback, - gpointer callback_data) -{ - ChooseComponentCallbackData search_criteria; - ChooseComponentCallbackData *choose_data; - - if (choose_component_hash_table == NULL) { - return; - } - - /* Search for an existing choose in progress. */ - search_criteria.file = file; - search_criteria.callback = callback; - search_criteria.callback_data = callback_data; - choose_data = g_hash_table_lookup (choose_component_hash_table, - &search_criteria); - if (choose_data == NULL) { - return; - } - - /* Stop it. */ - g_hash_table_remove (choose_component_hash_table, - choose_data); - nautilus_file_cancel_call_when_ready (file, - choose_component_callback, - choose_data); - choose_component_destroy (choose_data); -} - -/** - * nautilus_choose_application_for_file: - * - * Lets user choose an application with which to open a given file. - * - * @file: The NautilusFile to be viewed. - * @parent_window: If supplied, the application-choosing dialog is parented - * on this window. - * @callback: Callback called when choice has been made. - * @callback_data: Parameter passed back when callback is called. - */ - -static void -choose_application_callback (NautilusFile *file, - gpointer callback_data) -{ - ChooseApplicationCallbackData *choose_data; - GnomeDialog *dialog; - GnomeVFSMimeApplication *application; - - choose_data = callback_data; - - /* Remove from the hash table. */ - g_assert (g_hash_table_lookup (choose_application_hash_table, - choose_data) == choose_data); - g_hash_table_remove (choose_application_hash_table, - choose_data); - - /* The API uses a callback so we can do this non-modally in the future, - * but for now we just use a modal dialog. - */ - application = NULL; - dialog = NULL; - - if (nautilus_mime_has_any_applications_for_file_type (file)) { - dialog = set_up_program_chooser (file, GNOME_VFS_MIME_ACTION_TYPE_APPLICATION, - choose_data->parent_window); - if (gnome_dialog_run (dialog) == GNOME_OK) { - application = nautilus_program_chooser_get_application (dialog); - } - } else { - nautilus_program_chooser_show_no_choices_message (GNOME_VFS_MIME_ACTION_TYPE_APPLICATION, - file, - choose_data->parent_window); - } - - /* Call callback even if identifier is NULL, so caller can - * free callback_data if necessary and present some cancel - * UI if desired. - */ - (* choose_data->callback) (application, choose_data->callback_data); - - if (dialog != NULL) { - /* Destroy only after callback, since application struct will - * be destroyed too. - */ - gtk_widget_destroy (GTK_WIDGET (dialog)); - } - - choose_application_destroy (choose_data); -} - -void -nautilus_choose_application_for_file (NautilusFile *file, - GtkWindow *parent_window, - NautilusApplicationChoiceCallback callback, - gpointer callback_data) -{ - ChooseApplicationCallbackData *choose_data; - GList *attributes; - - g_return_if_fail (NAUTILUS_IS_FILE (file)); - g_return_if_fail (parent_window == NULL || GTK_IS_WINDOW (parent_window)); - g_return_if_fail (callback != NULL); - - /* Grab refs to the objects so they will still be around at - * callback time. - */ - nautilus_file_ref (file); - if (parent_window != NULL) { - gtk_object_ref (GTK_OBJECT (parent_window)); - } - - /* Create data to pass through. */ - choose_data = g_new (ChooseApplicationCallbackData, 1); - choose_data->file = file; - choose_data->parent_window = parent_window; - choose_data->callback = callback; - choose_data->callback_data = callback_data; - - /* Put pending entry into choose hash table. */ - if (choose_application_hash_table == NULL) { - choose_application_hash_table = eel_g_hash_table_new_free_at_exit - (choose_application_hash, - choose_application_equal, - "choose application"); - } - g_hash_table_insert (choose_application_hash_table, - choose_data, choose_data); - - /* Do the rest of the work when the attributes are ready. */ - attributes = nautilus_mime_actions_get_full_file_attributes (); - nautilus_file_call_when_ready (file, - attributes, - choose_application_callback, - choose_data); - g_list_free (attributes); -} - - -typedef struct { - NautilusFile *file; - GtkWindow *parent_window; -} LaunchParameters; - -static LaunchParameters * -launch_parameters_new (NautilusFile *file, - GtkWindow *parent_window) -{ - LaunchParameters *launch_parameters; - - launch_parameters = g_new0 (LaunchParameters, 1); - nautilus_file_ref (file); - launch_parameters->file = file; - gtk_widget_ref (GTK_WIDGET (parent_window)); - launch_parameters->parent_window = parent_window; - - return launch_parameters; -} - -static void -launch_parameters_free (LaunchParameters *launch_parameters) -{ - g_assert (launch_parameters != NULL); - - nautilus_file_unref (launch_parameters->file); - gtk_widget_unref (GTK_WIDGET (launch_parameters->parent_window)); - - g_free (launch_parameters); -} - -static void -launch_application_callback (GnomeVFSMimeApplication *application, - gpointer callback_data) -{ - LaunchParameters *launch_parameters; - - g_assert (callback_data != NULL); - - launch_parameters = (LaunchParameters *) callback_data; - - if (application != NULL) { - g_assert (NAUTILUS_IS_FILE (launch_parameters->file)); - - nautilus_launch_application (application, - launch_parameters->file, - launch_parameters->parent_window); - } - - launch_parameters_free (launch_parameters); - -} - -/** - * application_cannot_open_location - * - * Handle the case where an application has been selected to be launched, - * and it cannot handle the current uri scheme. This can happen - * because the default application for a file type may not be able - * to handle some kinds of locations. We want to tell users that their - * default application doesn't work here, rather than switching off to - * a different one without them noticing. - * - * @application: The application that was to be launched. - * @file: The file whose location was passed as a parameter to the application - * @parent_window: A window to use as the parent for any error dialogs. - * */ -static void -application_cannot_open_location (GnomeVFSMimeApplication *application, - NautilusFile *file, - const char *uri_scheme, - GtkWindow *parent_window) -{ - GnomeDialog *message_dialog; - LaunchParameters *launch_parameters; - char *message; - char *file_name; - - file_name = nautilus_file_get_name (file); - - if (nautilus_mime_has_any_applications_for_file (file)) { - message = g_strdup_printf (_("\"%s\" can't open \"%s\" because \"%s\" can't access files at \"%s\" " - "locations. Would you like to choose another application?"), - application->name, file_name, - application->name, uri_scheme); - message_dialog = eel_show_yes_no_dialog (message, - _("Can't Open Location"), - GNOME_STOCK_BUTTON_OK, - GNOME_STOCK_BUTTON_CANCEL, - parent_window); - if (gnome_dialog_run (message_dialog) == GNOME_OK) { - launch_parameters = launch_parameters_new (file, parent_window); - nautilus_choose_application_for_file - (file, - parent_window, - launch_application_callback, - launch_parameters); - - } - - } - else { - message = g_strdup_printf (_("\"%s\" can't open \"%s\" because \"%s\" can't access files at \"%s\" " - "locations. No other applications are available to view this file. " - "If you copy this file onto your computer, you may be able to open " - "it."), application->name, file_name, - application->name, uri_scheme); - eel_show_info_dialog (message, _("Can't Open Location"), parent_window); - } - - g_free (file_name); - g_free (message); -} - -/** - * nautilus_launch_application: - * - * Fork off a process to launch an application with a given file as a - * parameter. Provide a parent window for error dialogs. - * - * @application: The application to be launched. - * @file: The file whose location should be passed as a parameter to the application - * @parent_window: A window to use as the parent for any error dialogs. - */ -void -nautilus_launch_application (GnomeVFSMimeApplication *application, - NautilusFile *file, - GtkWindow *parent_window) -{ - char *parameter; - char *uri_scheme, *uri; - - uri_scheme = nautilus_file_get_uri_scheme (file); - - /* If the program can open URIs, always use a URI. This - * prevents any possible ambiguity for cases where a path - * would looks like a URI. - */ - if (application->expects_uris == GNOME_VFS_MIME_APPLICATION_ARGUMENT_TYPE_URIS || - ((application->expects_uris == GNOME_VFS_MIME_APPLICATION_ARGUMENT_TYPE_URIS_FOR_NON_FILES) && - eel_strcasecmp (uri_scheme, "file") != 0)) { - /* Check to be sure that the application also supports this particular URI scheme */ - if (g_list_find_custom (application->supported_uri_schemes, - uri_scheme, - eel_strcmp_compare_func) == NULL) { - application_cannot_open_location (application, - file, - uri_scheme, - parent_window); - g_free (uri_scheme); - return; - } - parameter = nautilus_file_get_uri (file); - } else { - uri = nautilus_file_get_uri (file); - parameter = gnome_vfs_get_local_path_from_uri (uri); - g_free (uri); - - if (parameter == NULL) { - /* This application can't deal with this URI, - * because it can only handle local - * files. Tell user. Some day we could offer - * to copy it locally for the user, if we knew - * where to put it, and who would delete it - * when done. - */ - application_cannot_open_location (application, - file, - uri_scheme, - parent_window); - g_free (uri_scheme); - return; - } - } - g_free (uri_scheme); - - nautilus_launch_application_from_command (application->name, - application->command, - parameter, - application->requires_terminal); - - g_free (parameter); -} - -static char * -get_xalf_prefix (const char *name) -{ - char *xalf_executable; - GString *s; - int argc, i; - char **argv; - char *quoted; - char *prefix; - - /* FIXME bugzilla.eazel.com 8206: At time I am writing this, - * xalf is still pretty buggy, and Nautilus uses it a lot more - * than the Panel does with no way to turn it off for - * individual programs the way you can in the Panel. Sadly, - * Ximian GNOME 1.4 ships with xalf on by default. So we did - * this lame thing and turned it off unless you define this - * environment variable. Some day we can remove this. - */ - if (g_getenv ("NAUTILUS_USE_XALF") == NULL) { - return g_strdup (""); - } - if (!gnome_config_get_bool ("/xalf/settings/enabled=true")) { - return g_strdup (""); - } - xalf_executable = gnome_is_program_in_path ("xalf"); - if (xalf_executable == NULL) { - return g_strdup (""); - } - - s = g_string_new (xalf_executable); - g_string_append (s, " --title "); - quoted = eel_shell_quote (name); - g_string_append (s, quoted); - g_free (quoted); - g_string_append_c (s, ' '); - - gnome_config_get_vector ("/xalf/settings/options", - &argc, &argv); - for (i = 0; i < argc; i++) { - quoted = eel_shell_quote (argv[i]); - g_free (argv[i]); - - g_string_append (s, quoted); - g_string_append_c (s, ' '); - - g_free (quoted); - } - g_free (argv); - - prefix = s->str; - g_string_free (s, FALSE); - return prefix; -} - -/** - * nautilus_launch_application_from_command: - * - * Fork off a process to launch an application with a given uri as - * a parameter. - * - * @command_string: The application to be launched, with any desired - * command-line options. - * @parameter: Passed as a parameter to the application as is. - */ -void -nautilus_launch_application_from_command (const char *name, - const char *command_string, - const char *parameter, - gboolean use_terminal) -{ - char *full_command; - char *quoted_parameter; - char *final_command; - char *xalf_prefix; - - if (parameter != NULL) { - quoted_parameter = eel_shell_quote (parameter); - full_command = g_strconcat (command_string, " ", quoted_parameter, NULL); - g_free (quoted_parameter); - } else { - full_command = g_strdup (command_string); - } - - xalf_prefix = get_xalf_prefix (name); - - if (use_terminal) { - final_command = g_strconcat (xalf_prefix, full_command, NULL); - eel_gnome_open_terminal (final_command); - } else { - final_command = g_strconcat (xalf_prefix, full_command, " &", NULL); - system (final_command); - } - - g_free (final_command); - g_free (full_command); - g_free (xalf_prefix); -} diff --git a/libnautilus-extensions/nautilus-program-choosing.h b/libnautilus-extensions/nautilus-program-choosing.h deleted file mode 100644 index e3c374fc2..000000000 --- a/libnautilus-extensions/nautilus-program-choosing.h +++ /dev/null @@ -1,61 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ - -/* nautilus-program-choosing.h - functions for selecting and activating - programs for opening/viewing particular files. - - Copyright (C) 2000 Eazel, Inc. - - The Gnome 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 Gnome 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 the Gnome 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. - - Author: John Sullivan <sullivan@eazel.com> -*/ - -#ifndef NAUTILUS_PROGRAM_CHOOSING_H -#define NAUTILUS_PROGRAM_CHOOSING_H - -#include "nautilus-file.h" -#include "nautilus-view-identifier.h" -#include <gtk/gtkwindow.h> -#include <libgnomevfs/gnome-vfs-mime-handlers.h> - -typedef void (*NautilusApplicationChoiceCallback) (GnomeVFSMimeApplication *application, - gpointer callback_data); -typedef void (*NautilusComponentChoiceCallback) (NautilusViewIdentifier *identifier, - gpointer callback_data); - -void nautilus_choose_application_for_file (NautilusFile *file, - GtkWindow *parent_window, - NautilusApplicationChoiceCallback callback, - gpointer callback_data); -void nautilus_cancel_choose_application_for_file (NautilusFile *file, - NautilusComponentChoiceCallback callback, - gpointer callback_data); -void nautilus_choose_component_for_file (NautilusFile *file, - GtkWindow *parent_window, - NautilusComponentChoiceCallback callback, - gpointer callback_data); -void nautilus_cancel_choose_component_for_file (NautilusFile *file, - NautilusComponentChoiceCallback callback, - gpointer callback_data); -void nautilus_launch_application (GnomeVFSMimeApplication *application, - NautilusFile *file, - GtkWindow *parent_window); -void nautilus_launch_application_from_command (const char *name, - const char *command_string, - const char *parameter, - gboolean use_terminal); - -#endif /* NAUTILUS_PROGRAM_CHOOSING_H */ diff --git a/libnautilus-extensions/nautilus-search-uri.c b/libnautilus-extensions/nautilus-search-uri.c deleted file mode 100644 index 8f452a685..000000000 --- a/libnautilus-extensions/nautilus-search-uri.c +++ /dev/null @@ -1,728 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */ -/* Code to generate human-readable strings from search uris. - - 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; see the file COPYING. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. - - Author: Mathieu Lacage <mathieu@eazel.com> -*/ - -#include <config.h> -#include "nautilus-search-uri.h" - -/* Must be included before other libgnome headers. */ -#include <libgnome/gnome-defs.h> - -#include "nautilus-lib-self-check-functions.h" -#include <eel/eel-glib-extensions.h> -#include <eel/eel-string.h> -#include <libgnome/gnome-i18n.h> -#include <libgnomevfs/gnome-vfs-utils.h> - -static const char *strip_uri_beginning (const char *location_uri); -static GList * tokenize_uri (const char *string); -static char * get_translated_criterion (GList *criterion); -static char * get_nth_criterion_prefix (GList *criterion); -static char * parse_uri (const char *search_uri); -static void free_tokenized_uri (GList *list); - -/** - * strip_uri_beginning: - * @location_uri: search uri. - * - * strips the search:[file:///...] part of the input uri. - * - */ -static const char * -strip_uri_beginning (const char *location_uri) -{ - char **first_token; - char *ptr; - const char *ret_val; - - first_token = g_strsplit (location_uri, " ", 1); - if (first_token[0] == NULL) { - g_strfreev (first_token); - return NULL; - } - - /* parse the first token from the end to the beginning. - to extract the search:[] part. - */ - for (ptr = first_token[0]+strlen(first_token[0]); - ptr != first_token[0] && *ptr != ']'; - ptr--) {} - - ret_val = location_uri + (ptr - first_token[0]) + 1; - - g_strfreev (first_token); - - return ret_val; -} - -/** - * free_tokenized_uri: - * @list: tokenized uri to free - * - */ -static void -free_tokenized_uri (GList *list) -{ - GList *node; - - for (node = list; node != NULL; node = node->next) { - eel_g_list_free_deep (node->data); - } - g_list_free (list); -} - - -/** - * tokenize_uri - * @string: string to parse - * - * This function tokenizes a subset of the grand medusa uri specification. - * If it cannot, it returns NULL. CHECK FOR NULL upon return. - * - * Return value: a Singly linked list of singly linked lists. - * each of the element of the root linked list is a complete criterion. - * each criterin sinlgly linked list is made of the different tokens - * of the criterion. - */ -static GList * -tokenize_uri (const char *string) -{ - const char *temp_string; - char **criteria; - GList *criterion_list; - int i, j; - - if (string == NULL) { - return NULL; - } - - criterion_list = NULL; - - string = strip_uri_beginning (string); - if (string == NULL) { - return NULL; - } - - /* make sure we can handle this uri */ - if ( strchr (string , '(') != NULL - || strchr (string, ')') != NULL - || strchr (string, '|') != NULL) { - return NULL; - } - - /* split the uri in different criteria */ - criteria = g_strsplit (string, " & ", 0); - for (i = 0, temp_string = criteria[0]; - temp_string != NULL; - i++, temp_string = criteria[i]) { - char **tokens; - char *token; - GList *token_list; - - /* split a criterion in different tokens */ - token_list = NULL; - tokens = g_strsplit (temp_string, " ", 2); - for (j = 0, token = tokens[0]; token != NULL; j++, token = tokens[j]) { - /* g_strstrip does not return a newly allocated string. */ - token_list = g_list_append (token_list, g_strdup (g_strstrip (token))); - } - criterion_list = g_list_append (criterion_list, token_list); - g_strfreev (tokens); - } - g_strfreev (criteria); - - return criterion_list; -} - -typedef struct _value_criterion_item value_criterion_item; -typedef value_criterion_item *value_criterion_table; - -typedef struct _operand_criterion_item operand_criterion_item; -typedef operand_criterion_item *operand_criterion_table; - -typedef struct _field_criterion_item field_criterion_item; -typedef field_criterion_item *field_criterion_table; - -/* toplevel structure each entry points to a level 2 structure */ -struct _field_criterion_item { - char *id; - /* FIXME: This field is necessary so that - the size of this structure is the same - as the size of the other structures. - see the comment in the definition of "value_criterion_item" - to see what I mean. Yay, evil! - someone should make this go away. */ - char *unused_field_for_hack_compatibility; - operand_criterion_table items; -}; -/* second level structure. if items is NULL, the entry is a leaf - of our hierarchy. If it is not, it points to a level 3 leaf -*/ -struct _operand_criterion_item { - char *id; - char *translation; - value_criterion_table items; -}; -/* third level structure. leaf */ -struct _value_criterion_item { - char *id; - char *translation; - /* this field is there only to make the 3 structures similar enough - so that you can safely cast between them it is a kind of evil hack - but i like it. It is guaranteed to be always NULL. */ - value_criterion_table items; -}; - - -/* ------------------------------------------------------- - - file name - - ------------------------------------------------------- -*/ - -static operand_criterion_item file_name2_table [] = { - {"contains", - /* Human readable description for a criterion in a search for - files. Bracketed items are context, and are message - strings elsewhere. You don't have to translate the whole - string, and only the translation for "containing '%s' will - be used. If you do translate the whole string, leave the - translations of the rest of the text in brackets, so it - will not be used. - "%s" here is a pattern the file name - matched, such as "nautilus" */ - N_("[Items ]containing \"%s\" in their names"), - NULL}, - {"starts_with", - /* "%s" here is a pattern the file name started with, such as - "nautilus" */ - N_("[Items ]starting with \"%s\""), - NULL}, - {"ends_with", - /* "%s" here is a pattern the file name ended with, such as - "mime" */ - N_("[Items ]ending with %s"), - NULL}, - {"does_not_contain", - /* "%s" here is a pattern the file name did not match, such - as "nautilus" */ - N_("[Items ]not containing \"%s\" in their names"), - NULL}, - {"regexp_matches", - /* "%s" is a regular expression string, for example "[abc]" */ - N_("[Items ]matching the regular expression \"%s\""), - NULL}, - {"matches", - /* "%s" is a file glob, for example "*.txt" */ - N_("[Items ]matching the file pattern \"%s\""), - NULL}, - {NULL, NULL, NULL} - -}; - - -/* ------------------------------------------------------- - - file type - - ------------------------------------------------------- -*/ -static value_criterion_item file_type_options3_table [] = { - {"file", - N_("[Items that are ]regular files"), - NULL}, - {"text_file", - N_("[Items that are ]text files"), - NULL}, - {"application", - N_("[Items that are ]applications"), - NULL}, - {"directory", - N_("[Items that are ]folders"), - NULL}, - {"music", - N_("[Items that are ]music"), - NULL}, - {NULL, NULL, NULL} -}; -static operand_criterion_item file_type2_table [] = { - {"is_not", - /* "%s" here is a word describing a file type, for example - "folder" */ - N_("[Items ]that are not %s"), - file_type_options3_table}, - {"is", - /* "%s" here is a word describing a file type, for example - "folder" */ - N_("[Items ]that are %s"), - file_type_options3_table}, - {NULL, NULL, NULL} -}; - - -/* ------------------------------------------------------- - - owner - - ------------------------------------------------------- -*/ -static operand_criterion_item owner2_table [] = { - {"is_not", - /* "%s" here is the name of user on a Linux machine, such as - "root" */ - N_("[Items ]not owned by \"%s\""), - NULL}, - {"is", - /* "%s" here is the name of user on a Linux machine, such as - "root" */ - N_("[Items ]owned by \"%s\""), - NULL}, - {"has_uid", - N_("[Items ]with owner UID \"%s\""), - NULL}, - {"does_not_have_uid", - N_("[Items ]with owner UID other than \"%s\""), - NULL}, - {NULL, NULL, NULL} -}; - -/* ------------------------------------------------------- - - size - - ------------------------------------------------------- -*/ -static operand_criterion_item size2_table [] = { - {"larger_than", - N_("[Items ]larger than %s bytes"), - NULL}, - {"smaller_than", - N_("[Items ]smaller than %s bytes"), - NULL}, - {"is", - N_("[Items ]of %s bytes"), - NULL}, - {NULL, NULL, NULL} -}; - -/* ------------------------------------------------------- - - modified time - - ------------------------------------------------------- -*/ -static operand_criterion_item mod_time2_table [] = { - {"is today", - N_("[Items ]modified today"), - NULL}, - {"is yesterday", - N_("[Items ]modified yesterday"), - NULL}, - {"is", - N_("[Items ]modified on %s"), NULL}, - {"is_not", - N_("[Items ]not modified on %s"), - NULL}, - {"is_before", - N_("[Items ]modified before %s"), - NULL}, - {"is_after", - N_("[Items ]modified after %s"), - NULL}, - {"is_within_a_week_of", - N_("[Items ]modified within a week of %s"), - NULL}, - {"is_within_a_month_of", - N_("[Items ]modified within a month of %s"), - NULL}, - {NULL, NULL, NULL} -}; - -/* ------------------------------------------------------- - - emblems - - ------------------------------------------------------- -*/ - -static operand_criterion_item emblem2_table [] = { - { "include", - /* "%s" here is the name of an Emblem */ - N_("[Items ]marked with \"%s\""), - NULL}, - { "do_not_include", - /* "%s" here is the name of an Emblem */ - N_("[Items ]not marked with \"%s\""), - NULL}, - {NULL, NULL, NULL} -}; - - -/* ------------------------------------------------------- - - contains - - ------------------------------------------------------- -*/ - - -static operand_criterion_item contains2_table [] = { - {"includes_all_of", - /* "%s" here is a word or words present in the file, for - example "nautilus" or "apple orange" */ - N_("[Items ]with all the words \"%s\""), - NULL}, - {"includes_any_of", - /* "%s" here is a word or words present in the file, for - example "nautilus" or "apple orange" */ - N_("[Items ]containing one of the words \"%s\""), - NULL}, - {"does_not_include_all_of", - /* "%s" here is a word or words present in the file, for - example "nautilus" or "apple orange" */ - N_("[Items ]without all the words \"%s\""), - NULL}, - {"does_not_include_any_of", - /* "%s" here is a word or words present in the file, for - example "nautilus" or "apple orange" */ - N_("[Items ]without any of the words \"%s\""), - NULL}, - {NULL, NULL, NULL}, -}; - - - -/* ------------------------------------------------------- - - main table - - ------------------------------------------------------- */ -static field_criterion_item main_table[] = { - {"file_name", - NULL, - file_name2_table}, - {"file_type", - NULL, - file_type2_table}, - {"owner", - NULL, - owner2_table}, - {"size", - NULL, - size2_table}, - {"content", - NULL, - contains2_table}, - {"modified", - NULL, - mod_time2_table}, - {"keywords", - NULL, - emblem2_table}, - {NULL, NULL} -}; - - - -/** - * get_item_number: - * @current_table: the table to parse. - * @item: the string to search into the table. - * - * Small helper function which allows whoich serches for @item - * into the @current_table. - * it returns -1 if it could not find it. - * Yes, I know it is wrong to use the normal function return value - * to pass error status. */ -static int -get_item_number (field_criterion_item *current_table, char *item) -{ - int i; - - i = 0; - while (strcmp (current_table[i].id, - item) != 0) { - i++; - if (current_table[i].id == NULL) { - return -1; - } - } - - return i; -} - -/** - * get_translated_criterion: - * @criterion: criterion uri to parse - * - * Returns a translated string for a given criterion uri. - */ -static char * -get_translated_criterion (GList *criterion) -{ - - int item_number, value_item_number; - operand_criterion_item *operand_table; - value_criterion_item *value_table; - char *ret_val; - char *context_stripped_operand, *context_stripped_value; - - /* make sure we got a valid criterion */ - if (g_list_length (criterion) != 3) { - return NULL; - } - - - /* get through begening of criterion structure */ - item_number = get_item_number (main_table, (char *)criterion->data); - if (item_number == -1) { - return NULL; - } - operand_table = main_table[item_number].items; - criterion = criterion->next; - - /* get through operanddle criterion structure */ - item_number = get_item_number ((field_criterion_item *)operand_table, - (char *)criterion->data); - if (item_number == -1) { - return NULL; - } - value_table = operand_table[item_number].items; - criterion = criterion->next; - - /* get through value criterion structure. - The fun begins NOW. */ - - if (value_table == NULL && operand_table[item_number].translation != NULL) { - /* simplest case: if the pointer to the value criterion - structure is NULL and we have a translation, - we output a concat of the translation and the - last part of the uri. - */ - context_stripped_operand = eel_str_remove_bracketed_text (_(operand_table[item_number].translation)); - ret_val = g_strdup_printf (context_stripped_operand, - (char *) criterion->data); - g_free (context_stripped_operand); - return ret_val; - } else if (value_table != NULL) { - /* get through level 3 structure */ - - value_item_number = get_item_number ((field_criterion_item *) value_table, - (char *) criterion->data); - if (value_item_number == -1) { - return NULL; - } - - if (operand_table[item_number].translation == NULL) { - /* if we had no translation in operand criterion table */ - ret_val = eel_str_remove_bracketed_text (_(value_table[value_item_number].translation)); - } else { - /* if we have both some translation in level 2 and level 3 */ - context_stripped_operand = eel_str_remove_bracketed_text (_(operand_table[item_number].translation)); - context_stripped_value = eel_str_remove_bracketed_text (_(value_table[value_item_number].translation)); - ret_val = g_strdup_printf (context_stripped_operand, context_stripped_value); - g_free (context_stripped_operand); - g_free (context_stripped_value); - } - return ret_val; - } - - return g_strdup (""); -} - - -/** - * get_nth_criterion_prefix: - * @criterion: The GList whose data field points to the criterion GList. - * - * calculates the "," or "and" prefix for any criterion. - * - * return value: the translated prefix. - */ -static char * -get_nth_criterion_prefix (GList *criterion) -{ - /* if we are the last criterion, put it here. */ - - /* Human readable description for a criterion in a search for - files. Bracketed items are context, and are message - strings elsewhere. Translate only the words "and" here. */ - if (criterion->next == NULL) { - - return eel_str_remove_bracketed_text (_("[Items larger than 400K] and [without all the words \"apple orange\"]")); - } - /* Human readable description for a criterion in a search for - files. Bracketed items are context, and are message - strings elsewhere. Translate only the words "and" here. */ - return eel_str_remove_bracketed_text (_("[Items larger than 400K], [owned by root and without all the words \"apple orange\"]")); -} - -/** - * parse_uri: - * @search_uri: uri to translate. - * - * returns the translated version of the uri. - */ -static char * -parse_uri (const char *search_uri) -{ - GList *criteria, *criterion; - char *translated_criterion, *translated_prefix; - char *ret_val, *temp; - - criteria = tokenize_uri (search_uri); - if (criteria == NULL) { - return NULL; - } - - /* processes the first criterion and add the necessary "whose" prefix */ - translated_criterion = get_translated_criterion ((GList *)criteria->data); - if (translated_criterion == NULL) { - free_tokenized_uri (criteria); - return NULL; - } - /* The beginning of the description of a search that has just been - performed. The "%s" here is a description of a single criterion, - which in english might be "that contain the word 'foo'" */ - ret_val = g_strdup_printf (_("Items %s"), - translated_criterion); - g_free (translated_criterion); - - /* processes the other criteria and add the necessary "and" prefixes */ - for (criterion = criteria->next; criterion != NULL; criterion = criterion->next) { - translated_criterion = get_translated_criterion (criterion->data); - if (translated_criterion == NULL) { - g_free (ret_val); - free_tokenized_uri (criteria); - return NULL; - } - translated_prefix = get_nth_criterion_prefix (criterion); - temp = g_strconcat (ret_val, translated_prefix, - translated_criterion, NULL); - g_free (ret_val); - ret_val = temp; - g_free (translated_criterion); - g_free (translated_prefix); - } - - free_tokenized_uri (criteria); - - return ret_val; -} - - -/** - * nautilus_search_uri_to_human: - * @search_uri: search uri to translate to human langage. - * - * The returned string is already localized. - */ -char * -nautilus_search_uri_to_human (const char *search_uri) -{ - char *uri, *human; - - g_return_val_if_fail (search_uri != NULL, NULL); - - uri = gnome_vfs_unescape_string_for_display (search_uri); - human = parse_uri (uri); - if (human == NULL) { - return uri; - } - - g_free (uri); - - return human; -} - -char * -nautilus_get_target_uri_from_search_result_name (const char *search_result_name) -{ - return gnome_vfs_unescape_string (search_result_name, NULL); -} - -gboolean -nautilus_is_search_uri (const char *uri) -{ - g_return_val_if_fail (uri != NULL, FALSE); - - return eel_istr_has_prefix (uri, "search:") - || eel_istr_has_prefix (uri, "gnome-search:"); -} - -#if !defined (NAUTILUS_OMIT_SELF_CHECK) - -void -nautilus_self_check_search_uri (void) -{ - /* search_uri_to_human */ - - /* make sure that it does not accept non-supported uris.*/ - EEL_CHECK_STRING_RESULT (nautilus_search_uri_to_human (""), ""); - EEL_CHECK_STRING_RESULT (nautilus_search_uri_to_human ("s"), "s"); - EEL_CHECK_STRING_RESULT (nautilus_search_uri_to_human (" "), " "); - EEL_CHECK_STRING_RESULT (nautilus_search_uri_to_human (" "), " "); - EEL_CHECK_STRING_RESULT (nautilus_search_uri_to_human (" s"), " s"); - EEL_CHECK_STRING_RESULT (nautilus_search_uri_to_human (" s "), " s "); - EEL_CHECK_STRING_RESULT (nautilus_search_uri_to_human ("xxx:yyy"), "xxx:yyy"); - EEL_CHECK_STRING_RESULT (nautilus_search_uri_to_human ("search:[][]"), "search:[][]"); - EEL_CHECK_STRING_RESULT (nautilus_search_uri_to_human ("search:[][]fi"), "search:[][]fi"); - EEL_CHECK_STRING_RESULT (nautilus_search_uri_to_human ("search:[][]file_name"), - "search:[][]file_name"); - EEL_CHECK_STRING_RESULT (nautilus_search_uri_to_human ("search:[][]file_name cont"), - "search:[][]file_name cont"); - EEL_CHECK_STRING_RESULT (nautilus_search_uri_to_human ("search:[][]file_name contains"), - "search:[][]file_name contains"); - EEL_CHECK_STRING_RESULT (nautilus_search_uri_to_human ("search:[][]file_name c stuff"), - "search:[][]file_name c stuff"); - EEL_CHECK_STRING_RESULT (nautilus_search_uri_to_human ("search:[][]&"), - "search:[][]&"); - EEL_CHECK_STRING_RESULT (nautilus_search_uri_to_human ("search:[][]f & s"), - "search:[][]f & s"); - EEL_CHECK_STRING_RESULT (nautilus_search_uri_to_human ("search:[][]file_name contains stuff & f"), - "search:[][]file_name contains stuff & f"); - EEL_CHECK_STRING_RESULT (nautilus_search_uri_to_human ("search:[][]file_name contains stuff & file_type i"), - "search:[][]file_name contains stuff & file_type i"); - EEL_CHECK_STRING_RESULT (nautilus_search_uri_to_human ("search:[][]file_name contains stuff & file_type is f"), - "search:[][]file_name contains stuff & file_type is f"); - EEL_CHECK_STRING_RESULT (nautilus_search_uri_to_human ("search:[][]file_name contains stu)ff & file_type is file"), - "search:[][]file_name contains stu)ff & file_type is file"); - EEL_CHECK_STRING_RESULT (nautilus_search_uri_to_human ("search:[][]file_name contains stu(ff & file_type is file"), - "search:[][]file_name contains stu(ff & file_type is file"); - EEL_CHECK_STRING_RESULT (nautilus_search_uri_to_human ("search:[][]file_name contains stu|ff & file_type is file"), - "search:[][]file_name contains stu|ff & file_type is file"); - - /* make sure all the code paths work */ - EEL_CHECK_STRING_RESULT (nautilus_search_uri_to_human ("search:[][]file_name contains stuff"), - _("Items containing \"stuff\" in their names")); - EEL_CHECK_STRING_RESULT (nautilus_search_uri_to_human ("search:[][]file_type is file"), - _("Items that are regular files")); - /* FIXME bugzilla.eazel.com 5088: This may be what the function calls "human", but it's bad grammar. */ - EEL_CHECK_STRING_RESULT (nautilus_search_uri_to_human ("search:[][]file_name contains stuff & file_type is file"), - _("Items containing \"stuff\" in their names and that are regular files")); - /* FIXME bugzilla.eazel.com 5088: This may be what the function calls "human", but it's bad grammar. */ - EEL_CHECK_STRING_RESULT (nautilus_search_uri_to_human ("search:[][]file_name contains stuff & file_type is file" - " & size smaller_than 2000"), - _("Items containing \"stuff\" in their names, that are regular files and " - "smaller than 2000 bytes")); - /* FIXME bugzilla.eazel.com 5088: This may be what the function calls "human", but it's bad grammar. */ - EEL_CHECK_STRING_RESULT (nautilus_search_uri_to_human ("search:[][]file_name contains medusa & file_type is directory"), - _("Items containing \"medusa\" in their names and that are " - "folders")); - - /* is_search_uri */ - EEL_CHECK_BOOLEAN_RESULT (nautilus_is_search_uri (""), FALSE); - EEL_CHECK_BOOLEAN_RESULT (nautilus_is_search_uri ("search:"), TRUE); - EEL_CHECK_BOOLEAN_RESULT (nautilus_is_search_uri ("gnome-search:"), TRUE); - EEL_CHECK_BOOLEAN_RESULT (nautilus_is_search_uri ("xxx-search:"), FALSE); - EEL_CHECK_BOOLEAN_RESULT (nautilus_is_search_uri ("search:xxx"), TRUE); - EEL_CHECK_BOOLEAN_RESULT (nautilus_is_search_uri ("gnome-search:xxx"), TRUE); - EEL_CHECK_BOOLEAN_RESULT (nautilus_is_search_uri ("xxx-search:xxx"), FALSE); -} - -#endif /* !NAUTILUS_OMIT_SELF_CHECK */ - diff --git a/libnautilus-extensions/nautilus-search-uri.h b/libnautilus-extensions/nautilus-search-uri.h deleted file mode 100644 index 808ad17fd..000000000 --- a/libnautilus-extensions/nautilus-search-uri.h +++ /dev/null @@ -1,42 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */ -/* Code to generate human-readable strings from search uris. - - 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; see the file COPYING. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. - - Author: Mathieu Lacage <mathieu@eazel.com> -*/ - -#ifndef NAUTILUS_SEARCH_URI_H -#define NAUTILUS_SEARCH_URI_H - -#include <glib.h> - -/* These strings are used programatically; they must not be translated */ -#define NAUTILUS_SEARCH_URI_TEXT_NAME "file_name" -#define NAUTILUS_SEARCH_URI_TEXT_CONTENT "content" -#define NAUTILUS_SEARCH_URI_TEXT_TYPE "file_type" -#define NAUTILUS_SEARCH_URI_TEXT_SIZE "size" -#define NAUTILUS_SEARCH_URI_TEXT_EMBLEMS "keywords" -#define NAUTILUS_SEARCH_URI_TEXT_DATE_MODIFIED "modified" -#define NAUTILUS_SEARCH_URI_TEXT_OWNER "owner" - -gboolean nautilus_is_search_uri (const char *uri); -char * nautilus_search_uri_to_human (const char *search_uri); -char * nautilus_get_target_uri_from_search_result_name (const char *search_result_name); - -#endif /* NAUTILUS_SEARCH_URI_H */ diff --git a/libnautilus-extensions/nautilus-sidebar-functions.c b/libnautilus-extensions/nautilus-sidebar-functions.c deleted file mode 100644 index e285d674e..000000000 --- a/libnautilus-extensions/nautilus-sidebar-functions.c +++ /dev/null @@ -1,177 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ - -/* nautilus-sidebar-functions.c - Sidebar functions used throughout Nautilus. - - Copyright (C) 2001 Eazel, Inc. - - The Gnome 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 Gnome 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 the Gnome 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. - - Authors: Ramiro Estrugo <ramiro@eazel.com> -*/ - -#include <config.h> -#include "nautilus-sidebar-functions.h" - -#include <eel/eel-glib-extensions.h> -#include "nautilus-preferences.h" -#include <eel/eel-string.h> -#include "nautilus-view-identifier.h" - -#include <liboaf/liboaf.h> - -#define PREFERENCES_SIDEBAR_PANEL_PREFIX "sidebar-panels" - -#define NEWS_PANEL_IID "OAFIID:nautilus_news_view:041601" -#define NOTES_PANEL_IID "OAFIID:nautilus_notes_view:7f04c3cb-df79-4b9a-a577-38b19ccd4185" -#define HELP_PANEL_IID "OAFIID:hyperbola_navigation_tree:57542ce0-71ff-442d-a764-462c92514234" -#define HISTORY_PANEL_IID "OAFIID:nautilus_history_view:a7a85bdd-2ecf-4bc1-be7c-ed328a29aacb" -#define TREE_PANEL_IID "OAFIID:nautilus_tree_view:2d826a6e-1669-4a45-94b8-23d65d22802d" - -const char nautilus_sidebar_news_enabled_preference_name[] = PREFERENCES_SIDEBAR_PANEL_PREFIX "/" NEWS_PANEL_IID; -const char nautilus_sidebar_notes_enabled_preference_name[] = PREFERENCES_SIDEBAR_PANEL_PREFIX "/" NOTES_PANEL_IID; -const char nautilus_sidebar_help_enabled_preference_name[] = PREFERENCES_SIDEBAR_PANEL_PREFIX "/" HELP_PANEL_IID; -const char nautilus_sidebar_history_enabled_preference_name[] = PREFERENCES_SIDEBAR_PANEL_PREFIX "/" HISTORY_PANEL_IID; -const char nautilus_sidebar_tree_enabled_preference_name[] = PREFERENCES_SIDEBAR_PANEL_PREFIX "/" TREE_PANEL_IID; - -static char * -sidebar_panel_make_preference_key (const char *panel_iid) -{ - g_return_val_if_fail (panel_iid != NULL, NULL); - - return g_strdup_printf ("%s/%s", PREFERENCES_SIDEBAR_PANEL_PREFIX, panel_iid); -} - -static int -compare_view_identifiers (gconstpointer a, gconstpointer b) -{ - NautilusViewIdentifier *idenfifier_a; - NautilusViewIdentifier *idenfifier_b; - - g_assert (a != NULL); - g_assert (b != NULL); - - idenfifier_a = (NautilusViewIdentifier*) a; - idenfifier_b = (NautilusViewIdentifier*) b; - - return eel_strcmp (idenfifier_a->name, idenfifier_b->name); -} - -static gboolean -sidebar_is_sidebar_panel_enabled (NautilusViewIdentifier *panel_identifier) -{ - gboolean enabled; - gchar *key; - - g_return_val_if_fail (panel_identifier != NULL, FALSE); - g_return_val_if_fail (panel_identifier->iid != NULL, FALSE); - - key = sidebar_panel_make_preference_key (panel_identifier->iid); - g_return_val_if_fail (key != NULL, FALSE); - enabled = nautilus_preferences_get_boolean (key); - g_free (key); - - return enabled; -} - -static gboolean -sidebar_is_sidebar_panel_enabled_cover (gpointer data, gpointer callback_data) -{ - return sidebar_is_sidebar_panel_enabled (data); -} - -/* Make a query to find out what sidebar panels are available. */ -static GList * -sidebar_get_sidebar_panel_view_identifiers (void) -{ - CORBA_Environment ev; - const char *query; - OAF_ServerInfoList *oaf_result; - guint i; - NautilusViewIdentifier *id; - GList *view_identifiers; - - CORBA_exception_init (&ev); - - query = "nautilus:sidebar_panel_name.defined() AND repo_ids.has ('IDL:Bonobo/Control:1.0')"; - - oaf_result = oaf_query (query, NULL, &ev); - - view_identifiers = NULL; - - if (ev._major == CORBA_NO_EXCEPTION && oaf_result != NULL) { - for (i = 0; i < oaf_result->_length; i++) { - id = nautilus_view_identifier_new_from_sidebar_panel - (&oaf_result->_buffer[i]); - view_identifiers = g_list_prepend (view_identifiers, id); - } - view_identifiers = g_list_reverse (view_identifiers); - } - - if (oaf_result != NULL) { - CORBA_free (oaf_result); - } - - CORBA_exception_free (&ev); - - view_identifiers = g_list_sort (view_identifiers, compare_view_identifiers); - - return view_identifiers; -} - -GList * -nautilus_sidebar_get_enabled_sidebar_panel_view_identifiers (void) -{ - GList *enabled_view_identifiers; - GList *disabled_view_identifiers; - - enabled_view_identifiers = sidebar_get_sidebar_panel_view_identifiers (); - - enabled_view_identifiers = eel_g_list_partition (enabled_view_identifiers, - sidebar_is_sidebar_panel_enabled_cover, - NULL, - &disabled_view_identifiers); - - nautilus_view_identifier_list_free (disabled_view_identifiers); - - return enabled_view_identifiers; -} - -void -nautilus_sidebar_for_each_panel (NautilusSidebarPanelCallback callback, - gpointer callback_data) -{ - char *preference_key; - GList *view_identifiers; - GList *node; - NautilusViewIdentifier *identifier; - - g_return_if_fail (callback != NULL); - - view_identifiers = sidebar_get_sidebar_panel_view_identifiers (); - - for (node = view_identifiers; node != NULL; node = node->next) { - g_assert (node->data != NULL); - identifier = node->data; - - preference_key = sidebar_panel_make_preference_key (identifier->iid); - - (* callback) (identifier->name, identifier->iid, preference_key, callback_data); - - g_free (preference_key); - } - - nautilus_view_identifier_list_free (view_identifiers); -} diff --git a/libnautilus-extensions/nautilus-sidebar-functions.h b/libnautilus-extensions/nautilus-sidebar-functions.h deleted file mode 100644 index 7f2fd89df..000000000 --- a/libnautilus-extensions/nautilus-sidebar-functions.h +++ /dev/null @@ -1,49 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ - -/* nautilus-sidebar-functions.h - Sidebar functions used throughout Nautilus. - - Copyright (C) 2001 Eazel, Inc. - - The Gnome 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 Gnome 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 the Gnome 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. - - Authors: Ramiro Estrugo <ramiro@eazel.com> -*/ - -#ifndef NAUTILUS_SIDEBAR_FUNCTIONS_H -#define NAUTILUS_SIDEBAR_FUNCTIONS_H - -#include <glib.h> - -extern const char nautilus_sidebar_news_enabled_preference_name[]; -extern const char nautilus_sidebar_notes_enabled_preference_name[]; -extern const char nautilus_sidebar_help_enabled_preference_name[]; -extern const char nautilus_sidebar_history_enabled_preference_name[]; -extern const char nautilus_sidebar_tree_enabled_preference_name[]; - -/* - * A callback which can be invoked for each sidebar panel available. - */ -typedef void (*NautilusSidebarPanelCallback) (const char *name, - const char *iid, - const char *preference_key, - gpointer callback_data); - -GList *nautilus_sidebar_get_enabled_sidebar_panel_view_identifiers (void); -void nautilus_sidebar_for_each_panel (NautilusSidebarPanelCallback callback, - gpointer callback_data); - -#endif /* NAUTILUS_SIDEBAR_FUNCTIONS_H */ - diff --git a/libnautilus-extensions/nautilus-sound.c b/libnautilus-extensions/nautilus-sound.c deleted file mode 100644 index 80535dfa8..000000000 --- a/libnautilus-extensions/nautilus-sound.c +++ /dev/null @@ -1,119 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- - - nautilus-sound.c: manage the sound playing process and other sound utilities - - Copyright (C) 1999, 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. - - Author: Andy Hertzfeld <andy@eazel.com> -*/ - -#include <config.h> -#include <stdlib.h> -#include <unistd.h> -#include <signal.h> -#ifdef HAVE_WAIT_H -# include <wait.h> -#else -# ifdef HAVE_SYS_WAIT_H -# include <sys/wait.h> -# endif -#endif -#include <esd.h> - -#include "nautilus-gconf-extensions.h" -#include "nautilus-sound.h" - -/* Keep track of the sound playing process */ -#define CURRENT_SOUND_STATE_KEY "/apps/nautilus/sound_state" - -static void -kill_sound_if_necessary (void) -{ - pid_t child; - int status_result; - pid_t sound_process; - - /* fetch the sound state */ - sound_process = nautilus_gconf_get_integer (CURRENT_SOUND_STATE_KEY); - - /* if there was a sound playing, kill it */ - if (sound_process > 0) { - kill (-sound_process, SIGTERM); - child = waitpid (sound_process, &status_result, 0); - } -} - -/* initialize_sound is called at application start up time. It puts the sound system - into a quiescent state */ -void -nautilus_sound_initialize (void) -{ - nautilus_gconf_set_integer (CURRENT_SOUND_STATE_KEY, 0); - nautilus_gconf_suggest_sync (); -} - -/* if there is a sound registered, kill it, and register the empty sound */ -void -nautilus_sound_kill_sound (void) -{ - /* if there is a sound in progress, kill it */ - kill_sound_if_necessary (); - - /* set the process state to quiescent */ - nautilus_gconf_set_integer (CURRENT_SOUND_STATE_KEY, 0); - nautilus_gconf_suggest_sync (); -} - -/* register a new sound process, including kill any old one if necessary */ -void -nautilus_sound_register_sound (pid_t sound_process) -{ - /* if there is a sound in progress, kill it */ - kill_sound_if_necessary (); - - /* record the new sound process ID */ - nautilus_gconf_set_integer (CURRENT_SOUND_STATE_KEY, sound_process); - nautilus_gconf_suggest_sync (); -} - -/* This function does two things. First it checks to see a sound is currently playing. If it is, - * it returns the process id of the external application playing the sound. If no sound is playing, - * it return the value set in nautilus_sound_initialize() when system audio output capabilites - * were queried. - */ -gboolean -nautilus_sound_can_play_sound (void) -{ - int sound_process, open_result; - - /* first see if there's already one in progress; if so, return true */ - sound_process = nautilus_gconf_get_integer (CURRENT_SOUND_STATE_KEY); - if (sound_process > 0) { - return TRUE; - } - - /* Now check and see if system has audio out capabilites */ - open_result = esd_open_sound (NULL); - if (open_result == -1) { - return FALSE; - } else { - esd_close (open_result); - return TRUE; - } -} - diff --git a/libnautilus-extensions/nautilus-sound.h b/libnautilus-extensions/nautilus-sound.h deleted file mode 100644 index 3083c32a9..000000000 --- a/libnautilus-extensions/nautilus-sound.h +++ /dev/null @@ -1,36 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- - - nautilus-sound.h: manage the sound playing process and other sound utilities - - 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_SOUND_H -#define NAUTILUS_SOUND_H - -#include <glib.h> -#include <sys/wait.h> - -void nautilus_sound_initialize (void); -gboolean nautilus_sound_can_play_sound (void); -void nautilus_sound_kill_sound (void); -void nautilus_sound_register_sound (pid_t sound_process); - -#endif /* NAUTILUS_SOUND_H */ diff --git a/libnautilus-extensions/nautilus-theme.c b/libnautilus-extensions/nautilus-theme.c deleted file mode 100644 index 8263cb4c2..000000000 --- a/libnautilus-extensions/nautilus-theme.c +++ /dev/null @@ -1,856 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- - - nautilus-theme.c: theme framework with xml-based theme definition files - - Copyright (C) 1999, 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. - - Author: Andy Hertzfeld <andy@eazel.com> -*/ - -#include <config.h> -#include "nautilus-theme.h" - -#include "nautilus-file-utilities.h" -#include "nautilus-file.h" -#include "nautilus-global-preferences.h" -#include "nautilus-metadata.h" -#include "nautilus-preferences.h" -#include <eel/eel-glib-extensions.h> -#include <eel/eel-gdk-pixbuf-extensions.h> -#include <eel/eel-string-list.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-util.h> -#include <libgnomevfs/gnome-vfs.h> -#include <librsvg/rsvg.h> -#include <libgnome/gnome-defs.h> -#include <libgnome/gnome-i18n.h> -#include <libgnome/gnome-util.h> - -/* static globals to hold the last accessed and default theme files */ -static char *last_theme_name = NULL; -static xmlDocPtr last_theme_document = NULL; -static xmlDocPtr default_theme_document = NULL; - -static char *theme_from_preferences = NULL; - -#define THEME_PREVIEW_ICON_WIDTH 70 -#define THEME_PREVIEW_ICON_HEIGHT 48 - -static void -theme_changed_callback (gpointer callback_data) -{ - g_free (theme_from_preferences); - theme_from_preferences = nautilus_preferences_get (NAUTILUS_PREFERENCES_THEME); -} - -/* return the current theme by asking the preferences machinery */ -char * -nautilus_theme_get_theme (void) -{ - static gboolean theme_changed_callback_installed = FALSE; - - /* Add the callback once for the life of our process */ - if (!theme_changed_callback_installed) { - nautilus_preferences_add_callback (NAUTILUS_PREFERENCES_THEME, - theme_changed_callback, - NULL); - theme_changed_callback_installed = TRUE; - - /* Peek for the first time */ - theme_changed_callback (NULL); - } - - return g_strdup (theme_from_preferences); -} - -/* set the current theme */ -void -nautilus_theme_set_theme (const char *new_theme) -{ - char *old_theme; - - old_theme = nautilus_theme_get_theme (); - if (eel_strcmp (old_theme, new_theme)) { - nautilus_preferences_set (NAUTILUS_PREFERENCES_THEME, new_theme); - } - g_free (old_theme); -} - -/* load and parse a theme file */ -static xmlDocPtr -load_theme_document (const char *theme_name) -{ - xmlDocPtr theme_document; - char *theme_path, *temp_str; - char *user_themes_directory; - - /* formulate the theme path name */ - if (eel_str_is_equal (theme_name, "default")) { - theme_path = nautilus_pixmap_file ("default.xml"); - } else { - temp_str = g_strdup_printf("%s/%s.xml", theme_name, theme_name); - theme_path = nautilus_pixmap_file (temp_str); - g_free(temp_str); - } - - /* if we can't find the theme document in the global area, try in the user's home */ - if (theme_path == NULL) { - user_themes_directory = nautilus_theme_get_user_themes_directory (); - temp_str = g_strdup_printf("%s/%s.xml", theme_name, theme_name); - theme_path = nautilus_make_path (user_themes_directory, temp_str); - - g_free (user_themes_directory); - g_free (temp_str); - - if (!g_file_exists (theme_path)) { - g_free (theme_path); - theme_path = NULL; - } - } - - /* if the file cannot be found, return NULL for no document */ - if (theme_path == NULL) { - return NULL; - } - - /* load and parse the theme file */ - theme_document = xmlParseFile (theme_path); - g_free (theme_path); - - return theme_document; -} - -static void -free_last_theme (void) -{ - if (last_theme_document != NULL) { - xmlFreeDoc (last_theme_document); - } - g_free (last_theme_name); -} - -static void -free_default_theme (void) -{ - xmlFreeDoc (default_theme_document); -} - -/* Fetch data from the specified theme. Cache the last theme file as a parsed xml document - */ -char * -nautilus_theme_get_theme_data_from_theme (const char *resource_name, const char *property_name, const char* theme_name) -{ - char *temp_str; - char *theme_data; - xmlDocPtr theme_document; - xmlNodePtr resource_node; - static gboolean did_set_up_free_last_theme = FALSE; - - /* fetch the current theme name */ - theme_data = NULL; - - if (eel_strcmp (theme_name, last_theme_name) == 0) { - theme_document = last_theme_document; - } else { - /* release the old saved data, since the theme changed */ - if (!did_set_up_free_last_theme) { - g_atexit (free_last_theme); - did_set_up_free_last_theme = TRUE; - } - free_last_theme (); - - last_theme_name = g_strdup (theme_name); - last_theme_document = load_theme_document (theme_name); - theme_document = last_theme_document; - } - - if (theme_document != NULL) { - /* fetch the resource node */ - resource_node = eel_xml_get_child_by_name (xmlDocGetRootElement (theme_document), resource_name); - if (resource_node) { - temp_str = xmlGetProp(resource_node, property_name); - if (temp_str) { - theme_data = g_strdup (temp_str); - xmlFree (temp_str); - } - } - } - - /* if we couldn't find anything in the current theme, try the default theme */ - if (theme_data == NULL) { - if (default_theme_document == NULL) { - default_theme_document = load_theme_document ("default"); - g_atexit (free_default_theme); - } - - resource_node = eel_xml_get_child_by_name (xmlDocGetRootElement (default_theme_document), resource_name); - if (resource_node) { - temp_str = xmlGetProp (resource_node, property_name); - if (temp_str) { - theme_data = g_strdup (temp_str); - xmlFree (temp_str); - } - } - - } - - return theme_data; -} - -/* Fetch data from the current theme. - */ -char * -nautilus_theme_get_theme_data (const char *resource_name, const char *property_name) -{ - char *result; - char *theme_name; - theme_name = nautilus_theme_get_theme (); - result = nautilus_theme_get_theme_data_from_theme (resource_name, property_name, theme_name); - g_free (theme_name); - return result; -} - -/* utility routine to return the full path to a themed image that - searches the local themes if it can't find it in the shared space */ -static char * -nautilus_pixmap_file_may_be_local (const char *themed_image) -{ - char *image_path, *user_themes_directory; - - image_path = nautilus_pixmap_file (themed_image); - if (image_path == NULL) { - user_themes_directory = nautilus_theme_get_user_themes_directory (); - - image_path = nautilus_make_path (user_themes_directory, themed_image); - if (!g_file_exists (image_path)) { - g_free (image_path); - image_path = NULL; - } - - g_free (user_themes_directory); - } - return image_path; -} - -/* given a theme, fetch the full path name of an image with the passed-in name */ -/* return NULL if there isn't a corresponding image. Optionally, add a .png suffix if we */ -/* cant otherwise find one. */ - -char * -nautilus_theme_get_image_path_from_theme (const char *image_name, const char* theme_name) -{ - char *image_path, *png_string, *temp_str; - - if (!eel_str_is_equal (theme_name, "default")) { - temp_str = g_strdup_printf ("%s/%s", theme_name, image_name); - image_path = nautilus_pixmap_file_may_be_local (temp_str); - - /* see if a theme-specific image exists; if so, return it */ - if (image_path) { - g_free (temp_str); - return image_path; - } - - /* try if with a .png extension if it doesn't already have one */ - if (!eel_istr_has_suffix (image_name, ".png")) { - png_string = g_strconcat (temp_str, ".png", NULL); - image_path = nautilus_pixmap_file_may_be_local (png_string); - g_free (png_string); - - if (image_path) { - g_free (temp_str); - return image_path; - } - } - g_free (temp_str); - } - - /* we couldn't find a theme specific one, so look for a general image */ - image_path = nautilus_pixmap_file (image_name); - - if (image_path) { - return image_path; - } - - /* if it doesn't have a .png extension, try it with that */ - if (!eel_istr_has_suffix (image_name, ".png")) { - png_string = g_strconcat (image_name, ".png", NULL); - image_path = nautilus_pixmap_file (png_string); - g_free (png_string); - - if (image_path) { - return image_path; - } - } - - /* we couldn't find anything, so return NULL */ - g_free (image_path); - return NULL; -} - -/* commonly used cover to get_image_path_from_theme to return an image path using the current theme */ -char * -nautilus_theme_get_image_path (const char *image_name) -{ - char *theme_name, *image_path; - - theme_name = nautilus_theme_get_theme (); - image_path = nautilus_theme_get_image_path_from_theme (image_name, theme_name); - g_free (theme_name); - - return image_path; -} - -/* create a pixbuf that represents the passed in theme name */ -GdkPixbuf * -nautilus_theme_make_preview_pixbuf (const char *theme_name) -{ - char *pixbuf_file, *theme_preview_name; - char *user_themes_directory; - GdkPixbuf *pixbuf; - - /* first, see if we can find an explicit preview */ - - /* FIXME: This special handling for "default" is a little weird */ - if (eel_str_is_equal (theme_name, "default")) { - theme_preview_name = g_strdup ("theme_preview.png"); - } else { - theme_preview_name = g_strdup_printf ("%s/%s", theme_name, "theme_preview.png"); - } - - pixbuf_file = nautilus_pixmap_file (theme_preview_name); - if (pixbuf_file != NULL) { - pixbuf = gdk_pixbuf_new_from_file (pixbuf_file); - g_free (pixbuf_file); - return pixbuf; - } else { - /* try the user directory */ - user_themes_directory = nautilus_theme_get_user_themes_directory (); - pixbuf_file = nautilus_make_path (user_themes_directory, theme_preview_name); - g_free (user_themes_directory); - - if (g_file_exists (pixbuf_file)) { - pixbuf = gdk_pixbuf_new_from_file (pixbuf_file); - g_free (pixbuf_file); - return pixbuf; - } else { - g_free (pixbuf_file); - } - } - - /* couldn't find a custom one, so try for a directory */ - g_free (theme_preview_name); - theme_preview_name = g_strdup_printf ("%s/%s", theme_name, "i-directory.png"); - pixbuf_file = nautilus_pixmap_file (theme_preview_name); - g_free (theme_preview_name); - - if (pixbuf_file == NULL) { - theme_preview_name = g_strdup_printf ("%s/%s", theme_name, "i-directory.svg"); - pixbuf_file = nautilus_pixmap_file (theme_preview_name); - g_free (theme_preview_name); - } - - /* try the user directory if necessary */ - if (pixbuf_file == NULL) { - user_themes_directory = nautilus_theme_get_user_themes_directory (); - theme_preview_name = g_strdup_printf ("%s/i-directory.png", theme_name); - pixbuf_file = nautilus_make_path (user_themes_directory, theme_preview_name); - g_free (theme_preview_name); - - if (!g_file_exists (pixbuf_file)) { - g_free (pixbuf_file); - theme_preview_name = g_strdup_printf ("%s/i-directory.svg", theme_name); - pixbuf_file = nautilus_make_path (user_themes_directory, theme_preview_name); - g_free (theme_preview_name); - - if (!g_file_exists (pixbuf_file)) { - g_free (pixbuf_file); - pixbuf_file = NULL; - } - } - - g_free (user_themes_directory); - } - - /* if we can't find anything, return NULL */ - if (pixbuf_file == NULL) { - return NULL; - } - - pixbuf = NULL; - - /* load the icon that we found and return it */ - if (eel_istr_has_suffix (pixbuf_file, ".svg")) { - FILE *f = fopen (pixbuf_file, "rb"); - if (f != NULL) { - pixbuf = rsvg_render_file (f, 1.0); - fclose (f); - } - - } else { - pixbuf = gdk_pixbuf_new_from_file (pixbuf_file); - } - - g_free (pixbuf_file); - return pixbuf; -} - -typedef struct -{ - char *name; - char *path; - char *display_name; - char *description; - GdkPixbuf *preview_pixbuf; - gboolean builtin; -} ThemeAttibutes; - -/* Test for the presence of an icon file */ -static gboolean -vfs_file_exists (const char *file_uri) -{ - GnomeVFSResult result; - GnomeVFSFileInfo *file_info; - - file_info = gnome_vfs_file_info_new (); - result = gnome_vfs_get_file_info (file_uri, file_info, 0); - gnome_vfs_file_info_unref (file_info); - - return result == GNOME_VFS_OK; -} - -static gboolean -has_image_file (const char *path_uri, - const char *dir_name, - const char *image_file) -{ - char* image_uri; - gboolean exists; - - /* FIXME: This special handling for "default" is a little weird */ - if (eel_str_is_equal (dir_name, "default")) { - image_uri = g_strdup_printf ("%s/%s.png", path_uri, image_file); - } else { - image_uri = g_strdup_printf ("%s/%s/%s.png", path_uri, dir_name, image_file); - } - exists = vfs_file_exists (image_uri); - g_free (image_uri); - - if (exists) { - return TRUE; - } - - /* FIXME: This special handling for "default" is a little weird */ - if (eel_str_is_equal (dir_name, "default")) { - image_uri = g_strdup_printf ("%s/%s.svg", path_uri, image_file); - } else { - image_uri = g_strdup_printf ("%s/%s/%s.svg", path_uri, dir_name, image_file); - } - - exists = vfs_file_exists (image_uri); - g_free (image_uri); - - return exists; -} - -static char* -theme_get_property (const char *themes_location_uri, - const char *theme_name, - const char *property) -{ - char *theme_file_uri; - char *theme_file_name; - xmlDocPtr theme_document; - xmlChar *xml_result; - char *result; - - g_return_val_if_fail (themes_location_uri != NULL, NULL); - g_return_val_if_fail (theme_name != NULL, NULL); - g_return_val_if_fail (property != NULL, NULL); - - xml_result = NULL; - result = NULL; - - /* FIXME: This special handling for "default" is a little weird */ - if (eel_str_is_equal (theme_name, "default")) { - theme_file_uri = g_strdup_printf ("%s/%s.xml", - themes_location_uri, - theme_name); - } else { - theme_file_uri = g_strdup_printf ("%s/%s/%s.xml", - themes_location_uri, - theme_name, - theme_name); - } - - theme_file_name = gnome_vfs_get_local_path_from_uri (theme_file_uri); - g_free (theme_file_uri); - - g_return_val_if_fail (g_file_exists (theme_file_name), NULL); - - /* read the xml document */ - theme_document = xmlParseFile (theme_file_name); - g_free (theme_file_name); - g_return_val_if_fail (theme_document != NULL, NULL); - - /* fetch the property, if any */ - xml_result = eel_xml_get_property_translated (xmlDocGetRootElement (theme_document), - property); - xmlFreeDoc (theme_document); - - /* Convert the xml char* to a regular char* to get allocators matched */ - if (xml_result != NULL) { - result = g_strdup (xml_result); - xmlFree (xml_result); - } - - return result; -} - -static char* -theme_get_name_property (const char *themes_location_uri, - const char *theme_name) -{ - char *name; - - g_return_val_if_fail (theme_name != NULL, NULL); - g_return_val_if_fail (themes_location_uri != NULL, NULL); - - name = theme_get_property (themes_location_uri, theme_name, "name"); - - if (name == NULL) { - name = g_strdup (theme_name); - } - - return name; -} - -static char* -theme_get_description_property (const char *themes_location_uri, - const char *theme_name) -{ - char *description; - - g_return_val_if_fail (themes_location_uri != NULL, NULL); - g_return_val_if_fail (theme_name != NULL, NULL); - - description = theme_get_property (themes_location_uri, theme_name, "description"); - - if (description == NULL) { - description = g_strdup_printf (_("No description available for the \"%s\" theme"), theme_name); - } - - return description; -} - -static GList * -theme_list_insert (GList *theme_list, - const char *themes_location_uri, - const char *theme_name, - gboolean builtin) -{ - ThemeAttibutes *attributes; - GdkPixbuf *unscaled_preview_pixbuf; - - g_return_val_if_fail (theme_name != NULL, NULL); - g_return_val_if_fail (themes_location_uri != NULL, NULL); - - attributes = g_new0 (ThemeAttibutes, 1); - attributes->name = g_strdup (theme_name); - attributes->path = nautilus_make_path (themes_location_uri, theme_name); - - unscaled_preview_pixbuf = nautilus_theme_make_preview_pixbuf (theme_name); - attributes->preview_pixbuf = eel_gdk_pixbuf_scale_down_to_fit (unscaled_preview_pixbuf, - THEME_PREVIEW_ICON_WIDTH, - THEME_PREVIEW_ICON_HEIGHT); - gdk_pixbuf_unref (unscaled_preview_pixbuf); - - attributes->builtin = builtin; - - attributes->display_name = theme_get_name_property (themes_location_uri, theme_name); - attributes->description = theme_get_description_property (themes_location_uri, theme_name); - - return g_list_append (theme_list, attributes); -} - -static GList * -theme_get_themes_for_location (const char *themes_location_uri, - gboolean builtin) -{ - GnomeVFSResult result; - GnomeVFSFileInfo *file_info; - GList *possible_theme_directories; - GList *node; - GList *themes; - - g_return_val_if_fail (themes_location_uri != NULL, NULL); - - possible_theme_directories = NULL; - result = gnome_vfs_directory_list_load (&possible_theme_directories, - themes_location_uri, - GNOME_VFS_FILE_INFO_FOLLOW_LINKS, - NULL); - - if (result != GNOME_VFS_OK) { - return NULL; - } - - themes = NULL; - for (node = possible_theme_directories; node != NULL; node = node->next) { - g_assert (node->data != NULL); - - file_info = node->data; - - if ((file_info->type == GNOME_VFS_FILE_TYPE_DIRECTORY) - && (file_info->name[0] != '.')) { - if (has_image_file (themes_location_uri, file_info->name, "i-directory" )) { - themes = theme_list_insert (themes, - themes_location_uri, - file_info->name, - builtin); - } - } - } - - return themes; -} - -static GList * -theme_get_builtin_themes (void) -{ - char *pixmap_directory; - char *builtin_themes_location_uri; - GList *builtin_themes; - - pixmap_directory = nautilus_get_pixmap_directory (); - builtin_themes_location_uri = gnome_vfs_get_uri_from_local_path (pixmap_directory); - builtin_themes = theme_get_themes_for_location (builtin_themes_location_uri, TRUE); - g_free (pixmap_directory); - g_free (builtin_themes_location_uri); - - return builtin_themes; -} - -static GList * -theme_get_user_themes (void) -{ - char *user_themes_location; - char *user_themes_location_uri; - GList *user_themes; - - user_themes_location = nautilus_theme_get_user_themes_directory (); - user_themes_location_uri = gnome_vfs_get_uri_from_local_path (user_themes_location); - user_themes = theme_get_themes_for_location (user_themes_location_uri, FALSE); - g_free (user_themes_location); - g_free (user_themes_location_uri); - - return user_themes; -} - -/* Even though there is just one default theme, we use the theme - * attribute list machinery for simplicity */ -static GList * -theme_get_default_themes (void) -{ - char *pixmap_directory; - char *pixmap_directory_uri; - GList *default_themes; - - default_themes = NULL; - pixmap_directory = nautilus_get_pixmap_directory (); - pixmap_directory_uri = gnome_vfs_get_uri_from_local_path (pixmap_directory); - default_themes = theme_list_insert (default_themes, pixmap_directory_uri, "default", TRUE); - g_free (pixmap_directory_uri); - g_free (pixmap_directory); - - return default_themes; -} - -static void -theme_list_invoke_callback (GList *theme_list, - NautilusThemeCallback callback, - gpointer callback_data) -{ - GList *node; - const ThemeAttibutes *attributes; - - g_return_if_fail (callback != NULL); - - for (node = theme_list; node != NULL; node = node->next) { - g_assert (node->data != NULL); - attributes = node->data; - - g_assert (attributes->name != NULL); - g_assert (attributes->path != NULL); - g_assert (attributes->display_name != NULL); - g_assert (attributes->description != NULL); - g_assert (attributes->preview_pixbuf != NULL); - - (* callback) (attributes->name, - attributes->path, - attributes->display_name, - attributes->description, - attributes->preview_pixbuf, - attributes->builtin, - callback_data); - } -} - -static void -attributes_free (gpointer data, - gpointer user_data) -{ - ThemeAttibutes *attributes; - - g_return_if_fail (data != NULL); - - attributes = data; - - g_free (attributes->name); - g_free (attributes->path); - g_free (attributes->display_name); - g_free (attributes->description); - if (attributes->preview_pixbuf != NULL) { - gdk_pixbuf_unref (attributes->preview_pixbuf); - } -} - -void -nautilus_theme_for_each_theme (NautilusThemeCallback callback, - gpointer callback_data) -{ - GList *builtin_themes; - GList *user_themes; - GList *default_themes; - - g_return_if_fail (callback != NULL); - - builtin_themes = theme_get_builtin_themes (); - user_themes = theme_get_user_themes (); - default_themes = theme_get_default_themes (); - - theme_list_invoke_callback (default_themes, callback, callback_data); - theme_list_invoke_callback (builtin_themes, callback, callback_data); - theme_list_invoke_callback (user_themes, callback, callback_data); - - eel_g_list_free_deep_custom (default_themes, attributes_free, NULL); - eel_g_list_free_deep_custom (builtin_themes, attributes_free, NULL); - eel_g_list_free_deep_custom (user_themes, attributes_free, NULL); -} - -char * -nautilus_theme_get_user_themes_directory (void) -{ - char *user_directory; - char *user_themes_directory; - - user_directory = nautilus_get_user_directory (); - user_themes_directory = nautilus_make_path (user_directory, "themes"); - g_free (user_directory); - - return user_themes_directory; -} - -/* Remove the given theme name from from Nautilus. */ -GnomeVFSResult -nautilus_theme_remove_user_theme (const char *theme_to_remove_name) -{ - char *user_themes_directory; - char *theme_to_remove_path; - GnomeVFSResult result; - GList *uri_list; - - g_return_val_if_fail (theme_to_remove_name != NULL, GNOME_VFS_ERROR_BAD_PARAMETERS); - - user_themes_directory = nautilus_theme_get_user_themes_directory (); - theme_to_remove_path = nautilus_make_path (user_themes_directory, theme_to_remove_name); - g_free (user_themes_directory); - - uri_list = g_list_append (NULL, gnome_vfs_uri_new (theme_to_remove_path)); - g_free (theme_to_remove_path); - - result = gnome_vfs_xfer_delete_list (uri_list, GNOME_VFS_XFER_RECURSIVE, - GNOME_VFS_XFER_ERROR_MODE_ABORT, - NULL, NULL); - gnome_vfs_uri_list_free (uri_list); - - return result; -} - -/* Install the theme found at the given path (if valid). */ -NautilusThemeInstallResult -nautilus_theme_install_user_theme (const char *theme_to_install_path) -{ - GnomeVFSResult result; - char *theme_name; - char *theme_xml_path; - char *user_themes_directory; - char *theme_destination_path; - - if (theme_to_install_path == NULL - || !g_file_test (theme_to_install_path, G_FILE_TEST_EXISTS | G_FILE_TEST_ISDIR)) { - return NAUTILUS_THEME_INSTALL_NOT_A_THEME_DIRECTORY; - } - - theme_name = eel_uri_get_basename (theme_to_install_path); - g_return_val_if_fail (theme_name != NULL, GNOME_VFS_ERROR_BAD_PARAMETERS); - - theme_xml_path = g_strdup_printf ("%s/%s.xml", - theme_to_install_path, - theme_name); - - if (!g_file_exists (theme_xml_path)) { - g_free (theme_name); - return NAUTILUS_THEME_INSTALL_NOT_A_THEME_DIRECTORY; - } - g_free (theme_xml_path); - - user_themes_directory = nautilus_theme_get_user_themes_directory (); - - /* Create the user themes directory if it doesn't exist */ - if (!g_file_exists (user_themes_directory)) { - result = gnome_vfs_make_directory (user_themes_directory, - GNOME_VFS_PERM_USER_ALL - | GNOME_VFS_PERM_GROUP_ALL - | GNOME_VFS_PERM_OTHER_READ); - - if (result != GNOME_VFS_OK) { - g_free (user_themes_directory); - g_free (theme_name); - return NAUTILUS_THEME_INSTALL_FAILED_USER_THEMES_DIRECTORY_CREATION; - } - } - - theme_destination_path = nautilus_make_path (user_themes_directory, theme_name); - g_free (user_themes_directory); - g_free (theme_name); - - result = eel_copy_uri_simple (theme_to_install_path, theme_destination_path); - if (result != GNOME_VFS_OK) { - g_free (theme_destination_path); - return NAUTILUS_THEME_INSTALL_FAILED; - } - - g_free (theme_destination_path); - - return NAUTILUS_THEME_INSTALL_OK; -} diff --git a/libnautilus-extensions/nautilus-theme.h b/libnautilus-extensions/nautilus-theme.h deleted file mode 100644 index 4a834bf9f..000000000 --- a/libnautilus-extensions/nautilus-theme.h +++ /dev/null @@ -1,95 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- - - nautilus-theme.h: theme framework with xml-based theme definition files - - 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_THEME_H -#define NAUTILUS_THEME_H - - -#include <glib.h> -#include <gdk-pixbuf/gdk-pixbuf.h> -#include <libgnomevfs/gnome-vfs-types.h> - -/* A callback which can be invoked for each available theme. */ -typedef void (*NautilusThemeCallback) (const char *name, - const char *path, - const char *display_name, - const char *description, - GdkPixbuf *preview_pixbuf, - gboolean builtin, - gpointer callback_data); - -/* The result of a theme install operation. */ -typedef enum -{ - /* Theme installed OK */ - NAUTILUS_THEME_INSTALL_OK, - - /* The given path is not a vaild theme directory */ - NAUTILUS_THEME_INSTALL_NOT_A_THEME_DIRECTORY, - - /* Failed to create the user themes directory ~/.nautilus/themes */ - NAUTILUS_THEME_INSTALL_FAILED_USER_THEMES_DIRECTORY_CREATION, - - /* Failed to install the theme */ - NAUTILUS_THEME_INSTALL_FAILED -} NautilusThemeInstallResult; - -/* get and set the current theme */ -char *nautilus_theme_get_theme (void); -void nautilus_theme_set_theme (const char *new_theme); - - -/* fetch data from the current theme */ -char *nautilus_theme_get_theme_data (const char *resource_name, - const char *property_name); - -/* fetch data from the specified theme */ -char *nautilus_theme_get_theme_data_from_theme (const char *resource_name, - const char *property_name, - const char *theme_name); - -/* given the current theme, get the path name of an image with the passed-in name */ -char *nautilus_theme_get_image_path (const char *image_name); - -/* like get_image_path, put use the passed in theme instead of the current one */ -char *nautilus_theme_get_image_path_from_theme (const char *image_name, - const char *theme_name); - -/* create a pixbuf to represent the theme */ -GdkPixbuf *nautilus_theme_make_preview_pixbuf (const char *theme_name); - -/* Return the directory where user themes are stored */ -char *nautilus_theme_get_user_themes_directory (void); - -/* Invoke the given callback for each theme available to Nautilus */ -void nautilus_theme_for_each_theme (NautilusThemeCallback callback, - gpointer callback_data); - -/* Remove a user theme from Nautilus. */ -GnomeVFSResult nautilus_theme_remove_user_theme (const char *theme_to_remove_name); - -/* Install the theme found at the given path (if valid). */ -NautilusThemeInstallResult nautilus_theme_install_user_theme (const char *theme_to_install_path); - -#endif /* NAUTILUS_THEME_H */ diff --git a/libnautilus-extensions/nautilus-thumbnails-jpeg.c b/libnautilus-extensions/nautilus-thumbnails-jpeg.c deleted file mode 100644 index d4f1bf11b..000000000 --- a/libnautilus-extensions/nautilus-thumbnails-jpeg.c +++ /dev/null @@ -1,262 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- - - nautilus-thumbnails-jpeg.c: Fast loading of scaled jpeg images - - 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. - - Author: Alexander Larsson <alexl@redhat.com> -*/ - -#include <config.h> - -#ifdef HAVE_LIBJPEG - -#include "nautilus-thumbnails-jpeg.h" - -#include <eel/eel-glib-extensions.h> -#include <setjmp.h> - -#include <stdio.h> -#include <jpeglib.h> - -#include <libgnomevfs/gnome-vfs-types.h> -#include <libgnomevfs/gnome-vfs-ops.h> -#include <libgnomevfs/gnome-vfs-utils.h> - -#define BUFFER_SIZE 4096 - -typedef struct { - struct jpeg_source_mgr pub; /* public fields */ - GnomeVFSHandle *handle; - JOCTET buffer[BUFFER_SIZE]; -} Source; - -typedef struct { - struct jpeg_error_mgr pub; - jmp_buf setjmp_buffer; -} ErrorHandlerData; - -static void -fatal_error_handler (j_common_ptr cinfo) -{ - ErrorHandlerData *data; - - data = (ErrorHandlerData *) cinfo->err; - longjmp (data->setjmp_buffer, 1); -} - -static void -output_message_handler (j_common_ptr cinfo) -{ - /* If we don't supply this handler, libjpeg reports errors - * directly to stderr. - */ -} - -static void -init_source (j_decompress_ptr cinfo) -{ -} - -static gboolean -fill_input_buffer (j_decompress_ptr cinfo) -{ - Source *src; - GnomeVFSFileSize nbytes; - GnomeVFSResult result; - - src = (Source *) cinfo->src; - result = gnome_vfs_read (src->handle, - src->buffer, - EEL_N_ELEMENTS (src->buffer), - &nbytes); - - if (result != GNOME_VFS_OK || nbytes == 0) { - /* return a fake EOI marker so we will eventually terminate */ - src->buffer[0] = (JOCTET) 0xFF; - src->buffer[1] = (JOCTET) JPEG_EOI; - nbytes = 2; - } - - src->pub.next_input_byte = src->buffer; - src->pub.bytes_in_buffer = nbytes; - - return TRUE; -} - -static void -skip_input_data (j_decompress_ptr cinfo, long num_bytes) -{ - Source *src; - - src = (Source *) cinfo->src; - if (num_bytes > 0) { - while (num_bytes > (long) src->pub.bytes_in_buffer) { - num_bytes -= (long) src->pub.bytes_in_buffer; - fill_input_buffer (cinfo); - } - src->pub.next_input_byte += (size_t) num_bytes; - src->pub.bytes_in_buffer -= (size_t) num_bytes; - } -} - -static void -term_source (j_decompress_ptr cinfo) -{ -} - -static void -vfs_src (j_decompress_ptr cinfo, GnomeVFSHandle *handle) -{ - Source *src; - - if (cinfo->src == NULL) { /* first time for this JPEG object? */ - cinfo->src = &(g_new (Source, 1))->pub; - } - - src = (Source *) cinfo->src; - src->pub.init_source = init_source; - src->pub.fill_input_buffer = fill_input_buffer; - src->pub.skip_input_data = skip_input_data; - src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */ - src->pub.term_source = term_source; - src->handle = handle; - src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */ - src->pub.next_input_byte = NULL; /* until buffer loaded */ -} - -static int -calculate_divisor (int width, - int height, - int target_width, - int target_height) -{ - if (width/8 > target_width && height/8 > target_height) { - return 8; - } - if (width/4 > target_width && height/4 > target_height) { - return 4; - } - if (width/2 > target_width && height/2 > target_height) { - return 2; - } - return 1; -} - -static void -free_buffer (guchar *pixels, gpointer data) -{ - g_free (pixels); -} - -GdkPixbuf * -nautilus_thumbnail_load_scaled_jpeg (const char *uri, - int target_width, - int target_height) -{ - struct jpeg_decompress_struct cinfo; - ErrorHandlerData jerr; - GnomeVFSHandle *handle; - unsigned char *lines[1]; - guchar * volatile buffer; - guchar * volatile pixels; - guchar *ptr; - GnomeVFSResult result; - unsigned int i; - - result = gnome_vfs_open (&handle, - uri, - GNOME_VFS_OPEN_READ); - if (result != GNOME_VFS_OK) { - return NULL; - } - - cinfo.err = jpeg_std_error (&jerr.pub); - jerr.pub.error_exit = fatal_error_handler; - jerr.pub.output_message = output_message_handler; - - buffer = NULL; - pixels = NULL; - if (setjmp (jerr.setjmp_buffer)) { - /* Handle a JPEG error. */ - jpeg_destroy_decompress (&cinfo); - gnome_vfs_close (handle); - g_free (buffer); - g_free (pixels); - return NULL; - } - - jpeg_create_decompress (&cinfo); - - vfs_src (&cinfo, handle); - - jpeg_read_header (&cinfo, TRUE); - - cinfo.scale_num = 1; - cinfo.scale_denom = calculate_divisor (cinfo.image_width, - cinfo.image_height, - target_width, - target_height); - cinfo.dct_method = JDCT_FASTEST; - cinfo.do_fancy_upsampling = FALSE; - - jpeg_start_decompress (&cinfo); - - pixels = g_malloc (cinfo.output_width * cinfo.output_height * 3); - - ptr = pixels; - if (cinfo.num_components == 1) { - /* Allocate extra buffer for grayscale data */ - buffer = g_malloc (cinfo.output_width); - lines[0] = buffer; - } else { - lines[0] = pixels; - } - - while (cinfo.output_scanline < cinfo.output_height) { - jpeg_read_scanlines (&cinfo, lines, 1); - - if (cinfo.num_components == 1) { - /* Convert grayscale to rgb */ - for (i = 0; i < cinfo.output_width; i++) { - ptr[i*3] = buffer[i]; - ptr[i*3+1] = buffer[i]; - ptr[i*3+2] = buffer[i]; - } - ptr += cinfo.output_width * 3; - } else { - lines[0] += cinfo.output_width * 3; - } - } - - g_free (buffer); - buffer = NULL; - - jpeg_finish_decompress (&cinfo); - jpeg_destroy_decompress (&cinfo); - - gnome_vfs_close (handle); - - return gdk_pixbuf_new_from_data (pixels, GDK_COLORSPACE_RGB, FALSE, 8, - cinfo.output_width, - cinfo.output_height, - cinfo.output_width * 3, - free_buffer, NULL); -} - -#endif /* HAVE_LIBJPEG */ diff --git a/libnautilus-extensions/nautilus-thumbnails-jpeg.h b/libnautilus-extensions/nautilus-thumbnails-jpeg.h deleted file mode 100644 index a298b43e4..000000000 --- a/libnautilus-extensions/nautilus-thumbnails-jpeg.h +++ /dev/null @@ -1,34 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- - - nautilus-thumbnails-jpeg.h: Fast loading of scaled jpeg images - - 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. - - Author: Alexander Larsson <alexl@redhat.com> -*/ - -#ifndef NAUTILUS_THUMBNAILS_JPEG_H -#define NAUTILUS_THUMBNAILS_JPEG_H - -#include <gdk-pixbuf/gdk-pixbuf.h> - -GdkPixbuf *nautilus_thumbnail_load_scaled_jpeg (const char *uri, - int target_width, - int target_heigh); - -#endif /* NAUTILUS_THUMBNAILS_JPEG_H */ diff --git a/libnautilus-extensions/nautilus-thumbnails.c b/libnautilus-extensions/nautilus-thumbnails.c deleted file mode 100644 index 7ef9e44c1..000000000 --- a/libnautilus-extensions/nautilus-thumbnails.c +++ /dev/null @@ -1,674 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- - - nautilus-thumbnails.h: Thumbnail code for icon factory. - - Copyright (C) 2000, 2001 Eazel, Inc. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public - License along with this program; if not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. - - Author: Andy Hertzfeld <andy@eazel.com> -*/ - -#include <config.h> -#include "nautilus-thumbnails.h" - -#include "nautilus-directory-notify.h" -#include "nautilus-icon-factory-private.h" -#include "nautilus-theme.h" -#include "nautilus-thumbnails-jpeg.h" -#include <eel/eel-gdk-pixbuf-extensions.h> -#include <eel/eel-graphic-effects.h> -#include <eel/eel-string.h> -#include <eel/eel-vfs-extensions.h> -#include <gtk/gtkmain.h> -#include <libgnomevfs/gnome-vfs-file-info.h> -#include <librsvg/rsvg.h> -#include <stdio.h> -#include <string.h> -#include <sys/wait.h> -#include <unistd.h> - -/* permissions for thumbnail directory */ -#define THUMBNAIL_DIR_PERMISSIONS (GNOME_VFS_PERM_USER_ALL \ - | GNOME_VFS_PERM_GROUP_ALL \ - | GNOME_VFS_PERM_OTHER_ALL) - -#define THUMBNAIL_PLACEHOLDER_PERMISSIONS (GNOME_VFS_PERM_USER_READ | \ - GNOME_VFS_PERM_USER_WRITE | \ - GNOME_VFS_PERM_GROUP_READ | \ - GNOME_VFS_PERM_GROUP_WRITE | \ - GNOME_VFS_PERM_OTHER_READ) -/* thumbnail task state */ -static GList *thumbnails; -static char *new_thumbnail_uri; -static gboolean thumbnail_in_progress; - -/* id of timeout task for making thumbnails */ -static int thumbnail_timeout_id; - -static int make_thumbnails (gpointer data); - -/* utility to test whether a file exists using vfs */ -static gboolean -vfs_file_exists (const char *file_uri) -{ - gboolean result; - GnomeVFSURI *uri; - - uri = gnome_vfs_uri_new (file_uri); - if (uri == NULL) { - return FALSE; - } - - /* FIXME bugzilla.eazel.com 3137: The synchronous I/O here - * means this call is unsuitable for use on anything that - * might be remote. - */ - result = gnome_vfs_uri_exists (uri); - gnome_vfs_uri_unref (uri); - - return result; -} - -/* utility routine that, given the uri of an image, constructs the uri to the corresponding thumbnail */ - -static char * -make_thumbnail_uri (const char *image_uri, gboolean directory_only, gboolean use_local_directory, - gboolean anti_aliased, gboolean create_parents_if_needed) -{ - GnomeVFSURI *vfs_uri; - char *thumbnail_uri, *thumbnail_path; - char *directory_name = g_strdup (image_uri); - char *last_slash = strrchr (directory_name, '/'); - char *dot_pos, *slash_pos; - gboolean is_local; - - *last_slash = '\0'; - - vfs_uri = gnome_vfs_uri_new (image_uri); - is_local = gnome_vfs_uri_is_local (vfs_uri); - gnome_vfs_uri_unref (vfs_uri); - - /* either use the local directory or one in the user's home directory, as selected by the passed in flag */ - if (use_local_directory && is_local) { - thumbnail_uri = g_strdup_printf ("%s/.thumbnails", directory_name); - } else { - GnomeVFSResult result; - GnomeVFSURI *thumbnail_directory_uri; - - char *escaped_uri = gnome_vfs_escape_slashes (directory_name); - thumbnail_path = g_strdup_printf ("%s/.nautilus/thumbnails/%s", g_get_home_dir(), escaped_uri); - thumbnail_uri = gnome_vfs_get_uri_from_local_path (thumbnail_path); - g_free (thumbnail_path); - g_free(escaped_uri); - - /* we must create the directory if it doesn't exist */ - - thumbnail_directory_uri = gnome_vfs_uri_new (thumbnail_uri); - - if (!create_parents_if_needed) { - if (!gnome_vfs_uri_exists (thumbnail_directory_uri)) { - gnome_vfs_uri_unref (thumbnail_directory_uri); - return NULL; - } - } - /* FIXME bugzilla.eazel.com 3137: synchronous I/O - it - looks like the URI will be local-only, but best to - make sure. */ - - result = eel_make_directory_and_parents (thumbnail_directory_uri, THUMBNAIL_DIR_PERMISSIONS); - gnome_vfs_uri_unref (thumbnail_directory_uri); - } - - /* append the file name if necessary */ - if (!directory_only) { - char* old_uri = thumbnail_uri; - thumbnail_uri = g_strdup_printf ("%s/%s", thumbnail_uri, last_slash + 1); - g_free(old_uri); - - /* append the anti-aliased suffix if necessary */ - if (anti_aliased) { - char *old_uri = thumbnail_uri; - dot_pos = strrchr (thumbnail_uri, '.'); - slash_pos = strrchr (thumbnail_uri, '/'); - if (dot_pos && dot_pos > slash_pos) { - *dot_pos = '\0'; - thumbnail_uri = g_strdup_printf ("%s.aa.%s", old_uri, dot_pos + 1); - } else { - thumbnail_uri = g_strconcat (old_uri, ".aa", NULL); - } - g_free (old_uri); - } - - /* append an image suffix if the correct one isn't already present */ - if (!eel_istr_has_suffix (image_uri, ".png")) { - char *old_uri = thumbnail_uri; - thumbnail_uri = g_strdup_printf ("%s.png", thumbnail_uri); - g_free(old_uri); - } - } - - g_free (directory_name); - return thumbnail_uri; -} - -/* utility routine that takes two uris and returns true if the first file has been modified later than the second */ -/* FIXME bugzilla.eazel.com 2565: it makes synchronous file info calls, so for now, it returns FALSE if either of the uri's are non-local */ -static gboolean -first_file_more_recent(const char* file_uri, const char* other_file_uri) -{ - GnomeVFSURI *vfs_uri, *other_vfs_uri; - gboolean more_recent, is_local; - - GnomeVFSFileInfo *file_info, *other_file_info; - - /* if either file is remote, return FALSE. Eventually we'll make this async to fix this */ - vfs_uri = gnome_vfs_uri_new(file_uri); - other_vfs_uri = gnome_vfs_uri_new(other_file_uri); - is_local = gnome_vfs_uri_is_local (vfs_uri) && gnome_vfs_uri_is_local (other_vfs_uri); - gnome_vfs_uri_unref(vfs_uri); - gnome_vfs_uri_unref(other_vfs_uri); - - if (!is_local) { - return FALSE; - } - - /* gather the info and then compare modification times */ - file_info = gnome_vfs_file_info_new (); - gnome_vfs_get_file_info (file_uri, file_info, GNOME_VFS_FILE_INFO_DEFAULT); - - other_file_info = gnome_vfs_file_info_new (); - gnome_vfs_get_file_info (other_file_uri, other_file_info, GNOME_VFS_FILE_INFO_DEFAULT); - - more_recent = file_info->mtime > other_file_info->mtime; - - gnome_vfs_file_info_unref (file_info); - gnome_vfs_file_info_unref (other_file_info); - - return more_recent; -} - -/* structure used for making thumbnails, associating a uri with where the thumbnail is to be stored */ - -typedef struct { - char *thumbnail_uri; - gboolean is_local; - gboolean anti_aliased; - pid_t thumbnail_task; -} NautilusThumbnailInfo; - -/* GCompareFunc-style function for comparing NautilusThumbnailInfos. - * Returns 0 if they refer to the same uri. - */ -static int -compare_thumbnail_info (gconstpointer a, gconstpointer b) -{ - NautilusThumbnailInfo *info_a; - NautilusThumbnailInfo *info_b; - - info_a = (NautilusThumbnailInfo *)a; - info_b = (NautilusThumbnailInfo *)b; - - return strcmp (info_a->thumbnail_uri, info_b->thumbnail_uri) != 0; -} - -/* utility to create a placeholder thumbnail uri (which indicates that a - * previous thumbnailing attempt has failed) - */ -/* FIXME: A .x extension might exist on a real file, and we might - * recognize it by magic number even if it doesn't have the right - * extension. - */ -static char * -make_invalid_thumbnail_uri (const char *thumbnail_uri) -{ - return g_strconcat (thumbnail_uri, ".x", NULL); -} - -/* return true if there's a placeholder thumbnail present for the passed in - * file, which indicates that a previous thumbnailing attempt failed and - * we should use the mime-type icon instead - */ -gboolean nautilus_thumbnail_has_invalid_thumbnail (NautilusFile *file, - gboolean anti_aliased) -{ - char *file_uri, *thumbnail_uri, *invalid_thumbnail_uri; - GnomeVFSURI *temp_uri; - gboolean uri_is_local, is_invalid; - - file_uri = nautilus_file_get_uri (file); - - /* compose the uri for the thumbnail locally */ - temp_uri = gnome_vfs_uri_new (file_uri); - uri_is_local = gnome_vfs_uri_is_local (temp_uri); - gnome_vfs_uri_unref (temp_uri); - - thumbnail_uri = make_thumbnail_uri (file_uri, FALSE, uri_is_local, anti_aliased, TRUE); - invalid_thumbnail_uri = make_invalid_thumbnail_uri (thumbnail_uri); - - is_invalid = vfs_file_exists (invalid_thumbnail_uri); - - g_free (file_uri); - g_free (thumbnail_uri); - g_free (invalid_thumbnail_uri); - return is_invalid; -} - -/* routine that takes a uri of a large image file and returns the uri of its corresponding thumbnail. - If no thumbnail is available, put the image on the thumbnail queue so one is eventually made. */ -/* FIXME bugzilla.eazel.com 642: - * Most of this thumbnail machinery belongs in NautilusFile, not here. - */ - -char * -nautilus_get_thumbnail_uri (NautilusFile *file, gboolean anti_aliased) -{ - GnomeVFSResult result; - GnomeVFSURI *temp_uri; - char *thumbnail_uri; - char *file_uri; - gboolean can_write, uri_is_local; - NautilusFile *destination_file; - gboolean local_flag = TRUE; - gboolean remake_thumbnail = FALSE; - - file_uri = nautilus_file_get_uri (file); - - /* compose the uri for the thumbnail locally */ - temp_uri = gnome_vfs_uri_new (file_uri); - uri_is_local = gnome_vfs_uri_is_local (temp_uri); - gnome_vfs_uri_unref (temp_uri); - - thumbnail_uri = make_thumbnail_uri (file_uri, FALSE, uri_is_local, anti_aliased, TRUE); - - /* if the thumbnail file already exists locally, simply return the uri */ - - /* note: thumbnail_uri is always local here, so it's not a disaster that we make a synchronous call below. - Eventually, we'll want to do everything asynchronously, when we have time to restructure the thumbnail engine */ - if (vfs_file_exists (thumbnail_uri)) { - - /* see if the file changed since it was thumbnailed by comparing the modification time */ - remake_thumbnail = first_file_more_recent (file_uri, thumbnail_uri); - - /* if the file hasn't changed, return the thumbnail uri */ - if (!remake_thumbnail) { - g_free (file_uri); - return thumbnail_uri; - } else { - nautilus_icon_factory_remove_by_uri (thumbnail_uri); - - /* the thumbnail uri is always local, so we can do synchronous I/O to delete it */ - gnome_vfs_unlink (thumbnail_uri); - } - } - - /* now try it globally */ - if (!remake_thumbnail) { - g_free (thumbnail_uri); - thumbnail_uri = make_thumbnail_uri (file_uri, FALSE, FALSE, anti_aliased, TRUE); - - /* if the thumbnail file already exists in the common area, return that uri, */ - /* the uri is guaranteed to be local */ - if (vfs_file_exists (thumbnail_uri)) { - - /* see if the file changed since it was thumbnailed by comparing the modification time */ - remake_thumbnail = first_file_more_recent(file_uri, thumbnail_uri); - - /* if the file hasn't changed, return the thumbnail uri */ - if (!remake_thumbnail) { - g_free (file_uri); - return thumbnail_uri; - } else { - nautilus_icon_factory_remove_by_uri (thumbnail_uri); - - /* the uri is guaranteed to be local */ - gnome_vfs_unlink (thumbnail_uri); - } - } - } - - /* make the thumbnail directory if necessary, at first try it locally */ - g_free (thumbnail_uri); - local_flag = TRUE; - thumbnail_uri = make_thumbnail_uri (file_uri, TRUE, local_flag, anti_aliased, TRUE); - - /* FIXME bugzilla.eazel.com 3137: more potentially losing - synch I/O - this could be remote */ - - result = gnome_vfs_make_directory (thumbnail_uri, THUMBNAIL_DIR_PERMISSIONS); - - /* the directory could already exist, but we better make sure we can write to it */ - destination_file = nautilus_file_get (thumbnail_uri); - can_write = FALSE; - if (destination_file != NULL) { - can_write = nautilus_file_can_write (destination_file); - nautilus_file_unref (destination_file); - } - - /* if we can't make if locally, try it in the global place */ - if (!can_write || (result != GNOME_VFS_OK && result != GNOME_VFS_ERROR_FILE_EXISTS)) { - g_free (thumbnail_uri); - local_flag = FALSE; - thumbnail_uri = make_thumbnail_uri (file_uri, TRUE, local_flag, anti_aliased, TRUE); - /* this is guaranteed to be local, so synch I/O can be tolerated here */ - result = gnome_vfs_make_directory (thumbnail_uri, THUMBNAIL_DIR_PERMISSIONS); - } - - /* the thumbnail needs to be created (or recreated), so add an entry to the thumbnail list */ - - if (result != GNOME_VFS_OK && result != GNOME_VFS_ERROR_FILE_EXISTS) { - - g_warning ("error when making thumbnail directory %d, for %s", result, thumbnail_uri); - } else { - NautilusThumbnailInfo *info = g_new0 (NautilusThumbnailInfo, 1); - info->thumbnail_uri = file_uri; - info->is_local = local_flag; - info->anti_aliased = anti_aliased; - - if (thumbnails != NULL) { - if (g_list_find_custom (thumbnails, info, compare_thumbnail_info) == NULL) { - thumbnails = g_list_append (thumbnails, info); - } - } else { - thumbnails = g_list_alloc (); - thumbnails->data = info; - } - - if (thumbnail_timeout_id == 0) { - thumbnail_timeout_id = gtk_timeout_add - (400, make_thumbnails, NULL); - } - } - - g_free (thumbnail_uri); - - /* Return NULL to indicate the thumbnail is loading. */ - return NULL; -} - -static void -nautilus_update_thumbnail_file_renamed_one (const char *old_file_name, const char *new_file_name, - gboolean anti_aliased) -{ - GnomeVFSURI *uri; - gboolean is_local; - char *old_thumbnail_uri, *new_thumbnail_uri; - - uri = gnome_vfs_uri_new (old_file_name); - is_local = gnome_vfs_uri_is_local (uri); - gnome_vfs_uri_unref (uri); - - old_thumbnail_uri = make_thumbnail_uri (old_file_name, FALSE, is_local, anti_aliased, FALSE); - if (old_thumbnail_uri != NULL && vfs_file_exists (old_thumbnail_uri)) { - new_thumbnail_uri = make_thumbnail_uri (new_file_name, FALSE, is_local, anti_aliased, FALSE); - - g_assert (new_thumbnail_uri != NULL); - - gnome_vfs_move (old_thumbnail_uri, new_thumbnail_uri, FALSE); - - g_free (new_thumbnail_uri); - } - - g_free (old_thumbnail_uri); -} - -/* update the thumbnail after the thumbnailed file got renamed */ -void -nautilus_update_thumbnail_file_renamed (const char *old_file_name, const char *new_file_name) -{ - /* rename both the AA and non-AA thumbnails, if they exist */ - nautilus_update_thumbnail_file_renamed_one (old_file_name, new_file_name, FALSE); - nautilus_update_thumbnail_file_renamed_one (old_file_name, new_file_name, TRUE); -} - -static void -nautilus_remove_thumbnail_for_file_one (const char *old_file_name, gboolean anti_aliased) -{ - GnomeVFSURI *uri; - gboolean is_local; - char *thumbnail_uri; - - uri = gnome_vfs_uri_new (old_file_name); - is_local = gnome_vfs_uri_is_local (uri); - gnome_vfs_uri_unref (uri); - - thumbnail_uri = make_thumbnail_uri (old_file_name, FALSE, is_local, anti_aliased, FALSE); - if (thumbnail_uri != NULL && vfs_file_exists (thumbnail_uri)) { - gnome_vfs_unlink (thumbnail_uri); - } - - g_free (thumbnail_uri); -} - -/* remove the thumbnail after the thumbnailed file got deleted */ -void -nautilus_remove_thumbnail_for_file (const char *old_file_name) -{ - /* remove both the AA and non-AA thumbnails, if they exist */ - nautilus_remove_thumbnail_for_file_one (old_file_name, FALSE); - nautilus_remove_thumbnail_for_file_one (old_file_name, TRUE); -} - -/* check_for_thumbnails is a utility that checks to see if the current thumbnail task has terminated. - If it has, remove the thumbnail info from the queue and return TRUE; if it's still in progress, return FALSE. -*/ - -static gboolean -check_for_thumbnails (void) -{ - NautilusThumbnailInfo *info; - GList *head; - NautilusFile *file; - int status; - char *current_thumbnail, *invalid_uri; - gboolean task_terminated; - gboolean need_update; - GnomeVFSResult result; - GnomeVFSHandle *handle; - - info = (NautilusThumbnailInfo*) thumbnails->data; - - task_terminated = waitpid (info->thumbnail_task, &status, WNOHANG) != 0; - if (task_terminated) { - /* the thumbnail task has completed, so update the current entry from the list */ - file = nautilus_file_get (info->thumbnail_uri); - - current_thumbnail = make_thumbnail_uri (info->thumbnail_uri, FALSE, info->is_local, - info->anti_aliased, TRUE); - - /* if a thumbnail wasn't successfully made, create a placeholder to flag that we tried */ - need_update = TRUE; - if (!vfs_file_exists (current_thumbnail)) { - invalid_uri = make_invalid_thumbnail_uri (current_thumbnail); - result = gnome_vfs_create (&handle, invalid_uri, GNOME_VFS_OPEN_WRITE, - FALSE, THUMBNAIL_PLACEHOLDER_PERMISSIONS); - - if (result == GNOME_VFS_OK) { - gnome_vfs_close (handle); - } - - g_free (invalid_uri); - } - - /* update the file's icon */ - if (file != NULL && need_update) { - nautilus_file_changed (file); - } - - if (file != NULL) { - nautilus_file_unref (file); - } - - g_free (current_thumbnail); - g_free (info->thumbnail_uri); - g_free (info); - - /* remove it from the queue */ - head = thumbnails; - thumbnails = g_list_remove_link (thumbnails, head); - g_list_free_1 (head); - - return TRUE; - } - - return FALSE; -} - -/* make_thumbnails is invoked periodically as a timer task to launch a task to make thumbnails */ - -static GdkPixbuf* -load_thumbnail_frame (gboolean anti_aliased) -{ - char *image_path; - GdkPixbuf *frame_image; - - /* load the thumbnail frame */ - image_path = nautilus_theme_get_image_path (anti_aliased ? "thumbnail_frame.aa.png" : "thumbnail_frame.png"); - frame_image = gdk_pixbuf_new_from_file (image_path); - g_free (image_path); - return frame_image; -} - -static int -make_thumbnails (gpointer data) -{ - NautilusThumbnailInfo *info; - GList *next_thumbnail = thumbnails; - GdkPixbuf *scaled_image, *framed_image, *thumbnail_image_frame; - char *frame_offset_str; - int left_offset, top_offset, right_offset, bottom_offset; - - /* if the queue is empty, there's nothing more to do */ - if (next_thumbnail == NULL) { - gtk_timeout_remove (thumbnail_timeout_id); - thumbnail_timeout_id = 0; - return FALSE; - } - - info = (NautilusThumbnailInfo *) next_thumbnail->data; - - /* see which state we're in. If a thumbnail isn't in progress, start one up. Otherwise, - check if the pending one is completed. */ - if (thumbnail_in_progress) { - if (check_for_thumbnails ()) { - thumbnail_in_progress = FALSE; - } - } else { - /* start up a task to make the thumbnail corresponding to the queue element. */ - - /* First, compute the path name of the target thumbnail */ - g_free (new_thumbnail_uri); - new_thumbnail_uri = make_thumbnail_uri (info->thumbnail_uri, FALSE, info->is_local, - info->anti_aliased, TRUE); - - /* fork a task to make the thumbnail, using gdk-pixbuf to do the scaling */ - if (!(info->thumbnail_task = fork())) { - GdkPixbuf* full_size_image; - NautilusFile *file; - GnomeVFSFileSize file_size; - char *thumbnail_path; - - file = nautilus_file_get (info->thumbnail_uri); - file_size = nautilus_file_get_size (file); - full_size_image = NULL; - - if (nautilus_file_is_mime_type (file, "image/svg")) { - thumbnail_path = gnome_vfs_get_local_path_from_uri (info->thumbnail_uri); - if (thumbnail_path != NULL) { - FILE *f = fopen (thumbnail_path, "rb"); - if (f != NULL) { - full_size_image = rsvg_render_file (f, 1.0); - fclose (f); - } - } -#ifdef HAVE_LIBJPEG - } else if (nautilus_file_is_mime_type (file, "image/jpeg")) { - if (info->thumbnail_uri != NULL) { - full_size_image = nautilus_thumbnail_load_scaled_jpeg - (info->thumbnail_uri, 96, 96); - } -#endif - } else { - if (info->thumbnail_uri != NULL) { - full_size_image = eel_gdk_pixbuf_load (info->thumbnail_uri); - } - } - nautilus_file_unref (file); - - if (full_size_image != NULL) { - thumbnail_image_frame = load_thumbnail_frame (info->anti_aliased); - - /* scale the content image as necessary */ - scaled_image = eel_gdk_pixbuf_scale_down_to_fit (full_size_image, 96, 96); - gdk_pixbuf_unref (full_size_image); - - /* embed the content image in the frame, if necessary */ - if (file_size > SELF_THUMBNAIL_SIZE_THRESHOLD) { - - frame_offset_str = nautilus_theme_get_theme_data ("thumbnails", "FRAME_OFFSETS"); - if (frame_offset_str != NULL) { - sscanf (frame_offset_str," %d , %d , %d , %d %*s", - &left_offset, &top_offset, &right_offset, &bottom_offset); - } else { - /* use nominal values since the info in the theme couldn't be found */ - left_offset = 3; top_offset = 3; - right_offset = 6; bottom_offset = 6; - } - - framed_image = eel_embed_image_in_frame (scaled_image, thumbnail_image_frame, - left_offset, top_offset, right_offset, bottom_offset); - g_free (frame_offset_str); - - gdk_pixbuf_unref (scaled_image); - gdk_pixbuf_unref (thumbnail_image_frame); - } else { - framed_image = scaled_image; - } - - thumbnail_path = gnome_vfs_get_local_path_from_uri (new_thumbnail_uri); - if (thumbnail_path == NULL - || !eel_gdk_pixbuf_save_to_file (framed_image, thumbnail_path)) { - g_warning ("error saving thumbnail %s", thumbnail_path); - } - g_free (thumbnail_path); - gdk_pixbuf_unref (framed_image); - } else { - /* gdk-pixbuf couldn't load the image, so trying using ImageMagick */ - char *temp_str; - - thumbnail_path = gnome_vfs_get_local_path_from_uri (new_thumbnail_uri); - if (thumbnail_path != NULL) { - temp_str = g_strdup_printf ("png:%s", thumbnail_path); - g_free (thumbnail_path); - - thumbnail_path = gnome_vfs_get_local_path_from_uri (info->thumbnail_uri); - if (thumbnail_path != NULL) { - - /* scale the image */ - execlp ("convert", "convert", "-geometry", "96x96", thumbnail_path, temp_str, NULL); - } - } - - /* we don't come back from this call, so no point in freeing anything up */ - } - - _exit(0); - } - thumbnail_in_progress = TRUE; - } - - return TRUE; /* we're not done yet */ -} diff --git a/libnautilus-extensions/nautilus-thumbnails.h b/libnautilus-extensions/nautilus-thumbnails.h deleted file mode 100644 index d4d2c6377..000000000 --- a/libnautilus-extensions/nautilus-thumbnails.h +++ /dev/null @@ -1,40 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- - - nautilus-thumbnails.h: Thumbnail code for icon factory. - - 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. - - Author: Andy Hertzfeld <andy@eazel.com> -*/ - -#ifndef NAUTILUS_THUMBNAILS_H -#define NAUTILUS_THUMBNAILS_H - -#include "nautilus-file.h" - -/* Returns NULL if there's no thumbnail yet. */ -char *nautilus_get_thumbnail_uri (NautilusFile *file, gboolean anti_aliased); - -gboolean nautilus_thumbnail_has_invalid_thumbnail (NautilusFile *file, gboolean anti_aliased); - -void nautilus_update_thumbnail_file_renamed (const char *old_file_name, - const char *new_file_name); - -void nautilus_remove_thumbnail_for_file (const char *old_file_name); - -#endif /* NAUTILUS_THUMBNAILS_H */ diff --git a/libnautilus-extensions/nautilus-trash-directory.c b/libnautilus-extensions/nautilus-trash-directory.c deleted file mode 100644 index 0a8e930c9..000000000 --- a/libnautilus-extensions/nautilus-trash-directory.c +++ /dev/null @@ -1,399 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- - - nautilus-trash-directory.c: Subclass of NautilusDirectory to implement the - virtual trash directory. - - Copyright (C) 1999, 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. - - Author: Darin Adler <darin@eazel.com> -*/ - -#include <config.h> -#include "nautilus-trash-directory.h" - -#include "nautilus-directory-private.h" -#include "nautilus-file.h" -#include "nautilus-trash-monitor.h" -#include <eel/eel-glib-extensions.h> -#include <eel/eel-stock-dialogs.h> -#include <eel/eel-gtk-macros.h> -#include "nautilus-volume-monitor.h" -#include <gtk/gtksignal.h> -#include <gtk/gtkmain.h> -#include <libgnome/gnome-defs.h> -#include <libgnome/gnome-i18n.h> - -struct NautilusTrashDirectoryDetails { - GHashTable *volumes; -}; - -typedef struct { - NautilusTrashDirectory *trash; - NautilusVolume *volume; - - GnomeVFSAsyncHandle *handle; - NautilusDirectory *real_directory; -} TrashVolume; - -static void nautilus_trash_directory_initialize (gpointer object, - gpointer klass); -static void nautilus_trash_directory_initialize_class (gpointer klass); -static void add_volume (NautilusTrashDirectory *trash, - NautilusVolume *volume); - -EEL_DEFINE_CLASS_BOILERPLATE (NautilusTrashDirectory, - nautilus_trash_directory, - NAUTILUS_TYPE_MERGED_DIRECTORY) - -#define TRASH_SEARCH_TIMED_WAIT_DELAY 20000 - -static int pending_find_directory_count = 0; - -static void -find_directory_start (void) -{ - if (pending_find_directory_count == 0) { - eel_timed_wait_start_with_duration (TRASH_SEARCH_TIMED_WAIT_DELAY, - NULL, - add_volume, - _("Searching Disks"), - _("Nautilus is searching your disks for trash folders."), - NULL); - } - - ++pending_find_directory_count; -} - -static void -find_directory_end (void) -{ - --pending_find_directory_count; - - if (pending_find_directory_count == 0) { - eel_timed_wait_stop (NULL, add_volume); - } -} - -static void -find_directory_callback (GnomeVFSAsyncHandle *handle, - GList *results, - gpointer callback_data) -{ - TrashVolume *trash_volume; - GnomeVFSFindDirectoryResult *result; - char *uri; - NautilusDirectory *directory; - - trash_volume = callback_data; - - g_assert (eel_g_list_exactly_one_item (results)); - g_assert (trash_volume != NULL); - g_assert (NAUTILUS_IS_TRASH_DIRECTORY (trash_volume->trash)); - g_assert (trash_volume->real_directory == NULL); - g_assert (trash_volume->handle == handle); - - find_directory_end (); - - /* We are done with the async. I/O. */ - trash_volume->handle = NULL; - - /* If we can't find the trash, ignore it silently. */ - result = results->data; - if (result->result != GNOME_VFS_OK) { - return; - } - - /* If we can't make a directory object, ignore it silently. */ - uri = gnome_vfs_uri_to_string (result->uri, - GNOME_VFS_URI_HIDE_NONE); - directory = nautilus_directory_get (uri); - g_free (uri); - if (directory == NULL) { - return; - } - - /* Add the directory object. */ - trash_volume->real_directory = directory; - nautilus_merged_directory_add_real_directory - (NAUTILUS_MERGED_DIRECTORY (trash_volume->trash), - directory); -} - -static gboolean -get_trash_volume (NautilusTrashDirectory *trash, - NautilusVolume *volume, - TrashVolume **trash_volume, - GnomeVFSURI **volume_mount_uri) -{ - /* Quick out if we already know about this volume. */ - *trash_volume = g_hash_table_lookup (trash->details->volumes, - volume); - - if (*trash_volume != NULL && (*trash_volume)->real_directory != NULL) { - return FALSE; - } - - if (!nautilus_volume_monitor_should_integrate_trash (volume)) { - return FALSE; - } - - *volume_mount_uri = gnome_vfs_uri_new - (nautilus_volume_monitor_get_volume_mount_uri (volume)); - - if (*trash_volume == NULL) { - /* Make the structure used to track the trash for this volume. */ - *trash_volume = g_new0 (TrashVolume, 1); - (*trash_volume)->trash = trash; - (*trash_volume)->volume = volume; - g_hash_table_insert (trash->details->volumes, volume, *trash_volume); - } - - return TRUE; -} - -static void -add_volume (NautilusTrashDirectory *trash, - NautilusVolume *volume) -{ - TrashVolume *trash_volume; - GnomeVFSURI *volume_mount_uri; - GList vfs_uri_as_list; - - if (!get_trash_volume (trash, volume, &trash_volume, &volume_mount_uri)) { - return; - } - - /* Find the real trash directory for this one. */ - vfs_uri_as_list.data = volume_mount_uri; - vfs_uri_as_list.next = NULL; - vfs_uri_as_list.prev = NULL; - - /* Search for Trash directories but don't create new ones. */ - find_directory_start (); - gnome_vfs_async_find_directory - (&trash_volume->handle, &vfs_uri_as_list, - GNOME_VFS_DIRECTORY_KIND_TRASH, FALSE, TRUE, 0777, - find_directory_callback, trash_volume); -} - -static void -check_trash_created (NautilusTrashDirectory *trash, - NautilusVolume *volume) -{ - GnomeVFSResult result; - TrashVolume *trash_volume; - GnomeVFSURI *volume_mount_uri; - GnomeVFSURI *trash_uri; - char *uri; - - if (!get_trash_volume (trash, volume, &trash_volume, &volume_mount_uri)) { - return; - } - - /* Do a synch trash lookup -- if the trash directory was just created, it's location will - * be known and returned immediately without any blocking. - */ - result = gnome_vfs_find_directory (volume_mount_uri, GNOME_VFS_DIRECTORY_KIND_TRASH, - &trash_uri, FALSE, FALSE, 077); - - gnome_vfs_uri_unref (volume_mount_uri); - if (result != GNOME_VFS_OK) { - return; - } - - uri = gnome_vfs_uri_to_string (trash_uri, - GNOME_VFS_URI_HIDE_NONE); - trash_volume->real_directory = nautilus_directory_get (uri); - g_free (uri); - gnome_vfs_uri_unref (trash_uri); - if (trash_volume->real_directory == NULL) { - return; - } - - /* Add the directory object. */ - nautilus_merged_directory_add_real_directory - (NAUTILUS_MERGED_DIRECTORY (trash_volume->trash), - trash_volume->real_directory); -} - -static void -remove_trash_volume (TrashVolume *trash_volume) -{ - g_hash_table_remove (trash_volume->trash->details->volumes, - trash_volume->volume); - - if (trash_volume->handle != NULL) { - gnome_vfs_async_cancel (trash_volume->handle); - find_directory_end (); - } - if (trash_volume->real_directory != NULL) { - nautilus_merged_directory_remove_real_directory - (NAUTILUS_MERGED_DIRECTORY (trash_volume->trash), - trash_volume->real_directory); - nautilus_directory_unref (trash_volume->real_directory); - } - g_free (trash_volume); -} - - -static void -remove_volume (NautilusTrashDirectory *trash, - NautilusVolume *volume) -{ - TrashVolume *trash_volume; - - /* Quick out if don't already know about this volume. */ - trash_volume = g_hash_table_lookup (trash->details->volumes, - volume); - if (trash_volume != NULL) { - remove_trash_volume (trash_volume); - } -} - -static gboolean -add_one_volume (const NautilusVolume *volume, - gpointer callback_data) -{ - /* The const is a kinda silly idea which we must cast away. */ - add_volume (NAUTILUS_TRASH_DIRECTORY (callback_data), - (NautilusVolume *) volume); - return FALSE; /* don't stop iterating */ -} - -static void -check_trash_directory_added_callback (NautilusVolumeMonitor *monitor, - NautilusVolume *volume, - NautilusTrashDirectory *trash) -{ - check_trash_created (trash, volume); -} - -static void -volume_unmount_started_callback (NautilusVolumeMonitor *monitor, - NautilusVolume *volume, - NautilusTrashDirectory *trash) -{ - remove_volume (trash, volume); -} - -static void -volume_mounted_callback (NautilusVolumeMonitor *monitor, - NautilusVolume *volume, - NautilusTrashDirectory *trash) -{ - add_volume (trash, volume); -} - -static void -nautilus_trash_directory_initialize (gpointer object, gpointer klass) -{ - NautilusTrashDirectory *trash; - NautilusVolumeMonitor *volume_monitor; - - trash = NAUTILUS_TRASH_DIRECTORY (object); - - trash->details = g_new0 (NautilusTrashDirectoryDetails, 1); - trash->details->volumes = g_hash_table_new (NULL, NULL); - - volume_monitor = nautilus_volume_monitor_get (); - - gtk_signal_connect - (GTK_OBJECT (volume_monitor), "volume_mounted", - volume_mounted_callback, trash); - gtk_signal_connect - (GTK_OBJECT (volume_monitor), "volume_unmount_started", - volume_unmount_started_callback, trash); -} - -/* Finish initializing a new NautilusTrashDirectory. We have to do the - * remaining initialization here rather than in nautilus_trash_directory_initialize - * because of a cyclic dependency between the NautilusTrashDirectory and - * NautilusTrashMonitor instances. - */ -void -nautilus_trash_directory_finish_initializing (NautilusTrashDirectory *trash) -{ - NautilusVolumeMonitor *volume_monitor; - - volume_monitor = nautilus_volume_monitor_get (); - - gtk_signal_connect - (GTK_OBJECT (nautilus_trash_monitor_get ()), "check_trash_directory_added", - check_trash_directory_added_callback, trash); - nautilus_volume_monitor_each_mounted_volume - (volume_monitor, add_one_volume, trash); -} - -static void -remove_trash_volume_cover (gpointer key, gpointer value, gpointer callback_data) -{ - TrashVolume *trash_volume; - - g_assert (key != NULL); - g_assert (value != NULL); - g_assert (callback_data == NULL); - - trash_volume = value; - - g_assert (NAUTILUS_IS_TRASH_DIRECTORY (trash_volume->trash)); - g_assert (trash_volume->volume == key); - - remove_trash_volume (trash_volume); -} - -static void -trash_destroy (GtkObject *object) -{ - NautilusTrashDirectory *trash; - - trash = NAUTILUS_TRASH_DIRECTORY (object); - - gtk_signal_disconnect_by_data - (GTK_OBJECT (nautilus_volume_monitor_get ()), trash); - - eel_g_hash_table_safe_for_each - (trash->details->volumes, - remove_trash_volume_cover, - NULL); - g_hash_table_destroy (trash->details->volumes); - g_free (trash->details); - - EEL_CALL_PARENT (GTK_OBJECT_CLASS, destroy, (object)); -} - -static char * -trash_get_name_for_self_as_new_file (NautilusDirectory *directory) -{ - g_assert (NAUTILUS_IS_TRASH_DIRECTORY (directory)); - return g_strdup (_("Trash")); -} - -static void -nautilus_trash_directory_initialize_class (gpointer klass) -{ - GtkObjectClass *object_class; - NautilusDirectoryClass *directory_class; - - object_class = GTK_OBJECT_CLASS (klass); - directory_class = NAUTILUS_DIRECTORY_CLASS (klass); - - object_class->destroy = trash_destroy; - - directory_class->get_name_for_self_as_new_file = trash_get_name_for_self_as_new_file; -} - diff --git a/libnautilus-extensions/nautilus-trash-directory.h b/libnautilus-extensions/nautilus-trash-directory.h deleted file mode 100644 index ffa0f7cc5..000000000 --- a/libnautilus-extensions/nautilus-trash-directory.h +++ /dev/null @@ -1,56 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- - - nautilus-trash-directory.h: Subclass of NautilusDirectory to implement - the virtual trash directory. - - Copyright (C) 1999, 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. - - Author: Darin Adler <darin@eazel.com> -*/ - -#ifndef NAUTILUS_TRASH_DIRECTORY_H -#define NAUTILUS_TRASH_DIRECTORY_H - -#include "nautilus-merged-directory.h" - -#define NAUTILUS_TYPE_TRASH_DIRECTORY \ - (nautilus_trash_directory_get_type ()) -#define NAUTILUS_TRASH_DIRECTORY(obj) \ - (GTK_CHECK_CAST ((obj), NAUTILUS_TYPE_TRASH_DIRECTORY, NautilusTrashDirectory)) -#define NAUTILUS_TRASH_DIRECTORY_CLASS(klass) \ - (GTK_CHECK_CLASS_CAST ((klass), NAUTILUS_TYPE_TRASH_DIRECTORY, NautilusTrashDirectoryClass)) -#define NAUTILUS_IS_TRASH_DIRECTORY(obj) \ - (GTK_CHECK_TYPE ((obj), NAUTILUS_TYPE_TRASH_DIRECTORY)) -#define NAUTILUS_IS_TRASH_DIRECTORY_CLASS(klass) \ - (GTK_CHECK_CLASS_TYPE ((klass), NAUTILUS_TYPE_TRASH_DIRECTORY)) - -typedef struct NautilusTrashDirectoryDetails NautilusTrashDirectoryDetails; - -typedef struct { - NautilusMergedDirectory parent_slot; - NautilusTrashDirectoryDetails *details; -} NautilusTrashDirectory; - -typedef struct { - NautilusMergedDirectoryClass parent_slot; -} NautilusTrashDirectoryClass; - -GtkType nautilus_trash_directory_get_type (void); -void nautilus_trash_directory_finish_initializing (NautilusTrashDirectory *trash); - -#endif /* NAUTILUS_TRASH_DIRECTORY_H */ diff --git a/libnautilus-extensions/nautilus-trash-file.c b/libnautilus-extensions/nautilus-trash-file.c deleted file mode 100644 index b4f33a439..000000000 --- a/libnautilus-extensions/nautilus-trash-file.c +++ /dev/null @@ -1,828 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- - - nautilus-trash-file.c: Subclass of NautilusFile to help implement the - virtual trash directory. - - Copyright (C) 1999, 2000, 2001 Eazel, Inc. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public - License along with this program; if not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. - - Author: Darin Adler <darin@eazel.com> -*/ - -#include <config.h> -#include "nautilus-trash-file.h" - -#include "nautilus-directory-notify.h" -#include "nautilus-directory-private.h" -#include "nautilus-file-attributes.h" -#include "nautilus-file-private.h" -#include "nautilus-file-utilities.h" -#include <eel/eel-glib-extensions.h> -#include <eel/eel-gtk-macros.h> -#include "nautilus-trash-directory.h" -#include <gtk/gtksignal.h> -#include <libgnome/gnome-defs.h> -#include <libgnome/gnome-i18n.h> -#include <string.h> - -struct NautilusTrashFileDetails { - NautilusTrashDirectory *trash_directory; - - guint add_directory_connection_id; - guint remove_directory_connection_id; - - GList *files; - - GHashTable *callbacks; - GHashTable *monitors; -}; - -typedef struct { - NautilusTrashFile *trash; - NautilusFileCallback callback; - gpointer callback_data; - - GList *delegated_attributes; - GList *non_delegated_attributes; - - GList *non_ready_files; - - gboolean initializing; -} TrashCallback; - -typedef struct { - NautilusTrashFile *trash; - - GList *delegated_attributes; - GList *non_delegated_attributes; -} TrashMonitor; - -static const char * const delegated_attributes[] = { - NAUTILUS_FILE_ATTRIBUTE_DEEP_COUNTS, - NAUTILUS_FILE_ATTRIBUTE_DIRECTORY_ITEM_COUNT, - NAUTILUS_FILE_ATTRIBUTE_DIRECTORY_ITEM_MIME_TYPES -}; - -static void nautilus_trash_file_initialize (gpointer object, - gpointer klass); -static void nautilus_trash_file_initialize_class (gpointer klass); - -EEL_DEFINE_CLASS_BOILERPLATE (NautilusTrashFile, - nautilus_trash_file, - NAUTILUS_TYPE_FILE) - -static gboolean -is_delegated_attribute (const char *attribute) -{ - guint i; - - g_return_val_if_fail (attribute != NULL, FALSE); - - for (i = 0; i < EEL_N_ELEMENTS (delegated_attributes); i++) { - if (strcmp (attribute, delegated_attributes[i]) == 0) { - return TRUE; - } - } - return FALSE; -} - -static gboolean -is_delegated_attribute_predicate (gpointer data, - gpointer callback_data) -{ - return is_delegated_attribute (data); -} - -static void -partition_attributes (GList *attributes, - GList **delegated_attributes, - GList **non_delegated_attributes) -{ - *delegated_attributes = eel_g_list_partition - (attributes, - is_delegated_attribute_predicate, - NULL, - non_delegated_attributes); -} - -static void -real_monitor_add (NautilusFile *file, - gconstpointer client, - GList *attributes) -{ - nautilus_directory_monitor_add_internal - (file->details->directory, file, - client, TRUE, TRUE, attributes); -} - -static void -real_monitor_remove (NautilusFile *file, - gconstpointer client) -{ - nautilus_directory_monitor_remove_internal - (file->details->directory, file, client); -} - -static void -real_call_when_ready (NautilusFile *file, - GList *attributes, - NautilusFileCallback callback, - gpointer callback_data) - -{ - nautilus_directory_call_when_ready_internal - (file->details->directory, file, - attributes, NULL, callback, callback_data); -} - -static void -real_cancel_call_when_ready (NautilusFile *file, - NautilusFileCallback callback, - gpointer callback_data) -{ - nautilus_directory_cancel_callback_internal - (file->details->directory, file, - NULL, callback, callback_data); -} - -static gboolean -real_check_if_ready (NautilusFile *file, - GList *attributes) -{ - return nautilus_directory_check_if_ready_internal - (file->details->directory, file, - attributes); -} - -static guint -trash_callback_hash (gconstpointer trash_callback_as_pointer) -{ - const TrashCallback *trash_callback; - - trash_callback = trash_callback_as_pointer; - return GPOINTER_TO_UINT (trash_callback->callback) - ^ GPOINTER_TO_UINT (trash_callback->callback_data); -} - -static gboolean -trash_callback_equal (gconstpointer trash_callback_as_pointer, - gconstpointer trash_callback_as_pointer_2) -{ - const TrashCallback *trash_callback, *trash_callback_2; - - trash_callback = trash_callback_as_pointer; - trash_callback_2 = trash_callback_as_pointer_2; - - return trash_callback->callback == trash_callback_2->callback - && trash_callback->callback_data == trash_callback_2->callback_data; -} - -static void -trash_callback_destroy (TrashCallback *trash_callback) -{ - g_assert (trash_callback != NULL); - g_assert (NAUTILUS_IS_TRASH_FILE (trash_callback->trash)); - - nautilus_file_unref (NAUTILUS_FILE (trash_callback->trash)); - eel_g_list_free_deep (trash_callback->delegated_attributes); - eel_g_list_free_deep (trash_callback->non_delegated_attributes); - g_list_free (trash_callback->non_ready_files); - g_free (trash_callback); -} - -static void -trash_callback_check_done (TrashCallback *trash_callback) -{ - /* Check if we are ready. */ - if (trash_callback->initializing || trash_callback->non_ready_files != NULL) { - return; - } - - /* Remove from the hash table before sending it. */ - g_hash_table_remove (trash_callback->trash->details->callbacks, - trash_callback); - - /* We are ready, so do the real callback. */ - (* trash_callback->callback) (NAUTILUS_FILE (trash_callback->trash), - trash_callback->callback_data); - - /* And we are done. */ - trash_callback_destroy (trash_callback); -} - -static void -trash_callback_remove_file (TrashCallback *trash_callback, - NautilusFile *file) -{ - trash_callback->non_ready_files = g_list_remove - (trash_callback->non_ready_files, file); - trash_callback_check_done (trash_callback); -} - -static void -ready_callback (NautilusFile *file, - gpointer callback_data) -{ - TrashCallback *trash_callback; - - g_assert (NAUTILUS_IS_FILE (file)); - g_assert (callback_data != NULL); - - trash_callback = callback_data; - g_assert (g_list_find (trash_callback->non_ready_files, file) != NULL); - - trash_callback_remove_file (trash_callback, file); -} - -static void -real_file_changed_callback (NautilusFile *real_file, - gpointer callback_data) -{ - NautilusTrashFile *trash_file; - - trash_file = NAUTILUS_TRASH_FILE (callback_data); - nautilus_file_changed (NAUTILUS_FILE (trash_file)); -} - -static void -monitor_add_file (gpointer key, - gpointer value, - gpointer callback_data) -{ - TrashMonitor *monitor; - - monitor = value; - nautilus_file_monitor_add - (NAUTILUS_FILE (callback_data), - monitor, - monitor->delegated_attributes); -} - -static void -add_real_file (NautilusTrashFile *trash, - NautilusFile *real_file) -{ - g_return_if_fail (NAUTILUS_IS_TRASH_FILE (trash)); - g_return_if_fail (NAUTILUS_IS_FILE (real_file)); - g_return_if_fail (!NAUTILUS_IS_TRASH_FILE (real_file)); - g_return_if_fail (g_list_find (trash->details->files, real_file) == NULL); - - nautilus_file_ref (real_file); - trash->details->files = g_list_prepend - (trash->details->files, real_file); - - gtk_signal_connect (GTK_OBJECT (real_file), - "changed", - real_file_changed_callback, - trash); - - /* Add the file to any extant monitors. */ - g_hash_table_foreach (trash->details->monitors, - monitor_add_file, - real_file); -} - -static void -trash_callback_remove_file_cover (gpointer key, - gpointer value, - gpointer callback_data) -{ - trash_callback_remove_file - (value, NAUTILUS_FILE (callback_data)); -} - -static void -monitor_remove_file (gpointer key, - gpointer value, - gpointer callback_data) -{ - nautilus_file_monitor_remove - (NAUTILUS_FILE (callback_data), value); -} - -static void -remove_real_file (NautilusTrashFile *trash, - NautilusFile *real_file) -{ - g_return_if_fail (NAUTILUS_IS_TRASH_FILE (trash)); - g_return_if_fail (NAUTILUS_IS_FILE (real_file)); - g_return_if_fail (g_list_find (trash->details->files, real_file) != NULL); - - eel_g_hash_table_safe_for_each - (trash->details->callbacks, - trash_callback_remove_file_cover, - real_file); - g_hash_table_foreach - (trash->details->monitors, - monitor_remove_file, - real_file); - - gtk_signal_disconnect_by_func (GTK_OBJECT (real_file), - real_file_changed_callback, - trash); - - trash->details->files = g_list_remove - (trash->details->files, real_file); - nautilus_file_unref (real_file); -} - -static void -add_real_file_given_directory (NautilusTrashFile *trash_file, - NautilusDirectory *real_directory) -{ - NautilusFile *real_file; - - real_file = nautilus_directory_get_corresponding_file (real_directory); - add_real_file (trash_file, real_file); - nautilus_file_unref (real_file); -} - -static void -add_directory_callback (NautilusTrashDirectory *trash_directory, - NautilusDirectory *real_directory, - NautilusTrashFile *trash_file) -{ - g_assert (NAUTILUS_IS_TRASH_DIRECTORY (trash_directory)); - g_assert (NAUTILUS_IS_DIRECTORY (real_directory)); - g_assert (!NAUTILUS_IS_MERGED_DIRECTORY (real_directory)); - g_assert (NAUTILUS_IS_TRASH_FILE (trash_file)); - g_assert (trash_file->details->trash_directory == trash_directory); - - add_real_file_given_directory (trash_file, real_directory); - - nautilus_file_changed (NAUTILUS_FILE (trash_file)); -} - -static void -remove_directory_callback (NautilusTrashDirectory *trash_directory, - NautilusDirectory *real_directory, - NautilusTrashFile *trash_file) -{ - NautilusFile *real_file; - - g_assert (NAUTILUS_IS_TRASH_DIRECTORY (trash_directory)); - g_assert (NAUTILUS_IS_DIRECTORY (real_directory)); - g_assert (!NAUTILUS_IS_MERGED_DIRECTORY (real_directory)); - g_assert (NAUTILUS_IS_TRASH_FILE (trash_file)); - g_assert (trash_file->details->trash_directory == trash_directory); - - real_file = nautilus_directory_get_corresponding_file (real_directory); - remove_real_file (trash_file, real_file); - nautilus_file_unref (real_file); - - nautilus_file_changed (NAUTILUS_FILE (trash_file)); -} - -static void -trash_file_call_when_ready (NautilusFile *file, - GList *attributes, - NautilusFileCallback callback, - gpointer callback_data) - -{ - NautilusTrashFile *trash; - TrashCallback search_key, *trash_callback; - GList *node; - - trash = NAUTILUS_TRASH_FILE (file); - - /* Check to be sure we aren't overwriting. */ - search_key.callback = callback; - search_key.callback_data = callback_data; - if (g_hash_table_lookup (trash->details->callbacks, &search_key) != NULL) { - g_warning ("tried to add a new callback while an old one was pending"); - return; - } - - /* Create a trash_callback record. */ - trash_callback = g_new0 (TrashCallback, 1); - nautilus_file_ref (file); - trash_callback->trash = trash; - trash_callback->callback = callback; - trash_callback->callback_data = callback_data; - trash_callback->initializing = TRUE; - - partition_attributes (eel_g_str_list_copy (attributes), - &trash_callback->delegated_attributes, - &trash_callback->non_delegated_attributes); - - trash_callback->non_ready_files = g_list_prepend - (trash_callback->non_ready_files, file); - for (node = trash->details->files; node != NULL; node = node->next) { - trash_callback->non_ready_files = g_list_prepend - (trash_callback->non_ready_files, node->data); - } - - /* Put it in the hash table. */ - g_hash_table_insert (trash->details->callbacks, - trash_callback, trash_callback); - - /* Now connect to each file's call_when_ready. */ - real_call_when_ready - (file, trash_callback->non_delegated_attributes, - ready_callback, trash_callback); - for (node = trash->details->files; node != NULL; node = node->next) { - nautilus_file_call_when_ready - (node->data, trash_callback->delegated_attributes, - ready_callback, trash_callback); - } - - trash_callback->initializing = FALSE; - - /* Check if any files became read while we were connecting up - * the call_when_ready callbacks (also handles the pathological - * case where there are no files at all). - */ - trash_callback_check_done (trash_callback); -} - -static void -trash_file_cancel_call_when_ready (NautilusFile *file, - NautilusFileCallback callback, - gpointer callback_data) -{ - NautilusTrashFile *trash; - TrashCallback search_key, *trash_callback; - GList *node; - - trash = NAUTILUS_TRASH_FILE (file); - - /* Find the entry in the table. */ - search_key.callback = callback; - search_key.callback_data = callback_data; - trash_callback = g_hash_table_lookup (trash->details->callbacks, &search_key); - if (trash_callback == NULL) { - return; - } - - /* Remove from the hash table before working with it. */ - g_hash_table_remove (trash_callback->trash->details->callbacks, trash_callback); - - /* Tell all the directories to cancel the call. */ - real_cancel_call_when_ready (file, ready_callback, trash_callback); - for (node = trash_callback->non_ready_files; node != NULL; node = node->next) { - nautilus_file_cancel_call_when_ready - (node->data, ready_callback, trash_callback); - } - trash_callback_destroy (trash_callback); -} - -static gboolean -trash_file_check_if_ready (NautilusFile *file, - GList *attributes) -{ - GList *delegated_attributes, *non_delegated_attributes; - NautilusTrashFile *trash; - GList *node; - gboolean ready; - - trash = NAUTILUS_TRASH_FILE (file); - - partition_attributes (g_list_copy (attributes), - &delegated_attributes, - &non_delegated_attributes); - - ready = real_check_if_ready (file, non_delegated_attributes); - - if (ready) { - for (node = trash->details->files; node != NULL; node = node->next) { - if (!nautilus_file_check_if_ready (node->data, - delegated_attributes)) { - ready = FALSE; - break; - } - } - } - - g_list_free (delegated_attributes); - g_list_free (non_delegated_attributes); - - return ready; -} - -static void -trash_file_monitor_add (NautilusFile *file, - gconstpointer client, - GList *attributes) -{ - NautilusTrashFile *trash; - TrashMonitor *monitor; - GList *node; - - trash = NAUTILUS_TRASH_FILE (file); - - /* Map the client to a unique value so this doesn't interfere - * with direct monitoring of the file by the same client. - */ - monitor = g_hash_table_lookup (trash->details->monitors, client); - if (monitor != NULL) { - g_assert (monitor->trash == trash); - eel_g_list_free_deep (monitor->delegated_attributes); - eel_g_list_free_deep (monitor->non_delegated_attributes); - } else { - monitor = g_new0 (TrashMonitor, 1); - monitor->trash = trash; - g_hash_table_insert (trash->details->monitors, - (gpointer) client, monitor); - } - - partition_attributes (eel_g_str_list_copy (attributes), - &monitor->delegated_attributes, - &monitor->non_delegated_attributes); - - real_monitor_add (file, monitor, - monitor->non_delegated_attributes); - for (node = trash->details->files; node != NULL; node = node->next) { - nautilus_file_monitor_add (node->data, monitor, - monitor->delegated_attributes); - } -} - -static void -trash_file_monitor_remove (NautilusFile *file, - gconstpointer client) -{ - NautilusTrashFile *trash; - TrashMonitor *monitor; - GList *node; - - trash = NAUTILUS_TRASH_FILE (file); - - /* Map the client to the value used by the earlier add call. */ - monitor = g_hash_table_lookup (trash->details->monitors, client); - if (monitor == NULL) { - return; - } - g_hash_table_remove (trash->details->monitors, client); - - /* Call through to the real file remove calls. */ - real_monitor_remove (file, monitor); - for (node = trash->details->files; node != NULL; node = node->next) { - nautilus_file_monitor_remove (node->data, monitor); - } - - eel_g_list_free_deep (monitor->delegated_attributes); - eel_g_list_free_deep (monitor->non_delegated_attributes); - g_free (monitor); -} - -static GnomeVFSFileType -trash_file_get_file_type (NautilusFile *file) -{ - return GNOME_VFS_FILE_TYPE_DIRECTORY; -} - -static gboolean -trash_file_get_item_count (NautilusFile *file, - guint *count, - gboolean *count_unreadable) -{ - NautilusTrashFile *trash; - GList *node; - guint one_count, one_unreadable; - gboolean got_count; - - trash = NAUTILUS_TRASH_FILE (file); - - got_count = TRUE; - if (count != NULL) { - *count = 0; - } - if (count_unreadable != NULL) { - *count_unreadable = FALSE; - } - - for (node = trash->details->files; node != NULL; node = node->next) { - if (!nautilus_file_get_directory_item_count (node->data, - &one_count, - &one_unreadable)) { - got_count = FALSE; - } - - if (count != NULL) { - *count += one_count; - } - if (count_unreadable != NULL && one_unreadable) { - *count_unreadable = TRUE; - } - } - - return got_count; -} - -static NautilusRequestStatus -trash_file_get_deep_counts (NautilusFile *file, - guint *directory_count, - guint *file_count, - guint *unreadable_directory_count, - GnomeVFSFileSize *total_size) -{ - NautilusTrashFile *trash; - GList *node; - NautilusRequestStatus status, one_status; - guint one_directory_count, one_file_count, one_unreadable_directory_count; - GnomeVFSFileSize one_total_size; - - trash = NAUTILUS_TRASH_FILE (file); - - status = NAUTILUS_REQUEST_DONE; - if (directory_count != NULL) { - *directory_count = 0; - } - if (file_count != NULL) { - *file_count = 0; - } - if (unreadable_directory_count != NULL) { - *unreadable_directory_count = 0; - } - if (total_size != NULL) { - *total_size = 0; - } - - for (node = trash->details->files; node != NULL; node = node->next) { - one_status = nautilus_file_get_deep_counts - (node->data, - &one_directory_count, - &one_file_count, - &one_unreadable_directory_count, - &one_total_size); - - if (one_status < status) { - status = one_status; - } - if (directory_count != NULL) { - *directory_count += one_directory_count; - } - if (file_count != NULL) { - *file_count += one_file_count; - } - if (unreadable_directory_count != NULL) { - *unreadable_directory_count += one_unreadable_directory_count; - } - if (total_size != NULL) { - *total_size += one_total_size; - } - } - - return status; -} - -static gboolean -trash_file_get_date (NautilusFile *file, - NautilusDateType date_type, - time_t *date) -{ - NautilusTrashFile *trash; - GList *node; - gboolean got_at_least_one; - gboolean got_all; - time_t one_date; - - trash = NAUTILUS_TRASH_FILE (file); - - got_at_least_one = FALSE; - got_all = TRUE; - - for (node = trash->details->files; node != NULL; node = node->next) { - if (nautilus_file_get_date (node->data, - date_type, - &one_date)) { - if (!got_at_least_one) { - got_at_least_one = TRUE; - if (date != NULL) { - *date = one_date; - } - } else { - if (date != NULL && one_date > *date) { - *date = one_date; - } - } - } else { - got_all = FALSE; - } - } - - return got_at_least_one && got_all; -} - -static char * -trash_file_get_where_string (NautilusFile *file) -{ - return g_strdup (_("on the desktop")); -} - - -static void -remove_all_real_files (NautilusTrashFile *trash) -{ - while (trash->details->files != NULL) { - remove_real_file (trash, trash->details->files->data); - } -} - -static void -nautilus_trash_file_initialize (gpointer object, gpointer klass) -{ - NautilusTrashFile *trash_file; - NautilusTrashDirectory *trash_directory; - GList *real_directories, *node; - - trash_file = NAUTILUS_TRASH_FILE (object); - - trash_directory = NAUTILUS_TRASH_DIRECTORY (nautilus_directory_get (EEL_TRASH_URI)); - - trash_file->details = g_new0 (NautilusTrashFileDetails, 1); - trash_file->details->trash_directory = trash_directory; - - trash_file->details->callbacks = g_hash_table_new - (trash_callback_hash, trash_callback_equal); - trash_file->details->monitors = g_hash_table_new (NULL, NULL); - - trash_file->details->add_directory_connection_id = gtk_signal_connect - (GTK_OBJECT (trash_directory), - "add_real_directory", - add_directory_callback, - trash_file); - trash_file->details->remove_directory_connection_id = gtk_signal_connect - (GTK_OBJECT (trash_directory), - "remove_real_directory", - remove_directory_callback, - trash_file); - - real_directories = nautilus_merged_directory_get_real_directories - (NAUTILUS_MERGED_DIRECTORY (trash_directory)); - for (node = real_directories; node != NULL; node = node->next) { - add_real_file_given_directory (trash_file, node->data); - } - g_list_free (real_directories); -} - -static void -trash_destroy (GtkObject *object) -{ - NautilusTrashFile *trash_file; - NautilusTrashDirectory *trash_directory; - - trash_file = NAUTILUS_TRASH_FILE (object); - trash_directory = trash_file->details->trash_directory; - - remove_all_real_files (trash_file); - - if (g_hash_table_size (trash_file->details->callbacks) != 0) { - g_warning ("call_when_ready still pending when trash virtual file is destroyed"); - } - if (g_hash_table_size (trash_file->details->monitors) != 0) { - g_warning ("file monitor still active when trash virtual file is destroyed"); - } - - gtk_signal_disconnect (GTK_OBJECT (trash_directory), - trash_file->details->add_directory_connection_id); - gtk_signal_disconnect (GTK_OBJECT (trash_directory), - trash_file->details->remove_directory_connection_id); - - g_hash_table_destroy (trash_file->details->callbacks); - g_hash_table_destroy (trash_file->details->monitors); - - g_free (trash_file->details); - - nautilus_directory_unref (NAUTILUS_DIRECTORY (trash_directory)); - - EEL_CALL_PARENT (GTK_OBJECT_CLASS, destroy, (object)); -} - -static void -nautilus_trash_file_initialize_class (gpointer klass) -{ - GtkObjectClass *object_class; - NautilusFileClass *file_class; - - object_class = GTK_OBJECT_CLASS (klass); - file_class = NAUTILUS_FILE_CLASS (klass); - - object_class->destroy = trash_destroy; - - file_class->monitor_add = trash_file_monitor_add; - file_class->monitor_remove = trash_file_monitor_remove; - file_class->call_when_ready = trash_file_call_when_ready; - file_class->cancel_call_when_ready = trash_file_cancel_call_when_ready; - file_class->check_if_ready = trash_file_check_if_ready; - file_class->get_file_type = trash_file_get_file_type; - file_class->get_item_count = trash_file_get_item_count; - file_class->get_deep_counts = trash_file_get_deep_counts; - file_class->get_date = trash_file_get_date; - file_class->get_where_string = trash_file_get_where_string; -} diff --git a/libnautilus-extensions/nautilus-trash-file.h b/libnautilus-extensions/nautilus-trash-file.h deleted file mode 100644 index 0ee86a88f..000000000 --- a/libnautilus-extensions/nautilus-trash-file.h +++ /dev/null @@ -1,55 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- - - nautilus-trash-file.h: Subclass of NautilusFile to implement the - the case of a TRASH file. - - Copyright (C) 1999, 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. - - Author: Darin Adler <darin@eazel.com> -*/ - -#ifndef NAUTILUS_TRASH_FILE_H -#define NAUTILUS_TRASH_FILE_H - -#include "nautilus-file.h" - -#define NAUTILUS_TYPE_TRASH_FILE \ - (nautilus_trash_file_get_type ()) -#define NAUTILUS_TRASH_FILE(obj) \ - (GTK_CHECK_CAST ((obj), NAUTILUS_TYPE_TRASH_FILE, NautilusTrashFile)) -#define NAUTILUS_TRASH_FILE_CLASS(klass) \ - (GTK_CHECK_CLASS_CAST ((klass), NAUTILUS_TYPE_TRASH_FILE, NautilusTrashFileClass)) -#define NAUTILUS_IS_TRASH_FILE(obj) \ - (GTK_CHECK_TYPE ((obj), NAUTILUS_TYPE_TRASH_FILE)) -#define NAUTILUS_IS_TRASH_FILE_CLASS(klass) \ - (GTK_CHECK_CLASS_TYPE ((klass), NAUTILUS_TYPE_TRASH_FILE)) - -typedef struct NautilusTrashFileDetails NautilusTrashFileDetails; - -typedef struct { - NautilusFile parent_slot; - NautilusTrashFileDetails *details; -} NautilusTrashFile; - -typedef struct { - NautilusFileClass parent_slot; -} NautilusTrashFileClass; - -GtkType nautilus_trash_file_get_type (void); - -#endif /* NAUTILUS_TRASH_FILE_H */ diff --git a/libnautilus-extensions/nautilus-trash-monitor.c b/libnautilus-extensions/nautilus-trash-monitor.c deleted file mode 100644 index a392c3d56..000000000 --- a/libnautilus-extensions/nautilus-trash-monitor.c +++ /dev/null @@ -1,290 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ - -/* - nautilus-trash-monitor.c: Nautilus trash state watcher. - - Copyright (C) 2000, 2001 Eazel, Inc. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public - License along with this program; if not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. - - Author: Pavel Cisler <pavel@eazel.com> -*/ - -#include <config.h> -#include "nautilus-trash-monitor.h" - -#include "nautilus-directory-notify.h" -#include "nautilus-directory.h" -#include "nautilus-file-attributes.h" -#include "nautilus-trash-directory.h" -#include <eel/eel-gtk-macros.h> -#include <eel/eel-vfs-extensions.h> -#include <gtk/gtksignal.h> -#include <libgnomevfs/gnome-vfs-find-directory.h> -#include <libgnomevfs/gnome-vfs-types.h> -#include <libgnomevfs/gnome-vfs-uri.h> - -struct NautilusTrashMonitorDetails { - NautilusDirectory *trash_directory; - gboolean empty; -}; - -enum { - TRASH_STATE_CHANGED, - CHECK_TRASH_DIRECTORY_ADDED, - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL]; -static NautilusTrashMonitor *nautilus_trash_monitor; - -static void nautilus_trash_monitor_initialize_class (NautilusTrashMonitorClass *klass); -static void nautilus_trash_monitor_initialize (gpointer object, - gpointer klass); -static void destroy (GtkObject *object); - -EEL_DEFINE_CLASS_BOILERPLATE (NautilusTrashMonitor, nautilus_trash_monitor, GTK_TYPE_OBJECT) - -static void -nautilus_trash_monitor_initialize_class (NautilusTrashMonitorClass *klass) -{ - GtkObjectClass *object_class; - - object_class = GTK_OBJECT_CLASS (klass); - - object_class->destroy = destroy; - - signals[TRASH_STATE_CHANGED] = gtk_signal_new - ("trash_state_changed", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (NautilusTrashMonitorClass, trash_state_changed), - gtk_marshal_NONE__BOOL, - GTK_TYPE_NONE, 1, - GTK_TYPE_BOOL); - - signals[CHECK_TRASH_DIRECTORY_ADDED] = gtk_signal_new - ("check_trash_directory_added", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (NautilusTrashMonitorClass, check_trash_directory_added), - gtk_marshal_NONE__POINTER, - GTK_TYPE_NONE, 1, - GTK_TYPE_POINTER); - - gtk_object_class_add_signals (object_class, signals, LAST_SIGNAL); -} - -static void -nautilus_trash_files_changed_callback (NautilusDirectory *directory, GList *files, - gpointer callback_data) -{ - NautilusTrashMonitor *trash_monitor; - gboolean old_empty_state; - NautilusFile *file; - - trash_monitor = callback_data; - g_assert (NAUTILUS_IS_TRASH_MONITOR (trash_monitor)); - g_assert (trash_monitor->details->trash_directory == directory); - - /* Something about the Trash NautilusDirectory changed, find out if - * it affected the empty state. - */ - old_empty_state = trash_monitor->details->empty; - trash_monitor->details->empty = !nautilus_directory_is_not_empty (directory); - - if (old_empty_state != trash_monitor->details->empty) { - file = nautilus_file_get (EEL_TRASH_URI); - nautilus_file_changed (file); - nautilus_file_unref (file); - - /* trash got empty or full, notify everyone who cares */ - gtk_signal_emit (GTK_OBJECT (trash_monitor), - signals[TRASH_STATE_CHANGED], - trash_monitor->details->empty); - } -} - -static void -nautilus_trash_monitor_initialize (gpointer object, gpointer klass) -{ - NautilusDirectory *trash_directory; - NautilusTrashMonitor *trash_monitor; - GList *attributes; - - trash_monitor = NAUTILUS_TRASH_MONITOR (object); - - /* set up a NautilusDirectory for the Trash directory to monitor */ - - trash_directory = nautilus_directory_get (EEL_TRASH_URI); - - trash_monitor->details = g_new0 (NautilusTrashMonitorDetails, 1); - trash_monitor->details->trash_directory = trash_directory; - trash_monitor->details->empty = TRUE; - - attributes = g_list_append (NULL, NAUTILUS_FILE_ATTRIBUTE_METADATA); - - /* Make sure we get notified about changes */ - nautilus_directory_file_monitor_add - (trash_directory, trash_monitor, TRUE, TRUE, attributes); - - g_list_free (attributes); - - gtk_signal_connect_while_alive - (GTK_OBJECT (trash_directory), - "files_added", - nautilus_trash_files_changed_callback, - trash_monitor, - GTK_OBJECT (trash_monitor)); - gtk_signal_connect_while_alive - (GTK_OBJECT (trash_directory), - "files_changed", - nautilus_trash_files_changed_callback, - trash_monitor, - GTK_OBJECT (trash_monitor)); -} - -static void -destroy (GtkObject *object) -{ - NautilusTrashMonitor *trash_monitor; - - trash_monitor = NAUTILUS_TRASH_MONITOR (object); - - nautilus_directory_file_monitor_remove - (trash_monitor->details->trash_directory, - trash_monitor); - nautilus_directory_unref (trash_monitor->details->trash_directory); - g_free (trash_monitor->details); -} - -static void -unref_trash_monitor (void) -{ - gtk_object_unref (GTK_OBJECT (nautilus_trash_monitor)); -} - -NautilusTrashMonitor * -nautilus_trash_monitor_get (void) -{ - NautilusDirectory *trash_directory; - - if (nautilus_trash_monitor == NULL) { - /* not running yet, start it up */ - - /* the trash directory object will get created by this */ - trash_directory = nautilus_directory_get (EEL_TRASH_URI); - - nautilus_trash_monitor = NAUTILUS_TRASH_MONITOR - (gtk_object_new (NAUTILUS_TYPE_TRASH_MONITOR, NULL)); - gtk_object_ref (GTK_OBJECT (nautilus_trash_monitor)); - gtk_object_sink (GTK_OBJECT (nautilus_trash_monitor)); - g_atexit (unref_trash_monitor); - - /* make sure we get signalled when trash directories get added */ - nautilus_trash_directory_finish_initializing - (NAUTILUS_TRASH_DIRECTORY (trash_directory)); - - nautilus_directory_unref (trash_directory); - } - - return nautilus_trash_monitor; -} - -gboolean -nautilus_trash_monitor_is_empty (void) -{ - return nautilus_trash_monitor_get ()->details->empty; -} - -static gboolean -add_one_volume_trash (const NautilusVolume *volume, - gpointer callback_data) -{ - GnomeVFSURI *volume_mount_point_uri; - GnomeVFSURI *trash_uri; - GList **result; - - result = (GList **)callback_data; - - if (nautilus_volume_monitor_should_integrate_trash (volume)) { - - /* Get the uri of the volume mount point as the place - * "near" which to look for trash on the given volume. - */ - volume_mount_point_uri = gnome_vfs_uri_new ( - nautilus_volume_monitor_get_volume_mount_uri (volume)); - - g_assert (volume_mount_point_uri != NULL); - - /* Look for trash. It is OK to use a sync call here because - * the options we use (don't create, don't look for it if we - * already don't know where it is) do not cause any IO. - */ - if (gnome_vfs_find_directory (volume_mount_point_uri, - GNOME_VFS_DIRECTORY_KIND_TRASH, &trash_uri, - FALSE, FALSE, 0777) == GNOME_VFS_OK) { - - /* found trash, put it on the list */ - *result = g_list_append (*result, trash_uri); - } - - gnome_vfs_uri_unref (volume_mount_point_uri); - } - - /* don't stop iterating */ - return FALSE; -} - -GList * -nautilus_trash_monitor_get_trash_directories (void) -{ - GList *result; - - result = NULL; - - /* Collect the trash directories on all the mounted volumes. */ - nautilus_volume_monitor_each_mounted_volume - (nautilus_volume_monitor_get (), add_one_volume_trash, &result); - - return result; -} - -static gboolean -add_one_trash_directory_if_needed (const NautilusVolume *volume, - gpointer callback_data) -{ - NautilusTrashMonitor *trash_monitor; - - trash_monitor = NAUTILUS_TRASH_MONITOR (callback_data); - gtk_signal_emit (GTK_OBJECT (trash_monitor), - signals[CHECK_TRASH_DIRECTORY_ADDED], - volume); - - return FALSE; -} - -void -nautilus_trash_monitor_add_new_trash_directories (void) -{ - NautilusTrashMonitor *trash_monitor; - - trash_monitor = nautilus_trash_monitor_get (); - nautilus_volume_monitor_each_mounted_volume - (nautilus_volume_monitor_get (), add_one_trash_directory_if_needed, - trash_monitor); -} - diff --git a/libnautilus-extensions/nautilus-trash-monitor.h b/libnautilus-extensions/nautilus-trash-monitor.h deleted file mode 100644 index 7bcf3ff06..000000000 --- a/libnautilus-extensions/nautilus-trash-monitor.h +++ /dev/null @@ -1,70 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ - -/* - nautilus-trash-monitor.h: Nautilus trash state watcher. - - 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. - - Author: Pavel Cisler <pavel@eazel.com> -*/ - -#ifndef NAUTILUS_TRASH_MONITOR_H -#define NAUTILUS_TRASH_MONITOR_H - -#include <gtk/gtkobject.h> -#include <libgnomevfs/gnome-vfs.h> - -#include "nautilus-volume-monitor.h" - -typedef struct NautilusTrashMonitor NautilusTrashMonitor; -typedef struct NautilusTrashMonitorClass NautilusTrashMonitorClass; -typedef struct NautilusTrashMonitorDetails NautilusTrashMonitorDetails; - -#define NAUTILUS_TYPE_TRASH_MONITOR \ - (nautilus_trash_monitor_get_type ()) -#define NAUTILUS_TRASH_MONITOR(obj) \ - (GTK_CHECK_CAST ((obj), NAUTILUS_TYPE_TRASH_MONITOR, NautilusTrashMonitor)) -#define NAUTILUS_TRASH_MONITOR_CLASS(klass) \ - (GTK_CHECK_CLASS_CAST ((klass), NAUTILUS_TYPE_TRASH_MONITOR, NautilusTrashMonitorClass)) -#define NAUTILUS_IS_TRASH_MONITOR(obj) \ - (GTK_CHECK_TYPE ((obj), NAUTILUS_TYPE_TRASH_MONITOR)) -#define NAUTILUS_IS_TRASH_MONITOR_CLASS(klass) \ - (GTK_CHECK_CLASS_TYPE ((klass), NAUTILUS_TYPE_TRASH_MONITOR)) - -struct NautilusTrashMonitor { - GtkObject object; - NautilusTrashMonitorDetails *details; -}; - -struct NautilusTrashMonitorClass { - GtkObjectClass parent_class; - - void (* trash_state_changed) (NautilusTrashMonitor *trash_monitor, - gboolean new_state); - void (* check_trash_directory_added) (NautilusTrashMonitor *trash_monitor, - NautilusVolume *volume); -}; - -GtkType nautilus_trash_monitor_get_type (void); - -NautilusTrashMonitor *nautilus_trash_monitor_get (void); -gboolean nautilus_trash_monitor_is_empty (void); -GList * nautilus_trash_monitor_get_trash_directories (void); -void nautilus_trash_monitor_add_new_trash_directories (void); - -#endif diff --git a/libnautilus-extensions/nautilus-undo-context.c b/libnautilus-extensions/nautilus-undo-context.c deleted file mode 100644 index 279d010b9..000000000 --- a/libnautilus-extensions/nautilus-undo-context.c +++ /dev/null @@ -1,163 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ - -/* NautilusUndoContext - Used internally by undo machinery. - * Not public. - * - * Copyright (C) 2000 Eazel, Inc. - * - * Author: Gene Z. Ragan <gzr@eazel.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. - * - * This 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; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#include <config.h> -#include "nautilus-undo-context.h" - -#include <eel/eel-gtk-macros.h> -#include <bonobo/bonobo-main.h> -#include <gtk/gtksignal.h> -#include <libnautilus/nautilus-bonobo-workarounds.h> - -typedef struct { - POA_Nautilus_Undo_Context servant; - NautilusUndoContext *bonobo_object; -} impl_POA_Nautilus_Undo_Context; - -/* GtkObject */ -static void nautilus_undo_context_initialize_class (NautilusUndoContextClass *class); -static void nautilus_undo_context_initialize (NautilusUndoContext *item); -static void destroy (GtkObject *object); - -/* CORBA/Bonobo */ -static Nautilus_Undo_Manager impl_Nautilus_Undo_Context__get_undo_manager (PortableServer_Servant servant, - CORBA_Environment *ev); - -EEL_DEFINE_CLASS_BOILERPLATE (NautilusUndoContext, nautilus_undo_context, BONOBO_OBJECT_TYPE) - -POA_Nautilus_Undo_Context__epv libnautilus_Nautilus_Undo_Context_epv = -{ - NULL, /* _private */ - &impl_Nautilus_Undo_Context__get_undo_manager, -}; - -static PortableServer_ServantBase__epv base_epv; -static POA_Nautilus_Undo_Context__vepv vepv = -{ - &base_epv, - NULL, - &libnautilus_Nautilus_Undo_Context_epv -}; - -static void -impl_Nautilus_Undo_Context__destroy (BonoboObject *object, - PortableServer_Servant servant) -{ - PortableServer_ObjectId *object_id; - CORBA_Environment ev; - - CORBA_exception_init (&ev); - - object_id = PortableServer_POA_servant_to_id (bonobo_poa (), servant, &ev); - PortableServer_POA_deactivate_object (bonobo_poa (), object_id, &ev); - CORBA_free (object_id); - object->servant = NULL; - - POA_Nautilus_Undo_Context__fini (servant, &ev); - g_free (servant); - - CORBA_exception_free (&ev); -} - -static Nautilus_Undo_Context -impl_Nautilus_Undo_Context__create (NautilusUndoContext *bonobo_object, - CORBA_Environment *ev) -{ - impl_POA_Nautilus_Undo_Context *servant; - - servant = g_new0 (impl_POA_Nautilus_Undo_Context, 1); - servant->servant.vepv = &vepv; - vepv.Bonobo_Unknown_epv = nautilus_bonobo_object_get_epv (); - POA_Nautilus_Undo_Context__init ((PortableServer_Servant) servant, ev); - - gtk_signal_connect (GTK_OBJECT (bonobo_object), "destroy", - GTK_SIGNAL_FUNC (impl_Nautilus_Undo_Context__destroy), - servant); - - servant->bonobo_object = bonobo_object; - return bonobo_object_activate_servant (BONOBO_OBJECT (bonobo_object), servant); -} - -static Nautilus_Undo_Manager -impl_Nautilus_Undo_Context__get_undo_manager (PortableServer_Servant servant, - CORBA_Environment *ev) -{ - NautilusUndoContext *context; - - context = ((impl_POA_Nautilus_Undo_Context *) servant)->bonobo_object; - g_assert (NAUTILUS_IS_UNDO_CONTEXT (context)); - return CORBA_Object_duplicate (context->undo_manager, ev); -} - -NautilusUndoContext * -nautilus_undo_context_new (Nautilus_Undo_Manager undo_manager) -{ - CORBA_Environment ev; - NautilusUndoContext *context; - - CORBA_exception_init (&ev); - - context = NAUTILUS_UNDO_CONTEXT (gtk_object_new (nautilus_undo_context_get_type (), NULL)); - context->undo_manager = CORBA_Object_duplicate (undo_manager, &ev); - - CORBA_exception_free (&ev); - - return context; -} - -static void -nautilus_undo_context_initialize (NautilusUndoContext *context) -{ - CORBA_Environment ev; - - CORBA_exception_init (&ev); - - bonobo_object_construct (BONOBO_OBJECT (context), - impl_Nautilus_Undo_Context__create (context, &ev)); - - CORBA_exception_free (&ev); -} - -static void -destroy (GtkObject *object) -{ - CORBA_Environment ev; - NautilusUndoContext *context; - - CORBA_exception_init (&ev); - - context = NAUTILUS_UNDO_CONTEXT (object); - CORBA_Object_release (context->undo_manager, &ev); - - CORBA_exception_free (&ev); - - EEL_CALL_PARENT (GTK_OBJECT_CLASS, destroy, (object)); -} - -static void -nautilus_undo_context_initialize_class (NautilusUndoContextClass *klass) -{ - GTK_OBJECT_CLASS (klass)->destroy = destroy; -} diff --git a/libnautilus-extensions/nautilus-undo-context.h b/libnautilus-extensions/nautilus-undo-context.h deleted file mode 100644 index 2559f764e..000000000 --- a/libnautilus-extensions/nautilus-undo-context.h +++ /dev/null @@ -1,55 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ - -/* NautilusUndoContext - Used internally by undo machinery. - * Not public. - * - * Copyright (C) 2000 Eazel, Inc. - * - * Author: Gene Z. Ragan <gzr@eazel.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. - * - * This 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; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef NAUTILUS_UNDO_CONTEXT_H -#define NAUTILUS_UNDO_CONTEXT_H - -#include <bonobo/bonobo-object.h> -#include <libnautilus/nautilus-distributed-undo.h> - -#define NAUTILUS_TYPE_UNDO_CONTEXT \ - (nautilus_undo_context_get_type ()) -#define NAUTILUS_UNDO_CONTEXT(obj) \ - (GTK_CHECK_CAST ((obj), NAUTILUS_TYPE_UNDO_CONTEXT, NautilusUndoContext)) -#define NAUTILUS_UNDO_CONTEXT_CLASS(klass) \ - (GTK_CHECK_CLASS_CAST ((klass), NAUTILUS_TYPE_UNDO_CONTEXT, NautilusUndoContextClass)) -#define NAUTILUS_IS_UNDO_CONTEXT(obj) \ - (GTK_CHECK_TYPE ((obj), NAUTILUS_TYPE_UNDO_CONTEXT)) -#define NAUTILUS_IS_UNDO_CONTEXT_CLASS(klass) \ - (GTK_CHECK_CLASS_TYPE ((klass), NAUTILUS_TYPE_UNDO_CONTEXT)) - -typedef struct { - BonoboObject parent_slot; - Nautilus_Undo_Manager undo_manager; -} NautilusUndoContext; - -typedef struct { - BonoboObjectClass parent_slot; -} NautilusUndoContextClass; - -GtkType nautilus_undo_context_get_type (void); -NautilusUndoContext *nautilus_undo_context_new (Nautilus_Undo_Manager undo_manager); - -#endif /* NAUTILUS_UNDO_CONTEXT_H */ diff --git a/libnautilus-extensions/nautilus-undo-manager.c b/libnautilus-extensions/nautilus-undo-manager.c deleted file mode 100644 index ea92de5e0..000000000 --- a/libnautilus-extensions/nautilus-undo-manager.c +++ /dev/null @@ -1,444 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ - -/* NautilusUndoManager - Undo/Redo transaction manager. - * - * Copyright (C) 2000 Eazel, Inc. - * - * Author: Gene Z. Ragan <gzr@eazel.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. - * - * This 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; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#include <config.h> -#include "nautilus-undo-manager.h" - -#include <eel/eel-gtk-macros.h> -#include <eel/eel-gtk-extensions.h> -#include <gtk/gtksignal.h> -#include <bonobo/bonobo-main.h> -#include <libnautilus/nautilus-bonobo-workarounds.h> -#include <libnautilus/nautilus-undo-private.h> -#include "nautilus-undo-context.h" - -struct NautilusUndoManagerDetails { - Nautilus_Undo_Transaction transaction; - - /* These are used to tell undo from redo. */ - gboolean current_transaction_is_redo; - gboolean new_transaction_is_redo; - - /* These are used only so that we can complain if we get more - * than one transaction inside undo. - */ - gboolean undo_in_progress; - int num_transactions_during_undo; -}; - -enum { - CHANGED, - LAST_SIGNAL -}; -static guint signals[LAST_SIGNAL]; - -typedef struct { - POA_Nautilus_Undo_Manager servant; - NautilusUndoManager *bonobo_object; -} UndoManagerServant; - -typedef struct { -#ifdef UIH - BonoboUIHandler *handler; -#endif /* UIH */ - char *path; - char *no_undo_menu_item_label; - char *no_undo_menu_item_hint; -} UndoMenuHandlerConnection; - -/* GtkObject */ -static void nautilus_undo_manager_initialize_class (NautilusUndoManagerClass *class); -static void nautilus_undo_manager_initialize (NautilusUndoManager *item); -static void destroy (GtkObject *object); - -/* CORBA/Bonobo */ -static void corba_append (PortableServer_Servant servant, - Nautilus_Undo_Transaction transaction, - CORBA_Environment *ev); -static void corba_forget (PortableServer_Servant servant, - Nautilus_Undo_Transaction transaction, - CORBA_Environment *ev); -static void corba_undo (PortableServer_Servant servant, - CORBA_Environment *ev); - -EEL_DEFINE_CLASS_BOILERPLATE (NautilusUndoManager, nautilus_undo_manager, BONOBO_OBJECT_TYPE) - -static PortableServer_ServantBase__epv base_epv; -static POA_Nautilus_Undo_Manager__epv epv = { - NULL, - &corba_append, - &corba_forget, - &corba_undo, -}; -static POA_Nautilus_Undo_Manager__vepv vepv = { - &base_epv, - NULL, - &epv -}; - -static void -destroy_servant (BonoboObject *object, - UndoManagerServant *servant) -{ - PortableServer_ObjectId *object_id; - CORBA_Environment ev; - - CORBA_exception_init (&ev); - - /* Deactivate the object. */ - object_id = PortableServer_POA_servant_to_id (bonobo_poa (), servant, &ev); - PortableServer_POA_deactivate_object (bonobo_poa (), object_id, &ev); - CORBA_free (object_id); - - /* Disconnect the object from the servant. */ - object->servant = NULL; - - /* Free the servant. */ - POA_Nautilus_Undo_Manager__fini (servant, &ev); - g_free (servant); - - CORBA_exception_free (&ev); -} - -static Nautilus_Undo_Manager -create_servant (NautilusUndoManager *bonobo_object, - CORBA_Environment *ev) -{ - UndoManagerServant *servant; - - /* Create the servant. */ - servant = g_new0 (UndoManagerServant, 1); - servant->servant.vepv = &vepv; - servant->bonobo_object = bonobo_object; - POA_Nautilus_Undo_Manager__init ((PortableServer_Servant) servant, ev); - - /* Set up code so we will destroy the servant when the bonobo_object is destroyed. */ - gtk_signal_connect (GTK_OBJECT (bonobo_object), "destroy", - destroy_servant, servant); - - /* Activate the servant to create the CORBA object. */ - return bonobo_object_activate_servant (BONOBO_OBJECT (bonobo_object), servant); -} - -static void -release_transaction (NautilusUndoManager *manager) -{ - Nautilus_Undo_Transaction transaction; - - CORBA_Environment ev; - - CORBA_exception_init (&ev); - - transaction = manager->details->transaction; - manager->details->transaction = CORBA_OBJECT_NIL; - if (!CORBA_Object_is_nil (transaction, &ev)) { - bonobo_object_release_unref (transaction, &ev); - } - - CORBA_exception_free (&ev); -} - -static void -corba_append (PortableServer_Servant servant, - Nautilus_Undo_Transaction transaction, - CORBA_Environment *ev) -{ - NautilusUndoManager *manager; - Nautilus_Undo_Transaction duplicate_transaction; - - manager = ((UndoManagerServant *) servant)->bonobo_object; - g_assert (NAUTILUS_IS_UNDO_MANAGER (manager)); - - /* Check, complain, and ignore the passed-in transaction if we - * get more than one within a single undo operation. The single - * transaction we get during the undo operation is supposed to - * be the one for redoing the undo (or re-undoing the redo). - */ - if (manager->details->undo_in_progress) { - manager->details->num_transactions_during_undo += 1; - g_return_if_fail (manager->details->num_transactions_during_undo == 1); - } - - g_return_if_fail (!CORBA_Object_is_nil (transaction, ev)); - - /* Keep a copy of this transaction (dump the old one). */ - duplicate_transaction = CORBA_Object_duplicate (transaction, ev); - Nautilus_Undo_Transaction_ref (duplicate_transaction, ev); - release_transaction (manager); - manager->details->transaction = duplicate_transaction; - manager->details->current_transaction_is_redo = - manager->details->new_transaction_is_redo; - - /* Fire off signal indicating that the undo state has changed. */ - gtk_signal_emit (GTK_OBJECT (manager), signals[CHANGED]); -} - -static void -corba_forget (PortableServer_Servant servant, - Nautilus_Undo_Transaction transaction, - CORBA_Environment *ev) -{ - NautilusUndoManager *manager; - - manager = ((UndoManagerServant *) servant)->bonobo_object; - g_assert (NAUTILUS_IS_UNDO_MANAGER (manager)); - - /* Nothing to forget unless the item we are passed is the - * transaction we are currently holding. - */ - if (!CORBA_Object_is_equivalent (manager->details->transaction, transaction, ev)) { - return; - } - - /* Get rid of the transaction we are holding on to. */ - release_transaction (manager); - - /* Fire off signal indicating that the undo state has changed. */ - gtk_signal_emit (GTK_OBJECT (manager), signals[CHANGED]); -} - -static void -corba_undo (PortableServer_Servant servant, - CORBA_Environment *ev) -{ - NautilusUndoManager *manager; - - manager = ((UndoManagerServant *) servant)->bonobo_object; - g_assert (NAUTILUS_IS_UNDO_MANAGER (manager)); - - nautilus_undo_manager_undo (manager); -} - -NautilusUndoManager * -nautilus_undo_manager_new (void) -{ - return NAUTILUS_UNDO_MANAGER (gtk_object_new (nautilus_undo_manager_get_type (), NULL)); -} - -static void -nautilus_undo_manager_initialize (NautilusUndoManager *manager) -{ - CORBA_Environment ev; - - CORBA_exception_init (&ev); - - manager->details = g_new0 (NautilusUndoManagerDetails, 1); - - bonobo_object_construct (BONOBO_OBJECT (manager), - create_servant (manager, &ev)); - - CORBA_exception_free (&ev); -} - -static void -nautilus_undo_manager_initialize_class (NautilusUndoManagerClass *klass) -{ - GtkObjectClass *object_class; - - vepv.Bonobo_Unknown_epv = nautilus_bonobo_object_get_epv (); - - object_class = GTK_OBJECT_CLASS (klass); - - object_class->destroy = destroy; - - signals[CHANGED] = gtk_signal_new - ("changed", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (NautilusUndoManagerClass, - changed), - gtk_marshal_NONE__NONE, - GTK_TYPE_NONE, 0); - - gtk_object_class_add_signals (object_class, signals, LAST_SIGNAL); -} - -void -nautilus_undo_manager_undo (NautilusUndoManager *manager) -{ - CORBA_Environment ev; - Nautilus_Undo_Transaction transaction; - - g_return_if_fail (NAUTILUS_IS_UNDO_MANAGER (manager)); - - CORBA_exception_init (&ev); - - transaction = manager->details->transaction; - manager->details->transaction = CORBA_OBJECT_NIL; - if (!CORBA_Object_is_nil (transaction, &ev)) { - /* Perform the undo. New transactions that come in - * during an undo are redo transactions. New - * transactions that come in during a redo are undo - * transactions. Transactions that come in outside - * are always undo and never redo. - */ - manager->details->new_transaction_is_redo = - !manager->details->current_transaction_is_redo; - manager->details->undo_in_progress = TRUE; - manager->details->num_transactions_during_undo = 0; - Nautilus_Undo_Transaction_undo (transaction, &ev); - manager->details->undo_in_progress = FALSE; - manager->details->new_transaction_is_redo = FALSE; - - /* Let go of the transaction. */ - bonobo_object_release_unref (transaction, &ev); - - /* Fire off signal indicating the undo state has changed. */ - gtk_signal_emit (GTK_OBJECT (manager), signals[CHANGED]); - } - - CORBA_exception_free (&ev); -} - -static void -destroy (GtkObject *object) -{ - NautilusUndoManager *manager; - - manager = NAUTILUS_UNDO_MANAGER (object); - - release_transaction (manager); - - EEL_CALL_PARENT (GTK_OBJECT_CLASS, destroy, (object)); -} - -void -nautilus_undo_manager_attach (NautilusUndoManager *manager, GtkObject *target) -{ - g_return_if_fail (NAUTILUS_IS_UNDO_MANAGER (manager)); - g_return_if_fail (GTK_IS_OBJECT (target)); - - nautilus_undo_attach_undo_manager - (target, - bonobo_object_corba_objref (BONOBO_OBJECT (manager))); -} - -void -nautilus_undo_manager_add_interface (NautilusUndoManager *manager, BonoboObject *object) -{ - NautilusUndoContext *context; - - g_return_if_fail (NAUTILUS_IS_UNDO_MANAGER (manager)); - g_return_if_fail (BONOBO_IS_OBJECT (object)); - - context = nautilus_undo_context_new (bonobo_object_corba_objref (BONOBO_OBJECT (manager))); - bonobo_object_add_interface (object, BONOBO_OBJECT (context)); -} - -#ifdef UIH -static void -update_undo_menu_item (NautilusUndoManager *manager, - UndoMenuHandlerConnection *connection) -{ - CORBA_Environment ev; - Nautilus_Undo_MenuItem *menu_item; - - g_assert (NAUTILUS_IS_UNDO_MANAGER (manager)); - g_assert (connection != NULL); - g_assert (BONOBO_IS_UI_HANDLER (connection->handler)); - g_assert (connection->path != NULL); - g_assert (connection->no_undo_menu_item_label != NULL); - g_assert (connection->no_undo_menu_item_hint != NULL); - - CORBA_exception_init (&ev); - - if (CORBA_Object_is_nil (manager->details->transaction, &ev)) { - menu_item = NULL; - } else { - if (manager->details->current_transaction_is_redo) { - menu_item = Nautilus_Undo_Transaction__get_redo_menu_item - (manager->details->transaction, &ev); - } else { - menu_item = Nautilus_Undo_Transaction__get_undo_menu_item - (manager->details->transaction, &ev); - } - } - - bonobo_ui_handler_menu_set_sensitivity - (connection->handler, connection->path, - menu_item != NULL); - bonobo_ui_handler_menu_set_label - (connection->handler, connection->path, - menu_item == NULL - ? connection->no_undo_menu_item_label - : menu_item->label); - bonobo_ui_handler_menu_set_hint - (connection->handler, connection->path, - menu_item == NULL - ? connection->no_undo_menu_item_hint - : menu_item->hint); - - CORBA_free (menu_item); - - CORBA_exception_free (&ev); -} - -static void -undo_menu_handler_connection_free (UndoMenuHandlerConnection *connection) -{ - g_assert (connection != NULL); - g_assert (BONOBO_IS_UI_HANDLER (connection->handler)); - g_assert (connection->path != NULL); - g_assert (connection->no_undo_menu_item_label != NULL); - g_assert (connection->no_undo_menu_item_hint != NULL); - - g_free (connection->path); - g_free (connection->no_undo_menu_item_label); - g_free (connection->no_undo_menu_item_hint); - g_free (connection); -} - -static void -undo_menu_handler_connection_free_cover (gpointer data) -{ - undo_menu_handler_connection_free (data); -} - -void -nautilus_undo_manager_set_up_bonobo_ui_handler_undo_item (NautilusUndoManager *manager, - BonoboUIHandler *handler, - const char *path, - const char *no_undo_menu_item_label, - const char *no_undo_menu_item_hint) -{ - UndoMenuHandlerConnection *connection; - - connection = g_new (UndoMenuHandlerConnection, 1); - connection->handler = handler; - connection->path = g_strdup (path); - connection->no_undo_menu_item_label = g_strdup (no_undo_menu_item_label); - connection->no_undo_menu_item_hint = g_strdup (no_undo_menu_item_hint); - - /* Set initial state of menu item. */ - update_undo_menu_item (manager, connection); - - /* Update it again whenever the changed signal is emitted. */ - eel_gtk_signal_connect_full_while_alive - (GTK_OBJECT (manager), "changed", - GTK_SIGNAL_FUNC (update_undo_menu_item), NULL, - connection, undo_menu_handler_connection_free_cover, - FALSE, FALSE, - GTK_OBJECT (handler)); -} -#endif /* UIH */ diff --git a/libnautilus-extensions/nautilus-undo-manager.h b/libnautilus-extensions/nautilus-undo-manager.h deleted file mode 100644 index 354ba6034..000000000 --- a/libnautilus-extensions/nautilus-undo-manager.h +++ /dev/null @@ -1,78 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ - -/* NautilusUndoManager - Manages undo and redo transactions. - * This is the public interface used by the application. - * - * Copyright (C) 2000 Eazel, Inc. - * - * Author: Gene Z. Ragan <gzr@eazel.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. - * - * This 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; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef NAUTILUS_UNDO_MANAGER_H -#define NAUTILUS_UNDO_MANAGER_H - -#include <bonobo/bonobo-object.h> - -#define NAUTILUS_TYPE_UNDO_MANAGER \ - (nautilus_undo_manager_get_type ()) -#define NAUTILUS_UNDO_MANAGER(obj) \ - (GTK_CHECK_CAST ((obj), NAUTILUS_TYPE_UNDO_MANAGER, NautilusUndoManager)) -#define NAUTILUS_UNDO_MANAGER_CLASS(klass) \ - (GTK_CHECK_CLASS_CAST ((klass), NAUTILUS_TYPE_UNDO_MANAGER, NautilusUndoManagerClass)) -#define NAUTILUS_IS_UNDO_MANAGER(obj) \ - (GTK_CHECK_TYPE ((obj), NAUTILUS_TYPE_UNDO_MANAGER)) -#define NAUTILUS_IS_UNDO_MANAGER_CLASS(klass) \ - (GTK_CHECK_CLASS_TYPE ((klass), NAUTILUS_TYPE_UNDO_MANAGER)) - -typedef struct NautilusUndoManagerDetails NautilusUndoManagerDetails; - -typedef struct { - BonoboObject parent; - NautilusUndoManagerDetails *details; -} NautilusUndoManager; - -typedef struct { - BonoboObjectClass parent_slot; - void (* changed) (GtkObject *object, gpointer data); -} NautilusUndoManagerClass; - -GtkType nautilus_undo_manager_get_type (void); -NautilusUndoManager *nautilus_undo_manager_new (void); - -/* Undo operations. */ -void nautilus_undo_manager_undo (NautilusUndoManager *undo_manager); - -#ifdef UIH -/* Connect the manager to a particular menu item. */ -void nautilus_undo_manager_set_up_bonobo_ui_handler_undo_item (NautilusUndoManager *manager, - BonoboUIHandler *handler, - const char *path, - const char *no_undo_menu_item_label, - const char *no_undo_menu_item_hint); - -#endif - -/* Attach the undo manager to a Gtk object so that object and the widgets inside it can participate in undo. */ -void nautilus_undo_manager_attach (NautilusUndoManager *manager, - GtkObject *object); - -/* Attach the undo manager to a Bonobo object so another component can find it. */ -void nautilus_undo_manager_add_interface (NautilusUndoManager *manager, - BonoboObject *object); - -#endif /* NAUTILUS_UNDO_MANAGER_H */ diff --git a/libnautilus-extensions/nautilus-undo-signal-handlers.c b/libnautilus-extensions/nautilus-undo-signal-handlers.c deleted file mode 100644 index 2d55ae555..000000000 --- a/libnautilus-extensions/nautilus-undo-signal-handlers.c +++ /dev/null @@ -1,344 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ - -/* Signal handlers to enable undo in Gtk Widgets. - * - * Copyright (C) 2000 Eazel, Inc. - * - * Author: Gene Z. Ragan <gzr@eazel.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. - * - * This 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; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - - -#include <config.h> -#include <gtk/gtk.h> - -#include <libgnome/gnome-defs.h> -#include <libgnome/gnome-i18n.h> -#include <libnautilus/nautilus-undo.h> - -#include <eel/eel-gtk-macros.h> - -#include "nautilus-undo-signal-handlers.h" - - -typedef struct { - char *undo_text; - gint position; - guint selection_start; - guint selection_end; -} EditableUndoData; - -typedef struct { - gboolean undo_registered; -} EditableUndoObjectData; - - -static void restore_editable_from_undo_snapshot_callback (GtkObject *target, - gpointer callback_data); -static void editable_register_edit_undo (GtkEditable *editable); -static void free_editable_object_data (gpointer data); - -/* nautilus_undo_set_up_nautilus_entry_for_undo - * - * Functions and callback methods to handle undo - * in a NautilusEntry - */ - -static void -nautilus_entry_user_changed_callback (NautilusEntry *entry) -{ - /* Register undo transaction */ - editable_register_edit_undo (GTK_EDITABLE (entry)); -} - -void -nautilus_undo_set_up_nautilus_entry_for_undo (NautilusEntry *entry) -{ - EditableUndoObjectData *data; - - if (!NAUTILUS_IS_ENTRY (entry) ) { - return; - } - - data = g_new(EditableUndoObjectData, 1); - data->undo_registered = FALSE; - gtk_object_set_data_full (GTK_OBJECT (entry), "undo_registered", - data, free_editable_object_data); - - /* Connect to entry signals */ - gtk_signal_connect (GTK_OBJECT (entry), - "user_changed", - GTK_SIGNAL_FUNC (nautilus_entry_user_changed_callback), - NULL); -} - -void -nautilus_undo_tear_down_nautilus_entry_for_undo (NautilusEntry *entry) -{ - if (!NAUTILUS_IS_ENTRY (entry) ) { - return; - } - - /* Disconnect from entry signals */ - gtk_signal_disconnect_by_func (GTK_OBJECT (entry), - GTK_SIGNAL_FUNC (nautilus_entry_user_changed_callback), - NULL); - -} - -/* nautilus_undo_set_up_nautilus_entry_for_undo - * - * Functions and callback methods to handle undo - * in a NautilusEntry - */ - -static void -free_editable_undo_data (gpointer data) -{ - EditableUndoData *undo_data; - - undo_data = (EditableUndoData *) data; - - g_free (undo_data->undo_text); - g_free (undo_data); -} - -static void -free_editable_object_data (gpointer data) -{ - g_free (data); -} - - -static void -editable_insert_text_callback (GtkEditable *editable) -{ - /* Register undo transaction */ - editable_register_edit_undo (editable); -} - -static void -editable_delete_text_callback (GtkEditable *editable) -{ - /* Register undo transaction */ - editable_register_edit_undo (editable); -} - -static void -editable_register_edit_undo (GtkEditable *editable) -{ - EditableUndoData *undo_data; - EditableUndoObjectData *undo_info; - gpointer data; - - if (!GTK_IS_EDITABLE (editable) ) { - return; - } - - /* Check our undo registered flag */ - data = gtk_object_get_data (GTK_OBJECT (editable), "undo_registered"); - if (data == NULL) { - g_warning ("Undo data is NULL"); - return; - } - - undo_info = (EditableUndoObjectData *)data; - if (undo_info->undo_registered) { - return; - } - - undo_data = g_new (EditableUndoData, 1); - undo_data->undo_text = g_strdup (gtk_editable_get_chars (editable, 0, -1)); - undo_data->position = gtk_editable_get_position (editable); - undo_data->selection_start = editable->selection_start_pos; - undo_data->selection_end = editable->selection_end_pos; - - nautilus_undo_register - (GTK_OBJECT (editable), - restore_editable_from_undo_snapshot_callback, - undo_data, - (GDestroyNotify) free_editable_undo_data, - _("Edit"), - _("Undo Edit"), - _("Undo the edit"), - _("Redo Edit"), - _("Redo the edit")); - - undo_info->undo_registered = TRUE; -} - -void -nautilus_undo_set_up_editable_for_undo (GtkEditable *editable) -{ - EditableUndoObjectData *data; - - if (!GTK_IS_EDITABLE (editable) ) { - return; - } - - /* Connect to editable signals */ - gtk_signal_connect (GTK_OBJECT (editable), - "insert_text", - GTK_SIGNAL_FUNC (editable_insert_text_callback), - NULL); - - gtk_signal_connect (GTK_OBJECT (editable), - "delete_text", - GTK_SIGNAL_FUNC (editable_delete_text_callback), - NULL); - - - data = g_new (EditableUndoObjectData, 1); - data->undo_registered = FALSE; - gtk_object_set_data_full (GTK_OBJECT (editable), "undo_registered", - data, free_editable_object_data); -} - -void -nautilus_undo_tear_down_editable_for_undo (GtkEditable *editable) -{ - if (!GTK_IS_EDITABLE (editable) ) { - return; - } - - /* Disconnect from entry signals */ - gtk_signal_disconnect_by_func (GTK_OBJECT (editable), - GTK_SIGNAL_FUNC (editable_insert_text_callback), - NULL); - - gtk_signal_disconnect_by_func (GTK_OBJECT (editable), - GTK_SIGNAL_FUNC (editable_delete_text_callback), - NULL); -} - -/* restore_editable_from_undo_snapshot_callback - * - * Restore edited text. - */ -static void -restore_editable_from_undo_snapshot_callback (GtkObject *target, gpointer callback_data) -{ - GtkEditable *editable; - GtkWindow *window; - EditableUndoData *undo_data; - EditableUndoObjectData *data; - gint position; - - editable = GTK_EDITABLE (target); - undo_data = (EditableUndoData *) callback_data; - - /* Check our undo registered flag */ - data = gtk_object_get_data (target, "undo_registered"); - if (data == NULL) { - g_warning ("Undo regisetred flag not found"); - return; - } - - /* Reset the registered flag so we get a new item for future editing. */ - data->undo_registered = FALSE; - - /* Register a new undo transaction for redo. */ - editable_register_edit_undo (editable); - - /* Restore the text. */ - position = 0; - gtk_editable_delete_text (editable, 0, -1); - gtk_editable_insert_text (editable, undo_data->undo_text, - strlen (undo_data->undo_text), &position); - - /* Set focus to widget */ - window = GTK_WINDOW (gtk_widget_get_toplevel ( GTK_WIDGET (target))); - gtk_window_set_focus (window, GTK_WIDGET (editable)); - - /* We have to do this call, because the previous call selects all text */ - gtk_editable_select_region (editable, 0, 0); - - /* Restore selection */ - gtk_editable_select_region (editable, undo_data->selection_start, - undo_data->selection_end); - - /* Set the i-beam to the saved position */ - gtk_editable_set_position (editable, undo_data->position); - - /* Reset the registered flag so we get a new item for future editing. */ - data->undo_registered = FALSE; -} - - -/* editable_set_undo_key - * - * Allow the use of ctrl-z from within widget. - */ - -/* Undo is disabled until we have a better implementation. - * Both here and in nautilus-shell-ui.xml. - */ - -/* FIXME bugzilla.eazel.com 3515: Undo doesn't work */ -#ifdef UNDO_ENABLED - -static gboolean -editable_key_press_event (GtkEditable *editable, GdkEventKey *event, gpointer user_data) -{ - switch (event->keyval) { - /* Undo */ - case 'z': - if ((event->state & GDK_CONTROL_MASK) != 0) { - nautilus_undo (GTK_OBJECT (editable)); - gtk_signal_emit_stop_by_name (GTK_OBJECT (editable), - "key_press_event"); - return TRUE; - } - break; - - default: - break; - } - - return FALSE; -} - -#endif - -/* editable_set_undo_key - * - * Allow the use of ctrl-z from within widget. This should only be - * set if there is no menu bar to use to undo the widget. - */ - -void -nautilus_undo_editable_set_undo_key (GtkEditable *editable, gboolean value) -{ -/* FIXME bugzilla.eazel.com 3515: Undo doesn't work */ -#ifdef UNDO_ENABLED - if (value) { - /* Connect to entry signals */ - gtk_signal_connect (GTK_OBJECT (editable), - "key_press_event", - GTK_SIGNAL_FUNC (editable_key_press_event), - NULL); - } else { - /* FIXME bugzilla.eazel.com 5092: Warns if the handler - * is not already connected. We could use object data - * to prevent that little problem. - */ - gtk_signal_disconnect_by_func (GTK_OBJECT (editable), - GTK_SIGNAL_FUNC (editable_key_press_event), - NULL); - } -#endif -} diff --git a/libnautilus-extensions/nautilus-undo-signal-handlers.h b/libnautilus-extensions/nautilus-undo-signal-handlers.h deleted file mode 100644 index bd2acf707..000000000 --- a/libnautilus-extensions/nautilus-undo-signal-handlers.h +++ /dev/null @@ -1,37 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ - -/* Signal handlers to enable undo in Gtk Widgets. - * - * Copyright (C) 2000 Eazel, Inc. - * - * Author: Gene Z. Ragan <gzr@eazel.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. - * - * This 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; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef NAUTILUS_UNDO_SIGNAL_HANDLERS_H -#define NAUTILUS_UNDO_SIGNAL_HANDLERS_H - -#include <libnautilus-extensions/nautilus-entry.h> - -void nautilus_undo_set_up_nautilus_entry_for_undo (NautilusEntry *entry); -void nautilus_undo_tear_down_nautilus_entry_for_undo (NautilusEntry *entry); -void nautilus_undo_set_up_editable_for_undo (GtkEditable *editable); -void nautilus_undo_tear_down_editable_for_undo (GtkEditable *editable); -void nautilus_undo_editable_set_undo_key (GtkEditable *editable, - gboolean value); - -#endif /* NAUTILUS_UNDO_SIGNAL_HANDLERS_H */ diff --git a/libnautilus-extensions/nautilus-vfs-directory.c b/libnautilus-extensions/nautilus-vfs-directory.c deleted file mode 100644 index 946315aca..000000000 --- a/libnautilus-extensions/nautilus-vfs-directory.c +++ /dev/null @@ -1,188 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- - - nautilus-vfs-directory.c: Subclass of NautilusDirectory to help implement the - virtual trash directory. - - Copyright (C) 1999, 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. - - Author: Darin Adler <darin@eazel.com> -*/ - -#include <config.h> -#include "nautilus-vfs-directory.h" - -#include "nautilus-directory-private.h" -#include <eel/eel-gtk-macros.h> -#include "nautilus-file-private.h" - -struct NautilusVFSDirectoryDetails { -}; - -static void nautilus_vfs_directory_initialize (gpointer object, - gpointer klass); -static void nautilus_vfs_directory_initialize_class (gpointer klass); - -EEL_DEFINE_CLASS_BOILERPLATE (NautilusVFSDirectory, - nautilus_vfs_directory, - NAUTILUS_TYPE_DIRECTORY) - -static void -nautilus_vfs_directory_initialize (gpointer object, gpointer klass) -{ - NautilusVFSDirectory *directory; - - directory = NAUTILUS_VFS_DIRECTORY (object); - - directory->details = g_new0 (NautilusVFSDirectoryDetails, 1); -} - -static void -vfs_destroy (GtkObject *object) -{ - EEL_CALL_PARENT (GTK_OBJECT_CLASS, destroy, (object)); -} - -static gboolean -vfs_contains_file (NautilusDirectory *directory, - NautilusFile *file) -{ - g_assert (NAUTILUS_IS_VFS_DIRECTORY (directory)); - g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE); - - return file->details->directory == directory; -} - -static void -vfs_call_when_ready (NautilusDirectory *directory, - GList *file_attributes, - NautilusDirectoryCallback callback, - gpointer callback_data) -{ - g_assert (NAUTILUS_IS_VFS_DIRECTORY (directory)); - - nautilus_directory_call_when_ready_internal - (directory, - NULL, - file_attributes, - callback, - NULL, - callback_data); -} - -static void -vfs_cancel_callback (NautilusDirectory *directory, - NautilusDirectoryCallback callback, - gpointer callback_data) -{ - g_assert (NAUTILUS_IS_VFS_DIRECTORY (directory)); - - nautilus_directory_cancel_callback_internal - (directory, - NULL, - callback, - NULL, - callback_data); -} - -static void -vfs_file_monitor_add (NautilusDirectory *directory, - gconstpointer client, - gboolean monitor_hidden_files, - gboolean monitor_backup_files, - GList *file_attributes) -{ - g_assert (NAUTILUS_IS_VFS_DIRECTORY (directory)); - g_assert (client != NULL); - - nautilus_directory_monitor_add_internal - (directory, NULL, - client, - monitor_hidden_files, - monitor_backup_files, - file_attributes); -} - -static void -vfs_file_monitor_remove (NautilusDirectory *directory, - gconstpointer client) -{ - g_assert (NAUTILUS_IS_VFS_DIRECTORY (directory)); - g_assert (client != NULL); - - nautilus_directory_monitor_remove_internal (directory, NULL, client); -} - -static void -vfs_force_reload (NautilusDirectory *directory) -{ - GList *all_attributes; - - g_assert (NAUTILUS_IS_DIRECTORY (directory)); - - all_attributes = nautilus_file_get_all_attributes (); - nautilus_directory_force_reload_internal (directory, - all_attributes); - g_list_free (all_attributes); -} - -static gboolean -vfs_are_all_files_seen (NautilusDirectory *directory) -{ - g_assert (NAUTILUS_IS_VFS_DIRECTORY (directory)); - - return directory->details->directory_loaded; -} - -static gboolean -vfs_is_not_empty (NautilusDirectory *directory) -{ - GList *node; - - g_return_val_if_fail (NAUTILUS_IS_VFS_DIRECTORY (directory), FALSE); - g_return_val_if_fail (nautilus_directory_is_anyone_monitoring_file_list (directory), FALSE); - - for (node = directory->details->file_list; node != NULL; node = node->next) { - if (!nautilus_file_is_metafile (NAUTILUS_FILE (node->data))) { - /* Return TRUE if the directory contains anything besides a metafile. */ - return TRUE; - } - } - - return FALSE; -} - -static void -nautilus_vfs_directory_initialize_class (gpointer klass) -{ - GtkObjectClass *object_class; - NautilusDirectoryClass *directory_class; - - object_class = GTK_OBJECT_CLASS (klass); - directory_class = NAUTILUS_DIRECTORY_CLASS (klass); - - object_class->destroy = vfs_destroy; - - directory_class->contains_file = vfs_contains_file; - directory_class->call_when_ready = vfs_call_when_ready; - directory_class->cancel_callback = vfs_cancel_callback; - directory_class->file_monitor_add = vfs_file_monitor_add; - directory_class->file_monitor_remove = vfs_file_monitor_remove; - directory_class->force_reload = vfs_force_reload; - directory_class->are_all_files_seen = vfs_are_all_files_seen; - directory_class->is_not_empty = vfs_is_not_empty; -} diff --git a/libnautilus-extensions/nautilus-vfs-directory.h b/libnautilus-extensions/nautilus-vfs-directory.h deleted file mode 100644 index 922b768bb..000000000 --- a/libnautilus-extensions/nautilus-vfs-directory.h +++ /dev/null @@ -1,55 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- - - nautilus-vfs-directory.h: Subclass of NautilusDirectory to implement the - the case of a VFS directory. - - Copyright (C) 1999, 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. - - Author: Darin Adler <darin@eazel.com> -*/ - -#ifndef NAUTILUS_VFS_DIRECTORY_H -#define NAUTILUS_VFS_DIRECTORY_H - -#include "nautilus-directory.h" - -#define NAUTILUS_TYPE_VFS_DIRECTORY \ - (nautilus_vfs_directory_get_type ()) -#define NAUTILUS_VFS_DIRECTORY(obj) \ - (GTK_CHECK_CAST ((obj), NAUTILUS_TYPE_VFS_DIRECTORY, NautilusVFSDirectory)) -#define NAUTILUS_VFS_DIRECTORY_CLASS(klass) \ - (GTK_CHECK_CLASS_CAST ((klass), NAUTILUS_TYPE_VFS_DIRECTORY, NautilusVFSDirectoryClass)) -#define NAUTILUS_IS_VFS_DIRECTORY(obj) \ - (GTK_CHECK_TYPE ((obj), NAUTILUS_TYPE_VFS_DIRECTORY)) -#define NAUTILUS_IS_VFS_DIRECTORY_CLASS(klass) \ - (GTK_CHECK_CLASS_TYPE ((klass), NAUTILUS_TYPE_VFS_DIRECTORY)) - -typedef struct NautilusVFSDirectoryDetails NautilusVFSDirectoryDetails; - -typedef struct { - NautilusDirectory parent_slot; - NautilusVFSDirectoryDetails *details; -} NautilusVFSDirectory; - -typedef struct { - NautilusDirectoryClass parent_slot; -} NautilusVFSDirectoryClass; - -GtkType nautilus_vfs_directory_get_type (void); - -#endif /* NAUTILUS_VFS_DIRECTORY_H */ diff --git a/libnautilus-extensions/nautilus-vfs-file.c b/libnautilus-extensions/nautilus-vfs-file.c deleted file mode 100644 index b02b90159..000000000 --- a/libnautilus-extensions/nautilus-vfs-file.c +++ /dev/null @@ -1,271 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- - - nautilus-vfs-file.c: Subclass of NautilusFile to help implement the - virtual trash directory. - - Copyright (C) 1999, 2000, 2001 Eazel, Inc. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public - License along with this program; if not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. - - Author: Darin Adler <darin@eazel.com> -*/ - -#include <config.h> -#include "nautilus-vfs-file.h" - -#include "nautilus-directory-private.h" -#include "nautilus-file-private.h" -#include <eel/eel-gtk-macros.h> - -struct NautilusVFSFileDetails { -}; - -static void nautilus_vfs_file_initialize (gpointer object, - gpointer klass); -static void nautilus_vfs_file_initialize_class (gpointer klass); - -EEL_DEFINE_CLASS_BOILERPLATE (NautilusVFSFile, - nautilus_vfs_file, - NAUTILUS_TYPE_FILE) - -static void -vfs_file_monitor_add (NautilusFile *file, - gconstpointer client, - GList *attributes) -{ - nautilus_directory_monitor_add_internal - (file->details->directory, file, - client, TRUE, TRUE, attributes); -} - -static void -vfs_file_monitor_remove (NautilusFile *file, - gconstpointer client) -{ - nautilus_directory_monitor_remove_internal - (file->details->directory, file, client); -} - -static void -vfs_file_call_when_ready (NautilusFile *file, - GList *file_attributes, - NautilusFileCallback callback, - gpointer callback_data) - -{ - nautilus_directory_call_when_ready_internal - (file->details->directory, file, - file_attributes, NULL, callback, callback_data); -} - -static void -vfs_file_cancel_call_when_ready (NautilusFile *file, - NautilusFileCallback callback, - gpointer callback_data) -{ - nautilus_directory_cancel_callback_internal - (file->details->directory, file, - NULL, callback, callback_data); -} - -static gboolean -vfs_file_check_if_ready (NautilusFile *file, - GList *file_attributes) -{ - return nautilus_directory_check_if_ready_internal - (file->details->directory, file, - file_attributes); -} - -static GnomeVFSFileType -vfs_file_get_file_type (NautilusFile *file) -{ - return nautilus_file_info_missing (file, GNOME_VFS_FILE_INFO_FIELDS_TYPE) - ? GNOME_VFS_FILE_TYPE_UNKNOWN : file->details->info->type; -} - -static gboolean -vfs_file_get_item_count (NautilusFile *file, - guint *count, - gboolean *count_unreadable) -{ - if (count_unreadable != NULL) { - *count_unreadable = file->details->directory_count_failed; - } - if (!file->details->got_directory_count) { - if (count != NULL) { - *count = 0; - } - return FALSE; - } - if (count != NULL) { - *count = file->details->directory_count; - } - return TRUE; -} - -static NautilusRequestStatus -vfs_file_get_deep_counts (NautilusFile *file, - guint *directory_count, - guint *file_count, - guint *unreadable_directory_count, - GnomeVFSFileSize *total_size) -{ - GnomeVFSFileType type; - - if (directory_count != NULL) { - *directory_count = 0; - } - if (file_count != NULL) { - *file_count = 0; - } - if (unreadable_directory_count != NULL) { - *unreadable_directory_count = 0; - } - if (total_size != NULL) { - *total_size = 0; - } - - if (!nautilus_file_is_directory (file)) { - return NAUTILUS_REQUEST_DONE; - } - - if (file->details->deep_counts_status != NAUTILUS_REQUEST_NOT_STARTED) { - if (directory_count != NULL) { - *directory_count = file->details->deep_directory_count; - } - if (file_count != NULL) { - *file_count = file->details->deep_file_count; - } - if (unreadable_directory_count != NULL) { - *unreadable_directory_count = file->details->deep_unreadable_count; - } - if (total_size != NULL) { - *total_size = file->details->deep_size; - } - return file->details->deep_counts_status; - } - - /* For directories, or before we know the type, we haven't started. */ - type = nautilus_file_get_file_type (file); - if (type == GNOME_VFS_FILE_TYPE_UNKNOWN - || type == GNOME_VFS_FILE_TYPE_DIRECTORY) { - return NAUTILUS_REQUEST_NOT_STARTED; - } - - /* For other types, we are done, and the zeros are permanent. */ - return NAUTILUS_REQUEST_DONE; -} - -static gboolean -vfs_file_get_date (NautilusFile *file, - NautilusDateType date_type, - time_t *date) -{ - switch (date_type) { - case NAUTILUS_DATE_TYPE_CHANGED: - /* Before we have info on a file, the date is unknown. */ - if (nautilus_file_info_missing (file, GNOME_VFS_FILE_INFO_FIELDS_CTIME)) { - return FALSE; - } - if (date != NULL) { - *date = file->details->info->ctime; - } - return TRUE; - case NAUTILUS_DATE_TYPE_ACCESSED: - /* Before we have info on a file, the date is unknown. */ - if (nautilus_file_info_missing (file, GNOME_VFS_FILE_INFO_FIELDS_ATIME)) { - return FALSE; - } - if (date != NULL) { - *date = file->details->info->atime; - } - return TRUE; - case NAUTILUS_DATE_TYPE_MODIFIED: - /* Before we have info on a file, the date is unknown. */ - if (nautilus_file_info_missing (file, GNOME_VFS_FILE_INFO_FIELDS_MTIME)) { - return FALSE; - } - if (date != NULL) { - *date = file->details->info->mtime; - } - return TRUE; - case NAUTILUS_DATE_TYPE_PERMISSIONS_CHANGED: - /* Before we have info on a file, the date is unknown. */ - if (nautilus_file_info_missing (file, GNOME_VFS_FILE_INFO_FIELDS_MTIME) || - nautilus_file_info_missing (file, GNOME_VFS_FILE_INFO_FIELDS_CTIME)) { - return FALSE; - } - /* mtime is when the contents changed; ctime is when the - * contents or the permissions (inc. owner/group) changed. - * So we can only know when the permissions changed if mtime - * and ctime are different. - */ - if (file->details->info->mtime == file->details->info->ctime) { - return FALSE; - } - if (date != NULL) { - *date = file->details->info->ctime; - } - return TRUE; - } - return FALSE; -} - -static char * -vfs_file_get_where_string (NautilusFile *file) -{ - return nautilus_file_get_parent_uri_for_display (file); -} - -static void -nautilus_vfs_file_initialize (gpointer object, gpointer klass) -{ - NautilusVFSFile *file; - - file = NAUTILUS_VFS_FILE (object); - - file->details = g_new0 (NautilusVFSFileDetails, 1); -} - -static void -vfs_destroy (GtkObject *object) -{ - EEL_CALL_PARENT (GTK_OBJECT_CLASS, destroy, (object)); -} - -static void -nautilus_vfs_file_initialize_class (gpointer klass) -{ - GtkObjectClass *object_class; - NautilusFileClass *file_class; - - object_class = GTK_OBJECT_CLASS (klass); - file_class = NAUTILUS_FILE_CLASS (klass); - - object_class->destroy = vfs_destroy; - - file_class->monitor_add = vfs_file_monitor_add; - file_class->monitor_remove = vfs_file_monitor_remove; - file_class->call_when_ready = vfs_file_call_when_ready; - file_class->cancel_call_when_ready = vfs_file_cancel_call_when_ready; - file_class->check_if_ready = vfs_file_check_if_ready; - file_class->get_file_type = vfs_file_get_file_type; - file_class->get_item_count = vfs_file_get_item_count; - file_class->get_deep_counts = vfs_file_get_deep_counts; - file_class->get_date = vfs_file_get_date; - file_class->get_where_string = vfs_file_get_where_string; -} diff --git a/libnautilus-extensions/nautilus-vfs-file.h b/libnautilus-extensions/nautilus-vfs-file.h deleted file mode 100644 index 377b6d1b4..000000000 --- a/libnautilus-extensions/nautilus-vfs-file.h +++ /dev/null @@ -1,55 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- - - nautilus-vfs-file.h: Subclass of NautilusFile to implement the - the case of a VFS file. - - Copyright (C) 1999, 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. - - Author: Darin Adler <darin@eazel.com> -*/ - -#ifndef NAUTILUS_VFS_FILE_H -#define NAUTILUS_VFS_FILE_H - -#include "nautilus-file.h" - -#define NAUTILUS_TYPE_VFS_FILE \ - (nautilus_vfs_file_get_type ()) -#define NAUTILUS_VFS_FILE(obj) \ - (GTK_CHECK_CAST ((obj), NAUTILUS_TYPE_VFS_FILE, NautilusVFSFile)) -#define NAUTILUS_VFS_FILE_CLASS(klass) \ - (GTK_CHECK_CLASS_CAST ((klass), NAUTILUS_TYPE_VFS_FILE, NautilusVFSFileClass)) -#define NAUTILUS_IS_VFS_FILE(obj) \ - (GTK_CHECK_TYPE ((obj), NAUTILUS_TYPE_VFS_FILE)) -#define NAUTILUS_IS_VFS_FILE_CLASS(klass) \ - (GTK_CHECK_CLASS_TYPE ((klass), NAUTILUS_TYPE_VFS_FILE)) - -typedef struct NautilusVFSFileDetails NautilusVFSFileDetails; - -typedef struct { - NautilusFile parent_slot; - NautilusVFSFileDetails *details; -} NautilusVFSFile; - -typedef struct { - NautilusFileClass parent_slot; -} NautilusVFSFileClass; - -GtkType nautilus_vfs_file_get_type (void); - -#endif /* NAUTILUS_VFS_FILE_H */ diff --git a/libnautilus-extensions/nautilus-view-identifier.c b/libnautilus-extensions/nautilus-view-identifier.c deleted file mode 100644 index 7dbff08a8..000000000 --- a/libnautilus-extensions/nautilus-view-identifier.c +++ /dev/null @@ -1,243 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- - - nautilus-view-identifier.c: Unique ID/Human-readable name pairs for views - - 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. - - Author: Maciej Stachowiak <mjs@eazel.com> -*/ - -#include <config.h> -#include "nautilus-view-identifier.h" - -#include <libgnome/gnome-defs.h> -#include <libgnome/gnome-i18n.h> - - -#include <eel/eel-glib-extensions.h> -#include <eel/eel-string.h> -#include <glib.h> -#include <stdlib.h> - -static NautilusViewIdentifier * -nautilus_view_identifier_new (const char *iid, - const char *name, - const char *view_as_label, - const char *label_viewer); - - - -NautilusViewIdentifier * -nautilus_view_identifier_new (const char *iid, - const char *name, - const char *view_as_label, - const char *viewer_label) -{ - NautilusViewIdentifier *new_identifier; - - g_return_val_if_fail (iid != NULL, NULL); - g_return_val_if_fail (name != NULL, NULL); - - new_identifier = g_new0 (NautilusViewIdentifier, 1); - new_identifier->iid = g_strdup (iid); - new_identifier->name = g_strdup (name); - - new_identifier->view_as_label = view_as_label ? g_strdup (view_as_label) : - g_strdup_printf (_("View as %s"), name); - - new_identifier->viewer_label = view_as_label ? g_strdup (viewer_label) : - g_strdup_printf (_("%s Viewer"), name); - - return new_identifier; -} - -NautilusViewIdentifier * -nautilus_view_identifier_copy (const NautilusViewIdentifier *identifier) -{ - if (identifier == NULL) { - return NULL; - } - - return nautilus_view_identifier_new (identifier->iid, - identifier->name, - identifier->view_as_label, - identifier->viewer_label); -} - -/* Returns a list of languages, containing - the LANG or LANGUAGE environment setting (with and without region code). - The elements in the returned list must be freed */ -static GSList * -get_lang_list (void) -{ - GSList *retval; - char *lang, *lang_with_locale, *tmp, *org_pointer; - char *equal_char; - - retval = NULL; - - tmp = g_getenv ("LANGUAGE"); - - if (tmp == NULL) { - tmp = g_getenv ("LANG"); - } - - lang = g_strdup (tmp); - org_pointer = lang; - - if (lang != NULL) { - /* envs can be in NAME=VALUE form */ - equal_char = strchr (lang, '='); - if (equal_char != NULL) { - lang = equal_char + 1; - } - - /* lang may be in form LANG_LOCALE */ - equal_char = strchr (lang, '_'); - if (equal_char != NULL) { - lang_with_locale = g_strdup (lang); - *equal_char = 0; - } else { - lang_with_locale = NULL; - } - - /* Make sure we don't give oaf an empty - lang string */ - if (!eel_str_is_empty (lang_with_locale)) { - retval = g_slist_prepend (retval, - g_strdup (lang_with_locale)); - } - g_free (lang_with_locale); - if (!eel_str_is_empty (lang)) { - retval = g_slist_prepend (retval, g_strdup (lang)); - } - } - g_free (org_pointer); - - return retval; -} - -NautilusViewIdentifier * -nautilus_view_identifier_new_from_oaf_server_info (OAF_ServerInfo *server, char *name_attribute) -{ - const char *view_as_name; - const char *view_as_label; - const char *viewer_label; - GSList *langs; - - langs = get_lang_list (); - - view_as_name = oaf_server_info_prop_lookup (server, name_attribute, langs); - view_as_label = oaf_server_info_prop_lookup (server, "nautilus:view_as_label", langs); - viewer_label = oaf_server_info_prop_lookup (server, "nautilus:viewer_label", langs); - - if (view_as_name == NULL) { - view_as_name = oaf_server_info_prop_lookup (server, "name", langs); - } - if (view_as_name == NULL) { - view_as_name = server->iid; - } - - eel_g_slist_free_deep (langs); - - /* if the name is an OAFIID, clean it up for display */ - if (eel_str_has_prefix (view_as_name, "OAFIID:")) { - char *display_name, *colon_ptr; - NautilusViewIdentifier *new_identifier; - - display_name = g_strdup (view_as_name + 7); - colon_ptr = strchr (display_name, ':'); - if (colon_ptr) { - *colon_ptr = '\0'; - } - - new_identifier = nautilus_view_identifier_new (server->iid, display_name, - view_as_label, viewer_label); - g_free(display_name); - return new_identifier; - } - - return nautilus_view_identifier_new (server->iid, view_as_name, - view_as_label, viewer_label); -} - -NautilusViewIdentifier * -nautilus_view_identifier_new_from_content_view (OAF_ServerInfo *server) -{ - return nautilus_view_identifier_new_from_oaf_server_info - (server, "nautilus:view_as_name"); -} - -NautilusViewIdentifier * -nautilus_view_identifier_new_from_sidebar_panel (OAF_ServerInfo *server) -{ - return nautilus_view_identifier_new_from_oaf_server_info - (server, "nautilus:sidebar_panel_name"); -} - -void -nautilus_view_identifier_free (NautilusViewIdentifier *identifier) -{ - if (identifier != NULL) { - g_free (identifier->iid); - g_free (identifier->name); - g_free (identifier->view_as_label); - g_free (identifier->viewer_label); - g_free (identifier); - } -} - -GList * -nautilus_view_identifier_list_copy (GList *list) -{ - GList *copy, *node; - - copy = NULL; - for (node = list; node != NULL; node = node->next) { - copy = g_list_prepend - (copy, nautilus_view_identifier_copy (node->data)); - } - return g_list_reverse (copy); -} - -static void -nautilus_view_identifier_free_callback (gpointer identifier, gpointer ignore) -{ - g_assert (ignore == NULL); - nautilus_view_identifier_free (identifier); -} - -void -nautilus_view_identifier_list_free (GList *list) -{ - eel_g_list_free_deep_custom - (list, nautilus_view_identifier_free_callback, NULL); -} - -int -nautilus_view_identifier_compare (const NautilusViewIdentifier *a, - const NautilusViewIdentifier *b) -{ - int result; - - result = strcmp (a->iid, b->iid); - if (result != 0) { - return result; - } - return strcmp (a->name, b->name); -} diff --git a/libnautilus-extensions/nautilus-view-identifier.h b/libnautilus-extensions/nautilus-view-identifier.h deleted file mode 100644 index 787a5bb74..000000000 --- a/libnautilus-extensions/nautilus-view-identifier.h +++ /dev/null @@ -1,49 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- - - nautilus-view-identifier.h: Unique ID/Human-readable name pairs for views - - 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. - - Author: Maciej Stachowiak <mjs@eazel.com> -*/ - -#ifndef NAUTILUS_VIEW_IDENTIFIER_H -#define NAUTILUS_VIEW_IDENTIFIER_H - -#include <liboaf/liboaf.h> - -typedef struct { - char *iid; /* Unique ID */ - char *name; /* human-readable name */ - char *view_as_label; /* "View as <name>" */ - char *viewer_label; /* "<name> Viewer" */ -} NautilusViewIdentifier; - -NautilusViewIdentifier *nautilus_view_identifier_new_from_oaf_server_info (OAF_ServerInfo *server, - char *name_attribute); -NautilusViewIdentifier *nautilus_view_identifier_new_from_content_view (OAF_ServerInfo *server); -NautilusViewIdentifier *nautilus_view_identifier_new_from_sidebar_panel (OAF_ServerInfo *server); -NautilusViewIdentifier *nautilus_view_identifier_copy (const NautilusViewIdentifier *identifier); -void nautilus_view_identifier_free (NautilusViewIdentifier *identifier); -int nautilus_view_identifier_compare (const NautilusViewIdentifier *a, - const NautilusViewIdentifier *b); -/* lists of NautilusViewIdentifier */ -GList * nautilus_view_identifier_list_copy (GList *list); -void nautilus_view_identifier_list_free (GList *list); - -#endif /* NAUTILUS_VIEW_IDENTIFIER */ diff --git a/libnautilus-extensions/nautilus-volume-monitor.c b/libnautilus-extensions/nautilus-volume-monitor.c deleted file mode 100644 index be73c78e5..000000000 --- a/libnautilus-extensions/nautilus-volume-monitor.c +++ /dev/null @@ -1,2066 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ - -/* nautilus-volume-monitor.c - Desktop volume mounting routines. - - Copyright (C) 2000, 2001 Eazel, Inc. - - The Gnome 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 Gnome 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 the Gnome 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. - - Authors: Gene Z. Ragan <gzr@eazel.com> -*/ - -#include <config.h> -#include "nautilus-volume-monitor.h" - -#include "nautilus-cdrom-extensions.h" -#include "nautilus-directory-notify.h" -#include "nautilus-file-utilities.h" -#include "nautilus-iso9660.h" -#include "nautilus-volume-monitor.h" -#include <eel/eel-gnome-extensions.h> -#include <eel/eel-gtk-extensions.h> -#include <eel/eel-gtk-macros.h> -#include <eel/eel-stock-dialogs.h> -#include <eel/eel-string-list.h> -#include <eel/eel-string.h> -#include <errno.h> -#include <fcntl.h> -#include <gnome-xml/parser.h> -#include <gnome-xml/xmlmemory.h> -#include <gtk/gtkmain.h> -#include <libgnome/gnome-config.h> -#include <libgnome/gnome-defs.h> -#include <libgnome/gnome-exec.h> -#include <libgnome/gnome-i18n.h> -#include <libgnome/gnome-util.h> -#include <libgnomeui/gnome-messagebox.h> -#include <libgnomevfs/gnome-vfs-utils.h> -#include <pthread.h> -#include <stdio.h> -#include <stdlib.h> -#include <sys/ioctl.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <unistd.h> - -#ifdef HAVE_SYS_VFSTAB_H -#include <sys/vfstab.h> -#else -#include <fstab.h> -#endif - -#ifdef HAVE_MNTENT_H -#include <mntent.h> -#define MOUNT_TABLE_PATH _PATH_MNTTAB -#endif - -#ifdef HAVE_SYS_MNTTAB_H -#define SOLARIS_MNT 1 -#include <sys/mnttab.h> -#define MOUNT_TABLE_PATH "/etc/mnttab" -#endif - -#ifdef SOLARIS_MNT -#define USE_VOLRMMOUNT 1 -#else -#define USE_VOLRMMOUNT 0 -#endif - -#ifndef MNTOPT_RO -#define MNTOPT_RO "ro" -#endif - -#ifndef HAVE_SETMNTENT -#define setmntent(f,m) fopen(f,m) -#endif - -#ifdef HAVE_CDDA_INTERFACE_H -#ifdef HAVE_CDDA_PARANOIA_H -/* Take this out for now */ -/*#define HAVE_CDDA 1*/ -#endif -#endif - -#ifdef HAVE_CDDA - -#define size16 short -#define size32 int - -#include <cdda_interface.h> -#include <cdda_paranoia.h> - -#define CD_AUDIO_PATH "/dev/cdrom" -#define CDDA_SCHEME "cdda" - -/* This is here to work around a broken header file. cdda_interface.h - * has a statically defined array of chars that is unused. This will - * break our build due to our strict error checking. - */ -char **broken_cdda_interface_h_workaround = strerror_tr; - -#endif - -#define CHECK_STATUS_INTERVAL 2000 - -#define FLOPPY_MOUNT_PATH_PREFIX "/mnt/fd" - -#ifdef HAVE_SYS_MNTTAB_H -typedef struct mnttab MountTableEntry; -#else -typedef struct mntent MountTableEntry; -#endif - -struct NautilusVolumeMonitorDetails -{ - GList *mounts; - GList *removable_volumes; - guint mount_volume_timer_id; - GHashTable *readable_mount_point_names; -}; - -static NautilusVolumeMonitor *global_volume_monitor = NULL; -static const char *floppy_device_path_prefix; -static const char *noauto_string; -static gboolean mnttab_exists; - - -/* The NautilusVolumeMonitor signals. */ -enum { - VOLUME_MOUNTED, - VOLUME_UNMOUNT_STARTED, - VOLUME_UNMOUNT_FAILED, - VOLUME_UNMOUNTED, - LAST_SIGNAL -}; -static guint signals[LAST_SIGNAL]; - - -static void nautilus_volume_monitor_initialize (NautilusVolumeMonitor *desktop_mounter); -static void nautilus_volume_monitor_initialize_class (NautilusVolumeMonitorClass *klass); -static void nautilus_volume_monitor_destroy (GtkObject *object); -static void get_iso9660_volume_name (NautilusVolume *volume, - int volume_fd); -static void get_ext2_volume_name (NautilusVolume *volume); -static void get_msdos_volume_name (NautilusVolume *volume); -static void get_nfs_volume_name (NautilusVolume *volume); -static void get_reiser_volume_name (NautilusVolume *volume); -static void get_ufs_volume_name (NautilusVolume *volume); -static void get_generic_volume_name (NautilusVolume *volume); -static void mount_volume_get_name (NautilusVolume *volume); -static void mount_volume_activate (NautilusVolumeMonitor *view, - NautilusVolume *volume); -static void mount_volume_deactivate (NautilusVolumeMonitor *monitor, - NautilusVolume *volume); -static void load_additional_mount_list_info (GList *volume_list); -static GList * mount_volume_add_filesystem (NautilusVolume *volume, - GList *volume_list); -static NautilusVolume *create_volume (const char *device_path, - const char *mount_path, - const char *filesystem); -static NautilusVolume *copy_volume (NautilusVolume *volume); -static void find_volumes (NautilusVolumeMonitor *monitor); -static void free_mount_list (GList *mount_list); -static GList * get_removable_volumes (void); -static GHashTable * create_readable_mount_point_name_table (void); -static int get_cdrom_type (const char *vol_dev_path, - int *fd); - -#ifdef HAVE_CDDA -static gboolean locate_audio_cd (void); -#endif - -EEL_DEFINE_CLASS_BOILERPLATE (NautilusVolumeMonitor, - nautilus_volume_monitor, - GTK_TYPE_OBJECT) - -static void -nautilus_volume_monitor_initialize (NautilusVolumeMonitor *monitor) -{ - /* Set up details */ - monitor->details = g_new0 (NautilusVolumeMonitorDetails, 1); - monitor->details->mounts = NULL; - monitor->details->removable_volumes = NULL; - monitor->details->readable_mount_point_names = create_readable_mount_point_name_table (); - - monitor->details->removable_volumes = get_removable_volumes (); - - find_volumes (monitor); -} - -static void -nautilus_volume_monitor_initialize_class (NautilusVolumeMonitorClass *klass) -{ - GtkObjectClass *object_class; - - object_class = GTK_OBJECT_CLASS (klass); - - object_class->destroy = nautilus_volume_monitor_destroy; - - signals[VOLUME_MOUNTED] - = gtk_signal_new ("volume_mounted", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (NautilusVolumeMonitorClass, - volume_mounted), - gtk_marshal_NONE__POINTER, - GTK_TYPE_NONE, 1, GTK_TYPE_POINTER); - - signals[VOLUME_UNMOUNT_STARTED] - = gtk_signal_new ("volume_unmount_started", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (NautilusVolumeMonitorClass, - volume_unmount_started), - gtk_marshal_NONE__POINTER, - GTK_TYPE_NONE, 1, GTK_TYPE_POINTER); - - signals[VOLUME_UNMOUNT_FAILED] - = gtk_signal_new ("volume_unmoun_failed", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (NautilusVolumeMonitorClass, - volume_unmount_failed), - gtk_marshal_NONE__POINTER, - GTK_TYPE_NONE, 1, GTK_TYPE_POINTER); - - signals[VOLUME_UNMOUNTED] - = gtk_signal_new ("volume_unmounted", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (NautilusVolumeMonitorClass, - volume_unmounted), - gtk_marshal_NONE__POINTER, - GTK_TYPE_NONE, 1, GTK_TYPE_POINTER); - - gtk_object_class_add_signals (object_class, signals, LAST_SIGNAL); - - /* Check environment a bit. */ - if (g_file_exists ("/vol/dev")) { - floppy_device_path_prefix = "/vol/dev/diskette/"; - } else { - floppy_device_path_prefix = "/dev/fd"; - } - if (g_file_exists ("/vol")) { - noauto_string = "/vol/"; - } else { - noauto_string = "/dev/fd"; - } - mnttab_exists = g_file_exists ("/etc/mnttab"); -} - -static void -nautilus_volume_monitor_destroy (GtkObject *object) -{ - NautilusVolumeMonitor *monitor; - - monitor = NAUTILUS_VOLUME_MONITOR (object); - - /* Remove timer function */ - gtk_timeout_remove (monitor->details->mount_volume_timer_id); - - /* Clean up mount info */ - free_mount_list (monitor->details->mounts); - free_mount_list (monitor->details->removable_volumes); - - /* Clean up readable names table */ - g_hash_table_destroy (monitor->details->readable_mount_point_names); - - /* Clean up details */ - g_free (monitor->details); - - global_volume_monitor = NULL; - - EEL_CALL_PARENT (GTK_OBJECT_CLASS, destroy, (object)); -} - -static void -unref_global_volume_monitor (void) -{ - gtk_object_unref (GTK_OBJECT (global_volume_monitor)); -} - -/* Return the global instance of the NautilusVolumeMonitor. Create one - * if we have not done so already - */ -NautilusVolumeMonitor * -nautilus_volume_monitor_get (void) -{ - if (global_volume_monitor == NULL) { - global_volume_monitor = NAUTILUS_VOLUME_MONITOR - (gtk_object_new (nautilus_volume_monitor_get_type(), - NULL)); - gtk_object_ref (GTK_OBJECT (global_volume_monitor)); - gtk_object_sink (GTK_OBJECT (global_volume_monitor)); - g_atexit (unref_global_volume_monitor); - } - - return global_volume_monitor; -} - -static int -floppy_sort (const NautilusVolume *volume1, const NautilusVolume *volume2) -{ - gboolean is_floppy_1, is_floppy_2; - - is_floppy_1 = volume1->device_type == NAUTILUS_DEVICE_FLOPPY_DRIVE; - is_floppy_2 = volume2->device_type == NAUTILUS_DEVICE_FLOPPY_DRIVE; - - if (is_floppy_1 && !is_floppy_2) { - return -1; - } - if (!is_floppy_1 && is_floppy_2) { - return +1; - } - return 0; -} - -gboolean -nautilus_volume_monitor_volume_is_removable (const NautilusVolume *volume) -{ - return volume->is_removable; -} - - -/* nautilus_volume_monitor_get_removable_volumes - * - * Accessor. List and internal data is not to be freed. - */ - -const GList * -nautilus_volume_monitor_get_removable_volumes (NautilusVolumeMonitor *monitor) -{ - return monitor->details->removable_volumes; -} - - -static gboolean -has_removable_mntent_options (MountTableEntry *ent) -{ - /* Use "owner" or "user" or "users" as our way of determining a removable volume */ - if (hasmntopt (ent, "user") != NULL - || hasmntopt (ent, "users") != NULL - || hasmntopt (ent, "owner") != NULL) { - return TRUE; - } - -#ifdef SOLARIS_MNT - if (eel_str_has_prefix (ent->mnt_special, "/vol/")) { - return TRUE; - } -#endif - - return FALSE; -} - - -/* get_removable_volumes - * - * Returns a list a device paths. - * Caller needs to free these as well as the list. - */ - -static GList * -get_removable_volumes (void) -{ - FILE *file; - GList *volumes; - MountTableEntry *ent; - NautilusVolume *volume; -#ifdef HAVE_SYS_MNTTAB_H - MountTableEntry ent_storage; -#endif - - volumes = NULL; - - file = setmntent (MOUNT_TABLE_PATH, "r"); - if (file == NULL) { - return NULL; - } - -#ifdef HAVE_SYS_MNTTAB_H - ent = &ent_storage; - while (! getmntent (file, ent)) { - /* On Solaris look for /vol/ for determining a removable volume */ - if (eel_str_has_prefix (ent->mnt_special, noauto_string)) { - volume = create_volume (ent->mnt_special, ent->mnt_mountp, ent->mnt_fstype); - volume->is_removable = TRUE; - volume->is_read_only = hasmntopt (ent, MNTOPT_RO) != NULL; - volumes = mount_volume_add_filesystem (volume, volumes); - } - } -#else - while ((ent = getmntent (file)) != NULL) { - if (has_removable_mntent_options (ent)) { - volume = create_volume (ent->mnt_fsname, ent->mnt_dir, ent->mnt_type); - volumes = mount_volume_add_filesystem (volume, volumes); - } - } -#endif /* HAVE_SYS_MNTTAB_H */ - - fclose (file); - -#ifdef HAVE_CDDA - volume = create_volume (CD_AUDIO_PATH, CD_AUDIO_PATH, CDDA_SCHEME); - volumes = mount_volume_add_filesystem (volume, volumes); -#endif - - load_additional_mount_list_info (volumes); - - /* Move all floppy mounts to top of list */ - return g_list_sort (g_list_reverse (volumes), (GCompareFunc) floppy_sort); -} - - -static gboolean -volume_is_removable (const NautilusVolume *volume) -{ - FILE *file; - MountTableEntry *ent; -#ifdef HAVE_SYS_MNTTAB_H - MountTableEntry ent_storage; -#endif - - file = setmntent (MOUNT_TABLE_PATH, "r"); - if (file == NULL) { - return FALSE; - } - - /* Search for our device in the fstab */ -#ifdef HAVE_SYS_MNTTAB_H - MountTableEntry *ent = &ent_storage; - while (!getmntent (file, ent)) { - if (strcmp (volume->device_path, ent->mnt_special) == 0) { - /* On Solaris look for /vol/ for determining - a removable volume */ - if (eel_str_has_prefix (ent->mnt_special, noauto_string)) { - fclose (file); - return TRUE; - } - } - } -#else - while ((ent = getmntent (file)) != NULL) { - if (strcmp (volume->device_path, ent->mnt_fsname) == 0 - && has_removable_mntent_options (ent)) { - fclose (file); - return TRUE; - } - } -#endif /* HAVE_SYS_MNTTAB_H */ - - fclose (file); - return FALSE; -} - -static gboolean -volume_is_read_only (const NautilusVolume *volume) -{ - FILE *file; - MountTableEntry *ent; - -#ifdef HAVE_SYS_MNTTAB_H - MountTableEntry ent_storage; - - file = setmntent (MOUNT_TABLE_PATH, "r"); - if (file == NULL) { - return FALSE; - } - - /* Search for our device in the fstab */ - ent = &ent_storage; - while (!getmntent (file, ent)) { - if (strcmp (volume->device_path, ent->mnt_special) == 0) { - if (strstr (ent->mnt_mntopts, MNTOPT_RO) != NULL) { - fclose (file); - return TRUE; - } - } - } -#else - file = setmntent (MOUNT_TABLE_PATH, "r"); - if (file == NULL) { - return FALSE; - } - - /* Search for our device in the fstab */ - while ((ent = getmntent (file)) != NULL) { - if (strcmp (volume->device_path, ent->mnt_fsname) == 0) { - if (strstr (ent->mnt_opts, MNTOPT_RO) != NULL) { - fclose (file); - return TRUE; - } - } - } -#endif - - fclose (file); - return FALSE; -} - - -char * -nautilus_volume_monitor_get_volume_name (const NautilusVolume *volume) -{ - if (volume->volume_name == NULL) { - return g_strdup (_("Unknown")); - } - - return g_strdup (volume->volume_name); -} - - -/* modify_volume_name_for_display - * - * Modify volume to be in human readable form - */ - -static void -modify_volume_name_for_display (NautilusVolume *volume) -{ - int index; - char *name; - - if (volume->volume_name == NULL) { - volume->volume_name = g_strdup (_("Unknown")); - return; - } - - name = g_strdup (volume->volume_name); - - /* Strip whitespace from the end of the name. */ - g_strchomp (name); - - /* The volume name may have '/' characters. We need to convert - * them to something that's suitable for use in the name of a - * link on the desktop. - */ - for (index = 0; ; index++) { - if (name [index] == '\0') { - break; - } - if (name [index] == '/') { - name [index] = '-'; - } - } - - /* Save pretty name back into volume info */ - g_free (volume->volume_name); - volume->volume_name = name; -} - -/* nautilus_volume_monitor_get_target_uri - * - * Returns the activation uri of the volume - */ - -char * -nautilus_volume_monitor_get_target_uri (const NautilusVolume *volume) -{ - char *uri; - - switch (volume->volume_type) { - case NAUTILUS_VOLUME_CDDA: - uri = g_strdup_printf ("cdda://%s", volume->mount_path); - break; - - default: - uri = gnome_vfs_get_uri_from_local_path (volume->mount_path); - break; - } - - return uri; -} - -gboolean -nautilus_volume_monitor_should_integrate_trash (const NautilusVolume *volume) -{ - /* Hand-pick a bunch of file system types that we know we can support - * trash on. It would probably be harder to keep a list of the ones - * we can't try to support trash on because the list would have to be - * more definitive. - */ - return volume->volume_type == NAUTILUS_VOLUME_EXT2 - || volume->volume_type == NAUTILUS_VOLUME_FAT - || volume->volume_type == NAUTILUS_VOLUME_NFS - || volume->volume_type == NAUTILUS_VOLUME_VFAT - || volume->volume_type == NAUTILUS_VOLUME_REISER - || volume->volume_type == NAUTILUS_VOLUME_UFS - || volume->volume_type == NAUTILUS_VOLUME_SMB; -} - -const char * -nautilus_volume_monitor_get_volume_mount_uri (const NautilusVolume *volume) -{ - return volume->mount_path; -} - - -/* create_readable_mount_point_name_table - * - * Create a table with mapping between the mount point names that are found - * in /etc/fstab and names that are clear and easy to understand. - */ -static GHashTable * -create_readable_mount_point_name_table (void) -{ - GHashTable *table; - - table = g_hash_table_new (g_str_hash, g_str_equal); - - /* Populate table with items we know localized names for. */ - g_hash_table_insert (table, "floppy", _("Floppy")); - g_hash_table_insert (table, "cdrom", _("CD-ROM")); - g_hash_table_insert (table, "zip", _("Zip Drive")); - - return table; -} - -static void -mount_volume_get_cdrom_name (NautilusVolume *volume) -{ - int fd, disctype; - - disctype = get_cdrom_type (volume->device_path, &fd); - - switch (disctype) { - case CDS_AUDIO: - volume->volume_name = g_strdup (_("Audio CD")); - break; - - case CDS_DATA_1: - case CDS_DATA_2: - case CDS_XA_2_1: - case CDS_XA_2_2: - case CDS_MIXED: - /* Get volume name */ - get_iso9660_volume_name (volume, fd); - break; - - default: - break; - } - - close (fd); -} - -static void -mount_volume_get_cdda_name (NautilusVolume *volume) -{ - volume->volume_name = g_strdup (_("Audio CD")); -} - - -static void -mount_volume_activate_cdda (NautilusVolumeMonitor *monitor, NautilusVolume *volume) -{ - int fd, disctype; - - disctype = get_cdrom_type (volume->device_path, &fd); - - switch (disctype) { - case CDS_AUDIO: - break; - default: - break; - } - - close(fd); -} - -static void -mount_volume_activate_cdrom (NautilusVolumeMonitor *monitor, NautilusVolume *volume) -{ - int fd, disctype; - - disctype = get_cdrom_type (volume->device_path, &fd); - - switch (disctype) { - case CDS_AUDIO: - break; - - case CDS_DATA_1: - case CDS_DATA_2: - case CDS_XA_2_1: - case CDS_XA_2_2: - case CDS_MIXED: - /* Get volume name */ - get_iso9660_volume_name (volume, fd); - break; - - default: - break; - } - - close (fd); -} - -static void -mount_volume_activate_ext2 (NautilusVolumeMonitor *view, NautilusVolume *volume) -{ -} - -static void -mount_volume_activate_msdos (NautilusVolumeMonitor *view, NautilusVolume *volume) -{ -} - -static void -mount_volume_activate_nfs (NautilusVolumeMonitor *view, NautilusVolume *volume) -{ -} - -static void -mount_volume_activate_generic (NautilusVolumeMonitor *view, NautilusVolume *volume) -{ -} - - -typedef void (* ChangeNautilusVolumeFunction) (NautilusVolumeMonitor *view, NautilusVolume *volume); - - -static void -mount_volume_get_name (NautilusVolume *volume) -{ - switch (volume->volume_type) { - case NAUTILUS_VOLUME_CDDA: - mount_volume_get_cdda_name (volume); - break; - - case NAUTILUS_VOLUME_CDROM: - case NAUTILUS_VOLUME_HSFS: - mount_volume_get_cdrom_name (volume); - break; - - case NAUTILUS_VOLUME_EXT2: - get_ext2_volume_name (volume); - break; - - case NAUTILUS_VOLUME_FAT: - case NAUTILUS_VOLUME_VFAT: - case NAUTILUS_VOLUME_MSDOS: - get_msdos_volume_name (volume); - break; - - case NAUTILUS_VOLUME_NFS: - get_nfs_volume_name (volume); - break; - - case NAUTILUS_VOLUME_REISER: - get_reiser_volume_name (volume); - break; - case NAUTILUS_VOLUME_UFS: - get_ufs_volume_name (volume); - break; - - case NAUTILUS_VOLUME_AFFS: - case NAUTILUS_VOLUME_AUTO: - case NAUTILUS_VOLUME_HPFS: - case NAUTILUS_VOLUME_MINIX: - case NAUTILUS_VOLUME_SMB: - case NAUTILUS_VOLUME_UDF: - case NAUTILUS_VOLUME_UNSDOS: - case NAUTILUS_VOLUME_XENIX: - case NAUTILUS_VOLUME_XIAFS: - get_generic_volume_name (volume); - break; - - default: - g_assert_not_reached (); - break; - } -} - - -static void -mount_volume_activate (NautilusVolumeMonitor *monitor, NautilusVolume *volume) -{ - switch (volume->volume_type) { - case NAUTILUS_VOLUME_CDDA: - mount_volume_activate_cdda (monitor, volume); - break; - - case NAUTILUS_VOLUME_CDROM: - case NAUTILUS_VOLUME_HSFS: - mount_volume_activate_cdrom (monitor, volume); - break; - - case NAUTILUS_VOLUME_EXT2: - mount_volume_activate_ext2 (monitor, volume); - break; - - case NAUTILUS_VOLUME_MSDOS: - mount_volume_activate_msdos (monitor, volume); - break; - - case NAUTILUS_VOLUME_NFS: - mount_volume_activate_nfs (monitor, volume); - break; - - case NAUTILUS_VOLUME_AFFS: - case NAUTILUS_VOLUME_FAT: - case NAUTILUS_VOLUME_HPFS: - case NAUTILUS_VOLUME_MINIX: - case NAUTILUS_VOLUME_REISER: - case NAUTILUS_VOLUME_UFS: - case NAUTILUS_VOLUME_SMB: - case NAUTILUS_VOLUME_UDF: - case NAUTILUS_VOLUME_UNSDOS: - case NAUTILUS_VOLUME_VFAT: - case NAUTILUS_VOLUME_XENIX: - case NAUTILUS_VOLUME_XIAFS: - mount_volume_activate_generic (monitor, volume); - break; - - default: - g_assert_not_reached (); - break; - } - - gtk_signal_emit (GTK_OBJECT (monitor), - signals[VOLUME_MOUNTED], - volume); -} - - -static void * -eject_device (void *arg) -{ - char *command, *path; - - path = arg; - - if (path != NULL) { - command = g_strdup_printf ("eject %s", path); - eel_gnome_shell_execute (command); - g_free (command); - g_free (path); - } - - pthread_exit (NULL); - - /* compilation on Solaris warns of no return - value on non-void function...so....*/ - return (void *) 0; -} - -static void -mount_volume_deactivate (NautilusVolumeMonitor *monitor, NautilusVolume *volume) -{ - pthread_t eject_thread; - - switch (volume->volume_type) { - case NAUTILUS_VOLUME_CDROM: - case NAUTILUS_VOLUME_HSFS: - pthread_create (&eject_thread, NULL, eject_device, g_strdup (volume->device_path)); - break; - - default: - break; - } - - gtk_signal_emit (GTK_OBJECT (monitor), - signals[VOLUME_UNMOUNTED], - volume); -} - -static void -free_mount_list (GList *mount_list) -{ - if (mount_list == NULL) { - return; - } - - g_list_foreach (mount_list, (GFunc) nautilus_volume_monitor_free_volume, NULL); - g_list_free (mount_list); - mount_list = NULL; -} - - -/* List returned, but not the data it contains, must be freed by caller */ -static GList * -build_volume_list_delta (GList *list_one, GList *list_two) -{ - GList *ptrOne, *ptrTwo; - GList *new_list; - NautilusVolume *volOne, *volTwo, *new_volume; - gboolean found_match; - - new_list = NULL; - - for (ptrOne = list_one; ptrOne != NULL; ptrOne = ptrOne->next) { - - found_match = FALSE; - volOne = (NautilusVolume *) ptrOne->data; - - for (ptrTwo = list_two; ptrTwo != NULL; ptrTwo = ptrTwo->next) { - - volTwo = (NautilusVolume *) ptrTwo->data; - - /* Check and see if mount point from list one is in list two */ - if (strcmp (volOne->mount_path, volTwo->mount_path) == 0) { - found_match = TRUE; - break; - } - } - - if (!found_match) { - /* No match. Add it to the list to be returned; */ - new_volume = copy_volume (volOne); - new_list = g_list_append (new_list, new_volume); - } - } - - return new_list; -} - - -static GList * -get_current_mount_list (void) -{ - GList *current_mounts = NULL; - NautilusVolume *volume = NULL; - FILE *fh; - -#ifdef SOLARIS_MNT - MountTableEntry ent_storage; - MountTableEntry *ent = &ent_storage; - - fh = setmntent (MOUNT_TABLE_PATH, "r"); - if (fh != NULL) { - while (! getmntent (fh, ent)) { - volume = create_volume (ent->mnt_special, ent->mnt_mountp, ent->mnt_fstype); - volume->is_removable = has_removable_mntent_options (ent); - volume->is_read_only = hasmntopt (ent, MNTOPT_RO) != NULL; - current_mounts = mount_volume_add_filesystem (volume, current_mounts); - } - } -#else - const char *file_name; - const char *separator; - char line[PATH_MAX * 3]; - char device_name[sizeof (line)]; - EelStringList *list; - char *device_path, *mount_path, *filesystem; - - if (mnttab_exists) { - file_name = "/etc/mnttab"; - separator = "\t"; - } else { - file_name = "/proc/mounts"; - separator = " "; - } - fh = fopen (file_name, "r"); - if (fh == NULL) { - g_warning ("Unable to open %s: %s", file_name, strerror (errno)); - return NULL; - } - - while (fgets (line, sizeof(line), fh)) { - if (sscanf (line, "%s", device_name) == 1) { - list = eel_string_list_new_from_tokens (line, separator, FALSE); - if (list != NULL) { - /* The string list needs to have at least 3 items per line. - * We need to find at least device path, mount path and file system type. - */ - if (eel_string_list_get_length (list) >= 3) { - device_path = eel_string_list_nth (list, 0); - mount_path = eel_string_list_nth (list, 1); - filesystem = eel_string_list_nth (list, 2); - volume = create_volume (device_path, mount_path, filesystem); - g_free (device_path); - g_free (mount_path); - g_free (filesystem); - current_mounts = mount_volume_add_filesystem (volume, current_mounts); - } - eel_string_list_free (list); - } - } - } -#endif /* SOLARIS_MNT */ - - if (fh != NULL) { - fclose (fh); - } - -#ifdef HAVE_CDDA - /* CD Audio tricks */ - if (locate_audio_cd ()) { - volume = create_volume (CD_AUDIO_PATH, CD_AUDIO_PATH, CDDA_SCHEME); - mount_volume_get_name (volume); - current_mounts = mount_volume_add_filesystem (volume, current_mounts); - } -#endif - - return current_mounts; -} - - -static void -update_modifed_volume_name (GList *mount_list, NautilusVolume *volume) -{ - GList *element; - NautilusVolume *found_volume; - - for (element = mount_list; element != NULL; element = element->next) { - found_volume = element->data; - if (strcmp (volume->device_path, found_volume->device_path) == 0) { - g_free (volume->volume_name); - volume->volume_name = g_strdup (found_volume->volume_name); - } - } -} - -static gboolean -mount_lists_are_identical (GList *list_a, GList *list_b) -{ - GList *p, *q; - NautilusVolume *volumeOne, *volumeTwo; - - for (p = list_a, q = list_b; p != NULL && q != NULL; p = p->next, q = q->next) { - volumeOne = p->data; - volumeTwo = q->data; - - if (strcmp (volumeOne->device_path, volumeTwo->device_path) != 0) { - return FALSE; - } - } - return p == NULL && q == NULL; -} - -static void -verify_current_mount_state (NautilusVolumeMonitor *monitor) -{ - GList *new_mounts, *old_mounts, *current_mounts; - GList *saved_mount_list, *p; - - /* Get all current mounts */ - current_mounts = get_current_mount_list (); - if (current_mounts == NULL) { - return; - } - - /* If the new list is the same of the current list, bail. */ - if (mount_lists_are_identical (current_mounts, monitor->details->mounts)) { - free_mount_list (current_mounts); - return; - } - - /* Create list of new and old mounts */ - new_mounts = build_volume_list_delta (current_mounts, monitor->details->mounts); - old_mounts = build_volume_list_delta (monitor->details->mounts, current_mounts); - - /* Stash a copy of the current mount list for updating mount names later. */ - saved_mount_list = monitor->details->mounts; - - /* Free previous mount list and replace with new */ - monitor->details->mounts = current_mounts; - - /* Process list results to check for a properties that require opening files on disk. */ - load_additional_mount_list_info (new_mounts); - - if (old_mounts != NULL) { - load_additional_mount_list_info (old_mounts); - load_additional_mount_list_info (saved_mount_list); - } - - /* Check and see if we have new mounts to add */ - for (p = new_mounts; p != NULL; p = p->next) { - mount_volume_activate (monitor, (NautilusVolume *)p->data); - } - - /* Check and see if we have old mounts to remove */ - for (p = old_mounts; p != NULL; p = p->next) { - /* First we need to update the volume names in this list with modified names in the old list. Names in - * the old list may have been modifed due to icon name conflicts. The list of old mounts is unable - * take this into account when it is created - */ - update_modifed_volume_name (saved_mount_list, (NautilusVolume *) p->data); - - /* Deactivate the volume. */ - mount_volume_deactivate (monitor, (NautilusVolume *) p->data); - } - - free_mount_list (old_mounts); - free_mount_list (new_mounts); - - free_mount_list (saved_mount_list); -} - -static int -mount_volumes_check_status (NautilusVolumeMonitor *monitor) -{ - verify_current_mount_state (monitor); - - return TRUE; -} - -static gboolean -mount_volume_ext2_add (NautilusVolume *volume) -{ - volume->volume_type = NAUTILUS_VOLUME_EXT2; - volume->device_type = NAUTILUS_DEVICE_UNKNOWN; - - return TRUE; -} - -static gboolean -mount_volume_udf_add (NautilusVolume *volume) -{ - volume->volume_type = NAUTILUS_VOLUME_UDF; - volume->device_type = NAUTILUS_DEVICE_UNKNOWN; - - return TRUE; -} - -static gboolean -mount_volume_vfat_add (NautilusVolume *volume) -{ - volume->volume_type = NAUTILUS_VOLUME_VFAT; - volume->device_type = NAUTILUS_DEVICE_UNKNOWN; - - return TRUE; -} - -static gboolean -mount_volume_msdos_add (NautilusVolume *volume) -{ - volume->volume_type = NAUTILUS_VOLUME_MSDOS; - volume->device_type = NAUTILUS_DEVICE_UNKNOWN; - - return TRUE; -} - -static int -get_cdrom_type (const char *vol_dev_path, int* fd) -{ -#ifndef SOLARIS_MNT - *fd = open (vol_dev_path, O_RDONLY|O_NONBLOCK); - return ioctl (*fd, CDROM_DISC_STATUS, CDSL_CURRENT); -#else - GString *new_dev_path; - struct cdrom_tocentry entry; - struct cdrom_tochdr header; - int type; - - /* For ioctl call to work dev_path has to be /vol/dev/rdsk. - * There has to be a nicer way to do this. - */ - new_dev_path = g_string_new (vol_dev_path); - new_dev_path = g_string_insert_c (new_dev_path, 9, 'r'); - *fd = open (new_dev_path->str, O_RDONLY | O_NONBLOCK); - g_string_free (new_dev_path, TRUE); - - if (*fd < 0) { - return CDS_DATA_1; - } - - if (ioctl (*fd, CDROMREADTOCHDR, &header) == 0) { - return CDS_DATA_1; - } - - type = CDS_DATA_1; - - for (entry.cdte_track = 1; - entry.cdte_track <= header.cdth_trk1; - entry.cdte_track++) { - entry.cdte_format = CDROM_LBA; - if (ioctl (*fd, CDROMREADTOCENTRY, &entry) == 0) { - if (entry.cdte_ctrl & CDROM_DATA_TRACK) { - type = CDS_AUDIO; - break; - } - } - } - - return type; -#endif -} - -static gboolean -mount_volume_iso9660_add (NautilusVolume *volume) -{ -#ifndef SOLARIS_MNT - int fd; - - fd = open (volume->device_path, O_RDONLY | O_NONBLOCK); - if (fd < 0) { - return FALSE; - } - - /* If this fails it's probably not a CD-ROM drive */ - if (ioctl (fd, CDROM_DRIVE_STATUS, CDSL_CURRENT) < 0) { - return FALSE; - } - close (fd); -#endif - - volume->volume_type = NAUTILUS_VOLUME_CDROM; - volume->device_type = NAUTILUS_DEVICE_CD_ROM_DRIVE; - - return TRUE; -} - -static gboolean -mount_volume_affs_add (NautilusVolume *volume) -{ - volume->volume_type = NAUTILUS_VOLUME_AFFS; - volume->device_type = NAUTILUS_DEVICE_UNKNOWN; - - return TRUE; -} - -/* This is intended mainly for adding removable volumes from /etc/fstab. - * The auto type will not show up in /proc/mounts. The NAUTILUS_VOLUME_AUTO - * type is just a practical placeholder. - */ -static gboolean -mount_volume_auto_add (NautilusVolume *volume) -{ - if (eel_str_has_prefix (volume->device_path, floppy_device_path_prefix)) { - volume->volume_type = NAUTILUS_VOLUME_AUTO; - volume->device_type = NAUTILUS_DEVICE_FLOPPY_DRIVE; - } else { - volume->volume_type = NAUTILUS_VOLUME_AUTO; - volume->device_type = NAUTILUS_DEVICE_UNKNOWN; - } - return TRUE; -} - -static gboolean -mount_volume_cdda_add (NautilusVolume *volume) -{ - volume->volume_type = NAUTILUS_VOLUME_CDDA; - volume->device_type = NAUTILUS_DEVICE_CD_ROM_DRIVE; - - return TRUE; -} - -static gboolean -mount_volume_fat_add (NautilusVolume *volume) -{ - volume->volume_type = NAUTILUS_VOLUME_FAT; - volume->device_type = NAUTILUS_DEVICE_UNKNOWN; - - return TRUE; -} - -static gboolean -mount_volume_hpfs_add (NautilusVolume *volume) -{ - volume->volume_type = NAUTILUS_VOLUME_HPFS; - volume->device_type = NAUTILUS_DEVICE_UNKNOWN; - - return TRUE; -} - -static gboolean -mount_volume_hsfs_add (NautilusVolume *volume) -{ - volume->volume_type = NAUTILUS_VOLUME_HSFS; - volume->device_type = NAUTILUS_DEVICE_UNKNOWN; - - return TRUE; -} - -static gboolean -mount_volume_minix_add (NautilusVolume *volume) -{ - volume->volume_type = NAUTILUS_VOLUME_MINIX; - volume->device_type = NAUTILUS_DEVICE_UNKNOWN; - - return TRUE; -} - -static gboolean -mount_volume_nfs_add (NautilusVolume *volume) -{ - /* We need to filter out autofs magic NFS directories. These entries will have the text - * "(pid" in the first element of its entry in /proc/mounts. An example would be eazel:(pid1234) - * or eazel(pid1234). If we signal that the volume monitor has added this type of file system - * the trash monitor will become confused and recurse indefinitely. - */ - - if (strstr (volume->device_path, "(pid") != NULL) { - return FALSE; - } - - volume->volume_type = NAUTILUS_VOLUME_NFS; - volume->device_type = NAUTILUS_DEVICE_NFS; - - return TRUE; -} - -static gboolean -mount_volume_proc_add (NautilusVolume *volume) -{ - volume->volume_type = NAUTILUS_VOLUME_EXT2; - volume->device_type = NAUTILUS_DEVICE_UNKNOWN; - - return TRUE; -} -static gboolean -mount_volume_reiserfs_add (NautilusVolume *volume) -{ - volume->volume_type = NAUTILUS_VOLUME_REISER; - volume->device_type = NAUTILUS_DEVICE_UNKNOWN; - - return TRUE; -} - -static gboolean -mount_volume_ufs_add (NautilusVolume *volume) -{ - volume->volume_type = NAUTILUS_VOLUME_UFS; - volume->device_type = NAUTILUS_DEVICE_UNKNOWN; - - return TRUE; -} - -static gboolean -mount_volume_smb_add (NautilusVolume *volume) -{ - volume->volume_type = NAUTILUS_VOLUME_SMB; - volume->device_type = NAUTILUS_DEVICE_UNKNOWN; - - return TRUE; -} - -static gboolean -mount_volume_unsdos_add (NautilusVolume *volume) -{ - volume->volume_type = NAUTILUS_VOLUME_UNSDOS; - volume->device_type = NAUTILUS_DEVICE_UNKNOWN; - - return TRUE; -} - -static gboolean -mount_volume_xenix_add (NautilusVolume *volume) -{ - volume->volume_type = NAUTILUS_VOLUME_XENIX; - volume->device_type = NAUTILUS_DEVICE_UNKNOWN; - - return TRUE; -} - -static gboolean -mount_volume_xiafs_add (NautilusVolume *volume) -{ - volume->volume_type = NAUTILUS_VOLUME_XIAFS; - volume->device_type = NAUTILUS_DEVICE_UNKNOWN; - - return TRUE; -} - -static void -find_volumes (NautilusVolumeMonitor *monitor) -{ - /* make sure the mount states of disks are set up */ - mount_volumes_check_status (monitor); - load_additional_mount_list_info (monitor->details->mounts); - - /* Add a timer function to check for status change in mounted volumes periodically */ - monitor->details->mount_volume_timer_id = - gtk_timeout_add (CHECK_STATUS_INTERVAL, - (GtkFunction) mount_volumes_check_status, - monitor); -} - -void -nautilus_volume_monitor_each_mounted_volume (NautilusVolumeMonitor *monitor, - NautilusEachVolumeFunction function, - gpointer context) -{ - GList *p; - NautilusVolume *volume; - - for (p = monitor->details->mounts; p != NULL; p = p->next) { - volume = (NautilusVolume *) p->data; - (* function) (volume, context); - } -} - - -gboolean -nautilus_volume_monitor_volume_is_mounted (NautilusVolumeMonitor *monitor, - const NautilusVolume *volume) -{ - GList *p; - NautilusVolume *new_volume; - - for (p = monitor->details->mounts; p != NULL; p = p->next) { - new_volume = (NautilusVolume *)p->data; - - if (strcmp (new_volume->mount_path, volume->mount_path) == 0) { - return TRUE; - } - } - - return FALSE; -} - - -#if USE_VOLRMMOUNT - -static const char *volrmmount_locations [] = { - "/usr/bin/volrmmount", - NULL -}; - -#define MOUNT_COMMAND volrmmount_locations -#define MOUNT_SEPARATOR " -i " -#define UMOUNT_COMMAND volrmmount_locations -#define UMOUNT_SEPARATOR " -e " - -#else - -static const char *mount_known_locations [] = { - "/sbin/mount", "/bin/mount", - "/usr/sbin/mount", "/usr/bin/mount", - NULL -}; - -static const char *umount_known_locations [] = { - "/sbin/umount", "/bin/umount", - "/usr/sbin/umount", "/usr/bin/umount", - NULL -}; - -#define MOUNT_COMMAND mount_known_locations -#define MOUNT_SEPARATOR " " -#define UMOUNT_COMMAND umount_known_locations -#define UMOUNT_SEPARATOR " " - -#endif /* USE_VOLRMMOUNT */ - -/* Returns the full path to the queried command */ -static const char * -find_command (const char **known_locations) -{ - int i; - - for (i = 0; known_locations [i]; i++){ - if (g_file_exists (known_locations [i])) - return known_locations [i]; - } - return NULL; -} - -/* Pipes are guaranteed to be able to hold at least 4096 bytes */ -/* More than that would be unportable */ -#define MAX_PIPE_SIZE 4096 - -static int error_pipe[2]; /* File descriptors of error pipe */ -static int old_error; /* File descriptor of old standard error */ - -/* Creates a pipe to hold standard error for a later analysis. */ -static void -open_error_pipe (void) -{ - pipe (error_pipe); - - old_error = dup (2); - if (old_error < 0 || close(2) || dup (error_pipe[1]) != 2) { - close (error_pipe[0]); - close (error_pipe[1]); - } - - close (error_pipe[1]); -} - -typedef struct { - char *command; - char *mount_point; - gboolean should_mount; -} MountThreadInfo; - -typedef struct { - char *message; - char *detailed_message; - char *mount_point; - gboolean mount; -} MountStatusInfo; - - -static gboolean -display_mount_error (gpointer callback_data) -{ - MountStatusInfo *info; - const char *title; - NautilusVolumeMonitor *monitor; - NautilusVolume *volume; - GList *p; - - info = callback_data; - - title = info->mount ? _("Mount Error") : _("Unmount Error"); - - eel_show_error_dialog_with_details - (info->message, title, info->detailed_message, NULL); - - if (!info->mount) { - /* Locate volume in current list */ - monitor = nautilus_volume_monitor_get (); - for (p = monitor->details->mounts; p != NULL; p = p->next) { - volume = (NautilusVolume *)p->data; - if (strcmp (volume->mount_path, info->mount_point) == 0) { - gtk_signal_emit (GTK_OBJECT (monitor), signals[VOLUME_UNMOUNT_FAILED], volume); - break; - } - } - } - - g_free (info->mount_point); - g_free (info->message); - g_free (info->detailed_message); - g_free (info); - - return FALSE; -} - -static void -close_error_pipe (gboolean mount, const char *mount_path) -{ - char *message; - char detailed_msg[MAX_PIPE_SIZE]; - int length; - gboolean is_floppy; - MountStatusInfo *info; - - if (old_error < 0) { - return; - } - - close (2); - dup (old_error); - close (old_error); - - /* FIXME: This keeps reading into the same buffer over and - * over again and makes no attempt to save bytes from any - * calls other than the last read call. - */ - do { - length = read (error_pipe[0], detailed_msg, MAX_PIPE_SIZE); - } while (length < 0); - - if (length >= 0) { - detailed_msg[length] = 0; - } - - close (error_pipe[0]); - - /* No output to show */ - if (length == 0) { - return; - } - - is_floppy = strstr (mount_path, "floppy") != NULL; - - /* Determine a user readable message from the obscure pipe error */ - /* Attention localizers: The strings being examined by strstr need to be identical - to the errors returned to the terminal by mount. */ - if (mount) { - if (strstr (detailed_msg, _("is write-protected, mounting read-only")) != NULL) { - /* This is not an error. Just an informative message from mount. */ - return; - } else if ((strstr (detailed_msg, _("is not a valid block device")) != NULL) || - (strstr (detailed_msg, _("No medium found")) != NULL)) { - /* No media in drive */ - if (is_floppy) { - /* Handle floppy case */ - message = g_strdup_printf (_("Nautilus was unable to mount the floppy drive. " - "There is probably no floppy in the drive.")); - } else { - /* All others */ - message = g_strdup_printf (_("Nautilus was unable to mount the volume. " - "There is probably no media in the device.")); - } - } else if (strstr (detailed_msg, _("wrong fs type, bad option, bad superblock on")) != NULL) { - /* Unknown filesystem */ - if (is_floppy) { - message = g_strdup_printf (_("Nautilus was unable to mount the floppy drive. " - "The floppy is probably in a format that cannot be mounted.")); - } else { - message = g_strdup_printf (_("Nautilus was unable to mount the selected volume. " - "The volume is probably in a format that cannot be mounted.")); - } - } else { - if (is_floppy) { - message = g_strdup (_("Nautilus was unable to mount the selected floppy drive.")); - } else { - message = g_strdup (_("Nautilus was unable to mount the selected volume.")); - } - } - } else { - /* FIXME: Should we parse this message and report something more meaningful? */ - message = g_strdup (_("Nautilus was unable to unmount the selected volume.")); - } - - /* Set up info and pass it to callback to display dialog. We do this because this - routine may be called from a thread */ - info = g_new0 (MountStatusInfo, 1); - info->message = message; - info->detailed_message = g_strdup (detailed_msg); - info->mount_point = g_strdup (mount_path); - info->mount = mount; - gtk_idle_add (display_mount_error, info); -} - - -static void * -mount_unmount_callback (void *arg) -{ - FILE *file; - MountThreadInfo *info; - info = arg; - - if (info != NULL) { - open_error_pipe (); - file = popen (info->command, "r"); - close_error_pipe (info->should_mount, info->mount_point); - pclose (file); - - g_free (info->command); - g_free (info->mount_point); - g_free (info); - } - - pthread_exit (NULL); - - return NULL; -} - - -void -nautilus_volume_monitor_mount_unmount_removable (NautilusVolumeMonitor *monitor, - const char *mount_point, - gboolean should_mount) -{ - const char *command; - GList *p; - NautilusVolume *volume; - char *command_string; - MountThreadInfo *mount_info; - pthread_t mount_thread; - const char *name; - - volume = NULL; - - /* Check and see if volume exists in mounts already */ - for (p = monitor->details->mounts; p != NULL; p = p->next) { - volume = (NautilusVolume *)p->data; - if (strcmp (volume->mount_path, mount_point) == 0) { - if (should_mount) { - return; - } else { - break; - } - } - } - -#if USE_VOLRMMOUNT - name = strrchr (mount_point, '/'); - if (name != NULL) { - name = name + 1; - } else { - name = mount_point; - } -#else - name = mount_point; -#endif /* USE_VOLRMMOUNT */ - - if (should_mount) { - command = find_command (MOUNT_COMMAND); - command_string = g_strconcat (command, MOUNT_SEPARATOR, name, NULL); - } else { - command = find_command (UMOUNT_COMMAND); - command_string = g_strconcat (command, UMOUNT_SEPARATOR, name, NULL); - if (volume != NULL) { - gtk_signal_emit (GTK_OBJECT (monitor), signals[VOLUME_UNMOUNT_STARTED], volume); - } - } - - mount_info = g_new0 (MountThreadInfo, 1); - mount_info->command = g_strdup (command_string); - mount_info->mount_point = g_strdup (mount_point); - mount_info->should_mount = should_mount; - - pthread_create (&mount_thread, NULL, mount_unmount_callback, mount_info); - - g_free (command_string); -} - - -void -nautilus_volume_monitor_set_volume_name (NautilusVolumeMonitor *monitor, - const NautilusVolume *volume, const char *volume_name) -{ - GList *element; - NautilusVolume *found_volume; - - /* Find volume and set new name */ - for (element = monitor->details->mounts; element != NULL; element = element->next) { - found_volume = element->data; - if (strcmp (found_volume->device_path, volume->device_path) == 0) { - g_free (found_volume->volume_name); - found_volume->volume_name = g_strdup (volume_name); - return; - } - } -} - - -static NautilusVolume * -create_volume (const char *device_path, const char *mount_path, const char *filesystem) -{ - NautilusVolume *volume; - - volume = g_new0 (NautilusVolume, 1); - volume->device_path = g_strdup (device_path); - volume->mount_path = g_strdup (mount_path); - volume->filesystem = g_strdup (filesystem); - - volume->volume_type = NAUTILUS_VOLUME_UNKNOWN; - volume->device_type = NAUTILUS_DEVICE_UNKNOWN; - - return volume; -} - -static NautilusVolume * -copy_volume (NautilusVolume *volume) -{ - NautilusVolume *new_volume; - new_volume = create_volume (volume->device_path, volume->mount_path, volume->filesystem); - - new_volume->volume_type = volume->volume_type; - new_volume->device_type = volume->device_type; - new_volume->volume_name = g_strdup (volume->volume_name); - new_volume->is_removable = volume->is_removable; - new_volume->is_read_only = volume->is_read_only; - - return new_volume; -} - -void -nautilus_volume_monitor_free_volume (NautilusVolume *volume) -{ - g_free (volume->device_path); - g_free (volume->mount_path); - g_free (volume->volume_name); - g_free (volume->filesystem); - g_free (volume); -} - -static void -get_iso9660_volume_name (NautilusVolume *volume, int fd) -{ - struct iso_primary_descriptor iso_buffer; - - lseek (fd, (off_t) 2048*16, SEEK_SET); - read (fd, &iso_buffer, 2048); - - g_free (volume->volume_name); - - volume->volume_name = g_strdup (iso_buffer.volume_id); - if (volume->volume_name == NULL) { - volume->volume_name = g_strdup (_("ISO 9660 Volume")); - } else { - modify_volume_name_for_display (volume); - } -} - -static void -get_ext2_volume_name (NautilusVolume *volume) -{ - char *name; - - name = strrchr (volume->mount_path, '/'); - if (name != NULL) { - /* Handle special case for "/" */ - if (strlen (name) == 1 && strcmp (name, "/") == 0) { - volume->volume_name = g_strdup (_("Root")); - } else { - name++; - volume->volume_name = g_strdup (name); - modify_volume_name_for_display (volume); - } - } else { - volume->volume_name = g_strdup (_("Ext2 Volume")); - } -} - -static void -get_msdos_volume_name (NautilusVolume *volume) -{ - char *name; - - name = strrchr (volume->mount_path, '/'); - if (name != NULL) { - name++; - volume->volume_name = g_strdup (name); - modify_volume_name_for_display (volume); - } else { - volume->volume_name = g_strdup (_("MSDOS Volume")); - } -} - -static void -get_nfs_volume_name (NautilusVolume *volume) -{ - char *name; - - name = strrchr (volume->mount_path, '/'); - if (name != NULL) { - name++; - volume->volume_name = g_strdup (name); - modify_volume_name_for_display (volume); - } else { - volume->volume_name = g_strdup (_("NFS Volume")); - } -} - -static void -get_reiser_volume_name (NautilusVolume *volume) -{ - char *name; - - name = strrchr (volume->mount_path, '/'); - if (name != NULL) { - name++; - volume->volume_name = g_strdup (name); - modify_volume_name_for_display (volume); - } else { - volume->volume_name = g_strdup (_("ReiserFS Volume")); - } -} - - -static void -get_ufs_volume_name (NautilusVolume *volume) -{ - char *name; - - name = strrchr (volume->mount_path, '/'); - if (name != NULL) { - name++; - volume->volume_name = g_strdup (name); - modify_volume_name_for_display (volume); - } else { - volume->volume_name = g_strdup (_("UFS Volume")); - } -} - -static void -get_generic_volume_name (NautilusVolume *volume) -{ - char *name; - - name = strrchr (volume->mount_path, '/'); - if (name != NULL) { - name++; - volume->volume_name = g_strdup (name); - modify_volume_name_for_display (volume); - } else { - volume->volume_name = g_strdup (_("Unknown Volume")); - } -} - - -static void -load_additional_mount_list_info (GList *volume_list) -{ - GList *element; - NautilusVolume *volume; - - for (element = volume_list; element != NULL; element = element->next) { - volume = element->data; - -#ifndef SOLARIS_MNT - /* These are set up by get_current_mount_list for Solaris. */ - volume->is_removable = volume_is_removable (volume); - volume->is_read_only = volume_is_read_only (volume); -#endif - - mount_volume_get_name (volume); - } -} - - -static GList * -mount_volume_add_filesystem (NautilusVolume *volume, GList *volume_list) -{ - gboolean added; - char *device_name; - - added = FALSE; - - if (strcmp (volume->filesystem, "affs") == 0) { - added = mount_volume_affs_add (volume); - } else if (strcmp (volume->filesystem, "auto") == 0) { - added = mount_volume_auto_add (volume); - } else if (strcmp (volume->filesystem, "cdda") == 0) { - added = mount_volume_cdda_add (volume); - } else if (strcmp (volume->filesystem, "hsfs") == 0) { - added = mount_volume_hsfs_add (volume); - } else if (strcmp (volume->filesystem, "ext2") == 0) { - added = mount_volume_ext2_add (volume); - } else if (strcmp (volume->filesystem, "fat") == 0) { - added = mount_volume_fat_add (volume); - } else if (strcmp (volume->filesystem, "hpfs") == 0) { - added = mount_volume_hpfs_add (volume); - } else if (strcmp (volume->filesystem, "iso9660") == 0) { - added = mount_volume_iso9660_add (volume); - } else if (strcmp (volume->filesystem, "minix") == 0) { - added = mount_volume_minix_add (volume); - } else if (strcmp (volume->filesystem, "msdos") == 0) { - added = mount_volume_msdos_add (volume); - } else if (strcmp (volume->filesystem, "nfs") == 0) { - added = mount_volume_nfs_add (volume); - } else if (strcmp (volume->filesystem, "proc") == 0) { - added = mount_volume_proc_add (volume); - } else if (strcmp (volume->filesystem, "reiserfs") == 0) { - added = mount_volume_reiserfs_add (volume); - } else if (strcmp (volume->filesystem, "ufs") == 0) { - added = mount_volume_ufs_add (volume); - } else if (strcmp (volume->filesystem, "smb") == 0) { - added = mount_volume_smb_add (volume); - } else if (strcmp (volume->filesystem, "udf") == 0) { - added = mount_volume_udf_add (volume); - } else if (strcmp (volume->filesystem, "ufs") == 0) { - added = mount_volume_udf_add (volume); - } else if (strcmp (volume->filesystem, "unsdos") == 0) { - added = mount_volume_unsdos_add (volume); - } else if (strcmp (volume->filesystem, "vfat") == 0) { - added = mount_volume_vfat_add (volume); - } else if (strcmp (volume->filesystem, "xenix") == 0) { - added = mount_volume_xenix_add (volume); - } else if (strcmp (volume->filesystem, "xiafs") == 0) { - added = mount_volume_xiafs_add (volume); - } - - if (added) { - volume_list = g_list_append (volume_list, volume); - - /* Identify device type */ - if (eel_str_has_prefix (volume->mount_path, "/mnt/")) { - device_name = g_strdup (volume->mount_path + 5); - - if (eel_str_has_prefix (device_name, "cdrom")) { - volume->device_type = NAUTILUS_DEVICE_CD_ROM_DRIVE; - volume->is_removable = TRUE; - } else if (eel_str_has_prefix (device_name, "floppy")) { - volume->device_type = NAUTILUS_DEVICE_FLOPPY_DRIVE; - volume->is_removable = TRUE; - } else if (eel_str_has_prefix (volume->device_path, floppy_device_path_prefix)) { - volume->device_type = NAUTILUS_DEVICE_FLOPPY_DRIVE; - volume->is_removable = TRUE; - } else if (eel_str_has_prefix (device_name, "zip")) { - volume->device_type = NAUTILUS_DEVICE_ZIP_DRIVE; - volume->is_removable = TRUE; - } else if (eel_str_has_prefix (device_name, "jaz")) { - volume->device_type = NAUTILUS_DEVICE_JAZ_DRIVE; - volume->is_removable = TRUE; - } else if (eel_str_has_prefix (device_name, "camera")) { - volume->device_type = NAUTILUS_DEVICE_CAMERA; - volume->is_removable = TRUE; - } else if (eel_str_has_prefix (device_name, "memstick")) { - volume->device_type = NAUTILUS_DEVICE_MEMORY_STICK; - volume->is_removable = TRUE; - } else { - volume->device_type = NAUTILUS_DEVICE_UNKNOWN; - volume->is_removable = FALSE; - } - - g_free (device_name); - } - } else { - nautilus_volume_monitor_free_volume (volume); - } - - return volume_list; -} - -char * -nautilus_volume_monitor_get_mount_name_for_display (NautilusVolumeMonitor *monitor, NautilusVolume *volume) -{ - const char *name, *found_name; - - if (monitor == NULL || volume == NULL) { - return NULL; - } - - name = strrchr (volume->mount_path, '/'); - if (name != NULL) { - name = name + 1; - } else { - name = volume->mount_path; - } - - /* Look for a match in out localized mount name list */ - found_name = g_hash_table_lookup (monitor->details->readable_mount_point_names, name); - if (found_name != NULL) { - return g_strdup (found_name); - } else { - return g_strdup (name); - } -} - -#ifdef HAVE_CDDA - -static gboolean -locate_audio_cd (void) -{ - cdrom_drive *drive; - gboolean opened; - - drive = cdda_identify (CD_AUDIO_PATH, FALSE, NULL); - if (drive == NULL) { - return FALSE; - } - - /* Turn off verbosity */ - cdda_verbose_set (drive, CDDA_MESSAGE_FORGETIT, CDDA_MESSAGE_FORGETIT); - - /* Open drive */ - switch (cdda_open (drive)) { - case -2: - case -3: - case -4: - case -5: - /*g_message ("Unable to open disc. Is there an audio CD in the drive?");*/ - opened = FALSE; - break; - - case -6: - /*g_message ("CDDA method could not find a way to read audio from this drive.");*/ - opened = FALSE; - break; - - case 0: - opened = TRUE; - break; - - default: - /*g_message ("Unable to open disc.");*/ - opened = FALSE; - break; - } - cdda_close (drive); - - return opened; -} - -#endif /* HAVE_CDDA */ diff --git a/libnautilus-extensions/nautilus-volume-monitor.h b/libnautilus-extensions/nautilus-volume-monitor.h deleted file mode 100644 index c7eb3489e..000000000 --- a/libnautilus-extensions/nautilus-volume-monitor.h +++ /dev/null @@ -1,135 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ - -/* nautilus-volume-monitor.h - interface for desktop mounting functions. - - Copyright (C) 2000 Eazel, Inc. - - The Gnome 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 Gnome 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 the Gnome 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. - - Authors: Gene Z. Ragan <gzr@eazel.com> -*/ - -#ifndef NAUTILUS_VOLUME_MONITOR_H -#define NAUTILUS_VOLUME_MONITOR_H - -#include <gtk/gtkobject.h> - -typedef struct NautilusVolumeMonitor NautilusVolumeMonitor; -typedef struct NautilusVolumeMonitorClass NautilusVolumeMonitorClass; -typedef struct NautilusVolumeMonitorDetails NautilusVolumeMonitorDetails; - -#define NAUTILUS_TYPE_VOLUME_MONITOR (nautilus_volume_monitor_get_type()) -#define NAUTILUS_VOLUME_MONITOR(obj) (GTK_CHECK_CAST ((obj), NAUTILUS_TYPE_VOLUME_MONITOR, NautilusVolumeMonitor)) -#define NAUTILUS_VOLUME_MONITOR_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), NAUTILUS_TYPE_VOLUME_MONITOR, NautilusVolumeMonitorClass)) -#define IS_NAUTILUS_VOLUME_MONITOR(obj) (GTK_CHECK_TYPE ((obj), NAUTILUS_TYPE_VOLUME_MONITOR)) - -struct NautilusVolumeMonitor { - GtkObject parent; - NautilusVolumeMonitorDetails *details; -}; - -typedef struct NautilusVolume NautilusVolume; - -struct NautilusVolumeMonitorClass { - GtkObjectClass parent_class; - - /* Signals */ - void (* volume_mounted) (NautilusVolumeMonitor *monitor, - const NautilusVolume *volume); - void (* volume_unmount_started) (NautilusVolumeMonitor *monitor, - const NautilusVolume *volume); - void (* volume_unmount_failed) (NautilusVolumeMonitor *monitor, - const NautilusVolume *volume); - void (* volume_unmounted) (NautilusVolumeMonitor *monitor, - const NautilusVolume *volume); -}; - -typedef enum { - NAUTILUS_VOLUME_AFFS, - NAUTILUS_VOLUME_AUTO, - NAUTILUS_VOLUME_CDDA, - NAUTILUS_VOLUME_CDROM, - NAUTILUS_VOLUME_EXT2, - NAUTILUS_VOLUME_FAT, - NAUTILUS_VOLUME_HPFS, - NAUTILUS_VOLUME_HSFS, - NAUTILUS_VOLUME_MINIX, - NAUTILUS_VOLUME_MSDOS, - NAUTILUS_VOLUME_NFS, - NAUTILUS_VOLUME_REISER, - NAUTILUS_VOLUME_SMB, - NAUTILUS_VOLUME_UDF, - NAUTILUS_VOLUME_UFS, - NAUTILUS_VOLUME_UNSDOS, - NAUTILUS_VOLUME_VFAT, - NAUTILUS_VOLUME_XENIX, - NAUTILUS_VOLUME_XIAFS, - NAUTILUS_VOLUME_UNKNOWN -} NautilusVolumeType; - -typedef enum { - NAUTILUS_DEVICE_AUDIO_CD, - NAUTILUS_DEVICE_CAMERA, - NAUTILUS_DEVICE_CD_ROM_DRIVE, - NAUTILUS_DEVICE_FLOPPY_DRIVE, - NAUTILUS_DEVICE_JAZ_DRIVE, - NAUTILUS_DEVICE_MEMORY_STICK, - NAUTILUS_DEVICE_NFS, - NAUTILUS_DEVICE_ZIP_DRIVE, - NAUTILUS_DEVICE_UNKNOWN -} NautilusDeviceType; - -struct NautilusVolume { - NautilusVolumeType volume_type; - NautilusDeviceType device_type; - - char *device_path; - char *mount_path; - char *volume_name; - char *filesystem; - - gboolean is_removable; - gboolean is_read_only; -}; - -typedef gboolean (* NautilusEachVolumeFunction) (const NautilusVolume *, gpointer); - -GtkType nautilus_volume_monitor_get_type (void); -NautilusVolumeMonitor *nautilus_volume_monitor_get (void); -char *nautilus_volume_monitor_get_volume_name (const NautilusVolume *volume); - -void nautilus_volume_monitor_mount_unmount_removable (NautilusVolumeMonitor *monitor, - const char *mount_point, - gboolean should_mount); -gboolean nautilus_volume_monitor_volume_is_mounted (NautilusVolumeMonitor *monitor, - const NautilusVolume *mount_point); -gboolean nautilus_volume_monitor_volume_is_removable (const NautilusVolume *volume); -gboolean nautilus_volume_monitor_is_volume_link (const char *path); - -gboolean nautilus_volume_monitor_should_integrate_trash (const NautilusVolume *volume); -const char *nautilus_volume_monitor_get_volume_mount_uri (const NautilusVolume *volume); -void nautilus_volume_monitor_each_mounted_volume (NautilusVolumeMonitor *monitor, - NautilusEachVolumeFunction function, - gpointer context); -const GList *nautilus_volume_monitor_get_removable_volumes (NautilusVolumeMonitor *monitor); -void nautilus_volume_monitor_free_volume (NautilusVolume *volume); -char *nautilus_volume_monitor_get_target_uri (const NautilusVolume *volume); -void nautilus_volume_monitor_set_volume_name (NautilusVolumeMonitor *monitor, - const NautilusVolume *volume, - const char *volume_name); -char *nautilus_volume_monitor_get_mount_name_for_display (NautilusVolumeMonitor *monitor, - NautilusVolume *volume); -#endif /* NAUTILUS_VOLUME_MONITOR_H */ |