Slicer3:Loadable Modules:HOWTO
In order to allow a module to be detected and loaded at runtime a number of changes are required. The first is within the module's GUI class. The vtkSlicerModuleGUI-derived class _must_ implement "void SetModuleLogic(vtkSlicerLogic*)". This allows the library loading methods to load the GUI without knowing the specific class type.
A text file named after the module must also be created.
Last, macros for module creation and handling must be added to the CMakeLists file.
For more information on these edits, plus some optional changes, see below.
Contents
vtkModuleNameGUI
vtkModuleNameGUI.h/cxx
Do not create this class if you want your module to be GUI-less
Required
For your vtkSlicerModuleGUI-derived class, declare and implement:
virtual void SetModuleLogic(vtkSlicerLogic*)
This is necessary so that the Loadable module code does not need to cast the Logic pointer returned from the defined entry point.
Optional
To add module-specific MRML events to observe, declare and implement:
virtual vtkIntArray* NewObservableEvents();
To add module-specific initialization code, declare and implement:
virtual void Init();
This is useful to have your module register callbacks for Picking (See QdecModule).
vtkModuleNameLogic
vtkModuleNameLogic.h/cxx
Optional
To add module-specific MRML events to observe, declare and implement:
virtual vtkIntArray* NewObservableEvents();
ModuleName.xml
ModuleName.xml
Create ModuleName.xml in the module's directory. ModuleName should follow the naming convention for the *GUI and *Logic classes.
For example, with two classes named vtkOpenIGTLinkLogic & vtkOpenIGTLinkGUI, create an XML file named OpenIGTLink.xml
This file contains naming directives, as well as lists dependencies. At a minimum, the module name & GUI name must be specified:
<Name>Open IGT Link</Name> <GUIName>OpenIGT</GUIName>
When creating a GUI-less module, omit the GUIName directive.
Optionally, other attributes may be listed:
<Description>This is a description of my module.</Description> <SourceLocation>https://use/the/source/luke</SourceLocation> <HomePage>http://my/module/homepage</HomePage> <Version>1.0</Version> <Dependency>Module One</Dependency> <Dependency>Module Two</Dependency> <Author>Karl Fardman</Author> <Acknowledgement>All the little people</Acknowledgement>
CMakeLists.txt
CMakeLists.txt
Most modules will be defined outside of the main Slicer3 build tree. To enable your module to be loaded dynamically, a couple entries in CMakeLists.txt are required.
Near the top of the file, include the directives that will locate the Slicer 3 build tree:
if(NOT Slicer3_SOURCE_DIR) find_package(Slicer3 REQUIRED) include(${Slicer3_USE_FILE}) slicer3_set_default_install_prefix_for_external_projects() endif(NOT Slicer3_SOURCE_DIR)
Next, tell CMake to generate the supporting files for Loadable Module:
generatelm(OpenIGTLink_SRCS OpenIGTLink.txt)
NOTE: The macro should be placed after TCL wrapping is done, as it adds to the source variable. For more details, check the NeuroNav module CMakeLists.txt file, as it provides a good starting point.
Finally, direct CMake to copy the binary files to the Slicer3 library location. This should be the last entry in your CMakeLists file:
install(TARGETS ${lib_name} RUNTIME DESTINATION ${Slicer3_INSTALL_MODULES_BIN_DIR} COMPONENT RuntimeLibraries LIBRARY DESTINATION ${Slicer3_INSTALL_MODULES_LIB_DIR} COMPONENT RuntimeLibraries ARCHIVE DESTINATION ${Slicer3_INSTALL_MODULES_LIB_DIR} COMPONENT Development )
Slicer3 Extension Description
In order to add the module to the extension server, a Slicer3 Extension file needs to be added to /Slicer3/Extensions:
scm svn svnpath https://www.nitrc.org/svn/slicer3examples/trunk/Slicer3ExampleModules/Loadable svnusername slicerbot svnpassword slicer depends homepage http://www.nitrc.org/projects/slicer3examples/ category Examples status Beta description An example of a loadable module using Slicer3 GUI and Logic classes, plus a MRML node.
Adding logo to your module
To add logo to a C++ loadable module, you can use KWConvertImageToHeader tool, which is compiled in Slicer3-lib/KWWidgets-build/bin to convert an image to C++ header file. Once you include this file, you can initialize the logo vtkKWIcon as follows:
// Logo setup. To prepare the header file with the logo information, use // KWConvertImageToHeader tool supplied with KWWidgets, with --zlib option. vtkKWIcon* logo = vtkKWIcon::New(); logo->SetImage(image_bsf_logo, image_bsf_logo_width, image_bsf_logo_height, image_bsf_logo_pixel_size, image_bsf_logo_length, 0); this->Logo = logo; logo->Delete();
Next, you can insert logo into the logo frame in the BuildGUI() method:
this->BuildHelpAndAboutFrame(module_page, help_text, ack_text); // Show the logo if (this->GetLogo()) { vtkKWLabel *logoLabel = vtkKWLabel::New(); logoLabel->SetParent( this->GetLogoFrame() ); logoLabel->Create(); logoLabel->SetImageToIcon( this->GetLogo() ); app->Script("pack %s", logoLabel->GetWidgetName() ); logoLabel->Delete(); }
Examples
Building and testing a loadable module locally
1) check out the example and make a build directory
svn checkout https://www.nitrc.org/svn/slicer3examples/trunk/Slicer3ExampleModules/Loadable mkdir Loadable-build cd Loadable-build/
2) run the version of cmake that you built with slicer (it's the latest version and may not be installed on your machine)
/csail/vision-polina2/pieper/slicer3/latest/Slicer3-lib/CMake-build/bin/ccmake ../Loadable
(in cmake, confirm that Slicer3_DIR points to your build of slicer's Slicer3-build directory. Press 'c' twice then 'g').
3) make the module
make
4) run your locally built version of slicer
/csail/vision-polina2/pieper/slicer3/latest/Slicer3-build/Slicer3
in the View->Application Settings->Module Settings add the path to the built loadable module (it will be something like /csail/vision-polina2/pieper/slicer3/latest/examples/Loadable-build/lib/Slicer3/Modules)
5) restart slicer and you should see "ExampleLM" in the modules menu.
From here you can edit/modify the example loadable module to make it do what you need to do.