diff --git a/ChangeLog b/ChangeLog index 00f49321c3db718f7192cbd7ee18254956685615..ccb465417cb62d64b523f6bedaf8861388d2bffe 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2006-02-06 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-chmod-job.c, thunar-vfs/thunar-vfs-chown-job.c, + thunar-vfs/thunar-vfs-listdir-job.c, thunar-vfs/thunar-vfs-scandir.c, + thunar-vfs/thunar-vfs-scandir.h, thunar-vfs/thunar-vfs-transfer-job.c, + thunar-vfs/thunar-vfs-unlink-job.c: The directory scanning is now + cancelable. Bug #1239. + * thunar/thunar-icon-factory.c: Properly reload/regenerate thumbnails + when image files are changed. Bug #1435. + * thunar-vfs/thunar-vfs-mime-application.c + (thunar_vfs_mime_application_new_from_file): Check TryExec (or Exec) + first prior to allocating a ThunarVfsMimeApplication for a .desktop + file, whose associated program cannot be run. Bug #1436. + 2006-02-06 Benedikt Meurer <benny@xfce.org> * thunar/thunar-standard-view.c: Autoscroll while dragging to a diff --git a/thunar-vfs/thunar-vfs-chmod-job.c b/thunar-vfs/thunar-vfs-chmod-job.c index 60eec75dafd1236e57911c24e02c331c2f839a39..927a7eac2b943cc004861af2ede5ff8e96127815 100644 --- a/thunar-vfs/thunar-vfs-chmod-job.c +++ b/thunar-vfs/thunar-vfs-chmod-job.c @@ -169,7 +169,7 @@ thunar_vfs_chmod_job_execute (ThunarVfsJob *job) /* check if we should operate recursively and collect the paths */ if (G_UNLIKELY (chmod_job->recursive)) - path_list = thunar_vfs_scandir (chmod_job->path, THUNAR_VFS_SCANDIR_RECURSIVE, NULL, NULL); + path_list = thunar_vfs_scandir (chmod_job->path, &job->cancelled, THUNAR_VFS_SCANDIR_RECURSIVE, NULL, NULL); path_list = thunar_vfs_path_list_prepend (path_list, chmod_job->path); /* determine the total number of paths (atleast one!) */ diff --git a/thunar-vfs/thunar-vfs-chown-job.c b/thunar-vfs/thunar-vfs-chown-job.c index af54ee0bb75663acf704e5894f8a557a94c0518a..9b47de8e3adf0db79f899708cd0594b4daed744b 100644 --- a/thunar-vfs/thunar-vfs-chown-job.c +++ b/thunar-vfs/thunar-vfs-chown-job.c @@ -167,7 +167,7 @@ thunar_vfs_chown_job_execute (ThunarVfsJob *job) /* check if we should operate recursively and collect the paths */ if (G_UNLIKELY (chown_job->recursive)) - path_list = thunar_vfs_scandir (chown_job->path, THUNAR_VFS_SCANDIR_RECURSIVE, NULL, NULL); + path_list = thunar_vfs_scandir (chown_job->path, &job->cancelled, THUNAR_VFS_SCANDIR_RECURSIVE, NULL, NULL); path_list = thunar_vfs_path_list_prepend (path_list, chown_job->path); /* determine the total number of paths (atleast one!) */ diff --git a/thunar-vfs/thunar-vfs-listdir-job.c b/thunar-vfs/thunar-vfs-listdir-job.c index 119ea85d416f8e3192392e09329a6ff2a0a04de4..9657531732aad5f7cd1f722434483149fe4d2afe 100644 --- a/thunar-vfs/thunar-vfs-listdir-job.c +++ b/thunar-vfs/thunar-vfs-listdir-job.c @@ -179,7 +179,7 @@ thunar_vfs_listdir_job_execute (ThunarVfsJob *job) guint n; /* scan the given directory */ - list = thunar_vfs_scandir (THUNAR_VFS_LISTDIR_JOB (job)->path, THUNAR_VFS_SCANDIR_FOLLOW_LINKS, pathcmp, &error); + list = thunar_vfs_scandir (THUNAR_VFS_LISTDIR_JOB (job)->path, &job->cancelled, THUNAR_VFS_SCANDIR_FOLLOW_LINKS, pathcmp, &error); if (G_LIKELY (list != NULL)) { for (lp = hp = list, n = 0; lp != NULL; lp = lp->next, ++n) diff --git a/thunar-vfs/thunar-vfs-mime-application.c b/thunar-vfs/thunar-vfs-mime-application.c index e7463883f05a4886ddae01749afe6af116ae78da..e194ad6f45c4c24f5d84e699e370384da11a96a8 100644 --- a/thunar-vfs/thunar-vfs-mime-application.c +++ b/thunar-vfs/thunar-vfs-mime-application.c @@ -199,9 +199,11 @@ thunar_vfs_mime_application_new_from_file (const gchar *path, ThunarVfsMimeHandlerFlags flags = 0; ThunarVfsMimeApplication *application = NULL; ThunarVfsMimeAction *action; + const gchar *tryexec; const gchar *exec; const gchar *icon; const gchar *name; + gboolean present; XfceRc *rc; gchar *command; gchar **actions; @@ -224,6 +226,33 @@ thunar_vfs_mime_application_new_from_file (const gchar *path, exec = xfce_rc_read_entry_untranslated (rc, "Exec", NULL); icon = xfce_rc_read_entry_untranslated (rc, "Icon", NULL); + /* check if we have a TryExec field */ + tryexec = xfce_rc_read_entry_untranslated (rc, "TryExec", NULL); + tryexec = (tryexec != NULL) ? tryexec : exec; + if (G_LIKELY (tryexec != NULL && g_shell_parse_argv (tryexec, NULL, &mt, NULL))) + { + /* check if we have an absolute path to an existing file */ + present = g_file_test (mt[0], G_FILE_TEST_EXISTS); + + /* else, we may have a program in $PATH */ + if (G_LIKELY (!present)) + { + command = g_find_program_in_path (mt[0]); + present = (command != NULL); + g_free (command); + } + + /* cleanup */ + g_strfreev (mt); + + /* if the program is not present, there's no reason to allocate a MimeApplication for it */ + if (G_UNLIKELY (!present)) + { + xfce_rc_close (rc); + return NULL; + } + } + /* generate the application object */ if (G_LIKELY (exec != NULL && name != NULL && g_utf8_validate (name, -1, NULL))) { diff --git a/thunar-vfs/thunar-vfs-scandir.c b/thunar-vfs/thunar-vfs-scandir.c index 442a2693d725260db0204417831c3de311aac4eb..70fbd95158e880e50033e663deaa939cb56e11e5 100644 --- a/thunar-vfs/thunar-vfs-scandir.c +++ b/thunar-vfs/thunar-vfs-scandir.c @@ -89,6 +89,7 @@ static gboolean thunar_vfs_scandir_collect_slow (ThunarVfsScandirHandle *handle, ThunarVfsPath *path, GList **directoriesp); static gboolean thunar_vfs_scandir_collect (ThunarVfsScandirHandle *handle, + volatile gboolean *cancelled, ThunarVfsPath *path); @@ -374,6 +375,7 @@ error: static gboolean thunar_vfs_scandir_collect (ThunarVfsScandirHandle *handle, + volatile gboolean *cancelled, ThunarVfsPath *path) { gboolean succeed = FALSE; @@ -402,7 +404,16 @@ thunar_vfs_scandir_collect (ThunarVfsScandirHandle *handle, /* perform the recursion */ for (lp = directories; lp != NULL && succeed; lp = lp->next) { - succeed = thunar_vfs_scandir_collect (handle, lp->data); + /* check if the user cancelled the scanning */ + if (G_UNLIKELY (cancelled != NULL && *cancelled)) + { + succeed = FALSE; + errno = EINTR; + break; + } + + /* collect the files for this directory */ + succeed = thunar_vfs_scandir_collect (handle, cancelled, lp->data); if (G_UNLIKELY (!succeed)) { /* we can ignore certain errors here */ @@ -425,6 +436,10 @@ thunar_vfs_scandir_collect (ThunarVfsScandirHandle *handle, /** * thunar_vfs_scandir: * @path + * @cancelled : pointer to a volatile boolean variable, which if + * %TRUE means to cancel the scan operation. May be + * %NULL in which case the scanner cannot be + * cancelled. * @flags * @func * @error : return location for errors or %NULL. @@ -433,10 +448,14 @@ thunar_vfs_scandir_collect (ThunarVfsScandirHandle *handle, * using thunar_vfs_path_list_free() when no longer * needed. * + * If @cancelled becomes true during the scan operation, %NULL + * will be returned and @error will be set to %G_FILE_ERROR_INTR. + * * Return value: **/ GList* thunar_vfs_scandir (ThunarVfsPath *path, + volatile gboolean *cancelled, ThunarVfsScandirFlags flags, GCompareFunc func, GError **error) @@ -452,7 +471,7 @@ thunar_vfs_scandir (ThunarVfsPath *path, handle.path_list = NULL; /* collect the paths */ - if (!thunar_vfs_scandir_collect (&handle, path)) + if (!thunar_vfs_scandir_collect (&handle, cancelled, path)) { /* forward the error */ g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno), g_strerror (errno)); diff --git a/thunar-vfs/thunar-vfs-scandir.h b/thunar-vfs/thunar-vfs-scandir.h index 72ad4e4ed5064326e41c40ec9fc19425267ae0a3..b931c761a91d3deeb119416363ed72471ddb42b2 100644 --- a/thunar-vfs/thunar-vfs-scandir.h +++ b/thunar-vfs/thunar-vfs-scandir.h @@ -37,6 +37,7 @@ typedef enum /*< flags >*/ } ThunarVfsScandirFlags; GList *thunar_vfs_scandir (ThunarVfsPath *path, + volatile gboolean *cancelled, ThunarVfsScandirFlags flags, GCompareFunc func, GError **error) G_GNUC_INTERNAL; diff --git a/thunar-vfs/thunar-vfs-transfer-job.c b/thunar-vfs/thunar-vfs-transfer-job.c index ea84a8a2088ad2bc83286e0d64737254814fc8ac..49ceb6955115ccc7f9b0b8492cc823ed950376d6 100644 --- a/thunar-vfs/thunar-vfs-transfer-job.c +++ b/thunar-vfs/thunar-vfs-transfer-job.c @@ -535,7 +535,7 @@ thunar_vfs_transfer_job_collect_pairs (ThunarVfsTransferJob *transfer_job, return NULL; /* scan the pair directory */ - paths = thunar_vfs_scandir (pair->source_path, THUNAR_VFS_SCANDIR_RECURSIVE, NULL, &serror); + paths = thunar_vfs_scandir (pair->source_path, &THUNAR_VFS_JOB (transfer_job)->cancelled, THUNAR_VFS_SCANDIR_RECURSIVE, NULL, &serror); if (G_UNLIKELY (serror != NULL)) { g_propagate_error (error, serror); diff --git a/thunar-vfs/thunar-vfs-unlink-job.c b/thunar-vfs/thunar-vfs-unlink-job.c index b84a02a9cd8995808c14e2fec44a67b0c82f002d..0b38416759e135c8cee5242b1bb95d96ac3f5178 100644 --- a/thunar-vfs/thunar-vfs-unlink-job.c +++ b/thunar-vfs/thunar-vfs-unlink-job.c @@ -165,7 +165,7 @@ thunar_vfs_unlink_job_execute (ThunarVfsJob *job) for (lp = unlink_job->path_list; lp != NULL && !thunar_vfs_job_cancelled (job); lp = lp->next) { /* scan the directory */ - paths = thunar_vfs_scandir (lp->data, THUNAR_VFS_SCANDIR_RECURSIVE, NULL, &error); + paths = thunar_vfs_scandir (lp->data, &job->cancelled, THUNAR_VFS_SCANDIR_RECURSIVE, NULL, &error); if (G_UNLIKELY (error != NULL)) { /* we can safely ignore ENOTDIR errors here */ diff --git a/thunar/thunar-icon-factory.c b/thunar/thunar-icon-factory.c index bbbdda672ac6c1b017c8769f359809ebdb32bc30..1b1b31af2d4d8690f76813f28befcd8bb86a3c4d 100644 --- a/thunar/thunar-icon-factory.c +++ b/thunar/thunar-icon-factory.c @@ -133,6 +133,8 @@ struct _ThunarIconKey static GObjectClass *thunar_icon_factory_parent_class = NULL; static GQuark thunar_icon_factory_quark = 0; +static GQuark thunar_icon_thumb_path_quark = 0; +static GQuark thunar_icon_thumb_time_quark = 0; static GQuark thunar_file_thumb_path_quark = 0; @@ -174,6 +176,10 @@ thunar_icon_factory_class_init (ThunarIconFactoryClass *klass) /* determine the parent type class */ thunar_icon_factory_parent_class = g_type_class_peek_parent (klass); + /* setup the thunar-icon-thumb-{path,time} quarks */ + thunar_icon_thumb_path_quark = g_quark_from_static_string ("thunar-icon-thumb-path"); + thunar_icon_thumb_time_quark = g_quark_from_static_string ("thunar-icon-thumb-time"); + /* setup the thunar-file-thumb-path quark */ thunar_file_thumb_path_quark = g_quark_from_static_string ("thunar-file-thumb-path"); @@ -837,7 +843,10 @@ thunar_icon_factory_load_file_icon (ThunarIconFactory *factory, gint icon_size) { ThunarFileThumbState thumb_state; + ThunarVfsFileTime time; ThunarVfsInfo *info; + ThunarVfsPath *path; + ThunarIconKey key; const gchar *icon_name; GdkPixbuf *icon; gchar *thumb_path; @@ -865,6 +874,7 @@ thunar_icon_factory_load_file_icon (ThunarIconFactory *factory, /* check if we haven't yet determine the thumbnail state */ if (thumb_state == THUNAR_FILE_THUMB_STATE_UNKNOWN) { +again: /* determine the ThunarVfsInfo for the file */ info = thunar_file_get_info (file); @@ -913,10 +923,46 @@ thunar_icon_factory_load_file_icon (ThunarIconFactory *factory, thumb_path = g_object_get_qdata (G_OBJECT (file), thunar_file_thumb_path_quark); if (G_LIKELY (thumb_path != NULL)) { - // FIXME: Check mtime and URI for the returned icon + /* try to load the thumbnail for the given path */ icon = thunar_icon_factory_lookup_icon (factory, thumb_path, icon_size, FALSE); if (G_LIKELY (icon != NULL)) - return icon; + { + /* determine the VFS info for the file */ + info = thunar_file_get_info (file); + + /* determine mtime and path for the thumbnail */ + path = g_object_get_qdata (G_OBJECT (icon), thunar_icon_thumb_path_quark); + time = GPOINTER_TO_UINT (g_object_get_qdata (G_OBJECT (icon), thunar_icon_thumb_time_quark)); + + /* check if mtime and path was already associated with the thumbnail */ + if (G_UNLIKELY (path == NULL)) + { + /* just save mtime and path for the thumbnail */ + g_object_set_qdata_full (G_OBJECT (icon), thunar_icon_thumb_path_quark, + thunar_vfs_path_ref (info->path), + (GDestroyNotify) thunar_vfs_path_unref); + g_object_set_qdata (G_OBJECT (icon), thunar_icon_thumb_time_quark, + GUINT_TO_POINTER (info->mtime)); + } + else if (G_UNLIKELY (time != info->mtime || !thunar_vfs_path_equal (path, info->path))) + { + /* the thumbnail is no longer valid, remove it from our internal cache */ + key.name = thumb_path; + key.size = icon_size; + + /* try to remove based on the key */ + if (g_hash_table_remove (factory->icon_cache, &key)) + { + /* we only restart the operation if we were successfull, else we could recurse infinitely */ + thumb_state = THUNAR_FILE_THUMB_STATE_UNKNOWN; + g_object_unref (G_OBJECT (icon)); + goto again; + } + } + + /* ok, we have a valid thumbnail */ + return icon; + } } }