UltraScan III
us_experiment_gui_ra.cpp
Go to the documentation of this file.
1 
3 #include <QtGui>
4 
5 #include "us_experiment_gui_ra.h"
6 #include "us_passwd.h"
7 #include "us_settings.h"
8 #include "us_gui_settings.h"
9 #include "us_db2.h"
10 #include "us_investigator.h"
11 #include "us_project_gui.h"
12 #include "us_rotor_gui.h"
13 
15  bool signal_wanted,
16  const US_ExperimentRa& dataIn,
17  int select_db_disk ) :
18  US_WidgetsDialog( 0, 0 ), expInfo( dataIn )
19 {
20  signal = signal_wanted;
21 
22  setPalette( US_GuiSettings::frameColor() );
23  setWindowTitle( tr( "Experiment Information" ) );
24  setAttribute( Qt::WA_DeleteOnClose );
25 
26  // Set up left panel with experiment information
27  QGridLayout* experiment = new QGridLayout;
28  int row = 0;
29 
30  // Current experiment information
31  QLabel* lb_experiment_banner = us_banner( tr( "Experiment: " ) );
32  experiment->addWidget( lb_experiment_banner, row++, 0, 1, 2 );
33 
34  // Show current runID
35  QLabel* lb_runID = us_label( tr( "Run ID " ) );
36  experiment->addWidget( lb_runID, row++, 0, 1, 2 );
37  le_runID = us_lineedit( "", 0, true );
38 
39  experiment->addWidget( le_runID, row++, 0, 1, 2 );
40 
41  // Experiment label
42  QLabel* lb_label = us_label( tr( "Label:" ) );
43  experiment->addWidget( lb_label, row++, 0, 1, 2 );
45  connect( le_label, SIGNAL( editingFinished () ),
46  SLOT ( saveLabel () ) );
47  experiment->addWidget( le_label, row++, 0, 1, 2 );
48 
49  // Project
50  QLabel* lb_project = us_label( tr( "Project:" ) );
51  experiment->addWidget( lb_project, row, 0 );
52  QPushButton* pb_project = us_pushbutton( tr( "Select Project" ) );
53  connect( pb_project, SIGNAL( clicked() ), SLOT( selectProject() ) );
54  pb_project->setEnabled( true );
55  experiment->addWidget( pb_project, row++, 1 );
56 
57  le_project = us_lineedit( "", 0, true );
58  experiment->addWidget( le_project, row++, 0, 1, 2 );
59 
60  // Experiment type
61  QLabel* lb_expType = us_label( tr( "Experiment Type:" ) );
62  experiment->addWidget( lb_expType, row, 0 );
64  experiment->addWidget( cb_expType, row++, 1 );
65 
66  // Optical system
67  QLabel* lb_opticalSystem = us_label( tr( "Optical System:" ) );
68  experiment->addWidget( lb_opticalSystem, row, 0 );
69  QLineEdit* le_opticalSystem = us_lineedit( "", 0, true );
70  experiment->addWidget( le_opticalSystem, row++, 1 );
71 
72  // The optical system won't change
73  if ( ( expInfo.opticalSystem == "RA" ) ||
74  ( expInfo.opticalSystem == "WA" ) )
75  le_opticalSystem->setText( "Absorbance" );
76 
77  else if ( ( expInfo.opticalSystem == "RI" ) ||
78  ( expInfo.opticalSystem == "WI" ) )
79  le_opticalSystem->setText( "Intensity" );
80 
81  else if ( expInfo.opticalSystem == "IP" )
82  le_opticalSystem->setText( "Interference" );
83 
84  else if ( expInfo.opticalSystem == "FI" )
85  le_opticalSystem->setText( "Fluorescence" );
86 
87  else // Unsupported optical system
88  le_opticalSystem->setText( "Unsupported" );
89 
90  // Now for predominantly hardware info
91  QGridLayout* hardware = new QGridLayout;
92  row = 0;
93 
94  // Selected hardware information
95  QLabel* lb_hardware_banner = us_banner( tr( "Hardware: " ) );
96  hardware->addWidget( lb_hardware_banner, row++, 0, 1, 2 );
97 
98  QPushButton* pb_rotor = us_pushbutton( tr( "Select Lab / Rotor / Calibration" ) );
99  connect( pb_rotor, SIGNAL( clicked() ), SLOT( selectRotor() ) );
100  pb_rotor->setEnabled( true );
101  hardware->addWidget( pb_rotor, row++, 0, 1, 2 );
102 
103  le_rotorDesc = us_lineedit( "", 0, true );
104  hardware->addWidget( le_rotorDesc, row++, 0, 1, 2 );
105 
106  // Rotor speeds
107  QLabel* lb_rotorSpeeds = us_label( tr( "Unique Rotor Speeds:" ) );
108  hardware->addWidget( lb_rotorSpeeds, row++, 0, 1, 2 );
110  lw_rotorSpeeds ->setMaximumHeight( 50 );
111  lw_rotorSpeeds ->setPalette( vlgray );
112  hardware->addWidget( lw_rotorSpeeds, row, 0, 2, 2 );
113  row += 2;
114 
115  // instrumentID
116  QLabel* lb_instrument = us_label( tr( "Instrument:" ) );
117  hardware->addWidget( lb_instrument, row, 0 );
118  cb_instrument = new US_SelectBoxRa( this );
119  connect( cb_instrument, SIGNAL( activated ( int ) ),
120  SLOT ( change_instrument( int ) ) );
121  hardware->addWidget( cb_instrument, row++, 1 );
122 
123  // operatorID
124  QLabel* lb_operator = us_label( tr( "Operator:" ) );
125  hardware->addWidget( lb_operator, row, 0 );
126  cb_operator = new US_SelectBoxRa( this );
127  hardware->addWidget( cb_operator, row++, 1 );
128 
129  // Run Temperature
130  QLabel* lb_runTemp = us_label( tr( "Average Run Temperature:" ) );
131  hardware->addWidget( lb_runTemp, row, 0 );
132  le_runTemp = us_lineedit( "", 0, true );
133  hardware->addWidget( le_runTemp, row++, 1 );
134 
135  // Run temperature won't change
136  le_runTemp ->setText( expInfo.runTemp );
137 
138  // Some pushbuttons
139  QHBoxLayout* buttons = new QHBoxLayout;
140 
141  QPushButton* pb_help = us_pushbutton( tr( "Help" ) );
142  connect( pb_help, SIGNAL( clicked() ), SLOT( help() ) );
143  buttons->addWidget( pb_help );
144 
145  QPushButton* pb_cancel = us_pushbutton( tr( "Cancel" ) );
146  connect( pb_cancel, SIGNAL( clicked() ), SLOT( cancel() ) );
147  buttons->addWidget( pb_cancel );
148 
149  pb_accept = us_pushbutton( tr( "Accept" ) );
150  connect( pb_accept, SIGNAL( clicked() ), SLOT( accept() ) );
151  buttons->addWidget( pb_accept );
152 
153  // Now let's assemble the page
154  QGridLayout* main = new QGridLayout( this );
155  main->setSpacing ( 2 );
156  main->setContentsMargins ( 2, 2, 2, 2 );
157 
158  row = 0;
159 
160  // Database choices
161  QStringList DB = US_Settings::defaultDB();
162  if ( DB.isEmpty() ) DB << "Undefined";
163  QLabel* lb_DB = us_banner( tr( "Database: " ) + DB.at( 0 ) );
164  main->addWidget( lb_DB, row++, 0, 1, 2 );
165 
166  // Investigator
167  if ( US_Settings::us_inv_level() > 2 )
168  {
169  QPushButton* pb_investigator = us_pushbutton( tr( "Select Investigator" ) );
170  connect( pb_investigator, SIGNAL( clicked() ), SLOT( selectInvestigator() ) );
171  main->addWidget( pb_investigator, row, 0 );
172  }
173  else
174  {
175  QLabel* lb_investigator = us_label( tr( "Investigator:" ) );
176  main->addWidget( lb_investigator, row, 0 );
177  }
178 
179  le_investigator = us_lineedit( tr( "Not Selected" ) );
180  le_investigator->setReadOnly( true );
181  main->addWidget( le_investigator, row++, 1 );
182 
183  disk_controls = new US_Disk_DB_Controls( select_db_disk );
184  connect( disk_controls, SIGNAL( changed ( bool ) ),
185  SLOT ( source_changed( bool ) ) );
186  main->addLayout( disk_controls, row++, 0, 1, 2 );
187 
188  main->addLayout( experiment, row, 0 );
189  main->addLayout( hardware, row, 1 );
190  row++; // += 10;
191 
192  // Experiment comments
193  QLabel* lb_comment = us_label( tr( "Comments:" ) );
194  main->addWidget( lb_comment, row++, 0, 1, 2 );
195 
197  main->addWidget( te_comment, row, 0, 4, 2 );
198  te_comment->setMaximumHeight( 80 );
199  te_comment->setReadOnly( false );
200  row += 4;
201 
202  main->addLayout( buttons, row++, 0, 1, 2 );
203 
204  // Let's load everything we can
205  if ( ! load() )
206  {
207  cancel();
208  return;
209  }
210 
211  reset();
212 }
213 
215 {
216  reload();
217 
218  le_investigator ->clear();
219  le_label ->clear();
220  le_runID ->setText( expInfo.runID );
221  le_project ->clear();
222  te_comment ->clear();
223 
224  pb_accept ->setEnabled( false );
225 
226  // Update controls to represent selected experiment
229 
230  le_label ->setText( expInfo.label );
231  le_project ->setText( expInfo.project.projectDesc );
232  te_comment ->setText( expInfo.comments );
233 
234  // Experiment types combo
235  cb_expType->setCurrentIndex( 0 ); // default is "velocity"
236  for ( int i = 0; i < experimentTypes.size(); i++ )
237  {
238  if ( experimentTypes[ i ].toUpper() == expInfo.expType.toUpper() )
239  {
240  cb_expType->setCurrentIndex( i );
241  break;
242  }
243  }
244 
245  // Display investigator
247 
248  if ( expInfo.invID > 0 || ! disk_controls->db() )
249  {
250  le_investigator->setText( QString::number( expInfo.invID ) + ": "
252 
253  if ( disk_controls->db() )
254  {
255  US_Passwd pw;
256  QString masterPW = pw.getPasswd();
257  US_DB2 db( masterPW );
258 
259  int runIDStatus = US_DB2::NO_EXPERIMENT;
260  if ( db.lastErrno() == US_DB2::OK )
261  runIDStatus = expInfo.checkRunID( &db );
262 
263  if ( expInfo.expID > 0 )
264  pb_accept ->setEnabled( true );
265 
266  else if ( runIDStatus != US_DB2::OK )
267  {
268  // Then an investigator has been chosen, and
269  // the current runID doesn't exist in the db
270  pb_accept ->setEnabled( true );
271  }
272  }
273 
274  else
275  {
276  // We can always accept in disk mode
277  pb_accept ->setEnabled( true );
278  }
279 
280  // However, project needs to be selected, either from db or disk
281  if ( expInfo.project.projectID == 0 && expInfo.project.projectGUID.isEmpty() )
282  pb_accept ->setEnabled( false );
283 
284  // The label can't be empty either
285  if ( expInfo.label.isEmpty() )
286  pb_accept ->setEnabled( false );
287  }
288 
289  else
291 
292 }
293 
294 // function to load what we can initially
295 // returns true if successful
297 {
298  if ( expInfo.invID == 0 )
299  {
300  // Try to get info from settings
301  int inv = US_Settings::us_inv_ID();
302  if ( inv > -1 )
303  {
304  expInfo.invID = inv;
306  }
307  }
308 
309  // Load values that were passed in
310  if ( ! expInfo.rotorName.isEmpty() )
311  le_rotorDesc->setText( expInfo.rotorName + " / " +
312  expInfo.rotorUpdated.toString( "yyyy-MM-dd" ) );
313 
314  if ( ! expInfo.label.isEmpty() )
315  le_label->setText( expInfo.label );
316 
317  if ( expInfo.project.projectID > 0 )
319 
320  if ( ! expInfo.comments.isEmpty() )
321  te_comment->setText( expInfo.comments );
322 
323  if ( disk_controls->db() )
324  {
325  US_Passwd pw;
326  QString masterPW = pw.getPasswd();
327  US_DB2 db( masterPW );
328 
329  if ( db.lastErrno() == US_DB2::OK )
331 
332  if ( labList.size() > 0 && labList[ 0 ].instruments.size() == 0 )
333  { // If empty instrument table, warn and exit
334  US_Rotor::Instrument instrument;
335  US_Rotor::Operator loperator;
336  instrument.ID = 1;
337  instrument.name = "XLA #1";
338  instrument.serial = "9999";
339  loperator.ID = 1;
340  loperator.GUID = "";
341  loperator.lname = "operator";
342  loperator.fname = "some";
343  instrument.operators << loperator;
344  labList[ 0 ].instruments << instrument;
345 
346  QMessageBox::warning( this,
347  tr( "No Instruments" ),
348  tr( "There is no instrument record in the database.\n"
349  "At least one instrument record should be added\n"
350  " through the LIMS interface.\n\n"
351  "The current Convert Legacy Data program\n"
352  " WILL NOW BE CLOSED!!!!" ) );
353 
354  cancel();
355  exit( 99 );
356  }
357  }
358 
359  else
361 
362  lab_changed = true; // so boxes will go through all the reload code 1st time
363 
364  return( true );
365 }
366 
368 {
369 qDebug() << "ExpG:reload: IN labList size" << labList.size();
370  if ( lab_changed && labList.size() > 0 )
371  {
372  // Find labList info for this lab
373  currentLab = 0;
374  bool found = false;
375  for ( int i = 0; i < labList.size(); i++ )
376  {
377  if ( labList[ i ].ID == expInfo.labID )
378  {
379  found = true;
380  currentLab = i;
381  break;
382  }
383  }
384 
385  if ( ! found )
386  {
387  // replace with the first one on the list
388  expInfo.labID = labList[ 0 ].ID;
389  currentLab = 0;
390  }
391 
392 qDebug() << "ExpG:reload: call setInstr";
394 qDebug() << "ExpG:reload: call setOper";
395  setOperatorList();
396 
397 qDebug() << "ExpG:reload: call instr load()";
398  cb_instrument ->load();
399 qDebug() << "ExpG:reload: call oper load()";
400  cb_operator ->load();
401 qDebug() << "ExpG:reload: retn fr open load()";
402  }
403 qDebug() << "ExpG:reload: RTN";
404 
405  lab_changed = false;
406 }
407 
409 {
410 }
411 
413 {
414  US_Investigator* inv_dialog = new US_Investigator( true, expInfo.invID );
415 
416  connect( inv_dialog,
417  SIGNAL( investigator_accepted( int ) ),
418  SLOT ( assignInvestigator ( int ) ) );
419 
420  inv_dialog->exec();
421 }
422 
424 {
425  expInfo.invID = invID;
426 
427  QString number = ( invID > 0 ) ? QString::number( invID ) + ": " : "";
428  le_investigator->setText( number + US_Settings::us_inv_name());
429 }
430 
432 {
433  expInfo.invID = US_Settings::us_inv_ID(); // just to be sure
435 
436  if ( disk_controls->db() )
437  {
438  US_Passwd pw;
439  QString masterPW = pw.getPasswd();
440  US_DB2 db( masterPW );
441 
442  if ( db.lastErrno() == US_DB2::OK )
443  {
444  QStringList q( "get_person_info" );
445  q << QString::number( expInfo.invID );
446  db.query( q );
447 
448  if ( db.next() )
449  expInfo.invGUID = db.value( 9 ).toString();
450  }
451  }
452 }
453 
455 {
456  QStringList DB = US_Settings::defaultDB();
457 
458  if ( db && ( DB.size() < 5 ) )
459  {
460  QMessageBox::warning( this,
461  tr( "Attention" ),
462  tr( "There is no default database set." ) );
463  }
464 
465  emit use_db( db );
466  qApp->processEvents();
467 
468  //load();
469  reset();
470 }
471 
473 {
474  ( db ) ? disk_controls->set_db() : disk_controls->set_disk();
475 
476  // Pass it on to US_Convert dialog
477  emit use_db( db );
478 }
479 
481 {
482  // Save other elements on the page first
483  expInfo.label = le_label ->text();
484  expInfo.comments = te_comment ->toPlainText();
485  expInfo.expType = cb_expType ->currentText().toLower();
486 
487  int dbdisk = ( disk_controls->db() ) ? US_Disk_DB_Controls::DB
489 
490  US_Project project = expInfo.project;
491 
492  US_ProjectGui* projInfo = new US_ProjectGui( true, dbdisk, project );
493 
494  connect( projInfo,
495  SIGNAL( updateProjectGuiSelection( US_Project& ) ),
496  SLOT ( assignProject ( US_Project& ) ) );
497 
498  connect( projInfo,
499  SIGNAL( cancelProjectGuiSelection( ) ),
500  SLOT ( cancelProject ( ) ) );
501 
502  connect( projInfo, SIGNAL( use_db ( bool ) ),
503  SLOT ( update_disk_db( bool ) ) );
504 
505  projInfo->exec();
506  delete projInfo;
507 }
508 
510 {
511  expInfo.project = project;
512 
513  reset();
514 }
515 
517 {
518  reset();
519 }
520 
521 // Function to update the labe associated with the current experiment
523 {
524  expInfo.label = le_label->text();
525  expInfo.label = expInfo.label.trimmed();
526 
527  // Save other elements on the page before reset
528  expInfo.comments = te_comment ->toPlainText();
529  expInfo.expType = cb_expType ->currentText().toLower();
530 
531  reset(); // To get the pb_accept enable code
532 }
533 
535 {
536  QComboBox* cb = us_comboBox();
537 
538  // Experiment types
539  experimentTypes.clear();
540  experimentTypes << "Velocity"
541  << "Equilibrium"
542  << "Diffusion"
543  << "Buoyancy"
544  << "Calibration"
545  << "Other";
546 
547  cb->addItems( experimentTypes );
548 
549  return cb;
550 }
551 
553 {
554 qDebug() << "ExpG: setInstrL: IN labList size" << labList.size()
555  << "currentLab" << currentLab;
556  QList< listInfo > options;
557  QList< US_Rotor::Instrument > instruments = labList[ currentLab ].instruments;
558 qDebug() << "ExpG: setInstrL: instruments size" << instruments.size();
559 
560  foreach ( US_Rotor::Instrument instrument, instruments )
561  {
562  struct listInfo option;
563  option.ID = QString::number( instrument.ID );
564  option.text = instrument.name;
565  options << option;
566  }
567 
568  cb_instrument->clear();
569  if ( options.size() > 0 )
570  {
571  cb_instrument->addOptions( options );
572 
573  // is the instrument ID in the list?
574  currentInstrument = 0;
575  for ( int i = 0; i < options.size(); i++ )
576  {
577  if ( expInfo.instrumentID == options[ i ].ID.toInt() )
578  {
579  currentInstrument = i;
580  break;
581  }
582  }
583 
584  // Replace instrument ID with one from the list
585  expInfo.instrumentID = instruments[ currentInstrument ].ID;
586  expInfo.instrumentSerial = instruments[ currentInstrument ].serial;
587 qDebug() << "ExpG: setInstrL: ins ID Ser" << expInfo.instrumentID
589  }
590 }
591 
593 {
594  QList< listInfo > options;
595  QList< US_Rotor::Instrument > instruments = labList[ currentLab ].instruments;
596  QList< US_Rotor::Operator > operators = instruments[ currentInstrument ].operators;
597 
598  foreach ( US_Rotor::Operator oper, operators )
599  {
600  struct listInfo option;
601  option.ID = QString::number( oper.ID );
602  option.text = oper.lname + ", " + oper.fname;
603  options << option;
604  }
605 
606  cb_operator->clear();
607  if ( options.size() > 0 )
608  {
609  int currentOperator = 0;
610 
611  if ( ! disk_controls->db() )
612  {
613  struct listInfo disk_only;
614  disk_only.ID = QString( "0" );
615  disk_only.text = "Local";
616  cb_operator->addOption( disk_only );
617 
618  expInfo.operatorID = 0;
619  expInfo.operatorGUID = "";
620  }
621 
622  else
623  {
624  cb_operator->addOptions( options );
625 
626  // is the operator ID in the list?
627  for ( int i = 0; i < options.size(); i++ )
628  {
629  if ( expInfo.operatorID == options[ i ].ID.toInt() )
630  {
631  currentOperator = i;
632  break;
633  }
634  }
635 
636  // Replace operator ID with one from the list
637  expInfo.operatorID = operators[ currentOperator ].ID;
638  expInfo.operatorGUID = operators[ currentOperator ].GUID;
639  }
640 
641  }
642 }
643 
644 // Function to change the current instrument
646 {
647  // First time through here the combo box might not be displayed yet
651 
652  // Save other elements on the page too
653  expInfo.label = le_label ->text();
654  expInfo.comments = te_comment ->toPlainText();
655  expInfo.expType = cb_expType ->currentText();
656 
657  lab_changed = true;
658  reset();
659 }
660 
662 {
663  // Save other elements on the page first
664  expInfo.label = le_label ->text();
665  expInfo.comments = te_comment ->toPlainText();
666  expInfo.expType = cb_expType ->currentText().toLower();
667 
668  US_Rotor::Rotor rotor;
669  rotor.ID = expInfo.rotorID;
670 
671  US_Rotor::RotorCalibration calibration;
672  calibration.ID = expInfo.calibrationID;
673 
674  int dbdisk = ( disk_controls->db() ) ? US_Disk_DB_Controls::DB
676 
677  US_RotorGui* rotorInfo = new US_RotorGui( true, // signal_wanted
678  dbdisk,
679  rotor, calibration );
680 
681  connect( rotorInfo, SIGNAL( RotorCalibrationSelected( US_Rotor::Rotor&, US_Rotor::RotorCalibration& ) ),
683 
684  connect( rotorInfo, SIGNAL( RotorCalibrationCanceled( ) ),
685  SLOT ( cancelRotor ( ) ) );
686 
687  connect( rotorInfo, SIGNAL( use_db ( bool ) ),
688  SLOT ( update_disk_db( bool ) ) );
689 
690  rotorInfo->exec();
691 }
692 
694 {
695  expInfo.rotorID = rotor.ID;
696  expInfo.rotorGUID = rotor.GUID;
698  expInfo.rotorName = rotor.name;
699  expInfo.labID = rotor.labID;
700  expInfo.calibrationID = calibration.ID;
701  expInfo.rotorCoeff1 = calibration.coeff1;
702  expInfo.rotorCoeff2 = calibration.coeff2;
703  expInfo.rotorUpdated = calibration.lastUpdated;
704 
705  le_rotorDesc->setText( rotor.name + " / " +
706  calibration.lastUpdated.toString( "yyyy-MM-dd" ) );
707 
708  lab_changed = true;
710  setOperatorList();
711 
712  reset();
713 }
714 
716 {
717  reset();
718 }
719 
721 {
722  // We can sync with the DB
723  expInfo.syncOK = true;
724 
725  // Overwrite data directly from the form
726 
727  // First get the invID
731 
732  // Other info on the form
733  expInfo.runID = le_runID ->text();
736  expInfo.expType = cb_expType ->currentText().toLower();
737  expInfo.runTemp = le_runTemp ->text();
738  expInfo.label = le_label ->text();
739  expInfo.comments = te_comment ->toPlainText();
740 
741  // Update items from the DB after getting values from the form, if we can
742  if ( disk_controls->db() )
743  {
744  US_Passwd pw;
745  QString masterPW = pw.getPasswd();
746  US_DB2 db( masterPW );
747 
748  if ( db.lastErrno() == US_DB2::OK )
749  {
750  QStringList q( "get_instrument_info" );
751  q << QString::number( expInfo.instrumentID );
752  db.query( q );
753  db.next();
754  expInfo.instrumentSerial = db.value( 1 ).toString();
755 
756  q.clear();
757  q << "get_person_info"
758  << QString::number( expInfo.operatorID );
759  db.query( q );
760  db.next();
761  expInfo.operatorGUID = db.value( 9 ).toString();
762  }
763  }
764 
766  close();
767 }
768 
770 {
771 // expInfo.clear();
772 
773  emit cancelExpInfoSelection();
774  close();
775 }
776 
777 void US_ExperimentGuiRa::connect_error( const QString& error )
778 {
779  QMessageBox::warning( this, tr( "Connection Problem" ),
780  tr( "Could not connect to database \n" ) + error );
781 }