tool_manager.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 <QKeyEvent>
31 #include <QRegExp>
32 
33 #include <ros/assert.h>
34 
35 #include "rviz/failed_tool.h"
38 
39 #include "rviz/tool_manager.h"
40 
41 namespace rviz
42 {
43 QString addSpaceToCamelCase(QString input)
44 {
45  QRegExp re = QRegExp("([A-Z])([a-z]*)");
46  input.replace(re, " \\1\\2");
47  return input.trimmed();
48 }
49 
51  : factory_(new PluginlibFactory<Tool>("rviz", "rviz::Tool"))
52  , property_tree_model_(new PropertyTreeModel(new Property()))
53  , context_(context)
54  , current_tool_(nullptr)
55  , default_tool_(nullptr)
56 {
57  connect(property_tree_model_, SIGNAL(configChanged()), this, SIGNAL(configChanged()));
58 }
59 
61 {
62  removeAll();
63  delete factory_;
64  delete property_tree_model_;
65 }
66 
68 {
69  // Possibly this should be done with a loop over
70  // factory_->getDeclaredClassIds(), but then I couldn't control the
71  // order.
72  addTool("rviz/MoveCamera");
73  addTool("rviz/Interact");
74  addTool("rviz/Select");
75  addTool("rviz/SetInitialPose");
76  addTool("rviz/SetGoal");
77 }
78 
80 {
81  for (int i = tools_.size() - 1; i >= 0; i--)
82  {
83  removeTool(i);
84  }
85 }
86 
87 void ToolManager::load(const Config& config)
88 {
89  removeAll();
90 
91  int num_tools = config.listLength();
92  for (int i = 0; i < num_tools; i++)
93  {
94  Config tool_config = config.listChildAt(i);
95 
96  QString class_id;
97  if (tool_config.mapGetString("Class", &class_id))
98  {
99  Tool* tool = addTool(class_id);
100  tool->load(tool_config);
101  }
102  }
103 }
104 
105 void ToolManager::save(Config config) const
106 {
107  for (int i = 0; i < tools_.size(); i++)
108  {
109  tools_[i]->save(config.listAppendNew());
110  }
111 }
112 
113 bool ToolManager::toKey(QString const& str, uint& key)
114 {
115  QKeySequence seq(str);
116 
117  // We should only working with a single key here
118  if (seq.count() == 1)
119  {
120  key = seq[0];
121  return true;
122  }
123  else
124  {
125  return false;
126  }
127 }
128 
129 void ToolManager::handleChar(QKeyEvent* event, RenderPanel* panel)
130 {
131  // if the incoming key is ESC fallback to the default tool
132  if (event->key() == Qt::Key_Escape)
133  {
135  return;
136  }
137 
138  // check if the incoming key triggers the activation of another tool
139  auto tool_it = shortkey_to_tool_map_.find(event->key());
140  if (tool_it != shortkey_to_tool_map_.end())
141  {
142  Tool* tool = tool_it->second;
143  // if tool matches the current tool
144  if (current_tool_ == tool)
145  {
146  // ... deactivate the current tool and fallback to default
148  }
149  else
150  {
151  // if no, check if the current tool accesses all key events
153  {
154  // if yes, pass the key
155  current_tool_->processKeyEvent(event, panel);
156  }
157  else
158  {
159  // if no, switch the tool
160  setCurrentTool(tool);
161  }
162  }
163  }
164  else if (current_tool_)
165  {
166  // if the incoming key triggers no other tool,
167  // just hand down the key event
168  current_tool_->processKeyEvent(event, panel);
169  }
170 }
171 
173 {
174  if (current_tool_)
175  {
177  }
178 
179  current_tool_ = tool;
180 
181  if (current_tool_)
182  {
184  }
185 
186  Q_EMIT toolChanged(current_tool_);
187 }
188 
190 {
191  default_tool_ = tool;
192 }
193 
195 {
196  ROS_ASSERT(index >= 0);
197  ROS_ASSERT(index < (int)tools_.size());
198 
199  return tools_[index];
200 }
201 
203 {
204  if (container->numChildren() > 0)
205  {
206  if (!property_tree_model_->getRoot()->contains(container))
207  {
208  property_tree_model_->getRoot()->addChild(container);
209  container->expand();
210  }
211  }
212  else
213  {
214  property_tree_model_->getRoot()->takeChild(container);
215  }
216 }
217 
219 {
221 }
222 
223 Tool* ToolManager::addTool(const QString& class_id)
224 {
225  QString error;
226  bool failed = false;
227  Tool* tool = factory_->make(class_id, &error);
228  if (!tool)
229  {
230  tool = new FailedTool(class_id, error);
231  failed = true;
232  }
233 
234  tools_.append(tool);
235  tool->setName(addSpaceToCamelCase(factory_->getClassName(class_id)));
236  tool->setIcon(factory_->getIcon(class_id));
237  tool->initialize(context_);
238 
239  if (tool->getShortcutKey() != '\0')
240  {
241  uint key;
242  QString str = QString(tool->getShortcutKey());
243 
244  if (toKey(str, key))
245  {
246  shortkey_to_tool_map_[key] = tool;
247  }
248  }
249 
250  Property* container = tool->getPropertyContainer();
251  connect(container, SIGNAL(childListChanged(Property*)), this,
253  updatePropertyVisibility(container);
254 
255  Q_EMIT toolAdded(tool);
256 
257  // If the default tool is unset and this tool loaded correctly, set
258  // it as the default and current.
259  if (default_tool_ == nullptr && !failed)
260  {
261  setDefaultTool(tool);
262  setCurrentTool(tool);
263  }
264 
265  QObject::connect(tool, SIGNAL(close()), this, SLOT(closeTool()));
266 
267  Q_EMIT configChanged();
268 
269  return tool;
270 }
271 
272 void ToolManager::removeTool(int index)
273 {
274  Tool* tool = tools_.takeAt(index);
275  Tool* fallback = nullptr;
276  if (!tools_.empty())
277  {
278  fallback = tools_[0];
279  }
280  if (tool == current_tool_)
281  {
282  setCurrentTool(fallback);
283  }
284  if (tool == default_tool_)
285  {
286  setDefaultTool(fallback);
287  }
288  Q_EMIT toolRemoved(tool);
289 
290  uint key;
291  if (toKey(QString(tool->getShortcutKey()), key))
292  {
293  shortkey_to_tool_map_.erase(key);
294  }
295  delete tool;
296  Q_EMIT configChanged();
297 }
298 
300 {
301  Q_EMIT toolRefreshed(tool);
302 }
303 
305 {
306  QStringList class_names;
307  for (int i = 0; i < tools_.size(); i++)
308  {
309  class_names.append(tools_[i]->getClassId());
310  }
311  return class_names;
312 }
313 
314 } // end namespace rviz
void toolChanged(Tool *)
Emitted by setCurrentTool() after the newly chosen tool is activated.
virtual void activate()=0
PluginlibFactory< Tool > * factory_
Definition: tool_manager.h:162
virtual void expand()
Expand (show the children of) this Property.
Definition: property.cpp:564
void load(const Config &config)
void setDefaultTool(Tool *tool)
Set the default tool.
bool accessAllKeys()
Definition: tool.h:86
virtual Property * getPropertyContainer() const
Return the container for properties of this Tool.
Definition: tool.h:76
A FailedTool instance represents a Tool class we tried and failed to instantiate. ...
Definition: failed_tool.h:46
void removeTool(int index)
void toolRefreshed(Tool *)
Emitted by refreshTool() to gedraw the tool&#39;s icon in the toolbar&#39;.
A single element of a property tree, with a name, value, description, and possibly children...
Definition: property.h:100
int listLength() const
Returns the length of the List in this Node, or 0 if this Node does not have type List...
Definition: config.cpp:329
bool mapGetString(const QString &key, QString *value_out) const
Convenience function for looking up a named string.
Definition: config.cpp:293
Tool * getTool(int index)
Return the tool at a given index in the Tool list. If index is less than 0 or greater than the number...
ToolManager(DisplayContext *context)
char getShortcutKey()
Definition: tool.h:81
void initialize()
Initialization for after the DisplayContext is created. Loads standard RViz tools.
void setCurrentTool(Tool *tool)
Set the current tool. The current tool is given all mouse and keyboard events which VisualizationMana...
Property * takeChild(Property *child)
Remove a given child object and return a pointer to it.
Definition: property.cpp:321
Configuration data storage class.
Definition: config.h:124
void toolRemoved(Tool *)
void configChanged()
Emitted when anything changes which will change the saved config file contents.
void updatePropertyVisibility(Property *property)
If property has children, it is added to the tool property tree, and if it does not, it is removed.
Pure-virtual base class for objects which give Display subclasses context in which to work...
void save(Config config) const
~ToolManager() override
std::map< int, Tool * > shortkey_to_tool_map_
Definition: tool_manager.h:168
QStringList getToolClasses()
void toolAdded(Tool *)
Emitted by addTool() after the tool is added to the list of tools.
Property * getRoot() const
virtual void load(const Config &config)
Load properties from the given Config.
Definition: tool.cpp:90
QList< Tool * > tools_
Definition: tool_manager.h:164
DisplayContext * context_
Definition: tool_manager.h:165
Tool * addTool(const QString &tool_class_lookup_name)
Create a tool by class lookup name, add it to the list, and return it.
PropertyTreeModel * property_tree_model_
Definition: tool_manager.h:163
void setName(const QString &name)
Set the name of the tool.
Definition: tool.cpp:72
bool toKey(QString const &str, uint &key_out)
void handleChar(QKeyEvent *event, RenderPanel *panel)
void initialize(DisplayContext *context)
Definition: tool.cpp:52
virtual int numChildren() const
Return the number of child objects (Property or otherwise).
Definition: property.h:227
void setIcon(const QIcon &icon)
Set the toolbar icon for this tool (will also set its cursor).
Definition: tool.cpp:61
void closeTool()
Deactivates the current tool and sets the default tool.
Config listAppendNew()
Ensure the referenced Node is of type List, append a new Empty Node to the end of the list...
Definition: config.cpp:346
Config listChildAt(int i) const
Return the i&#39;th child in the list, if the referenced Node has type List. Returns an Invalid Config if...
Definition: config.cpp:334
virtual void addChild(Property *child, int index=-1)
Add a child property.
Definition: property.cpp:355
void refreshTool(Tool *tool)
Triggers redrawing the tool&#39;s icon/text in the toolbar.
virtual void deactivate()=0
bool contains(Property *possible_child) const
Return true if the list of children includes possible_child, false if not.
Definition: property.cpp:218
#define ROS_ASSERT(cond)
Tool * getDefaultTool()
Get the default tool.
Definition: tool_manager.h:122
virtual int processKeyEvent(QKeyEvent *event, RenderPanel *panel)
Definition: tool.h:117
QString addSpaceToCamelCase(QString input)


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