Parcourir la source

Add ctkModalityWidget to select image modalities

By default, only a subset of modality is visible.
Julien Finet il y a 14 ans
Parent
commit
0b39cb1656

+ 4 - 0
Libs/Widgets/CMakeLists.txt

@@ -66,6 +66,8 @@ SET(KIT_SRCS
   ctkMatrixWidget.h
   ctkMenuButton.cpp
   ctkMenuButton.h
+  ctkModalityWidget.cpp
+  ctkModalityWidget.h
   ctkPathLineEdit.cpp
   ctkPathLineEdit.h
   ctkPixmapIconEngine.cpp
@@ -165,6 +167,7 @@ SET(KIT_MOC_SRCS
   ctkMaterialPropertyWidget.h
   ctkMatrixWidget.h
   ctkMenuButton.h
+  ctkModalityWidget.h
   ctkPathLineEdit.h
   ctkRangeSlider.h
   ctkRangeWidget.h
@@ -207,6 +210,7 @@ SET(KIT_UI_FORMS
   Resources/UI/ctkRangeWidget.ui
   Resources/UI/ctkDateRangeWidget.ui
   Resources/UI/ctkMaterialPropertyWidget.ui
+  Resources/UI/ctkModalityWidget.ui
   Resources/UI/ctkScreenshotDialog.ui
   Resources/UI/ctkSettingsDialog.ui
   Resources/UI/ctkSliderWidget.ui

+ 3 - 0
Libs/Widgets/Plugins/CMakeLists.txt

@@ -49,6 +49,8 @@ SET(PLUGIN_SRCS
   ctkMatrixWidgetPlugin.h
   ctkMenuButtonPlugin.cpp
   ctkMenuButtonPlugin.h
+  ctkModalityWidgetPlugin.cpp
+  ctkModalityWidgetPlugin.h
   ctkPathLineEditPlugin.cpp
   ctkPathLineEditPlugin.h
   ctkRangeSliderPlugin.cpp
@@ -93,6 +95,7 @@ SET(PLUGIN_MOC_SRCS
   ctkMaterialPropertyPreviewLabelPlugin.h
   ctkMatrixWidgetPlugin.h
   ctkMenuButtonPlugin.h
+  ctkModalityWidgetPlugin.h
   ctkPathLineEditPlugin.h
   ctkRangeSliderPlugin.h
   ctkRangeWidgetPlugin.h

+ 68 - 0
Libs/Widgets/Plugins/ctkModalityWidgetPlugin.cpp

@@ -0,0 +1,68 @@
+/*=========================================================================
+
+  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.commontk.org/LICENSE
+
+  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.
+
+=========================================================================*/
+
+// CTK includes
+#include "ctkModalityWidgetPlugin.h"
+#include "ctkModalityWidget.h"
+
+//-----------------------------------------------------------------------------
+ctkModalityWidgetPlugin::ctkModalityWidgetPlugin(QObject* parentObject)
+  : QObject(parentObject)
+{
+}
+
+//-----------------------------------------------------------------------------
+QWidget* ctkModalityWidgetPlugin::createWidget(QWidget* parentWidget)
+{
+  ctkModalityWidget* newWidget = new ctkModalityWidget(parentWidget);
+  return newWidget;
+}
+
+//-----------------------------------------------------------------------------
+QString ctkModalityWidgetPlugin::domXml() const
+{
+  return "<widget class=\"ctkModalityWidget\" \
+          name=\"ModalityWidget\">\n"
+          "</widget>\n";
+}
+
+//-----------------------------------------------------------------------------
+QIcon ctkModalityWidgetPlugin::icon() const
+{
+  return QIcon(":/Icons/pushbutton.png");
+}
+
+//-----------------------------------------------------------------------------
+QString ctkModalityWidgetPlugin::includeFile() const
+{
+  return "ctkModalityWidget.h";
+}
+
+//-----------------------------------------------------------------------------
+bool ctkModalityWidgetPlugin::isContainer() const
+{
+  return false;
+}
+
+//-----------------------------------------------------------------------------
+QString ctkModalityWidgetPlugin::name() const
+{
+  return "ctkModalityWidget";
+}

+ 44 - 0
Libs/Widgets/Plugins/ctkModalityWidgetPlugin.h

@@ -0,0 +1,44 @@
+/*=========================================================================
+
+  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.commontk.org/LICENSE
+
+  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.
+
+=========================================================================*/
+
+#ifndef __ctkModalityWidgetPlugin_h
+#define __ctkModalityWidgetPlugin_h
+
+// CTK includes
+#include "ctkWidgetsAbstractPlugin.h"
+
+class CTK_WIDGETS_PLUGINS_EXPORT ctkModalityWidgetPlugin
+  : public QObject
+  , public ctkWidgetsAbstractPlugin
+{
+  Q_OBJECT
+
+public:
+  ctkModalityWidgetPlugin(QObject *_parent = 0);
+  
+  QWidget *createWidget(QWidget *_parent);
+  QString  domXml() const;
+  QIcon    icon() const;
+  QString  includeFile() const;
+  bool     isContainer() const;
+  QString  name() const;
+};
+
+#endif

+ 2 - 0
Libs/Widgets/Plugins/ctkWidgetsPlugins.h

@@ -43,6 +43,7 @@
 #include "ctkMaterialPropertyWidgetPlugin.h"
 #include "ctkMatrixWidgetPlugin.h"
 #include "ctkMenuButtonPlugin.h"
+#include "ctkModalityWidgetPlugin.h"
 #include "ctkPathLineEditPlugin.h"
 #include "ctkRangeSliderPlugin.h"
 #include "ctkRangeWidgetPlugin.h"
@@ -82,6 +83,7 @@ public:
             << new ctkMaterialPropertyWidgetPlugin
             << new ctkMatrixWidgetPlugin
             << new ctkMenuButtonPlugin
+            << new ctkModalityWidgetPlugin
             << new ctkPathLineEditPlugin
             << new ctkRangeSliderPlugin
             << new ctkRangeWidgetPlugin

+ 501 - 0
Libs/Widgets/Resources/UI/ctkModalityWidget.ui

@@ -0,0 +1,501 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>ctkModalityWidget</class>
+ <widget class="QWidget" name="ctkModalityWidget">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>94</width>
+    <height>1098</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Modality</string>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <property name="margin">
+    <number>0</number>
+   </property>
+   <item>
+    <widget class="QCheckBox" name="AnyCheckBox">
+     <property name="text">
+      <string>Any</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QCheckBox" name="CRCheckBox">
+     <property name="toolTip">
+      <string>Computed Radiography</string>
+     </property>
+     <property name="text">
+      <string>CR</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QCheckBox" name="CTCheckBox">
+     <property name="toolTip">
+      <string>Computed Tomography</string>
+     </property>
+     <property name="text">
+      <string>CT</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QCheckBox" name="MRCheckBox">
+     <property name="toolTip">
+      <string>Magnetic Resonance</string>
+     </property>
+     <property name="text">
+      <string>MR</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QCheckBox" name="NMCheckBox">
+     <property name="toolTip">
+      <string>Nuclear Medicine</string>
+     </property>
+     <property name="text">
+      <string>NM</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QCheckBox" name="USCheckBox">
+     <property name="toolTip">
+      <string>Ultrasound</string>
+     </property>
+     <property name="text">
+      <string>US</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QCheckBox" name="OTCheckBox">
+     <property name="toolTip">
+      <string>Other</string>
+     </property>
+     <property name="text">
+      <string>OT</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QCheckBox" name="BICheckBox">
+     <property name="toolTip">
+      <string>Biomagnetic imaging</string>
+     </property>
+     <property name="text">
+      <string>BI</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QCheckBox" name="CDCheckBox">
+     <property name="toolTip">
+      <string>Color flow Doppler</string>
+     </property>
+     <property name="text">
+      <string>CD</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QCheckBox" name="DDCheckBox">
+     <property name="toolTip">
+      <string>Duplex Doppler</string>
+     </property>
+     <property name="text">
+      <string>DD</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QCheckBox" name="DGCheckBox">
+     <property name="toolTip">
+      <string>Diaphanography</string>
+     </property>
+     <property name="text">
+      <string>DG</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QCheckBox" name="ESCheckBox">
+     <property name="toolTip">
+      <string>Endoscopy</string>
+     </property>
+     <property name="text">
+      <string>ES</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QCheckBox" name="LSCheckBox">
+     <property name="toolTip">
+      <string>Laser surface scan</string>
+     </property>
+     <property name="text">
+      <string>LS</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QCheckBox" name="PTCheckBox">
+     <property name="toolTip">
+      <string>Positron emission tomography (PET)</string>
+     </property>
+     <property name="text">
+      <string>PT</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QCheckBox" name="RGCheckBox">
+     <property name="toolTip">
+      <string>Radiographic imaging (conventional film/screen)</string>
+     </property>
+     <property name="text">
+      <string>RG</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QCheckBox" name="STCheckBox">
+     <property name="toolTip">
+      <string>Single-photon emission computed tomography (SPECT)</string>
+     </property>
+     <property name="text">
+      <string>ST</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QCheckBox" name="TGCheckBox">
+     <property name="toolTip">
+      <string>Thermography</string>
+     </property>
+     <property name="text">
+      <string>TG</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QCheckBox" name="XACheckBox">
+     <property name="toolTip">
+      <string>X-Ray Angiography</string>
+     </property>
+     <property name="text">
+      <string>XA</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QCheckBox" name="RFCheckBox">
+     <property name="toolTip">
+      <string>Radio Fluoroscopy</string>
+     </property>
+     <property name="text">
+      <string>RF</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QCheckBox" name="RTImageCheckBox">
+     <property name="toolTip">
+      <string>Radiotherapy Image</string>
+     </property>
+     <property name="text">
+      <string>RTIMAGE</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QCheckBox" name="RTDoseCheckBox">
+     <property name="toolTip">
+      <string>Radiotherapy Dose</string>
+     </property>
+     <property name="text">
+      <string>RTDOSE</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QCheckBox" name="RTStructCheckBox">
+     <property name="toolTip">
+      <string>Radiotherapy Structure Set</string>
+     </property>
+     <property name="text">
+      <string>RTSTRUCT</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QCheckBox" name="RTPlanCheckBox">
+     <property name="toolTip">
+      <string>Radiotherapy Plan</string>
+     </property>
+     <property name="text">
+      <string>RTPLAN</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QCheckBox" name="RTRectorCheckBox">
+     <property name="toolTip">
+      <string>RT Treatment Record</string>
+     </property>
+     <property name="text">
+      <string>RTRECTORD</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QCheckBox" name="HCCheckBox">
+     <property name="toolTip">
+      <string>Hard Copy</string>
+     </property>
+     <property name="text">
+      <string>HC</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QCheckBox" name="DXCheckBox">
+     <property name="toolTip">
+      <string>Digital Radiography</string>
+     </property>
+     <property name="text">
+      <string>DX</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QCheckBox" name="MGCheckBox">
+     <property name="toolTip">
+      <string>Mammography</string>
+     </property>
+     <property name="text">
+      <string>MG</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QCheckBox" name="IOCheckBox">
+     <property name="toolTip">
+      <string>Intra-oral Radiography</string>
+     </property>
+     <property name="text">
+      <string>IO</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QCheckBox" name="PXCheckBox">
+     <property name="toolTip">
+      <string>Panoramic X-Ray</string>
+     </property>
+     <property name="text">
+      <string>PX</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QCheckBox" name="GMCheckBox">
+     <property name="toolTip">
+      <string>General Microscopy</string>
+     </property>
+     <property name="text">
+      <string>GM</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QCheckBox" name="SMCheckBox">
+     <property name="toolTip">
+      <string>Slide Microscopy</string>
+     </property>
+     <property name="text">
+      <string>SM</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QCheckBox" name="XCCheckBox">
+     <property name="toolTip">
+      <string>External-camera Photography</string>
+     </property>
+     <property name="text">
+      <string>XC</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QCheckBox" name="PRCheckBox">
+     <property name="toolTip">
+      <string>Presentation State</string>
+     </property>
+     <property name="text">
+      <string>PR</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QCheckBox" name="AUCheckBox">
+     <property name="toolTip">
+      <string>Audio</string>
+     </property>
+     <property name="text">
+      <string>AU</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QCheckBox" name="ECGCheckBox">
+     <property name="toolTip">
+      <string>Electrocardiography</string>
+     </property>
+     <property name="text">
+      <string>ECG</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QCheckBox" name="EPSCheckBox">
+     <property name="toolTip">
+      <string>Cardiac Electrophysiology</string>
+     </property>
+     <property name="text">
+      <string>EPS</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QCheckBox" name="HDCheckBox">
+     <property name="toolTip">
+      <string>Hemodynamic Waveform</string>
+     </property>
+     <property name="text">
+      <string>HD</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QCheckBox" name="SRCheckBox">
+     <property name="toolTip">
+      <string>SR Document</string>
+     </property>
+     <property name="text">
+      <string>SR</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QCheckBox" name="IVUSCheckBox">
+     <property name="toolTip">
+      <string>Intravascular Ultrasound</string>
+     </property>
+     <property name="text">
+      <string>IVUS</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QCheckBox" name="OPCheckBox">
+     <property name="toolTip">
+      <string>Ophthalmic Photography</string>
+     </property>
+     <property name="text">
+      <string>OP</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QCheckBox" name="SMRCheckBox">
+     <property name="toolTip">
+      <string>Stereometric Relationship</string>
+     </property>
+     <property name="text">
+      <string>SMR</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QCheckBox" name="OCTCheckBox">
+     <property name="toolTip">
+      <string>Optical Coherence Tomography</string>
+     </property>
+     <property name="text">
+      <string>OCT</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QCheckBox" name="OPRCheckBox">
+     <property name="toolTip">
+      <string>Ophthalmic Refraction</string>
+     </property>
+     <property name="text">
+      <string>OPR</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QCheckBox" name="OPVCheckBox">
+     <property name="toolTip">
+      <string>Ophthalmic Visual Field</string>
+     </property>
+     <property name="text">
+      <string>OPV</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QCheckBox" name="OPMCheckBox">
+     <property name="toolTip">
+      <string>Ophthalmic Mapping</string>
+     </property>
+     <property name="text">
+      <string>OPM</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QCheckBox" name="KOCheckBox">
+     <property name="toolTip">
+      <string>Key Object Selection</string>
+     </property>
+     <property name="text">
+      <string>KO</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QCheckBox" name="SEGCheckBox">
+     <property name="toolTip">
+      <string>Segmentation</string>
+     </property>
+     <property name="text">
+      <string>SEG</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QCheckBox" name="REGCheckBox">
+     <property name="toolTip">
+      <string>Registration</string>
+     </property>
+     <property name="text">
+      <string>REG</string>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>

+ 2 - 0
Libs/Widgets/Testing/Cpp/CMakeLists.txt

@@ -32,6 +32,7 @@ CREATE_TEST_SOURCELIST(Tests ${KIT}CppTests.cxx
   ctkMatrixWidgetTest1.cpp
   ctkMatrixWidgetTest2.cpp
   ctkMenuButtonTest1.cpp
+  ctkModalityWidgetTest1.cpp
   ctkPathLineEditTest1.cpp
   ctkRangeSliderTest1.cpp
   ctkRangeWidgetTest1.cpp
@@ -117,6 +118,7 @@ SIMPLE_TEST( ctkMaterialPropertyWidgetTest1 )
 SIMPLE_TEST( ctkMatrixWidgetTest1 )
 SIMPLE_TEST( ctkMatrixWidgetTest2 )
 SIMPLE_TEST( ctkMenuButtonTest1 )
+SIMPLE_TEST( ctkModalityWidgetTest1 )
 SIMPLE_TEST( ctkPathLineEditTest1 )
 SIMPLE_TEST( ctkRangeSliderTest1 )
 SIMPLE_TEST( ctkRangeWidgetTest1 )

+ 59 - 0
Libs/Widgets/Testing/Cpp/ctkModalityWidgetTest1.cpp

@@ -0,0 +1,59 @@
+/*=========================================================================
+
+  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.commontk.org/LICENSE
+
+  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.
+
+=========================================================================*/
+
+// Qt includes
+#include <QApplication>
+#include <QSignalSpy>
+#include <QTimer>
+
+// CTK includes
+#include "ctkModalityWidget.h"
+
+// STD includes
+#include <iostream>
+
+//-----------------------------------------------------------------------------
+int ctkModalityWidgetTest1(int argc, char * argv [] )
+{
+  QApplication app(argc, argv);
+
+  ctkModalityWidget modalityWidget;
+  
+  QSignalSpy spy(&modalityWidget, SIGNAL(selectedModalitiesChanged(const QStringList&)));
+  modalityWidget.unselectAll();
+
+  if (spy.count() != 1)
+    {
+    std::cerr << "ctkModalityWidget::setProperty(): "
+              << spy.count() << std::endl;
+    return EXIT_FAILURE;
+    }
+  spy.clear();
+
+  modalityWidget.showAll();
+
+  modalityWidget.show();
+  if (argc < 2 || QString(argv[1]) != "-I" )
+    {
+    QTimer::singleShot(200, &app, SLOT(quit()));
+    }
+  return app.exec();
+}
+

+ 283 - 0
Libs/Widgets/ctkModalityWidget.cpp

@@ -0,0 +1,283 @@
+/*=========================================================================
+
+  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.commontk.org/LICENSE
+
+  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.
+
+=========================================================================*/
+
+// Qt includes
+#include <QDebug>
+#include <QStringList>
+
+// CTK includes
+#include "ctkModalityWidget.h"
+#include "ui_ctkModalityWidget.h"
+#include "ctkLogger.h"
+#include "ctkFlowLayout.h"
+
+// STD includes
+#include <cmath>
+
+static ctkLogger logger("org.commontk.libs.widgets.ctkModalityWidget");
+
+QStringList sDefaultVisibleModalities;
+
+//-----------------------------------------------------------------------------
+class ctkModalityWidgetPrivate: public Ui_ctkModalityWidget
+{
+  Q_DECLARE_PUBLIC(ctkModalityWidget);
+protected:
+  ctkModalityWidget* const q_ptr;
+
+public:
+  ctkModalityWidgetPrivate(ctkModalityWidget& object);
+  void init();
+  void updateAnyCheckBoxState();
+  
+  QStringList SelectedModalities;
+  QStringList VisibleModalities;
+  QMap<QString, QCheckBox*> Modalities;
+};
+
+// --------------------------------------------------------------------------
+ctkModalityWidgetPrivate::ctkModalityWidgetPrivate(ctkModalityWidget& object)
+  :q_ptr(&object)
+{
+  if (sDefaultVisibleModalities.isEmpty())
+    {
+    sDefaultVisibleModalities << "CT" << "MR" << "US" << "CR" << "XA" << "NM" << "PT";
+    }
+}
+
+// --------------------------------------------------------------------------
+void ctkModalityWidgetPrivate::init()
+{
+  Q_Q(ctkModalityWidget);
+  this->setupUi(q);
+  
+  this->AnyCheckBox->setTristate(true);
+  QObject::connect(this->AnyCheckBox, SIGNAL(stateChanged(int)),
+                   q, SLOT(onAnyChanged(int)));
+
+  foreach(QCheckBox* box, q->findChildren<QCheckBox*>())
+    {
+    if (box == this->AnyCheckBox)
+      {
+      continue;
+      }
+    this->Modalities[box->text()] = box;
+    QObject::connect(box, SIGNAL(toggled(bool)),
+                     q, SLOT(onModalityChecked(bool)));
+    }
+
+  // reparent items into a flow layout
+  QLayout* layout = q->layout();
+  ctkFlowLayout* flowLayout = new ctkFlowLayout(Qt::Horizontal);
+  flowLayout->setContentsMargins(layout->contentsMargins());
+  flowLayout->setPreferredExpandingDirections(Qt::Vertical);
+  QLayoutItem* item;
+  while ((item = layout->takeAt(0)))
+    {
+    flowLayout->addItem(item);
+    }
+  delete layout;
+  q->setLayout(flowLayout);
+  
+  q->setVisibleModalities(sDefaultVisibleModalities);
+  QSize sizeHint = flowLayout->sizeHint();
+  double area = sizeHint.width() * sizeHint.height();
+  area = sqrt(area);
+  sizeHint = QSize(area, area);
+  q->resize(sizeHint);
+  q->selectAll();
+}
+
+// --------------------------------------------------------------------------
+void ctkModalityWidgetPrivate::updateAnyCheckBoxState()
+{
+  if (this->SelectedModalities.isEmpty())
+    {
+    this->AnyCheckBox->setCheckState(Qt::Unchecked);
+    }
+  else if (this->SelectedModalities.count() == this->Modalities.count())
+    {
+    this->AnyCheckBox->setCheckState(Qt::Checked);
+    }
+  else
+    {
+    this->AnyCheckBox->setCheckState(Qt::PartiallyChecked);
+    }
+}
+
+// --------------------------------------------------------------------------
+ctkModalityWidget::ctkModalityWidget(QWidget* parentWidget)
+  : Superclass(parentWidget)
+  , d_ptr(new ctkModalityWidgetPrivate(*this))
+{
+  Q_D(ctkModalityWidget);
+  d->init();
+}
+
+// --------------------------------------------------------------------------
+ctkModalityWidget::~ctkModalityWidget()
+{
+}
+
+// --------------------------------------------------------------------------
+QStringList ctkModalityWidget::selectedModalities()const
+{
+  Q_D(const ctkModalityWidget);
+  return d->SelectedModalities;
+}
+
+// --------------------------------------------------------------------------
+void ctkModalityWidget::setSelectedModalities(const QStringList& modalities)
+{
+  if (modalities == this->selectedModalities())
+    {
+    return;
+    }
+  bool blocked = this->blockSignals(true);
+  this->unselectAll();
+  foreach(QString modality, modalities)
+    {
+    this->selectModality(modality);
+    }
+  this->blockSignals(blocked);
+  emit this->selectedModalitiesChanged(modalities);
+}
+
+// --------------------------------------------------------------------------
+QStringList ctkModalityWidget::visibleModalities()const
+{
+  Q_D(const ctkModalityWidget);
+  return d->VisibleModalities;
+}
+
+// --------------------------------------------------------------------------
+void ctkModalityWidget::setVisibleModalities(const QStringList& modalities)
+{
+  if (modalities == this->visibleModalities())
+    {
+    return;
+    }
+  this->hideAll();
+  foreach(QString modality, modalities)
+    {
+    this->showModality(modality);
+    }
+}
+
+// --------------------------------------------------------------------------
+void ctkModalityWidget::selectModality(const QString& modality, bool select)
+{
+  Q_D(ctkModalityWidget);
+  QCheckBox* modalityBox = d->Modalities[modality];
+  modalityBox->setChecked(select);
+}
+
+// --------------------------------------------------------------------------
+void ctkModalityWidget::showModality(const QString& modality, bool show)
+{
+  Q_D(ctkModalityWidget);
+  QCheckBox* modalityBox = d->Modalities[modality];
+  modalityBox->setVisible(show);
+}
+
+// --------------------------------------------------------------------------
+void ctkModalityWidget::selectAll()
+{
+  Q_D(ctkModalityWidget);
+  if (d->SelectedModalities.count() == d->Modalities.count())
+    {
+    return;
+    }
+  bool blocked = this->blockSignals(true);
+  foreach(const QString& modality, d->Modalities.keys())
+    {
+    this->selectModality(modality, true);
+    }
+  this->blockSignals(blocked);
+  emit this->selectedModalitiesChanged(d->SelectedModalities);
+}
+
+// --------------------------------------------------------------------------
+void ctkModalityWidget::unselectAll()
+{
+  Q_D(ctkModalityWidget);
+  if (d->SelectedModalities.count() == 0)
+    {
+    return;
+    }
+  bool blocked = this->blockSignals(true);
+  foreach(const QString& modality, d->Modalities.keys())
+    {
+    this->selectModality(modality, false);
+    }
+  this->blockSignals(blocked);
+  emit this->selectedModalitiesChanged(d->SelectedModalities);
+}
+
+// --------------------------------------------------------------------------
+void ctkModalityWidget::showAll()
+{
+  Q_D(ctkModalityWidget);
+  foreach(const QString& modality, d->Modalities.keys())
+    {
+    this->showModality(modality, true);
+    }
+}
+
+// --------------------------------------------------------------------------
+void ctkModalityWidget::hideAll()
+{
+  Q_D(ctkModalityWidget);
+  foreach(const QString& modality, d->Modalities.keys())
+    {
+    this->showModality(modality, false);
+    }
+}
+
+// --------------------------------------------------------------------------
+void ctkModalityWidget::onAnyChanged(int state)
+{
+  if (state == Qt::Unchecked)
+    {
+    this->unselectAll();
+    }
+  else if (state == Qt::Checked)
+    {
+    this->selectAll();
+    }
+}
+
+// --------------------------------------------------------------------------
+void ctkModalityWidget::onModalityChecked(bool checked)
+{
+  Q_D(ctkModalityWidget);
+  QCheckBox* box = qobject_cast<QCheckBox*>(this->sender());
+  QString modality = box->text();
+  if (checked)
+    {
+    d->SelectedModalities.append(modality);
+    }
+  else
+    {
+    d->SelectedModalities.removeAll(modality);
+    }
+  d->updateAnyCheckBoxState();    
+  emit this->selectedModalitiesChanged(d->SelectedModalities);
+}

+ 79 - 0
Libs/Widgets/ctkModalityWidget.h

@@ -0,0 +1,79 @@
+/*=========================================================================
+
+  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.commontk.org/LICENSE
+
+  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.
+
+=========================================================================*/
+
+#ifndef __ctkModalityWidget_h
+#define __ctkModalityWidget_h
+
+// Qt includes
+#include <QWidget>
+
+// CTK includes
+#include "ctkWidgetsExport.h"
+class ctkModalityWidgetPrivate;
+
+///
+/// ctkModalityWidget allows the user to ...
+class CTK_WIDGETS_EXPORT ctkModalityWidget : public QWidget
+{
+  Q_OBJECT
+  Q_PROPERTY(QStringList selectedModalities READ selectedModalities WRITE setSelectedModalities)
+  Q_PROPERTY(QStringList visibleModalities READ visibleModalities WRITE setVisibleModalities)
+public:
+  /// Superclass typedef
+  typedef QWidget Superclass;
+
+  /// Constructor
+  /// If \li parent is null, ctkModalityWidget will be a top-level widget
+  /// \note The \li parent can be set later using QWidget::setParent()
+  explicit ctkModalityWidget(QWidget* parent = 0);
+  
+  /// Destructor
+  virtual ~ctkModalityWidget();
+
+  QStringList selectedModalities()const;
+  void setSelectedModalities(const QStringList& modalities);
+  
+  QStringList visibleModalities()const;
+  void setVisibleModalities(const QStringList& modalities);
+  
+  void selectModality(const QString& modality, bool select = true);
+  void showModality(const QString& modality, bool show = true);
+  
+  void showAll();
+  void hideAll();
+public slots:
+  void selectAll();
+  void unselectAll();
+
+signals:
+  void selectedModalitiesChanged(const QStringList modalities);
+protected slots:
+  void onAnyChanged(int state);
+  void onModalityChecked(bool);
+
+protected:
+  QScopedPointer<ctkModalityWidgetPrivate> d_ptr;
+
+private:
+  Q_DECLARE_PRIVATE(ctkModalityWidget);
+  Q_DISABLE_COPY(ctkModalityWidget);
+};
+
+#endif