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   if ( role == Qt::TextColorRole &&
00236        ( parent_ && parent_->getDisableChildren() ) )
00237   {
00238     return Qt::gray;
00239   }
00240 
00241   switch( column )
00242   {
00243   case 0: // left column: names
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: // right column: values
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   // Pass down the disableChildren flag
00271   if ( parent_ )
00272   {
00273     return parent_->getDisableChildren();
00274   }
00275   return false;
00276 }
00277 
00278 Qt::ItemFlags Property::getViewFlags( int column ) const
00279 {
00280   // if the parent propery is a disabled bool property or
00281   // has its own enabled view flag not set, disable this property as well
00282   Qt::ItemFlags enabled_flag = ( parent_ && parent_->getDisableChildren() ) ? Qt::NoItemFlags : Qt::ItemIsEnabled;  // || is_read_only_
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     // A special map entry named "Value" means the value of this property, not a child.
00428     // (If child "Value"does not exist, loadValue() will do nothing.)
00429     loadValue( config.mapGetChild( "Value" ));
00430 
00431     // Loop over all child Properties.
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       // Load the child Property with the config under the child property's name.
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   // If there are child properties, save them in a map from names to children.
00463   if( children_.size() > 0 )
00464   {
00465     // If this property has child properties *and* a value itself,
00466     // save the value in a special map entry named "Value".
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 // Else there are no child properties, so just save the value itself.
00482   {
00483     if( value_.isValid() )
00484     {
00485       config.setValue( value_ );
00486     }
00487     else
00488     {
00489       // Empty Properties get saved as empty Maps instead of null values.
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 } // end namespace rviz


rviz
Author(s): Dave Hershberger, David Gossow, Josh Faust
autogenerated on Thu Aug 27 2015 15:02:27