Prechádzať zdrojové kódy

Generalized the handling of parameter values and cmd line arguments.

Sascha Zelzer 13 rokov pred
rodič
commit
b613959023

+ 4 - 3
Applications/ctkCommandLineModuleExplorer/ctkCLModuleExplorerMainWindow.cpp

@@ -68,9 +68,6 @@ void ctkCLModuleExplorerMainWindow::on_actionRun_triggered()
 {
   qDebug() << "Creating module command line...";
 
-//  QStringList cmdLineArgs = ctkCmdLineModuleManager::createCommandLineArgs(ui->mainTabWidget->currentWidget());
-//  qDebug() << cmdLineArgs;
-
   ctkCmdLineModuleInstance* moduleInstance = mapTabToModuleRef[ui->mainTabWidget->currentIndex()];
   if (!moduleInstance)
   {
@@ -78,6 +75,10 @@ void ctkCLModuleExplorerMainWindow::on_actionRun_triggered()
     return;
   }
 
+  QStringList cmdLineArgs = moduleInstance->commandLineArguments();
+  qDebug() << cmdLineArgs;
+
+
   //ctkCmdLineModuleProcessFuture future = moduleInstance->run();
   //future.waitForFinished();
   //qDebug() << future.standardOutput();

+ 0 - 1
Libs/CommandLineModules/Core/CMakeLists.txt

@@ -21,7 +21,6 @@ set(KIT_SRCS
   ctkCmdLineModuleInstance.cpp
   ctkCmdLineModuleInstanceFactory.cpp
   ctkCmdLineModuleManager.cpp
-  ctkCmdLineModuleObjectHierarchyReader.cpp
   ctkCmdLineModuleParameter.cpp
   ctkCmdLineModuleParameterPrivate.cpp
   ctkCmdLineModuleParameterGroup.cpp

+ 1 - 1
Libs/CommandLineModules/Core/ctkCmdLineModuleDescription.cpp

@@ -31,7 +31,7 @@ limitations under the License.
 
 //----------------------------------------------------------------------------
 ctkCmdLineModuleDescription::ctkCmdLineModuleDescription()
-  : d(new ctkCmdLineModuleDescriptionPrivate)
+  : d(new ctkCmdLineModuleDescriptionPrivate())
 {
 }
 

+ 96 - 74
Libs/CommandLineModules/Core/ctkCmdLineModuleInstance.cpp

@@ -20,9 +20,10 @@
 =============================================================================*/
 
 #include "ctkCmdLineModuleInstance.h"
+#include "ctkCmdLineModuleDescription.h"
+#include "ctkCmdLineModuleParameter.h"
+#include "ctkCmdLineModuleParameterGroup.h"
 #include "ctkCmdLineModuleReference.h"
-#include "ctkCmdLineModuleObjectHierarchyReader.h"
-#include "ctkCmdLineModuleObjectHierarchyReader.h"
 #include "ctkCmdLineModuleProcess_p.h"
 
 #include "ctkException.h"
@@ -30,14 +31,6 @@
 #include <QStringList>
 #include <QDebug>
 
-namespace {
-
-QString normalizeFlag(const QString& flag)
-{
-  return flag.trimmed().remove(QRegExp("^-*"));
-}
-
-}
 
 struct ctkCmdLineModuleInstancePrivate
 {
@@ -48,59 +41,15 @@ struct ctkCmdLineModuleInstancePrivate
 
   }
 
-  QStringList createCommandLineArgs()
+  QString normalizeFlag(const QString& flag)
   {
-    ctkCmdLineModuleObjectHierarchyReader reader(q->parameterValueModel());
-
-    QStringList cmdLineArgs;
-    QHash<int, QString> indexedArgs;
-    while(reader.readNextParameter())
-    {
-      if (reader.index() > -1)
-      {
-        indexedArgs.insert(reader.index(), reader.value().toString());
-      }
-      else
-      {
-        QString argFlag;
-        if (reader.longFlag().isEmpty())
-        {
-          argFlag = QString("-") + normalizeFlag(reader.flag());
-        }
-        else
-        {
-          argFlag = QString("--") + normalizeFlag(reader.longFlag());
-        }
-
-        QStringList args;
-        if (reader.isMultiple())
-        {
-          args = reader.value().toString().split(',', QString::SkipEmptyParts);
-        }
-        else
-        {
-          args.push_back(reader.value().toString());
-        }
-
-        foreach(QString arg, args)
-        {
-          cmdLineArgs << argFlag << arg;
-        }
-      }
-    }
-
-    QList<int> indexes = indexedArgs.keys();
-    qSort(indexes.begin(), indexes.end());
-    foreach(int index, indexes)
-    {
-      cmdLineArgs << indexedArgs[index];
-    }
-
-    return cmdLineArgs;
+    return flag.trimmed().remove(QRegExp("^-*"));
   }
 
   ctkCmdLineModuleReference ModuleReference;
 
+  QList<QString> ParameterNames;
+
 private:
 
   ctkCmdLineModuleInstance* q;
@@ -117,32 +66,84 @@ ctkCmdLineModuleInstance::~ctkCmdLineModuleInstance()
 {
 }
 
-QObject *ctkCmdLineModuleInstance::parameterValueModel() const
+QList<QString> ctkCmdLineModuleInstance::parameterNames() const
+{
+  if (!d->ParameterNames.isEmpty()) return d->ParameterNames;
+
+  foreach (ctkCmdLineModuleParameterGroup paramGroup,
+           moduleReference().description().parameterGroups())
+  {
+    foreach (ctkCmdLineModuleParameter param, paramGroup.parameters())
+    {
+      d->ParameterNames.push_back(param.name());
+    }
+  }
+  return d->ParameterNames;
+}
+
+ctkCmdLineModuleReference ctkCmdLineModuleInstance::moduleReference() const
 {
-  return guiHandle();
+  return d->ModuleReference;
 }
 
-QVariant ctkCmdLineModuleInstance::value(const QString &parameter) const
+QString ctkCmdLineModuleInstance::location() const
 {
-  throw ctkException("not implemented yet");
+  return d->ModuleReference.location();
 }
 
-void ctkCmdLineModuleInstance::setValue(const QString &parameter, const QVariant &value)
+QStringList ctkCmdLineModuleInstance::commandLineArguments() const
 {
-  ctkCmdLineModuleObjectHierarchyReader reader(parameterValueModel());
-  while(reader.readNextParameter())
+  QStringList cmdLineArgs;
+  QHash<int, QString> indexedArgs;
+
+  QHash<QString,QVariant> currentValues = values();
+  ctkCmdLineModuleDescription description = moduleReference().description();
+  QHashIterator<QString,QVariant> valuesIter(currentValues);
+  while(valuesIter.hasNext())
   {
-    if(reader.name() == parameter && reader.value() != value)
+    valuesIter.next();
+    ctkCmdLineModuleParameter parameter = description.parameter(valuesIter.key());
+    if (parameter.index() > -1)
     {
-      reader.setValue(value);
-      emit valueChanged(parameter, value);
+      indexedArgs.insert(parameter.index(), valuesIter.value().toString());
+    }
+    else
+    {
+      QString argFlag;
+      if (parameter.longFlag().isEmpty())
+      {
+        argFlag = QString("-") + d->normalizeFlag(parameter.flag());
+      }
+      else
+      {
+        argFlag = QString("--") + d->normalizeFlag(parameter.longFlag());
+      }
+
+      QStringList args;
+      if (parameter.multiple())
+      {
+        args = valuesIter.value().toString().split(',', QString::SkipEmptyParts);
+      }
+      else
+      {
+        args.push_back(valuesIter.value().toString());
+      }
+
+      foreach(QString arg, args)
+      {
+        cmdLineArgs << argFlag << arg;
+      }
     }
   }
-}
 
-ctkCmdLineModuleReference ctkCmdLineModuleInstance::moduleReference() const
-{
-  return d->ModuleReference;
+  QList<int> indexes = indexedArgs.keys();
+  qSort(indexes.begin(), indexes.end());
+  foreach(int index, indexes)
+  {
+    cmdLineArgs << indexedArgs[index];
+  }
+
+  return cmdLineArgs;
 }
 
 struct ctkCmdLineModuleFuture {};
@@ -150,9 +151,30 @@ struct ctkCmdLineModuleFuture {};
 ctkCmdLineModuleFuture ctkCmdLineModuleInstance::run() const
 {
 //  // TODO: manage memory
-//  QStringList args = d->createCommandLineArgs();
-//  qDebug() << args;
+  QStringList args = commandLineArguments();
+  qDebug() << args;
 //  ctkCmdLineModuleProcessRunner* moduleProcess =
 //      new ctkCmdLineModuleProcessRunner(d->ModuleReference.location(), args);
 //  return moduleProcess->start();
 }
+
+
+QHash<QString, QVariant> ctkCmdLineModuleInstance::values() const
+{
+  QHash<QString,QVariant> result;
+  foreach(QString parameterName, parameterNames())
+  {
+    result.insert(parameterName, value(parameterName));
+  }
+  return result;
+}
+
+void ctkCmdLineModuleInstance::setValues(const QHash<QString, QVariant> &values)
+{
+  QHashIterator<QString,QVariant> iter(values);
+  while(iter.hasNext())
+  {
+    iter.next();
+    setValue(iter.key(), iter.value());
+  }
+}

+ 14 - 3
Libs/CommandLineModules/Core/ctkCmdLineModuleInstance.h

@@ -26,6 +26,8 @@
 
 #include <QObject>
 
+template<class K, class V> class QHash;
+
 class ctkCmdLineModuleFuture;
 class ctkCmdLineModuleReference;
 class ctkCmdLineModuleInstancePrivate;
@@ -43,11 +45,20 @@ public:
 
   virtual QObject* guiHandle() const = 0;
 
-  QVariant value(const QString& parameter) const;
-  void setValue(const QString& parameter, const QVariant& value);
+  virtual QVariant value(const QString& parameter) const = 0;
+  virtual void setValue(const QString& parameter, const QVariant& value) = 0;
+
+  virtual QList<QString> parameterNames() const;
+
+  virtual QHash<QString,QVariant> values() const;
+  virtual void setValues(const QHash<QString,QVariant>& values);
 
   ctkCmdLineModuleReference moduleReference() const;
 
+  QString location() const;
+
+  QStringList commandLineArguments() const;
+
   ctkCmdLineModuleFuture run() const;
 
   Q_SIGNAL void valueChanged(const QString& parameter, const QVariant& value);
@@ -56,7 +67,7 @@ protected:
 
   ctkCmdLineModuleInstance(const ctkCmdLineModuleReference& moduleRef);
 
-  virtual QObject* parameterValueModel() const;
+  //virtual QObject* parameterValueModel() const;
 
 private:
 

+ 0 - 1
Libs/CommandLineModules/Core/ctkCmdLineModuleManager.cpp

@@ -22,7 +22,6 @@
 #include "ctkCmdLineModuleManager.h"
 
 #include "ctkCmdLineModuleXmlValidator.h"
-#include "ctkCmdLineModuleObjectHierarchyReader.h"
 #include "ctkCmdLineModuleReference.h"
 #include "ctkCmdLineModuleReferencePrivate.h"
 #include "ctkCmdLineModuleInstanceFactory.h"

+ 0 - 275
Libs/CommandLineModules/Core/ctkCmdLineModuleObjectHierarchyReader.cpp

@@ -1,275 +0,0 @@
-/*=============================================================================
-  
-  Library: CTK
-  
-  Copyright (c) German Cancer Research Center,
-    Division of Medical and Biological Informatics
-    
-  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.apache.org/licenses/LICENSE-2.0
-    
-  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.
-  
-=============================================================================*/
-
-#include "ctkCmdLineModuleObjectHierarchyReader.h"
-
-#include <QObject>
-#include <QStack>
-#include <QVariant>
-
-namespace {
-
-static QString PREFIX_EXECUTABLE = "executable:";
-static QString PREFIX_PARAMETER_GROUP = "paramGroup:";
-static QString PREFIX_PARAMETER = "parameter:";
-
-}
-
-class ctkCmdLineModuleObjectHierarchyReaderPrivate
-{
-public:
-
-  ctkCmdLineModuleObjectHierarchyReaderPrivate(QObject* root)
-    : rootObject(root), currentObject(0), currentToken(ctkCmdLineModuleObjectHierarchyReader::NoToken),
-      atEnd(false)
-  {
-  }
-
-  QVariant property(const QString& propName) const
-  {
-    if (currentObject == 0) return QString();
-
-    QString prefixedName;
-    switch(currentToken)
-    {
-    case ctkCmdLineModuleObjectHierarchyReader::Executable: prefixedName = PREFIX_EXECUTABLE + propName;
-    case ctkCmdLineModuleObjectHierarchyReader::ParameterGroup: prefixedName = PREFIX_PARAMETER_GROUP + propName;
-    case ctkCmdLineModuleObjectHierarchyReader::Parameter: prefixedName = PREFIX_PARAMETER + propName;
-    default: ;
-    }
-
-    return currentObject->property(qPrintable(prefixedName));
-  }
-
-  ctkCmdLineModuleObjectHierarchyReader::TokenType token(QObject* obj)
-  {
-    if (obj == 0) return ctkCmdLineModuleObjectHierarchyReader::NoToken;
-    QString name = obj->objectName();
-    if (name.startsWith(PREFIX_EXECUTABLE)) return ctkCmdLineModuleObjectHierarchyReader::Executable;
-    if (name.startsWith(PREFIX_PARAMETER_GROUP)) return ctkCmdLineModuleObjectHierarchyReader::ParameterGroup;
-    if (name.startsWith(PREFIX_PARAMETER)) return ctkCmdLineModuleObjectHierarchyReader::Parameter;
-    return ctkCmdLineModuleObjectHierarchyReader::NoToken;
-  }
-
-  bool setCurrent(QObject* obj)
-  {
-    ctkCmdLineModuleObjectHierarchyReader::TokenType t = token(obj);
-    if (t != ctkCmdLineModuleObjectHierarchyReader::NoToken)
-    {
-      currentObject = obj;
-      currentToken = t;
-      return true;
-    }
-    return false;
-  }
-
-  QObject* rootObject;
-  QObject* currentObject;
-
-  ctkCmdLineModuleObjectHierarchyReader::TokenType currentToken;
-  bool atEnd;
-
-  QStack<QObject*> objectStack;
-};
-
-ctkCmdLineModuleObjectHierarchyReader::ctkCmdLineModuleObjectHierarchyReader(QObject *root)
-  : d(new ctkCmdLineModuleObjectHierarchyReaderPrivate(root))
-{
-}
-
-ctkCmdLineModuleObjectHierarchyReader::~ctkCmdLineModuleObjectHierarchyReader()
-{
-}
-
-void ctkCmdLineModuleObjectHierarchyReader::setRootObject(QObject* root)
-{
-  d->rootObject = root;
-  clear();
-}
-
-void ctkCmdLineModuleObjectHierarchyReader::clear()
-{
-  d->currentToken = NoToken;
-  d->currentObject = 0;
-  d->objectStack.clear();
-}
-
-bool ctkCmdLineModuleObjectHierarchyReader::atEnd() const
-{
-  return d->atEnd || d->rootObject == 0;
-}
-
-bool ctkCmdLineModuleObjectHierarchyReader::isParameterGroup() const
-{
-  return d->currentToken == ParameterGroup;
-}
-
-bool ctkCmdLineModuleObjectHierarchyReader::isParameter() const
-{
-  return d->currentToken == Parameter;
-}
-
-QString ctkCmdLineModuleObjectHierarchyReader::name() const
-{
-  if (d->currentObject == 0) return QString();
-  switch(d->currentToken)
-  {
-  case Executable: return d->currentObject->objectName().mid(PREFIX_EXECUTABLE.size());
-  case ParameterGroup: return d->currentObject->objectName().mid(PREFIX_PARAMETER_GROUP.size());
-  case Parameter: return d->currentObject->objectName().mid(PREFIX_PARAMETER.size());
-  default: return QString();
-  }
-}
-
-QString ctkCmdLineModuleObjectHierarchyReader::label() const
-{
-  if (d->currentObject == 0) return QString();
-  switch(d->currentToken)
-  {
-  case Executable: return d->currentObject->objectName().mid(PREFIX_EXECUTABLE.size());
-  case ParameterGroup: return d->property("title").toString();
-  case Parameter: return property("label").toString();
-  default: return QString();
-  }
-}
-
-QVariant ctkCmdLineModuleObjectHierarchyReader::value() const
-{
-  QString valProp = property("valueProperty").toString();
-  return property(valProp);
-}
-
-void ctkCmdLineModuleObjectHierarchyReader::setValue(const QVariant& value)
-{
-  QVariant valProp = property("valueProperty");
-  if (valProp.isValid())
-  {
-    d->currentObject->setProperty(qPrintable(valProp.toString()), value);
-  }
-}
-
-QString ctkCmdLineModuleObjectHierarchyReader::flag() const
-{
-  QVariant v = property("flag");
-  return v.isValid() ? v.toString() : QString();
-}
-
-QString ctkCmdLineModuleObjectHierarchyReader::longFlag() const
-{
-  QVariant v = property("longflag");
-  return v.isValid() ? v.toString() : QString();
-}
-
-int ctkCmdLineModuleObjectHierarchyReader::index() const
-{
-  QVariant v = property("index");
-  return v.isValid() ? v.toInt() : -1;
-}
-
-bool ctkCmdLineModuleObjectHierarchyReader::isMultiple() const
-{
-  QVariant v = property("multiple");
-  return v.isValid() ? v.toBool() : false;
-}
-
-QVariant ctkCmdLineModuleObjectHierarchyReader::property(const QString &propName) const
-{
-  if (d->currentObject == 0) return QVariant();
-
-  // First try to get a prefixed property
-  QVariant res = d->property(propName);
-  // Try to get a property with the original name
-  if (!res.isValid()) res = d->currentObject->property(qPrintable(propName));
-  return res;
-}
-
-ctkCmdLineModuleObjectHierarchyReader::TokenType ctkCmdLineModuleObjectHierarchyReader::readNext() const
-{
-  if (d->atEnd) return NoToken;
-
-  QObject* curr = 0;
-  if (d->currentObject == 0)
-  {
-    curr = d->rootObject;
-    if (d->setCurrent(curr)) return d->currentToken;
-  }
-  else
-  {
-    curr = d->currentObject;
-  }
-
-  while (true)
-  {
-    if (curr)
-    {
-      QObjectList children = curr->children();
-      QListIterator<QObject*> i(children);
-      i.toBack();
-      while (i.hasPrevious())
-      {
-        d->objectStack.push(i.previous());
-      }
-      if (children.isEmpty())
-      {
-        curr = 0;
-      }
-      else
-      {
-        curr = d->objectStack.pop();
-        if (d->setCurrent(curr)) return d->currentToken;
-      }
-      continue;
-    }
-
-    if (d->objectStack.isEmpty()) break;
-    curr = d->objectStack.pop();
-    if (d->setCurrent(curr)) return d->currentToken;
-  }
-
-  d->atEnd = true;
-  d->currentObject = 0;
-  d->currentToken = NoToken;
-
-  return NoToken;
-}
-
-bool ctkCmdLineModuleObjectHierarchyReader::readNextExecutable() const
-{
-  while (!(readNext() == Executable || d->atEnd));
-  return !d->atEnd;
-}
-
-bool ctkCmdLineModuleObjectHierarchyReader::readNextParameterGroup() const
-{
-  while (!(readNext() == ParameterGroup || d->atEnd));
-  return !d->atEnd;
-}
-
-bool ctkCmdLineModuleObjectHierarchyReader::readNextParameter() const
-{
-  while (!(readNext() == Parameter || d->atEnd));
-  return !d->atEnd;
-}
-
-ctkCmdLineModuleObjectHierarchyReader::TokenType ctkCmdLineModuleObjectHierarchyReader::tokenType() const
-{
-  return d->currentToken;
-}

+ 2 - 2
Libs/CommandLineModules/Core/ctkCmdLineModuleReferencePrivate.cpp

@@ -26,8 +26,8 @@
 
 ctkCmdLineModuleDescription ctkCmdLineModuleReferencePrivate::description() const
 {
-  // lazy creation
-  if (!Description.d)
+  // Lazy creation. The title is a requirement XML element.
+  if (Description.title().isNull())
   {
     QByteArray xml(RawXmlDescription);
     QBuffer xmlInput(&xml);

+ 2 - 0
Libs/CommandLineModules/QtGui/CMakeLists.txt

@@ -17,6 +17,8 @@ set(KIT_SRCS
   ctkCmdLineModuleInstanceFactoryQtGui.cpp
   ctkCmdLineModuleInstanceQtGui_p.h
   ctkCmdLineModuleInstanceQtGui.cpp
+  ctkCmdLineModuleObjectTreeWalker_p.h
+  ctkCmdLineModuleObjectTreeWalker.cpp
 )
 
 # Headers that should run through moc

+ 45 - 5
Libs/CommandLineModules/QtGui/ctkCmdLineModuleInstanceQtGui.cpp

@@ -22,6 +22,7 @@
 #include "ctkCmdLineModuleInstanceQtGui_p.h"
 #include "ctkCmdLineModuleReference.h"
 #include "ctkCmdLineModuleXslTransform.h"
+#include "ctkCmdLineModuleObjectTreeWalker_p.h"
 
 #include <QBuffer>
 #include <QUiLoader>
@@ -32,7 +33,7 @@
 
 ctkCmdLineModuleInstanceQtGui::ctkCmdLineModuleInstanceQtGui(const ctkCmdLineModuleReference& moduleRef)
   : ctkCmdLineModuleInstance(moduleRef),
-    WidgetTree(NULL), XmlDescription(moduleRef.rawXmlDescription())
+    WidgetTree(NULL)
 {
 }
 
@@ -41,7 +42,7 @@ QObject* ctkCmdLineModuleInstanceQtGui::guiHandle() const
   if (WidgetTree) return WidgetTree;
 
   QBuffer input;
-  input.setData(XmlDescription);
+  input.setData(moduleReference().rawXmlDescription());
 
   ctkCmdLineModuleXslTransform xslTransform(&input);
   if (!xslTransform.transform())
@@ -56,15 +57,54 @@ QObject* ctkCmdLineModuleInstanceQtGui::guiHandle() const
   uiBlob.append(xslTransform.output());
 
   QBuffer uiForm(&uiBlob);
-  return uiLoader.load(&uiForm);
+  WidgetTree = uiLoader.load(&uiForm);
+  return WidgetTree;
 }
 
-QVariant ctkCmdLineModuleInstanceQtGui::value(const QString& parameter) const
+QVariant ctkCmdLineModuleInstanceQtGui::value(const QString &parameter) const
 {
+  if (!WidgetTree) return QVariant();
+
+  ctkCmdLineModuleObjectTreeWalker reader(WidgetTree);
+  while(reader.readNextParameter())
+  {
+    if(reader.name() == parameter)
+    {
+      return reader.value();
+    }
+  }
   return QVariant();
 }
 
-void ctkCmdLineModuleInstanceQtGui::setValue(const QString& parameter, const QVariant& value)
+void ctkCmdLineModuleInstanceQtGui::setValue(const QString &parameter, const QVariant &value)
+{
+  if (!WidgetTree) return;
+
+  ctkCmdLineModuleObjectTreeWalker walker(WidgetTree);
+  while(walker.readNextParameter())
+  {
+    if(walker.name() == parameter && walker.value() != value)
+    {
+      walker.setValue(value);
+      emit valueChanged(parameter, value);
+    }
+  }
+}
+
+QList<QString> ctkCmdLineModuleInstanceQtGui::parameterNames() const
 {
+  if (!ParameterNames.empty()) return ParameterNames;
 
+  // Compute the list of parameter names using the widget hierarchy
+  // if it has already created (otherwise fall back to the superclass
+  // implementation.
+  // This avoids creating a ctkCmdLineModuleDescription instance.
+  if (WidgetTree == 0) return ctkCmdLineModuleInstance::parameterNames();
+
+  ctkCmdLineModuleObjectTreeWalker walker(WidgetTree);
+  while(walker.readNextParameter())
+  {
+    ParameterNames.push_back(walker.name());
+  }
+  return ParameterNames;
 }

+ 4 - 1
Libs/CommandLineModules/QtGui/ctkCmdLineModuleInstanceQtGui_p.h

@@ -40,11 +40,14 @@ public:
   virtual QVariant value(const QString& parameter) const;
   virtual void setValue(const QString& parameter, const QVariant& value);
 
+  virtual QList<QString> parameterNames() const;
+
 private:
 
   mutable QWidget* WidgetTree;
 
-  const QByteArray XmlDescription;
+  // Cache the list of parameter names
+  mutable QList<QString> ParameterNames;
 };
 
 #endif // CTKCMDLINEMODULEINSTANCEQTGUI_H

+ 258 - 0
Libs/CommandLineModules/QtGui/ctkCmdLineModuleObjectTreeWalker.cpp

@@ -0,0 +1,258 @@
+/*=============================================================================
+  
+  Library: CTK
+  
+  Copyright (c) German Cancer Research Center,
+    Division of Medical and Biological Informatics
+    
+  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.apache.org/licenses/LICENSE-2.0
+    
+  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.
+  
+=============================================================================*/
+
+#include "ctkCmdLineModuleObjectTreeWalker_p.h"
+
+#include <QObject>
+#include <QStack>
+#include <QVariant>
+
+namespace {
+
+static QString PREFIX_EXECUTABLE = "executable:";
+static QString PREFIX_PARAMETER_GROUP = "paramGroup:";
+static QString PREFIX_PARAMETER = "parameter:";
+
+}
+
+ctkCmdLineModuleObjectTreeWalker::ctkCmdLineModuleObjectTreeWalker(QObject *root)
+  : RootObject(root), CurrentObject(0), CurrentToken(NoToken),
+    AtEnd(false)
+{
+}
+
+ctkCmdLineModuleObjectTreeWalker::~ctkCmdLineModuleObjectTreeWalker()
+{
+}
+
+void ctkCmdLineModuleObjectTreeWalker::setRootObject(QObject* root)
+{
+  RootObject = root;
+  clear();
+}
+
+void ctkCmdLineModuleObjectTreeWalker::clear()
+{
+  CurrentToken = NoToken;
+  CurrentObject = 0;
+  ObjectStack.clear();
+}
+
+bool ctkCmdLineModuleObjectTreeWalker::atEnd() const
+{
+  return AtEnd || RootObject == 0;
+}
+
+bool ctkCmdLineModuleObjectTreeWalker::isParameterGroup() const
+{
+  return CurrentToken == ParameterGroup;
+}
+
+bool ctkCmdLineModuleObjectTreeWalker::isParameter() const
+{
+  return CurrentToken == Parameter;
+}
+
+QString ctkCmdLineModuleObjectTreeWalker::name() const
+{
+  if (CurrentObject == 0) return QString();
+  switch(CurrentToken)
+  {
+  case Executable: return CurrentObject->objectName().mid(PREFIX_EXECUTABLE.size());
+  case ParameterGroup: return CurrentObject->objectName().mid(PREFIX_PARAMETER_GROUP.size());
+  case Parameter: return CurrentObject->objectName().mid(PREFIX_PARAMETER.size());
+  default: return QString();
+  }
+}
+
+QString ctkCmdLineModuleObjectTreeWalker::label() const
+{
+  if (CurrentObject == 0) return QString();
+  switch(CurrentToken)
+  {
+  case Executable: return CurrentObject->objectName().mid(PREFIX_EXECUTABLE.size());
+  case ParameterGroup: return property("title").toString();
+  case Parameter: return property("label").toString();
+  default: return QString();
+  }
+}
+
+QVariant ctkCmdLineModuleObjectTreeWalker::value() const
+{
+  QString valProp = property("valueProperty").toString();
+  return property(valProp);
+}
+
+void ctkCmdLineModuleObjectTreeWalker::setValue(const QVariant& value)
+{
+  QVariant valProp = property("valueProperty");
+  if (valProp.isValid())
+  {
+    CurrentObject->setProperty(qPrintable(valProp.toString()), value);
+  }
+}
+
+QString ctkCmdLineModuleObjectTreeWalker::flag() const
+{
+  QVariant v = property("flag");
+  return v.isValid() ? v.toString() : QString();
+}
+
+QString ctkCmdLineModuleObjectTreeWalker::longFlag() const
+{
+  QVariant v = property("longflag");
+  return v.isValid() ? v.toString() : QString();
+}
+
+int ctkCmdLineModuleObjectTreeWalker::index() const
+{
+  QVariant v = property("index");
+  return v.isValid() ? v.toInt() : -1;
+}
+
+bool ctkCmdLineModuleObjectTreeWalker::isMultiple() const
+{
+  QVariant v = property("multiple");
+  return v.isValid() ? v.toBool() : false;
+}
+
+QVariant ctkCmdLineModuleObjectTreeWalker::property(const QString &propName) const
+{
+  if (CurrentObject == 0) return QVariant();
+
+  // First try to get a prefixed property
+  QVariant res = prefixedProperty(propName);
+  // Try to get a property with the original name
+  if (!res.isValid()) res = CurrentObject->property(qPrintable(propName));
+  return res;
+}
+
+ctkCmdLineModuleObjectTreeWalker::TokenType ctkCmdLineModuleObjectTreeWalker::readNext()
+{
+  if (AtEnd) return NoToken;
+
+  QObject* curr = 0;
+  if (CurrentObject == 0)
+  {
+    curr = RootObject;
+    if (setCurrent(curr)) return CurrentToken;
+  }
+  else
+  {
+    curr = CurrentObject;
+  }
+
+  while (true)
+  {
+    if (curr)
+    {
+      QObjectList children = curr->children();
+      QListIterator<QObject*> i(children);
+      i.toBack();
+      while (i.hasPrevious())
+      {
+        ObjectStack.push(i.previous());
+      }
+      if (children.isEmpty())
+      {
+        curr = 0;
+      }
+      else
+      {
+        curr = ObjectStack.pop();
+        if (setCurrent(curr)) return CurrentToken;
+      }
+      continue;
+    }
+
+    if (ObjectStack.isEmpty()) break;
+    curr = ObjectStack.pop();
+    if (setCurrent(curr)) return CurrentToken;
+  }
+
+  AtEnd = true;
+  CurrentObject = 0;
+  CurrentToken = NoToken;
+
+  return NoToken;
+}
+
+bool ctkCmdLineModuleObjectTreeWalker::readNextExecutable()
+{
+  while (!(readNext() == Executable || AtEnd));
+  return !AtEnd;
+}
+
+bool ctkCmdLineModuleObjectTreeWalker::readNextParameterGroup()
+{
+  while (!(readNext() == ParameterGroup || AtEnd));
+  return !AtEnd;
+}
+
+bool ctkCmdLineModuleObjectTreeWalker::readNextParameter()
+{
+  while (!(readNext() == Parameter || AtEnd));
+  return !AtEnd;
+}
+
+ctkCmdLineModuleObjectTreeWalker::TokenType ctkCmdLineModuleObjectTreeWalker::tokenType() const
+{
+  return CurrentToken;
+}
+
+QVariant ctkCmdLineModuleObjectTreeWalker::prefixedProperty(const QString& propName) const
+{
+  if (CurrentObject == 0) return QString();
+
+  QString prefixedName;
+  switch(CurrentToken)
+  {
+  case ctkCmdLineModuleObjectTreeWalker::Executable: prefixedName = PREFIX_EXECUTABLE + propName;
+  case ctkCmdLineModuleObjectTreeWalker::ParameterGroup: prefixedName = PREFIX_PARAMETER_GROUP + propName;
+  case ctkCmdLineModuleObjectTreeWalker::Parameter: prefixedName = PREFIX_PARAMETER + propName;
+  default: ;
+  }
+
+  return CurrentObject->property(qPrintable(prefixedName));
+}
+
+ctkCmdLineModuleObjectTreeWalker::TokenType
+ctkCmdLineModuleObjectTreeWalker::token(QObject* obj)
+{
+  if (obj == 0) return ctkCmdLineModuleObjectTreeWalker::NoToken;
+  QString name = obj->objectName();
+  if (name.startsWith(PREFIX_EXECUTABLE)) return ctkCmdLineModuleObjectTreeWalker::Executable;
+  if (name.startsWith(PREFIX_PARAMETER_GROUP)) return ctkCmdLineModuleObjectTreeWalker::ParameterGroup;
+  if (name.startsWith(PREFIX_PARAMETER)) return ctkCmdLineModuleObjectTreeWalker::Parameter;
+  return ctkCmdLineModuleObjectTreeWalker::NoToken;
+}
+
+bool ctkCmdLineModuleObjectTreeWalker::setCurrent(QObject* obj)
+{
+  ctkCmdLineModuleObjectTreeWalker::TokenType t = token(obj);
+  if (t != ctkCmdLineModuleObjectTreeWalker::NoToken)
+  {
+    CurrentObject = obj;
+    CurrentToken = t;
+    return true;
+  }
+  return false;
+}

+ 23 - 21
Libs/CommandLineModules/Core/ctkCmdLineModuleObjectHierarchyReader.h

@@ -19,23 +19,15 @@
   
 =============================================================================*/
 
-#ifndef CTKCMDLINEMODULEOBJECTHIERARCHYREADER_H
-#define CTKCMDLINEMODULEOBJECTHIERARCHYREADER_H
+#ifndef CTKCMDLINEMODULEOBJECTTREEWALKER_H
+#define CTKCMDLINEMODULEOBJECTTREEWALKER_H
 
-#include <QString>
-#include <QScopedPointer>
-#include <QVariant>
-
-#include <ctkCommandLineModulesCoreExport.h>
+#include <QStack>
 
 class QObject;
+class QVariant;
 
-class ctkCmdLineModuleObjectHierarchyReaderPrivate;
-
-/**
- *  \ingroup CommandLineModulesCore
- */
-class CTK_CMDLINEMODULECORE_EXPORT ctkCmdLineModuleObjectHierarchyReader
+class ctkCmdLineModuleObjectTreeWalker
 {
 
 public:
@@ -47,8 +39,8 @@ public:
     Parameter
   };
 
-  ctkCmdLineModuleObjectHierarchyReader(QObject* root = 0);
-  ~ctkCmdLineModuleObjectHierarchyReader();
+  ctkCmdLineModuleObjectTreeWalker(QObject* root = 0);
+  ~ctkCmdLineModuleObjectTreeWalker();
 
   void setRootObject(QObject* root);
   void clear();
@@ -73,17 +65,27 @@ public:
 
   QVariant property(const QString& propName) const;
 
-  TokenType readNext() const;
-  bool readNextExecutable() const;
-  bool readNextParameterGroup() const;
-  bool readNextParameter() const;
+  TokenType readNext();
+  bool readNextExecutable();
+  bool readNextParameterGroup();
+  bool readNextParameter();
 
   TokenType tokenType() const;
 
 private:
 
-  QScopedPointer<ctkCmdLineModuleObjectHierarchyReaderPrivate> d;
+  TokenType token(QObject* obj);
+  bool setCurrent(QObject* obj);
+  QVariant prefixedProperty(const QString& propName) const;
+
+  QObject* RootObject;
+  QObject* CurrentObject;
+
+  TokenType CurrentToken;
+  bool AtEnd;
+
+  QStack<QObject*> ObjectStack;
 
 };
 
-#endif // CTKCMDLINEMODULEOBJECTHIERARCHYREADER_H
+#endif // CTKCMDLINEMODULEOBJECTTREEWALKER_H