Documentation/4.0/Developers/Tutorials/ModuleWriting

From SlicerWiki
Jump to: navigation, search
Home < Documentation < 4.0 < Developers < Tutorials < ModuleWriting

For the latest Slicer developers documentation, visit the Nightly page.

Consider also reading

Initialization

1) Create the module directory

Use the module wizard to generate files and directory based on a template.

Linux Mac Windows
$ cd Slicer4
$ python Utilities/Scripts/ModuleWizard.py MY_MODULE_NAME

You need to open a terminal and go to the Slicer4 source directory.
Start -> Microsoft Visual Studio 2008 -> Visual Studio Tools -> Visual Studio 2008 Command Prompt
Then type in the terminal:

$ cd path\to\Slicer4
$ ..\Slicer4-Superbuild\python-build\PCBuild\python.exe Utilities\Scripts\ModuleWizard.py MY_MODULE_NAME

Replace MY_MODULE_NAME with the name of the module you want (e.g. HelloWorld)
After running the script, a new directory MY_MODULE_NAME should be created in Slicer4/Modules/Loadable

2) Add the module in CMake

Edit the file Slicer4/Modules/Loadable/CMakeLists.txt: Add the name of your module at the end of the qtmodules variable assignment:

...
set(qtmodules
  ...
  MY_MODULE_NAME
  )
...



3) Compile

Compile the inner build (Slicer-build inside the Superbuild directory).

Linux Mac Windows
$ cd ../Slicer4-Superbuild/Slicer-build;
$ make -j4
$ cd ..\Slicer4-Superbuild\Slicer-build;
$ .\Slicer.exe --VisualStudio Slicer.sln

In Visual Studio, go to Build -> Build Solution



4) Check the module

Start Slicer and make sure the module is present (listed under "Module Template")

$ ./Slicer

To change the module title that shows up in Slicer, edit the file Slicer4/Modules/Loadable/MY_MODULE_NAME/CMakeLists.txt

set(qt_module_title "Your title") 

Other properties for the module such as help, acknowledgment or categories can be re-implemented directly in C++ by editing Slicer4/Modules/Loadable/MY_MODULE_NAME/qSlicerMY_MODULE_NAME.cxx.

5) Open Qt Designer using the launcher

Slicer (the launcher) searches Qt Designer on your machine (using QT_QMAKE_EXECUTABLE set at configure time). It starts the designer after setting the correct environment variables (QT_PLUGIN_PATH for the widgets designer plugins and PATH/LD_LIBRARY_PATH for the libraries).

$ ./Slicer --designer



6) Change the UI

Using Qt Designer, edit the module UI file: Modules/Loadable/MY_MODULE_NAME/Resources/UI/qSlicerMY_MODULE_NAMEModule.ui
More info on how to use the designer

7) Edit the module files

Slicer4/Modules/Loadable/MY_MODULE_NAME/qSlicerMY_MODULE_NAME.[h|cxx]
Slicer4/Modules/Loadable/MY_MODULE_NAME/qSlicerMY_MODULE_NAMEWidget.[h|cxx]
Slicer4/Modules/Loadable/MY_MODULE_NAME/Logic/vtkSlicerMY_MODULE_NAMELogic.[h|cxx]
...



Qt Designer

  • How to set icons to widgets
    • In the icon property entry of the widget (Property Editor), select a resource file
      • Slicer4/Modules/Loadable/MY_MODULE_NAME/Resources/qSlicerMY_MODULE_NAMEModule.qrc
      • Slicer4/Libs/MRML/Widgets/Resources/qMRMLWidget.qrc
      • Slicer4/Base/QTGUI/Resources/qSlicerBaseQTGUI.qrc
  • How to add an icon in a resource file
    • Add the icon in Slicer4/Modules/Loadable/MY_MODULE_NAME/Resources/Icon
    • Edit the resource file by adding the line
      • "<file>Icons/MyIcon.png</file>"

Dependency between modules

It is possible that your module needs to access information from another module. Typically the logic of a module. The following code is an example of what can be done to make your module dependent to the Volumes module logic: In CMakeLists.txt:

 set(qt_module_include_directories
   ${CMAKE_CURRENT_SOURCE_DIR}/Widgets
   ${CMAKE_CURRENT_BINARY_DIR}/Widgets
   ${vtkSlicerVolumesModuleLogic_SOURCE_DIR}
   ${vtkSlicerVolumesModuleLogic_BINARY_DIR}
   )
  ... 
 set(qt_module_target_libraries
   ...
   vtkSlicerVolumesModuleLogic
   )

In qSlicerMY_MODULE_NAMEModule.cxx:

 QStringList qSlicerMY_MODULE_NAMEModule::dependencies()const
 {
 return QStringList() << "Volumes";
 }
 void qSlicerMY_MODULE_NAMEModule::setup()
 {
 this->Superclass::setup();

 vtkSlicerMY_MODULE_NAMELogic* moduleLogic =
   vtkSlicerMY_MODULE_NAMELogic::SafeDownCast(this->logic());

 qSlicerAbstractCoreModule* volumesModule =
   qSlicerCoreApplication::application()->moduleManager()->module("Volumes");
 if (volumesModule)
   {
   vtkSlicerVolumesLogic* volumesLogic = 
     vtkSlicerVolumesLogic::SafeDownCast(volumesModule->logic());
   moduleLogic->SetVolumesLogic(volumesLogic);
   }

By specifying the module as a dependency, you are insured that the dependency will be setup before your module is setup.

Follow the same pattern in CMakeLists.txt to add dependency on a module widgets:

set(qt_module_include_directories
  ... 
  ${qSlicerVolumesModuleWidgets_SOURCE_DIR}
  ${qSlicerVolumesModuleWidgets_BINARY_DIR}
  ...
  )
 ...
 set(qt_module_target_libraries
   ...
   qSlicerVolumesModuleWidgets
   )