moveit2
The MoveIt Motion Planning Framework for ROS 2.
Loading...
Searching...
No Matches
controllers_widget.cpp
Go to the documentation of this file.
1/*********************************************************************
2 * Software License Agreement (BSD License)
3 *
4 * Copyright (c) 2018, Mohamad Ayman.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
17 * * The name of Mohamad Ayman may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
32 *********************************************************************/
33
34/* Author: Mohamad Ayman */
35
36// SA
39#include <moveit_msgs/msg/joint_limits.hpp>
40// Qt
41#include <QApplication>
42#include <QDoubleValidator>
43#include <QFormLayout>
44#include <QGroupBox>
45#include <QHBoxLayout>
46#include <QLabel>
47#include <QLineEdit>
48#include <QMessageBox>
49#include <QPushButton>
50#include <QScrollArea>
51#include <QStackedWidget>
52#include <QString>
53#include <QTableWidget>
54#include <QTreeWidget>
55#include <QTreeWidgetItem>
56#include <QVBoxLayout>
57
58#include <regex>
60
61namespace moveit_setup
62{
63namespace controllers
64{
65// ******************************************************************************************
66// Outer User Interface for MoveIt Configuration Assistant
67// ******************************************************************************************
69{
70 // Basic widget container
71 QVBoxLayout* layout = new QVBoxLayout();
72
73 layout->setAlignment(Qt::AlignTop);
74
75 // Title
76 setWindowTitle("Controller Configuration"); // title of window
77
78 // Top Header Area ------------------------------------------------
79 auto header = new HeaderWidget("Setup " + setup_step_->getName(), setup_step_->getInstructions(), this);
80 layout->addWidget(header);
81
82 // Tree Box ----------------------------------------------------------------------
84
85 // Joints edit widget
86 joints_widget_ = new DoubleListWidget(this, "Joint Collection", "Joint");
87 connect(joints_widget_, SIGNAL(cancelEditing()), this, SLOT(cancelEditing()));
88 connect(joints_widget_, SIGNAL(doneEditing()), this, SLOT(saveJointsScreen()));
89 connect(joints_widget_, SIGNAL(previewSelected(std::vector<std::string>)), this,
90 SLOT(previewSelectedJoints(std::vector<std::string>)));
91
92 // Joints Groups Widget
93 joint_groups_widget_ = new DoubleListWidget(this, "Group Joints Collection", "Group");
94 connect(joint_groups_widget_, SIGNAL(cancelEditing()), this, SLOT(cancelEditing()));
95 connect(joint_groups_widget_, SIGNAL(doneEditing()), this, SLOT(saveJointsGroupsScreen()));
96 connect(joint_groups_widget_, SIGNAL(previewSelected(std::vector<std::string>)), this,
97 SLOT(previewSelectedGroup(std::vector<std::string>)));
98
99 // Controller Edit Widget
100 controller_edit_widget_ = new ControllerEditWidget(this, setup_step_->getAdditionalControllerFields());
101 connect(controller_edit_widget_, SIGNAL(cancelEditing()), this, SLOT(cancelEditing()));
102 connect(controller_edit_widget_, SIGNAL(deleteController()), this, SLOT(deleteController()));
103 connect(controller_edit_widget_, SIGNAL(save()), this, SLOT(saveControllerScreenEdit()));
104 connect(controller_edit_widget_, SIGNAL(saveJoints()), this, SLOT(saveControllerScreenJoints()));
105 connect(controller_edit_widget_, SIGNAL(saveJointsGroups()), this, SLOT(saveControllerScreenGroups()));
106
107 // Combine into stack
108 stacked_widget_ = new QStackedWidget(this);
109 stacked_widget_->addWidget(controllers_tree_widget_); // screen index 0
110 stacked_widget_->addWidget(joints_widget_); // screen index 1
111 stacked_widget_->addWidget(controller_edit_widget_); // screen index 2
112 stacked_widget_->addWidget(joint_groups_widget_); // screen index 3
113 layout->addWidget(stacked_widget_);
114
115 setLayout(layout);
116}
117
118// ******************************************************************************************
119// Create the main tree view widget
120// ******************************************************************************************
122{
123 // Main widget
124 QWidget* content_widget = new QWidget(this);
125
126 // Basic widget container
127 QVBoxLayout* layout = new QVBoxLayout(this);
128
129 QHBoxLayout* upper_controls_layout = new QHBoxLayout();
130
131 // Add default controller
132 QPushButton* btn_add_default = new QPushButton(setup_step_->getButtonText().c_str(), this);
133 btn_add_default->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
134 btn_add_default->setMaximumWidth(600);
135 connect(btn_add_default, SIGNAL(clicked()), this, SLOT(addDefaultControllers()));
136 upper_controls_layout->addWidget(btn_add_default);
137 upper_controls_layout->setAlignment(btn_add_default, Qt::AlignLeft);
138
139 // Add Controls to layout
140 layout->addLayout(upper_controls_layout);
141
142 // Tree Box ----------------------------------------------------------------------
143 controllers_tree_ = new QTreeWidget(this);
144 controllers_tree_->setColumnCount(2);
145 QStringList labels;
146 labels << "Controller"
147 << "Controller Type";
148 controllers_tree_->setHeaderLabels(labels);
149 controllers_tree_->setColumnWidth(0, 250);
150 connect(controllers_tree_, SIGNAL(itemDoubleClicked(QTreeWidgetItem*, int)), this, SLOT(editSelected()));
151 connect(controllers_tree_, SIGNAL(itemClicked(QTreeWidgetItem*, int)), this,
152 SLOT(previewSelected(QTreeWidgetItem*, int)));
153 connect(controllers_tree_, SIGNAL(itemSelectionChanged()), this, SLOT(itemSelectionChanged()));
154 layout->addWidget(controllers_tree_);
155
156 // Bottom Controls -------------------------------------------------------------
157
158 controls_layout_ = new QHBoxLayout();
159
160 // Expand/Contract controls
161 QLabel* expand_controls = new QLabel(this);
162 expand_controls->setText("<a href='expand'>Expand All</a> <a href='contract'>Collapse All</a>");
163 connect(expand_controls, SIGNAL(linkActivated(const QString)), this, SLOT(alterTree(const QString)));
164 controls_layout_->addWidget(expand_controls);
165
166 // Spacer
167 controls_layout_->addItem(new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum));
168
169 // Delete
170 btn_delete_ = new QPushButton("&Delete Controller", this);
171 btn_delete_->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
172 btn_delete_->setMaximumWidth(200);
173 connect(btn_delete_, SIGNAL(clicked()), this, SLOT(deleteController()));
174 controls_layout_->addWidget(btn_delete_);
175 controls_layout_->setAlignment(btn_delete_, Qt::AlignRight);
176
177 // Add Controller Button
178 btn_add_ = new QPushButton("&Add Controller", this);
179 btn_add_->setMaximumWidth(300);
180 connect(btn_add_, SIGNAL(clicked()), this, SLOT(addController()));
181 controls_layout_->addWidget(btn_add_);
182 controls_layout_->setAlignment(btn_add_, Qt::AlignRight);
183
184 // Edit
185 btn_edit_ = new QPushButton("&Edit Selected", this);
186 btn_edit_->setMaximumWidth(300);
187 connect(btn_edit_, SIGNAL(clicked()), this, SLOT(editSelected()));
188 controls_layout_->addWidget(btn_edit_);
189 controls_layout_->setAlignment(btn_edit_, Qt::AlignRight);
190
191 // Add Controls to layout
192 layout->addLayout(controls_layout_);
193
194 // Set layout
195 content_widget->setLayout(layout);
196
197 return content_widget;
198}
199
200// ******************************************************************************************
201// Displays data in the controller_configs_ data structure into a QtTableWidget
202// ******************************************************************************************
204{
205 // Disable Tree
206 controllers_tree_->setUpdatesEnabled(false); // prevent table from updating until we are completely done
207 controllers_tree_->setDisabled(true); // make sure we disable it so that the cellChanged event is not called
208 controllers_tree_->clear(); // reset the tree
209
210 // Display all controllers by looping through them
211 for (ControllerInfo& controller : setup_step_->getControllers())
212 {
213 loadToControllersTree(controller);
214 }
215
216 // Re-enable Tree
217 controllers_tree_->setUpdatesEnabled(true); // prevent table from updating until we are completely done
218 controllers_tree_->setDisabled(false); // make sure we disable it so that the cellChanged event is not called
219 current_edit_controller_.clear(); // no controller is being edited
220 alterTree("expand");
221}
222
223// ******************************************************************************************
224// Displays data in the controller_config_ data structure into a QtTableWidget
225// ******************************************************************************************
227{
228 // Fonts for tree
229 const QFont top_level_font(QFont().defaultFamily(), 11, QFont::Bold);
230 const QFont type_font(QFont().defaultFamily(), 11, QFont::Normal, QFont::StyleItalic);
231
232 QTreeWidgetItem* controller;
233
234 controller = new QTreeWidgetItem();
235
236 // First column
237 controller->setText(0, controller_it.name_.c_str());
238 controller->setFont(0, top_level_font);
239 controller->setData(0, Qt::UserRole, QVariant::fromValue(0));
240
241 // Second column
242 controller->setText(1, controller_it.type_.c_str());
243 controller->setFont(1, type_font);
244 controller->setData(1, Qt::UserRole, QVariant::fromValue(4));
245 controllers_tree_->addTopLevelItem(controller);
246
247 if (!controller_it.joints_.empty())
248 {
249 // Joints --------------------------------------------------------------
250 QTreeWidgetItem* joints = new QTreeWidgetItem(controller);
251 joints->setText(0, "Joints");
252 joints->setFont(0, type_font);
253 joints->setData(0, Qt::UserRole, QVariant::fromValue(1));
254 controller->addChild(joints);
255
256 // Loop through all available joints
257 for (const std::string& joint : controller_it.joints_)
258 {
259 QTreeWidgetItem* joint_item = new QTreeWidgetItem(joints);
260 joint_item->setData(0, Qt::UserRole, QVariant::fromValue(2));
261
262 // Add to tree
263 joint_item->setText(0, joint.c_str());
264 joints->addChild(joint_item);
265 }
266 }
267}
268
269// ******************************************************************************************
270// Called when setup assistant navigation switches to this screen
271// ******************************************************************************************
273{
274 // load controllers tree
275 btn_edit_->setEnabled(false);
276 btn_delete_->setEnabled(false);
278}
279
280// ******************************************************************************************
281// Load the popup screen with correct data for joints
282// ******************************************************************************************
284{
285 // Get the names of the all joints
286 const std::vector<std::string>& joints = setup_step_->getJointNames();
287
288 if (joints.empty())
289 {
290 QMessageBox::critical(this, "Error Loading", "No joints found for robot model");
291 return;
292 }
293
294 // Set the available joints (left box)
296
297 // Set the selected joints (right box)
298 joints_widget_->setSelected(this_controller->joints_);
299
300 // Set the title
301 joints_widget_->title_->setText(
302 QString("Edit '").append(QString::fromUtf8(this_controller->name_.c_str())).append("' Joint Collection"));
303
304 // Remember what is currently being edited so we can later save changes
305 current_edit_controller_ = this_controller->name_;
306}
307
308// ******************************************************************************************
309// Load the popup screen with correct data for gcroups
310// ******************************************************************************************
312{
313 // Set the available groups (left box)
315
316 // Set the selected groups (right box)
317 joint_groups_widget_->setSelected(this_controller->joints_);
318
319 // Set the title
321 QString("Edit '").append(QString::fromUtf8(this_controller->name_.c_str())).append("' Joints groups collection"));
322
323 // Remember what is currently being edited so we can later save changes
324 current_edit_controller_ = this_controller->name_;
325}
326
327// ******************************************************************************************
328// Delete a controller
329// ******************************************************************************************
330void ControllersWidget::deleteController()
331{
332 std::string controller_name = current_edit_controller_;
333
334 if (controller_name.empty())
335 {
336 QTreeWidgetItem* item = controllers_tree_->currentItem();
337 // Check that something was actually selected
338 if (item == nullptr)
339 return;
340
341 // Get the user custom properties of the currently selected row
342 int type = item->data(0, Qt::UserRole).value<int>();
343 if (type == 0)
344 controller_name = item->text(0).toUtf8().constData();
345 }
346
347 // Confirm user wants to delete controller
348 if (QMessageBox::question(
349 this, "Confirm Controller Deletion",
350 QString("Are you sure you want to delete the controller '").append(controller_name.c_str()).append(" ?"),
351 QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Cancel)
352 {
353 return;
354 }
355 // Delete actual controller
356 if (setup_step_->deleteController(controller_name))
357 {
358 RCLCPP_INFO_STREAM(setup_step_->getLogger(), "Controller " << controller_name << " deleted successfully");
359 }
360 else
361 {
362 RCLCPP_WARN_STREAM(setup_step_->getLogger(), "Couldn't delete Controller " << controller_name);
363 }
364
366
367 // Switch to main screen
369
370 // Reload main screen table
372}
373
374// ******************************************************************************************
375// Create a new controller
376// ******************************************************************************************
377void ControllersWidget::addController()
378{
379 // New Controller
381
382 // Load the data
383 loadControllerScreen(nullptr); // nullptr indicates this is a new controller, not an existing one
384 changeScreen(2); // 1 is index of controller edit
385}
386
387// ******************************************************************************************
388// Add a Follow Joint Trajectory action Controller for each Planning Group
389// ******************************************************************************************
390void ControllersWidget::addDefaultControllers()
391{
392 if (!setup_step_->addDefaultControllers())
393 QMessageBox::warning(this, "Error adding controllers", "No Planning Groups configured!");
395}
396
397// ******************************************************************************************
398// Load the popup screen with correct data for controllers
399// ******************************************************************************************
401{
402 // Load the avail controllers. This function only runs once
404
405 if (this_controller == nullptr) // this is a new screen
406 {
407 current_edit_controller_.clear(); // provide a blank controller name
408 controller_edit_widget_->setTitle("Create New Controller");
410 controller_edit_widget_->showNewButtonsWidget(); // helps user choose next step
411 controller_edit_widget_->showSave(); // this is only for edit mode
412 }
413 else // load the controller name into the widget
414 {
415 current_edit_controller_ = this_controller->name_;
416 controller_edit_widget_->setTitle(QString("Edit Controller '").append(current_edit_controller_.c_str()).append("'"));
418 controller_edit_widget_->hideNewButtonsWidget(); // not necessary for existing controllers
419 controller_edit_widget_->showSave(); // this is only for edit mode
420 }
421
422 // Set the data in the edit box
423 ControllerInfo* searched_controller = setup_step_->findControllerByName(current_edit_controller_);
425}
426
427// ******************************************************************************************
428// Call when edit screen is canceled
429// ******************************************************************************************
430void ControllersWidget::cancelEditing()
431{
433 {
434 ControllerInfo* editing = setup_step_->findControllerByName(current_edit_controller_);
435 if (editing && editing->joints_.empty())
436 {
437 setup_step_->deleteController(current_edit_controller_);
439
440 // Load the data to the tree
442 }
443 }
444 else
445 {
447 }
448
449 // Switch to main screen
451}
452
453// ******************************************************************************************
454// Called from Double List widget to highlight joints
455// ******************************************************************************************
456void ControllersWidget::previewSelectedJoints(const std::vector<std::string>& joints)
457{
458 // Unhighlight all links
460
461 for (const std::string& joint : joints)
462 {
463 // Get the name of the link
464 const std::string link = setup_step_->getChildOfJoint(joint);
465
466 if (link.empty())
467 {
468 continue;
469 }
470
471 // Highlight link
472 rviz_panel_->highlightLink(link, QColor(255, 0, 0));
473 }
474}
475
476// ******************************************************************************************
477// Called from Double List widget to highlight a group
478// ******************************************************************************************
479void ControllersWidget::previewSelectedGroup(const std::vector<std::string>& groups)
480{
481 // Unhighlight all links
483
484 for (const std::string& group : groups)
485 {
486 // Highlight group
488 }
489}
490
491// ******************************************************************************************
492// Called when an item is selected from the controllers tree
493// ******************************************************************************************
494void ControllersWidget::previewSelected(QTreeWidgetItem* selected_item, int /*column*/)
495{
496 // Get the user custom properties of the currently selected row
497 int type = selected_item->data(0, Qt::UserRole).value<int>();
498 btn_edit_->setEnabled(true);
499
500 // Enable delete button if a controller was selected
501 if (type == 0)
502 {
503 btn_delete_->setEnabled(true);
504 }
505 else
506 {
507 btn_delete_->setEnabled(false);
508 }
509}
510
511// ******************************************************************************************
512// Call when a new controller is created and ready to progress to next screen
513// ******************************************************************************************
514void ControllersWidget::saveControllerScreenJoints()
515{
516 // Save the controller
517 if (!saveControllerScreen())
518 return;
519
520 // Find the controller we are editing based on the controller name string
521 ControllerInfo* editing_controller = setup_step_->findControllerByName(current_edit_controller_);
522
523 loadJointsScreen(editing_controller);
524
525 // Switch to screen
526 changeScreen(1); // 1 is index of joints
527}
528
529// ******************************************************************************************
530// Call when a new controller is created and ready to progress to next screen
531// ******************************************************************************************
532void ControllersWidget::saveControllerScreenGroups()
533{
534 // Save the controller
535 if (!saveControllerScreen())
536 return;
537
538 // Find the controller we are editing based on the controller name string
539 ControllerInfo* editing_controller = setup_step_->findControllerByName(current_edit_controller_);
540
541 loadGroupsScreen(editing_controller);
542
543 // Switch to screen
544 changeScreen(3); // 3 is index of groups
545}
546
547// ******************************************************************************************
548// Call when joints edit screen is done and needs to be saved
549// ******************************************************************************************
550void ControllersWidget::saveJointsScreen()
551{
552 // Find the controller we are editing based on the controller name string
553 ControllerInfo* searched_controller = setup_step_->findControllerByName(current_edit_controller_);
554
555 // Clear the old data
556 searched_controller->joints_.clear();
557
558 // Copy the data
559 for (int i = 0; i < joints_widget_->selected_data_table_->rowCount(); ++i)
560 {
561 searched_controller->joints_.push_back(joints_widget_->selected_data_table_->item(i, 0)->text().toStdString());
562 }
563
564 // Switch to main screen
566
567 // Reload main screen table
569}
570
571// ******************************************************************************************
572// Call when joints edit screen is done and needs to be saved
573// ******************************************************************************************
574void ControllersWidget::saveJointsGroupsScreen()
575{
576 // Find the controller we are editing based on the controller name string
577 ControllerInfo* searched_controller = setup_step_->findControllerByName(current_edit_controller_);
578
579 // Clear the old data
580 searched_controller->joints_ = setup_step_->getJointsFromGroups(joint_groups_widget_->getSelectedValues());
581
582 // Switch to main screen
584
585 // Reload main screen table
587}
588
589// ******************************************************************************************
590// Call when joints edit screen is done and needs to be saved
591// ******************************************************************************************
592void ControllersWidget::saveControllerScreenEdit()
593{
594 // Save the controller
595 if (!saveControllerScreen())
596 return;
597
598 // Switch to main screen
600}
601
602// ******************************************************************************************
603// Call when controller edit screen is done and needs to be saved
604// ******************************************************************************************
605bool ControllersWidget::saveControllerScreen()
606{
607 // Get a reference to the supplied strings
608 const std::string& controller_name = controller_edit_widget_->getControllerName();
609 const std::string& controller_type = controller_edit_widget_->getControllerType();
610 std::map<std::string, std::string> controller_parameters = controller_edit_widget_->getAdditionalParameters();
611
612 // Used for editing existing controllers
613 ControllerInfo* searched_controller = nullptr;
614
615 std::smatch invalid_name_match;
616 std::regex invalid_reg_ex("[^a-z|^1-9|^_]");
617
618 // Check that a valid controller name has been given
619 if (controller_name.empty() || std::regex_search(controller_name, invalid_name_match, invalid_reg_ex))
620 {
621 QMessageBox::warning(this, "Error Saving", "Invalid controller name");
622 return false;
623 }
624
625 // Check if this is an existing controller
626 if (!current_edit_controller_.empty())
627 {
628 // Find the controller we are editing based on the group name string
629 searched_controller = setup_step_->findControllerByName(current_edit_controller_);
630 }
631
632 // Check that the controller name is unique
633 for (const auto& controller : setup_step_->getControllers())
634 {
635 if (controller.name_.compare(controller_name) == 0) // the names are the same
636 {
637 // is this our existing controller? check if controller pointers are same
638 if (&controller != searched_controller)
639 {
640 QMessageBox::warning(this, "Error Saving", "A controller already exists with that name!");
641 return false;
642 }
643 }
644 }
645
647
648 // Save the new controller name or create the new controller
649 if (searched_controller == nullptr) // create new
650 {
651 ControllerInfo new_controller;
652 new_controller.name_ = controller_name;
653 new_controller.type_ = controller_type;
654 new_controller.parameters_ = controller_parameters;
655 setup_step_->addController(new_controller);
656
657 adding_new_controller_ = true; // remember this controller is new
658 }
659 else
660 {
661 // Remember old controller name and type
662 const std::string old_controller_name = searched_controller->name_;
663
664 // Change controller name
665 searched_controller->name_ = controller_name;
666 searched_controller->type_ = controller_type;
667 searched_controller->parameters_ = controller_parameters;
668 }
669
670 // Reload main screen table
672
673 // Update the current edit controller so that we can proceed to the next screen, if user desires
674 current_edit_controller_ = controller_name;
675
676 return true;
677}
678
679// ******************************************************************************************
680// Edit whenever element is selected in the controllers tree view
681// ******************************************************************************************
682void ControllersWidget::editSelected()
683{
684 QTreeWidgetItem* item = controllers_tree_->currentItem();
685 QTreeWidgetItem* controller_item;
686
687 // Check that something was actually selected
688 if (item == nullptr)
689 return;
690
692
693 // Get the user custom properties of the currently selected row
694 int type = item->data(0, Qt::UserRole).value<int>();
695
696 if (type == 2)
697 {
698 // The controller this joint belong to
699 controller_item = item->parent()->parent();
700 current_edit_controller_ = controller_item->text(0).toUtf8().constData();
701 ControllerInfo* this_controller = setup_step_->findControllerByName(current_edit_controller_);
702
703 // Load the data
704 loadJointsScreen(this_controller);
705
706 // Switch to screen
707 changeScreen(1); // 1 is index of joints
708 }
709 else if (type == 1)
710 {
711 controller_item = item->parent();
712 current_edit_controller_ = controller_item->text(0).toUtf8().constData();
713 ControllerInfo* this_controller = setup_step_->findControllerByName(current_edit_controller_);
714
715 // Load the data
716 loadJointsScreen(this_controller);
717
718 // Switch to screen
719 changeScreen(1); // 1 is index of joints
720 }
721 else if (type == 0)
722 {
723 // Load the data
724 current_edit_controller_ = item->text(0).toUtf8().constData();
725 ControllerInfo* this_controller = setup_step_->findControllerByName(current_edit_controller_);
726 loadControllerScreen(this_controller);
727
728 // Switch to screen
729 changeScreen(2); // 1 is index of controller edit
730 }
731 else
732 {
733 QMessageBox::critical(this, "Error Loading", "An internal error has occurred while loading.");
734 }
735}
736
737// ******************************************************************************************
738// Edit a controller
739// ******************************************************************************************
740void ControllersWidget::editController()
741{
742 QTreeWidgetItem* item = controllers_tree_->currentItem();
743
744 // Check that something was actually selected
745 if (item == nullptr)
746 return;
747
749
751
752 // Switch to screen
753 changeScreen(2); // 1 is index of controller edit
754}
755
756// ******************************************************************************************
757// Switch to current controllers view
758// ******************************************************************************************
760{
761 stacked_widget_->setCurrentIndex(0);
762
763 // Announce that this widget is not in modal mode
764 Q_EMIT setModalMode(false);
765}
766
767// ******************************************************************************************
768// Switch which screen is being shown
769// ******************************************************************************************
771{
772 stacked_widget_->setCurrentIndex(index);
773
774 // Announce this widget's mode
775 Q_EMIT setModalMode(index != 0);
776}
777
778// ******************************************************************************************
779// Expand/Collapse Tree
780// ******************************************************************************************
781void ControllersWidget::alterTree(const QString& link)
782{
783 if (link.contains("expand"))
784 {
785 controllers_tree_->expandAll();
786 }
787 else
788 {
789 controllers_tree_->collapseAll();
790 }
791}
792
793void ControllersWidget::itemSelectionChanged()
794{
795 QList<QTreeWidgetItem*> selected_items = controllers_tree_->selectedItems();
796 if (selected_items.empty())
797 {
798 btn_edit_->setEnabled(false);
799 btn_delete_->setEnabled(false);
800 }
801}
802
803} // namespace controllers
804} // namespace moveit_setup
std::vector< std::string > getSelectedValues() const
Return all the values that are in the "selected" subset.
void setAvailable(const std::vector< std::string > &items)
Loads the available data list.
void setSelected(const std::vector< std::string > &items)
Set the right box.
void highlightGroup(const std::string &group_name)
void highlightLink(const std::string &link_name, const QColor &color)
void setModalMode(bool isModal)
Event for when the current screen is in modal view. Disables the left navigation.
std::map< std::string, std::string > getAdditionalParameters()
Get the names and values for any additional parameters.
void setSelected(const std::string &controller_name, const ControllerInfo *info)
Set the previous data.
void loadControllersTypesComboBox(const std::vector< std::string > &controller_types)
Populate the combo dropdown box with controllers types.
void setTitle(const QString &title)
Set widget title.
QTreeWidget * controllers_tree_
Main table for holding controllers.
QStackedWidget * stacked_widget_
For changing between table and different add/edit views.
bool adding_new_controller_
Remember whethere we're editing a controller or adding a new one.
void loadJointsScreen(ControllerInfo *this_controller)
void focusGiven() override
Received when this widget is chosen from the navigation menu.
void loadControllerScreen(ControllerInfo *this_controller)
void loadToControllersTree(const ControllerInfo &controller_it)
std::string current_edit_controller_
Remember what controller we are editing when an edit screen is being shown.
void loadGroupsScreen(ControllerInfo *this_controller)
QWidget * createContentsWidget()
Builds the main screen list widget.