28#include <QDialogButtonBox>
31#include <QInputDialog>
35#include <QProgressDialog>
66 QList<QVariant> headerInfo,
68 QLineEdit* filterLineEdit,
75 qRegisterMetaType<StateTreeNodePtr>(
"StateTreeNodePtr");
78 "XMLRemoteStateOffererRun", finder.
getBinaryDir(),
"ArmarXCore"));
79 this->variantInfo = variantInfo;
80 this->profiles = statechartProfiles;
81 this->currentProfile = currentProfile;
82 this->packageTool = packageTool;
83 this->headerInfo = headerInfo;
84 this->treeView = treeView;
86 this->rootNode = this->stateTreeModel->getRootNode();
87 this->groupCloner = std::make_shared<GroupCloner>(stateTreeModel, packageTool);
88 this->groupRenamer = std::make_shared<GroupRenamer>(groupCloner);
89 this->communicator = ic;
93 proxyModel->setSourceModel(
this);
94 proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
95 treeView->setModel(proxyModel);
98 contextMenuGroup =
new QMenu(treeView);
99 contextMenuFolder =
new QMenu(treeView);
100 contextMenuState =
new QMenu(treeView);
101 treeView->setContextMenuPolicy(Qt::CustomContextMenu);
103 actionDeleteNode =
new QAction(QIcon(
":/icons/delete.ico"),
"Delete", treeView);
104 actionMakeStatePublic =
new QAction(
"Public State", treeView);
105 actionMakeStatePublic->setCheckable(
true);
106 actionNewFolder =
new QAction(QIcon(
":/icons/folder-new.svg"),
"Add new Folder", treeView);
107 actionNewStateDefinition =
108 new QAction(QIcon(
":/icons/images/add-state.png"),
"Add new State Definition", treeView);
109 actionNewDynamicRemoteStateDefinition =
110 new QAction(
"Add new Dynamic Remote State Definition", treeView);
111 actionFindStateUsages =
new QAction(QIcon(
":/icons/search.svg"),
"Find State Usages", treeView);
112 actionRenameState =
new QAction(QIcon(
":/icons/rename.svg"),
"Rename State", treeView);
113 actionOpenCMakeProject =
114 new QAction(QIcon(
":/icons/qt-small.png"),
"Open CMake Project", treeView);
115 actionShowFullPath =
new QAction(QIcon(
":/icons/search.svg"),
"Show Full Path", treeView);
116 actionOpenStateCPP =
new QAction(QIcon(
":/icons/cpp.svg"),
"Open C++ Code", treeView);
118 new QAction(QIcon(
":/icons/run.svg"),
"Execute Statechart Group", treeView);
121 actionGenerateStateCPP =
122 new QAction(QIcon(
":/icons/document-properties.svg"),
"Generate State C++ Files", treeView);
123 actionRenameGroup =
new QAction(QIcon(
":/icons/rename.svg"),
"Rename Group", treeView);
124 actionCloneGroup =
new QAction(QIcon(
":/icons/clone.svg"),
"Clone Group", treeView);
125 actionGroupProperties =
126 new QAction(QIcon(
":/icons/document-properties.svg"),
"Group Properties", treeView);
128 QList<QAction*> groupActions, folderActions, stateActions;
130 groupActions.append(actionNewStateDefinition);
131 groupActions.append(actionNewDynamicRemoteStateDefinition);
132 groupActions.append(actionNewFolder);
133 groupActions.append(actionDeleteNode);
134 groupActions.append(actionOpenCMakeProject);
135 groupActions.append(actionShowFullPath);
136 groupActions.append(actionExecuteGroup);
138 groupActions.append(actionRenameGroup);
139 groupActions.append(actionCloneGroup);
140 groupActions.append(actionGroupProperties);
142 folderActions.append(actionNewStateDefinition);
143 folderActions.append(actionNewDynamicRemoteStateDefinition);
144 folderActions.append(actionNewFolder);
145 folderActions.append(actionDeleteNode);
147 stateActions.append(actionMakeStatePublic);
148 stateActions.append(actionFindStateUsages);
149 stateActions.append(actionRenameState);
150 stateActions.append(actionDeleteNode);
151 stateActions.append(actionOpenStateCPP);
153 stateActions.append(actionGenerateStateCPP);
155 for (QAction* a : groupActions)
157 a->setIconVisibleInMenu(
true);
160 for (QAction* a : folderActions)
162 a->setIconVisibleInMenu(
true);
165 for (QAction* a : stateActions)
167 a->setIconVisibleInMenu(
true);
170 contextMenuGroup->addActions(groupActions);
171 contextMenuFolder->addActions(folderActions);
172 contextMenuState->addActions(stateActions);
175 connect(stateTreeModel.get(), SIGNAL(stateAddedOrRemoved()), SLOT(stateAddedOrRemoved()));
176 connect(treeView, SIGNAL(customContextMenuRequested(QPoint)), SLOT(
onContextMenu(QPoint)));
179 connect(actionNewDynamicRemoteStateDefinition,
182 connect(actionDeleteNode, SIGNAL(triggered()), SLOT(
onDeleteNode()));
183 connect(actionMakeStatePublic, SIGNAL(triggered(
bool)), SLOT(
onMakeStatePublic(
bool)));
184 connect(actionNewFolder, SIGNAL(triggered()), SLOT(
onNewFolder()));
186 connect(actionRenameState, SIGNAL(triggered()), SLOT(
onRenameState()));
187 connect(actionOpenCMakeProject, SIGNAL(triggered()),
this, SLOT(
onOpenCMakeProject()));
188 connect(actionShowFullPath, SIGNAL(triggered()),
this, SLOT(
onShowFullPath()));
189 connect(actionOpenStateCPP, SIGNAL(triggered()),
this, SLOT(
onOpenStateCPP()));
190 connect(actionExecuteGroup, SIGNAL(triggered()),
this, SLOT(
onExecuteGroup()));
194 connect(actionRenameGroup, SIGNAL(triggered()),
this, SLOT(
onRenameGroup()));
195 connect(actionCloneGroup, SIGNAL(triggered()),
this, SLOT(
onCloneGroup()));
196 connect(actionGroupProperties, SIGNAL(triggered()),
this, SLOT(
onGroupProperties()));
198 connect(filterLineEdit,
199 SIGNAL(textChanged(QString)),
201 SLOT(setFilterFixedString(QString)));
202 connect(filterLineEdit, SIGNAL(textChanged(QString)),
this, SLOT(expandFilterResults(QString)));
208 ARMARX_INFO <<
"Killing " << processes.size() <<
" statechart processes";
209 for (
auto& process : processes)
212 process->terminate();
214 for (
auto& process : processes)
216 ARMARX_INFO <<
"Waiting for process " << process->pid();
217 process->waitForFinished(2000);
219 for (
auto& process : processes)
221 if (process->pid() > 0)
232 if (!
index.isValid())
241 case Qt::DisplayRole:
244 return node->getDisplay() + (node->getState() ?
"" :
" [no .xml]") +
245 (node->getCppExists() ?
"" :
" [no .cpp]") +
246 (node->isPublic() ?
" (public)" :
"") +
253 return node->getDisplay();
256 case Qt::DecorationRole:
262 return getIcon(
":/icons/folder-locked.svg");
264 if (treeView->isExpanded(
index))
266 return getIcon(
":/icons/folder-open.svg");
270 return getIcon(
":/icons/folder.svg");
275 if (node->getState())
277 if (node->getState()->getSubstates().count() > 0)
279 return getIcon(node->isPublic() ?
":/statechart-editor/states-public.svg"
280 :
":/statechart-editor/states.svg");
284 return getIcon(node->isPublic() ?
":/statechart-editor/state-public.svg"
285 :
":/statechart-editor/state.svg");
290 return getIcon(
":/statechart-editor/state-broken.svg");
296 case Qt::ToolTipRole:
298 return QString::fromStdString(node->getAbsoluteBoostPath().string());
308 if (!
index.isValid())
315 flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
319 if (node->getState() || node->isGroup())
321 flags |= Qt::ItemIsDragEnabled;
331 if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
333 return headerInfo.value(section);
342 if (!hasIndex(row, column, parentIndex))
344 return QModelIndex();
349 if (!parentIndex.isValid())
351 parentNode = this->rootNode.get();
355 parentNode =
static_cast<StateTreeNode*
>(parentIndex.internalPointer());
362 return createIndex(row, column, childNode);
366 return QModelIndex();
373 if (!
index.isValid())
375 return QModelIndex();
381 if (parentNode == rootNode)
383 return QModelIndex();
386 return createIndex(parentNode->row(), 0, parentNode.get());
400 return rootNode->childCount();
405 <<
"The internal pointer of a tree node is zero";
421 return rootNode->columnCount();
428 bool load = !groupDefinitionFile.isEmpty();
431 QFileDialog selectGroupFile(treeView,
"Open Statechart Group");
433 selectGroupFile.setOption(QFileDialog::ReadOnly,
true);
434 selectGroupFile.setOption(QFileDialog::HideNameFilterDetails,
false);
435 selectGroupFile.setFileMode(QFileDialog::ExistingFile);
437 urls << QUrl::fromLocalFile(
438 QDesktopServices::storageLocation(QDesktopServices::HomeLocation))
439 << QUrl::fromLocalFile(
440 QDesktopServices::storageLocation(QDesktopServices::DesktopLocation));
447 selectGroupFile.setSidebarUrls(urls);
449 filters <<
"Statechart Group (*.scgxml)";
451 selectGroupFile.setNameFilters(
filters);
452 load = selectGroupFile.exec() == QDialog::Accepted;
453 if (load && groupDefinitionFile.isEmpty())
455 groupDefinitionFile = selectGroupFile.selectedFiles().first();
473 stateTreeModel->loadGroupStates(group);
475 catch (std::exception& e)
477 QString reason(QString::fromStdString(e.what()));
478 reason.truncate(200);
480 QMessageBox::warning(0,
481 "Error while loading States",
482 QString(
"An error while loading states - Reason:\n" + reason));
485 catch (std::exception& e)
487 QString reason = QString::fromStdString(e.what());
488 reason.truncate(200);
489 QMessageBox::warning(0,
490 "Error while loading Statechart Group",
491 QString(
"An error while loading the statechart group file '") +
492 groupDefinitionFile +
"' - Reason:\n" + reason);
505 this->layoutAboutToBeChanged();
513 rootNode->appendChild(group->getRootNode());
514 rootNode->sortChildren();
516 this->layoutChanged();
519 treeView->expand(getIndex(groupNode));
520 treeView->setCurrentIndex(getIndex(groupNode));
527 const QString& groupPath,
528 const QString& description,
529 const QString& packageName,
530 const QList<QString> proxies,
531 bool generateContext,
532 const QMap<QString, QString>& statechartGroupConfigurations)
535 std::filesystem::path defPath = groupPath.toUtf8().data();
536 defPath /= (groupName +
".scgxml").
toUtf8().data();
544 statechartGroupConfigurations,
548 group->setRootNode(groupRootNode);
550 stateTreeModel->addGroup(group);
551 rootNode->appendChild(group->getRootNode());
553 rootNode->sortChildren();
557 QMetaObject::invokeMethod(
558 this,
"selectNode", Qt::QueuedConnection, Q_ARG(
StateTreeNodePtr, group->getRootNode()));
566 stateTreeModel->loadAllStates();
572 return stateTreeModel->getNodeByState(state);
578 QModelIndex selected = treeView->currentIndex();
580 if (!selected.isValid())
591 return node ? node->getClosestParentFolderOrGroupNode() :
StateTreeNodePtr();
667 QList<StateInstancePtr> instances = stateTreeModel->findStateUsages(node);
669 if (instances.count() > 0)
671 QString message = QString(
"Cannot delete state, it is still being used by %1 state(s):\n%2")
672 .arg(instances.count())
673 .arg(buildStateUsageString(instances));
674 QMessageBox::warning(NULL,
"Cannot delete State", message);
678 if (node->getState())
680 QString question = QString(
"You are about to delete the State Definition '%1'.\nDo you "
681 "also want to permanently remove the underlying file %2?")
682 .arg(node->getDisplay(), node->getBasename());
683 QMessageBox::StandardButton reply =
684 QMessageBox::question(NULL,
685 "Delete State Definition File?",
687 QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel);
689 if (reply == QMessageBox::Cancel)
693 else if (reply == QMessageBox::Yes)
695 std::filesystem::remove(node->getAbsoluteBoostPath());
696 if (node->getCppExists())
698 std::filesystem::remove(node->getBoostCppFilePath());
699 std::filesystem::remove(node->getBoostHFilePath());
700 std::filesystem::remove(node->getBoostGeneratedHFilePath());
706 QString question = QString(
"Remove State Definition '%1'?").arg(node->getDisplay());
707 QMessageBox::StandardButton reply = QMessageBox::question(
708 NULL,
"Delete State Definition?", question, QMessageBox::Ok | QMessageBox::Cancel);
710 if (reply == QMessageBox::Cancel)
719 QString::fromUtf8((node->getGroup()->getBoostDefinitionFilePath()).c_str()));
725 bool createDynamicRemoteState)
727 this->layoutAboutToBeChanged();
731 if (!createDynamicRemoteState)
734 state->addEndSubstate(
"Success",
"Success");
735 state->addEndSubstate(
"Failure",
"Failure");
737 evt->name =
"Failure";
739 "Event for statechart-internal failures or optionally user-code failures";
740 state->setOutgoingEvents(
EventList{evt});
748 state->setStateName(name);
752 stateTreeModel->setNodeState(node, state);
753 parent->appendChild(node);
755 stateTreeModel->notifyNewStateTreeNode(node);
756 this->layoutChanged();
757 treeView->sortByColumn(0, Qt::AscendingOrder);
759 QMetaObject::invokeMethod(
768 this->layoutAboutToBeChanged();
771 parent->appendChild(node);
774 this->layoutChanged();
776 treeView->expand(getIndex(
parent));
777 treeView->setCurrentIndex(getIndex(node));
785 if (!
index.isValid())
791 if (
index.model() == proxyModel)
806 treeView->setCurrentIndex(proxyModel->mapFromSource(getIndex(node)));
813 QModelIndex
index = treeView->indexAt(point);
823 actionMakeStatePublic->setEnabled(
true);
824 actionRenameState->setEnabled(
true);
825 actionRenameGroup->setEnabled(
true);
826 actionGenerateStateCPP->setEnabled(
true);
827 actionNewFolder->setEnabled(
true);
828 actionNewStateDefinition->setEnabled(
true);
829 actionNewDynamicRemoteStateDefinition->setEnabled(
true);
830 actionOpenCMakeProject->setEnabled(
true);
831 actionOpenStateCPP->setEnabled(
true);
832 actionGroupProperties->setEnabled(
true);
833 actionDeleteNode->setEnabled(
true);
835 auto applyReadOnlyStatusToMenu = [&,
this]()
842 actionMakeStatePublic->setEnabled(writable);
843 actionRenameState->setEnabled(writable);
844 actionRenameGroup->setEnabled(writable);
845 actionGenerateStateCPP->setEnabled(writable);
846 actionNewFolder->setEnabled(writable);
847 actionNewStateDefinition->setEnabled(writable);
848 actionNewDynamicRemoteStateDefinition->setEnabled(writable);
849 actionOpenCMakeProject->setEnabled(writable);
850 actionOpenStateCPP->setEnabled(writable);
851 actionGroupProperties->setEnabled(writable);
852 actionDeleteNode->setEnabled(writable);
859 actionMakeStatePublic->setEnabled(node->getState() != NULL);
860 actionMakeStatePublic->setChecked(node->isPublic());
861 actionFindStateUsages->setEnabled(node->getState() != NULL);
862 actionRenameState->setEnabled(node->isState());
863 actionGenerateStateCPP->setEnabled(!node->getCppExists() &&
864 node->getState()->getType() == eNormalState);
865 actionOpenStateCPP->setEnabled(node->getCppExists());
866 applyReadOnlyStatusToMenu();
867 contextMenuState->exec(treeView->mapToGlobal(point));
869 else if (node->isGroup())
872 QMap<QString, QProcess*>::const_iterator it;
875 && (it = processes.find(node->getGroup()->getGroupPath())) != processes.end() &&
876 it.value()->state() != QProcess::NotRunning)
878 actionExecuteGroup->setText(
"Stop and Execute Statechart Group");
882 actionExecuteGroup->setText(
"Execute Statechart Group");
884 applyReadOnlyStatusToMenu();
885 contextMenuGroup->exec(treeView->mapToGlobal(point));
887 else if (node->isFolder() && node != rootNode)
889 applyReadOnlyStatusToMenu();
890 contextMenuFolder->exec(treeView->mapToGlobal(point));
903 label =
new QLabel(
"Enter the state name",
this);
905 QRegExp rx(
"^([a-zA-Z_]{1})([a-zA-Z_0-9]+)$");
906 QValidator* validator =
new QRegExpValidator(rx,
this);
908 setWindowTitle(
"New State Definition");
910 checkbox =
new QCheckBox(
"Create C++ Files",
this);
911 QBoxLayout* layout =
new QBoxLayout(QBoxLayout::TopToBottom,
this);
913 buttonBox->setObjectName(QString::fromUtf8(
"buttonBox"));
914 buttonBox->setOrientation(Qt::Horizontal);
915 buttonBox->setStandardButtons(QDialogButtonBox::Cancel | QDialogButtonBox::Ok);
916 layout->addWidget(
label);
920 QObject::connect(
buttonBox, SIGNAL(accepted()),
this, SLOT(accept()));
921 QObject::connect(
buttonBox, SIGNAL(rejected()),
this, SLOT(reject()));
926StateTreeController::retrieveNewStateName(QString& newStateName,
928 bool& createCPPFiles,
935 QMessageBox::warning(
936 NULL,
"Nothing selected",
"Error: No state, group or folder selected.");
940 node = node->getClosestParentFolderOrGroupNode();
942 StateCreationDialog dialog;
943 dialog.
checkbox->setEnabled(askForCPPFiles);
945 if (dialog.exec() == QDialog::Rejected)
951 createCPPFiles = dialog.
checkbox->isChecked();
955 QMessageBox::warning(NULL,
957 QString(
"Error: Provided name '%1' does not meet requirements: Has to "
958 "start with a letter, followed by letters and digits. Sorry.")
963 if (node->getGroup()->findNodeByStateName(newStateName))
965 QMessageBox::warning(
967 "Duplicate State Name",
968 QString(
"Error: State with name '%1' exists already. Sorry.").arg(newStateName));
972 if (node->getGroup()->getName() == newStateName)
974 QMessageBox::warning(
975 NULL,
"Name Conflict", QString(
"Error: State cannot have same name as Group. Sorry."));
983StateTreeController::getIcon(
const QString& path)
const
985 if (!icons.contains(path))
987 icons[path] = QIcon(path);
997 QString newStateName;
999 if (!retrieveNewStateName(newStateName, node, createCPPFiles,
true))
1011 if (!packageTool->addFullXmlStatechart(
1012 newState->getGroup()->getName().toUtf8().data(),
1013 newState->getBoostPathRelativeToGroup().replace_extension().string(),
1014 newState->getGroup()->getPackagePath().toUtf8().data()))
1016 ARMARX_WARNING_S <<
"Creating source files for state " << newStateName <<
" failed";
1021 if (!packageTool->addXmlOnlyXmlStatechart(
1022 newState->getGroup()->getName().toUtf8().data(),
1023 newState->getBoostPathRelativeToGroup().replace_extension().string(),
1024 newState->getGroup()->getPackagePath().toUtf8().data()))
1026 ARMARX_WARNING_S <<
"Creating source files for state " << newStateName <<
" failed";
1030 newState->checkCppExists();
1037 bool createCPPFiles;
1039 QString newStateName;
1041 if (!retrieveNewStateName(newStateName, node, createCPPFiles,
false))
1058 QMessageBox::warning(
1059 NULL,
"Nothing selected",
"Error: No state, group or folder selected.");
1065 QMessageBox::warning(NULL,
"Internal error",
"Internal error.");
1070 QString name = QInputDialog::getText(
1071 NULL, QString(
"New Folder"), QString(
"Enter name"), QLineEdit::Normal, QString(), &ok);
1079 std::filesystem::create_directory(newFolderNode->getAbsoluteBoostPath());
1104 msgBox.setText(
"Error: No state selected.");
1113 treeView->repaint();
1119 QList<StateInstancePtr> instances = stateTreeModel->findStateUsages(
getSelectedNode());
1121 QString message(
"Usage count: ");
1122 message += QString::number(instances.count());
1123 message +=
"\n" + buildStateUsageString(instances);
1125 msgBox.setText(message);
1134 if (node && node->isState())
1141 if (d.exec() == QDialog::Accepted)
1153 auto groups = stateTreeModel->getGroups();
1154 stateTreeModel->clear();
1156 for (
const auto&
c : rootNode->getChildren())
1172 if (loadedGroup->getDefinitionFilePath() == group->getDefinitionFilePath())
1174 stateTreeModel->generateBaseClasses(loadedGroup);
1180 ARMARX_WARNING_S <<
"Renaming state '" << state->getStateName() <<
"' to '"
1197 ARMARX_INFO_S << node->getBoostPathRelativeToGroup().string()
1198 <<
" group path: " << node->getGroup()->getGroupPath().toStdString();
1200 opener.
openFile(
"qtcreatorProject",
1201 node->getGroup()->getPackagePath().toStdString() +
"/CMakeLists.txt");
1214 QMessageBox::information(treeView,
1215 "Path for Group " + node->getGroup()->getName(),
1216 node->getGroup()->getGroupPath());
1234 if (processes.find(group->getGroupPath()) != processes.end())
1236 processes[group->getGroupPath()]->terminate();
1237 processes[group->getGroupPath()]->waitForFinished(1000);
1238 processes[group->getGroupPath()]->kill();
1239 processes.remove(group->getGroupPath());
1248 if (processes.find(group->getGroupPath()) == processes.end())
1250 processes[group->getGroupPath()] =
new QProcess(
this);
1254 QProcess* p = processes[group->getGroupPath()];
1258 if (!startState.isEmpty())
1260 args <<
"--ArmarX.XMLStateComponent.StatesToEnter=" + startState;
1262 args <<
"--ArmarX.XMLStateComponent.XMLStatechartGroupDefinitionFile=" +
1263 group->getDefinitionFilePath();
1264 args <<
"--ArmarX.XMLStateComponent.XMLStatechartProfile=" +
1265 QString::fromStdString(currentProfile->getName());
1266 args <<
"--ArmarX.XMLStateComponent.ObjectName=" + group->getName() +
"StateComponent";
1267 args <<
"--ArmarX.ApplicationName=" + group->getName() +
"StateComponentApp";
1268 QString path = QString::fromStdString(
core.getBinaryDir()) +
"/XMLRemoteStateOffererRun";
1269 ARMARX_INFO_S << path <<
" " << args.join(
" ").toStdString();
1271 std::string username;
1274 username = getenv(
"USER");
1276 std::string tempLogDir = (std::filesystem::temp_directory_path() / (
"armarx-" + username) /
1277 group->getName().toStdString())
1279 if (!std::filesystem::exists(tempLogDir) && !std::filesystem::create_directories(tempLogDir))
1281 ARMARX_WARNING_S <<
"Could not create log dirs for executing group - aborting";
1284 p->setStandardOutputFile(QString::fromStdString(tempLogDir) +
"/out.log");
1285 p->setStandardErrorFile(QString::fromStdString(tempLogDir) +
"/err.log");
1286 p->setProcessChannelMode(QProcess::MergedChannels);
1287 p->start(path, args);
1288 connect(p, SIGNAL(readyReadStandardOutput()),
this, SLOT(processOutputReady()));
1289 connect(p, SIGNAL(readyReadStandardError()),
this, SLOT(processErrorsReady()));
1307 deps.push_back(group);
1311 if (processes.find(dep->getGroupPath()) != processes.end())
1313 processes[dep->getGroupPath()]->terminate();
1316 auto startTime = IceUtil::Time::now();
1319 if (processes.find(dep->getGroupPath()) != processes.end())
1321 auto timeLeftToWait =
1322 std::max<int>(0, 1000 - (IceUtil::Time::now() - startTime).toMilliSeconds());
1323 processes[dep->getGroupPath()]->waitForFinished(timeLeftToWait);
1324 processes[dep->getGroupPath()]->kill();
1325 processes.remove(dep->getGroupPath());
1341 QString noneState(
"---");
1342 states << noneState;
1345 if (curnode->isPublic() && curnode->isState())
1347 states << curnode->getState()->getStateName();
1351 QString startState = QInputDialog::getItem(
1352 0,
"State",
"Select the state to start or none", states, 0,
false, &ok);
1357 if (startState == noneState)
1376 auto process = qobject_cast<QProcess*>(sender());
1379 ARMARX_INFO_S << process->pid() <<
" exited with code " << exitCode;
1440 if (!node || !node->isState())
1442 QMessageBox::warning(NULL,
"No State selected",
"Error: No state selected.");
1446 if (!packageTool->addCppOnlyXmlStatechart(
1447 node->getGroup()->getName().toUtf8().data(),
1448 node->getBoostPathRelativeToGroup().replace_extension().string(),
1449 node->getGroup()->getPackagePath().toUtf8().data()))
1451 ARMARX_WARNING_S <<
"Creating source files for state " << node->getBasename()
1453 << packageTool->getLastOutput();
1456 node->checkCppExists();
1464 if (node && node->isGroup())
1470 if (d.exec() == QDialog::Accepted)
1474 if (!g.first->existsCMakeLists())
1476 QMessageBox::warning(0,
1478 g.first->getName() +
" at " + g.first->getGroupPath() +
1479 " contains no CMakeLists.txt - is it an installed "
1480 "package? Installed packages cannot be cloned.");
1485 if (
auto newMapping = groupCloner->cloneGroupsTo(
1489 <<
"Cloning successful, creating/overwriting mapping file in package: "
1493 const QString packageName = QFileInfo(d.
getPackagePath()).fileName();
1498 groupDir.cd(
"source");
1499 groupDir.cd(packageName);
1500 groupDir.cd(
"statecharts");
1501 groupDir.cd(g.second);
1502 QString newDefFile = groupDir.path() + QDir::separator() + g.second +
".scgxml";
1515 if (node && node->isGroup())
1520 if (d.exec() == QDialog::Accepted)
1528 if (
auto newGroupDirPath =
1531 QString newGroupDefinitionPath =
1532 *newGroupDirPath + QDir::separator() + d.
getNewName() +
".scgxml";
1538 stateTreeModel->clear();
1540 for (
const auto&
c : rootNode->getChildren())
1550 if (g->getGroupPath() == group->getGroupPath())
1570 if (node && node->isGroup())
1577 group->getProxies(),
1578 group->contextGenerationEnabled(),
1580 group->getConfigurations(),
1581 group->getDescription(),
1584 if (d.exec() == QDialog::Accepted)
1597 treeView->collapseAll();
1604 treeView->expand(proxyModel->mapFromSource(getIndex(node->getParent())));
1605 treeView->setCurrentIndex(proxyModel->mapFromSource(getIndex(node)));
1611 if (!node->getCppExists())
1613 QMessageBox::warning(NULL,
1615 QString(
"File '") + node->getBoostCppFilePath().c_str() +
1620 opener.openFileWithDefaultEditor(node->getBoostCppFilePath().c_str());
1625StateTreeController::processOutputReady()
1627 QProcess* p = qobject_cast<QProcess*>(sender());
1631 std::cout << QString(p->readAllStandardOutput());
1640StateTreeController::processErrorsReady()
1642 QProcess* p = qobject_cast<QProcess*>(sender());
1646 std::cerr << QString(p->readAllStandardError());
1655StateTreeController::stateAddedOrRemoved()
1657 std::cout <<
"StateTreeController::stateAddedOrRemoved()" << std::endl;
1658 treeView->repaint();
1662StateTreeController::expandFilterResults(
const QString& filterString)
1664 if (filterString.length() == 0)
1675 if (!node || node == rootNode || !node->getParent())
1677 return QModelIndex();
1680 return createIndex(node->row(), 0, node.get());
1684StateTreeController::buildStateUsageString(QList<StateInstancePtr> instances)
1687 QListIterator<StateInstancePtr> i(instances);
1693 stateTreeModel->getNodeByState(stateInstance->getParent())->getGroup()->getName() +
1694 "/" + stateInstance->getParent()->getStateName() +
": '" +
1695 stateInstance->getInstanceName() +
"'\n";
1698 return message.trimmed();
1705 stateTreeModel->notifyDeleteStateTreeNode(stateNode);
1718 if (node->getChildren().count() > 0)
1720 QMessageBox::warning(
1721 NULL,
"Folder cannot be deleted.",
"Folder cannot be deleted. It is not empty.");
1727 std::filesystem::remove(node->getAbsoluteBoostPath());
1731 QString::fromUtf8((node->getGroup()->getBoostDefinitionFilePath()).c_str()));
1733 catch (std::exception&)
1735 QMessageBox::warning(
1736 NULL,
"Folder cannot be deleted.",
"Folder cannot be deleted. It is not empty. ");
1756 auto statechartsCmakeListPath = QString::fromUtf8(
1757 (node->getAbsoluteBoostPath().remove_filename().parent_path() /
"CMakeLists.txt").c_str());
1759 filecontents = filecontents.remove(
"add_subdirectory(" + node->getBasename() +
")");
1762 std::filesystem::remove_all(node->getAbsoluteBoostPath().remove_filename());
1770 int row = node->row();
1772 this->beginRemoveRows(getIndex(node->getParent()), row, row);
1774 node->getParent()->removeChild(node);
1776 this->endRemoveRows();
1786 d.setMinimumDuration(1000);
1787 stateTreeModel->saveAll(&d);
1791 stateTreeModel->generateAllBaseClasses(&d);
1806 result <<
"application/x-State";
1807 result <<
"application/pointer";
1814 if (indexes.size() == 0)
1816 return new QMimeData();
1821 if (node->isGroup())
1823 QMimeData*
mimeData =
new QMimeData();
1824 QByteArray encodedData;
1826 QDataStream stream(&encodedData, QIODevice::WriteOnly);
1829 foreach (
const QModelIndex&
index, indexes)
1831 if (
index.isValid())
1836 << node->getGroup()->getPackageName().toStdString();
1838 auto prop = appForDrag->getProperties();
1841 node->getGroup()->getBoostDefinitionFilePath().string());
1842 prop->getProperties()->setProperty(
1843 "ArmarX.XMLStateComponent.XMLStatechartGroupDefinitionFile",
1844 relativeGroupFilePath);
1845 prop->getProperties()->setProperty(
"ArmarX.XMLStateComponent.XMLStatechartProfile",
1846 currentProfile->getName());
1847 prop->getProperties()->setProperty(
"ArmarX.XMLStateComponent.ObjectName",
1848 node->getGroup()->getName().toStdString() +
1849 "XMLStateComponent");
1850 prop->getProperties()->setProperty(
1851 "ArmarX.ApplicationName", node->getGroup()->getName().toStdString() +
"App");
1852 appForDrag->setProperties(prop);
1855 stream << reinterpret_cast<quint64>(appForDrag.get())
1856 << node->getGroup()->getName() ;
1861 mimeData->setData(
"application/pointer", encodedData);
1865 if (!node || !node->getState())
1867 return new QMimeData();
1871 StateMimeData*
data =
new StateMimeData(node->getState(), stateTreeModel);
1885 return stateTreeModel->getNodeByState(this->state)->getGroup() ==
1886 stateTreeModel->getNodeByState(
state)->getGroup();
1890StateTreeController::StateMimeData::isPublic()
const
1892 return stateTreeModel->getNodeByState(this->state)->isPublic();
#define STATEOFFERERSUFFIX
Class containing data about an application Provides methods to get and set the date contained in the ...
The AbstractStateMimeData class is used to transport state data from the treeview to the stateview an...
statechartmodel::StatePtr state
static std::string relativeTo(const std::string &from, const std::string &to)
Transform an absolute filepath into a relative path of the other absolute filepath.
static std::string getHomePath()
The CMakePackageFinder class provides an interface to the CMake Package finder capabilities.
std::string getBinaryDir() const
std::vector< std::string > getIncludePathList() const
Return the include paths in a vector.
bool packageFound() const
Returns whether or not this package was found with cmake.
StatechartGroupMapping getStatechartGroupMapping() const
QString getPackagePath() const
QVector< QPair< StatechartGroupPtr, QString > > getGroupsToClone() const
QMap< QString, QString > getConfigurations() const
QString getGroupDescription() const
QList< QString > getProxies() const
bool contextGenerationEnabled() const
The EditorFileOpener class.
void openFile(const std::string &editorName, const std::string &filepath, int lineNumber=0)
QVector< StatechartGroupPtr > getGroupDependencies(const StatechartGroupPtr &group, bool includeSelf=false)
static void WriteFileContents(QString path, QString contents)
static void WriteXml(StatechartGroupPtr group, QString path, bool indent=true)
static QString ReadFileContents(QString path)
This proxy model reimplements the filterAcceptsRow function with a new behavior: All elements that fi...
static void ExpandFilterResults(QTreeView *treeView)
Expands the treeview that all items that match the filterstring are expanded and directly visible.
bool isSaveAllRequested() const
QString getNewName() const
QVector< StatechartGroupPtr > getAllGroups() const
QVector< StatechartGroupPtr > getDependantGroups() const
bool isSaveAllRequested() const
QString getNewStateName() const
QVector< StateRenamer::InstanceRenameInfo > getInstanceRenameInfos() const
static bool RenameState(const QVector< InstanceRenameInfo > &instanceRenameInfos, const StateTreeNodePtr &state, const QString &newStateName, const StatechartGroupPtr &group)
void closeAllTabsRequested()
bool selectedNodeIsFolderOrGroup()
QStringList mimeTypes() const override
void stopGroupExecutionWithDependencies(StatechartGroupPtr group)
bool selectedNodeIsGroup()
void onNewStateDefinition()
void onOpenGroup(QString groupFile="")
StateTreeNodePtr getClosestParentFolderOrGroupNode(StateTreeNodePtr node)
StateTreeNodePtr getNodeByState(statechartmodel::StatePtr state)
StatechartGroupPtr addNewGroup(const QString &groupName, const QString &groupPath, const QString &description, const QString &packageName, const QList< QString > proxies, bool generateContext, const QMap< QString, QString > &statechartGroupConfigurations)
void stopGroupExecution(StatechartGroupPtr group)
StateTreeNodePtr createNewState(QString name, StateTreeNodePtr parent, bool createDynamicRemoteState=false)
QVariant headerData(int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const override
void onNewDynamicRemoteStateDefinition()
void onOpenCMakeProject()
int rowCount(const QModelIndex &parent=QModelIndex()) const override
void removeFolder(StateTreeNodePtr folderNode)
Qt::ItemFlags flags(const QModelIndex &index) const override
void onMakeStatePublic(bool enable)
bool nodeIsFolderOrGroup(StateTreeNodePtr node)
void executeGroup(StatechartGroupPtr group, QString startState="")
void onGenerateStateCppFiles()
bool selectedNodeIsFolder()
void removeNodeFromTree(StateTreeNodePtr node)
StateTreeNodePtr tryCreateNewState(QString name)
bool selectedNodeIsState()
~StateTreeController() override
StateTreeNodePtr createNewFolder(QString name, StateTreeNodePtr parent)
StatechartGroupPtr loadGroup(QString groupDefinitionFile)
void executeGroupWithDependencies(StatechartGroupPtr group, QString startState)
StateTreeController(Ice::CommunicatorPtr ic, VariantInfoPtr variantInfo, QList< QVariant > headerInfo, QTreeView *treeView, QLineEdit *filterLineEdit, const ArmarXPackageToolInterfacePtr &packageTool, const StatechartProfilesPtr &statechartProfiles, StatechartProfilePtr currentProfile, QObject *parent=0)
int columnCount(const QModelIndex &parent=QModelIndex()) const override
void selectNode(StateTreeNodePtr node)
StateTreeNodePtr getNode(QModelIndex index) const
QModelIndex parent(const QModelIndex &index) const override
void onContextMenu(const QPoint &point)
void selectNodeByState(statechartmodel::StatePtr state)
void openStateCPP(StateTreeNodePtr node)
void onStatechartFinished(int exitCode)
bool nodeIsFolder(StateTreeNodePtr node)
StateTreeNodePtr getSelectedNode()
QModelIndex index(int row, int column, const QModelIndex &parentIndex=QModelIndex()) const override
QVariant data(const QModelIndex &index, int role) const override
StatechartGroupPtr loadAndAddGroup(QString groupDefinitionFile)
bool nodeIsState(StateTreeNodePtr node)
QMimeData * mimeData(const QModelIndexList &indexes) const override
bool nodeIsGroup(StateTreeNodePtr node)
void removeState(StateTreeNodePtr stateNode)
StateTreeNodePtr child(int row)
static bool CheckNodeName(QString name)
StateTreeNodePtr getParent() const
#define ARMARX_CHECK_EXPRESSION(expression)
This macro evaluates the expression and if it turns out to be false it will throw an ExpressionExcept...
#define ARMARX_CHECK_GREATER_EQUAL(lhs, rhs)
This macro evaluates whether lhs is greater or equal (>=) rhs and if it turns out to be false it will...
#define ARMARX_INFO
The normal logging level.
#define ARMARX_WARNING_S
The logging level for unexpected behaviour, but not a serious problem.
::IceInternal::Handle<::Ice::Communicator > CommunicatorPtr
std::string toUtf8(QString const &qstring)
std::shared_ptr< State > StatePtr
std::shared_ptr< StateInstance > StateInstancePtr
std::shared_ptr< Event > EventPtr
QList< EventPtr > EventList
This file offers overloads of toIce() and fromIce() functions for STL container types.
std::shared_ptr< StatechartProfiles > StatechartProfilesPtr
std::shared_ptr< StatechartGroup > StatechartGroupPtr
std::shared_ptr< VariantInfo > VariantInfoPtr
std::shared_ptr< StateTreeModel > StateTreeModelPtr
std::shared_ptr< class StatechartProfile > StatechartProfilePtr
std::shared_ptr< StateTreeNode > StateTreeNodePtr
std::shared_ptr< ArmarXPackageToolInterface > ArmarXPackageToolInterfacePtr
StateCreationDialog(QWidget *parent=0, Qt::WindowFlags flags=0)
QDialogButtonBox * buttonBox