Difference between revisions of "Documentation/4.0/Developers/Tutorials/ModuleWriting"

From Slicer Wiki
Jump to: navigation, search
(Prepend documentation/versioncheck template. See http://na-mic.org/Mantis/view.php?id=2887)
 
(30 intermediate revisions by 5 users not shown)
Line 1: Line 1:
[[Slicer4:QtPort|QtSlicer]]/[[Slicer4:QtPort/Tutorials|Tutorials]]←
+
<noinclude>{{documentation/versioncheck}}</noinclude>
 +
=Consider also reading=
 +
*[[Media:QtPortInSlicer.ppt|QtPortInSlicer - How to write a module]]
 +
*[[Documentation/{{documentation/version}}/Developers/Tutorials/ExternalModuleWriting|How to write an external module]]
 +
 
 
= Initialization =
 
= Initialization =
* Create the Module directory
+
=== 1) Create the module directory ===
  cd Slicer4
+
Use the [[Documentation/4.0/Developers/ModuleWizard|module wizard]] to generate files and directory based on a template.
  python Scripts/ModuleWizard.py MY_MODULE_NAME
+
{|
Note: on Windows
+
! style="border-bottom: 1px solid darkgrey;"| <small>Linux</small>
  ..\Slicer4-Superbuild\python-build\PCBuild\python.exe Scripts\ModuleWizard.py MY_MODULE_NAME
+
! style="border-bottom: 1px solid darkgrey;"| <small>Mac</small>
* Add the newly created module into Slicer4/QTModules/CMakeLists.txt
+
! style="border-bottom: 1px solid darkgrey;"| <small>Windows</small>
* Compile
+
|-
* Start Slicer and verify the module is present
+
| colspan=2; valign="top" |
* Open the designer via the launcher
+
  $ cd Slicer4
  cd Slicer4-Superbuild/Slicer-build
+
  $ python Utilities/Scripts/ModuleWizard.py MY_MODULE_NAME
  slicer4 --designer
+
| valign="top" |
*Open the module UI file (QTModules/MY_MODULE_NAME/Resources/UI/qSlicerMY_MODULE_NAMEModule.ui)
+
You need to open a terminal and go to the Slicer4 source directory.<br>
 +
Start -> Microsoft Visual Studio 2008 -> Visual Studio Tools -> Visual Studio 2008 Command Prompt<br>
 +
Then type in the terminal:<br>
 +
$ 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)<br>
 +
After running the script, a new directory MY_MODULE_NAME should be created in ''Slicer4/Modules/Loadable''
 +
<br><br>
 +
 
 +
=== 2) Add the module in CMake ===
 +
Edit the file [http://viewvc.slicer.org/viewvc.cgi/Slicer4/trunk/Modules/Loadable/CMakeLists.txt?view=markup Slicer4/Modules/Loadable/CMakeLists.txt]:
 +
Add the name of your module at the end of the qtmodules variable assignment:
 +
...
 +
set(qtmodules
 +
  ...
 +
  MY_MODULE_NAME
 +
  )
 +
...
 +
<br><br>
 +
=== 3) Compile ===
 +
Compile the inner build (''Slicer-build'' inside the Superbuild directory).
 +
{|
 +
! style="border-bottom: 1px solid darkgrey;"| <small>Linux</small>
 +
! style="border-bottom: 1px solid darkgrey;"| <small>Mac</small>
 +
! style="border-bottom: 1px solid darkgrey;"| <small>Windows</small>
 +
|-
 +
| colspan=2; valign="top" |
 +
$ cd ../Slicer4-Superbuild/Slicer-build;
 +
$ make -j4
 +
| valign="top" |
 +
$ cd ..\Slicer4-Superbuild\Slicer-build;
 +
$ .\Slicer.exe --VisualStudio Slicer.sln
 +
In Visual Studio, go to Build -> Build Solution
 +
|}
 +
<br><br>
 +
 
 +
=== 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 [http://slicer.org/doc/html/classqSlicerAbstractCoreModule.html#properties 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''.
 +
<br><br>
 +
 
 +
=== 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
 +
<br><br>
 +
 
 +
=== 6) Change the UI ===
 +
Using Qt Designer, edit the module UI file: ''Modules/Loadable/MY_MODULE_NAME/Resources/UI/qSlicerMY_MODULE_NAMEModule.ui''<br>
 +
[[Slicer4:Developers:Projects:QtSlicer/Tutorials/QtDesigner|More info on how to use the designer]]
 +
<br><br>
 +
 
 +
=== 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]
 +
...
 +
<br><br>
 +
 
 
= Qt Designer =
 
= Qt Designer =
 
* How to set icons to widgets
 
* How to set icons to widgets
 
** In the icon property entry of the widget (Property Editor), select a resource file
 
** In the icon property entry of the widget (Property Editor), select a resource file
*** Slicer4\QTModules\MY_MODULE_NAME\Resources\qSlicerMY_MODULE_NAMEModule.qrc
+
*** Slicer4/Modules/Loadable/MY_MODULE_NAME/Resources/qSlicerMY_MODULE_NAMEModule.qrc
*** Slicer4\Libs\qMRMLWidgets\Resources\qMRMLWidget.qrc
+
*** Slicer4/Libs/MRML/Widgets/Resources/qMRMLWidget.qrc
*** Slicer4\Base\QTGUI\Resources\qSlicerBaseQTGUI.qrc
+
*** Slicer4/Base/QTGUI/Resources/qSlicerBaseQTGUI.qrc
 
* How to add an icon in a resource file
 
* How to add an icon in a resource file
** Add the icon in Slicer4/QTModules/MY_MODULE_NAME/Resources/Icon
+
** Add the icon in Slicer4/Modules/Loadable/MY_MODULE_NAME/Resources/Icon
 
** Edit the resource file by adding the line
 
** Edit the resource file by adding the line
 
*** "<file>Icons/MyIcon.png</file>"
 
*** "<file>Icons/MyIcon.png</file>"
= Qt Creator =
+
 
[http://qt.nokia.com/products/developer-tools?currentflipperobject=821c7594d32e33932297b1e065a976b8 Qt Creator] is a cross-platform IDE that fully integrates Qt into the development of applications. Slicer CMake project is supported by Qt Creator, the following describes tips using Qt Creator.  
+
= Dependency between modules =
* launch qtcreator through slicer to setup paths and paths to paths:
+
It is possible that your module needs to access information from another module. Typically the logic of a module.
  Slicer4 --launch /your/qtcreator/location
+
The following code is an example of what can be done to make your module dependent to the Volumes module logic:
* turn off verbose make using this from Slicer-build:
+
In CMakeLists.txt:
  cmake -D CMAKE_VERBOSE_MAKEFILE:BOOL=OFF .
+
  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
 +
    )

Latest revision as of 07:29, 14 June 2013

Home < Documentation < 4.0 < Developers < Tutorials < ModuleWriting


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
$ 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
   )