瀏覽代碼

ENH: Added class ctkVTKCommandOptions and associated tests

Jean-Christophe Fillion-Robin 15 年之前
父節點
當前提交
1ee6220c0b

+ 2 - 0
Libs/Visualization/VTK/Core/CMakeLists.txt

@@ -23,6 +23,8 @@ SET(KIT_include_directories
   
 # Source files
 SET(KIT_SRCS
+  ctkVTKCommandOptions.cpp
+  ctkVTKCommandOptions.h
   ctkVTKConnection.cpp
   ctkVTKConnection.h
   ctkVTKObject.h

+ 60 - 0
Libs/Visualization/VTK/Core/Testing/Cpp/CMakeLists.txt

@@ -18,10 +18,27 @@ SET(KIT_HELPER_SRCS
 QT4_WRAP_CPP(KIT_HELPER_SRCS ctkVTKObjectTestHelper.h)
 
 #
+# Testing data
+#
+
+SET(TESTING_DATA ${CMAKE_CURRENT_SOURCE_DIR}/Data)
+
+# Resource file used for testing is generated running:
+#    bin/ctkVisualizationVTKCoreCppTests ctkVTKCommandOptionsTest1 --generate-test-data
+
+SET(CTKVTKCOMMANDOPTIONSTEST_SETTINGS ${TESTING_DATA}/Settings/ctkVTKCommandOptionsTest1.ini)
+
+CONFIGURE_FILE(
+  ${CMAKE_CURRENT_SOURCE_DIR}/ctkVisualizationVTKCoreCppTestsConfigure.h.in
+  ${CMAKE_CURRENT_BINARY_DIR}/ctkVisualizationVTKCoreCppTestsConfigure.h
+  )
+
+#
 # Tests
 #
 
 CREATE_TEST_SOURCELIST(Tests ${KIT}CppTests.cpp
+  ctkVTKCommandOptionsTest1.cpp
   ctkVTKObjectTest1.cpp
   #EXTRA_INCLUDE TestingMacros.h
   )
@@ -49,3 +66,46 @@ ENDMACRO( SIMPLE_TEST  )
 #
 
 SIMPLE_TEST( ctkVTKObjectTest1 )
+
+ADD_TEST( ctkVTKCommandOptionsTest1 ${KIT_TESTS}
+          ctkVTKCommandOptionsTest1 --help )
+          
+ADD_TEST( ctkVTKCommandOptionsTest2 ${KIT_TESTS}
+          ctkVTKCommandOptionsTest1 --enable-awesome-test )
+
+ADD_TEST( ctkVTKCommandOptionsTest3 ${KIT_TESTS}
+          ctkVTKCommandOptionsTest1 -eat )
+
+ADD_TEST( ctkVTKCommandOptionsTest4 ${KIT_TESTS}
+          ctkVTKCommandOptionsTest1 --disable-settings --test-if-disablesettings-flag-works )
+
+SET(arg1 "Testing with")
+SET(arg2 " cmake is ")
+SET(arg3 "super awesome !")
+SET(arg4 "CMake rocks !")
+
+IF(WIN32)
+ADD_TEST( ctkVTKCommandOptionsTest5 ${KIT_TESTS}
+          ctkVTKCommandOptionsTest1 --my-list-of-strings "${arg1}" "${arg2}" "${arg3}"
+          -ms="${arg4}" --test-if-commandline-overwrite-settings )
+
+ADD_TEST( ctkVTKCommandOptionsTest6 ${KIT_TESTS}
+          ctkVTKCommandOptionsTest1 -mlos "${arg1}" "${arg2}" "${arg3}"
+          --my-string="${arg4}" --test-if-commandline-overwrite-settings )
+ELSE()
+ADD_TEST( ctkVTKCommandOptionsTest5 ${KIT_TESTS}
+          ctkVTKCommandOptionsTest1 --my-list-of-strings ${arg1} ${arg2} ${arg3}
+          -ms=${arg4} --test-if-commandline-overwrite-settings )
+
+ADD_TEST( ctkVTKCommandOptionsTest6 ${KIT_TESTS}
+          ctkVTKCommandOptionsTest1 -mlos ${arg1} ${arg2} ${arg3}
+          --my-string=${arg4} --test-if-commandline-overwrite-settings )
+ENDIF()
+
+ADD_TEST( ctkVTKCommandOptionsTest7 ${KIT_TESTS}
+          ctkVTKCommandOptionsTest1 --test-if-ignorerest-flag-works
+          --ignore-rest --nothing=foo extra1 /? )
+
+ADD_TEST( ctkVTKCommandOptionsTest8 ${KIT_TESTS}
+          ctkVTKCommandOptionsTest1 --test-if-ignorerest-flag-works
+          -- --nothing=foo extra1 /? )

+ 4 - 0
Libs/Visualization/VTK/Core/Testing/Cpp/Data/Settings/ctkVTKCommandOptionsTest1.ini

@@ -0,0 +1,4 @@
+[General]
+enable-awesome-test=true
+my-list-of-strings=Testing, " is ", awesome !
+my-string=Testing rocks !

+ 369 - 0
Libs/Visualization/VTK/Core/Testing/Cpp/ctkVTKCommandOptionsTest1.cpp

@@ -0,0 +1,369 @@
+/*=========================================================================
+
+  Library:   CTK
+
+  Copyright (c) Kitware Inc. 
+  All rights reserved.
+  Distributed under a BSD License. See LICENSE.txt file.
+
+  This software is distributed "AS IS" WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the above copyright notice for more information.
+
+=========================================================================*/
+
+// Qt includes
+#include <QCoreApplication>
+#include <QSettings>
+#include <QStringList>
+#include <QList>
+#include <QFile>
+#include <QDebug>
+
+// CTK includes
+#include "ctkVTKCommandOptions.h"
+#include "ctkVisualizationVTKCoreCppTestsConfigure.h"
+
+// STD includes
+#include <cstdlib>
+#include <iostream>
+
+//-----------------------------------------------------------------------------
+namespace
+{
+class ctkVTKCommandOptionsTest : public ctkVTKCommandOptions
+{
+public:
+  typedef ctkVTKCommandOptions Superclass;
+  ctkVTKCommandOptionsTest(QSettings* _settings):Superclass(_settings)
+    {
+    this->AwesomeTestEnabled = false;
+    this->CurrentSettingsDisabled = false;
+    this->TestIfCommandLineOverwriteSettings = false;
+    this->TestIfDisableSettingsFlagWorks = false;
+    this->GenerateTestData = false;
+    this->TestIfIgnoreRestFlagWorks = false;
+    }
+  virtual ~ctkVTKCommandOptionsTest(){}
+
+  // Added as public member for testing purposes ...
+  bool          AwesomeTestEnabled;
+  bool          CurrentSettingsDisabled;
+  bool          TestIfCommandLineOverwriteSettings;
+  bool          TestIfDisableSettingsFlagWorks;
+  bool          TestIfIgnoreRestFlagWorks;
+  bool          GenerateTestData;
+  QString       WrongArgument;
+  QStringList   MyListOfStrings;
+  QString       MyString; 
+  
+
+  // Convenient method allowing to generate a INI file
+  void generateIniFile()
+    {
+    std::cout << "Saving test data:" << CTKVTKCOMMANDOPTIONSTEST_SETTINGS << std::endl;
+    
+    QSettings newSettings(CTKVTKCOMMANDOPTIONSTEST_SETTINGS, QSettings::IniFormat);
+
+    newSettings.clear();
+    
+    newSettings.setValue("enable-awesome-test", QVariant(true));
+
+    newSettings.setValue("my-string", QVariant("Testing rocks !"));
+    
+    QStringList mystringlist;
+    mystringlist << "Testing"; mystringlist << " is "; mystringlist << "awesome !";
+    newSettings.setValue("my-list-of-strings", QVariant(mystringlist));
+    }
+
+  virtual void printAdditionalInfo()
+    {
+    Superclass::printAdditionalInfo();
+    qDebug() << "ctkVTKCommandOptionsTest:" << this << endl
+             << " CurrentSettingsDisabled:" << this->CurrentSettingsDisabled << endl
+             << " WrongArgument:" << this->WrongArgument << endl
+             << " TestIfCommandLineOverwriteSettings:" << this->TestIfCommandLineOverwriteSettings << endl
+             << " TestIfDisableSettingsFlagWorks:" << this->TestIfDisableSettingsFlagWorks << endl
+             << " TestIfIgnoreRestFlagWorks:" << this->TestIfIgnoreRestFlagWorks << endl
+             << " GenerateTestData:" << this->GenerateTestData << endl
+             << " SettingsFile:" << CTKVTKCOMMANDOPTIONSTEST_SETTINGS << endl
+             << " MyListOfStrings:" << this->MyListOfStrings << endl
+             << " MyString:" << this->MyString << endl;
+    
+    }
+  
+protected:
+
+  /// Initialize arguments
+  virtual void initialize()
+    {
+    this->Superclass::initialize();
+
+    this->addBooleanArgument("--enable-awesome-test", "-eat", &this->AwesomeTestEnabled,
+                             "Enables awesome test.");
+
+    this->addBooleanArgument("--test-if-commandline-overwrite-settings", 0,
+                             &this->TestIfCommandLineOverwriteSettings,
+                             "Should we test if QListString setting is overwriten by the "
+                             "corresponding command line argument.");
+
+    this->addBooleanArgument("--test-if-disablesettings-flag-works", 0,
+                             &this->TestIfDisableSettingsFlagWorks,
+                             "Indicates if '--disable-settings' flags should be tested.");
+
+    this->addBooleanArgument("--test-if-ignorerest-flag-works", 0,
+                             &this->TestIfIgnoreRestFlagWorks,
+                             "Indicates if '--ignore-rest' flags should be tested.");
+
+    this->addBooleanArgument("--generate-test-data", 0, &this->GenerateTestData,
+                             "Generates test data and save it to the file specified using '--settings-file'");
+
+    this->addArgument("--my-list-of-strings", "-mlos", &this->MyListOfStrings,
+                      "My list of strings.");
+
+    this->addArgument("--my-string", "-ms", &this->MyString,
+                      "My string.");
+                      
+    }
+
+  // Disable current settings
+  virtual void disableCurrentSettings()
+    {
+    this->CurrentSettingsDisabled = true;
+    }
+
+  /// This method is called when wrong argument is found. If it returns False, then
+  /// the parsing will fail.
+  virtual bool wrongArgument(const char* argument)
+    {
+    this->WrongArgument = QLatin1String(argument);
+    return false;
+    }
+    
+};
+}
+
+//-----------------------------------------------------------------------------
+int ctkVTKCommandOptionsTest1(int argc, char * argv [] )
+{
+  QCoreApplication app(argc, argv);
+
+  app.setOrganizationName("ctkVisualizationVTKCoreCppTests");
+  app.setApplicationName("ctkVTKCommandOptionsTest1");
+
+  // Check if settings file exists
+  if (!QFile::exists(CTKVTKCOMMANDOPTIONSTEST_SETTINGS))
+    {
+    std::cerr << "Problem with configuration of the test - "
+              << "Settings file doesn't exist: [" << CTKVTKCOMMANDOPTIONSTEST_SETTINGS << "]" << std::endl;
+    return EXIT_FAILURE;
+    }
+
+  //std::cout << "CTKVTKCOMMANDOPTIONSTEST_SETTINGS:" << CTKVTKCOMMANDOPTIONSTEST_SETTINGS << std::endl;
+
+  QSettings setting(CTKVTKCOMMANDOPTIONSTEST_SETTINGS, QSettings::IniFormat);
+
+  ctkVTKCommandOptionsTest commandOptions(&setting);
+
+  if (!commandOptions.parse(argc, argv))
+    {
+    commandOptions.printAdditionalInfo();
+    std::cerr << "Problem parsing command line arguments.  Try with --help." << std::endl;
+    return EXIT_FAILURE;
+    }
+
+  if (commandOptions.helpSelected())
+    {
+    std::cout << commandOptions.help().toStdString() << std::endl;
+    return EXIT_SUCCESS;
+    }
+    
+  // Convenient flags allowing to generate test data
+  if (commandOptions.GenerateTestData)
+    {
+    commandOptions.generateIniFile();
+    return EXIT_SUCCESS;
+    }
+
+  // Test if '--ignore-rest' flag works
+  if (commandOptions.TestIfIgnoreRestFlagWorks)
+    {
+    if (!commandOptions.ignoreRest())
+      {
+      commandOptions.printAdditionalInfo();
+      std::cerr << "Error with parse() function - ignoreRest() should return True" << std::endl;
+      return EXIT_FAILURE;
+      }
+    QStringList _ignoreArguments = commandOptions.ignoredArguments(); 
+    if (_ignoreArguments.size() != 3)
+      {
+      commandOptions.printAdditionalInfo();
+      std::cerr << "Error with parse() function - "
+                << "ignoredArguments() returns an incorrect QStringList." << std::endl
+                << " expected size: 3" << std::endl
+                << " current size: " << _ignoreArguments.size() << std::endl;
+      
+      return EXIT_FAILURE;
+      }
+    if (_ignoreArguments[0] != "--nothing=foo" ||
+        _ignoreArguments[1] != "extra1" ||
+        _ignoreArguments[2] != "/?")
+      {
+      commandOptions.printAdditionalInfo();
+      std::cerr << "Error with parse() function - "
+                << "Content of list returned by ignoredArguments() is incorrect" << std::endl
+                << "expected[0] => [--nothing=foo]" << std::endl
+                << "expected[1] => [extra1]" << std::endl
+                << "expected[2] => [/?]" << std::endl;
+      for(int i=0; i < _ignoreArguments.size(); ++i)
+        {
+        std::cerr << "ignoreArguments[" << i << "] => ["
+                  << qPrintable(_ignoreArguments[i]) << "]" << std::endl;
+        }
+      return EXIT_FAILURE;
+      }
+    }
+  else
+    {
+    if (commandOptions.ignoreRest())
+      {
+      commandOptions.printAdditionalInfo();
+      std::cerr << "Error with parse() function - ignoreRest() should return False" << std::endl;
+      return EXIT_FAILURE;
+      }
+    QStringList _ignoreArguments = commandOptions.ignoredArguments(); 
+    if (_ignoreArguments.size() != 0)
+      {
+      commandOptions.printAdditionalInfo();
+      std::cerr << "Error with parse() function - "
+                << "ignoredArguments() returns an incorrect QStringList." << std::endl
+                << " expected size: 0" << std::endl
+                << " current size: " << _ignoreArguments.size() << std::endl;
+      
+      return EXIT_FAILURE;
+      }
+    }
+
+  // Test if '--disable-settings' flag works
+  if (commandOptions.TestIfDisableSettingsFlagWorks)
+    {
+    if (!commandOptions.CurrentSettingsDisabled)
+      {
+      commandOptions.printAdditionalInfo();
+      std::cerr << "Error with parse() function - Settings should be disabled" << std::endl;
+      return EXIT_FAILURE;
+      }
+    return EXIT_SUCCESS;
+    }
+
+  // Test case when a wrong argument is a parsing error
+//   if (commandOptions.TestIfDisableSettingsFlagWorks)
+//     {
+//     if (!commandOptions.CurrentSettingsDisabled)
+//       {
+//       std::cerr << "Error with parse() function - Settings should be disabled" << std::endl;
+//       return EXIT_FAILURE;
+//       }
+//     return EXIT_SUCCESS;
+//     }
+
+  // Since MyListOfStringss should have been updated using the settings file,
+  // let's check if MyListOfStrings has the expected size
+  if (commandOptions.MyListOfStrings.size() != 3)
+    {
+    commandOptions.printAdditionalInfo();
+    std::cerr << "Error with parse() function - "
+              << "MyListOfStrings expected size is 3 - Current size: "
+              << commandOptions.MyListOfStrings.size() << std::endl;
+    for(int i=0; i < commandOptions.MyListOfStrings.size(); ++i)
+      {
+      std::cerr << "MyListOfStrings[" << i << "] => ["
+                << qPrintable(commandOptions.MyListOfStrings[i]) << "]" << std::endl;
+      }
+    return EXIT_FAILURE;
+    }
+      
+  // Test if command line argument overwrite settings
+  if (commandOptions.TestIfCommandLineOverwriteSettings)
+    {
+    if (commandOptions.MyListOfStrings[0] != "Testing with" ||
+        commandOptions.MyListOfStrings[1] != " cmake is " ||
+        commandOptions.MyListOfStrings[2] != "super awesome !")
+      {
+      commandOptions.printAdditionalInfo();
+      std::cerr << "Error with parse() function - "
+                << "Content of MyListOfStrings is incorrect" << std::endl
+                << "expected[0] => [Testing with]" << std::endl
+                << "expected[1] => [ cmake is ]" << std::endl
+                << "expected[2] => [super awesome !]" << std::endl;
+      for(int i=0; i < commandOptions.MyListOfStrings.size(); ++i)
+        {
+        std::cerr << "MyListOfStrings[" << i << "] => ["
+                  << qPrintable(commandOptions.MyListOfStrings[i]) << "]" << std::endl;
+        }
+      return EXIT_FAILURE;
+      }
+    // Check MyString value 
+    if (commandOptions.MyString != "CMake rocks !")
+      {
+      commandOptions.printAdditionalInfo();
+      std::cerr << "Error with parse() function - Content of MyString is incorrect" << std::endl
+                << "expected value is [CMake rocks !]" << std::endl
+                << "current value is [" << qPrintable(commandOptions.MyString) << "]" << std::endl;
+      }
+    return EXIT_SUCCESS;
+    }
+  else
+    {
+    if (commandOptions.MyListOfStrings[0] != "Testing" ||
+        commandOptions.MyListOfStrings[1] != " is " ||
+        commandOptions.MyListOfStrings[2] != "awesome !")
+      {
+      commandOptions.printAdditionalInfo();
+      std::cerr << "Error with parse() function - "
+                << "Content of MyListOfStrings is incorrect" << std::endl
+                << "expected[0] => [Testing]" << std::endl
+                << "expected[1] => [ is ]" << std::endl
+                << "expected[2] => [awesome !]" << std::endl;
+      for(int i=0; i < commandOptions.MyListOfStrings.size(); ++i)
+        {
+        std::cerr << "MyListOfStrings[" << i << "] => ["
+                  << qPrintable(commandOptions.MyListOfStrings[i]) << "]" << std::endl;
+        }
+      return EXIT_FAILURE;
+      }
+    // Check MyString value 
+    if (commandOptions.MyString != "Testing rocks !")
+      {
+      commandOptions.printAdditionalInfo();
+      std::cerr << "Error with parse() function - Content of MyString is incorrect" << std::endl
+                << "expected value is [Testing rocks !]" << std::endl
+                << "current value is [" << qPrintable(commandOptions.MyString) << "]" << std::endl;
+      }
+    }
+
+  if (commandOptions.CurrentSettingsDisabled)
+    {
+    commandOptions.printAdditionalInfo();
+    std::cerr << "Error with parse() function - Settings should *NOT* be disabled" << std::endl;
+    return EXIT_FAILURE;
+    }
+
+  if (!commandOptions.WrongArgument.isEmpty())
+    {
+    commandOptions.printAdditionalInfo();
+    std::cerr << "Error with parse() function - "
+              << "WrongArgument should *NOT* be set to ["
+              << qPrintable(commandOptions.WrongArgument) << "]" << std::endl;
+    return EXIT_FAILURE;
+    }
+
+  if (!commandOptions.AwesomeTestEnabled)
+    {
+    commandOptions.printAdditionalInfo();
+    std::cerr << "Error with parse() function - AwesomeTestEnabled should be True" << std::endl;
+    return EXIT_FAILURE;
+    }
+
+  return EXIT_SUCCESS;
+}

+ 21 - 0
Libs/Visualization/VTK/Core/Testing/Cpp/ctkVisualizationVTKCoreCppTestsConfigure.h.in

@@ -0,0 +1,21 @@
+/*=========================================================================
+
+  Library:   CTK
+
+  Copyright (c) Kitware Inc. 
+  All rights reserved.
+  Distributed under a BSD License. See LICENSE.txt file.
+
+  This software is distributed "AS IS" WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the above copyright notice for more information.
+
+=========================================================================*/
+
+
+#ifndef __ctkVisualizationVTKCoreCppTestsConfigure_h
+#define __ctkVisualizationVTKCoreCppTestsConfigure_h
+
+#define CTKVTKCOMMANDOPTIONSTEST_SETTINGS "@CTKVTKCOMMANDOPTIONSTEST_SETTINGS@"
+
+#endif

+ 505 - 0
Libs/Visualization/VTK/Core/ctkVTKCommandOptions.cpp

@@ -0,0 +1,505 @@
+/*=========================================================================
+
+  Library:   CTK
+
+  Copyright (c) Kitware Inc. 
+  All rights reserved.
+  Distributed under a BSD License. See LICENSE.txt file.
+
+  This software is distributed "AS IS" WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the above copyright notice for more information.
+
+=========================================================================*/
+/*=========================================================================
+  
+  Program:   ParaView
+  Module:    $RCSfile: vtkCommandOptions.h,v $
+
+  Copyright (c) Kitware, Inc.
+  All rights reserved.
+  See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details.
+
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notice for more information.
+
+=========================================================================*/
+
+// Qt includes
+#include <QDebug>
+#include <QString>
+#include <QLatin1String>
+#include <QSettings>
+#include <QHash>
+#include <QList>
+#include <QPointer>
+#include <QStringList>
+
+// CTK includes
+#include <ctkUtils.h>
+#include "ctkVTKCommandOptions.h"
+
+// VTKSYS includes
+#include <vtksys/CommandLineArguments.hxx>
+
+// --------------------------------------------------------------------------
+class ctkVTKCommandOptionsPrivate: public ctkPrivate<ctkVTKCommandOptions>
+{
+public:
+  typedef ctkVTKCommandOptionsPrivate Self;
+  ctkVTKCommandOptionsPrivate();
+  ~ctkVTKCommandOptionsPrivate();
+
+  void cleanArgcArgv();
+
+  /// Callback executed when an unknown arguments is parsed
+  static int unknownArgumentHandler(const char* argument, void* call_data);
+
+  /// If case the --ignore-rest flag has been specified, this method will
+  /// catch the first argument parsed and add it to the ignoredArguments list.
+  /// If not, it will call the virtual method 'wrongArgument(const char* argument)'
+  bool checkForIgnoreRestFlag(const char* argument);
+
+  /// Callback executed when a deprecated arguments is parsed
+  static int deprecatedArgumentHandler(const char* argument, const char* value, void* call_data);
+                                                       
+  /// Since vtksys::CommandLineArguments will only update char*, returns
+  /// a valid char* pointer that it could use.
+  char** mapQStringPtrToCharPtr(QString* qStringPtr);
+
+  /// Since vtksys::CommandLineArguments will only update std::vector<std::string>*, returns
+  /// a valid std::vector<std::string>* pointer that it could use.
+  std::vector<std::string>* mapQStringListPtrToStringVectorPtr(QStringList* qStringListPtr);
+
+  /// If required, sync the updated char* with the corresponding QString*
+  void syncQStringPtrWithCharPtr();
+
+  /// If required, sync the updated std::vector<std::string> with the corresponding QStringList*
+  void syncQStringListPtrWithStringVectorPtr();
+
+  vtksys::CommandLineArguments   CMD;
+  QString                        UnknownArgument;
+  QString                        ErrorMessage;
+  bool                           HelpSelected;
+  bool                           DisableSettings;
+  bool                           IgnoreRest;
+  QStringList                    IgnoredArguments;
+  int                            Argc;
+  char**                         Argv;
+  QPointer<QSettings>            Settings;
+  int                            ProcessType; // GUI, Batch, Daemon, ...
+  
+  QHash<QString*, char**>                         QStringPointerToCharPointerMap;
+  QHash<QStringList*, std::vector<std::string>*>  QStringListPointerToStringVectorPointerMap;
+};
+
+//-----------------------------------------------------------------------------
+// ctkVTKCommandOptionsPrivate methods
+
+// --------------------------------------------------------------------------
+ctkVTKCommandOptionsPrivate::ctkVTKCommandOptionsPrivate()
+{
+  this->CMD.SetUnknownArgumentCallback(ctkVTKCommandOptionsPrivate::unknownArgumentHandler);
+  this->CMD.SetClientData(this);
+
+  this->Argc = 0;
+  this->Argv = 0; 
+  this->HelpSelected = false;
+  this->DisableSettings = false;
+  this->IgnoreRest = false;
+}
+
+// --------------------------------------------------------------------------
+ctkVTKCommandOptionsPrivate::~ctkVTKCommandOptionsPrivate()
+{
+  this->cleanArgcArgv();
+  foreach (QString* qStringPtr, this->QStringPointerToCharPointerMap.keys())
+    {
+    delete this->QStringPointerToCharPointerMap[qStringPtr];
+    }
+  foreach (QStringList* qStringListPtr, this->QStringListPointerToStringVectorPointerMap.keys())
+    {
+    delete this->QStringListPointerToStringVectorPointerMap[qStringListPtr];
+    }
+}
+
+// --------------------------------------------------------------------------
+void ctkVTKCommandOptionsPrivate::cleanArgcArgv()
+{
+  int cc;
+  if (this->Argv)
+    {
+    for (cc = 0; cc < this->Argc; cc++)
+      {
+      delete [] this->Argv[cc];
+      }
+    delete [] this->Argv;
+    this->Argv = 0;
+    }
+}
+
+//----------------------------------------------------------------------------
+int ctkVTKCommandOptionsPrivate::unknownArgumentHandler(const char* argument,
+                                                      void* call_data)
+{
+  ctkVTKCommandOptionsPrivate* self =
+    static_cast<ctkVTKCommandOptionsPrivate*>(call_data);
+  if (self)
+    {
+    self->UnknownArgument = QString::fromLatin1(argument);
+    return self->checkForIgnoreRestFlag(argument);
+    }
+  return 0;
+}
+
+//----------------------------------------------------------------------------
+bool ctkVTKCommandOptionsPrivate::checkForIgnoreRestFlag(const char* argument)
+{
+  CTK_P(ctkVTKCommandOptions);
+  if (this->IgnoreRest)
+    {
+    this->IgnoredArguments << QLatin1String(argument);
+    return true;
+    }
+  else
+    {
+    return p->wrongArgument(argument);
+    }
+}
+
+//----------------------------------------------------------------------------
+int ctkVTKCommandOptionsPrivate::deprecatedArgumentHandler(const char* argument,
+                                                         const char* , void* call_data)
+{
+  //qDebug() << "UnknownArgumentHandler: " << argument;
+  ctkVTKCommandOptionsPrivate* self = static_cast<ctkVTKCommandOptionsPrivate*>(call_data);
+  if (self)
+    {
+    return self->ctk_p()->deprecatedArgument(argument);
+    }
+  return 0;
+}
+
+// --------------------------------------------------------------------------
+char** ctkVTKCommandOptionsPrivate::mapQStringPtrToCharPtr(QString* qStringPtr)
+{
+  Q_ASSERT(!this->QStringPointerToCharPointerMap.contains(qStringPtr));
+  char** charPtr = new char*; // Create a new pointer
+  *charPtr = 0; // Initialize to 0
+  this->QStringPointerToCharPointerMap[qStringPtr] = charPtr;
+  return charPtr;
+}
+
+// --------------------------------------------------------------------------
+std::vector<std::string>*
+ctkVTKCommandOptionsPrivate::mapQStringListPtrToStringVectorPtr(QStringList* qStringListPtr)
+{
+  Q_ASSERT(!this->QStringListPointerToStringVectorPointerMap.contains(qStringListPtr));
+  std::vector<std::string>* vectorPtr = new std::vector<std::string>(); // Create a new vector
+  this->QStringListPointerToStringVectorPointerMap[qStringListPtr] = vectorPtr;
+  return vectorPtr;
+}
+
+// --------------------------------------------------------------------------
+void ctkVTKCommandOptionsPrivate::syncQStringPtrWithCharPtr()
+{
+  foreach(QString* qStringPtr, this->QStringPointerToCharPointerMap.keys())
+    {
+    char** charPtr = this->QStringPointerToCharPointerMap[qStringPtr];
+    Q_ASSERT(charPtr);
+    // Update QString only if the content pointed by charPtr is valid
+    if (*charPtr)
+      {
+      qStringPtr->clear();
+      qStringPtr->append(QLatin1String(*charPtr));
+      }
+    }
+}
+
+// --------------------------------------------------------------------------
+void ctkVTKCommandOptionsPrivate::syncQStringListPtrWithStringVectorPtr()
+{
+  foreach(QStringList* qStringListPtr, this->QStringListPointerToStringVectorPointerMap.keys())
+    {
+    std::vector<std::string>* vectorPtr =
+      this->QStringListPointerToStringVectorPointerMap[qStringListPtr];
+    Q_ASSERT(vectorPtr);
+    // Update QString only if vectorPtr is not empty
+    if (vectorPtr->size() > 0)
+      {
+      qStringListPtr->clear();
+      QStringList convertedVector;
+      ctkUtils::stlVectorToQList(*vectorPtr, convertedVector);
+      qStringListPtr->append(convertedVector);
+      }
+    }
+}
+
+//-----------------------------------------------------------------------------
+// ctkVTKCommandOptions methods
+
+// --------------------------------------------------------------------------
+ctkVTKCommandOptions::ctkVTKCommandOptions(QSettings* _settings)
+{
+  CTK_INIT_PRIVATE(ctkVTKCommandOptions);
+  Q_ASSERT(_settings);
+  CTK_D(ctkVTKCommandOptions);
+  d->Settings = _settings;
+}
+
+//----------------------------------------------------------------------------
+ctkVTKCommandOptions::~ctkVTKCommandOptions()
+{
+}
+
+//----------------------------------------------------------------------------
+void ctkVTKCommandOptions::printAdditionalInfo()
+{
+  CTK_D(ctkVTKCommandOptions);
+  qDebug() << "ctkVTKCommandOptions:" << this << endl
+           << " HelpSelected:" << this->helpSelected() << endl
+           << " DisableSettings:" << d->DisableSettings << endl
+           << " IgnoreRest:" << d->IgnoreRest << endl
+           << " IgnoredArguments:" << d->IgnoredArguments;
+}
+
+//----------------------------------------------------------------------------
+CTK_GET_CXX(ctkVTKCommandOptions, QString, errorMessage, ErrorMessage);
+CTK_GET_CXX(ctkVTKCommandOptions, QString, unknownArgument, UnknownArgument);
+CTK_GET_CXX(ctkVTKCommandOptions, bool, helpSelected, HelpSelected);
+CTK_GET_CXX(ctkVTKCommandOptions, bool, disableSettings, DisableSettings);
+CTK_GET_CXX(ctkVTKCommandOptions, QSettings*, settings, Settings);
+CTK_GET_CXX(ctkVTKCommandOptions, bool, ignoreRest, IgnoreRest);
+CTK_GET_CXX(ctkVTKCommandOptions, QStringList, ignoredArguments, IgnoredArguments);
+
+//----------------------------------------------------------------------------
+CTK_GET_CXX(ctkVTKCommandOptions, int, processType, ProcessType);
+CTK_SET_CXX(ctkVTKCommandOptions, int, setProcessType, ProcessType);
+
+//----------------------------------------------------------------------------
+void ctkVTKCommandOptions::initialize()
+{
+}
+
+//----------------------------------------------------------------------------
+QString ctkVTKCommandOptions::help()
+{
+  CTK_D(ctkVTKCommandOptions);
+  d->CMD.SetLineLength(300);
+  return QLatin1String(d->CMD.GetHelp());
+}
+
+//----------------------------------------------------------------------------
+bool ctkVTKCommandOptions::postProcess(int, const char* const*)
+{
+  return true;
+}
+
+//----------------------------------------------------------------------------
+bool ctkVTKCommandOptions::parse(int argc, const char* const argv[])
+{
+  CTK_D(ctkVTKCommandOptions);
+  d->CMD.Initialize(argc, argv);
+  this->initialize();
+  this->addBooleanArgument("--help", "/?", &d->HelpSelected,
+                           "Displays available command line arguments.");
+
+  this->addBooleanArgument("--disable-settings", 0, &d->DisableSettings,
+                           "Start application ignoring user settings.");
+
+
+  this->addBooleanArgument("--ignore-rest", "--", &d->IgnoreRest,
+                           "Ignores the rest of the labeled arguments following this flag.");
+
+  // Get options from the command line
+  bool res1 = d->CMD.Parse();
+  bool res2 = this->postProcess(argc, argv);
+  //qDebug() << "Res1:" << res1 << ", Res2:" << res2;
+  d->cleanArgcArgv();
+  d->CMD.GetRemainingArguments(&d->Argc, &d->Argv);
+
+  if (d->DisableSettings)
+    {
+    this->disableCurrentSettings();
+    }
+
+  d->syncQStringPtrWithCharPtr();
+  d->syncQStringListPtrWithStringVectorPtr();
+
+  // Since CommandLineArguments include arg0 in the list
+  // of remaining arguments, let's create a temporary list and remove it.
+  QStringList _remaingingArguments = this->remainingArguments();
+  _remaingingArguments.removeFirst();
+
+  // Update ignored arguments list
+  d->IgnoredArguments << _remaingingArguments;
+  
+  return res1 && res2;
+}
+
+//----------------------------------------------------------------------------
+QStringList ctkVTKCommandOptions::remainingArguments()
+{
+  CTK_D(ctkVTKCommandOptions);
+  QStringList tmp; 
+  for(int i=0; i < d->Argc; ++i)
+    {
+    tmp << d->Argv[i]; 
+    }
+  return tmp;
+}
+
+//----------------------------------------------------------------------------
+void ctkVTKCommandOptions::remainingArguments(int* argc, char*** argv)
+{
+  CTK_D(ctkVTKCommandOptions);
+  *argc = d->Argc;
+  *argv = d->Argv;
+}
+
+//----------------------------------------------------------------------------
+void ctkVTKCommandOptions::addDeprecatedArgument(const char* longarg, const char* shortarg,
+                                               const char* arghelp, int type)
+{
+  CTK_D(ctkVTKCommandOptions);
+
+  // If it is for settings or not for the current process do nothing
+  if((type & ctkVTKCommandOptions::QSETTINGS_ONLY) ||
+     !(type & d->ProcessType || type == ctkVTKCommandOptions::ALL))
+    {
+    return;
+    }
+  
+  // Add a callback for the deprecated argument handling
+  d->CMD.AddCallback(longarg, vtksys::CommandLineArguments::NO_ARGUMENT,
+                     ctkVTKCommandOptionsPrivate::deprecatedArgumentHandler, this, arghelp);
+  if(shortarg)
+    {
+    d->CMD.AddCallback(shortarg, vtksys::CommandLineArguments::NO_ARGUMENT,
+                       ctkVTKCommandOptionsPrivate::deprecatedArgumentHandler, this, arghelp);
+    }
+}
+
+//----------------------------------------------------------------------------
+bool ctkVTKCommandOptions::deprecatedArgument(const char* argument)
+{
+  CTK_D(ctkVTKCommandOptions);
+  d->ErrorMessage = QString("  %1").arg(d->CMD.GetHelp(argument));
+  return false;
+}
+
+//----------------------------------------------------------------------------
+bool ctkVTKCommandOptions::wrongArgument(const char* argument)
+{
+  Q_UNUSED(argument);
+  return false;
+}
+
+//----------------------------------------------------------------------------
+void ctkVTKCommandOptions::addBooleanArgument(const char* longarg, const char* shortarg,
+                                            bool* var, const char* arghelp,
+                                            bool defaultValue, int type)
+{
+  CTK_D(ctkVTKCommandOptions);
+
+  // Attempt to read from settings only if longarg is different from '--disable-settings'.
+  if (QLatin1String(longarg) != "--disable-settings")
+    {
+    *var = d->Settings->value(QLatin1String(longarg+2), defaultValue).toBool();
+    
+    if(type & ctkVTKCommandOptions::QSETTINGS_ONLY)
+      {
+      return;
+      }
+    }
+
+  // If the process type matches then add the argument to the command line
+  if(type & d->ProcessType || type == ctkVTKCommandOptions::ALL)
+    {
+    d->CMD.AddBooleanArgument(longarg, var, arghelp);
+    if (shortarg)
+      {
+      d->CMD.AddBooleanArgument(shortarg, var, longarg);
+      }
+    }
+}
+
+//----------------------------------------------------------------------------
+void ctkVTKCommandOptions::addArgument(const char* longarg, const char* shortarg, QString* var,
+                                    const char* arghelp, const QString& defaultValue, int type)
+{
+  CTK_D(ctkVTKCommandOptions);
+  *var = d->Settings->value(QLatin1String(longarg+2), defaultValue).toString();
+  
+  if(type & ctkVTKCommandOptions::QSETTINGS_ONLY)
+    {
+    return;
+    }
+  
+  if(type & d->ProcessType || type == ctkVTKCommandOptions::ALL)
+    {
+    char ** charstar = d->mapQStringPtrToCharPtr(var);
+    typedef vtksys::CommandLineArguments argT;
+    d->CMD.AddArgument(longarg, argT::EQUAL_ARGUMENT, charstar, arghelp);
+    if ( shortarg )
+      {
+      d->CMD.AddArgument(shortarg, argT::EQUAL_ARGUMENT, charstar, longarg);
+      }
+    }
+}
+
+//----------------------------------------------------------------------------
+void ctkVTKCommandOptions::addArgument(const char* longarg, const char* shortarg,
+                                     QStringList* var, const char* arghelp,
+                                     const QStringList& defaultValue, int type)
+{
+  CTK_D(ctkVTKCommandOptions);
+  *var = d->Settings->value(QLatin1String(longarg+2), defaultValue).toStringList();
+  
+  if(type & ctkVTKCommandOptions::QSETTINGS_ONLY)
+    {
+    return;
+    }
+    
+  if(type & d->ProcessType || type == ctkVTKCommandOptions::ALL)
+    {
+    std::vector<std::string>* vectorPtr = d->mapQStringListPtrToStringVectorPtr(var);
+    typedef vtksys::CommandLineArguments argT;
+    d->CMD.AddArgument(longarg, argT::MULTI_ARGUMENT, vectorPtr, arghelp);
+    if (shortarg)
+      {
+      d->CMD.AddArgument(shortarg, argT::MULTI_ARGUMENT, vectorPtr, longarg);
+      }
+    }
+}
+
+//----------------------------------------------------------------------------
+void ctkVTKCommandOptions::addArgument(const char* longarg, const char* shortarg, int* var,
+                                     const char* arghelp, int defaultValue, int type)
+{
+  CTK_D(ctkVTKCommandOptions);
+  *var = d->Settings->value(QLatin1String(longarg+2), defaultValue).toInt();
+  
+  if(type & ctkVTKCommandOptions::QSETTINGS_ONLY)
+    {
+    return;
+    }
+    
+  if(type & d->ProcessType || type == ctkVTKCommandOptions::ALL)
+    {
+    typedef vtksys::CommandLineArguments argT;
+    d->CMD.AddArgument(longarg, argT::EQUAL_ARGUMENT, var, arghelp);
+    if (shortarg)
+      {
+      d->CMD.AddArgument(shortarg, argT::EQUAL_ARGUMENT, var, longarg);
+      }
+    }
+}
+
+//----------------------------------------------------------------------------
+int ctkVTKCommandOptions::indexOfLastParsedArgument()
+{
+  CTK_D(ctkVTKCommandOptions);
+  return d->CMD.GetLastArgument();
+}

+ 156 - 0
Libs/Visualization/VTK/Core/ctkVTKCommandOptions.h

@@ -0,0 +1,156 @@
+/*=========================================================================
+
+  Library:   CTK
+
+  Copyright (c) Kitware Inc. 
+  All rights reserved.
+  Distributed under a BSD License. See LICENSE.txt file.
+
+  This software is distributed "AS IS" WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the above copyright notice for more information.
+
+=========================================================================*/
+/*=========================================================================
+  
+  Program:   ParaView
+  Module:    $RCSfile: vtkCommandOptions.h,v $
+
+  Copyright (c) Kitware, Inc.
+  All rights reserved.
+  See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details.
+
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notice for more information.
+
+=========================================================================*/
+
+#ifndef __ctkVTKCommandOptions_h
+#define __ctkVTKCommandOptions_h
+
+// Qt includes
+#include <QStringList>
+
+// CTK includes
+#include <ctkPimpl.h>
+
+// STD includes
+#include <vector>
+#include <string>
+
+#include "CTKVisualizationVTKCoreExport.h"
+
+class QSettings;
+class ctkVTKCommandOptionsPrivate;
+
+class CTK_VISUALIZATION_VTK_CORE_EXPORT ctkVTKCommandOptions
+{
+public:
+  /// Constructors
+  explicit ctkVTKCommandOptions(QSettings* _settings);
+  virtual ~ctkVTKCommandOptions();
+
+  virtual void printAdditionalInfo();
+
+  enum
+  {
+    ALL = 0,
+    QSETTINGS_ONLY = 0x1
+  };
+
+  ///
+  /// Parse the arguments
+  bool parse(int argc, const char* const argv[]);
+
+  ///
+  /// If parse return False, this function will return the unparsed arguments
+  QStringList remainingArguments();
+  void remainingArguments(int* argc, char*** argv);
+
+  ///
+  /// Return True if flag '--ignore-rest' has been specified
+  bool ignoreRest()const;
+
+  ///
+  /// If any, return the list of ignored arguments
+  QStringList ignoredArguments()const;
+
+  ///
+  /// Get the index of the last parsed argument.
+  int indexOfLastParsedArgument();
+  
+  ///
+  /// Was help selected?
+  bool helpSelected()const;
+  QString help(); 
+
+  ///
+  /// Should user settings be considered ?
+  bool disableSettings()const;
+
+  ///
+  /// Set/Get the type of the process for this set of options.
+  /// GUI application, Batch, Daemon, etc ...
+  int processType()const;
+  void setProcessType(int p);
+
+  ///
+  /// Convenient method to get associated Settings object
+  QSettings* settings()const;
+
+  ///
+  /// In case of unknown argument, return its name.
+  QString unknownArgument()const;
+
+  ///
+  /// Get the error message if Parse returned 0.
+  QString errorMessage()const;
+
+protected:
+  
+  /// Add a command line argument.
+  /// For each argument added there is a long version --long and a short version -l,
+  /// a help string, and a variable that is set to the value of the option.
+  /// The types can be int, QString, boolean (set to 1 if argument is present) or QStringList.
+  /// Also deprecated arguments can be added with only a help string.  The help
+  /// string should say that the argument is deprecated and suggest the
+  /// alternative argument to use.
+  void addBooleanArgument(const char* longarg, const char* shortarg,
+                          bool* var, const char* arghelp, bool defaultValue = false,
+                          int type=ALL);
+  void addDeprecatedArgument(const char* longarg, const char* shortarg,
+                             const char* arghelp, int type=ALL);
+  void addArgument(const char* longarg, const char* shortarg,
+                   int* var, const char* arghelp, int defaultValue = 0, int type=ALL);
+  void addArgument(const char* longarg, const char* shortarg,
+                   QString* var, const char* arghelp,
+                   const QString& defaultValue = QString(), int type=ALL);
+  void addArgument(const char* longarg, const char* shortarg,
+                   QStringList* var, const char* arghelp,
+                   const QStringList& defaultValue = QStringList(), int type=ALL);
+
+
+  /// Initialize arguments.
+  virtual void initialize();
+
+  /// Disable current settings
+  virtual void disableCurrentSettings() = 0;
+  
+  ///
+  /// After parsing, process extra option dependencies.
+  virtual bool postProcess(int argc, const char* const* argv);
+
+  /// This method is called when wrong argument is found. If it returns False, then
+  /// the parsing will fail.
+  virtual bool wrongArgument(const char* argument);
+
+  /// This method is called when a deprecated argument is found. If it returns False, then
+  /// the parsing will fail.
+  virtual bool deprecatedArgument(const char* argument);
+  
+private:
+  CTK_DECLARE_PRIVATE(ctkVTKCommandOptions);
+}; 
+
+#endif