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