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( count == 0 )
00108     return;
00109 
00110   if( model_ )
00111   {
00112     model_->beginRemove( this, start_index, count );
00113   }
00114   // Destroy my children.
00115   for( int i = start_index; i < start_index + count; i++ )
00116   {
00117     Property* child = children_.at( i );
00118     child->setParent( NULL ); // prevent child destructor from calling getParent()->takeChild().
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   // Print a useful error message showing the whole ancestry of this
00187   // property, but don't crash.
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   // numChildren() and childAtUnchecked() can both be overridden, so
00200   // call them instead of accessing our children_ list directly.
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: // left column: names
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: // right column: values
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   // Pass down the disableChildren flag
00278   if ( parent_ )
00279   {
00280     return parent_->getDisableChildren();
00281   }
00282   return false;
00283 }
00284 
00285 Qt::ItemFlags Property::getViewFlags( int column ) const
00286 {
00287   // if the parent propery is a disabled bool property or
00288   // has its own enabled view flag not set, disable this property as well
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     // A special map entry named "Value" means the value of this property, not a child.
00435     // (If child "Value"does not exist, loadValue() will do nothing.)
00436     loadValue( config.mapGetChild( "Value" ));
00437 
00438     // Loop over all child Properties.
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       // Load the child Property with the config under the child property's name.
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   // If there are child properties, save them in a map from names to children.
00470   if( children_.size() > 0 )
00471   {
00472     // If this property has child properties *and* a value itself,
00473     // save the value in a special map entry named "Value".
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 // Else there are no child properties, so just save the value itself.
00489   {
00490     if( value_.isValid() )
00491     {
00492       config.setValue( value_ );
00493     }
00494     else
00495     {
00496       // Empty Properties get saved as empty Maps instead of null values.
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 } // end namespace rviz


rviz
Author(s): Dave Hershberger, David Gossow, Josh Faust
autogenerated on Tue Oct 3 2017 03:19:31