28 #include <QDialogButtonBox>
31 #include <QMessageBox>
32 #include <QPushButton>
33 #include <QTableWidgetItem>
34 #include <QToolButton>
35 #include <QVBoxLayout>
39 #include <QInputDialog>
41 #include <QStyledItemDelegate>
42 #include <QPropertyAnimation>
57 #include <Ice/ObjectFactory.h>
75 defaultValueState(Qt::Unchecked)
79 setlocale(LC_ALL,
"C");
82 qRegisterMetaType<statechartmodel::StateParameterMap>(
"statechartmodel::StateParameterMap");
88 if (params.size() == 0)
99 setItemDelegateForColumn(
eKey, &delegate);
118 icon.addFile(QString::fromUtf8(
":/icons/help-about.ico"), QSize(), QIcon::Normal,
QIcon::Off);
119 showHelpButton->setIcon(icon);
120 showHelpButton->setToolTip(
"Show or edit help to this parameter.");
121 connect(showHelpButton, SIGNAL(clicked()),
this, SLOT(
showHelpDialog()));
126 QAction* addInputToParentAction =
new QAction(showHelpButton);
128 icon.addFile(QString::fromUtf8(
":/icons/add.png"), QSize(), QIcon::Normal,
QIcon::Off);
129 addInputToParentAction->setIcon(icon);
130 addInputToParentAction->setIconVisibleInMenu(
true);
131 addInputToParentAction->setText(
"Add to parent's input");
132 addInputToParentAction->setToolTip(
"Add this parameter to parent's input. This applies immediatly.");
133 addInputToParentAction->setData(row);
134 connect(addInputToParentAction, SIGNAL(triggered()),
this, SLOT(
addInputToParent()));
136 QMenu* subMenu =
new QMenu(showHelpButton);
137 subMenu->addAction(addInputToParentAction);
138 showHelpButton->setMenu(subMenu);
146 QToolButton* showHelpButton = qobject_cast<QToolButton*>(cellWidget(row,
eAdditionalButtons));
158 showHelpButton->setProperty(
"MarkdownDocText", pm->description);
159 QColor color = pm->description.isEmpty() ? QColor {250, 0, 0}:
162 QPalette pal = showHelpButton->palette();
163 showHelpButton->setAutoFillBackground(
true);
164 QPropertyAnimation* animation =
new QPropertyAnimation(showHelpButton,
"color",
this);
165 animation->setDuration(3000);
169 animation->setKeyValueAt(t, color);
171 animation->setKeyValueAt(t, pal.color(QPalette::Button));
174 animation->setKeyValueAt(1, pal.color(QPalette::Button));
175 animation->setEasingCurve(QEasingCurve::InOutQuad);
189 QDialog editDefaultDialog;
190 editDefaultDialog.setWindowTitle(
"Statechart Parameter Documentation Editor");
191 editDefaultDialog.resize(QSize(600, 400));
195 QVBoxLayout* layout =
new QVBoxLayout;
196 layout->addWidget(dialogTextEdit);
197 QDialogButtonBox* buttonBox =
new QDialogButtonBox(dialogTextEdit);
198 buttonBox->setOrientation(Qt::Horizontal);
199 buttonBox->setStandardButtons(QDialogButtonBox::Cancel | QDialogButtonBox::Ok);
200 layout->addWidget(buttonBox);
201 editDefaultDialog.setLayout(layout);
203 connect(buttonBox, SIGNAL(accepted()), &editDefaultDialog, SLOT(accept()));
204 connect(buttonBox, SIGNAL(rejected()), &editDefaultDialog, SLOT(reject()));
206 if (editDefaultDialog.exec() == QDialog::Accepted)
208 sender()->setProperty(
"MarkdownDocText", dialogTextEdit->
toPlainText());
217 QAction* action = qobject_cast<QAction*>(sender());
218 row = action->data().toInt();
219 QString keyName = item(row,
eKey)->text();
221 auto parent =
state->getParent();
224 auto inputAndLocal = parent->getInputAndLocalParameters();
226 if (inputAndLocal.count(keyName) > 0)
228 QMessageBox::warning(
this,
"State Editing Error",
"The key '" + keyName +
"' already exists");
234 state->getParent()->setInputParameters(
input);
239 auto profileNames = getRelevantProfiles();
242 setColumnCount(columnCount);
250 for (
int i = 0; i < profileNames.size(); ++i)
253 setHorizontalHeaderItem(
eEditableValue + i,
new QTableWidgetItem(profileNames[i]));
265 this->keyBlackList = keyBlackList;
270 QSet<QString> result;
272 for (
int row = 0; row < rowCount(); row++)
274 if (item(row,
eKey) && !item(row,
eKey)->text().isEmpty())
276 result.insert(item(row,
eKey)->text());
286 for (
int i = 0; i < rowCount(); ++i)
295 if (
getKey(row).isEmpty())
306 p->description = descriptionWidget->property(
"MarkdownDocText").toString();
312 for (
const auto& profileName : getRelevantProfiles())
314 p->profileDefaultValues[profileName] = {variants[profileName], jsonValues[profileName]};
324 for (
int row = 0; row < rowCount(); ++row)
328 result[
getKey(row)] = param;
348 if (row >= rowCount() || row < 0)
350 throw LocalException(
"row index out of range: ") << row;
353 QMap<QString, QString> result;
355 auto profileNames = getRelevantProfiles();
357 for (
int i = 0; i < profileNames.size(); ++i)
359 auto widget = qobject_cast<ProfileDefaultValueEditWidget*>(cellWidget(row,
eEditableValue + i));
361 if (
auto value = widget->getValueAsString())
363 result[profileNames[i]] = *
value;
374 for (
int i = 0; i < rowCount(); i++)
383 if (row >= rowCount() || row < 0)
385 throw LocalException(
"row index out of range: ") << row;
388 QMap<QString, QString> result;
390 auto profileNames = getRelevantProfiles();
392 for (
int i = 0; i < profileNames.size(); ++i)
394 auto widget = qobject_cast<ProfileDefaultValueEditWidget*>(cellWidget(row,
eEditableValue + i));
396 if (
auto value = widget->getValueAsJson())
398 result[profileNames[i]] = *
value;
408 if (row >= rowCount() || row < 0)
410 throw LocalException(
"row index out of range: ") << row;
413 QMap<QString, VariantContainerBasePtr> result;
415 auto profileNames = getRelevantProfiles();
417 for (
int i = 0; i < profileNames.size(); ++i)
419 auto widget = qobject_cast<ProfileDefaultValueEditWidget*>(cellWidget(row,
eEditableValue + i));
420 result[profileNames[i]] = widget->getVariantContainer();
428 if (row >= rowCount())
430 throw LocalException(
"row index out of range: ") << row;
433 if (!item(row,
eKey))
438 return item(row,
eKey)->text();
443 if (row >= rowCount())
445 throw LocalException(
"row index out of range: ") << row;
448 QComboBox* CBvalueType = qobject_cast<QComboBox*>(cellWidget(row, 1));
455 QString type = getBaseNameFromHumanName(CBvalueType->currentText());
470 for (
int i = 0; i < rowCount(); i++)
481 throw LocalException(
"could not find key ") << key.toStdString();
489 if (row >= rowCount())
491 throw LocalException(
"row index out of range: ") << row;
494 QComboBox* cbOptional = qobject_cast<QComboBox*>(cellWidget(row,
eOptional));
495 return cbOptional->currentText() ==
"true";
502 int row = rowCount();
504 setItem(row,
eKey,
new QTableWidgetItem());
510 QComboBox* valueTypebox =
new QComboBox;
511 valueTypebox->setEditable(
true);
514 setCellWidget(row,
eType, valueTypebox);
515 QStringList types = addVariantTypesToComboBox(valueTypebox);
517 fullCompleter->setCompletionMode(QCompleter::PopupCompletion);
518 fullCompleter->setCaseSensitivity(Qt::CaseInsensitive);
519 valueTypebox->setCompleter(fullCompleter);
520 valueTypebox->setEditText(
"string");
521 connect(valueTypebox, SIGNAL(editTextChanged(QString)),
this, SLOT(
typeCbChanged(QString)));
522 connect(valueTypebox->lineEdit(), SIGNAL(textEdited(QString)), fullCompleter, SLOT(setCompletionInfix(QString)));
524 QComboBox* cbOptional;
525 cbOptional =
new QComboBox();
526 cbOptional->addItems(QString(
"true;false").
split(
";"));
527 cbOptional->setCurrentIndex(1);
528 setCellWidget(row,
eOptional, cbOptional);
532 icon.addFile(QString::fromUtf8(
":/icons/dialog-close.ico"), QSize(), QIcon::Normal,
QIcon::Off);
533 QToolButton* deleteButton =
new QToolButton(
this);
534 deleteButton->setIcon(icon);
535 deleteButton->setToolTip(
"Add this parameter to parent's input");
536 deleteButton->setToolTip(
"Delete this row");
538 connect(deleteButton, SIGNAL(clicked()),
this, SLOT(
deleteRow()));
540 auto profileNames = getRelevantProfiles();
542 for (
int i = 0; i < profileNames.size(); ++i)
557 item(row,
eKey)->setText(key);
559 QComboBox* valueTypeBox = qobject_cast<QComboBox*>(cellWidget(row,
eType));
561 valueTypeBox->setEditText(getHumanNameFromBaseName(variantIdStr));
563 QComboBox* optionalBox = qobject_cast<QComboBox*>(cellWidget(row,
eOptional));
564 optionalBox->setCurrentIndex(optional ? 0 : 1);
566 for (
int i = 0; i <
values.size(); ++i)
577 QWidget* wid = qobject_cast<QWidget*>(sender());
583 int row = rowAt(wid->pos().y());
585 QComboBox* typeBox = qobject_cast<QComboBox*>(cellWidget(row,
eType));
586 QString typeStr = getBaseNameFromHumanName(typeBox->currentText());
592 if (typeStr != valueWidget->getType())
595 setCellWidget(row, i, newWidget);
608 QWidget* wid = qobject_cast<QWidget*>(sender());
609 QModelIndex mIndex = indexAt(wid->pos());
620 connectUserEditSlots();
648 auto keyitem = item(row,
eKey);
652 if ((keyBlackList.find(keyitem->text()) != keyBlackList.end() || findItems(keyitem->text(), Qt::MatchExactly).size() > 1))
654 keyitem->setText(item(row,
eKey)->text() +
"_2");
655 ARMARX_WARNING_S <<
"Keys must be unique (input and local parameters share the same key pool)";
660 if (row >= rowCount() - 1 && item(rowCount() - 1, 0) && !item(rowCount() - 1, 0)->text().isEmpty())
668 for (
int row = 0; row < rowCount(); row++)
670 QComboBox* valueTypeBox = qobject_cast<QComboBox*>(cellWidget(row,
eType));
671 addVariantTypesToComboBox(valueTypeBox);
677 void StatechartEditorParameterEditor::connectUserEditSlots()
679 connect(
this, SIGNAL(cellEntered(
int,
int)),
this, SLOT(
checkAndUpdateRowCount(
int,
int)), Qt::UniqueConnection);
680 connect(
this, SIGNAL(cellPressed(
int,
int)),
this, SLOT(
checkAndUpdateRowCount(
int,
int)), Qt::UniqueConnection);
681 connect(
this, SIGNAL(cellChanged(
int,
int)),
this, SLOT(
checkAndUpdateRowCount(
int,
int)), Qt::UniqueConnection);
684 QStringList StatechartEditorParameterEditor::addVariantTypesToComboBox(QComboBox* combo)
688 return QStringList();
696 for (std::pair<VariantTypeId, std::string> pair : types)
698 QString typeName = tr(pair.second.c_str());
701 if (typeName.contains(
"Invalid"))
706 list.append(getHumanNameFromBaseName(typeName));
713 std::vector<VariantContainerType> containers;
717 for (VariantContainerType
c : containers)
719 for (
auto it : types)
721 QString typeName = tr(it.second.c_str());
724 if (typeName.contains(
"Invalid"))
730 typeName = QString::fromStdString(typeStr);
731 list.append(getHumanNameFromBaseName(typeName));
739 qSort(
list.begin(),
list.end(), compareVariantNames);
740 combo->addItems(
list);
744 QString StatechartEditorParameterEditor::getHumanNameFromBaseName(QString variantBaseTypeName)
const
748 return variantBaseTypeName;
751 std::string humanName = variantInfo->getNestedHumanNameFromBaseName(variantBaseTypeName.toUtf8().data());
753 if (humanName.empty())
755 return variantBaseTypeName;
758 return QString::fromUtf8(humanName.c_str());
761 QString StatechartEditorParameterEditor::getBaseNameFromHumanName(QString humanName)
const
768 std::string variantBaseTypeName = variantInfo->getNestedBaseNameFromHumanName(humanName.toUtf8().data());
770 if (variantBaseTypeName.empty())
775 return QString::fromUtf8(variantBaseTypeName.c_str());
778 bool StatechartEditorParameterEditor::compareVariantNames(
const QString&
a,
const QString& b)
783 pa =
a.contains(
"(");
784 pb = b.contains(
"(");
792 pa =
a.contains(
":");
793 pb = b.contains(
":");
801 int ia =
a.indexOf(
"(");
802 int ib = b.indexOf(
"(");
803 pa = ia > 0 &&
a.count() > ia + 1 &&
a[ia + 1].isLower();
804 pb = ib > 0 && b.count() > ib + 1 && b[ib + 1].isLower();
805 if (pa != pb &&
a.left(ia) == b.left(ib))
811 pa =
a.count() > 0 &&
a[0].isLower();
812 pb = b.count() > 0 && b[0].isLower();
819 return a.compare(b) < 0;
823 return defaultValueState;
828 defaultValueState =
value;
833 const auto& relevantProfiles = getRelevantProfiles();
835 for (
int i = 0; i < relevantProfiles.size(); ++i)
843 QStringList headerLabels {
"Key",
"Type",
"Optional",
"Del"};
844 setColumnWidth(
eKey, 180);
845 setColumnWidth(
eType, 225);
850 auto profileNames = getRelevantProfiles();
853 for (
int i = 0; i < profileNames.size(); ++i)
855 setColumnWidth(col + i, 200);
856 headerLabels.push_back(profileNames[i]);
859 setHorizontalHeaderLabels(headerLabels);
871 QWidget* tempW =
new QLabel(
"mylabel",
this);
872 tempW->deleteLater();
875 disconnect(
this, SIGNAL(cellEntered(
int,
int)));
876 disconnect(
this, SIGNAL(cellPressed(
int,
int)));
877 disconnect(
this, SIGNAL(cellChanged(
int,
int)));
879 auto relevantProfiles = getRelevantProfiles();
881 for (
const auto& entry : map.toStdMap())
883 const QString& name = entry.first;
887 QVector<QString> jsonStrs;
888 QString typeStr = param->type;
890 for (
const QString& profile : relevantProfiles)
892 QString jsonStr = param->profileDefaultValues[profile].second;
893 jsonStrs.push_back(jsonStr);
901 connectUserEditSlots();
906 QVector<QString> StatechartEditorParameterEditor::getRelevantProfiles()
const
910 return QVector<QString>();
913 QVector<QString> result {QString::fromUtf8(currentProfile->getName().c_str())};
914 auto profile = currentProfile;
916 while ((profile = profile->getParent()))
918 result.push_back(QString::fromUtf8(profile->getName().c_str()));
924 QWidget* StatechartEditorParameterEditor::LineEditDelegate::createEditor(QWidget* parent,
const QStyleOptionViewItem&
option,
const QModelIndex&
index)
const
926 QLineEdit* lineEdit =
new QLineEdit(parent);
927 QString regExpStr(
"(|([a-z_]{1})([a-z_0-9]*))");
928 QRegExp reg(regExpStr, Qt::CaseInsensitive);
929 lineEdit->setValidator(
new QRegExpValidator(reg, lineEdit));
938 QString val = QString(
"background-color: rgb(%1, %2, %3);").arg(
color.red()).arg(
color.green()).arg(
color.blue());