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 switch( column )
00236 {
00237 case 0:
00238 switch( role )
00239 {
00240 case Qt::DisplayRole: return getName();
00241 case Qt::DecorationRole: return icon_;
00242 default: return QVariant();
00243 }
00244 break;
00245 case 1:
00246 switch( role )
00247 {
00248 case Qt::DisplayRole:
00249 case Qt::EditRole: return (value_.type() == QVariant::Bool ? QVariant() : getValue());
00250 case Qt::CheckStateRole:
00251 if( value_.type() == QVariant::Bool )
00252 return (value_.toBool() ? Qt::Checked : Qt::Unchecked);
00253 else
00254 return QVariant();
00255 default: return QVariant();
00256 }
00257 break;
00258 default: return QVariant();
00259 }
00260 }
00261
00262 bool Property::getDisableChildren()
00263 {
00264
00265 if ( parent_ )
00266 {
00267 return parent_->getDisableChildren();
00268 }
00269 return false;
00270 }
00271
00272 Qt::ItemFlags Property::getViewFlags( int column ) const
00273 {
00274
00275
00276 Qt::ItemFlags enabled_flag = Qt::ItemIsEnabled;
00277 if ( parent_ )
00278 {
00279 if( parent_->getDisableChildren() )
00280 {
00281 enabled_flag = 0;
00282 }
00283 }
00284
00285 if( column == 0 || is_read_only_ )
00286 {
00287 return enabled_flag | Qt::ItemIsSelectable;
00288 }
00289 if( value_.isValid() )
00290 {
00291 if( value_.type() == QVariant::Bool )
00292 {
00293 return Qt::ItemIsUserCheckable | enabled_flag | Qt::ItemIsSelectable;
00294 }
00295 return Qt::ItemIsEditable | enabled_flag | Qt::ItemIsSelectable;
00296 }
00297 return enabled_flag | Qt::ItemIsSelectable;
00298 }
00299
00300 bool Property::isAncestorOf( Property* possible_child ) const
00301 {
00302 Property* prop = possible_child->getParent();
00303 while( prop != NULL && prop != this )
00304 {
00305 prop = prop->getParent();
00306 }
00307 return prop == this;
00308 }
00309
00310 Property* Property::takeChild( Property* child )
00311 {
00312 for( int i = 0; i < numChildren(); i++ )
00313 {
00314 if( childAtUnchecked( i ) == child )
00315 {
00316 return takeChildAt( i );
00317 }
00318 }
00319 return NULL;
00320 }
00321
00322 Property* Property::takeChildAt( int index )
00323 {
00324 if( index < 0 || index >= children_.size() )
00325 {
00326 return NULL;
00327 }
00328 if( model_ )
00329 {
00330 model_->beginRemove( this, index, 1 );
00331 }
00332 Property* child = children_.takeAt( index );
00333 child->setModel( NULL );
00334 child->parent_ = NULL;
00335 child_indexes_valid_ = false;
00336 if( model_ )
00337 {
00338 model_->endRemove();
00339 }
00340 Q_EMIT childListChanged( this );
00341 return child;
00342 }
00343
00344 void Property::addChild( Property* child, int index )
00345 {
00346 if( !child )
00347 {
00348 return;
00349 }
00350 int num_children = children_.size();
00351 if( index < 0 || index > num_children )
00352 {
00353 index = num_children;
00354 }
00355 if( model_ )
00356 {
00357 model_->beginInsert( this, index );
00358 }
00359
00360 children_.insert( index, child );
00361 child_indexes_valid_ = false;
00362 child->setModel( model_ );
00363 child->parent_ = this;
00364
00365 if( model_ )
00366 {
00367 model_->endInsert();
00368 }
00369
00370 Q_EMIT childListChanged( this );
00371 }
00372
00373 void Property::setModel( PropertyTreeModel* model )
00374 {
00375 model_ = model;
00376 if( model_ && hidden_ )
00377 {
00378 model_->emitPropertyHiddenChanged( this );
00379 }
00380 int num_children = numChildren();
00381 for( int i = 0; i < num_children; i++ )
00382 {
00383 Property* child = childAtUnchecked( i );
00384 child->setModel( model );
00385 }
00386 }
00387
00388 void Property::reindexChildren()
00389 {
00390 int num_children = numChildren();
00391 for( int i = 0; i < num_children; i++ )
00392 {
00393 Property* child = childAtUnchecked( i );
00394 child->row_number_within_parent_ = i;
00395 }
00396 child_indexes_valid_ = true;
00397 }
00398
00399 int Property::rowNumberInParent() const
00400 {
00401 Property* parent = getParent();
00402 if( !parent )
00403 {
00404 return -1;
00405 }
00406 if( !parent->child_indexes_valid_ )
00407 {
00408 parent->reindexChildren();
00409 }
00410 return row_number_within_parent_;
00411 }
00412
00413 void Property::moveChild( int from_index, int to_index )
00414 {
00415 children_.move( from_index, to_index );
00416 child_indexes_valid_ = false;
00417 Q_EMIT childListChanged( this );
00418 }
00419
00420 void Property::load( const Config& config )
00421 {
00422 if( config.getType() == Config::Value )
00423 {
00424 loadValue( config );
00425 }
00426 else if( config.getType() == Config::Map )
00427 {
00428
00429
00430 loadValue( config.mapGetChild( "Value" ));
00431
00432
00433 int num_property_children = children_.size();
00434 for( int i = 0; i < num_property_children; i++ )
00435 {
00436 Property* child = children_.at( i );
00437
00438 child->load( config.mapGetChild( child->getName() ));
00439 }
00440 }
00441 }
00442
00443 void Property::loadValue( const Config& config )
00444 {
00445 if( config.getType() == Config::Value )
00446 {
00447 switch( int( value_.type() ))
00448 {
00449 case QVariant::Int: setValue( config.getValue().toInt() ); break;
00450 case QMetaType::Float:
00451 case QVariant::Double: setValue( config.getValue().toDouble() ); break;
00452 case QVariant::String: setValue( config.getValue().toString() ); break;
00453 case QVariant::Bool: setValue( config.getValue().toBool() ); break;
00454 default:
00455 printf( "Property::loadValue() TODO: error handling - unexpected QVariant type %d.\n", int( value_.type() ));
00456 break;
00457 }
00458 }
00459 }
00460
00461 void Property::save( Config config ) const
00462 {
00463
00464 if( children_.size() > 0 )
00465 {
00466
00467
00468 if( value_.isValid() )
00469 {
00470 config.mapSetValue( "Value", value_ );
00471 }
00472 int num_properties = children_.size();
00473 for( int i = 0; i < num_properties; i++ )
00474 {
00475 Property* prop = children_.at( i );
00476 if( prop && prop->shouldBeSaved() )
00477 {
00478 prop->save( config.mapMakeChild( prop->getName() ));
00479 }
00480 }
00481 }
00482 else
00483 {
00484 if( value_.isValid() )
00485 {
00486 config.setValue( value_ );
00487 }
00488 else
00489 {
00490
00491 config.setType( Config::Map );
00492 }
00493 }
00494 }
00495
00496 QWidget* Property::createEditor( QWidget* parent,
00497 const QStyleOptionViewItem& option )
00498 {
00499 switch( int( value_.type() ))
00500 {
00501 case QVariant::Int:
00502 {
00503 QSpinBox* editor = new QSpinBox( parent );
00504 editor->setFrame( false );
00505 editor->setRange( INT_MIN, INT_MAX );
00506 return editor;
00507 }
00508 case QMetaType::Float:
00509 case QVariant::Double:
00510 {
00511 FloatEdit* editor = new FloatEdit( parent );
00512 return editor;
00513 }
00514 case QVariant::String:
00515 default:
00516 {
00517 QLineEdit* editor = new QLineEdit( parent );
00518 editor->setFrame( false );
00519 return editor;
00520 }
00521 }
00522 }
00523
00524 void Property::setHidden( bool hidden )
00525 {
00526 if( hidden != hidden_ )
00527 {
00528 hidden_ = hidden;
00529 if( model_ )
00530 {
00531 model_->emitPropertyHiddenChanged( this );
00532 }
00533 }
00534 }
00535
00536 void Property::expand()
00537 {
00538 if( model_ )
00539 {
00540 model_->expandProperty( this );
00541 }
00542 }
00543
00544 void Property::collapse()
00545 {
00546 if( model_ )
00547 {
00548 model_->collapseProperty( this );
00549 }
00550 }
00551
00552 }