mirror of
https://gitlab.gnome.org/GNOME/nautilus
synced 2024-08-25 02:36:07 +00:00
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:
parent
1a0af90190
commit
1035b5ea66
69
ChangeLog
69
ChangeLog
|
@ -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)
|
||||
|
|
15
configure.in
15
configure.in
|
@ -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"
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 ();
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
33
libnautilus-extensions/nautilus-icon-factory-private.h
Normal file
33
libnautilus-extensions/nautilus-icon-factory-private.h
Normal 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
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
505
libnautilus-extensions/nautilus-thumbnails.c
Normal file
505
libnautilus-extensions/nautilus-thumbnails.c
Normal 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 */
|
||||
}
|
33
libnautilus-extensions/nautilus-thumbnails.h
Normal file
33
libnautilus-extensions/nautilus-thumbnails.h
Normal 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 */
|
|
@ -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 \
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 ();
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
33
libnautilus-private/nautilus-icon-factory-private.h
Normal file
33
libnautilus-private/nautilus-icon-factory-private.h
Normal 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
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
505
libnautilus-private/nautilus-thumbnails.c
Normal file
505
libnautilus-private/nautilus-thumbnails.c
Normal 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 */
|
||||
}
|
33
libnautilus-private/nautilus-thumbnails.h
Normal file
33
libnautilus-private/nautilus-thumbnails.h
Normal 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 */
|
|
@ -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
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
*.lo
|
||||
Makefile
|
||||
Makefile.in
|
||||
test-nautilus-background
|
||||
test-nautilus-font
|
||||
test-nautilus-font-picker
|
||||
test-nautilus-image
|
||||
|
|
Loading…
Reference in a new issue