UltraScan III
us_get_run.cpp
Go to the documentation of this file.
1 
3 #include "us_get_run.h"
4 #include "us_settings.h"
5 #include "us_gui_settings.h"
6 #include "us_db2.h"
7 #include "us_passwd.h"
8 #include "us_util.h"
9 #include "us_investigator.h"
10 
11 // Primary constructor to establish the dialog
12 US_GetRun::US_GetRun( QString& run, bool inDB )
13 : US_WidgetsDialog( 0, 0 ), runID( run )
14 {
15  int ddstate;
16  if ( inDB )
17  {
18  setWindowTitle( tr( "Available US3 Runs in DB" ) );
19  ddstate = US_Disk_DB_Controls::DB;
20  }
21  else
22  {
23  setWindowTitle( tr( "Available US3 Runs on Local Disk" ) );
24  ddstate = US_Disk_DB_Controls::Disk;
25  }
26 
27  setPalette( US_GuiSettings::frameColor() );
28 
29  QVBoxLayout* main = new QVBoxLayout( this );
30  main->setSpacing ( 2 );
31  main->setContentsMargins( 2, 2, 2, 2 );
32 
33  dkdb_cntrls = new US_Disk_DB_Controls( ddstate );
34  connect( dkdb_cntrls, SIGNAL( changed ( bool ) ),
35  this, SLOT ( update_disk_db( bool ) ) );
36 
37  // Investigator
39  QHBoxLayout* investigator = new QHBoxLayout;
40  pb_invest = us_pushbutton( tr( "Select Investigator" ) );
41  investigator->addWidget( pb_invest );
42  QString invval = QString::number( personID ) + ": " +
44  le_invest = us_lineedit( invval, 1, true );
45  investigator->addWidget( le_invest );
46  connect( pb_invest, SIGNAL( clicked () ),
47  this, SLOT ( sel_investigator() ) );
48 
49  // Search
50  QHBoxLayout* search = new QHBoxLayout;
51  QLabel* lb_search = us_label( tr( "Search" ) );
52  le_search = us_lineedit( "" );
53  search ->addWidget( lb_search );
54  search ->addWidget( le_search );
55  connect( le_search, SIGNAL( textChanged( const QString& ) ),
56  this, SLOT ( limit_data ( const QString& ) ) );
57 
58  // Load the runInfo structure with current data
59  if ( inDB )
60  load_db();
61  else
62  load_disk();
63 
64  // Tree
65  tw = new QTableWidget( runInfo.size(), 4, this );
66  populate_list();
67 
68  // Button Row
69  QHBoxLayout* buttons = new QHBoxLayout;
70 
71  QPushButton* pb_cancel = us_pushbutton( tr( "Cancel" ) );
72  connect( pb_cancel, SIGNAL( clicked() ), SLOT( reject() ) );
73  buttons->addWidget( pb_cancel );
74 
75  QPushButton* pb_delete = us_pushbutton( tr( "Delete" ) );
76  connect( pb_delete, SIGNAL( clicked() ), SLOT( deleteRun() ) );
77  buttons->addWidget( pb_delete );
78 
79  QPushButton* pb_accept = us_pushbutton( tr( "Select" ) );
80  connect( pb_accept, SIGNAL( clicked() ), SLOT( select() ) );
81  buttons->addWidget( pb_accept );
82 
83  main->addLayout( dkdb_cntrls );
84  main->addLayout( investigator );
85  main->addLayout( search );
86  main->addWidget( tw );
87  main->addLayout( buttons );
88 qDebug() << "gDBr: size" << size();
89  resize( 720, 440 );
90 qDebug() << "gDBr: size" << size();
91 }
92 
93 // Function to load the runInfo structure with all runID's in the DB
94 void US_GetRun::load_db( void )
95 {
96 qDebug() << "LdDb: IN";
97  US_Passwd pw;
98  QString masterPW = pw.getPasswd();
99  US_DB2 db( masterPW );
100 
101  if ( db.lastErrno() != US_DB2::OK )
102  {
103  QMessageBox::information( this,
104  tr( "Error" ),
105  tr( "Error making the DB connection.\n" ) );
106  return;
107  }
108 
109  // Get information we want about all experiments
110  runInfo.clear();
111  QStringList q( "get_experiment_desc" );
112  q << QString::number( US_Settings::us_inv_ID() );
113  db.query( q );
114 
115  while( db.next() )
116  {
117  RunInfo rr;
118  rr.ID = db.value( 0 ).toString().toInt();
119  rr.runID = db.value( 1 ).toString();
120  rr.label = db.value( 4 ).toString();
122  .toDateTime().toString( Qt::ISODate ), true )
123  .section( " ", 0, 0 ).simplified();
124 //qDebug() << "expID" << expID << "ID date runID label"
125 // << rr.ID << rr.date << rr.runID << rr.label;
126 
127  runInfo << rr;
128  }
129 
130  if ( runInfo.size() < 1 )
131  {
132  QMessageBox::information( this,
133  tr( "Error" ),
134  tr( "There are no US3 runs in the DB to load.\n" ) );
135  }
136 
137  return;
138 }
139 
140 // Function to load the runInfo structure with all runID's on local disk
142 {
143  QString resdir = US_Settings::resultDir();
144  QStringList rdirs = QDir( resdir ).entryList(
145  QDir::AllDirs | QDir::NoDotAndDotDot, QDir::Name );
146 qDebug() << "LdDk: rdirs count" << rdirs.count();
147  resdir = resdir + "/";
148  QStringList efilt;
149  efilt << "*.auc" << "*.??.xml";
150  QStringList runids;
151 
152  // Get the list of all Run IDs with data in their work directories
153  for ( int ii = 0; ii < rdirs.count(); ii++ )
154  {
155  QString wdir = resdir + rdirs[ ii ];
156  QStringList efiles = QDir( wdir ).entryList( efilt, QDir::Files,
157  QDir::Name );
158 
159  if ( efiles.count() < 1 )
160  continue;
161 
162  runids << rdirs[ ii ];
163 //qDebug() << "LdDk: ii" << ii << "run" << rdirs[ii];
164  }
165 qDebug() << "LdDk: runids count" << runids.count();
166 
167  runInfo.clear();
168 
169  // Now fill in the runInfo for those runs
170  for ( int ii = 0; ii < runids.count(); ii++ )
171  {
172  QString runID = runids[ ii ];
173  QString wdir = resdir + runID;
174  efilt.clear();
175  efilt << runID + ".??.xml";
176  QStringList efiles = QDir( wdir ).entryList( efilt, QDir::Files,
177  QDir::Name );
178 
179 //qDebug() << "LdDk: ii" << ii << "ef" << efilt << "efcount" << efiles.count()
180 // << " run" << runID;
181  if ( efiles.count() != 1 )
182  continue;
183 
184  QString rfn = wdir + "/" + efiles[ 0 ];
185  QString expID;
186  QString label;
187  QString date = US_Util::toUTCDatetimeText(
188  QFileInfo( rfn ).lastModified().toUTC()
189  .toString( Qt::ISODate ), true )
190  .section( " ", 0, 0 ).simplified();
191 
192 //qDebug() << "LdDk: ii" << ii << " rfn" << rfn;
193  QFile xfi( rfn );
194  if ( ! xfi.open( QIODevice::ReadOnly | QIODevice::Text ) )
195  continue;
196 
197  QXmlStreamReader xml( &xfi );
198 
199  while ( ! xml.atEnd() )
200  { // Read experiment elements
201  QString xname;
202  QString attv;
203  QXmlStreamAttributes attr;
204 
205  xml.readNext();
206 
207  if ( xml.isStartElement() )
208  {
209  xname = xml.name().toString();
210 
211  if ( xname == "experiment" )
212  {
213  attr = xml.attributes();
214  expID = attr.value( "id" ).toString();
215  }
216 
217  else if ( xname == "label" )
218  {
219  xml.readNext();
220  label = xml.text().toString();
221  }
222  }
223  }
224 
225  RunInfo rr;
226  rr.ID = expID.toInt();
227  rr.date = date;
228  rr.runID = runID;
229  rr.label = label;
230 //qDebug() << "LdDk: ii" << ii << " expID" << expID << "ID date runID label"
231 // << rr.ID << rr.date << rr.runID << rr.label;
232 
233  runInfo << rr;
234  }
235 
236  if ( runInfo.size() < 1 )
237  {
238  QMessageBox::information( this,
239  tr( "Error" ),
240  tr( "There are no US3 runs on the local Disk to load.\n" ) );
241  }
242 
243  return;
244 }
245 
246 // Function to pass information back when select button is pressed
247 void US_GetRun::select( void )
248 {
249  int ndx = tw ->currentRow();
250 
251  runID = tw ->item( ndx, 0 )->text();
252 qDebug() << "GetRun: accept : runID" << runID;
253  accept();
254 }
255 
256 // Function to delete the highlighted run when delete button is pressed
258 {
259  US_Passwd pw;
260  QString masterPW = pw.getPasswd();
261  US_DB2 db( masterPW );
262 
263  if ( db.lastErrno() != US_DB2::OK )
264  {
265  QMessageBox::information( this,
266  tr( "Error" ),
267  tr( "Error making the DB connection.\n" ) );
268  return;
269  }
270 
271  int status = QMessageBox::information( this,
272  tr( "Warning" ),
273  tr( "Are you sure you want to delete this run from the DB? " ) +
274  tr( "This action is not reversible. Proceed? " ),
275  tr( "&OK" ), tr( "&Cancel" ),
276  0, 0, 1 );
277  if ( status != 0 ) return;
278 
279  int ndx = tw ->currentRow();
280  QString expID = tw ->item( ndx, 2 )->text();
281 
282  // Let's make sure it's not a calibration experiment in use
283  QStringList q( "count_calibration_experiments " );
284  q << expID;
285  int count = db.functionQuery( q );
286 
287  if ( count < 0 )
288  {
289  qDebug() << "count_calibration_experiments( "
290  << expID
291  << " ) returned a negative count";
292  return;
293  }
294 
295  else if ( count > 0 )
296  {
297  QMessageBox::information( this,
298  tr( "Error" ),
299  tr( "Cannot delete an experiment that is associated "
300  "with a rotor calibration\n" ) );
301  return;
302  }
303 
304  tw->removeRow( ndx );
305 
306  // Delete links between experiment and solutions
307  q.clear();
308  q << "delete_experiment_solutions"
309  << expID ;
310  status = db.statusQuery( q );
311 
312  // Same with cell table
313  q.clear();
314  q << "delete_cell_experiments"
315  << expID ;
316  status = db.statusQuery( q );
317 
318  // Now delete the experiment and all existing rawData,
319  // because we're starting over
320  q.clear();
321  q << "delete_experiment"
322  << expID ;
323  status = db.statusQuery( q );
324 qDebug() << "GetRun:delRun: del_exp stat" << status;
325 
326  if ( status != US_DB2::OK )
327  {
328  QMessageBox::information( this,
329  tr( "Error / Warning" ),
330  db.lastError() + tr( " (error=%1, expID=%2)" )
331  .arg( status ).arg( expID ) );
332  }
333 }
334 
335 // Function to populate the data tree
337 {
338  QFont tw_font( US_Widgets::fixedFont().family(),
340  QFontMetrics* fm = new QFontMetrics( tw_font );
341  int rowht = fm->height() + 2;
342 // tw = new QTableWidget( runInfo.size(), 4, this );
343  tw->setFont ( tw_font );
344  tw->setPalette( US_GuiSettings::editColor() );
345  tw->setRowCount( runInfo.count() );
346 
347  QStringList headers;
348  headers << "Run"
349  << "Date"
350  << "dbID"
351  << "Label";
352 
353  tw->setHorizontalHeaderLabels( headers );
354  tw->verticalHeader()->hide();
355  tw->setShowGrid( false );
356  tw->setSelectionBehavior( QAbstractItemView::SelectRows );
357  tw->setMinimumWidth( 640 );
358  tw->setMinimumHeight( 480 );
359  tw->setColumnWidth( 0, 250 );
360  tw->setColumnWidth( 1, 150 );
361  tw->setColumnWidth( 2, 50 );
362  tw->setColumnWidth( 3, 350 );
363  tw->setSortingEnabled( false );
364  tw->clearContents();
365 
366  // Now load the table, marking each as not-editable
367  for ( int ii = 0; ii < runInfo.size(); ii++ )
368  {
369  QTableWidgetItem* item;
370  RunInfo rr = runInfo[ ii ];
371 
372  item = new QTableWidgetItem( rr.runID );
373  item->setFlags( item->flags() ^ Qt::ItemIsEditable );
374  tw ->setItem( ii, 0, item );
375 
376  item = new QTableWidgetItem( rr.date );
377  item->setFlags( item->flags() ^ Qt::ItemIsEditable );
378  tw ->setItem( ii, 1, item );
379 
380  item = new QTableWidgetItem( QString().sprintf( "%6d", rr.ID ) );
381  item->setFlags( item->flags() ^ Qt::ItemIsEditable );
382  tw ->setItem( ii, 2, item );
383 
384  item = new QTableWidgetItem( rr.label );
385  item->setFlags( item->flags() ^ Qt::ItemIsEditable );
386  tw ->setItem( ii, 3, item );
387 //qDebug() << "setItems ii" << ii << "ID date runID label"
388 // << rr.ID << rr.date << rr.runID << rr.label;
389 
390  tw ->setRowHeight( ii, rowht );
391  }
392 
393  tw->setSortingEnabled( true );
394  tw->sortByColumn( 1, Qt::DescendingOrder );
395  tw->resizeColumnsToContents();
396  tw->adjustSize();
397  tw->resize( size().width() - 4, tw->size().height() );
398  qApp->processEvents();
399 }
400 
401 // Function to update the selection of disk or DB
402 void US_GetRun::update_disk_db( bool isDB )
403 {
404 qDebug() << "UpdDkDb: isDB" << isDB;
405  if ( isDB )
406  {
407  load_db();
408  setWindowTitle( tr( "Available US3 Runs in DB" ) );
409  }
410  else
411  {
412  load_disk();
413  setWindowTitle( tr( "Available US3 Runs on Local Disk" ) );
414  }
415 
416  populate_list();
417 
418  QString sfilt = le_search->text();
419  if ( ! sfilt.isEmpty() )
420  limit_data( sfilt );
421 
422  emit dkdb_changed( isDB );
423 }
424 
425 // Function to limit table data shown based on search criteria
426 void US_GetRun::limit_data( const QString& sfilt )
427 {
428 qDebug() << "LimData: sfilt" << sfilt;
429  bool have_search = ! sfilt.isEmpty();
430  QFont tw_font( US_Widgets::fixedFont().family(),
432  QFontMetrics* fm = new QFontMetrics( tw_font );
433  int rowht = fm->height() + 2;
434  tw->clearContents();
435  tw->setSortingEnabled( false );
436 
437  for ( int ii = 0; ii < runInfo.size(); ii++ )
438  {
439  QTableWidgetItem* item;
440  RunInfo rr = runInfo[ ii ];
441 
442  // Skip the item if search text exists and the runID does not contain it
443  if ( have_search &&
444  ! rr.runID.contains( sfilt, Qt::CaseInsensitive ) )
445  continue;
446 
447  item = new QTableWidgetItem( rr.runID );
448  item->setFlags( item->flags() ^ Qt::ItemIsEditable );
449  tw ->setItem( ii, 0, item );
450 
451  item = new QTableWidgetItem( rr.date );
452  item->setFlags( item->flags() ^ Qt::ItemIsEditable );
453  tw ->setItem( ii, 1, item );
454 
455  item = new QTableWidgetItem( QString().sprintf( "%6d", rr.ID ) );
456  item->setFlags( item->flags() ^ Qt::ItemIsEditable );
457  tw ->setItem( ii, 2, item );
458 
459  item = new QTableWidgetItem( rr.label );
460  item->setFlags( item->flags() ^ Qt::ItemIsEditable );
461  tw ->setItem( ii, 3, item );
462 //qDebug() << "setItems ii" << ii << "ID date runID label"
463 // << rr.ID << rr.date << rr.runID << rr.label;
464 
465  tw ->setRowHeight( ii, rowht );
466  }
467 
468  tw->setSortingEnabled( true );
469  tw->sortByColumn( 1, Qt::DescendingOrder );
470  tw->resizeColumnsToContents();
471  tw->adjustSize();
472 // tw->update();
473 // update();
474  tw->resize( size().width() - 4, tw->size().height() );
475  qApp->processEvents();
476 }
477 
478 // Open the dialog to select a new investigator
480 {
481  if ( !dkdb_cntrls->db() ) return; // Ignore if Disk selected
482 
483  US_Investigator* inv_dialog = new US_Investigator( true, personID );
484 
485  connect( inv_dialog, SIGNAL( investigator_accepted( int ) ),
486  this, SLOT ( assign_investigator ( int ) ) );
487 
488  inv_dialog->exec();
489 }
490 
491 // Assign this dialog's investigator text and re-populate tree
493 {
494  personID = invID;
495  QString number = ( invID > 0 ) ? QString::number( invID ) + ": " : "";
496 
497  le_invest->setText( number + US_Settings::us_inv_name() );
498 
499  load_db();
500 
501  populate_list();
502 }
503