File Manager Integration for Linux (TortoiseHG)
Summary
Last milestone: Polished the history widget to be reused in other applications, implemented the FolderView widget, which were integrated in a single application.
Current development (last for SoC): Refactoring the status and diff viewer as widgets.
Current implementation
Source code
- Nautilus improvements (Fixed the Nautilus support for submenus used in extensions):
- A new version with this bug fixed was released by June 30 (Nautilus 2.22.4).
TortoiseHG synced with the latest development version and the patches queue ready to apply in tortoisehg
- You can get your copy through:
cd tortoisehg/.hg
You will find several guards (hg qguard -l to list them), which is the way I divided the group of patches.
- You can get your copy through:
Ubuntu packages
There are packages available for Ubuntu at Personal Package Archive:
nautilus. A fixed version with support for submenus working fine in extensions.
mercurial-tortoisehg. A version to use hgtk from the shell.
nautilus-mercurial-tortoisehg. A plugin for working
It is possible to use those packages to build them for Debian or any other Debian based distribution.
These packages have some caveats:
hgtk about doesn't work, because it has problems to load the COPYING.txt file. As a document file, it is stored compressed, in a different directory whic
- Icons are not shown in Nautilus' menus.
Observations
Packages and distributions:
- The paths used to load icons and files should not be hardcoded, because packages must be relocalatables. The same is applied for distutils (setup.py).
The hard part is the use of the environment variables TORTOISEHG_PATH and THG_ICON_PATH. Probably having a single file (init.py) could be helpful.
Nautilus menus:
- There is no order to load the menu items.
- It doesn't matter the order the menuitems are created.
- I thought it was sorted according the name of each menuitem, but using names such as 10foo, 20bar, ... they seems to work sometimes.
- Next Debian version (Lenny) will be realeased with Gnome 2.20, which means it won't have the fixes for working with submenus.
- By the time TortoiseHG 0.5 will released (the target version of this SoC) all major distributions (except Debian) will offer Gnome 2.24 (scheduled for september 2008).
- It will be necessary to have two implementations of the plugin (one for Debian and old versions of distributions)
- It is not possible to ask the version of Nautilus, so a flag inside the plugin will define its behavior.
Current view of Nautilus integration:
Milestones
- Improve the integration between Nautilus and TortoiseHG
Make the plugin stable
Enable the plugin works not only in debug mode
Fix/Enable support for submenus
- Enable other options still hidden for Nautilus
- Provide a consistent GUI to follow a project using Mercurial
- Get reusable widgets out of each dialog/command
Done for simple dialogs (clone, merge, update, about)
History/Log view
Folder viewer (new)
Diff viewer & Diff buffer (in progress)
Diff list (custom !Liststore for Status viewer)
Propose an integrated UI with the refactored widgets (partially done)
Improve the UI (partially done)
- Get reusable widgets out of each dialog/command
- Other improvements
Provide packages for a Debian based distribution
User Interface Improvements
From a technical point of view, it seems it is not clearity when a GtkDialog and/or a GtkWindow is used in TortoiseHG. Some of them are GtkDialog and some of them GtkWindow without any clear distinction.
The following diagram shows the relation between dialogs/windows. There are two windows that can be invoked from the shell (hgtk) or from another window (history). Please note that history is also invoked from the shell (hgtk log) but for simplicity doesn't appear linked in the diagram.
Because both update and datamine can be invoked directly or indirectly from hgtk is needed to know how to close the dialog (hide it or destroy it) according the circunstances.
Cloning repositories
The following screenshot show the current user interface of hgtk clone:
The usability may be improved just agruping common items and using proper buttons instead of a toolbar. The button 'X' in the upper right corner is reduntant, because the window managar provides such button and in a dialog a button 'Cancel' or 'Close' could give better feedback.
Merging repositories
The same criteria as Cloning repositories may be applied in this dialog. The current one is:
and the proposal:
It worth noting that the former window has two different behaviors: merge and undo a merge. The button in the toolbar is activated/deactivated according to that. The same happen with the label "Merge with revision".
It could be confusing having two dialogs in one. One possible change could be:
Updating repositories
Selecting a changeset
The actions merge and update allows to select the changeset to be used, which may be choosen by the user filling the entry field or browsing the logs. The logging browsing is a common window:
The data is the same shown as hgtk log, but shorter. It would be nicer to share the same widget to choose the current.
Widgets
Notes about internal changes that need to be improved to reuse some widgets.
History
This widget, implemented under hggtk/vis/treeview.py, can receive as parameter another widget: a status bar.
The status bar is not a standar Gtk.StatusBar, it is a custom one. The status bar is not directly related to an history viewer. It is used to give feedback about a working in progress.
Issues:
- It allows the status bar received is None. Hence, it is optional. However, it tries to access the methods begin() and end() of the status bar, but if the status bar is None it will fail.
- It fails if the repo given is None. It is needed if there is an application that browse directories through the system. No every directory has a repo.
Solution:
- A simple workaround is to validate if status bar is not None before using any method.
- The final solution is not using any status bar in the History view and emit signal any time some action happens ('begin' and 'end').
- Make the repo calls conditional and add a method to set a new repo later. If repo is None, the view should be cleaned.
Diff and Status viewer
These are not implemented as widgets, they are implemented together in a window, which is reused in both history and datamine windows. In the history window is embedded inside a horizontal panel and in the datamine one is shown in a dialog.
Issues:
- They are not separated, so it's harder to reuse them in a standalone application.
- There are three parts where a diff viewer is used:
- Inside the history window
- As a dialog in history window
- As a dialog in datamine window
- There are two different ways to show diffs:
- A simple one using sourceview with syntax highlighting (display in the graph)
- A clone of htk (used as status and diff in the graph)
Solution:
- To reimplement them as widgets.
- They can communicate each other through signals or sharing a model.
This has been harder than expected, because it mixes code:
- Internal handling of the repository (diff)
Handling of a !TextBuffer/!TextView, for viewing diffs
Handling of a !ListStore/!TreeView, for status view
Some parts of the code were taken from hgview, which were extended but without any abstraction of the repository.
I spent more time in solving this particular issue because an abstraction of the repository will be helpful in the future, for instance:
- To deal with different versions of Mercurial without touching any widget.
- Some parts of the communication between the UI and Mercurial are done using the output of Mercurial's commands, while other uses the UI. It will make easier to migrate them to use the API.
- To allow different backends (using stdout or the API).
The handle of the diff buffer (to be used in a TextView) is still in progress, while the ListStore to be shared with the diff buffer is done (still pending some polishing).
Folder viewer
This widget didn't exist because there was not a standalone application.
This is implemented to work with local folder and emiting a signal every time a different folder is selected. Connecting that signal in the application it is possible to find the proper repository to fill the history widget.
Project viewer
This widget didn't exist because there was not a standalone application.
This is a specialization between the Folder viewer and the Status viewer. The idea is to have filtered the files involved in the project.
Integrated UI
Once:
- The UI and the program logic is separated;
- The specialized widgets are isolated;
- Dialogs are written in separated files (libglade/gtkbuilder)
It is possible to integrate them in a unified interface and it makes easy to rearrange the widgets to experiment with different dispositions.
As a proof of concept, the following interface has the main window designed with Glade, the application that load it also add the widgets Folder and TreeView (it should be renamed to GraphView or any better name than TreeView). Every time a different folder is selected is needed to check if still we are using the same repository, another one or just in common folder (without revision). Once the check is done, the TreeView is updated.
The integration of other widgets will be as easy as that. For instance, the not finished yet isolation of StatusView is also possible to embed: