moveit2
The MoveIt Motion Planning Framework for ROS 2.
Loading...
Searching...
No Matches
double_list_widget.cpp
Go to the documentation of this file.
1/*********************************************************************
2 * Software License Agreement (BSD License)
3 *
4 * Copyright (c) 2012, Willow Garage, Inc.
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 * * Neither the name of Willow Garage nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
33 *********************************************************************/
34
35/* Author: Dave Coleman */
36
37#include <QFormLayout>
38#include <QGroupBox>
39#include <QHBoxLayout>
40#include <QHeaderView>
41#include <QLabel>
42#include <QLineEdit>
43#include <QMessageBox>
44#include <QPushButton>
45#include <QString>
46#include <QTableWidget>
47#include <QVBoxLayout>
49
50namespace moveit_setup
51{
52// ******************************************************************************************
53//
54// ******************************************************************************************
55DoubleListWidget::DoubleListWidget(QWidget* parent, const QString& long_name, const QString& short_name,
56 bool add_ok_cancel)
57 : QWidget(parent), long_name_(long_name), short_name_(short_name)
58{
59 // Basic widget container
60 QVBoxLayout* layout = new QVBoxLayout();
61
62 // Label ------------------------------------------------
63 title_ = new QLabel("", this); // specify the title from the parent widget
64 QFont group_title_font(QFont().defaultFamily(), 12, QFont::Bold);
65 title_->setFont(group_title_font);
66 layout->addWidget(title_);
67
68 // Double selection lists -------------------------------
69 QHBoxLayout* hlayout = new QHBoxLayout();
70
71 // Left column -------------------------------------------
72 QVBoxLayout* column1 = new QVBoxLayout();
73
74 // Label
75 column1_label_ = new QLabel(QString("Available ").append(short_name_).append('s'), this);
76 column1->addWidget(column1_label_);
77
78 // Table
79 data_table_ = new QTableWidget(this);
80 data_table_->setColumnCount(1);
81 data_table_->setSortingEnabled(true);
82 column1->addWidget(data_table_);
83 connect(data_table_->selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)), this,
84 SLOT(previewSelectedLeft(QItemSelection, QItemSelection)));
85
86 // Table headers
87 QStringList data_header_list;
88 data_header_list.append(QString(" Names").prepend(short_name_));
89 data_table_->setHorizontalHeaderLabels(data_header_list);
90 data_table_->horizontalHeader()->setDefaultAlignment(Qt::AlignHCenter);
91
92 // Add layouts
93 hlayout->addLayout(column1);
94
95 // Center column ------------------------------------------
96 QVBoxLayout* column2 = new QVBoxLayout();
97 column2->setSizeConstraint(QLayout::SetFixedSize); // constraint it
98
99 // Right Arrow Button
100 QPushButton* btn_right = new QPushButton(">", this);
101 btn_right->setMaximumSize(25, 80);
102 connect(btn_right, SIGNAL(clicked()), this, SLOT(selectDataButtonClicked()));
103 column2->addWidget(btn_right);
104
105 // Left Arrow Button
106 QPushButton* btn_left = new QPushButton("<", this);
107 btn_left->setMaximumSize(25, 80);
108 connect(btn_left, SIGNAL(clicked()), this, SLOT(deselectDataButtonClicked()));
109 column2->addWidget(btn_left);
110
111 // Add layouts
112 hlayout->addLayout(column2);
113
114 // Right column -------------------------------------------
115 QVBoxLayout* column3 = new QVBoxLayout();
116
117 // Label
118 column2_label_ = new QLabel(QString("Selected ").append(short_name_).append("s"), this);
119 column3->addWidget(column2_label_);
120
121 // Table
122 selected_data_table_ = new QTableWidget(this);
123 selected_data_table_->setColumnCount(1);
124 selected_data_table_->setSortingEnabled(true);
125 column3->addWidget(selected_data_table_);
126 connect(selected_data_table_->selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)), this,
127 SLOT(previewSelectedRight(QItemSelection, QItemSelection)));
128
129 // Table Headers (use same)
130 selected_data_table_->setHorizontalHeaderLabels(data_header_list);
131
132 // Add layouts
133 hlayout->addLayout(column3);
134
135 // End Double Selection List ---------------------------------
136 layout->addLayout(hlayout);
137
138 if (add_ok_cancel)
139 {
140 // Button controls -------------------------------------------
141 QHBoxLayout* controls_layout = new QHBoxLayout();
142 controls_layout->setContentsMargins(0, 25, 0, 15);
143
144 // Spacer
145 controls_layout->addItem(new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum));
146
147 // Save
148 QPushButton* btn_save = new QPushButton("&Save", this);
149 // btn_save->setMaximumWidth( 200 );
150 connect(btn_save, SIGNAL(clicked()), this, SIGNAL(doneEditing()));
151 controls_layout->addWidget(btn_save);
152 controls_layout->setAlignment(btn_save, Qt::AlignRight);
153
154 // Cancel
155 QPushButton* btn_cancel = new QPushButton("&Cancel", this);
156 // btn_cancel->setMaximumWidth( 200 );
157 connect(btn_cancel, SIGNAL(clicked()), this, SIGNAL(cancelEditing()));
158 controls_layout->addWidget(btn_cancel);
159 controls_layout->setAlignment(btn_cancel, Qt::AlignRight);
160
161 // Add layout
162 layout->addLayout(controls_layout);
163 }
164
165 // Finish Layout --------------------------------------------------
166 setLayout(layout);
167}
168
169// ******************************************************************************************
170// Set the left box
171// ******************************************************************************************
172void DoubleListWidget::setAvailable(const std::vector<std::string>& items)
173{
174 setTable(items, data_table_);
175
176 // Resize both tables
177 data_table_->resizeColumnToContents(0);
178 selected_data_table_->setColumnWidth(0, data_table_->columnWidth(0));
179}
180
181// ******************************************************************************************
182// Set the right box
183// ******************************************************************************************
184void DoubleListWidget::setSelected(const std::vector<std::string>& items)
185{
187}
188
190{
191 selected_data_table_->clearContents();
192 data_table_->clearContents();
193}
194
195void DoubleListWidget::setColumnNames(const QString& col1, const QString& col2)
196{
197 column1_label_->setText(col1);
198 column2_label_->setText(col2);
199}
200
201// ******************************************************************************************
202// Convenience function for reusing set table code
203// ******************************************************************************************
204void DoubleListWidget::setTable(const std::vector<std::string>& items, QTableWidget* table)
205{
206 // Disable Table
207 table->setUpdatesEnabled(false); // prevent table from updating until we are completely done
208 table->setDisabled(true); // make sure we disable it so that the cellChanged event is not called
209 table->clearContents();
210
211 // Set size of datatable
212 table->setRowCount(items.size());
213
214 // Loop through every item
215 int row = 0;
216 for (const std::string& item : items)
217 {
218 // This is a hack to prevent a dummy joint from being added. Not really the best place to place this but
219 // here is computationally smart
220 if (item == "ASSUMED_FIXED_ROOT_JOINT")
221 continue;
222
223 // Create row elements
224 QTableWidgetItem* data_name = new QTableWidgetItem(item.c_str());
225 data_name->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
226
227 // Add to table
228 table->setItem(row, 0, data_name);
229
230 // Increment counter
231 ++row;
232 }
233
234 table->setRowCount(row);
235
236 // Re-enable
237 table->setUpdatesEnabled(true); // prevent table from updating until we are completely done
238 table->setDisabled(false); // make sure we disable it so that the cellChanged event is not called
239}
240
241// ******************************************************************************************
242// Move selected data right
243// ******************************************************************************************
244void DoubleListWidget::selectDataButtonClicked()
245{
246 // Get list of all selected items
247 QList<QTableWidgetItem*> selected = data_table_->selectedItems();
248
249 // Loop through all selected items
250 for (QTableWidgetItem* item : selected)
251 {
252 std::string name = item->text().toStdString();
253 bool already_exists = false;
254 int row_to_add = 0;
255
256 // Check if this selected joint is already in the selected joint table
257 for (int r = 0; r < selected_data_table_->rowCount(); ++r)
258 {
259 QTableWidgetItem* item = selected_data_table_->item(r, 0);
260
261 if (item->text().toStdString() == name)
262 {
263 already_exists = true;
264 break;
265 }
266 row_to_add = r + 1;
267 }
268
269 // This joint needs to be added to the selected joint table
270 if (!already_exists)
271 {
272 selected_data_table_->setRowCount(selected_data_table_->rowCount() + 1);
273 QTableWidgetItem* new_item = new QTableWidgetItem(name.c_str());
274 new_item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
275 selected_data_table_->setItem(row_to_add, 0, new_item);
276 }
277 }
278
279 Q_EMIT(selectionUpdated());
280}
281
282// ******************************************************************************************
283// Move selected data left
284// ******************************************************************************************
285void DoubleListWidget::deselectDataButtonClicked()
286{
287 // Get list of joints to be removed from selected list
288 QList<QTableWidgetItem*> deselected = selected_data_table_->selectedItems();
289
290 // loop through deselect list and remove
291 for (QTableWidgetItem* item : deselected)
292 {
293 selected_data_table_->removeRow(item->row());
294 }
295
296 Q_EMIT(selectionUpdated());
297}
298
299// ******************************************************************************************
300// Highlight links of robot for left list
301// ******************************************************************************************
302void DoubleListWidget::previewSelectedLeft(const QItemSelection& /*selected*/, const QItemSelection& /*deselected*/)
303{
304 const QList<QTableWidgetItem*> selected_items = data_table_->selectedItems();
305 previewSelected(selected_items);
306}
307
308// ******************************************************************************************
309// Highlight links of robot for right list
310// ******************************************************************************************
311void DoubleListWidget::previewSelectedRight(const QItemSelection& /*selected*/, const QItemSelection& /*deselected*/)
312{
313 const QList<QTableWidgetItem*> selected_items = selected_data_table_->selectedItems();
314 previewSelected(selected_items);
315}
316
317// ******************************************************************************************
318// Highlight links of robot
319// ******************************************************************************************
320void DoubleListWidget::previewSelected(const QList<QTableWidgetItem*>& selected)
321{
322 // Check that an element was selected
323 if (selected.empty())
324 return;
325
326 std::vector<std::string> selected_vector;
327
328 // Convert QList to std vector
329 selected_vector.reserve(selected.size());
330 for (QTableWidgetItem* item : selected)
331 selected_vector.emplace_back(item->text().toStdString());
332
333 // Send to shared function
334 Q_EMIT(previewSelected(selected_vector));
335}
336
337std::vector<std::string> DoubleListWidget::getSelectedValues() const
338{
339 std::vector<std::string> values;
340 values.reserve(selected_data_table_->rowCount());
341 for (int i = 0; i < selected_data_table_->rowCount(); ++i)
342 {
343 values.push_back(selected_data_table_->item(i, 0)->text().toStdString());
344 }
345 return values;
346}
347
348} // namespace moveit_setup
void setColumnNames(const QString &col1, const QString &col2)
Set the names of the two columns in the widget.
void doneEditing()
Event sent when this widget is done making data changes and parent widget can save.
void selectionUpdated()
When the set of selected items has changed.
std::vector< std::string > getSelectedValues() const
Return all the values that are in the "selected" subset.
void setTable(const std::vector< std::string > &items, QTableWidget *table)
Convenience function for reusing set table code.
DoubleListWidget(QWidget *parent, const QString &long_name, const QString &short_name, bool add_ok_cancel=true)
Constructor.
void previewSelected(std::vector< std::string >)
Signal to highlight parts of robot.
void cancelEditing()
Event sent when user presses cancel button.
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.
name
Definition setup.py:7