Isis 3 Programmer Reference
UserInterface.cpp
1
6/* SPDX-License-Identifier: CC0-1.0 */#include "UserInterface.h"
7
8#include <sstream>
9#include <vector>
10
11#include <QDir>
12
13#include "Application.h"
14#include "FileName.h"
15#include "Gui.h"
16#include "IException.h"
17#include "IString.h"
18#include "Message.h"
19#include "Preference.h"
20#include "ProgramLauncher.h"
21#include "TextFile.h"
22
23using namespace std;
24namespace Isis {
35 UserInterface::UserInterface(const QString &xmlfile, QVector<QString> &args) : IsisAml::IsisAml(xmlfile) {
36 p_interactive = false;
37 p_info = false;
38 p_infoFileName = "";
39 p_gui = NULL;
40 p_errList = "";
41 p_saveFile = "";
42 p_abortOnError = true;
43 p_parentId = 0;
44
45 // Make sure the user has a .Isis and .Isis/history directory
46 try {
47 FileName setup = "$HOME/.Isis/history";
48 // cannot completely test this if in unit test
49 if ( !setup.fileExists() ) {
50 setup.dir().mkpath(".");
51 }
52 }
53 catch (IException &) {
54 }
55
56 // Parse the user input
57 loadCommandLine(args);
58 }
59
60
71 UserInterface::UserInterface(const QString &xmlfile, int &argc,
72 char *argv[]) : IsisAml::IsisAml(xmlfile) {
73 p_interactive = false;
74 p_info = false;
75 p_infoFileName = "";
76 p_gui = NULL;
77 p_errList = "";
78 p_saveFile = "";
79 p_abortOnError = true;
80 p_parentId = 0;
81
82 // Make sure the user has a .Isis and .Isis/history directory
83 try {
84 FileName setup = "$HOME/.Isis/history";
85 // cannot completely test this if in unit test
86 if ( !setup.fileExists() ) {
87 setup.dir().mkpath(".");
88 }
89 }
90 catch (IException &) {
91 }
92
93 // Parse the user input
94 loadCommandLine(argc, argv);
95
96 // See if we need to create the gui
97 // can't unit test - don't want to create a Gui object while unit testing
98 if (p_interactive) {
100 p_gui = Gui::Create(*this, argc, argv);
101 }
102 }
103
104
107 // can't unit test - p_gui will be NULL in unit test
108 if (p_gui) {
109 delete p_gui;
110 p_gui = NULL;
111 }
112 }
113
121 return p_infoFileName;
122 }
123
124
132 return p_info;
133 }
134
135
145 //Clear all parameters currently in the gui
146 for (int k = 0; k < NumGroups(); k++) {
147 for (int j = 0; j < NumParams(k); j++) {
148 Clear( ParamName(k, j) );
149 }
150 }
151
152 //Load the new parameters into the gui
153 cout << p_progName << " ";
154
155 for (unsigned int currArgument = 1; currArgument < p_cmdline.size(); currArgument ++) {
156 QString paramName;
157 vector<QString> paramValue;
158
159
160 try {
161 getNextParameter(currArgument, paramName, paramValue);
162
163 if (paramName[0] == '-')
164 continue;
165
166 for (unsigned int value = 0; value < paramValue.size(); value++) {
167 IString thisValue = paramValue[value];
168 QString token = thisValue.Token("$").ToQt();
169
170 QString newValue;
171
172 while (thisValue != "") {
173 newValue += token;
174 try {
175 int j = toInt( thisValue.substr(0, 1).c_str() ) - 1;
176 newValue += p_batchList[i][j];
177 thisValue.replace(0, 1, "");
178 token = thisValue.Token("$").ToQt();
179 }
180 catch (IException &e) {
181 // Let the variable be parsed by the application
182 newValue += "$";
183 token = thisValue.Token("$").ToQt();
184 }
185 }
186
187 if (token != "")
188 newValue += token;
189
190 paramValue[value] = newValue;
191 }
192 }
193 // can't test with unit test - command line is already parsed before SetBatchList() is called
194 catch (IException &e) {
195 throw IException(IException::User, "Invalid command line", _FILEINFO_);
196 }
197
198 PutAsString(paramName, paramValue);
199
200 cout << paramName;
201
202 if(paramValue.size() == 1) {
203 cout << "=" << paramValue[0] << " ";
204 }
205 else if (paramValue.size() > 1) {
206 cout << "=(";
207
208 for (unsigned int value = 0; value < paramValue.size(); value++) {
209 if(value != 0)
210 cout << ",";
211
212 cout << paramValue[value] << endl;
213 }
214
215 cout << ") ";
216 }
217 }
218 cout << endl;
219
220 // Verify the command line
221 VerifyAll();
222 }
223
224
236 if (p_errList != "") {
237 std::ofstream os;
238 QString fileName( FileName(p_errList).expanded() );
239 os.open(fileName.toLatin1().data(), std::ios::app);
240
241 // did not unit test since it is assumed ofstream will be instantiated correctly
242 if ( !os.good() ) {
243 QString msg = "Unable to create error list [" + p_errList
244 + "] Disk may be full or directory permissions not writeable";
245 throw IException(IException::User, msg, _FILEINFO_);
246 }
247
248 for (int j = 0; j < (int) p_batchList[i].size(); j++) {
249 os << p_batchList[i][j] << " ";
250 }
251
252 os << endl;
253 os.close();
254 }
255 }
256
257
263
264 // If history recording is off, return
265 Preference &p = Preference::Preferences();
266 PvlGroup &grp = p.findGroup("UserInterface", Isis::Pvl::Traverse);
267 if (grp["HistoryRecording"][0] == "Off")
268 return;
269
270 // Get the current history file
271 Isis::FileName histFile(grp["HistoryPath"][0] + "/" + ProgramName() + ".par");
272
273 // If a save file is specified, override the default file path
274 if (p_saveFile != "")
275 histFile = p_saveFile;
276
277 // Get the current command line
278 Isis::Pvl cmdLine;
279 CommandLine(cmdLine);
280
281 Isis::Pvl hist;
282
283 // If the history file's Pvl is corrupted, then
284 // leave hist empty such that the history gets
285 // overwriten with the new entry.
286 try {
287 if ( histFile.fileExists() ) {
288 hist.read( histFile.expanded() );
289 }
290 }
291 catch (IException &) {
292 }
293
294 // Add it
295 hist.addGroup( cmdLine.findGroup("UserParameters") );
296
297 // See if we have exceeded history length
298 while( hist.groups() > toInt(grp["HistoryLength"][0]) ) {
299 hist.deleteGroup("UserParameters");
300 }
301
302 // Write it
303 try {
304 hist.write( histFile.expanded() );
305 }
306 catch (IException &) {
307 }
308 }
309
310
323 void UserInterface::loadBatchList(const QString file) {
324 // Read in the batch list
325 TextFile temp;
326 try {
327 temp.Open(file);
328 }
329 catch (IException &e) {
330 QString msg = "The batchlist file [" + file + "] could not be opened";
331 throw IException(IException::User, msg, _FILEINFO_);
332 }
333
334 p_batchList.resize( temp.LineCount() );
335
336 for (int i = 0; i < temp.LineCount(); i++) {
337 QString t;
338 temp.GetLine(t);
339
340 // Convert tabs to spaces but leave tabs inside quotes alone
341 t = IString(t).Replace("\t", " ", true).ToQt();
342
343 t = IString(t).Compress().ToQt().trimmed();
344 // Allow " ," " , " or ", " as a valid single seperator
345 t = IString(t).Replace(" ,", ",", true).ToQt();
346 t = IString(t).Replace(", ", ",", true).ToQt();
347 // Convert all spaces to "," the use "," as delimiter
348 t = IString(t).Replace(" ", ",", true).ToQt();
349 int j = 0;
350
351 QStringList tokens = t.split(",");
352
353 foreach (QString token, tokens) {
354 // removes quotes from tokens. NOTE: also removes escaped quotes.
355 token = token.remove( QRegExp("[\"']") );
356 p_batchList[i].push_back(token);
357 j++ ;
358 }
359
360 p_batchList[i].resize(j);
361 // Every row in the batchlist must have the same number of columns
362 if (i == 0)
363 continue;
364 if ( p_batchList[i - 1].size() != p_batchList[i].size() ) {
365 QString msg = "The number of columns must be constant in batchlist";
366 throw IException(IException::User, msg, _FILEINFO_);
367 }
368 }
369 // The batchlist cannot be empty
370 if (p_batchList.size() < 1) {
371 QString msg = "The list file [" + file + "] does not contain any data";
372 throw IException(IException::User, msg, _FILEINFO_);
373 }
374 }
375
376
377
391 void UserInterface::loadCommandLine(QVector<QString> &args, bool ignoreAppName) {
392 char **c_args;
393
394 if (ignoreAppName) {
395 args.prepend("someapp");
396 }
397
398 c_args = (char**)malloc(sizeof(char*)*args.size());
399
400 for (int i = 0; i < args.size(); i++) {
401 c_args[i] = (char*)malloc(sizeof(char)*args[i].size()+1);
402 strcpy(c_args[i], args[i].toLatin1().data());
403 }
404
405 loadCommandLine(args.size(), c_args);
406 }
407
408
424 void UserInterface::loadCommandLine(int argc, char *argv[]) {
425 // The program will be interactive if it has no arguments or
426 // if it has the name unitTest
427 p_progName = argv[0];
429 // cannot completely test in a unit test since unitTest will always evaluate to true
430 if ( (argc == 1) && (file.name() != "unitTest") ) {
431 p_interactive = true;
432 }
433
434 p_cmdline.clear();
435 for (int i = 0; i < argc; i++) {
436 p_cmdline.push_back(argv[i]);
437 }
438
439 // Check for special tokens (reserved parameters) (those beginning with a dash)
440 vector<QString> options;
441 options.push_back("-GUI");
442 options.push_back("-NOGUI");
443 options.push_back("-BATCHLIST");
444 options.push_back("-LAST");
445 options.push_back("-RESTORE");
446 options.push_back("-WEBHELP");
447 options.push_back("-HELP");
448 options.push_back("-ERRLIST");
449 options.push_back("-ONERROR");
450 options.push_back("-SAVE");
451 options.push_back("-INFO");
452 options.push_back("-PREFERENCE");
453 options.push_back("-LOG");
454 options.push_back("-VERBOSE");
455 options.push_back("-PID");
456
457 bool usedDashLast = false;
458 bool usedDashRestore = false; //< for throwing -batchlist exceptions at end of function
459
460 // pre-process command line for -HELP first
461 preProcess("-HELP", options);
462 // pre-process command line for -WEBHELP
463 preProcess("-WEBHELP", options);
464 // now, parse command line to evaluate -LAST
465 preProcess("-LAST", options);
466
467 for (unsigned int currArgument = 1; currArgument < (unsigned)argc; currArgument++) {
468 QString paramName;
469 vector<QString> paramValue;
470
471 getNextParameter(currArgument, paramName, paramValue);
472
473 // we now have a name,value pair
474 if (paramName[0] == '-') {
475 paramName = paramName.toUpper();
476
477 // where if(paramname == -last ) to continue } was originally
478
479 if (paramValue.size() > 1) {
480 QString msg = "Invalid value for reserve parameter ["
481 + paramName + "]";
482 throw IException(IException::User, msg, _FILEINFO_);
483 }
484
485 // resolve the reserved parameter (e.g. set -h to -HELP)
486 paramName = resolveParameter(paramName, options);
487
488
489
490 // Prevent double handling of -LAST to prevent conflicts
491 // Keep track of using -LAST to prevent conflicts with -BATCHLIST
492 if (paramName == "-LAST") {
493 usedDashLast = true;
494 continue;
495 }
496
497
498 // Keep track of using -RESTORE to prevent conflicts with -BATCHLIST
499 if (paramName == "-RESTORE") {
500 usedDashRestore = true;
501 }
502
503
504 QString realValue = "";
505
506 if ( paramValue.size() ) {
507 realValue = paramValue[0];
508 }
509
510 evaluateOption(paramName, realValue);
511
512 continue;
513 }
514
515 try {
516 Clear(paramName);
517 PutAsString(paramName, paramValue);
518 }
519 catch (IException &e) {
520 throw IException(e, IException::User, "Invalid command line", _FILEINFO_);
521 }
522
523 }
524 if(usedDashLast) {
525 Pvl temp;
526 CommandLine(temp);
527 cout << BuildNewCommandLineFromPvl(temp) << endl;
528 }
529
530 // Can't use the batchlist with the gui, save, last or restore option
531 if ( BatchListSize() != 0 && (p_interactive || usedDashLast || p_saveFile != ""
532 || usedDashRestore) ) {
533 QString msg = "-BATCHLIST cannot be used with -GUI, -SAVE, -RESTORE, ";
534 msg += "or -LAST";
535 throw IException(IException::User, msg, _FILEINFO_);
536 }
537
538 // Must use batchlist if using errorlist or onerror=continue
539 if ( (BatchListSize() == 0) && (!p_abortOnError || p_errList != "") ) {
540 QString msg = "-ERRLIST and -ONERROR=continue cannot be used without ";
541 msg += " the -BATCHLIST option";
542 throw IException(IException::User, msg, _FILEINFO_);
543 }
544 }
545
546 QString UserInterface::BuildNewCommandLineFromPvl(Pvl temp){
547 PvlGroup group = temp.group(0);
548 int numKeywords = group.keywords();
549 QString returnVal = p_progName + " ";
550
551 for(int i = 0; i < numKeywords; i++){
552 PvlKeyword key = group[i];
553 returnVal += key.name();
554 returnVal += "=";
555 returnVal += QString(key);
556 returnVal += " ";
557 }
558 return returnVal;
559 }
571 void UserInterface::loadHistory(const QString file) {
572 Isis::FileName hist(file);
573 if ( hist.fileExists() ) {
574 try {
575 Isis::Pvl lab( hist.expanded() );
576
577 int g = lab.groups() - 1;
578 if (g >= 0 && lab.group(g).isNamed("UserParameters") ) {
579 Isis::PvlGroup &up = lab.group(g);
580 QString commandline(p_progName + " ");
581 for (int k = 0; k < up.keywords(); k++) {
582 QString keyword = up[k].name();
583
584 vector<QString> values;
585
586 for (int i = 0; i < up[k].size(); i++) {
587 values.push_back(up[k][i]);
588 }
589
590 const IsisParameterData *paramData = ReturnParam(keyword);
591
592 bool matchesDefault = false;
593 if (values.size() == 1 && paramData->internalDefault == values[0])
594 matchesDefault = true;
595
596 if (!matchesDefault) {
597 matchesDefault =
598 (values.size() == paramData->defaultValues.size());
599
600 for (int i = 0; matchesDefault && i < (int)values.size(); i++) {
601 matchesDefault = matchesDefault &&
602 values[i] == paramData->defaultValues[i];
603 }
604 }
605
606 if (!matchesDefault) {
607 PutAsString(keyword, values);
608 commandline += keyword + "=";
609 foreach(QString val, values) {
610 commandline += val + " ";
611 }
612 }
613 }
614
615 return;
616 }
617
618 for (int o = lab.objects() - 1; o >= 0; o--) {
619 if ( lab.object(o).isNamed( ProgramName() ) ) {
620 Isis::PvlObject &obj = lab.object(o);
621 for (int g = obj.groups() - 1; g >= 0; g--) {
622 Isis::PvlGroup &up = obj.group(g);
623 if ( up.isNamed("UserParameters") ) {
624 for (int k = 0; k < up.keywords(); k++) {
625 QString keyword = up[k].name();
626 QString value = up[k][0];
627 PutAsString(keyword, value);
628 }
629 }
630 return;
631 }
632 }
633 }
634
635 /*QString msg = "[" + hist.expanded() +
636 "] does not contain any parameters to restore";
637 throw Isis::iException::Message( Isis::iException::User, msg, _FILEINFO_ );*/
638 }
639 catch (...) {
640 QString msg = "The history file [" + file + "] is for a different application or corrupt, "\
641 "please fix or delete this file";
642 throw IException(IException::User, msg, _FILEINFO_);
643 }
644 }
645 else {
646 QString msg = "The history file [" + file + "] does not exist";
647 throw IException(IException::User, msg, _FILEINFO_);
648 }
649 }
650
651
669 void UserInterface::evaluateOption(const QString name,
670 const QString value) {
671 // check to see if the program is a unitTest
672 bool unitTest = false;
673 if (FileName(p_progName).name() == "unitTest") {
674 unitTest = true;
675 }
676 Preference &p = Preference::Preferences();
677
678 if (name == "-GUI") {
679 p_interactive = true;
680 }
681 else if (name == "-NOGUI") {
682 p_interactive = false;
683 }
684 else if (name == "-BATCHLIST") {
685 loadBatchList(value);
686 }
687 else if (name == "-LAST") {
688 QString histFile;
689 // need to handle for unit test since -LAST is preprocessed
690 if (unitTest) {
691 histFile = "./" + FileName(p_progName).name() + ".par";
692 }
693 else {
694 PvlGroup &grp = p.findGroup("UserInterface", Isis::Pvl::Traverse);
695 histFile = grp["HistoryPath"][0] + "/" + FileName(p_progName).name() + ".par";
696 }
697
698 loadHistory(histFile);
699 }
700 else if(name == "-RESTORE") {
701 loadHistory(value);
702 }
703 else if(name == "-WEBHELP") {
704 Isis::PvlGroup &pref = Isis::Preference::Preferences().findGroup("UserInterface");
705 QString command = pref["GuiHelpBrowser"];
706 command += " $ISISROOT/docs/Application/presentation/Tabbed/";
707 command += FileName(p_progName).name() + "/" + FileName(p_progName).name() + ".html";
708 // cannot test else in unit test - don't want to open webhelp
709 if (unitTest) {
711 "Evaluating -WEBHELP should only throw this exception during a unitTest",
712 _FILEINFO_);
713 }
714 else {
716 exit(0);
717 }
718
719 }
720 else if (name == "-INFO") {
721 p_info = true;
722
723 // check for filename and set value
724 if (value.size() != 0) {
725 p_infoFileName = value;
726 }
727 }
728 else if (name == "-HELP") {
729 if (value.size() == 0) {
730 Pvl params;
731 params.setTerminator("");
732 for (int k = 0; k < NumGroups(); k++) {
733 for (int j = 0; j < NumParams(k); j++) {
734 if (ParamListSize(k, j) == 0) {
735 params += PvlKeyword( ParamName(k, j), ParamDefault(k, j) );
736 }
737 else {
738 PvlKeyword key( ParamName(k, j) );
739 QString def = ParamDefault(k, j);
740 for (int l = 0; l < ParamListSize(k, j); l++) {
741 if (ParamListValue(k, j, l) == def)
742 key.addValue("*" + def);
743 else
744 key.addValue( ParamListValue(k, j, l) );
745 }
746 params += key;
747 }
748 }
749 }
750 cout << params;
751 }
752 else {
753 Pvl param;
754 param.setTerminator("");
755 QString key = value;
756 for (int k = 0; k < NumGroups(); k++) {
757 for (int j = 0; j < NumParams(k); j++) {
758 if (ParamName(k, j) == key) {
759 param += PvlKeyword("ParameterName", key);
760 param += PvlKeyword( "Brief", ParamBrief(k, j) );
761 param += PvlKeyword( "Type", ParamType(k, j) );
762 if (PixelType(k, j) != "") {
763 param += PvlKeyword( "PixelType", PixelType(k, j) );
764 }
765 if (ParamInternalDefault(k, j) != "") {
766 param += PvlKeyword( "InternalDefault", ParamInternalDefault(k, j) );
767 }
768 else {
769 param += PvlKeyword( "Default", ParamDefault(k, j) );
770 }
771 if (ParamMinimum(k, j) != "") {
772 if (ParamMinimumInclusive(k, j).toUpper() == "YES") {
773 param += PvlKeyword( "GreaterThanOrEqual",
774 ParamMinimum(k, j) );
775 }
776 else {
777 param += PvlKeyword( "GreaterThan",
778 ParamMinimum(k, j) );
779 }
780 }
781 if (ParamMaximum(k, j) != "") {
782 if (ParamMaximumInclusive(k, j).toUpper() == "YES") {
783 param += PvlKeyword( "LessThanOrEqual",
784 ParamMaximum(k, j) );
785 }
786 else {
787 param += PvlKeyword( "LessThan",
788 ParamMaximum(k, j) );
789 }
790 }
791 if (ParamLessThanSize(k, j) > 0) {
792 PvlKeyword key("LessThan");
793 for(int l = 0; l < ParamLessThanSize(k, j); l++) {
794 key.addValue( ParamLessThan(k, j, l) );
795 }
796 param += key;
797 }
798 if (ParamLessThanOrEqualSize(k, j) > 0) {
799 PvlKeyword key("LessThanOrEqual");
800 for (int l = 0; l < ParamLessThanOrEqualSize(k, j); l++) {
801 key.addValue( ParamLessThanOrEqual(k, j, l) );
802 }
803 param += key;
804 }
805 if (ParamNotEqualSize(k, j) > 0) {
806 PvlKeyword key("NotEqual");
807 for (int l = 0; l < ParamNotEqualSize(k, j); l++) {
808 key.addValue( ParamNotEqual(k, j, l) );
809 }
810 param += key;
811 }
812 if (ParamGreaterThanSize(k, j) > 0) {
813 PvlKeyword key("GreaterThan");
814 for (int l = 0; l < ParamGreaterThanSize(k, j); l++) {
815 key.addValue( ParamGreaterThan(k, j, l) );
816 }
817 param += key;
818 }
819 if (ParamGreaterThanOrEqualSize(k, j) > 0) {
820 PvlKeyword key("GreaterThanOrEqual");
821 for(int l = 0; l < ParamGreaterThanOrEqualSize(k, j); l++) {
822 key.addValue( ParamGreaterThanOrEqual(k, j, l) );
823 }
824 param += key;
825 }
826 if (ParamIncludeSize(k, j) > 0) {
827 PvlKeyword key("Inclusions");
828 for (int l = 0; l < ParamIncludeSize(k, j); l++) {
829 key.addValue( ParamInclude(k, j, l) );
830 }
831 param += key;
832 }
833 if (ParamExcludeSize(k, j) > 0) {
834 PvlKeyword key("Exclusions");
835 for (int l = 0; l < ParamExcludeSize(k, j); l++) {
836 key.addValue( ParamExclude(k, j, l) );
837 }
838 param += key;
839 }
840 if (ParamOdd(k, j) != "") {
841 param += PvlKeyword( "Odd", ParamOdd(k, j) );
842 }
843 if (ParamListSize(k, j) != 0) {
844 for (int l = 0; l < ParamListSize(k, j); l++) {
845 PvlGroup grp( ParamListValue(k, j, l) );
846 grp += PvlKeyword( "Brief", ParamListBrief(k, j, l) );
847 if (ParamListIncludeSize(k, j, l) != 0) {
848 PvlKeyword include("Inclusions");
849 for (int m = 0; m < ParamListIncludeSize(k, j, l); m++) {
850 include.addValue( ParamListInclude(k, j, l, m) );
851 }
852 grp += include;
853 }
854 if (ParamListExcludeSize(k, j, l) != 0) {
855 PvlKeyword exclude("Exclusions");
856 for (int m = 0; m < ParamListExcludeSize(k, j, l); m++) {
857 exclude.addValue( ParamListExclude(k, j, l, m) );
858 }
859 grp += exclude;
860 }
861 param.addGroup(grp);
862 }
863 }
864 cout << param;
865 }
866 }
867 }
868 }
869 // we must throw an exception for unitTest to handle to continue testing
870 if (unitTest) {
872 "Evaluating -HELP should only throw this exception during a unitTest",
873 _FILEINFO_);
874 }
875 // all other apps shall exit when -HELP is present
876 else {
877 exit(0);
878 }
879 }
880 else if (name == "-PID") {
881 p_parentId = toInt(value);
882 }
883 else if (name == "-ERRLIST") {
884 p_errList = value;
885
886 if (value == "") {
887 QString msg = "-ERRLIST expects a file name";
888 throw IException(IException::User, msg, _FILEINFO_);
889 }
890
891 if ( FileName(p_errList).fileExists() ) {
892 QFile::remove(p_errList);
893 }
894 }
895 else if (name == "-ONERROR") {
896 if (value.toUpper() == "CONTINUE") {
897 p_abortOnError = false;
898 }
899
900 else if (value.toUpper() == "ABORT") {
901 p_abortOnError = true;
902 }
903
904 else {
905 QString msg = "[" + value
906 + "] is an invalid value for -ONERROR, options are ABORT or CONTINUE";
907 throw IException(IException::User, msg, _FILEINFO_);
908 }
909 }
910 else if (name == "-SAVE") {
911 if (value.size() == 0) {
912 p_saveFile = ProgramName() + ".par";
913 }
914 else {
915 p_saveFile = value;
916 }
917 }
918 else if (name == "-PREFERENCE") {
919 p.Load(value);
920 p_preference = value;
921 }
922 else if (name == "-LOG") {
923 if( value.isEmpty() ) {
924 p.findGroup("SessionLog")["FileOutput"].setValue("On");
925 }
926 else {
927 p.findGroup("SessionLog")["FileOutput"].setValue("On");
928 p.findGroup("SessionLog")["FileName"].setValue(value);
929 }
930 }
931 // this only evaluates to true in unit test since this is last else if
932 else if (name == "-VERBOSE") {
933 p.findGroup("SessionLog")["TerminalOutput"].setValue("On");
934 }
935
936 // Can't have a parent id and the gui
937 if (p_parentId > 0 && p_interactive) {
938 QString msg = "-GUI and -PID are incompatible arguments";
939 throw IException(IException::Unknown, msg, _FILEINFO_);
940 }
941 }
942
943
944
956 void UserInterface::getNextParameter(unsigned int &curPos,
957 QString &name,
958 std::vector<QString> &value) {
959 QString paramName = p_cmdline[curPos];
960 QString paramValue = "";
961
962 // we need to split name and value, they can either be in 1, 2 or 3 arguments,
963 // try to see if "=" is end of argument to distinguish. Some options have no
964 // "=" and they are value-less (-gui for example).
965 if ( !paramName.contains("=") ) {
966 // This looks value-less, but lets make sure
967 // the next argument is not an equals sign by
968 // itself
969 if (curPos < p_cmdline.size() - 2) {
970 if (QString(p_cmdline[curPos + 1]).compare("=") == 0) {
971 paramValue = p_cmdline[curPos + 2];
972
973 // increment extra to skip 2 elements next time around
974 curPos += 2;
975 }
976 }
977 }
978 // = is end of parameter, next item must be value
979 else if ( paramName.endsWith("=") ) {
980 paramName = paramName.mid(0, paramName.size() - 1);
981
982 if (curPos + 1 < p_cmdline.size() ) {
983 paramValue = p_cmdline[curPos + 1];
984 }
985
986 // increment extra to skip next element next time around
987 curPos++ ;
988 }
989 // we found "=" in the middle
990 else if (paramName.indexOf("=") > 0) {
991 QString parameterLiteral = p_cmdline[curPos];
992 paramName = parameterLiteral.mid( 0, parameterLiteral.indexOf("=") );
993 paramValue = parameterLiteral.mid(parameterLiteral.indexOf("=") + 1);
994 }
995 // We found "=" at the beginning - did we find "appname param =value" ?
996 else {
997 // parameters can not start with "="
998 QString msg = "Unknown parameter [" + QString(p_cmdline[curPos])
999 + "]";
1000 throw IException(IException::User, msg, _FILEINFO_);
1001 }
1002
1003 name = paramName;
1004 value.clear();
1005
1006 // read arrays out of paramValue
1007 paramValue = paramValue.trimmed();
1008
1009 if (paramValue.length() > 0 && paramValue[0] != '(') {
1010 // We dont have an array... if they escaped
1011 // an open paren, undo their escape
1012
1013 // escape: \‍( result: (
1014 if (paramValue.length() > 1 && paramValue.mid(0, 2) =="\\(") {
1015 paramValue = paramValue.mid(1);
1016 }
1017 // escape: \\‍( result: \‍(
1018 else if (paramValue.length() > 2 && paramValue.mid(0, 3) == "\\\\(") {
1019 paramValue = paramValue.mid(1);
1020 }
1021
1022 value.push_back(paramValue);
1023 }
1024 else if ( paramValue.length() ) {
1025 // We have an array...
1026 value = readArray(paramValue);
1027 }
1028 }
1029
1030
1043 void UserInterface::preProcess(QString fullReservedName,
1044 std::vector<QString> &reservedParams) {
1045 for (unsigned int currArgument = 1; currArgument < (unsigned)p_cmdline.size();
1046 currArgument++) {
1047
1048 QString paramName = p_cmdline[currArgument];
1049 QString trueParamValue = "";
1050 vector<QString> paramValue;
1051
1052 // reserved parameters start with -
1053 if (paramName[0] == '-') {
1054
1055 // grab the current argument
1056 getNextParameter(currArgument, paramName, paramValue);
1057 paramName = paramName.toUpper();
1058
1059 // grab the argument's value
1060 if ( paramValue.size() ) {
1061 trueParamValue = paramValue[0].toUpper();
1062 }
1063
1064 // resolve the reserved parameter token
1065 paramName = resolveParameter(paramName, reservedParams, false);
1066
1067 // evaluate the resolved parameter if it matches fullReservedName
1068 if (fullReservedName == paramName) {
1069 evaluateOption(paramName, trueParamValue);
1070 }
1071 }
1072 }
1073 }
1074
1075
1089 std::vector<QString> UserInterface::readArray(QString arrayString) {
1090 std::vector<QString> values;
1091
1092 bool inDoubleQuotes = false;
1093 bool inSingleQuotes = false;
1094 bool arrayClosed = false;
1095 bool nextElementStarted = false;
1096 QString currElement = "";
1097
1098 for (int strPos = 0; strPos < arrayString.size(); strPos++) {
1099 if (strPos == 0) {
1100 if (arrayString[strPos] != '(') {
1101 QString msg = "Invalid array format [" + arrayString + "]";
1102 throw IException(IException::User, msg, _FILEINFO_);
1103 }
1104
1105 continue;
1106 }
1107
1108 // take literally anything that is escaped and not quoted
1109 if ( arrayString[strPos] == '\\' && strPos + 1 < (int)arrayString.size() ) {
1110 currElement += arrayString[strPos+1];
1111 strPos++;
1112 continue;
1113 }
1114 // ends in a backslash??
1115 else if (arrayString[strPos] == '\\') {
1116 QString msg = "Invalid array format [" + arrayString + "]";
1117 throw IException(IException::User, msg, _FILEINFO_);
1118 }
1119
1120 // not in quoted part of QString
1121 if (!inDoubleQuotes && !inSingleQuotes) {
1122 if (arrayClosed) {
1123 QString msg = "Invalid array format [" + arrayString + "]";
1124 throw IException(IException::User, msg, _FILEINFO_);
1125 }
1126
1127 nextElementStarted = (nextElementStarted || arrayString[strPos] != ' ');
1128
1129 if (!nextElementStarted) {
1130 continue;
1131 }
1132
1133 if (arrayString[strPos] == '"') {
1134 inDoubleQuotes = true;
1135 }
1136 else if (arrayString[strPos] == '\'') {
1137 inSingleQuotes = true;
1138 }
1139 else if (arrayString[strPos] == ',') {
1140 values.push_back(currElement);
1141 currElement = "";
1142 nextElementStarted = false;
1143 }
1144 else if (arrayString[strPos] == ')') {
1145 values.push_back(currElement);
1146 currElement = "";
1147 arrayClosed = true;
1148 nextElementStarted = false;
1149 }
1150 else if (nextElementStarted && arrayString[strPos] == ' ') {
1151 // Make sure there's something before the next ',' or ')'
1152 bool onlyWhite = true;
1153 int closingPos = strPos + 1;
1154
1155 for( int pos = strPos;
1156 onlyWhite && arrayString[pos] != ',' && arrayString[pos] != ')' &&
1157 pos < arrayString.size(); pos++) {
1158 closingPos++;
1159 onlyWhite &= (arrayString[pos] == ' ');
1160 }
1161
1162 if (!onlyWhite) {
1163 currElement += arrayString[strPos];
1164 }
1165 }
1166 else if (nextElementStarted) {
1167 currElement += arrayString[strPos];
1168 }
1169 }
1170 else if (inSingleQuotes) {
1171 if(arrayString[strPos] == '\'') {
1172 inSingleQuotes = false;
1173 }
1174 else {
1175 currElement += arrayString[strPos];
1176 }
1177 }
1178 // in double quotes
1179 else {
1180 if (arrayString[strPos] == '"') {
1181 inDoubleQuotes = false;
1182 }
1183 else {
1184 currElement += arrayString[strPos];
1185 }
1186 }
1187 }
1188
1189 if (!arrayClosed || currElement != "") {
1190 QString msg = "Invalid array format [" + arrayString + "]";
1191 throw IException(IException::User, msg, _FILEINFO_);
1192 }
1193
1194 return values;
1195 }
1196
1197
1216 QString UserInterface::resolveParameter(QString &unresolvedParam,
1217 std::vector<QString> &reservedParams,
1218 bool handleNoMatches) {
1219 // index of the reserved parameter in options that matches the cmdline parameter
1220 int matchOption = -1;
1221 // determine if the reserved parameter on cmdline is shortened (e.g. -h for -HELP)
1222 for (int option = 0; option < (int)reservedParams.size(); option++) {
1223 // If our option starts with the parameter name so far, this is it
1224 if ( reservedParams[option].startsWith(unresolvedParam) ) {
1225 if (matchOption >= 0) {
1226 QString msg = "Ambiguous Reserve Parameter ["
1227 + unresolvedParam + "]. Please clarify.";
1228 throw IException(IException::User, msg, _FILEINFO_);
1229 }
1230 // set match to current iteration in loop
1231 matchOption = option;
1232 }
1233 }
1234 // handle matches by default
1235 if (handleNoMatches) {
1236 // handle no matches
1237 if (matchOption < 0) {
1238 QString msg = "Invalid Reserve Parameter Option ["
1239 + unresolvedParam + "]. Choices are ";
1240
1241 QString msgOptions;
1242 for (int option = 0; option < (int)reservedParams.size(); option++) {
1243 // Make sure not to show -PID as an option
1244 if (reservedParams[option].compare("-PID") == 0) {
1245 continue;
1246 }
1247
1248 msgOptions += reservedParams[option];
1249 msgOptions += ",";
1250
1251 // this condition will never evaluate to FALSE -
1252 // this condition is only reachable when reservedParams.size() == 0 (empty) -
1253 // if this is the case, this for loop will never be entered
1254// if ( !reservedParams.empty() ) {
1255// msgOptions += ",";
1256// }
1257 }
1258
1259 // remove the terminating ',' from msgOptions
1260 msgOptions.chop(1);
1261 msg += " [" + msgOptions + "]";
1262
1263 throw IException(IException::User, msg, _FILEINFO_);
1264 }
1265 }
1266 if (matchOption < 0) {
1267 return "";
1268 }
1269 else {
1270 return reservedParams[matchOption];
1271 }
1272 }
1273} // end namespace isis
File name manipulation and expansion.
Definition FileName.h:100
QDir dir() const
Returns the path of the file's parent directory as a QDir object.
Definition FileName.cpp:465
QString name() const
Returns the name of the file excluding the path and the attributes in the file name.
Definition FileName.cpp:162
static void checkX11()
check to see if X is available
Definition Gui.cpp:55
Isis exception class.
Definition IException.h:91
@ Unknown
A type of error that cannot be classified as any of the other error types.
Definition IException.h:118
@ User
A type of error that could only have occurred due to a mistake on the user's part (e....
Definition IException.h:126
@ Programmer
This error is for when a programmer made an API call that was illegal.
Definition IException.h:146
Adds specific functionality to C++ strings.
Definition IString.h:165
IString Compress(bool force=false)
Collapses multiple spaces into single spaces.
Definition IString.cpp:974
IString Token(const IString &separator)
Returns the first token in the IString.
Definition IString.cpp:897
QString ToQt() const
Retuns the object string as a QString.
Definition IString.cpp:869
IString Replace(const std::string &from, const std::string &to, int maxReplaceCount=20)
Replaces all instances of the first input string with the second input string.
Definition IString.cpp:1037
Reads user preferences from a data file.
Definition Preference.h:60
static void RunSystemCommand(QString commandLine)
This runs arbitrary system commands.
int keywords() const
Returns the number of keywords contained in the PvlContainer.
QString name() const
Returns the container name.
Contains multiple PvlContainers.
Definition PvlGroup.h:41
Container for cube-like labels.
Definition Pvl.h:119
void setTerminator(const QString &term)
Sets the terminator used to signify the end of the PVL informationDefaults to "END".
Definition Pvl.h:144
void read(const QString &file)
Loads PVL information from a stream.
Definition Pvl.cpp:90
A single keyword-value pair.
Definition PvlKeyword.h:87
QString name() const
Returns the keyword name.
Definition PvlKeyword.h:103
void addValue(QString value, QString unit="")
Adds a value with units.
Contains Pvl Groups and Pvl Objects.
Definition PvlObject.h:61
PvlObject & object(const int index)
Return the object at the specified index.
@ Traverse
Search child objects.
Definition PvlObject.h:158
Provides access to sequential ASCII stream I/O.
Definition TextFile.h:38
void Open(const QString &filename, const char *openmode="input", const char *extension="")
Opens a text file.
Definition TextFile.cpp:217
QString p_saveFile
FileName to save last history to.
int p_parentId
This is a status to indicate if the GUI is running or not.
void preProcess(QString fullReservedName, std::vector< QString > &reservedParams)
This parses the command line and looks for the specified reserved parameter name passed.
std::vector< std::vector< QString > > p_batchList
Vector of batchlist data.
QString resolveParameter(QString &name, std::vector< QString > &reservedParams, bool handleNoMatches=true)
This resolves a reserved parameter token on the command line to its fullname.
QString p_progName
Name of program to run.
QString p_infoFileName
FileName to save debugging info.
QString GetInfoFileName()
This method returns the filename where the debugging info is stored when the "-info" tag is used.
std::vector< char * > p_cmdline
This variable will contain argv.
bool p_interactive
Boolean value representing whether the program is interactive or not.
bool p_info
Boolean value representing if it's in debug mode.
UserInterface(const QString &xmlfile, int &argc, char *argv[])
Constructs an UserInterface object.
void loadBatchList(const QString file)
Loads the user entered batchlist file into a private variable for later use.
void loadCommandLine(QVector< QString > &args, bool ignoreAppName=true)
This is used to load the command line into p_cmdline and the Aml object using information contained i...
bool GetInfoFlag()
This method returns the flag state of info.
std::vector< QString > readArray(QString arrayString)
This interprets an array value from the command line.
void evaluateOption(const QString name, const QString value)
This interprets the "-" options for reserved parameters.
void loadHistory(const QString file)
Loads the previous history for the program.
bool p_abortOnError
Boolean value representing whether to abort or continue on error.
Gui * p_gui
Pointer to the gui object.
QString p_errList
FileName to write batchlist line that caused error on.
int BatchListSize()
Returns the size of the batchlist.
void SetErrorList(int i)
This method adds the line specified in the BatchList that the error occured on.
void SaveHistory()
Saves the user parameter information in the history of the program for later use.
void SetBatchList(int i)
Clears the gui parameters and sets the batch list information at line i as the new parameters.
~UserInterface()
Destroys the UserInterface object.
void getNextParameter(unsigned int &curPos, QString &unresolvedParam, std::vector< QString > &value)
This gets the next parameter in the list of arguments.
Application program XML file parameter manager.
Definition IsisAml.h:140
void CommandLine(Isis::Pvl &lab) const
Creates a QString which could be used as a command line.
Definition IsisAml.cpp:3099
QString ParamOdd(const int &group, const int &param) const
Returns whether the selected parameter has a restriction on odd values or not.
Definition IsisAml.cpp:1461
int ParamExcludeSize(const int &group, const int &param) const
Returns the number of parameters excluded in this parameter's exclusions.
Definition IsisAml.cpp:1894
QString ParamLessThan(const int &group, const int &param, const int &great) const
Returns the name of the specified lessThan parameter.
Definition IsisAml.cpp:1575
QString ParamLessThanOrEqual(const int &group, const int &param, const int &les) const
Returns the name of the specified lessThanOrEqual parameter.
Definition IsisAml.cpp:1591
QString ParamBrief(const int &group, const int &param) const
Returns the brief description of a parameter in a specified group.
Definition IsisAml.cpp:1376
QString ParamListInclude(const int &group, const int &param, const int &option, const int &include) const
Returns the parameter name to be included if this option is selected.
Definition IsisAml.cpp:1879
int ParamListIncludeSize(const int &group, const int &param, const int &option) const
Returns the number of items in a parameters list include section.
Definition IsisAml.cpp:1863
QString ParamListValue(const int &group, const int &param, const int &option) const
Returns the option value for a specific option to a parameter.
Definition IsisAml.cpp:1783
int NumGroups() const
Returns the number of groups found in the XML.
Definition IsisAml.cpp:1164
int ParamListExcludeSize(const int &group, const int &param, const int &option) const
Returns the number of items in a parameters list exclude section.
Definition IsisAml.cpp:1831
int ParamGreaterThanSize(const int &group, const int &param) const
Returns the number of values in the parameters greater than list.
Definition IsisAml.cpp:1475
QString ParamNotEqual(const int &group, const int &param, const int &notEq) const
Returns the name of the specified notEqual parameter.
Definition IsisAml.cpp:1607
QString ParamGreaterThanOrEqual(const int &group, const int &param, const int &great) const
Returns the name of the specified greaterThanOrEqual parameter.
Definition IsisAml.cpp:1559
QString ParamMaximumInclusive(const int &group, const int &param) const
Returns whether the maximum value is inclusive or not.
Definition IsisAml.cpp:1446
QString ParamType(const int &group, const int &param) const
Returns the parameter type of a parameter in a specified group.
Definition IsisAml.cpp:1654
int ParamListSize(const int &group, const int &param) const
Returns the number of options in the specified parameter's list.
Definition IsisAml.cpp:1769
int NumParams(const int &) const
Returns the number of parameters in a group.
Definition IsisAml.cpp:1349
QString ParamExclude(const int &group, const int &param, const int &exclude) const
Returns the name of the specified excluded parameter.
Definition IsisAml.cpp:1623
const IsisParameterData * ReturnParam(const QString &paramName) const
Returns a pointer to a parameter whose name starts with paramName.
Definition IsisAml.cpp:2152
QString ParamListExclude(const int &group, const int &param, const int &option, const int &exclude) const
Returns the parameter name to be excluded if this option is selected.
Definition IsisAml.cpp:1847
int ParamLessThanOrEqualSize(const int &group, const int &param) const
Returns the number of values in the parameters less than or equal list.
Definition IsisAml.cpp:1515
QString ParamListBrief(const int &group, const int &param, const int &option) const
Returns the brief description for a specific option to a parameter.
Definition IsisAml.cpp:1799
QString ParamDefault(const int &group, const int &param) const
Returns the default for a parameter in a specified group.
Definition IsisAml.cpp:1668
int ParamLessThanSize(const int &group, const int &param) const
Returns the number of values in the parameters less than list.
Definition IsisAml.cpp:1502
QString ParamInclude(const int &group, const int &param, const int &include) const
Returns the name of the specified included parameter.
Definition IsisAml.cpp:1639
int ParamGreaterThanOrEqualSize(const int &group, const int &param) const
Returns the number of values in the parameters greater than or equal list.
Definition IsisAml.cpp:1488
QString ParamInternalDefault(const int &group, const int &param) const
Returns the internal default for a parameter in a specified group.
Definition IsisAml.cpp:1688
int ParamNotEqualSize(const int &group, const int &param) const
Returns the number of values in the not equal list.
Definition IsisAml.cpp:1529
QString ProgramName() const
Returns the Program name.
Definition IsisAml.cpp:1133
int ParamIncludeSize(const int &group, const int &param) const
Returns the number of parameters included in this parameter's inclusions.
Definition IsisAml.cpp:1907
QString ParamMinimumInclusive(const int &group, const int &param) const
Returns whether the minimum value is inclusive or not.
Definition IsisAml.cpp:1432
QString ParamGreaterThan(const int &group, const int &param, const int &great) const
Returns the name of the specified greaterThan parameter.
Definition IsisAml.cpp:1543
QString ParamMinimum(const int &group, const int &param) const
Returns the minimum value of a parameter in a specified group.
Definition IsisAml.cpp:1404
void Clear(const QString &paramName)
Clears the value(s) in the named parameter.
Definition IsisAml.cpp:2037
void VerifyAll()
Verify all parameters.
Definition IsisAml.cpp:2575
QString ParamName(const int &group, const int &param) const
Returns the parameter name.
Definition IsisAml.cpp:1362
void PutAsString(const QString &paramName, const QString &value)
Allows the insertion of a value for any parameter.
Definition IsisAml.cpp:68
QString ParamMaximum(const int &group, const int &param) const
Returns the maximum value of a parameter in a specified group.
Definition IsisAml.cpp:1418
This is free and unencumbered software released into the public domain.
Definition Apollo.h:16
int toInt(const QString &string)
Global function to convert from a string to an integer.
Definition IString.cpp:93
PixelType
Enumerations for Isis Pixel Types.
Definition PixelType.h:27
Namespace for the standard library.