UltraScan III
us_rotor.cpp
Go to the documentation of this file.
1 
3 #include "us_rotor.h"
4 #include "us_settings.h"
5 #include "us_util.h"
6 #include "us_db2.h"
7 
8 // The constructor clears out the data structure
10 {
11 }
12 
13 // A function to read information about all labs
15  QVector< US_Rotor::Lab >& labList, US_DB2* db )
16 {
17  QStringList q( "get_lab_names" );
18  db->query( q );
19 
20  QStringList labIDs;
21  while ( db->next() )
22  labIDs << db->value( 0 ).toString();
23 
24  if ( labIDs.size() == 0 )
25  return NOT_FOUND;
26 
27  // Save information about all the labs
28  labList.clear();
29  for ( int i = 0; i < labIDs.size(); i++ )
30  {
31  US_Rotor::Lab lab;
32 
33  lab.readDB( labIDs[ i ].toInt(), db );
34  labList.push_back( lab );
35  }
36 
37  // Since we're not really editing labs, let's just copy
38  // the information to disk directly
39  saveLabsDisk( labList );
40 
41  return ROTOR_OK;
42 }
43 
44 // Function to save abstract rotor information to disk
45 void US_Rotor::saveLabsDisk( QVector< US_Rotor::Lab >& labList )
46 {
47  // Currently labs.xml is in with the rotors
48  QString path;
49  if ( ! diskPath( path ) ) return;
50 
51  QString filename = path + "/labs.xml";
52 
53  QFile file( filename );
54  if ( !file.open( QIODevice::WriteOnly | QIODevice::Text) )
55  {
56  qDebug() << "Error: can't open file for writing"
57  << filename;
58  return;
59  }
60 
61  // Generate xml
62  QXmlStreamWriter xml;
63  xml.setDevice( &file );
64  xml.setAutoFormatting( true );
65 
66  xml.writeStartDocument();
67  xml.writeDTD("<!DOCTYPE US_Lab>");
68  xml.writeStartElement("LabData");
69  xml.writeAttribute("version", "1.0");
70 
71  // Loop through all the labs
72  for ( int i = 0; i < labList.size(); i++ )
73  {
74  US_Rotor::Lab lab = labList[ i ];
75 
76  xml.writeStartElement( "lab" );
77  xml.writeAttribute ( "id", QString::number( lab.ID ) );
78  xml.writeAttribute ( "guid", lab.GUID );
79  xml.writeAttribute ( "name", lab.name );
80  xml.writeAttribute ( "building", lab.building );
81  xml.writeAttribute ( "room", lab.room );
82 
83  foreach ( US_Rotor::Instrument instrument, lab.instruments )
84  {
85  xml.writeStartElement( "instrument" );
86  xml.writeAttribute ( "id", QString::number( instrument.ID ) );
87  xml.writeAttribute ( "name", instrument.name );
88  xml.writeAttribute ( "serial", instrument.serial );
89 
90  foreach( US_Rotor::Operator oper, instrument.operators )
91  {
92  xml.writeStartElement( "operator" );
93  xml.writeAttribute ( "id", QString::number( oper.ID ) );
94  xml.writeAttribute ( "guid", oper.GUID );
95  xml.writeAttribute ( "lname", oper.lname );
96  xml.writeAttribute ( "fname", oper.fname );
97  xml.writeEndElement (); // Operator
98  }
99 
100  xml.writeEndElement (); // Instrument
101  }
102 
103  xml.writeEndElement (); // Lab
104  }
105 
106  xml.writeEndElement (); // LabData
107  xml.writeEndDocument ();
108 
109  file.close();
110 }
111 
112 // Function to read all the lab info from disk
113 US_Rotor::Status US_Rotor::readLabsDisk( QVector< US_Rotor::Lab >& labList )
114 {
115  // Currently labs.xml is in with the rotors
116  // Make sure the rotors directory is there and has something in it
117  QString path;
118  if ( ! diskPath( path ) ) return US_Rotor::NOT_FOUND;
119 
120  QString labFilename = US_Settings::dataDir() + "/rotors/labs.xml";
121  QFile file( labFilename );
122 
123  if ( ! file.open( QIODevice::ReadOnly | QIODevice::Text ) )
124  {
125  // copy from etc
126  QString defaultFilename = US_Settings::appBaseDir() + "/etc/labs.xml";
127  QFile::copy( defaultFilename, labFilename );
128 
129  if ( ! file.open( QIODevice::ReadOnly | QIODevice::Text) )
130  {
131  qDebug() << "Error: Could not read lab file\n"
132  << labFilename;
133  return US_Rotor::NOT_FOUND;
134  }
135  }
136 
137  labList.clear();
138 
139  QXmlStreamReader xml( &file );
140 
141  while ( ! xml.atEnd() )
142  {
143  xml.readNext();
144 
145  if ( xml.isStartElement() )
146  {
147  if ( xml.name() == "lab" )
148  {
149  US_Rotor::Lab lab;
150 
151  QXmlStreamAttributes a = xml.attributes();
152  lab.ID = a.value( "id" ).toString().toInt();
153  lab.GUID = a.value( "guid" ).toString();
154  lab.name = a.value( "name" ).toString();
155  lab.building = a.value( "building" ).toString();
156  lab.room = a.value( "room" ).toString();
157  readInstrumentInfo( xml, lab );
158 
159  labList.push_back( lab );
160  }
161  }
162  }
163 
164  file.close();
165 
166  if ( xml.hasError() )
167  {
168  qDebug() << "Error: xml error: \n"
169  << xml.errorString();
170  return US_Rotor::MISC_ERROR;
171  }
172 
173  return US_Rotor::ROTOR_OK;
174 }
175 
176 void US_Rotor::readInstrumentInfo( QXmlStreamReader& xml, US_Rotor::Lab& lab )
177 {
178  while ( ! xml.atEnd() )
179  {
180  xml.readNext();
181 
182  if ( xml.isEndElement() && xml.name() == "lab" ) return;
183 
184  if ( xml.isStartElement() )
185  {
186  if ( xml.name() == "instrument" )
187  {
188  US_Rotor::Instrument instrument;
189 
190  QXmlStreamAttributes a = xml.attributes();
191  instrument.ID = a.value( "id" ).toString().toInt();
192  instrument.name = a.value( "name" ).toString();
193  instrument.serial = a.value( "serial" ).toString();
194 
195  readOperatorInfo( xml, instrument );
196  lab.instruments << instrument;
197  }
198  }
199  }
200 }
201 
202 void US_Rotor::readOperatorInfo( QXmlStreamReader& xml, US_Rotor::Instrument& instrument )
203 {
204  while ( ! xml.atEnd() )
205  {
206  xml.readNext();
207 
208  if ( xml.isEndElement() && xml.name() == "instrument" ) return;
209 
210  if ( xml.isStartElement() )
211  {
212  if ( xml.name() == "operator" )
213  {
214  US_Rotor::Operator oper;
215 
216  QXmlStreamAttributes a = xml.attributes();
217  oper.ID = a.value( "id" ).toString().toInt();
218  oper.GUID = a.value( "guid" ).toString();
219  oper.lname = a.value( "lname" ).toString();
220  oper.fname = a.value( "fname" ).toString();
221 
222  instrument.operators << oper;
223  }
224  }
225  }
226 }
227 
228 // A function to read information about all abstract rotors from DB
230  QVector< US_Rotor::AbstractRotor >& arList, US_DB2* db )
231 {
232  QStringList q( "get_abstractRotor_names" );
233  db->query( q );
234 
235  QStringList arIDs;
236  while ( db->next() )
237  arIDs << db->value( 0 ).toString();
238 
239  if ( arIDs.size() == 0 )
240  return NOT_FOUND;
241 
242  // Save information about all the abstract rotors
243  arList.clear();
244  for ( int i = 0; i < arIDs.size(); i++ )
245  {
247 
248  ar.readDB( arIDs[ i ].toInt(), db );
249  arList.push_back( ar );
250  }
251 
252  return ROTOR_OK;
253 }
254 
255 // Function to read all the abstract rotor info from disk
256 US_Rotor::Status US_Rotor::readAbstractRotorsDisk( QVector< US_Rotor::AbstractRotor >& arList )
257 {
258  QString filename = US_Settings::appBaseDir() + "/etc/rotors/abstractRotors.xml";
259  QFile file( filename );
260 
261  arList.clear();
262 
263  if ( ! file.open( QIODevice::ReadOnly | QIODevice::Text) )
264  {
265  qDebug() << "Error: Could not read abstract rotor file\n"
266  << filename;
267  return US_Rotor::NOT_FOUND;
268  }
269 
270  QXmlStreamReader xml( &file );
271 
272  while ( ! xml.atEnd() )
273  {
274  xml.readNext();
275 
276  if ( xml.isStartElement() )
277  {
278  if ( xml.name() == "abstractRotor" )
279  {
281 
282  QXmlStreamAttributes a = xml.attributes();
283  ar.ID = a.value( "id" ).toString().toInt();
284  ar.GUID = a.value( "guid" ).toString();
285  ar.name = a.value( "name" ).toString();
286  ar.material = a.value( "materialName" ).toString();
287  ar.numHoles = a.value( "numHoles" ).toString().toInt();
288  ar.maxRPM = a.value( "maxRPM" ).toString().toInt();
289  ar.magnetOffset = a.value( "magnetOffset" ).toString().toFloat();
290  ar.cellCenter = a.value( "cellCenter" ).toString().toFloat();
291  ar.manufacturer = a.value( "manufacturer" ).toString();
292 
293  arList.push_back( ar );
294  }
295  }
296  }
297 
298  file.close();
299 
300  if ( xml.hasError() )
301  {
302  qDebug() << "Error: xml error: \n"
303  << xml.errorString();
304  return US_Rotor::MISC_ERROR;
305  }
306 
307  return US_Rotor::ROTOR_OK;
308 }
309 
310 // A function to read rotor information concerning a single lab from disk
312  QVector< US_Rotor::Rotor >& rotors, int labID )
313 {
314  // Get the rotor files
315  QString path = US_Settings::dataDir() + "/rotors";
316 
317  rotors.clear();
318  if ( ! diskPath( path ) ) return( US_Rotor::NOT_FOUND );
319 
320  QDir dir( path );
321  QStringList filter( "R*.xml" );
322  QStringList names = dir.entryList( filter, QDir::Files, QDir::Name );
323 
324  for ( int i = 0; i < names.size(); i++ )
325  {
326  QFile file( path + "/" + names[ i ] );
327 
328  if ( ! file.open( QIODevice::ReadOnly | QIODevice::Text) )
329  {
330  qDebug() << "Error: Could not read rotor file\n"
331  << names[ i ];
332  continue;
333  }
334 
335  QXmlStreamReader xml( &file );
336 
337  while ( ! xml.atEnd() )
338  {
339  xml.readNext();
340 
341  if ( xml.isStartElement() )
342  {
343  if ( xml.name() == "Rotor" )
344  {
345  US_Rotor::Rotor r;
346  QXmlStreamAttributes a = xml.attributes();
347 
348  r.ID = a.value( "id" ).toString().toInt();
349  r.GUID = a.value( "guid" ).toString();
350  r.abstractRotorID = a.value( "abstractRotorID" ).toString().toInt();
351  r.abstractRotorGUID = a.value( "abstractRotorGUID" ).toString();
352  r.labID = a.value( "labID" ).toString().toInt();
353  r.name = a.value( "name" ).toString();
354  r.serialNumber = a.value( "serialNumber" ).toString();
355 
356  if ( r.labID == labID )
357  rotors.push_back( r );
358 
359  }
360  }
361  }
362 
363  file.close();
364 
365  if ( xml.hasError() )
366  {
367  qDebug() << "Error: xml error: \n"
368  << xml.errorString();
369  }
370 
371  }
372 
373  if ( rotors.size() == 0 )
374  return US_Rotor::NOT_FOUND;
375 
376  return US_Rotor::ROTOR_OK;
377 }
378 
379 // A function to read rotor calibration profile information about a single rotor from disk
381  QVector< US_Rotor::RotorCalibration >& profiles, int rotorID )
382 {
383  // Get the calibration files
384  QString path = US_Settings::dataDir() + "/rotors";
385 
386  profiles.clear();
387  if ( ! diskPath( path ) ) return( US_Rotor::NOT_FOUND );
388 
389  QDir dir( path );
390  QStringList filter( "C*.xml" );
391  QStringList names = dir.entryList( filter, QDir::Files, QDir::Name );
392 
393  for ( int i = 0; i < names.size(); i++ )
394  {
395  QFile file( path + "/" + names[ i ] );
396 
397  if ( ! file.open( QIODevice::ReadOnly | QIODevice::Text) )
398  {
399  qDebug() << "Error: Could not read rotor calibration file\n"
400  << names[ i ];
401  continue;
402  }
403 
404  QXmlStreamReader xml( &file );
406 
407  while ( ! xml.atEnd() )
408  {
409  xml.readNext();
410 
411  if ( xml.isStartElement() )
412  {
413  if ( xml.name() == "Calibration" )
414  {
415  QXmlStreamAttributes a = xml.attributes();
416 
417  rc.ID = a.value( "id" ).toString().toInt();
418  rc.GUID = a.value( "guid" ).toString();
419  rc.rotorID = a.value( "rotorID" ).toString().toInt();
420  rc.rotorGUID = a.value( "rotorGUID" ).toString();
421  rc.calibrationExperimentID = a.value( "calExpID" ).toString().toInt();
422  rc.calibrationExperimentGUID = a.value( "calExpGUID" ).toString();
423  rc.coeff1 = a.value( "coeff1" ).toString().toFloat();
424  rc.coeff2 = a.value( "coeff2" ).toString().toFloat();
425  rc.label = a.value( "label" ).toString();
426  rc.report = QString( "" );
427  rc.lastUpdated = QDate::fromString( a.value( "lastUpdated" ).toString(), "yyyy-MM-dd" );
428  rc.omega2t = a.value( "omega2t" ).toString().toFloat();
429 
430  rc.readReport( xml );
431  }
432  }
433  }
434 
435  file.close();
436 
437  if ( xml.hasError() )
438  {
439  qDebug() << "Error: xml error: \n"
440  << xml.errorString();
441  }
442 
443  if ( rc.rotorID == rotorID )
444  profiles.push_back( rc );
445  }
446 
447  if ( profiles.size() == 0 )
448  return US_Rotor::NOT_FOUND;
449 
450  return US_Rotor::ROTOR_OK;
451 }
452 
453 // Function to find the file name of a rotor or calibration on disk, if it exists
454 bool US_Rotor::diskFilename( const QString& fileMask,
455  const QString& lookupTag,
456  const int& lookupID,
457  QString& filename )
458 {
459  // Get a path and file name
460  QString path;
461  if ( ! diskPath( path ) )
462  {
463  qDebug() << "Error: could not create the directory";
464  return false;
465  }
466 
467  QDir dir( path );
468  QStringList filter( fileMask ); // like "R*.xml"
469  QStringList names = dir.entryList( filter, QDir::Files, QDir::Name );
470  bool found = false;
471 
472  for ( int i = 0; i < names.size(); i++ )
473  {
474  filename = path + "/" + names[ i ];
475  QFile file( filename );
476 
477  if ( ! file.open( QIODevice::ReadOnly | QIODevice::Text) ) continue;
478 
479  QXmlStreamReader xml( &file );
480  while ( ! xml.atEnd() )
481  {
482  xml.readNext();
483 
484  if ( xml.isStartElement() )
485  {
486  if ( xml.name() == lookupTag )
487  {
488  QXmlStreamAttributes a = xml.attributes();
489 
490  if ( a.value( "id" ).toString().toInt() == lookupID ) found = true;
491  break;
492  }
493  }
494  }
495 
496  file.close();
497  if ( found ) break; // Break out of this loop too
498  }
499 
500  if ( ! found )
501  {
502  filename = QString( "" );
503  return false;
504  }
505 
506  return true;
507 }
508 
509 // Get the path to the rotor info. Create it if necessary.
510 bool US_Rotor::diskPath( QString& path )
511 {
512  QDir dir;
513  path = US_Settings::dataDir() + "/rotors";
514 
515  if ( ! dir.exists( path ) )
516  {
517  if ( ! dir.mkpath( path ) )
518  {
519  qDebug() << "Error: Could not create default directory for rotors\n"
520  << path;
521  return false;
522  }
523 
524  // Copy default rotors and rotor calibrations here
525  QString defaultDir = US_Settings::appBaseDir() + "/etc/rotors";
526  QDir etcDir ( defaultDir );
527  QStringList files = etcDir.entryList( QDir::NoDotAndDotDot | QDir::Files );
528 
529  foreach( QString file, files )
530  QFile::copy( defaultDir + "/" + file, path + "/" + file );
531  }
532 
533  return true;
534 }
535 
536 // Function to check if filename already exists, and perhaps generate a new one
538  const QString& path, const QString& fileMask,
539  const QString& lookupTag, const int& lookupID, bool& newFile )
540 {
541  QDir f( path );
542  QStringList filter( fileMask );
543  QStringList f_names = f.entryList( filter, QDir::Files, QDir::Name );
544  QString filename;
545  newFile = true;
546 
547  for ( int i = 0; i < f_names.size(); i++ )
548  {
549  QFile b_file( path + "/" + f_names[ i ] );
550 
551  if ( ! b_file.open( QIODevice::ReadOnly | QIODevice::Text) ) continue;
552 
553  QXmlStreamReader xml( &b_file );
554 
555  while ( ! xml.atEnd() )
556  {
557  xml.readNext();
558 
559  if ( xml.isStartElement() )
560  {
561  if ( xml.name() == lookupTag )
562  {
563  QXmlStreamAttributes a = xml.attributes();
564 
565  if ( a.value( "id" ).toString().toInt() == lookupID )
566  {
567  newFile = false;
568  filename = path + "/" + f_names[ i ];
569  }
570 
571  break;
572  }
573  }
574  }
575 
576  b_file.close();
577  if ( ! newFile ) return filename;
578  }
579 
580  // If we get here, generate a new filename
581  int number = ( f_names.size() > 0 ) ? f_names.last().mid( 1, 7 ).toInt() : 0;
582 
583  QString startName = "/" + fileMask.left( 1 ); // for instance "/R" for rotors
584  return path + startName + QString().sprintf( "%07i", number + 1 ) + ".xml";
585 }
586 
588 {
589  reset();
590 }
591 
592 // A function to read information about a single lab from DB
594 {
595  // Try to get lab info
596  QStringList q( "get_lab_info" );
597  q << QString::number( labID );
598  db->query( q );
599  int readStatus = db->lastErrno();
600 
601  if ( readStatus == US_DB2::NOROWS )
602  return NOT_FOUND;
603 
604  else if ( readStatus != US_DB2::OK )
605  return MISC_ERROR;
606 
607  db->next();
608  this->ID = labID;
609  GUID = db->value( 0 ).toString();
610  name = db->value( 1 ).toString();
611  building = db->value( 2 ).toString();
612  room = db->value( 3 ).toString();
613 
614  // Now try to get instrument info for this lab
615  instruments.clear();
616  q.clear();
617  q << QString( "get_instrument_names" )
618  << QString::number( labID );
619  db->query( q );
620  readStatus = db->lastErrno();
621 
622  if ( readStatus == US_DB2::OK ) // If not, no instruments defined
623  {
624  QList< int > instrumentIDs;
625 
626  // Grab all the IDs so we can reuse the db connection
627  while ( db->next() )
628  {
629  int ID = db->value( 0 ).toString().toInt();
630  instrumentIDs << ID;
631  }
632 
633  // Instrument information
634  foreach ( int ID, instrumentIDs )
635  {
636  US_Rotor::Instrument instrument;
637 
638  q.clear();
639  q << QString( "get_instrument_info" )
640  << QString::number( ID );
641  db->query( q );
642  db->next();
643 
644  instrument.ID = ID;
645  instrument.name = db->value( 0 ).toString();
646  instrument.serial = db->value( 1 ).toString();
647  instrument.operators.clear();
648 
649  this->instruments << instrument;
650  }
651 
652  // Operator information
653  for ( int i = 0; i < instruments.size(); i++ )
654  {
655  q.clear();
656  q << QString( "get_operator_names" )
657  << QString::number( instruments[ i ].ID );
658  db->query( q );
659 
660  if ( db->lastErrno() == US_DB2::OK )
661  {
662  while ( db->next() )
663  {
664  US_Rotor::Operator oper;
665 
666  oper.ID = db->value( 0 ).toString().toInt();
667  oper.GUID = db->value( 1 ).toString();
668  oper.lname = db->value( 2 ).toString();
669  oper.fname = db->value( 3 ).toString();
670 
671  this->instruments[ i ].operators << oper;
672  }
673  }
674  }
675  }
676 
677  return ROTOR_OK;
678 }
679 
681 {
682  ID = -1;
683  GUID = "";
684  name = "";
685  building = "";
686  room = "";
687  instruments.clear();
688 }
689 
691 {
692  qDebug() << "ID = " << ID ;
693  qDebug() << "GUID = " << GUID ;
694  qDebug() << "name = " << name ;
695  qDebug() << "building = " << building ;
696  qDebug() << "room = " << room ;
697 
698  qDebug() << "Instruments...";
699  foreach ( US_Rotor::Instrument instrument, instruments )
700  {
701  qDebug() << " instrument ID = " << instrument.ID ;
702  qDebug() << " instrument name = " << instrument.name ;
703  qDebug() << " instrument serial = " << instrument.serial ;
704 
705  qDebug() << " Operators...";
706  foreach( US_Rotor::Operator oper, instrument.operators )
707  {
708  qDebug() << " operator ID = " << oper.ID ;
709  qDebug() << " operator GUID = " << oper.GUID ;
710  qDebug() << " operator lname = " << oper.lname ;
711  qDebug() << " operator fname = " << oper.fname ;
712  }
713  }
714 }
715 
717 {
718  reset();
719 }
720 
721 // A function to read information about a single abstract rotor from DB
723 {
724  // Try to get rotor info
725  QStringList q( "get_abstractRotor_info" );
726  q << QString::number( abstractRotorID );
727  db->query( q );
728  int readStatus = db->lastErrno();
729 
730  if ( readStatus == US_DB2::NOROWS )
731  return NOT_FOUND;
732 
733  else if ( readStatus != US_DB2::OK )
734  return MISC_ERROR;
735 
736  db->next();
737  this->ID = abstractRotorID;
738  GUID = db->value(0).toString();
739  name = db->value(1).toString();
740  material = db->value(2).toString();
741  numHoles = db->value(3).toInt();
742  maxRPM = db->value(4).toInt();
743  magnetOffset = db->value(5).toFloat();
744  cellCenter = db->value(6).toFloat();
745  manufacturer = db->value(7).toString();
746 
747  return ROTOR_OK;
748 }
749 
751 {
752  ID = -1;
753  GUID = "";
754  name = "";
755  material = "";
756  numHoles = -1;
757  maxRPM = -1;
758  magnetOffset = -1;
759  cellCenter = -1.0;
760  manufacturer = "";
761 }
762 
764 {
765  qDebug() << "ID = " << ID ;
766  qDebug() << "GUID = " << GUID ;
767  qDebug() << "name = " << name ;
768  qDebug() << "material = " << material ;
769  qDebug() << "numHoles = " << numHoles ;
770  qDebug() << "maxRPM = " << maxRPM ;
771  qDebug() << "magnetOffset = " << magnetOffset ;
772  qDebug() << "cellCenter = " << cellCenter ;
773  qDebug() << "manufacturer = " << manufacturer ;
774 }
775 
777 {
778  reset();
779 }
780 
781 // A function to add the current rotor as a new rotor in the DB
783 {
784  QStringList q( "add_rotor" );
785  q << QString::number( abstractRotorID )
786  << abstractRotorGUID
787  << QString::number( labID )
788  << GUID
789  << name
790  << serialNumber;
791 
792  int status = db->statusQuery( q );
793 
794  return status;
795 }
796 
797 // A function to read information about a single rotor from DB
799 {
800  // Try to get rotor info
801  QStringList q( "get_rotor_info" );
802  q << QString::number( rotorID );
803  db->query( q );
804  int readStatus = db->lastErrno();
805 
806  if ( readStatus == US_DB2::NOROWS )
807  return NOT_FOUND;
808 
809  else if ( readStatus != US_DB2::OK )
810  return MISC_ERROR;
811 
812  db->next();
813  this->ID = rotorID;
814  abstractRotorID = db->value( 4 ).toString().toInt();
815  abstractRotorGUID = db->value( 5 ).toString();
816  labID = db->value( 6 ).toString().toInt();
817  GUID = db->value( 0 ).toString();
818  name = db->value( 1 ).toString();
819  serialNumber = db->value( 2 ).toString();
820 
821  return ROTOR_OK;
822 }
823 
824 // A function to delete the specified rotor from the DB
825 int US_Rotor::Rotor::deleteRotorDB( int rotorID, US_DB2* db )
826 {
827  QStringList q( "delete_rotor" );
828  q << QString::number( rotorID );
829 
830  int status = db->statusQuery( q );
831 
832  // most likely status would be OK or ROTOR_IN_USE
833  return status;
834 }
835 
836 // Function to save current rotor information to disk
838 {
839  // First make sure we have a GUID
840  QRegExp rx( "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$" );
841 
842  if ( ! rx.exactMatch( GUID ) )
843  GUID = US_Util::new_guid();
844 
845  // Get a path and file name for the rotor
846  QString path;
847  if ( ! diskPath( path ) ) return;
848 
849  bool newFile;
850  QString filename = get_filename(
851  path,
852  "R???????.xml",
853  "Rotor",
854  ID,
855  newFile );
856 
857  QFile file( filename );
858  if ( !file.open( QIODevice::WriteOnly | QIODevice::Text) )
859  {
860  qDebug() << "Error: can't open file for writing"
861  << filename;
862  return;
863  }
864 
865  // Generate xml
866  QXmlStreamWriter xml;
867  xml.setDevice( &file );
868  xml.setAutoFormatting( true );
869 
870  xml.writeStartDocument();
871  xml.writeDTD("<!DOCTYPE US_Rotor>");
872  xml.writeStartElement("RotorData");
873  xml.writeAttribute("version", "1.0");
874 
875  xml.writeStartElement( "Rotor" );
876  xml.writeAttribute ( "id", QString::number( ID ) );
877  xml.writeAttribute ( "guid", GUID );
878  xml.writeAttribute ( "abstractRotorID", QString::number( abstractRotorID ) );
879  xml.writeAttribute ( "abstractRotorGUID", abstractRotorGUID );
880  xml.writeAttribute ( "labID", QString::number( labID ) );
881  xml.writeAttribute ( "name", name );
882  xml.writeAttribute ( "serialNumber", serialNumber );
883  xml.writeEndElement ();
884 
885  xml.writeEndElement (); // RotorData
886  xml.writeEndDocument ();
887 
888  file.close();
889 }
890 
891 // Function to read all the rotor info from disk
893 {
894  QString filename;
895  bool found = diskFilename( "R*.xml", "Rotor", id, filename );
896 
897  if ( ! found )
898  {
899  qDebug() << "Error: file not found for id "
900  << id;
901  return US_Rotor::NOT_FOUND;
902  }
903 
904  QFile file( filename );
905  if ( !file.open( QIODevice::ReadOnly | QIODevice::Text) )
906  {
907  qDebug() << "Error: can't open file for reading"
908  << filename;
909  return US_Rotor::NOT_OPENED;
910  }
911 
912 
913  QXmlStreamReader xml( &file );
914 
915  reset();
916 
917  while ( ! xml.atEnd() )
918  {
919  xml.readNext();
920 
921  if ( xml.isStartElement() )
922  {
923  if ( xml.name() == "Rotor" )
924  {
925  QXmlStreamAttributes a = xml.attributes();
926 
927  ID = a.value( "id" ).toString().toInt();
928  GUID = a.value( "guid" ).toString();
929  abstractRotorID = a.value( "abstractRotorID" ).toString().toInt();
930  abstractRotorGUID = a.value( "abstractRotorGUID" ).toString();
931  labID = a.value( "labID" ).toString().toInt();
932  name = a.value( "name" ).toString();
933  serialNumber = a.value( "serialNumber" ).toString();
934 
935  }
936  }
937  }
938 
939  file.close();
940 
941  if ( xml.hasError() )
942  {
943  qDebug() << "Error: xml error: \n"
944  << xml.errorString();
945  return US_Rotor::MISC_ERROR;
946  }
947 
948  return US_Rotor::ROTOR_OK;
949 }
950 
952 {
953  ID = -1;
954  abstractRotorID = -1;
955  labID = -1;
956  GUID = "";
957  name = "< Not Selected >";
958  serialNumber = "< Not Selected >";
959 }
960 
962 {
963  qDebug() << "ID = " << ID ;
964  qDebug() << "abstractRotorID = " << abstractRotorID ;
965  qDebug() << "labID = " << labID ;
966  qDebug() << "GUID = " << GUID ;
967  qDebug() << "name = " << name ;
968  qDebug() << "serialNumber = " << serialNumber ;
969 }
970 
972 {
973  reset();
974 }
975 
977 {
978  QStringList q( "add_rotor_calibration" );
979  q << QString::number( rotorID )
980  << GUID
981  << report
982  << QString::number( coeff1 )
983  << QString::number( coeff2 )
984  << QString::number( omega2t )
985  << QString::number( calibrationExperimentID )
986  << label;
987 
988  int status = db->statusQuery( q );
989 
990  if ( status == US_DB2::OK )
991  this->ID = db->lastInsertID();
992 
993  return status;
994 }
995 
996 // A function to read information about a single rotor calibration profile from DB
998 {
999  // Try to get rotor info
1000  QStringList q( "get_rotor_calibration_info" );
1001  q << QString::number( calibrationID );
1002  db->query( q );
1003  int readStatus = db->lastErrno();
1004 
1005  if ( readStatus == US_DB2::NOROWS )
1006  return NOT_FOUND;
1007 
1008  else if ( readStatus != US_DB2::OK )
1009  return MISC_ERROR;
1010 
1011  db->next();
1012  this->ID = calibrationID;
1013  this->GUID = db->value( 0 ).toString();
1014  this->rotorID = db->value( 1 ).toString().toInt();
1015  this->rotorGUID = db->value( 2 ).toString();
1016  this->calibrationExperimentID = db->value( 8 ).toString().toInt();
1017  //this->calibrationExperimentGUID = not implemented in stored routines db->value( ).toString();
1018  this->coeff1 = db->value( 4 ).toString().toFloat();
1019  this->coeff2 = db->value( 5 ).toString().toFloat();
1020  this->label = db->value( 9 ).toString();
1021  this->report = db->value( 3 ).toString();
1022 
1023  QStringList dateParts = db->value( 7 ).toString().split( " " );
1024  this->lastUpdated = QDate::fromString( dateParts[ 0 ], "yyyy-MM-dd" );
1025 
1026  this->omega2t = db->value( 6 ).toString().toFloat();
1027 
1028  // QString calibrationExperimentGUID; //!< The GUID of the experiment that contains the calibration data
1029  return ROTOR_OK;
1030 }
1031 
1032 // A function to delete the specified rotor calibration from the DB
1034 {
1035  QStringList q( "delete_rotor_calibration" );
1036  q << QString::number( calibrationID );
1037 
1038  int status = db->statusQuery( q );
1039 
1040  // most likely status would be OK or ROTOR_IN_USE
1041  return status;
1042 }
1043 
1044 // A function to find out if the original dummy calibration is still there,
1045 // and replace it with the current one if it does.
1046 int US_Rotor::RotorCalibration::replaceDummyDB( int& oldCalibrationID, US_DB2* db )
1047 {
1048  QStringList calibrationIDs;
1049 
1050  QStringList q( "get_rotor_calibration_profiles" );
1051  q << QString::number( rotorID );
1052 
1053  db->query( q );
1054 
1055  while ( db->next() )
1056  calibrationIDs << db->value( 0 ).toString();
1057 
1058  // Let's remove the one we just added from the list
1059  int ndx = calibrationIDs.indexOf( QString::number( this->ID ) );
1060  calibrationIDs.removeAt( ndx );
1061 
1062  // Let's make sure we still have some
1063  if ( calibrationIDs.isEmpty() )
1064  return US_DB2::OK; // Not really an error
1065 
1066  oldCalibrationID = -1; // = -1 means we haven't found it
1067  foreach ( QString calibrationID, calibrationIDs )
1068  {
1069  q.clear();
1070  q << "get_rotor_calibration_info"
1071  << calibrationID;
1072 
1073  db->query( q );
1074  db->next();
1075  QString report = db->value( 3 ).toString();
1076  QString label = db->value( 9 ).toString();
1077 
1078  if ( report.contains( "This is a dummy calibration --- please replace." ) &&
1079  label.contains( "Dummy Calibration" ) )
1080  {
1081  oldCalibrationID = calibrationID.toInt();
1082  break;
1083  }
1084  }
1085 
1086  // Let's see if we found it
1087  if ( oldCalibrationID == -1 )
1088  return US_DB2::OK; // Not an error either
1089 
1090  // Ok found one, replace
1091  q.clear();
1092  q << "replace_rotor_calibration"
1093  << QString::number( oldCalibrationID )
1094  << QString::number( this->ID );
1095  int status = db->statusQuery( q );
1096 
1097  return status;
1098 }
1099 
1100 // Function to save current calibration information to disk
1102 {
1103  // First make sure we have a GUID
1104  QRegExp rx( "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$" );
1105 
1106  if ( ! rx.exactMatch( GUID ) )
1107  GUID = US_Util::new_guid();
1108 
1109  // Get a path and file name for the calibration
1110  QString path;
1111  if ( ! diskPath( path ) ) return;
1112 
1113  bool newFile;
1114  QString filename = get_filename(
1115  path,
1116  "C???????.xml",
1117  "Calibration",
1118  ID,
1119  newFile );
1120 
1121  QFile file( filename );
1122  if ( !file.open( QIODevice::WriteOnly | QIODevice::Text) )
1123  {
1124  qDebug() << "Error: can't open file for writing"
1125  << filename;
1126  return;
1127  }
1128 
1129  // Generate xml
1130  QXmlStreamWriter xml;
1131  xml.setDevice( &file );
1132  xml.setAutoFormatting( true );
1133 
1134  xml.writeStartDocument();
1135  xml.writeDTD("<!DOCTYPE US_RotorCalibration>");
1136  xml.writeStartElement("RotorCalibrationData");
1137  xml.writeAttribute("version", "1.0");
1138 
1139  xml.writeStartElement( "Calibration" );
1140  xml.writeAttribute ( "id", QString::number( ID ) );
1141  xml.writeAttribute ( "guid", GUID );
1142  xml.writeAttribute ( "rotorID", QString::number( rotorID ) );
1143  xml.writeAttribute ( "rotorGUID", rotorGUID );
1144  xml.writeAttribute ( "calExpID", QString::number( calibrationExperimentID ) );
1145  xml.writeAttribute ( "calExpGUID", calibrationExperimentGUID );
1146  xml.writeAttribute ( "coeff1", QString::number( coeff1 ) );
1147  xml.writeAttribute ( "coeff2", QString::number( coeff2 ) );
1148  xml.writeAttribute ( "lastUpdated", lastUpdated.toString( "yyyy-MM-dd" ) );
1149  xml.writeAttribute ( "omega2t", QString::number( omega2t ) );
1150  xml.writeAttribute ( "label", label );
1151  xml.writeTextElement ( "report", report );
1152  xml.writeEndElement ();
1153 
1154  xml.writeEndElement (); // RotorCalibrationData
1155  xml.writeEndDocument ();
1156 
1157  file.close();
1158 }
1159 
1160 // Function to read all the calibration info from disk
1162 {
1163  QString filename;
1164  bool found = diskFilename( "C*.xml", "Calibration", id, filename );
1165 
1166  if ( ! found )
1167  {
1168  qDebug() << "Error: file not found for id "
1169  << id;
1170  return US_Rotor::NOT_FOUND;
1171  }
1172 
1173  QFile file( filename );
1174  if ( !file.open( QIODevice::ReadOnly | QIODevice::Text) )
1175  {
1176  qDebug() << "Error: can't open file for reading"
1177  << filename;
1178  return US_Rotor::NOT_OPENED;
1179  }
1180 
1181 
1182  QXmlStreamReader xml( &file );
1183 
1184  reset();
1185 
1186  while ( ! xml.atEnd() )
1187  {
1188  xml.readNext();
1189 
1190  if ( xml.isStartElement() )
1191  {
1192  if ( xml.name() == "Calibration" )
1193  {
1194  QXmlStreamAttributes a = xml.attributes();
1195 
1196  ID = a.value( "id" ).toString().toInt();
1197  GUID = a.value( "guid" ).toString();
1198  rotorID = a.value( "rotorID" ).toString().toInt();
1199  rotorGUID = a.value( "rotorGUID" ).toString();
1200  calibrationExperimentID = a.value( "calExpID" ).toString().toInt();
1201  calibrationExperimentGUID = a.value( "calExpGUID" ).toString();
1202  coeff1 = a.value( "coeff1" ).toString().toFloat();
1203  coeff2 = a.value( "coeff2" ).toString().toFloat();
1204  lastUpdated = QDate::fromString( a.value( "lastUpdated" ).toString(), "yyyy-MM-dd" );
1205  omega2t = a.value( "omega2t" ).toString().toFloat();
1206  label = a.value( "label" ).toString();
1207 
1208  readReport( xml );
1209  }
1210  }
1211  }
1212 
1213  file.close();
1214 
1215  if ( xml.hasError() )
1216  {
1217  qDebug() << "Error: xml error: \n"
1218  << xml.errorString();
1219  return US_Rotor::MISC_ERROR;
1220  }
1221 
1222  return US_Rotor::ROTOR_OK;
1223 }
1224 
1225 void US_Rotor::RotorCalibration::readReport( QXmlStreamReader& xml )
1226 {
1227  while ( !xml.atEnd() )
1228  {
1229  xml.readNext();
1230 
1231  if ( xml.isEndElement() && xml.name() == "Calibration" ) return;
1232 
1233  if ( xml.isStartElement() )
1234  {
1235  if ( xml.name() == "report" )
1236  {
1237  xml.readNext();
1238  report = xml.text().toString();
1239  }
1240  }
1241  }
1242 }
1243 
1245 {
1246  ID = -1;
1247  GUID = "";
1248  calibrationExperimentGUID = "";
1249  coeff1 = 0.0;
1250  coeff2 = 0.0;
1251  label = "";
1252  report = "";
1253  lastUpdated = QDate::currentDate();
1254  omega2t = 0.0;
1255 }
1256 
1258 {
1259  qDebug() << "GUID = " << GUID;
1260  qDebug() << "rotorID = " << rotorID;
1261  qDebug() << "rotorGUID = " << rotorGUID;
1262  qDebug() << "calibration experiment ID = " << calibrationExperimentID;
1263  qDebug() << "calibration experiment GUID = " << calibrationExperimentGUID;
1264  qDebug() << "coeff1 = " << coeff1;
1265  qDebug() << "coeff2 = " << coeff2;
1266  qDebug() << "last updated = " << lastUpdated.toString( "yyyy-MM-dd" );
1267  qDebug() << "omega2t = " << QString::number( omega2t );
1268  qDebug() << "label = " << label;
1269  qDebug() << "report";
1270  qDebug() << report;
1271 }