30 #include <QGridLayout>
32 #include <QSortFilterProxyModel>
39 connect(
ui->pushButtonLoadLib, SIGNAL(released()),
this, SLOT(loadLibClicked()));
40 connect(
ui->comboBoxPackage, SIGNAL(currentIndexChanged(QString)),
this, SLOT(packageEditChanged()));
41 connect(
ui->comboBoxPackage, SIGNAL(editTextChanged(QString)),
this, SLOT(packageEditChanged()));
42 ui->comboBoxPackage->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
43 ui->comboBoxPackage->setFixedWidth(300);
47 using namespace std::filesystem;
48 std::string homeDir = QDir::homePath().toStdString();
49 path p = path {homeDir} /
".cmake" /
"packages";
52 for (
const path& entry : directory_iterator(p))
54 const std::string pkg = entry.filename().string();
57 ui->comboBoxPackage->addItem(QString::fromStdString(pkg));
61 QSortFilterProxyModel* proxy =
new QSortFilterProxyModel(
ui->comboBoxPackage);
62 proxy->setSourceModel(
ui->comboBoxPackage->model());
65 ui->comboBoxPackage->model()->setParent(proxy);
66 ui->comboBoxPackage->setModel(proxy);
67 ui->comboBoxPackage->model()->sort(0);
71 ui->comboBoxPackage->setEditText(
"");
74 ui->treeWidget->setColumnCount(2);
76 QTreeWidgetItem* head =
ui->treeWidget->headerItem();
77 head->setText(0,
"Class");
79 head->setToolTip(0,
"Controller class name");
80 ui->treeWidget->header()->setResizeMode(0, QHeaderView::Fixed);
81 ui->treeWidget->header()->setResizeMode(1, QHeaderView::Fixed);
93 std::unique_lock<std::recursive_timed_mutex> guard {
mutex};
100 auto data = ru->getNJointControllerClassDescription(name);
102 nJointControllerClassDescriptions[
data.className] = std::move(
data);
105 QMetaObject::invokeMethod(
this,
"updateContent", Qt::QueuedConnection);
112 if (oldName == createdName || force)
114 ++defaultControllerName;
116 for (
auto& pair : entries)
118 pair.second->updateDefaultName(oldName, newName);
125 return QString::number(defaultControllerName);
130 ui->lineEditLibrary->setText(settings->value(
"classLoadLineEditLib",
"").toString());
131 ui->comboBoxPackage->lineEdit()->setText(settings->value(
"classLoadComboBoxPkg",
"").toString());
132 ui->comboBoxLibrary->lineEdit()->setText(settings->value(
"classLoadComboBoxLib",
"").toString());
137 settings->setValue(
"classLoadLineEditLib",
ui->lineEditLibrary->text());
138 settings->setValue(
"classLoadComboBoxPkg",
ui->comboBoxPackage->currentText());
139 settings->setValue(
"classLoadComboBoxLib",
ui->comboBoxLibrary->currentText());
145 nJointControllerClassDescriptions.clear();
150 for (
const auto& pair : nJointControllerClassDescriptions)
154 nJointControllerClassDescriptions.clear();
159 auto temp =
robotUnit->getNJointControllerClassDescriptions();
161 std::unique_lock<std::recursive_timed_mutex> guard {
mutex};
162 for (NJointControllerClassDescription& ds : temp)
164 nJointControllerClassDescriptions[ds.className] = std::move(ds);
171 if (nJointControllerClassDescriptions.empty())
175 add(nJointControllerClassDescriptions.begin()->second);
176 nJointControllerClassDescriptions.erase(nJointControllerClassDescriptions.begin());
180 void NJointControllerClassesWidget::filterUpdated()
182 for (
auto& entry : entries)
185 if (! filterNameActive->isChecked() && !filterRemoteCreationActive->isChecked())
190 const bool combineOr = (filterCombination->currentText() ==
"Or");
191 bool showName = !combineOr;
192 bool showRemote = !combineOr;
194 if (filterNameActive->isChecked())
196 showName = (item->
matchName(filterName->text()) != filterNameInverted->isChecked());
198 if (filterRemoteCreationActive->isChecked())
202 showRemote = (filterRemoteCreation->currentText() !=
"Without");
206 showRemote = (filterRemoteCreation->currentText() !=
"With");
220 void NJointControllerClassesWidget::add(
const NJointControllerClassDescription& desc)
222 std::unique_lock<std::recursive_timed_mutex> guard {
mutex};
223 if (entries.count(desc.className))
227 entries[desc.className] =
new NJointControllerClassesWidgetEntry(*
this, *(
ui->treeWidget), desc,
robotUnit);
230 void NJointControllerClassesWidget::addFilter()
232 QTreeWidgetItem* filterHeader =
new QTreeWidgetItem;
233 ui->treeWidget->addTopLevelItem(filterHeader);
234 filterHeader->setText(0,
"Filter");
236 QTreeWidgetItem* filter =
new QTreeWidgetItem;
237 filterHeader->addChild(filter);
238 filter->setFirstColumnSpanned(
true);
239 QWidget* w =
new QWidget;
240 QGridLayout* l =
new QGridLayout;
242 l->setContentsMargins(0, 0, 0, 0);
243 l->addItem(
new QSpacerItem {0, 0, QSizePolicy::MinimumExpanding}, 0, 3);
244 l->addWidget(
new QLabel {
"Combine filters with"}, 0, 0, 1, 1);
245 filterCombination =
new QComboBox;
246 filterCombination->addItem(
"Or");
247 filterCombination->addItem(
"And");
248 l->addWidget(filterCombination, 0, 1, 1, 1);
250 filterNameActive =
new QCheckBox;
251 filterNameActive->setText(
"Filter by name");
252 l->addWidget(filterNameActive, 1, 0, 1, 1);
254 filterName =
new QLineEdit;
255 l->addWidget(filterName, 1, 1, 1, 1);
257 filterNameInverted =
new QCheckBox;
258 filterNameInverted->setText(
"Invert filter");
259 l->addWidget(filterNameInverted, 1, 2, 1, 1);
260 connect(filterNameActive, SIGNAL(toggled(
bool)), filterName, SLOT(setEnabled(
bool)));
261 connect(filterNameActive, SIGNAL(toggled(
bool)), filterNameInverted, SLOT(setEnabled(
bool)));
262 filterName->setEnabled(
false);
263 filterNameInverted->setEnabled(
false);
265 filterRemoteCreationActive =
new QCheckBox;
266 filterRemoteCreationActive->setText(
"Filter by remote creation capabilities");
267 l->addWidget(filterRemoteCreationActive, 2, 0, 1, 1);
268 filterRemoteCreation =
new QComboBox;
269 filterRemoteCreation->addItem(
"Both");
270 filterRemoteCreation->addItem(
"With");
271 filterRemoteCreation->addItem(
"Without");
272 l->addWidget(filterRemoteCreation, 2, 1, 1, 1);
273 connect(filterRemoteCreationActive, SIGNAL(toggled(
bool)), filterRemoteCreation, SLOT(setEnabled(
bool)));
274 filterRemoteCreationActive->setEnabled(
false);
276 connect(filterCombination, SIGNAL(currentIndexChanged(QString)),
this, SLOT(filterUpdated()));
277 connect(filterNameActive, SIGNAL(clicked(
bool)),
this, SLOT(filterUpdated()));
278 connect(filterRemoteCreationActive, SIGNAL(clicked(
bool)),
this, SLOT(filterUpdated()));
279 connect(filterNameInverted, SIGNAL(clicked(
bool)),
this, SLOT(filterUpdated()));
280 connect(filterName, SIGNAL(textChanged(QString)),
this, SLOT(filterUpdated()));
281 connect(filterRemoteCreation, SIGNAL(currentIndexChanged(
int)),
this, SLOT(filterUpdated()));
283 filterNameActive->setChecked(
false);
284 filterRemoteCreationActive->setChecked(
false);
286 ui->treeWidget->setItemWidget(filter, 0, w);
291 QTreeWidget& treeWidget,
292 const NJointControllerClassDescription& desc,
296 className {desc.className},
297 classNameQStr {QString::fromStdString(className)},
298 robotUnit {robotUnit},
301 header =
new QTreeWidgetItem {{QString::fromStdString(desc.className)}};
302 treeWidget.addTopLevelItem(header);
303 treeWidget.resizeColumnToContents(0);
304 QWidget* headerW =
new QWidget;
305 headerW->setLayout(
new QHBoxLayout);
306 headerW->layout()->setContentsMargins(0, 0, 0, 0);
307 headerW->layout()->addItem(
new QSpacerItem {0, 0, QSizePolicy::MinimumExpanding});
308 if (desc.configDescription)
312 nameEdit =
new QLineEdit;
313 nameEdit->setText(parent.getDefaultName());
314 nameEdit->setToolTip(
"The instance name for the created controller instance");
315 headerW->layout()->addWidget(
new QLabel {
"Controller name"});
316 headerW->layout()->addWidget(nameEdit);
317 QPushButton* button =
new QPushButton {
"Create"};
318 headerW->layout()->addWidget(button);
319 button->setToolTip(
"Create a new controller instance of this class");
320 connect(button, &QPushButton::clicked,
this, &NJointControllerClassesWidgetEntry::createCtrl);
321 connect(nameEdit, &QLineEdit::returnPressed,
this, &NJointControllerClassesWidgetEntry::createCtrl);
325 QTreeWidgetItem* child =
new QTreeWidgetItem;
326 header->addChild(child);
327 child->setFirstColumnSpanned(
true);
328 QWidget* compressWid =
new QWidget;
329 QHBoxLayout* compressLay =
new QHBoxLayout;
330 compressWid->setLayout(compressLay);
331 compressLay->setContentsMargins(0, 0, 0, 0);
333 creator->layout()->setContentsMargins(0, 0, 0, 0);
334 compressLay->addWidget(creator);
335 compressLay->addItem(
new QSpacerItem {0, 0, QSizePolicy::MinimumExpanding});
336 treeWidget.setItemWidget(child, 0, compressWid);
342 QLineEdit* dummy =
new QLineEdit;
343 dummy->setFixedWidth(0);
344 dummy->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum);
345 headerW->layout()->addWidget(dummy);
347 headerW->layout()->addWidget(
new QLabel {
"No remote creation allowed."});
349 treeWidget.setItemWidget(header, 1, headerW);
375 void NJointControllerClassesWidgetEntry::createCtrl()
377 const auto instanceName =
nameEdit->text().toStdString();
379 if (variants.empty())
381 ARMARX_INFO <<
"creating " << instanceName <<
" of class " <<
className <<
" with no parameters\n";
385 std::stringstream ss;
386 ss <<
"creating " << instanceName <<
" of class " <<
className <<
" with parameters:\n";
387 for (
const auto& pair : variants)
392 if (pair.second->data)
394 ss <<
" '" << pair.first <<
"' of type " << pair.second->data->ice_id() <<
"\n";
398 ss <<
" '" << pair.first <<
"' nullptr data \n";
403 ss <<
" '" << pair.first <<
"' nullptr\n";
408 robotUnit->createNJointControllerFromVariantConfig(
className, instanceName, variants);
412 void NJointControllerClassesWidget::packageEditChanged()
414 auto package = ui->comboBoxPackage->currentText();
415 if (package.isEmpty())
417 selectLibMode = SelectLibsMode::LineEdit;
418 ui->lineEditLibrary->setVisible(
true);
419 ui->comboBoxLibrary->setVisible(
false);
420 ui->pushButtonLoadLib->setEnabled(
true);
421 ui->labelPackageFound->setPixmap(QPixmap(
":/icons/Blank.svg").scaled(16, 16));
422 ui->labelPackageFound->setToolTip(
"");
426 libShortNameToFileName.clear();
427 ui->comboBoxLibrary->clear();
429 selectLibMode = SelectLibsMode::ComboBox;
430 ui->lineEditLibrary->setVisible(
false);
431 ui->comboBoxLibrary->setVisible(
true);
432 CMakePackageFinder pFinder(package.toStdString());
433 if (pFinder.packageFound())
435 ui->pushButtonLoadLib->setEnabled(
true);
436 ui->labelPackageFound->setPixmap(QPixmap(
":/icons/user-online.svg").scaled(16, 16));
437 ui->labelPackageFound->setToolTip(
"Found Package");
439 for (
const std::string& lib :
Split(pFinder.getLibs(),
",; ",
true))
445 const auto libPrefix = lib.find(
"lib");
446 const auto libSubstrStart = libPrefix == lib.npos ? 0 : libPrefix + 3;
447 const auto libSuffix = lib.find(
".");
448 const auto libSubstrEnd = libSuffix - libSubstrStart;
449 std::string shortName = lib.substr(libSubstrStart, libSubstrEnd);
450 libShortNameToFileName[shortName] = lib;
451 ui->comboBoxLibrary->addItem(QString::fromStdString(shortName));
452 if (libidx == -1 && (lib.find(
"Controller") != lib.npos || lib.find(
"controller") != lib.npos))
454 libidx = libShortNameToFileName.size() - 1 ;
456 ui->comboBoxLibrary->setCurrentIndex(libidx);
461 ui->pushButtonLoadLib->setEnabled(
false);
462 ui->labelPackageFound->setPixmap(QPixmap(
":/icons/dialog-cancel-5.svg").scaled(16, 16));
463 ui->labelPackageFound->setToolTip(
"Cannot find Package");
468 void NJointControllerClassesWidget::loadLibClicked()
470 ARMARX_WARNING <<
"The functionality of dynamically loading libraries during runtime is no longer supported. Use"
471 "the component properties to load additional libraries.";