Преглед изворни кода

PythonQt module can be compiled either as python module or as static library

* A convenient macro named ctkMacroBuildLibWrapper has been added

* Decorators are not compiled anymore within the CTK library itself but
are included in a dedicated library named "<LIBNAME>PythonQt" that can
be either a static library or a python module.

* If any, the decorator associated with a library has to be named following
this pattern: "<LIBNAME>PythonQtDecorators.h"

* .. and a function named "init<LIBNAME>PythonQtDecorators()" in
charge of registering the decorator is expected.

* Instead of the function "PythonQt_init_<NAMESPACE>_<LIBNAME>(PyObject*)",
the function "init<LIBNAME>PythonQt" is now exposed.
Jean-Christophe Fillion-Robin пре 13 година
родитељ
комит
916309756d
35 измењених фајлова са 472 додато и 333 уклоњено
  1. 13 9
      Applications/ctkSimplePythonShell/CMakeLists.txt
  2. 2 2
      Applications/ctkSimplePythonShell/Python/ctkSimplePythonShell.py
  3. 16 7
      Applications/ctkSimplePythonShell/ctkSimplePythonManager.cpp.in
  4. 3 16
      Applications/ctkSimplePythonShell/ctkSimplePythonQtDecorators.h
  5. 1 0
      Applications/ctkSimplePythonShell/ctkSimplePythonShellConfigure.h.in
  6. 10 54
      CMake/ctkMacroBuildLib.cmake
  7. 147 0
      CMake/ctkMacroBuildLibWrapper.cmake
  8. 45 41
      CMake/ctkMacroWrapPythonQt.cmake
  9. 25 12
      CMake/ctkMacroWrapPythonQtModuleInit.cpp.in
  10. 9 8
      CMake/ctkScriptWrapPythonQt_Full.cmake
  11. 26 25
      CMake/ctkScriptWrapPythonQt_Light.cmake
  12. 9 8
      CMakeLists.txt
  13. 9 8
      CTKConfig.cmake.in
  14. 6 17
      Libs/Core/CMakeLists.txt
  15. 0 1
      Libs/Core/Testing/Cpp/CMakeLists.txt
  16. 1 1
      Libs/Core/ctkAbstractFactory.h
  17. 11 11
      Libs/Core/ctkCheckableModelHelper.h
  18. 15 12
      Libs/Core/ctkCorePythonQtDecorators.h
  19. 8 20
      Libs/DICOM/Core/CMakeLists.txt
  20. 6 3
      Libs/DICOM/Core/ctkDICOMCorePythonQtDecorators.h
  21. 7 18
      Libs/DICOM/Widgets/CMakeLists.txt
  22. 6 3
      Libs/DICOM/Widgets/ctkDICOMWidgetsPythonQtDecorators.h
  23. 7 1
      Libs/ImageProcessing/ITK/Core/CMakeLists.txt
  24. 7 1
      Libs/Messaging/Core/CMakeLists.txt
  25. 7 1
      Libs/ModuleDescription/CMakeLists.txt
  26. 7 1
      Libs/PluginFramework/CMakeLists.txt
  27. 1 2
      Libs/Scripting/Python/Core/CMakeLists.txt
  28. 21 21
      Libs/Scripting/Python/Core/Python/ctk/__init__.py.in
  29. 7 1
      Libs/Scripting/Python/Widgets/CMakeLists.txt
  30. 7 1
      Libs/Visualization/VTK/Core/CMakeLists.txt
  31. 8 2
      Libs/Visualization/VTK/Widgets/CMakeLists.txt
  32. 7 1
      Libs/Visualization/XIP/CMakeLists.txt
  33. 6 18
      Libs/Widgets/CMakeLists.txt
  34. 6 3
      Libs/Widgets/ctkWidgetsPythonQtDecorators.h
  35. 6 4
      Utilities/LastConfigureStep/CTKGenerateCTKConfig.cmake

+ 13 - 9
Applications/ctkSimplePythonShell/CMakeLists.txt

@@ -62,21 +62,25 @@ SET(VTK_LIBRARIES
 # The following macro will read the target libraries from the file 'target_libraries.cmake'
 ctkFunctionGetTargetLibraries(KIT_target_libraries)
 
-# Configure file will be configured using CTK_WRAP_PYTHONQT_{LIGHT, FULL} variable
+# Configure file will be configured using CTK_WRAP_PYTHONQT_{LIGHT, FULL} and
+# CTK_BUILD_SHARED_LIBS variables
 CONFIGURE_FILE(
   ctkSimplePythonShellConfigure.h.in
   ${CMAKE_CURRENT_BINARY_DIR}/ctkSimplePythonShellConfigure.h
   )
-  
-IF(CTK_WRAP_PYTHONQT_LIGHT OR CTK_WRAP_PYTHONQT_FULL)
+
+# The following block generate the code required to initialize the wrapper
+# when CTK is statically built.
+IF(NOT CTK_BUILD_SHARED_LIBS
+   AND (CTK_WRAP_PYTHONQT_LIGHT OR CTK_WRAP_PYTHONQT_FULL))
 
   # Update list of target libraries with the list of available PythonQt libraries
   # and set variables holding list of pythonqt initialization method
   SET(CTK_PYTHONQT_INITIALIZATION_METHOD_DEFINITION)
   SET(CTK_PYTHONQT_INITIALIZATION_METHOD_CALL)
-  
-  # To avoid the complex process of resolving the dependencies associated with each 
-  # external project required by each decorator. For now, let's just include the decorator 
+
+  # To avoid the complex process of resolving the dependencies associated with each
+  # external project required by each decorator. For now, let's just include the decorator
   # associated with CTKCore and CTKWidgets.
   SET(MY_CTK_WRAPPED_LIBRARIES_PYTHONQT)
   IF(CTK_LIB_Core)
@@ -91,18 +95,18 @@ IF(CTK_WRAP_PYTHONQT_LIGHT OR CTK_WRAP_PYTHONQT_FULL)
   IF(CTK_LIB_DICOM/Widgets)
     LIST(APPEND MY_CTK_WRAPPED_LIBRARIES_PYTHONQT CTKDICOMWidgets)
   ENDIF()
-  
+
   FOREACH(lib_name ${MY_CTK_WRAPPED_LIBRARIES_PYTHONQT})
 
     LIST(APPEND KIT_target_libraries ${lib_name}PythonQt)
 
     SET(CTK_PYTHONQT_INITIALIZATION_METHOD_DEFINITION
       "${CTK_PYTHONQT_INITIALIZATION_METHOD_DEFINITION}
-void PythonQt_init_org_commontk_${lib_name}(PyObject*);")
+extern \"C\"{ void init${lib_name}PythonQt(); }")
 
     SET(CTK_PYTHONQT_INITIALIZATION_METHOD_CALL
       "${CTK_PYTHONQT_INITIALIZATION_METHOD_CALL}
-PythonQt_init_org_commontk_${lib_name}(0);")
+init${lib_name}PythonQt();")
 
   ENDFOREACH()
 ENDIF()

+ 2 - 2
Applications/ctkSimplePythonShell/Python/ctkSimplePythonShell.py

@@ -2,9 +2,9 @@ import qt, ctk
 
 def app():
   return _ctkSimplePythonShellInstance
-  
+
 def quit():
   exit()
-    
+
 def exit():
   app().quit()

+ 16 - 7
Applications/ctkSimplePythonShell/ctkSimplePythonManager.cpp.in

@@ -11,11 +11,13 @@
 #include "ctkSimplePythonManager.h"
 #include "ctkSimplePythonQtDecorators.h"
 
-#include "ctkSimplePythonShellConfigure.h" // For CTK_WRAP_PYTHONQT_{LIGHT, FULL}
+#include "ctkSimplePythonShellConfigure.h" // For CTK_WRAP_PYTHONQT_{LIGHT, FULL} and CTK_BUILD_SHARED_LIBS
 
 #if defined(CTK_WRAP_PYTHONQT_LIGHT) || defined(CTK_WRAP_PYTHONQT_FULL)
-// PythonQt wrapper initialization methods
-@CTK_PYTHONQT_INITIALIZATION_METHOD_DEFINITION@
+# ifndef CTK_BUILD_SHARED_LIBS
+  // PythonQt wrapper initialization methods
+  @CTK_PYTHONQT_INITIALIZATION_METHOD_DEFINITION@
+# endif
 #endif
 
 #ifdef CTK_WRAP_PYTHONQT_USE_VTK
@@ -38,7 +40,7 @@ ctkSimplePythonManager::~ctkSimplePythonManager()
 
 //-----------------------------------------------------------------------------
 QStringList ctkSimplePythonManager::pythonPaths()
-{  
+{
   QStringList paths;
   paths << Superclass::pythonPaths();
 
@@ -51,6 +53,11 @@ QStringList ctkSimplePythonManager::pythonPaths()
   ctk_python_dir.append("/Python");
   paths << QFileInfo(ctk_python_dir).absoluteFilePath();
 
+#ifdef CTK_BUILD_SHARED_LIBS
+  // Path containing python module
+  paths << self_dir;
+#endif
+
 #ifdef CTK_WRAP_PYTHONQT_USE_VTK
 
   // Try to put the VTK python module location in sys.path.
@@ -79,7 +86,7 @@ QStringList ctkSimplePythonManager::pythonPaths()
     // TODO Handle case when the application is started from an installed tree
     }
 #endif
-  
+
   return paths;
 }
 
@@ -89,13 +96,15 @@ void ctkSimplePythonManager::preInitialization()
   Superclass::preInitialization();
 
 #if defined(CTK_WRAP_PYTHONQT_LIGHT) || defined(CTK_WRAP_PYTHONQT_FULL)
+# ifndef CTK_BUILD_SHARED_LIBS
   // Initialize wrappers
   @CTK_PYTHONQT_INITIALIZATION_METHOD_CALL@
+# endif
 #endif
 
   // Register decorators
-  this->registerPythonQtDecorator(new ctkSimplePythonQtDecorators(this));  
-  
+  this->registerPythonQtDecorator(new ctkSimplePythonQtDecorators(this));
+
   // Add object to python interpreter context
   this->addObjectToPythonMain("_ctkSimplePythonShellInstance", qApp);
 }

+ 3 - 16
Applications/ctkSimplePythonShell/ctkSimplePythonQtDecorators.h

@@ -21,17 +21,12 @@
 #ifndef __ctkSimplePythonQtDecorators_h
 #define __ctkSimplePythonQtDecorators_h
 
-// CTK includes
-#include "ctkSimplePythonShellConfigure.h" // For CTK_WRAP_PYTHONQT_LIGHT
-#include <ctkAbstractPythonManager.h>
-#ifdef CTK_WRAP_PYTHONQT_LIGHT
-# include <ctkCorePythonQtDecorators.h>
-# include <ctkWidgetsPythonQtDecorators.h>
-#endif
-
 // PythonQt includes
 #include <PythonQt.h>
 
+// CTK includes
+#include <ctkAbstractPythonManager.h>
+
 // NOTE:
 //
 // For decorators it is assumed that the methods will never be called
@@ -47,19 +42,11 @@ public:
 
   ctkSimplePythonQtDecorators(ctkAbstractPythonManager* pythonManager)
     {
-    Q_ASSERT(pythonManager);
-#ifdef CTK_WRAP_PYTHONQT_LIGHT
-    pythonManager->registerPythonQtDecorator(new ctkCorePythonQtDecorators);
-    pythonManager->registerPythonQtDecorator(new ctkWidgetsPythonQtDecorators);
-#else
     Q_UNUSED(pythonManager);
-#endif
     }
 
 public slots:
 
-  
-  
 };
 
 #endif

+ 1 - 0
Applications/ctkSimplePythonShell/ctkSimplePythonShellConfigure.h.in

@@ -6,6 +6,7 @@
 /// Here is where system computed values get stored
 ///
 
+#cmakedefine CTK_BUILD_SHARED_LIBS
 #cmakedefine CTK_WRAP_PYTHONQT_LIGHT
 #cmakedefine CTK_WRAP_PYTHONQT_FULL
 

+ 10 - 54
CMake/ctkMacroBuildLib.cmake

@@ -27,7 +27,7 @@
 MACRO(ctkMacroBuildLib)
   ctkMacroParseArguments(MY
     "NAME;EXPORT_DIRECTIVE;SRCS;MOC_SRCS;UI_FORMS;INCLUDE_DIRECTORIES;TARGET_LIBRARIES;RESOURCES;LIBRARY_TYPE"
-    "DISABLE_WRAP_PYTHONQT"
+    ""
     ${ARGN}
     )
 
@@ -57,7 +57,7 @@ MACRO(ctkMacroBuildLib)
     # with CMake >2.9, use QT4_MAKE_OUTPUT_FILE instead ?
     ${CMAKE_CURRENT_BINARY_DIR}/Resources/UI
     ${MY_INCLUDE_DIRECTORIES}
-    )  
+    )
 
   # Add the include directories from the library dependencies
   ctkFunctionGetIncludeDirs(my_includes ${lib_name})
@@ -65,20 +65,19 @@ MACRO(ctkMacroBuildLib)
   INCLUDE_DIRECTORIES(
     ${my_includes}
     )
-    
+
   # Add the library directories from the external project
   ctkFunctionGetLibraryDirs(my_library_dirs ${lib_name})
-  
+
   LINK_DIRECTORIES(
     ${my_library_dirs}
     )
 
-
   SET(MY_LIBRARY_EXPORT_DIRECTIVE ${MY_EXPORT_DIRECTIVE})
   SET(MY_EXPORT_HEADER_PREFIX ${MY_NAME})
   STRING(REGEX REPLACE "^CTK" "ctk" MY_EXPORT_HEADER_PREFIX ${MY_EXPORT_HEADER_PREFIX})
   SET(MY_LIBNAME ${lib_name})
-  
+
   CONFIGURE_FILE(
     ${CTK_SOURCE_DIR}/Libs/ctkExport.h.in
     ${CMAKE_CURRENT_BINARY_DIR}/${MY_EXPORT_HEADER_PREFIX}Export.h
@@ -113,32 +112,9 @@ MACRO(ctkMacroBuildLib)
     ${MY_QRC_SRCS}
     ${MY_MOC_CPP}
     ${MY_UI_CPP}
+    ${MOC_CPP_DECORATOR}
     )
 
-  # Since the PythonQt decorator depends on PythonQt, Python and VTK, let's link against
-  # these ones to avoid complaints of MSVC
-  # Note: "LINK_DIRECTORIES" has to be invoked before "ADD_LIBRARY"
-  SET(my_EXTRA_PYTHON_LIBRARIES)
-  IF(CTK_WRAP_PYTHONQT_LIGHT AND NOT ${MY_DISABLE_WRAP_PYTHONQT})
-    # Does a header having the expected filename exists ?
-    STRING(REGEX REPLACE "^CTK" "ctk" lib_name_lc_ctk ${lib_name})
-    SET(decorator_header_filename ${lib_name_lc_ctk}PythonQtDecorators.h)
-    IF(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${decorator_header_filename})
-      LIST(APPEND my_EXTRA_PYTHON_LIBRARIES ${PYTHON_LIBRARY} ${PYTHONQT_LIBRARIES})
-      # Should we link against VTK
-      IF(CTK_LIB_Scripting/Python/Core_PYTHONQT_USE_VTK)
-        LIST(APPEND my_EXTRA_PYTHON_LIBRARIES vtkCommon vtkPythonCore)
-      ENDIF()
-    ENDIF()
-  ENDIF()
-
-  # The current library might not be wrapped. Nevertheless, if one of its dependent library
-  # is linked using vtkCommon or vtkPythonCore, VTK_LIBRARY_DIRS should be added
-  # as a link directories.
-  IF(CTK_WRAP_PYTHONQT_LIGHT AND CTK_LIB_Scripting/Python/Core_PYTHONQT_USE_VTK)
-    LINK_DIRECTORIES(${VTK_LIBRARY_DIRS})
-  ENDIF()
-  
   ADD_LIBRARY(${lib_name} ${MY_LIBRARY_TYPE}
     ${MY_SRCS}
     ${MY_MOC_CPP}
@@ -154,7 +130,7 @@ MACRO(ctkMacroBuildLib)
     SET_TARGET_PROPERTIES(${lib_name} PROPERTIES ${CTK_LIBRARY_PROPERTIES})
   ENDIF()
   SET_TARGET_PROPERTIES(${lib_name} PROPERTIES CTK_LIB_TARGET_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
-  
+
   # Library properties specific to STATIC build
   IF(MY_LIBRARY_TYPE STREQUAL "STATIC")
     IF(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64")
@@ -169,7 +145,7 @@ MACRO(ctkMacroBuildLib)
       LIBRARY DESTINATION ${CTK_INSTALL_LIB_DIR} COMPONENT Runtime
       ARCHIVE DESTINATION ${CTK_INSTALL_LIB_DIR} COMPONENT Development)
   ENDIF()
-  
+
   SET(my_libs
     ${MY_TARGET_LIBRARIES}
     )
@@ -177,15 +153,13 @@ MACRO(ctkMacroBuildLib)
   IF(MINGW)
     LIST(APPEND my_libs ssp) # add stack smash protection lib
   ENDIF(MINGW)
-
-  # See above for definition of my_EXTRA_PYTHON_LIBRARIES
-  TARGET_LINK_LIBRARIES(${lib_name} ${my_libs} ${my_EXTRA_PYTHON_LIBRARIES})
+  TARGET_LINK_LIBRARIES(${lib_name} ${my_libs})
 
   # Update CTK_BASE_LIBRARIES
   SET(CTK_BASE_LIBRARIES ${my_libs} ${lib_name} CACHE INTERNAL "CTK base libraries" FORCE)
   SET(CTK_LIBRARIES ${CTK_LIBRARIES} ${lib_name} CACHE INTERNAL "CTK libraries" FORCE)
   SET(CTK_BASE_INCLUDE_DIRS ${CTK_BASE_INCLUDE_DIRS} ${my_includes} CACHE INTERNAL "CTK includes" FORCE)
-  
+
   # Install headers
   FILE(GLOB headers "${CMAKE_CURRENT_SOURCE_DIR}/*.h")
   INSTALL(FILES
@@ -194,24 +168,6 @@ MACRO(ctkMacroBuildLib)
     DESTINATION ${CTK_INSTALL_INCLUDE_DIR} COMPONENT Development
     )
 
-  IF((CTK_WRAP_PYTHONQT_LIGHT OR CTK_WRAP_PYTHONQT_FULL) AND NOT ${MY_DISABLE_WRAP_PYTHONQT})
-    set(KIT_PYTHONQT_SRCS) # Clear variable
-    ctkMacroWrapPythonQt("org.commontk" ${lib_name}
-      KIT_PYTHONQT_SRCS "${MY_SRCS}" ${CTK_WRAP_PYTHONQT_FULL})
-    ADD_LIBRARY(${lib_name}PythonQt STATIC ${KIT_PYTHONQT_SRCS})
-    TARGET_LINK_LIBRARIES(${lib_name}PythonQt ${lib_name})
-    IF(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64")
-      SET_TARGET_PROPERTIES(${lib_name}PythonQt PROPERTIES COMPILE_FLAGS "-fPIC")
-    ENDIF()
-    # Set labels associated with the target.
-    SET_TARGET_PROPERTIES(${lib_name}PythonQt PROPERTIES LABELS ${lib_name})
-
-    # Update list of libraries wrapped with PythonQt
-    SET(CTK_WRAPPED_LIBRARIES_PYTHONQT
-      ${CTK_WRAPPED_LIBRARIES_PYTHONQT} ${lib_name}
-      CACHE INTERNAL "CTK libraries wrapped using PythonQt" FORCE)
-  ENDIF()
-
 ENDMACRO()
 
 

+ 147 - 0
CMake/ctkMacroBuildLibWrapper.cmake

@@ -0,0 +1,147 @@
+###########################################################################
+#
+#  Library:   CTK
+#
+#  Copyright (c) Kitware Inc.
+#
+#  Licensed under the Apache License, Version 2.0 (the "License");
+#  you may not use this file except in compliance with the License.
+#  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0.txt
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+#
+###########################################################################
+
+#
+# Depends on:
+#  CTK/CMake/ctkMacroParseArguments.cmake
+#
+
+
+#! When CTK is built as shared library, the following macro builds a python module
+#! associated the PythonQt wrapper. When loaded, this python module will
+#! dynamically loads both the (1) generated decorators and the (2) hand written one.
+#! On the other hand, when CTK is built statically, it creates a
+#! static library providing a initialization function that will allow to load
+#! both (1) and (2).
+  
+#! \ingroup CMakeAPI
+MACRO(ctkMacroBuildLibWrapper)
+  ctkMacroParseArguments(MY
+    "NAMESPACE;TARGET;SRCS;WRAPPER_LIBRARY_TYPE;ARCHIVE_OUTPUT_DIRECTORY;LIBRARY_OUTPUT_DIRECTORY;RUNTIME_OUTPUT_DIRECTORYINSTALL_BIN_DIR;INSTALL_LIB_DIR"
+    "NO_INSTALL"
+    ${ARGN}
+    )
+
+  # Sanity checks
+  IF(NOT DEFINED MY_TARGET)
+    MESSAGE(FATAL_ERROR "NAME is mandatory")
+  ENDIF()
+  IF(NOT DEFINED MY_WRAPPER_LIBRARY_TYPE OR "${MY_WRAPPER_LIBRARY_TYPE}" STREQUAL "SHARED")
+    SET(MY_WRAPPER_LIBRARY_TYPE "MODULE")
+  ENDIF()
+
+  IF(NOT DEFINED MY_NAMESPACE)
+    SET(MY_NAMESPACE "org.commontk")
+  ENDIF()
+  IF(NOT DEFINED CTK_WRAP_PYTHONQT_FULL)
+    SET(CTK_WRAP_PYTHONQT_FULL FALSE)
+  ENDIF()
+  FOREACH(type RUNTIME LIBRARY ARCHIVE)
+    IF(NOT DEFINED MY_${type}_OUTPUT_DIRECTORY)
+      SET(MY_${type}_OUTPUT_DIRECTORY ${CMAKE_${type}_OUTPUT_DIRECTORY})
+    ENDIF()
+  ENDFOREACH()
+  IF(NOT DEFINED MY_INSTALL_BIN_DIR)
+    SET(MY_INSTALL_BIN_DIR ${CTK_INSTALL_BIN_DIR})
+  ENDIF()
+  IF(NOT DEFINED MY_INSTALL_LIB_DIR)
+    SET(MY_INSTALL_LIB_DIR ${CTK_INSTALL_LIB_DIR})
+  ENDIF()
+
+  # Define library name
+  SET(lib_name ${MY_TARGET})
+
+  # Include dirs
+  SET(my_includes
+    ${CMAKE_CURRENT_SOURCE_DIR}
+    ${CMAKE_CURRENT_BINARY_DIR}
+    )
+
+  # Since the PythonQt decorator depends on PythonQt, Python and VTK, let's link against
+  # these ones to avoid complaints of MSVC
+  # Note: "LINK_DIRECTORIES" has to be invoked before "ADD_LIBRARY"
+  SET(my_EXTRA_PYTHON_LIBRARIES ${PYTHON_LIBRARY} ${PYTHONQT_LIBRARIES})
+  # Should we link against VTK
+  #IF(CTK_LIB_Scripting/Python/Core_PYTHONQT_USE_VTK)
+  #  LIST(APPEND my_EXTRA_PYTHON_LIBRARIES vtkCommon vtkPythonCore)
+  #ENDIF()
+
+  # The current library might not be wrapped. Nevertheless, if one of its dependent library
+  # is linked using vtkCommon or vtkPythonCore, VTK_LIBRARY_DIRS should be added
+  # as a link directories.
+  #IF(NOT CTK_BUILD_SHARED_LIBS
+  #   AND CTK_LIB_Scripting/Python/Core_PYTHONQT_USE_VTK)
+  #  LINK_DIRECTORIES(${VTK_LIBRARY_DIRS})
+  #ENDIF()
+
+  # Does a header having the expected filename exists ?
+  STRING(REGEX REPLACE "^CTK" "ctk" lib_name_lc_ctk ${lib_name})
+  SET(DECORATOR_HEADER ${lib_name_lc_ctk}PythonQtDecorators.h)
+  SET(HAS_DECORATOR FALSE)
+  IF(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${DECORATOR_HEADER})
+    SET(HAS_DECORATOR TRUE)
+    SET(DECORATOR_HEADER ${DECORATOR_HEADER})
+    SET_SOURCE_FILES_PROPERTIES(${DECORATOR_HEADER} WRAP_EXCLUDE)
+  ENDIF()
+  #message("HAS_DECORATOR:${HAS_DECORATOR}")
+  #message("path/to/DECORATOR_HEADER:${CMAKE_CURRENT_SOURCE_DIR}/${DECORATOR_HEADER}")
+
+  SET(KIT_PYTHONQT_SRCS) # Clear variable
+  ctkMacroWrapPythonQt(${MY_NAMESPACE} ${lib_name}
+    KIT_PYTHONQT_SRCS "${MY_SRCS}" ${CTK_WRAP_PYTHONQT_FULL} ${HAS_DECORATOR})
+  IF(HAS_DECORATOR)
+    LIST(APPEND KIT_PYTHONQT_SRCS ${DECORATOR_HEADER})
+    QT4_WRAP_CPP(KIT_PYTHONQT_SRCS ${DECORATOR_HEADER} OPTIONS -f${DECORATOR_HEADER})
+  ENDIF()
+  ADD_LIBRARY(${lib_name}PythonQt ${MY_WRAPPER_LIBRARY_TYPE} ${KIT_PYTHONQT_SRCS})
+  TARGET_LINK_LIBRARIES(${lib_name}PythonQt ${lib_name} ${my_EXTRA_PYTHON_LIBRARIES})
+  IF(MY_WRAPPER_LIBRARY_TYPE STREQUAL "STATIC")
+    IF(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64")
+      SET_TARGET_PROPERTIES(${lib_name}PythonQt PROPERTIES COMPILE_FLAGS "-fPIC")
+    ENDIF()
+  ENDIF()
+  IF(MY_WRAPPER_LIBRARY_TYPE STREQUAL "MODULE")
+    # Make sure that no prefix is set on the library
+    set_target_properties(${lib_name}PythonQt PROPERTIES PREFIX "")
+  ENDIF()
+  set_target_properties(${lib_name}PythonQt PROPERTIES
+    RUNTIME_OUTPUT_DIRECTORY "${MY_RUNTIME_OUTPUT_DIRECTORY}"
+    LIBRARY_OUTPUT_DIRECTORY "${MY_LIBRARY_OUTPUT_DIRECTORY}"
+    ARCHIVE_OUTPUT_DIRECTORY "${MY_ARCHIVE_OUTPUT_DIRECTORY}"
+    )
+
+  # Set labels associated with the target.
+  SET_TARGET_PROPERTIES(${lib_name}PythonQt PROPERTIES LABELS ${lib_name})
+
+  # Update list of libraries wrapped with PythonQt
+  SET(CTK_WRAPPED_LIBRARIES_PYTHONQT
+    ${CTK_WRAPPED_LIBRARIES_PYTHONQT} ${lib_name}
+    CACHE INTERNAL "CTK libraries wrapped using PythonQt" FORCE)
+
+  # Install rules
+  IF(NOT MY_NO_INSTALL AND MY_WRAPPER_LIBRARY_TYPE STREQUAL "MODULE")
+    INSTALL(TARGETS ${lib_name}
+      RUNTIME DESTINATION ${MY_INSTALL_BIN_DIR} COMPONENT Runtime
+      LIBRARY DESTINATION ${MY_INSTALL_LIB_DIR} COMPONENT Runtime
+      ARCHIVE DESTINATION ${MY_INSTALL_LIB_DIR} COMPONENT Development)
+  ENDIF()
+
+ENDMACRO()
+

+ 45 - 41
CMake/ctkMacroWrapPythonQt.cmake

@@ -43,6 +43,8 @@
 #!
 #!    IS_WRAP_FULL .....: Indicate if a Full wrapping if desired.
 #!
+#!    HAS_DECORATOR ....: Indicate if a custom PythonQt decorator header is expected.
+#!
 
 #!
 #! LOG FILE:
@@ -89,7 +91,7 @@ else: print 'TRUE'
     ERROR_VARIABLE error
     OUTPUT_STRIP_TRAILING_WHITESPACE
     )
-  
+
   IF(result)
     MESSAGE(FATAL_ERROR "reSearchFile - Problem with regex: ${regex}\n${error}")
   ENDIF()
@@ -97,13 +99,13 @@ else: print 'TRUE'
 ENDFUNCTION()
 
 #! \ingroup CMakeUtilities
-MACRO(ctkMacroWrapPythonQt WRAPPING_NAMESPACE TARGET SRCS_LIST_NAME SOURCES IS_WRAP_FULL)
-  
+MACRO(ctkMacroWrapPythonQt WRAPPING_NAMESPACE TARGET SRCS_LIST_NAME SOURCES IS_WRAP_FULL HAS_DECORATOR)
+
   # Sanity check
   IF(IS_WRAP_FULL AND NOT EXISTS "${PYTHONQTGENERATOR_EXECUTABLE}")
     MESSAGE(FATAL_ERROR "PYTHONQTGENERATOR_EXECUTABLE not specified or inexistent when calling ctkMacroWrapPythonQt")
   ENDIF()
-  
+
   # TODO: this find package seems not to work when called form a superbuild, but the call is needed
   # in general to find the python interpreter.  In CTK, the toplevel CMakeLists.txt does the find
   # package so this is a no-op.  Other uses of this file may need to have this call so it is still enabled.
@@ -118,19 +120,19 @@ MACRO(ctkMacroWrapPythonQt WRAPPING_NAMESPACE TARGET SRCS_LIST_NAME SOURCES IS_W
   IF(WIN32)
     set(PYTHON_LIBRARY_PATH ${PYTHON_DIR_PATH})
   ENDIF(WIN32)
-  
+
   # Clear log file
   FILE(WRITE "${CMAKE_CURRENT_BINARY_DIR}/ctkMacroWrapPythonQt_log.txt" "")
-  
+
   # Convert wrapping namespace to subdir
   STRING(REPLACE "." "_" WRAPPING_NAMESPACE_UNDERSCORE ${WRAPPING_NAMESPACE})
-  
+
   SET(SOURCES_TO_WRAP)
   # For each class
   FOREACH(FILE ${SOURCES})
-  
+
     SET(skip_wrapping FALSE)
-    
+
     IF(NOT skip_wrapping)
       # Skip wrapping if file is NOT regular header
       IF(NOT ${FILE} MATCHES "^.*\\.[hH]$")
@@ -138,7 +140,7 @@ MACRO(ctkMacroWrapPythonQt WRAPPING_NAMESPACE TARGET SRCS_LIST_NAME SOURCES IS_W
         ctkMacroWrapPythonQt_log("${FILE}: skipping - Not a regular header")
       ENDIF()
     ENDIF()
-    
+
     IF(NOT skip_wrapping)
       # Skip wrapping if file is a pimpl header
       IF(${FILE} MATCHES "^.*_[pP]\\.[hH]$")
@@ -146,7 +148,7 @@ MACRO(ctkMacroWrapPythonQt WRAPPING_NAMESPACE TARGET SRCS_LIST_NAME SOURCES IS_W
         ctkMacroWrapPythonQt_log("${FILE}: skipping - Pimpl header (*._p.h)")
       ENDIF()
     ENDIF()
-    
+
     IF(NOT skip_wrapping)
       # Skip wrapping if file should excluded
       SET(skip_wrapping TRUE)
@@ -158,13 +160,13 @@ MACRO(ctkMacroWrapPythonQt WRAPPING_NAMESPACE TARGET SRCS_LIST_NAME SOURCES IS_W
         ctkMacroWrapPythonQt_log("${FILE}: skipping - WRAP_EXCLUDE")
       ENDIF()
     ENDIF()
-    
+
     # what is the filename without the extension
     GET_FILENAME_COMPONENT(TMP_FILENAME ${FILE} NAME_WE)
-    
+
     # Extract classname - NOTE: We assume the filename matches the associated class
     SET(className ${TMP_FILENAME})
-    
+
     IF(NOT skip_wrapping)
       # Skip wrapping if IS_WRAP_FULL=FALSE and if file do NOT contain Q_OBJECT
       IF(NOT IS_WRAP_FULL)
@@ -175,7 +177,7 @@ MACRO(ctkMacroWrapPythonQt WRAPPING_NAMESPACE TARGET SRCS_LIST_NAME SOURCES IS_W
         ENDIF()
       ENDIF()
     ENDIF()
-    
+
     IF(NOT skip_wrapping)
       # Skip wrapping if IS_WRAP_FULL=FALSE and if constructor doesn't match:
       #    my_class()
@@ -192,9 +194,9 @@ MACRO(ctkMacroWrapPythonQt WRAPPING_NAMESPACE TARGET SRCS_LIST_NAME SOURCES IS_W
         ENDIF()
       ENDIF()
     ENDIF()
-    
+
     IF(NOT skip_wrapping)
-      # Skip wrapping if object has a virtual pure method 
+      # Skip wrapping if object has a virtual pure method
       # "x3b" is the unicode for semicolon
       SET(regex "virtual[\\w\\n\\s\\*\\(\\)]+\\=[\\s\\n]*(0|NULL)[\\s\\n]*\\x3b")
       ctkMacroWrapPythonQt_reSearchFile(${PYTHON_EXECUTABLE} ${PYTHON_LIBRARY_PATH}
@@ -204,37 +206,37 @@ MACRO(ctkMacroWrapPythonQt WRAPPING_NAMESPACE TARGET SRCS_LIST_NAME SOURCES IS_W
         ctkMacroWrapPythonQt_log("${FILE}: skipping - Contains a virtual pure method")
       ENDIF()
     ENDIF()
-    
+
     # if we should wrap it
     IF (NOT skip_wrapping)
-      
+
       # the input file might be full path so handle that
       GET_FILENAME_COMPONENT(TMP_FILEPATH ${FILE} PATH)
-      
+
       # compute the input filename
       IF (TMP_FILEPATH)
-        SET(TMP_INPUT ${TMP_FILEPATH}/${TMP_FILENAME}.h) 
+        SET(TMP_INPUT ${TMP_FILEPATH}/${TMP_FILENAME}.h)
       ELSE (TMP_FILEPATH)
         SET(TMP_INPUT ${CMAKE_CURRENT_SOURCE_DIR}/${TMP_FILENAME}.h)
       ENDIF (TMP_FILEPATH)
-        
+
       LIST(APPEND SOURCES_TO_WRAP ${TMP_INPUT})
-        
+
     ENDIF()
   ENDFOREACH()
-  
+
   # PythonQtGenerator expects a colon ':' separated list
   SET(INCLUDE_DIRS_TO_WRAP)
   FOREACH(include ${CTK_BASE_INCLUDE_DIRS})
     SET(INCLUDE_DIRS_TO_WRAP "${INCLUDE_DIRS_TO_WRAP}:${include}")
   ENDFOREACH()
-  
+
   # Prepare custom_command argument
   SET(SOURCES_TO_WRAP_ARG)
   FOREACH(source ${SOURCES_TO_WRAP})
     SET(SOURCES_TO_WRAP_ARG "${SOURCES_TO_WRAP_ARG}^^${source}")
   ENDFOREACH()
-  
+
   # Define wrap type and wrap intermediate directory
   SET(wrap_type "Light")
   SET(wrap_int_dir generated_cpp/${WRAPPING_NAMESPACE_UNDERSCORE}_${TARGET}/)
@@ -244,10 +246,10 @@ MACRO(ctkMacroWrapPythonQt WRAPPING_NAMESPACE TARGET SRCS_LIST_NAME SOURCES IS_W
     SET(extra_files ${wrap_int_dir}ctkPythonQt_${TARGET}_masterinclude.h)
   ENDIF()
   #message("wrap_type:${wrap_type} - wrap_int_dir:${wrap_int_dir}")
-  
+
   # Create intermediate output directory
   EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/${wrap_int_dir})
-  
+
   # On Windows, to avoid "too long input" error, dump INCLUDE_DIRS_TO_WRAP into a file
   IF(WIN32)
     # File containing the moc flags
@@ -257,14 +259,14 @@ MACRO(ctkMacroWrapPythonQt WRAPPING_NAMESPACE TARGET SRCS_LIST_NAME SOURCES IS_W
     # The arg passed to the custom command will be the file containing the list of include dirs to wrap
     SET(INCLUDE_DIRS_TO_WRAP ${include_dirs_to_wrap_file})
   ENDIF()
-  
+
   set(wrapper_init_cpp_filename ${WRAPPING_NAMESPACE_UNDERSCORE}_${TARGET}_init.cpp)
   set(wrapper_init_cpp_file ${CMAKE_CURRENT_BINARY_DIR}/${wrap_int_dir}${wrapper_init_cpp_filename})
 
   set(wrapper_module_init_cpp_filename ${WRAPPING_NAMESPACE_UNDERSCORE}_${TARGET}_module_init.cpp)
   set(wrapper_module_init_cpp_file ${CMAKE_CURRENT_BINARY_DIR}/${wrap_int_dir}${wrapper_module_init_cpp_filename})
 
-  # Custom command allow to generate ${WRAPPING_NAMESPACE_UNDERSCORE}_${TARGET}_init.cpp and 
+  # Custom command allow to generate ${WRAPPING_NAMESPACE_UNDERSCORE}_${TARGET}_init.cpp and
   # associated wrappers ${WRAPPING_NAMESPACE_UNDERSCORE}_${TARGET}{0-N}.cpp
   ADD_CUSTOM_COMMAND(
     OUTPUT
@@ -287,17 +289,18 @@ MACRO(ctkMacroWrapPythonQt WRAPPING_NAMESPACE TARGET SRCS_LIST_NAME SOURCES IS_W
       -DOUTPUT_DIR:PATH=${CMAKE_CURRENT_BINARY_DIR}
       -DWRAP_INT_DIR:STRING=${wrap_int_dir}
       -DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}
+      -DHAS_DECORATOR:BOOL=${HAS_DECORATOR}
       -P ${CTK_CMAKE_DIR}/ctkScriptWrapPythonQt_${wrap_type}.cmake
     COMMENT "PythonQt ${wrap_type} Wrapping - Generating ${wrapper_init_cpp_filename}"
     VERBATIM
     )
-  
+
   # Clear variable
   SET(moc_flags)
-  
+
   # Grab moc flags
   QT4_GET_MOC_FLAGS(moc_flags)
-  
+
   # Prepare custom_command argument
   SET(moc_flags_arg)
   FOREACH(flag ${moc_flags})
@@ -313,11 +316,11 @@ MACRO(ctkMacroWrapPythonQt WRAPPING_NAMESPACE TARGET SRCS_LIST_NAME SOURCES IS_W
     # The arg passed to the custom command will be the file containing the list of moc flags
     SET(moc_flags_arg ${wrapper_master_moc_flags_file})
   ENDIF()
-  
+
   # File to run through moc
   SET(wrapper_master_moc_filename moc_${WRAPPING_NAMESPACE_UNDERSCORE}_${TARGET}_all.cpp)
   SET(wrapper_master_moc_file ${CMAKE_CURRENT_BINARY_DIR}/${wrap_int_dir}${wrapper_master_moc_filename})
-  
+
   # Custom command allowing to call moc to process the wrapper headers
   ADD_CUSTOM_COMMAND(
     OUTPUT ${wrap_int_dir}${wrapper_master_moc_filename}
@@ -337,21 +340,22 @@ MACRO(ctkMacroWrapPythonQt WRAPPING_NAMESPACE TARGET SRCS_LIST_NAME SOURCES IS_W
     COMMENT "PythonQt ${wrap_type} Wrapping - Moc'ing ${WRAPPING_NAMESPACE_UNDERSCORE}_${TARGET} wrapper headers"
     VERBATIM
     )
-  
-  #The following files are generated
+
+  # The following files are generated
   SET_SOURCE_FILES_PROPERTIES(
     ${wrap_int_dir}${wrapper_init_cpp_filename}
     ${wrap_int_dir}${wrapper_module_init_cpp_filename}
     ${wrap_int_dir}${wrapper_master_moc_filename}
     PROPERTIES GENERATED TRUE)
-    
+
   # Create the Init File
-  SET(${SRCS_LIST_NAME} 
+  SET(${SRCS_LIST_NAME}
     ${${SRCS_LIST_NAME}}
     ${wrap_int_dir}${wrapper_init_cpp_filename}
     ${wrap_int_dir}${wrapper_module_init_cpp_filename}
-    ${wrap_int_dir}${wrapper_master_moc_filename})
-  
+    ${wrap_int_dir}${wrapper_master_moc_filename}
+    )
+
   #
   # Let's include the headers associated with PythonQt
   #

+ 25 - 12
CMake/ctkMacroWrapPythonQtModuleInit.cpp.in

@@ -3,6 +3,13 @@
 #include <PythonQt.h>
 #include <Python.h>
 
+//-----------------------------------------------------------------------------
+static PyMethodDef Py@TARGET@PythonQt_ClassMethods[] = {
+{NULL, NULL, 0, NULL}};
+
+//-----------------------------------------------------------------------------
+extern "C" { void Q_DECL_EXPORT init@TARGET@PythonQt(); }
+
 #ifdef __GNUC__
 // Disable warnings related to Py_DECREF() macro
 // See http://gcc.gnu.org/onlinedocs/gcc/Diagnostic-Pragmas.html
@@ -10,12 +17,9 @@
 #pragma GCC diagnostic ignored "-Wold-style-cast"
 #endif
 
-//-----------------------------------------------------------------------------
-static PyMethodDef Py@TARGET@PythonQt_ClassMethods[] = {
-{NULL, NULL, 0, NULL}};
-
-extern  "C" { void init@TARGET@PythonQt(); }
+#cmakedefine HAS_DECORATOR
 
+namespace {
 //-----------------------------------------------------------------------------
 void copyAttributes(PyObject* orig_module, PyObject* dest_module)
 {
@@ -43,21 +47,30 @@ void copyAttributes(PyObject* orig_module, PyObject* dest_module)
     Py_DECREF(keys);
     }
 }
-
-//-----------------------------------------------------------------------------
-extern  "C" {void PythonQt_init_@WRAPPING_NAMESPACE_UNDERSCORE@_@TARGET@(PyObject*); }
+} // end of anonymous namespace
 
 //-----------------------------------------------------------------------------
 void init@TARGET@PythonQt()
 {
-  static const char @TARGET@[] = "@TARGET@PythonQt";
+  static const char modulename[] = "@TARGET@PythonQt";
   PyObject *m;
 
-  m = Py_InitModule((char*)@TARGET@, Py@TARGET@PythonQt_ClassMethods);
+  m = Py_InitModule((char*)modulename, Py@TARGET@PythonQt_ClassMethods);
+  extern void PythonQt_init_@WRAPPING_NAMESPACE_UNDERSCORE@_@TARGET@(PyObject*);
   PythonQt_init_@WRAPPING_NAMESPACE_UNDERSCORE@_@TARGET@(m);
-  
-  // Since invoking 'PythonQt_init_@WRAPPING_NAMESPACE_UNDERSCORE@_@TARGET@', will create 
+
+#ifdef HAS_DECORATOR
+  extern void init@TARGET@PythonQtDecorators();
+  init@TARGET@PythonQtDecorators();
+#endif
+
+  // Since invoking 'PythonQt_init_@WRAPPING_NAMESPACE_UNDERSCORE@_@TARGET@', will create
   // the module "PythonQt.@TARGET@". Let's copy its content into the current module.
   PythonQtObjectPtr currentModule = PyImport_ImportModule((char*)"PythonQt.@TARGET@");
+  if(currentModule.isNull())
+    {
+    PyErr_SetString(PyExc_ImportError, (char*)"Failed to import PythonQt.@TARGET@");
+    return;
+    }
   copyAttributes(currentModule, m);
 }

+ 9 - 8
CMake/ctkScriptWrapPythonQt_Full.cmake

@@ -28,14 +28,15 @@
 #
 
 #
-# This script should be invoked either as a CUSTOM_COMMAND 
+# This script should be invoked either as a CUSTOM_COMMAND
 # or from the command line using the following syntax:
 #
-#    cmake -DWRAPPING_NAMESPACE:STRING=org.commontk -DTARGET:STRING=MyLib 
+#    cmake -DWRAPPING_NAMESPACE:STRING=org.commontk -DTARGET:STRING=MyLib
 #          -DSOURCES:STRING="file1^^file2" -DINCLUDE_DIRS:STRING=/path1:/path2
 #          -DWRAP_INT_DIR:STRING=subir/subir/
 #          -DPYTHONQTGENERATOR_EXECUTABLE:FILEPATH=/path/to/exec
 #          -DOUTPUT_DIR:PATH=/path  -DQT_QMAKE_EXECUTABLE:PATH=/path/to/qt/qmake
+#          -DHAS_DECORATOR:BOOL=True
 #          -P ctkScriptWrapPythonQt_Full.cmake
 #
 
@@ -47,7 +48,7 @@ IF(NOT DEFINED CMAKE_CURRENT_LIST_FILENAME)
 ENDIF()
 
 # Check for non-defined var
-FOREACH(var SOURCES TARGET INCLUDE_DIRS WRAP_INT_DIR WRAPPING_NAMESPACE)
+FOREACH(var SOURCES TARGET INCLUDE_DIRS WRAP_INT_DIR WRAPPING_NAMESPACE HAS_DECORATOR)
   IF(NOT DEFINED ${var})
     MESSAGE(FATAL_ERROR "${var} not specified when calling ctkScriptWrapPythonQt")
   ENDIF()
@@ -70,10 +71,10 @@ FOREACH(FILE ${SOURCES})
 
   # what is the filename without the extension
   GET_FILENAME_COMPONENT(TMP_FILENAME ${FILE} NAME_WE)
-    
-  SET(includes 
+
+  SET(includes
     "${includes}\n#include \"${TMP_FILENAME}.h\"")
-        
+
   # Extract classname - NOTE: We assume the filename matches the associated class
   set(className ${TMP_FILENAME})
   #message(STATUS "FILE:${FILE}, className:${className}")
@@ -97,7 +98,7 @@ FILE(WRITE ${OUTPUT_DIR}/${WRAP_INT_DIR}typesystem_${TARGET}.xml "
 </typesystem>
 ")
 
-# Extract PYTHONQTGENERATOR_DIR 
+# Extract PYTHONQTGENERATOR_DIR
 GET_FILENAME_COMPONENT(PYTHONQTGENERATOR_DIR ${PYTHONQTGENERATOR_EXECUTABLE} PATH)
 #message(PYTHONQTGENERATOR_DIR:${PYTHONQTGENERATOR_DIR})
 
@@ -146,7 +147,7 @@ CONFIGURE_FILE(
 
 # Since PythonQtGenerator or FILE(WRITE ) doesn't 'update the timestamp - Let's touch the files
 EXECUTE_PROCESS(
-  COMMAND ${CMAKE_COMMAND} -E touch 
+  COMMAND ${CMAKE_COMMAND} -E touch
     ${OUTPUT_DIR}/${WRAP_INT_DIR}${WRAPPING_NAMESPACE_UNDERSCORE}_${TARGET}_init.cpp
     ${OUTPUT_DIR}/${WRAP_INT_DIR}ctkPythonQt_${TARGET}_masterinclude.h
   )

+ 26 - 25
CMake/ctkScriptWrapPythonQt_Light.cmake

@@ -28,21 +28,22 @@
 #
 
 #
-# This script should be invoked either as a CUSTOM_COMMAND 
+# This script should be invoked either as a CUSTOM_COMMAND
 # or from the command line using the following syntax:
 #
-#    cmake -DWRAPPING_NAMESPACE:STRING=org.commontk -DTARGET:STRING=MyLib 
+#    cmake -DWRAPPING_NAMESPACE:STRING=org.commontk -DTARGET:STRING=MyLib
 #          -DSOURCES:STRING="file1^^file2" -DINCLUDE_DIRS:STRING=/path1:/path2
 #          -DWRAP_INT_DIR:STRING=subir/subir/
 #          -DOUTPUT_DIR:PATH=/path  -DQT_QMAKE_EXECUTABLE:PATH=/path/to/qt/qmake
 #          -DPYTHON_EXECUTABLE:FILEPATH=/path/to/python
 #          -DPYTHON_LIBRARY_PATH:PATH=/path/to/pythonlib
+#          -DHAS_DECORATOR:BOOL=True
 #          -P ctkScriptWrapPythonQt_Light.cmake
 #
 
 #
 # LOG FILE:
-#   File ctkScriptWrapPythonQt_Light_log.txt will be created in the current directory. 
+#   File ctkScriptWrapPythonQt_Light_log.txt will be created in the current directory.
 #   It will contain the list of class and the constructor signature that will be wrapped.
 #
 
@@ -67,11 +68,11 @@ FUNCTION(reSearchFile python_exe python_library_path regex file is_matching)
 
   set(python_cmd "import re\; f = open('${file}', 'r')\;
 res = re.search\(\"${regex}\", f.read(), re.MULTILINE\)\;
-if res == None: print \"FALSE\" 
+if res == None: print \"FALSE\"
 else: print \"TRUE\"
 ")
   #message("python_cmd: ${python_cmd}")
-  
+
   IF(WIN32)
     SET(ENV{PATH} ${python_library_path};$ENV{PATH})
   ELSEIF(APPLE)
@@ -87,13 +88,13 @@ else: print \"TRUE\"
     ERROR_VARIABLE error
     OUTPUT_STRIP_TRAILING_WHITESPACE
     )
-  
+
   IF(result)
     MESSAGE(FATAL_ERROR "reSearchFile - Problem with regex: ${regex}\n${error}")
   ENDIF()
   #message(${output})
   SET(is_matching ${output} PARENT_SCOPE)
-  
+
 ENDFUNCTION()
 
 IF(NOT DEFINED CMAKE_CURRENT_LIST_DIR)
@@ -104,7 +105,7 @@ IF(NOT DEFINED CMAKE_CURRENT_LIST_FILENAME)
 ENDIF()
 
 # Check for non-defined var
-FOREACH(var WRAPPING_NAMESPACE TARGET SOURCES INCLUDE_DIRS WRAP_INT_DIR)
+FOREACH(var WRAPPING_NAMESPACE TARGET SOURCES INCLUDE_DIRS WRAP_INT_DIR HAS_DECORATOR)
   IF(NOT DEFINED ${var})
     MESSAGE(FATAL_ERROR "${var} not specified when calling ctkScriptWrapPythonQt")
   ENDIF()
@@ -119,7 +120,7 @@ ENDFOREACH()
 
 # Clear log file
 FILE(WRITE "${CMAKE_CURRENT_BINARY_DIR}/ctkScriptWrapPythonQt_Light_log.txt" "")
-  
+
 # Convert wrapping namespace to subdir
 STRING(REPLACE "." "_" WRAPPING_NAMESPACE_UNDERSCORE ${WRAPPING_NAMESPACE})
 
@@ -130,17 +131,17 @@ FOREACH(FILE ${SOURCES})
 
   # what is the filename without the extension
   GET_FILENAME_COMPONENT(TMP_FILENAME ${FILE} NAME_WE)
-      
-  SET(includes 
+
+  SET(includes
     "${includes}\n#include \"${TMP_FILENAME}.h\"")
-        
+
   # Extract classname - NOTE: We assume the filename matches the associated class
   set(className ${TMP_FILENAME})
   #message(STATUS "FILE:${FILE}, className:${className}")
-  
+
   # Extract parent classname
   SET(parentClassName)
-  
+
   IF("${parentClassName}" STREQUAL "")
     # Does constructor signature is of the form: myclass()
     SET(regex "[^~]${className}[\\s\\n]*\\([\\s\\n]*\\)")
@@ -150,7 +151,7 @@ FOREACH(FILE ${SOURCES})
       log("${TMP_FILENAME} - constructor of the form: ${className}\(\)")
     ENDIF()
   ENDIF()
-  
+
   IF("${parentClassName}" STREQUAL "")
     # Does constructor signature is of the form: myclass(QObject * parent ...)
     SET(regex "${className}[\\s\\n]*\\([\\s\\n]*QObject[\\s\\n]*\\*[\\s\\n]*\\w+[\\s\\n]*(\\=[\\s\\n]*(0|NULL)|,.*\\=.*\\)|\\))")
@@ -160,7 +161,7 @@ FOREACH(FILE ${SOURCES})
       log("${TMP_FILENAME} - constructor of the form: ${className}\(QObject * parent ... \)")
     ENDIF()
   ENDIF()
-  
+
   IF("${parentClassName}" STREQUAL "")
     # Does constructor signature is of the form: myclass(QWidget * parent ...)
     SET(regex "${className}[\\s\\n]*\\([\\s\\n]*QWidget[\\s\\n]*\\*[\\s\\n]*\\w+[\\s\\n]*(\\=[\\s\\n]*(0|NULL)|,.*\\=.*\\)|\\))")
@@ -170,11 +171,11 @@ FOREACH(FILE ${SOURCES})
       log("${TMP_FILENAME} - constructor of the form: ${className}\(QWidget * parent ... \)")
     ENDIF()
   ENDIF()
- 
+
   # Generate PythonQtWrapper class
   IF("${parentClassName}" STREQUAL "QObject" OR "${parentClassName}" STREQUAL "QWidget")
-  
-    SET(pythonqtWrappers 
+
+    SET(pythonqtWrappers
       "${pythonqtWrappers}
 //-----------------------------------------------------------------------------
 class PythonQtWrapper_${className} : public QObject
@@ -191,11 +192,11 @@ public slots:
 ")
 
   ELSEIF("${parentClassName}" STREQUAL "No")
-  
-    SET(pythonqtWrappers 
+
+    SET(pythonqtWrappers
       "${pythonqtWrappers}
 //-----------------------------------------------------------------------------
-class PythonQtWrapper_${className} : public QObject
+class Q_DECL_EXPORT PythonQtWrapper_${className} : public QObject
 {
 Q_OBJECT
 public:
@@ -209,9 +210,9 @@ public slots:
 ")
 
   ELSE() # Case parentClassName is empty
-  
+
     MESSAGE(WARNING "ctkScriptWrapPythonQt_Light - Problem wrapping ${FILE}")
-    
+
   ENDIF()
 
   # Generate code allowing to register the class metaobject and its associated "light" wrapper
@@ -260,7 +261,7 @@ CONFIGURE_FILE(
 
 # Since FILE(WRITE ) doesn't update the timestamp - Let's touch the files
 EXECUTE_PROCESS(
-  COMMAND ${CMAKE_COMMAND} -E touch 
+  COMMAND ${CMAKE_COMMAND} -E touch
     ${OUTPUT_DIR}/${WRAP_INT_DIR}${WRAPPING_NAMESPACE_UNDERSCORE}_${TARGET}_init.cpp
   )
 

+ 9 - 8
CMakeLists.txt

@@ -94,7 +94,7 @@ FOREACH(type LIBRARY RUNTIME ARCHIVE)
      AND NOT EXISTS ${CTK_CMAKE_${type}_OUTPUT_DIRECTORY})
     MESSAGE(FATAL_ERROR "CTK_CMAKE_${type}_OUTPUT_DIRECTORY is set to a non-existing directory [${CTK_CMAKE_${type}_OUTPUT_DIRECTORY}]")
   ENDIF()
-  
+
   IF(CTK_SUPERBUILD)
     SET(output_dir ${CTK_BINARY_DIR}/bin)
     IF(NOT DEFINED CTK_CMAKE_${type}_OUTPUT_DIRECTORY)
@@ -176,6 +176,7 @@ INCLUDE(CMake/ctkMacroParseArguments.cmake)
 INCLUDE(CMake/ctkMacroSetPaths.cmake)
 INCLUDE(CMake/ctkMacroListFilter.cmake)
 INCLUDE(CMake/ctkMacroBuildLib.cmake)
+INCLUDE(CMake/ctkMacroBuildLibWrapper.cmake)
 INCLUDE(CMake/ctkMacroBuildPlugin.cmake)
 INCLUDE(CMake/ctkMacroBuildApp.cmake)
 INCLUDE(CMake/ctkMacroCompilePythonScript.cmake)
@@ -211,7 +212,7 @@ IF(BUILD_TESTING)
   INCLUDE(CTest)
   SET(CPP_TEST_PATH ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
   MARK_AS_ADVANCED(TCL_TCLSH DART_ROOT)
-    
+
   # Setup file for setting custom ctest vars
   CONFIGURE_FILE(
     CMake/CTestCustom.cmake.in
@@ -288,7 +289,7 @@ SET(CTK_CXX_FLAGS "${CMAKE_CXX_FLAGS_INIT} ${VISIBILITY_CXX_FLAGS} ${COVERAGE_CX
 
 IF(CMAKE_COMPILER_IS_GNUCXX)
   SET(cflags "-Wall -Wextra -Wpointer-arith -Winvalid-pch -Wcast-align -Wwrite-strings -D_FORTIFY_SOURCE=2")
-  
+
   ctkFunctionCheckCompilerFlags("-fdiagnostics-show-option" cflags)
   ctkFunctionCheckCompilerFlags("-Wl,--no-undefined" cflags)
 
@@ -303,7 +304,7 @@ IF(CMAKE_COMPILER_IS_GNUCXX)
     # suppress warnings about auto imported symbols
     SET(CTK_CXX_FLAGS "-Wl,--enable-auto-import ${CTK_CXX_FLAGS}")
   ENDIF()
-  
+
   SET(CTK_C_FLAGS "${cflags} ${CTK_C_FLAGS}")
   SET(CTK_CXX_FLAGS "${cflags} -Woverloaded-virtual -Wold-style-cast -Wstrict-null-sentinel -Wsign-promo ${CTK_CXX_FLAGS}")
 ENDIF()
@@ -388,7 +389,7 @@ SET(CTK_APPLICATIONS
   ctkDICOMObjectViewer:OFF
   ctkSimplePythonShell:OFF
   )
-  
+
 #-----------------------------------------------------------------------------
 # To make options show up in both CTK-SuperBuild and CTK regular build, let's add them
 # before the SuperBuild script is included
@@ -415,7 +416,7 @@ SET(CTK_APPLICATIONS_SUBDIRS )
 # The following FOREACH loops are used to:
 #   1) Add build options associated with either libraries, plugins and applications
 #   2) Update either CTK_LIBS_SUBDIRS, CTK_PLUGINS_SUBDIRS or CTK_APPS_SUBDIRS variables
-# 
+#
 # For CTK libraries, if the file Libs/<DIR>/<LIBNAME>/ctk_library_options.cmake exists,
 # in addition to 'CTK_LIB_<DIR>/<LIBNAME>' option, the following ones
 # will also be available in CMake configure menu:
@@ -547,7 +548,7 @@ EXECUTE_PROCESS(
   OUTPUT_VARIABLE CTEST_PROJECT_SUBPROJECTS_OUTPUT
   ERROR_VARIABLE error
   OUTPUT_STRIP_TRAILING_WHITESPACE
-  )      
+  )
 IF(RESULT_VAR)
   MESSAGE(FATAL_ERROR "Failed to obtain list of target ordered topologically.\n${RESULT_VAR}\n${CTK_BINARY_DIR}\n${error}")
 ENDIF()
@@ -651,7 +652,7 @@ ENDIF()
 
 CONFIGURE_FILE(${CTK_SOURCE_DIR}/UseCTK.cmake.in
                ${CTK_SUPERBUILD_BINARY_DIR}/UseCTK.cmake COPYONLY IMMEDIATE)
-               
+
 #-----------------------------------------------------------------------------
 # Set C/CXX Flags
 #

+ 9 - 8
CTKConfig.cmake.in

@@ -50,6 +50,7 @@ ENDIF()
 INCLUDE("@CTK_CMAKE_DIR_CONFIG@/ctkMacroParseArguments.cmake")
 INCLUDE("@CTK_CMAKE_DIR_CONFIG@/ctkMacroSetPaths.cmake")
 INCLUDE("@CTK_CMAKE_DIR_CONFIG@/ctkMacroListFilter.cmake")
+INCLUDE("@CTK_CMAKE_DIR_CONFIG@/ctkMacroBuildLibWrapper.cmake")
 INCLUDE("@CTK_CMAKE_DIR_CONFIG@/ctkMacroBuildPlugin.cmake")
 INCLUDE("@CTK_CMAKE_DIR_CONFIG@/ctkMacroTargetLibraries.cmake") # Import multiple macros
 INCLUDE("@CTK_CMAKE_DIR_CONFIG@/ctkFunctionExtractOptionNameAndValue.cmake")
@@ -87,7 +88,7 @@ INCLUDE("@CTK_PLUGIN_USE_FILE@")
 
 # The CTK include file directories.
 SET(CTK_INCLUDE_DIRS "@CTK_BUILD_DIR@;@CTK_INCLUDE_DIRS_CONFIG@")
- 
+
 # The CTK library directories. Note that if
 # CTK_CONFIGURATION_TYPES is set (see below) then these directories
 # will be the parent directories under which there will be a directory
@@ -102,13 +103,13 @@ SET(CTK_EXTERNAL_LIBRARIES "@CTK_EXTERNAL_LIBRARIES_CONFIG@")
 # will be the parent directories under which there will be a directory
 # of runtime binaries for each configuration type.
 SET(CTK_EXTERNAL_LIBRARY_DIRS "@CTK_EXTERNAL_LIBRARY_DIRS_CONFIG@")
- 
+
 # The CTK binary executable directories. Note that if
 # CTK_CONFIGURATION_TYPES is set (see below) then these directories
 # will be the parent directories under which there will be a directory
 # of runtime binaries for each configuration type.
 SET(CTK_EXECUTABLE_DIRS "@CTK_EXECUTABLE_DIRS_CONFIG@")
- 
+
 # The CTK runtime library directories. Note that if
 # CTK_CONFIGURATION_TYPES is set (see below) then these directories
 # will be the parent directories under which there will be a directory
@@ -134,14 +135,14 @@ SET(CTK_QT_QMAKE_EXECUTABLE "@QT_QMAKE_EXECUTABLE@")
 SET(CTK_MAJOR_VERSION "@CTK_MAJOR_VERSION@")
 SET(CTK_MINOR_VERSION "@CTK_MINOR_VERSION@")
 SET(CTK_BUILD_VERSION "@CTK_BUILD_VERSION@")
- 
+
 # The location of the UseCTK.cmake file.
 SET(CTK_USE_FILE "@CTK_USE_FILE@")
- 
+
 # CMake extension module directory
 SET(CTK_CMAKE_DIR "@CTK_CMAKE_DIR_CONFIG@")
 SET(CTK_CMAKE_UTILITIES_DIR "@CTK_CMAKE_UTILITIES_DIR_CONFIG@")
- 
+
 # TODO The list of available libraries.
 
 # TODO The list of available plugins.
@@ -150,13 +151,13 @@ SET(CTK_CMAKE_UTILITIES_DIR "@CTK_CMAKE_UTILITIES_DIR_CONFIG@")
 
 # TODO The Doxygen configuration.
 #SET(CTK_DOXYGEN_HOME "@CTK_DOXYGEN_HOME_CONFIG@")
- 
+
 # TODO Relative install paths in the CTK install tree
 #SET(CTK_INSTALL_BIN_DIR "@CTK_INSTALL_BIN_DIR@")
 SET(CTK_INSTALL_INCLUDE_DIR "@CTK_INSTALL_INCLUDE_DIR@")
 SET(CTK_INSTALL_LIB_DIR "@CTK_INSTALL_LIB_DIR@")
 #SET(CTK_INSTALL_PACKAGE_DIR "@CTK_INSTALL_PACKAGE_DIR@")
- 
+
 # A CTK install tree always provides one build configuration. A CTK
 # build tree may provide either one or multiple build configurations
 # depending on the CMake generator used. Since CTK can be used either

+ 6 - 17
Libs/Core/CMakeLists.txt

@@ -80,17 +80,6 @@ IF(HAVE_BFD)
     )
 ENDIF()
 
-IF(CTK_WRAP_PYTHONQT_LIGHT)
-  LIST(APPEND KIT_SRCS
-    ctkCorePythonQtDecorators.h
-    )
-  # Let's make sure the decorator are not wrapped !
-  SET_SOURCE_FILES_PROPERTIES(
-    ctkCorePythonQtDecorators.h
-    WRAP_EXCLUDE
-    )
-ENDIF()
-
 # Headers that should run through moc
 SET(KIT_MOC_SRCS
   ctkCallback.h
@@ -109,12 +98,6 @@ SET(KIT_MOC_SRCS
   ctkWorkflowTransitions.h
   )
 
-IF(CTK_WRAP_PYTHONQT_LIGHT)
-  LIST(APPEND KIT_MOC_SRCS
-    ctkCorePythonQtDecorators.h
-    )
-ENDIF()
-
 # UI files
 SET(KIT_UI_FORMS
 )
@@ -140,6 +123,12 @@ ctkMacroBuildLib(
   LIBRARY_TYPE ${CTK_LIBRARY_MODE}
   )
 
+ctkMacroBuildLibWrapper(
+  TARGET ${PROJECT_NAME}
+  SRCS ${KIT_SRCS}
+  WRAPPER_LIBRARY_TYPE ${CTK_LIBRARY_MODE}
+  )
+
 # Testing
 IF(BUILD_TESTING)
   ADD_SUBDIRECTORY(Testing)

+ 0 - 1
Libs/Core/Testing/Cpp/CMakeLists.txt

@@ -7,7 +7,6 @@ ctkMacroBuildLib(
   MOC_SRCS "ctkDummyPlugin.h"
   TARGET_LIBRARIES ${CTK_BASE_LIBRARIES}
   LIBRARY_TYPE "SHARED"
-  DISABLE_WRAP_PYTHONQT
   )
 GET_TARGET_PROPERTY(ctkDummyPluginPATH "CTKDummyPlugin" LOCATION)
 REMOVE_DEFINITIONS(-DCTKDummyPlugin)

+ 1 - 1
Libs/Core/ctkAbstractFactory.h

@@ -93,7 +93,7 @@ private:
 /// <p> ctkAbstractFactory contains a collection of ctkAbstractFactoryItems that
 /// are uniquely identifyed by a key. Subclasses of ctkAbstractFactory are
 /// responsible for populating the list of ctkAbstractFactoryItems.
-/// BaseClassType could be any type (most probably a QObject) 
+/// BaseClassType could be any type (most probably a QObject)
 template<typename BaseClassType>
 class ctkAbstractFactory
 {

+ 11 - 11
Libs/Core/ctkCheckableModelHelper.h

@@ -26,7 +26,7 @@
    All rights reserved.
 
    ParaView is a free software; you can redistribute it and/or modify it
-   under the terms of the ParaView license version 1.2. 
+   under the terms of the ParaView license version 1.2.
 
    See http://www.paraview.org/paraview/project/license.html for the full ParaView license.
    A copy of this license can be obtained by contacting
@@ -70,13 +70,13 @@ class CTK_CORE_EXPORT ctkCheckableModelHelper : public QObject
   Q_PROPERTY(bool forceCheckability READ forceCheckability WRITE setForceCheckability);
   Q_PROPERTY(int propagateDepth READ propagateDepth WRITE setPropagateDepth);
   Q_PROPERTY(Qt::CheckState defaultCheckState READ defaultCheckState WRITE setDefaultCheckState);
-  
+
 public:
   ctkCheckableModelHelper(Qt::Orientation orientation, QObject *parent=0);
   virtual ~ctkCheckableModelHelper();
 
   Qt::Orientation orientation()const;
-  
+
 
   ///
   /// When setting the model, if PropagateToItems is true (by default), the check
@@ -92,22 +92,22 @@ public:
   QModelIndex rootIndex()const;
   virtual void setRootIndex(const QModelIndex &index);
 
-  /// 
-  /// A section is checkable if its CheckStateRole data is non null. 
+  ///
+  /// A section is checkable if its CheckStateRole data is non null.
   /// One can access the same value through the model:
   /// model->headerData(orientation, section, Qt::CheckStateRole).isEmpty()
   bool isHeaderCheckable(int section)const;
   bool isCheckable(const QModelIndex& index)const;
 
   ///
-  /// Utility function that returns the checkState of the section. 
+  /// Utility function that returns the checkState of the section.
   /// One can access the same value through the model:
   /// model->headerData(orientation, section, Qt::CheckStateRole)
   Qt::CheckState headerCheckState(int section)const;
   Qt::CheckState checkState(const QModelIndex&)const;
 
   ///
-  /// Utility function that returns the checkState of the section. 
+  /// Utility function that returns the checkState of the section.
   /// One can access the same value through the model:
   /// model->headerData(orientation, section, Qt::CheckStateRole)
   bool headerCheckState(int section, Qt::CheckState& checkState )const;
@@ -118,8 +118,8 @@ public:
   /// -1 by default
   void setPropagateDepth(int depth);
   int  propagateDepth()const;
-  
-  /// When true, the new items are automatically set to checkable 
+
+  /// When true, the new items are automatically set to checkable
   void setForceCheckability(bool force);
   bool forceCheckability()const;
 
@@ -129,14 +129,14 @@ public:
 public slots:
   void setCheckState(const QModelIndex& modelIndex, Qt::CheckState checkState);
   ///
-  /// Warning, setting the check state automatically set the 
+  /// Warning, setting the check state automatically set the
   /// header section checkable
   void setHeaderCheckState(int section, Qt::CheckState checkState);
 
   /// Utility function to toggle the checkstate of an index
   void toggleCheckState(const QModelIndex& modelIndex);
   void toggleHeaderCheckState(int section);
-  
+
 private slots:
   void onHeaderDataChanged(Qt::Orientation orient, int first, int last);
 

+ 15 - 12
Libs/Core/ctkCorePythonQtDecorators.h

@@ -21,9 +21,6 @@
 #ifndef __ctkCorePythonQtDecorators_h
 #define __ctkCorePythonQtDecorators_h
 
-// Qt includes
-#include <QObject>
-
 // PythonQt includes
 #include <PythonQt.h>
 
@@ -72,7 +69,7 @@ public slots:
     {
     delete step;
     }
-    
+
   ctkWorkflow* workflow(ctkWorkflowStep* step)const
     {
     return step->workflow();
@@ -92,7 +89,7 @@ public slots:
     {
     return step->name();
     }
-    
+
   void setName(ctkWorkflowStep* step, const QString& newName)
     {
     step->setName(newName);
@@ -102,7 +99,7 @@ public slots:
     {
     return step->description();
     }
-    
+
   void setDescription(ctkWorkflowStep* step, const QString& newDescription)
     {
     step->setDescription(newDescription);
@@ -117,7 +114,7 @@ public slots:
     {
     return step->hasValidateCommand();
     }
-    
+
   void setHasValidateCommand(ctkWorkflowStep* step, bool newHasValidateCommand)
     {
     step->setHasValidateCommand(newHasValidateCommand);
@@ -127,7 +124,7 @@ public slots:
     {
     return step->hasOnEntryCommand();
     }
-    
+
   void setHasOnEntryCommand(ctkWorkflowStep* step, bool newHasOnEntryCommand)
     {
     step->setHasOnEntryCommand(newHasOnEntryCommand);
@@ -137,12 +134,12 @@ public slots:
     {
     return step->hasOnExitCommand();
     }
-    
+
   void setHasOnExitCommand(ctkWorkflowStep* step, bool newHasOnExitCommand)
     {
     step->setHasOnExitCommand(newHasOnExitCommand);
     }
-  
+
   QObject* ctkWorkflowStepQObject(ctkWorkflowStep* step)
     {
     return step->ctkWorkflowStepQObject();
@@ -155,16 +152,22 @@ public slots:
     {
     return new ctkWorkflowInterstepTransition(newTransitionType);
     }
-  
+
   ctkWorkflowInterstepTransition* new_ctkWorkflowInterstepTransition(ctkWorkflowInterstepTransition::InterstepTransitionType newTransitionType, const QString& newId)
     {
     return new ctkWorkflowInterstepTransition(newTransitionType, newId);
     }
-    
+
   void delete_ctkWorkflowInterstepTransition(ctkWorkflowInterstepTransition * transition)
     {
     delete transition;
     }
 };
 
+//-----------------------------------------------------------------------------
+void initCTKCorePythonQtDecorators()
+{
+  PythonQt::self()->addDecorators(new ctkCorePythonQtDecorators);
+}
+
 #endif

+ 8 - 20
Libs/DICOM/Core/CMakeLists.txt

@@ -6,7 +6,7 @@ PROJECT(CTKDICOMCore)
 
 SET(KIT_export_directive "CTK_DICOM_CORE_EXPORT")
 
-  
+
 # Source files
 SET(KIT_SRCS
   ctkDICOMAbstractThumbnailGenerator.cpp
@@ -37,18 +37,6 @@ SET_SOURCE_FILES_PROPERTIES(
   WRAP_EXCLUDE
   )
 
-IF(CTK_WRAP_PYTHONQT_LIGHT)
-  LIST(APPEND KIT_SRCS
-    ctkDICOMCorePythonQtDecorators.h
-    )
-  # Let's make sure the decorator are not wrapped !
-  SET_SOURCE_FILES_PROPERTIES(
-    ctkDICOMCorePythonQtDecorators.h
-    WRAP_EXCLUDE
-    )
-ENDIF()
-
-
 # Headers that should run through moc
 SET(KIT_MOC_SRCS
   ctkDICOMAbstractThumbnailGenerator.h
@@ -61,12 +49,6 @@ SET(KIT_MOC_SRCS
   ctkDICOMTester.h
   )
 
-IF(CTK_WRAP_PYTHONQT_LIGHT)
-  LIST(APPEND KIT_MOC_SRCS
-    ctkDICOMCorePythonQtDecorators.h
-    )
-ENDIF()
-
 # UI files
 SET(KIT_UI_FORMS
 )
@@ -79,7 +61,7 @@ SET(KIT_resources
 # Target libraries - See CMake/ctkFunctionGetTargetLibraries.cmake
 # The following macro will read the target libraries from the file 'target_libraries.cmake'
 ctkFunctionGetTargetLibraries(KIT_target_libraries)
-  
+
 # create a dcm query/retrieve service config file that points to the build dir
 set (DCMQRSCP_STORE_DIR ${CMAKE_CURRENT_BINARY_DIR}/Testing)
 CONFIGURE_FILE( Resources/dcmqrscp.cfg.in dcmqrscp.cfg )
@@ -96,6 +78,12 @@ ctkMacroBuildLib(
   LIBRARY_TYPE ${CTK_LIBRARY_MODE}
   )
 
+ctkMacroBuildLibWrapper(
+  TARGET ${PROJECT_NAME}
+  SRCS ${KIT_SRCS}
+  WRAPPER_LIBRARY_TYPE ${CTK_LIBRARY_MODE}
+  )
+
 # Plugins
 #IF(BUILD_QTDESIGNER_PLUGINS)
 #  ADD_SUBDIRECTORY(Plugins)

+ 6 - 3
Libs/DICOM/Core/ctkDICOMCorePythonQtDecorators.h

@@ -21,9 +21,6 @@
 #ifndef __ctkDICOMCorePythonQtDecorators_h
 #define __ctkDICOMCorePythonQtDecorators_h
 
-// Qt includes
-#include <QObject>
-
 // PythonQt includes
 #include <PythonQt.h>
 
@@ -58,4 +55,10 @@ public slots:
 
 };
 
+//-----------------------------------------------------------------------------
+void initCTKDICOMCorePythonQtDecorators()
+{
+  PythonQt::self()->addDecorators(new ctkDICOMCorePythonQtDecorators);
+}
+
 #endif

+ 7 - 18
Libs/DICOM/Widgets/CMakeLists.txt

@@ -6,7 +6,7 @@ PROJECT(CTKDICOMWidgets)
 
 SET(KIT_export_directive "CTK_DICOM_WIDGETS_EXPORT")
 
-  
+
 # Source files
 SET(KIT_SRCS
   ctkDICOMAppWidget.cpp
@@ -35,17 +35,6 @@ SET(KIT_SRCS
   ctkDICOMThumbnailListWidget.h
   )
 
-IF(CTK_WRAP_PYTHONQT_LIGHT)
-  LIST(APPEND KIT_SRCS
-    ctkDICOMWidgetsPythonQtDecorators.h
-    )
-  # Let's make sure the decorator are not wrapped !
-  SET_SOURCE_FILES_PROPERTIES(
-    ctkDICOMWidgetsPythonQtDecorators.h
-    WRAP_EXCLUDE
-    )
-ENDIF()
-
 # Headers that should run through moc
 SET(KIT_MOC_SRCS
   ctkDICOMAppWidget.h
@@ -60,12 +49,6 @@ SET(KIT_MOC_SRCS
   ctkDICOMThumbnailListWidget.h
   )
 
-IF(CTK_WRAP_PYTHONQT_LIGHT)
-  LIST(APPEND KIT_MOC_SRCS
-    ctkDICOMWidgetsPythonQtDecorators.h
-    )
-ENDIF()
-
 # UI files - includes new widgets
 SET(KIT_UI_FORMS
   Resources/UI/ctkDICOMAppWidget.ui
@@ -96,6 +79,12 @@ ctkMacroBuildLib(
   LIBRARY_TYPE ${CTK_LIBRARY_MODE}
   )
 
+ctkMacroBuildLibWrapper(
+  TARGET ${PROJECT_NAME}
+  SRCS ${KIT_SRCS}
+  WRAPPER_LIBRARY_TYPE ${CTK_LIBRARY_MODE}
+  )
+
 # Plugins
 IF(BUILD_QTDESIGNER_PLUGINS)
   ADD_SUBDIRECTORY(Plugins)

+ 6 - 3
Libs/DICOM/Widgets/ctkDICOMWidgetsPythonQtDecorators.h

@@ -21,9 +21,6 @@
 #ifndef __ctkDICOMWidgetsPythonQtDecorators_h
 #define __ctkDICOMWidgetsPythonQtDecorators_h
 
-// Qt includes
-#include <QObject>
-
 // PythonQt includes
 #include <PythonQt.h>
 
@@ -58,4 +55,10 @@ public slots:
 
 };
 
+//-----------------------------------------------------------------------------
+void initCTKDICOMWidgetsPythonQtDecorators()
+{
+  PythonQt::self()->addDecorators(new ctkDICOMWidgetsPythonQtDecorators);
+}
+
 #endif

+ 7 - 1
Libs/ImageProcessing/ITK/Core/CMakeLists.txt

@@ -11,7 +11,7 @@ INCLUDE(${ITK_USE_FILE})
 
 SET(KIT_export_directive "CTK_IMAGEPROCESSING_ITK_CORE_EXPORT")
 
-  
+
 # Source files
 SET(KIT_SRCS
   ctkITKErrorLogMessageHandler.cpp
@@ -45,6 +45,12 @@ ctkMacroBuildLib(
   LIBRARY_TYPE ${CTK_LIBRARY_MODE}
   )
 
+ctkMacroBuildLibWrapper(
+  TARGET ${PROJECT_NAME}
+  SRCS ${KIT_SRCS}
+  WRAPPER_LIBRARY_TYPE ${CTK_LIBRARY_MODE}
+  )
+
 # Plugins
 #IF(BUILD_QTDESIGNER_PLUGINS)
 #  ADD_SUBDIRECTORY(Plugins)

+ 7 - 1
Libs/Messaging/Core/CMakeLists.txt

@@ -6,7 +6,7 @@ PROJECT(CTKMessagingCore)
 
 SET(KIT_export_directive "CTK_MESSAGING_CORE_EXPORT")
 
-  
+
 # Source files
 SET(KIT_SRCS
   ctkMessagingServer.h
@@ -48,6 +48,12 @@ ctkMacroBuildLib(
   LIBRARY_TYPE ${CTK_LIBRARY_MODE}
   )
 
+ctkMacroBuildLibWrapper(
+  TARGET ${PROJECT_NAME}
+  SRCS ${KIT_SRCS}
+  WRAPPER_LIBRARY_TYPE ${CTK_LIBRARY_MODE}
+  )
+
 # Plugins
 #IF(BUILD_QTDESIGNER_PLUGINS)
 #  ADD_SUBDIRECTORY(Plugins)

+ 7 - 1
Libs/ModuleDescription/CMakeLists.txt

@@ -11,7 +11,7 @@ PROJECT(CTKModuleDescription)
 SET(KIT_export_directive "CTK_MODULDESC_EXPORT")
 
 # Additional directories to include
-  
+
 # Source files
 SET(KIT_SRCS
   ctkModuleDescription.h
@@ -66,6 +66,12 @@ ctkMacroBuildLib(
   LIBRARY_TYPE ${CTK_LIBRARY_MODE}
   )
 
+ctkMacroBuildLibWrapper(
+  TARGET ${PROJECT_NAME}
+  SRCS ${KIT_SRCS}
+  WRAPPER_LIBRARY_TYPE ${CTK_LIBRARY_MODE}
+  )
+
 # Testing
 IF(BUILD_TESTING)
   ADD_SUBDIRECTORY(Testing)

+ 7 - 1
Libs/PluginFramework/CMakeLists.txt

@@ -6,7 +6,7 @@ PROJECT(CTKPluginFramework)
 
 SET(KIT_export_directive "CTK_PLUGINFW_EXPORT")
 
-  
+
 # Source files
 SET(KIT_SRCS
   ctkCaseInsensitiveString.cpp
@@ -151,6 +151,12 @@ ctkMacroBuildLib(
   LIBRARY_TYPE ${CTK_LIBRARY_MODE}
   )
 
+ctkMacroBuildLibWrapper(
+  TARGET ${PROJECT_NAME}
+  SRCS ${KIT_SRCS}
+  WRAPPER_LIBRARY_TYPE ${CTK_LIBRARY_MODE}
+  )
+
 # Testing
 IF(BUILD_TESTING)
   ADD_SUBDIRECTORY(Testing)

+ 1 - 2
Libs/Scripting/Python/Core/CMakeLists.txt

@@ -13,7 +13,7 @@ ENDIF()
 
 SET(KIT_export_directive "CTK_SCRIPTING_PYTHON_CORE_EXPORT")
 
-  
+
 # Source files
 SET(KIT_SRCS
   ctkAbstractPythonManager.cpp
@@ -64,7 +64,6 @@ ctkMacroBuildLib(
   TARGET_LIBRARIES ${KIT_target_libraries}
   RESOURCES ${KIT_resources}
   LIBRARY_TYPE ${CTK_LIBRARY_MODE}
-  DISABLE_WRAP_PYTHONQT
   )
 
 # Plugins

+ 21 - 21
Libs/Scripting/Python/Core/Python/ctk/__init__.py.in

@@ -8,17 +8,17 @@ _CTK_VERBOSE_IMPORT = False
 
 for kit in __kits_to_load:
   try:
-    exec "from PythonQt.CTK%s import *" % (kit)
+    exec "from CTK%sPythonQt import *" % (kit)
   except ImportError as detail:
-    if _CTK_VERBOSE_IMPORT: 
+    if _CTK_VERBOSE_IMPORT:
       print detail
 
 def add_methodclass_to_ctkWorkflowStep_or_ctkWorkflowWidgetStep(workflowstep_class):
-  
+
   def validate(self, validationSucceed, desiredBranchId):
     """Validates the computation performed in this step's processing state."""
     self.ctkWorkflowStepQObject().validationComplete(validationSucceed, desiredBranchId)
-    
+
   def onEntry(self, comingFrom, transitionType):
     """Reimplement this function for step-specific processing when entering a step."""
     self.ctkWorkflowStepQObject().onEntryComplete()
@@ -26,40 +26,40 @@ def add_methodclass_to_ctkWorkflowStep_or_ctkWorkflowWidgetStep(workflowstep_cla
   def onExit(self, comingFrom, transitionType):
     """Reimplement this function for step-specific processing when exiting a step."""
     self.ctkWorkflowStepQObject().onExitComplete()
-    
+
   def initialize(self, stepid):
     workflowstep_class.__init__(self)
     self.setId(stepid)
     self.setHasValidateCommand(True)
     self.setHasOnEntryCommand(True)
     self.setHasOnExitCommand(True)
-    
+
     qobj = self.ctkWorkflowStepQObject()
-    
+
     qobj.connect('invokeValidateCommand(const QString&)', self.validate)
-    
+
     qobj.connect('invokeOnEntryCommand(const ctkWorkflowStep*, \
       ctkWorkflowInterstepTransition::InterstepTransitionType)', self.onEntry)
-      
+
     qobj.connect('invokeOnExitCommand(const ctkWorkflowStep*, \
-      ctkWorkflowInterstepTransition::InterstepTransitionType)', self.onExit)    
-    
+      ctkWorkflowInterstepTransition::InterstepTransitionType)', self.onExit)
+
   workflowstep_class.validate = validate
   workflowstep_class.onEntry = onEntry
   workflowstep_class.onExit = onExit
   workflowstep_class.initialize = initialize
 
 def add_methodclass_to_ctkWorkflowWidgetStep():
-  
+
   def createUserInterface(self):
     self.ctkWorkflowStepQObject().createUserInterfaceComplete()
-    
+
   #def showUserInterface(self):
   #  self.ctkWorkflowStepQObject().showUserInterfaceComplete()
-    
+
   ctkWorkflowWidgetStep.createUserInterface = createUserInterface;
   #ctkWorkflowWidgetStep.showUserInterface = showUserInterface;
-    
+
 def decorates_ctkWorkflowWidgetStep_initialize_method():
   """Decorates ctkWorkflowWidgetStep::initialize() method.
   The properties 'hasCreateUserInterfaceCommand' and 'hasShowUserInterfaceCommand'
@@ -67,21 +67,21 @@ def decorates_ctkWorkflowWidgetStep_initialize_method():
   Signals 'invokeCreateUserInterfaceCommand' and 'invokeShowUserInterfaceCommand'
   are respectively connected to the slots 'createUserInterface' and 'showUserInterface'.
   """
-  
+
   f = ctkWorkflowWidgetStep.initialize
-  
+
   from functools import wraps
   @wraps(f)
   def decorated(self, *args, **kwargs):
     f(self, *args, **kwargs)
     self.setHasCreateUserInterfaceCommand(True)
     #self.setHasShowUserInterfaceCommand(True)
-    
+
     qobj = self.ctkWorkflowStepQObject()
-    
+
     qobj.connect('invokeCreateUserInterfaceCommand()', self.createUserInterface)
     #qobj.connect('invokeShowUserInterfaceCommand()', self.showUserInterface)
-  
+
   ctkWorkflowWidgetStep.initialize = decorated
 
 #
@@ -91,7 +91,7 @@ def decorates_ctkWorkflowWidgetStep_initialize_method():
 _lib = next((_lib for _lib in __kits_to_load if _lib == 'Core'), None)
 if _lib == 'Core':
   add_methodclass_to_ctkWorkflowStep_or_ctkWorkflowWidgetStep(ctkWorkflowStep)
-  
+
 _lib = next((_lib for _lib in __kits_to_load if _lib == 'Widgets'), None)
 if _lib == 'Widgets':
   add_methodclass_to_ctkWorkflowStep_or_ctkWorkflowWidgetStep(ctkWorkflowWidgetStep)

+ 7 - 1
Libs/Scripting/Python/Widgets/CMakeLists.txt

@@ -13,7 +13,7 @@ ENDIF()
 
 SET(KIT_export_directive "CTK_SCRIPTING_PYTHON_WIDGETS_EXPORT")
 
-  
+
 # Source files
 SET(KIT_SRCS
   ctkPythonConsole.cpp
@@ -48,6 +48,12 @@ ctkMacroBuildLib(
   LIBRARY_TYPE ${CTK_LIBRARY_MODE}
   )
 
+ctkMacroBuildLibWrapper(
+  TARGET ${PROJECT_NAME}
+  SRCS ${KIT_SRCS}
+  WRAPPER_LIBRARY_TYPE ${CTK_LIBRARY_MODE}
+  )
+
 # Plugins
 IF(BUILD_QTDESIGNER_PLUGINS)
   ADD_SUBDIRECTORY(Plugins)

+ 7 - 1
Libs/Visualization/VTK/Core/CMakeLists.txt

@@ -11,7 +11,7 @@ INCLUDE(${VTK_USE_FILE})
 
 SET(KIT_export_directive "CTK_VISUALIZATION_VTK_CORE_EXPORT")
 
-  
+
 # Source files
 SET(KIT_SRCS
   ctkVTKColorTransferFunction.cpp
@@ -84,6 +84,12 @@ ctkMacroBuildLib(
   LIBRARY_TYPE ${CTK_LIBRARY_MODE}
   )
 
+ctkMacroBuildLibWrapper(
+  TARGET ${PROJECT_NAME}
+  SRCS ${KIT_SRCS}
+  WRAPPER_LIBRARY_TYPE ${CTK_LIBRARY_MODE}
+  )
+
 # Plugins
 #IF(BUILD_QTDESIGNER_PLUGINS)
 #  ADD_SUBDIRECTORY(Plugins)

+ 8 - 2
Libs/Visualization/VTK/Widgets/CMakeLists.txt

@@ -6,7 +6,7 @@ PROJECT(CTKVisualizationVTKWidgets)
 
 SET(KIT_export_directive "CTK_VISUALIZATION_VTK_WIDGETS_EXPORT")
 
-  
+
 # Source files
 SET(KIT_SRCS
   ctkVTKAbstractMatrixWidget.cpp
@@ -99,7 +99,7 @@ IF (${CTK_USE_CHARTS})
       ctkVTKScalarsToColorsWidget.cpp
       ctkVTKScalarsToColorsWidget.h
       ${KIT_SRCS})
-  SET(KIT_MOC_SRCS 
+  SET(KIT_MOC_SRCS
       ctkVTKChartView.h
       ctkVTKVolumePropertyWidget.h
       ctkVTKScalarsToColorsView.h
@@ -130,6 +130,12 @@ ctkMacroBuildLib(
   LIBRARY_TYPE ${CTK_LIBRARY_MODE}
   )
 
+ctkMacroBuildLibWrapper(
+  TARGET ${PROJECT_NAME}
+  SRCS ${KIT_SRCS}
+  WRAPPER_LIBRARY_TYPE ${CTK_LIBRARY_MODE}
+  )
+
 # Plugins
 IF(BUILD_QTDESIGNER_PLUGINS)
   ADD_SUBDIRECTORY(Plugins)

+ 7 - 1
Libs/Visualization/XIP/CMakeLists.txt

@@ -6,7 +6,7 @@ PROJECT(CTKVisualizationXIP)
 
 SET(KIT_export_directive "CTK_VISUALIZATION_XIP_EXPORT")
 
-  
+
 # Source files
 SET(KIT_SRCS
   ctkXIPAdaptor.cpp
@@ -41,6 +41,12 @@ ctkMacroBuildLib(
   LIBRARY_TYPE ${CTK_LIBRARY_MODE}
   )
 
+ctkMacroBuildLibWrapper(
+  TARGET ${PROJECT_NAME}
+  SRCS ${KIT_SRCS}
+  WRAPPER_LIBRARY_TYPE ${CTK_LIBRARY_MODE}
+  )
+
 # Plugins
 #IF(BUILD_QTDESIGNER_PLUGINS)
 #  ADD_SUBDIRECTORY(Plugins)

+ 6 - 18
Libs/Widgets/CMakeLists.txt

@@ -160,17 +160,6 @@ SET(KIT_SRCS
   ctkWorkflowWidgetStep.h
   )
 
-IF(CTK_WRAP_PYTHONQT_LIGHT)
-  LIST(APPEND KIT_SRCS
-    ctkWidgetsPythonQtDecorators.h
-    )
-  # Let's make sure the decorator are not wrapped !
-  SET_SOURCE_FILES_PROPERTIES(
-    ctkWidgetsPythonQtDecorators.h
-    WRAP_EXCLUDE
-    )
-ENDIF()
-
 # Headers that should run through moc
 SET(KIT_MOC_SRCS
   ctkActionsWidget.h
@@ -250,13 +239,6 @@ SET(KIT_MOC_SRCS
   ctkWorkflowWidgetStep_p.h
   )
 
-
-IF(CTK_WRAP_PYTHONQT_LIGHT)
-  LIST(APPEND KIT_MOC_SRCS
-    ctkWidgetsPythonQtDecorators.h
-    )
-ENDIF()
-
 # UI files
 SET(KIT_UI_FORMS
   Resources/UI/ctkAddRemoveComboBox.ui
@@ -293,6 +275,12 @@ ctkMacroBuildLib(
   LIBRARY_TYPE ${CTK_LIBRARY_MODE}
   )
 
+ctkMacroBuildLibWrapper(
+  TARGET ${PROJECT_NAME}
+  SRCS ${KIT_SRCS}
+  WRAPPER_LIBRARY_TYPE ${CTK_LIBRARY_MODE}
+  )
+
 # Plugins
 IF(BUILD_QTDESIGNER_PLUGINS)
   ADD_SUBDIRECTORY(Plugins)

+ 6 - 3
Libs/Widgets/ctkWidgetsPythonQtDecorators.h

@@ -21,9 +21,6 @@
 #ifndef __ctkWidgetsPythonQtDecorators_h
 #define __ctkWidgetsPythonQtDecorators_h
 
-// Qt includes
-#include <QObject>
-
 // PythonQt includes
 #include <PythonQt.h>
 
@@ -75,4 +72,10 @@ public slots:
     }
 };
 
+//-----------------------------------------------------------------------------
+void initCTKWidgetsPythonQtDecorators()
+{
+  PythonQt::self()->addDecorators(new ctkWidgetsPythonQtDecorators);
+}
+
 #endif

+ 6 - 4
Utilities/LastConfigureStep/CTKGenerateCTKConfig.cmake

@@ -70,9 +70,11 @@ SET(CTK_USE_FILE ${CTK_SUPERBUILD_BINARY_DIR}/UseCTK.cmake)
 SET(CTK_TARGETS_TO_EXPORT ${CTK_LIBRARIES} ${CTK_PLUGIN_LIBRARIES})
 
 # Append CTK PythonQt static libraries
-FOREACH(lib ${CTK_WRAPPED_LIBRARIES_PYTHONQT})
-  LIST(APPEND CTK_TARGETS_TO_EXPORT ${lib}PythonQt)
-ENDFOREACH()
+IF(NOT CTK_BUILD_SHARED_LIBS)
+  FOREACH(lib ${CTK_WRAPPED_LIBRARIES_PYTHONQT})
+    LIST(APPEND CTK_TARGETS_TO_EXPORT ${lib}PythonQt)
+  ENDFOREACH()
+ENDIF()
 
 # Export targets so they can be imported by a project using CTK
 # as an external library
@@ -89,7 +91,7 @@ FOREACH(lib ${CTK_LIBRARIES})
   ctkFunctionGetIncludeDirs(${lib}_INCLUDE_DIRS ${lib})
   SET(CTK_LIBRARY_INCLUDE_DIRS_CONFIG "${CTK_LIBRARY_INCLUDE_DIRS_CONFIG}
 SET(${lib}_INCLUDE_DIRS \"${${lib}_INCLUDE_DIRS}\")")
-  
+
   ctkFunctionGetLibraryDirs(${lib}_LIBRARY_DIRS ${lib})
   SET(CTK_LIBRARY_LIBRARY_DIRS_CONFIG "${CTK_LIBRARY_LIBRARY_DIRS_CONFIG}
 SET(${lib}_LIBRARY_DIRS \"${${lib}_LIBRARY_DIRS}\")")