Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include <stdio.h>
00031 #include <limits.h>
00032
00033 #include <QLineEdit>
00034 #include <QSpinBox>
00035
00036 #include "rviz/properties/float_edit.h"
00037 #include "rviz/properties/property_tree_model.h"
00038
00039 #include "rviz/properties/property.h"
00040
00041 namespace rviz
00042 {
00043
00044 class FailureProperty: public Property
00045 {
00046 public:
00047 virtual Property* subProp( const QString& sub_name ) { return this; }
00048 };
00049
00052 Property* Property::failprop_ = new FailureProperty;
00053
00054 Property::Property( const QString& name,
00055 const QVariant default_value,
00056 const QString& description,
00057 Property* parent,
00058 const char *changed_slot,
00059 QObject* receiver )
00060 : value_( default_value )
00061 , model_( 0 )
00062 , child_indexes_valid_( false )
00063 , parent_( 0 )
00064 , description_( description )
00065 , hidden_( false )
00066 , is_read_only_( false )
00067 , save_( true )
00068 {
00069 setName( name );
00070 if( parent )
00071 {
00072 parent->addChild( this );
00073 }
00074 if( receiver == 0 )
00075 {
00076 receiver = parent;
00077 }
00078 if( receiver && changed_slot )
00079 {
00080 connect( this, SIGNAL( changed() ), receiver, changed_slot );
00081 }
00082 }
00083
00084 Property::~Property()
00085 {
00086
00087 if( getParent() )
00088 {
00089 getParent()->takeChild( this );
00090 }
00091
00092 for( int i = children_.size() - 1; i >= 0; i-- )
00093 {
00094 Property* child = children_.takeAt( i );
00095 child->setParent( NULL );
00096 delete child;
00097 }
00098 }
00099
00100 void Property::removeChildren( int start_index, int count )
00101 {
00102 if( count < 0 )
00103 {
00104 count = children_.size() - start_index;
00105 }
00106
00107 if( model_ )
00108 {
00109 model_->beginRemove( this, start_index, count );
00110 }
00111
00112 for( int i = start_index; i < start_index + count; i++ )
00113 {
00114 Property* child = children_.at( i );
00115 child->setParent( NULL );
00116 delete child;
00117 }
00118 children_.erase( children_.begin() + start_index, children_.begin() + start_index + count );
00119 child_indexes_valid_ = false;
00120 if( model_ )
00121 {
00122 model_->endRemove();
00123 }
00124 Q_EMIT childListChanged( this );
00125 }
00126
00127 bool Property::setValue( const QVariant& new_value )
00128 {
00129 if( new_value != value_ ) {
00130 Q_EMIT aboutToChange();
00131 value_ = new_value;
00132 Q_EMIT changed();
00133 if( model_ )
00134 {
00135 model_->emitDataChanged( this );
00136 }
00137 return true;
00138 }
00139 return false;
00140 }
00141
00142 QVariant Property::getValue() const
00143 {
00144 return value_;
00145 }
00146
00147 void Property::setName( const QString& name )
00148 {
00149 setObjectName( name );
00150 if( model_ )
00151 {
00152 model_->emitDataChanged( this );
00153 }
00154 }
00155
00156 QString Property::getName() const
00157 {
00158 return objectName();
00159 }
00160
00161 void Property::setDescription( const QString& description )
00162 {
00163 description_ = description;
00164 }
00165
00166 QString Property::getDescription() const
00167 {
00168 return description_;
00169 }
00170
00171 Property* Property::subProp( const QString& sub_name )
00172 {
00173 int size = numChildren();
00174 for( int i = 0; i < size; i++ )
00175 {
00176 Property* prop = childAtUnchecked( i );
00177 if( prop->getName() == sub_name )
00178 {
00179 return prop;
00180 }
00181 }
00182
00183
00184
00185 QString ancestry = "";
00186 for( Property* prop = this; prop != NULL; prop = prop->getParent() )
00187 {
00188 ancestry = "\"" + prop->getName() + "\"->" + ancestry;
00189 }
00190 printf( "ERROR: Undefined property %s \"%s\" accessed.\n", qPrintable( ancestry ), qPrintable( sub_name ));
00191 return failprop_;
00192 }
00193
00194 Property* Property::childAt( int index ) const
00195 {
00196
00197
00198 if( 0 <= index && index < numChildren() )
00199 {
00200 return childAtUnchecked( index );
00201 }
00202 return NULL;
00203 }
00204
00205 Property* Property::childAtUnchecked( int index ) const
00206 {
00207 return children_.at( index );
00208 }
00209
00210 bool Property::contains( Property* possible_child ) const
00211 {
00212 int num_children = numChildren();
00213 for( int i = 0; i < num_children; i++ )
00214 {
00215 if( childAtUnchecked( i ) == possible_child )
00216 {
00217 return true;
00218 }
00219 }
00220 return false;
00221 }
00222
00223 Property* Property::getParent() const
00224 {
00225 return parent_;
00226 }
00227
00228 void Property::setParent( Property* new_parent )
00229 {
00230 parent_ = new_parent;
00231 }
00232
00233 QVariant Property::getViewData( int column, int role ) const
00234 {
00235 if ( role == Qt::TextColorRole &&
00236 ( parent_ && parent_->getDisableChildren() ) )
00237 {
00238 return Qt::gray;
00239 }
00240
00241 switch( column )
00242 {
00243 case 0:
00244 switch( role )
00245 {
00246 case Qt::DisplayRole: return getName();
00247 case Qt::DecorationRole: return icon_;
00248 default: return QVariant();
00249 }
00250 break;
00251 case 1:
00252 switch( role )
00253 {
00254 case Qt::DisplayRole:
00255 case Qt::EditRole: return (value_.type() == QVariant::Bool ? QVariant() : getValue());
00256 case Qt::CheckStateRole:
00257 if( value_.type() == QVariant::Bool )
00258 return (value_.toBool() ? Qt::Checked : Qt::Unchecked);
00259 else
00260 return QVariant();
00261 default: return QVariant();
00262 }
00263 break;
00264 default: return QVariant();
00265 }
00266 }
00267
00268 bool Property::getDisableChildren()
00269 {
00270
00271 if ( parent_ )
00272 {
00273 return parent_->getDisableChildren();
00274 }
00275 return false;
00276 }
00277
00278 Qt::ItemFlags Property::getViewFlags( int column ) const
00279 {
00280
00281
00282 Qt::ItemFlags enabled_flag = ( parent_ && parent_->getDisableChildren() ) ? Qt::NoItemFlags : Qt::ItemIsEnabled;
00283
00284 if( column == 0 )
00285 {
00286 return enabled_flag | Qt::ItemIsSelectable;
00287 }
00288 if( value_.isValid() )
00289 {
00290 if( value_.type() == QVariant::Bool )
00291 {
00292 return Qt::ItemIsUserCheckable | enabled_flag | Qt::ItemIsSelectable;
00293 }
00294 return Qt::ItemIsEditable | enabled_flag | Qt::ItemIsSelectable;
00295 }
00296 return enabled_flag | Qt::ItemIsSelectable;
00297 }
00298
00299 bool Property::isAncestorOf( Property* possible_child ) const
00300 {
00301 Property* prop = possible_child->getParent();
00302 while( prop != NULL && prop != this )
00303 {
00304 prop = prop->getParent();
00305 }
00306 return prop == this;
00307 }
00308
00309 Property* Property::takeChild( Property* child )
00310 {
00311 for( int i = 0; i < numChildren(); i++ )
00312 {
00313 if( childAtUnchecked( i ) == child )
00314 {
00315 return takeChildAt( i );
00316 }
00317 }
00318 return NULL;
00319 }
00320
00321 Property* Property::takeChildAt( int index )
00322 {
00323 if( index < 0 || index >= children_.size() )
00324 {
00325 return NULL;
00326 }
00327 if( model_ )
00328 {
00329 model_->beginRemove( this, index, 1 );
00330 }
00331 Property* child = children_.takeAt( index );
00332 child->setModel( NULL );
00333 child->parent_ = NULL;
00334 child_indexes_valid_ = false;
00335 if( model_ )
00336 {
00337 model_->endRemove();
00338 }
00339 Q_EMIT childListChanged( this );
00340 return child;
00341 }
00342
00343 void Property::addChild( Property* child, int index )
00344 {
00345 if( !child )
00346 {
00347 return;
00348 }
00349 int num_children = children_.size();
00350 if( index < 0 || index > num_children )
00351 {
00352 index = num_children;
00353 }
00354 if( model_ )
00355 {
00356 model_->beginInsert( this, index );
00357 }
00358
00359 children_.insert( index, child );
00360 child_indexes_valid_ = false;
00361 child->setModel( model_ );
00362 child->parent_ = this;
00363
00364 if( model_ )
00365 {
00366 model_->endInsert();
00367 }
00368
00369 Q_EMIT childListChanged( this );
00370 }
00371
00372 void Property::setModel( PropertyTreeModel* model )
00373 {
00374 model_ = model;
00375 if( model_ && hidden_ )
00376 {
00377 model_->emitPropertyHiddenChanged( this );
00378 }
00379 int num_children = numChildren();
00380 for( int i = 0; i < num_children; i++ )
00381 {
00382 Property* child = childAtUnchecked( i );
00383 child->setModel( model );
00384 }
00385 }
00386
00387 void Property::reindexChildren()
00388 {
00389 int num_children = numChildren();
00390 for( int i = 0; i < num_children; i++ )
00391 {
00392 Property* child = childAtUnchecked( i );
00393 child->row_number_within_parent_ = i;
00394 }
00395 child_indexes_valid_ = true;
00396 }
00397
00398 int Property::rowNumberInParent() const
00399 {
00400 Property* parent = getParent();
00401 if( !parent )
00402 {
00403 return -1;
00404 }
00405 if( !parent->child_indexes_valid_ )
00406 {
00407 parent->reindexChildren();
00408 }
00409 return row_number_within_parent_;
00410 }
00411
00412 void Property::moveChild( int from_index, int to_index )
00413 {
00414 children_.move( from_index, to_index );
00415 child_indexes_valid_ = false;
00416 Q_EMIT childListChanged( this );
00417 }
00418
00419 void Property::load( const Config& config )
00420 {
00421 if( config.getType() == Config::Value )
00422 {
00423 loadValue( config );
00424 }
00425 else if( config.getType() == Config::Map )
00426 {
00427
00428
00429 loadValue( config.mapGetChild( "Value" ));
00430
00431
00432 int num_property_children = children_.size();
00433 for( int i = 0; i < num_property_children; i++ )
00434 {
00435 Property* child = children_.at( i );
00436
00437 child->load( config.mapGetChild( child->getName() ));
00438 }
00439 }
00440 }
00441
00442 void Property::loadValue( const Config& config )
00443 {
00444 if( config.getType() == Config::Value )
00445 {
00446 switch( int( value_.type() ))
00447 {
00448 case QVariant::Int: setValue( config.getValue().toInt() ); break;
00449 case QMetaType::Float:
00450 case QVariant::Double: setValue( config.getValue().toDouble() ); break;
00451 case QVariant::String: setValue( config.getValue().toString() ); break;
00452 case QVariant::Bool: setValue( config.getValue().toBool() ); break;
00453 default:
00454 printf( "Property::loadValue() TODO: error handling - unexpected QVariant type %d.\n", int( value_.type() ));
00455 break;
00456 }
00457 }
00458 }
00459
00460 void Property::save( Config config ) const
00461 {
00462
00463 if( children_.size() > 0 )
00464 {
00465
00466
00467 if( value_.isValid() )
00468 {
00469 config.mapSetValue( "Value", value_ );
00470 }
00471 int num_properties = children_.size();
00472 for( int i = 0; i < num_properties; i++ )
00473 {
00474 Property* prop = children_.at( i );
00475 if( prop && prop->shouldBeSaved() )
00476 {
00477 prop->save( config.mapMakeChild( prop->getName() ));
00478 }
00479 }
00480 }
00481 else
00482 {
00483 if( value_.isValid() )
00484 {
00485 config.setValue( value_ );
00486 }
00487 else
00488 {
00489
00490 config.setType( Config::Map );
00491 }
00492 }
00493 }
00494
00495 QWidget* Property::createEditor( QWidget* parent,
00496 const QStyleOptionViewItem& option )
00497 {
00498 switch( int( value_.type() ))
00499 {
00500 case QVariant::Int:
00501 {
00502 QSpinBox* editor = new QSpinBox( parent );
00503 editor->setFrame( false );
00504 editor->setRange( INT_MIN, INT_MAX );
00505 return editor;
00506 }
00507 case QMetaType::Float:
00508 case QVariant::Double:
00509 {
00510 FloatEdit* editor = new FloatEdit( parent );
00511 return editor;
00512 }
00513 case QVariant::String:
00514 default:
00515 {
00516 QLineEdit* editor = new QLineEdit( parent );
00517 editor->setFrame( false );
00518 return editor;
00519 }
00520 }
00521 }
00522
00523 void Property::setHidden( bool hidden )
00524 {
00525 if( hidden != hidden_ )
00526 {
00527 hidden_ = hidden;
00528 if( model_ )
00529 {
00530 model_->emitPropertyHiddenChanged( this );
00531 }
00532 }
00533 }
00534
00535 void Property::expand()
00536 {
00537 if( model_ )
00538 {
00539 model_->expandProperty( this );
00540 }
00541 }
00542
00543 void Property::collapse()
00544 {
00545 if( model_ )
00546 {
00547 model_->collapseProperty( this );
00548 }
00549 }
00550
00551 }