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

Merge branch 'ctksettingswidget'

* ctksettingswidget:
  Add plugin to ctkSettingsWidget and ctkSettingsPanel
  Add ctkSettingsWidget and ctkSettingsPanel
Julien Finet пре 14 година
родитељ
комит
e57f73485a

+ 7 - 0
Libs/Widgets/CMakeLists.txt

@@ -73,6 +73,10 @@ SET(KIT_SRCS
   ctkScreenshotDialog_p.h
   ctkSettings.cpp
   ctkSettings.h
+  ctkSettingsPanel.cpp
+  ctkSettingsPanel.h
+  ctkSettingsWidget.cpp
+  ctkSettingsWidget.h
   ctkSliderWidget.cpp
   ctkSliderWidget.h
   ctkTestApplication.cpp
@@ -144,6 +148,8 @@ SET(KIT_MOC_SRCS
   ctkScreenshotDialog.h
   ctkScreenshotDialog_p.h
   ctkSettings.h
+  ctkSettingsPanel.h
+  ctkSettingsWidget.h
   ctkSliderWidget.h
   ctkTestApplication.h
   ctkToolTipTrapper.h
@@ -171,6 +177,7 @@ SET(KIT_UI_FORMS
   Resources/UI/ctkDateRangeWidget.ui
   Resources/UI/ctkMaterialPropertyWidget.ui
   Resources/UI/ctkScreenshotDialog.ui
+  Resources/UI/ctkSettingsWidget.ui
   Resources/UI/ctkSliderWidget.ui
   Resources/UI/ctkWorkflowGroupBox.ui
   )

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

@@ -55,6 +55,10 @@ SET(PLUGIN_SRCS
   ctkTransferFunctionViewPlugin.h
   ctkTreeComboBoxPlugin.cpp
   ctkTreeComboBoxPlugin.h
+  ctkSettingsPanelPlugin.cpp
+  ctkSettingsPanelPlugin.h
+  ctkSettingsWidgetPlugin.cpp
+  ctkSettingsWidgetPlugin.h
   ctkSliderWidgetPlugin.cpp
   ctkSliderWidgetPlugin.h
   ctkWorkflowButtonBoxWidgetPlugin.cpp
@@ -88,6 +92,8 @@ SET(PLUGIN_MOC_SRCS
   ctkRangeWidgetPlugin.h
   ctkTransferFunctionViewPlugin.h
   ctkTreeComboBoxPlugin.h
+  ctkSettingsPanelPlugin.h
+  ctkSettingsWidgetPlugin.h
   ctkSliderWidgetPlugin.h
   ctkWorkflowButtonBoxWidgetPlugin.h
   ctkWorkflowWidgetStepPlugin.h

+ 6 - 5
Libs/Widgets/Plugins/ctkMaterialPropertyWidgetPlugin.cpp

@@ -23,15 +23,16 @@
 #include "ctkMaterialPropertyWidget.h"
 
 //-----------------------------------------------------------------------------
-ctkMaterialPropertyWidgetPlugin::ctkMaterialPropertyWidgetPlugin(QObject *_parent) : QObject(_parent)
+ctkMaterialPropertyWidgetPlugin::ctkMaterialPropertyWidgetPlugin(QObject *pluginParent)
+  : QObject(pluginParent)
 {
 }
 
 //-----------------------------------------------------------------------------
-QWidget *ctkMaterialPropertyWidgetPlugin::createWidget(QWidget *_parent)
+QWidget *ctkMaterialPropertyWidgetPlugin::createWidget(QWidget *widgetParent)
 {
-  ctkMaterialPropertyWidget* _widget = new ctkMaterialPropertyWidget(_parent);
-  return _widget;
+  ctkMaterialPropertyWidget* newWidget = new ctkMaterialPropertyWidget(widgetParent);
+  return newWidget;
 }
 
 //-----------------------------------------------------------------------------
@@ -45,7 +46,7 @@ QString ctkMaterialPropertyWidgetPlugin::domXml() const
 //-----------------------------------------------------------------------------
 QIcon ctkMaterialPropertyWidgetPlugin::icon() const
 {
-  return QIcon(":/Icons/pushbutton.png");
+  return QIcon(":/Icons/widget.png");
 }
 
 //-----------------------------------------------------------------------------

+ 68 - 0
Libs/Widgets/Plugins/ctkSettingsPanelPlugin.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 "ctkSettingsPanelPlugin.h"
+#include "ctkSettingsPanel.h"
+
+//-----------------------------------------------------------------------------
+ctkSettingsPanelPlugin::ctkSettingsPanelPlugin(QObject *pluginParent)
+  : QObject(pluginParent)
+{
+}
+
+//-----------------------------------------------------------------------------
+QWidget *ctkSettingsPanelPlugin::createWidget(QWidget* widgetParent)
+{
+  ctkSettingsPanel* newWidget = new ctkSettingsPanel(widgetParent);
+  return newWidget;
+}
+
+//-----------------------------------------------------------------------------
+QString ctkSettingsPanelPlugin::domXml() const
+{
+  return "<widget class=\"ctkSettingsPanel\" \
+          name=\"SettingsPanel\">\n"
+          "</widget>\n";
+}
+
+//-----------------------------------------------------------------------------
+QIcon ctkSettingsPanelPlugin::icon() const
+{
+  return QIcon(":/Icons/widget.png");
+}
+
+//-----------------------------------------------------------------------------
+QString ctkSettingsPanelPlugin::includeFile() const
+{
+  return "ctkSettingsPanel.h";
+}
+
+//-----------------------------------------------------------------------------
+bool ctkSettingsPanelPlugin::isContainer() const
+{
+  return true;
+}
+
+//-----------------------------------------------------------------------------
+QString ctkSettingsPanelPlugin::name() const
+{
+  return "ctkSettingsPanel";
+}

+ 44 - 0
Libs/Widgets/Plugins/ctkSettingsPanelPlugin.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 __ctkSettingsPanelPlugin_h
+#define __ctkSettingsPanelPlugin_h
+
+// CTK includes
+#include "ctkWidgetsAbstractPlugin.h"
+
+class CTK_WIDGETS_PLUGINS_EXPORT ctkSettingsPanelPlugin :
+  public QObject,
+  public ctkWidgetsAbstractPlugin
+{
+  Q_OBJECT
+
+public:
+  ctkSettingsPanelPlugin(QObject *_parent = 0);
+  
+  QWidget *createWidget(QWidget *_parent);
+  QString  domXml() const;
+  QIcon    icon() const;
+  QString  includeFile() const;
+  bool     isContainer() const;
+  QString  name() const;
+};
+
+#endif

+ 68 - 0
Libs/Widgets/Plugins/ctkSettingsWidgetPlugin.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 "ctkSettingsWidgetPlugin.h"
+#include "ctkSettingsWidget.h"
+
+//-----------------------------------------------------------------------------
+ctkSettingsWidgetPlugin::ctkSettingsWidgetPlugin(QObject *pluginParent)
+  : QObject(pluginParent)
+{
+}
+
+//-----------------------------------------------------------------------------
+QWidget *ctkSettingsWidgetPlugin::createWidget(QWidget* widgetParent)
+{
+  ctkSettingsWidget* newWidget = new ctkSettingsWidget(widgetParent);
+  return newWidget;
+}
+
+//-----------------------------------------------------------------------------
+QString ctkSettingsWidgetPlugin::domXml() const
+{
+  return "<widget class=\"ctkSettingsWidget\" \
+          name=\"SettingsWidget\">\n"
+          "</widget>\n";
+}
+
+//-----------------------------------------------------------------------------
+QIcon ctkSettingsWidgetPlugin::icon() const
+{
+  return QIcon(":/Icons/widget.png");
+}
+
+//-----------------------------------------------------------------------------
+QString ctkSettingsWidgetPlugin::includeFile() const
+{
+  return "ctkSettingsWidget.h";
+}
+
+//-----------------------------------------------------------------------------
+bool ctkSettingsWidgetPlugin::isContainer() const
+{
+  return false;
+}
+
+//-----------------------------------------------------------------------------
+QString ctkSettingsWidgetPlugin::name() const
+{
+  return "ctkSettingsWidget";
+}

+ 44 - 0
Libs/Widgets/Plugins/ctkSettingsWidgetPlugin.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 __ctkSettingsWidgetPlugin_h
+#define __ctkSettingsWidgetPlugin_h
+
+// CTK includes
+#include "ctkWidgetsAbstractPlugin.h"
+
+class CTK_WIDGETS_PLUGINS_EXPORT ctkSettingsWidgetPlugin :
+  public QObject,
+  public ctkWidgetsAbstractPlugin
+{
+  Q_OBJECT
+
+public:
+  ctkSettingsWidgetPlugin(QObject *_parent = 0);
+  
+  QWidget *createWidget(QWidget *_parent);
+  QString  domXml() const;
+  QIcon    icon() const;
+  QString  includeFile() const;
+  bool     isContainer() const;
+  QString  name() const;
+};
+
+#endif

+ 5 - 1
Libs/Widgets/Plugins/ctkWidgetsPlugins.h

@@ -44,9 +44,11 @@
 #include "ctkMenuButtonPlugin.h"
 #include "ctkRangeSliderPlugin.h"
 #include "ctkRangeWidgetPlugin.h"
+#include "ctkSettingsPanelPlugin.h"
+#include "ctkSettingsWidgetPlugin.h"
+#include "ctkSliderWidgetPlugin.h"
 #include "ctkTransferFunctionViewPlugin.h"
 #include "ctkTreeComboBoxPlugin.h"
-#include "ctkSliderWidgetPlugin.h"
 #include "ctkWorkflowButtonBoxWidgetPlugin.h"
 #include "ctkWorkflowWidgetStepPlugin.h"
 
@@ -79,6 +81,8 @@ public:
             << new ctkMenuButtonPlugin
             << new ctkRangeSliderPlugin
             << new ctkRangeWidgetPlugin
+            << new ctkSettingsPanelPlugin
+            << new ctkSettingsWidgetPlugin
             << new ctkSliderWidgetPlugin
             << new ctkTransferFunctionViewPlugin
             << new ctkTreeComboBoxPlugin

+ 39 - 0
Libs/Widgets/Resources/UI/ctkSettingsWidget.ui

@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>ctkSettingsWidget</class>
+ <widget class="QWidget" name="ctkSettingsWidget">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>693</width>
+    <height>300</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Settings</string>
+  </property>
+  <layout class="QHBoxLayout" name="horizontalLayout" stretch="0,1">
+   <property name="margin">
+    <number>0</number>
+   </property>
+   <item>
+    <widget class="QTreeWidget" name="SettingsTreeWidget">
+     <property name="headerHidden">
+      <bool>true</bool>
+     </property>
+     <column>
+      <property name="text">
+       <string notr="true">1</string>
+      </property>
+     </column>
+    </widget>
+   </item>
+   <item>
+    <widget class="QStackedWidget" name="SettingsStackedWidget"/>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>

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

@@ -30,7 +30,9 @@ CREATE_TEST_SOURCELIST(Tests ${KIT}CppTests.cxx
   ctkRangeSliderTest1.cpp
   ctkRangeWidgetTest1.cpp
   ctkDateRangeWidgetTest1.cpp
+  ctkSettingsPanelTest1.cpp
   ctkSettingsTest1.cpp
+  ctkSettingsWidgetTest1.cpp
   ctkSliderWidgetTest1.cpp
   ctkTreeComboBoxTest1.cpp
   ctkWorkflowWidgetTest1.cpp
@@ -102,7 +104,9 @@ SIMPLE_TEST( ctkMenuButtonTest1 )
 SIMPLE_TEST( ctkRangeSliderTest1 )
 SIMPLE_TEST( ctkRangeWidgetTest1 )
 SIMPLE_TEST( ctkDateRangeWidgetTest1 )
+SIMPLE_TEST( ctkSettingsPanelTest1 )
 SIMPLE_TEST( ctkSettingsTest1 )
+SIMPLE_TEST( ctkSettingsWidgetTest1 )
 SIMPLE_TEST( ctkSliderWidgetTest1 )
 SIMPLE_TEST( ctkTreeComboBoxTest1 )
 SIMPLE_TEST( ctkWorkflowWidgetTest1 )

+ 72 - 0
Libs/Widgets/Testing/Cpp/ctkSettingsPanelTest1.cpp

@@ -0,0 +1,72 @@
+/*=========================================================================
+
+  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 <QCheckBox>
+#include <QSettings>
+#include <QTimer>
+
+// CTK includes
+#include "ctkSettingsPanel.h"
+
+// STD includes
+#include <stdlib.h>
+#include <iostream>
+
+//-----------------------------------------------------------------------------
+int ctkSettingsPanelTest1(int argc, char * argv [] )
+{
+  QApplication app(argc, argv);
+  
+  QSettings settings(QSettings::IniFormat, QSettings::UserScope, "Common ToolKit", "CTK");
+
+  ctkSettingsPanel settingsPanel;
+  settingsPanel.setSettings(&settings);
+
+  QCheckBox* box = new QCheckBox(&settingsPanel);
+
+  settingsPanel.registerProperty("key 1", box, "checked",
+                                  SIGNAL(toggled(bool)));
+  
+  QVariant boxVal = settings.value("key 1");
+  if (!boxVal.isValid() || boxVal.toBool() != false)
+    {
+    std::cerr << "Saving to settings failed" << std::endl;
+    return EXIT_FAILURE;
+    }
+  box->setChecked(true);
+  boxVal = settings.value("key 1");
+  if (!boxVal.isValid() || boxVal.toBool() != true)
+    {
+    std::cerr << "Saving to settings failed" << std::endl;
+    return EXIT_FAILURE;
+    }
+
+  settingsPanel.show();
+      
+  if (argc < 2 || QString(argv[1]) != "-I" )
+    {
+    QTimer::singleShot(200, &app, SLOT(quit()));
+    }
+
+  return app.exec();
+}
+

+ 87 - 0
Libs/Widgets/Testing/Cpp/ctkSettingsWidgetTest1.cpp

@@ -0,0 +1,87 @@
+/*=========================================================================
+
+  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 <QCheckBox>
+#include <QSettings>
+#include <QTimer>
+
+// CTK includes
+#include "ctkSettingsPanel.h"
+#include "ctkSettingsWidget.h"
+
+// STD includes
+#include <stdlib.h>
+#include <iostream>
+
+//-----------------------------------------------------------------------------
+int ctkSettingsWidgetTest1(int argc, char * argv [] )
+{
+  QApplication app(argc, argv);
+  
+  QSettings settings(QSettings::IniFormat, QSettings::UserScope, "Common ToolKit", "CTK");
+
+  ctkSettingsWidget settingsWidget;
+  settingsWidget.setSettings(&settings);
+
+  ctkSettingsPanel* panel1 = new ctkSettingsPanel;
+  settingsWidget.addPanel("Panel 1", panel1); 
+  if (panel1->settings() != &settings)
+    {
+    std::cerr << "ctkSettingsWidget::addPanel settings failed" << panel1->settings() << std::endl;
+    return EXIT_FAILURE;
+    }
+  settingsWidget.addPanel("Panel 2", new ctkSettingsPanel);
+  settingsWidget.addPanel("Panel 3", new ctkSettingsPanel);
+  ctkSettingsPanel* panel4 = new ctkSettingsPanel;
+  settingsWidget.addPanel("Panel 4", panel4, panel1);
+
+  QCheckBox* box = new QCheckBox(panel4);
+  box->setChecked(false); // false by default but we just want to make sure
+  panel4->registerProperty("key 1", box, "checked",
+                           SIGNAL(toggled(bool)));
+  
+  QVariant boxVal = settings.value("key 1");
+  if (!boxVal.isValid() || boxVal.toBool() != false)
+    {
+    std::cerr << "Saving to settings failed" << std::endl;
+    return EXIT_FAILURE;
+    }
+  box->setChecked(true);
+  boxVal = settings.value("key 1");
+  if (!boxVal.isValid() || boxVal.toBool() != true)
+    {
+    std::cerr << "Saving to settings failed" << std::endl;
+    return EXIT_FAILURE;
+    }
+
+  settingsWidget.setCurrentPanel("Panel 4");
+
+  settingsWidget.show();
+      
+  if (argc < 2 || QString(argv[1]) != "-I" )
+    {
+    QTimer::singleShot(200, &app, SLOT(quit()));
+    }
+
+  return app.exec();
+}
+

+ 191 - 0
Libs/Widgets/ctkSettingsPanel.cpp

@@ -0,0 +1,191 @@
+/*=========================================================================
+
+  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 <QSettings>
+#include <QSignalMapper>
+
+// CTK includes
+#include "ctkSettingsPanel.h"
+#include "ctkLogger.h"
+
+static ctkLogger logger("org.commontk.libs.widgets.ctkSettingsPanel");
+
+typedef QPair<QObject*, QString> PropertyType;
+
+//-----------------------------------------------------------------------------
+class ctkSettingsPanelPrivate
+{
+  Q_DECLARE_PUBLIC(ctkSettingsPanel);
+protected:
+  ctkSettingsPanel* const q_ptr;
+
+public:
+  ctkSettingsPanelPrivate(ctkSettingsPanel& object);
+  void init();
+
+  PropertyType property(const QString& key);
+  QVariant propertyValue(const PropertyType& property)const;
+  bool setPropertyValue(const PropertyType& property, const QVariant& val);
+
+  QSettings*                   Settings;
+  QMap<QString, PropertyType > Properties;
+  QSignalMapper*               SignalMapper;
+  bool                         SaveToSettingsWhenRegister;
+};
+
+// --------------------------------------------------------------------------
+ctkSettingsPanelPrivate::ctkSettingsPanelPrivate(ctkSettingsPanel& object)
+  :q_ptr(&object)
+{
+  this->Settings = 0;
+  this->SignalMapper = 0;
+  this->SaveToSettingsWhenRegister = true;
+}
+
+// --------------------------------------------------------------------------
+void ctkSettingsPanelPrivate::init()
+{
+  Q_Q(ctkSettingsPanel);
+  
+  this->SignalMapper = new QSignalMapper(q);
+  QObject::connect(this->SignalMapper, SIGNAL(mapped(const QString&)),
+                   q, SLOT(updateSetting(const QString&)));
+}
+
+// --------------------------------------------------------------------------
+PropertyType ctkSettingsPanelPrivate::property(const QString& key)
+{
+  PropertyType defaultProp(0, QString());
+  return this->Properties.value(key, defaultProp);
+}
+
+// --------------------------------------------------------------------------
+QVariant ctkSettingsPanelPrivate::propertyValue(const PropertyType& prop)const
+{
+  if (prop.first == 0 ||
+      prop.second.isEmpty())
+    {
+    return QVariant();
+    }
+  return prop.first->property(prop.second.toLatin1());
+}
+
+// --------------------------------------------------------------------------
+bool ctkSettingsPanelPrivate::setPropertyValue(const PropertyType& prop, const QVariant& val)
+{
+  if (prop.first == 0 ||
+      prop.second.isEmpty())
+    {
+    return false;
+    }
+  // the following return true if the property has been added using Q_PROPERTY
+  // false otherwise (and the property is then a dynamic property)
+  return prop.first->setProperty(prop.second.toLatin1(), val);
+}
+
+// --------------------------------------------------------------------------
+ctkSettingsPanel::ctkSettingsPanel(QWidget* _parent)
+  : Superclass(_parent)
+  , d_ptr(new ctkSettingsPanelPrivate(*this))
+{
+  Q_D(ctkSettingsPanel);
+  d->init();
+}
+
+// --------------------------------------------------------------------------
+ctkSettingsPanel::~ctkSettingsPanel()
+{
+}
+
+// --------------------------------------------------------------------------
+QSettings* ctkSettingsPanel::settings()const
+{
+  Q_D(const ctkSettingsPanel);
+  return d->Settings;
+}
+
+// --------------------------------------------------------------------------
+void ctkSettingsPanel::setSettings(QSettings* settings)
+{
+  Q_D(ctkSettingsPanel);
+  d->Settings = settings;
+  this->updateProperties();
+}
+
+// --------------------------------------------------------------------------
+void ctkSettingsPanel::updateProperties()
+{
+  Q_D(ctkSettingsPanel);
+  if (!d->Settings)
+    {
+    return;
+    }
+  foreach(const QString& key, d->Properties.keys())
+    {
+    QVariant value = d->Settings->contains(key);
+    if (value.isValid())
+      {
+      bool res = d->setPropertyValue(d->property(key), value);
+      Q_ASSERT(res);
+      Q_UNUSED(res);
+      }
+    }
+}
+
+// --------------------------------------------------------------------------
+void ctkSettingsPanel::registerProperty(const QString& key,
+                                        QObject* object,
+                                        const QString& property,
+                                        const char* signal)
+{
+  Q_D(ctkSettingsPanel);
+  d->Properties[key] = PropertyType(object, property);
+  d->SignalMapper->setMapping(object, key);
+  connect(object, signal, d->SignalMapper, SLOT(map()));
+  if (d->SaveToSettingsWhenRegister)
+    {
+    this->updateSetting(key);
+    }
+}
+
+// --------------------------------------------------------------------------
+void ctkSettingsPanel::updateSetting(const QString& key)
+{
+  Q_D(ctkSettingsPanel);
+  if (!d->Settings)
+    {
+    return;
+    }
+  QVariant oldVal = d->Settings->value(key);
+  QVariant newVal = d->propertyValue(d->property(key));
+  d->Settings->setValue(key, newVal);
+  if (d->Settings->status() != QSettings::NoError)
+    {
+    logger.warn( QString("Error %1 while writing setting %1")
+      .arg(d->Settings->status())
+      .arg(key));
+    }
+  if (oldVal != newVal)
+    {
+    emit settingChanged(key, newVal);
+    }
+}

+ 68 - 0
Libs/Widgets/ctkSettingsPanel.h

@@ -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.
+
+=========================================================================*/
+
+#ifndef __ctkSettingsPanel_h
+#define __ctkSettingsPanel_h
+
+// Qt includes
+#include <QWidget>
+
+// CTK includes
+#include "ctkWidgetsExport.h"
+
+class QSettings;
+class ctkSettingsPanelPrivate;
+
+class CTK_WIDGETS_EXPORT ctkSettingsPanel : public QWidget
+{
+  Q_OBJECT
+public:
+  /// Superclass typedef
+  typedef QWidget Superclass;
+
+  /// Constructor
+  explicit ctkSettingsPanel(QWidget* parent = 0);
+
+  /// Destructor
+  virtual ~ctkSettingsPanel();
+
+  QSettings* settings()const;
+  void setSettings(QSettings* settings);
+
+  void registerProperty(const QString& key,
+                        QObject* object,
+                        const QString& property,
+                        const char* signal);
+signals:
+  void settingChanged(const QString& key, const QVariant& value);
+
+protected slots:
+  void updateSetting(const QString& key);
+
+protected:
+  QScopedPointer<ctkSettingsPanelPrivate> d_ptr;
+
+  virtual void updateProperties();
+private:
+  Q_DECLARE_PRIVATE(ctkSettingsPanel);
+  Q_DISABLE_COPY(ctkSettingsPanel);
+};
+
+#endif

+ 217 - 0
Libs/Widgets/ctkSettingsWidget.cpp

@@ -0,0 +1,217 @@
+/*=========================================================================
+
+  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 <QMap>
+#include <QSettings>
+
+// CTK includes
+#include "ctkSettingsPanel.h"
+#include "ctkSettingsWidget.h"
+#include "ui_ctkSettingsWidget.h"
+#include "ctkLogger.h"
+
+static ctkLogger logger("org.commontk.libs.widgets.ctkSettingsWidget");
+
+//-----------------------------------------------------------------------------
+class ctkSettingsWidgetPrivate: public Ui_ctkSettingsWidget
+{
+  Q_DECLARE_PUBLIC(ctkSettingsWidget);
+protected:
+  ctkSettingsWidget* const q_ptr;
+public:
+  ctkSettingsWidgetPrivate(ctkSettingsWidget& object);
+  void init();
+
+  ctkSettingsPanel* panel(QTreeWidgetItem* item)const;
+  QTreeWidgetItem* item(ctkSettingsPanel* panel)const;
+  QTreeWidgetItem* item(const QString& label)const;
+
+  void beginGroup(ctkSettingsPanel* panel);
+  void endGroup(ctkSettingsPanel* panel);
+
+  QSettings* Settings;
+
+protected:
+  QMap<QTreeWidgetItem*, ctkSettingsPanel*> Panels;
+};
+
+// --------------------------------------------------------------------------
+ctkSettingsWidgetPrivate::ctkSettingsWidgetPrivate(ctkSettingsWidget& object)
+  :q_ptr(&object)
+{
+  this->Settings = 0;
+}
+
+// --------------------------------------------------------------------------
+void ctkSettingsWidgetPrivate::init()
+{
+  Q_Q(ctkSettingsWidget);
+  this->setupUi(q);
+
+  QObject::connect(this->SettingsTreeWidget,
+    SIGNAL(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)),
+    q, SLOT(onCurrentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)));
+}
+
+// --------------------------------------------------------------------------
+ctkSettingsPanel* ctkSettingsWidgetPrivate::panel(QTreeWidgetItem* item)const
+{
+  return this->Panels.value(item, 0);
+}
+
+// --------------------------------------------------------------------------
+QTreeWidgetItem* ctkSettingsWidgetPrivate::item(ctkSettingsPanel* panel)const
+{
+  return this->Panels.key(panel, this->SettingsTreeWidget->invisibleRootItem());
+}
+
+// --------------------------------------------------------------------------
+QTreeWidgetItem* ctkSettingsWidgetPrivate::item(const QString& label)const
+{
+  QMap<QTreeWidgetItem*, ctkSettingsPanel*>::const_iterator it;
+  for (it = this->Panels.constBegin(); it != this->Panels.constEnd(); ++it)
+    {
+    if (it.value()->windowTitle() == label)
+      {
+      return it.key();
+      }
+    }
+  return this->SettingsTreeWidget->invisibleRootItem();
+}
+
+// --------------------------------------------------------------------------
+ctkSettingsWidget::ctkSettingsWidget(QWidget* _parent)
+  : Superclass(_parent)
+  , d_ptr(new ctkSettingsWidgetPrivate(*this))
+{
+  Q_D(ctkSettingsWidget);
+  d->init();
+}
+
+// --------------------------------------------------------------------------
+ctkSettingsWidget::~ctkSettingsWidget()
+{
+}
+
+// --------------------------------------------------------------------------
+QSettings* ctkSettingsWidget::settings()const
+{
+  Q_D(const ctkSettingsWidget);
+  return d->Settings;
+}
+
+// --------------------------------------------------------------------------
+void ctkSettingsWidget::setSettings(QSettings* settings)
+{
+  Q_D(ctkSettingsWidget);
+
+  d->Settings = settings;
+  foreach(ctkSettingsPanel* panel, d->Panels.values())
+    {
+    panel->setSettings(settings);
+    }
+}
+
+// --------------------------------------------------------------------------
+void ctkSettingsWidget
+::addPanel(ctkSettingsPanel* panel, ctkSettingsPanel* parentPanel)
+{
+  Q_D(ctkSettingsWidget);
+  QTreeWidgetItem* newPanelItem = new QTreeWidgetItem;
+  newPanelItem->setText(0, panel->windowTitle());
+  newPanelItem->setIcon(0, panel->windowIcon());
+
+  d->Panels[newPanelItem] = panel;
+  QTreeWidgetItem* parentItem = d->item(parentPanel);
+  parentItem->addChild(newPanelItem);
+  d->SettingsStackedWidget->addWidget(panel);
+
+  connect(panel, SIGNAL(settingChanged(const QString&, const QVariant&)),
+          this, SIGNAL(settingChanged(const QString&, const QVariant&)));
+  panel->setSettings(this->settings());
+}
+
+// --------------------------------------------------------------------------
+void ctkSettingsWidget
+::addPanel(const QString& label, ctkSettingsPanel* panel, 
+           ctkSettingsPanel* parentPanel)
+{
+  panel->setWindowTitle(label);
+  this->addPanel(panel, parentPanel);
+}
+
+// --------------------------------------------------------------------------
+void ctkSettingsWidget
+::addPanel(const QString& label, const QIcon& icon,
+           ctkSettingsPanel* panel, ctkSettingsPanel* parentPanel)
+{
+  panel->setWindowTitle(label);
+  panel->setWindowIcon(icon);
+  this->addPanel(panel, parentPanel);
+}
+
+// --------------------------------------------------------------------------
+void ctkSettingsWidget::setCurrentPanel(ctkSettingsPanel* panel)
+{
+  Q_D(ctkSettingsWidget);
+  // eventually calls onCurrentItemChanged() where all the work is done
+  d->SettingsTreeWidget->setCurrentItem(d->item(panel));
+}
+
+// --------------------------------------------------------------------------
+void ctkSettingsWidget::setCurrentPanel(const QString& label)
+{
+  Q_D(ctkSettingsWidget);
+  // eventually calls onCurrentItemChanged() where all the work is done
+  d->SettingsTreeWidget->setCurrentItem(d->item(label));
+}
+
+// --------------------------------------------------------------------------
+ctkSettingsPanel* ctkSettingsWidget::currentPanel()const
+{
+  Q_D(const ctkSettingsWidget);
+  return d->panel(d->SettingsTreeWidget->currentItem());
+}
+
+// --------------------------------------------------------------------------
+ctkSettingsPanel* ctkSettingsWidget::panel(const QString& label)const
+{
+  Q_D(const ctkSettingsWidget);
+  foreach(ctkSettingsPanel* settingsPanel, d->Panels.values())
+    {
+    if (settingsPanel->windowTitle() == label)
+      {
+      return settingsPanel;
+      }
+    }
+  return 0;
+}
+
+// --------------------------------------------------------------------------
+void ctkSettingsWidget
+::onCurrentItemChanged(QTreeWidgetItem* currentItem, QTreeWidgetItem* previousItem)
+{
+  Q_D(ctkSettingsWidget);
+  Q_UNUSED(previousItem);
+  d->SettingsStackedWidget->setCurrentWidget(
+    d->panel(currentItem));
+}

+ 78 - 0
Libs/Widgets/ctkSettingsWidget.h

@@ -0,0 +1,78 @@
+/*=========================================================================
+
+  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 __ctkSettingsWidget_h
+#define __ctkSettingsWidget_h
+
+// Qt includes
+#include <QWidget>
+
+// CTK includes
+#include "ctkWidgetsExport.h"
+
+class ctkSettingsWidgetPrivate;
+class QTreeWidgetItem;
+class ctkSettingsPanel;
+class QSettings;
+
+class CTK_WIDGETS_EXPORT ctkSettingsWidget : public QWidget
+{
+  Q_OBJECT
+public:
+  /// Superclass typedef
+  typedef QWidget Superclass;
+
+  /// Constructor
+  explicit ctkSettingsWidget(QWidget* parent = 0);
+
+  /// Destructor
+  virtual ~ctkSettingsWidget();
+
+  QSettings* settings()const;
+  void setSettings(QSettings* settings);
+
+  ctkSettingsPanel* panel(const QString& panel)const;
+  ctkSettingsPanel* currentPanel()const;
+
+  /// Uses the ctkSettingsPanel::windowTitle property to show in the list
+  void addPanel(ctkSettingsPanel* panel, ctkSettingsPanel* parentPanel = 0);
+  /// Utility function 
+  void addPanel(const QString& label, ctkSettingsPanel* panel, ctkSettingsPanel* parentPanel = 0);
+  void addPanel(const QString& label, const QIcon& icon, ctkSettingsPanel* panel, ctkSettingsPanel* parentPanel = 0);
+
+public slots:
+  void setCurrentPanel(ctkSettingsPanel* panel);
+  void setCurrentPanel(const QString& label);
+
+signals:
+  void settingChanged(const QString& key, const QVariant& value);
+
+protected slots:
+  void onCurrentItemChanged(QTreeWidgetItem* currentItem, QTreeWidgetItem* previous);
+
+protected:
+  QScopedPointer<ctkSettingsWidgetPrivate> d_ptr;
+
+private:
+  Q_DECLARE_PRIVATE(ctkSettingsWidget);
+  Q_DISABLE_COPY(ctkSettingsWidget);
+};
+
+#endif