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


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