<commit_before>// Copyright (C) 2010 - 2016 by Pedro Mendes, Virginia Tech Intellectual
// Properties, Inc., University of Heidelberg, and The University
// of Manchester.
// All rights reserved.

/*
 * CQModelWidget.cpp
 *
 *  Created on: Aug 13, 2010
 *      Author: shoops
 */

#include "CQModelWidget.h"
#include "CQUpdateAvogadro.h"
#include "qtUtilities.h"

#include "resourcesUI/CQIconResource.h"

#include "copasi/model/CModel.h"
#include "copasi/utilities/CUnit.h"
#include "copasi/report/CCopasiRootContainer.h"

#include <QUndoStack>
#include <copasi/undoFramework/ModelChangeCommand.h>
#include <copasi/UI/copasiui3window.h>
#include <copasi/UI/CQCopasiApplication.h>

CQModelWidget::CQModelWidget(QWidget* parent, const char* name) :
  CopasiWidget(parent, name),
  mpModel(NULL)
{
  setupUi(this);

  updateUnitComboBoxes();

  mpUndoStack = NULL;

#ifndef COPASI_EXTUNIT
  mpLblAreaUnit->hide();
  mpComboAreaUnit->hide();

  mpLblLengthUnit->hide();
  mpComboLengthUnit->hide();

  mpEditAvogadro->hide();
  mpBtnUpdateAvogadro->hide();
#endif

  mpBtnUpdateAvogadro->setIcon(CQIconResource::icon(CQIconResource::tool));
  mpEditAvogadro->setEnabled(false);
}

CQModelWidget::~CQModelWidget()
{}

void CQModelWidget::load()
{
  if (mpModel == NULL)
    return;

  updateUnitComboBoxes(); //findText, below, needs any newly loaded units to be available to match.

  mpComboTimeUnit->setCurrentIndex(mpComboTimeUnit->findText(FROM_UTF8(mpModel->getTimeUnitName())));
  mpComboVolumeUnit->setCurrentIndex(mpComboVolumeUnit->findText(FROM_UTF8(mpModel->getVolumeUnitName())));
  mpComboQuantityUnit->setCurrentIndex(mpComboQuantityUnit->findText(FROM_UTF8(mpModel->getQuantityUnitName())));
  mpComboAreaUnit->setCurrentIndex(mpComboAreaUnit->findText(FROM_UTF8(mpModel->getAreaUnitName())));
  mpComboLengthUnit->setCurrentIndex(mpComboLengthUnit->findText(FROM_UTF8(mpModel->getLengthUnitName())));

  mpEditAvogadro->setText(QString::number(mpModel->getAvogadro(), 'g', 14));

#ifdef COPASI_EXTUNIT

  if (mpModel->getAvogadro() == CUnit::Avogadro)
    {
      mpBtnUpdateAvogadro->hide();
    }
  else
    {
      mpBtnUpdateAvogadro->show();
    }

#endif

  mpCheckStochasticCorrection->setChecked(mpModel->getModelType() == CModel::deterministic);

  mpLblInitialTime->setText("Initial Time [" + mpComboTimeUnit->currentText() + "]");
  mpEditInitialTime->setText(QString::number(mpModel->getInitialTime(), 'g', 10));
  mpEditInitialTime->setReadOnly(mpModel->isAutonomous());

  mpLblCurrentTime->setText("Time [" + mpComboTimeUnit->currentText() + "]");
  mpEditCurrentTime->setText(QString::number(mpModel->getTime(), 'g', 10));

  return;
}

void CQModelWidget::save()
{
  if (mpModel == NULL)
    return;

  bool changed = false;

  mIgnoreUpdates = true;

  if (mpUndoStack == NULL)
    {
      mpUndoStack = static_cast<CQCopasiApplication*>(qApp)
                    ->getMainWindow()->getUndoStack();
    }

  if (TO_UTF8(mpComboTimeUnit->currentText()) != mpModel->getTimeUnitName())
    {
      mpUndoStack->push(
        new ModelChangeCommand(CCopasiUndoCommand::MODEL_TIME_UNIT_CHANGE,
                               FROM_UTF8(mpModel->getTimeUnitName()),
                               mpComboTimeUnit->currentText(),
                               this));
      changed = true;
    }

  if (TO_UTF8(mpComboVolumeUnit->currentText()) != mpModel->getVolumeUnitName())
    {
      mpUndoStack->push(
        new ModelChangeCommand(CCopasiUndoCommand::MODEL_VOLUME_UNIT_CHANGE,
                               FROM_UTF8(mpModel->getVolumeUnitName()),
                               mpComboVolumeUnit->currentText(),
                               this));
      changed = true;
    }

  if (TO_UTF8(mpComboAreaUnit->currentText()) != mpModel->getAreaUnitName())
    {
      mpUndoStack->push(
        new ModelChangeCommand(CCopasiUndoCommand::MODEL_AREA_UNIT_CHANGE,
                               FROM_UTF8(mpModel->getAreaUnitName()),
                               mpComboAreaUnit->currentText(),
                               this));
      changed = true;
    }

  if (TO_UTF8(mpComboLengthUnit->currentText()) != mpModel->getLengthUnitName())
    {
      mpUndoStack->push(
        new ModelChangeCommand(CCopasiUndoCommand::MODEL_LENGTH_UNIT_CHANGE,
                               FROM_UTF8(mpModel->getLengthUnitName()),
                               mpComboLengthUnit->currentText(),
                               this));
      changed = true;
    }

  if (TO_UTF8(mpComboQuantityUnit->currentText()) != mpModel->getQuantityUnitName())
    {
      QList< QVariant > OldValues, NewValues;

      OldValues.append(FROM_UTF8(mpModel->getQuantityUnitName()));
      NewValues.append(mpComboQuantityUnit->currentText());
      OldValues.append(mFramework);
      NewValues.append(mFramework);

      mpUndoStack->push(
        new ModelChangeCommand(CCopasiUndoCommand::MODEL_QUANTITY_UNIT_CHANGE,
                               OldValues, NewValues,
                               this));
      changed = true;
    }

  if (mpEditAvogadro->text() != QString::number(mpModel->getAvogadro(), 'g', 10))
    {
      QList< QVariant > OldValues, NewValues;

      OldValues.append(mpModel->getAvogadro());
      NewValues.append(mpEditAvogadro->text());
      OldValues.append(mFramework);
      NewValues.append(mFramework);

      mpUndoStack->push(
        new ModelChangeCommand(CCopasiUndoCommand::MODEL_AVOGADRO_NUMBER_CHANGE,
                               OldValues, NewValues,
                               this));
      changed = true;
    }

  if (mpCheckStochasticCorrection->isChecked() != (mpModel->getModelType() == CModel::deterministic))
    {
      mpUndoStack->push(
        new ModelChangeCommand(CCopasiUndoCommand::MODEL_STOCHASTIC_CORRECTION_CHANGE,
                               mpModel->getModelType() == CModel::deterministic,
                               mpCheckStochasticCorrection->isChecked(),
                               this));
      changed = true;
    }

  if (mpEditInitialTime->text() != QString::number(mpModel->getInitialTime()))
    {
      mpUndoStack->push(
        new ModelChangeCommand(CCopasiUndoCommand::MODEL_INITIAL_TIME_CHANGE,
                               mpModel->getInitialTime(),
                               mpEditInitialTime->text().toDouble(),
                               this));
      changed = true;
    }

  mIgnoreUpdates = false;

  if (changed)
    {
      if (mpDataModel != NULL)
        {
          mpDataModel->changed();
        }

      protectedNotify(ListViews::MODEL, ListViews::CHANGE, mKey);

      load();
    }

  return;
}

void CQModelWidget::slotBtnRevertClicked()
{
  load();
}

void CQModelWidget::slotBtnOKClicked()
{
  save();
  load();
}

bool CQModelWidget::update(ListViews::ObjectType objectType,
                           ListViews::Action C_UNUSED(action), const std::string & key)
{
  if (mIgnoreUpdates) return true;

  switch (objectType)
    {
      case ListViews::MODEL:
        enter(key);
        break;

      case ListViews::UNIT:
        updateUnitComboBoxes();
        break;

      default:
        break;
    }

  return true;
}

bool CQModelWidget::leave()
{
  save();

  mpNotes->leave();

  return true;
}

bool CQModelWidget::enterProtected()
{
  if (mpObject != NULL)
    mpModel = dynamic_cast< CModel * >(mpObject);
  else
    mpModel = NULL;

  load();

  mpNotes->enter(mKey);

  return true;
}

bool
CQModelWidget::changeValue(CCopasiUndoCommand::Type type, const QVariant& newValue)
{
  mpListView->switchToOtherWidget(C_INVALID_INDEX, mKey);

  if (mpModel == NULL)
    {
      GET_MODEL_OR(pModel, return false);
      mpModel = pModel;
    }

  if (type == CCopasiUndoCommand::MODEL_TIME_UNIT_CHANGE)
    {
      mpModel->setTimeUnit(TO_UTF8(newValue.toString()));
    }
  else if (type == CCopasiUndoCommand::MODEL_QUANTITY_UNIT_CHANGE)
    {
      QList< QVariant > Values = newValue.toList();
      mpModel->setQuantityUnit(TO_UTF8(Values[0].toString()), (CModelParameter::Framework) Values[1].toInt());
    }
  else if (type == CCopasiUndoCommand::MODEL_VOLUME_UNIT_CHANGE)
    {
      mpModel->setVolumeUnit(TO_UTF8(newValue.toString()));
    }
  else if (type == CCopasiUndoCommand::MODEL_AREA_UNIT_CHANGE)
    {
      mpModel->setAreaUnit(TO_UTF8(newValue.toString()));
    }
  else if (type == CCopasiUndoCommand::MODEL_LENGTH_UNIT_CHANGE)
    {
      mpModel->setLengthUnit(TO_UTF8(newValue.toString()));
    }
  else if (type == CCopasiUndoCommand::MODEL_AVOGADRO_NUMBER_CHANGE)
    {
      QList< QVariant > Values = newValue.toList();
      mpModel->setAvogadro(Values[0].toDouble(), (CModelParameter::Framework) Values[1].toInt());
    }
  else if (type == CCopasiUndoCommand::MODEL_INITIAL_TIME_CHANGE)
    {
      mpModel->setInitialTime(newValue.toDouble());
    }
  else if (type == CCopasiUndoCommand::MODEL_STOCHASTIC_CORRECTION_CHANGE)
    {
      if (newValue.toBool())
        {
          mpModel->setModelType(CModel::deterministic);
        }
      else
        {
          mpModel->setModelType(CModel::stochastic);
        }
    }
  else
    {
      return false;
    }

  if (mIgnoreUpdates) return true;

  if (mpDataModel != NULL)
    {
      mpDataModel->changed();
    }

  protectedNotify(ListViews::MODEL, ListViews::CHANGE, mKey);

  load();

  return true;
}

void CQModelWidget::updateUnitComboBoxes()
{
  QStringList ComboEntries;
  std::vector< CUnit >::const_iterator it, itEnd;

  // Take advantage of the implicit sorting in std::set
  std::vector< CUnit > ValidUnitSet =  CCopasiRootContainer::getUnitList()->getAllValidUnits("s", 1);

  for (it = ValidUnitSet.begin(), itEnd = ValidUnitSet.end(); it != itEnd; ++it)
    {
      ComboEntries.push_back(FROM_UTF8(it->getExpression()));
    }

  mpComboTimeUnit->clear();
  mpComboTimeUnit->insertItems(0, ComboEntries);

  ValidUnitSet = CCopasiRootContainer::getUnitList()->getAllValidUnits("m", 3);
  ComboEntries.clear();

  for (it = ValidUnitSet.begin(), itEnd = ValidUnitSet.end(); it != itEnd; ++it)
    {
      ComboEntries.push_back(FROM_UTF8(it->getExpression()));
    }

  mpComboVolumeUnit->clear();
  mpComboVolumeUnit->insertItems(0, ComboEntries);

  ValidUnitSet = CCopasiRootContainer::getUnitList()->getAllValidUnits("m", 2);
  ComboEntries.clear();

  for (it = ValidUnitSet.begin(), itEnd = ValidUnitSet.end(); it != itEnd; ++it)
    {
      ComboEntries.push_back(FROM_UTF8(it->getExpression()));
    }

  mpComboAreaUnit->clear();
  mpComboAreaUnit->insertItems(0, ComboEntries);

  ValidUnitSet = CCopasiRootContainer::getUnitList()->getAllValidUnits("m", 1);
  ComboEntries.clear();

  for (it = ValidUnitSet.begin(), itEnd = ValidUnitSet.end(); it != itEnd; ++it)
    {
      ComboEntries.push_back(FROM_UTF8(it->getExpression()));
    }

  mpComboLengthUnit->clear();
  mpComboLengthUnit->insertItems(0, ComboEntries);

  ValidUnitSet = CCopasiRootContainer::getUnitList()->getAllValidUnits("#", 1);
  ComboEntries.clear();

  for (it = ValidUnitSet.begin(), itEnd = ValidUnitSet.end(); it != itEnd; ++it)
    {
      ComboEntries.push_back(FROM_UTF8(it->getExpression()));
    }

  mpComboQuantityUnit->clear();
  mpComboQuantityUnit->insertItems(0, ComboEntries);
}

// virtual
void CQModelWidget::slotUpdateAvogadro()
{
  CQUpdateAvogadro *pDialog = new CQUpdateAvogadro(this);

  pDialog->setSelection(mFramework == 0 ? 0 : 1);

  switch (pDialog->exec())
    {
      case QDialog::Accepted:
        if (mpUndoStack == NULL)
          {
            mpUndoStack = static_cast<CQCopasiApplication*>(qApp)
                          ->getMainWindow()->getUndoStack();
          }

        {
          QList< QVariant > OldValues, NewValues;

          OldValues.append(mpModel->getAvogadro());
          NewValues.append(CUnit::Avogadro);
          OldValues.append(pDialog->getSelection());
          NewValues.append(pDialog->getSelection());

          mpUndoStack->push(
            new ModelChangeCommand(CCopasiUndoCommand::MODEL_AVOGADRO_NUMBER_CHANGE,
                                   OldValues, NewValues,
                                   this));

          load();
        }

        break;

      case QDialog::Rejected:
        break;
    }
}
<commit_msg>Block signals while updating unit combo box entries.<commit_after>// Copyright (C) 2010 - 2016 by Pedro Mendes, Virginia Tech Intellectual
// Properties, Inc., University of Heidelberg, and The University
// of Manchester.
// All rights reserved.

/*
 * CQModelWidget.cpp
 *
 *  Created on: Aug 13, 2010
 *      Author: shoops
 */

#include "CQModelWidget.h"
#include "CQUpdateAvogadro.h"
#include "qtUtilities.h"

#include "resourcesUI/CQIconResource.h"

#include "copasi/model/CModel.h"
#include "copasi/utilities/CUnit.h"
#include "copasi/report/CCopasiRootContainer.h"

#include <QUndoStack>
#include <copasi/undoFramework/ModelChangeCommand.h>
#include <copasi/UI/copasiui3window.h>
#include <copasi/UI/CQCopasiApplication.h>

CQModelWidget::CQModelWidget(QWidget* parent, const char* name) :
  CopasiWidget(parent, name),
  mpModel(NULL)
{
  setupUi(this);

  updateUnitComboBoxes();

  mpUndoStack = NULL;

#ifndef COPASI_EXTUNIT
  mpLblAreaUnit->hide();
  mpComboAreaUnit->hide();

  mpLblLengthUnit->hide();
  mpComboLengthUnit->hide();

  mpEditAvogadro->hide();
  mpBtnUpdateAvogadro->hide();
#endif

  mpBtnUpdateAvogadro->setIcon(CQIconResource::icon(CQIconResource::tool));
  mpEditAvogadro->setEnabled(false);
}

CQModelWidget::~CQModelWidget()
{}

void CQModelWidget::load()
{
  if (mpModel == NULL)
    return;

  updateUnitComboBoxes(); //findText, below, needs any newly loaded units to be available to match.

  mpComboTimeUnit->setCurrentIndex(mpComboTimeUnit->findText(FROM_UTF8(mpModel->getTimeUnitName())));
  mpComboVolumeUnit->setCurrentIndex(mpComboVolumeUnit->findText(FROM_UTF8(mpModel->getVolumeUnitName())));
  mpComboQuantityUnit->setCurrentIndex(mpComboQuantityUnit->findText(FROM_UTF8(mpModel->getQuantityUnitName())));
  mpComboAreaUnit->setCurrentIndex(mpComboAreaUnit->findText(FROM_UTF8(mpModel->getAreaUnitName())));
  mpComboLengthUnit->setCurrentIndex(mpComboLengthUnit->findText(FROM_UTF8(mpModel->getLengthUnitName())));

  mpEditAvogadro->setText(QString::number(mpModel->getAvogadro(), 'g', 14));

#ifdef COPASI_EXTUNIT

  if (mpModel->getAvogadro() == CUnit::Avogadro)
    {
      mpBtnUpdateAvogadro->hide();
    }
  else
    {
      mpBtnUpdateAvogadro->show();
    }

#endif

  mpCheckStochasticCorrection->setChecked(mpModel->getModelType() == CModel::deterministic);

  mpLblInitialTime->setText("Initial Time [" + mpComboTimeUnit->currentText() + "]");
  mpEditInitialTime->setText(QString::number(mpModel->getInitialTime(), 'g', 10));
  mpEditInitialTime->setReadOnly(mpModel->isAutonomous());

  mpLblCurrentTime->setText("Time [" + mpComboTimeUnit->currentText() + "]");
  mpEditCurrentTime->setText(QString::number(mpModel->getTime(), 'g', 10));

  return;
}

void CQModelWidget::save()
{
  if (mpModel == NULL)
    return;

  bool changed = false;

  mIgnoreUpdates = true;

  if (mpUndoStack == NULL)
    {
      mpUndoStack = static_cast<CQCopasiApplication*>(qApp)
                    ->getMainWindow()->getUndoStack();
    }

  if (TO_UTF8(mpComboTimeUnit->currentText()) != mpModel->getTimeUnitName())
    {
      mpUndoStack->push(
        new ModelChangeCommand(CCopasiUndoCommand::MODEL_TIME_UNIT_CHANGE,
                               FROM_UTF8(mpModel->getTimeUnitName()),
                               mpComboTimeUnit->currentText(),
                               this));
      changed = true;
    }

  if (TO_UTF8(mpComboVolumeUnit->currentText()) != mpModel->getVolumeUnitName())
    {
      mpUndoStack->push(
        new ModelChangeCommand(CCopasiUndoCommand::MODEL_VOLUME_UNIT_CHANGE,
                               FROM_UTF8(mpModel->getVolumeUnitName()),
                               mpComboVolumeUnit->currentText(),
                               this));
      changed = true;
    }

  if (TO_UTF8(mpComboAreaUnit->currentText()) != mpModel->getAreaUnitName())
    {
      mpUndoStack->push(
        new ModelChangeCommand(CCopasiUndoCommand::MODEL_AREA_UNIT_CHANGE,
                               FROM_UTF8(mpModel->getAreaUnitName()),
                               mpComboAreaUnit->currentText(),
                               this));
      changed = true;
    }

  if (TO_UTF8(mpComboLengthUnit->currentText()) != mpModel->getLengthUnitName())
    {
      mpUndoStack->push(
        new ModelChangeCommand(CCopasiUndoCommand::MODEL_LENGTH_UNIT_CHANGE,
                               FROM_UTF8(mpModel->getLengthUnitName()),
                               mpComboLengthUnit->currentText(),
                               this));
      changed = true;
    }

  if (TO_UTF8(mpComboQuantityUnit->currentText()) != mpModel->getQuantityUnitName())
    {
      QList< QVariant > OldValues, NewValues;

      OldValues.append(FROM_UTF8(mpModel->getQuantityUnitName()));
      NewValues.append(mpComboQuantityUnit->currentText());
      OldValues.append(mFramework);
      NewValues.append(mFramework);

      mpUndoStack->push(
        new ModelChangeCommand(CCopasiUndoCommand::MODEL_QUANTITY_UNIT_CHANGE,
                               OldValues, NewValues,
                               this));
      changed = true;
    }

  if (mpEditAvogadro->text() != QString::number(mpModel->getAvogadro(), 'g', 10))
    {
      QList< QVariant > OldValues, NewValues;

      OldValues.append(mpModel->getAvogadro());
      NewValues.append(mpEditAvogadro->text());
      OldValues.append(mFramework);
      NewValues.append(mFramework);

      mpUndoStack->push(
        new ModelChangeCommand(CCopasiUndoCommand::MODEL_AVOGADRO_NUMBER_CHANGE,
                               OldValues, NewValues,
                               this));
      changed = true;
    }

  if (mpCheckStochasticCorrection->isChecked() != (mpModel->getModelType() == CModel::deterministic))
    {
      mpUndoStack->push(
        new ModelChangeCommand(CCopasiUndoCommand::MODEL_STOCHASTIC_CORRECTION_CHANGE,
                               mpModel->getModelType() == CModel::deterministic,
                               mpCheckStochasticCorrection->isChecked(),
                               this));
      changed = true;
    }

  if (mpEditInitialTime->text() != QString::number(mpModel->getInitialTime()))
    {
      mpUndoStack->push(
        new ModelChangeCommand(CCopasiUndoCommand::MODEL_INITIAL_TIME_CHANGE,
                               mpModel->getInitialTime(),
                               mpEditInitialTime->text().toDouble(),
                               this));
      changed = true;
    }

  mIgnoreUpdates = false;

  if (changed)
    {
      if (mpDataModel != NULL)
        {
          mpDataModel->changed();
        }

      protectedNotify(ListViews::MODEL, ListViews::CHANGE, mKey);

      load();
    }

  return;
}

void CQModelWidget::slotBtnRevertClicked()
{
  load();
}

void CQModelWidget::slotBtnOKClicked()
{
  save();
  load();
}

bool CQModelWidget::update(ListViews::ObjectType objectType,
                           ListViews::Action C_UNUSED(action), const std::string & key)
{
  if (mIgnoreUpdates) return true;

  switch (objectType)
    {
      case ListViews::MODEL:
        enter(key);
        break;

      case ListViews::UNIT:
        updateUnitComboBoxes();
        break;

      default:
        break;
    }

  return true;
}

bool CQModelWidget::leave()
{
  save();

  mpNotes->leave();

  return true;
}

bool CQModelWidget::enterProtected()
{
  if (mpObject != NULL)
    mpModel = dynamic_cast< CModel * >(mpObject);
  else
    mpModel = NULL;

  load();

  mpNotes->enter(mKey);

  return true;
}

bool
CQModelWidget::changeValue(CCopasiUndoCommand::Type type, const QVariant& newValue)
{
  mpListView->switchToOtherWidget(C_INVALID_INDEX, mKey);

  if (mpModel == NULL)
    {
      GET_MODEL_OR(pModel, return false);
      mpModel = pModel;
    }

  if (type == CCopasiUndoCommand::MODEL_TIME_UNIT_CHANGE)
    {
      mpModel->setTimeUnit(TO_UTF8(newValue.toString()));
    }
  else if (type == CCopasiUndoCommand::MODEL_QUANTITY_UNIT_CHANGE)
    {
      QList< QVariant > Values = newValue.toList();
      mpModel->setQuantityUnit(TO_UTF8(Values[0].toString()), (CModelParameter::Framework) Values[1].toInt());
    }
  else if (type == CCopasiUndoCommand::MODEL_VOLUME_UNIT_CHANGE)
    {
      mpModel->setVolumeUnit(TO_UTF8(newValue.toString()));
    }
  else if (type == CCopasiUndoCommand::MODEL_AREA_UNIT_CHANGE)
    {
      mpModel->setAreaUnit(TO_UTF8(newValue.toString()));
    }
  else if (type == CCopasiUndoCommand::MODEL_LENGTH_UNIT_CHANGE)
    {
      mpModel->setLengthUnit(TO_UTF8(newValue.toString()));
    }
  else if (type == CCopasiUndoCommand::MODEL_AVOGADRO_NUMBER_CHANGE)
    {
      QList< QVariant > Values = newValue.toList();
      mpModel->setAvogadro(Values[0].toDouble(), (CModelParameter::Framework) Values[1].toInt());
    }
  else if (type == CCopasiUndoCommand::MODEL_INITIAL_TIME_CHANGE)
    {
      mpModel->setInitialTime(newValue.toDouble());
    }
  else if (type == CCopasiUndoCommand::MODEL_STOCHASTIC_CORRECTION_CHANGE)
    {
      if (newValue.toBool())
        {
          mpModel->setModelType(CModel::deterministic);
        }
      else
        {
          mpModel->setModelType(CModel::stochastic);
        }
    }
  else
    {
      return false;
    }

  if (mIgnoreUpdates) return true;

  if (mpDataModel != NULL)
    {
      mpDataModel->changed();
    }

  protectedNotify(ListViews::MODEL, ListViews::CHANGE, mKey);

  load();

  return true;
}

void CQModelWidget::updateUnitComboBoxes()
{
  QStringList ComboEntries;
  std::vector< CUnit >::const_iterator it, itEnd;

  // Take advantage of the implicit sorting in std::set
  std::vector< CUnit > ValidUnitSet =  CCopasiRootContainer::getUnitList()->getAllValidUnits("s", 1);

  for (it = ValidUnitSet.begin(), itEnd = ValidUnitSet.end(); it != itEnd; ++it)
    {
      ComboEntries.push_back(FROM_UTF8(it->getExpression()));
    }

  mpComboTimeUnit->blockSignals(true);
  mpComboTimeUnit->clear();
  mpComboTimeUnit->insertItems(0, ComboEntries);
  mpComboTimeUnit->blockSignals(false);

  ValidUnitSet = CCopasiRootContainer::getUnitList()->getAllValidUnits("m", 3);
  ComboEntries.clear();

  for (it = ValidUnitSet.begin(), itEnd = ValidUnitSet.end(); it != itEnd; ++it)
    {
      ComboEntries.push_back(FROM_UTF8(it->getExpression()));
    }

  mpComboVolumeUnit->blockSignals(true);
  mpComboVolumeUnit->clear();
  mpComboVolumeUnit->insertItems(0, ComboEntries);
  mpComboVolumeUnit->blockSignals(false);

  ValidUnitSet = CCopasiRootContainer::getUnitList()->getAllValidUnits("m", 2);
  ComboEntries.clear();

  for (it = ValidUnitSet.begin(), itEnd = ValidUnitSet.end(); it != itEnd; ++it)
    {
      ComboEntries.push_back(FROM_UTF8(it->getExpression()));
    }

  mpComboAreaUnit->blockSignals(true);
  mpComboAreaUnit->clear();
  mpComboAreaUnit->insertItems(0, ComboEntries);
  mpComboAreaUnit->blockSignals(false);

  ValidUnitSet = CCopasiRootContainer::getUnitList()->getAllValidUnits("m", 1);
  ComboEntries.clear();

  for (it = ValidUnitSet.begin(), itEnd = ValidUnitSet.end(); it != itEnd; ++it)
    {
      ComboEntries.push_back(FROM_UTF8(it->getExpression()));
    }

  mpComboLengthUnit->blockSignals(true);
  mpComboLengthUnit->clear();
  mpComboLengthUnit->insertItems(0, ComboEntries);
  mpComboLengthUnit->blockSignals(false);

  ValidUnitSet = CCopasiRootContainer::getUnitList()->getAllValidUnits("#", 1);
  ComboEntries.clear();

  for (it = ValidUnitSet.begin(), itEnd = ValidUnitSet.end(); it != itEnd; ++it)
    {
      ComboEntries.push_back(FROM_UTF8(it->getExpression()));
    }

  mpComboQuantityUnit->blockSignals(true);
  mpComboQuantityUnit->clear();
  mpComboQuantityUnit->insertItems(0, ComboEntries);
  mpComboQuantityUnit->blockSignals(false);
}

// virtual
void CQModelWidget::slotUpdateAvogadro()
{
  CQUpdateAvogadro *pDialog = new CQUpdateAvogadro(this);

  pDialog->setSelection(mFramework == 0 ? 0 : 1);

  switch (pDialog->exec())
    {
      case QDialog::Accepted:
        if (mpUndoStack == NULL)
          {
            mpUndoStack = static_cast<CQCopasiApplication*>(qApp)
                          ->getMainWindow()->getUndoStack();
          }

        {
          QList< QVariant > OldValues, NewValues;

          OldValues.append(mpModel->getAvogadro());
          NewValues.append(CUnit::Avogadro);
          OldValues.append(pDialog->getSelection());
          NewValues.append(pDialog->getSelection());

          mpUndoStack->push(
            new ModelChangeCommand(CCopasiUndoCommand::MODEL_AVOGADRO_NUMBER_CHANGE,
                                   OldValues, NewValues,
                                   this));

          load();
        }

        break;

      case QDialog::Rejected:
        break;
    }
}
<|endoftext|>


<commit_before>/* Begin CVS Header
   $Source: /Volumes/Home/Users/shoops/cvs/copasi_dev/copasi/scan/CScanMethod.cpp,v $
   $Revision: 1.38 $
   $Name:  $
   $Author: ssahle $
   $Date: 2005/04/11 17:36:15 $
   End CVS Header */

/**
 *  CScanMethod class.
 *  This class describes the Scan method
 *
 *  Created for Copasi by Rohan Luktuke 2002
 */

#include <string>

//#define COPASI_TRACE_CONSTRUCTION
#include "mathematics.h"
#include "copasi.h"
#include "model/CModel.h"
#include "model/CState.h"
#include "utilities/CReadConfig.h"
#include "randomGenerator/CRandom.h"
//#include "utilities/CWriteConfig.h"
#include "CScanProblem.h"
#include "CScanMethod.h"
#include "CScanTask.h"
#include "CopasiDataModel/CCopasiDataModel.h"

// this will have to be defined somewhere else with the
// values of other distribution types
//#define SD_UNIFORM 0
//#define SD_GAUSS 1
//#define SD_BOLTZ 2
//#define SD_REGULAR 3

//**************** CScanItem classes ***************************

//static
CScanItem* CScanItem::createScanItemFromParameterGroup(const CCopasiParameterGroup* si,
    CRandom* rg,
    CScanTask* st)
{
  if (!si) return NULL;

  CScanProblem::Type type = *(CScanProblem::Type*)(si->getValue("Type"));

  CScanItem* tmp;

  if (type == CScanProblem::SCAN_REPEAT)
    tmp = new CScanItemRepeat(si);

  if (type == CScanProblem::SCAN_LINEAR)
    tmp = new CScanItemLinear(si);

  if (type == CScanProblem::SCAN_RANDOM)
    tmp = new CScanItemRandom(si, rg);

  /*  if (type == CScanProblem::SCAN_BREAK)
      tmp = new CScanItemBreak(si, st);*/

  return tmp;
}

CScanItem::CScanItem(const CCopasiParameterGroup* si)
    : mNumSteps(0),
    mpValue(NULL),
    mStoreValue(0.0),
    mIndex(0),
    mFlagFinished(false)
{
  mNumSteps = *(unsigned C_INT32*)(si->getValue("Number of steps"));

  std::string tmpString = *(std::string*)(si->getValue("Object"));
  CCopasiObject* tmpObject = CCopasiContainer::ObjectFromName(tmpString);
  if (!tmpObject) {mpValue = NULL; return;}
  if (!tmpObject->isValueDbl()) {mpValue = NULL; return;}
  mpValue = tmpObject;
}

unsigned C_INT32 CScanItem::getNumSteps() const {return mNumSteps;};

void CScanItem::restoreValue() const
  {
    if (mpValue)
      mpValue->setObjectValue(mStoreValue);
  };

void CScanItem::storeValue()
{if (mpValue) mStoreValue = * (C_FLOAT64 *) mpValue->getReference();};

void CScanItem::reset()
{
  mIndex = 0;
  mFlagFinished = false;
  this->step(); //purely virtual
}

bool CScanItem::isFinished() const {return mFlagFinished;};

//*******

CScanItemRepeat::CScanItemRepeat(const CCopasiParameterGroup* si)
    : CScanItem(si)
{
  if (mNumSteps >= 1)
    --mNumSteps; // for the repeat item mNumSteps is the number of iterations, not of intervals
}

void CScanItemRepeat::step()
{
  //do something ...

  //the index
  if (mIndex > mNumSteps)
    mFlagFinished = true;
  ++mIndex;

  //  std::cout << "SIRepeat " << mIndex-1<< std::endl;
}

//*******

CScanItemLinear::CScanItemLinear(const CCopasiParameterGroup* si)
    : CScanItem(si),
    mLog(false)
{
  mLog = *(bool*)(si->getValue("log"));
  mMin = *(C_FLOAT64*)(si->getValue("Minimum"));
  mMax = *(C_FLOAT64*)(si->getValue("Maximum"));
  if (mLog)
    {
      mMin = log(mMin);
      mMax = log(mMax);
    }
  mFaktor = (mMax - mMin) / mNumSteps;
}

void CScanItemLinear::step()
{
  //do something ...
  C_FLOAT64 Value = mMin + mIndex * mFaktor;

  if (mLog)
    Value = exp(Value);
  //the index
  if (mIndex > mNumSteps)
    mFlagFinished = true;

  mpValue->setObjectValue(Value);
  ++mIndex;

  //std::cout << "SILinear " << mMin + (mIndex-1)*mFaktor<< std::endl;
}

//*******

CScanItemRandom::CScanItemRandom(const CCopasiParameterGroup* si, CRandom* rg)
    : CScanItem(si),
    mRg(rg),
    mRandomType(0),
    mLog(false)
{
  mRandomType = *(unsigned C_INT32*)(si->getValue("Distribution type"));
  std::cout << " ****** " << mRandomType << std::endl;
  mLog = *(bool*)(si->getValue("log"));
  mMin = *(C_FLOAT64*)(si->getValue("Minimum"));
  mMax = *(C_FLOAT64*)(si->getValue("Maximum"));
  if (mLog)
    {
      mMin = log(mMin);
      mMax = log(mMax);
    }
  mNumSteps = 0;
  mFaktor = (mMax - mMin);
}

void CScanItemRandom::step()
{
  C_FLOAT64 Value;

  //the index
  if (mIndex > mNumSteps)
    mFlagFinished = true;
  else
    {
      C_FLOAT64 tmpF;
      switch (mRandomType)
        {
        case 0:       //uniform
          Value = mMin + mRg->getRandomCC() * mFaktor;
          if (mLog)
            Value = exp(Value);
          break;

        case 1:       //normal
          tmpF = mRg->getRandomNormal01();
          Value = mMin + tmpF * mMax;
          if (mLog)
            Value = exp(Value);
          break;

        case 2:       //poisson
          Value = mRg->getRandomPoisson(mMin);
          //if (mLog)
          //  *mpValue = exp(*mpValue);
          break;
        }
    }

  mpValue->setObjectValue(Value);
  ++mIndex;
}

//*******

/*CScanItemBreak::CScanItemBreak(const CCopasiParameterGroup* si, CScanTask* st)
    : CScanItem(si),
    mPlotB(0),
    mReportB(0),
    mST(NULL)
{
  mReportB = *(unsigned C_INT32*)(si->getValue("Report break"));
  mPlotB = *(unsigned C_INT32*)(si->getValue("Plot break"));
  mST = st;
  mNumSteps = 0;
}

void CScanItemBreak::step()
{
  //the index
  if (mIndex > mNumSteps)
    mFlagFinished = true;
  else
    {
      //TODO: tell the task what exactly to do...
      mST->outputSeparatorCallback();
    }

  ++mIndex;
}*/

//**************** CScanMethod class ***************************

CScanMethod * CScanMethod::createMethod() {return new CScanMethod;}

CScanMethod::CScanMethod():
    CCopasiMethod(CCopasiTask::scan, CCopasiMethod::scanMethod),
    mpProblem(NULL),
    mpRandomGenerator(NULL),
    mTotalSteps(1)
    //    mVariableSize(0),
    //    mpVariables(NULL)
{
  //  addParameter("Random Number Generator", CCopasiParameter::STRING,
  //               CRandom::TypeName[1]);
  //  addParameter("Random Number Seed", CCopasiParameter::INT, (C_INT32) 0);
  mpRandomGenerator = CRandom::createGenerator(CRandom::r250);
}

/*CScanMethod::CScanMethod(const CScanMethod & src,
                         const CCopasiContainer * pParent):
    CCopasiMethod(src, pParent),
    mpProblem(NULL),
    mpRandomGenerator(NULL)
    //    mVariableSize(0),
    //    mpVariables(NULL)
{}*/

CScanMethod::~CScanMethod()
{
  cleanupScanItems();
  delete mpRandomGenerator;
  mpRandomGenerator = NULL;
}

bool CScanMethod::cleanupScanItems()
{
  if (!mpProblem) return false;
  unsigned C_INT32 i, imax = mScanItems.size();
  for (i = 0; i < imax; ++i) if (mScanItems[i]) delete mScanItems[i];

  mScanItems.clear();
  return true;
}

bool CScanMethod::init()
{
  if (!mpProblem) return false;

  cleanupScanItems();

  mTotalSteps = 1;

  unsigned C_INT32 i, imax = mpProblem->getNumberOfScanItems();
  for (i = 0; i < imax; ++i)
    {
      mScanItems.push_back(CScanItem::createScanItemFromParameterGroup(mpProblem->getScanItem(i),
                           mpRandomGenerator,
                           (CScanTask*)(getObjectParent())));
      mTotalSteps *= mScanItems[i]->getNumSteps();
    }

  //set mLastNestingItem
  mLastNestingItem = -1;
  if (imax != 0)
    {
      //search from the end
      C_INT32 j;
      for (j = mScanItems.size() - 1; j >= 0; --j)
        {
          if (mScanItems[j]->isNesting())
            {
              mLastNestingItem = j;
              break;
            }
        }
    }

  return true;
}

bool CScanMethod::scan()
{
  if (!mpProblem) return false;

  //a hack to ensure that the first subtask is run with initial conditions
  CCopasiDataModel::Global->getModel()->setState(&mpProblem->getInitialState());

  bool success = true;

  unsigned C_INT32 i, imax = mScanItems.size();

  //store old parameter values
  for (i = 0; i < imax; ++i)
    mScanItems[i]->storeValue();

  //Do the scan...
  success = loop(0);

  //restore old parameter values
  for (i = 0; i < imax; ++i)
    mScanItems[i]->restoreValue();

  return success;
}

bool CScanMethod::loop(unsigned C_INT32 level)
{
  bool isLastMasterItem = (level == (mScanItems.size() - 1)); //TODO

  CScanItem* currentSI = mScanItems[level];

  for (currentSI->reset(); !currentSI->isFinished(); currentSI->step())
    {
      //TODO: handle slave SIs

      if (isLastMasterItem)
        {
          if (!calculate()) return false;
        }
      else
        {
          if (!loop(level + 1)) return false;
        } //TODO

      //separator needs to be handled slightly differently if we are at the last item
      if (currentSI->isNesting())
        ((CScanTask*)(getObjectParent()))->outputSeparatorCallback(level == mLastNestingItem);
    }

  return true;
}

bool CScanMethod::calculate() const
  {
    //std::cout << "*********** Scan: calculate... ************" << std::endl;
    return ((CScanTask*)(getObjectParent()))->processCallback();
  }

void CScanMethod::setProblem(const CScanProblem * problem)
{mpProblem = problem;}
<commit_msg>fix #267: now scan does not crash if there is no scan item.<commit_after>/* Begin CVS Header
   $Source: /Volumes/Home/Users/shoops/cvs/copasi_dev/copasi/scan/CScanMethod.cpp,v $
   $Revision: 1.39 $
   $Name:  $
   $Author: ssahle $
   $Date: 2005/04/11 21:19:24 $
   End CVS Header */

/**
 *  CScanMethod class.
 *  This class describes the Scan method
 *
 *  Created for Copasi by Rohan Luktuke 2002
 */

#include <string>

//#define COPASI_TRACE_CONSTRUCTION
#include "mathematics.h"
#include "copasi.h"
#include "model/CModel.h"
#include "model/CState.h"
#include "utilities/CReadConfig.h"
#include "randomGenerator/CRandom.h"
//#include "utilities/CWriteConfig.h"
#include "CScanProblem.h"
#include "CScanMethod.h"
#include "CScanTask.h"
#include "CopasiDataModel/CCopasiDataModel.h"

// this will have to be defined somewhere else with the
// values of other distribution types
//#define SD_UNIFORM 0
//#define SD_GAUSS 1
//#define SD_BOLTZ 2
//#define SD_REGULAR 3

//**************** CScanItem classes ***************************

//static
CScanItem* CScanItem::createScanItemFromParameterGroup(const CCopasiParameterGroup* si,
    CRandom* rg,
    CScanTask* st)
{
  if (!si) return NULL;

  CScanProblem::Type type = *(CScanProblem::Type*)(si->getValue("Type"));

  CScanItem* tmp;

  if (type == CScanProblem::SCAN_REPEAT)
    tmp = new CScanItemRepeat(si);

  if (type == CScanProblem::SCAN_LINEAR)
    tmp = new CScanItemLinear(si);

  if (type == CScanProblem::SCAN_RANDOM)
    tmp = new CScanItemRandom(si, rg);

  /*  if (type == CScanProblem::SCAN_BREAK)
      tmp = new CScanItemBreak(si, st);*/

  return tmp;
}

CScanItem::CScanItem(const CCopasiParameterGroup* si)
    : mNumSteps(0),
    mpValue(NULL),
    mStoreValue(0.0),
    mIndex(0),
    mFlagFinished(false)
{
  mNumSteps = *(unsigned C_INT32*)(si->getValue("Number of steps"));

  std::string tmpString = *(std::string*)(si->getValue("Object"));
  CCopasiObject* tmpObject = CCopasiContainer::ObjectFromName(tmpString);
  if (!tmpObject) {mpValue = NULL; return;}
  if (!tmpObject->isValueDbl()) {mpValue = NULL; return;}
  mpValue = tmpObject;
}

unsigned C_INT32 CScanItem::getNumSteps() const {return mNumSteps;};

void CScanItem::restoreValue() const
  {
    if (mpValue)
      mpValue->setObjectValue(mStoreValue);
  };

void CScanItem::storeValue()
{if (mpValue) mStoreValue = * (C_FLOAT64 *) mpValue->getReference();};

void CScanItem::reset()
{
  mIndex = 0;
  mFlagFinished = false;
  this->step(); //purely virtual
}

bool CScanItem::isFinished() const {return mFlagFinished;};

//*******

CScanItemRepeat::CScanItemRepeat(const CCopasiParameterGroup* si)
    : CScanItem(si)
{
  if (mNumSteps >= 1)
    --mNumSteps; // for the repeat item mNumSteps is the number of iterations, not of intervals
}

void CScanItemRepeat::step()
{
  //do something ...

  //the index
  if (mIndex > mNumSteps)
    mFlagFinished = true;
  ++mIndex;

  //  std::cout << "SIRepeat " << mIndex-1<< std::endl;
}

//*******

CScanItemLinear::CScanItemLinear(const CCopasiParameterGroup* si)
    : CScanItem(si),
    mLog(false)
{
  mLog = *(bool*)(si->getValue("log"));
  mMin = *(C_FLOAT64*)(si->getValue("Minimum"));
  mMax = *(C_FLOAT64*)(si->getValue("Maximum"));
  if (mLog)
    {
      mMin = log(mMin);
      mMax = log(mMax);
    }
  mFaktor = (mMax - mMin) / mNumSteps;
}

void CScanItemLinear::step()
{
  //do something ...
  C_FLOAT64 Value = mMin + mIndex * mFaktor;

  if (mLog)
    Value = exp(Value);
  //the index
  if (mIndex > mNumSteps)
    mFlagFinished = true;

  mpValue->setObjectValue(Value);
  ++mIndex;

  //std::cout << "SILinear " << mMin + (mIndex-1)*mFaktor<< std::endl;
}

//*******

CScanItemRandom::CScanItemRandom(const CCopasiParameterGroup* si, CRandom* rg)
    : CScanItem(si),
    mRg(rg),
    mRandomType(0),
    mLog(false)
{
  mRandomType = *(unsigned C_INT32*)(si->getValue("Distribution type"));
  std::cout << " ****** " << mRandomType << std::endl;
  mLog = *(bool*)(si->getValue("log"));
  mMin = *(C_FLOAT64*)(si->getValue("Minimum"));
  mMax = *(C_FLOAT64*)(si->getValue("Maximum"));
  if (mLog)
    {
      mMin = log(mMin);
      mMax = log(mMax);
    }
  mNumSteps = 0;
  mFaktor = (mMax - mMin);
}

void CScanItemRandom::step()
{
  C_FLOAT64 Value;

  //the index
  if (mIndex > mNumSteps)
    mFlagFinished = true;
  else
    {
      C_FLOAT64 tmpF;
      switch (mRandomType)
        {
        case 0:        //uniform
          Value = mMin + mRg->getRandomCC() * mFaktor;
          if (mLog)
            Value = exp(Value);
          break;

        case 1:        //normal
          tmpF = mRg->getRandomNormal01();
          Value = mMin + tmpF * mMax;
          if (mLog)
            Value = exp(Value);
          break;

        case 2:        //poisson
          Value = mRg->getRandomPoisson(mMin);
          //if (mLog)
          //  *mpValue = exp(*mpValue);
          break;
        }
    }

  mpValue->setObjectValue(Value);
  ++mIndex;
}

//*******

/*CScanItemBreak::CScanItemBreak(const CCopasiParameterGroup* si, CScanTask* st)
    : CScanItem(si),
    mPlotB(0),
    mReportB(0),
    mST(NULL)
{
  mReportB = *(unsigned C_INT32*)(si->getValue("Report break"));
  mPlotB = *(unsigned C_INT32*)(si->getValue("Plot break"));
  mST = st;
  mNumSteps = 0;
}

void CScanItemBreak::step()
{
  //the index
  if (mIndex > mNumSteps)
    mFlagFinished = true;
  else
    {
      //TODO: tell the task what exactly to do...
      mST->outputSeparatorCallback();
    }

  ++mIndex;
}*/

//**************** CScanMethod class ***************************

CScanMethod * CScanMethod::createMethod() {return new CScanMethod;}

CScanMethod::CScanMethod():
    CCopasiMethod(CCopasiTask::scan, CCopasiMethod::scanMethod),
    mpProblem(NULL),
    mpRandomGenerator(NULL),
    mTotalSteps(1)
    //    mVariableSize(0),
    //    mpVariables(NULL)
{
  //  addParameter("Random Number Generator", CCopasiParameter::STRING,
  //               CRandom::TypeName[1]);
  //  addParameter("Random Number Seed", CCopasiParameter::INT, (C_INT32) 0);
  mpRandomGenerator = CRandom::createGenerator(CRandom::r250);
}

/*CScanMethod::CScanMethod(const CScanMethod & src,
                         const CCopasiContainer * pParent):
    CCopasiMethod(src, pParent),
    mpProblem(NULL),
    mpRandomGenerator(NULL)
    //    mVariableSize(0),
    //    mpVariables(NULL)
{}*/

CScanMethod::~CScanMethod()
{
  cleanupScanItems();
  delete mpRandomGenerator;
  mpRandomGenerator = NULL;
}

bool CScanMethod::cleanupScanItems()
{
  if (!mpProblem) return false;
  unsigned C_INT32 i, imax = mScanItems.size();
  for (i = 0; i < imax; ++i) if (mScanItems[i]) delete mScanItems[i];

  mScanItems.clear();
  return true;
}

bool CScanMethod::init()
{
  if (!mpProblem) return false;

  cleanupScanItems();

  mTotalSteps = 1;

  unsigned C_INT32 i, imax = mpProblem->getNumberOfScanItems();
  for (i = 0; i < imax; ++i)
    {
      mScanItems.push_back(CScanItem::createScanItemFromParameterGroup(mpProblem->getScanItem(i),
                           mpRandomGenerator,
                           (CScanTask*)(getObjectParent())));
      mTotalSteps *= mScanItems[i]->getNumSteps();
    }

  //set mLastNestingItem
  mLastNestingItem = -1;
  if (imax != 0)
    {
      //search from the end
      C_INT32 j;
      for (j = mScanItems.size() - 1; j >= 0; --j)
        {
          if (mScanItems[j]->isNesting())
            {
              mLastNestingItem = j;
              break;
            }
        }
    }

  return true;
}

bool CScanMethod::scan()
{
  if (!mpProblem) return false;

  //a hack to ensure that the first subtask is run with initial conditions
  CCopasiDataModel::Global->getModel()->setState(&mpProblem->getInitialState());

  bool success = true;

  unsigned C_INT32 i, imax = mScanItems.size();

  //store old parameter values
  for (i = 0; i < imax; ++i)
    mScanItems[i]->storeValue();

  //Do the scan...
  if (imax) //there are scan items
    success = loop(0);
  else
    success = calculate(); //nothing to scan, only one call to the subtask

  //restore old parameter values
  for (i = 0; i < imax; ++i)
    mScanItems[i]->restoreValue();

  return success;
}

bool CScanMethod::loop(unsigned C_INT32 level)
{
  bool isLastMasterItem = (level == (mScanItems.size() - 1)); //TODO

  CScanItem* currentSI = mScanItems[level];

  for (currentSI->reset(); !currentSI->isFinished(); currentSI->step())
    {
      //TODO: handle slave SIs

      if (isLastMasterItem)
        {
          if (!calculate()) return false;
        }
      else
        {
          if (!loop(level + 1)) return false;
        } //TODO

      //separator needs to be handled slightly differently if we are at the last item
      if (currentSI->isNesting())
        ((CScanTask*)(getObjectParent()))->outputSeparatorCallback(level == mLastNestingItem);
    }

  return true;
}

bool CScanMethod::calculate() const
  {
    //std::cout << "*********** Scan: calculate... ************" << std::endl;
    return ((CScanTask*)(getObjectParent()))->processCallback();
  }

void CScanMethod::setProblem(const CScanProblem * problem)
{mpProblem = problem;}
<|endoftext|>


<commit_before>/*****************************************************************************
* PROGRAM NAME: CMca.cpp
* PROGRAMMER: Wei Sun	wsun@vt.edu
* PURPOSE: Implement the CMca Class, its value is updated in simulation running
*	       and outputed in Rep_MCA()
*****************************************************************************/

#include <cmath>      //for fabs()
#include <limits.h>

#include "copasi.h"
#include "utilities/utilities.h"
#include "model/model.h"
#include "CMca.h"

// #define DBL_MAX  1.7976931348623158e+308

/**
 * Defaulut constructor
 */
CMca::CMca()
{
}

/**
 * User defined constructor
 * @param refer to Model and factor
 */
CMca::CMca(CModel model, C_FLOAT64 factor)
{
  Model = model;

  mDxv.newsize(Model.getTotSteps(), Model.getIndMetab());
  mFcc.newsize(Model.getTotSteps(), Model.getTotSteps());
  mGamma.newsize(Model.getIndMetab(), Model.getTotSteps());
  mSsx.resize(Model.getIndMetab() + 1);

  mFactor = factor;
}

/**
 * Deconstructor
 */
CMca::~CMca()
{
  delSsipvt();
}

/**
 * Set the Model
 */
void CMca::setModel(CModel model)
{
  Model = model;
}

/**
 * return the mDxv matrix
 * @return Matrix
 */
TNT::Matrix < C_FLOAT64 > CMca::getDxv()
{
  return mDxv;
}

/**
 * return the mFCC matrix
 * @return Matrix
 */
TNT::Matrix < C_FLOAT64 > CMca::getFcc()
{
  return mFcc;
}

/**
 * return the mGamma matrix
 * @return Matrix
 */
TNT::Matrix < C_FLOAT64 > CMca::getGamma()
{
  return mGamma;
}

/**
 *	Clear Dxv with zeros
 */
void CMca::clearDxv()
{
  register int i, j;

  for(i = 0; i < mDxv.num_rows(); i++)
    for(j = 0; j < mDxv.num_cols(); j++ )
      mDxv[i][j] = 0.0;
}

/**
 * Initialize mDxv with the unscaled elasticities
 * @param src is newtown variable, (is ss_x in Gespasi project)
 * @param res is the resolution of steady state
 */
void CMca::initDxv(C_FLOAT64 res)
{
  register int i, j;
  C_FLOAT64 store, temp, *f1, *f2;
  C_FLOAT64 K1, K2, K3;

  // constants for differentiation by finite differences
  K1 = 1 + mFactor;
  K2 = 1 - mFactor;
  K3 = 2 * mFactor;

  // Arrays to store function value
  f1 = new C_FLOAT64[mDxv.num_rows()];
  f2 = new C_FLOAT64[mDxv.num_rows()];

  // load Dxv with elasticities
  for (j = 0; j < mDxv.num_cols(); j++)
    {
      /**
       * if src[i+1] (x_ss[i+1]) is zero, the derivative will be calculated at a small
       * positive value (no point in considering negative values!).
       * let's stick with res*K1 (SSRes)
       */
      store = mSsx[j+1];
      if (store < res) temp = res * K1;
      else temp = store;

      // let's take X_dx
      mSsx[j+1] = temp * K1;
      // Calcualte the fluxes
      for (i = 0; i < mDxv.num_rows(); i++)
	f1[i] = Model.getReactions()[i].calculate();
      // now X-dx
      mSsx[j+1] = temp * K2;
      // calculate the fluxes
      for (i = 0; i < mDxv.num_rows(); i++)
	f2[i] = Model.getReactions()[i].calculate();

      // set column j of Dxv
      for( i = 0; i < mDxv.num_rows(); i++ )
	mDxv[i][j] = (f1[i]-f2[i])/(temp*K3);

      // restore the value of (src[i])ss_x[i]
      mSsx[j+1] = store;
    }

  // Clean up memory
  delete [] f1;
  delete [] f2;
}

/**
 *	Calculates the flux-control coefficients
 *  @param refer to the condition when calculating
 */
void CMca::CalcFCC(int condition)
{
  register int i, j, k;

  if (condition == MCA_SINGULAR)
    {
      for (i = 0; i < mFcc.num_rows(); i++)
	for (j = 0; j < mFcc.num_cols(); j++)
	  mFcc[i][j] = 0.0;
    }
  else {
    // mFcc = I + mDxv * mGamma
    for (i = 0; i < mFcc.num_rows(); i++)
      for (j = 0; j < mFcc.num_cols(); j++)
	{
	  mFcc[i][j] = (i == j) ? 1.0 :0.0;
	  for (k = 0; k < mDxv.num_cols(); k++)
	    mFcc[i][j] += mDxv[i][k] * mGamma[k][j];
	}
  }
}

/**
 * Calculates the concentration-control coefficients
 */
int CMca::CalcGamma()
{
  register int i, j, k;
  C_FLOAT64 **aux1, **aux2;
  int dim;
  C_INT32 info;

  // Create auxiliary matrices as big as needed
  if (Model.getIndMetab() > Model.getTotSteps())
    dim = Model.getIndMetab() + 1;
  else dim = Model.getTotSteps() + 1;

  // Create aux1 and aux2
  aux1 = (C_FLOAT64 **) malloc((dim) * sizeof(*aux1));
  aux2 = (C_FLOAT64 **) malloc((dim) * sizeof(*aux2));

  for (i = 0 ; i < dim ; i++)
    {
      aux1[i] = (C_FLOAT64 *) malloc((dim) * sizeof(C_FLOAT64));
      aux2[i] = (C_FLOAT64 *) malloc((dim) * sizeof(C_FLOAT64));
    }

  // set mGamma to zeros
  for (i = 0; i < mGamma.num_rows(); i++)
    for (j = 0; j < mGamma.num_cols(); i++)
      mGamma[i][j] = 0.0;

  // aux1 = rstoi * mDxv
  for (i = 0; i < Model.getIndMetab(); i++)
    for (j = 0; j < Model.getIndMetab(); j++)
      {
	aux1[i][j] = 0.0;
	for (k = 0; k < Model.getTotSteps(); k++)
	  aux1[i][j] += (C_FLOAT64) Model.getRedStoi()[i][k] * mDxv[k][j];
      }

  // aux2 = aux1 * m1 (shifting indices for dgefa)
  for (i = 0; i < Model.getIndMetab(); i++)
    for (j = 0; j < Model.getIndMetab(); j++)
      {
	aux2[i+1][j+1] = 0.0;
	for (k = 0; k < Model.getIndMetab(); k++)
	  aux2[i+1][j+1] += aux1[i][k] * Model.getL()(k+1,j+1); //???
      }

  // LU decomposition if aux2 (for inversion)
  //	dgefa -> luX??
  dgefa(aux2, Model.getIndMetab(), mSsipvt, &info);

  if (info != 0)
    {
      // matrix is singular
      // return now (mGamma[i][j] = 0)
      // delete matrices
      for(i = 0; i < dim; i++)
	{
	  free((void *) aux1[i]);
	  free((void *) aux2[i]);
	}
      free((void *) aux1);
      free((void *) aux2);

      return MCA_SINGULAR;
    }

  // set aux1 to the identity matrix (for inversion with dgesl)
  for (i = 0; i < Model.getIndMetab(); i++)
    for (j = 0; j < Model.getIndMetab(); j++)
      aux1[i+1][j+1] = (i == j)? 1.0 : 0.0;

  // now invert aux2 (result in aux1)
  for (i = 0; i < Model.getIndMetab(); i++)
    dgesl(aux2, Model.getIndMetab(), mSsipvt, aux1[i+1], 1);
  // aux2 = - ml * aux1 (shifting indeces back to 0 again)
  for (i = 0; i < Model.getIndMetab(); i++)
    for (j = 0; j < Model.getIndMetab(); j++)
      {
	aux2[i][j] = 0.0;
	for (k = 0; k < Model.getIndMetab(); k++)
	  aux2[i][j] -= (C_FLOAT64)Model.getmLU()[i][k] * aux1[k+1][j+1];
      }

  // mGamma = aux2 *RedStoi
  for (i = 0; i < Model.getIndMetab(); i++)
    for (j = 0; j < Model.getTotSteps(); j++)
      for (k = 0; k < Model.getIndMetab(); k++)
	mGamma[i][j] += aux2[i][k] * (C_FLOAT64) Model.getRedStoi()[k][j];

  // delete matrices
  for(i = 0; i < dim; i++)
    {
      free((void *) aux1[i]);
      free((void *) aux2[i]);
    }
  free((void *) aux1);
  free((void *) aux2);

  return MCA_OK;
}

/**
 * Initialize ss_ipvt
 */
void CMca::initSsipvt()
{
  mSsipvt = (C_INT32 *) malloc((Model.getIndMetab()) * sizeof(C_INT32));
}

/**
 * Deletet ss_ipvt
 */
void CMca::delSsipvt()
{
  free((void *) mSsipvt);
}

/**
 * Initialize the MCA matrices: mDxv, mFcc, mGamma
 */
void CMca::init()
{
  mDxv.newsize(Model.getTotSteps(), Model.getTotMetab());
  mFcc.newsize(Model.getTotSteps(), Model.getTotSteps());
  mGamma.newsize(Model.getIndMetab(), Model.getTotSteps());
  mSsx.resize(Model.getTotMetab() + 1);
}

/**
 * the steady state MCA entry point
 * @param ss_solution refer to steady-state solution
 * @param refer to the resolution
 */
int CMca::CalculateMCA(int ss_solution, int res)
{
  int ret;

  // Initialize the ss_ipvt vector
  initSsipvt();

  // Create mDxv, mFcc, mGamma
  init();

  if (!ss_solution) initDxv(res);
  else clearDxv();

  ret = CalcGamma();
  CalcFCC(ret);

  if (!mSSReder) ScaleMCA(ret, res);

  return ret;
}

/**
 * Read SSMCAUnscaled from configuration file
 */
C_INT32 CMca::load(CReadConfig & configBuffer)
{
  C_INT32	Fail = 0;

  if ((Fail = configBuffer.getVariable("SSMCAUnscaled", "C_INT16",
				       (void *) &mSSReder,
				       CReadConfig::LOOP)))
    return Fail;

  return Fail;
}

/**
 * Scales the coefficients (i.e. Kacser format, rather than Reder)
 * @param refer to the condition
 * @param refer to the resolution
 */
void CMca::ScaleMCA(int condition, int res)
{
  register int i, j;

  // if previous calcutations failed return now
  if( condition != MCA_OK ) return;

  // Scale Dxv
  for(i = 0; i < Model.getTotSteps(); i++)
    for(j = 0; j < Model.getTotMetab(); j++)
      {
	// change the use of Col[] and Row[] to mStepsX and mMetabolitesX
	if( fabs( Model.getStepsX()[i]->getFlux() ) >= res )
	  {
	    mDxv[i][j] *=   *Model.getMetabolitesX()[j]->getConcentration()
	      * Model.getMetabolitesX()[j]->getCompartment()->getVolume()
	      / Model.getStepsX()[i]->getFlux();
	  }
	else mDxv[i][j] = DBL_MAX;
      }

  // Scale Gamma
  for(i = 0; i < Model.getIndMetab(); i++)
    for(j = 0; j < Model.getTotSteps(); j++)
      {
	if( fabs(*Model.getMetabolitesX()[i]->getConcentration()) >= res)
	  mGamma[i][j] *=   Model.getStepsX()[j]->getFlux()
	    / (*Model.getMetabolitesX()[i]->getConcentration()
	       *
	       Model.getMetabolitesX()[j]->getCompartment()->getVolume());
	else mGamma[i][j] = DBL_MAX;
      }

  // Scale FCC
  for(i = 0; i < Model.getTotSteps(); i++)
    for(j = 0; j < Model.getTotSteps(); j++)
      {
	if( fabs( Model.getStepsX()[i]->getFlux()  ) >= res )
	  mFcc[i][j] *=   Model.getStepsX()[j]->getFlux()
	    / Model.getStepsX()[i]->getFlux();
	else mFcc[i][j] = DBL_MAX;
      }

}

/**
 * the time dependent MCA entry point
 * @param refer to the resolution
 */
void CMca::CalculateTimeMCA(int res)
{
  register int i, j;

  mSsx.resize(Model.getTotMetab());

  //copy concentrations to ss_x
  for(i = 0; i < Model.getTotMetab(); i++)
    mSsx[i+1] = *Model.getMetabolitesX()[i]->getConcentration() *
      Model.getMetabolitesX()[i]->getCompartment()->getVolume();

  // calculate the elasticites
  initDxv(res);

  // scale the elasticities if needed
  if (mSSReder == 0)
    {
      for(i = 0; i < Model.getTotSteps(); i++)
	for(j = 0; j < Model.getTotMetab(); j++)
	  {
	    if( fabs( Model.getStepsX()[i]->getFlux() ) >= res )
	      mDxv[i][j] *= *Model.getMetabolitesX()[j]->getConcentration() /
		Model.getStepsX()[i]->getFlux();
	    else mDxv[i][j] = DBL_MAX;
	  }

    }

}

/**
 * Return the mSSx vector for calculate time mca
 * @return vector <C_FLOAT64>
 */
vector <C_FLOAT64> CMca::getSsx()
{
  return mSsx;
}

/**
 *  Saves the SSReder of the object to a CWriteConfig object.
 *  @param pconfigbuffer reference to a CWriteConfig object.
 *  @return mFail
 *  @see mFail
 */
C_INT32 CMca::save(CWriteConfig & configbuffer)
{
  C_INT32 Fail = 0;

  if ((Fail = configbuffer.setVariable("SSMCAUnscaled", "C_INT16",
				       &mSSReder)))
    return Fail;

  return Fail;
}
<commit_msg>Fixed undefined DBL_MAX in limits.h under Windows<commit_after>/*****************************************************************************
* PROGRAM NAME: CMca.cpp
* PROGRAMMER: Wei Sun	wsun@vt.edu
* PURPOSE: Implement the CMca Class, its value is updated in simulation running
*	       and outputed in Rep_MCA()
*****************************************************************************/

#include <cmath>      //for fabs()
#include <limits.h>

#include "copasi.h"
#include "utilities/utilities.h"
#include "model/model.h"
#include "CMca.h"

#ifndef DBL_MAX
#define DBL_MAX 1.7976931348623158e+308
#endif //DBL_MAX

/**
 * Defaulut constructor
 */
CMca::CMca()
{
}

/**
 * User defined constructor
 * @param refer to Model and factor
 */
CMca::CMca(CModel model, C_FLOAT64 factor)
{
  Model = model;

  mDxv.newsize(Model.getTotSteps(), Model.getIndMetab());
  mFcc.newsize(Model.getTotSteps(), Model.getTotSteps());
  mGamma.newsize(Model.getIndMetab(), Model.getTotSteps());
  mSsx.resize(Model.getIndMetab() + 1);

  mFactor = factor;
}

/**
 * Deconstructor
 */
CMca::~CMca()
{
  delSsipvt();
}

/**
 * Set the Model
 */
void CMca::setModel(CModel model)
{
  Model = model;
}

/**
 * return the mDxv matrix
 * @return Matrix
 */
TNT::Matrix < C_FLOAT64 > CMca::getDxv()
{
  return mDxv;
}

/**
 * return the mFCC matrix
 * @return Matrix
 */
TNT::Matrix < C_FLOAT64 > CMca::getFcc()
{
  return mFcc;
}

/**
 * return the mGamma matrix
 * @return Matrix
 */
TNT::Matrix < C_FLOAT64 > CMca::getGamma()
{
  return mGamma;
}

/**
 *	Clear Dxv with zeros
 */
void CMca::clearDxv()
{
  register int i, j;

  for(i = 0; i < mDxv.num_rows(); i++)
    for(j = 0; j < mDxv.num_cols(); j++ )
      mDxv[i][j] = 0.0;
}

/**
 * Initialize mDxv with the unscaled elasticities
 * @param src is newtown variable, (is ss_x in Gespasi project)
 * @param res is the resolution of steady state
 */
void CMca::initDxv(C_FLOAT64 res)
{
  register int i, j;
  C_FLOAT64 store, temp, *f1, *f2;
  C_FLOAT64 K1, K2, K3;

  // constants for differentiation by finite differences
  K1 = 1 + mFactor;
  K2 = 1 - mFactor;
  K3 = 2 * mFactor;

  // Arrays to store function value
  f1 = new C_FLOAT64[mDxv.num_rows()];
  f2 = new C_FLOAT64[mDxv.num_rows()];

  // load Dxv with elasticities
  for (j = 0; j < mDxv.num_cols(); j++)
    {
      /**
       * if src[i+1] (x_ss[i+1]) is zero, the derivative will be calculated at a small
       * positive value (no point in considering negative values!).
       * let's stick with res*K1 (SSRes)
       */
      store = mSsx[j+1];
      if (store < res) temp = res * K1;
      else temp = store;

      // let's take X_dx
      mSsx[j+1] = temp * K1;
      // Calcualte the fluxes
      for (i = 0; i < mDxv.num_rows(); i++)
	f1[i] = Model.getReactions()[i].calculate();
      // now X-dx
      mSsx[j+1] = temp * K2;
      // calculate the fluxes
      for (i = 0; i < mDxv.num_rows(); i++)
	f2[i] = Model.getReactions()[i].calculate();

      // set column j of Dxv
      for( i = 0; i < mDxv.num_rows(); i++ )
	mDxv[i][j] = (f1[i]-f2[i])/(temp*K3);

      // restore the value of (src[i])ss_x[i]
      mSsx[j+1] = store;
    }

  // Clean up memory
  delete [] f1;
  delete [] f2;
}

/**
 *	Calculates the flux-control coefficients
 *  @param refer to the condition when calculating
 */
void CMca::CalcFCC(int condition)
{
  register int i, j, k;

  if (condition == MCA_SINGULAR)
    {
      for (i = 0; i < mFcc.num_rows(); i++)
	for (j = 0; j < mFcc.num_cols(); j++)
	  mFcc[i][j] = 0.0;
    }
  else {
    // mFcc = I + mDxv * mGamma
    for (i = 0; i < mFcc.num_rows(); i++)
      for (j = 0; j < mFcc.num_cols(); j++)
	{
	  mFcc[i][j] = (i == j) ? 1.0 :0.0;
	  for (k = 0; k < mDxv.num_cols(); k++)
	    mFcc[i][j] += mDxv[i][k] * mGamma[k][j];
	}
  }
}

/**
 * Calculates the concentration-control coefficients
 */
int CMca::CalcGamma()
{
  register int i, j, k;
  C_FLOAT64 **aux1, **aux2;
  int dim;
  C_INT32 info;

  // Create auxiliary matrices as big as needed
  if (Model.getIndMetab() > Model.getTotSteps())
    dim = Model.getIndMetab() + 1;
  else dim = Model.getTotSteps() + 1;

  // Create aux1 and aux2
  aux1 = (C_FLOAT64 **) malloc((dim) * sizeof(*aux1));
  aux2 = (C_FLOAT64 **) malloc((dim) * sizeof(*aux2));

  for (i = 0 ; i < dim ; i++)
    {
      aux1[i] = (C_FLOAT64 *) malloc((dim) * sizeof(C_FLOAT64));
      aux2[i] = (C_FLOAT64 *) malloc((dim) * sizeof(C_FLOAT64));
    }

  // set mGamma to zeros
  for (i = 0; i < mGamma.num_rows(); i++)
    for (j = 0; j < mGamma.num_cols(); i++)
      mGamma[i][j] = 0.0;

  // aux1 = rstoi * mDxv
  for (i = 0; i < Model.getIndMetab(); i++)
    for (j = 0; j < Model.getIndMetab(); j++)
      {
	aux1[i][j] = 0.0;
	for (k = 0; k < Model.getTotSteps(); k++)
	  aux1[i][j] += (C_FLOAT64) Model.getRedStoi()[i][k] * mDxv[k][j];
      }

  // aux2 = aux1 * m1 (shifting indices for dgefa)
  for (i = 0; i < Model.getIndMetab(); i++)
    for (j = 0; j < Model.getIndMetab(); j++)
      {
	aux2[i+1][j+1] = 0.0;
	for (k = 0; k < Model.getIndMetab(); k++)
	  aux2[i+1][j+1] += aux1[i][k] * Model.getL()(k+1,j+1); //???
      }

  // LU decomposition if aux2 (for inversion)
  //	dgefa -> luX??
  dgefa(aux2, Model.getIndMetab(), mSsipvt, &info);

  if (info != 0)
    {
      // matrix is singular
      // return now (mGamma[i][j] = 0)
      // delete matrices
      for(i = 0; i < dim; i++)
	{
	  free((void *) aux1[i]);
	  free((void *) aux2[i]);
	}
      free((void *) aux1);
      free((void *) aux2);

      return MCA_SINGULAR;
    }

  // set aux1 to the identity matrix (for inversion with dgesl)
  for (i = 0; i < Model.getIndMetab(); i++)
    for (j = 0; j < Model.getIndMetab(); j++)
      aux1[i+1][j+1] = (i == j)? 1.0 : 0.0;

  // now invert aux2 (result in aux1)
  for (i = 0; i < Model.getIndMetab(); i++)
    dgesl(aux2, Model.getIndMetab(), mSsipvt, aux1[i+1], 1);
  // aux2 = - ml * aux1 (shifting indeces back to 0 again)
  for (i = 0; i < Model.getIndMetab(); i++)
    for (j = 0; j < Model.getIndMetab(); j++)
      {
	aux2[i][j] = 0.0;
	for (k = 0; k < Model.getIndMetab(); k++)
	  aux2[i][j] -= (C_FLOAT64)Model.getmLU()[i][k] * aux1[k+1][j+1];
      }

  // mGamma = aux2 *RedStoi
  for (i = 0; i < Model.getIndMetab(); i++)
    for (j = 0; j < Model.getTotSteps(); j++)
      for (k = 0; k < Model.getIndMetab(); k++)
	mGamma[i][j] += aux2[i][k] * (C_FLOAT64) Model.getRedStoi()[k][j];

  // delete matrices
  for(i = 0; i < dim; i++)
    {
      free((void *) aux1[i]);
      free((void *) aux2[i]);
    }
  free((void *) aux1);
  free((void *) aux2);

  return MCA_OK;
}

/**
 * Initialize ss_ipvt
 */
void CMca::initSsipvt()
{
  mSsipvt = (C_INT32 *) malloc((Model.getIndMetab()) * sizeof(C_INT32));
}

/**
 * Deletet ss_ipvt
 */
void CMca::delSsipvt()
{
  free((void *) mSsipvt);
}

/**
 * Initialize the MCA matrices: mDxv, mFcc, mGamma
 */
void CMca::init()
{
  mDxv.newsize(Model.getTotSteps(), Model.getTotMetab());
  mFcc.newsize(Model.getTotSteps(), Model.getTotSteps());
  mGamma.newsize(Model.getIndMetab(), Model.getTotSteps());
  mSsx.resize(Model.getTotMetab() + 1);
}

/**
 * the steady state MCA entry point
 * @param ss_solution refer to steady-state solution
 * @param refer to the resolution
 */
int CMca::CalculateMCA(int ss_solution, int res)
{
  int ret;

  // Initialize the ss_ipvt vector
  initSsipvt();

  // Create mDxv, mFcc, mGamma
  init();

  if (!ss_solution) initDxv(res);
  else clearDxv();

  ret = CalcGamma();
  CalcFCC(ret);

  if (!mSSReder) ScaleMCA(ret, res);

  return ret;
}

/**
 * Read SSMCAUnscaled from configuration file
 */
C_INT32 CMca::load(CReadConfig & configBuffer)
{
  C_INT32	Fail = 0;

  if ((Fail = configBuffer.getVariable("SSMCAUnscaled", "C_INT16",
				       (void *) &mSSReder,
				       CReadConfig::LOOP)))
    return Fail;

  return Fail;
}

/**
 * Scales the coefficients (i.e. Kacser format, rather than Reder)
 * @param refer to the condition
 * @param refer to the resolution
 */
void CMca::ScaleMCA(int condition, int res)
{
  register int i, j;

  // if previous calcutations failed return now
  if( condition != MCA_OK ) return;

  // Scale Dxv
  for(i = 0; i < Model.getTotSteps(); i++)
    for(j = 0; j < Model.getTotMetab(); j++)
      {
	// change the use of Col[] and Row[] to mStepsX and mMetabolitesX
	if( fabs( Model.getStepsX()[i]->getFlux() ) >= res )
	  {
	    mDxv[i][j] *=   *Model.getMetabolitesX()[j]->getConcentration()
	      * Model.getMetabolitesX()[j]->getCompartment()->getVolume()
	      / Model.getStepsX()[i]->getFlux();
	  }
	else mDxv[i][j] = DBL_MAX;
      }

  // Scale Gamma
  for(i = 0; i < Model.getIndMetab(); i++)
    for(j = 0; j < Model.getTotSteps(); j++)
      {
	if( fabs(*Model.getMetabolitesX()[i]->getConcentration()) >= res)
	  mGamma[i][j] *=   Model.getStepsX()[j]->getFlux()
	    / (*Model.getMetabolitesX()[i]->getConcentration()
	       *
	       Model.getMetabolitesX()[j]->getCompartment()->getVolume());
	else mGamma[i][j] = DBL_MAX;
      }

  // Scale FCC
  for(i = 0; i < Model.getTotSteps(); i++)
    for(j = 0; j < Model.getTotSteps(); j++)
      {
	if( fabs( Model.getStepsX()[i]->getFlux()  ) >= res )
	  mFcc[i][j] *=   Model.getStepsX()[j]->getFlux()
	    / Model.getStepsX()[i]->getFlux();
	else mFcc[i][j] = DBL_MAX;
      }

}

/**
 * the time dependent MCA entry point
 * @param refer to the resolution
 */
void CMca::CalculateTimeMCA(int res)
{
  register int i, j;

  mSsx.resize(Model.getTotMetab());

  //copy concentrations to ss_x
  for(i = 0; i < Model.getTotMetab(); i++)
    mSsx[i+1] = *Model.getMetabolitesX()[i]->getConcentration() *
      Model.getMetabolitesX()[i]->getCompartment()->getVolume();

  // calculate the elasticites
  initDxv(res);

  // scale the elasticities if needed
  if (mSSReder == 0)
    {
      for(i = 0; i < Model.getTotSteps(); i++)
	for(j = 0; j < Model.getTotMetab(); j++)
	  {
	    if( fabs( Model.getStepsX()[i]->getFlux() ) >= res )
	      mDxv[i][j] *= *Model.getMetabolitesX()[j]->getConcentration() /
		Model.getStepsX()[i]->getFlux();
	    else mDxv[i][j] = DBL_MAX;
	  }

    }

}

/**
 * Return the mSSx vector for calculate time mca
 * @return vector <C_FLOAT64>
 */
vector <C_FLOAT64> CMca::getSsx()
{
  return mSsx;
}

/**
 *  Saves the SSReder of the object to a CWriteConfig object.
 *  @param pconfigbuffer reference to a CWriteConfig object.
 *  @return mFail
 *  @see mFail
 */
C_INT32 CMca::save(CWriteConfig & configbuffer)
{
  C_INT32 Fail = 0;

  if ((Fail = configbuffer.setVariable("SSMCAUnscaled", "C_INT16",
				       &mSSReder)))
    return Fail;

  return Fail;
}
<|endoftext|>


<commit_before>#ifndef STAN_MATH_PRIM_MAT_FUN_OPENCL_COPY_HPP
#define STAN_MATH_PRIM_MAT_FUN_OPENCL_COPY_HPP
#ifdef STAN_OPENCL

#include <stan/math/opencl/opencl_context.hpp>
#include <stan/math/opencl/kernel_cl.hpp>
#include <stan/math/opencl/matrix_cl.hpp>
#include <stan/math/opencl/kernels/copy.hpp>
#include <stan/math/opencl/kernels/pack.hpp>
#include <stan/math/opencl/kernels/unpack.hpp>
#include <stan/math/opencl/buffer_types.hpp>
#include <stan/math/opencl/err/check_opencl.hpp>
#include <stan/math/prim/mat/fun/Eigen.hpp>
#include <stan/math/prim/scal/err/check_size_match.hpp>
#include <stan/math/prim/arr/fun/vec_concat.hpp>

#include <CL/cl.hpp>
#include <iostream>
#include <vector>
#include <algorithm>
#include <type_traits>

namespace stan {
namespace math {

/**
 * Copies the source Eigen matrix to
 * the destination matrix that is stored
 * on the OpenCL device.
 *
 * @tparam T type of data in the Eigen matrix
 * @param src source Eigen matrix
 * @return matrix_cl with a copy of the data in the source matrix
 * @throw std::invalid_argument if the
 * matrices do not have matching dimensions
 */
template <int R, int C>
inline matrix_cl to_matrix_cl(const Eigen::Matrix<double, R, C>& src) {
  matrix_cl dst(src.rows(), src.cols());
  if (src.size() == 0) {
    return dst;
  }
  try {
    /**
     * Writes the contents of src to the OpenCL buffer
     * starting at the offset 0
     * CL_FALSE denotes that the call is non-blocking
     * This means that future kernels need to know about the copy_event
     * So that they do not execute until this transfer finishes.
     */
    cl::Event copy_event;
    const cl::CommandQueue& queue = opencl_context.queue();
    queue.enqueueWriteBuffer(dst.buffer(), CL_FALSE, 0,
                             sizeof(double) * dst.size(), src.data(),
                             &dst.write_events(), &copy_event);
    dst.add_write_event(copy_event);
  } catch (const cl::Error& e) {
    check_opencl_error("copy Eigen->(OpenCL)", e);
  }
  return dst;
}

/**
 * Copies the source matrix that is stored
 * on the OpenCL device to the destination Eigen
 * matrix.
 *
 * @param src source matrix on the OpenCL device
 * @return Eigen matrix with a copy of the data in the source matrix
 * @throw std::invalid_argument if the
 * matrices do not have matching dimensions
 */
inline Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> from_matrix_cl(
    const matrix_cl& src) {
  Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> dst(src.rows(),
                                                            src.cols());
  if (src.size() == 0) {
    return dst;
  }
  try {
    /**
     * Reads the contents of the OpenCL buffer
     * starting at the offset 0 to the Eigen
     * matrix
     * CL_TRUE denotes that the call is blocking
     * We do not want to pass data back to the CPU until all of the jobs
     * called on the source matrix are finished.
     */
    cl::Event copy_event;
    const cl::CommandQueue queue = opencl_context.queue();
    queue.enqueueReadBuffer(src.buffer(), CL_FALSE, 0,
                            sizeof(double) * dst.size(), dst.data(),
                            &src.write_events(), &copy_event);
    copy_event.wait();
    src.clear_write_events();
  } catch (const cl::Error& e) {
    check_opencl_error("copy (OpenCL)->Eigen", e);
  }
  return dst;
}

/**
 * Packs the flat triagnular matrix on the OpenCL device and
 * copies it to the std::vector.
 *
 * @tparam triangular_view the triangularity of the source matrix
 * @param src the flat triangular source matrix on the OpenCL device
 * @return the packed std::vector
 */
template <TriangularViewCL triangular_view>
inline std::vector<double> packed_copy(const matrix_cl& src) {
  const int packed_size = src.rows() * (src.rows() + 1) / 2;
  std::vector<double> dst(packed_size);
  if (dst.size() == 0) {
    return dst;
  }
  try {
    const cl::CommandQueue queue = opencl_context.queue();
    matrix_cl packed(packed_size, 1);
    stan::math::opencl_kernels::pack(cl::NDRange(src.rows(), src.rows()),
                                     packed, src, src.rows(), src.rows(),
                                     triangular_view);
    const std::vector<cl::Event> mat_events
        = vec_concat(packed.read_write_events(), src.write_events());
    cl::Event copy_event;
    queue.enqueueReadBuffer(packed.buffer(), CL_FALSE, 0,
                            sizeof(double) * packed_size, dst.data(),
                            &mat_events, &copy_event);
    copy_event.wait();
    src.clear_write_events();
  } catch (const cl::Error& e) {
    check_opencl_error("packed_copy (OpenCL->std::vector)", e);
  }
  return dst;
}

/**
 * Copies the packed triangular matrix from
 * the source std::vector to an OpenCL buffer and
 * unpacks it to a flat matrix on the OpenCL device.
 *
 * @tparam triangular_view the triangularity of the source matrix
 * @param src the packed source std::vector
 * @param rows the number of rows in the flat matrix
 * @return the destination flat matrix on the OpenCL device
 * @throw std::invalid_argument if the
 * size of the vector does not match the expected size
 * for the packed triangular matrix
 */
template <TriangularViewCL triangular_view>
inline matrix_cl packed_copy(const std::vector<double>& src, int rows) {
  const int packed_size = rows * (rows + 1) / 2;
  check_size_match("copy (packed std::vector -> OpenCL)", "src.size()",
                   src.size(), "rows * (rows + 1) / 2", packed_size);
  matrix_cl dst(rows, rows);
  if (dst.size() == 0) {
    return dst;
  }
  try {
    matrix_cl packed(packed_size, 1);
    cl::Event packed_event;
    const cl::CommandQueue queue = opencl_context.queue();
    queue.enqueueWriteBuffer(packed.buffer(), CL_FALSE, 0,
                             sizeof(double) * packed_size, src.data(), NULL,
                             &packed_event);
    packed.add_write_event(packed_event);
    stan::math::opencl_kernels::unpack(cl::NDRange(dst.rows(), dst.rows()), dst,
                                       packed, dst.rows(), dst.rows(),
                                       triangular_view);
  } catch (const cl::Error& e) {
    check_opencl_error("packed_copy (std::vector->OpenCL)", e);
  }
  return dst;
}

/**
 * Copies the source matrix to the
 * destination matrix. Both matrices
 * are stored on the OpenCL device.
 *
 * @param src source matrix
 * @return matrix_cl with copies of values in the source matrix
 * @throw std::invalid_argument if the
 * matrices do not have matching dimensions
 */
inline matrix_cl copy_cl(const matrix_cl& src) {
  matrix_cl dst(src.rows(), src.cols());
  if (src.size() == 0) {
    return dst;
  }
  try {
    /**
     * Copies the contents of the src buffer to the dst buffer
     * see the matrix_cl(matrix_cl&) constructor
     *  for explanation
     */
    cl::CommandQueue queue = opencl_context.queue();
    const std::vector<cl::Event> mat_events
        = vec_concat(dst.read_write_events(), src.write_events());
    cl::Event copy_event;
    queue.enqueueCopyBuffer(src.buffer(), dst.buffer(), 0, 0,
                            sizeof(double) * src.size(), &mat_events,
                            &copy_event);
    dst.add_write_event(copy_event);
    src.add_read_event(copy_event);
  } catch (const cl::Error& e) {
    check_opencl_error("copy (OpenCL)->(OpenCL)", e);
  }
}

/**
 * Copy A 1 by 1 source matrix from the Device to  the host.
 * @tparam An arithmetic type to pass the value from the OpenCL matrix to.
 * @param dst Arithmetic to receive the matrix_cl value.
 * @param src A 1x1 matrix on the device.
 */
template <typename T, std::enable_if_t<std::is_arithmetic<T>::value, int> = 0>
inline T from_matrix_cl(const matrix_cl& src) {
  T dst;
  check_size_match("copy ((OpenCL) -> (OpenCL))", "src.rows()", src.rows(),
                   "dst.rows()", 1);
  check_size_match("copy ((OpenCL) -> (OpenCL))", "src.cols()", src.cols(),
                   "dst.cols()", 1);
  try {
    cl::Event copy_event;
    const cl::CommandQueue queue = opencl_context.queue();
    queue.enqueueReadBuffer(src.buffer(), CL_FALSE, 0, sizeof(T), &dst,
                            &src.write_events(), &copy_event);
    copy_event.wait();
    src.clear_write_events();
  } catch (const cl::Error& e) {
    check_opencl_error("copy (OpenCL)->(OpenCL)", e);
  }
  return dst;
}

/**
 * Copy an arithmetic type to the device.
 * @tparam An arithmetic type to pass the value from the OpenCL matrix to.
 * @param src Arithmetic to receive the matrix_cl value.
 * @param dst A 1x1 matrix on the device.
 */
template <typename T, std::enable_if_t<std::is_arithmetic<T>::value, int> = 0>
inline matrix_cl to_matrix_cl(const T& src) {
  matrix_cl dst(1, 1);
  check_size_match("copy ((OpenCL) -> (OpenCL))", "src.rows()", dst.rows(),
                   "dst.rows()", 1);
  check_size_match("copy ((OpenCL) -> (OpenCL))", "src.cols()", dst.cols(),
                   "dst.cols()", 1);
  try {
    cl::Event copy_event;
    const cl::CommandQueue queue = opencl_context.queue();
    queue.enqueueWriteBuffer(dst.buffer(), CL_FALSE, 0, sizeof(T), &src,
                             &dst.write_events(), &copy_event);
    dst.add_write_event(copy_event);
  } catch (const cl::Error& e) {
    check_opencl_error("copy (OpenCL)->(OpenCL)", e);
  }
  return dst;
}

}  // namespace math
}  // namespace stan
#endif
#endif
<commit_msg>doxygen fix<commit_after>#ifndef STAN_MATH_PRIM_MAT_FUN_OPENCL_COPY_HPP
#define STAN_MATH_PRIM_MAT_FUN_OPENCL_COPY_HPP
#ifdef STAN_OPENCL

#include <stan/math/opencl/opencl_context.hpp>
#include <stan/math/opencl/kernel_cl.hpp>
#include <stan/math/opencl/matrix_cl.hpp>
#include <stan/math/opencl/kernels/copy.hpp>
#include <stan/math/opencl/kernels/pack.hpp>
#include <stan/math/opencl/kernels/unpack.hpp>
#include <stan/math/opencl/buffer_types.hpp>
#include <stan/math/opencl/err/check_opencl.hpp>
#include <stan/math/prim/mat/fun/Eigen.hpp>
#include <stan/math/prim/scal/err/check_size_match.hpp>
#include <stan/math/prim/arr/fun/vec_concat.hpp>

#include <CL/cl.hpp>
#include <iostream>
#include <vector>
#include <algorithm>
#include <type_traits>

namespace stan {
namespace math {

/**
 * Copies the source Eigen matrix to
 * the destination matrix that is stored
 * on the OpenCL device.
 *
 * @tparam T type of data in the Eigen matrix
 * @param src source Eigen matrix
 * @return matrix_cl with a copy of the data in the source matrix
 * @throw std::invalid_argument if the
 * matrices do not have matching dimensions
 */
template <int R, int C>
inline matrix_cl to_matrix_cl(const Eigen::Matrix<double, R, C>& src) {
  matrix_cl dst(src.rows(), src.cols());
  if (src.size() == 0) {
    return dst;
  }
  try {
    /**
     * Writes the contents of src to the OpenCL buffer
     * starting at the offset 0
     * CL_FALSE denotes that the call is non-blocking
     * This means that future kernels need to know about the copy_event
     * So that they do not execute until this transfer finishes.
     */
    cl::Event copy_event;
    const cl::CommandQueue& queue = opencl_context.queue();
    queue.enqueueWriteBuffer(dst.buffer(), CL_FALSE, 0,
                             sizeof(double) * dst.size(), src.data(),
                             &dst.write_events(), &copy_event);
    dst.add_write_event(copy_event);
  } catch (const cl::Error& e) {
    check_opencl_error("copy Eigen->(OpenCL)", e);
  }
  return dst;
}

/**
 * Copies the source matrix that is stored
 * on the OpenCL device to the destination Eigen
 * matrix.
 *
 * @param src source matrix on the OpenCL device
 * @return Eigen matrix with a copy of the data in the source matrix
 * @throw std::invalid_argument if the
 * matrices do not have matching dimensions
 */
inline Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> from_matrix_cl(
    const matrix_cl& src) {
  Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> dst(src.rows(),
                                                            src.cols());
  if (src.size() == 0) {
    return dst;
  }
  try {
    /**
     * Reads the contents of the OpenCL buffer
     * starting at the offset 0 to the Eigen
     * matrix
     * CL_TRUE denotes that the call is blocking
     * We do not want to pass data back to the CPU until all of the jobs
     * called on the source matrix are finished.
     */
    cl::Event copy_event;
    const cl::CommandQueue queue = opencl_context.queue();
    queue.enqueueReadBuffer(src.buffer(), CL_FALSE, 0,
                            sizeof(double) * dst.size(), dst.data(),
                            &src.write_events(), &copy_event);
    copy_event.wait();
    src.clear_write_events();
  } catch (const cl::Error& e) {
    check_opencl_error("copy (OpenCL)->Eigen", e);
  }
  return dst;
}

/**
 * Packs the flat triagnular matrix on the OpenCL device and
 * copies it to the std::vector.
 *
 * @tparam triangular_view the triangularity of the source matrix
 * @param src the flat triangular source matrix on the OpenCL device
 * @return the packed std::vector
 */
template <TriangularViewCL triangular_view>
inline std::vector<double> packed_copy(const matrix_cl& src) {
  const int packed_size = src.rows() * (src.rows() + 1) / 2;
  std::vector<double> dst(packed_size);
  if (dst.size() == 0) {
    return dst;
  }
  try {
    const cl::CommandQueue queue = opencl_context.queue();
    matrix_cl packed(packed_size, 1);
    stan::math::opencl_kernels::pack(cl::NDRange(src.rows(), src.rows()),
                                     packed, src, src.rows(), src.rows(),
                                     triangular_view);
    const std::vector<cl::Event> mat_events
        = vec_concat(packed.read_write_events(), src.write_events());
    cl::Event copy_event;
    queue.enqueueReadBuffer(packed.buffer(), CL_FALSE, 0,
                            sizeof(double) * packed_size, dst.data(),
                            &mat_events, &copy_event);
    copy_event.wait();
    src.clear_write_events();
  } catch (const cl::Error& e) {
    check_opencl_error("packed_copy (OpenCL->std::vector)", e);
  }
  return dst;
}

/**
 * Copies the packed triangular matrix from
 * the source std::vector to an OpenCL buffer and
 * unpacks it to a flat matrix on the OpenCL device.
 *
 * @tparam triangular_view the triangularity of the source matrix
 * @param src the packed source std::vector
 * @param rows the number of rows in the flat matrix
 * @return the destination flat matrix on the OpenCL device
 * @throw std::invalid_argument if the
 * size of the vector does not match the expected size
 * for the packed triangular matrix
 */
template <TriangularViewCL triangular_view>
inline matrix_cl packed_copy(const std::vector<double>& src, int rows) {
  const int packed_size = rows * (rows + 1) / 2;
  check_size_match("copy (packed std::vector -> OpenCL)", "src.size()",
                   src.size(), "rows * (rows + 1) / 2", packed_size);
  matrix_cl dst(rows, rows);
  if (dst.size() == 0) {
    return dst;
  }
  try {
    matrix_cl packed(packed_size, 1);
    cl::Event packed_event;
    const cl::CommandQueue queue = opencl_context.queue();
    queue.enqueueWriteBuffer(packed.buffer(), CL_FALSE, 0,
                             sizeof(double) * packed_size, src.data(), NULL,
                             &packed_event);
    packed.add_write_event(packed_event);
    stan::math::opencl_kernels::unpack(cl::NDRange(dst.rows(), dst.rows()), dst,
                                       packed, dst.rows(), dst.rows(),
                                       triangular_view);
  } catch (const cl::Error& e) {
    check_opencl_error("packed_copy (std::vector->OpenCL)", e);
  }
  return dst;
}

/**
 * Copies the source matrix to the
 * destination matrix. Both matrices
 * are stored on the OpenCL device.
 *
 * @param src source matrix
 * @return matrix_cl with copies of values in the source matrix
 * @throw std::invalid_argument if the
 * matrices do not have matching dimensions
 */
inline matrix_cl copy_cl(const matrix_cl& src) {
  matrix_cl dst(src.rows(), src.cols());
  if (src.size() == 0) {
    return dst;
  }
  try {
    /**
     * Copies the contents of the src buffer to the dst buffer
     * see the matrix_cl(matrix_cl&) constructor
     *  for explanation
     */
    cl::CommandQueue queue = opencl_context.queue();
    const std::vector<cl::Event> mat_events
        = vec_concat(dst.read_write_events(), src.write_events());
    cl::Event copy_event;
    queue.enqueueCopyBuffer(src.buffer(), dst.buffer(), 0, 0,
                            sizeof(double) * src.size(), &mat_events,
                            &copy_event);
    dst.add_write_event(copy_event);
    src.add_read_event(copy_event);
  } catch (const cl::Error& e) {
    check_opencl_error("copy (OpenCL)->(OpenCL)", e);
  }
}

/**
 * Copy A 1 by 1 source matrix from the Device to  the host.
 * @tparam An arithmetic type to pass the value from the OpenCL matrix to.
 * @param src A 1x1 matrix on the device.
 * @return dst Arithmetic to receive the matrix_cl value.
 */
template <typename T, std::enable_if_t<std::is_arithmetic<T>::value, int> = 0>
inline T from_matrix_cl(const matrix_cl& src) {
  T dst;
  check_size_match("copy ((OpenCL) -> (OpenCL))", "src.rows()", src.rows(),
                   "dst.rows()", 1);
  check_size_match("copy ((OpenCL) -> (OpenCL))", "src.cols()", src.cols(),
                   "dst.cols()", 1);
  try {
    cl::Event copy_event;
    const cl::CommandQueue queue = opencl_context.queue();
    queue.enqueueReadBuffer(src.buffer(), CL_FALSE, 0, sizeof(T), &dst,
                            &src.write_events(), &copy_event);
    copy_event.wait();
    src.clear_write_events();
  } catch (const cl::Error& e) {
    check_opencl_error("copy (OpenCL)->(OpenCL)", e);
  }
  return dst;
}

/**
 * Copy an arithmetic type to the device.
 * @tparam An arithmetic type to pass the value from the OpenCL matrix to.
 * @param src Arithmetic to receive the matrix_cl value.
 * @return A 1x1 matrix on the device.
 */
template <typename T, std::enable_if_t<std::is_arithmetic<T>::value, int> = 0>
inline matrix_cl to_matrix_cl(const T& src) {
  matrix_cl dst(1, 1);
  check_size_match("copy ((OpenCL) -> (OpenCL))", "src.rows()", dst.rows(),
                   "dst.rows()", 1);
  check_size_match("copy ((OpenCL) -> (OpenCL))", "src.cols()", dst.cols(),
                   "dst.cols()", 1);
  try {
    cl::Event copy_event;
    const cl::CommandQueue queue = opencl_context.queue();
    queue.enqueueWriteBuffer(dst.buffer(), CL_FALSE, 0, sizeof(T), &src,
                             &dst.write_events(), &copy_event);
    dst.add_write_event(copy_event);
  } catch (const cl::Error& e) {
    check_opencl_error("copy (OpenCL)->(OpenCL)", e);
  }
  return dst;
}

}  // namespace math
}  // namespace stan
#endif
#endif
<|endoftext|>


<commit_before>/******************************************************************************
 * This file is part of the Gluon Development Platform
 * Copyright (c) 2009 Dan Leinir Turthra Jensen <admin@leinir.dk>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "gluonobjectfactory.h"
#include "gluonobject.h"
#include "debughelper.h"
#include "gluon_global.h"

#include <QtCore/QDir>
#include <QtCore/QPluginLoader>
#include <QtGui/QApplication>
#include <QVariant>

#include <QtCore/QDebug>

using namespace GluonCore;

template<> GluonObjectFactory* Singleton<GluonObjectFactory>::m_instance = 0;

QStringList
GluonObjectFactory::objectTypeNames() const
{
    QStringList theNames;

    QHash<QString, const QMetaObject*>::const_iterator i;
    for( i = m_objectTypes.constBegin(); i != m_objectTypes.constEnd(); ++i )
        theNames << i.key();

    return theNames;
}

QHash<QString, const QMetaObject*>
GluonObjectFactory::objectTypes() const
{
    return m_objectTypes;
}

const QHash<QString, int>
GluonObjectFactory::objectTypeIDs() const
{
    return m_objectTypeIDs;
}

QStringList
GluonObjectFactory::objectMimeTypes() const
{
    return m_mimeTypes.keys();
}

GluonObject*
GluonObjectFactory::instantiateObjectByName( const QString& objectTypeName )
{
    DEBUG_BLOCK
    QString fullObjectTypeName( objectTypeName );
    if( !objectTypeName.contains( "::" ) )
        fullObjectTypeName = QString( "Gluon::" ) + fullObjectTypeName;

    const QMetaObject *meta;
    if ((meta = m_objectTypes.value(objectTypeName, 0)))
    {
        GluonObject* obj = qobject_cast<GluonObject*>( meta->newInstance() );
        if( obj )
        {
            return obj;
        }
        else
        {
            DEBUG_TEXT2( "If you are seeing this message, you have most likely failed to mark the constructor of %1 as Q_INVOKABLE", objectTypeName );
            return 0;
        }
    }

    DEBUG_TEXT( QString( "Object type named %1 not found in factory!" ).arg( objectTypeName ) );

    return 0;
}

GluonObject*
GluonObjectFactory::instantiateObjectByMimetype( const QString& objectMimeType )
{
    return instantiateObjectByName( m_mimeTypes[objectMimeType] );
}

QVariant
GluonObjectFactory::wrapObject( const QVariant& original, GluonObject* newValue )
{
    DEBUG_BLOCK
    QString type = original.typeName();

    if( type.endsWith( '*' ) ) //Remove the * from the type
    {
        type = type.left( type.length() - 1 );
    }

    if( m_objectTypes.contains( type ) )
    {
        QScopedPointer<GluonObject> obj( instantiateObjectByName( type ) );
        return obj->toVariant( newValue );
    }

    DEBUG_TEXT( QString( "Warning: Type %1 not found." ).arg( type ) );

    return QVariant();
}

QVariant
GluonObjectFactory::wrapObject( const QString& type, GluonObject* newValue )
{
    DEBUG_BLOCK
    QString typeName = type;
    if( type.endsWith( '*' ) )
        typeName = type.left( type.length() - 1 );

    if( m_objectTypes.contains( typeName ) )
    {
        QScopedPointer<GluonObject> obj( instantiateObjectByName( typeName ) );
        return obj->toVariant( newValue );
    }

    DEBUG_TEXT( QString( "Warning: Type %1 not found." ).arg( typeName ) );

    return QVariant();
}

GluonObject*
GluonObjectFactory::wrappedObject( const QVariant& wrappedObject )
{
    QString type( wrappedObject.typeName() );
    QString typeName = type;
    if( type.endsWith( '*' ) )
        typeName = type.left( type.length() - 1 );

    if( m_objectTypes.contains( typeName ) )
    {
        QScopedPointer<GluonObject> obj( instantiateObjectByName( typeName ) );
        return obj->fromVariant( wrappedObject );
    }

    DEBUG_BLOCK
    DEBUG_TEXT( QString( "Warning: Type %1 not found." ).arg( typeName ) );

    return 0;
}

void
GluonObjectFactory::loadPlugins()
{
    DEBUG_FUNC_NAME
    QList<QDir> pluginDirs;

    QDir pluginDir( QApplication::applicationDirPath() );

#if defined(Q_OS_WIN)
    if( pluginDir.dirName().toLower() == "debug" || pluginDir.dirName().toLower() == "release" )
        pluginDir.cdUp();
#elif defined(Q_OS_MAC)
    if( pluginDir.dirName() == "MacOS" )
    {
        pluginDir.cdUp();
    }
#endif
    if( pluginDir.cd( "PlugIns" ) )
        pluginDirs.append( pluginDir );

    if( pluginDir.cd( GluonCore::Global::libDirectory() ) )
        pluginDirs.append( pluginDir );

    // this is the plugin dir on windows
    if( pluginDir.cd( GluonCore::Global::libDirectory() + "/kde4") )
        pluginDirs.append( pluginDir );

    if( pluginDir.cd( GluonCore::Global::libDirectory() + "/gluon" ) )
        pluginDirs.append( pluginDir );

    if( pluginDir.cd( QDir::homePath() + "/gluonplugins" ) )
        pluginDirs.append( pluginDir );

    DEBUG_TEXT( QString( "Number of plugin locations: %1" ).arg( pluginDirs.count() ) );
    foreach( QDir theDir, pluginDirs )
    {
        DEBUG_TEXT( QString( "Looking for pluggable components in %1" ).arg( theDir.absolutePath() ) );

#ifdef Q_WS_X11
        //Only attempt to load our current version. This makes it possible to have different versions
        //of the plugins in the plugin dir.
        theDir.setNameFilters( QStringList() << QString( "*.so.%1.%2.%3" ).arg( GLUON_VERSION_MAJOR ).arg( GLUON_VERSION_MINOR ).arg( GLUON_VERSION_PATCH ) );
#endif

        DEBUG_TEXT( QString( "Found %1 potential plugins. Attempting to load..." ).arg( theDir.count() - 2 ) );
        foreach( const QString & fileName, theDir.entryList( QDir::Files ) )
        {
            // Don't attempt to load non-gluon_plugin prefixed libraries
            if( !fileName.contains( "gluon" ) )
                continue;

            // Don't attempt to load non-libraries
            if( !QLibrary::isLibrary( theDir.absoluteFilePath( fileName ) ) )
                continue;

            QPluginLoader loader( theDir.absoluteFilePath( fileName ) );
            loader.load();

            if( !loader.isLoaded() )
            {
                DEBUG_TEXT( loader.errorString() );
            }
        }
    }

    DEBUG_TEXT2( "Total number of objects in factory after loading: %1", m_objectTypes.count() );
}

#include "gluonobjectfactory.moc"
<commit_msg>Set QDir::NoDotAndDotDot filter for plugin seaching.<commit_after>/******************************************************************************
 * This file is part of the Gluon Development Platform
 * Copyright (c) 2009 Dan Leinir Turthra Jensen <admin@leinir.dk>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "gluonobjectfactory.h"
#include "gluonobject.h"
#include "debughelper.h"
#include "gluon_global.h"

#include <QtCore/QDir>
#include <QtCore/QPluginLoader>
#include <QtGui/QApplication>
#include <QVariant>

#include <QtCore/QDebug>

using namespace GluonCore;

template<> GluonObjectFactory* Singleton<GluonObjectFactory>::m_instance = 0;

QStringList
GluonObjectFactory::objectTypeNames() const
{
    QStringList theNames;

    QHash<QString, const QMetaObject*>::const_iterator i;
    for( i = m_objectTypes.constBegin(); i != m_objectTypes.constEnd(); ++i )
        theNames << i.key();

    return theNames;
}

QHash<QString, const QMetaObject*>
GluonObjectFactory::objectTypes() const
{
    return m_objectTypes;
}

const QHash<QString, int>
GluonObjectFactory::objectTypeIDs() const
{
    return m_objectTypeIDs;
}

QStringList
GluonObjectFactory::objectMimeTypes() const
{
    return m_mimeTypes.keys();
}

GluonObject*
GluonObjectFactory::instantiateObjectByName( const QString& objectTypeName )
{
    DEBUG_BLOCK
    QString fullObjectTypeName( objectTypeName );
    if( !objectTypeName.contains( "::" ) )
        fullObjectTypeName = QString( "Gluon::" ) + fullObjectTypeName;

    const QMetaObject *meta;
    if ((meta = m_objectTypes.value(objectTypeName, 0)))
    {
        GluonObject* obj = qobject_cast<GluonObject*>( meta->newInstance() );
        if( obj )
        {
            return obj;
        }
        else
        {
            DEBUG_TEXT2( "If you are seeing this message, you have most likely failed to mark the constructor of %1 as Q_INVOKABLE", objectTypeName );
            return 0;
        }
    }

    DEBUG_TEXT( QString( "Object type named %1 not found in factory!" ).arg( objectTypeName ) );

    return 0;
}

GluonObject*
GluonObjectFactory::instantiateObjectByMimetype( const QString& objectMimeType )
{
    return instantiateObjectByName( m_mimeTypes[objectMimeType] );
}

QVariant
GluonObjectFactory::wrapObject( const QVariant& original, GluonObject* newValue )
{
    DEBUG_BLOCK
    QString type = original.typeName();

    if( type.endsWith( '*' ) ) //Remove the * from the type
    {
        type = type.left( type.length() - 1 );
    }

    if( m_objectTypes.contains( type ) )
    {
        QScopedPointer<GluonObject> obj( instantiateObjectByName( type ) );
        return obj->toVariant( newValue );
    }

    DEBUG_TEXT( QString( "Warning: Type %1 not found." ).arg( type ) );

    return QVariant();
}

QVariant
GluonObjectFactory::wrapObject( const QString& type, GluonObject* newValue )
{
    DEBUG_BLOCK
    QString typeName = type;
    if( type.endsWith( '*' ) )
        typeName = type.left( type.length() - 1 );

    if( m_objectTypes.contains( typeName ) )
    {
        QScopedPointer<GluonObject> obj( instantiateObjectByName( typeName ) );
        return obj->toVariant( newValue );
    }

    DEBUG_TEXT( QString( "Warning: Type %1 not found." ).arg( typeName ) );

    return QVariant();
}

GluonObject*
GluonObjectFactory::wrappedObject( const QVariant& wrappedObject )
{
    QString type( wrappedObject.typeName() );
    QString typeName = type;
    if( type.endsWith( '*' ) )
        typeName = type.left( type.length() - 1 );

    if( m_objectTypes.contains( typeName ) )
    {
        QScopedPointer<GluonObject> obj( instantiateObjectByName( typeName ) );
        return obj->fromVariant( wrappedObject );
    }

    DEBUG_BLOCK
    DEBUG_TEXT( QString( "Warning: Type %1 not found." ).arg( typeName ) );

    return 0;
}

void
GluonObjectFactory::loadPlugins()
{
    DEBUG_FUNC_NAME
    QList<QDir> pluginDirs;

    QDir pluginDir( QApplication::applicationDirPath() );

#if defined(Q_OS_WIN)
    if( pluginDir.dirName().toLower() == "debug" || pluginDir.dirName().toLower() == "release" )
        pluginDir.cdUp();
#elif defined(Q_OS_MAC)
    if( pluginDir.dirName() == "MacOS" )
    {
        pluginDir.cdUp();
    }
#endif
    if( pluginDir.cd( "PlugIns" ) )
        pluginDirs.append( pluginDir );

    if( pluginDir.cd( GluonCore::Global::libDirectory() ) )
        pluginDirs.append( pluginDir );

    // this is the plugin dir on windows
    if( pluginDir.cd( GluonCore::Global::libDirectory() + "/kde4") )
        pluginDirs.append( pluginDir );

    if( pluginDir.cd( GluonCore::Global::libDirectory() + "/gluon" ) )
        pluginDirs.append( pluginDir );

    if( pluginDir.cd( QDir::homePath() + "/gluonplugins" ) )
        pluginDirs.append( pluginDir );

    DEBUG_TEXT( QString( "Number of plugin locations: %1" ).arg( pluginDirs.count() ) );
    foreach( QDir theDir, pluginDirs )
    {
        DEBUG_TEXT( QString( "Looking for pluggable components in %1" ).arg( theDir.absolutePath() ) );

#ifdef Q_WS_X11
        //Only attempt to load our current version. This makes it possible to have different versions
        //of the plugins in the plugin dir.
        theDir.setNameFilters( QStringList() << QString( "*.so.%1.%2.%3" ).arg( GLUON_VERSION_MAJOR ).arg( GLUON_VERSION_MINOR ).arg( GLUON_VERSION_PATCH ) );
#endif
        theDir.setFilter( QDir::NoDotAndDotDot );

        DEBUG_TEXT( QString( "Found %1 potential plugins. Attempting to load..." ).arg( theDir.count() ) );
        foreach( const QString & fileName, theDir.entryList( QDir::Files ) )
        {
            // Don't attempt to load non-gluon_plugin prefixed libraries
            if( !fileName.contains( "gluon" ) )
                continue;

            // Don't attempt to load non-libraries
            if( !QLibrary::isLibrary( theDir.absoluteFilePath( fileName ) ) )
                continue;

            QPluginLoader loader( theDir.absoluteFilePath( fileName ) );
            loader.load();

            if( !loader.isLoaded() )
            {
                DEBUG_TEXT( loader.errorString() );
            }
        }
    }

    DEBUG_TEXT2( "Total number of objects in factory after loading: %1", m_objectTypes.count() );
}

#include "gluonobjectfactory.moc"
<|endoftext|>