moveit2
The MoveIt Motion Planning Framework for ROS 2.
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 
61 namespace moveit_setup
62 {
63 namespace 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  this->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  this->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)
295  joints_widget_->setAvailable(joints);
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)
314  joint_groups_widget_->setAvailable(setup_step_->getGroupNames());
315 
316  // Set the selected groups (right box)
317  joint_groups_widget_->setSelected(this_controller->joints_);
318 
319  // Set the title
320  joint_groups_widget_->title_->setText(
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 // ******************************************************************************************
330 void 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 succefully");
359  }
360  else
361  {
362  RCLCPP_WARN_STREAM(setup_step_->getLogger(), "Couldn't delete Controller " << controller_name);
363  }
364 
365  current_edit_controller_.clear();
366 
367  // Switch to main screen
368  showMainScreen();
369 
370  // Reload main screen table
372 }
373 
374 // ******************************************************************************************
375 // Create a new controller
376 // ******************************************************************************************
377 void ControllersWidget::addController()
378 {
379  // New Controller
380  adding_new_controller_ = true;
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 // ******************************************************************************************
390 void 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 // ******************************************************************************************
430 void 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_);
438  current_edit_controller_.clear();
439 
440  // Load the data to the tree
442  }
443  }
444  else
445  {
446  current_edit_controller_.clear();
447  }
448 
449  // Switch to main screen
450  showMainScreen();
451 }
452 
453 // ******************************************************************************************
454 // Called from Double List widget to highlight joints
455 // ******************************************************************************************
456 void 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 // ******************************************************************************************
479 void 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 seleceted from the controllers tree
493 // ******************************************************************************************
494 void 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 // ******************************************************************************************
514 void 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 // ******************************************************************************************
532 void 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 // ******************************************************************************************
550 void 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
565  showMainScreen();
566 
567  // Reload main screen table
569 }
570 
571 // ******************************************************************************************
572 // Call when joints edit screen is done and needs to be saved
573 // ******************************************************************************************
574 void 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
583  showMainScreen();
584 
585  // Reload main screen table
587 }
588 
589 // ******************************************************************************************
590 // Call when joints edit screen is done and needs to be saved
591 // ******************************************************************************************
592 void ControllersWidget::saveControllerScreenEdit()
593 {
594  // Save the controller
595  if (!saveControllerScreen())
596  return;
597 
598  // Switch to main screen
599  showMainScreen();
600 }
601 
602 // ******************************************************************************************
603 // Call when controller edit screen is done and needs to be saved
604 // ******************************************************************************************
605 bool 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 
646  adding_new_controller_ = false;
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 // ******************************************************************************************
682 void 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 
691  adding_new_controller_ = false;
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 // ******************************************************************************************
740 void ControllersWidget::editController()
741 {
742  QTreeWidgetItem* item = controllers_tree_->currentItem();
743 
744  // Check that something was actually selected
745  if (item == nullptr)
746  return;
747 
748  adding_new_controller_ = false;
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 // ******************************************************************************************
781 void ControllersWidget::alterTree(const QString& link)
782 {
783  if (link.contains("expand"))
784  controllers_tree_->expandAll();
785  else
786  controllers_tree_->collapseAll();
787 }
788 
789 void ControllersWidget::itemSelectionChanged()
790 {
791  QList<QTreeWidgetItem*> selected_items = controllers_tree_->selectedItems();
792  if (selected_items.empty())
793  {
794  btn_edit_->setEnabled(false);
795  btn_delete_->setEnabled(false);
796  }
797 }
798 
799 } // namespace controllers
800 } // 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)
Definition: rviz_panel.hpp:104
void highlightLink(const std::string &link_name, const QColor &color)
Definition: rviz_panel.hpp:96
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.
std::string append(const std::string &left, const std::string &right)