ctkVTKCommandOptions.cpp

Go to the documentation of this file.
00001 /*=========================================================================
00002 
00003   Library:   CTK
00004  
00005   Copyright (c) 2010  Kitware Inc.
00006 
00007   Licensed under the Apache License, Version 2.0 (the "License");
00008   you may not use this file except in compliance with the License.
00009   You may obtain a copy of the License at
00010 
00011       http://www.commontk.org/LICENSE
00012 
00013   Unless required by applicable law or agreed to in writing, software
00014   distributed under the License is distributed on an "AS IS" BASIS,
00015   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00016   See the License for the specific language governing permissions and
00017   limitations under the License.
00018  
00019 =========================================================================*/
00020 /*=========================================================================
00021   
00022   Program:   ParaView
00023   Module:    $RCSfile: vtkCommandOptions.h,v $
00024 
00025   Copyright (c) Kitware, Inc.
00026   All rights reserved.
00027   See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details.
00028 
00029      This software is distributed WITHOUT ANY WARRANTY; without even
00030      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
00031      PURPOSE.  See the above copyright notice for more information.
00032 
00033 =========================================================================*/
00034 
00035 // Qt includes
00036 #include <QDebug>
00037 #include <QString>
00038 #include <QLatin1String>
00039 #include <QSettings>
00040 #include <QHash>
00041 #include <QList>
00042 #include <QPointer>
00043 #include <QStringList>
00044 
00045 // CTK includes
00046 #include <ctkUtils.h>
00047 #include "ctkVTKCommandOptions.h"
00048 
00049 // VTKSYS includes
00050 #include <vtksys/CommandLineArguments.hxx>
00051 
00052 // --------------------------------------------------------------------------
00053 class ctkVTKCommandOptionsPrivate: public ctkPrivate<ctkVTKCommandOptions>
00054 {
00055 public:
00056   typedef ctkVTKCommandOptionsPrivate Self;
00057   ctkVTKCommandOptionsPrivate();
00058   ~ctkVTKCommandOptionsPrivate();
00059 
00060   void cleanArgcArgv();
00061 
00063   static int unknownArgumentHandler(const char* argument, void* call_data);
00064 
00068   bool checkForIgnoreRestFlag(const char* argument);
00069 
00071   static int deprecatedArgumentHandler(const char* argument, const char* value, void* call_data);
00072                                                        
00075   char** mapQStringPtrToCharPtr(QString* qStringPtr);
00076 
00079   std::vector<std::string>* mapQStringListPtrToStringVectorPtr(QStringList* qStringListPtr);
00080 
00082   void syncQStringPtrWithCharPtr();
00083 
00085   void syncQStringListPtrWithStringVectorPtr();
00086 
00087   vtksys::CommandLineArguments   CMD;
00088   QString                        UnknownArgument;
00089   QString                        ErrorMessage;
00090   bool                           HelpSelected;
00091   bool                           DisableSettings;
00092   bool                           IgnoreRest;
00093   QStringList                    IgnoredArguments;
00094   int                            Argc;
00095   char**                         Argv;
00096   QPointer<QSettings>            Settings;
00097   int                            ProcessType; // GUI, Batch, Daemon, ...
00098   
00099   QHash<QString*, char**>                         QStringPointerToCharPointerMap;
00100   QHash<QStringList*, std::vector<std::string>*>  QStringListPointerToStringVectorPointerMap;
00101 };
00102 
00103 //-----------------------------------------------------------------------------
00104 // ctkVTKCommandOptionsPrivate methods
00105 
00106 // --------------------------------------------------------------------------
00107 ctkVTKCommandOptionsPrivate::ctkVTKCommandOptionsPrivate()
00108 {
00109   this->CMD.SetUnknownArgumentCallback(ctkVTKCommandOptionsPrivate::unknownArgumentHandler);
00110   this->CMD.SetClientData(this);
00111 
00112   this->Argc = 0;
00113   this->Argv = 0; 
00114   this->HelpSelected = false;
00115   this->DisableSettings = false;
00116   this->IgnoreRest = false;
00117 }
00118 
00119 // --------------------------------------------------------------------------
00120 ctkVTKCommandOptionsPrivate::~ctkVTKCommandOptionsPrivate()
00121 {
00122   this->cleanArgcArgv();
00123   foreach (QString* qStringPtr, this->QStringPointerToCharPointerMap.keys())
00124     {
00125     delete this->QStringPointerToCharPointerMap[qStringPtr];
00126     }
00127   foreach (QStringList* qStringListPtr, this->QStringListPointerToStringVectorPointerMap.keys())
00128     {
00129     delete this->QStringListPointerToStringVectorPointerMap[qStringListPtr];
00130     }
00131 }
00132 
00133 // --------------------------------------------------------------------------
00134 void ctkVTKCommandOptionsPrivate::cleanArgcArgv()
00135 {
00136   int cc;
00137   if (this->Argv)
00138     {
00139     for (cc = 0; cc < this->Argc; cc++)
00140       {
00141       delete [] this->Argv[cc];
00142       }
00143     delete [] this->Argv;
00144     this->Argv = 0;
00145     }
00146 }
00147 
00148 //----------------------------------------------------------------------------
00149 int ctkVTKCommandOptionsPrivate::unknownArgumentHandler(const char* argument,
00150                                                       void* call_data)
00151 {
00152   ctkVTKCommandOptionsPrivate* self =
00153     static_cast<ctkVTKCommandOptionsPrivate*>(call_data);
00154   if (self)
00155     {
00156     self->UnknownArgument = QString::fromLatin1(argument);
00157     return self->checkForIgnoreRestFlag(argument);
00158     }
00159   return 0;
00160 }
00161 
00162 //----------------------------------------------------------------------------
00163 bool ctkVTKCommandOptionsPrivate::checkForIgnoreRestFlag(const char* argument)
00164 {
00165   CTK_P(ctkVTKCommandOptions);
00166   if (this->IgnoreRest)
00167     {
00168     this->IgnoredArguments << QLatin1String(argument);
00169     return true;
00170     }
00171   else
00172     {
00173     return p->wrongArgument(argument);
00174     }
00175 }
00176 
00177 //----------------------------------------------------------------------------
00178 int ctkVTKCommandOptionsPrivate::deprecatedArgumentHandler(const char* argument,
00179                                                          const char* , void* call_data)
00180 {
00181   //qDebug() << "UnknownArgumentHandler: " << argument;
00182   ctkVTKCommandOptionsPrivate* self = static_cast<ctkVTKCommandOptionsPrivate*>(call_data);
00183   if (self)
00184     {
00185     return self->ctk_p()->deprecatedArgument(argument);
00186     }
00187   return 0;
00188 }
00189 
00190 // --------------------------------------------------------------------------
00191 char** ctkVTKCommandOptionsPrivate::mapQStringPtrToCharPtr(QString* qStringPtr)
00192 {
00193   Q_ASSERT(!this->QStringPointerToCharPointerMap.contains(qStringPtr));
00194   char** charPtr = new char*; // Create a new pointer
00195   *charPtr = 0; // Initialize to 0
00196   this->QStringPointerToCharPointerMap[qStringPtr] = charPtr;
00197   return charPtr;
00198 }
00199 
00200 // --------------------------------------------------------------------------
00201 std::vector<std::string>*
00202 ctkVTKCommandOptionsPrivate::mapQStringListPtrToStringVectorPtr(QStringList* qStringListPtr)
00203 {
00204   Q_ASSERT(!this->QStringListPointerToStringVectorPointerMap.contains(qStringListPtr));
00205   std::vector<std::string>* vectorPtr = new std::vector<std::string>(); // Create a new vector
00206   this->QStringListPointerToStringVectorPointerMap[qStringListPtr] = vectorPtr;
00207   return vectorPtr;
00208 }
00209 
00210 // --------------------------------------------------------------------------
00211 void ctkVTKCommandOptionsPrivate::syncQStringPtrWithCharPtr()
00212 {
00213   foreach(QString* qStringPtr, this->QStringPointerToCharPointerMap.keys())
00214     {
00215     char** charPtr = this->QStringPointerToCharPointerMap[qStringPtr];
00216     Q_ASSERT(charPtr);
00217     // Update QString only if the content pointed by charPtr is valid
00218     if (*charPtr)
00219       {
00220       qStringPtr->clear();
00221       qStringPtr->append(QLatin1String(*charPtr));
00222       }
00223     }
00224 }
00225 
00226 // --------------------------------------------------------------------------
00227 void ctkVTKCommandOptionsPrivate::syncQStringListPtrWithStringVectorPtr()
00228 {
00229   foreach(QStringList* qStringListPtr, this->QStringListPointerToStringVectorPointerMap.keys())
00230     {
00231     std::vector<std::string>* vectorPtr =
00232       this->QStringListPointerToStringVectorPointerMap[qStringListPtr];
00233     Q_ASSERT(vectorPtr);
00234     // Update QString only if vectorPtr is not empty
00235     if (vectorPtr->size() > 0)
00236       {
00237       qStringListPtr->clear();
00238       QStringList convertedVector;
00239       ctkUtils::stlVectorToQList(*vectorPtr, convertedVector);
00240       qStringListPtr->append(convertedVector);
00241       }
00242     }
00243 }
00244 
00245 //-----------------------------------------------------------------------------
00246 // ctkVTKCommandOptions methods
00247 
00248 // --------------------------------------------------------------------------
00249 ctkVTKCommandOptions::ctkVTKCommandOptions(QSettings* _settings)
00250 {
00251   CTK_INIT_PRIVATE(ctkVTKCommandOptions);
00252   Q_ASSERT(_settings);
00253   CTK_D(ctkVTKCommandOptions);
00254   d->Settings = _settings;
00255 }
00256 
00257 //----------------------------------------------------------------------------
00258 ctkVTKCommandOptions::~ctkVTKCommandOptions()
00259 {
00260 }
00261 
00262 //----------------------------------------------------------------------------
00263 void ctkVTKCommandOptions::printAdditionalInfo()
00264 {
00265   CTK_D(ctkVTKCommandOptions);
00266   qDebug() << "ctkVTKCommandOptions:" << this << endl
00267            << " HelpSelected:" << this->helpSelected() << endl
00268            << " DisableSettings:" << d->DisableSettings << endl
00269            << " IgnoreRest:" << d->IgnoreRest << endl
00270            << " IgnoredArguments:" << d->IgnoredArguments;
00271 }
00272 
00273 //----------------------------------------------------------------------------
00274 CTK_GET_CXX(ctkVTKCommandOptions, QString, errorMessage, ErrorMessage);
00275 CTK_GET_CXX(ctkVTKCommandOptions, QString, unknownArgument, UnknownArgument);
00276 CTK_GET_CXX(ctkVTKCommandOptions, bool, helpSelected, HelpSelected);
00277 CTK_GET_CXX(ctkVTKCommandOptions, bool, disableSettings, DisableSettings);
00278 CTK_GET_CXX(ctkVTKCommandOptions, QSettings*, settings, Settings);
00279 CTK_GET_CXX(ctkVTKCommandOptions, bool, ignoreRest, IgnoreRest);
00280 CTK_GET_CXX(ctkVTKCommandOptions, QStringList, ignoredArguments, IgnoredArguments);
00281 
00282 //----------------------------------------------------------------------------
00283 CTK_GET_CXX(ctkVTKCommandOptions, int, processType, ProcessType);
00284 CTK_SET_CXX(ctkVTKCommandOptions, int, setProcessType, ProcessType);
00285 
00286 //----------------------------------------------------------------------------
00287 void ctkVTKCommandOptions::initialize()
00288 {
00289 }
00290 
00291 //----------------------------------------------------------------------------
00292 QString ctkVTKCommandOptions::help()
00293 {
00294   CTK_D(ctkVTKCommandOptions);
00295   d->CMD.SetLineLength(300);
00296   return QLatin1String(d->CMD.GetHelp());
00297 }
00298 
00299 //----------------------------------------------------------------------------
00300 bool ctkVTKCommandOptions::postProcess(int, const char* const*)
00301 {
00302   return true;
00303 }
00304 
00305 //----------------------------------------------------------------------------
00306 bool ctkVTKCommandOptions::parse(int argc, const char* const argv[])
00307 {
00308   CTK_D(ctkVTKCommandOptions);
00309   d->CMD.Initialize(argc, argv);
00310   this->initialize();
00311   this->addBooleanArgument("--help", "/?", &d->HelpSelected,
00312                            "Displays available command line arguments.");
00313 
00314   this->addBooleanArgument("--disable-settings", 0, &d->DisableSettings,
00315                            "Start application ignoring user settings.");
00316 
00317 
00318   this->addBooleanArgument("--ignore-rest", "--", &d->IgnoreRest,
00319                            "Ignores the rest of the labeled arguments following this flag.");
00320 
00321   // Get options from the command line
00322   bool res1 = d->CMD.Parse();
00323   bool res2 = this->postProcess(argc, argv);
00324   //qDebug() << "Res1:" << res1 << ", Res2:" << res2;
00325   d->cleanArgcArgv();
00326   d->CMD.GetRemainingArguments(&d->Argc, &d->Argv);
00327 
00328   if (d->DisableSettings)
00329     {
00330     this->disableCurrentSettings();
00331     }
00332 
00333   d->syncQStringPtrWithCharPtr();
00334   d->syncQStringListPtrWithStringVectorPtr();
00335 
00336   // Since CommandLineArguments include arg0 in the list
00337   // of remaining arguments, let's create a temporary list and remove it.
00338   QStringList _remaingingArguments = this->remainingArguments();
00339   _remaingingArguments.removeFirst();
00340 
00341   // Update ignored arguments list
00342   d->IgnoredArguments << _remaingingArguments;
00343   
00344   return res1 && res2;
00345 }
00346 
00347 //----------------------------------------------------------------------------
00348 QStringList ctkVTKCommandOptions::remainingArguments()
00349 {
00350   CTK_D(ctkVTKCommandOptions);
00351   QStringList tmp; 
00352   for(int i=0; i < d->Argc; ++i)
00353     {
00354     tmp << d->Argv[i]; 
00355     }
00356   return tmp;
00357 }
00358 
00359 //----------------------------------------------------------------------------
00360 void ctkVTKCommandOptions::remainingArguments(int* argc, char*** argv)
00361 {
00362   CTK_D(ctkVTKCommandOptions);
00363   *argc = d->Argc;
00364   *argv = d->Argv;
00365 }
00366 
00367 //----------------------------------------------------------------------------
00368 void ctkVTKCommandOptions::addDeprecatedArgument(const char* longarg, const char* shortarg,
00369                                                const char* arghelp, int type)
00370 {
00371   CTK_D(ctkVTKCommandOptions);
00372 
00373   // If it is for settings or not for the current process do nothing
00374   if((type & ctkVTKCommandOptions::QSETTINGS_ONLY) ||
00375      !(type & d->ProcessType || type == ctkVTKCommandOptions::ALL))
00376     {
00377     return;
00378     }
00379   
00380   // Add a callback for the deprecated argument handling
00381   d->CMD.AddCallback(longarg, vtksys::CommandLineArguments::NO_ARGUMENT,
00382                      ctkVTKCommandOptionsPrivate::deprecatedArgumentHandler, this, arghelp);
00383   if(shortarg)
00384     {
00385     d->CMD.AddCallback(shortarg, vtksys::CommandLineArguments::NO_ARGUMENT,
00386                        ctkVTKCommandOptionsPrivate::deprecatedArgumentHandler, this, arghelp);
00387     }
00388 }
00389 
00390 //----------------------------------------------------------------------------
00391 bool ctkVTKCommandOptions::deprecatedArgument(const char* argument)
00392 {
00393   CTK_D(ctkVTKCommandOptions);
00394   d->ErrorMessage = QString("  %1").arg(d->CMD.GetHelp(argument));
00395   return false;
00396 }
00397 
00398 //----------------------------------------------------------------------------
00399 bool ctkVTKCommandOptions::wrongArgument(const char* argument)
00400 {
00401   Q_UNUSED(argument);
00402   return false;
00403 }
00404 
00405 //----------------------------------------------------------------------------
00406 void ctkVTKCommandOptions::addBooleanArgument(const char* longarg, const char* shortarg,
00407                                             bool* var, const char* arghelp,
00408                                             bool defaultValue, int type)
00409 {
00410   CTK_D(ctkVTKCommandOptions);
00411 
00412   // Attempt to read from settings only if longarg is different from '--disable-settings'.
00413   if (QLatin1String(longarg) != "--disable-settings")
00414     {
00415     *var = d->Settings->value(QLatin1String(longarg+2), defaultValue).toBool();
00416     
00417     if(type & ctkVTKCommandOptions::QSETTINGS_ONLY)
00418       {
00419       return;
00420       }
00421     }
00422 
00423   // If the process type matches then add the argument to the command line
00424   if(type & d->ProcessType || type == ctkVTKCommandOptions::ALL)
00425     {
00426     d->CMD.AddBooleanArgument(longarg, var, arghelp);
00427     if (shortarg)
00428       {
00429       d->CMD.AddBooleanArgument(shortarg, var, longarg);
00430       }
00431     }
00432 }
00433 
00434 //----------------------------------------------------------------------------
00435 void ctkVTKCommandOptions::addArgument(const char* longarg, const char* shortarg, QString* var,
00436                                     const char* arghelp, const QString& defaultValue, int type)
00437 {
00438   CTK_D(ctkVTKCommandOptions);
00439   *var = d->Settings->value(QLatin1String(longarg+2), defaultValue).toString();
00440   
00441   if(type & ctkVTKCommandOptions::QSETTINGS_ONLY)
00442     {
00443     return;
00444     }
00445   
00446   if(type & d->ProcessType || type == ctkVTKCommandOptions::ALL)
00447     {
00448     char ** charstar = d->mapQStringPtrToCharPtr(var);
00449     typedef vtksys::CommandLineArguments argT;
00450     d->CMD.AddArgument(longarg, argT::EQUAL_ARGUMENT, charstar, arghelp);
00451     if ( shortarg )
00452       {
00453       d->CMD.AddArgument(shortarg, argT::EQUAL_ARGUMENT, charstar, longarg);
00454       }
00455     }
00456 }
00457 
00458 //----------------------------------------------------------------------------
00459 void ctkVTKCommandOptions::addArgument(const char* longarg, const char* shortarg,
00460                                      QStringList* var, const char* arghelp,
00461                                      const QStringList& defaultValue, int type)
00462 {
00463   CTK_D(ctkVTKCommandOptions);
00464   *var = d->Settings->value(QLatin1String(longarg+2), defaultValue).toStringList();
00465   
00466   if(type & ctkVTKCommandOptions::QSETTINGS_ONLY)
00467     {
00468     return;
00469     }
00470     
00471   if(type & d->ProcessType || type == ctkVTKCommandOptions::ALL)
00472     {
00473     std::vector<std::string>* vectorPtr = d->mapQStringListPtrToStringVectorPtr(var);
00474     typedef vtksys::CommandLineArguments argT;
00475     d->CMD.AddArgument(longarg, argT::MULTI_ARGUMENT, vectorPtr, arghelp);
00476     if (shortarg)
00477       {
00478       d->CMD.AddArgument(shortarg, argT::MULTI_ARGUMENT, vectorPtr, longarg);
00479       }
00480     }
00481 }
00482 
00483 //----------------------------------------------------------------------------
00484 void ctkVTKCommandOptions::addArgument(const char* longarg, const char* shortarg, int* var,
00485                                      const char* arghelp, int defaultValue, int type)
00486 {
00487   CTK_D(ctkVTKCommandOptions);
00488   *var = d->Settings->value(QLatin1String(longarg+2), defaultValue).toInt();
00489   
00490   if(type & ctkVTKCommandOptions::QSETTINGS_ONLY)
00491     {
00492     return;
00493     }
00494     
00495   if(type & d->ProcessType || type == ctkVTKCommandOptions::ALL)
00496     {
00497     typedef vtksys::CommandLineArguments argT;
00498     d->CMD.AddArgument(longarg, argT::EQUAL_ARGUMENT, var, arghelp);
00499     if (shortarg)
00500       {
00501       d->CMD.AddArgument(shortarg, argT::EQUAL_ARGUMENT, var, longarg);
00502       }
00503     }
00504 }
00505 
00506 //----------------------------------------------------------------------------
00507 int ctkVTKCommandOptions::indexOfLastParsedArgument()
00508 {
00509   CTK_D(ctkVTKCommandOptions);
00510   return d->CMD.GetLastArgument();
00511 }
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines