COPASI API  4.16.103
CQReactionDM.cpp
Go to the documentation of this file.
1 // Copyright (C) 2010 - 2013 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) 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 #include <QtCore/QString>
12 #include <QtCore/QList>
13 
16 #include "model/CChemEqInterface.h"
17 #include "model/CReaction.h"
19 
20 #include "CQMessageBox.h"
21 #include "CQReactionDM.h"
22 #include "qtUtilities.h"
23 
24 CQReactionDM::CQReactionDM(QObject *parent):
25  CQBaseDataModel(parent),
26  mNewEquation()
27 {}
28 
29 int CQReactionDM::rowCount(const QModelIndex& C_UNUSED(parent)) const
30 {
31  return (int)(*CCopasiRootContainer::getDatamodelList())[0]->getModel()->getReactions().size() + 1;
32 }
33 int CQReactionDM::columnCount(const QModelIndex& C_UNUSED(parent)) const
34 {
35  return TOTAL_COLS_REACTIONS;
36 }
37 
38 Qt::ItemFlags CQReactionDM::flags(const QModelIndex &index) const
39 {
40  if (!index.isValid())
41  return Qt::ItemIsEnabled;
42 
43  if (index.column() == COL_NAME_REACTIONS || index.column() == COL_EQUATION)
44  return QAbstractItemModel::flags(index) | Qt::ItemIsEditable;
45  else
46  return QAbstractItemModel::flags(index);
47 }
48 
49 QVariant CQReactionDM::data(const QModelIndex &index, int role) const
50 {
51  if (!index.isValid())
52  return QVariant();
53 
54  if (index.row() >= rowCount())
55  return QVariant();
56 
57  if (index.column() > 0 && role == Qt::ForegroundRole && !(flags(index) & Qt::ItemIsEditable))
58  return QColor(Qt::darkGray);
59 
60  if (role == Qt::DisplayRole || role == Qt::EditRole)
61  {
62  if (isDefaultRow(index))
63  {
64  switch (index.column())
65  {
66  case COL_ROW_NUMBER:
67  return QVariant(QString(""));
68 
69  case COL_NAME_REACTIONS:
70  return QVariant(QString("New Reaction"));
71 
72  default:
73  return QVariant(QString(""));
74  }
75  }
76  else
77  {
78  CReaction *pRea = (*CCopasiRootContainer::getDatamodelList())[0]->getModel()->getReactions()[index.row()];
79 
80  switch (index.column())
81  {
82  case COL_ROW_NUMBER:
83  return QVariant(index.row() + 1);
84 
85  case COL_NAME_REACTIONS:
86  return QVariant(QString(FROM_UTF8(pRea->getObjectName())));
87 
88  case COL_EQUATION:
89 
90  if (mNewEquation.isEmpty())
91  {
92  return QVariant(QString(FROM_UTF8(CChemEqInterface::getChemEqString((*CCopasiRootContainer::getDatamodelList())[0]->getModel(), *pRea, false))));
93  }
94  else
95  {
96  return QVariant(mNewEquation);
97  }
98 
99  case COL_RATE_LAW:
100 
101  if (pRea->getFunction())
102  return QVariant(QString(FROM_UTF8(pRea->getFunction()->getObjectName())));
103  else
104  return QVariant();
105 
106  case COL_FLUX:
107  return QVariant(pRea->getFlux());
108 
109  case COL_PARTICLE_FLUX:
110  return QVariant(pRea->getParticleFlux());
111  }
112  }
113  }
114 
115  return QVariant();
116 }
117 
118 QVariant CQReactionDM::headerData(int section, Qt::Orientation orientation,
119  int role) const
120 {
121  if (role != Qt::DisplayRole)
122  return QVariant();
123 
124  if (orientation == Qt::Horizontal)
125  {
126  switch (section)
127  {
128  case COL_ROW_NUMBER:
129  return QVariant(QString("#"));
130 
131  case COL_NAME_REACTIONS:
132  return QVariant(QString("Name"));
133 
134  case COL_EQUATION:
135  return QVariant(QString("Reaction"));
136 
137  case COL_RATE_LAW:
138  return QVariant(QString("Rate Law"));
139 
140  case COL_FLUX:
141  {
142  const CModel * pModel = (*CCopasiRootContainer::getDatamodelList())[0]->getModel();
143 
144  if (pModel == NULL) return QVariant();
145 
146  QString RateUnits;
147 
148  if (pModel)
149  RateUnits = FROM_UTF8(pModel->getQuantityRateUnitsDisplayString());
150 
151  if (!RateUnits.isEmpty())
152  RateUnits = "\n(" + RateUnits + ")";
153 
154  return QVariant("Flux" + RateUnits);
155  }
156 
157  case COL_PARTICLE_FLUX:
158  {
159  const CModel * pModel = (*CCopasiRootContainer::getDatamodelList())[0]->getModel();
160 
161  if (pModel == NULL) return QVariant();
162 
163  QString FrequencyUnits;
164 
165  if (pModel)
166  FrequencyUnits = FROM_UTF8(pModel->getFrequencyUnitsDisplayString());
167 
168  if (!FrequencyUnits.isEmpty())
169  FrequencyUnits = "\n(" + FrequencyUnits + ")";
170 
171  return QVariant("Flux" + FrequencyUnits);
172  }
173 
174  default:
175  return QVariant();
176  }
177  }
178  else
179  return QString("%1").arg(section + 1);
180 }
181 
182 bool CQReactionDM::setData(const QModelIndex &index, const QVariant &value,
183  int role)
184 {
185  if (index.isValid() && role == Qt::EditRole)
186  {
187  bool defaultRow = isDefaultRow(index);
188 
189  if (defaultRow)
190  {
191  if (index.data() != value)
192  insertRow();
193  else
194  return false;
195  }
196 
197  // this loads the reaction into a CReactionInterface object.
198  // the gui works on this object and later writes back the changes to ri;
199  assert(CCopasiRootContainer::getDatamodelList()->size() > 0);
201  CReaction *pRea = (*CCopasiRootContainer::getDatamodelList())[0]->getModel()->getReactions()[index.row()];
202 
203  if (index.column() == COL_NAME_REACTIONS)
204  pRea->setObjectName(TO_UTF8(value.toString()));
205  else if (index.column() == COL_EQUATION)
206  setEquation(pRea, index, value);
207 
208  if (defaultRow && this->index(index.row(), COL_NAME_REACTIONS).data().toString() == "reaction")
210 
211  emit dataChanged(index, index);
213  }
214 
215  return true;
216 }
217 
218 void CQReactionDM::setEquation(const CReaction *pRea, const QModelIndex& index, const QVariant &value)
219 {
220  std::string objKey = pRea->getKey();
221  mNewEquation = value.toString();
222 
223  assert(CCopasiRootContainer::getDatamodelList()->size() > 0);
225  assert(pDataModel != NULL);
226  CModel * pModel = pDataModel->getModel();
227 
228  if (pModel == NULL) return;
229 
230  // this loads the reaction into a CReactionInterface object.
231  // the gui works on this object and later writes back the changes to ri;
232  assert(CCopasiRootContainer::getDatamodelList()->size() > 0);
234  ri.initFromReaction(objKey);
235 
236  if (TO_UTF8(mNewEquation) != ri.getChemEqString())
237  {
238  //first check if the string is a valid equation
240  {
241  mNewEquation = "";
242  return;
243  }
244  else
245  {
246  //tell the reaction interface
248  }
249  }
250 
251  // Before we save any changes we must check whether any local reaction parameters,
252  // which are used in any mathematical expression in the model are removed.
253  // If that is the case the user must have option to cancel the changes or remove the
254  // affected expressions.
255  std::set< const CCopasiObject * > DeletedParameters = ri.getDeletedParameters();
256 
257  if (DeletedParameters.size() != 0)
258  {
259  QString ObjectType = "parameter(s) of reaction " + this->index(index.row(), COL_NAME_REACTIONS).data().toString();
260  QString Objects;
261 
262  std::set< const CCopasiObject * >::const_iterator itParameter, endParameter = DeletedParameters.end();
263  std::set< const CCopasiObject * > DeletedObjects;
264 
265  for (itParameter = DeletedParameters.begin(); itParameter != endParameter; ++itParameter) //all parameters
266  {
267  Objects.append(FROM_UTF8((*itParameter)->getObjectName()) + ", ");
268  DeletedObjects.insert(static_cast< const CCopasiObject * >((*itParameter)->getObject(CCopasiObjectName("Reference=Value"))));
269  }
270 
271  Objects.remove(Objects.length() - 2, 2);
272 
273  QMessageBox::StandardButton choice =
274  CQMessageBox::confirmDelete(NULL, ObjectType,
275  Objects, DeletedObjects);
276 
277  switch (choice)
278  {
279  case QMessageBox::Ok:
280 
281  for (itParameter = DeletedParameters.begin(); itParameter != endParameter; ++itParameter) //all parameters
282  pModel->removeLocalReactionParameter((*itParameter)->getKey());
283 
284  break;
285 
286  default:
287  mNewEquation = "";
288  return;
289  break;
290  }
291  }
292 
293  // We need to check whether the current reaction still exists, since it is possible that
294  // removing a local reaction parameter triggers its deletion.
295  CReaction * reac = dynamic_cast< CReaction * >(CCopasiRootContainer::getKeyFactory()->get(objKey));
296 
297  if (reac == NULL)
298  {
301  emit notifyGUI(ListViews::REACTION, ListViews::DELETE, ""); //Refresh all as there may be dependencies.
302  mNewEquation = "";
303  return;
304  }
305 
306  //first check if new metabolites need to be created
307  bool createdMetabs = ri.createMetabolites();
308  bool createdObjects = ri.createOtherObjects();
309  //this writes all changes to the reaction
310  ri.writeBackToReaction(NULL);
311 
312  //(*CCopasiRootContainer::getDatamodelList())[0]->getModel()->compile();
313  //this tells the gui what it needs to know.
314  if (createdObjects ||
315  DeletedParameters.size() != 0)
316  {
318  }
319  else if (createdMetabs)
320  {
322  }
323 
324  mNewEquation = "";
325 }
326 
327 bool CQReactionDM::insertRows(int position, int rows, const QModelIndex&)
328 {
329  beginInsertRows(QModelIndex(), position, position + rows - 1);
330 
331  for (int row = 0; row < rows; ++row)
332  {
333  CReaction *pRea = (*CCopasiRootContainer::getDatamodelList())[0]->getModel()->createReaction(TO_UTF8(createNewName("reaction", COL_NAME_REACTIONS)));
335  }
336 
337  endInsertRows();
338 
339  return true;
340 }
341 
342 bool CQReactionDM::removeRows(int position, int rows, const QModelIndex&)
343 {
344  if (rows <= 0)
345  return true;
346 
347  beginRemoveRows(QModelIndex(), position, position + rows - 1);
348 
349  CModel * pModel = (*CCopasiRootContainer::getDatamodelList())[0]->getModel();
350 
351  std::vector< std::string > DeletedKeys;
352  DeletedKeys.resize(rows);
353 
354  std::vector< std::string >::iterator itDeletedKey;
355  std::vector< std::string >::iterator endDeletedKey = DeletedKeys.end();
356 
357  CCopasiVector< CReaction >::const_iterator itRow = pModel->getReactions().begin() + position;
358 
359  for (itDeletedKey = DeletedKeys.begin(); itDeletedKey != endDeletedKey; ++itDeletedKey, ++itRow)
360  {
361  *itDeletedKey = (*itRow)->getKey();
362  }
363 
364  for (itDeletedKey = DeletedKeys.begin(); itDeletedKey != endDeletedKey; ++itDeletedKey)
365  {
366  pModel->removeReaction(*itDeletedKey);
367  emit notifyGUI(ListViews::REACTION, ListViews::DELETE, *itDeletedKey);
368  emit notifyGUI(ListViews::REACTION, ListViews::DELETE, "");//Refresh all as there may be dependencies.
369  }
370 
371  endRemoveRows();
372 
373  return true;
374 }
375 
376 bool CQReactionDM::removeRows(QModelIndexList rows, const QModelIndex&)
377 {
378  if (rows.isEmpty())
379  return false;
380 
381  assert(CCopasiRootContainer::getDatamodelList()->size() > 0);
383  assert(pDataModel != NULL);
384  CModel * pModel = pDataModel->getModel();
385 
386  if (pModel == NULL)
387  return false;
388 
389 //Build the list of pointers to items to be deleted
390 //before actually deleting any item.
391  QList <CReaction *> pReactions;
392  QModelIndexList::const_iterator i;
393 
394  for (i = rows.begin(); i != rows.end(); ++i)
395  {
396  if (!isDefaultRow(*i) && pModel->getReactions()[(*i).row()])
397  pReactions.append(pModel->getReactions()[(*i).row()]);
398  }
399 
400  QList <CReaction *>::const_iterator j;
401 
402  for (j = pReactions.begin(); j != pReactions.end(); ++j)
403  {
404  CReaction * pReaction = *j;
405 
406  size_t delRow =
407  pModel->getReactions().CCopasiVector< CReaction >::getIndex(pReaction);
408 
409  if (delRow != C_INVALID_INDEX)
410  {
411  QMessageBox::StandardButton choice =
412  CQMessageBox::confirmDelete(NULL, "reaction",
413  FROM_UTF8(pReaction->getObjectName()),
414  pReaction->getDeletedObjects());
415 
416  if (choice == QMessageBox::Ok)
417  removeRow((int) delRow);
418  }
419  }
420 
421  return true;
422 }
void setChemEqString(const std::string &eq, const std::string &newFunction)
bool createOtherObjects() const
#define COL_FLUX
Definition: CQReactionDM.h:28
#define FROM_UTF8(__x)
Definition: qtUtilities.h:73
const C_FLOAT64 & getParticleFlux() const
Definition: CReaction.cpp:201
void notifyGUI(ListViews::ObjectType objectType, ListViews::Action action, const std::string &key="")
const std::string & getObjectName() const
std::string getFrequencyUnitsDisplayString() const
Definition: CModel.cpp:4539
CCopasiObject * get(const std::string &key)
virtual const std::string & getKey() const
Definition: CReaction.cpp:190
iterator begin()
#define COL_EQUATION
virtual int columnCount(const QModelIndex &parent=QModelIndex()) const
std::string getQuantityRateUnitsDisplayString() const
Definition: CModel.cpp:4657
void initFromReaction(const std::string &key)
void setEquation(const CReaction *pRea, const QModelIndex &index, const QVariant &value)
#define C_INVALID_INDEX
Definition: copasi.h:222
#define C_UNUSED(p)
Definition: copasi.h:220
const C_FLOAT64 & getFlux() const
Definition: CReaction.cpp:192
virtual std::set< const CCopasiObject * > getDeletedObjects() const
Definition: CReaction.cpp:959
bool setData(const QModelIndex &index, const QVariant &value, int role=Qt::EditRole)
bool removeRow(int position)
QVariant data(const QModelIndex &index, int role) const
#define COL_PARTICLE_FLUX
Definition: CQReactionDM.h:29
static bool isValidEq(const std::string &eq)
const CFunction * getFunction() const
Definition: CReaction.cpp:252
std::vector< CType * >::const_iterator const_iterator
Definition: CCopasiVector.h:57
#define COL_NAME_REACTIONS
Definition: CQReactionDM.h:25
#define COL_RATE_LAW
Definition: CQReactionDM.h:27
static StandardButton confirmDelete(QWidget *parent, const QString &objectType, const QString &objects, const std::set< const CCopasiObject * > &deletedObjects)
static CCopasiVector< CCopasiDataModel > * getDatamodelList()
std::string getChemEqString(bool expanded) const
QString createNewName(const QString name, const int nameCol)
std::set< const CCopasiObject * > getDeletedParameters() const
static CKeyFactory * getKeyFactory()
virtual int rowCount(const QModelIndex &parent=QModelIndex()) const
QVariant headerData(int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const
CCopasiVectorNS< CReaction > & getReactions()
Definition: CModel.cpp:1039
#define TO_UTF8(__x)
Definition: qtUtilities.h:74
std::string getChemEqString() const
QString mNewEquation
Definition: CQReactionDM.h:55
Definition: CModel.h:50
bool writeBackToReaction(CReaction *rea)
#define TOTAL_COLS_REACTIONS
Definition: CQReactionDM.h:30
virtual bool isDefaultRow(const QModelIndex &i) const
bool setObjectName(const std::string &name)
bool insertRows(int position, int rows, const QModelIndex &index=QModelIndex())
bool removeRows(QModelIndexList rows, const QModelIndex &index=QModelIndex())
bool removeLocalReactionParameter(const std::string &key, const bool &recursive=true)
Definition: CModel.cpp:2818
CQReactionDM(QObject *parent=0)
bool removeReaction(const CReaction *pReaction, const bool &recursive=true)
Definition: CModel.cpp:2792
void setFunctionWithEmptyMapping(const std::string &fn)
#define COL_ROW_NUMBER
Qt::ItemFlags flags(const QModelIndex &index) const