Difference between revisions of "Slicer3:Loadable Modules:HOWTO"

From Slicer Wiki
Jump to: navigation, search
 
(16 intermediate revisions by 2 users not shown)
Line 8: Line 8:
  
 
== vtkModuleNameGUI ==
 
== vtkModuleNameGUI ==
 +
 +
vtkModuleNameGUI.h/cxx
 +
 +
'''Do not create this class if you want your module to be GUI-less'''
  
 
=== Required ===
 
=== Required ===
Line 30: Line 34:
  
 
== vtkModuleNameLogic ==
 
== vtkModuleNameLogic ==
 +
 +
vtkModuleNameLogic.h/cxx
  
 
=== Optional ===
 
=== Optional ===
Line 38: Line 44:
  
 
== ModuleName.xml ==
 
== ModuleName.xml ==
 +
 +
ModuleName.xml
  
 
Create ModuleName.xml in the module's directory.  ModuleName should follow the naming convention for the *GUI and *Logic classes.
 
Create ModuleName.xml in the module's directory.  ModuleName should follow the naming convention for the *GUI and *Logic classes.
  
For two clases named vtkOpenIGTLinkLogic & vtkOpenIGTLinkGUI, create an XML file, OpenIGTLink.xml
+
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 must be specified:
+
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>
 
   <Name>Open IGT Link</Name>
 +
  <GUIName>OpenIGT</GUIName>
  
Optionally, a GUI specific name and dependencies can be listed:
+
'''When creating a GUI-less module, omit the GUIName directive.'''
  
 +
Optionally, other attributes may be listed:
  
   <GUIName>OpenIGT</GUIName>
+
   <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 One</Dependency>
 
   <Dependency>Module Two</Dependency>
 
   <Dependency>Module Two</Dependency>
 +
  <Author>Karl Fardman</Author>
 +
  <Acknowledgement>All the little people</Acknowledgement>
  
 
== CMakeLists.txt ==
 
== 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.
 
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.
Line 80: Line 97:
 
     ARCHIVE DESTINATION ${Slicer3_INSTALL_MODULES_LIB_DIR} COMPONENT Development
 
     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:
 +
 +
<pre>
 +
  // 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();
 +
</pre>
 +
 +
Next, you can insert logo into the logo frame in the BuildGUI() method:
 +
 +
<pre>
 +
  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();
 +
  }
 +
</pre>
 +
 +
== Examples ==
 +
 +
[http://tinyurl.com/53jqbp Loadable Module]
 +
 +
[http://tinyurl.com/c6e7ab Loadable GUI-less Module]
 +
 +
 +
== 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.

Latest revision as of 21:25, 15 April 2010

Home < 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.

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

Loadable Module

Loadable GUI-less Module


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.