Last year GtkSourceView saw a new search and replace API. This year it’s the file loading and saving that has just landed! It is in the continuity of making the gedit source code more reusable for other text editors.
In short, the back-end part of the file loading and saving in gedit has been moved to GtkSourceView, with a new and more flexible API to better wrap the feature. The code has been modified to follow GIO conventions for asynchronous operations, to use GTask internally, and replace the uses of GSettings by properties.
The file loader auto-detects encodings, newline types and compression type (yes gedit can open gzip files). Invalid characters can also be displayed with their corresponding hexadecimal value, because GtkTextBuffer accepts only valid UTF-8 text. And progress information is reported during the operation.
The API is stateful: the file parameters (encoding etc) are remembered between a file loading and a file saving in a GtkSourceFile object. Unfortunately the new API is still quite low-level. The application must configure the file loader and the file saver, and some errors are returned to the application.
The front-end and errors handling is still implemented in gedit. Errors and progress information are displayed in an info bar, above the GtkSourceView widget. For some errors, gedit proposes different actions to the user, like choosing another encoding.
The info bars and the GtkSourceView widget are included in the GeditTab container. The GtkSourceView library doesn’t have a GtkSourceTab class, that’s partly why the GtkSourceFile API is a bit low-level.
If you are a text editor developer, don’t hesitate to have a look at the GtkSourceFile API. The API can still change during this 3.13 development cycle. The notes about the API design are available on bugzilla (there has been four iterations). Here is a summary.
The API is a bit heavy, with the following classes: GtkSourceEncoding, GtkSourceFile, GtkSourceFileLoader and GtkSourceFileSaver. There are good reasons for having two class’ names derived from a verb (“to load” and “to save”), which is generally a hint that those classes should be replaced by a method (i.e. an action). The reasons are partly similar with the new GSubprocessLauncher in GIO: the FileLoader and FileSaver classes are there not only for launching the operation, but also for configuring it with a nicer and more extensible API than one function with a dozen parameters. With the FileLoader and FileSaver, we can add properties, functions and even signals. And the FileLoader and FileSaver classes are quite useful in gedit: when an error occurs and the user clicks on a button in the info bar, the loader or saver object is reconfigured and the operation is relaunched. Also, the FileLoader or FileSaver properties are applied to the GtkSourceFile object only on a successful operation, so the GtkSourceFile state is (normally) consistent with the underlying file on the disk, at least at the time of the last load or save done with GtkSourceView.
Possible follow-ups work
A possible follow-up is to make the remaining file loading and saving gedit code more reusable, either by creating new classes in GtkSourceView, or by creating a git submodule, like the libgd (without API stability guarantees in the latter case).
Another possible follow-up is to analyze and improve the performances, which are currently quite bad. For short files it is not visible of course, but opening a very big log file takes a lot of time.
There are other possible improvements, like unescaping invalid characters when saving, or avoid blocking the GtkTextBuffer when (auto-)saving a short remote file on a slow network connection.
Changes for gedit plugins
Unfortunately there are some changes in the gedit API for plugins, mainly in GeditDocument. Fortunately the changes are well documented, and most plugins should still work without any modification.
The file loading and saving can quickly become a fairly complex beast. Now this code is available for other GTK+ text editors.
Thanks to Paolo Borelli for the reviews!
- In gedit: 49 files changed, 1888 insertions(+), 8819 deletions(-)
- In GtkSourceView: 29 files changed, 7909 insertions(+), 3 deletions(-)
This is a 12% code increase in GtkSourceView, and a 6% code decrease in gedit.
PS: As usual, some tests would be more than welcome before the stable version in September.