26 #include "../io/GroupXmlReader.h"
27 #include "../io/GroupXmlWriter.h"
28 #include "../io/XmlWriter.h"
37 #include <QMessageBox>
44 using namespace statechartio;
45 using namespace statechartmodel;
49 variantInfo(variantInfo)
58 QList<statechartmodel::StatePtr> statesToAnnotate;
60 for (
int i = 0; i < groups.count(); i++)
65 for (
int j = 0; j < group->getRootNode()->getChildren().count(); j++)
67 loadNode(group->getRootNode()->getChildren().at(j), group->getBoostGroupPath(), statesToAnnotate);
76 QList<statechartmodel::StatePtr> statesToAnnotate;
78 for (
int j = 0; j < group->getRootNode()->getChildren().count(); j++)
80 loadNode(group->getRootNode()->getChildren().at(j), group->getBoostGroupPath(), statesToAnnotate);
88 QMap<QString, statechartmodel::StatePtr> referenceMap;
89 QMapIterator<QString, StateTreeNodePtr> i(uuidToNodeMap);
94 referenceMap.insert(i.key(), i.value()->getState());
97 for (
int i = 0; i < statesToAnnotate.count(); i++)
99 statesToAnnotate.at(i)->addReferences(referenceMap);
105 QMap<QString, statechartmodel::StatePtr> referenceMap;
106 QMapIterator<QString, StateTreeNodePtr> i(uuidToNodeMap);
111 referenceMap.insert(i.key(), i.value()->getState());
114 for (
auto i : uuidToNodeMap)
116 i->getState()->addReferences(referenceMap);
122 std::filesystem::path nodePath = node->getBoostPath(parentPath);
129 std::shared_ptr<XmlReader> reader(
new XmlReader(iceCommunicator, variantInfo));
130 reader->parseXml(xml);
134 uuidToNodeMap.insert(state->getUUID(), node);
135 allTheStates.append(state);
145 for (
int i = 0; i < node->getChildren().count(); i++)
147 loadNode(node->getChildren().at(i), nodePath, allTheStates);
160 group->getPackageName();
162 groups.append(group);
169 uuidToNodeMap.clear();
174 groups.append(group);
181 uuidToNodeMap.insert(node->getState()->getUUID(), node);
189 uuidToNodeMap.remove(node->getState()->getUUID());
197 progressDialog->setMinimum(0);
198 progressDialog->setMaximum(groups.count());
199 progressDialog->setLabelText(
"Saving statechart groups");
201 auto startTime = IceUtil::Time::now();
202 #pragma omp parallel for schedule(static,1)
203 for (
int i = 0; i < groups.count(); i++)
210 std::filesystem::create_directories(group->getBoostDefinitionFilePath().parent_path());
213 for (
int j = 0; j < group->getRootNode()->getChildren().count(); j++)
215 saveNode(group->getRootNode()->getChildren().at(j), group->getBoostGroupPath());
217 if (omp_get_thread_num() == 0)
219 if (progressDialog && (IceUtil::Time::now() - startTime).toMilliSeconds() > 1000)
221 progressDialog->setValue(i + 1);
230 std::filesystem::path nodePath = node->getBoostPath(parentPath);
241 if (node->getState())
244 writer.
serialize(node->getState(), uuidToNodeMap);
248 ARMARX_INFO_S <<
"Writing new state definition to " << nodePath.string();
256 catch (std::exception& e)
258 QMetaObject::invokeMethod(
this,
"showWarning", Q_ARG(QString,
"Saving state failed!"), Q_ARG(QString, QString::fromStdString(std::string(e.what())).split(
"Backtrace:").first()));
265 std::filesystem::create_directory(nodePath);
267 for (
int i = 0; i < node->getChildren().count(); i++)
269 saveNode(node->getChildren().at(i), nodePath);
276 QString doxString =
"/**\n";
277 doxString +=
"@defgroup " + group->getPackageName() +
"-" + group->getName() +
" " + group->getName() +
"";
278 doxString +=
"\n@ingroup Statecharts\n";
279 doxString += group->getDescription();
280 doxString +=
"@defgroup " + group->getPackageName() +
"-" + group->getName() +
"-Substates " + group->getName() +
" Substates\n";
281 doxString +=
"@ingroup " + group->getPackageName() +
"-" + group->getName();
289 std::unique_lock lock(findersMutex);
290 auto it = finders.find(packageName);
291 if (it == finders.end())
293 finders.insert(std::make_pair(packageName,
CMakePackageFinder(packageName.toStdString())));
294 return finders.at(packageName);
307 bool loaded = variantInfo->isPackageLoaded(packageName);
308 if (!finder.packageFound())
312 ARMARX_WARNING_S <<
"Could not find package " << packageName <<
" - generated code might be incomplete";
319 ARMARX_INFO_S <<
"Loading variant info for " << packageName <<
" and its dependencies";
322 auto contains = [](
const std::map<VariantTypeId, std::string>& map,
const std::string &
value)
324 for (
const auto&
v : map)
337 if (lib->getPackageName() != packageName)
348 DynamicLibraryPtr lib = variantInfo->loadLibraryOfVariant(var->getBaseTypeName());
350 lib->setUnloadOnDestruct(
false);
356 if (iceCommunicator->getValueFactoryManager()->find(var->getBaseTypeName()))
358 ARMARX_INFO <<
"Loaded variant " << var->getBaseTypeName();
362 ARMARX_WARNING <<
"variant " << var->getBaseTypeName() <<
" could not be loaded. Adding Variant TypeName only.";
368 for (
auto& dep : finder.getDependencies())
379 progressDialog->setMinimum(0);
380 progressDialog->setMaximum(groups.count());
381 progressDialog->setLabelText(
"Generating code for statechart groups");
383 auto startTime = IceUtil::Time::now();
384 #pragma omp parallel for schedule(static,1)
385 for (
int i = 0; i < groups.size(); ++i)
390 if (omp_get_thread_num() == 0)
392 if (progressDialog && (IceUtil::Time::now() - startTime).toMilliSeconds() > 1000)
394 progressDialog->setValue(i + 1);
400 if (progressDialog && (IceUtil::Time::now() - startTime).toMilliSeconds() > 1000)
402 QMetaObject::invokeMethod(progressDialog,
"setValue", Q_ARG(
int, (i + 1)));
408 std::set<std::string> StateTreeModel::getVariantOfStatesWithNoCpp(
const StatechartGroupPtr& group)
410 std::set<std::string> variantTypes;
411 std::set<std::string> alreadyLinkedTypes;
414 std::set<std::string>* currentTypeSet = &variantTypes;
416 if (stateNode->checkCppExists())
419 currentTypeSet = &alreadyLinkedTypes;
421 auto state = stateNode->getState();
426 for (
auto param : state->getInputAndLocalParameters())
428 QString type = param->type;
429 currentTypeSet->insert(type.toStdString());
431 for (
auto param : state->getOutputParameters())
433 QString type = param->type;
434 currentTypeSet->insert(type.toStdString());
439 std::set<std::string> resultingTypes;
440 std::set_difference(variantTypes.begin(), variantTypes.end(),
441 alreadyLinkedTypes.begin(), alreadyLinkedTypes.end(),
442 std::inserter(resultingTypes, resultingTypes.end()));
444 std::set<std::string> innerVariantTypes;
445 for (
auto& type : resultingTypes)
448 while (containerType->subType)
450 containerType = containerType->subType;
452 if (!variantInfo->isBasic(containerType->typeId))
454 innerVariantTypes.insert(containerType->typeId);
458 return innerVariantTypes;
469 if (!finder.packageFound())
471 QMetaObject::invokeMethod(
this,
"showWarning", Q_ARG(QString,
"State Generation Error"), Q_ARG(QString,
"Could not find the package '" + QString::fromStdString(finder.getName()) +
"' - Did you run cmake for that package already? Skipping state generation of stategroup " + group->getName()));
481 std::map<QString, CMakePackageFinder>::const_iterator it;
483 std::unique_lock lock(findersMutex);
484 it = finders.find(group->getPackageName());
488 if (it == finders.end())
492 if (!checkPackage(finder))
497 it = finders.insert(std::make_pair(group->getPackageName(), finder)).first;
503 if (!checkPackage(packageFinder))
509 ARMARX_WARNING_S <<
"Build dir for package '" << packageFinder.
getName() <<
"' is empty! Skipping generating files.";
514 std::filesystem::path doxyFile = packageFinder.
getBuildDir();
516 if (!doxyFile.string().empty())
518 doxyFile /=
"doxygen";
525 doxyFile /= group->getName().toStdString() +
".dox";
528 std::set<std::string> proxies;
529 proxies.insert(
"ArmarXCoreInterfaces.systemObserver");
530 proxies.insert(
"ArmarXCoreInterfaces.conditionHandler");
531 for (QString p : group->getProxies())
533 proxies.insert(p.toUtf8().data());
535 Ice::StringSeq proxyVec(proxies.begin(), proxies.end());
536 if (group->contextGenerationEnabled())
538 std::set<std::string> innerVariantTypes = getVariantOfStatesWithNoCpp(group);
540 group->getPackageName().toUtf8().data(),
541 group->getName().toUtf8().data(),
563 if (node->getState() && node->getCppExists())
566 writer.
serialize(node->getState(), uuidToNodeMap);
567 std::string xml = writer.
getXmlString(
false).toUtf8().data();
578 catch (std::exception& e)
580 QMessageBox::warning(0,
"Saving state failed!", QString::fromStdString(std::string(e.what())).split(
"Backtrace:").first());
596 bool identical =
false;
598 if (std::filesystem::exists(std::filesystem::path(targetPath)))
601 identical = contents == currentContents;
606 QString qtargetPath = QString::fromUtf8(targetPath.data());
613 ARMARX_LOG_S <<
"Skipping identical file " << targetPath;
625 return QList<StatechartGroupPtr>(groups);
630 auto it = std::find_if(groups.constBegin(), groups.constEnd(), [&](
const StatechartGroupPtr & g)
632 return g->getName() == groupName;
635 if (it != groups.constEnd())
657 QMap<QString, StateTreeNodePtr>::const_iterator it = uuidToNodeMap.find(uuid);
659 if (it != uuidToNodeMap.end())
672 node->checkCppExists();
673 node->display = state->getStateName();
679 QList<StateInstancePtr> instances;
680 QMapIterator<QString, StateTreeNodePtr> i(uuidToNodeMap);
685 QMapIterator<QString, StateInstancePtr> itSubstate = i.value()->getState()->getSubstates();
687 while (itSubstate.hasNext())
692 if (state && node->getState() == state)
694 instances.append(itSubstate.value());
711 if (g->getBoostGroupPath() == groupPath)
727 void StateTreeModel::showWarning(QString title, QString
message)
729 QMessageBox::warning(0, title,
message);