Official websites use .gov
A .gov website belongs to an official government organization in the United States.

Secure .gov websites use HTTPS
A lock ( ) or https:// means you’ve safely connected to the .gov website. Share sensitive information only on official, secure websites.

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