property_tree_model.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>
31 
32 #include <QIODevice>
33 #include <QStringList>
34 #include <QMimeData>
35 
37 
39 
40 namespace rviz
41 {
42 PropertyTreeModel::PropertyTreeModel(Property* root_property, QObject* parent)
43  : QAbstractItemModel(parent), root_property_(root_property)
44 {
45  root_property_->setModel(this);
46 }
47 
49 {
50  delete root_property_;
51 }
52 
53 Property* PropertyTreeModel::getProp(const QModelIndex& index) const
54 {
55  if (index.isValid())
56  {
57  Property* prop = static_cast<Property*>(index.internalPointer());
58  if (prop)
59  {
60  return prop;
61  }
62  }
63  return root_property_;
64 }
65 
66 Qt::ItemFlags PropertyTreeModel::flags(const QModelIndex& index) const
67 {
68  if (!index.isValid())
69  {
71  }
72  Property* property = getProp(index);
73  return property->getViewFlags(index.column());
74 }
75 
76 QModelIndex PropertyTreeModel::index(int row, int column, const QModelIndex& parent_index) const
77 {
78  if (parent_index.isValid() && parent_index.column() != 0)
79  {
80  return QModelIndex();
81  }
82  Property* parent = getProp(parent_index);
83 
84  Property* child = parent->childAt(row);
85  if (child)
86  {
87  return createIndex(row, column, child);
88  }
89  else
90  {
91  return QModelIndex();
92  }
93 }
94 
95 QModelIndex PropertyTreeModel::parent(const QModelIndex& child_index) const
96 {
97  if (!child_index.isValid())
98  {
99  return QModelIndex();
100  }
101  Property* child = getProp(child_index);
102  return parentIndex(child);
103 }
104 
105 QModelIndex PropertyTreeModel::parentIndex(const Property* child) const
106 {
107  if (!child)
108  {
109  return QModelIndex();
110  }
111  Property* parent = child->getParent();
112  return indexOf(parent);
113 }
114 
115 int PropertyTreeModel::rowCount(const QModelIndex& parent_index) const
116 {
117  return getProp(parent_index)->numChildren();
118 }
119 
120 QVariant PropertyTreeModel::data(const QModelIndex& index, int role) const
121 {
122  if (!index.isValid())
123  {
124  return QVariant();
125  }
126 
127  return getProp(index)->getViewData(index.column(), role);
128 }
129 
130 QVariant
131 PropertyTreeModel::headerData(int /*section*/, Qt::Orientation /*orientation*/, int /*role*/) const
132 {
133  // we don't use headers.
134  return QVariant();
135 }
136 
137 bool PropertyTreeModel::setData(const QModelIndex& index, const QVariant& value, int role)
138 {
139  Property* property = getProp(index);
140 
141  if (property->getValue().type() == QVariant::Bool && role == Qt::CheckStateRole)
142  {
143  if (property->setValue(value.toInt() != Qt::Unchecked))
144  {
145  return true;
146  }
147  }
148 
149  if (role != Qt::EditRole)
150  {
151  return false;
152  }
153 
154  if (index.column() != 0)
155  return property->setValue(value);
156  else if (value.type() == QVariant::String)
157  {
158  property->setName(value.toString());
159  return true;
160  }
161  return false;
162 }
163 
170 QMimeData* PropertyTreeModel::mimeData(const QModelIndexList& indexes) const
171 {
172  if (indexes.count() <= 0)
173  {
174  return nullptr;
175  }
176  QStringList types = mimeTypes();
177  if (types.isEmpty())
178  {
179  return nullptr;
180  }
181  QMimeData* data = new QMimeData();
182  const QString& format = types.at(0);
183  QByteArray encoded;
184  QDataStream stream(&encoded, QIODevice::WriteOnly);
185 
186  QModelIndexList::ConstIterator it = indexes.begin();
187  for (; it != indexes.end(); ++it)
188  {
189  if ((*it).column() == 0)
190  {
191  void* pointer = (*it).internalPointer();
192  stream.writeRawData((char*)&pointer, sizeof(void*));
193  }
194  }
195 
196  data->setData(format, encoded);
197  return data;
198 }
199 
207 bool PropertyTreeModel::dropMimeData(const QMimeData* data,
208  Qt::DropAction action,
209  int dest_row,
210  int /*dest_column*/,
211  const QModelIndex& dest_parent)
212 {
213  if (!data || action != Qt::MoveAction)
214  {
215  return false;
216  }
217  QStringList types = mimeTypes();
218  if (types.isEmpty())
219  {
220  return false;
221  }
222  const QString& format = types.at(0);
223  if (!data->hasFormat(format))
224  {
225  return false;
226  }
227  QByteArray encoded = data->data(format);
228  QDataStream stream(&encoded, QIODevice::ReadOnly);
229 
230  Property* dest_parent_property = getProp(dest_parent);
231 
232  QList<Property*> source_properties;
233 
234  // Decode the mime data.
235  while (!stream.atEnd())
236  {
237  void* pointer;
238  if (sizeof(void*) != stream.readRawData((char*)&pointer, sizeof(void*)))
239  {
240  printf("ERROR: dropped mime data has invalid pointer data.\n");
241  return false;
242  }
243  Property* prop = static_cast<Property*>(pointer);
244  if (prop == dest_parent_property || prop->isAncestorOf(dest_parent_property))
245  {
246  // Can't drop a row into its own child.
247  return false;
248  }
249  source_properties.append(prop);
250  }
251 
252  if (dest_row == -1)
253  {
254  dest_row = dest_parent_property->numChildren();
255  }
256  for (int i = 0; i < source_properties.size(); i++)
257  {
258  Property* prop = source_properties.at(i);
259  // When moving multiple items, source indices can change.
260  // Therefore we ask each property for its row just before we move
261  // it.
262  int source_row = prop->rowNumberInParent();
263 
264  prop->getParent()->takeChildAt(source_row);
265 
266  if (dest_parent_property == prop->getParent() && dest_row > source_row)
267  {
268  dest_row--;
269  }
270 
271  dest_parent_property->addChild(prop, dest_row);
272  dest_row++;
273  }
274 
275  return true;
276 }
277 
278 QStringList PropertyTreeModel::mimeTypes() const
279 {
280  QStringList result;
281  result.append("application/x-rviz-" + drag_drop_class_);
282  return result;
283 }
284 
285 QModelIndex PropertyTreeModel::indexOf(Property* property) const
286 {
287  if (property == root_property_ || !property)
288  {
289  return QModelIndex();
290  }
291  return createIndex(property->rowNumberInParent(), 0, property);
292 }
293 
294 void PropertyTreeModel::emitDataChanged(Property* property, bool emit_config_changed)
295 {
296  if (emit_config_changed && property->shouldBeSaved() && !property->getReadOnly())
297  {
298  Q_EMIT configChanged();
299  }
300  QModelIndex left_index = indexOf(property);
301  QModelIndex right_index = createIndex(left_index.row(), 1, left_index.internalPointer());
302  Q_EMIT dataChanged(left_index, right_index);
303 }
304 
305 void PropertyTreeModel::beginInsert(Property* parent_property, int row_within_parent, int count)
306 {
307  // printf( "PropertyTreeModel::beginInsert() into %s row %d, %d rows. Persistent indices:\n",
308  // qPrintable( parent_property->getName()), row_within_parent, count );
309  // printPersistentIndices();
310 
311  beginInsertRows(indexOf(parent_property), row_within_parent, row_within_parent + count - 1);
312 }
313 
315 {
316  endInsertRows();
317  // printf( "PropertyTreeModel::endInsert()\n" );
318 }
319 
320 void PropertyTreeModel::beginRemove(Property* parent_property, int row_within_parent, int count)
321 {
322  // printf( "PropertyTreeModel::beginRemove() from %s row %d, %d rows. Persistent indices:\n",
323  // qPrintable( parent_property->getName()), row_within_parent, count );
324  // printPersistentIndices();
325 
326  beginRemoveRows(indexOf(parent_property), row_within_parent, row_within_parent + count - 1);
327 }
328 
330 {
331  endRemoveRows();
332  // printf( "PropertyTreeModel::endRemove()\n" );
333 }
334 
336 {
337  Q_EMIT expand(indexOf(property));
338 }
339 
341 {
342  Q_EMIT collapse(indexOf(property));
343 }
344 
346 {
347  QModelIndexList indexes = persistentIndexList();
348  QModelIndexList::ConstIterator it = indexes.begin();
349  for (; it != indexes.end(); ++it)
350  {
351  if (!(*it).isValid())
352  {
353  printf(" invalid index\n");
354  }
355  else
356  {
357  Property* prop = getProp(*it);
358  if (!prop)
359  {
360  printf(" null property\n");
361  }
362  else
363  {
364  printf(" prop name '%s'\n", qPrintable(prop->getName()));
365  }
366  }
367  }
368 }
369 
370 } // end namespace rviz
rviz::PropertyTreeModel::setData
bool setData(const QModelIndex &index, const QVariant &value, int role=Qt::EditRole) override
Definition: property_tree_model.cpp:137
rviz::PropertyTreeModel::headerData
QVariant headerData(int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const override
Definition: property_tree_model.cpp:131
rviz::PropertyTreeModel::expand
void expand(const QModelIndex &index)
Emitted when a Property wants to expand (display its children).
rviz::PropertyTreeModel::collapse
void collapse(const QModelIndex &index)
Emitted when a Property wants to collapse (hide its children).
rviz::PropertyTreeModel::expandProperty
void expandProperty(Property *property)
Expand (show the children of) the given Property.
Definition: property_tree_model.cpp:335
rviz::PropertyTreeModel::dropMimeData
bool dropMimeData(const QMimeData *data, Qt::DropAction action, int destination_row, int destination_column, const QModelIndex &destination_parent) override
Override from QAbstractItemModel. Takes a (non-standard) mime-encoded version of an index list and dr...
Definition: property_tree_model.cpp:207
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
rviz::PropertyTreeModel::~PropertyTreeModel
~PropertyTreeModel() override
Destructor. Deletes the root property (and thus the entire property tree).
Definition: property_tree_model.cpp:48
rviz::PropertyTreeModel::getProp
Property * getProp(const QModelIndex &index) const
return the Property at the given index, or the root property if the index is invalid.
Definition: property_tree_model.cpp:53
rviz::Property::addChild
virtual void addChild(Property *child, int index=-1)
Add a child property.
Definition: property.cpp:356
rviz::Property::shouldBeSaved
bool shouldBeSaved() const
Returns true if the property has data worth saving.
Definition: property.h:441
rviz::Property::numChildren
virtual int numChildren() const
Return the number of child objects (Property or otherwise).
Definition: property.h:287
rviz::PropertyTreeModel::parentIndex
QModelIndex parentIndex(const Property *child) const
Same as parent() but taking a Property pointer instead of an index.
Definition: property_tree_model.cpp:105
rviz::PropertyTreeModel::rowCount
int rowCount(const QModelIndex &parent=QModelIndex()) const override
Return the number of rows under the given parent index.
Definition: property_tree_model.cpp:115
rviz::PropertyTreeModel::collapseProperty
void collapseProperty(Property *property)
Collapse (hide the children of) the given Property.
Definition: property_tree_model.cpp:340
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
Definition: add_display_dialog.cpp:54
rviz::PropertyTreeModel::configChanged
void configChanged()
Emitted when a Property which should be saved changes.
rviz::PropertyTreeModel::endRemove
void endRemove()
Definition: property_tree_model.cpp:329
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::PropertyTreeModel::parent
QModelIndex parent(const QModelIndex &index) const override
Definition: property_tree_model.cpp:95
rviz::PropertyTreeModel::indexOf
QModelIndex indexOf(Property *property) const
Definition: property_tree_model.cpp:285
rviz::PropertyTreeModel::index
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
Definition: property_tree_model.cpp:76
property_tree_model.h
rviz::Property::getParent
Property * getParent() const
Return the parent Property.
Definition: property.cpp:231
rviz::PropertyTreeModel::printPersistentIndices
void printPersistentIndices()
For debugging only. Uses printf() to print the property names of current persistent indices.
Definition: property_tree_model.cpp:345
rviz::PropertyTreeModel::beginInsert
void beginInsert(Property *parent_property, int row_within_parent, int count=1)
Definition: property_tree_model.cpp:305
rviz::PropertyTreeModel::root_property_
Property * root_property_
Definition: property_tree_model.h:164
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::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::PropertyTreeModel::mimeTypes
QStringList mimeTypes() const override
Returns a list with just "application/x-rviz-" plus drag_drop_class_.
Definition: property_tree_model.cpp:278
rviz::Property::getName
virtual QString getName() const
Return the name of this Property as a QString.
Definition: property.cpp:164
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::PropertyTreeModel::flags
Qt::ItemFlags flags(const QModelIndex &index) const override
Definition: property_tree_model.cpp:66
rviz::PropertyTreeModel::mimeData
QMimeData * mimeData(const QModelIndexList &indexes) const override
Override from QAbstractItemModel. Returns a (non-standard) mime-encoded version of the given indexes.
Definition: property_tree_model.cpp:170
rviz::PropertyTreeModel::data
QVariant data(const QModelIndex &index, int role) const override
Definition: property_tree_model.cpp:120
rviz::PropertyTreeModel::PropertyTreeModel
PropertyTreeModel(Property *root_property, QObject *parent=nullptr)
Constructor.
Definition: property_tree_model.cpp:42
rviz::PropertyTreeModel::drag_drop_class_
QString drag_drop_class_
Definition: property_tree_model.h:165
rviz::Property::setModel
void setModel(PropertyTreeModel *model)
Set the model managing this Property and all its child properties, recursively.
Definition: property.cpp:394
rviz::Property::getReadOnly
virtual bool getReadOnly() const
Return the read-only-ness of this property.
Definition: property.h:504


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