void 
ExtModelReferenceCycles::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)
        && !alreadyExistsInMap(logged, 
                    pair<const std::string, std::string>(id, (*it).second))
        && !alreadyExistsInMap(logged, 
                    pair<const std::string, std::string>((*it).second, id)))
      {
        logCycle(m, id, (*it).second);
        logged.insert(pair<const std::string, std::string>(id, (*it).second));
      }
    }
  }
}
Example #2
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);
}
Example #3
0
DispatcherGenerator::CodeBranchGenerationResult DispatcherGenerator::generateReturnActionCode(
		qReal::Id const &currentNode) const
{
	QString const returnValue = mApi.name(currentNode).isEmpty()
			? ""
			: (" " + mApi.name(currentNode))
			;

	QString returnWithValueTemplate = mTemplateUtils["@@Return@@"];
	returnWithValueTemplate.replace("@@OptionalReturnValue@@", returnValue);

	IdList const links = mApi.outgoingLinks(currentNode);

	if (links.size() == 0) {
		return CodeBranchGenerationResult(returnWithValueTemplate, currentNode);
	} else {
		mErrorReporter.addError(QObject::tr("ReturnAction node shall have no outgoing links"), currentNode);
		return CodeBranchGenerationResult("", currentNode);
	}
}
Example #4
0
void MetaEditorSupportPlugin::generateEditorWithQrmc()
{
    qrmc::MetaCompiler metaCompiler(*mLogicalRepoApi, ".");

    IdList const metamodels = mLogicalRepoApi->children(Id::rootId());

    QProgressBar *progress = new QProgressBar(mMainWindowInterface->windowWidget());
    progress->show();
    int const progressBarWidth = 240;
    int const progressBarHeight = 20;

    QApplication::processEvents();
    QRect const screenRect = qApp->desktop()->availableGeometry();
    progress->move(screenRect.width() / 2 - progressBarWidth / 2, screenRect.height() / 2 - progressBarHeight / 2);
    progress->setFixedWidth(progressBarWidth);
    progress->setFixedHeight(progressBarHeight);
    progress->setRange(0, 100);

    int forEditor = 60 / metamodels.size();

    foreach (Id const &key, metamodels) {
        QString const objectType = key.element();
        if (objectType == "MetamodelDiagram" && mLogicalRepoApi->isLogicalElement(key)) {
            QString nameOfTheDirectory = mLogicalRepoApi->stringProperty(key, "name of the directory");
            QString nameOfMetamodel = mLogicalRepoApi->stringProperty(key, "name");
            QString nameOfPlugin = nameOfTheDirectory.split("/").last();

            if (QMessageBox::question(mMainWindowInterface->windowWidget()
                                      , tr("loading..")
                                      , QString(tr("Do you want to compile and load editor %1?")).arg(nameOfPlugin)
                                      , QMessageBox::Yes, QMessageBox::No)
                    == QMessageBox::No)
            {
                continue;
            }

            progress->setValue(5);

            const QString normalizedName = nameOfMetamodel.at(0).toUpper() + nameOfMetamodel.mid(1);
            const bool stateOfLoad = mMainWindowInterface->pluginLoaded(normalizedName);
            if (!mMainWindowInterface->unloadPlugin(normalizedName)) {
                progress->close();
                delete progress;
                return;
            }

            if (!metaCompiler.compile(nameOfMetamodel)) { // generating source code for all metamodels
                QMessageBox::warning(mMainWindowInterface->windowWidget()
                                     , tr("error")
                                     , tr("Cannot generate source code for editor ") + nameOfPlugin);
                continue;
            }
            progress->setValue(20);

            QStringList qmakeArgs;
            qmakeArgs.append("CONFIG+=" + mLogicalRepoApi->stringProperty(key, "buildConfiguration"));
            qmakeArgs.append(nameOfMetamodel + ".pro");

            QProcess builder;
            builder.setWorkingDirectory(nameOfTheDirectory);
            const QStringList environment = QProcess::systemEnvironment();
            builder.setEnvironment(environment);
            builder.start(SettingsManager::value("pathToQmake").toString(), qmakeArgs);

            qDebug()  << "qmake";
            if ((builder.waitForFinished()) && (builder.exitCode() == 0)) {
                progress->setValue(40);
                builder.start(SettingsManager::value("pathToMake").toString());

                bool finished = builder.waitForFinished(100000);
                qDebug()  << "make";

                if (finished && (builder.exitCode() == 0)) {
                    if (stateOfLoad) {
                        QMessageBox::warning(mMainWindowInterface->windowWidget()
                                             , tr("Attention!"), tr("Please restart QReal."));
                        progress->close();
                        delete progress;
                        return;
                    }
                    qDebug()  << "make ok";
                    progress->setValue(progress->value() + forEditor / 2);

                    if (!nameOfMetamodel.isEmpty()) {
                        if (!mMainWindowInterface->unloadPlugin(normalizedName)) {
                            QMessageBox::warning(mMainWindowInterface->windowWidget()
                                                 , tr("error")
                                                 , tr("cannot unload plugin ") + normalizedName);
                            progress->close();
                            delete progress;
                            continue;
                        }
                    }

                    QString suffix = "";
                    if (mLogicalRepoApi->stringProperty(key, "buildConfiguration") == "debug") {
                        suffix = "-d";
                    }

                    QString const generatedPluginFileName = SettingsManager::value("prefix").toString()
                                                            + nameOfMetamodel
                                                            + suffix
                                                            + "."
                                                            + SettingsManager::value("pluginExtension").toString()
                                                            ;

                    if (mMainWindowInterface->loadPlugin(generatedPluginFileName, normalizedName)) {
                        progress->setValue(progress->value() + forEditor / 2);
                    }
                }
                progress->setValue(100);
            }
        }
    }
Example #5
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;
}
Example #6
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;
}
/*
  * 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)))));
  }

}