浏览代码

ENH: Add lib CTK/Scripting/Python/Core with class ctkAbstractPythonManager

Jean-Christophe Fillion-Robin 15 年之前
父节点
当前提交
b916694a7c

+ 1 - 0
CMakeLists.txt

@@ -209,6 +209,7 @@ SET(CTK_LIBS
   Widgets
   DICOM/Core
   DICOM/Widgets
+  Scripting/Python/Core
   Visualization/VTK/Core
   Visualization/VTK/Widgets
   Visualization/XIP

+ 65 - 0
Libs/Scripting/Python/Core/CMakeLists.txt

@@ -0,0 +1,65 @@
+PROJECT(CTKScriptingPythonCore)
+
+#
+# 3rd party dependencies
+#
+
+FIND_PACKAGE(PythonQt)
+IF(NOT PYTHONQT_FOUND)
+  MESSAGE(FATAL_ERROR "error: PythonQt package is required to build ${PROJECT_NAME}")
+ENDIF()
+
+#
+# See CTK/CMake/ctkMacroBuildLib.cmake for details
+#
+
+SET(KIT_export_directive "CTK_SCRIPTING_PYTHON_CORE_EXPORT")
+
+# Additional directories to include
+SET(KIT_include_directories
+  ${PYTHON_INCLUDE_DIRS}
+  ${PYTHONQT_INCLUDE_DIR}
+  )
+  
+# Source files
+SET(KIT_SRCS
+  ctkAbstractPythonManager.cpp
+  ctkAbstractPythonManager.h
+  )
+
+# Headers that should run through moc
+SET(KIT_MOC_SRCS
+  ctkAbstractPythonManager.h
+  )
+
+# UI files
+SET(KIT_UI_FORMS
+)
+
+# Resources
+SET(KIT_resources
+)
+
+# Target libraries - See CMake/ctkMacroGetTargetLibraries.cmake
+# The following macro will read the target libraries from the file 'target_libraries.cmake'
+ctkMacroGetTargetLibraries(KIT_target_libraries)
+
+ctkMacroBuildLib(
+  NAME ${PROJECT_NAME}
+  EXPORT_DIRECTIVE ${KIT_export_directive}
+  INCLUDE_DIRECTORIES ${KIT_include_directories}
+  SRCS ${KIT_SRCS}
+  MOC_SRCS ${KIT_MOC_SRCS}
+  UI_FORMS ${KIT_UI_FORMS}
+  TARGET_LIBRARIES ${KIT_target_libraries}
+  RESOURCES ${KIT_resources}
+  LIBRARY_TYPE ${CTK_LIBRARY_MODE}
+  )
+
+# Plugins
+#ADD_SUBDIRECTORY(Plugins)
+
+# Testing
+IF(BUILD_TESTING)
+  #ADD_SUBDIRECTORY(Testing)
+ENDIF(BUILD_TESTING)

+ 1 - 0
Libs/Scripting/Python/Core/Testing/CMakeLists.txt

@@ -0,0 +1 @@
+ADD_SUBDIRECTORY(Cpp)

+ 30 - 0
Libs/Scripting/Python/Core/Testing/Cpp/CMakeLists.txt

@@ -0,0 +1,30 @@
+SET(KIT ${PROJECT_NAME})
+
+CREATE_TEST_SOURCELIST(Tests ${KIT}CppTests.cpp
+  
+  #EXTRA_INCLUDE TestingMacros.h
+  )
+
+SET (TestsToRun ${Tests})
+REMOVE (TestsToRun ${KIT}CppTests.cpp)
+
+SET(LIBRARY_NAME ${PROJECT_NAME})
+
+ADD_EXECUTABLE(${KIT}CppTests ${Tests})
+TARGET_LINK_LIBRARIES(${KIT}CppTests ${LIBRARY_NAME} ${CTK_BASE_LIBRARIES})
+
+SET( KIT_TESTS ${CXX_TEST_PATH}/${KIT}CppTests)
+IF(WIN32)
+  SET(KIT_TESTS ${CXX_TEST_PATH}/${CMAKE_BUILD_TYPE}/${KIT}CppTests)
+ENDIF(WIN32)
+
+MACRO( SIMPLE_TEST  TESTNAME )
+  ADD_TEST( ${TESTNAME} ${KIT_TESTS} ${TESTNAME} )
+  SET_PROPERTY(TEST ${TESTNAME} PROPERTY LABELS ${PROJECT_NAME})
+ENDMACRO( SIMPLE_TEST  )
+
+#
+# Add Tests
+#
+
+#SIMPLE_TEST( ctkModelTesterTest1 )

+ 168 - 0
Libs/Scripting/Python/Core/ctkAbstractPythonManager.cpp

@@ -0,0 +1,168 @@
+/*=========================================================================
+
+  Library:   CTK
+
+  Copyright (c) Kitware Inc. 
+  All rights reserved.
+  Distributed under a BSD License. See LICENSE.txt file.
+
+  This software is distributed "AS IS" WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the above copyright notice for more information.
+
+=========================================================================*/
+
+// Qt includes
+#include <QDir>
+#include <QDebug>
+
+// CTK includes
+#include "ctkAbstractPythonManager.h"
+
+// PythonQT includes
+#include <PythonQt.h>
+
+// STD includes
+#include <csignal>
+
+//-----------------------------------------------------------------------------
+ctkAbstractPythonManager::ctkAbstractPythonManager(QObject* _parent) : Superclass(_parent)
+{
+
+}
+
+//-----------------------------------------------------------------------------
+ctkAbstractPythonManager::~ctkAbstractPythonManager()
+{
+  PythonQt::cleanup();
+}
+
+//-----------------------------------------------------------------------------
+PythonQtObjectPtr ctkAbstractPythonManager::mainContext()
+{
+  if (!PythonQt::self())
+    {
+    this->initPythonQt();
+    }
+  if (PythonQt::self())
+    {
+    return PythonQt::self()->getMainModule();
+    }
+  return PythonQtObjectPtr();
+}
+
+//-----------------------------------------------------------------------------
+void ctkAbstractPythonManager::initPythonQt()
+{
+  PythonQt::init(PythonQt::IgnoreSiteModule | PythonQt::RedirectStdOut);
+
+  // Python maps SIGINT (control-c) to its own handler.  We will remap it
+  // to the default so that control-c works.
+  #ifdef SIGINT
+  signal(SIGINT, SIG_DFL);
+  #endif
+
+  PythonQtObjectPtr _mainContext = PythonQt::self()->getMainModule();
+
+  this->connect(PythonQt::self(), SIGNAL(pythonStdOut(const QString&)),
+                SLOT(printStdout(const QString&)));
+  this->connect(PythonQt::self(), SIGNAL(pythonStdErr(const QString&)),
+                SLOT(printStderr(const QString&)));
+
+  QStringList initCode;
+  initCode << "import sys";
+  foreach (QString path, this->pythonPaths())
+    {
+    initCode << QString("sys.path.append('%1')").arg(QDir::fromNativeSeparators(path));
+    }
+
+  _mainContext.evalScript(initCode.join("\n"));
+
+  this->preInitialization();
+
+  emit this->pythonInitialized();
+}
+
+//-----------------------------------------------------------------------------
+QStringList ctkAbstractPythonManager::pythonPaths()
+{
+  return QStringList();
+}
+
+//-----------------------------------------------------------------------------
+void ctkAbstractPythonManager::preInitialization()
+{
+}
+
+//-----------------------------------------------------------------------------
+void ctkAbstractPythonManager::registerPythonQtDecorator(QObject* decorator)
+{
+  PythonQt::self()->addDecorators(decorator);
+}
+
+//-----------------------------------------------------------------------------
+void ctkAbstractPythonManager::registerClassForPythonQt(const QMetaObject* metaobject)
+{
+  PythonQt::self()->registerClass(metaobject);
+}
+
+//-----------------------------------------------------------------------------
+void ctkAbstractPythonManager::registerCPPClassForPythonQt(const char* name)
+{
+  PythonQt::self()->registerCPPClass(name);
+}
+
+//-----------------------------------------------------------------------------
+QVariant ctkAbstractPythonManager::executeString(const QString& code)
+{
+  QVariant ret;
+  PythonQtObjectPtr main = ctkAbstractPythonManager::mainContext();
+  if (main)
+    {
+    ret = main.evalScript(code, Py_single_input);
+    }
+  return ret;
+}
+
+//-----------------------------------------------------------------------------
+void ctkAbstractPythonManager::executeFile(const QString& filename)
+{
+  PythonQtObjectPtr main = ctkAbstractPythonManager::mainContext();
+  if (main)
+    {
+    main.evalFile(filename);
+    }
+}
+
+//-----------------------------------------------------------------------------
+void ctkAbstractPythonManager::addObjectToPythonMain(const QString& name, QObject* obj)
+{
+  PythonQtObjectPtr main = ctkAbstractPythonManager::mainContext();
+  if (main && obj)
+    {
+    main.addObject(name, obj);
+    }
+}
+
+//-----------------------------------------------------------------------------
+QVariant ctkAbstractPythonManager::getVariable(const QString& name)
+{
+  PythonQtObjectPtr main = ctkAbstractPythonManager::mainContext();
+  if (main)
+    {
+    return PythonQt::self()->getVariable(main, name);
+    }
+  return QVariant();
+}
+
+//-----------------------------------------------------------------------------
+void ctkAbstractPythonManager::printStdout(const QString& text)
+{
+  std::cout << qPrintable(text);
+}
+
+//-----------------------------------------------------------------------------
+void ctkAbstractPythonManager::printStderr(const QString& text)
+{
+  std::cout << qPrintable(text);
+}

+ 76 - 0
Libs/Scripting/Python/Core/ctkAbstractPythonManager.h

@@ -0,0 +1,76 @@
+/*=========================================================================
+
+  Library:   CTK
+
+  Copyright (c) Kitware Inc. 
+  All rights reserved.
+  Distributed under a BSD License. See LICENSE.txt file.
+
+  This software is distributed "AS IS" WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the above copyright notice for more information.
+
+=========================================================================*/
+
+#ifndef __ctkAbstractPythonManager_h
+#define __ctkAbstractPythonManager_h
+
+// Qt includes
+#include <QObject>
+#include <QList>
+#include <QStringList>
+
+// CTK includes
+#include "CTKScriptingPythonCoreExport.h"
+
+class PythonQtObjectPtr;
+
+class CTK_SCRIPTING_PYTHON_CORE_EXPORT ctkAbstractPythonManager : public QObject
+{
+  Q_OBJECT
+
+public:
+  typedef QObject Superclass;
+  ctkAbstractPythonManager(QObject* _parent=NULL);
+  ~ctkAbstractPythonManager();
+
+  PythonQtObjectPtr mainContext();
+  void addObjectToPythonMain(const QString& name, QObject* obj);
+  void registerPythonQtDecorator(QObject* decorator);
+  void registerClassForPythonQt(const QMetaObject* metaobject);
+  void registerCPPClassForPythonQt(const char* name);
+
+  ///
+  /// Execute a python of python code (can be multiple lines separated with newline)
+  /// and return the result as a QVariant.
+  QVariant executeString(const QString& code);
+
+  ///
+  /// Gets the value of the variable looking in the __main__ module.
+  /// If the variable is not found returns a default initialized QVariant.
+  QVariant getVariable(const QString& varName);
+
+  ///
+  /// Execute a python script with the given filename.
+  void executeFile(const QString& filename);
+
+signals:
+
+  ///
+  /// This signal is emitted after python is initialized.  Observers can listen
+  /// for this signal to handle additional initialization steps.
+  void pythonInitialized();
+
+protected slots:
+  void printStderr(const QString&);
+  void printStdout(const QString&);
+
+protected:
+
+  void initPythonQt();
+
+  virtual QStringList     pythonPaths();
+  virtual void            preInitialization();
+
+};
+#endif

+ 11 - 0
Libs/Scripting/Python/Core/target_libraries.cmake

@@ -0,0 +1,11 @@
+#
+# See CMake/ctkMacroGetTargetLibraries.cmake
+# 
+# This file should list the libraries required to build the current CTK libraries
+#
+
+SET(target_libraries
+  PYTHON_LIBRARIES
+  PYTHONQT_LIBRARIES
+  CTKCore
+  )

+ 4 - 1
SuperBuild.cmake

@@ -390,7 +390,10 @@ ExternalProject_Add(${proj}
     -DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}
     -DCTK_KWSTYLE_EXECUTABLE:FILEPATH=${CTK_KWSTYLE_EXECUTABLE}
     -DDCMTK_DIR:PATH=${DCMTK_DIR} # FindDCMTK expects DCMTK_DIR
-    -DVTK_DIR:PATH=${VTK_DIR} # FindVTK expects VTK_DIR
+    -DVTK_DIR:PATH=${VTK_DIR}     # FindVTK expects VTK_DIR
+    -DPYTHON_INCLUDE_DIR:PATH=${DPYTHON_INCLUDE_DIR}    # FindPythonQt expects PYTHON_INCLUDE_DIR
+    -DPYTHON_LIBRARY:FILEPATH=${DPYTHON_LIBRARY}        # FindPythonQt expects PYTHON_LIBRARY
+    -DPYTHONQT_INSTALL_DIR:PATH=${PYTHONQT_INSTALL_DIR} # FindPythonQt expects PYTHONQT_INSTALL_DIR
   SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}
   BINARY_DIR ${CMAKE_BINARY_DIR}/CTK-build
   BUILD_COMMAND ""