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 
42 PropertyTreeModel::PropertyTreeModel( Property* root_property, QObject* parent )
43  : QAbstractItemModel( parent )
44  , root_property_( root_property )
45 {
46  root_property_->setModel( this );
47 }
48 
50 {
51  delete root_property_;
52 }
53 
54 Property* PropertyTreeModel::getProp( const QModelIndex& index ) const
55 {
56  if( index.isValid() )
57  {
58  Property* prop = static_cast<Property*>( index.internalPointer() );
59  if( prop )
60  {
61  return prop;
62  }
63  }
64  return root_property_;
65 }
66 
67 Qt::ItemFlags PropertyTreeModel::flags( const QModelIndex& index ) const
68 {
69  if( !index.isValid() )
70  {
72  }
73  Property* property = getProp( index );
74  return property->getViewFlags( index.column() );
75 }
76 
77 QModelIndex PropertyTreeModel::index( int row, int column, const QModelIndex& parent_index ) const
78 {
79  if( parent_index.isValid() && parent_index.column() != 0 )
80  {
81  return QModelIndex();
82  }
83  Property* parent = getProp( parent_index );
84 
85  Property* child = parent->childAt( row );
86  if( child )
87  {
88  return createIndex( row, column, child );
89  }
90  else
91  {
92  return QModelIndex();
93  }
94 }
95 
96 QModelIndex PropertyTreeModel::parent( const QModelIndex& child_index ) const
97 {
98  if( !child_index.isValid() )
99  {
100  return QModelIndex();
101  }
102  Property* child = getProp( child_index );
103  return parentIndex( child );
104 }
105 
106 QModelIndex PropertyTreeModel::parentIndex( const Property* child ) const
107 {
108  if( !child )
109  {
110  return QModelIndex();
111  }
112  Property* parent = child->getParent();
113  if( parent == root_property_ || !parent )
114  {
115  return QModelIndex();
116  }
117  return indexOf( parent );
118 }
119 
120 int PropertyTreeModel::rowCount( const QModelIndex& parent_index ) const
121 {
122  return getProp( parent_index )->numChildren();
123 }
124 
125 QVariant PropertyTreeModel::data( const QModelIndex& index, int role ) const
126 {
127  if( !index.isValid() )
128  {
129  return QVariant();
130  }
131 
132  return getProp( index )->getViewData( index.column(), role );
133 }
134 
135 QVariant PropertyTreeModel::headerData( int section, Qt::Orientation orientation, int role ) const
136 {
137  // we don't use headers.
138  return QVariant();
139 }
140 
141 bool PropertyTreeModel::setData( const QModelIndex& index, const QVariant& value, int role )
142 {
143  Property *property = getProp( index );
144 
145  if( property->getValue().type() == QVariant::Bool && role == Qt::CheckStateRole )
146  {
147  if( property->setValue( value.toInt() != Qt::Unchecked ))
148  {
149  return true;
150  }
151  }
152 
153  if( role != Qt::EditRole )
154  {
155  return false;
156  }
157 
158  if( property->setValue( value ))
159  {
160  return true;
161  }
162  return false;
163 }
164 
171 QMimeData* PropertyTreeModel::mimeData( const QModelIndexList& indexes ) const
172 {
173  if( indexes.count() <= 0 )
174  {
175  return 0;
176  }
177  QStringList types = mimeTypes();
178  if( types.isEmpty() )
179  {
180  return 0;
181  }
182  QMimeData *data = new QMimeData();
183  QString format = types.at(0);
184  QByteArray encoded;
185  QDataStream stream( &encoded, QIODevice::WriteOnly );
186 
187  QModelIndexList::ConstIterator it = indexes.begin();
188  for( ; it != indexes.end(); ++it )
189  {
190  if( (*it).column() == 0 )
191  {
192  void* pointer = (*it).internalPointer();
193  stream.writeRawData( (char*)&pointer, sizeof( void* ));
194  }
195  }
196 
197  data->setData( format, encoded );
198  return data;
199 }
200 
208 bool PropertyTreeModel::dropMimeData( const QMimeData* data,
209  Qt::DropAction action,
210  int dest_row, 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  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 
295 {
296  if( property->shouldBeSaved() )
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
virtual QVariant headerData(int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const
Property * getParent() const
Return the parent Property.
Definition: property.cpp:226
virtual QModelIndex parent(const QModelIndex &index) const
PropertyTreeModel(Property *root_property, QObject *parent=0)
Constructor.
int rowNumberInParent() const
Return the row number of this property within its parent, or -1 if it has no parent.
Definition: property.cpp:405
virtual QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const
virtual ~PropertyTreeModel()
Destructor. Deletes the root property (and thus the entire property tree).
QString drag_drop_class_
Identifier to add to mimeTypes() entry to keep drag/drops from crossing types.
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...
bool shouldBeSaved() const
Returns true if the property is not read-only AND has data worth saving.
Definition: property.h:357
virtual int rowCount(const QModelIndex &parent=QModelIndex()) const
Return the number of rows under the given parent index.
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:236
void collapse(const QModelIndex &index)
Emitted when a Property wants to collapse (hide its children).
void expand(const QModelIndex &index)
Emitted when a Property wants to expand (display its children).
void beginRemove(Property *parent_property, int row_within_parent, int count=1)
virtual int numChildren() const
Return the number of child objects (Property or otherwise).
Definition: property.h:215
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:306
QModelIndex parentIndex(const Property *child) const
Same as parent() but taking a Property pointer instead of an index.
virtual QStringList mimeTypes() const
Returns a list with just "application/x-rviz-" plus drag_drop_class_.
virtual QMimeData * mimeData(const QModelIndexList &indexes) const
Override from QAbstractItemModel. Returns a (non-standard) mime-encoded version of the given indexes...
void expandProperty(Property *property)
Expand (show the children of) the given Property.
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:197
QModelIndex indexOf(Property *property) const
virtual QVariant data(const QModelIndex &index, int role) const
void setModel(PropertyTreeModel *model)
Set the model managing this Property and all its child properties, recursively.
Definition: property.cpp:379
virtual bool setData(const QModelIndex &index, const QVariant &value, int role=Qt::EditRole)
void configChanged()
Emitted when a Property which should be saved changes.
virtual Qt::ItemFlags flags(const QModelIndex &index) const
virtual Property * takeChildAt(int index)
Take a child out of the child list, but don&#39;t destroy it.
Definition: property.cpp:328
virtual void addChild(Property *child, int index=-1)
Add a child property.
Definition: property.cpp:350
void collapseProperty(Property *property)
Collapse (hide the children of) the given Property.
virtual bool dropMimeData(const QMimeData *data, Qt::DropAction action, int destination_row, int destination_column, const QModelIndex &destination_parent)
Override from QAbstractItemModel. Takes a (non-standard) mime-encoded version of an index list and dr...
void emitDataChanged(Property *property)
void beginInsert(Property *parent_property, int row_within_parent, int count=1)
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:159
virtual Qt::ItemFlags getViewFlags(int column) const
Return item flags appropriate for the given column (0 or 1) for this Property.
Definition: property.cpp:285


rviz
Author(s): Dave Hershberger, David Gossow, Josh Faust
autogenerated on Wed Aug 28 2019 04:01:51