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