Proposal for making the GtkFileChooser code asynchronous



Hi,

The last few weeks I have been working on making the GtkFileChooser code
asynchronous.  I've been making quite a bit of progress and hope to get the
changes in on time for GTK+ 2.10.  However, one of the most important
changes is making the GtkFileSystem API suitable for asynchronous operation,
which should not be a problem since GtkFileSystem is not supported API for
general use (see gtkfilesystem.h).

In this mail I will propose a set of changes to the GtkFileSystem API.  If
people are ok with these changes, I can go ahead and adapt all components
-- GtkFileChooser*, GtkFileSystemUnix, GtkFileSystemGnomeVFS -- to the new
GtkFileSystem API.


1. Let's start out with a somewhat more general change.  We need to be able
   to cancel currently running asynchronous operations.  For this we need
   to have a handle on an operation, so we need to introduce a
   GtkFileSystemHandle which would be defined the same way as GtkFileFolder --
   each backend can provide it's own handle object.  Of course we add a
   call which we can use to actually cancel an operation:

   gboolean gtk_file_system_cancel_operation (GtkFileSystem        *file_system,
                                              GtkFileSystemHandle  *handle,
                                              GError              **error);

   The gboolean return value will indicate success or failure, in the latter
   case the error will be provided via GError.

2. Addition of gtk_file_system_get_info(), so we are able to retrieve
   information about a file without having to create a folder.  This is
   useful in for example GtkPathBar. Prototypes:

   typedef void (* GtkFileSystemGetInfoCallback) (GtkFileSystem       *file_system,
                                                  GtkFileSystemHandle *handle,
                                                  GtkFileInfo         *file_info,
                                                  GError              *error,
                                                  gpointer             data);

   GtkFileSystemHandle *gtk_file_system_get_info (GtkFileSystem                 *file_system,
                                                  const GtkFilePath             *path,
                                                  GtkFileInfoType                types,
                                                  GtkFileSystemGetInfoCallback   callback,
                                                  gpointer                       data,
                                                  GError                       **error);


   If the return value of gtk_file_system_get_info() is NULL, and the error
   argument is non-NULL a description of the error will be provided in there.
   Only errors which occurred before the asynchronous information acquisition
   process started will be reported this way.  All other errors will be
   reported via the callback.

3. Change gtk_file_system_get_folder().  We cannot directly return a folder
   here, because we need to access the file system to figure out if the
   given path is really a folder.  Let's use the following as a new call:

   typedef void (* GtkFileSystemGetFolderCallback) (GtkFileSystem       *file_system,
                                                    GtkFileSystemHandle *handle,
                                                    GtkFileFolder       *folder,
                                                    GError              *error,
                                                    gpointer             data);

   GtkFileSystemHandle *gtk_file_system_get_folder (GtkFileSystem                  *file_system,
                                                    const GtkFilePath              *path,
                                                    GtkFileInfoType                 types,
                                                    GtkFileSystemGetFolderCallback  callback,
                                                    gpointer                        data,
                                                    GError                        **error);


   If the return value of gtk_file_system_get_folder() is NULL, and the error
   argument is non NULL a description of the error will be provided in there.
   As with the other functions, only errors which occurred before the actual
   asynchronous operation started will be reported this way.

   Using this new call would work as follows:
      I.   Call gtk_file_system_get_folder().
      II.  The callback provided will be called to tell whether the folder
           exists or not.  If it exists, you will be provided with a pointer
           to a valid GtkFileFolder, if not the process ends here.
      III. A directory load will immediately start, children will be added via
           the "files-added" signal until you receive a "finished-loading"
           signal.

   The functions gtk_file_folder_list_children() and gtk_file_folder_get_info()
   will not be changed.

4. gtk_file_system_create_folder() needs to be changed in order to be able
   to operate asynchronously.  The new prototypes:

   typedef void (* GtkFileSystemCreateFolderCallback) (GtkFileSystem     *file_system,
                                                       const GtkFilePath *path
                                                       GError            *error,
                                                       gpointer           data);

   GtkFileSystemHandle *gtk_file_system_create_folder (GtkFileSystem                      *file_system,
                                                       const GtkFilePath                  *path,
                                                       GtkFileSystemCreateFolderCallback   callback,
                                                       gpointer                            data,
                                                       GError                            **error);

   The error reporting works on the same way as the other functions.

5. We will also change gtk_file_system_volume_mount() to report the result
   of the operation via a callback as follows:

   typedef void (* GtkFileSystemVolumeMountCallback) (GtkFileSystem       *file_system,
                                                      GtkFileSystemVolume *volume,
                                                      GError              *error,
                                                      gpointer             data);

   GtkFileSystemHandle *gtk_file_system_volume_mount (GtkFileSystem                     *file_system,
                                                      GtkFileSystemVolume               *volume,
                                                      GtkFileSystemVolumeMountCallback   callback,
                                                      gpointer                           data,
                                                      GError                           **error);

   The error reporting works on the same way as the other functions.

6. Right now gtk_file_system_render_icon() is synchronous, because it needs
   some information about the file in order to be able to render a suitable
   icon.  We think that loading icons asychronously, during the asynchronous
   folder loading process, is the way to go.  Because we need a widget to
   render icons for us, we need to add:

   void gtk_file_system_set_widget (GtkFileSystem *file_system,
                                    GtkWidget     *widget);

   Then we will add an icon field to GtkFileInfo, appropriate get/set functions
   and GTK_FILE_INFO_ICON.  We will remove gtk_file_system_render_icon().
   Now we have gtk_file_system_set_widget(), we plan on changing
   gtk_file_system_volume_render_icon() to:

   GdkPixbuf *gtk_file_system_volume_get_icon (GtkFileSystem        *file_system,
                                               GtkFileSystemVolume  *volume,
                                               gint                  pixel_size,
                                               GError              **error);


I would say that it is clear that we are going to break the API completely
here, and also not continuing to support the old API.  Third party code
should not notice anything of these changes, except for third party code
using the GtkFileSystem API.  Since the GtkFileSystem API is not supported,
I assume that there isn't much code out there using the GtkFileSystem API.
In order to not have that kind of code crash and burn on a system with a newer
GTK+, we need to build in some kind of protection.  Does anyone have
suggestions on this one?



I am looking forward to your feedback.


thanks,

-kris.



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]