Qt in Slicer3
This page captures the design considerations about moving Slicer3 from KWWidgets to Qt. As of August 2009 there are no concrete plans for a switch; however there is significant momentum around Qt as an open source technology and interest in making it available to the Slicer community.
When Slicer3 was being designed in 2004 Qt was available only under the GPL license or a commercial (pay) license (See the wikipedia discussion) and neither license option was acceptable to the community. In March 2009 Qt 4.5 was released under the LGPL license and became a possible technology for use in Slicer.
Slicer3 is implemented using KWWidgets which has proven to be extremely capable and robust. However, due to the small size of the developer team for KWWidgets Kitware has been clear that it will not be able to compete with the features being added to Qt and is in fact adopting Qt for many of its internal projects (see, for example, ParaView which migrated to Qt over the past several years).
In August of 2009 several members of the slicer development team have been learning about Qt and reviewing options. Things that are currently working:
- Qt and KWWidgets can co-exist in same application environment (in different top level windows).
- Qt widgets interfaces can be assembled using the QtDesigner, C++, or python.
- It is feasible to create slicer widgets that use Qt (e.g. a NodeSelector widget).
Overall the experience has been positive but the experiments have shown that there will be a significant amount of programming work to be done for each part of the interface. Most of the work is probably best characterized as "easy but time consuming". The net result of converting is expected to be positive but it is likely to be several years for there to be a payoff in terms of overall increased developer productivity and improved functionality of the overall package.
Development Plan Option for Transition to Qt
The following is a summary of the work to be done organized in a more-or-less priority order that would allow a transition in-place of functionality from KWW to Qt.
- Configure CPack to include Qt libraries and turn on Qt support by default in nightly builds of slicer
- Create prototype modules built using Qt (these would appear in a distinct top level window from the rest of slicer. The size and position would be under programatic control to make the two interface somewhat unified).
- Migrate the vtkSlicerViewerWidget, vtkSlicerSliceControllerWidget, and vtkSlicerSliceWidget from KWW to Qt. This would allow the right side (2D/3D viewers) of the interface to exist in Qt with the left side (module interfaces) to exist in KWWidgets.
- Migrate interfaces from modules and left side functions into Qt
- the menu bar, tool bar, modules menu, module search and history controls
- the CommandLineModuleGUI (so CLI modules will work in Qt)
- the "Manipulate Slice Views" and "Manipulate 3D View" controls
- Transition other dialogs and modules to Qt
- Build Skeleton Generator script
- Add Data, Add Volume, Save, Extension Wizard, Application Settings, Cache & Remote I/O Manager, Tcl/Python Interactors, ErrorLog Dialog, Keyboard Shortcuts...
- Core Modules: Colors, Data, Fiducials, Measurements, Models, ROI, SlicerWelcome, Slices, Transforms, Volume Rendering, Volumes
- ScriptedModules: Editor
- Application Modules: Change Tracker, IA_FEMesh, Qdec, FetchMI, Query Atlas, AC/PC Transform, ModelMirror, EMSegment, LabelStatistics, Tractography, Fiber Bundles, NeuroNav, OpenIGTLink IF, ProstateNav, Clip Model, Extract Subvolume ROI, 4D Volume, 4D Analysis.
- Extension Modules and DBP Projects: Perk Station, VMTK Vessel Tools, others...
- Remove KWW from the builds and do a new release.
Slicer's KWWidgets-based GUI
- There are 3309 KWWidgets instances created in slicer core and modules (calls to New)
- These calls are from 123 different KWWidget classes (including 'pure' KW classes in slicer that only depend on vtkKW and not MRML or other slicer code)
- 37 KKWidgets subclasses are vtkKWMimx classes in the Meshing module
- There are 105 classes that subclass from KWWidget classes
Statistics methods: Calculations based on slicer3 trunk revision 10456 2009-09-10. This does not include Tcl or Python code or extension modules (they use basically the same widgets).
grep -r vtkKW . | grep -v svn | grep New | wc grep -r vtkKW . | grep -v svn | grep "::New" | tr " " "\n" | tr "=" "\n" | tr ">" "\n" | grep -v "^//" | grep "vtkKW.*New" | sed 's/::New.*//' | sort | uniq | wc grep -r vtkKW . | grep -v svn | grep "::New" | tr " " "\n" | tr "=" "\n" | tr ">" "\n" | grep -v "^//" | grep "vtkKW.*New" | sed 's/::New.*//' | sort | uniq | grep Mimx | wc grep -r vtkKW . | grep -v svn | grep public | wc'
Qt widgets of interest
Playing with Qt Designer is a good way to explore Qt's core widgets. However, some KWW widgets are fairly complex, or uses Tk canvases pretty heavily; here are a few Qt widgets replacements worth considering. They are either found in the core distribution, or in Qt Solutions Catalog (LGPL):
- KWW's FileBrowser set of classes. Qt provides a QFileDialog class. It uses the native file dialogs on Win32/MacOS, and a different one on Unix, though it can use the same non-native dialog on all platforms. It can be set to pick directories only; a combination of QFile and QDirView can achieve a similar/better result. ParaView uses a custom (rewritten) File Dialog to handle client-server file browsing. Load/Save buttons are trivial to implement.
- KWW's Color Picker. Qt provides a QColorDialog, QtColorPicker, QtColorTriangle and QtColorComboBox. It is worth noting that QColorDialog offers basic colors (swatches), custom colors, RGB/HSV sliders on Win32/Unix, but uses a much more elaborate (native?) dialog on Mac.
- KWW's Transfer Function Editors. ParaView (BSD) and Maverick share a similar transfer function editor that is not as elaborated as KWW's, though this might do the trick for now. ParaView recently added a second (user-contributed) transfer function editor that provides free-form and gaussian curves.
- KWW's Collapsible Frames. The first (easiest) solution is to use a QGroupBox and manually connect the checked SIGNAL with the setVisible SLOT of all the children. You would get the same behavior (a checkbox on the left of the title instead of a cross and arrow on the left). The second solution is to inherit from QGroupBox and change the display (change the mark in the checkbox display to have + and -). screenshot for both solutions. Qt also offers tab widgets and toolboxes widgets to save space.
- KWW's Wizard classes. Qt provides sophisticated QWizard classes, as well as a Qt State Machine framework. It is not clear if a Qt Wizard can be embedded inside another widget, since it inherits QDialog.
- KWW's Range and Extent Widgets. JS will show how to develop a Range slider in a few minutes (ok, say a couple hours).
- KWW's error/info log window. A Qt Log Dialog was developed internally at Kitware (SB), and could most likely be reused.
- KWW's Multi Column Widget and Tree. Qt provides a sophisticated Qt Property Browser, as well as a large set of classes part of its Model/View Framework, including tree, list and tables views/widgets, delegates, selection models, drag&drop, etc. See how it is used in Kitware's Merlin/Maverick.
- Undo/Redo. Qt offers a Undo/Redo framework.
- Qt's resource editor is way more powerful and easy to use, and integrated in Qt Designer.
Considerations and Open Questions
- Coding styles and conventions for classes that interface vtk and Qt
- memory management (see how many smart pointer classes does Qt have?)
- a significant number of higher level Qt widgets are required (Ranges, Extents, TransferFunctionEditors, Material Properties...)
- Work needs to be coordinated among developers at multiple sites. Significant face-to-face time should be planned to keep everyone in sync on the progress.
- It will be inevitable that revisiting some modules will involve redesign and feature improvements even if our focus is specifically on swapping the GUI.
- Difficult bugs will occur somewhere along the process even if the plan appears smooth.
- We should consider training courses or conferences to get us up to speed on best practices for development. (http://www.ics.com/QuickStart/, http://qt.nokia.com/qtdevdays2009)
- What larger design re-works should be considered at the same time? I.e. should slicer functionality be re-organized as python packages so we can get away from the monolithic application attributes of the current main program (without a reduction in functionality or usability).
Development Approaches / Tradeoffs
Several development approaches could be taken each of which has pros/cons and risks.
- Immediate rewrite: this approach would be to start a from scratch to build a new GUI using Qt. Pros: likely to result in a cleaner architecture. Cons: all progress stops until new version is ready; current slicer developers are not Qt experts so not ready to build complex application from scratch; Qt does not have all the needed widgets to implement slicer (they need to be built along side slicer).
- Wait and see: wait until Qt more 3rd party widgets fill in the missing functionality and then do the rewrite. Cons: any new GUI development in the old framework will seem like a dead end. Pros: the current framework isn't really broken so why change?
- Peaceful coexistence: allow both GUI frameworks to be used together and allow people to develop in whichever is most productive for them. Cons: extra dependencies and potential maintenance issues; may require duplicated code; still need to resolve the architecture issues for mixing vtk and qt. Pros: removes pressure to do instant port; allows developers to get good at Qt before undertaking a big porting effort; allows development of 3rd party widgets that will make future ports easier.