32
Port of 3D Slicer to Qt Julien Finet & Jean-Christophe Fillion- Robin Kitware Inc. June 22 th 2010

Port of 3D Slicer to Qt Julien Finet & Jean-Christophe Fillion-Robin Kitware Inc. June 22 th 2010

Embed Size (px)

Citation preview

Page 1: Port of 3D Slicer to Qt Julien Finet & Jean-Christophe Fillion-Robin Kitware Inc. June 22 th 2010

Port of 3D Slicer to Qt

Julien Finet & Jean-Christophe Fillion-RobinKitware Inc.June 22th 2010

Page 2: Port of 3D Slicer to Qt Julien Finet & Jean-Christophe Fillion-Robin Kitware Inc. June 22 th 2010

Background

• Slicer version 3.x use KWWidgets– VTK-style interface to Tk– 3D Slicer 1.x, 2.x used Tk directly

• Qt– Embedded Linux, Mac OS X, Windows,

Linux/X11, Windows CE/Mobile, Symbian, Maemo

– Commercial/LGPL– 600+ classes– Tens of thousands of applications– 15+ millions of users

Page 3: Port of 3D Slicer to Qt Julien Finet & Jean-Christophe Fillion-Robin Kitware Inc. June 22 th 2010

Qt – How to get Qt

• Required version: Qt 4.6.2

• Building Slicer with Qt – Use Superbuild– http://www.slicer.org/slicerWiki/index.php/

Slicer4:Build_Instructions

Page 4: Port of 3D Slicer to Qt Julien Finet & Jean-Christophe Fillion-Robin Kitware Inc. June 22 th 2010

Events with KWWidgets

1. Connect vtkCallbackCommand

vtkObject::AddObserver

2. Fire eventvtkObject::InvokeEvent()

3. ProcessmyClass::myMethod()

Page 5: Port of 3D Slicer to Qt Julien Finet & Jean-Christophe Fillion-Robin Kitware Inc. June 22 th 2010

Events with KWWidgets

Object 1 Object 2

Object2 Callback

Node Selected

Event

Page 6: Port of 3D Slicer to Qt Julien Finet & Jean-Christophe Fillion-Robin Kitware Inc. June 22 th 2010

Events with KWWidgets 1) Connect

Object 1 Object 2MethodX

Node Selected

Event

this->CallbackCommand = vtkCallbackCommand::New();this->CallbackCommand->SetClientData(object2); this->CallbackCommand->SetCallback(vtkObject2::MethodX);

Object2 Callback

Page 7: Port of 3D Slicer to Qt Julien Finet & Jean-Christophe Fillion-Robin Kitware Inc. June 22 th 2010

Object2 Callback

Events with KWWidgets 1) Connect

Object 1 Object 2

object1>AddObserver(vtkObject1::NodeSelectedEvent, this>CallbackCommand);

Node Selected

Event

Page 8: Port of 3D Slicer to Qt Julien Finet & Jean-Christophe Fillion-Robin Kitware Inc. June 22 th 2010

Events with KWWidgets 2) Signal

Object 1 Object 2Method2

void vtkObject1::Method2(){ … this->InvokeEvent(vtkObject1::NodeSelectedEvent, NULL);}

Object2 Callback

Node Selected

Event

Page 9: Port of 3D Slicer to Qt Julien Finet & Jean-Christophe Fillion-Robin Kitware Inc. June 22 th 2010

void vtkObject2::MethodX(vtkObject *caller, unsigned long event, void *callData ){ if (vtkObject2::SafeDownCast(caller) && event == vtkObject2::NodeSelectedEvent) { …

Events with KWWidgets 3) Process

Object 1 Object 2MethodX

Node Selected

Event

Object2 Callback

Page 10: Port of 3D Slicer to Qt Julien Finet & Jean-Christophe Fillion-Robin Kitware Inc. June 22 th 2010

Events with Qt

1. Connect QObject::connect(obj1,signal, obj2, slot);

2. Fire eventemit mySignal();

3. ProcessmyClass::mySlot();

Page 11: Port of 3D Slicer to Qt Julien Finet & Jean-Christophe Fillion-Robin Kitware Inc. June 22 th 2010

Events with Qt

Object 1 Object 2

Node Selected

Signal

Page 12: Port of 3D Slicer to Qt Julien Finet & Jean-Christophe Fillion-Robin Kitware Inc. June 22 th 2010

Events with Qt 1) Connect

Object 1 Object 2

this->QObject::connect(obj1, SIGNAL(nodeSelected(vtkMRMLNode*)), obj2, SLOT(methodX(vtkMRMLNode*)));

Node Selected

Signal

Page 13: Port of 3D Slicer to Qt Julien Finet & Jean-Christophe Fillion-Robin Kitware Inc. June 22 th 2010

Events with Qt 2) Signal

Object 1 Object 2

Node Selected

Signal

void vtkObject1::Method2(){ … emit this->currentNodeSelected(node);}

Page 14: Port of 3D Slicer to Qt Julien Finet & Jean-Christophe Fillion-Robin Kitware Inc. June 22 th 2010

Events with Qt 3) Process

Object 1 Object 2MethodX

Node Selected

Signal

void vtkObject2::MethodX(vtkMRMLNode* node){ …}

Page 15: Port of 3D Slicer to Qt Julien Finet & Jean-Christophe Fillion-Robin Kitware Inc. June 22 th 2010

Qt and VTK: qVTKConnect

• qvtkConnect(vtkObject* vtk_obj, unsigned long vtk_event,

const QObject* qt_obj, const char* qt_slot, float priority = 0.0)

• Also: qvtkReconnect, qvtkDisconnect, qvtkDisconnectAll…

Page 16: Port of 3D Slicer to Qt Julien Finet & Jean-Christophe Fillion-Robin Kitware Inc. June 22 th 2010

Qt and VTK: qVTKConnect

Usage// CTK includes#include <ctkVTKObject.h>…class MyWidget: public QWidget{ Q_OBJECT QVTK_OBJECTpublic:void setNode(vtkMRMLNode* mrmlNode);

protected slots: void onMRMLNodeModified(vtkObject* sender);};

…void MyWidget::setNode(vtkMRMLNode* mrmlNode){ …qvtkConnect( mrmlNode, vtkCommand::ModifiedEvent, this, SLOT(onMRMLNodeModified(vtkObject*))); …}

void MyWidget::onMRMLNodeModified(vtkObject* sender){ vtkMRMLNode* node = vtkMRMLNode::SafeDowncast(sender); …}

QVTK_OBJECT adds the function qvtkConnect()

Page 17: Port of 3D Slicer to Qt Julien Finet & Jean-Christophe Fillion-Robin Kitware Inc. June 22 th 2010

Interaction between MRML & Qt

MRML Node

Module Widget

Qt Slider

void onNodeModified( vtkMRMLNode* node){ slider->setValue(node->GetValue());}

Modified Event

void onValueChanged(double newValue){ node->SetValue(newValue);}

valueChanged(double)

Page 18: Port of 3D Slicer to Qt Julien Finet & Jean-Christophe Fillion-Robin Kitware Inc. June 22 th 2010

Private Implementation

• Hide the implementation details of an interface

• http://en.wikipedia.org/wiki/Opaque_pointer

#include "qCTKPimpl.h"…class MyButtonPrivate;…class MyButton : public QAbstractButton{ Q_OBJECTpublic: …private: CTK_DECLARE_PRIVATE(MyButton);}; friend class MyButtonPrivate;

ctkPrivateInterface<MyButton, MyButtonPrivate> ctk_d;

Don’t forget to declare the private class

Page 19: Port of 3D Slicer to Qt Julien Finet & Jean-Christophe Fillion-Robin Kitware Inc. June 22 th 2010

Private Implementationclass MyButtonPrivate : public qCTKPrivate<MyButton>{public: CTK_DECLARE_PUBLIC(MyButton); void init(); bool Collapsed; …};

void MyButtonPrivate::init(){ CTK_P(MyButton); p->setCheckable(true); this->Collapsed = false;}

MyButton::MyButton(QWidget* parent) :QAbstractButton(parent){ CTK_INIT_PRIVATE(MyButton); ctk_d()->init();}

void MyButton::collapse(bool c){ CTK_D(MyButton); if (c == d->Collapsed) { return; } …}MyButtonPrivate* d = ctk_d()

MyButton* p = ctk_p()

Page 20: Port of 3D Slicer to Qt Julien Finet & Jean-Christophe Fillion-Robin Kitware Inc. June 22 th 2010

Slicer3 vs SlicerQt

• SlicerQtQt only

• Slicer3 KWWidgets + Qt

Page 21: Port of 3D Slicer to Qt Julien Finet & Jean-Christophe Fillion-Robin Kitware Inc. June 22 th 2010

Slicer

qMRMLWidgets QtGUI

Slicer Architecture

QtCoreCTKCore

CTKWidgets

Base/QTCore

Base/QTGUI

Base/Logic MRML

Page 22: Port of 3D Slicer to Qt Julien Finet & Jean-Christophe Fillion-Robin Kitware Inc. June 22 th 2010

Modules

• Core Modules: Slicer3/Base/QTCoreModules– Transforms qSlicerTransformsModule– …

• Loadable Modules: Slicer3/QTModules– TractographyFiducialSeeding libqSlicerTractographyFiducialSeedingModule.so

– Volumes libqSlicerVolumesModule.so– …

• CLI Modules: Slicer3/Applications/CLI– …

Page 23: Port of 3D Slicer to Qt Julien Finet & Jean-Christophe Fillion-Robin Kitware Inc. June 22 th 2010

QTCLI

• Same idea than KWWidgets– Parse XML to build UI

• Support– Shared Libraries– Executables– Python

UI panel in Slicer

Page 24: Port of 3D Slicer to Qt Julien Finet & Jean-Christophe Fillion-Robin Kitware Inc. June 22 th 2010

QTCLI: Example…<parameters> <label>Registration Parameters</label> <description>Parameters used for registration</description> <integer> <name>HistogramBins</name> <flag>b</flag> <longflag>histogrambins</longflag> <description>Number of histogram bins to use for Mattes Mutual Information. </description> <label>Histogram Bins</label> <default>30</default> <constraints> <minimum>1</minimum> <maximum>500</maximum> <step>5</step> </constraints> </integer>…

…If (paramType == “integer”) { QSlider* intParameter = new QSlider(registrationParameters); intParameter->setMinimum(paramMin); intParameter->setMaximum(paramMax); intParameter->setStep(paramStep); intParameter->setValue(paramValue); QObject::connect(intParameter, SIGNAL(valueChanged(int)), this, SIGNAL(onParamValueChanged(int))); }else if (paramType == “double”) …

3) Dynamically created panel

1) Xml description

2) Parse parameters and generate UI

Page 25: Port of 3D Slicer to Qt Julien Finet & Jean-Christophe Fillion-Robin Kitware Inc. June 22 th 2010

Plugin Mechanism

• Previously: itksys::DynamicLoader(dlopen)

• Now: Use the QT Plugins framework…class Q_SLICER_QTMODULES_VOLUMES_EXPORT qSlicerVolumesModule : public qSlicerAbstractLoadableModule{ Q_INTERFACES(qSlicerAbstractLoadableModule);public: …};

…Q_EXPORT_PLUGIN2(qSlicerVolumesModule, qSlicerVolumesModule);…

QPluginLoader loader;loader.setFileName(pluginPath);loader.load();QObject * object = this->Loader.instance();qSlicerAbstractLoadableModule* module = qobject_cast<qSlicerAbstractLoadableModule*>(object); Plugin Loader

Plugin implementation

Plugin header

Page 26: Port of 3D Slicer to Qt Julien Finet & Jean-Christophe Fillion-Robin Kitware Inc. June 22 th 2010

Loadable Modules: Logic + UI

Logic(vtkSlicerModuleLogic)

create()create() create()create()

Module Widget (qSlicerAbstractModuleWidget)

Module Plugin(qSlicerAbstractModule)

vtkMRMLSceneModule Designer UIqSlicer…ModuleWidget.ui

Page 27: Port of 3D Slicer to Qt Julien Finet & Jean-Christophe Fillion-Robin Kitware Inc. June 22 th 2010

Widgets Awareness

Library QTCore QtGui VTK MRML App.

CTK/Libs/Core Yes

CTK/Libs/Widgets Yes Yes

CTK/Libs/Visualization/VTK/Core Yes Yes

CTK/Libs/Visualization/VTK/Widgets Yes Yes

Slicer3/Libs/qMRMLWidgets Yes Yes Yes Yes

Slicer3/Base/QTCore Yes Yes Yes Yes

Slicer3/Base/QTGUI Yes Yes Yes Yes Yes

Page 28: Port of 3D Slicer to Qt Julien Finet & Jean-Christophe Fillion-Robin Kitware Inc. June 22 th 2010

CTK Widgets commontk.org

• http://www.commontk.org/index.php/Documentation/ImageGallery

ctkCollapsibleButton

ctkCollapsibleGroupBox

ctkColorPickerButton ctkTreeComboBox

ctkFixedTitleComboBox

Page 29: Port of 3D Slicer to Qt Julien Finet & Jean-Christophe Fillion-Robin Kitware Inc. June 22 th 2010

qMRMLWidgets• http://wiki.slicer.org/slicerWiki/index.php/

Slicer3:Developers:Projects:QtSlicer/Gallery• Usually contains the slot setMRMLScene(vtkMRMLScene*)

qMRMLNodeSelector

qMRMLTreeWidget

qMRMLListWidget

qMRMLWindowLevelWidget

Page 30: Port of 3D Slicer to Qt Julien Finet & Jean-Christophe Fillion-Robin Kitware Inc. June 22 th 2010

Widgets in Qt Designer

• A plugin must be created– Slicer3/Libs/qMRMLWidgets/Plugins/qMRMLNodeSelectorPlugin.[h|cxx]

• More info on– http://wiki.slicer.org/slicerWiki/index.php/Slicer3:Developers:Projects:QtSlicer/Tutorials/WidgetWriting

Page 31: Port of 3D Slicer to Qt Julien Finet & Jean-Christophe Fillion-Robin Kitware Inc. June 22 th 2010

Widget ExampleQt Designer

class QCTK_WIDGETS_EXPORT qCTKCollapsibleButton : public QAbstractButton{ Q_OBJECT Q_PROPERTY(bool collapsed READ collapsed WRITE setCollapsed) Q_PROPERTY(int collapsedHeight READ collapsedHeight WRITE setCollapsedHeight) …

public: void setCollapsed(bool); bool collapsed()const;

void setCollapsedHeight(int); int collapsedHeight()const;

qCTKCollapsibleButton.h

void qCTKCollapsibleButtonPrivate::init(){ QCTK_P(qCTKCollapsibleButton); … this->Collapsed = false; … this->CollapsedHeight = 10; …} qCTKCollapsibleButton.cxx

10 = default value

Page 32: Port of 3D Slicer to Qt Julien Finet & Jean-Christophe Fillion-Robin Kitware Inc. June 22 th 2010

Questions

• More info: http://wiki.slicer.org/slicerWiki/index.php/Slicer3:Developers:Projects:QtSlicer