35#include <ArmarXGui/gui-plugins/StatechartEditorPlugin/view/dialogs/ui_CloneGroupDialog.h>
46 packageTool(packageTool),
48 groupCloner(groupCloner),
49 validGroupNameRegExp(
"([a-zA-Z][a-zA-Z0-9]*)"),
50 colorGreen(QColor::fromRgb(120, 255, 120)),
51 colorRed(QColor::fromRgb(255, 120, 120)),
52 colorYellow(QColor::fromRgb(255, 200, 0)),
53 alreadyChecking(false)
57 connect(ui->btnSelectPackageFolder, SIGNAL(clicked()),
this, SLOT(
selectPackagePath()));
58 connect(ui->editPackagePath,
59 SIGNAL(textChanged(QString)),
62 connect(ui->editGroupPrefix,
63 SIGNAL(textChanged(QString)),
66 connect(ui->groupsWidget,
67 SIGNAL(itemChanged(QTableWidgetItem*)),
70 connect(ui->checkBoxCloneRobotSkillTemplates,
71 SIGNAL(toggled(
bool)),
75 ui->editGroupPrefix->setEnabled(
false);
76 ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(
false);
78 ui->editGroupPrefix->setValidator(
new QRegExpValidator(validGroupNameRegExp,
this));
80 timer =
new QTimer(
this);
82 timer->setSingleShot(
true);
100 return QString::fromUtf8(path.filename().c_str());
106 std::filesystem::path path = ui->editPackagePath->text().toUtf8().data();
107 std::filesystem::path cleanPath = path;
111 cleanPath = std::filesystem::canonical(path);
117 if (*cleanPath.string().rbegin() ==
'/' || *cleanPath.string().rbegin() ==
'\\')
119 cleanPath = cleanPath.remove_filename();
123 return QString::fromUtf8(cleanPath.c_str());
144 QVector<QPair<StatechartGroupPtr, QString>>
147 QVector<QPair<StatechartGroupPtr, QString>> result;
149 if (ui->groupsWidget->rowCount() == 0 || ui->groupsWidget->columnCount() < 2)
154 for (
const auto& g : groupsToClone)
156 for (
int i = 0; i < ui->groupsWidget->rowCount(); ++i)
158 const auto oldName = ui->groupsWidget->item(i, 0)->data(Qt::UserRole).toString();
160 if (oldName == g->getName())
162 const auto newName = ui->groupsWidget->item(i, 1)->text();
164 <<
"oldName == newName of group " << g->getName();
165 result.push_back({g, newName});
184 const int c = item->column();
186 if (
c == 0 || ui->groupsWidget->columnCount() < 2)
198 alreadyChecking =
true;
200 bool hasNameCollisions =
false;
202 for (
int i = 0; i < ui->groupsWidget->rowCount(); ++i)
204 const auto& itemTest = ui->groupsWidget->item(i, 1);
206 if (!itemTest || (!itemTest->flags().testFlag(Qt::ItemIsEditable)))
211 bool collision =
false;
213 for (
int j = 0; j < ui->groupsWidget->rowCount() && !collision; ++j)
215 const auto& itemL = ui->groupsWidget->item(j, 0);
216 const auto& itemR = ui->groupsWidget->item(j, 1);
218 collision |= itemL && itemTest->text() == itemL->text();
219 collision |= itemR && (i != j) && itemTest->text() == itemR->text();
222 itemTest->setBackgroundColor(collision ? colorRed : colorGreen);
223 hasNameCollisions |= collision;
226 bool validName = validGroupNameRegExp.exactMatch(item->text());
227 item->setBackgroundColor(!validName ? colorRed : item->backgroundColor());
229 ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(validName && !hasNameCollisions);
230 alreadyChecking =
false;
242 groupPrefix = prefix;
253 CloneGroupDialog::buildGroupList()
255 if (groupPrefix.size() == 0)
257 ui->groupsWidget->clear();
258 ui->groupsWidget->setColumnCount(0);
259 ui->groupsWidget->setRowCount(0);
262 updateGroupDependencies();
264 ui->buttonBox->button(QDialogButtonBox::Ok)
265 ->setEnabled(!deps.empty() && !groupsToClone.empty() && groupPrefix.size() != 0);
267 if (deps.empty() || groupPrefix.size() == 0)
272 ui->groupsWidget->clear();
273 ui->groupsWidget->setRowCount(deps.size());
274 ui->groupsWidget->setColumnCount(2);
275 ui->groupsWidget->horizontalHeader()->setResizeMode(QHeaderView::Stretch);
276 ui->groupsWidget->setHorizontalHeaderLabels(
277 {
"Original StatechartGroup",
"Cloned StatechartGroup"});
279 for (
int i = 0; i < deps.size(); ++i)
281 const auto& g = deps[i];
283 QTableWidgetItem* item =
284 new QTableWidgetItem(g->getName() +
" [" + g->getPackageName() +
"]");
285 item->setData(Qt::UserRole, g->getName());
286 item->setFlags(item->flags() ^ Qt::ItemIsEditable);
287 QTableWidgetItem* renamed =
new QTableWidgetItem(groupPrefix + g->getName());
289 bool alreadyCloned = std::find_if(groupsToClone.constBegin(),
290 groupsToClone.constEnd(),
292 return g->getGroupPath() == dep->getGroupPath();
293 }) == groupsToClone.constEnd();
297 item->setBackgroundColor(colorGreen);
298 renamed->setBackgroundColor(colorGreen);
302 item->setBackgroundColor(colorYellow);
303 renamed->setBackgroundColor(colorYellow);
304 renamed->setFlags(renamed->flags() ^ Qt::ItemIsEditable);
306 if (
auto newGroupName = mapping.queryMappedGroupName(g->getName()))
308 renamed->setText(*newGroupName);
312 renamed->setText(
"<Error: Something went terribly wrong>");
313 renamed->setBackgroundColor(colorRed);
317 ui->groupsWidget->setItem(i, 0, item);
318 ui->groupsWidget->setItem(i, 1, renamed);
321 if (groupsToClone.empty())
323 ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(
false);
330 QFileDialog selectFolder(
this,
"Select Target Package Root Folder");
332 urls << QUrl::fromLocalFile(
333 QDesktopServices::storageLocation(QDesktopServices::HomeLocation))
334 << QUrl::fromLocalFile(
335 QDesktopServices::storageLocation(QDesktopServices::DesktopLocation));
342 selectFolder.setSidebarUrls(urls);
344 selectFolder.setOption(QFileDialog::ReadOnly,
true);
345 selectFolder.setOption(QFileDialog::HideNameFilterDetails,
false);
346 selectFolder.setFileMode(QFileDialog::Directory);
348 if (selectFolder.exec() == QDialog::Accepted)
350 ui->editPackagePath->setText(*selectFolder.selectedFiles().begin());
355 CloneGroupDialog::updateGroupDependencies()
357 deps = groupCloner->getGroupDependencies(group,
true);
358 if (!ui->checkBoxCloneRobotSkillTemplates->isChecked())
360 auto it = std::remove_if(deps.begin(),
363 { return g->getPackageName() ==
"RobotSkillTemplates"; });
364 deps.erase(it, deps.end());
367 QVector<StatechartGroupPtr> existingDeps = groupCloner->getMappedGroups(mapping);
369 groupsToClone.clear();
371 for (
const auto& g : deps)
373 bool alreadyCloned = std::find_if(existingDeps.constBegin(),
374 existingDeps.constEnd(),
376 return g->getGroupPath() == dep->getGroupPath();
377 }) != existingDeps.constEnd();
381 groupsToClone.push_back(g);
389 if (packageTool->checkPackagePath(ui->editPackagePath->text().toStdString()))
391 ui->labelPackageError->setText(
"Package path is valid.");
392 QPalette p(ui->labelPackageError->palette());
393 p.setColor(ui->labelPackageError->backgroundRole(), colorGreen);
395 ui->labelPackageError->setPalette(p);
405 updateGroupDependencies();
407 ui->editGroupPrefix->setEnabled(
true);
409 QString prefixSuggestion;
411 if (!mapping.groupMappings.empty())
413 const auto gm = *mapping.groupMappings.begin();
414 prefixSuggestion = QString(gm.newGroupName).replace(gm.groupName,
"");
417 ui->editGroupPrefix->setText(prefixSuggestion);
421 ui->labelPackageError->setText(
"Package path is not valid!");
422 QPalette p(ui->labelPackageError->palette());
423 p.setColor(ui->labelPackageError->backgroundRole(), colorRed);
424 ui->labelPackageError->setPalette(p);
425 ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(
false);
static std::string cleanPath(const std::string &filepathStr)
static std::string getHomePath()
GroupClonerPtr getGroupCloner() const
StatechartGroupMapping getStatechartGroupMapping() const
QString getPackagePath() const
ArmarXPackageToolInterfacePtr getPackageTool() const
void verifyName(QTableWidgetItem *item)
void requestCheckPackagePath(QString path)
void cloneRobotSkillTemplatesToggled(bool state)
QString getGroupPrefix() const
void requestPrefixUpdate(QString prefix)
CloneGroupDialog(ArmarXPackageToolInterfacePtr packageTool, StatechartGroupPtr group, GroupClonerPtr groupCloner, QWidget *parent=0)
~CloneGroupDialog() override
QString getPackageName() const
StatechartGroupPtr getGroup() const
QVector< QPair< StatechartGroupPtr, QString > > getGroupsToClone() const
#define ARMARX_CHECK_EXPRESSION(expression)
This macro evaluates the expression and if it turns out to be false it will throw an ExpressionExcept...
This file offers overloads of toIce() and fromIce() functions for STL container types.
std::shared_ptr< StatechartGroup > StatechartGroupPtr
std::shared_ptr< GroupCloner > GroupClonerPtr
std::shared_ptr< ArmarXPackageToolInterface > ArmarXPackageToolInterfacePtr