Fixed bug 640 (icon cache never frees images (awaiting GdkPixbuf

fix)). Also took care of bug 3145 (zillions of 'main_loops !=
	NULL' assertion failures when quitting) and bug 3138 (Some code in
	the icon factory is cut and pasted from elsewhere). And a few
	unrelated things that came up while I was busy working on these.

	* configure.in: Applied patch from Dan Winship to fix handling of
	CFLAGS and LDFLAGS. Fixes some missing quoting and other mistakes.

	* libnautilus-extensions/Makefile.am:
	* libnautilus-extensions/nautilus-icon-factory-private.h:
	* libnautilus-extensions/nautilus-thumbnails.c:
	* libnautilus-extensions/nautilus-thumbnails.h:
	Broke out the thumbnailing code into its own source file for
	clarity.

	* libnautilus-extensions/nautilus-directory.c:
	* libnautilus-extensions/nautilus-file-utilities.h:
	* libnautilus-extensions/nautilus-file-utilities.c:
	(nautilus_make_directory_and_parents):
	Moved nautilus_make_directory_and_parents into a place where the
	thumbnail code can share it instead of requiring its own copy.

	* libnautilus-extensions/nautilus-global-preferences.h:
	* libnautilus-extensions/nautilus-global-preferences.c:
	(destroy_global_prefs_dialog), (global_preferences_get_dialog),
	(nautilus_global_preferences_dialog_update),
	(nautilus_global_preferences_initialize):
	* libnautilus-extensions/nautilus-preferences.h:
	* libnautilus-extensions/nautilus-preferences.c:
	(preferences_initialize_if_needed), (preferences_shutdown):
	* src/nautilus-application.c: (nautilus_application_destroy):
	Changed code so that it cleans up with g_atexit instead of with an
	explicit shutdown call. This makes it sequence correctly with
	other atexit code.

	* libnautilus-extensions/nautilus-icon-canvas-item.h:
	* libnautilus-extensions/nautilus-icon-canvas-item.c:
	(nautilus_icon_canvas_item_destroy),
	(nautilus_icon_canvas_item_set_attach_points),
	(emblem_layout_next):
	* libnautilus-extensions/nautilus-icon-container.c:
	(nautilus_icon_container_update_icon):
	Added a Nautilus prefix to the EmblemAttachPoints typedef, since
	it's public.

	* libnautilus-extensions/nautilus-icon-factory.h:
	* libnautilus-extensions/nautilus-icon-factory.c:
	Changed the icon factory structure so that it will actually free
	pixbufs when done with them. Made some other small fixes to the
	icon factory in passing, including removing some redundant code
	and fixing the logic for getting custom icons and deleting the
	icon factory and g_atexit time.

	* src/file-manager/fm-icon-view.c: (play_file), (preview_sound):
	Restructured the logic for playing sound previews a little to get
	rid of compiler warnings and close some loopholes in the old code.

	* src/nautilus-main.c: (is_event_loop_needed),
	(quit_if_in_main_loop), (nautilus_gtk_main_quit_all),
	(event_loop_unregister), (nautilus_main_event_loop_register),
	(nautilus_main_is_event_loop_mainstay),
	(nautilus_main_event_loop_quit), (main): Fixed the main loop
	quitting logic so that it is a bit simpler and works with the
	gnome-vfs code that runs event handling after the last main loop
	is gone.
This commit is contained in:
Darin Adler 2000-09-20 00:44:07 +00:00
parent 1a0af90190
commit 1035b5ea66
38 changed files with 3053 additions and 2553 deletions

View file

@ -1,3 +1,72 @@
2000-09-19 Darin Adler <darin@eazel.com>
Fixed bug 640 (icon cache never frees images (awaiting GdkPixbuf
fix)). Also took care of bug 3145 (zillions of 'main_loops !=
NULL' assertion failures when quitting) and bug 3138 (Some code in
the icon factory is cut and pasted from elsewhere). And a few
unrelated things that came up while I was busy working on these.
* configure.in: Applied patch from Dan Winship to fix handling of
CFLAGS and LDFLAGS. Fixes some missing quoting and other mistakes.
* libnautilus-extensions/Makefile.am:
* libnautilus-extensions/nautilus-icon-factory-private.h:
* libnautilus-extensions/nautilus-thumbnails.c:
* libnautilus-extensions/nautilus-thumbnails.h:
Broke out the thumbnailing code into its own source file for
clarity.
* libnautilus-extensions/nautilus-directory.c:
* libnautilus-extensions/nautilus-file-utilities.h:
* libnautilus-extensions/nautilus-file-utilities.c:
(nautilus_make_directory_and_parents):
Moved nautilus_make_directory_and_parents into a place where the
thumbnail code can share it instead of requiring its own copy.
* libnautilus-extensions/nautilus-global-preferences.h:
* libnautilus-extensions/nautilus-global-preferences.c:
(destroy_global_prefs_dialog), (global_preferences_get_dialog),
(nautilus_global_preferences_dialog_update),
(nautilus_global_preferences_initialize):
* libnautilus-extensions/nautilus-preferences.h:
* libnautilus-extensions/nautilus-preferences.c:
(preferences_initialize_if_needed), (preferences_shutdown):
* src/nautilus-application.c: (nautilus_application_destroy):
Changed code so that it cleans up with g_atexit instead of with an
explicit shutdown call. This makes it sequence correctly with
other atexit code.
* libnautilus-extensions/nautilus-icon-canvas-item.h:
* libnautilus-extensions/nautilus-icon-canvas-item.c:
(nautilus_icon_canvas_item_destroy),
(nautilus_icon_canvas_item_set_attach_points),
(emblem_layout_next):
* libnautilus-extensions/nautilus-icon-container.c:
(nautilus_icon_container_update_icon):
Added a Nautilus prefix to the EmblemAttachPoints typedef, since
it's public.
* libnautilus-extensions/nautilus-icon-factory.h:
* libnautilus-extensions/nautilus-icon-factory.c:
Changed the icon factory structure so that it will actually free
pixbufs when done with them. Made some other small fixes to the
icon factory in passing, including removing some redundant code
and fixing the logic for getting custom icons and deleting the
icon factory and g_atexit time.
* src/file-manager/fm-icon-view.c: (play_file), (preview_sound):
Restructured the logic for playing sound previews a little to get
rid of compiler warnings and close some loopholes in the old code.
* src/nautilus-main.c: (is_event_loop_needed),
(quit_if_in_main_loop), (nautilus_gtk_main_quit_all),
(event_loop_unregister), (nautilus_main_event_loop_register),
(nautilus_main_is_event_loop_mainstay),
(nautilus_main_event_loop_quit), (main): Fixed the main loop
quitting logic so that it is a bit simpler and works with the
gnome-vfs code that runs event handling after the last main loop
is gone.
2000-09-19 John Sullivan <sullivan@eazel.com>
Fixed bug 2519 (fix hideous queue_size_request hack)

View file

@ -120,7 +120,7 @@ _save_cc="$CC"
dnl Hack flags to find the mozilla stuff
CFLAGS="$_save_cflags -I$_mozilla_include_place"
LDFLAGS="$_save_cflags -L$_mozilla_lib_place"
LDFLAGS="$_save_ldflags -L$_mozilla_lib_place"
dnl Check for nspr and friends
AC_CHECK_LIB(nspr4, PR_Init, [_mozilla_nspr_libs="-lnspr4"])
@ -149,20 +149,20 @@ else
fi
dnl The next two are pure from evil
CC=$_save_cc
CC="$_save_cc"
dnl gtk superwin library
LDFLAGS="$_save_cflags -L$_mozilla_lib_place $_mozilla_all_nspr_flags -lgtksuperwin"
LDFLAGS="$_save_ldflags -L$_mozilla_lib_place $_mozilla_all_nspr_flags -lgtksuperwin"
AC_CHECK_LIB(gtksuperwin, gdk_superwin_get_type, [_mozilla_gtk_super_win_libs="-lgtksuperwin"])
dnl gtk moz embed library
LDFLAGS="$_save_cflags -L$_mozilla_lib_place $_mozilla_all_nspr_flags -lgtkembedmoz $_mozilla_xpcom_libs"
LDFLAGS="$_save_ldflags -L$_mozilla_lib_place $_mozilla_all_nspr_flags -lgtkembedmoz $_mozilla_xpcom_libs"
AC_CHECK_LIB(gtkembedmoz, gtk_moz_embed_get_type, [_mozilla_gtk_moz_embed_libs="-lgtkembedmoz"])
dnl Restore the flags and compiler
CFLAGS=$_save_cflags
LDFLAGS=$_save_ldflags
CC=$_save_cc
CFLAGS="$_save_cflags"
LDFLAGS="$_save_ldflags"
CC="$_save_cc"
dnl Now make sure all the libraries are good
AC_MSG_CHECKING(for Mozilla)
@ -258,7 +258,6 @@ dnl =>
AC_CHECK_LIB(popt, poptParseArgvString, [rpm_libs="$rpm_libs -lpopt"])
AC_CHECK_LIB(rpm, rpmRunTransactions,[build_rpmview=true],
[build_rpmview=false],-lz $rpm_libs -ldb)
LDFLAGS="$save_LDFLAGS"
if test "x$build_rpmview" = "xtrue" ; then
AC_DEFINE(HAVE_RPM)
RPM_LIBS="-lrpm -lz $rpm_libs -ldb"

View file

@ -117,6 +117,7 @@ libnautilus_extensions_la_SOURCES = \
nautilus-string.c \
nautilus-text-caption.c \
nautilus-theme.c \
nautilus-thumbnails.c \
nautilus-trash-directory.c \
nautilus-undo-context.c \
nautilus-undo-manager.c \
@ -177,6 +178,7 @@ noinst_HEADERS = \
nautilus-icon-container.h \
nautilus-icon-dnd.h \
nautilus-icon-factory.h \
nautilus-icon-factory-private.h \
nautilus-icon-private.h \
nautilus-icon-text-item.h \
nautilus-image.h \
@ -213,6 +215,7 @@ noinst_HEADERS = \
nautilus-string.h \
nautilus-text-caption.h \
nautilus-theme.h \
nautilus-thumbnails.h \
nautilus-trash-directory.h \
nautilus-undo-context.h \
nautilus-undo-manager.h \

View file

@ -67,8 +67,6 @@ static void nautilus_directory_destroy (GtkObject *obje
static void nautilus_directory_initialize (gpointer object,
gpointer klass);
static void nautilus_directory_initialize_class (NautilusDirectoryClass *klass);
static GnomeVFSResult nautilus_make_directory_and_parents (GnomeVFSURI *uri,
guint permissions);
static NautilusDirectory *nautilus_directory_new (const char *uri);
static char *real_get_name_for_self_as_new_file (NautilusDirectory *directory);
@ -343,42 +341,6 @@ nautilus_directory_get_uri (NautilusDirectory *directory)
return g_strdup (directory->details->uri);
}
static GnomeVFSResult
nautilus_make_directory_and_parents (GnomeVFSURI *uri, guint permissions)
{
GnomeVFSResult result;
GnomeVFSURI *parent_uri;
/* Make the directory, and return right away unless there's
a possible problem with the parent.
*/
result = gnome_vfs_make_directory_for_uri (uri, permissions);
if (result != GNOME_VFS_ERROR_NOT_FOUND) {
return result;
}
/* If we can't get a parent, we are done. */
parent_uri = gnome_vfs_uri_get_parent (uri);
if (parent_uri == NULL) {
return result;
}
/* If we can get a parent, use a recursive call to create
the parent and its parents.
*/
result = nautilus_make_directory_and_parents (parent_uri, permissions);
gnome_vfs_uri_unref (parent_uri);
if (result != GNOME_VFS_OK) {
return result;
}
/* A second try at making the directory after the parents
have all been created.
*/
result = gnome_vfs_make_directory_for_uri (uri, permissions);
return result;
}
static GnomeVFSURI *
construct_private_metafile_vfs_uri (const char *uri)
{

View file

@ -725,6 +725,42 @@ nautilus_read_file_cancel (NautilusReadFileHandle *handle)
g_free (handle);
}
GnomeVFSResult
nautilus_make_directory_and_parents (GnomeVFSURI *uri, guint permissions)
{
GnomeVFSResult result;
GnomeVFSURI *parent_uri;
/* Make the directory, and return right away unless there's
a possible problem with the parent.
*/
result = gnome_vfs_make_directory_for_uri (uri, permissions);
if (result != GNOME_VFS_ERROR_NOT_FOUND) {
return result;
}
/* If we can't get a parent, we are done. */
parent_uri = gnome_vfs_uri_get_parent (uri);
if (parent_uri == NULL) {
return result;
}
/* If we can get a parent, use a recursive call to create
the parent and its parents.
*/
result = nautilus_make_directory_and_parents (parent_uri, permissions);
gnome_vfs_uri_unref (parent_uri);
if (result != GNOME_VFS_OK) {
return result;
}
/* A second try at making the directory after the parents
have all been created.
*/
result = gnome_vfs_make_directory_for_uri (uri, permissions);
return result;
}
#if !defined (NAUTILUS_OMIT_SELF_CHECK)
void

View file

@ -40,9 +40,8 @@ char * nautilus_format_uri_for_display (const char
char * nautilus_make_uri_from_input (const char *location);
gboolean nautilus_uri_is_trash (const char *uri);
char * nautilus_make_uri_canonical (const char *uri);
gboolean nautilus_uris_match (const char *uri_1,
const char *uri_2);
gboolean nautilus_uris_match (const char *uri_1,
const char *uri_2);
/* FIXME bugzilla.eazel.com 2424:
* This is the same as gnome-libs g_concat_dir_and_file except
* for handling path == NULL.
@ -89,4 +88,8 @@ NautilusReadFileHandle *nautilus_read_file_async (const char
gpointer callback_data);
void nautilus_read_file_cancel (NautilusReadFileHandle *handle);
/* gnome-vfs cover to make a directory and parents */
GnomeVFSResult nautilus_make_directory_and_parents (GnomeVFSURI *uri,
guint permissions);
#endif /* NAUTILUS_FILE_UTILITIES_H */

View file

@ -389,16 +389,33 @@ nautilus_global_preferences_get_disabled_sidebar_panel_view_identifiers (void)
return disabled_view_identifiers;
}
static void
destroy_global_prefs_dialog (void)
{
/* Free the dialog first, cause it has refs to preferences */
if (global_prefs_dialog != NULL) {
/* Since it's a top-level window, it's OK to destroy rather than unref'ing. */
gtk_widget_destroy (global_prefs_dialog);
}
}
static GtkWidget *
global_preferences_get_dialog (void)
{
static gboolean set_up_exit = FALSE;
nautilus_global_preferences_initialize ();
if (!global_prefs_dialog)
{
if (global_prefs_dialog == NULL) {
global_prefs_dialog = global_preferences_create_dialog ();
}
if (!set_up_exit) {
g_atexit (destroy_global_prefs_dialog);
set_up_exit = TRUE;
}
return global_prefs_dialog;
}
@ -863,9 +880,10 @@ nautilus_global_preferences_dialog_update (void)
was_showing = GTK_WIDGET_VISIBLE (global_prefs_dialog);
gtk_widget_destroy (global_prefs_dialog);
global_prefs_dialog = NULL;
}
global_prefs_dialog = global_preferences_create_dialog ();
global_preferences_get_dialog ();
if (was_showing) {
nautilus_global_preferences_show_dialog ();
@ -885,16 +903,3 @@ nautilus_global_preferences_initialize (void)
initialized = TRUE;
}
void
nautilus_global_preferences_shutdown (void)
{
/* Free the dialog first, cause it has refs to preferences */
if (global_prefs_dialog != NULL) {
gtk_widget_destroy (global_prefs_dialog);
}
/* Now free the preferences tables and stuff */
nautilus_preferences_shutdown ();
}

View file

@ -124,7 +124,6 @@ typedef enum
void nautilus_global_preferences_initialize (void);
void nautilus_global_preferences_shutdown (void);
void nautilus_global_preferences_show_dialog (void);
void nautilus_global_preferences_hide_dialog (void);
void nautilus_global_preferences_set_dialog_title (const char *title);

View file

@ -68,7 +68,7 @@ struct NautilusIconCanvasItemDetails {
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;
EmblemAttachPoints *attach_pointer;
NautilusEmblemAttachPoints *attach_points;
/* Size of the text at current font. */
int text_width;
@ -301,7 +301,7 @@ nautilus_icon_canvas_item_destroy (GtkObject *object)
nautilus_gdk_pixbuf_list_free (details->emblem_pixbufs);
g_free (details->editable_text);
g_free (details->additional_text);
g_free (details->attach_pointer);
g_free (details->attach_points);
if (details->font != NULL) {
gdk_font_unref (details->font);
@ -531,14 +531,14 @@ nautilus_icon_canvas_item_set_emblems (NautilusIconCanvasItem *item,
void
nautilus_icon_canvas_item_set_attach_points (NautilusIconCanvasItem *item,
EmblemAttachPoints *attach_points)
NautilusEmblemAttachPoints *attach_points)
{
g_free (item->details->attach_pointer);
item->details->attach_pointer = NULL;
g_free (item->details->attach_points);
item->details->attach_points = NULL;
if (attach_points && attach_points->has_attach_points) {
item->details->attach_pointer = g_new0 (EmblemAttachPoints, 1);
*item->details->attach_pointer = *attach_points;
if (attach_points != NULL && attach_points->num_points != 0) {
item->details->attach_points = g_new (NautilusEmblemAttachPoints, 1);
*item->details->attach_points = *attach_points;
}
}
@ -945,7 +945,7 @@ emblem_layout_next (EmblemLayout *layout,
{
GdkPixbuf *pixbuf;
int width, height, x, y;
EmblemAttachPoints *attach_info ;
NautilusEmblemAttachPoints *attach_points;
/* Check if we have layed out all of the pixbufs. */
if (layout->emblem == NULL) {
@ -961,13 +961,14 @@ emblem_layout_next (EmblemLayout *layout,
/* Advance to the next emblem. */
layout->emblem = layout->emblem->next;
if (layout->icon_item->details->attach_pointer) {
if (layout->index >= MAX_ATTACH_POINTS)
attach_points = layout->icon_item->details->attach_points;
if (attach_points != NULL) {
if (layout->index >= attach_points->num_points) {
return FALSE;
}
attach_info = layout->icon_item->details->attach_pointer;
x = layout->icon_rect.x0 + attach_info->attach_points[layout->index].x;
y = layout->icon_rect.y0 + attach_info->attach_points[layout->index].y;
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;

View file

@ -66,34 +66,33 @@ 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,
EmblemAttachPoints *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);
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,
const ArtDRect *world_rectangle);
gboolean nautilus_icon_canvas_item_hit_test_stretch_handles (NautilusIconCanvasItem *item,
const ArtPoint *world_point);
void nautilus_icon_canvas_item_get_icon_rectangle (NautilusIconCanvasItem *item,
ArtDRect *world_rectangle);
void nautilus_icon_canvas_item_update_bounds (NautilusIconCanvasItem *item);
void nautilus_icon_canvas_item_set_smooth_font (NautilusIconCanvasItem *item,
NautilusScalableFont *font);
void nautilus_icon_canvas_item_set_smooth_font_size (NautilusIconCanvasItem *item,
guint font_size);
gboolean nautilus_icon_canvas_item_hit_test_rectangle (NautilusIconCanvasItem *item,
const ArtDRect *world_rectangle);
gboolean nautilus_icon_canvas_item_hit_test_stretch_handles (NautilusIconCanvasItem *item,
const ArtPoint *world_point);
void nautilus_icon_canvas_item_get_icon_rectangle (NautilusIconCanvasItem *item,
ArtDRect *world_rectangle);
void nautilus_icon_canvas_item_update_bounds (NautilusIconCanvasItem *item);
void nautilus_icon_canvas_item_set_smooth_font (NautilusIconCanvasItem *item,
NautilusScalableFont *font);
void nautilus_icon_canvas_item_set_smooth_font_size (NautilusIconCanvasItem *item,
guint font_size);
END_GNOME_DECLS

View file

@ -3209,7 +3209,7 @@ nautilus_icon_container_update_icon (NautilusIconContainer *container,
NautilusIconContainerDetails *details;
guint icon_size_x, icon_size_y, max_image_size, max_emblem_size;
NautilusScalableIcon *scalable_icon;
EmblemAttachPoints attach_points;
NautilusEmblemAttachPoints attach_points;
GdkPixbuf *pixbuf, *emblem_pixbuf;
GList *emblem_scalable_icons, *emblem_pixbufs, *p;
char *editable_text, *additional_text;

View file

@ -0,0 +1,33 @@
/* -*- 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"
void nautilus_icon_factory_remove_by_uri (const char *uri);
#endif /* NAUTILUS_ICON_FACTORY_PRIVATE_H */

File diff suppressed because it is too large Load diff

View file

@ -82,9 +82,9 @@ typedef struct NautilusScalableIcon NautilusScalableIcon;
#define MAX_ATTACH_POINTS 8
typedef struct {
gboolean has_attach_points;
GdkPoint attach_points[MAX_ATTACH_POINTS];
} EmblemAttachPoints;
int num_points;
GdkPoint points[MAX_ATTACH_POINTS];
} NautilusEmblemAttachPoints;
/* Instead of a class declaration here, I will just document
* the signals.
@ -98,19 +98,19 @@ typedef struct {
GtkObject * nautilus_icon_factory_get (void);
/* Relationship between zoom levels and icons sizes. */
guint nautilus_get_icon_size_for_zoom_level (NautilusZoomLevel zoom_level);
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 anti_aliased);
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,
gboolean anti_aliased,
NautilusStringList *exclude);
NautilusScalableIcon *nautilus_icon_factory_get_emblem_icon_by_name (const char *emblem_name,
gboolean anti_aliased);
NautilusScalableIcon *nautilus_icon_factory_get_icon_for_file (NautilusFile *file,
const char *modifier,
gboolean anti_aliased);
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,
gboolean anti_aliased,
NautilusStringList *exclude);
NautilusScalableIcon *nautilus_icon_factory_get_emblem_icon_by_name (const char *emblem_name,
gboolean anti_aliased);
/* Render an icon to a particular size.
* Ownership of a ref. count in this pixbuf comes with the deal.
@ -118,59 +118,59 @@ NautilusScalableIcon *nautilus_icon_factory_get_emblem_icon_by_name (const cha
* 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
*/
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,
EmblemAttachPoints *attach_points);
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,
NautilusEmblemAttachPoints *attach_points);
/* 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 anti_aliased);
GdkPixbuf * nautilus_icon_factory_get_pixbuf_for_file (NautilusFile *file,
const char *modifer,
guint size_in_pixels,
gboolean anti_aliased);
/* 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);
void nautilus_icon_factory_get_pixmap_and_mask_for_file (NautilusFile *file,
const char *modifer,
guint size_in_pixels,
GdkPixmap **pixmap,
GdkBitmap **mask);
/* 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);
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 **name_return,
char **modifier_return,
char **embedded_text_return);
void nautilus_scalable_icon_get_text_pieces (NautilusScalableIcon *scalable_icon,
char **uri_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 *name,
const char *modifier,
const char *embedded_text,
gboolean anti_aliased);
NautilusScalableIcon *nautilus_scalable_icon_new_from_text_pieces (const char *uri,
const char *name,
const char *modifier,
const char *embedded_text,
gboolean anti_aliased);
/* 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);
void nautilus_scalable_icon_list_free (GList *scalable_icon_list);
#endif /* NAUTILUS_ICON_FACTORY_H */

View file

@ -121,6 +121,7 @@ static void preferences_hash_node_remove_callback
static PreferencesHashNode * preferences_hash_node_lookup (const char *name);
static void preferences_register (const char *name);
static gboolean preferences_initialize_if_needed (void);
static void preferences_shutdown (void);
static char * preferences_make_make_gconf_key (const char *preference_name);
/* GConf callbacks */
@ -130,7 +131,7 @@ static void preferences_gconf_by_user_level_callback
GConfValue *value,
gboolean is_default,
gpointer user_data);
static void preferences_gconf_callback (GConfClient *client,
static void preferences_gconf_callback (GConfClient *client,
guint cnxn_id,
const gchar *key,
GConfValue *value,
@ -737,6 +738,8 @@ preferences_initialize_if_needed (void)
user_level_changed_callback,
NULL);
g_atexit (preferences_shutdown);
return TRUE;
}
@ -1048,8 +1051,8 @@ nautilus_preferences_get (const char *name,
return value;
}
void
nautilus_preferences_shutdown (void)
static void
preferences_shutdown (void)
{
if (GLOBAL.preference_table == NULL && GLOBAL.gconf_client == NULL) {
return;

View file

@ -89,8 +89,6 @@ void nautilus_preferences_set (const char
const char *value);
char * nautilus_preferences_get (const char *name,
const gchar *default_value);
void nautilus_preferences_shutdown (void);
END_GNOME_DECLS

View file

@ -0,0 +1,505 @@
/* -*- 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>
*/
#include <config.h>
#include "nautilus-thumbnails.h"
#include <libgnomevfs/gnome-vfs-file-info.h>
#include <string.h>
#include "nautilus-file-utilities.h"
#include "nautilus-string.h"
#include <gtk/gtkmain.h>
#include "nautilus-icon-factory-private.h"
#include "nautilus-directory-notify.h"
#include "nautilus-theme.h"
#include <stdio.h>
#include "nautilus-gdk-pixbuf-extensions.h"
#include <unistd.h>
#include <librsvg/rsvg.h>
#include "nautilus-graphic-effects.h"
/* permissions for thumbnail directory */
#define THUMBNAIL_DIR_PERMISSIONS (GNOME_VFS_PERM_USER_ALL \
| GNOME_VFS_PERM_GROUP_ALL \
| GNOME_VFS_PERM_OTHER_ALL)
/* thumbnail task state */
static GList *thumbnails;
static char *new_thumbnail_path;
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)
{
GnomeVFSResult result;
GnomeVFSFileInfo *file_info;
file_info = gnome_vfs_file_info_new ();
/* 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_get_file_info (file_uri, file_info, 0);
gnome_vfs_file_info_unref (file_info);
return result == GNOME_VFS_OK;
}
/* utility routine that, given the uri of an image, constructs the uri to the corresponding thumbnail */
static char *
make_thumbnail_path (const char *image_uri, gboolean directory_only, gboolean use_local_directory, gboolean anti_aliased)
{
char *thumbnail_uri, *thumbnail_path;
char *directory_name = g_strdup (image_uri);
char *last_slash = strrchr (directory_name, '/');
char *dot_pos;
*last_slash = '\0';
/* either use the local directory or one in the user's home directory, as selected by the passed in flag */
if (use_local_directory) {
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 doesnt exist */
thumbnail_directory_uri = gnome_vfs_uri_new (thumbnail_uri);
/* FIXME bugzilla.eazel.com 3137: synchronous I/O - it
looks like the URI will be local-only, but best to
make sure. */
result = nautilus_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, '.');
if (dot_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 (!nautilus_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 */
gnome_vfs_file_info_init (&file_info);
gnome_vfs_get_file_info (file_uri, &file_info, GNOME_VFS_FILE_INFO_DEFAULT);
gnome_vfs_file_info_init (&other_file_info);
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_clear (&file_info);
gnome_vfs_file_info_clear (&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;
} 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;
}
/* 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;
char *thumbnail_uri;
char *file_uri;
gboolean local_flag = TRUE;
gboolean remake_thumbnail = FALSE;
file_uri = nautilus_file_get_uri (file);
/* compose the uri for the thumbnail locally */
thumbnail_uri = make_thumbnail_path (file_uri, FALSE, TRUE, anti_aliased);
/* if the thumbnail file already exists locally, simply return the uri */
/* FIXME bugzilla.eazel.com 3137: this synchronous I/O is a
disaster when loading remote locations. It blocks the UI
when trying to load a slow remote image over http for
instance. The fact that we must do this potentially slow
operation implies the IconFactory interface needs to be
asynchronous! Either that, or thumbnail existence is
somthing we need to be able to monitor/call_when_ready on,
on a NautilusFile. */
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);
/* FIXME bugzilla.eazel.com 3137: more potentially
losing synch I/O. */
gnome_vfs_unlink (thumbnail_uri);
}
}
/* now try it globally */
if (!remake_thumbnail) {
g_free (thumbnail_uri);
thumbnail_uri = make_thumbnail_path (file_uri, FALSE, FALSE, anti_aliased);
/* if the thumbnail file already exists in the common area, return that uri */
/* FIXME bugzilla.eazel.com 3137: more potentially losing
synch I/O - this should be guaranteed local, so
perhaps not as bad (unless you have an NFS homedir,
say... */
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);
/* FIXME bugzilla.eazel.com 3137: more potentially losing
synch I/O - this should be guaranteed local, so
perhaps not as bad (unless you have an NFS homedir,
say... */
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_path (file_uri, TRUE, local_flag, anti_aliased);
/* 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);
/* if we can't make if locally, try it in the global place */
if (result != GNOME_VFS_OK && result != GNOME_VFS_ERROR_FILE_EXISTS) {
g_free (thumbnail_uri);
local_flag = FALSE;
thumbnail_uri = make_thumbnail_path (file_uri, TRUE, local_flag, anti_aliased);
/* FIXME bugzilla.eazel.com 3137: more potentially
losing synch I/O - this is probably local? */
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_prepend (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;
}
/* check_for_thumbnails is a utility that checks to see if any of the thumbnails in the pending
list have been created yet. If it finds one, it removes the elements from the queue and
returns true, otherwise it returns false
*/
static gboolean
check_for_thumbnails (void)
{
char *current_thumbnail;
NautilusThumbnailInfo *info;
GList *stop_element;
GList *next_thumbnail;
NautilusFile *file;
for (next_thumbnail = thumbnails;
next_thumbnail != NULL;
next_thumbnail = next_thumbnail->next) {
info = (NautilusThumbnailInfo*) next_thumbnail->data;
current_thumbnail = make_thumbnail_path (info->thumbnail_uri, FALSE, info->is_local, info->anti_aliased);
/* FIXME bugzilla.eazel.com 3137: synchronous I/O */
if (vfs_file_exists (current_thumbnail)) {
/* we found one, so update the icon and remove all of the elements up to and including
this one from the pending list. */
g_free (current_thumbnail);
file = nautilus_file_get (info->thumbnail_uri);
if (file != NULL) {
nautilus_file_changed (file);
nautilus_file_unref (file);
}
stop_element = next_thumbnail->next;
while (thumbnails != stop_element) {
info = (NautilusThumbnailInfo *) thumbnails->data;
g_free (info->thumbnail_uri);
g_free (info);
thumbnails = g_list_remove_link (thumbnails, thumbnails);
}
return TRUE;
}
g_free (current_thumbnail);
}
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)
{
pid_t thumbnail_pid;
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_path);
new_thumbnail_path = make_thumbnail_path (info->thumbnail_uri, FALSE, info->is_local, info->anti_aliased);
/* fork a task to make the thumbnail, using gdk-pixbuf to do the scaling */
if (!(thumbnail_pid = fork())) {
GdkPixbuf* full_size_image;
NautilusFile *file;
char *thumbnail_path;
file = nautilus_file_get (info->thumbnail_uri);
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);
}
}
} else {
if (info->thumbnail_uri != NULL)
full_size_image = nautilus_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 = nautilus_gdk_pixbuf_scale_down_to_fit(full_size_image, 96, 96);
gdk_pixbuf_unref (full_size_image);
/* embed the content image in the frame */
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 = nautilus_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);
thumbnail_path = gnome_vfs_get_local_path_from_uri (new_thumbnail_path);
if (!nautilus_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_path);
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);
/* 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 */
}

View file

@ -0,0 +1,33 @@
/* -*- 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);
#endif /* NAUTILUS_THUMBNAILS_H */

View file

@ -117,6 +117,7 @@ libnautilus_extensions_la_SOURCES = \
nautilus-string.c \
nautilus-text-caption.c \
nautilus-theme.c \
nautilus-thumbnails.c \
nautilus-trash-directory.c \
nautilus-undo-context.c \
nautilus-undo-manager.c \
@ -177,6 +178,7 @@ noinst_HEADERS = \
nautilus-icon-container.h \
nautilus-icon-dnd.h \
nautilus-icon-factory.h \
nautilus-icon-factory-private.h \
nautilus-icon-private.h \
nautilus-icon-text-item.h \
nautilus-image.h \
@ -213,6 +215,7 @@ noinst_HEADERS = \
nautilus-string.h \
nautilus-text-caption.h \
nautilus-theme.h \
nautilus-thumbnails.h \
nautilus-trash-directory.h \
nautilus-undo-context.h \
nautilus-undo-manager.h \

View file

@ -67,8 +67,6 @@ static void nautilus_directory_destroy (GtkObject *obje
static void nautilus_directory_initialize (gpointer object,
gpointer klass);
static void nautilus_directory_initialize_class (NautilusDirectoryClass *klass);
static GnomeVFSResult nautilus_make_directory_and_parents (GnomeVFSURI *uri,
guint permissions);
static NautilusDirectory *nautilus_directory_new (const char *uri);
static char *real_get_name_for_self_as_new_file (NautilusDirectory *directory);
@ -343,42 +341,6 @@ nautilus_directory_get_uri (NautilusDirectory *directory)
return g_strdup (directory->details->uri);
}
static GnomeVFSResult
nautilus_make_directory_and_parents (GnomeVFSURI *uri, guint permissions)
{
GnomeVFSResult result;
GnomeVFSURI *parent_uri;
/* Make the directory, and return right away unless there's
a possible problem with the parent.
*/
result = gnome_vfs_make_directory_for_uri (uri, permissions);
if (result != GNOME_VFS_ERROR_NOT_FOUND) {
return result;
}
/* If we can't get a parent, we are done. */
parent_uri = gnome_vfs_uri_get_parent (uri);
if (parent_uri == NULL) {
return result;
}
/* If we can get a parent, use a recursive call to create
the parent and its parents.
*/
result = nautilus_make_directory_and_parents (parent_uri, permissions);
gnome_vfs_uri_unref (parent_uri);
if (result != GNOME_VFS_OK) {
return result;
}
/* A second try at making the directory after the parents
have all been created.
*/
result = gnome_vfs_make_directory_for_uri (uri, permissions);
return result;
}
static GnomeVFSURI *
construct_private_metafile_vfs_uri (const char *uri)
{

View file

@ -725,6 +725,42 @@ nautilus_read_file_cancel (NautilusReadFileHandle *handle)
g_free (handle);
}
GnomeVFSResult
nautilus_make_directory_and_parents (GnomeVFSURI *uri, guint permissions)
{
GnomeVFSResult result;
GnomeVFSURI *parent_uri;
/* Make the directory, and return right away unless there's
a possible problem with the parent.
*/
result = gnome_vfs_make_directory_for_uri (uri, permissions);
if (result != GNOME_VFS_ERROR_NOT_FOUND) {
return result;
}
/* If we can't get a parent, we are done. */
parent_uri = gnome_vfs_uri_get_parent (uri);
if (parent_uri == NULL) {
return result;
}
/* If we can get a parent, use a recursive call to create
the parent and its parents.
*/
result = nautilus_make_directory_and_parents (parent_uri, permissions);
gnome_vfs_uri_unref (parent_uri);
if (result != GNOME_VFS_OK) {
return result;
}
/* A second try at making the directory after the parents
have all been created.
*/
result = gnome_vfs_make_directory_for_uri (uri, permissions);
return result;
}
#if !defined (NAUTILUS_OMIT_SELF_CHECK)
void

View file

@ -40,9 +40,8 @@ char * nautilus_format_uri_for_display (const char
char * nautilus_make_uri_from_input (const char *location);
gboolean nautilus_uri_is_trash (const char *uri);
char * nautilus_make_uri_canonical (const char *uri);
gboolean nautilus_uris_match (const char *uri_1,
const char *uri_2);
gboolean nautilus_uris_match (const char *uri_1,
const char *uri_2);
/* FIXME bugzilla.eazel.com 2424:
* This is the same as gnome-libs g_concat_dir_and_file except
* for handling path == NULL.
@ -89,4 +88,8 @@ NautilusReadFileHandle *nautilus_read_file_async (const char
gpointer callback_data);
void nautilus_read_file_cancel (NautilusReadFileHandle *handle);
/* gnome-vfs cover to make a directory and parents */
GnomeVFSResult nautilus_make_directory_and_parents (GnomeVFSURI *uri,
guint permissions);
#endif /* NAUTILUS_FILE_UTILITIES_H */

View file

@ -389,16 +389,33 @@ nautilus_global_preferences_get_disabled_sidebar_panel_view_identifiers (void)
return disabled_view_identifiers;
}
static void
destroy_global_prefs_dialog (void)
{
/* Free the dialog first, cause it has refs to preferences */
if (global_prefs_dialog != NULL) {
/* Since it's a top-level window, it's OK to destroy rather than unref'ing. */
gtk_widget_destroy (global_prefs_dialog);
}
}
static GtkWidget *
global_preferences_get_dialog (void)
{
static gboolean set_up_exit = FALSE;
nautilus_global_preferences_initialize ();
if (!global_prefs_dialog)
{
if (global_prefs_dialog == NULL) {
global_prefs_dialog = global_preferences_create_dialog ();
}
if (!set_up_exit) {
g_atexit (destroy_global_prefs_dialog);
set_up_exit = TRUE;
}
return global_prefs_dialog;
}
@ -863,9 +880,10 @@ nautilus_global_preferences_dialog_update (void)
was_showing = GTK_WIDGET_VISIBLE (global_prefs_dialog);
gtk_widget_destroy (global_prefs_dialog);
global_prefs_dialog = NULL;
}
global_prefs_dialog = global_preferences_create_dialog ();
global_preferences_get_dialog ();
if (was_showing) {
nautilus_global_preferences_show_dialog ();
@ -885,16 +903,3 @@ nautilus_global_preferences_initialize (void)
initialized = TRUE;
}
void
nautilus_global_preferences_shutdown (void)
{
/* Free the dialog first, cause it has refs to preferences */
if (global_prefs_dialog != NULL) {
gtk_widget_destroy (global_prefs_dialog);
}
/* Now free the preferences tables and stuff */
nautilus_preferences_shutdown ();
}

View file

@ -124,7 +124,6 @@ typedef enum
void nautilus_global_preferences_initialize (void);
void nautilus_global_preferences_shutdown (void);
void nautilus_global_preferences_show_dialog (void);
void nautilus_global_preferences_hide_dialog (void);
void nautilus_global_preferences_set_dialog_title (const char *title);

View file

@ -68,7 +68,7 @@ struct NautilusIconCanvasItemDetails {
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;
EmblemAttachPoints *attach_pointer;
NautilusEmblemAttachPoints *attach_points;
/* Size of the text at current font. */
int text_width;
@ -301,7 +301,7 @@ nautilus_icon_canvas_item_destroy (GtkObject *object)
nautilus_gdk_pixbuf_list_free (details->emblem_pixbufs);
g_free (details->editable_text);
g_free (details->additional_text);
g_free (details->attach_pointer);
g_free (details->attach_points);
if (details->font != NULL) {
gdk_font_unref (details->font);
@ -531,14 +531,14 @@ nautilus_icon_canvas_item_set_emblems (NautilusIconCanvasItem *item,
void
nautilus_icon_canvas_item_set_attach_points (NautilusIconCanvasItem *item,
EmblemAttachPoints *attach_points)
NautilusEmblemAttachPoints *attach_points)
{
g_free (item->details->attach_pointer);
item->details->attach_pointer = NULL;
g_free (item->details->attach_points);
item->details->attach_points = NULL;
if (attach_points && attach_points->has_attach_points) {
item->details->attach_pointer = g_new0 (EmblemAttachPoints, 1);
*item->details->attach_pointer = *attach_points;
if (attach_points != NULL && attach_points->num_points != 0) {
item->details->attach_points = g_new (NautilusEmblemAttachPoints, 1);
*item->details->attach_points = *attach_points;
}
}
@ -945,7 +945,7 @@ emblem_layout_next (EmblemLayout *layout,
{
GdkPixbuf *pixbuf;
int width, height, x, y;
EmblemAttachPoints *attach_info ;
NautilusEmblemAttachPoints *attach_points;
/* Check if we have layed out all of the pixbufs. */
if (layout->emblem == NULL) {
@ -961,13 +961,14 @@ emblem_layout_next (EmblemLayout *layout,
/* Advance to the next emblem. */
layout->emblem = layout->emblem->next;
if (layout->icon_item->details->attach_pointer) {
if (layout->index >= MAX_ATTACH_POINTS)
attach_points = layout->icon_item->details->attach_points;
if (attach_points != NULL) {
if (layout->index >= attach_points->num_points) {
return FALSE;
}
attach_info = layout->icon_item->details->attach_pointer;
x = layout->icon_rect.x0 + attach_info->attach_points[layout->index].x;
y = layout->icon_rect.y0 + attach_info->attach_points[layout->index].y;
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;

View file

@ -66,34 +66,33 @@ 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,
EmblemAttachPoints *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);
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,
const ArtDRect *world_rectangle);
gboolean nautilus_icon_canvas_item_hit_test_stretch_handles (NautilusIconCanvasItem *item,
const ArtPoint *world_point);
void nautilus_icon_canvas_item_get_icon_rectangle (NautilusIconCanvasItem *item,
ArtDRect *world_rectangle);
void nautilus_icon_canvas_item_update_bounds (NautilusIconCanvasItem *item);
void nautilus_icon_canvas_item_set_smooth_font (NautilusIconCanvasItem *item,
NautilusScalableFont *font);
void nautilus_icon_canvas_item_set_smooth_font_size (NautilusIconCanvasItem *item,
guint font_size);
gboolean nautilus_icon_canvas_item_hit_test_rectangle (NautilusIconCanvasItem *item,
const ArtDRect *world_rectangle);
gboolean nautilus_icon_canvas_item_hit_test_stretch_handles (NautilusIconCanvasItem *item,
const ArtPoint *world_point);
void nautilus_icon_canvas_item_get_icon_rectangle (NautilusIconCanvasItem *item,
ArtDRect *world_rectangle);
void nautilus_icon_canvas_item_update_bounds (NautilusIconCanvasItem *item);
void nautilus_icon_canvas_item_set_smooth_font (NautilusIconCanvasItem *item,
NautilusScalableFont *font);
void nautilus_icon_canvas_item_set_smooth_font_size (NautilusIconCanvasItem *item,
guint font_size);
END_GNOME_DECLS

View file

@ -3209,7 +3209,7 @@ nautilus_icon_container_update_icon (NautilusIconContainer *container,
NautilusIconContainerDetails *details;
guint icon_size_x, icon_size_y, max_image_size, max_emblem_size;
NautilusScalableIcon *scalable_icon;
EmblemAttachPoints attach_points;
NautilusEmblemAttachPoints attach_points;
GdkPixbuf *pixbuf, *emblem_pixbuf;
GList *emblem_scalable_icons, *emblem_pixbufs, *p;
char *editable_text, *additional_text;

View file

@ -0,0 +1,33 @@
/* -*- 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"
void nautilus_icon_factory_remove_by_uri (const char *uri);
#endif /* NAUTILUS_ICON_FACTORY_PRIVATE_H */

File diff suppressed because it is too large Load diff

View file

@ -82,9 +82,9 @@ typedef struct NautilusScalableIcon NautilusScalableIcon;
#define MAX_ATTACH_POINTS 8
typedef struct {
gboolean has_attach_points;
GdkPoint attach_points[MAX_ATTACH_POINTS];
} EmblemAttachPoints;
int num_points;
GdkPoint points[MAX_ATTACH_POINTS];
} NautilusEmblemAttachPoints;
/* Instead of a class declaration here, I will just document
* the signals.
@ -98,19 +98,19 @@ typedef struct {
GtkObject * nautilus_icon_factory_get (void);
/* Relationship between zoom levels and icons sizes. */
guint nautilus_get_icon_size_for_zoom_level (NautilusZoomLevel zoom_level);
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 anti_aliased);
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,
gboolean anti_aliased,
NautilusStringList *exclude);
NautilusScalableIcon *nautilus_icon_factory_get_emblem_icon_by_name (const char *emblem_name,
gboolean anti_aliased);
NautilusScalableIcon *nautilus_icon_factory_get_icon_for_file (NautilusFile *file,
const char *modifier,
gboolean anti_aliased);
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,
gboolean anti_aliased,
NautilusStringList *exclude);
NautilusScalableIcon *nautilus_icon_factory_get_emblem_icon_by_name (const char *emblem_name,
gboolean anti_aliased);
/* Render an icon to a particular size.
* Ownership of a ref. count in this pixbuf comes with the deal.
@ -118,59 +118,59 @@ NautilusScalableIcon *nautilus_icon_factory_get_emblem_icon_by_name (const cha
* 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
*/
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,
EmblemAttachPoints *attach_points);
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,
NautilusEmblemAttachPoints *attach_points);
/* 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 anti_aliased);
GdkPixbuf * nautilus_icon_factory_get_pixbuf_for_file (NautilusFile *file,
const char *modifer,
guint size_in_pixels,
gboolean anti_aliased);
/* 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);
void nautilus_icon_factory_get_pixmap_and_mask_for_file (NautilusFile *file,
const char *modifer,
guint size_in_pixels,
GdkPixmap **pixmap,
GdkBitmap **mask);
/* 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);
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 **name_return,
char **modifier_return,
char **embedded_text_return);
void nautilus_scalable_icon_get_text_pieces (NautilusScalableIcon *scalable_icon,
char **uri_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 *name,
const char *modifier,
const char *embedded_text,
gboolean anti_aliased);
NautilusScalableIcon *nautilus_scalable_icon_new_from_text_pieces (const char *uri,
const char *name,
const char *modifier,
const char *embedded_text,
gboolean anti_aliased);
/* 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);
void nautilus_scalable_icon_list_free (GList *scalable_icon_list);
#endif /* NAUTILUS_ICON_FACTORY_H */

View file

@ -121,6 +121,7 @@ static void preferences_hash_node_remove_callback
static PreferencesHashNode * preferences_hash_node_lookup (const char *name);
static void preferences_register (const char *name);
static gboolean preferences_initialize_if_needed (void);
static void preferences_shutdown (void);
static char * preferences_make_make_gconf_key (const char *preference_name);
/* GConf callbacks */
@ -130,7 +131,7 @@ static void preferences_gconf_by_user_level_callback
GConfValue *value,
gboolean is_default,
gpointer user_data);
static void preferences_gconf_callback (GConfClient *client,
static void preferences_gconf_callback (GConfClient *client,
guint cnxn_id,
const gchar *key,
GConfValue *value,
@ -737,6 +738,8 @@ preferences_initialize_if_needed (void)
user_level_changed_callback,
NULL);
g_atexit (preferences_shutdown);
return TRUE;
}
@ -1048,8 +1051,8 @@ nautilus_preferences_get (const char *name,
return value;
}
void
nautilus_preferences_shutdown (void)
static void
preferences_shutdown (void)
{
if (GLOBAL.preference_table == NULL && GLOBAL.gconf_client == NULL) {
return;

View file

@ -89,8 +89,6 @@ void nautilus_preferences_set (const char
const char *value);
char * nautilus_preferences_get (const char *name,
const gchar *default_value);
void nautilus_preferences_shutdown (void);
END_GNOME_DECLS

View file

@ -0,0 +1,505 @@
/* -*- 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>
*/
#include <config.h>
#include "nautilus-thumbnails.h"
#include <libgnomevfs/gnome-vfs-file-info.h>
#include <string.h>
#include "nautilus-file-utilities.h"
#include "nautilus-string.h"
#include <gtk/gtkmain.h>
#include "nautilus-icon-factory-private.h"
#include "nautilus-directory-notify.h"
#include "nautilus-theme.h"
#include <stdio.h>
#include "nautilus-gdk-pixbuf-extensions.h"
#include <unistd.h>
#include <librsvg/rsvg.h>
#include "nautilus-graphic-effects.h"
/* permissions for thumbnail directory */
#define THUMBNAIL_DIR_PERMISSIONS (GNOME_VFS_PERM_USER_ALL \
| GNOME_VFS_PERM_GROUP_ALL \
| GNOME_VFS_PERM_OTHER_ALL)
/* thumbnail task state */
static GList *thumbnails;
static char *new_thumbnail_path;
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)
{
GnomeVFSResult result;
GnomeVFSFileInfo *file_info;
file_info = gnome_vfs_file_info_new ();
/* 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_get_file_info (file_uri, file_info, 0);
gnome_vfs_file_info_unref (file_info);
return result == GNOME_VFS_OK;
}
/* utility routine that, given the uri of an image, constructs the uri to the corresponding thumbnail */
static char *
make_thumbnail_path (const char *image_uri, gboolean directory_only, gboolean use_local_directory, gboolean anti_aliased)
{
char *thumbnail_uri, *thumbnail_path;
char *directory_name = g_strdup (image_uri);
char *last_slash = strrchr (directory_name, '/');
char *dot_pos;
*last_slash = '\0';
/* either use the local directory or one in the user's home directory, as selected by the passed in flag */
if (use_local_directory) {
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 doesnt exist */
thumbnail_directory_uri = gnome_vfs_uri_new (thumbnail_uri);
/* FIXME bugzilla.eazel.com 3137: synchronous I/O - it
looks like the URI will be local-only, but best to
make sure. */
result = nautilus_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, '.');
if (dot_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 (!nautilus_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 */
gnome_vfs_file_info_init (&file_info);
gnome_vfs_get_file_info (file_uri, &file_info, GNOME_VFS_FILE_INFO_DEFAULT);
gnome_vfs_file_info_init (&other_file_info);
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_clear (&file_info);
gnome_vfs_file_info_clear (&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;
} 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;
}
/* 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;
char *thumbnail_uri;
char *file_uri;
gboolean local_flag = TRUE;
gboolean remake_thumbnail = FALSE;
file_uri = nautilus_file_get_uri (file);
/* compose the uri for the thumbnail locally */
thumbnail_uri = make_thumbnail_path (file_uri, FALSE, TRUE, anti_aliased);
/* if the thumbnail file already exists locally, simply return the uri */
/* FIXME bugzilla.eazel.com 3137: this synchronous I/O is a
disaster when loading remote locations. It blocks the UI
when trying to load a slow remote image over http for
instance. The fact that we must do this potentially slow
operation implies the IconFactory interface needs to be
asynchronous! Either that, or thumbnail existence is
somthing we need to be able to monitor/call_when_ready on,
on a NautilusFile. */
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);
/* FIXME bugzilla.eazel.com 3137: more potentially
losing synch I/O. */
gnome_vfs_unlink (thumbnail_uri);
}
}
/* now try it globally */
if (!remake_thumbnail) {
g_free (thumbnail_uri);
thumbnail_uri = make_thumbnail_path (file_uri, FALSE, FALSE, anti_aliased);
/* if the thumbnail file already exists in the common area, return that uri */
/* FIXME bugzilla.eazel.com 3137: more potentially losing
synch I/O - this should be guaranteed local, so
perhaps not as bad (unless you have an NFS homedir,
say... */
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);
/* FIXME bugzilla.eazel.com 3137: more potentially losing
synch I/O - this should be guaranteed local, so
perhaps not as bad (unless you have an NFS homedir,
say... */
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_path (file_uri, TRUE, local_flag, anti_aliased);
/* 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);
/* if we can't make if locally, try it in the global place */
if (result != GNOME_VFS_OK && result != GNOME_VFS_ERROR_FILE_EXISTS) {
g_free (thumbnail_uri);
local_flag = FALSE;
thumbnail_uri = make_thumbnail_path (file_uri, TRUE, local_flag, anti_aliased);
/* FIXME bugzilla.eazel.com 3137: more potentially
losing synch I/O - this is probably local? */
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_prepend (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;
}
/* check_for_thumbnails is a utility that checks to see if any of the thumbnails in the pending
list have been created yet. If it finds one, it removes the elements from the queue and
returns true, otherwise it returns false
*/
static gboolean
check_for_thumbnails (void)
{
char *current_thumbnail;
NautilusThumbnailInfo *info;
GList *stop_element;
GList *next_thumbnail;
NautilusFile *file;
for (next_thumbnail = thumbnails;
next_thumbnail != NULL;
next_thumbnail = next_thumbnail->next) {
info = (NautilusThumbnailInfo*) next_thumbnail->data;
current_thumbnail = make_thumbnail_path (info->thumbnail_uri, FALSE, info->is_local, info->anti_aliased);
/* FIXME bugzilla.eazel.com 3137: synchronous I/O */
if (vfs_file_exists (current_thumbnail)) {
/* we found one, so update the icon and remove all of the elements up to and including
this one from the pending list. */
g_free (current_thumbnail);
file = nautilus_file_get (info->thumbnail_uri);
if (file != NULL) {
nautilus_file_changed (file);
nautilus_file_unref (file);
}
stop_element = next_thumbnail->next;
while (thumbnails != stop_element) {
info = (NautilusThumbnailInfo *) thumbnails->data;
g_free (info->thumbnail_uri);
g_free (info);
thumbnails = g_list_remove_link (thumbnails, thumbnails);
}
return TRUE;
}
g_free (current_thumbnail);
}
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)
{
pid_t thumbnail_pid;
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_path);
new_thumbnail_path = make_thumbnail_path (info->thumbnail_uri, FALSE, info->is_local, info->anti_aliased);
/* fork a task to make the thumbnail, using gdk-pixbuf to do the scaling */
if (!(thumbnail_pid = fork())) {
GdkPixbuf* full_size_image;
NautilusFile *file;
char *thumbnail_path;
file = nautilus_file_get (info->thumbnail_uri);
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);
}
}
} else {
if (info->thumbnail_uri != NULL)
full_size_image = nautilus_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 = nautilus_gdk_pixbuf_scale_down_to_fit(full_size_image, 96, 96);
gdk_pixbuf_unref (full_size_image);
/* embed the content image in the frame */
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 = nautilus_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);
thumbnail_path = gnome_vfs_get_local_path_from_uri (new_thumbnail_path);
if (!nautilus_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_path);
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);
/* 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 */
}

View file

@ -0,0 +1,33 @@
/* -*- 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);
#endif /* NAUTILUS_THUMBNAILS_H */

View file

@ -1731,36 +1731,40 @@ band_select_ended_callback (NautilusIconContainer *container,
/* here's the timer task that actually plays the file using mpg123. */
/* FIXME bugzilla.eazel.com 1258: we should get the application from our mime-type stuff */
static gint
play_file (NautilusFile *file)
static int
play_file (gpointer callback_data)
{
NautilusFile *file;
char *file_uri;
char *file_path, *mime_type;
mp3_pid = fork ();
if (mp3_pid == (pid_t) 0) {
file_uri = nautilus_file_get_uri (file);
file_path = gnome_vfs_get_local_path_from_uri (file_uri);
if (file_path != NULL) {
mime_type = nautilus_file_get_mime_type (file);
gboolean is_mp3;
/* set the group (session) id to this process for future killing */
file = NAUTILUS_FILE (callback_data);
file_uri = nautilus_file_get_uri (file);
file_path = gnome_vfs_get_local_path_from_uri (file_uri);
mime_type = nautilus_file_get_mime_type (file);
is_mp3 = nautilus_strcasecmp (mime_type, "audio/x-mp3") == 0;
if (file_path != NULL) {
mp3_pid = fork ();
if (mp3_pid == (pid_t) 0) {
/* Set the group (session) id to this process for future killing. */
setsid();
if (nautilus_strcasecmp (mime_type, "audio/x-mp3") == 0) {
if (is_mp3) {
execlp ("mpg123", "mpg123", "-y", "-q", file_path, NULL);
} else {
execlp ("play", "play", file_path, NULL);
}
/* Who cares about storage leaks in the fork? */
_exit (0);
}
g_free (file_path);
g_free (mime_type);
g_free (file_uri);
_exit (0);
}
g_free (file_path);
g_free (file_uri);
g_free (mime_type);
timeout = -1;
return 0;
@ -1777,19 +1781,17 @@ play_file (NautilusFile *file)
static void
preview_sound (NautilusFile *file, gboolean start_flag)
{
if (start_flag) {
timeout = gtk_timeout_add (1000, (GtkFunction) play_file, file);
} else {
if (mp3_pid) {
kill (-mp3_pid, SIGTERM);
mp3_pid = 0;
}
if (timeout >= 0) {
gtk_timeout_remove (timeout);
timeout = -1;
}
if (mp3_pid) {
kill (-mp3_pid, SIGTERM);
mp3_pid = 0;
}
if (timeout >= 0) {
gtk_timeout_remove (timeout);
timeout = -1;
}
if (start_flag) {
timeout = gtk_timeout_add (1000, play_file, file);
}
}
static int

View file

@ -188,15 +188,6 @@ nautilus_application_new (void)
static void
nautilus_application_destroy (GtkObject *object)
{
/* Shut down preferences. This is needed so that the global
* preferences object and all its allocations are freed. Not
* calling this function would NOT cause the user to lose
* preferences. The only effect would be to leak those
* objects - which would be collected at exit() time anyway,
* but it adds noise to memory profile tool runs.
*/
nautilus_global_preferences_shutdown ();
nautilus_bookmarks_exiting ();
NAUTILUS_CALL_PARENT_CLASS (GTK_OBJECT_CLASS, destroy, (object));

View file

@ -49,46 +49,72 @@
#include <stdlib.h>
/* Keeps track of everyone who wants the main event loop kept active */
static GSList *nautilus_main_event_loop_registrants;
static GSList *event_loop_registrants;
static gboolean
nautilus_main_is_event_loop_needed (void)
is_event_loop_needed (void)
{
return nautilus_main_event_loop_registrants != NULL;
return event_loop_registrants != NULL;
}
static int
quit_if_in_main_loop (gpointer callback_data)
{
guint level;
g_assert (callback_data == NULL);
level = gtk_main_level ();
/* We can be called even outside the main loop by gnome_vfs_shutdown,
* so check that we are in a loop before calling quit.
*/
if (level != 0) {
gtk_main_quit ();
}
/* We need to be called again if we quit a nested loop. */
return level > 1;
}
static void
nautilus_main_event_loop_unregister (GtkObject* object)
nautilus_gtk_main_quit_all (void)
{
g_assert (g_slist_find (nautilus_main_event_loop_registrants, object) != NULL);
nautilus_main_event_loop_registrants = g_slist_remove (nautilus_main_event_loop_registrants, object);
if (!nautilus_main_is_event_loop_needed ()) {
/* Calling gtk_main_quit directly only kills the current/top event loop.
* This idler will be run by the current event loop, killing it, and then
* by the next event loop, ...
*/
gtk_idle_add ((GtkFunction) gtk_main_quit, NULL);
/* Calling gtk_main_quit directly only kills the current/top event loop.
* This idler will be run by the current event loop, killing it, and then
* by the next event loop, ...
*/
gtk_idle_add (quit_if_in_main_loop, NULL);
}
static void
event_loop_unregister (GtkObject* object)
{
g_assert (g_slist_find (event_loop_registrants, object) != NULL);
event_loop_registrants = g_slist_remove (event_loop_registrants, object);
if (!is_event_loop_needed ()) {
nautilus_gtk_main_quit_all ();
}
}
void
nautilus_main_event_loop_register (GtkObject* object)
{
gtk_signal_connect (object, "destroy", nautilus_main_event_loop_unregister, NULL);
nautilus_main_event_loop_registrants = g_slist_prepend (nautilus_main_event_loop_registrants, object);
gtk_signal_connect (object, "destroy", event_loop_unregister, NULL);
event_loop_registrants = g_slist_prepend (event_loop_registrants, object);
}
gboolean
nautilus_main_is_event_loop_mainstay (GtkObject* object)
{
return g_slist_length (nautilus_main_event_loop_registrants) == 1 && nautilus_main_event_loop_registrants->data == object;
return g_slist_length (event_loop_registrants) == 1 && event_loop_registrants->data == object;
}
void
nautilus_main_event_loop_quit (void)
{
while (nautilus_main_event_loop_registrants != NULL) {
gtk_object_destroy (nautilus_main_event_loop_registrants->data);
while (event_loop_registrants != NULL) {
gtk_object_destroy (event_loop_registrants->data);
}
}
@ -203,7 +229,7 @@ main (int argc, char *argv[])
kill_shell, restart_shell,
stop_desktop, start_desktop,
args);
if (nautilus_main_is_event_loop_needed ()) {
if (is_event_loop_needed ()) {
bonobo_main ();
}
bonobo_object_unref (BONOBO_OBJECT (application));

View file

@ -4,6 +4,7 @@
*.lo
Makefile
Makefile.in
test-nautilus-background
test-nautilus-font
test-nautilus-font-picker
test-nautilus-image