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 
40 
42 
43 namespace rviz
44 {
45 class FailureProperty : public Property
46 {
47 public:
48  Property* subProp(const QString& /*sub_name*/) override
49  {
50  return this;
51  }
52 };
53 
57 
58 Property::Property(const QString& name,
59  const QVariant default_value,
60  const QString& description,
61  Property* parent,
62  const char* changed_slot,
63  QObject* receiver)
64  : value_(default_value)
65  , model_(nullptr)
66  , child_indexes_valid_(false)
67  , parent_(nullptr)
68  , description_(description)
69  , hidden_(false)
70  , is_read_only_(false)
71  , save_(true)
72 {
73  setName(name);
74  if (parent)
75  {
76  parent->addChild(this);
77  }
78  if (receiver == nullptr)
79  {
80  receiver = parent;
81  }
82  if (receiver && changed_slot)
83  {
84  connect(this, SIGNAL(changed()), receiver, changed_slot);
85  }
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 {
171  description_ = description;
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::TextColorRole && 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  return getName();
253  case Qt::DecorationRole:
254  return icon_;
255  default:
256  return QVariant();
257  }
258  break;
259  case 1: // right column: values
260  switch (role)
261  {
262  case Qt::DisplayRole:
263  case Qt::EditRole:
264  return (value_.type() == QVariant::Bool ? QVariant() : getValue());
265  case Qt::CheckStateRole:
266  if (value_.type() == QVariant::Bool)
267  return (value_.toBool() ? Qt::Checked : Qt::Unchecked);
268  else
269  return QVariant();
270  default:
271  return QVariant();
272  }
273  break;
274  default:
275  return QVariant();
276  }
277 }
278 
280 {
281  // Pass down the disableChildren flag
282  if (parent_)
283  {
284  return parent_->getDisableChildren();
285  }
286  return false;
287 }
288 
289 Qt::ItemFlags Property::getViewFlags(int column) const
290 {
291  // if the parent propery is a disabled bool property or
292  // has its own enabled view flag not set, disable this property as well
293  Qt::ItemFlags enabled_flag =
294  (parent_ && parent_->getDisableChildren()) ? Qt::NoItemFlags : Qt::ItemIsEnabled;
295 
296  if (column == 0)
297  {
298  return enabled_flag | Qt::ItemIsSelectable;
299  }
300  if (value_.isValid())
301  {
302  if (value_.type() == QVariant::Bool)
303  {
304  return Qt::ItemIsUserCheckable | enabled_flag | Qt::ItemIsSelectable;
305  }
306  return Qt::ItemIsEditable | enabled_flag | Qt::ItemIsSelectable;
307  }
308  return enabled_flag | Qt::ItemIsSelectable;
309 }
310 
311 bool Property::isAncestorOf(Property* possible_child) const
312 {
313  Property* prop = possible_child->getParent();
314  while (prop != nullptr && prop != this)
315  {
316  prop = prop->getParent();
317  }
318  return prop == this;
319 }
320 
322 {
323  for (int i = 0; i < numChildren(); i++)
324  {
325  if (childAtUnchecked(i) == child)
326  {
327  return takeChildAt(i);
328  }
329  }
330  return nullptr;
331 }
332 
334 {
335  if (index < 0 || index >= children_.size())
336  {
337  return nullptr;
338  }
339  if (model_)
340  {
341  model_->beginRemove(this, index, 1);
342  }
343  Property* child = children_.takeAt(index);
344  child->setModel(nullptr);
345  child->parent_ = nullptr;
346  child_indexes_valid_ = false;
347  if (model_)
348  {
349  model_->endRemove();
350  }
351  Q_EMIT childListChanged(this);
352  return child;
353 }
354 
355 void Property::addChild(Property* child, int index)
356 {
357  if (!child)
358  {
359  return;
360  }
361  int num_children = children_.size();
362  if (index < 0 || index > num_children)
363  {
364  index = num_children;
365  }
366  if (model_)
367  {
368  model_->beginInsert(this, index);
369  }
370 
371  children_.insert(index, child);
372  child_indexes_valid_ = false;
373  child->setModel(model_);
374  child->parent_ = this;
375 
376  if (model_)
377  {
378  model_->endInsert();
379  }
380 
381  Q_EMIT childListChanged(this);
382 }
383 
385 {
386  auto it = std::lower_bound(children_.cbegin(), children_.cend(), child,
387  [](Property* element, Property* child) {
388  return element->getName() < child->getName();
389  });
390  addChild(child, it - children_.cbegin());
391 }
392 
394 {
395  model_ = model;
396  if (model_ && hidden_)
397  {
399  }
400  int num_children = numChildren();
401  for (int i = 0; i < num_children; i++)
402  {
403  Property* child = childAtUnchecked(i);
404  child->setModel(model);
405  }
406 }
407 
409 {
410  int num_children = numChildren();
411  for (int i = 0; i < num_children; i++)
412  {
413  Property* child = childAtUnchecked(i);
414  child->row_number_within_parent_ = i;
415  }
416  child_indexes_valid_ = true;
417 }
418 
420 {
421  Property* parent = getParent();
422  if (!parent)
423  {
424  return -1;
425  }
426  if (!parent->child_indexes_valid_)
427  {
428  parent->reindexChildren();
429  }
431 }
432 
433 void Property::moveChild(int from_index, int to_index)
434 {
435  children_.move(from_index, to_index);
436  child_indexes_valid_ = false;
437  Q_EMIT childListChanged(this);
438 }
439 
440 void Property::load(const Config& config)
441 {
442  if (config.getType() == Config::Value)
443  {
444  loadValue(config);
445  }
446  else if (config.getType() == Config::Map)
447  {
448  // A special map entry named "Value" means the value of this property, not a child.
449  // (If child "Value"does not exist, loadValue() will do nothing.)
450  loadValue(config.mapGetChild("Value"));
451 
452  // Loop over all child Properties.
453  int num_property_children = children_.size();
454  for (int i = 0; i < num_property_children; i++)
455  {
456  Property* child = children_.at(i);
457  // Load the child Property with the config under the child property's name.
458  child->load(config.mapGetChild(child->getName()));
459  }
460  }
461 }
462 
463 void Property::loadValue(const Config& config)
464 {
465  if (config.getType() == Config::Value)
466  {
467  switch (int(value_.type()))
468  {
469  case QVariant::Int:
470  setValue(config.getValue().toInt());
471  break;
472  case QMetaType::Float:
473  case QVariant::Double:
474  setValue(config.getValue().toDouble());
475  break;
476  case QVariant::String:
477  setValue(config.getValue().toString());
478  break;
479  case QVariant::Bool:
480  setValue(config.getValue().toBool());
481  break;
482  default:
483  printf("Property::loadValue() TODO: error handling - unexpected QVariant type %d.\n",
484  int(value_.type()));
485  break;
486  }
487  }
488 }
489 
490 void Property::save(Config config) const
491 {
492  // If there are child properties, save them in a map from names to children.
493  if (!children_.empty())
494  {
495  // If this property has child properties *and* a value itself,
496  // save the value in a special map entry named "Value".
497  if (value_.isValid())
498  {
499  config.mapSetValue("Value", value_);
500  }
501  int num_properties = children_.size();
502  for (int i = 0; i < num_properties; i++)
503  {
504  Property* prop = children_.at(i);
505  if (prop && prop->shouldBeSaved())
506  {
507  prop->save(config.mapMakeChild(prop->getName()));
508  }
509  }
510  }
511  else // Else there are no child properties, so just save the value itself.
512  {
513  if (value_.isValid())
514  {
515  config.setValue(value_);
516  }
517  else
518  {
519  // Empty Properties get saved as empty Maps instead of null values.
520  config.setType(Config::Map);
521  }
522  }
523 }
524 
525 QWidget* Property::createEditor(QWidget* parent, const QStyleOptionViewItem& /*option*/)
526 {
527  switch (int(value_.type()))
528  {
529  case QVariant::Int:
530  {
531  QSpinBox* editor = new QSpinBox(parent);
532  editor->setFrame(false);
533  editor->setRange(INT_MIN, INT_MAX);
534  return editor;
535  }
536  case QMetaType::Float:
537  case QVariant::Double:
538  {
539  FloatEdit* editor = new FloatEdit(parent);
540  return editor;
541  }
542  case QVariant::String:
543  default:
544  {
545  QLineEdit* editor = new QLineEdit(parent);
546  editor->setFrame(false);
547  return editor;
548  }
549  }
550 }
551 
552 void Property::setHidden(bool hidden)
553 {
554  if (hidden != hidden_)
555  {
556  hidden_ = hidden;
557  if (model_)
558  {
560  }
561  }
562 }
563 
565 {
566  if (model_)
567  {
568  model_->expandProperty(this);
569  }
570 }
571 
573 {
574  if (model_)
575  {
576  model_->collapseProperty(this);
577  }
578 }
579 
580 } // end namespace rviz
QList< Property * > children_
Definition: property.h:516
void setValue(const QVariant &value)
Ensures this is a valid Config object, sets the type to Value then sets the value.
Definition: config.cpp:317
QString description_
Definition: property.h:517
virtual void save(Config config) const
Write the value of this property and/or its children into the given Config reference.
Definition: property.cpp:490
virtual void expand()
Expand (show the children of) this Property.
Definition: property.cpp:564
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:48
QVariant getValue() const
If this config object is valid and is a Value type, this returns its value. Otherwise it returns an i...
Definition: config.cpp:324
void changed()
Emitted by setValue() just after the value has changed.
PropertyTreeModel * model_
Pointer to the PropertyTreeModel managing this property tree.
Definition: property.h:499
Property * getParent() const
Return the parent Property.
Definition: property.cpp:231
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:311
virtual void load(const Config &config)
Load the value of this property and/or its children from the given Config reference.
Definition: property.cpp:440
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
bool child_indexes_valid_
True if row_number_within_parent_ of all children is valid, false if not.
Definition: property.h:506
A single element of a property tree, with a name, value, description, and possibly children...
Definition: property.h:100
void childListChanged(Property *this_property)
Emitted after insertions and deletions of child Properties.
virtual void setName(const QString &name)
Set the name.
Definition: property.cpp:155
virtual bool getDisableChildren()
If true, the children of this property should set their ItemIsEnabled flag to false.
Definition: property.cpp:279
Config mapGetChild(const QString &key) const
If the referenced Node is a Map and it has a child with the given key, return a reference to the chil...
Definition: config.cpp:212
int rowNumberInParent() const
Return the row number of this property within its parent, or -1 if it has no parent.
Definition: property.cpp:419
virtual void setDescription(const QString &description)
Set the description.
Definition: property.cpp:169
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:485
void beginRemove(Property *parent_property, int row_within_parent, int count=1)
virtual QString getDescription() const
Return the description.
Definition: property.cpp:174
void mapSetValue(const QString &key, QVariant value)
Set a named child to the given value.
Definition: config.cpp:196
Property * takeChild(Property *child)
Remove a given child object and return a pointer to it.
Definition: property.cpp:321
int row_number_within_parent_
Definition: property.h:524
Configuration data storage class.
Definition: config.h:124
virtual void collapse()
Collapse (hide the children of) this Property.
Definition: property.cpp:572
void loadValue(const Config &config)
Load the value of this property specifically, not including children.
Definition: property.cpp:463
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
void reindexChildren()
Set row_number_within_parent_ correctly for every child. Sets child_indexes_valid_ to true when done...
Definition: property.cpp:408
void expandProperty(Property *property)
Expand (show the children of) the given Property.
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
static Property * failprop_
The property returned by subProp() when the requested name is not found.
Definition: property.h:522
void setParent(Property *new_parent)
Set parent property, without telling the parent.
Definition: property.cpp:236
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
void setModel(PropertyTreeModel *model)
Set the model managing this Property and all its child properties, recursively.
Definition: property.cpp:393
virtual void moveChild(int from_index, int to_index)
Move the child at from_index to to_index.
Definition: property.cpp:433
virtual Qt::ItemFlags getViewFlags(int column) const
Return item flags appropriate for the given column (0 or 1) for this Property.
Definition: property.cpp:289
virtual QString getName() const
Return the name of this Property as a QString.
Definition: property.cpp:164
Config mapMakeChild(const QString &key)
Create a child node stored with the given key, and return the child.
Definition: config.cpp:201
Property * parent_
Definition: property.h:515
bool shouldBeSaved() const
Returns true if the property is not read-only AND has data worth saving.
Definition: property.h:381
Property(const QString &name=QString(), const QVariant default_value=QVariant(), const QString &description=QString(), Property *parent=nullptr, const char *changed_slot=nullptr, QObject *receiver=nullptr)
Constructor.
Definition: property.cpp:58
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:178
void insertChildSorted(Property *child)
Insert a child property, sorted by name.
Definition: property.cpp:384
virtual Property * takeChildAt(int index)
Take a child out of the child list, but don&#39;t destroy it.
Definition: property.cpp:333
bool is_read_only_
Definition: property.h:525
virtual void setHidden(bool hidden)
Hide or show this property in any PropertyTreeWidget viewing its parent.
Definition: property.cpp:552
virtual int numChildren() const
Return the number of child objects (Property or otherwise).
Definition: property.h:227
~Property() override
Destructor. Removes this property from its parent&#39;s list of children.
Definition: property.cpp:88
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
void aboutToChange()
Emitted by setValue() just before the value has changed.
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
virtual void addChild(Property *child, int index=-1)
Add a child property.
Definition: property.cpp:355
void collapseProperty(Property *property)
Collapse (hide the children of) the given Property.
void emitDataChanged(Property *property)
void beginInsert(Property *parent_property, int row_within_parent, int count=1)
virtual QWidget * createEditor(QWidget *parent, const QStyleOptionViewItem &option)
Create an editor widget to edit the value of this property.
Definition: property.cpp:525
bool contains(Property *possible_child) const
Return true if the list of children includes possible_child, false if not.
Definition: property.cpp:218
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
void emitPropertyHiddenChanged(const Property *property)
Emit the propertyHiddenChanged() signal for the given Property.
void setType(Type new_type)
Set the type of this Config Node.
Definition: config.cpp:183


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