Difference between revisions of "Documentation/4.1/Developers/Tutorials/CreateLoadableModule"

From Slicer Wiki
Jump to: navigation, search
(Prepend documentation/versioncheck template. See http://na-mic.org/Mantis/view.php?id=2887)
 
(5 intermediate revisions by 3 users not shown)
Line 1: Line 1:
 +
<noinclude>{{documentation/versioncheck}}</noinclude>
 
=Consider also reading=
 
=Consider also reading=
 
*[[Media:QtPortInSlicer.ppt|QtPortInSlicer - How to write a module]]
 
*[[Media:QtPortInSlicer.ppt|QtPortInSlicer - How to write a module]]
Line 17: Line 18:
 
  $ python Utilities/Scripts/ModuleWizard.py MY_MODULE_NAME
 
  $ python Utilities/Scripts/ModuleWizard.py MY_MODULE_NAME
 
| valign="top" |
 
| valign="top" |
Start <code>cmd.exe</code> terminal, then type the following (in 64-bit mode replace <code>PCbuild</code> with <code>PCbuild\amd64</code>:<br>
+
Start <code>cmd.exe</code> terminal, then type the following (in 64-bit mode replace <code>PCbuild</code> with <code>PCbuild\amd64</code>):<br>
 
  $ cd C:\path\to\Slicer4
 
  $ cd C:\path\to\Slicer4
 
  $ ..\Slicer4-Superbuild\python-build\PCBuild\python.exe Utilities\Scripts\ModuleWizard.py MY_MODULE_NAME
 
  $ ..\Slicer4-Superbuild\python-build\PCBuild\python.exe Utilities\Scripts\ModuleWizard.py MY_MODULE_NAME
Line 67: Line 68:
 
=== 6) Change the UI ===
 
=== 6) Change the UI ===
 
Using Qt Designer, edit the module UI file: <code>Modules/Loadable/MY_MODULE_NAME/Resources/UI/qSlicerMY_MODULE_NAMEModule.ui</code><br>
 
Using Qt Designer, edit the module UI file: <code>Modules/Loadable/MY_MODULE_NAME/Resources/UI/qSlicerMY_MODULE_NAMEModule.ui</code><br>
[[Slicer4:Developers:Projects:QtSlicer/Tutorials/QtDesigner|More info on how to use the designer]]
+
[[Documentation/{{documentation/version}}/Developers/Tutorials/QtDesigner|More info on how to use the designer]]
 
<br><br>
 
<br><br>
  
Line 93: Line 94:
  
 
In CMakeLists.txt:
 
In CMakeLists.txt:
   set(qt_module_include_directories
+
   set(MODULE_INCLUDE_DIRECTORIES
 
     ${CMAKE_CURRENT_SOURCE_DIR}/Widgets
 
     ${CMAKE_CURRENT_SOURCE_DIR}/Widgets
 
     ${CMAKE_CURRENT_BINARY_DIR}/Widgets
 
     ${CMAKE_CURRENT_BINARY_DIR}/Widgets
Line 100: Line 101:
 
     )
 
     )
 
   ...  
 
   ...  
   set(qt_module_target_libraries
+
   set(MODULE_TARGET_LIBRARIES
 
     ...
 
     ...
 
     vtkSlicerVolumesModuleLogic
 
     vtkSlicerVolumesModuleLogic
Line 106: Line 107:
  
 
In qSlicerMY_MODULE_NAMEModule.cxx:
 
In qSlicerMY_MODULE_NAMEModule.cxx:
 
+
 
 +
  //-----------------------------------------------------------------------------
 
   QStringList qSlicerMY_MODULE_NAMEModule::dependencies()const
 
   QStringList qSlicerMY_MODULE_NAMEModule::dependencies()const
 
   {
 
   {
Line 112: Line 114:
 
   }
 
   }
 
    
 
    
 +
  //-----------------------------------------------------------------------------
 
   void qSlicerMY_MODULE_NAMEModule::setup()
 
   void qSlicerMY_MODULE_NAMEModule::setup()
 
   {
 
   {
Line 131: Line 134:
  
 
Follow the same pattern in CMakeLists.txt to add dependency on a module widgets:
 
Follow the same pattern in CMakeLists.txt to add dependency on a module widgets:
  set(qt_module_include_directories
+
 
 +
  set(MODULE_INCLUDE_DIRECTORIES
 
   ...  
 
   ...  
 
   ${qSlicerVolumesModuleWidgets_SOURCE_DIR}
 
   ${qSlicerVolumesModuleWidgets_SOURCE_DIR}
Line 138: Line 142:
 
   )
 
   )
 
   ...
 
   ...
   set(qt_module_target_libraries
+
   set(MODULE_TARGET_LIBRARIES
 
     ...
 
     ...
 
     qSlicerVolumesModuleWidgets
 
     qSlicerVolumesModuleWidgets
Line 146: Line 150:
  
 
== Examples ==
 
== Examples ==
# [[Documentation/{{documentation/version}}/Modules/CropVolume|Crop Volume]] module [http://viewvc.slicer.org/viewvc.cgi/Slicer4/trunk/Modules/Loadable/CropVolume/qSlicerCropVolumeModule.cxx?view=markup depends on] [[Documentation/{{documentation/version}}/Modules/Volumes|Volumes]] module
+
# [[Documentation/{{documentation/version}}/Modules/CropVolume|Crop Volume]] module [http://viewvc.slicer.org/viewvc.cgi/Slicer4/trunk/Modules/Loadable/CropVolume/qSlicerCropVolumeModule.cxx?view=markup depends] on [[Documentation/{{documentation/version}}/Modules/Volumes|Volumes]] module

Latest revision as of 07:28, 14 June 2013

Home < Documentation < 4.1 < Developers < Tutorials < CreateLoadableModule


For the latest Slicer documentation, visit the read-the-docs.


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

Start terminal (bash or Terminal.app), then type the following:

$ cd /path/to/Slicer4
$ python Utilities/Scripts/ModuleWizard.py MY_MODULE_NAME

Start cmd.exe terminal, then type the following (in 64-bit mode replace PCbuild with PCbuild\amd64):

$ cd C:\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 will 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(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 or the custom MRML classes 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(MODULE_INCLUDE_DIRECTORIES
   ${CMAKE_CURRENT_SOURCE_DIR}/Widgets
   ${CMAKE_CURRENT_BINARY_DIR}/Widgets
   ${vtkSlicerVolumesModuleLogic_SOURCE_DIR}
   ${vtkSlicerVolumesModuleLogic_BINARY_DIR}
   )
  ... 
 set(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 module will be setup before your module is setup.

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

set(MODULE_INCLUDE_DIRECTORIES
  ... 
  ${qSlicerVolumesModuleWidgets_SOURCE_DIR}
  ${qSlicerVolumesModuleWidgets_BINARY_DIR}
  ...
  )
 ...
 set(MODULE_TARGET_LIBRARIES
   ...
   qSlicerVolumesModuleWidgets
   )

It works the same if you want to access the custom MRML (vtkSlicerDEPENDENT_MODULEModuleMRML_SOURCE_DIR) or displayable manager (vtkSlicerDEPENDENT_MODULEModuleDisplayableManager_SOURCE_DIR) classes.

Examples

  1. Crop Volume module depends on Volumes module