Documentation/Nightly/Developers/Tutorials/MigrationGuide/VTK7-Qt4-to-VTK8-Qt5
Contents
- 1 Migration Guide
- 1.1 Qt5: Update loadable modules to use new plugin macros
- 1.2 Qt5: Update DesignerPlugin to use QtUiPlugin/QDesignerCustomWidgetInterface
- 1.3 Qt5: any use of QWebKit needs to switch to QWebEngine
- 1.4 VTK8: Use hierarchy files for VTK Python wrapping
- 1.5 VTK8: Use of vtkTypeMacro requires to use the correct base class
- 1.6 VTK8: Copy constructor and equal operator should be disabled
- 1.7 VTK8: Call InitializeObjectBase() in vtkObject New() methods
- 1.8 VTK8: Add C++11 keywords
- 1.9 Qt5: QVTKOpenGLWidget
- 1.10 VTK8: vtkWindowToImageFilter::SetMagnification() is deprecated
- 1.11 Enable C++11 in extensions
- 1.12 Qt5: Fix error: 'class QString' has no member named 'toAscii'
- 1.13 Qt5: Fix error: ‘class QHeaderView’ has no member named ‘setResizeMode’
- 1.14 VTK8: vtkInstantiator is deprecated
Migration Guide
This section lists categories of code changes necessary to build and run Slicer with VTK 8.0 and Qt5. Each category has a short description, a suggested upgrade path, and references to relevant commits (TBD once merged).
Qt5: Update loadable modules to use new plugin macros
In Qt5, the Q_EXPORT_PLUGIN
, Q_EXPORT_PLUGIN2
macros have been deprecated in favor of the new Q_PLUGIN_METADATA
macro.
Error message similar to:
error: static assertion failed: Old plugin system used
Solution (part 1):
In qSlicer<NameOfModule>Module.h, replace lines like:
Q_OBJECT Q_INTERFACES(qSlicerLoadableModule);
with:
Q_OBJECT #ifdef Slicer_HAVE_QT5 Q_PLUGIN_METADATA(IID "org.slicer.modules.loadable.qSlicerLoadableModule/1.0"); #endif Q_INTERFACES(qSlicerLoadableModule);
Solution (part 2):
In qSlicer<NameOfModule>Module.cxx, Replace lines like:
Q_EXPORT_PLUGIN2(qSlicer<NameOfModule>Module, qSlicer<NameOfModule>Module);
with:
#if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0)) #include <QtPlugin> Q_EXPORT_PLUGIN2(qSlicer<NameOfModule>Module, qSlicer<NameOfModule>Module); #endif
References:
Qt5: Update DesignerPlugin to use QtUiPlugin/QDesignerCustomWidgetInterface
In Qt5, the QtDesigner/QDesignerCustomWidgetInterface
header have been deprecated in favor of the new QtUiPlugin/QDesignerCustomWidgetInterface
header.
Error message similar to:
/path/to/include/QtDesigner/QDesignerCustomWidgetInterface:4:4: warning: #warning Header <QtDesigner/QDesignerCustomWidgetInterface> is deprecated. Please include <QtUiPlugin/QDesignerCustomWidgetInterface> instead. [-Wcpp] # warning Header <QtDesigner/QDesignerCustomWidgetInterface> is deprecated. Please include <QtUiPlugin/QDesignerCustomWidgetInterface> instead. ^
Solution (part 1):
In Widgets/DesignerPlugins/qSlicer<NameOfModule>ModuleWidgetsAbstractPlugin.h, replace lines like:
#include <QDesignerCustomWidgetInterface>
with:
#include <QtGlobal> #if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0)) #include <QDesignerCustomWidgetInterface> #else #include <QtUiPlugin/QDesignerCustomWidgetInterface> #endif
Solution (part 2):
In Widgets/DesignerPlugins/qSlicer<NameOfModule>ModuleWidgetsAbstractPlugin.h, replace lines like:
Q_INTERFACES(QDesignerCustomWidgetInterface);
with:
#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)) Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QDesignerCustomWidgetInterface") #endif Q_INTERFACES(QDesignerCustomWidgetInterface);
Qt5: any use of QWebKit needs to switch to QWebEngine
TBD
VTK8: Use hierarchy files for VTK Python wrapping
In VTK8 it's necessary to generate hierarchy files for proper wrapping VTK classes in Python. Without the information provided by the hierarchy files, the Python wrapping tool lacks complete information about classes and types. In this case, the generated classes contain methods that shouldn't be wrapped and fail to compile, and include references to types such as vtkTypeBool. Once the hierarchy files are generated and provided to the Python wrapping tool, the generated classes compile and typedefs like vtkTypeBool are correctly resolved.
Once the VTK8 changes are merged, generating hierarchy files is handled by https://github.com/Slicer/Slicer/blob/master/CMake/vtkMacroKitPythonWrap.cmake.
References:
VTK8: Use of vtkTypeMacro requires to use the correct base class
Error message similar to:
error: expected unqualified-id before 'protected'
This error is usually a symptom of an incorrect base class when using vtkTypeMacro.
Solution:
Assuming the class vtkIGTLToMRMLPoint derives from vtkIGTLToMRMLBase,
Replace lines like:
vtkTypeMacro(vtkIGTLToMRMLPoint,vtkObject);
with:
vtkTypeMacro(vtkIGTLToMRMLPoint,vtkIGTLToMRMLBase);
References:
VTK8: Copy constructor and equal operator should be disabled
Error message similar to:
error: use of deleted function 'vtkMyClass::vtkMyClass(const vtkMyClass&)'
This error is usually a symptom of not disabling the copy constructor and equal operator.
Solution:
Replace lines like:
protected: vtkMyClass(); ~vtkMyClass();
with:
protected: vtkMyClass(); ~vtkMyClass(); vtkMyClass(const vtkMyClass&); void operator=(const vtkMyClass&);
VTK8: Call InitializeObjectBase() in vtkObject New() methods
In VTK8 it's necessary for vtkObject New() methods to call InitializeObjectBase() on the new object for proper tracking with vtkDebugLeaks. The standard macros (vtkStandardNewMacro, vtkObjectFactoryNewMacro) handle this. For those classes that don't use the macros, add a call to InitializeObjectBase() immediately after constructing the object by new vtkXXX().
Additionally, vtkObjectFactory::CreateInstance() now doesn't register the class name with vtkDebugLeaks if the factory fails to create the object. Therefore, it's no longer necessary to unregister the class name with vtkDebugLeaks. Remove calls to vtkDebugLeaks::DestructClass(className) following vtkObjectFactory::CreateInstance().
To support both VTK8 and earlier versions of VTK, wrap these changes in preprocessor checks for whether VTK_HAS_INITIALIZE_OBJECT_BASE is defined.
References:
- https://github.com/Kitware/VTK/commit/e5c793dbdf87e838bb2b60c6a5905ced0e5548f9
- http://public.kitware.com/pipermail/vtk-developers/2016-September/034332.html
VTK8: Add C++11 keywords
VTK8 requires C++11. Subclasses of VTK classes must mark overridden methods with VTK_OVERRIDE.
Qt5: QVTKOpenGLWidget
When using Qt5, QVTKOpenGLWidget should be used in place of QVTKGLWidget. To ensure that QVTKOpenGLWidget receives a properly configured OpenGL context it's necessary to call QSurfaceFormat::setDefaultFormat() before constructing the QApplication instance. QVTKOpenGLWidget::defaultFormat() supplies a suitable format, although it's recommended to disable multisampling for full compatibility with advanced rendering techniques. See http://doc.qt.io/qt-5/qopenglwidget.html.
VTK8: vtkWindowToImageFilter::SetMagnification() is deprecated
VTK8.1 deprecated vtkWindowToImageFilter::SetMagnification() and vtkWindowToImageFilter::GetMagnification(). Replace calls to those methods with SetScale() and GetScale(). See https://github.com/Kitware/VTK/commit/af0a95fa7dd4e25ef869a0bc6077e547f18baa29.
Enable C++11 in extensions
SuperBuild extensions may have to enable C++11 for their external projects. Add the following lines to CMAKE_CACHE_ARGS in ExternalProject_Add
-DCMAKE_CXX_STANDARD:STRING=${CMAKE_CXX_STANDARD} -DCMAKE_CXX_STANDARD_REQUIRED:BOOL=${CMAKE_CXX_STANDARD_REQUIRED} -DCMAKE_CXX_EXTENSIONS:BOOL=${CMAKE_CXX_EXTENSIONS}
Qt5: Fix error: 'class QString' has no member named 'toAscii'
Replace call to toAscii().data()
with toLatin1().data()
References:
Qt5: Fix error: ‘class QHeaderView’ has no member named ‘setResizeMode’
Error message similar to:
error: ‘class QHeaderView’ has no member named ‘setResizeMode’ headerView->setResizeMode(FileColumn, QHeaderView::Stretch);
Solution:
Replace lines like:
headerView->setResizeMode(FileColumn, QHeaderView::Stretch);
with:
#if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0)) headerView->setResizeMode(FileColumn, QHeaderView::Stretch); #else headerView->setSectionResizeMode(FileColumn, QHeaderView::Stretch); #endif
VTK8: vtkInstantiator is deprecated
VTK8.1 deprecated vtkInstantiator. See https://github.com/Kitware/VTK/commit/11bb6a4d395e877847355a63de2e2e8f8d9e1d91
Error message similar to:
/path/to/SlicerIGT-Release/ToolWatchdog/MRMLDM/WatchdogInstantiator.cxx:10:1: error: expected constructor, destructor, or type conversion before ‘void’ void WatchdogInstantiator::ClassInitialize() ^ /path/to/SlicerIGT-Release/ToolWatchdog/MRMLDM/WatchdogInstantiator.cxx: In static member function ‘static void WatchdogInstantiator::ClassFinalize()’: /path/to/SlicerIGT-Release/ToolWatchdog/MRMLDM/WatchdogInstantiator.cxx:21:3: error: ‘vtkInstantiator’ has not been declared vtkInstantiator::UnRegisterInstantiator("vtkMRMLWatchdogDisplayableManager", vtkInstantiatorvtkMRMLWatchdogDisplayableManagerNew); ^ /path/to/SlicerIGT-Release/ToolWatchdog/MRMLDM/WatchdogInstantiator.cxx:21:80: error: ‘vtkInstantiatorvtkMRMLWatchdogDisplayableManagerNew’ was not declared in this scope vtkInstantiator::UnRegisterInstantiator("vtkMRMLWatchdogDisplayableManager", vtkInstantiatorvtkMRMLWatchdogDisplayableManagerNew); ^
Solution:
Update associated CMakeLists.txt replacing lines like:
set(VTK_USE_INSTANTIATOR_NEW 1) if(${VTK_VERSION_MAJOR} GREATER 5) include(${VTK_CMAKE_DIR}/vtkMakeInstantiator.cmake) endif() VTK_MAKE_INSTANTIATOR3("${MODULE_NAME}Instantiator" displayable_manager_instantiator_SRCS "${displayable_manager_SRCS}" "${${KIT}_EXPORT_DIRECTIVE}" ${CMAKE_CURRENT_BINARY_DIR} "${KIT}Export.h" )
with:
SlicerConfigureDisplayableManagerObjectFactory( TARGET_NAME ${KIT} SRCS "${displayable_manager_SRCS}" EXPORT_MACRO "${${KIT}_EXPORT_DIRECTIVE}" EXPORT_HEADER "${KIT}Export.h" OUTPUT_SRCS_VAR displayable_manager_instantiator_SRCS )