property.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 <stdio.h> // for printf()
31 #include <limits.h> // for INT_MIN and INT_MAX
32 
33 #include <QApplication>
34 #include <QPalette>
35 #include <QLineEdit>
36 #include <QSpinBox>
37 #include <QTimer>
38 
41 
43 
44 namespace rviz
45 {
46 class FailureProperty : public Property
47 {
48 public:
49  Property* subProp(const QString& /*sub_name*/) override
50  {
51  return this;
52  }
53 };
54 
57 Property* Property::failprop_ = new FailureProperty;
58 
59 Property::Property(const QString& name,
60  const QVariant& default_value,
61  const QString& description,
62  Property* parent)
63  : value_(default_value)
64  , model_(nullptr)
65  , child_indexes_valid_(false)
66  , parent_(nullptr)
67  , description_(description)
68  , hidden_(false)
69  , is_read_only_(false)
70  , save_(true)
71 {
72  Property::setName(name);
73  if (parent)
74  parent->addChild(this);
75 }
76 
77 QMetaObject::Connection
78 Property::connect(const QObject* receiver, const char* slot, Qt::ConnectionType type)
79 {
80  if (!receiver)
81  receiver = parent_;
82  if (receiver && slot)
83  return QObject::connect(this, SIGNAL(changed()), receiver, slot, type);
84  else
85  return QMetaObject::Connection();
86 }
87 
89 {
90  // Disconnect myself from my parent.
91  if (getParent())
92  {
93  getParent()->takeChild(this);
94  }
95  // Destroy my children.
96  for (int i = children_.size() - 1; i >= 0; i--)
97  {
98  Property* child = children_.takeAt(i);
99  child->setParent(nullptr);
100  delete child;
101  }
102 }
103 
104 void Property::removeChildren(int start_index, int count)
105 {
106  if (count < 0)
107  {
108  count = children_.size() - start_index;
109  }
110 
111  if (count == 0)
112  return;
113 
114  if (model_)
115  {
116  model_->beginRemove(this, start_index, count);
117  }
118  // Destroy my children.
119  for (int i = start_index; i < start_index + count; i++)
120  {
121  Property* child = children_.at(i);
122  child->setParent(nullptr); // prevent child destructor from calling getParent()->takeChild().
123  delete child;
124  }
125  children_.erase(children_.begin() + start_index, children_.begin() + start_index + count);
126  child_indexes_valid_ = false;
127  if (model_)
128  {
129  model_->endRemove();
130  }
131  Q_EMIT childListChanged(this);
132 }
133 
134 bool Property::setValue(const QVariant& new_value)
135 {
136  if (new_value != value_)
137  {
138  Q_EMIT aboutToChange();
139  value_ = new_value;
140  Q_EMIT changed();
141  if (model_)
142  {
143  model_->emitDataChanged(this);
144  }
145  return true;
146  }
147  return false;
148 }
149 
150 QVariant Property::getValue() const
151 {
152  return value_;
153 }
154 
155 void Property::setName(const QString& name)
156 {
157  setObjectName(name);
158  if (model_)
159  {
160  model_->emitDataChanged(this);
161  }
162 }
163 
164 QString Property::getName() const
165 {
166  return objectName();
167 }
168 
169 void Property::setDescription(const QString& description)
170 {
172 }
173 
175 {
176  return description_;
177 }
178 
179 Property* Property::subProp(const QString& sub_name)
180 {
181  int size = numChildren();
182  for (int i = 0; i < size; i++)
183  {
184  Property* prop = childAtUnchecked(i);
185  if (prop->getName() == sub_name)
186  {
187  return prop;
188  }
189  }
190 
191  // Print a useful error message showing the whole ancestry of this
192  // property, but don't crash.
193  QString ancestry = "";
194  for (Property* prop = this; prop != nullptr; prop = prop->getParent())
195  {
196  ancestry = "\"" + prop->getName() + "\"->" + ancestry;
197  }
198  printf("ERROR: Undefined property %s \"%s\" accessed.\n", qPrintable(ancestry), qPrintable(sub_name));
199  return failprop_;
200 }
201 
202 Property* Property::childAt(int index) const
203 {
204  // numChildren() and childAtUnchecked() can both be overridden, so
205  // call them instead of accessing our children_ list directly.
206  if (0 <= index && index < numChildren())
207  {
208  return childAtUnchecked(index);
209  }
210  return nullptr;
211 }
212 
214 {
215  return children_.at(index);
216 }
217 
218 bool Property::contains(Property* possible_child) const
219 {
220  int num_children = numChildren();
221  for (int i = 0; i < num_children; i++)
222  {
223  if (childAtUnchecked(i) == possible_child)
224  {
225  return true;
226  }
227  }
228  return false;
229 }
230 
232 {
233  return parent_;
234 }
235 
236 void Property::setParent(Property* new_parent)
237 {
238  parent_ = new_parent;
239 }
240 
241 QVariant Property::getViewData(int column, int role) const
242 {
243  if (role == Qt::ForegroundRole && parent_ && parent_->getDisableChildren())
244  return QApplication::palette().brush(QPalette::Disabled, QPalette::Text);
245 
246  switch (column)
247  {
248  case 0: // left column: names
249  switch (role)
250  {
251  case Qt::DisplayRole:
252  case Qt::EditRole:
253  return getName();
254  case Qt::DecorationRole:
255  return icon_;
256  default:
257  return QVariant();
258  }
259  break;
260  case 1: // right column: values
261  switch (role)
262  {
263  case Qt::DisplayRole:
264  case Qt::EditRole:
265  return (value_.type() == QVariant::Bool ? QVariant() : getValue());
266  case Qt::CheckStateRole:
267  if (value_.type() == QVariant::Bool)
268  return (value_.toBool() ? Qt::Checked : Qt::Unchecked);
269  else
270  return QVariant();
271  default:
272  return QVariant();
273  }
274  break;
275  default:
276  return QVariant();
277  }
278 }
279 
281 {
282  // Pass down the disableChildren flag
283  if (parent_)
284  {
285  return parent_->getDisableChildren();
286  }
287  return false;
288 }
289 
290 Qt::ItemFlags Property::getViewFlags(int column) const
291 {
292  // if the parent propery is a disabled bool property or
293  // has its own enabled view flag not set, disable this property as well
294  Qt::ItemFlags enabled_flag =
295  (parent_ && parent_->getDisableChildren()) ? Qt::NoItemFlags : Qt::ItemIsEnabled;
296 
297  if (column == 0)
298  {
299  return enabled_flag | Qt::ItemIsSelectable;
300  }
301  if (value_.isValid())
302  {
303  if (value_.type() == QVariant::Bool)
304  {
305  return Qt::ItemIsUserCheckable | enabled_flag | Qt::ItemIsSelectable;
306  }
307  return Qt::ItemIsEditable | enabled_flag | Qt::ItemIsSelectable;
308  }
309  return enabled_flag | Qt::ItemIsSelectable;
310 }
311 
312 bool Property::isAncestorOf(Property* possible_child) const
313 {
314  Property* prop = possible_child->getParent();
315  while (prop != nullptr && prop != this)
316  {
317  prop = prop->getParent();
318  }
319  return prop == this;
320 }
321 
323 {
324  for (int i = 0; i < numChildren(); i++)
325  {
326  if (childAtUnchecked(i) == child)
327  {
328  return takeChildAt(i);
329  }
330  }
331  return nullptr;
332 }
333 
335 {
336  if (index < 0 || index >= children_.size())
337  {
338  return nullptr;
339  }
340  if (model_)
341  {
342  model_->beginRemove(this, index, 1);
343  }
344  Property* child = children_.takeAt(index);
345  child->setModel(nullptr);
346  child->parent_ = nullptr;
347  child_indexes_valid_ = false;
348  if (model_)
349  {
350  model_->endRemove();
351  }
352  Q_EMIT childListChanged(this);
353  return child;
354 }
355 
356 void Property::addChild(Property* child, int index)
357 {
358  if (!child)
359  {
360  return;
361  }
362  int num_children = children_.size();
363  if (index < 0 || index > num_children)
364  {
365  index = num_children;
366  }
367  if (model_)
368  {
369  model_->beginInsert(this, index);
370  }
371 
372  children_.insert(index, child);
373  child_indexes_valid_ = false;
374  child->setModel(model_);
375  child->parent_ = this;
376 
377  if (model_)
378  {
379  model_->endInsert();
380  }
381 
382  Q_EMIT childListChanged(this);
383 }
384 
386 {
387  auto it = std::lower_bound(children_.cbegin(), children_.cend(), child,
388  [](Property* element, Property* child) {
389  return element->getName() < child->getName();
390  });
391  addChild(child, it - children_.cbegin());
392 }
393 
395 {
396  model_ = model;
397  if (model_ && hidden_)
398  {
399  // process propertyHiddenChanged after insertion into model has finished
400  QTimer::singleShot(0, this, [this]() { model_->emitPropertyHiddenChanged(this); });
401  }
402  int num_children = numChildren();
403  for (int i = 0; i < num_children; i++)
404  {
405  Property* child = childAtUnchecked(i);
406  child->setModel(model);
407  }
408 }
409 
411 {
412  int num_children = numChildren();
413  for (int i = 0; i < num_children; i++)
414  {
415  Property* child = childAtUnchecked(i);
416  child->row_number_within_parent_ = i;
417  }
418  child_indexes_valid_ = true;
419 }
420 
422 {
423  Property* parent = getParent();
424  if (!parent)
425  {
426  return -1;
427  }
428  if (!parent->child_indexes_valid_)
429  {
430  parent->reindexChildren();
431  }
433 }
434 
435 void Property::moveChild(int from_index, int to_index)
436 {
437  children_.move(from_index, to_index);
438  child_indexes_valid_ = false;
439  Q_EMIT childListChanged(this);
440 }
441 
442 void Property::load(const Config& config)
443 {
444  if (config.getType() == Config::Value)
445  {
446  loadValue(config);
447  }
448  else if (config.getType() == Config::Map)
449  {
450  // A special map entry named "Value" means the value of this property, not a child.
451  // (If child "Value"does not exist, loadValue() will do nothing.)
452  loadValue(config.mapGetChild("Value"));
453 
454  // Loop over all child Properties.
455  int num_property_children = children_.size();
456  for (int i = 0; i < num_property_children; i++)
457  {
458  Property* child = children_.at(i);
459  // Load the child Property with the config under the child property's name.
460  child->load(config.mapGetChild(child->getName()));
461  }
462  }
463 }
464 
465 void Property::loadValue(const Config& config)
466 {
467  if (config.getType() == Config::Value)
468  {
469  switch (int(value_.type()))
470  {
471  case QVariant::Int:
472  setValue(config.getValue().toInt());
473  break;
474  case QMetaType::Float:
475  case QVariant::Double:
476  setValue(config.getValue().toDouble());
477  break;
478  case QVariant::String:
479  setValue(config.getValue().toString());
480  break;
481  case QVariant::Bool:
482  setValue(config.getValue().toBool());
483  break;
484  default:
485  printf("Property::loadValue() TODO: error handling - unexpected QVariant type %d.\n",
486  int(value_.type()));
487  break;
488  }
489  }
490 }
491 
492 void Property::save(Config config) const
493 {
494  // If there are child properties, save them in a map from names to children.
495  if (!children_.empty())
496  {
497  bool valid = false;
498  // If this property has child properties *and* a value itself,
499  // save the value in a special map entry named "Value".
500  if (!is_read_only_ && value_.isValid())
501  {
502  config.mapSetValue("Value", value_);
503  valid = true;
504  }
505  int num_properties = children_.size();
506  for (int i = 0; i < num_properties; i++)
507  {
508  Property* prop = children_.at(i);
509  if (prop && prop->shouldBeSaved())
510  {
511  Config child = config.mapMakeChild(prop->getName());
512  prop->save(child);
513  if (child.getType() == Config::Invalid)
514  // if child property didn't save anything, remove it again
515  config.mapRemoveChild(prop->getName());
516  else
517  valid = true;
518  }
519  }
520  if (!valid)
521  // if we didn't save anything in this property, mark the config as invalid
522  config.setType(Config::Invalid);
523  }
524  // Else (there are no child properties), just save the value itself if it's not read-only
525  else if (!is_read_only_)
526  {
527  if (value_.isValid())
528  {
529  config.setValue(value_);
530  }
531  else
532  {
533  // Empty Properties get saved as empty Maps instead of null values.
534  config.setType(Config::Map);
535  }
536  }
537 }
538 
539 QWidget* Property::createEditor(QWidget* parent, const QStyleOptionViewItem& /*option*/)
540 {
541  switch (int(value_.type()))
542  {
543  case QVariant::Int:
544  {
545  QSpinBox* editor = new QSpinBox(parent);
546  editor->setFrame(false);
547  editor->setRange(INT_MIN, INT_MAX);
548  return editor;
549  }
550  case QMetaType::Float:
551  case QVariant::Double:
552  {
553  FloatEdit* editor = new FloatEdit(parent);
554  return editor;
555  }
556  case QVariant::String:
557  default:
558  {
559  QLineEdit* editor = new QLineEdit(parent);
560  editor->setFrame(false);
561  return editor;
562  }
563  }
564 }
565 
566 void Property::setHidden(bool hidden)
567 {
568  if (hidden != hidden_)
569  {
570  hidden_ = hidden;
571  if (model_)
572  {
574  }
575  }
576 }
577 
579 {
580  if (model_)
581  {
582  model_->expandProperty(this);
583  }
584 }
585 
587 {
588  if (model_)
589  {
590  model_->collapseProperty(this);
591  }
592 }
593 
594 } // end namespace rviz
rviz::Property::insertChildSorted
void insertChildSorted(Property *child)
Insert a child property, sorted by name.
Definition: property.cpp:385
rviz::PropertyTreeModel::emitPropertyHiddenChanged
void emitPropertyHiddenChanged(const Property *property)
Emit the propertyHiddenChanged() signal for the given Property.
Definition: property_tree_model.h:135
rviz::Property::childAt
Property * childAt(int index) const
Return the child Property with the given index, or NULL if the index is out of bounds or if the child...
Definition: property.cpp:202
rviz::Property::setHidden
virtual void setHidden(bool hidden)
Hide or show this property in any PropertyTreeWidget viewing its parent.
Definition: property.cpp:566
rviz::Property::setName
virtual void setName(const QString &name)
Set the name.
Definition: property.cpp:155
rviz::Property::failprop_
static Property * failprop_
The property returned by subProp() when the requested name is not found.
Definition: property.h:583
rviz::PropertyTreeModel::expandProperty
void expandProperty(Property *property)
Expand (show the children of) the given Property.
Definition: property_tree_model.cpp:335
rviz::PropertyTreeModel
Definition: property_tree_model.h:38
rviz::Property::getViewData
virtual QVariant getViewData(int column, int role) const
Return data appropriate for the given column (0 or 1) and role for this Property.
Definition: property.cpp:241
rviz::PropertyTreeModel::endInsert
void endInsert()
Definition: property_tree_model.cpp:314
property.h
description
description
rviz::Property::addChild
virtual void addChild(Property *child, int index=-1)
Add a child property.
Definition: property.cpp:356
rviz::Property::row_number_within_parent_
int row_number_within_parent_
Definition: property.h:585
rviz::Property::collapse
virtual void collapse()
Collapse (hide the children of) this Property.
Definition: property.cpp:586
rviz::Property::is_read_only_
bool is_read_only_
Definition: property.h:586
rviz::Property::shouldBeSaved
bool shouldBeSaved() const
Returns true if the property has data worth saving.
Definition: property.h:441
rviz::Property::subProp
virtual Property * subProp(const QString &sub_name)
Return the first child Property with the given name, or the FailureProperty if no child has the name.
Definition: property.cpp:179
rviz::FailureProperty::subProp
Property * subProp(const QString &) override
Return the first child Property with the given name, or the FailureProperty if no child has the name.
Definition: property.cpp:49
rviz::Property::numChildren
virtual int numChildren() const
Return the number of child objects (Property or otherwise).
Definition: property.h:287
rviz::FailureProperty
Definition: property.cpp:46
rviz::Property::contains
bool contains(Property *possible_child) const
Return true if the list of children includes possible_child, false if not.
Definition: property.cpp:218
rviz::Property::getValue
virtual QVariant getValue() const
Return the value of this Property as a QVariant. If the value has never been set, an invalid QVariant...
Definition: property.cpp:150
rviz::Property::Property
Property(const QString &name=QString(), const QVariant &default_value=QVariant(), const QString &description=QString(), Property *parent=nullptr)
Constructor.
Definition: property.cpp:59
rviz::Property::description_
QString description_
Definition: property.h:578
rviz::PropertyTreeModel::collapseProperty
void collapseProperty(Property *property)
Collapse (hide the children of) the given Property.
Definition: property_tree_model.cpp:340
rviz::Property::connect
QMetaObject::Connection connect(const QObject *receiver, const char *slot, Qt::ConnectionType type=Qt::AutoConnection)
Connect changed() signal to given slot of receiver.
Definition: property.cpp:78
rviz::Property::~Property
~Property() override
Destructor. Removes this property from its parent's list of children.
Definition: property.cpp:88
rviz::Property
A single element of a property tree, with a name, value, description, and possibly children.
Definition: property.h:100
rviz::PropertyTreeModel::emitDataChanged
void emitDataChanged(Property *property, bool emit_config_changed=true)
Definition: property_tree_model.cpp:294
rviz::Property::parent_
Property * parent_
Definition: property.h:576
float_edit.h
rviz::Property::createEditor
virtual QWidget * createEditor(QWidget *parent, const QStyleOptionViewItem &option)
Create an editor widget to edit the value of this property.
Definition: property.cpp:539
rviz::Property::expand
virtual void expand()
Expand (show the children of) this Property.
Definition: property.cpp:578
rviz::Property::setValue
virtual bool setValue(const QVariant &new_value)
Set the new value for this property. Returns true if the new value is different from the old value,...
Definition: property.cpp:134
rviz
Definition: add_display_dialog.cpp:54
rviz::PropertyTreeModel::endRemove
void endRemove()
Definition: property_tree_model.cpp:329
rviz::Property::hidden_
bool hidden_
Definition: property.h:579
rviz::Property::takeChildAt
virtual Property * takeChildAt(int index)
Take a child out of the child list, but don't destroy it.
Definition: property.cpp:334
rviz::Property::model_
PropertyTreeModel * model_
Pointer to the PropertyTreeModel managing this property tree.
Definition: property.h:560
property_tree_model.h
rviz::Property::childListChanged
void childListChanged(Property *this_property)
Emitted after insertions and deletions of child Properties.
rviz::Config::Value
@ Value
Definition: config.h:152
rviz::Property::getParent
Property * getParent() const
Return the parent Property.
Definition: property.cpp:231
rviz::PropertyTreeModel::beginInsert
void beginInsert(Property *parent_property, int row_within_parent, int count=1)
Definition: property_tree_model.cpp:305
rviz::Property::child_indexes_valid_
bool child_indexes_valid_
True if row_number_within_parent_ of all children is valid, false if not.
Definition: property.h:567
rviz::Property::rowNumberInParent
int rowNumberInParent() const
Return the row number of this property within its parent, or -1 if it has no parent.
Definition: property.cpp:421
rviz::Property::setDescription
virtual void setDescription(const QString &description)
Set the description.
Definition: property.cpp:169
rviz::PropertyTreeModel::beginRemove
void beginRemove(Property *parent_property, int row_within_parent, int count=1)
Definition: property_tree_model.cpp:320
rviz::Property::getViewFlags
virtual Qt::ItemFlags getViewFlags(int column) const
Return item flags appropriate for the given column (0 or 1) for this Property.
Definition: property.cpp:290
rviz::Config::getType
Type getType() const
Return the Type of the referenced Node, or Invalid if this Config does not refer to a Node at all.
Definition: config.cpp:172
rviz::Property::getName
virtual QString getName() const
Return the name of this Property as a QString.
Definition: property.cpp:164
rviz::Property::getDescription
virtual QString getDescription() const
Return the description.
Definition: property.cpp:174
rviz::Property::isAncestorOf
bool isAncestorOf(Property *possible_child) const
Returns true if this is an ancestor of possible_child, meaning is the parent or parent of parent etc.
Definition: property.cpp:312
rviz::Property::setParent
void setParent(Property *new_parent)
Set parent property, without telling the parent.
Definition: property.cpp:236
rviz::Property::children_
QList< Property * > children_
Definition: property.h:577
rviz::Config::Invalid
@ Invalid
Definition: config.h:154
default_value
def default_value(type_)
rviz::Config::Map
@ Map
Definition: config.h:150
rviz::Property::changed
void changed()
Emitted by setValue() just after the value has changed.
rviz::Property::save
virtual void save(Config config) const
Write the value of this property and/or its children into the given Config reference.
Definition: property.cpp:492
rviz::Property::loadValue
void loadValue(const Config &config)
Load the value of this property specifically, not including children.
Definition: property.cpp:465
rviz::FloatEdit
Definition: float_edit.h:36
rviz::Property::reindexChildren
void reindexChildren()
Set row_number_within_parent_ correctly for every child. Sets child_indexes_valid_ to true when done.
Definition: property.cpp:410
rviz::Property::icon_
QIcon icon_
Definition: property.h:569
rviz::Property::removeChildren
virtual void removeChildren(int start_index=0, int count=-1)
Remove and delete some or all child Properties. Does not change the value of this Property.
Definition: property.cpp:104
rviz::Property::value_
QVariant value_
This is the central property value. If you set it directly in a subclass, do so with care because man...
Definition: property.h:546
rviz::Property::childAtUnchecked
virtual Property * childAtUnchecked(int index) const
Return the child Property with the given index, without checking whether the index is within bounds.
Definition: property.cpp:213
rviz::Property::aboutToChange
void aboutToChange()
Emitted by setValue() just before the value has changed.
rviz::Property::getDisableChildren
virtual bool getDisableChildren()
If true, the children of this property should set their ItemIsEnabled flag to false.
Definition: property.cpp:280
config
config
rviz::Property::takeChild
Property * takeChild(Property *child)
Remove a given child object and return a pointer to it.
Definition: property.cpp:322
rviz::Property::load
virtual void load(const Config &config)
Load the value of this property and/or its children from the given Config reference.
Definition: property.cpp:442
rviz::Config
Configuration data storage class.
Definition: config.h:124
rviz::Property::moveChild
virtual void moveChild(int from_index, int to_index)
Move the child at from_index to to_index.
Definition: property.cpp:435
rviz::Property::setModel
void setModel(PropertyTreeModel *model)
Set the model managing this Property and all its child properties, recursively.
Definition: property.cpp:394


rviz
Author(s): Dave Hershberger, David Gossow, Josh Faust, William Woodall
autogenerated on Fri Dec 13 2024 03:31:02