property.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> // for printf()
00031 #include <limits.h> // for INT_MIN and INT_MAX
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   // Disconnect myself from my parent.
00087   if( getParent() )
00088   {
00089     getParent()->takeChild( this );
00090   }
00091   // Destroy my children.
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   // Destroy my children.
00112   for( int i = start_index; i < start_index + count; i++ )
00113   {
00114     Property* child = children_.at( i );
00115     child->setParent( NULL ); // prevent child destructor from calling getParent()->takeChild().
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   // Print a useful error message showing the whole ancestry of this
00184   // property, but don't crash.
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   // numChildren() and childAtUnchecked() can both be overridden, so
00197   // call them instead of accessing our children_ list directly.
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: // left column: names
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: // right column: values
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   // Pass down the disableChildren flag
00265   if ( parent_ )
00266   {
00267     return parent_->getDisableChildren();
00268   }
00269   return false;
00270 }
00271 
00272 Qt::ItemFlags Property::getViewFlags( int column ) const
00273 {
00274   // if the parent propery is a disabled bool property or
00275   // has its own enabled view flag not set, disable this property as well
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     // A special map entry named "Value" means the value of this property, not a child.
00429     // (If child "Value"does not exist, loadValue() will do nothing.)
00430     loadValue( config.mapGetChild( "Value" ));
00431 
00432     // Loop over all child Properties.
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       // Load the child Property with the config under the child property's name.
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   // If there are child properties, save them in a map from names to children.
00464   if( children_.size() > 0 )
00465   {
00466     // If this property has child properties *and* a value itself,
00467     // save the value in a special map entry named "Value".
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 // Else there are no child properties, so just save the value itself.
00483   {
00484     if( value_.isValid() )
00485     {
00486       config.setValue( value_ );
00487     }
00488     else
00489     {
00490       // Empty Properties get saved as empty Maps instead of null values.
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 } // end namespace rviz


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