property_tree_model.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2012, Willow Garage, Inc.
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions are met:
00007  *
00008  *     * Redistributions of source code must retain the above copyright
00009  *       notice, this list of conditions and the following disclaimer.
00010  *     * Redistributions in binary form must reproduce the above copyright
00011  *       notice, this list of conditions and the following disclaimer in the
00012  *       documentation and/or other materials provided with the distribution.
00013  *     * Neither the name of the Willow Garage, Inc. nor the names of its
00014  *       contributors may be used to endorse or promote products derived from
00015  *       this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00018  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00021  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00022  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00023  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00024  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00025  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00026  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00027  * POSSIBILITY OF SUCH DAMAGE.
00028  */
00029 
00030 #include <stdio.h>
00031 
00032 #include <QStringList>
00033 #include <QMimeData>
00034 
00035 #include "rviz/properties/property.h"
00036 
00037 #include "rviz/properties/property_tree_model.h"
00038 
00039 namespace rviz
00040 {
00041 
00042 PropertyTreeModel::PropertyTreeModel( Property* root_property, QObject* parent )
00043   : QAbstractItemModel( parent )
00044   , root_property_( root_property )
00045 {
00046   root_property_->setModel( this );
00047 }
00048 
00049 PropertyTreeModel::~PropertyTreeModel()
00050 {
00051   delete root_property_;
00052 }
00053 
00054 Property* PropertyTreeModel::getProp( const QModelIndex& index ) const
00055 {
00056   if( index.isValid() )
00057   {
00058     Property* prop = static_cast<Property*>( index.internalPointer() );
00059     if( prop )
00060     {
00061       return prop;
00062     }
00063   }
00064   return root_property_;
00065 }
00066 
00067 Qt::ItemFlags PropertyTreeModel::flags( const QModelIndex& index ) const
00068 {
00069   if( !index.isValid() )
00070   {
00071     root_property_->getViewFlags( 0 );
00072   }
00073   Property* property = getProp( index );
00074   return property->getViewFlags( index.column() );
00075 }
00076 
00077 QModelIndex PropertyTreeModel::index( int row, int column, const QModelIndex& parent_index ) const
00078 {
00079   if( parent_index.isValid() && parent_index.column() != 0 )
00080   {
00081     return QModelIndex();
00082   }
00083   Property* parent = getProp( parent_index );
00084 
00085   Property* child = parent->childAt( row );
00086   if( child )
00087   {
00088     return createIndex( row, column, child );
00089   }
00090   else
00091   {
00092     return QModelIndex();
00093   }
00094 }
00095 
00096 QModelIndex PropertyTreeModel::parent( const QModelIndex& child_index ) const
00097 {
00098   if( !child_index.isValid() )
00099   {
00100     return QModelIndex();
00101   }
00102   Property* child = getProp( child_index );
00103   return parentIndex( child );
00104 }
00105 
00106 QModelIndex PropertyTreeModel::parentIndex( const Property* child ) const
00107 {
00108   if( !child )
00109   {
00110     return QModelIndex();
00111   }
00112   Property* parent = child->getParent();
00113   if( parent == root_property_ || !parent )
00114   {
00115     return QModelIndex();
00116   }
00117   return indexOf( parent );
00118 }
00119 
00120 int PropertyTreeModel::rowCount( const QModelIndex& parent_index ) const
00121 {
00122   return getProp( parent_index )->numChildren();
00123 }
00124 
00125 QVariant PropertyTreeModel::data( const QModelIndex& index, int role ) const
00126 {
00127   if( !index.isValid() )
00128   {
00129     return QVariant();
00130   }
00131 
00132   return getProp( index )->getViewData( index.column(), role );
00133 }
00134 
00135 QVariant PropertyTreeModel::headerData( int section, Qt::Orientation orientation, int role ) const
00136 {
00137   // we don't use headers.
00138   return QVariant();
00139 }
00140 
00141 bool PropertyTreeModel::setData( const QModelIndex& index, const QVariant& value, int role )
00142 {
00143   Property *property = getProp( index );
00144 
00145   if( property->getValue().type() == QVariant::Bool && role == Qt::CheckStateRole )
00146   {
00147     if( property->setValue( value.toInt() != Qt::Unchecked ))
00148     {
00149       return true;
00150     }
00151   }
00152 
00153   if( role != Qt::EditRole )
00154   {
00155     return false;
00156   }
00157 
00158   if( property->setValue( value ))
00159   {
00160     return true;
00161   }
00162   return false;
00163 }
00164 
00171 QMimeData* PropertyTreeModel::mimeData( const QModelIndexList& indexes ) const
00172 {
00173   if( indexes.count() <= 0 )
00174   {
00175     return 0;
00176   }
00177   QStringList types = mimeTypes();
00178   if( types.isEmpty() )
00179   {
00180     return 0;
00181   }
00182   QMimeData *data = new QMimeData();
00183   QString format = types.at(0);
00184   QByteArray encoded;
00185   QDataStream stream( &encoded, QIODevice::WriteOnly );
00186 
00187   QModelIndexList::ConstIterator it = indexes.begin();
00188   for( ; it != indexes.end(); ++it )
00189   {
00190     if( (*it).column() == 0 )
00191     {
00192       void* pointer = (*it).internalPointer();
00193       stream.writeRawData( (char*)&pointer, sizeof( void* ));
00194     }
00195   }
00196 
00197   data->setData( format, encoded );
00198   return data;
00199 }
00200 
00208 bool PropertyTreeModel::dropMimeData( const QMimeData* data,
00209                                       Qt::DropAction action,
00210                                       int dest_row, int dest_column,
00211                                       const QModelIndex& dest_parent )
00212 {
00213   if( !data || action != Qt::MoveAction )
00214   {
00215     return false;
00216   }
00217   QStringList types = mimeTypes();
00218   if( types.isEmpty() )
00219   {
00220     return false;
00221   }
00222   QString format = types.at(0);
00223   if( !data->hasFormat( format ))
00224   {
00225     return false;
00226   }
00227   QByteArray encoded = data->data( format );
00228   QDataStream stream( &encoded, QIODevice::ReadOnly );
00229 
00230   Property* dest_parent_property = getProp( dest_parent );
00231 
00232   QList<Property*> source_properties;
00233 
00234   // Decode the mime data.
00235   while( !stream.atEnd() )
00236   {
00237     void* pointer;
00238     if( sizeof( void* ) != stream.readRawData( (char*)&pointer, sizeof( void* )))
00239     {
00240       printf("ERROR: dropped mime data has invalid pointer data.\n");
00241       return false;
00242     }
00243     Property* prop = static_cast<Property*>( pointer );
00244     if( prop == dest_parent_property || prop->isAncestorOf( dest_parent_property ))
00245     {
00246       // Can't drop a row into its own child.
00247       return false;
00248     }
00249     source_properties.append( prop );
00250   }
00251 
00252   if( dest_row == -1 )
00253   {
00254     dest_row = dest_parent_property->numChildren();
00255   }
00256   for( int i = 0; i < source_properties.size(); i++ )
00257   {
00258     Property* prop = source_properties.at( i );
00259     // When moving multiple items, source indices can change.
00260     // Therefore we ask each property for its row just before we move
00261     // it.
00262     int source_row = prop->rowNumberInParent();
00263 
00264     prop->getParent()->takeChildAt( source_row );
00265 
00266     if( dest_parent_property == prop->getParent() && dest_row > source_row )
00267     {
00268       dest_row--;
00269     }
00270 
00271     dest_parent_property->addChild( prop, dest_row );
00272     dest_row++;
00273   }
00274 
00275   return true;
00276 }
00277 
00278 QStringList PropertyTreeModel::mimeTypes() const
00279 {
00280   QStringList result;
00281   result.append( "application/x-rviz-" + drag_drop_class_ );
00282   return result;
00283 }
00284 
00285 QModelIndex PropertyTreeModel::indexOf( Property* property ) const
00286 {
00287   if( property == root_property_ || !property )
00288   {
00289     return QModelIndex();
00290   }
00291   return createIndex( property->rowNumberInParent(), 0, property );
00292 }
00293 
00294 void PropertyTreeModel::emitDataChanged( Property* property )
00295 {
00296   if( property->shouldBeSaved() )
00297   {
00298     Q_EMIT configChanged();
00299   }
00300   QModelIndex left_index = indexOf( property );
00301   QModelIndex right_index = createIndex( left_index.row(), 1, left_index.internalPointer() );
00302   Q_EMIT dataChanged( left_index, right_index );
00303 }
00304 
00305 void PropertyTreeModel::beginInsert( Property* parent_property, int row_within_parent, int count )
00306 {
00307   // printf( "PropertyTreeModel::beginInsert() into %s row %d, %d rows.  Persistent indices:\n",
00308   //         qPrintable( parent_property->getName()), row_within_parent, count );
00309   // printPersistentIndices();
00310 
00311   beginInsertRows( indexOf( parent_property ), row_within_parent, row_within_parent + count - 1 );
00312 }
00313 
00314 void PropertyTreeModel::endInsert()
00315 {
00316   endInsertRows();
00317   // printf( "PropertyTreeModel::endInsert()\n" );
00318 }
00319 
00320 void PropertyTreeModel::beginRemove( Property* parent_property, int row_within_parent, int count )
00321 {
00322   // printf( "PropertyTreeModel::beginRemove() from %s row %d, %d rows.  Persistent indices:\n",
00323   //         qPrintable( parent_property->getName()), row_within_parent, count );
00324   // printPersistentIndices();
00325 
00326   beginRemoveRows( indexOf( parent_property ), row_within_parent, row_within_parent + count - 1 );
00327 }
00328 
00329 void PropertyTreeModel::endRemove()
00330 {
00331   endRemoveRows();
00332 //  printf( "PropertyTreeModel::endRemove()\n" );
00333 }
00334 
00335 void PropertyTreeModel::expandProperty( Property* property )
00336 {
00337   Q_EMIT expand( indexOf( property ));
00338 }
00339 
00340 void PropertyTreeModel::collapseProperty( Property* property )
00341 {
00342   Q_EMIT collapse( indexOf( property ));
00343 }
00344 
00345 void PropertyTreeModel::printPersistentIndices()
00346 {
00347   QModelIndexList indexes = persistentIndexList();
00348   QModelIndexList::ConstIterator it = indexes.begin();
00349   for( ; it != indexes.end(); ++it )
00350   {
00351     if( !(*it).isValid() )
00352     {
00353       printf( "  invalid index\n" );
00354     }
00355     else
00356     {
00357       Property* prop = getProp( *it );
00358       if( !prop )
00359       {
00360         printf( "  null property\n" );
00361       }
00362       else
00363       {
00364         printf( "  prop name '%s'\n", qPrintable( prop->getName() ));
00365       }
00366     }
00367   }  
00368 }
00369 
00370 } // end namespace rviz


rviz
Author(s): Dave Hershberger, David Gossow, Josh Faust
autogenerated on Mon Oct 6 2014 07:26:35