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