UltraScan III
us_combine_models.cpp
Go to the documentation of this file.
1 
3 #include <QApplication>
4 
5 #include "us_combine_models.h"
6 #include "us_settings.h"
7 #include "us_gui_settings.h"
8 #include "us_constants.h"
9 #include "us_license_t.h"
10 #include "us_license.h"
11 #include "us_passwd.h"
12 #include "us_editor.h"
13 #include "us_select_runs.h"
14 #include "us_model_loader.h"
15 #include "us_db2.h"
16 #include "us_util.h"
17 #include "us_sleep.h"
18 
19 // main program
20 int main( int argc, char* argv[] )
21 {
22  QApplication application( argc, argv );
23 
24  #include "main1.inc"
25 
26  // License is OK. Start up.
27 
29  w.show();
30  return application.exec();
31 }
32 
33 // US_CombineModels class constructor
35 {
36  // set up the GUI
37  setWindowTitle( tr( "Create Global Model" ) );
38  setPalette( US_GuiSettings::frameColor() );
40  mfilter = QString( "" );
41 
42  // primary layout
43  QGridLayout* mainLayout = new QGridLayout( this );
44  mainLayout->setSpacing ( 2 );
45  mainLayout->setContentsMargins( 2, 2, 2, 2 );
46 
47  // fill in the GUI components
48  QLabel* lb_main = us_label( tr( "Combine Models for Global Fit" ) );
49  pb_prefilt = us_pushbutton( tr( "Select PreFilter" ) );
50  le_prefilt = us_lineedit ( "", -1, true );
51  pb_add = us_pushbutton( tr( "Add Models" ) );
52  pb_reset = us_pushbutton( tr( "Reset List" ) );
53  pb_save = us_pushbutton( tr( "Save Global Model" ) );
54  pb_help = us_pushbutton( tr( "Help" ) );
55  pb_close = us_pushbutton( tr( "Close" ) );
59 
60  int row = 0;
61  mainLayout->addWidget( lb_main, row++, 0, 1, 4 );
62  mainLayout->addWidget( lw_models, row++, 0, 1, 4 );
63  mainLayout->addLayout( dkdb_cntrls, row++, 0, 1, 4 );
64  mainLayout->addWidget( pb_prefilt, row, 0, 1, 1 );
65  mainLayout->addWidget( le_prefilt, row++, 1, 1, 3 );
66  mainLayout->addWidget( pb_add, row, 0, 1, 2 );
67  mainLayout->addWidget( pb_reset, row++, 2, 1, 2 );
68  mainLayout->addWidget( pb_save, row, 0, 1, 2 );
69  mainLayout->addWidget( pb_help, row, 2, 1, 1 );
70  mainLayout->addWidget( pb_close, row++, 3, 1, 1 );
71 
72  connect( pb_prefilt, SIGNAL( clicked() ),
73  this, SLOT( select_filt() ) );
74  connect( pb_add, SIGNAL( clicked() ),
75  this, SLOT( add_models() ) );
76  connect( pb_reset, SIGNAL( clicked() ),
77  this, SLOT( reset() ) );
78  connect( pb_close, SIGNAL( clicked() ),
79  this, SLOT( close() ) );
80  connect( pb_help, SIGNAL( clicked() ),
81  this, SLOT( help() ) );
82  connect( pb_save, SIGNAL( clicked() ),
83  this, SLOT( save() ) );
84 
85  lw_models ->setToolTip(
86  tr( "List of models to combine for a global model" ) );
87  pb_prefilt->setToolTip(
88  tr( "Choose RunIDs to pre-filter the models list" ) );
89  le_prefilt->setToolTip(
90  tr( "Chosen RunID pre-filter to the models list" ) );
91  pb_add ->setToolTip(
92  tr( "Add to the list of component models" ) );
93  pb_reset ->setToolTip(
94  tr( "Clear the models list to allow re-selection" ) );
95  pb_help ->setToolTip(
96  tr( "Display detailed US_CombineModels documentation text and images" ) );
97  pb_close ->setToolTip(
98  tr( "Close the US_CombineModels window and exit" ) );
99  pb_save ->setToolTip(
100  tr( "Create a global model from the listed component models" ) );
101  pb_reset->setEnabled( false );
102  pb_save ->setEnabled( false );
103 
104  rbtn_click = false;
105  runsel = true;
106  latest = true;
107 
108  setMinimumSize( 480, 200 );
109  adjustSize();
110  show();
111 }
112 
113 // Filter events to catch right-mouse-button-click on tree widget
114 bool US_CombineModels::eventFilter( QObject *obj, QEvent *e )
115 {
116  if ( obj->objectName() == "tree-widget" &&
117  e->type() == QEvent::ContextMenu )
118  { // catch tree row right-mouse click
119  rbtn_click = true;
120 DbgLv(1) << "eventFilter rbtn_click" << rbtn_click;
121  return false;
122  }
123 
124  else
125  { // pass all others for normal handling
126  return US_Widgets::eventFilter( obj, e );
127  }
128 }
129 
130 // Add selected model(s) to list of component models
132 {
133  bool loadDB = dkdb_cntrls->db();
134  QList< US_Model > tmodels;
135  QStringList tmdescs;
136  QApplication::setOverrideCursor( QCursor( Qt::WaitCursor ) );
137  US_ModelLoader dialog( loadDB, mfilter, tmodels, tmdescs, pfilts );
138  dialog.move( this->pos() + QPoint( 200, 200 ) );
139 
140  connect( &dialog, SIGNAL( changed( bool ) ),
141  this, SLOT( update_disk_db( bool ) ) );
142  QApplication::restoreOverrideCursor();
143 
144  if ( dialog.exec() != QDialog::Accepted )
145  return; // No selection was made
146 
147 
148  for ( int jj = 0; jj < tmodels.count(); jj++ )
149  {
150  QString desc = tmdescs[ jj ];
151  QString sepa = desc.left( 1 );
152  QString mdesc = desc.section( sepa, 1, 1 );
153  lw_models->addItem( mdesc );
154  this->models << tmodels[ jj ];
155  this->mdescs << mdesc;
156  }
157 
158  pb_reset->setEnabled( true );
159  pb_save ->setEnabled( models.size() > 1 );
160 }
161 
162 // View
164 {
165  models .clear();
166  mdescs .clear();
167  lw_models->clear();
168  pb_reset ->setEnabled( false );
169  pb_save ->setEnabled( false );
170 }
171 
172 // Save
174 {
175  const int mxtotrl = 60;
176  QStringList runIDs;
177  int nmodels = models.size();
178 qDebug() << "SAVE: nmodels" << nmodels;
179  // Initialize output combo model from first input
180  US_Model cmodel = models[ 0 ];
181  int ncomps = cmodel.components.size();
182  QString runID = mdescs[ 0 ].section( ".", 0, -4 );
183  runIDs << runID;
184  cmodel.update_coefficients();
185 
186  for ( int ii = 1; ii < nmodels; ii++ )
187  { // Add components from the remainder of the models
188  US_Model* imodel = &models[ ii ];
189 
190  imodel->update_coefficients();
191  int kcomps = imodel->components.size();
192  runID = mdescs[ ii ].section( ".", 0, -4 );
193 
194  if ( !runIDs.contains( runID ) )
195  runIDs << runID; // Build the list of unique run IDs
196 
197  for ( int jj = 0; jj < kcomps; jj++ )
198  { // Add model components to the combo model
199  bool dupc = false;
200  US_Model::SimulationComponent sc = imodel->components[ jj ];
201 
202  for ( int kk = 0; kk < ncomps; kk++ )
203  { // See if this component already exists
204  if ( sc.s == cmodel.components[ kk ].s &&
205  sc.f_f0 == cmodel.components[ kk ].f_f0 )
206  { // This component is a duplicate, so break
207  dupc = true;
208  break;
209  }
210  }
211 
212  if ( dupc ) continue; // Skip adding a duplicate component
213 
214  ncomps++;
215  sc.name = QString().sprintf( "SC%04d", ncomps );
216  cmodel.components << sc; // Add a component and bump count
217  }
218  }
219 qDebug() << "SAVE: ncomps" << ncomps << cmodel.components.size();
220 qDebug() << "SAVE: nrunIDs" << runIDs.size();
221 
222  // Default output name derives from the name of the first input
223  cmodel_name = "global-" + mdescs[ 0 ];
224  QString mdlbnam = cmodel_name.section( ".", 0, -3 ) + ".";
225  QString mdlanno = cmodel_name.section( ".", -2, -2 );
226  QString mdlaedt = mdlanno.section( "_", 0, 0 ) + "_";
227  QString mdlaanl = "a" + QDateTime::currentDateTime().toString( "yyMMddhhmm" ) + "_";
228  QString mdlatyp = mdlanno.section( "_", 2, 2 ).section( "-", 0, 0 ) + "-GL";
229  QString mdliter = "_local_i01.model";
230  cmodel_name = mdlbnam + mdlaedt + mdlaanl + mdlatyp + mdliter;
231 qDebug() << "SAVE: cmodel_name" << cmodel_name;
232  QString mdlguid = US_Util::new_guid();
233  cmodel.modelGUID = mdlguid;
234  cmodel.requestGUID = mdlguid;
235  cmodel.global = US_Model::GLOBAL;
236  cmodel.monteCarlo = false;
237 
238  // Open a dialog that reports and allows modification of description
239  runID = cmodel_name.section( ".", 0, -4 );
240  QString odesc = cmodel_name.section( ".", -3, -1 );
241  QMessageBox mbox;
242 
243  QString msg1 = tr( "An output combined model has been created. "
244  "It's description is:<br/><b>" )
245  + cmodel_name + "</b>.<br/><br/>"
246  + tr( "It combines %1 models with a total of %2 components. "
247  "Click:<br/><br/>" )
248  .arg( nmodels ).arg( ncomps )
249  + tr( " <b>OK</b> to output the model as is;<br/>"
250  " <b>Edit</b> to modify the model description (runID);<br/>"
251  " <b>Cancel</b> to abort model creation.<br/>" );
252 
253  mbox.setWindowTitle( tr( "Save Global Model" ) );
254  mbox.setText ( msg1 );
255  QPushButton *pb_ok = mbox.addButton( tr( "OK" ),
256  QMessageBox::YesRole );
257  QPushButton *pb_edit = mbox.addButton( tr( "Edit" ) ,
258  QMessageBox::AcceptRole );
259  QPushButton *pb_canc = mbox.addButton( tr( "Cancel" ),
260  QMessageBox::RejectRole );
261  mbox.setEscapeButton ( pb_canc );
262  mbox.setDefaultButton( pb_ok );
263 
264  mbox.exec();
265 
266  if ( mbox.clickedButton() == pb_canc ) return;
267 
268  if ( mbox.clickedButton() == pb_edit )
269  { // Open another dialog to get a modified runID
270  bool ok;
271  bool getruni = true;
272 
273  while ( getruni )
274  {
275  int curriln = runID.length();
276  QString msg2 = tr( "The default run ID for the output combined"
277  " model is <br/><b>" ) + runID + "</b>.<br/><br/>"
278  + tr( "You may modify this part of the model description"
279  " (currently %1 characters).<br/>"
280  "Use alphanumeric characters, underscores, or hyphens"
281  " (no spaces).<br/>"
282  "Enter so the total is from 3 to %2 characters.<br/><br/>"
283  "It is <b>strongly</b> recommended that you only"
284  " <b>append</b> any descriptive string to the original<br/>"
285  "runID in order to facilitate finding the model in"
286  " subsequent model loader dialogs." )
287  .arg( curriln ).arg( mxtotrl );
288  runID = QInputDialog::getText( this,
289  tr( "Modify Global Model Description RunID" ),
290  msg2, QLineEdit::Normal, runID, &ok );
291 
292  if ( !ok ) return;
293 
294  runID.remove( QRegExp( "[^\\w\\d_-]" ) );
295  int slen = runID.length();
296  getruni = false;
297 
298  if ( slen < 3 )
299  runID += QString( "GLO" ).left( 3 - slen );
300 
301  else if ( slen > mxtotrl )
302  {
303  runID = runID.left( mxtotrl );
304  getruni = true;
305  }
306  }
307 
308  cmodel_name = runID + "." + odesc;
309 qDebug() << "SAVE: (2)cmodel_name" << cmodel_name;
310  }
311 
312  cmodel.description = cmodel_name;
313 
314  // Output the combined model
315  if ( dkdb_cntrls->db() )
316  {
317  US_Passwd pw;
318  US_DB2 db( pw.getPasswd() );
319  cmodel.write( &db );
320 qDebug() << "SAVE: DB";
321  }
322 
323  else
324  {
325  bool newFile;
326  QString mdlpath;
327  US_Model::model_path( mdlpath );
328  QString fnamo = US_Model::get_filename( mdlpath, mdlguid, newFile );
329  cmodel.write( fnamo );
330 qDebug() << "SAVE: fnamo" << fnamo;
331  }
332 
333 }
334 
335 // Update DB/Disk setting from the model loader dialog
337 {
338  if ( isDB )
339  dkdb_cntrls->set_db();
340  else
342 }
343 
344 // Select RunID/Edit prefilter of models list
346 {
347  QString pfmsg;
348  int nruns = 0;
349  pfilts.clear();
350 
351  US_SelectRuns srdiag( dkdb_cntrls->db(), pfilts );
352  srdiag.move( this->pos() + QPoint( 200, 200 ) );
353  connect( &srdiag, SIGNAL( dkdb_changed ( bool ) ),
354  this, SLOT ( update_disk_db( bool ) ) );
355 
356  if ( srdiag.exec() == QDialog::Accepted )
357  nruns = pfilts.size();
358  else
359  pfilts.clear();
360 
361  if ( nruns == 0 )
362  pfmsg = tr( "(none chosen)" );
363 
364  else if ( nruns == 1 )
365  pfmsg = tr( "RunID prefilter - 1 run: " )
366  + QString( pfilts[ 0 ] ).left( 20 ) + "...";
367 
368  else
369  pfmsg = tr( "RunID prefilter - %1 runs: " ).arg( nruns )
370  + QString( pfilts[ 0 ] ).left( 20 ) + "*,...";
371 
372  le_prefilt->setText( pfmsg );
373 }
374