UltraScan III
us_dmga_init.cpp
Go to the documentation of this file.
1 
3 #include <QApplication>
4 
5 #include "us_dmga_init.h"
6 #include "us_constraints_edit.h"
7 #include "us_model_loader.h"
8 #include "us_license_t.h"
9 #include "us_license.h"
10 #include "us_settings.h"
11 #include "us_gui_settings.h"
12 #include "us_math2.h"
13 #include "us_matrix.h"
14 #include "us_constants.h"
15 #include "us_passwd.h"
16 #include "us_report.h"
17 #include "us_investigator.h"
18 #include "us_util.h"
19 #include "us_passwd.h"
20 #include "us_associations_gui.h"
21 #include "us_settings.h"
22 #include "us_gui_settings.h"
23 #include "us_constants.h"
24 #include "us_model.h"
25 
26 #ifndef DbgLv
27 #define DbgLv(a) if(dbg_level>=a)qDebug()
28 #endif
29 
30 // main program
31 int main( int argc, char* argv[] )
32 {
33  QApplication application( argc, argv );
34 
35  #include "main1.inc"
36 
37  // License is OK. Start up.
38 
39  US_DMGA_Init w;
40  w.show();
41  return application.exec();
42 }
43 
44 // US_DMGA_Init class constructor
46 {
47  // set up the GUI
48 
49  setWindowTitle( tr( "Discrete Genetic Algorithm Initialization" ) );
50  setPalette( US_GuiSettings::frameColor() );
51 
53 
54  // Grid
55  QGridLayout* main = new QGridLayout( this );
56  main->setSpacing( 2 );
57  main->setContentsMargins( 2, 2, 2, 2 );
58  int dataloc = US_Settings::default_data_location();
59 
60  // Disk/DB
61  dkdb_cntrls = new US_Disk_DB_Controls( dataloc );
62  // Model and constraints
63  QLabel* lb_modcnst = us_banner( tr( "Model and Constraints" ) );
64  pb_loadmodel = us_pushbutton( tr( "Load Base Model" ) );
65  pb_loadconstr = us_pushbutton( tr( "Load Constraints" ) );
66  pb_defmodel = us_pushbutton( tr( "Define Base Model" ) );
67  pb_defconstr = us_pushbutton( tr( "Define Constraints" ) );
68  pb_savemodel = us_pushbutton( tr( "Save Base Model" ) );
69  pb_saveconstr = us_pushbutton( tr( "Save Constraints" ) );
70  pb_savemodel ->setEnabled( false );
71  pb_saveconstr->setEnabled( false );
72 
73  // General control
74  QLabel* lb_gencntrl = us_banner( tr( "General Control" ) );
75  pb_help = us_pushbutton( tr( "Help" ) );
76  pb_close = us_pushbutton( tr( "Close" ) );
77  le_status = us_lineedit( tr( "(no model/constraints loaded)" ),
78  1, true );
79  QPalette stpal;
80  stpal.setColor( QPalette::Text, Qt::white );
81  stpal.setColor( QPalette::Base, Qt::blue );
82  le_status->setPalette( stpal );
83 
84  // Layout
85  int row = 0;
86  main->addLayout( dkdb_cntrls, row++, 0, 1, 4 );
87  main->addWidget( lb_modcnst, row++, 0, 1, 4 );
88  main->addWidget( pb_loadmodel, row, 0, 1, 2 );
89  main->addWidget( pb_loadconstr, row++, 2, 1, 2 );
90  main->addWidget( pb_defmodel, row, 0, 1, 2 );
91  main->addWidget( pb_defconstr, row++, 2, 1, 2 );
92  main->addWidget( pb_savemodel, row, 0, 1, 2 );
93  main->addWidget( pb_saveconstr, row++, 2, 1, 2 );
94 
95  main->addWidget( lb_gencntrl, row++, 0, 1, 4 );
96  main->addWidget( le_status, row++, 0, 1, 4 );
97  main->addWidget( pb_help, row, 0, 1, 2 );
98  main->addWidget( pb_close, row++, 2, 1, 2 );
99 
100  // Signals and slots
101  connect( dkdb_cntrls, SIGNAL( changed ( bool ) ),
102  SLOT ( update_disk_db( bool ) ) );
103  connect( pb_loadmodel, SIGNAL( clicked () ),
104  SLOT ( load_model () ) );
105  connect( pb_loadconstr, SIGNAL( clicked () ),
106  SLOT ( load_constraints () ) );
107  connect( pb_defmodel, SIGNAL( clicked () ),
108  SLOT ( define_model () ) );
109  connect( pb_defconstr, SIGNAL( clicked () ),
110  SLOT ( define_constraints() ) );
111  connect( pb_savemodel, SIGNAL( clicked () ),
112  SLOT ( save_model () ) );
113  connect( pb_saveconstr, SIGNAL( clicked () ),
114  SLOT ( save_constraints () ) );
115  connect( pb_help, SIGNAL( clicked () ),
116  SLOT ( help () ) );
117  connect( pb_close, SIGNAL( clicked () ),
118  SLOT ( close () ) );
119 
120  resize( 500, 200 );
121 
122  const int sctmms = 1000; // Delay 1 second to start model scan
123  sctm_id = startTimer( sctmms );
124  le_status->setText( tr( "Scanning models for unassigned edits" ) );
125  qApp->processEvents();
126 }
127 
128 // US_DMGA_Init class destructor
130 {
132 
133  attribs .clear();
134  flt_attrs .clear();
135 }
136 
137 // Load an existing base model
139 {
140 DbgLv(1) << "dGA:load_model";
141  le_status->setText( tr( "Loading a list of base models" ) );
142  qApp->processEvents();
143  bool loadDB = dkdb_cntrls->db();
144  QString mfilt = "=m";
145  QString mdesc = "";
146  QString eGUID = "";
147 //mfilt="";
148 //eGUID="00000000-0000-0000-0000-000000000000";
149  US_ModelLoader mldiag( loadDB, mfilt, bmodel, mdesc, eGUID );
150 
151  connect( &mldiag, SIGNAL( changed ( bool ) ),
152  SLOT ( update_disk_db( bool ) ) );
153 
154  if ( mldiag.exec() == QDialog::Accepted )
155  {
156  le_status->setText( tr( "A base model has been loaded." ) );
158  pb_savemodel->setEnabled( true );
159  }
160  else
161  {
162  le_status->setText( tr( "No base model was loaded." ) );
163  }
164 
165  qApp->processEvents();
166 }
167 
168 // Define a base model
170 {
171 DbgLv(1) << "dGA:define_model";
172  US_ModelGui* mddiag = new US_ModelGui( bmodel );
173  le_status->setText( tr( "Editing or creating a base model" ) );
174  qApp->processEvents();
175 
176  connect( mddiag, SIGNAL( valueChanged ( US_Model ) ),
177  SLOT ( new_base_model( US_Model ) ) );
178 
179  mddiag->exec();
180 
181  if ( bmodel.components.size() > 0 )
182  {
183  le_status->setText( tr( "A base model has been created or edited." ) );
185  pb_savemodel->setEnabled( true );
186  }
187  else
188  {
189  le_status->setText( tr( "No base model was defined." ) );
190  }
191 
192  qApp->processEvents();
193 }
194 
195 // Load an existing constraints model
197 {
198 DbgLv(1) << "dGA:load_constraints";
199 
200  bool loadDB = dkdb_cntrls->db();
201  QString mfilt = "=u Constr";
202  QString mdesc = "";
203  QString eGUID = "";
204  le_status->setText( tr( "Loading a list of existing constraints models" ) );
205  qApp->processEvents();
206 
207  US_ModelLoader mldiag( loadDB, mfilt, cmodel, mdesc, eGUID );
208 
209  connect( &mldiag, SIGNAL( changed ( bool ) ),
210  SLOT ( update_disk_db( bool ) ) );
211  if ( mldiag.exec() != QDialog::Accepted )
212  return;
213 
214 DbgLv(1) << "dGA:load_constraints model comps" << cmodel.components.size();
215  US_ConstraintsEdit cediag( cmodel );
216 
217  if ( cediag.exec() == QDialog::Accepted )
218  {
219  le_status->setText( tr( "A constraints model has been loaded." ) );
221  pb_saveconstr->setEnabled( true );
222  }
223 
224  else
225  {
226  le_status->setText( tr( "No constraints model was loaded." ) );
227  }
228 
229  qApp->processEvents();
230 }
231 
232 // Define a constraints model
234 {
235 DbgLv(1) << "dGA:define_constraints";
236  if ( cmodel.components.size() == 0 )
237  { // If no constraints model, point to the base model
238  cmodel = bmodel;
240  }
241 
242  US_ConstraintsEdit cediag( cmodel );
243 
244  le_status->setText( tr( "Editor to define a constraints model" ) );
245  qApp->processEvents();
246 
247  if ( cediag.exec() == QDialog::Accepted )
248  {
249  le_status->setText( tr( "A constraints model has been defined." ) );
251  pb_saveconstr->setEnabled( true );
252  }
253 
254  else
255  {
256  le_status->setText( tr( "No constraints model was defined." ) );
257  }
258 
259  qApp->processEvents();
260 }
261 
262 // Save a defined base model
264 {
265 DbgLv(1) << "dGA:save_model";
266  QString msg1 = tr( "A Base Model has been loaded or created."
267  " It's description is:" )
268  + "<br/>&nbsp;&nbsp;<b>" + bmodel.description + "</b>.<br/><br/>"
269  + tr( "It may be saved as it is or you may modify the description"
270  " or other attributes by clicking the <b>Cancel</b> button"
271  " here and clicking the <b>Define Base Model</b> in the"
272  " main dialog. The model may also be updated or saved within"
273  " the resulting dialog.<br/><br/>"
274  "&nbsp;&nbsp;Click:<br/>"
275  "<b>OK</b><br/>&nbsp;&nbsp;to output the model as is;<br/>"
276  "<b>Cancel</b><br/>&nbsp;&nbsp;to abort the model save.<br/>" );
277 
278  QMessageBox mbox;
279  mbox.setWindowTitle( tr( "Save Current Base Model" ) );
280  mbox.setText ( msg1 );
281  QPushButton *pb_ok = mbox.addButton( tr( "OK" ),
282  QMessageBox::YesRole );
283  QPushButton *pb_canc = mbox.addButton( tr( "Cancel" ),
284  QMessageBox::RejectRole );
285  mbox.setEscapeButton ( pb_canc );
286  mbox.setDefaultButton( pb_ok );
287 
288  mbox.exec();
289 
290  if ( mbox.clickedButton() == pb_canc ) return;
291 
292  // Output the base model
293  int code;
294 
295  if ( dkdb_cntrls->db() )
296  { // Write to DB and local
297  US_Passwd pw;
298  US_DB2 db( pw.getPasswd() );
299 
300  code = bmodel.write( &db );
301  }
302  else
303  { // Write to local disk only
304  bool newFile;
305  QString modelPath;
306  US_Model::model_path( modelPath );
307  QString modelGuid = bmodel.modelGUID;
308 
309  if ( modelGuid.isEmpty() )
310  {
311  modelGuid = US_Util::new_guid();
312  bmodel.modelGUID = modelGuid;
313  }
314 
315  QString fnameo = US_Model::get_filename( modelPath, modelGuid, newFile );
316  code = bmodel.write( fnameo );
317  }
318 
319  QString mtitle = tr( "Base Model Saving ..." );
320 
321  if ( code == US_DB2::OK )
322  {
323  QString destination = dkdb_cntrls->db() ?
324  tr( "local disk and database." ) :
325  tr( "local disk." );
326  QMessageBox::information( this, mtitle,
327  tr( "The file \"" ) + cmodel.description
328  + tr( "\"\n was successfully saved to " ) + destination );
329  }
330  else
331  {
332  QMessageBox::warning( this, mtitle,
333  tr( "Writing the file \"" ) + cmodel.description
334  + tr( "\"\n resulted in error code %1 ." ).arg( code ) );
335  }
336 }
337 
338 // Save a defined constraints model
340 {
341 DbgLv(1) << "dGA:save_constraints";
342  QString now = QDateTime::currentDateTime()
343  .toUTC().toString( "yyyyMMdd-hhmm" );
344  QString ftype = QString( "-DMGA_Constraints" );
345  QString suffix = "";
346  QString fext = ".model";
347  QString cmfdesc = now + ftype + suffix + fext;
348  QString modelGuid = US_Util::new_guid();
349  QString modelPath;
350  US_Model::model_path( modelPath );
351 
352 
353  QString msg1 = tr( "A Discrete Model Genetic Algorithm Constraints"
354  " model has been created. It's description is:" )
355  + "<br/><b>" + cmfdesc + "</b>.<br/><br/"
356  + tr( "Click:<br/><br/>"
357  " <b>OK</b> to output the model as is;<br/>"
358  " <b>Edit</b> to append custom text to the name;<br/>"
359  " <b>Cancel</b> to abort the model save.<br/>" );
360 
361  QMessageBox mbox;
362  mbox.setWindowTitle( tr( "Save Constraints Model" ) );
363  mbox.setText ( msg1 );
364  QPushButton *pb_ok = mbox.addButton( tr( "OK" ),
365  QMessageBox::YesRole );
366  QPushButton *pb_edit = mbox.addButton( tr( "Edit" ),
367  QMessageBox::AcceptRole );
368  QPushButton *pb_canc = mbox.addButton( tr( "Cancel" ),
369  QMessageBox::RejectRole );
370  mbox.setEscapeButton ( pb_canc );
371  mbox.setDefaultButton( pb_ok );
372 
373  mbox.exec();
374 
375  if ( mbox.clickedButton() == pb_canc ) return;
376  if ( mbox.clickedButton() == pb_edit )
377  { // Open another dialog to get a custom name prefix
378  bool ok;
379  QString msg2 = tr( "Enter optional suffix text to the"
380  " model description.<br/> Use alphumeric"
381  " characters, underscores, or hyphens<br/>"
382  " (no spaces). Enter 1 to 20 characters." );
383  suffix = QInputDialog::getText( this,
384  tr( "Model Description Suffix" ),
385  msg2,
386  QLineEdit::Normal,
387  suffix,
388  &ok );
389 
390  if ( !ok ) return;
391 
392  suffix.remove( QRegExp( "[^\\w\\d_-]" ) );
393 
394  if ( suffix.length() > 20 ) suffix = suffix.left( 20 );
395  cmfdesc = now + ftype + suffix + fext;
396  }
397 
398  // Output the constraints model
400  cmodel.description = cmfdesc;
401  cmodel.modelGUID = modelGuid;
402  int code;
403 
404  if ( dkdb_cntrls->db() )
405  {
406  US_Passwd pw;
407  US_DB2 db( pw.getPasswd() );
408 
409  code = cmodel.write( &db );
410  }
411  else
412  {
413  bool newFile;
414  QString fnameo = US_Model::get_filename( modelPath, modelGuid, newFile );
415  code = cmodel.write( fnameo );
416  }
417 
418  QString mtitle = tr( "Constraints Model Saving ..." );
419 
420  if ( code == US_DB2::OK )
421  {
422  QString destination = dkdb_cntrls->db() ?
423  tr( "local disk and database." ) :
424  tr( "local disk." );
425  QMessageBox::information( this, mtitle,
426  tr( "The file \"" ) + cmodel.description
427  + tr( "\"\n was successfully saved to " ) + destination );
428  }
429  else
430  {
431  QMessageBox::warning( this, mtitle,
432  tr( "Writing the file \"" ) + cmodel.description
433  + tr( "\"\n resulted in error code %1 ." ).arg( code ) );
434  }
435 }
436 
437 // Slot to handle a dialog change in the disk/db selection
439 {
440  if ( isDB )
441  dkdb_cntrls->set_db();
442  else
444 
445  sctm_id = startTimer( 1000 );
446  le_status->setText( tr( "Scanning models for unassigned edits" ) );
447  qApp->processEvents();
448 }
449 
450 // Slot to handle a model changed in the model editor
452 {
453  bmodel = new_model;
454 }
455 
456 // Protected slot to filter timer event and handle model-scan delay
457 void US_DMGA_Init::timerEvent( QTimerEvent* event )
458 {
459  const QString uaeditID( "1" );
460  int tm_id = event->timerId();
461 DbgLv(1) << "dGA:tmEv: tm_id" << tm_id << sctm_id;
462 
463  if ( tm_id != sctm_id )
464  { // If other than scan delay, pass it on to the normal handler
465  QObject::timerEvent( event );
466  return;
467  }
468 
469  // Otherwise, count and display models with unassigned edit
470  QApplication::setOverrideCursor( QCursor( Qt::WaitCursor ) );
471  QString atypeMan = QString::number( US_Model::MANUAL );
472  QString atypeCgr = QString::number( US_Model::CUSTOMGRID );
473  QString atypeDga = QString::number( US_Model::DMGA_CONSTR );
474 DbgLv(1) << " Atype Man Cgr Dga" << atypeMan << atypeCgr << atypeDga;
475  qApp->processEvents();
476  QTime timer;
477  QStringList mdlIDs;
478  QString invID = QString::number( US_Settings::us_inv_ID() );
479  timer.start();
480  int numodel = 0;
481  int ndmodel = 0;
482  int nmmodel = 0;
483  int ncmodel = 0;
484  int nlmodel = 0;
485 DbgLv(1) << " Timing(count_models)" << timer.elapsed();
486  if ( dkdb_cntrls->db() )
487  { // Scan models in the database
488  US_Passwd pw;
489  US_DB2 db( pw.getPasswd() );
490  QStringList qry;
491  qry << "count_models_by_editID" << invID << uaeditID;
492  numodel = db.functionQuery( qry );
493 
494  if ( numodel > 0 )
495  { // If there are models unassigned to edits, scan them
496  qry.clear();
497  qry << "get_model_desc_by_editID" << invID << uaeditID;
498  db.query( qry );
499 
500  while ( db.next() )
501  {
502  QString mdlID = db.value( 0 ).toString();
503  QString mdesc = db.value( 2 ).toString();
504  QString edtGID = db.value( 5 ).toString();
505  int edtID = db.value( 6 ).toString().toInt();
506 
507  if ( !mdesc.contains( "Custom" ) )
508  {
509  mdlIDs << mdlID;
510  nlmodel++;
511  }
512 DbgLv(1) << " mdlID" << mdlID << "mdesc" << mdesc << "editID" << edtID
513  << "editGUID" << edtGID;
514  }
515 DbgLv(1) << " Timing(get_model_desc)" << timer.elapsed();
516 
517  // Scan to parse analysis types
518  for ( int ii = 0; ii < nlmodel; ii++ )
519  {
520  QString mdlID = mdlIDs[ ii ];
521  qry.clear();
522  qry << "get_model_info" << mdlID;
523  db.query( qry );
524  db.next();
525  QString xmlmdl = db.value( 2 ).toString();
526  int jj = xmlmdl.indexOf( "analysisType=" );
527  QString atype = xmlmdl.mid( jj, 40 ).section( "\"", 1, 1 );
528 DbgLv(1) << " mdlID" << mdlID << "atype" << atype << "jj" << jj;
529 
530  if ( atype == atypeDga )
531  ndmodel++;
532  else if ( atype == atypeCgr )
533  ncmodel++;
534  else if ( atype == atypeMan )
535  nmmodel++;
536  }
537 DbgLv(1) << " Timing(get_model_info)" << timer.elapsed();
538  }
539  }
540 
541  else
542  { // Scan local disk models
543  const QString uaGUID( "00000000-0000-0000-0000-000000000000" );
544  QString path = US_Settings::dataDir() + "/models";
545  QDir dir;
546  if ( !dir.exists( path ) )
547  dir.mkpath( path );
548  dir = QDir( path );
549  QStringList mfilt( "M*.xml" );
550  QStringList f_names = dir.entryList( mfilt, QDir::Files, QDir::Name );
551  QXmlStreamAttributes attr;
552 
553  for ( int ii = 0; ii < f_names.size(); ii++ )
554  {
555  QString fname( path + "/" + f_names[ ii ] );
556  QFile m_file( fname );
557  if ( !m_file.open( QIODevice::ReadOnly | QIODevice::Text ) )
558  continue;
559  QXmlStreamReader xml( &m_file );
560 
561  while( ! xml.atEnd() )
562  {
563  xml.readNext();
564  if ( xml.isStartElement() && xml.name() == "model" )
565  {
566  attr = xml.attributes();
567  QString edGUID = attr.value( "editGUID" ).toString();
568 
569  if ( ! edGUID.isEmpty() && edGUID != uaGUID )
570  continue;
571 
572  numodel++;
573 
574  QString atype = attr.value( "analysisType" ).toString();
575 
576  if ( atype == atypeDga )
577  ndmodel++;
578  else if ( atype == atypeCgr )
579  ncmodel++;
580  else if ( atype == atypeMan )
581  nmmodel++;
582  }
583  }
584 
585  m_file.close();
586  }
587  }
588 
589 DbgLv(1) << " numodel" << numodel << "ndmodel ncmodel nmmodel"
590  << ndmodel << ncmodel << nmmodel;
591 
592  le_status->setText( tr( "%1 unassigned-edit models found"
593  " (%2 Manual, %3 DMGA, %4 CGrid)" )
594  .arg( numodel ).arg( nmmodel ).arg( ndmodel ).arg( ncmodel ) );
595  QApplication::restoreOverrideCursor();
596  QApplication::restoreOverrideCursor();
597  qApp->processEvents();
598 
599  killTimer( tm_id );
600  return;
601 }
602