UncertMLNode * 
UncertMLNode::createStatisticsNode(std::string arguments,  
                                   std::string argumentIds)
{
  UncertMLNode *node = new UncertMLNode();
  node->setElementName("StatisticsCollection");

  XMLAttributes attr = XMLAttributes();
  /* really the url should be specific to the distribtuion
  * but whilst the attribue is required in uncertML it does not require
  * it to be an exact match
  */
  attr.add("definition", "http://www.uncertml.org/statistics");
  node->setAttributes(attr);

  /* create an idlist from the arguments 
   * and check we have the same number of args and ids
   */
  IdList args = IdList(arguments);
  IdList argIds = IdList(argumentIds);

  unsigned int numArgs = args.size();
  unsigned int numIds = argIds.size();

  if (numArgs != numIds)
  {
    return NULL;
  }


  for (unsigned int i = 0; i < numArgs; i++)
  {
    UncertMLNode * varChild = new UncertMLNode();
    varChild->setElementName("var");
    
    XMLAttributes attributes = XMLAttributes();
    attributes.add("varId", argIds.at(i));
    varChild->setAttributes(attributes);

    UncertMLNode * valueChild = new UncertMLNode();
    valueChild->setElementName("value");

    valueChild->addChild(varChild);

    UncertMLNode * child = new UncertMLNode();
    child->setElementName(args.at(i));
    XMLAttributes attr1 = XMLAttributes();
    attr1.add("definition", "http://www.uncertml.org/statistics");
    child->setAttributes(attr1);

    child->addChild(valueChild);

    node->addChild(child);
  }



  return node;
}
bool LoopElementGenerator::nextElementsGeneration()
{
	IdList const outgoingLinks = mNxtGen->api()->outgoingLinks(mElementId);
	Q_ASSERT(outgoingLinks.size() == 2);

	int elementConnectedByIterationEdgeNumber = -1;
	int afterLoopElementNumber = -1;

	if (mNxtGen->api()->stringProperty(mNxtGen->api()->logicalId(outgoingLinks.at(0)), "Guard").toUtf8() == "итерация") {
		elementConnectedByIterationEdgeNumber = 0;
		afterLoopElementNumber = 1;
	} else {
		elementConnectedByIterationEdgeNumber = 1;
		afterLoopElementNumber = 0;
	}

	//generate loop
	Id const loopNextElement = mNxtGen->api()->to(outgoingLinks.at(elementConnectedByIterationEdgeNumber));
	if (loopNextElement == Id::rootId()) {
		mNxtGen->errorReporter().addError("Loop block " + mElementId.toString() + " has no correct loop branch!"\
				" May be you need to connect it to some diagram element.", mElementId);
		return false;
	}

	AbstractElementGenerator* const loopGen = ElementGeneratorFactory::generator(mNxtGen
			, loopNextElement, *mNxtGen->api());

	mNxtGen->previousElement() = mElementId;
	mNxtGen->previousLoopElements().push(mElementId);
	if (!loopGen->generate()) {
		return false;
	}
	delete loopGen;

	//generate next blocks
	Id const nextBlockElement = mNxtGen->api()->to(outgoingLinks.at(afterLoopElementNumber));
	if (nextBlockElement == Id::rootId()) {
		mNxtGen->errorReporter().addError("Loop block " + mElementId.toString() + " has no correct next block branch!"\
				" May be you need to connect it to some diagram element.", mElementId);
		return false;
	}

	AbstractElementGenerator* nextBlocksGen = ElementGeneratorFactory::generator(mNxtGen
			, nextBlockElement, *mNxtGen->api());

	mNxtGen->previousElement() = mElementId;
	mNxtGen->previousLoopElements().push(mElementId);
	if (!nextBlocksGen->generate()) {
		return false;
	}
	delete nextBlocksGen;

	return true;
}
bool LoopElementGenerator::preGenerationCheck()
{
	IdList const outgoingLinks = mNxtGen->api()->outgoingLinks(mElementId);

	if ((outgoingLinks.size() != 2) ||
		((mNxtGen->api()->property(mNxtGen->api()->logicalId(outgoingLinks.at(0)), "Guard").toString() == "итерация")
		&& (mNxtGen->api()->property(mNxtGen->api()->logicalId(outgoingLinks.at(1)), "Guard").toString() == "итерация") )
	) {
		return false;
	}

	return true;
}
Exemple #4
0
void VisualDebugger::createIdByLineCorrelation(UML::Element *elem, int& line)
{
	UML::Element *curElem = dynamic_cast<UML::NodeElement *>(elem);
	if (curElem && elem->id().element().compare("InitialNode") != 0) {
		if (elem->id().element().compare("Action") == 0) {
			mIdByLineCorrelation[line] = elem->id();
			line++;
			if (mLogicalModelApi.logicalRepoApi().outgoingLinks(curElem->id()).count() != 0) {
				Id nextEdge = mLogicalModelApi.logicalRepoApi().outgoingLinks(curElem->id()).at(0);
				createIdByLineCorrelation(mEditor->mvIface()->scene()->getElem(nextEdge), line);
			} else {
				error(missingEndNode);
				mHasNotEndWithFinalNode = true;
			}
		} else {
			if (elem->id().element().compare("ConditionNode") == 0) {
				mIdByLineCorrelation[line] = elem->id();
				line++;
				IdList outLinks = mLogicalModelApi.logicalRepoApi().outgoingLinks(curElem->id());
				Id falseEdge = falseEdge.rootId();
				Id trueEdge = trueEdge.rootId();
				for (int i=0; i<outLinks.count(); i++) {
					bool type = getProperty(outLinks.at(i), "type").toBool();
					if (type) {
						trueEdge = outLinks.at(i);
					} else {
						falseEdge = outLinks.at(i);
					}
				}
				createIdByLineCorrelation(mEditor->mvIface()->scene()->getElem(trueEdge), line);
				line++;
				if (falseEdge != falseEdge.rootId()) {
					line++;
					createIdByLineCorrelation(mEditor->mvIface()->scene()->getElem(falseEdge), line);
					line++;
				}
			} else {
				mIdByLineCorrelation[line] = elem->id();
			}
		}
	} else {
		if (elem->id().element().compare("InitialNode") != 0) {
			Id nextNode  = mLogicalModelApi.logicalRepoApi().to(elem->id());
			createIdByLineCorrelation(mEditor->mvIface()->scene()->getElem(nextNode), line);
		} else {
			Id nextEdge = mLogicalModelApi.logicalRepoApi().outgoingLinks(curElem->id()).at(0);
			createIdByLineCorrelation(mEditor->mvIface()->scene()->getElem(nextEdge), line);
		}
	}
}
void MultipleRemoveCommand::setItemsToDelete(IdList &itemsToDelete)
{
	IdList itemsToUpdate;

	addEdgesToBeDeleted(itemsToDelete);
	// QGraphicsScene::selectedItems() returns items in no particular order,
	// so we should handle parent-child relationships manually
	while (!itemsToDelete.isEmpty()) {
		const Id currentItem = itemsToDelete.at(0);
		const IdList children = mGraphicalApi.children(currentItem);
		foreach (const Id &child, children) {
			itemsToDelete.removeAll(child);
			// Child remove commands will be added in currentItem delete command
		}

		const bool isEdge = !mLogicalApi.editorManagerInterface().isGraphicalElementNode(currentItem);
		if (isEdge) {
			const Id src = mGraphicalApi.from(currentItem);
			if (src != Id() && !itemsToUpdate.contains(src)) {
				itemsToUpdate.append(src);
			}
			const Id dst = mGraphicalApi.to(currentItem);
			if (dst != Id() && !itemsToUpdate.contains(dst)) {
				itemsToUpdate.append(dst);
			}

			insertPreAction(graphicalDeleteCommand(currentItem), 0);
		} else {
			addPreAction(graphicalDeleteCommand(currentItem));
		}

		itemsToDelete.removeAll(currentItem);
	}
Exemple #6
0
Id VisualDebugger::findValidLink()
{
	IdList outLinks = mModelApi.graphicalRepoApi().outgoingLinks(mCurrentId);
	QString conditionStr = mModelApi.graphicalRepoApi().property(mCurrentId, "condition").toString();
	int pos=0;
	bool condition = mBlockParser->parseCondition(conditionStr, pos, mCurrentId);
	for (int i=0; i<outLinks.count(); i++) {
		bool type = mModelApi.graphicalRepoApi().property(outLinks.at(i), "type").toBool();
		if (type == condition) {
			return outLinks.at(i);
		}
	}
	if (!mBlockParser->hasErrors()) {
		error(VisualDebugger::missingValidLink);
	}
	return ROOT_ID;
}
Exemple #7
0
void QWizardContainer::insertWidget(int index, QWidget *widget)
{
    enum { delta = 5 };

    QWizardPage *newPage = qobject_cast<QWizardPage *>(widget);
    if (!newPage) {
        qWarning("%s", msgWrongType);
        return;
    }

    const IdList idList = m_wizard->pageIds();
    const int pageCount = idList.size();
    if (index >= pageCount) {
        addWidget(widget);
        return;
    }

    // Insert before, reshuffle ids if required
    const int idBefore = idList.at(index);
    const int newId = idBefore - 1;
    const bool needsShuffle =
        (index == 0 && newId < 0)                        // At start: QWizard refuses to insert id -1
        || (index > 0 && idList.at(index - 1) == newId); // In-between
    if (needsShuffle) {
        // Create a gap by shuffling pages
        WizardPageList pageList;
        pageList.push_back(newPage);
        for (int i = index; i < pageCount; i++) {
            pageList.push_back(m_wizard->page(idList.at(i)));
            m_wizard->removePage(idList.at(i));
        }
        int newId = idBefore + delta;
        const WizardPageList::const_iterator wcend = pageList.constEnd();
        for (WizardPageList::const_iterator it = pageList.constBegin(); it != wcend; ++it) {
            m_wizard->setPage(newId, *it);
            newId += delta;
        }
    } else {
        // Gap found, just insert
        m_wizard->setPage(newId, newPage);
    }
    // Might be at -1 after adding the first page
    setCurrentIndex(index);
}
Exemple #8
0
QWidget *QWizardContainer::widget(int index) const
{
    QWidget *rc = 0;
    if (index >= 0) {
        const IdList idList = m_wizard->pageIds();
        if (index < idList.size())
            rc = m_wizard->page(idList.at(index));
    }
    return rc;
}
Exemple #9
0
DispatcherGenerator::CodeBranchGenerationResult DispatcherGenerator::generateInitialNodeCode(
		qReal::Id const &currentNode) const
{
	IdList const links = mApi.outgoingLinks(currentNode);

	if (links.size() != 1) {
		mErrorReporter.addError(QObject::tr("Initial node should have exactly 1 outgoing link"), currentNode);
		return CodeBranchGenerationResult("", currentNode);
	}

	Id const nextNode = mApi.otherEntityFromLink(links.at(0), currentNode);

	return generateOperatorCode(nextNode);
}
Exemple #10
0
QString DispatcherGenerator::generateCaseBody(qReal::Id const &handlerStart) const
{
	IdList const links = mApi.outgoingLinks(handlerStart);
	if (links.size() > 1) {
		mErrorReporter.addError(QObject::tr("Start node should have exactly 1 outgoing link"), handlerStart);
		return "";
	}

	if (links.size() == 0) {
		return "";
	}

	Id const nextNode = mApi.otherEntityFromLink(links.at(0), handlerStart);
	return generateOperatorCode(nextNode).text;
}
void 
FunctionDefinitionRecursion::determineCycles(const Model& m)
{
  IdIter it;
  IdRange range;
  IdList variables;
  IdMap logged;
  std::string id;
  variables.clear();

  /* create a list of variables that are cycles ie (x, x) */
  for (it = mIdMap.begin(); it != mIdMap.end(); it++)
  {
    if ((*it).first == (*it).second)
    {
      id = (*it).first;
      if (!variables.contains(id))
      {
        variables.append(id);
      }
    }
  }

  /* loop thru other dependencies for each; if the dependent is also
   * in the list then this is the cycle
   * keep a record of logged dependencies to avoid logging twice
   */
   
  for (unsigned int n = 0; n < variables.size(); n++)
  {
    id = variables.at((int)n);
    range = mIdMap.equal_range(id);
    for (it = range.first; it != range.second; it++)
    {
      if (((*it).second != id)
        && (variables.contains((*it).second))
        && !alreadyExistsInMap(logged, 
                   pair<const std::string, std::string>(id, (*it).second))
        && !alreadyExistsInMap(logged, 
                   pair<const std::string, std::string>((*it).second, id)))
      {
        logCycle(m.getFunctionDefinition(id), m.getFunctionDefinition((*it).second));
        logged.insert(pair<const std::string, std::string>(id, (*it).second));
      }
    }
  }
}
Exemple #12
0
void QWizardContainer::remove(int index)
{
    if (index < 0)
        return;

    const IdList idList = m_wizard->pageIds();
    if (index >= idList.size())
        return;

    m_wizard->removePage(idList.at(index));
    // goto next page, preferably
    const int newSize = idList.size() - 1;
    if (index < newSize) {
        setCurrentIndex(index);
    } else {
        if (newSize > 0)
            setCurrentIndex(newSize - 1);
    }
}
Exemple #13
0
DispatcherGenerator::CodeBranchGenerationResult DispatcherGenerator::generateActionCode(
		qReal::Id const &currentNode) const
{
	QString operatorCode = mApi.name(currentNode);

	IdList const links = mApi.outgoingLinks(currentNode);

	if (links.size() == 0) {
		return CodeBranchGenerationResult(operatorCode, currentNode);
	} else if (links.size() > 1) {
		mErrorReporter.addError(QObject::tr("Action node should have exactly 1 outgoing link"), currentNode);
		return CodeBranchGenerationResult("", currentNode);
	}

	Id const nextNode = mApi.otherEntityFromLink(links.at(0), currentNode);

	CodeBranchGenerationResult result = generateOperatorCode(nextNode);
	result.text = operatorCode + "\n" + result.text;
	return result;
}
void SimpleElementGenerator::generateMethodBody()
{
	generateBodyWithoutNextElementCall();
	
	IdList const outgoingConnectedElements = mNxtGen->mApi->outgoingConnectedElements(mElementId);
	if (outgoingConnectedElements.size() > 1) {
		mNxtGen->mErrorReporter.addError(QObject::tr("Too many outgoing connections!"), mElementId);
		return;
	}

	//if (outgoingConnectedElements.size() == 0) - case of last loop element, for example
	
	if (outgoingConnectedElements.size() == 1) {
		Id nextElement = outgoingConnectedElements.at(0);
		if (!mNxtGen->mApi->isLogicalElement(nextElement)) {
			nextElement = mNxtGen->mApi->logicalId(nextElement);
		}
		
		QString const methodName = mNxtGen->mIdToMethodNameMap[nextElement.toString()];
		mNxtGen->mGeneratedStrings.append(SmartLine(methodName + "();", mElementId));
	}
}
Exemple #15
0
void VisualDebugger::generateCode(UML::Element *elem, QFile &codeFile)
{
	UML::Element *curElem = dynamic_cast<UML::NodeElement *>(elem);
	if (curElem && elem->id().element().compare("InitialNode") != 0) {
		if (elem->id().element().compare("Action") == 0) {
			QString code = getProperty(curElem->id(), "process").toString();
			if (code.mid(0,4).compare("var ") == 0) {
				codeFile.write(code.mid(4).toAscii());
			} else {
				codeFile.write(code.toAscii());
			}

			codeFile.write("\n");
			if (mLogicalModelApi.logicalRepoApi().outgoingLinks(curElem->id()).count() != 0) {
				Id nextEdge = mLogicalModelApi.logicalRepoApi().outgoingLinks(curElem->id()).at(0);
				generateCode(mEditor->mvIface()->scene()->getElem(nextEdge), codeFile);
			} else {
				error(VisualDebugger::missingEndNode);
				error(codeGenerationError);
				return;
			}
		} else {
			if (elem->id().element().compare("ConditionNode") == 0) {
				codeFile.write("if (");
				codeFile.write(getProperty(curElem->id(), "condition").toByteArray());
				codeFile.write(") {\n");
				IdList outLinks = mLogicalModelApi.logicalRepoApi().outgoingLinks(curElem->id());
				Id falseEdge = falseEdge.rootId();
				Id trueEdge = trueEdge.rootId();
				for (int i=0; i<outLinks.count(); i++) {
					bool type = getProperty(outLinks.at(i), "type").toBool();
					if (type) {
						trueEdge = outLinks.at(i);
					} else {
						falseEdge = outLinks.at(i);
					}
				}
				if (trueEdge == trueEdge.rootId()) {
					error(VisualDebugger::missingValidLink);
					error(codeGenerationError);
					return;
				}
				generateCode(mEditor->mvIface()->scene()->getElem(trueEdge), codeFile);
				codeFile.write("}\n");
				if (falseEdge != falseEdge.rootId()) {
					codeFile.write("else {\n");
					generateCode(mEditor->mvIface()->scene()->getElem(falseEdge), codeFile);
					codeFile.write("}\n");
				}
			}
		}
	} else {
		if (elem->id().element().compare("InitialNode") != 0) {
			Id nextNode = mLogicalModelApi.logicalRepoApi().to(elem->id());
			generateCode(mEditor->mvIface()->scene()->getElem(nextNode), codeFile);
		} else {
			Id nextEdge = mLogicalModelApi.logicalRepoApi().outgoingLinks(curElem->id()).at(0);
			generateCode(mEditor->mvIface()->scene()->getElem(nextEdge), codeFile);
		}
	}

	return;
}
Exemple #16
0
DispatcherGenerator::CodeBranchGenerationResult DispatcherGenerator::generateDecisionNodeCode(
		qReal::Id const &currentNode) const
{
	Id thenBranch;
	Id elseBranch;
	Id *currentBranch = nullptr;

	for (Id const &link : mApi.outgoingLinks(currentNode)) {
		if (!mApi.stringProperty(link, "guard").isEmpty()) {
			currentBranch = &thenBranch;
		} else {
			currentBranch = &elseBranch;
		}
		if (*currentBranch == Id()) {
			*currentBranch = link;
		} else {
			mErrorReporter.addError(QObject::tr("Decision node shall have exactly one outgoing link without guard")
					, currentNode);

			return CodeBranchGenerationResult("", currentNode);
		}
	}

	if (thenBranch == Id()) {
		mErrorReporter.addError(QObject::tr("Decision node shall have exactly one outgoing link with guard")
				, currentNode);

		return CodeBranchGenerationResult("", currentNode);
	}
	if (elseBranch == Id()) {
		mErrorReporter.addError(QObject::tr("Decision node shall have exactly one outgoing link without guard")
				, currentNode);

		return CodeBranchGenerationResult("", currentNode);
	}

	QString const guard = mApi.stringProperty(thenBranch, "guard");

	QString ifTemplate = mTemplateUtils["@@If@@"];

	CodeBranchGenerationResult thenBranchGenerationResult = generateOperatorCode(mApi.otherEntityFromLink(thenBranch
			, currentNode));

	CodeBranchGenerationResult elseBranchGenerationResult = generateOperatorCode(mApi.otherEntityFromLink(elseBranch
			, currentNode));

	if (thenBranchGenerationResult.text.endsWith('\n')) {
		thenBranchGenerationResult.text.chop(1);
	}
	if (elseBranchGenerationResult.text.endsWith('\n')) {
		elseBranchGenerationResult.text.chop(1);
	}

	Id nextNode;
	if (thenBranchGenerationResult.stopNode.element() == "MergeNode") {
		nextNode = thenBranchGenerationResult.stopNode;
	}
	if (elseBranchGenerationResult.stopNode.element() == "MergeNode") {
		if (elseBranchGenerationResult.stopNode != nextNode) {
			mErrorReporter.addError(QObject::tr("Decision branches shall end on the same merge node"), currentNode);
			return CodeBranchGenerationResult("", currentNode);
		}
	}

	if (elseBranchGenerationResult.text.trimmed().isEmpty()) {
		ifTemplate = mTemplateUtils["@@IfWithoutElse@@"];
	}

	ifTemplate.replace("@@Condition@@", guard)
			.replace("@@Then@@", thenBranchGenerationResult.text)
			.replace("@@Else@@", elseBranchGenerationResult.text)
			;

	if (nextNode == Id()) {
		return CodeBranchGenerationResult(ifTemplate, nextNode);
	}

	IdList const links = mApi.outgoingLinks(nextNode);
	if (links.size() == 0) {
		return CodeBranchGenerationResult(ifTemplate, nextNode);
	} else if (links.size() > 1) {
		mErrorReporter.addError(QObject::tr("Branches merge node should have no more than 1 outgoing link")
				, currentNode);

		return CodeBranchGenerationResult("", nextNode);
	}

	Id const nextNodeToGenerate = mApi.otherEntityFromLink(links.at(0), nextNode);

	CodeBranchGenerationResult result = generateOperatorCode(nextNodeToGenerate);
	result.text = ifTemplate + "\n" + result.text;
	return result;
}
Exemple #17
0
DispatcherGenerator::CodeBranchGenerationResult DispatcherGenerator::generateFunctionCallCode(
		qReal::Id const &currentNode) const
{
	QString operatorCode = mTemplateUtils["@@CaseCode@@"];

	QString code = mApi.name(currentNode) + "(";
	for (Id const &argument : mApi.children(currentNode)) {
		if (!mApi.isLogicalElement(argument) || (argument.element() != "ActualParameter")) {
			continue;
		}

		code += (mApi.name(argument) + ", ");
	}
	code.chop(2); // terminating space and comma
	code += ")";

	QString returnValue;
	for (Id const &argument : mApi.children(currentNode)) {
		if (!mApi.isLogicalElement(argument) || (argument.element() != "ReturnValue")) {
			continue;
		}

		if (!returnValue.isEmpty()) {
			mErrorReporter.addError(QObject::tr("FunctionCall shall have no more than one return value"), currentNode);
			return CodeBranchGenerationResult("", currentNode);
		}

		QString returnValueTemplate = mTemplateUtils["@@ReturnValue@@"];
		QString const type = mApi.stringProperty(argument, "type").isEmpty()
				? ""
				: mApi.stringProperty(argument, "type") + " ";

		returnValueTemplate.replace("@@OptionalType@@", type)
				.replace("@@Name@@", mApi.name(argument))
				;

		returnValue += returnValueTemplate;
	}

	if (returnValue.endsWith('\n')) {
		returnValue.chop(1);
	}

	code = returnValue + code;

	operatorCode.replace("@@Command@@", code);

	IdList const links = mApi.outgoingLinks(currentNode);

	if (links.size() == 0) {
		return CodeBranchGenerationResult(operatorCode, currentNode);
	} else if (links.size() > 1) {
		mErrorReporter.addError(QObject::tr("FunctionCall node should have exactly 1 outgoing link"), currentNode);
		return CodeBranchGenerationResult("", currentNode);
	}

	Id const nextNode = mApi.otherEntityFromLink(links.at(0), currentNode);

	CodeBranchGenerationResult result = generateOperatorCode(nextNode);
	result.text = operatorCode + result.text;
	return result;
}
Exemple #18
0
void VisualDebugger::debug()
{
	mDebugType = VisualDebugger::fullDebug;
	QSettings settings("SPbSU", "QReal");
	setTimeout(settings.value("debuggerTimeout", 750).toInt());

	if (VisualDebugger::noErrors != doFirstStep(findBeginNode("InitialNode"))) {
		return;
	}

	mBlockParser->setErrorReporter(mInterpretersInterface.errorReporter());

	IdList outLinks = mLogicalModelApi.logicalRepoApi().outgoingLinks(mCurrentId);

	while (outLinks.count() > 0) {
		pause(mTimeout);

		if (mCurrentElem->id().element().compare("ConditionNode") == 0) {
			Id validLinkId = findValidLink();
			if (mBlockParser->hasErrors()) {
				deinitialize();
				return;
			}
			if (validLinkId != Id::rootId()) {
				doStep(validLinkId);
			} else {
				return;
			}
		} else {
			doStep(outLinks.at(0));
			if (mBlockParser->hasErrors()) {
				deinitialize();
				return;
			}
		}

		pause(mTimeout);

		if (!hasEndOfLinkNode(mCurrentId)) {
			error(VisualDebugger::missingEndOfLinkNode);
			return;
		}

		doStep(mLogicalModelApi.logicalRepoApi().to(mCurrentId));
		if (mBlockParser->hasErrors()) {
			deinitialize();
			return;
		}

		outLinks = mLogicalModelApi.logicalRepoApi().outgoingLinks(mCurrentId);
	}

	pause(mTimeout);

	if (!isFinalNode(mCurrentId)) {
		error(VisualDebugger::endWithNotEndNode);
		return;
	}

	mInterpretersInterface.errorReporter()->addInformation("Debug finished successfully");
	deinitialize();
	return;
}
Exemple #19
0
gui::ErrorReporter& VisualDebugger::debug()
{
	if (VisualDebugger::noErrors != checkEditor()) {
		return *mErrorReporter;
	}

	mDebugType = VisualDebugger::fullDebug;
	QSettings settings("SPbSU", "QReal");
	setTimeout(settings.value("debuggerTimeout", 750).toInt());
	setDebugColor(settings.value("debugColor").toString());

	if (VisualDebugger::noErrors != doFirstStep(findBeginNode("InitialNode"))) {
		return *mErrorReporter;
	}

	mBlockParser->setErrorReporter(mErrorReporter);

	IdList outLinks = mModelApi.graphicalRepoApi().outgoingLinks(mCurrentId);

	while (outLinks.count() > 0) {
		pause(mTimeout);

		if (mCurrentElem->newType().element().compare("ConditionNode") == 0) {
			Id validLinkId = findValidLink();
			if (mBlockParser->hasErrors()) {
				deinitialize();
				return *mErrorReporter;
			}
			if (validLinkId != ROOT_ID) {
				doStep(validLinkId);
			} else {
				return *mErrorReporter;
			}
		} else {
			doStep(outLinks.at(0));
			if (mBlockParser->hasErrors()) {
				deinitialize();
				return *mErrorReporter;
			}
		}

		pause(mTimeout);

		if (!hasEndOfLinkNode(mCurrentId)) {
			error(VisualDebugger::missingEndOfLinkNode);
			return *mErrorReporter;
		}

		doStep(mModelApi.graphicalRepoApi().to(mCurrentId));
		if (mBlockParser->hasErrors()) {
			deinitialize();
			return *mErrorReporter;
		}

		outLinks = mModelApi.graphicalRepoApi().outgoingLinks(mCurrentId);
	}

	pause(mTimeout);

	if (!isFinalNode(mCurrentId)) {
		error(VisualDebugger::endWithNotEndNode);
		return *mErrorReporter;
	}

	mErrorReporter->addInformation("Debug finished successfully");
	deinitialize();
	return *mErrorReporter;
}
/*
  * Checks that the units of the result of the assignment rule
  * are consistent with variable being assigned
  *
  * @return @c true if units are consistent, false otherwise.
  */
void
KineticLawUnitsCheck::check_ (const Model& m, const Model&)
{
  unsigned int n, p;
  IdList matched;
  IdList unmatched;
  const UnitDefinition *ud1=NULL, *ud2=NULL;

  if (m.getLevel() < 3)
    return;

  if (m.getNumReactions() < 2)
    return;

  /* log first KL with units declared*/ 
  for (n = 0; n < m.getNumReactions(); n++)
  {
    if (m.getReaction(n)->isSetKineticLaw())
    {
      if (m.getReaction(n)->getKineticLaw()->isSetMath())
      {
        if (!(m.getReaction(n)->getKineticLaw()->containsUndeclaredUnits()))
        {
          ud1 = m.getReaction(n)->getKineticLaw()->getDerivedUnitDefinition();
          matched.append(m.getReaction(n)->getId());
          break;
        }
      }
    }
  }

  /* loop thru remaining kl - if they are fully declared check that they match
   * and add to matched or unmatch as appropriate
   */
  for (p = n+1; p < m.getNumReactions(); p++)
  {
    if (m.getReaction(p)->isSetKineticLaw())
    {
      if (m.getReaction(p)->getKineticLaw()->isSetMath())
      {
        if (!(m.getReaction(p)->getKineticLaw()->containsUndeclaredUnits()))
        {
          ud2 = m.getReaction(p)->getKineticLaw()->getDerivedUnitDefinition();
          if (UnitDefinition::areEquivalent(ud1, ud2))
          {
            matched.append(m.getReaction(p)->getId());
          }
          else
          {
            unmatched.append(m.getReaction(p)->getId());
          }
        }
      }
    }
  }

  /* see if we have any unmatched */
  for (n = 0; n < unmatched.size(); n++)
  {

    logKLConflict(*(m.getReaction(unmatched.at((int)n))->getKineticLaw()->getMath()),
                  *(static_cast<const SBase *>(m.getReaction(unmatched.at((int)n)))));
  }

}