displays_panel.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2012, Willow Garage, Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * * Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * * Neither the name of the Willow Garage, Inc. nor the names of its
14  * contributors may be used to endorse or promote products derived from
15  * this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 #include <QTimer>
31 #include <QHBoxLayout>
32 #include <QVBoxLayout>
33 #include <QPushButton>
34 #include <QInputDialog>
35 #include <QApplication>
36 #include <QProgressDialog>
37 
38 #include <boost/bind.hpp>
39 
40 #include "rviz/display_factory.h"
41 #include "rviz/display.h"
47 
48 #include "rviz/displays_panel.h"
49 
50 namespace rviz
51 {
52 DisplaysPanel::DisplaysPanel(QWidget* parent) : Panel(parent)
53 {
56 
57  QPushButton* add_button = new QPushButton("Add");
58  add_button->setShortcut(QKeySequence(QString("Ctrl+N")));
59  add_button->setToolTip("Add a new display, Ctrl+N");
60  duplicate_button_ = new QPushButton("Duplicate");
61  duplicate_button_->setShortcut(QKeySequence(QString("Ctrl+D")));
62  duplicate_button_->setToolTip("Duplicate a display, Ctrl+D");
63  duplicate_button_->setEnabled(false);
64  remove_button_ = new QPushButton("Remove");
65  remove_button_->setShortcut(QKeySequence(QString("Ctrl+X")));
66  remove_button_->setToolTip("Remove displays, Ctrl+X");
67  remove_button_->setEnabled(false);
68  rename_button_ = new QPushButton("Rename");
69  rename_button_->setShortcut(QKeySequence(QString("Ctrl+R")));
70  rename_button_->setToolTip("Rename a display, Ctrl+R");
71  rename_button_->setEnabled(false);
72 
73  QHBoxLayout* button_layout = new QHBoxLayout;
74  button_layout->addWidget(add_button);
75  button_layout->addWidget(duplicate_button_);
76  button_layout->addWidget(remove_button_);
77  button_layout->addWidget(rename_button_);
78  button_layout->setContentsMargins(2, 0, 2, 2);
79 
80  QVBoxLayout* layout = new QVBoxLayout;
81  layout->setContentsMargins(0, 0, 0, 2);
82  layout->addWidget(tree_with_help_);
83  layout->addLayout(button_layout);
84 
85  setLayout(layout);
86 
87  connect(add_button, SIGNAL(clicked(bool)), this, SLOT(onNewDisplay()));
88  connect(duplicate_button_, SIGNAL(clicked(bool)), this, SLOT(onDuplicateDisplay()));
89  connect(remove_button_, SIGNAL(clicked(bool)), this, SLOT(onDeleteDisplay()));
90  connect(rename_button_, SIGNAL(clicked(bool)), this, SLOT(onRenameDisplay()));
91  connect(property_grid_, SIGNAL(selectionHasChanged()), this, SLOT(onSelectionChanged()));
92 }
93 
95 {
96 }
97 
99 {
101 }
102 
104 {
105  QString lookup_name;
106  QString display_name;
107  QString topic;
108  QString datatype;
109 
110  QStringList empty;
111 
112  QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
113  AddDisplayDialog dialog(vis_manager_->getDisplayFactory(), "Display", empty, empty, &lookup_name,
114  &display_name, &topic, &datatype);
115  QApplication::restoreOverrideCursor();
116 
118  if (dialog.exec() == QDialog::Accepted)
119  {
120  Display* disp = vis_manager_->createDisplay(lookup_name, display_name, true);
121  if (!topic.isEmpty() && !datatype.isEmpty())
122  {
123  disp->setTopic(topic, datatype);
124  }
125  }
127  activateWindow(); // Force keyboard focus back on main window.
128 }
129 
131 {
132  QList<Display*> displays_to_duplicate = property_grid_->getSelectedObjects<Display>();
133  QList<Display*> duplicated_displays;
134  QProgressDialog progress_dlg("Duplicating displays...", "Cancel", 0, displays_to_duplicate.size(),
135  this);
137  progress_dlg.setWindowModality(Qt::WindowModal);
138  progress_dlg.show();
139  QApplication::processEvents(); // explicitly progress events for update
140 
141  // duplicate all selected displays
142  for (int i = 0; i < displays_to_duplicate.size(); i++)
143  {
144  // initialize display
145  QString lookup_name = displays_to_duplicate[i]->getClassId();
146  QString display_name = displays_to_duplicate[i]->getName();
147  Display* disp = vis_manager_->createDisplay(lookup_name, display_name, true);
148  // duplicate config
149  Config config;
150  displays_to_duplicate[i]->save(config);
151  disp->load(config);
152  duplicated_displays.push_back(disp);
153  progress_dlg.setValue(i + 1);
154  QApplication::processEvents(); // explicitly progress events for update
155  // push cancel to stop duplicate
156  if (progress_dlg.wasCanceled())
157  break;
158  }
159  // make sure the newly duplicated displays are selected.
160  if (!duplicated_displays.empty())
161  {
162  QModelIndex first = property_grid_->getModel()->indexOf(duplicated_displays.front());
163  QModelIndex last = property_grid_->getModel()->indexOf(duplicated_displays.back());
164  QItemSelection selection(first, last);
165  property_grid_->selectionModel()->select(selection, QItemSelectionModel::ClearAndSelect);
166  }
168  activateWindow(); // Force keyboard focus back on main window.
169 }
170 
172 {
173  QList<Display*> displays_to_delete = property_grid_->getSelectedObjects<Display>();
174 
175  for (int i = 0; i < displays_to_delete.size(); i++)
176  {
177  // Displays can emit signals from other threads with self pointers. We're
178  // freeing the display now, so ensure no one is listening to those signals.
179  displays_to_delete[i]->disconnect();
180  // Remove dipslay from property tree to avoid memory access after deletion
181  displays_to_delete[i]->getParent()->takeChild(displays_to_delete[i]);
182  // Delete display later in case there are pending signals to it.
183  displays_to_delete[i]->deleteLater();
184  }
185  // Select new current index
186  const QModelIndex& cur = property_grid_->currentIndex();
187  QItemSelection selection(cur.sibling(cur.row(), 0),
188  cur.sibling(cur.row(), cur.model()->columnCount() - 1));
189  property_grid_->selectionModel()->select(selection, QItemSelectionModel::ClearAndSelect);
190 
192 }
193 
195 {
196  QList<Display*> displays = property_grid_->getSelectedObjects<Display>();
197 
198  int num_displays_selected = displays.size();
199 
200  duplicate_button_->setEnabled(num_displays_selected > 0);
201  remove_button_->setEnabled(num_displays_selected > 0);
202  rename_button_->setEnabled(num_displays_selected == 1);
203 }
204 
206 {
207  QList<Display*> displays = property_grid_->getSelectedObjects<Display>();
208  if (displays.empty())
209  {
210  return;
211  }
212  Display* display_to_rename = displays[0];
213 
214  if (!display_to_rename)
215  {
216  return;
217  }
218 
219  QString old_name = display_to_rename->getName();
220  QString new_name =
221  QInputDialog::getText(this, "Rename Display", "New Name?", QLineEdit::Normal, old_name);
222 
223  if (new_name.isEmpty() || new_name == old_name)
224  {
225  return;
226  }
227 
228  display_to_rename->setName(new_name);
229 }
230 
231 void DisplaysPanel::save(Config config) const
232 {
233  Panel::save(config);
234  tree_with_help_->save(config);
235 }
236 
237 void DisplaysPanel::load(const Config& config)
238 {
239  Panel::load(config);
240  tree_with_help_->load(config);
241 }
242 
243 } // namespace rviz
void setModel(PropertyTreeModel *model)
Set the data model this widget should view.
QPushButton * duplicate_button_
VisualizationManager * vis_manager_
Definition: panel.h:113
PropertyTreeWidget * getTree()
QList< Type * > getSelectedObjects()
Return the list of objects of a given type which are currently selected.
Property * getParent() const
Return the parent Property.
Definition: property.cpp:231
void load(const Config &config) override
Read state from the given Config.
Display * createDisplay(const QString &class_lookup_name, const QString &name, bool enabled)
Create and add a display to this panel, by class lookup name.
config
void onDeleteDisplay()
Called when the "Remove" button is pressed.
virtual void setTopic(const QString &topic, const QString &datatype)
Set the ROS topic to listen to for this display.
Definition: display.h:122
void onNewDisplay()
Called when the "Add" button is pressed.
void load(const Config &config) override
Load the settings for this display from the given Config node, which must be a map.
Definition: display.cpp:228
virtual void save(Config config) const
Override to save configuration data. This version saves the name and class ID of the panel...
Definition: panel.cpp:50
PropertyTreeModel * getModel() const
Property * takeChild(Property *child)
Remove a given child object and return a pointer to it.
Definition: property.cpp:321
void save(Config config) const
Write state to the given Config.
Configuration data storage class.
Definition: config.h:124
PropertyTreeModel * getDisplayTreeModel() const
const char * datatype()
void onInitialize() override
QPushButton * remove_button_
void onRenameDisplay()
Called when the "Rename" button is pressed.
virtual QString getName() const
Return the name of this Property as a QString.
Definition: property.cpp:164
PropertyTreeWithHelp * tree_with_help_
QModelIndex indexOf(Property *property) const
DisplaysPanel(QWidget *parent=nullptr)
QPushButton * rename_button_
void save(Config config) const override
Write state to the given Config object.
PropertyTreeWidget * property_grid_
void load(const Config &config)
Read state from the given Config.
void setName(const QString &name) override
Overridden from Property to set associated widget title to the new name.
Definition: display.cpp:413
void notifyConfigChanged()
Notify this VisualizationManager that something about its display configuration has changed...
virtual void load(const Config &config)
Override to load configuration data. This version loads the name of the panel.
Definition: panel.cpp:56
void onDuplicateDisplay()
Called when the "copy" button is pressed.
void startUpdate()
Start timers. Creates and starts the update and idle timers, both set to 30Hz (33ms).
DisplayFactory * getDisplayFactory() const override
Return a factory for creating Display subclasses based on a class id string.


rviz
Author(s): Dave Hershberger, David Gossow, Josh Faust
autogenerated on Sat May 27 2023 02:06:24