property_tree_widget.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 <QHash>
32 #include <QSet>
33 
38 
40 
41 namespace rviz
42 {
43 PropertySelectionModel::PropertySelectionModel(QAbstractItemModel* model) : QItemSelectionModel(model)
44 {
45 }
46 
47 void PropertySelectionModel::setCurrentIndex(const QModelIndex& index,
48  QItemSelectionModel::SelectionFlags command)
49 {
50  QModelIndex property_index = index.sibling(index.row(), 1);
51  if (index.flags() & Qt::ItemIsEditable || !property_index.isValid())
52  {
53  QItemSelectionModel::setCurrentIndex(index, command);
54  }
55  else
56  {
57  QItemSelectionModel::setCurrentIndex(property_index, command);
58  }
59 }
60 
62  : QTreeView(parent), model_(nullptr), splitter_handle_(new SplitterHandle(this))
63 {
64  setItemDelegateForColumn(1, new PropertyTreeDelegate(this));
65  setDropIndicatorShown(true);
66  setUniformRowHeights(true);
67  setHeaderHidden(true);
68  setDragEnabled(true);
69  setAcceptDrops(true);
70  setAnimated(true);
71  setAllColumnsShowFocus(true);
72  setSelectionMode(QAbstractItemView::ExtendedSelection);
73  setEditTriggers(QAbstractItemView::AllEditTriggers);
74 
75  QTimer* timer = new QTimer(this);
76  connect(timer, SIGNAL(timeout()), this, SLOT(update()));
77  timer->start(100);
78 }
79 
80 void PropertyTreeWidget::currentChanged(const QModelIndex& new_current_index,
81  const QModelIndex& previous_current_index)
82 {
83  QTreeView::currentChanged(new_current_index, previous_current_index);
84  Q_EMIT currentPropertyChanged(static_cast<const Property*>(new_current_index.internalPointer()));
85 }
86 
87 void PropertyTreeWidget::selectionChanged(const QItemSelection& selected,
88  const QItemSelection& deselected)
89 {
90  QTreeView::selectionChanged(selected, deselected);
91  Q_EMIT selectionHasChanged();
92 }
93 
95 {
96  if (model_)
97  {
98  disconnect(model_, SIGNAL(propertyHiddenChanged(const Property*)), this,
99  SLOT(propertyHiddenChanged(const Property*)));
100  disconnect(model_, SIGNAL(expand(const QModelIndex&)), this, SLOT(expand(const QModelIndex&)));
101  disconnect(model_, SIGNAL(collapse(const QModelIndex&)), this, SLOT(collapse(const QModelIndex&)));
102  }
103  model_ = model;
104  QTreeView::setModel(model_);
105  if (model_)
106  {
107  QItemSelectionModel* m = selectionModel();
108  setSelectionModel(new PropertySelectionModel(model_));
109  m->deleteLater();
110 
111  connect(model_, SIGNAL(propertyHiddenChanged(const Property*)), this,
112  SLOT(propertyHiddenChanged(const Property*)), Qt::QueuedConnection);
113  connect(model_, SIGNAL(expand(const QModelIndex&)), this, SLOT(expand(const QModelIndex&)));
114  connect(model_, SIGNAL(collapse(const QModelIndex&)), this, SLOT(collapse(const QModelIndex&)));
115 
116  // this will trigger all hiddenChanged events to get re-fired
118  }
119 }
120 
122 {
123  if (model_)
124  {
125  setRowHidden(property->rowNumberInParent(), model_->parentIndex(property), property->getHidden());
126  }
127 }
128 
130 {
131  saveExpandedEntries(config.mapMakeChild("Expanded"), QModelIndex(), "");
132 
133  config.mapSetValue("Splitter Ratio", splitter_handle_->getRatio());
134 }
135 
137  const QModelIndex& parent_index,
138  const QString& prefix) const
139 {
140  int num_children = model_->rowCount(parent_index);
141  if (num_children > 0)
142  {
143  QHash<QString, int> name_counts;
144  for (int i = 0; i < num_children; i++)
145  {
146  QModelIndex child_index = model_->index(i, 0, parent_index);
147  Property* child = model_->getProp(child_index);
148  QString child_name = child->getName();
149  if (qobject_cast<StatusList*>(child))
150  {
151  // StatusList objects change their name dynamically, so
152  // normalize to a standard string.
153  child_name = "Status";
154  }
155  int name_occurrence = ++(name_counts[child_name]);
156  QString full_name = prefix + "/" + child_name + QString::number(name_occurrence);
157  if (isExpanded(child_index))
158  {
159  config.listAppendNew().setValue(full_name);
160  }
161  saveExpandedEntries(config, child_index, full_name);
162  }
163  }
164 }
165 
166 void PropertyTreeWidget::load(const Config& config)
167 {
168  Config expanded_list_config = config.mapGetChild("Expanded");
169  QSet<QString> expanded_full_names;
170  int num_expanded = expanded_list_config.listLength();
171  for (int i = 0; i < num_expanded; i++)
172  {
173  expanded_full_names.insert(expanded_list_config.listChildAt(i).getValue().toString());
174  }
175  expandEntries(expanded_full_names, QModelIndex(), "");
176 
177  float ratio;
178  if (config.mapGetFloat("Splitter Ratio", &ratio))
179  {
180  splitter_handle_->setRatio(ratio);
181  }
182 }
183 
184 void PropertyTreeWidget::expandEntries(const QSet<QString>& expanded_full_names,
185  const QModelIndex& parent_index,
186  const QString& prefix)
187 {
188  int num_children = model_->rowCount(parent_index);
189  if (num_children > 0)
190  {
191  QHash<QString, int> name_counts;
192  for (int i = 0; i < num_children; i++)
193  {
194  QModelIndex child_index = model_->index(i, 0, parent_index);
195  Property* child = model_->getProp(child_index);
196  QString child_name = child->getName();
197  if (qobject_cast<StatusList*>(child))
198  {
199  child_name = "Status";
200  }
201  int name_occurrence = ++(name_counts[child_name]);
202  QString full_name = prefix + "/" + child_name + QString::number(name_occurrence);
203  if (expanded_full_names.contains(full_name))
204  {
205  setExpanded(child_index, true);
206  }
207  expandEntries(expanded_full_names, child_index, full_name);
208  }
209  }
210 }
211 
212 } // end namespace rviz
void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected) override
Called whenever selection changes. Calls QTreeView implementation then emits selectionHasChanged().
void setModel(PropertyTreeModel *model)
Set the data model this widget should view.
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
void currentChanged(const QModelIndex &current, const QModelIndex &previous) override
Called whenever current item changes. Calls QTreeView implementation then emits currentPropertyChange...
float getRatio()
Get the ratio of the parent&#39;s left column to the parent widget width.
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
QModelIndex parentIndex(const Property *child) const
Same as parent() but taking a Property pointer instead of an index.
void setCurrentIndex(const QModelIndex &index, QItemSelectionModel::SelectionFlags command) override
int rowCount(const QModelIndex &parent=QModelIndex()) const override
Return the number of rows under the given parent index.
A single element of a property tree, with a name, value, description, and possibly children...
Definition: property.h:100
PropertySelectionModel(QAbstractItemModel *model=nullptr)
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
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
A tall skinny invisible widget providing left-right sliding column separator adjustment for a two-col...
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
PropertyTreeModel * getModel() const
Return the model managing this Property and its childrent.
Definition: property.h:356
int rowNumberInParent() const
Return the row number of this property within its parent, or -1 if it has no parent.
Definition: property.cpp:419
void mapSetValue(const QString &key, QVariant value)
Set a named child to the given value.
Definition: config.cpp:196
void update(const std::string &key, const XmlRpc::XmlRpcValue &v)
Configuration data storage class.
Definition: config.h:124
void load(const Config &config)
Read state from the given Config.
void setModel(PropertyTreeModel *model)
Set the model managing this Property and all its child properties, recursively.
Definition: property.cpp:393
void currentPropertyChanged(const Property *new_current_property)
Property * getRoot() const
Property * getProp(const QModelIndex &index) const
return the Property at the given index, or the root property if the index is invalid.
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
virtual void propertyHiddenChanged(const Property *property)
bool mapGetFloat(const QString &key, float *value_out) const
Convenience function for looking up a named float.
Definition: config.cpp:256
PropertyTreeWidget(QWidget *parent=nullptr)
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
void expandEntries(const QSet< QString > &expanded_full_names, const QModelIndex &parent_index, const QString &prefix)
Recursively expand entries whose full names appear in expanded_full_names.
void setRatio(float ratio)
Set the ratio of the parent&#39;s left column to the parent widget width.
void save(Config config) const
Write state to the given Config.
void saveExpandedEntries(Config config, const QModelIndex &parent_index, const QString &prefix) const
Recursively write full names of properties which are expanded in this view to the given Config...


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