UltraScan III
us_data_loader.cpp
Go to the documentation of this file.
1 
3 #include "us_data_loader.h"
4 #include "us_settings.h"
5 #include "us_gui_settings.h"
6 #include "us_matrix.h"
7 #include "us_investigator.h"
8 #include "us_passwd.h"
9 #include "us_db2.h"
10 #include "us_dataIO.h"
11 #include "us_util.h"
12 #include "us_editor.h"
13 #include "us_constants.h"
14 
15 // Main constructor with flags for edit, latest-edit and local-data
16 
18  bool late,
19  int local,
20  QVector< US_DataIO::RawData >& rData,
21  QVector< US_DataIO::EditedData >& eData,
22  QStringList& trips,
23  QString& desc,
24  QString tfilt )
25  : US_WidgetsDialog( 0, 0 ),
26  latest ( late ),
27  rawData ( rData ),
28  editedData ( eData ),
29  triples ( trips ),
30  description( desc ),
31  etype_filt ( tfilt )
32 {
33  setAttribute ( Qt::WA_DeleteOnClose );
34  setWindowTitle( tr( "Load Edited Data" ) );
35  setPalette ( US_GuiSettings::frameColor() );
36  setMinimumSize( 320, 300 );
37 
38  // Main layout
39  QVBoxLayout* main = new QVBoxLayout( this );
40  main->setContentsMargins( 2, 2, 2, 2 );
41  main->setSpacing ( 2 );
42 
43  // Top layout: buttons and fields above list widget
44  QGridLayout* top = new QGridLayout;
45  int row = 0;
46 
47  // Disk/ DB
48  disk_controls = new US_Disk_DB_Controls( local );
49  connect( disk_controls, SIGNAL( changed ( bool ) ),
50  SLOT( update_disk_db( bool ) ) );
51  top->addLayout( disk_controls, row++, 0, 1, 2 );
52 
53  // Investigator
54  // Only enable the investigator button for privileged users
55  pb_invest = us_pushbutton( tr( "Select Investigator" ) );
56  int invlev = US_Settings::us_inv_level();
57  pb_invest->setEnabled( ( invlev > 0 ) && disk_controls->db() );
58  connect( pb_invest, SIGNAL( clicked() ), SLOT( get_person() ) );
59  top->addWidget( pb_invest, row, 0 );
60 
61  QString inv_name = ( ( invlev > 0 )
62  ? QString::number( US_Settings::us_inv_ID() ) + ": "
63  : "" ) + US_Settings::us_inv_name();
64 
65  le_invest = us_lineedit( inv_name );
66  us_setReadOnly( le_invest, true );
67  top->addWidget( le_invest, row++, 1 );
68 
69  // Search line
70  QLabel* lb_filtdata = us_label( tr( "Search" ) );
71  top->addWidget( lb_filtdata, row, 0 );
72 
74  top->addWidget( le_dfilter, row++, 1 );
75 
76  connect( le_dfilter, SIGNAL( textChanged( const QString& ) ),
77  SLOT ( search ( const QString& ) ) );
78 
79  main->addLayout( top );
80 
81  QFont tw_font( US_Widgets::fixedFont().family(),
83 
84  // Tree widget to show data choices
85  tw_data = new QTreeWidget( this );
86  tw_data->setFrameStyle ( QFrame::NoFrame );
87  tw_data->setPalette ( US_GuiSettings::editColor() );
88  tw_data->setFont ( tw_font );
89  tw_data->setSelectionMode( QAbstractItemView::ExtendedSelection );
90  tw_data->installEventFilter( this );
91  main->addWidget( tw_data );
92 
93  // Notes
94  te_notes = new QTextEdit();
95  te_notes->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
96  te_notes->setTextColor( Qt::blue );
97  te_notes->setText( tr( "Right-mouse-button-click on a list selection"
98  " for details." ) );
99  int font_ht = QFontMetrics( tw_font ).lineSpacing();
100  te_notes->setMaximumHeight( font_ht * 2 + 12 );
101  main->addWidget( te_notes );
102 
103  // Button Row
104  QHBoxLayout* buttons = new QHBoxLayout;
105  QPushButton* pb_help = us_pushbutton( tr( "Help" ) );
106  QPushButton* pb_cancel = us_pushbutton( tr( "Cancel" ) );
107  QPushButton* pb_shedit = us_pushbutton( tr( "Show Edits" ) );
108  QPushButton* pb_accept = us_pushbutton( tr( "Load" ) );
109  buttons->addWidget( pb_help );
110  buttons->addWidget( pb_cancel );
111  buttons->addWidget( pb_shedit );
112  buttons->addWidget( pb_accept );
113  connect( pb_help, SIGNAL( clicked() ), SLOT( help() ) );
114  connect( pb_cancel, SIGNAL( clicked() ), SLOT( cancelled() ) );
115  connect( pb_shedit, SIGNAL( clicked() ), SLOT( selected() ) );
116  connect( pb_accept, SIGNAL( clicked() ), SLOT( accepted() ) );
117 
118  main->addLayout( buttons );
119 
120  // List from disk or db source
121  sel_run = false;
122  etype_filt = etype_filt.isEmpty() ? "velocity" : etype_filt.toLower();
123 
124  list_data(); // Populate an initial (runs) list
125 
126  resize( 720, 500 );
127 }
128 
129 // Re-display the list after a change in the search field
130 void US_DataLoader::search( const QString& search_string )
131 {
132  tw_data->setCurrentItem( NULL );
133 
134  for ( int i = 0; i < tw_data->topLevelItemCount(); i++ )
135  {
136  QTreeWidgetItem* twi = tw_data->topLevelItem( i );
137  bool hide = ! twi->text( 0 ).contains( search_string,
138  Qt::CaseInsensitive );
139  twi->setHidden( hide );
140  }
141 }
142 
143 // Load edit data list (along with raw) from selected set
145 {
146  editedData.clear();
147  rawData .clear();
148  triples .clear();
149 
150  QList< QTreeWidgetItem* > selections = tw_data->selectedItems();
151 
152  // Disallow selections from multiple RunIDs
153  QTreeWidgetItem* twi;
154  QList< QTreeWidgetItem* > topLevel;
155 
156  foreach ( twi, selections )
157  {
158  while ( twi->parent() != NULL ) twi = twi->parent();
159  if ( ! topLevel.contains( twi ) )
160  topLevel << twi;
161 
162  if ( ! sel_run )
163  break;
164  }
165 
166  if ( topLevel.size() > 1 )
167  {
168  QMessageBox::warning( this,
169  tr( "Invalid Selection" ),
170  tr( "Only items from one run may be selected." ) );
171  return false;
172  }
173 
174  // If we are here after a whole-run load at stage 1 (top-level only),
175  // then we must first fill out the data map for the selected run.
176  if ( ! sel_run )
177  {
178 //qDebug() << "LdEd: sel_run=false : scan edits";
179  QTreeWidgetItem* twi = selections[ 0 ];
180 
181  while ( twi->parent() != NULL )
182  twi = twi->parent();
183 
184  runID_sel = twi->text( 0 ); // Get the selected run ID
185  sel_run = true; // Mark run selected
186  datamap.clear();
187  dlabels.clear();
188 
189  QApplication::setOverrideCursor( QCursor( Qt::WaitCursor ) );
190  te_notes->setText( tr( "Gathering information on triples and edits"
191  " for run ID\n\"%1\"..." ).arg( runID_sel ) );
192  qApp->processEvents();
193  qApp->processEvents();
194 //qDebug() << "LdEd: gath info... message noted";
195 
196  if ( disk_controls->db() ) // Scan database data
197  {
198  scan_dbase_edit();
199  }
200  else // Scan local disk data
201  {
202  scan_local_edit();
203  }
204 //qDebug() << "LdEd: scan edit complete";
205 
206  QApplication::restoreOverrideCursor();
207  QApplication::restoreOverrideCursor();
208  qApp->processEvents();
209  dlabels = datamap.keys(); // Get keys for new mappings
210  sel_run = false; // Mark full edits data tree
211  }
212 
213  // Get a list of data to load
214  int index;
215  QList< int > indexes;
216 
217  if ( selections.size() > 1 || selections[ 0 ]->parent() != NULL )
218  { // Multiple selections, so test that they are valid
219  foreach ( twi, selections )
220  {
221  index = twi->type();
222  if ( ! indexes.contains( index ) ) indexes << index;
223  }
224 
225  // Disallow multiple EditIDs from the same triple
226  foreach ( index, indexes )
227  {
228  QString key = dlabels[ index ];
229  QString triple = QString( datamap[ key ].tripID )
230  .replace( ".", " / " );
231 
232  if ( triples.contains( triple ) )
233  {
234  QMessageBox::warning( this,
235  tr( "Invalid Selection" ),
236  tr( "Only one edit from each triple may be selected." ) );
237  return false;
238  }
239  }
240  }
241 
242  // If we have only a top level item, add the first edit item from
243  // each triple
244 
245  if ( selections.size() == 1 && selections[ 0 ]->parent() == NULL )
246  {
247 qDebug() << "LdEd: Only 1 top-level item dlabsize" << dlabels.size();
248  indexes.clear();
249 
250  if ( sel_run )
251  {
252  twi = selections[ 0 ];
253 
254  for ( int i = 0; i < twi->childCount(); i++ )
255  {
256  QTreeWidgetItem* child = twi->child( i );
257  if ( child == NULL ) continue;
258 
259  // Get type (label index) of grandchild
260  indexes << child->child( 0 )->type();
261  }
262  }
263 
264  else
265  {
266  for ( int ii = 0; ii < dlabels.size(); ii++ )
267  indexes << ii;
268  }
269  }
270 else
271 qDebug() << "LdEd: selsz" << selections.size() << "dlabsz" << dlabels.size();
272 
273  if ( indexes.size() < 1 )
274  {
275  twi = selections[ 0 ];
276  QMessageBox::warning( this,
277  tr( "No Edits Available" ),
278  tr( "No Edit children exist for selected run"
279  " '%1'. The run will be hidden." ).arg( runID_sel ) );
280  twi->setHidden( true );
281  return false;
282  }
283 
284  QApplication::setOverrideCursor( QCursor( Qt::WaitCursor ) );
285  te_notes->setText( tr( "Loading data from " ) +
286  ( disk_controls->db() ? "Database" : "Local Disk" ) +
287  " ..." );
288  qApp->processEvents();
289 
290  if ( ! disk_controls->db() ) // Load files from local disk
291  {
292  for ( int ii = 0; ii < indexes.size(); ii++ )
293  {
294  QString key = dlabels[ indexes[ ii ] ];
295  ddesc = datamap[ key ];
296  QString filename = ddesc.filename;
297  QString dtriple = ddesc.tripID;
298  QString triple = QString( dtriple ).replace( ".", " / " );
299 
300  triples << triple;
301 
302  QString clambda = dtriple .section( ".", -1, -1 );
303  QString filedir = filename.section( "/", 0, -2 );
304  filename = filename.section( "/", -1, -1 );
305  QString ftriple = filename.section( ".", -4, -2 );
306  QString message = tr( "Loading triple " ) + triple;
307 
308  if ( triple != ftriple && ftriple.contains( "-" ) )
309  { // Modify filename to signal MWL
310  QString ftrnode = "." + ftriple + ".";
311  QString utrnode = "." + ftriple + "@" + clambda + ".";
312  filename = filename.replace( ftrnode, utrnode );
313  }
314 
315  emit progress( message );
316  qApp->processEvents();
317 
318  try
319  {
320  US_DataIO::loadData( filedir, filename, editedData, rawData );
321  }
322  catch ( US_DataIO::ioError error )
323  {
324  QApplication::restoreOverrideCursor();
325  QMessageBox::warning( this,
326  tr( "Data Error" ),
327  US_DataIO::errorString( error ) );
328 
329  return false;
330  }
331  catch ( int err )
332  {
333  QApplication::restoreOverrideCursor();
334  QMessageBox::warning( this,
335  tr( "Data Error" ),
336  US_DataIO::errorString( err ) );
337 
338  return false;
339  }
340  }
341  }
342 
343  else // Load data from database
344  {
345  US_Passwd pw;
346  US_DB2 db( pw.getPasswd() );
347 
348  if ( db.lastErrno() != US_DB2::OK )
349  {
350  QApplication::restoreOverrideCursor();
351  QMessageBox::information( this,
352  tr( "DB Connection Problem" ),
353  tr( "There was an error connecting to the database:\n" )
354  + db.lastError() );
355 
356  return false;
357  }
358 
359  QStringList query;
360  QString prvfname = "";
361  QString efn = "";
362  bool dnld_auc = true;
363  bool dnld_edt = true;
364 
365  // Read first selection from DB, then generate a map of AUCfile::idAUC
366  ddesc = datamap[ dlabels[ indexes[ 0 ] ] ];
367 qDebug() << "LdEd: ndx0" << indexes[0] << "dlab0" << dlabels[indexes[0]];
368  QString recID = QString::number( ddesc.DB_id );
369  QString runID = ddesc.runID;
370  QString rdir = US_Settings::resultDir();
371  QString uresdir = rdir + "/" + runID + "/";
372  QDir( rdir ).mkpath( runID );
373  QString message = tr( "Browsing AUC data..." );
374  emit progress( message );
375  qApp->processEvents();
376 qDebug() << "LdEd:TM:10: " << QTime::currentTime().toString("hh:mm:ss:zzzz");
377 
378  for ( int ii = 0; ii < indexes.size(); ii++ )
379  { // Read in each of the edits that was selected
380  QString key = dlabels[ indexes[ ii ] ];
381  ddesc = datamap[ key ];
382  int idRec = ddesc.DB_id;
383  QString dtriple = ddesc.tripID;
384  QString triple = QString( dtriple ).replace( ".", " / " );
385 qDebug() << "LdEd: ii" << ii << "ndxii" << indexes[ii] << "triple" << triple;
386 
387  triples << triple;
388 
389  QString dscfname = ddesc.filename;
390  QString filename = dscfname;
391  QString clambda = dtriple .section( ".", -1, -1 );
392  QString filedir = filename.section( "/", 0, -2 );
393  filename = filename.section( "/", -1, -1 );
394  QString ftriple = filename.section( ".", -4, -2 );
395 
396  if ( triple != ftriple && ftriple.contains( "-" ) )
397  { // Modify filename to signal MWL
398  QString ftrnode = "." + ftriple + ".";
399  QString utrnode = "." + ftriple + "@" + clambda + ".";
400  filename = filename.replace( ftrnode, utrnode );
401  }
402 
403  QString recID = QString::number( idRec );
404  QString invID = QString::number( US_Settings::us_inv_ID() );
405  QString aucfn = ddesc.runID + "."
406  + filename.section( ".", -5, -3 )
407  + "." + clambda + ".auc";
408  QString afn = uresdir + aucfn;
409  int idAUC = ddesc.auc_id;
410  efn = uresdir + dscfname;
411  dnld_auc = true;
412 
413  QString message = tr( "Loading triple " ) + triple;
414  emit progress( message );
415  qApp->processEvents();
416 
417  if ( QFile( afn ).exists() )
418  { // AUC file exists, so only download if checksum mismatch
419  QString fcheck = US_Util::md5sum_file( afn );
420 
421  if ( ddesc.acheck.isEmpty() )
422  { // No database checksum+size, so get it
423  QString aucID = QString::number( idAUC );
424 qDebug() << "LdEd: was-empty, aucID" << aucID << idAUC;
425  query.clear();
426  query << "get_rawData" << aucID;
427  db.query( query );
428 qDebug() << "LdEd: w-e, num_rows" << db.numRows();
429  db.next();
430 qDebug() << "LdEd: w-e, dberr" << db.lastErrno() << US_DB2::OK;
431  ddesc.acheck = db.value( 8 ).toString() + " " +
432  db.value( 9 ).toString();
433 qDebug() << "LdEd: was-empty, now acheck" << ddesc.acheck;
434  }
435 qDebug() << "LdEd: fcheck" << fcheck;
436 qDebug() << "LdEd: acheck" << ddesc.acheck;
437 
438  dnld_auc = ( fcheck != ddesc.acheck );
439  }
440 qDebug() << "LdEd: dnld_auc" << dnld_auc << "afn" << afn;
441 
442  if ( dnld_auc )
443  {
444  db.readBlobFromDB( afn, "download_aucData", idAUC );
445 qDebug() << "LdEd: dnld_auc DONE" << dscfname << prvfname;
446  }
447 
448  if ( dscfname != prvfname )
449  {
450  efn = uresdir + dscfname;
451  prvfname = dscfname;
452  dnld_edt = true;
453 
454  if ( QFile( efn ).exists() )
455  { // Edit XML file exists, so only download if checksum mismatch
456  QString fcheck = US_Util::md5sum_file( efn );
457  dnld_edt = ( fcheck != ddesc.echeck );
458  }
459 
460 qDebug() << "LdEd: dnld_edt" << dnld_edt << "efn" << efn;
461  if ( dnld_edt )
462  db.readBlobFromDB( efn, "download_editData", idRec );
463 qDebug() << "LdEd: dnld_edt DONE";
464  }
465 
466  qApp->processEvents();
467 
468 qDebug() << "LdEd: loadData uresdir filename" << uresdir << filename;
469  US_DataIO::loadData( uresdir, filename, editedData, rawData );
470 qDebug() << "LdEd: loadData DONE";
471  } // END: edits loop
472 qDebug() << "LdEd:TM:11: " << QTime::currentTime().toString("hh:mm:ss:zzzz");
473  } // END: Load from DB
474 
475  QApplication::restoreOverrideCursor();
476  double dt = 0.0;
478 
479  foreach( ed, editedData )
480  {
481  double delta = ed.temperature_spread();
482  dt = ( dt < delta ) ? delta : dt;
483  }
484 
485  if ( dt > US_Settings::tempTolerance() )
486  {
487  QMessageBox::warning( this,
488  tr( "Temperature Problem" ),
489  tr( "The temperature in this run varied over the course\n"
490  "of the run to a larger extent than allowed by the\n"
491  "current threshold (" )
492  + QString::number( US_Settings::tempTolerance(), 'f', 1 )
493  + " " + DEGC + tr( ". The accuracy of experimental\n"
494  "results may be affected significantly." ) );
495  }
496 
497  return true;
498 }
499 
500 // Return description string of data last selected
502 {
503  QString label = ddesc.label;
504  QString descript = ddesc.descript;
505  QString dbID = QString::number( ddesc.DB_id );
506  QString filename = ddesc.filename;
507  QString dataGUID = ddesc.dataGUID;
508  QString aucGUID = ddesc.aucGUID;
509  QString aucID = QString::number( ddesc.auc_id );
510  QString cdesc = label + descript + filename + dataGUID + aucGUID + dbID;
511  QString sep = ";"; // Use semi-colon as separator
512 
513  if ( cdesc.contains( sep ) )
514  sep = "^"; // Use carat if semi-colon already in use
515 
516  // Create and return a composite description string
517  description = sep + label
518  + sep + descript
519  + sep + dbID
520  + sep + filename
521  + sep + dataGUID
522  + sep + aucID
523  + sep + aucGUID;
524 }
525 
526 // Investigator button clicked: get investigator from dialog
528 {
529  int invID = US_Settings::us_inv_ID();
530  US_Investigator* dialog = new US_Investigator( true, invID );
531 
532  connect(
533  dialog,
534  SIGNAL( investigator_accepted( int ) ),
535  SLOT( update_person( int ) ));
536 
537  dialog->exec();
538 }
539 
540 // Slot to handle accept in investigator dialog
542 {
543  QString number = ( ID > 0 ) ? QString::number( ID ) + ": " : "";
544  le_invest->setText( number + US_Settings::us_inv_name() );
545  list_data();
546 }
547 
548 // List data choices (from db or disk)
550 {
551  QApplication::setOverrideCursor( QCursor( Qt::WaitCursor ) );
552  datamap.clear();
553 
554  if ( sel_run )
555  { // A run has been selected, so scan for edits
556  if ( disk_controls->db() ) // Scan database data
557  {
558  scan_dbase_edit();
559  }
560  else // Scan local disk data
561  {
562  scan_local_edit();
563  }
564 
565  te_notes->setText( tr( "Right-mouse-button-click on a list selection"
566  " for details.\n"
567  "Select triples/edits and click on \"Load\""
568  " to load selected data." ) );
569  }
570  else
571  { // No run is selected, so scan for runs
572  if ( disk_controls->db() ) // Scan database data
573  {
574  scan_dbase_runs();
575  }
576  else // Scan local disk data
577  {
578  scan_local_runs();
579  }
580 
581  te_notes->setText( tr( "Select a run, then click on \"Show Edits\""
582  " to fill in triples and edits;\n"
583  "or click on \"Load\" to load all the latest"
584  " edits of triples for the selected run." ) );
585  }
586 
587  // Start building the data tree
588  qApp->processEvents();
589  QStringList crlabels;
590  QStringList hdrs;
591  hdrs << ( sel_run ? tr( "Run|Triple|Edit" ) : tr( "Run" ) )
592  << tr( "Date" )
593  << tr( "DbID" )
594  << tr( "Label" );
595  tw_data->clear();
596  tw_data->setColumnCount( 4 );
597  tw_data->setHeaderLabels( hdrs );
598  tw_data->setSortingEnabled( false );
599 
600  QTreeWidgetItem* twi_edit = NULL;
601  QTreeWidgetItem* twi_runi = NULL;
602  QTreeWidgetItem* twi_trip = NULL;
603 
604  dlabels = datamap.keys();
605  QList< DataDesc > ddescrs = datamap.values();
606  QString prlabel = "";
607  QString ptlabel = "";
608  int ndxt = 1;
609  int ndxe = 1;
610  bool fromDB = disk_controls->db();
611 
612  if ( dlabels.size() == 0 )
613  {
614  QString clabel = tr( "No data found." );
615  twi_runi = new QTreeWidgetItem( QStringList( clabel), 0 );
616  tw_data->addTopLevelItem( twi_runi );
617  QApplication::restoreOverrideCursor();
618  QApplication::restoreOverrideCursor();
619  return;
620  }
621 
622  for ( int ii = 0; ii < dlabels.size(); ii++ )
623  { // Propagate list widget with labels
624  QString cdescr = dlabels.at( ii );
625  DataDesc ddesc = ddescrs.at( ii );
626  QString dbID = fromDB
627  ? QString().sprintf( "%6d", ddesc.DB_id )
628  : QString( "" );
629  crlabels.clear();
630  crlabels << ddesc.runID
631  << QString( ddesc.date ).section( " ", 0, 0 ).simplified()
632  << dbID
633  << ddesc.elabel;
634  QString crlabel = ddesc.runID;
635  QString ctlabel = ddesc.tripID;
636  QString celabel = ddesc.editID;
637 
638  if ( crlabel != prlabel )
639  { // New runID: add top-level item
640  twi_runi = new QTreeWidgetItem( crlabels, ii );
641  tw_data->addTopLevelItem( twi_runi );
642 
643  if ( sel_run )
644  { // If in show-edits mode, add a triple child
645  twi_trip = new QTreeWidgetItem( QStringList( ctlabel ), ii );
646  twi_runi->addChild( twi_trip );
647  }
648 
649  prlabel = crlabel;
650  ptlabel = ctlabel;
651  ndxt = 1;
652  ndxe = 1;
653  }
654  else if ( ctlabel != ptlabel )
655  { // New triple in same runID: add triple child of run
656  twi_trip = new QTreeWidgetItem( QStringList( ctlabel ), ii );
657  twi_runi->addChild( twi_trip );
658  ptlabel = ctlabel;
659  ndxt++;
660  ndxe = 1;
661  }
662  else
663  { // Same triple as before
664  ndxe++;
665  }
666 
667  // Always add an edit child of triple (if in show-edits mode)
668  if ( sel_run )
669  {
670  twi_edit = new QTreeWidgetItem( QStringList( celabel ), ii );
671  twi_trip->addChild( twi_edit );
672  }
673 
674  ddesc.tripknt = ndxt;
675  ddesc.tripndx = ndxt;
676  ddesc.editknt = ndxe;
677  ddesc.editndx = ndxe;
678  datamap[ cdescr ] = ddesc;
679  }
680 
681  tw_data->expandAll();
682  tw_data->resizeColumnToContents( 0 );
683  tw_data->resizeColumnToContents( 1 );
684  tw_data->resizeColumnToContents( 2 );
685  tw_data->collapseAll();
686  tw_data->setSortingEnabled( true );
687  tw_data->sortByColumn( 0, Qt::AscendingOrder ); // Insure triples in order
688  tw_data->sortByColumn( 1, Qt::DescendingOrder ); // Default latest-top order
689 
690  // Walk through entries backwards to propagate edit,triple counts
691  prlabel = "";
692  ptlabel = "";
693  ndxt = 1;
694  ndxe = 1;
695  ddescrs = datamap.values();
696 
697  for ( int ii = dlabels.size() - 1; ii >= 0; ii-- )
698  {
699  bool update = false;
700  QString cdescr = dlabels.at( ii );
701  DataDesc ddesc = ddescrs.at( ii );
702  QString crlabel = ddesc.runID;
703  QString ctlabel = ddesc.tripID;
704 
705  if ( crlabel != prlabel )
706  { // New run: get triple and edit count
707  ndxt = ddesc.tripknt;
708  ndxe = ddesc.editknt;
709  prlabel = crlabel;
710  ptlabel = "";
711  }
712 
713  else
714  { // Same run: update triple count
715  ddesc.tripknt = ndxt;
716  update = true;
717  }
718 
719  if ( ctlabel != ptlabel )
720  { // New triple: get edit count
721  ndxe = ddesc.editknt;
722  ptlabel = ctlabel;
723  }
724 
725  else
726  { // Same triple: update edit count
727  ddesc.editknt = ndxe;
728  update = true;
729  }
730 
731  if ( update )
732  { // One or other count has been updated
733  datamap[ cdescr ] = ddesc;
734  }
735  }
736  QApplication::restoreOverrideCursor();
737 }
738 
739 // Cancel button: no models returned
741 {
742  reject();
743  close();
744 }
745 
746 // Select button: fill in list tree for selected run
748 {
749  QList< QTreeWidgetItem* > selitems = tw_data->selectedItems();
750 
751  if ( selitems.size() < 1 )
752  { // "Show Edits" with no run selected: build full data tree
753  runID_sel = "";
754  te_notes->setText( tr( "Reading edit information to fully populate"
755  " the list data tree..." ) );
756  }
757 
758  else
759  { // "Show Edits" with run selected: build a data tree for the selected run
760  QTreeWidgetItem* twi = selitems[ 0 ];
761 
762  while ( twi->parent() != NULL )
763  twi = twi->parent();
764 
765  runID_sel = twi->text( 0 );
766  te_notes->setText( tr( "Reading edit information for run \"%1\",\n"
767  " to populate its list data tree..." )
768  .arg( runID_sel ) );
769  }
770 
771  qApp->processEvents();
772  sel_run = true;
773 
774  list_data();
775 }
776 
777 // Accept button: set up to return data information
779 {
780  QList< QTreeWidgetItem* > selitems = tw_data->selectedItems();
781  QList< DataDesc > ddescrs = datamap.values();
782 
783  if ( selitems.size() == 0 )
784  {
785  QMessageBox::information( this,
786  tr( "No Data Selected" ),
787  tr( "You have not selected any data.\nSelect+Load or Cancel" ) );
788  return;
789  }
790 
791  if ( load_edit() )
792  {
793  describe();
794  accept(); // Signal that selection was accepted
795  close();
796  }
797 }
798 
799 // Scan database for edit sets
801 {
802 qDebug() << "ScDB:TM:00: " << QTime::currentTime().toString("hh:mm:ss:zzzz");
803  US_Passwd pw;
804  US_DB2 db( pw.getPasswd() );
805 
806  if ( db.lastErrno() != US_DB2::OK )
807  {
808  QMessageBox::information( this,
809  tr( "DB Connection Problem" ),
810  tr( "There was an error connecting to the database:\n" )
811  + db.lastError() );
812  return;
813  }
814 
815  bool tfilter = ( etype_filt != "none" ); // Type filtering?
816  bool rfilter = ( ! runID_sel.isEmpty() ); // Run filtering?
817  QString tempdir = US_Settings::tmpDir() + "/";
818  QDir dir;
819  if ( ! dir.exists( tempdir ) )
820  dir.mkpath( tempdir );
821  QStringList query;
822  QStringList edtIDs;
823  QString invID = QString::number( US_Settings::us_inv_ID() );
824 
825  setWindowTitle( tr( "Load Edited Data from DB" ) );
826 
827  // Accumulate a map of AUC filenames and IDs
828  QMap< QString, QString > aucIDs;
829 qDebug() << "ScDB:TM:01: " << QTime::currentTime().toString("hh:mm:ss:zzzz");
830  query.clear();
831 
832  if ( rfilter )
833  query << "get_raw_desc_by_runID" << invID << runID_sel;
834  else
835  query << "get_rawData_desc" << invID;
836 
837  db.query( query );
838 qDebug() << "ScDB:TM:02: " << QTime::currentTime().toString("hh:mm:ss:zzzz");
839 
840  while( db.next() )
841  { // Accumulate a mapping of AUC Filename to DB ID
842  QString rLabel = db.value( 1 ).toString();
843  QString aFname = db.value( 2 ).toString();
844  QString aucID = db.value( 0 ).toString();
845  QString expID = db.value( 3 ).toString();
846  QString aucGUID = db.value( 7 ).toString();
847  aucIDs[ aFname ] = aucID + "^" + aucGUID + "^" + expID + "^" + rLabel;
848 //qDebug() << "ScDB: aucIDs" << aucIDs[aFname] << "aF" << aFname;
849  }
850 
851 qDebug() << "ScDB:TM:03: " << QTime::currentTime().toString("hh:mm:ss:zzzz");
852  QStringList editpars;
853  query.clear();
854 
855  if ( rfilter )
856  query << "get_edit_desc_by_runID" << invID << runID_sel;
857  else
858  query << "all_editedDataIDs" << invID;
859 
860  db.query( query );
861 qDebug() << "ScDB:TM:04: " << QTime::currentTime().toString("hh:mm:ss:zzzz");
862 qDebug() << "ScDB: tfilter etype_filt" << tfilter << etype_filt;
863 
864  // Edit record parameters from the DB are first accumulated,
865  // since we may need to download the content blob for some entries (MWL)
866  while ( db.next() )
867  { // Accumulate edit record parameters from DB
868  QString etype = db.value( 8 ).toString().toLower();
869 
870  if ( tfilter && etype != etype_filt )
871  continue;
872 
873  QString recID = db.value( 0 ).toString();
874  QString descrip = db.value( 1 ).toString();
875  QString filename = db.value( 2 ).toString().replace( "\\", "/" );
876  QString filebase = filename.section( "/", -1, -1 );
877  QString runID = descrip.isEmpty() ? filebase.section( ".", 0, -7 )
878  : descrip;
879  QString parID = db.value( 3 ).toString();
880  QString date = US_Util::toUTCDatetimeText( db.value( 5 )
881  .toDateTime().toString( Qt::ISODate ), true );
882  QString cksum = db.value( 6 ).toString();
883  QString recsize = db.value( 7 ).toString();
884  QString recGUID = db.value( 9 ).toString();
885 
886  edtIDs << recID;
887  editpars << descrip;
888  editpars << filename;
889  editpars << parID;
890  editpars << date;
891  editpars << recGUID;
892  editpars << cksum + " " + recsize;
893  }
894 qDebug() << "ScDB:TM:05: " << QTime::currentTime().toString("hh:mm:ss:zzzz");
895 
896  // Now loop through the list of edit entries, building description records
897  int nedit = edtIDs.size();
898 qDebug() << "ScDB: nedit" << nedit;
899  int kp = 0;
900  for ( int ii = 0; ii < nedit; ii++ )
901  {
902  QString recID = edtIDs[ ii ];
903  int idRec = recID.toInt();
904 //qDebug() << "ScDB:TM:03: " << QTime::currentTime().toString("hh:mm:ss:zzzz");
905  QString descrip = editpars[ kp++ ];
906  QString filename = editpars[ kp++ ];
907  QString parID = editpars[ kp++ ];
908  QString date = editpars[ kp++ ];
909  QString recGUID = editpars[ kp++ ];
910  QString echeck = editpars[ kp++ ];
911 
912  QString filebase = filename.section( "/", -1, -1 );
913  QString runID = descrip.isEmpty() ? filebase.section( ".", 0, -7 )
914  : descrip;
915  QString editID = filebase.section( ".", -6, -6 );
916  QString dataType = filebase.section( ".", -5, -5 );
917  QString tripID = filebase.section( ".", -4, -2 );
918  QString edtlamb = tripID .section( ".", 2, 2 );
919  QString aucfname = runID + "." + dataType + "." + tripID + ".auc";
920  bool isMwl = edtlamb.contains( "-" );
921  int idAUC = aucIDs[ aucfname ].section( "^", 0, 0 ).toInt();
922  QString aucGUID = aucIDs[ aucfname ].section( "^", 1, 1 );
923  int idExp = aucIDs[ aucfname ].section( "^", 2, 2 ).toInt();
924  QString elabel = aucIDs[ aucfname ].section( "^", 3, 3 );
925  QString acheck = aucIDs[ aucfname ].section( "^", 4, 4 ).simplified();
926  if ( isMwl )
927  {
928  idAUC = 0;
929  idExp = 0;
930  }
931 //qDebug() << "ScDB: isMwl idAUC" << isMwl << idAUC << "aucfname" << aucfname;
932 
933 //qDebug() << "ScDB:TM:04: " << QTime::currentTime().toString("hh:mm:ss:zzzz");
934  QString label = runID;
935  descrip = runID + "." + tripID + "." + editID;
936  QString baselabl = label;
937 
938  ddesc.runID = runID;
939  ddesc.tripID = tripID;
940  ddesc.editID = editID;
941  ddesc.label = label;
942  ddesc.descript = descrip;
943  ddesc.filename = filename;
944  ddesc.dataGUID = recGUID;
945  ddesc.aucGUID = aucGUID;
946  ddesc.DB_id = idRec;
947  ddesc.elabel = elabel;
948  ddesc.exp_id = idExp;
949  ddesc.auc_id = idAUC;
950  ddesc.date = date;
951  ddesc.acheck = acheck;
952  ddesc.echeck = echeck;
953  ddesc.tripknt = 1;
954  ddesc.tripndx = 1;
955  ddesc.editknt = 1;
956  ddesc.editndx = 1;
957  ddesc.isEdit = true;
959 
960  if ( isMwl )
961  { // For MWL we must generate multiple entries for a Cell/Channel edit
962  QString edtfname = runID + "." + dataType + "." + tripID + ".xml";
963  QString edtpath = tempdir + "/" + edtfname;
964 
965  // Read the XML contents from the edit DB record
966  db.readBlobFromDB( edtpath, "download_editData", idRec );
967  qApp->processEvents();
968  QString elambda;
969 
970  // Open the temporary file and parse Lambdas from the XML
971  QFile filei( edtpath );
972 
973  if ( ! filei.open( QIODevice::ReadOnly | QIODevice::Text ) )
974  continue;
975  QStringList mwlambds;
976  QXmlStreamReader xml( &filei );
977  QXmlStreamAttributes attr;
978  QString recGUID;
979  QString parGUID;
980  QString expType;
981 
982  while( ! xml.atEnd() )
983  { // Build up a string list of Lambdas
984  xml.readNext();
985 
986  if ( xml.isStartElement() && xml.name() == "lambda" )
987  {
988  attr = xml.attributes();
989  elambda = attr.value( "value" ).toString();
990  mwlambds << elambda;
991  }
992 
993  else if ( xml.isEndElement() && xml.name() == "lambdas" )
994  break;
995  }
996 
997  filei.close();
998  filei.remove();
999 
1000  QString otripID = tripID;
1001  QString odescrip = descrip;
1002  QString aucEntr;
1003  int tripknt = mwlambds.size();
1004 
1005  for ( int ii = 0; ii < tripknt; ii++ )
1006  { // Add an entry for each Lambda in the edit
1007  elambda = mwlambds[ ii ];
1008  tripID = QString( otripID ).replace( edtlamb, elambda );
1009  descrip = QString( odescrip ).replace( otripID, tripID );
1010  aucfname = runID + "." + dataType + "." + tripID + ".auc";
1011  aucEntr = aucIDs[ aucfname ];
1012  idAUC = aucEntr.section( "^", 0, 0 ).toInt();
1013  parGUID = aucEntr.section( "^", 1, 1 );
1014  idExp = aucEntr.section( "^", 2, 2 ).toInt();
1015 
1016  ddesc.tripID = tripID;
1017  ddesc.editID = editID + "@" + elambda;
1018  ddesc.descript = descrip;
1019  ddesc.aucGUID = parGUID;
1020  ddesc.exp_id = idExp;
1021  ddesc.auc_id = idAUC;
1022  ddesc.tripknt = tripknt;
1023  ddesc.tripndx = ii + 1;
1024  datamap[ descrip ] = ddesc;
1025  }
1026  } // END: isMwl=true
1027 
1028  else
1029  datamap[ descrip ] = ddesc;
1030 //qDebug() << "ScDB:TM:06: " << QTime::currentTime().toString("hh:mm:ss:zzzz");
1031 //qDebug() << "ScDB: descrip" << descrip;
1032  } // END: loop to read DB edit records
1033 qDebug() << "ScDB:TM:08: " << QTime::currentTime().toString("hh:mm:ss:zzzz");
1034 
1035  if ( latest )
1036  pare_to_latest();
1037 qDebug() << "ScDB:TM:09: " << QTime::currentTime().toString("hh:mm:ss:zzzz");
1038 }
1039 
1040 // Scan local disk for edit sets
1042 {
1043  setWindowTitle( tr( "Load Edited Data from Local Disk" ) );
1044 
1045  bool tfilter = ( etype_filt != "none" );
1046  bool rfilter = ( ! runID_sel.isEmpty() );
1047  QString rdir = US_Settings::resultDir();
1048  QStringList aucdirs = QDir( rdir ).entryList(
1049  QDir::AllDirs | QDir::NoDotAndDotDot, QDir::Name );
1050 
1051  QStringList aucfilt( "*.auc" );
1052  QStringList edtfilt;
1053  QString elabel;
1054  QString expID;
1055 
1056  for ( int ii = 0; ii < aucdirs.size(); ii++ )
1057  {
1058  QString subdir = rdir + "/" + aucdirs.at( ii );
1059  QStringList aucfiles = QDir( subdir ).entryList(
1060  aucfilt, QDir::Files, QDir::Name );
1061 
1062  if ( aucfiles.size() < 1 )
1063  continue;
1064 
1065  QString aucfbase = aucfiles.at( 0 );
1066  QString aucfname = subdir + "/" + aucfbase;
1067  QString runID = aucfbase.section( ".", 0, -6 );
1068 
1069  if ( rfilter && runID != runID_sel )
1070  continue;
1071 
1072  experiment_info( subdir, elabel, expID );
1073 
1074  QString subType = aucfbase.section( ".", -5, -5 );
1075  QString tripl = aucfbase.section( ".", -4, -2 );
1076  QString auclamb = tripl .section( ".", 2, 2 );
1077 
1078  edtfilt.clear();
1079  edtfilt << runID + ".*." + subType + ".*.xml";
1080  QStringList edtfiles = QDir( subdir ).entryList(
1081  edtfilt, QDir::Files, QDir::Name );
1082  edtfiles.sort();
1083 
1084  if ( edtfiles.size() < 1 )
1085  continue;
1086 
1087  for ( int jj = 0; jj < edtfiles.size(); jj++ )
1088  {
1089  QStringList mwlambds;
1090  QString filebase = edtfiles.at( jj );
1091  QString filename = subdir + "/" + filebase;
1092  QString runID = filebase.section( ".", 0, -7 );
1093  QString editID = filebase.section( ".", -6, -6 );
1094  editID = ( editID.length() == 12 && editID.startsWith( "20" ) ) ?
1095  editID.mid( 2 ) : editID;
1096  QString tripID = filebase.section( ".", -4, -2 );
1097  QString edtlamb = tripID .section( ".", 2, 2 );
1098  QString label = runID;
1099  QString descrip = runID + "." + tripID + "." + editID;
1100  QString baselabl = label;
1101 
1102  QFile filei( filename );
1103 
1104  if ( ! filei.open( QIODevice::ReadOnly | QIODevice::Text ) )
1105  continue;
1106 
1107  QString date = US_Util::toUTCDatetimeText( QFileInfo( filename )
1108  .lastModified().toUTC().toString( Qt::ISODate ), true );
1109 
1110  QXmlStreamReader xml( &filei );
1111  QXmlStreamAttributes a;
1112  QString recGUID;
1113  QString parGUID;
1114  QString expType;
1115  QString elambda;
1116  bool isMwl = edtlamb.contains( "-" );
1117 
1118  while( ! xml.atEnd() )
1119  {
1120  xml.readNext();
1121 
1122  if ( xml.isStartElement() )
1123  {
1124  if ( xml.name() == "editGUID" )
1125  {
1126  a = xml.attributes();
1127  recGUID = a.value( "value" ).toString();
1128  }
1129 
1130  else if ( xml.name() == "rawDataGUID" )
1131  {
1132  a = xml.attributes();
1133  parGUID = a.value( "value" ).toString();
1134  }
1135 
1136  else if ( xml.name() == "experiment" )
1137  {
1138  a = xml.attributes();
1139  expType = a.value( "type" ).toString().toLower();
1140  }
1141 
1142  if ( isMwl && xml.name() == "lambda" )
1143  {
1144  a = xml.attributes();
1145  elambda = a.value( "value" ).toString();
1146  mwlambds << elambda;
1147 //qDebug() << "DLdr: elambda" << elambda;
1148  }
1149  }
1150  }
1151 
1152  filei.close();
1153 
1154  // If type filtering, ignore runIDs that do not match experiment type
1155  if ( tfilter && expType != etype_filt )
1156  continue;
1157 
1158  ddesc.runID = runID;
1159  ddesc.tripID = tripID;
1160  ddesc.editID = editID;
1161  ddesc.label = label;
1162  ddesc.descript = descrip;
1163  ddesc.filename = filename;
1164  ddesc.dataGUID = recGUID;
1165  ddesc.aucGUID = parGUID;
1166  ddesc.elabel = elabel;
1167  ddesc.DB_id = -1;
1168  ddesc.exp_id = expID.toInt();
1169  ddesc.auc_id = -1;
1170  ddesc.date = date;
1171  ddesc.acheck = US_Util::md5sum_file( filename );
1172  ddesc.tripknt = 1;
1173  ddesc.tripndx = 1;
1174  ddesc.editknt = 1;
1175  ddesc.editndx = 1;
1176  ddesc.isEdit = true;
1177  ddesc.isLatest = latest;
1178 
1179  if ( isMwl )
1180  {
1181  QString otripID = tripID;
1182  QString odescrip = descrip;
1183  int tripknt = mwlambds.size();
1184 
1185  for ( int ii = 0; ii < tripknt; ii++ )
1186  {
1187  elambda = mwlambds[ ii ];
1188  tripID = QString( otripID ).replace( edtlamb, elambda );
1189  descrip = QString( odescrip ).replace( otripID, tripID );
1190  ddesc.tripID = tripID;
1191  ddesc.editID = editID + "@" + elambda;
1192  ddesc.descript = descrip;
1193  ddesc.tripknt = tripknt;
1194  ddesc.tripndx = ii + 1;
1195  datamap[ descrip ] = ddesc;
1196  }
1197  }
1198 
1199  else
1200  datamap[ descrip ] = ddesc;
1201  }
1202  }
1203 
1204  if ( latest )
1205  pare_to_latest();
1206 }
1207 
1208 // Scan database for runs
1210 {
1211 qDebug() << "ScDB:TM:00: " << QTime::currentTime().toString("hh:mm:ss:zzzz");
1212  US_Passwd pw;
1213  US_DB2 db( pw.getPasswd() );
1214 
1215  if ( db.lastErrno() != US_DB2::OK )
1216  {
1217  QMessageBox::information( this,
1218  tr( "DB Connection Problem" ),
1219  tr( "There was an error connecting to the database:\n" )
1220  + db.lastError() );
1221  return;
1222  }
1223 
1224  QStringList query;
1225  QString invID = QString::number( US_Settings::us_inv_ID() );
1226 
1227  setWindowTitle( tr( "Load Run Data from DB" ) );
1228 
1229  // Accumulate a map of runs to dates,IDs,labels
1230  QMap< QString, QString > runinfo;
1231 qDebug() << "ScDB:TM:01: " << QTime::currentTime().toString("hh:mm:ss:zzzz");
1232  query.clear();
1233  query << "get_experiment_desc" << invID;
1234  db.query( query );
1235 qDebug() << "ScDB:TM:02: " << QTime::currentTime().toString("hh:mm:ss:zzzz");
1236  ddesc.tripID = "undetermined"; // Dummy edit description settings
1237  ddesc.editID = "undetermined";
1238  ddesc.filename = "undetermined";
1239  ddesc.dataGUID = "undetermined";
1240  ddesc.aucGUID = "undetermined";
1241  ddesc.acheck = "";
1242  ddesc.auc_id = -1;
1243  ddesc.tripknt = 1;
1244  ddesc.tripndx = 1;
1245  ddesc.editknt = 1;
1246  ddesc.editndx = 1;
1247  ddesc.isEdit = false;
1248  ddesc.isLatest = latest;
1249 
1250  while( db.next() )
1251  { // Accumulate a mapping of data descriptions to runs
1252  QString expID = db.value( 0 ).toString();
1253  QString runID = db.value( 1 ).toString();
1254  QString label = db.value( 4 ).toString();
1255  QString date = US_Util::toUTCDatetimeText( db.value( 5 )
1256  .toDateTime().toString( Qt::ISODate ), true );
1257 
1258  ddesc.runID = runID;
1259  ddesc.label = label;
1260  ddesc.descript = label;
1261  ddesc.elabel = label;
1262  ddesc.exp_id = expID.toInt();
1263  ddesc.DB_id = ddesc.exp_id;
1264  ddesc.date = date;
1265 
1266  datamap[ runID ] = ddesc;
1267  }
1268 
1269 qDebug() << "ScDB:TM:09: " << QTime::currentTime().toString("hh:mm:ss:zzzz");
1270 }
1271 
1272 // Scan local disk for runs
1274 {
1275  setWindowTitle( tr( "Load Run Data from Local Disk" ) );
1276 
1277  bool tfilter = ( etype_filt != "none" );
1278  QString rdir = US_Settings::resultDir();
1279  QStringList aucdirs = QDir( rdir ).entryList(
1280  QDir::AllDirs | QDir::NoDotAndDotDot, QDir::Name );
1281 
1282  QStringList aucfilt( "*.auc" );
1283  QStringList edtfilt;
1284  QString elabel;
1285  QString expID;
1286 
1287  ddesc.tripID = "undetermined"; // Dummy edit description settings
1288  ddesc.editID = "undetermined";
1289  ddesc.filename = "undetermined";
1290  ddesc.dataGUID = "undetermined";
1291  ddesc.aucGUID = "undetermined";
1292  ddesc.acheck = "";
1293  ddesc.DB_id = -1;
1294  ddesc.auc_id = -1;
1295  ddesc.tripknt = 1;
1296  ddesc.tripndx = 1;
1297  ddesc.editknt = 1;
1298  ddesc.editndx = 1;
1299  ddesc.isEdit = false;
1300  ddesc.isLatest = latest;
1301 
1302  for ( int ii = 0; ii < aucdirs.size(); ii++ )
1303  {
1304  QString subdir = rdir + "/" + aucdirs.at( ii );
1305  QStringList aucfiles = QDir( subdir ).entryList(
1306  aucfilt, QDir::Files, QDir::Name );
1307 
1308  if ( aucfiles.size() < 1 )
1309  continue;
1310 
1311  experiment_info( subdir, elabel, expID );
1312 
1313  QString aucfbase = aucfiles.at( 0 );
1314  QString aucfname = subdir + "/" + aucfbase;
1315  QString runID = aucfbase.section( ".", 0, -6 );
1316  QString subType = aucfbase.section( ".", -5, -5 );
1317  QString tripl = aucfbase.section( ".", -4, -2 );
1318  QString auclamb = tripl .section( ".", 2, 2 );
1319 
1320  edtfilt.clear();
1321  edtfilt << runID + ".*." + subType + ".*.xml";
1322  QStringList edtfiles = QDir( subdir ).entryList(
1323  edtfilt, QDir::Files, QDir::Name );
1324  edtfiles.sort();
1325 
1326  if ( edtfiles.size() < 1 )
1327  continue;
1328 
1329  QStringList mwlambds;
1330  QString filebase = edtfiles.at( 0 );
1331  QString filename = subdir + "/" + filebase;
1332  QString editID = filebase.section( ".", -6, -6 );
1333  editID = ( editID.length() == 12 && editID.startsWith( "20" ) ) ?
1334  editID.mid( 2 ) : editID;
1335  QString tripID = filebase.section( ".", -4, -2 );
1336  QString edtlamb = tripID .section( ".", 2, 2 );
1337  QString label = runID;
1338  QString descrip = runID + "." + tripID + "." + editID;
1339  QString baselabl = label;
1340 
1341  QFile filei( filename );
1342 
1343  if ( ! filei.open( QIODevice::ReadOnly | QIODevice::Text ) )
1344  continue;
1345 
1346  QString date = US_Util::toUTCDatetimeText( QFileInfo( filename )
1347  .lastModified().toUTC().toString( Qt::ISODate ), true );
1348 
1349  QXmlStreamReader xml( &filei );
1350  QXmlStreamAttributes a;
1351  QString recGUID;
1352  QString parGUID;
1353  QString expType;
1354  QString elambda;
1355  bool isMwl = edtlamb.contains( "-" );
1356 
1357  while( ! xml.atEnd() )
1358  {
1359  xml.readNext();
1360 
1361  if ( xml.isStartElement() )
1362  {
1363  if ( xml.name() == "editGUID" )
1364  {
1365  a = xml.attributes();
1366  recGUID = a.value( "value" ).toString();
1367  }
1368 
1369  else if ( xml.name() == "rawDataGUID" )
1370  {
1371  a = xml.attributes();
1372  parGUID = a.value( "value" ).toString();
1373  }
1374 
1375  else if ( xml.name() == "experiment" )
1376  {
1377  a = xml.attributes();
1378  expType = a.value( "type" ).toString().toLower();
1379  }
1380 
1381  if ( isMwl && xml.name() == "lambda" )
1382  {
1383  a = xml.attributes();
1384  elambda = a.value( "value" ).toString();
1385  mwlambds << elambda;
1386 //qDebug() << "DLdr: elambda" << elambda;
1387  }
1388  }
1389  }
1390 
1391  filei.close();
1392 
1393  // If type filtering, ignore runIDs that do not match experiment type
1394  if ( tfilter && expType != etype_filt )
1395  continue;
1396 
1397  ddesc.runID = runID;
1398  ddesc.label = label;
1399  ddesc.descript = descrip;
1400  ddesc.aucGUID = parGUID;
1401  ddesc.elabel = elabel;
1402  ddesc.exp_id = expID.toInt();
1403  ddesc.date = date;
1404 
1405  datamap[ descrip ] = ddesc;
1406  }
1407 }
1408 
1409 // Pare down data description map to only latest edit
1411 {
1412  int kmwl = 0;
1413 
1414  for ( int kk = 0; kk < 2; kk++ ) // May need two passes to pare down
1415  {
1416  QStringList keys = datamap.keys();
1417  QList< DataDesc > vals = datamap.values();
1418  int kchg = 0;
1419 
1420  for ( int ii = 0; ii < keys.size() - 1; ii++ )
1421  {
1422  int jj = ii + 1;
1423 
1424  QString clabel = keys.at( ii );
1425  QString flabel = keys.at( jj );
1426 
1427  QString crunid = clabel.section( ".", 0, -2 );
1428  QString frunid = flabel.section( ".", 0, -2 );
1429 
1430  if ( crunid != frunid )
1431  { // Likely difference in runid, but check for MWL
1432  QString cruncc = clabel.section( ".", 0, -3 );
1433  QString fruncc = flabel.section( ".", 0, -3 );
1434 
1435  if ( cruncc == fruncc )
1436  kmwl++; // Mark possible MWL case
1437 
1438  continue;
1439  }
1440 
1441  // This record's label differs from next only by edit code: remove it
1442  QString cdtxt = vals.at( ii ).date;
1443  QString fdtxt = vals.at( jj ).date;
1444  QDateTime cdate = QDateTime::fromString( cdtxt, Qt::ISODate );
1445  QDateTime fdate = QDateTime::fromString( fdtxt, Qt::ISODate );
1446 //qDebug() << "PARE ii" << ii << "C,F date" << cdtxt << fdtxt;
1447 //qDebug() << " C,F lab" << clabel << flabel;
1448 //qDebug() << " (C<=F)" << (cdate<=fdate) << " C,F dt" << cdate << fdate;
1449 
1450  if ( cdate <= fdate ) // Remove the earlier of the two
1451  {
1452  datamap.remove( clabel ); // Earlier is earlier in list
1453  }
1454 
1455  else
1456  {
1457  datamap.remove( flabel ); // Earlier is later in list
1458  kchg++; // Mark when early one later in list
1459  }
1460  }
1461 
1462 //qDebug() << "PARE kchg" << kchg << "kk" << kk;
1463  if ( kchg == 0 ) break; // We're done
1464 
1465  // Need to repeat above when any removed was later in list
1466  }
1467 
1468  if ( kmwl > 0 )
1469  pare_latest_mwl(); // More possible paring for MWL
1470 }
1471 
1472 // Pare down data description map to only latest edit of MWL RunIDs
1474 {
1475  QStringList keys = datamap.keys();
1476  QList< DataDesc > vals = datamap.values();
1477  QStringList mwruns;
1478  QStringList mwedts;
1479  QStringList mwrmvs;
1480 
1481  // First accumulate Runs and Edits for any MWL entries
1482  for ( int ii = 0; ii < keys.size(); ii++ )
1483  {
1484  QString fname = vals.at( ii ).filename;
1485  QString cwavln = fname.section( ".", -2, -2 );
1486 
1487  if ( ! cwavln.contains( "-" ) )
1488  continue; // Skip if not MWL
1489 
1490  QString cedit = fname.section( ".", 0, -6 );
1491  QString crunid = cedit.section( ".", 0, -2 );
1492 
1493  if ( ! mwruns.contains( crunid ) )
1494  mwruns << crunid;
1495 
1496  if ( ! mwedts.contains( cedit ) )
1497  mwedts << cedit;
1498  }
1499 
1500  // Go no further if there were less than 2 MWL edits
1501  // or if the MWL edits count equals the MWL run count
1502  if ( mwedts.count() < 2 || mwedts.count() == mwruns.count() )
1503  return;
1504 
1505  // Now accumulate a list of earlier edits to remove
1506  mwruns.sort(); // Insure sorted list
1507  QString prevedt = mwedts[ 0 ];
1508  QString prevrun = prevedt.section( ".", 0, -2 );
1509 
1510  for ( int ii = 1; ii < mwedts.count(); ii++ )
1511  {
1512  QString curredt = mwedts[ ii ];
1513  QString currrun = curredt.section( ".", 0, -2 );
1514 
1515  if ( currrun == prevrun )
1516  { // If runs are the same, list the earlier edit
1517  mwrmvs << curredt;
1518  }
1519 
1520  prevedt = curredt;
1521  prevrun = currrun;
1522  }
1523 
1524  // Finally, remove any in overall list that are marked for delete
1525  for ( int ii = 0; ii < keys.size(); ii++ )
1526  {
1527  QString fname = vals.at( ii ).filename;
1528  QString cwavln = fname.section( ".", -2, -2 );
1529 
1530  if ( ! cwavln.contains( "-" ) )
1531  continue; // Skip if not MWL
1532 
1533  QString cedit = fname.section( ".", 0, -6 );
1534 
1535  if ( mwrmvs.contains( cedit ) )
1536  { // Remove an entry found in remove list
1537  QString clabel = keys.at( ii );
1538  datamap.remove( clabel );
1539  }
1540  }
1541 }
1542 
1543 // Filter events to catch right-mouse-button-click on list widget
1544 bool US_DataLoader::eventFilter( QObject* obj, QEvent* e )
1545 {
1546  if ( obj == tw_data &&
1547  e->type() == QEvent::ContextMenu )
1548  {
1549  QPoint mpos = ((QContextMenuEvent*)e)->pos();
1550 
1551  show_data_info( mpos );
1552 
1553  return false;
1554  }
1555  else
1556  { // Pass all other events to normal handler
1557  return US_WidgetsDialog::eventFilter( obj, e );
1558  }
1559 }
1560 
1561 // Show selected-data information in text dialog
1563 {
1564  QList< QTreeWidgetItem* > selitems = tw_data->selectedItems();
1565 
1566  QTreeWidgetItem* item = selitems.size() > 0 ? selitems.at( 0 )
1567  : tw_data->itemAt( pos );
1568  int keyndx = item->type();
1569 
1570  ddesc = datamap.values()[ keyndx ];
1571 
1572  QString label = ddesc.label;
1573  QString descript = ddesc.descript;
1574  QString dbID = QString::number( ddesc.DB_id );
1575  QString aucID = QString::number( ddesc.auc_id );
1576  QString expID = QString::number( ddesc.exp_id );
1577  QString filename = ddesc.filename;
1578  QString filespec = filename;
1579 
1580  if ( ddesc.DB_id < 0 )
1581  { // Local disk: separate name and directory
1582  filespec = filename.section( "/", -1, -1 )
1583  + tr( "\n File Directory: " )
1584  + filename.section( "/", 0, -2 );
1585  }
1586 
1587  QString dtext = tr( "Data Information:" )
1588  + tr( "\n Label: " ) + label
1589  + tr( "\n Description: " ) + descript
1590  + tr( "\n Edit Database ID: " ) + dbID
1591  + tr( "\n Filename: " ) + filespec
1592  + tr( "\n Last Updated: " ) + ddesc.date
1593  + tr( "\n Edit Global ID: " ) + ddesc.dataGUID
1594  + tr( "\n AUC Global ID: " ) + ddesc.aucGUID
1595  + tr( "\n AUC DB ID: " ) + aucID
1596  + tr( "\n Experiment DB ID: " ) + expID
1597  + tr( "\n Experiment Label: " ) + ddesc.elabel
1598  + tr( "\n Run ID: " ) + ddesc.runID
1599  + tr( "\n Triple ID: " ) + ddesc.tripID
1600  + tr( "\n Edit ID: " ) + ddesc.editID
1601  + tr( "\n Triples per Run: " ) + QString::number( ddesc.tripknt )
1602  + tr( "\n Triple Index: " ) + QString::number( ddesc.tripndx )
1603  + tr( "\n Edits per Triple: " ) + QString::number( ddesc.editknt )
1604  + tr( "\n Edit Index: " ) + QString::number( ddesc.editndx )
1605  + "";
1606 
1607  // Open a dialog and display model information
1608  US_Editor* edit = new US_Editor( US_Editor::LOAD, true, "", this );
1609  edit->setWindowTitle( tr( "Data Information" ) );
1610  edit->move( this->pos() + pos + QPoint( 100, 100 ) );
1611  edit->resize( 700, 350 );
1612  edit->e->setFont( QFont( US_Widgets::fixedFont().family(),
1614  edit->e->setText( dtext );
1615  edit->show();
1616 }
1617 
1618 // Slot to update disk/db selection
1620 {
1621  emit changed( db );
1622 
1623  le_dfilter->disconnect();
1624  le_dfilter->clear();
1625  connect( le_dfilter, SIGNAL( textChanged( const QString& ) ),
1626  SLOT ( search ( const QString& ) ) );
1627  pb_invest->setEnabled( ( US_Settings::us_inv_level() > 0 ) && db );
1628 
1629  list_data();
1630 }
1631 
1632 // Internal utility to get local file experiment information (label,id)
1633 void US_DataLoader::experiment_info( QString& rundir, QString& elabel,
1634  QString& expID )
1635 {
1636  elabel = "";
1637  expID = "-1";
1638 
1639  rundir.replace( "\\", "/" );
1640  if ( QString( rundir ).right( 1 ) != "/" )
1641  rundir += "/";
1642 
1643  QString runID = QString( rundir ).section( "/", -2, -2 );
1644  QStringList ffilt( runID + ".??.xml" );
1645  QStringList efiles = QDir( rundir ).entryList( ffilt, QDir::Files,
1646  QDir::Name );
1647  if ( efiles.size() != 1 )
1648  return;
1649 
1650  QString fname = efiles[ 0 ];
1651  QString fpath = rundir + efiles[ 0 ];
1652  QFile filei( fpath );
1653 
1654  if ( ! filei.open( QIODevice::ReadOnly | QIODevice::Text ) )
1655  return;
1656 
1657  QXmlStreamReader xml( &filei );
1658 
1659  while( ! xml.atEnd() )
1660  {
1661  xml.readNext();
1662 
1663  if ( xml.isStartElement() )
1664  {
1665  if ( xml.name() == "experiment" )
1666  {
1667  QXmlStreamAttributes atts = xml.attributes();
1668  expID = atts.value( "id" ).toString();
1669  }
1670 
1671  else if ( xml.name() == "label" )
1672  {
1673  xml.readNext();
1674  elabel = xml.text().toString();
1675  }
1676  }
1677  }
1678 
1679  filei.close();
1680  return;
1681 }
1682