Fixed text file permissions
[snark14.git] / tools / Input / select.cpp
1 /** @file select.cpp
2     @package snark14Input
3     @author Bruno M. Carvalho and Deniz Sarioz
4     licensed under (open-source) QPL v1.0
5     which accompanies this distribution in the file QPL
6 */
7
8 #include "select.h"
9 #include "variables.h"
10 #include "misc.h"
11 #include <stdio.h>
12
13 #include <qbuttongroup.h>
14 #include <qcombobox.h>
15 #include <qframe.h>
16 #include <qlabel.h>
17 #include <qlineedit.h>
18 #include <qpushbutton.h>
19 #include <qradiobutton.h>
20 #include <qlayout.h>
21 #include <qvariant.h>
22 #include <qtooltip.h>
23 #include <qwhatsthis.h>
24 #include <qmessagebox.h>
25
26 /** 
27  *  Constructs a selectwindow which is a child of 'parent', with the 
28  *  name 'name' and widget flags set to 'f' 
29  *
30  *  The dialog will by default be modeless, unless you set 'modal' to
31  *  TRUE to construct a modal dialog.
32 @param void
33 @author Bruno M. Carvalho
34 @version 1.0 */
35 selectwindow::selectwindow( QWidget* parent,  const char* name, bool modal, WFlags fl )
36     : QDialog( parent, name, modal, fl )
37 {
38     if ( !name )
39         setName( "selectwindow" );
40     resize( 400, 350 ); 
41     setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)0, (QSizePolicy::SizeType)0, sizePolicy().hasHeightForWidth() ) );
42     setMinimumSize( QSize( 390, 350 ) );
43     setMaximumSize( QSize( 390, 350 ) );
44     setCaption( tr( "Select Window" ) );
45
46     selectlabel = new QLabel( this, "selectlabel" );
47     selectlabel->setGeometry( QRect( 10, 10, 90, 30 ) ); 
48     selectlabel->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)0, (QSizePolicy::SizeType)0, selectlabel->sizePolicy().hasHeightForWidth() ) );
49     selectlabel->setMinimumSize( QSize( 90, 30 ) );
50     selectlabel->setMaximumSize( QSize( 90, 30 ) );
51     selectlabel->setText( tr( "SELECT" ) );
52
53     selectbuttongroup = new QButtonGroup( this, "selectbuttongroup" );
54     selectbuttongroup->setGeometry( QRect( 20, 40, 110, 90 ) ); 
55     selectbuttongroup->setTitle( tr( "type" ) );
56     selectbuttongroup->setAlignment( int( QButtonGroup::AlignHCenter ) );
57
58     userbutton = new QRadioButton( selectbuttongroup, "userbutton" );
59     userbutton->setGeometry( QRect( 10, 20, 80, 24 ) ); 
60     userbutton->setText( tr( "USER" ) ); 
61
62     snarkbutton = new QRadioButton( selectbuttongroup, "snarkbutton" );
63     snarkbutton->setGeometry( QRect( 10, 50, 80, 24 ) ); 
64     snarkbutton->setText( tr( "SNARK" ) ); 
65     snarkbutton->setChecked(true);
66
67     //    QObject::connect(okbutton,SIGNAL(clicked()),this,SLOT(checkValues()));
68
69     type1 = new QComboBox( this, "type1" );
70     type1->setGeometry( QRect( 20, 170, 120, 28 ) ); 
71     type1->insertItem("RAYSEQ",-1);
72     type1->insertItem("PROJSEQ",-1);
73     type1->insertItem("RANDOM",-1);
74
75     type1label = new QLabel( this, "type1label" );
76     type1label->setGeometry( QRect( 50, 150, 40, 20 ) ); 
77     type1label->setText( tr( "type1" ) ); 
78
79     n1 = new QLineEdit( this, "n1" );
80     n1->setGeometry( QRect( 150, 170, 40, 28 ) ); 
81
82     n1label = new QLabel( this, "n1label" );
83     n1label->setGeometry( QRect( 160, 150, 20, 20 ) ); 
84     n1label->setText( tr( "n1" ) ); 
85
86     type2 = new QComboBox( this, "type2" );
87     type2->setGeometry( QRect( 200, 170, 120, 28 ) );  
88     type2->insertItem("",-1);
89     type2->insertItem("RAYSEQ",-1);
90     type2->insertItem("PROJSEQ",-1);
91     type2->insertItem("RANDOM",-1);
92
93     type2label = new QLabel( this, "type2label" );
94     type2label->setGeometry( QRect( 230, 150, 40, 20 ) ); 
95     type2label->setText( tr( "type2" ) ); 
96
97     n2 = new QLineEdit( this, "n2" );
98     n2->setGeometry( QRect( 330, 170, 40, 28 ) );
99
100     n2label = new QLabel( this, "n2label" );
101     n2label->setGeometry( QRect( 340, 150, 20, 20 ) ); 
102     n2label->setText( tr( "n2" ) ); 
103
104     steplabel = new QLabel( this, "steplabel" );
105     steplabel->setGeometry( QRect( 20, 245, 50, 20 ) ); 
106     steplabel->setText( tr( "STEP" ) ); 
107
108     mod1 = new QLineEdit( this, "mod1" );
109     mod1->setGeometry( QRect( 80, 240, 40, 28 ) ); 
110
111     mod1label = new QLabel( this, "mod1label" );
112     mod1label->setGeometry( QRect( 80, 220, 40, 20 ) ); 
113     mod1label->setText( tr( "mod1" ) ); 
114
115     mod2 = new QLineEdit( this, "mod2" );
116     mod2->setGeometry( QRect( 130, 240, 40, 28 ) );
117
118     mod2label = new QLabel( this, "mod2label" );
119     mod2label->setGeometry( QRect( 130, 220, 40, 20 ) ); 
120     mod2label->setText( tr( "mod2" ) ); 
121
122     Line12 = new QFrame( this, "Line12" );
123     Line12->setGeometry( QRect( 0, 275, 405, 16 ) ); 
124     Line12->setFrameStyle( QFrame::HLine | QFrame::Sunken );
125
126     efficientcb = new QCheckBox( this, "efficientcb" );
127     efficientcb->setGeometry( QRect( 147, 90, 100, 24 ) );
128     efficientcb->setText( "EFFICIENT" );
129     efficientcb->setChecked(true);
130     QObject::connect(efficientcb,SIGNAL(clicked()),this,SLOT(grayOrNot()));
131     grayOrNot();
132
133     okbutton = new QPushButton( this, "okbutton" );
134     okbutton->setGeometry( QRect( 50, 290, 100, 40 ) ); 
135     okbutton->setText( tr( "OK" ) );
136     QObject::connect(okbutton,SIGNAL(clicked()),this,SLOT(checkValues()));
137
138     cancelbutton = new QPushButton( this, "cancelbutton" );
139     cancelbutton->setGeometry( QRect( 250, 290, 100, 40 ) ); 
140     cancelbutton->setText( tr( "Cancel" ) );
141     QObject::connect(cancelbutton,SIGNAL(clicked()),this,SLOT(reject()));
142
143 }
144
145 /** @author deniz
146     @description grays out or ungrays out fields based on EFFICIENT
147 */
148 void selectwindow::grayOrNot() {
149   bool enab = (! (efficientcb->isChecked()));
150
151   type1->setEnabled(enab);
152   type1label->setEnabled(enab);
153   type2->setEnabled(enab);
154   type2label->setEnabled(enab);
155   n1->setEnabled(enab);
156   n2->setEnabled(enab);
157   n1label->setEnabled(enab);
158   n2label->setEnabled(enab);
159   steplabel->setEnabled(enab);
160   mod1->setEnabled(enab);
161   mod2->setEnabled(enab);
162   mod1label->setEnabled(enab);
163   mod2label->setEnabled(enab);
164 }
165
166 /**  
167  *  Destroys the object and frees any allocated resources
168  */
169 selectwindow::~selectwindow()
170 {
171     // no need to delete child widgets, Qt does it all for us
172 }
173
174 /** Returns a string for SELECT input sequence
175     pre: assume checkValues() accepts
176 @param void
177 @return select
178 @author Bruno M. Carvalho [simplified / fixed bug #118 by Deniz]
179 @version 1.0 */
180 QString selectwindow::getOutput()
181 {
182   QString output = "SELECT ";
183   if(userbutton->isChecked()) {
184     output += userbutton->text() + " ";
185   } else {
186     if(snarkbutton->isChecked()) {
187       output += snarkbutton->text() + " ";
188     }
189   }
190   if(efficientcb->isChecked()) {
191     output += efficientcb->text();
192   } else {
193     output += type1->currentText() + " ";
194     output += n1->text().simplifyWhiteSpace() + " ";
195     if(type2->currentItem()) {
196       output += type2->currentText() + " ";
197       output += n2->text().simplifyWhiteSpace() + " ";
198     }
199     //  if passed checkValues(), add the next line iff mod1 is non-whitespace
200     if (! (mod1->text().simplifyWhiteSpace().isEmpty())) {
201       output += "\nSTEP " + 
202         mod1->text().simplifyWhiteSpace() + " " +
203         mod2->text().simplifyWhiteSpace();
204     }
205   }
206   return output;
207 } // --selectwindow::getOutput()
208
209 /** @author deniz -- totally rewrote it while fixing bug #118
210 */
211 void selectwindow::checkValues()
212 {
213
214   if(efficientcb->isChecked()) { accept(); return; } // nothing can go wrong
215   // otherwise...
216
217   /**  the grammar of SELECT looks like:
218     >  SELECT {USER, SNARK} [type1 [n1 type2 [n2] ] ]
219       (where of course args in [] are optional and nesting them has the usual meaning)
220       (this means that n1 is there iff type2 is there)
221       cond, that is, ((type1==RANDOM) && (type2 does not appear)) XOR
222       this line is followed by a line:
223     >  STEP mod1 mod2
224     (all textbox arguments must be positive integers)
225     The new behavior coded by deniz:
226       selectwindow forces user to choose exactly one of USER and SNARK, so ignore those.
227       last 6 values: first check for existence and if exist, parse.
228       if exist, report parse errors first depending on desired types ranges etc
229       THEN check grammar (i.e., are "existences" compatible) and report grammar errors
230   */
231   // existence vars:
232   bool n1E = false, type2E = false, n2E = false, mod1E = false, mod2E = false;
233   bool type1isRandom = false, type2isRandom = false;
234   int n1i, n2i, mod1i, mod2i; // integers to read values into for range checking
235
236   type1isRandom = (type1->currentText().contains("RANDOM") ); // do NOT rely on position in combobox
237   
238   QString n1simple = n1->text().simplifyWhiteSpace();
239   // strs in textboxes: first check if empty, then check if type and rangewise valid
240   if (!n1simple.isEmpty()) {
241     n1E = true;
242     bool ok = true;
243     n1i = n1simple.toInt(&ok);
244     if(!ok) {
245       QMessageBox::information(this,"SnarkInput","Error!\n"
246                                "Invalid n1 format (must be positive integer).");
247       n1->setFocus();
248       return;
249     } else if(n1i < 1) {
250       QMessageBox::information(this,"SnarkInput","Error!\n"
251                                "n1 must be greater than 0.");
252       n1->setFocus();
253       return;
254     }
255   }
256   
257   if(type2->currentItem()) { // if something is selected at all in combobox for type 2...
258     type2E = true;
259     type2isRandom = (type2->currentText().contains("RANDOM") ); // do NOT rely on position in combobox    
260   }
261
262   QString n2simple = n2->text().simplifyWhiteSpace();
263   if(!n2simple.isEmpty()) {
264     n2E = true;
265     bool ok = true;
266     n2i = n2simple.toInt(&ok);
267     if(!ok) {
268       QMessageBox::information(this,"SnarkInput","Error!\n"
269                                "Invalid n2 format (must be positive integer).");
270       n2->setFocus();
271       return;
272     } else if(n2i < 1) {
273       QMessageBox::information(this,"SnarkInput","Error!\n"
274                                "n2 must be greater than 0.");
275       n2->setFocus();
276       return;
277     }
278   }
279   
280   QString mod1simple = mod1->text().simplifyWhiteSpace();
281   if(!mod1simple.isEmpty()) {
282     mod1E = true;
283     bool ok = true;
284     mod1i = mod1simple.toInt(&ok);
285     if(!ok) {
286       QMessageBox::information(this,"SnarkInput","Error!\n"
287                                "Invalid mod1 format (must be positive integer).");
288       mod1->setFocus();
289       return;
290     } else if(mod1i < 1) {
291       QMessageBox::information(this,"SnarkInput","Error!\n"
292                                "mod1 must be greater than 0.");
293       mod1->setFocus();
294       return;
295     }
296   }
297   
298   QString mod2simple = mod2->text().simplifyWhiteSpace();
299   if(!mod2simple.isEmpty()) {
300     mod2E = true;
301     bool ok = true;
302     mod2i = mod2simple.toInt(&ok);
303     if(!ok) {
304       QMessageBox::information(this,"SnarkInput","Error!\n"
305                                "Invalid mod2 format (must be positive integer).");
306       mod2->setFocus();
307       return;
308     } else if(mod2i < 1) {
309       QMessageBox::information(this,"SnarkInput","Error!\n"
310                                "mod2 must be greater than 0.");
311       mod2->setFocus();
312       return;
313     }
314   }
315
316   // check the grammar for "first line", from the outside in
317   // if control reaches here, EFFICIENT not selected and type1 necessarily there
318   if(  
319      ( n2E && (!n1E))     || 
320      ( type2E != n1E )
321      ) {
322     QMessageBox::information(this,"SnarkInput","Error!\n"
323                              "Check your grammar--optional parameter dependencies are like:\n"
324                              "[type1 [n1 type2 [n2] ] ]");
325     return;
326   }
327
328   if(type2E) { // which of course implies type1E since we got here
329     if(type1isRandom == type2isRandom) {
330       QMessageBox::information(this,"SnarkInput","Error!\n"
331                                "Since both type1 and type2 are present,\n"
332                                "exactly one of them must be RANDOM");
333       return;
334     }
335   }
336
337   //  bool cond = (type1isRandom && (!type2E));
338   if(! (type1isRandom && (!type2E)) )  { // "Unless cond, 'STEP' line must follow"
339     if (! (mod1E && mod2E)) {
340       QMessageBox::information(this,"SnarkInput","Error!\n"
341                                "Check your grammar: "
342                                "since it's not the case that type1 is random and type2 blank, \n"
343                                "values must be entered for both mod1 and mod2");
344       mod1->setFocus();
345       return;
346     }
347   } else { // "Restrictions: 'STEP' must be absent if cond "
348     if (mod1E || mod2E) {
349       QMessageBox::information(this,"SnarkInput","Error!\n"
350                                "Check your grammar: "
351                                "since type1 is random and type2 is blank, \n"
352                                "both mod1 and mod2 must be blank");
353       mod1->setFocus();
354       return;
355     }
356   }
357
358   // control getting here implies the arguments were valid
359   accept();    
360
361 } // --selectwindow::checkValues()