COPASI API  4.16.103
SliderDialog.cpp
Go to the documentation of this file.
1 // Copyright (C) 2010 - 2015 by Pedro Mendes, Virginia Tech Intellectual
2 // Properties, Inc., University of Heidelberg, and The University
3 // of Manchester.
4 // All rights reserved.
5 
6 // Copyright (C) 2008 - 2009 by Pedro Mendes, Virginia Tech Intellectual
7 // Properties, Inc., EML Research, gGmbH, University of Heidelberg,
8 // and The University of Manchester.
9 // All rights reserved.
10 
11 // Copyright (C) 2004 - 2007 by Pedro Mendes, Virginia Tech Intellectual
12 // Properties, Inc. and EML Research, gGmbH.
13 // All rights reserved.
14 
15 #include <iostream>
16 #include <sstream>
17 
18 //Added by qt3to4:
19 #include <QtGui/QContextMenuEvent>
20 #include <QtGui/QCloseEvent>
21 #include <QtGui/QMouseEvent>
22 #include <QtCore/QEvent>
23 
24 #include "copasi/UI/SliderDialog.h"
25 #include "copasi/UI/DataModelGUI.h"
29 #include "copasi/UI/ScanWidget.h"
30 #include "copasi/UI/CQMCAWidget.h"
31 #include "copasi/UI/CQLNAWidget.h"
35 #include "copasi/UI/CQMessageBox.h"
36 #include "copasi/UI/CopasiSlider.h"
37 #include "copasi/UI/listviews.h"
38 #include "copasi/UI/qtUtilities.h"
50 
51 #include "copasi/lna/CLNATask.h"
52 #include "copasi/scan/CScanTask.h"
56 #include "copasi/model/CModel.h"
59 
62 
63 size_t SliderDialog::numMappings = 14;
64 
65 size_t SliderDialog::folderMappings[][2] =
66 {
67  {21, 21}, {211, 21}, {23, 23}, {231, 23}, {24, 24},
68  {241, 24} , {31, 31}, {32, 32}, {321, 32}, {33, 33},
69  {331, 33}, {35, 35}, {28, 28}, {281, 28}
70 };
71 
72 //size_t SliderDialog::numKnownTasks = 4;
73 //size_t SliderDialog::[] = {21, 23, 24, 31};
74 //const char* SliderDialog::knownTaskNames[] = {"Steady State", "Time Course", "MCA" , "Scan"};
75 
76 SliderDialog::SliderDialog(QWidget* parent, const char* name, bool modal, Qt::WFlags fl):
77  CWindowInterface(parent, fl),
78  mpParentWindow(NULL),
79  mpContextMenu(NULL),
80  mpCurrSlider(NULL),
81  mSliderMap(),
82  mTaskMap(),
83  mCurrentFolderId(0),
84  mSliderValueChanged(false),
85  mSliderPressed(false),
86  mFramework(0),
87  mChanged(false)
88 {
89 #ifndef Darwin
91 #endif // not Darwin
92 
93  setupUi(this);
94 
96 
97  setObjectName(QString::fromUtf8(name));
98  setWindowTitle("Slider Window");
99 
100  mpSliderBox->layout()->addItem(new QSpacerItem(0, 5, QSizePolicy::Minimum, QSizePolicy::Expanding));
101 
102  this->mpContextMenu = new QMenu(this);
103  mpaCreateNewSlider = this->mpContextMenu->addAction("Add New Slider", this, SLOT(createNewSlider()));
104  mpaRemoveSlider = this->mpContextMenu->addAction("Remove Slider", this, SLOT(removeSlider()));
105  mpaEditSlider = this->mpContextMenu->addAction("Edit Slider", this, SLOT(editSlider()));
106  mpaResetValue = this->mpContextMenu->addAction("Reset Value", this, SLOT(resetValue()));
107  mpaSetDefault = this->mpContextMenu->addAction("Set new default value", this, SLOT(setDefault()));
108 
109  this->mSliderMap[C_INVALID_INDEX].push_back(new QLabel("<p>There are no sliders available for this task. If you select one of the tasks that supports sliders in the copasi object tree, this dialog will become active.</p>", mpSliderBox));
110 
113  this->mTaskMap[31] = &SliderDialog::runScanTask;
114  this->mTaskMap[24] = &SliderDialog::runMCATask;
115  this->mTaskMap[35] = &SliderDialog::runLNATask;
119 
120  connect(this->mpRunTaskButton, SIGNAL(clicked()), this, SLOT(runTask()));
121  connect(this->mpNewSliderButton, SIGNAL(clicked()), this, SLOT(createNewSlider()));
123  init();
124 }
125 
126 void SliderDialog::contextMenuEvent(QContextMenuEvent* e)
127 {
128  CopasiSlider* pSlider = findCopasiSliderAtPosition(e->pos());
129 
130  if (pSlider)
131  {
132  mpaCreateNewSlider->setEnabled(false);
133  mpaRemoveSlider->setEnabled(true);
134  mpaEditSlider->setEnabled(true);
135  setCurrentSlider(pSlider);
136  }
137  else
138  {
139  mpaCreateNewSlider->setEnabled(true);
140  mpaRemoveSlider->setEnabled(false);
141  mpaEditSlider->setEnabled(false);
142  }
143 
144  mpContextMenu->popup(e->globalPos());
145 }
146 
148 {
149  mpCurrSlider = pSlider;
150 
151  if (mpCurrSlider && isVisible())
152  {
154  }
155 }
156 
158 {
159  QWidget* pWidget = childAt(p);
160  CopasiSlider* pSlider = NULL;
161 
162  while (pWidget && pWidget != this && !pSlider)
163  {
164  pSlider = dynamic_cast<CopasiSlider*>(pWidget);
165  pWidget = (QWidget*)pWidget->parent();
166  }
167 
168  return pSlider;
169 }
170 
172 {
173  // allow the user to create more than one slider
174  std::vector<const CCopasiObject*> objects = CCopasiSelectionDialog::getObjectVector(this,
177  std::vector<CSlider*>* pVector = getCSlidersForCurrentFolderId();
178  std::vector<const CCopasiObject*>::const_iterator it = objects.begin(), endit = objects.end();
179  bool yesToAll = false;
180  bool noToAll = false;
181  // create the sliders for all the selected objects
182 
183  // first we need the task object because we need it later to associate the
184  // later with the correct task
186 
187  if (!object) return;
188 
189  CCopasiObject* pTmpObject = NULL;
190 
191  while (it != endit)
192  {
193  // create a new slider
194  assert((*it) != NULL);
195  pTmpObject = const_cast<CCopasiObject*>(determineCorrectObjectForSlider(*it));
196 
197  CSlider* pCSlider = new CSlider("slider", (*CCopasiRootContainer::getDatamodelList())[0]);
198 
199  if (pCSlider)
200  {
201  pCSlider->setSliderObject(pTmpObject);
202  pCSlider->setAssociatedEntityKey(object->getKey());
203  // check if a slider for that object already exists and if so, prompt
204  // the user what to do
205  CSlider* pEquivalentSlider = equivalentSliderExists(pCSlider);
206 
207  if (pEquivalentSlider != NULL)
208  {
209  CopasiSlider* pCopasiSlider = NULL;
210 
211  // if the user has specified yesToAll, we reset the ranges of all
212  // duplicate sliders
213  if (yesToAll)
214  {
215  pEquivalentSlider->resetRange();
216  // update the slider widget
217  pCopasiSlider = findCopasiSliderForCSlider(pEquivalentSlider);
218  assert(pCopasiSlider != NULL);
219 
220  if (pCopasiSlider != NULL)
221  {
222  pCopasiSlider->updateSliderData();
223  }
224  }
225  // if the user has not specified noToAll, we need to prompt
226  else if (!noToAll)
227  {
228  QMessageBox::StandardButton result = CQMessageBox::information(NULL, "Slider Exists",
229  "A slider for this object already exists.\n\nDo you want to reset the range of the slider?",
230  QMessageBox::Yes | QMessageBox::No | QMessageBox::YesToAll | QMessageBox::NoToAll, QMessageBox::No);
231 
232  // check the answer and maybe set some flags
233  switch (result)
234  {
235  case QMessageBox::YesToAll:
236  // set the flag
237  yesToAll = true;
238 
239  case QMessageBox::Yes:
240  // reset the range
241  pEquivalentSlider->resetRange();
242  // update the slider widget
243  pCopasiSlider = findCopasiSliderForCSlider(pEquivalentSlider);
244  assert(pCopasiSlider != NULL);
245 
246  if (pCopasiSlider != NULL)
247  {
248  pCopasiSlider->updateSliderData();
249  }
250 
251  break;
252 
253  case QMessageBox::NoToAll:
254  // set the flag
255  noToAll = true;
256  break;
257 
258  case QMessageBox::No:
259  // do nothing else
260  break;
261 
262  default:
263  // do nothing
264  break;
265  }
266  }
267 
268  delete pCSlider;
269  }
270  else
271  {
272  std::vector<CCopasiContainer*> listOfContainers;
273  assert(CCopasiRootContainer::getDatamodelList()->size() > 0);
274  listOfContainers.push_back((*CCopasiRootContainer::getDatamodelList())[0]->getModel());
275  pCSlider->compile(listOfContainers);
276  pCSlider->resetRange();
277  addSlider(pCSlider);
278  mChanged = true;
279  }
280  }
281 
282  ++it;
283  }
284 
285  delete pVector;
286 }
287 
289 {
290  if (mpCurrSlider)
291  {
292  assert(CCopasiRootContainer::getDatamodelList()->size() > 0);
293  CCopasiVector<CSlider>* pSliderList = (*CCopasiRootContainer::getDatamodelList())[0]->getGUI()->getSliderList();
294  size_t i, maxCount = pSliderList->size();
295 
296  for (i = 0; i < maxCount; ++i)
297  {
298  CSlider* pTmpSlider = (*pSliderList)[i];
299 
300  if (pTmpSlider == mpCurrSlider->getCSlider())
301  {
302  pSliderList->remove(i);
303  break;
304  }
305  }
306 
308  mpCurrSlider = NULL;
309  }
310 }
311 
313 {
314  if (pSlider)
315  {
316  std::vector<QWidget*>* v = &mSliderMap[mCurrentFolderId];
317  std::vector<QWidget*>::iterator it = v->begin();
318  std::vector<QWidget*>::iterator end = v->end();
319 
320  while (it != end)
321  {
322  if (*it == pSlider)
323  {
324  break;
325  }
326 
327  ++it;
328  }
329 
330  assert(it != end);
331  v->erase(it);
332  mpSliderBox->layout()->removeWidget(pSlider);
333  pdelete(pSlider);
334  mChanged = true;
335  }
336 }
337 
339 {
340  SliderSettingsDialog* pSettingsDialog = new SliderSettingsDialog(this);
341  assert(CCopasiRootContainer::getDatamodelList()->size() > 0);
342  pSettingsDialog->setModel((*CCopasiRootContainer::getDatamodelList())[0]->getModel());
343  // set the list of sliders that is already known
345 
346  if (!object) return;
347 
348  std::vector<CSlider*>* pVector = getCSlidersForCurrentFolderId();
349  pSettingsDialog->setDefinedSliders(*pVector);
350 
351  //pSettingsDialog->disableObjectChoosing(true);
352 
353  pSettingsDialog->setSlider(mpCurrSlider->getCSlider());
354 
355  if (pSettingsDialog->exec() == QDialog::Accepted)
356  {
357  addSlider(pSettingsDialog->getSlider());
359  /*
360  if ((!mpCurrSlider->isEnabled()) && mpCurrSlider->getCSlider()->compile())
361  {
362  mpCurrSlider->setEnabled(true);
363  }
364  */
365  }
366 
367  delete pSettingsDialog;
368  delete pVector;
369 }
370 
372 {
373  this->clear();
375  delete mpRunTaskButton;
376  delete mpAutoRunCheckBox;
377  delete mpAutoModifyRangesCheckBox;
378  delete mpSliderBox;
379  delete mpScrollView;
380 }
381 
383 {
384  this->clearSliderBox();
385  size_t j, maxWidgets;
386 
387  std::map< size_t, std::vector< QWidget* > >::iterator it = mSliderMap.begin();
388 
389  while (it != mSliderMap.end())
390  {
391  std::vector<QWidget*> v = it->second;
392  maxWidgets = v.size();
393 
394  for (j = 0; j < maxWidgets; ++j)
395  {
396  pdelete(v[j]);
397  }
398 
399  ++it;
400  }
401 
402  this->mSliderMap.clear();
403 }
404 
406 {}
407 
409 {
410  if (mpParentWindow == NULL)
411  return;
412 
413  // check if there already is a slider for this object
414  assert(CCopasiRootContainer::getDatamodelList()->size() > 0);
415  SCopasiXMLGUI* pGUI = (*CCopasiRootContainer::getDatamodelList())[0]->getGUI();
416  assert(pGUI);
417 
418  if (!equivalentSliderExists(pSlider))
419  {
420  std::vector<CCopasiContainer*> listOfContainers;
421  assert(CCopasiRootContainer::getDatamodelList()->size() > 0);
422  listOfContainers.push_back((*CCopasiRootContainer::getDatamodelList())[0]->getModel());
423  pSlider->compile(listOfContainers);
424  pGUI->getSliderList()->add(pSlider, true);
425  }
426 
428 
429  if (!tmp)
430  {
431  setCurrentSlider(new CopasiSlider(pSlider, mpParentWindow->getDataModel(), mpSliderBox));
432  mpCurrSlider->installEventFilter(this);
433  mpCurrSlider->setHidden(true);
435  // make sure the slider points to the correct object
436  // for the currently set framework
439  QBoxLayout* layout = static_cast<QBoxLayout*>(mpSliderBox->layout());
440  int childCount = layout->count() - 1;
441  layout->insertWidget(childCount, mpCurrSlider);
442  connect(mpCurrSlider, SIGNAL(valueChanged(double)), this , SLOT(sliderValueChanged()));
443  connect(mpCurrSlider, SIGNAL(sliderReleased()), this, SLOT(sliderReleased()));
444  connect(mpCurrSlider, SIGNAL(sliderPressed()), this, SLOT(sliderPressed()));
445  connect(mpCurrSlider, SIGNAL(closeClicked(CopasiSlider*)), this, SLOT(removeSlider(CopasiSlider*)));
446  connect(mpCurrSlider, SIGNAL(editClicked(CopasiSlider*)), this, SLOT(editSlider(CopasiSlider*)));
447  mpCurrSlider->setHidden(false);
448  mChanged = true;
449  }
450  else
451  {
452  mpCurrSlider = tmp;
453  }
454 }
455 
457 {
458  CSlider* pResult = NULL;
459  assert(CCopasiRootContainer::getDatamodelList()->size() > 0);
460  SCopasiXMLGUI* pGUI = (*CCopasiRootContainer::getDatamodelList())[0]->getGUI();
461  assert(pGUI);
462  size_t i, maxCount = pGUI->getSliderList()->size();
463 
464  for (i = 0; i < maxCount; ++i)
465  {
466  CSlider* pTmpSlider = (*(pGUI->getSliderList()))[i];
467 
468  if (pTmpSlider->getSliderObject() == pCSlider->getSliderObject() && pTmpSlider->getAssociatedEntityKey() == pCSlider->getAssociatedEntityKey())
469  {
470  pResult = pTmpSlider;
471  break;
472  }
473  }
474 
475  return pResult;
476 }
477 
479 {
480  CopasiSlider* pResult = NULL;
481  std::vector<QWidget*> v = mSliderMap[mCurrentFolderId];
482  size_t i, maxCount = v.size();
483  CopasiSlider* pTmpSlider;
484 
485  for (i = 0; i < maxCount; ++i)
486  {
487  pTmpSlider = dynamic_cast<CopasiSlider*>(v[i]);
488 
489  if (!pTmpSlider) break;
490 
491  if (pTmpSlider->getCSlider() == pCSlider)
492  {
493  pResult = pTmpSlider;
494  break;
495  }
496  }
497 
498  return pResult;
499 }
500 
502 {
503  id = mapFolderId2EntryId(id);
504 
505  if (id == mCurrentFolderId) return;
506 
507  if (id == C_INVALID_INDEX || !this->mpParentWindow->isEnabled())
508  {
509  setEnabled(false);
510  }
511  else
512  {
513  setEnabled(true);
514  }
515 
516  clearSliderBox();
517  mCurrentFolderId = id;
518 
519  // Set appropriate window title
520  QString thisWindowTitle = "Sliders";
521 
522  switch (id)
523  {
524  case 23:
525  thisWindowTitle = "Time Course " + thisWindowTitle;
526  break;
527 
528  case 21:
529  thisWindowTitle = "Steady-State " + thisWindowTitle;
530  break;
531 
532  case 31:
533  thisWindowTitle = "Parameter Scan " + thisWindowTitle;
534  break;
535 
536  case 24:
537  thisWindowTitle = "Metabolic Control Analysis " + thisWindowTitle;
538  break;
539 
540  case 35:
541  thisWindowTitle = "Linear Noise Approximation " + thisWindowTitle;
542  break;
543 
544  case 33:
545  thisWindowTitle = "Parameter Estimation " + thisWindowTitle;
546  break;
547 
548  case 32:
549  thisWindowTitle = "Optimization " + thisWindowTitle;
550  break;
551 
552  case 28:
553  thisWindowTitle = "Cross Section " + thisWindowTitle;
554  break;
555  }
556 
557  setWindowTitle(thisWindowTitle);
558 
559  fillSliderBox();
560 }
561 
562 CSlider *SliderDialog::getCSliderForCopasiSlider(std::vector<CSlider*>& v, QWidget* slider)
563 {
564  CopasiSlider* pTmpSlider = dynamic_cast<CopasiSlider*>(slider);
565 
566  if (!pTmpSlider) return NULL;
567 
568  std::vector<CSlider*>::const_iterator it;
569 
570  for (it = v.begin(); it != v.end(); ++it)
571  {
572  if (pTmpSlider->getCSlider() == *it)
573  {
574  return *it;
575  }
576  }
577 
578  return NULL;
579 }
580 
582 {
583  std::vector<QWidget*>::const_iterator it;
584 
585  for (it = v.begin(); it != v.end(); ++it)
586  {
587  CopasiSlider* pTmpSlider = dynamic_cast<CopasiSlider*>(*it);
588 
589  if (!pTmpSlider) break;
590 
591  if (pTmpSlider->getCSlider() == slider)
592  {
593  return pTmpSlider;
594  }
595  }
596 
597  return NULL;
598 }
599 
600 void SliderDialog::createSlidersForFolder(std::vector<QWidget*>& v)
601 {
603  return;
604 
605  std::vector<CSlider*>* pVector = getCSlidersForCurrentFolderId();
606  std::vector<CSlider*>::const_iterator it;
607  std::vector<QWidget*>::const_iterator wIt;
608  // maybe other program parts have added or deleted some sliders
609  assert(pVector);
610 
611  // add CopasiSlider for all CSliders that don't have one.
612  bool issueWarning = false;
613 
614  for (it = pVector->begin(); it != pVector->end(); ++it)
615  {
616  //bool found = false;
617 
618  // check whether we have a slider
619  CopasiSlider* pTmpSlider = getCopasiSliderForCSlider(v, *it);
620 
621  if (pTmpSlider != NULL) continue;
622 
623  // if not create one
624  setCurrentSlider(new CopasiSlider(*it, mpParentWindow->getDataModel(), mpSliderBox));
625  // make sure the slider points to the correct object
626  // for the currently set framework
628  connect(mpCurrSlider, SIGNAL(valueChanged(double)), this , SLOT(sliderValueChanged()));
629  connect(mpCurrSlider, SIGNAL(sliderReleased()), this, SLOT(sliderReleased()));
630  connect(mpCurrSlider, SIGNAL(sliderPressed()), this, SLOT(sliderPressed()));
631  connect(mpCurrSlider, SIGNAL(closeClicked(CopasiSlider*)), this, SLOT(removeSlider(CopasiSlider*)));
632  connect(mpCurrSlider, SIGNAL(editClicked(CopasiSlider*)), this, SLOT(editSlider(CopasiSlider*)));
633  mpCurrSlider->installEventFilter(this);
634  mpCurrSlider->setHidden(true);
636  }
637 
638  // delete CopasiSliders which have no correponding CSlider
639  for (wIt = v.begin(); wIt != v.end(); ++wIt)
640  {
641  bool found = getCSliderForCopasiSlider(*pVector, *wIt) != NULL;
642 
643  if (!found)
644  {
645  CopasiSlider* pTmpSlider = dynamic_cast<CopasiSlider*>(*wIt);
646  assert(pTmpSlider);
647  deleteSlider(pTmpSlider);
648  mChanged = true;
649  }
650  }
651 
652  if (issueWarning)
653  {
654  CQMessageBox::information(NULL, "Invalid Slider",
655  "One or more sliders are invalid and have been disabled!",
656  QMessageBox::Ok, QMessageBox::NoButton);
657  }
658 
659  delete pVector;
660 }
661 
663 {
664  if (mpParentWindow == NULL)
665  return;
666 
667  this->deleteInvalidSliders();
668  std::vector<QWidget*> v = mSliderMap[mCurrentFolderId];
669 
671 
673  size_t i, maxCount = v.size();
674 
675  for (i = maxCount; i != 0; --i)
676  {
677  QWidget* widget = v[i - 1];
678  widget->setHidden(true);
679  static_cast<QBoxLayout*>(mpSliderBox->layout())->insertWidget(0, widget);
680  setCurrentSlider(dynamic_cast<CopasiSlider*>(widget));
681 
682  if (mpCurrSlider)
683  {
684  // check if the slider value is determined by an expression
685  CModelEntity* pME = dynamic_cast<CModelEntity*>(this->mpCurrSlider->object()->getObjectParent());
686 
687  if (pME != NULL)
688  {
689  if (!pME->getInitialExpression().empty())
690  {
691  // we have to disable the slider widget and set a tooltip
692  // that explains why this slider is disabled
693  if (this->mpCurrSlider->isEnabled())
694  {
695  this->mpCurrSlider->setEnabled(false);
696  this->mpCurrSlider->setToolTip("This value is determined by an initial expression.");
697  }
698  }
699  else
700  {
701  // if the slider is disabled, we have to enable it and delete the tooltip
702  if (!this->mpCurrSlider->isEnabled())
703  {
704  this->mpCurrSlider->setEnabled(true);
705  this->mpCurrSlider->setToolTip("");
706  }
707  }
708  }
709 
711  }
712 
713  widget->setHidden(false);
714  }
715 }
716 
717 size_t SliderDialog::mapFolderId2EntryId(size_t folderId) const
718 {
719  size_t id = C_INVALID_INDEX;
720  size_t counter;
721 
722  for (counter = 0; counter < SliderDialog::numMappings; ++counter)
723  {
724  if (SliderDialog::folderMappings[counter][0] == folderId)
725  {
726  id = SliderDialog::folderMappings[counter][1];
727  break;
728  }
729  }
730 
731  return id;
732 }
733 
735 {
736  if (mpParentWindow == NULL
737  || !isEnabled()
738  || !mpParentWindow->isEnabled()
739  || mTaskMap.find(mCurrentFolderId) == mTaskMap.end())
740  return;
741 
743 
745  assert(pWidget != NULL);
746 
747  if (pWidget == NULL) return;
748 
749  // commit possible changes to the task widget before running the task
750  pWidget->leave();
751 
752  // execute task
753  ((this)->*(mTaskMap[mCurrentFolderId]))();
754 }
755 
757 {
758  mSliderValueChanged = true;
759 
760  if ((!mSliderPressed) && mpAutoRunCheckBox->isChecked()
762  {
763  CopasiSlider* slider = dynamic_cast<CopasiSlider*>(sender());
764 
765  if (slider != NULL && slider != mpCurrSlider)
766  setCurrentSlider(slider);
767 
768  mSliderValueChanged = false;
769  runTask();
770  }
771 }
772 
774 {
775  if (mSliderValueChanged && mpAutoRunCheckBox->isChecked())
776  {
777  mSliderValueChanged = false;
778  runTask();
779  }
780 
781  mSliderPressed = false;
782 }
783 
785 {
786  mSliderPressed = true;
787 }
788 
790 {
791  if (mpParentWindow)
792  {
793  assert(CCopasiRootContainer::getDatamodelList()->size() > 0);
794  mpParentWindow->getMainWidget()->getTrajectoryWidget()->enter((*(*CCopasiRootContainer::getDatamodelList())[0]->getTaskList())["Time-Course"]->getKey());
796  }
797 }
798 
800 {
801  if (mpParentWindow)
802  {
804  }
805 }
806 
808 {
809  if (mpParentWindow)
810  {
811  assert(CCopasiRootContainer::getDatamodelList()->size() > 0);
812  mpParentWindow->getMainWidget()->getScanWidget()->enter((*(*CCopasiRootContainer::getDatamodelList())[0]->getTaskList())["Scan"]->getKey());
814  }
815 }
816 
818 {
819  if (mpParentWindow)
820  {
821  assert(CCopasiRootContainer::getDatamodelList()->size() > 0);
822  mpParentWindow->getMainWidget()->getMCAWidget()->enter((*(*CCopasiRootContainer::getDatamodelList())[0]->getTaskList())["Metabolic Control Analysis"]->getKey());
824  }
825 }
826 
828 {
829  if (mpParentWindow)
830  {
831  assert(CCopasiRootContainer::getDatamodelList()->size() > 0);
832  mpParentWindow->getMainWidget()->getLNAWidget()->enter((*(*CCopasiRootContainer::getDatamodelList())[0]->getTaskList())["Linear Noise Approximation"]->getKey());
834  }
835 }
836 
838 {
839  if (mpParentWindow)
840  {
841  assert(CCopasiRootContainer::getDatamodelList()->size() > 0);
842  mpParentWindow->getMainWidget()->getFittingWidget()->enter((*(*CCopasiRootContainer::getDatamodelList())[0]->getTaskList())["Parameter Estimation"]->getKey());
844  }
845 }
846 
848 {
849  if (mpParentWindow)
850  {
851  assert(CCopasiRootContainer::getDatamodelList()->size() > 0);
852  mpParentWindow->getMainWidget()->getCrossSectionWidget()->enter((*(*CCopasiRootContainer::getDatamodelList())[0]->getTaskList())["Cross Section"]->getKey());
854  }
855 }
856 
858 {
859  if (mpParentWindow)
860  {
861  assert(CCopasiRootContainer::getDatamodelList()->size() > 0);
862  mpParentWindow->getMainWidget()->getOptimizationWidget()->enter((*(*CCopasiRootContainer::getDatamodelList())[0]->getTaskList())["Optimization"]->getKey());
864  }
865 }
866 
867 void SliderDialog::closeEvent(QCloseEvent* e)
868 {
869  CWindowInterface::closeEvent(e);
870 
871  if (mpParentWindow)
872  {
874  }
875 }
876 
878 {
879  folderId = mapFolderId2EntryId(folderId);
880  CCopasiTask* task = NULL;
881  assert(CCopasiRootContainer::getDatamodelList()->size() > 0);
882 
883  switch (folderId)
884  {
885  case 21:
886  task = dynamic_cast<CSteadyStateTask *>((*(*CCopasiRootContainer::getDatamodelList())[0]->getTaskList())["Steady-State"]);
887  break;
888 
889  case 23:
890  task = dynamic_cast<CTrajectoryTask *>((*(*CCopasiRootContainer::getDatamodelList())[0]->getTaskList())["Time-Course"]);
891  break;
892 
893  case 24:
894  task = dynamic_cast<CMCATask *>((*(*CCopasiRootContainer::getDatamodelList())[0]->getTaskList())["Metabolic Control Analysis"]);
895  break;
896 
897  case 31:
898  task = dynamic_cast<CScanTask *>((*(*CCopasiRootContainer::getDatamodelList())[0]->getTaskList())["Scan"]);
899  break;
900 
901  case 35:
902  task = dynamic_cast<CLNATask *>((*(*CCopasiRootContainer::getDatamodelList())[0]->getTaskList())["Linear Noise Approximation"]);
903  break;
904 
905  case 33:
906  task = dynamic_cast<CFitTask *>((*(*CCopasiRootContainer::getDatamodelList())[0]->getTaskList())["Parameter Estimation"]);
907  break;
908 
909  case 32:
910  task = dynamic_cast<COptTask *>((*(*CCopasiRootContainer::getDatamodelList())[0]->getTaskList())["Optimization"]);
911  break;
912 
913  case 28:
914  task = dynamic_cast<CCrossSectionTask *>((*(*CCopasiRootContainer::getDatamodelList())[0]->getTaskList())["Cross Section"]);
915  break;
916 
917  default:
918  task = NULL;
919  break;
920  }
921 
922  return task;
923 }
924 
926 {
927  if (!isVisible())
928  {
929  return;
930  }
931 
932  // this method might not always do what we want
933  // e.g. if we change a volume via a slider, the initial amount/concentrations
934  // of the species are updated automatically, but if there is a slider for the
935  // automatically updated value and we changed that value as well together with
936  // the volume, the change of amount/concentration is probably lost depending on
937  // the order of the sliders
938  // We need to do this in two rounds, first we set all the new values
939  //
940  // To solve this, I added a new argument to updateValue that determines if the call also updates the dependencies.
941  // Here we do not let the updateValue call update the dependencies, but we take care of this ourselves
942  // with a call to ListView::refreshInitialValues
943  if (mCurrentFolderId == C_INVALID_INDEX) return;
944 
945  bool autoModify = mpAutoModifyRangesCheckBox->isChecked();
946  this->deleteInvalidSliders();
947  std::vector<QWidget*> v = mSliderMap[mCurrentFolderId];
948  std::vector<QWidget*>::iterator wit = v.begin(), wendit = v.end();
949 
950  if (!v.empty())
951  {
952  // We make sure that all initial values of the model are up to date
953  // before we update the sliders.
954  if (mpParentWindow != NULL)
956 
957  // We go through the sliders and make sure that
958  // that the model values are updated.
959  wit = v.begin();
960  wendit = v.end();
961  CopasiSlider* pCopasiSlider = NULL;
962 
963  while (wit != wendit)
964  {
965  pCopasiSlider = dynamic_cast<CopasiSlider*>(*wit);
966 
967  if (pCopasiSlider)
968  {
969  pCopasiSlider->updateValue(autoModify, false);
970  pCopasiSlider->updateSliderData();
971  }
972 
973  ++wit;
974  }
975 
976  // We make sure that all dependent initial values of the model are up to date.
977  // Please note that this is context sensitive, i.e., concentration and particle numbers
978  // are dealt with correctly.
979  if (mpParentWindow != NULL)
981  }
982 }
983 
985 {
986  setCurrentSlider(slider);
987  removeSlider();
988 }
989 
991 {
992  setCurrentSlider(slider);
993  editSlider();
994 }
995 
996 std::vector<CSlider*>* SliderDialog::getCSlidersForObject(CCopasiObject* pObject, std::vector<CSlider*>* pVector) const
997 {
998  assert(CCopasiRootContainer::getDatamodelList()->size() > 0);
1000  assert(pDataModel != NULL);
1001  SCopasiXMLGUI* pGUI = pDataModel->getGUI();
1002  assert(pGUI);
1003  bool sliderDeleted = false;
1004  CCopasiVector<CSlider>* pSliderList = pGUI->getSliderList();
1005  assert(pSliderList);
1006  // go through the list in reverse so that items can be deleted
1007  size_t i, iMax = pSliderList->size();
1008  bool issueWarning = false;
1009 
1010  for (i = iMax; i > 0; --i)
1011  {
1012  CSlider* pSlider = (*pSliderList)[i - 1];
1013 
1014  if (sliderObjectChanged(pSlider))
1015  {
1016  if (!sliderDeleted)
1017  {
1018  CQMessageBox::information(NULL, "Missing slider objects",
1019  "One or more objects that had sliders defined have been deleted. Sliders will therefore be deleted as well.",
1020  QMessageBox::Ok | QMessageBox::Default, QMessageBox::NoButton);
1021  }
1022 
1023  pSliderList->remove(i - 1);
1024  sliderDeleted = true;
1025  }
1026  else
1027  {
1028  if (pSlider->getAssociatedEntityKey() == pDataModel->getModel()->getKey() || pSlider->getAssociatedEntityKey() == pObject->getKey())
1029  {
1030  if (!pSlider->compile())
1031  {
1032  issueWarning = true;
1033  }
1034 
1035  pVector->insert(pVector->begin(), pSlider);
1036  }
1037  }
1038  }
1039 
1040  return pVector;
1041 }
1042 
1044 {
1045  std::vector<QWidget*> v = mSliderMap[mCurrentFolderId];
1046  std::vector<QWidget*>::const_reverse_iterator it;
1047 
1048  for (it = v.rbegin(); it != v.rend(); ++it)
1049  {
1050  QWidget* widget = *it;
1051  widget->setHidden(true);
1052  mpSliderBox->layout()->removeWidget(widget);
1053  }
1054 }
1055 
1057 {
1059 
1060  if (!object) return NULL;
1061 
1062  std::vector<CSlider*>* pVector = new std::vector<CSlider*>();
1063 
1064  try
1065  {
1066  pVector = getCSlidersForObject(object, pVector);
1067  }
1068 
1069  catch (...) {}
1070 
1071  return pVector;
1072 }
1073 
1074 void SliderDialog::changeEvent(QEvent *event)
1075 {
1076  if (event->type() == QEvent::EnabledChange && isEnabled() && mpCurrSlider != NULL)
1077  {
1078  setFocus(Qt::OtherFocusReason);
1079  mpScrollView->setFocus(Qt::OtherFocusReason);
1080  mpSliderBox->setFocus(Qt::OtherFocusReason);
1082  }
1083 }
1084 
1085 bool SliderDialog::eventFilter(QObject*, QEvent* event)
1086 {
1087  QMouseEvent* pQME = dynamic_cast<QMouseEvent*>(event);
1088 
1089  if (pQME && pQME->type() == QEvent::MouseButtonPress && pQME->button() == Qt::LeftButton)
1090  {
1091  CopasiSlider* pSlider = findCopasiSliderAtPosition(mapFromGlobal(pQME->globalPos()));
1092  assert(pSlider);
1093  setCurrentSlider(pSlider);
1094  }
1095 
1096  return false;
1097 }
1098 
1100 {
1102 }
1103 
1105 {
1107 }
1108 
1110 {
1111  assert(CCopasiRootContainer::getDatamodelList()->size() > 0);
1112  CModel* pModel = (*CCopasiRootContainer::getDatamodelList())[0]->getModel();
1113  std::vector<CCopasiContainer*> listOfContainers;
1114  listOfContainers.push_back(pModel);
1115  return !pSlider->compile(listOfContainers);
1116 }
1117 
1119 {
1120  mpParentWindow = pPW;
1121 }
1122 
1123 // This method check if the given object is a reference to the initial amount or the initial concentration
1124 // of a metabolite. Then it checks the current framework and the metabolite if a slider to the object
1125 // is actually allowed and if it isn't, it will return the correct object
1127 {
1128  const CCopasiObject* pResult = NULL;
1129 
1130  if (pObject == NULL)
1131  {
1132  pResult = NULL;
1133  }
1134  else
1135  {
1136  CMetab* pMetab = dynamic_cast<CMetab*>((pObject)->getObjectParent());
1137  // we just assume the object is correct for the framework
1138  // this saves some additional test later on
1139  pResult = pObject;
1140 
1141  if (pMetab != NULL)
1142  {
1143  // now we have to check if the framework is the concentrations framework
1144  // and if we are actually allowed to change the concentration on a metabolite
1145  if (mFramework == 0)
1146  {
1147  // we are in the concentrations framework
1148  //
1149  // sometimes it is not allowed to change the concentration of a metabolite
1150  // because it would change the volume of the compartment
1151  if (pMetab->isInitialConcentrationChangeAllowed() && pObject == pMetab->getInitialValueReference())
1152  {
1153  // if the current object is for the concentration, we return a new object to the amount
1154  pResult = pMetab->getInitialConcentrationReference();
1155  assert(pResult != NULL);
1156  }
1157  }
1158  else
1159  {
1160  // we are in the particle number framework
1161  // if the object is for the amount, we leave it, otherwise we
1162  // return a new object for the amount
1163  if (pObject == pMetab->getInitialConcentrationReference())
1164  {
1165  pResult = pMetab->getInitialValueReference();
1166  assert(pResult != NULL);
1167  }
1168  }
1169  }
1170  }
1171 
1172  return pResult;
1173 }
1174 
1175 // sets the framework on the sliders dialog
1176 // This leads to changed sliders for metabolites
1177 // Because depending on the framework, we only allow sliders
1178 // for amount or concentration, but not both for the same metabolite
1179 void SliderDialog::setFramework(int framework)
1180 {
1181  mFramework = framework;
1182 
1183  bool changed = false;
1184  // we go through the sliders and check if the slider for species amount
1185  // or concentration are still appropriate for the framework that has been set
1186  std::map<size_t, std::vector<QWidget*> >::iterator it = this->mSliderMap.begin(), endit = this->mSliderMap.end();
1187  std::vector<QWidget*>::iterator it2, endit2;
1188  CopasiSlider* pSlider = NULL;
1189 
1190  while (it != endit)
1191  {
1192  it2 = it->second.begin();
1193  endit2 = it->second.end();
1194 
1195  while (it2 != endit2)
1196  {
1197  pSlider = dynamic_cast<CopasiSlider*>(*it2);
1198 
1199  if (pSlider != NULL)
1200  {
1201  const CCopasiObject* pTmpObj = pSlider->object();
1202  this->setCorrectSliderObject(pSlider);
1203 
1204  if (pSlider->object() != pTmpObj && !changed)
1205  {
1206  changed = true;
1207  }
1208  }
1209 
1210  ++it2;
1211  }
1212 
1213  ++it;
1214  }
1215 
1216  // we don't care if the change was for the current
1217  // task, we just update if there was any change at all
1218  if (changed == true)
1219  {
1220  this->update();
1221  }
1222 }
1223 
1224 /**
1225  * Takes a CopasiSlider object and checks if the associated model object
1226  * fits the currently set framework. If not, the slider object and the values are adjusted.
1227  *
1228  * On success, true is returned.
1229  */
1231 {
1232  if (pSlider == NULL)
1233  return false;
1234 
1235  CCopasiObject *pObject = NULL, *pTmpObject = NULL;
1236  pObject = pSlider->object();
1237 
1238  if (pObject == NULL)
1239  return false;
1240 
1241  pTmpObject = const_cast<CCopasiObject*>(this->determineCorrectObjectForSlider(pObject));
1242 
1243  if (pTmpObject != pObject)
1244  {
1245  // we have to recalculate the range
1246  double oldMin = pSlider->minValue();
1247  double oldMax = pSlider->maxValue();
1248  double oldValue = pSlider->value();
1249  // we have to set the new object on the slider
1250  pSlider->setObject(pTmpObject);
1251  double newValue = pSlider->value();
1252  double newMin = (oldMin / oldValue) * newValue;
1253  double newMax = (oldMax / oldValue) * newValue;
1254  pSlider->setMinValue(newMin);
1255  pSlider->setMaxValue(newMax);
1256  }
1257 
1258  return true;
1259 }
1260 
1261 void SliderDialog::showEvent(QShowEvent* pEvent)
1262 {
1263  // make sure only valid sliders are shown
1264  updateAllSliders();
1265  this->CWindowInterface::showEvent(pEvent);
1266 }
1267 
1269 {
1270  std::vector<QWidget*> &v = mSliderMap[mCurrentFolderId];
1271  std::vector<QWidget*>::iterator wit = v.begin(), wendit = v.end();
1272  bool sliderDeleted = false;
1273  CopasiSlider* pCopasiSlider = NULL;
1274 
1275  while (wit != wendit)
1276  {
1277  pCopasiSlider = dynamic_cast<CopasiSlider*>(*wit);
1278 
1279  if (pCopasiSlider && !pCopasiSlider->isValid())
1280  {
1281  // we need to remove the slider
1282  this->removeSlider(pCopasiSlider);
1283  wit = v.erase(wit);
1284  wendit = v.end();
1285  sliderDeleted = true;
1286  continue;
1287  }
1288 
1289  ++wit;
1290  }
1291 
1292  if (sliderDeleted)
1293  {
1294  CQMessageBox::information(NULL, "Invalid Slider",
1295  "One or more sliders are invalid and have been deleted!",
1296  QMessageBox::Ok, QMessageBox::NoButton);
1297  }
1298 }
1299 
1300 /**
1301  * Resets the SliderDialog to its initial state.
1302  * It basically calls clear and readds the Label
1303  * for the task widgets that don't support sliders.
1304  */
1306 {
1307  this->clear();
1308  assert(this->mSliderMap[C_INVALID_INDEX].size() == 0);
1309  this->mSliderMap[C_INVALID_INDEX].push_back(new QLabel("<p>There are no sliders available for this task.<br>If you select one of the tasks that supports<br>sliders in the copasi object tree, this dialog<br>will become active.</p>", NULL));
1310 }
1311 
1312 /**
1313  * Returns whether the slider dialog contains changes.
1314  */
1316 {
1317  return this->mChanged;
1318 }
1319 
1320 void SliderDialog::setChanged(bool changed)
1321 {
1322  this->mChanged = changed;
1323 }
1324 
1326 {
1327  return mpWindowMenu;
1328 }
bool compile(const std::vector< CCopasiContainer * > &listOfContainer=CCopasiContainer::EmptyList)
Definition: CSlider.cpp:69
SteadyStateWidget * getSteadyStateWidget()
Definition: listviews.cpp:1054
CCopasiVector< CSlider > * getSliderList()
SCopasiXMLGUI * getGUI()
bool mSliderValueChanged
Definition: SliderDialog.h:172
CSlider * getCSlider() const
SliderDialog(QWidget *parent, const char *name=0, bool modal=false, Qt::WFlags fl=0)
CQLNAWidget * getLNAWidget()
Definition: listviews.cpp:1069
void removeFromMainWindow(CopasiUI3Window *window=NULL)
#define pdelete(p)
Definition: copasi.h:215
bool mSliderPressed
Definition: SliderDialog.h:173
virtual void runLNATask()
void setFramework(int index)
CopasiSlider * findCopasiSliderAtPosition(const QPoint &p)
CQFittingWidget * getFittingWidget()
Definition: listviews.cpp:1074
virtual void runParameterEstimationTask()
virtual void showEvent(QShowEvent *pEvent)
void setCurrentSlider(CopasiSlider *pSlider)
virtual bool leave()
Definition: TaskWidget.cpp:542
bool setSliderObject(CCopasiObject *pObject)
Definition: CSlider.cpp:104
virtual size_t size() const
QAction * mpaEditSlider
Definition: SliderDialog.h:165
CQMCAWidget * getMCAWidget()
Definition: listviews.cpp:1064
void slotShowSliders(bool flag)
CSlider * equivalentSliderExists(CSlider *pCSlider)
virtual void setSlider(CSlider *slider)
CCopasiObject * object() const
void updateSliderData()
std::map< size_t, void(SliderDialog::*)() > mTaskMap
Definition: SliderDialog.h:170
CCopasiObject * getInitialValueReference() const
virtual void runCrossSectionTask()
static std::vector< const CCopasiObject * > getObjectVector(QWidget *pParent, const CQSimpleSelectionTree::ObjectClasses &classes, const std::vector< const CCopasiObject * > *pCurrentSelection=NULL)
bool setCorrectSliderObject(CopasiSlider *pSlider)
const std::string & getAssociatedEntityKey() const
Definition: CSlider.cpp:101
virtual void runScanTask()
virtual QMenu * getWindowMenu() const
static StandardButton information(QWidget *parent, const QString &title, const QString &text, StandardButtons buttons=Ok, StandardButton defaultButton=NoButton)
#define C_INVALID_INDEX
Definition: copasi.h:222
CopasiSlider * mpCurrSlider
Definition: SliderDialog.h:168
QAction * mpaRemoveSlider
Definition: SliderDialog.h:164
virtual ~SliderDialog()
std::vector< CSlider * > * getCSlidersForCurrentFolderId()
std::map< size_t, std::vector< QWidget * > > mSliderMap
Definition: SliderDialog.h:169
Definition: CMetab.h:178
virtual void runTimeCourse()
CSlider * getCSliderForCopasiSlider(std::vector< CSlider * > &v, QWidget *slider)
void updateValue(bool modifyRange, bool updateDependencies)
bool sliderObjectChanged(CSlider *pSlider) const
virtual void runMCATask()
virtual bool runTask()
size_t mCurrentFolderId
Definition: SliderDialog.h:171
void setCurrentFolderId(size_t id)
void createSlidersForFolder(std::vector< QWidget * > &v)
virtual const std::string & getKey() const
void sliderReleased()
static CConfigurationFile * getConfiguration()
void setOriginalValue(C_FLOAT64 value)
bool useAdvancedSliders() const
virtual void setDefinedSliders(std::vector< CSlider * > sliderVect)
bool setAssociatedEntityKey(const std::string &associatedEntityKey)
Definition: CSlider.cpp:94
CopasiWidget * findWidgetFromId(const size_t &id) const
Definition: listviews.cpp:678
virtual void closeEvent(QCloseEvent *e)
void deleteSlider(CopasiSlider *pSlider)
const bool & isInitialConcentrationChangeAllowed() const
Definition: CMetab.cpp:664
virtual bool add(const CType &src)
std::string getInitialExpression() const
static const QIcon & icon(const IconID &id)
void fillSliderBox()
void setChanged(bool changed)
C_FLOAT64 value() const
void setParentWindow(CopasiUI3Window *pPW)
static CCopasiVector< CCopasiDataModel > * getDatamodelList()
void removeSlider()
void refreshInitialValues()
void clearSliderBox()
virtual void setModel(CModel *model)
bool isChanged() const
virtual bool runTask()
Definition: CQMCAWidget.cpp:62
const std::string & getKey() const
Definition: CModel.cpp:1142
virtual void runSteadyStateTask()
QAction * mpaResetValue
Definition: SliderDialog.h:166
CQCrossSectionTaskWidget * getCrossSectionWidget()
Definition: listviews.cpp:1084
void sliderValueChanged()
CopasiUI3Window * mpParentWindow
Definition: SliderDialog.h:161
const CArrayAnnotation * pResult
void deleteInvalidSliders()
virtual void remove(const size_t &index)
QAction * mpaSetDefault
Definition: SliderDialog.h:167
void setMinValue(C_FLOAT64 value)
C_FLOAT64 minValue() const
CopasiSlider * findCopasiSliderForCSlider(CSlider *pCSlider)
void sliderPressed()
CQTrajectoryWidget * getTrajectoryWidget()
Definition: listviews.cpp:1049
bool isValid() const
void createNewSlider()
static size_t numMappings
Definition: SliderDialog.h:103
bool fl(const C_FLOAT64 &d1, const C_FLOAT64 &d2)
ListViews * getMainWidget()
void setObject(CCopasiObject *object)
size_t mapFolderId2EntryId(size_t folderId) const
virtual CCopasiTask * getTaskForFolderId(size_t folderId)
C_FLOAT64 maxValue() const
DataModelGUI * getDataModel()
Definition: CModel.h:50
virtual CSlider * getSlider()
virtual bool runTask()
Definition: CQLNAWidget.cpp:62
void addSlider(CSlider *slider)
CQOptimizationWidget * getOptimizationWidget()
Definition: listviews.cpp:1079
void addToMainWindow(CopasiUI3Window *window=NULL)
CConcentrationReference * getInitialConcentrationReference() const
Definition: CMetab.cpp:861
std::vector< CSlider * > * getCSlidersForObject(CCopasiObject *pObject, std::vector< CSlider * > *pVector) const
void focusSlider()
virtual void changeEvent(QEvent *)
virtual void updateAllSliders()
void resetRange()
Definition: CSlider.cpp:159
void setMaxValue(C_FLOAT64 value)
ScanWidget * getScanWidget()
Definition: listviews.cpp:1059
virtual void contextMenuEvent(QContextMenuEvent *e)
CCopasiContainer * getObjectParent() const
QAction * mpaCreateNewSlider
Definition: SliderDialog.h:163
const CCopasiObject * determineCorrectObjectForSlider(const CCopasiObject *pObject)
CCopasiObject * getSliderObject()
Definition: CSlider.cpp:176
virtual bool runTask()
Definition: ScanWidget.cpp:119
CopasiSlider * getCopasiSliderForCSlider(std::vector< QWidget * > &v, CSlider *slider)
QMenu * mpContextMenu
Definition: SliderDialog.h:162
virtual bool eventFilter(QObject *, QEvent *event)
virtual bool runTask()
static size_t folderMappings[][2]
Definition: SliderDialog.h:104
virtual void runOptimizationTask()
bool enter(const std::string &key)