UltraScan III
us_project.cpp
Go to the documentation of this file.
1 
3 #include <QtCore>
4 
5 #include "us_settings.h"
6 #include "us_db2.h"
7 #include "us_util.h"
8 #include "us_project.h"
9 
10 // The constructor clears out the data structure
12 {
13  clear();
14 }
15 
16 // Function to load a project from the disk
17 int US_Project::readFromDisk( QString& guid )
18 {
19  QString filename;
20  bool found = diskFilename( guid, filename );
21 
22  if ( ! found )
23  {
24  qDebug() << "Error: project file not found -- guid "
25  << guid;
26  return US_DB2::NO_PROJECT;
27  }
28 
29  QFile file( filename );
30  if ( !file.open( QIODevice::ReadOnly | QIODevice::Text) )
31  {
32  qDebug() << "Error: can't open file for reading"
33  << filename;
34  return US_DB2::NO_PROJECT;
35  }
36 
37  QXmlStreamReader xml( &file );
38 
39  clear();
40 
41  while ( ! xml.atEnd() )
42  {
43  xml.readNext();
44 
45  if ( xml.isStartElement() )
46  {
47  if ( xml.name() == "project" )
48  {
49  QXmlStreamAttributes a = xml.attributes();
50  projectID = a.value( "id" ).toString().toInt();
51  projectGUID = a.value( "guid" ).toString();
52 
53  readProjectInfo( xml );
54  }
55  }
56  }
57 
58  file.close();
59 
60  if ( xml.hasError() )
61  {
62  qDebug() << "Error: xml error: \n"
63  << xml.errorString();
64  return US_DB2::ERROR;
65  }
66 
68 
69  return US_DB2::OK;
70 }
71 
72 void US_Project::readProjectInfo( QXmlStreamReader& xml )
73 {
74  while ( ! xml.atEnd() )
75  {
76  xml.readNext();
77 
78  if ( xml.isEndElement() && xml.name() == "project" ) return;
79 
80  if ( xml.isStartElement() )
81  {
82  if ( xml.name() == "goals" )
83  {
84  xml.readNext();
85  goals = xml.text().toString();
86  }
87 
88  else if ( xml.name() == "molecules" )
89  {
90  xml.readNext();
91  molecules = xml.text().toString();
92  }
93 
94  else if ( xml.name() == "purity" )
95  {
96  xml.readNext();
97  purity = xml.text().toString();
98  }
99 
100  else if ( xml.name() == "expense" )
101  {
102  xml.readNext();
103  expense = xml.text().toString();
104  }
105 
106  else if ( xml.name() == "bufferComponents" )
107  {
108  xml.readNext();
109  bufferComponents = xml.text().toString();
110  }
111 
112  else if ( xml.name() == "saltInformation" )
113  {
114  xml.readNext();
115  saltInformation = xml.text().toString();
116  }
117 
118  else if ( xml.name() == "AUC_questions" )
119  {
120  xml.readNext();
121  AUC_questions = xml.text().toString();
122  }
123 
124  else if ( xml.name() == "expDesign" )
125  {
126  xml.readNext();
127  expDesign = xml.text().toString();
128  }
129 
130  else if ( xml.name() == "notes" )
131  {
132  xml.readNext();
133  notes = xml.text().toString();
134  }
135 
136  else if ( xml.name() == "description" )
137  {
138  xml.readNext();
139  projectDesc = xml.text().toString();
140  }
141  }
142  }
143 }
144 
145 // Function to load a project from the db
146 int US_Project::readFromDB ( int projectID, US_DB2* db )
147 {
148  // Try to get project info
149  QStringList q( "get_project_info" );
150  q << QString::number( projectID );
151  db->query( q );
152 
153  if ( db->next() )
154  {
155  this->projectID = projectID;
156  projectGUID = db->value( 1 ).toString();
157  goals = db->value( 2 ).toString();
158  molecules = db->value( 3 ).toString();
159  purity = db->value( 4 ).toString();
160  expense = db->value( 5 ).toString();
161  bufferComponents = db->value( 6 ).toString();
162  saltInformation = db->value( 7 ).toString();
163  AUC_questions = db->value( 8 ).toString();
164  notes = db->value( 9 ).toString();
165  projectDesc = db->value( 10 ).toString();
166  status = db->value( 11 ).toString();
167  // value 12 is personID
168  expDesign = db->value( 13 ).toString();
169 
170  }
171 
172  else
173  return US_DB2::NO_PROJECT;
174 
176 
177  return US_DB2::OK;
178 }
179 
180 // Function to save project information to disk
182 {
183  // First make sure we have a GUID
184  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}$" );
185 
186  if ( ! rx.exactMatch( projectGUID ) )
188 
189  // Get a path and file name for project
190  QString path;
191  if ( ! diskPath( path ) ) return;
192 
193  bool newFile;
194  QString filename = get_filename(
195  path,
196  newFile );
197 
198  QFile file( filename );
199  if ( !file.open( QIODevice::WriteOnly | QIODevice::Text) )
200  {
201  qDebug() << "Error: can't open file for writing"
202  << filename;
203  return;
204  }
205 
206  // Generate xml
207  QXmlStreamWriter xml;
208  xml.setDevice( &file );
209  xml.setAutoFormatting( true );
210 
211  xml.writeStartDocument();
212  xml.writeDTD("<!DOCTYPE US_Project>");
213  xml.writeStartElement("ProjectData");
214  xml.writeAttribute("version", "1.0");
215 
216  // elements
217  xml.writeStartElement( "project" );
218  xml.writeAttribute ( "id", QString::number( projectID ) );
219  xml.writeAttribute ( "guid", projectGUID );
220 
221  xml.writeTextElement( "goals", goals );
222  xml.writeTextElement( "molecules", molecules );
223  xml.writeTextElement( "purity", purity );
224  xml.writeTextElement( "expense", expense );
225  xml.writeTextElement( "bufferComponents", bufferComponents );
226  xml.writeTextElement( "saltInformation", saltInformation );
227  xml.writeTextElement( "AUC_questions", AUC_questions );
228  xml.writeTextElement( "expDesign", expDesign );
229  xml.writeTextElement( "notes", notes );
230  xml.writeTextElement( "description", projectDesc );
231 
232  xml.writeEndElement (); // project
233  xml.writeEndDocument ();
234 
235  file.close();
236 
238 }
239 
240 // Function to save project information to db
242 {
243  // Save it to disk too
244  saveToDisk();
245 
246  // Check for GUID in database
247  projectID = 0;
248  QStringList q( "get_projectID_from_GUID" );
249  q << projectGUID;
250  db->query( q );
251 
252  int db_status = db->lastErrno();
253  if ( db_status == US_DB2::OK )
254  {
255  // Edit existing project entry
256  db->next();
257  projectID = db->value( 0 ).toInt();
258  q.clear();
259  q << "update_project2"
260  << QString::number( projectID )
261  << projectGUID
262  << goals
263  << molecules
264  << purity
265  << expense
267  << saltInformation
268  << AUC_questions
269  << expDesign
270  << notes
271  << projectDesc
272  << status;
273 
274  db->statusQuery( q );
275  }
276 
277  else if ( db_status == US_DB2::NOROWS )
278  {
279  // Create new project entry
280  q.clear();
281  q << "new_project2"
282  << projectGUID
283  << goals
284  << molecules
285  << purity
286  << expense
288  << saltInformation
289  << AUC_questions
290  << expDesign
291  << notes
292  << projectDesc
293  << status
294  << QString::number( US_Settings::us_inv_ID() );
295 
296 
297  db->statusQuery( q );
298  projectID = db->lastInsertID();
299  }
300 
301  else // unspecified error
302  {
303  qDebug() << "MySQL error: " << db->lastError();
304  return db_status;
305  }
306 
307  if ( projectID == 0 ) // double check
308  return US_DB2::NO_PROJECT;
309 
310  saveStatus = BOTH;
311 
312  return US_DB2::OK;
313 }
314 
315 // Function to delete a project from disk
317 {
318  QString filename;
319  bool found = diskFilename( projectGUID, filename );
320 
321  if ( ! found )
322  {
323  // No file to delete
324  return;
325  }
326 
327  // Delete it
328  QFile file( filename );
329  if ( file.exists() )
330  file.remove();
331 
333 }
334 
335 // Function to delete a project from db
337 {
338  QStringList q;
339  if ( projectID == 0 )
340  {
341  // Then probably user selected from disk but is trying to delete from db,
342  // so let's try to get the db projectID from the GUID
343  q.clear();
344  q << "get_projectID_from_GUID"
345  << projectGUID;
346  db->query( q );
347 
348  if ( db->next() )
349  projectID = db->value( 0 ).toInt();
350 
351  }
352 
353  if ( projectID > 0 ) // otherwise it's not there to delete
354  {
355  q.clear();
356  q << "delete_project"
357  << QString::number( projectID );
358 
359  int status = db->statusQuery( q );
360  if ( status != US_DB2::OK )
361  qDebug() << "MySQL error: " << db->lastError();
362 
363  }
364 
365  clear();
366 
368 }
369 
370 // Function to find the file name of a project on disk, if it exists
371 bool US_Project::diskFilename( const QString& guid, QString& filename )
372 {
373  // Get a path and file name for project
374  QString path;
375  if ( ! diskPath( path ) )
376  {
377  qDebug() << "Error: could not create the projects directory";
378  return false;
379  }
380 
381  QDir dir( path );
382  QStringList filter( "P*.xml" );
383  QStringList names = dir.entryList( filter, QDir::Files, QDir::Name );
384  bool found = false;
385 
386  for ( int i = 0; i < names.size(); i++ )
387  {
388  filename = path + "/" + names[ i ];
389  QFile file( filename );
390 
391  if ( ! file.open( QIODevice::ReadOnly | QIODevice::Text) ) continue;
392 
393  QXmlStreamReader xml( &file );
394 
395  while ( ! xml.atEnd() )
396  {
397  xml.readNext();
398 
399  if ( xml.isStartElement() )
400  {
401  if ( xml.name() == "project" )
402  {
403  QXmlStreamAttributes a = xml.attributes();
404 
405  if ( a.value( "guid" ).toString() == guid ) found = true;
406  break;
407  }
408  }
409  }
410 
411  file.close();
412  if ( found ) break; // Break out of this loop too
413  }
414 
415  if ( ! found )
416  {
417  filename = QString( "" );
418  return false;
419  }
420 
421  return true;
422 }
423 
424 // Get the path to the projects. Create it if necessary.
425 bool US_Project::diskPath( QString& path )
426 {
427  QDir dir;
428  path = US_Settings::dataDir() + "/projects";
429 
430  if ( ! dir.exists( path ) )
431  {
432  if ( ! dir.mkpath( path ) )
433  {
434  qDebug() << "Error: Could not create default directory for projects\n"
435  << path;
436  return false;
437  }
438  }
439 
440  return true;
441 }
442 
443 // Function to check if filename already exists, and perhaps generate a new one
445  const QString& path, bool& newFile )
446 {
447  QDir f( path );
448  QStringList filter( "P???????.xml" );
449  QStringList f_names = f.entryList( filter, QDir::Files, QDir::Name );
450  QString filename;
451  newFile = true;
452 
453  for ( int i = 0; i < f_names.size(); i++ )
454  {
455  QFile b_file( path + "/" + f_names[ i ] );
456 
457  if ( ! b_file.open( QIODevice::ReadOnly | QIODevice::Text) ) continue;
458 
459  QXmlStreamReader xml( &b_file );
460 
461  while ( ! xml.atEnd() )
462  {
463  xml.readNext();
464 
465  if ( xml.isStartElement() )
466  {
467  if ( xml.name() == "project" )
468  {
469  QXmlStreamAttributes a = xml.attributes();
470 
471  if ( a.value( "guid" ).toString() == projectGUID )
472  {
473  newFile = false;
474  filename = path + "/" + f_names[ i ];
475  }
476 
477  break;
478  }
479  }
480  }
481 
482  b_file.close();
483  if ( ! newFile ) return filename;
484  }
485 
486  // If we get here, generate a new filename
487  int number = ( f_names.size() > 0 ) ? f_names.last().mid( 1, 7 ).toInt() : 0;
488 
489  return path + "/P" + QString().sprintf( "%07i", number + 1 ) + ".xml";
490 }
491 
492 void US_Project::clear( void )
493 {
494  projectID = 0;
495  projectGUID = QString( "" );
496  goals = QString( "" );
497  molecules = QString( "" );
498  purity = QString( "" );
499  expense = QString( "" );
500  bufferComponents = QString( "" );
501  saltInformation = QString( "" );
502  AUC_questions = QString( "" );
503  expDesign = QString( "" );
504  notes = QString( "" );
505  projectDesc = QString( "" );
506  status = QString( "submitted" );
507 
509 }
510 
511 void US_Project::show( void )
512 {
513  qDebug() << "projectID = " << projectID << '\n'
514  << "projectGUID = " << projectGUID << '\n'
515  << "goals = " << goals << '\n'
516  << "molecules = " << molecules << '\n'
517  << "purity = " << purity << '\n'
518  << "expense = " << expense << '\n'
519  << "bufferComponents = " << bufferComponents << '\n'
520  << "saltInformation = " << saltInformation << '\n'
521  << "AUC_questions = " << AUC_questions << '\n'
522  << "expDesign = " << expDesign << '\n'
523  << "notes = " << notes << '\n'
524  << "projectDesc = " << projectDesc << '\n'
525  << "status = " << status << '\n'
526  << "saveStatus = " << saveStatus << '\n';
527 }