property.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2008, 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 <QColor>
00031 
00032 #include <tf/transform_listener.h>
00033 
00034 #include "rviz/config.h"
00035 #include "rviz/frame_manager.h"
00036 #include "rviz/properties/property.h"
00037 #include "rviz/properties/property_manager.h"
00038 #include "rviz/properties/property_widget_item.h"
00039 #include "rviz/properties/property_tree_widget.h"
00040 #include "rviz/properties/topic_info_variant.h"
00041 #include "rviz/properties/color_item.h"
00042 #include "rviz/properties/enum_item.h"
00043 #include "rviz/properties/edit_enum_item.h"
00044 #include "rviz/properties/compound_widget_item.h"
00045 
00046 namespace rviz
00047 {
00048 
00049 static const QColor ERROR_COLOR(178, 23, 46); // red-ish
00050 static const QColor WARN_COLOR(222, 213, 17); // yellow-ish
00051 static const QColor CATEGORY_COLOR( 4, 89, 127 ); // blue-ish
00052 
00053 void PropertyBase::writeToGrid()
00054 {
00055   // Any change events coming from the grid during a "writeToGrid()"
00056   // call are caused by us, not by the user, so make sure we don't
00057   // end up calling readFromGrid() as a result (i.e. ignore them).
00058   bool ign = grid_->setIgnoreChanges( true );
00059   doWriteToGrid();
00060   grid_->setIgnoreChanges( ign );
00061 }
00062 
00063 PropertyWidgetItem* getCategoryPGProperty(const CategoryPropertyWPtr& wprop)
00064 {
00065   CategoryPropertyPtr prop = wprop.lock();
00066 
00067   if (prop)
00068   {
00069     return prop->getWidgetItem();
00070   }
00071 
00072   return NULL;
00073 }
00074 
00075 void setPropertyHelpText(PropertyTreeWidget* grid, PropertyWidgetItem* widget_item, const std::string& text)
00076 {
00077   if( widget_item )
00078   {
00079     bool ign = grid->setIgnoreChanges( true );
00080     widget_item->setWhatsThis( 0, QString::fromStdString( text ));
00081     widget_item->setWhatsThis( 1, QString::fromStdString( text ));
00082     grid->setIgnoreChanges( ign );
00083   }
00084 }
00085 
00086 void setPropertyToColors(PropertyTreeWidget* grid, PropertyWidgetItem* widget_item, const QColor& fg_color, const QColor& bg_color, uint32_t column)
00087 {
00088   if( widget_item )
00089   {
00090     bool ign = grid->setIgnoreChanges( true );
00091     widget_item->setForeground( column, fg_color );
00092     widget_item->setBackground( column, bg_color );
00093     grid->setIgnoreChanges( ign );
00094   }
00095 }
00096 
00097 void setPropertyToError(PropertyTreeWidget* grid, PropertyWidgetItem* property, uint32_t column)
00098 {
00099   setPropertyToColors(grid, property, Qt::white, ERROR_COLOR, column);
00100 }
00101 
00102 void setPropertyToWarn(PropertyTreeWidget* grid, PropertyWidgetItem* property, uint32_t column)
00103 {
00104   setPropertyToColors(grid, property, Qt::white, WARN_COLOR, column);
00105 }
00106 
00107 void setPropertyToOK(PropertyTreeWidget* grid, PropertyWidgetItem* property, uint32_t column)
00108 {
00109   setPropertyToColors(grid, property, Qt::black, Qt::white, column);
00110 }
00111 
00112 void setPropertyToDisabled(PropertyTreeWidget* grid, PropertyWidgetItem* property, uint32_t column)
00113 {
00114   setPropertyToColors(grid, property, QColor(0x33, 0x44, 0x44), QColor(0xaa, 0xaa, 0xaa), column);
00115 }
00116 
00117 PropertyBase::PropertyBase()
00118 : grid_(NULL)
00119 , widget_item_(NULL)
00120 , user_data_(NULL)
00121 , manager_(NULL)
00122 {
00123 }
00124 
00125 PropertyBase::~PropertyBase()
00126 {
00127   delete widget_item_;
00128 }
00129 
00130 void PropertyBase::reset()
00131 {
00132   grid_ = 0;
00133 
00134   delete widget_item_;
00135   widget_item_ = 0;
00136 }
00137 
00138 void PropertyBase::setPropertyTreeWidget(PropertyTreeWidget* grid)
00139 {
00140   grid_ = grid;
00141 }
00142 
00143 void PropertyBase::hide()
00144 {
00145   if( widget_item_ )
00146   {
00147     widget_item_->setHidden( true );
00148   }
00149 }
00150 
00151 void PropertyBase::show()
00152 {
00153   if( widget_item_ )
00154   {
00155     widget_item_->setHidden( false );
00156   }
00157 }
00158 
00159 bool PropertyBase::isSelected()
00160 {
00161   if( widget_item_ && grid_ )
00162   {
00163     return grid_->currentItem() == widget_item_;
00164   }
00165 
00166   return false;
00167 }
00168 
00169 void PropertyBase::changed()
00170 {
00171   // I needed to purge boost::signal, and I didn't really want to make
00172   // every Property a QObject.  There is only one class which needs to
00173   // be notified of property changes, and that is PropertyManager.
00174   // Therefore I'm making an explicit function call connection instead
00175   // of a Qt signal or a boost signal.
00176   if( manager_ )
00177   {
00178     manager_->propertySet( shared_from_this() );
00179   }
00180 }
00181 
00182 void PropertyBase::configChanged()
00183 {
00184   if( manager_ )
00185   {
00186     manager_->emitConfigChanged();
00187   }
00188 }
00189 
00190 StatusProperty::StatusProperty(const std::string& name, const std::string& prefix, const CategoryPropertyWPtr& parent, void* user_data)
00191 : name_(name)
00192 , prefix_(prefix)
00193 , parent_(parent)
00194 , top_widget_item_(0)
00195 , enabled_(true)
00196 , prefix_changed_(false)
00197 , top_status_(status_levels::Ok)
00198 {
00199   user_data_ = user_data;
00200 }
00201 
00202 StatusProperty::~StatusProperty()
00203 {
00204   delete top_widget_item_;
00205 }
00206 
00207 void StatusProperty::enable()
00208 {
00209   boost::mutex::scoped_lock lock(status_mutex_);
00210   enabled_ = true;
00211 
00212   changed();
00213 }
00214 
00215 void StatusProperty::disable()
00216 {
00217   clear();
00218 
00219   boost::mutex::scoped_lock lock(status_mutex_);
00220   enabled_ = false;
00221 
00222   changed();
00223 }
00224 
00225 void StatusProperty::setPrefix(const std::string& prefix)
00226 {
00227   boost::mutex::scoped_lock lock(status_mutex_);
00228   prefix_ = prefix;
00229   prefix_changed_ = true;
00230   changed();
00231 }
00232 
00233 void StatusProperty::clear()
00234 {
00235   boost::mutex::scoped_lock lock(status_mutex_);
00236 
00237   if (!enabled_)
00238   {
00239     return;
00240   }
00241 
00242   M_StringToStatus::iterator it = statuses_.begin();
00243   M_StringToStatus::iterator end = statuses_.end();
00244   for (; it != end; ++it)
00245   {
00246     Status& status = it->second;
00247     status.kill = true;
00248   }
00249 
00250   // Update the top level status here so that it can be used immediately
00251   updateTopLevelStatus();
00252 
00253   changed();
00254 }
00255 
00256 void StatusProperty::updateTopLevelStatus()
00257 {
00258   top_status_ = status_levels::Ok;
00259   M_StringToStatus::iterator it = statuses_.begin();
00260   M_StringToStatus::iterator end = statuses_.end();
00261   for (; it != end; ++it)
00262   {
00263     Status& status = it->second;
00264 
00265     if (status.kill)
00266     {
00267       continue;
00268     }
00269 
00270     if (status.level > top_status_)
00271     {
00272       top_status_ = status.level;
00273     }
00274   }
00275 }
00276 
00277 void StatusProperty::setStatus(StatusLevel level, const std::string& name, const std::string& text)
00278 {
00279   boost::mutex::scoped_lock lock(status_mutex_);
00280 
00281   if (!enabled_)
00282   {
00283     return;
00284   }
00285 
00286   Status& status = statuses_[name];
00287 
00288   // Status hasn't changed, return
00289   if (status.level == level && status.text == text && !status.kill)
00290   {
00291     return;
00292   }
00293 
00294   status.name = name;
00295   status.text = text;
00296   status.level = level;
00297   status.kill = false;
00298 
00299   // Update the top level status here so that it can be used immediately
00300   updateTopLevelStatus();
00301 
00302   changed();
00303 }
00304 
00305 void StatusProperty::deleteStatus(const std::string& name)
00306 {
00307   boost::mutex::scoped_lock lock(status_mutex_);
00308 
00309   if (!enabled_)
00310   {
00311     return;
00312   }
00313 
00314   M_StringToStatus::iterator it = statuses_.find(name);
00315   if (it != statuses_.end())
00316   {
00317     Status& status = it->second;
00318     status.kill = true;
00319   }
00320 
00321   // Update the top level status here so that it can be used immediately
00322   updateTopLevelStatus();
00323 
00324   changed();
00325 }
00326 
00327 void StatusProperty::doWriteToGrid()
00328 {
00329   boost::mutex::scoped_lock lock(status_mutex_);
00330 
00331   if ( !top_widget_item_ )
00332   {
00333     std::string top_name = name_ + "TopStatus";
00334 
00335     top_widget_item_ = new PropertyWidgetItem( this, "", false, false, true );
00336     top_widget_item_->addToParent();
00337   }
00338 
00339   bool expanded = top_widget_item_->isExpanded();
00340 
00341   top_status_ = status_levels::Ok;
00342 
00343   std::vector<std::string> to_erase;
00344   M_StringToStatus::iterator it = statuses_.begin();
00345   M_StringToStatus::iterator end = statuses_.end();
00346   for( ; it != end; ++it )
00347   {
00348     Status& status = it->second;
00349 
00350     if( status.kill )
00351     {
00352       to_erase.push_back(it->first);
00353       continue;
00354     }
00355 
00356     if( !status.widget_item )
00357     {
00358       status.widget_item = new PropertyWidgetItem( this, status.name, false, false, false );
00359       status.widget_item->addToParent( top_widget_item_ );
00360     }
00361 
00362     if( status.level > top_status_ )
00363     {
00364       top_status_ = status.level;
00365     }
00366 
00367     if( enabled_ )
00368     {
00369       switch( status.level )
00370       {
00371       case status_levels::Ok:
00372         setPropertyToOK( grid_, status.widget_item );
00373         break;
00374       case status_levels::Warn:
00375         setPropertyToColors( grid_, status.widget_item, WARN_COLOR, Qt::white );
00376         break;
00377       case status_levels::Error:
00378         setPropertyToColors( grid_, status.widget_item, ERROR_COLOR, Qt::white );
00379         break;
00380       }
00381     }
00382     else
00383     {
00384       setPropertyToDisabled( grid_, status.widget_item );
00385     }
00386 
00387     status.widget_item->setRightText( status.text );
00388     setPropertyHelpText( grid_, status.widget_item, status.text );
00389   }
00390 
00391   std::vector<std::string>::iterator kill_it = to_erase.begin();
00392   std::vector<std::string>::iterator kill_end = to_erase.end();
00393   for( ; kill_it != kill_end; ++kill_it )
00394   {
00395     Status& status = statuses_[*kill_it];
00396     delete status.widget_item;
00397     statuses_.erase( *kill_it );
00398   }
00399 
00400   top_widget_item_->setExpanded( expanded );
00401 
00402   std::string label;
00403   if( enabled_ )
00404   {
00405     switch( top_status_ )
00406     {
00407     case status_levels::Ok:
00408       setPropertyToColors( grid_, top_widget_item_, Qt::black, Qt::white );
00409       label = name_ + ": OK";
00410       break;
00411     case status_levels::Warn:
00412       setPropertyToColors( grid_, top_widget_item_, WARN_COLOR, Qt::white );
00413       label = name_ + ": Warning";
00414       break;
00415     case status_levels::Error:
00416       setPropertyToColors( grid_, top_widget_item_, ERROR_COLOR, Qt::white );
00417       label = name_ + ": Error";
00418       break;
00419     }
00420   }
00421   else
00422   {
00423     setPropertyToDisabled( grid_, top_widget_item_ );
00424     label = name_ + ": Disabled";
00425   }
00426 
00427   top_widget_item_->setLeftText( label );
00428   top_widget_item_->sortChildren( 0, Qt::AscendingOrder );
00429 }
00430 
00431 StatusLevel StatusProperty::getTopLevelStatus()
00432 {
00433   return top_status_;
00434 }
00435 
00436 void BoolProperty::doWriteToGrid()
00437 {
00438   if ( !widget_item_ )
00439   {
00440     widget_item_ = new PropertyWidgetItem( this, name_, hasSetter(), true );
00441     widget_item_->addToParent();
00442   }
00443   bool ign = getPropertyTreeWidget()->setIgnoreChanges( true );
00444 
00445   widget_item_->setData( 1, Qt::CheckStateRole, get() ? Qt::Checked : Qt::Unchecked );
00446   setPropertyHelpText(grid_, widget_item_, help_text_);
00447 
00448   getPropertyTreeWidget()->setIgnoreChanges( ign );
00449 }
00450 
00451 void BoolProperty::readFromGrid()
00452 {
00453   QVariant check_state = widget_item_->data( 1, Qt::CheckStateRole );
00454   set( check_state == Qt::Checked );
00455 }
00456 
00457 void BoolProperty::saveToConfig( Config* config )
00458 {
00459   config->set( prefix_ + name_, (int)get() );
00460 }
00461 
00462 void BoolProperty::loadFromConfig( Config* config )
00463 {
00464   int val;
00465   if( !config->get( prefix_ + name_, &val, get() ))
00466   {
00467     V_string::iterator it = legacy_names_.begin();
00468     V_string::iterator end = legacy_names_.end();
00469     for (; it != end; ++it)
00470     {
00471       if (config->get( prefix_ + *it, &val, get() ))
00472       {
00473         break;
00474       }
00475     }
00476   }
00477 
00478   set( (bool) val );
00479 }
00480 
00481 void IntProperty::setMin( int min )
00482 {
00483   if( widget_item_ )
00484   {
00485     widget_item_->min_ = min;
00486   }
00487   min_ = min;
00488 }
00489 
00490 void IntProperty::setMax( int max )
00491 {
00492   if (widget_item_)
00493   {
00494     widget_item_->max_ = max;
00495   }
00496   max_ = max;
00497 }
00498 
00499 void IntProperty::doWriteToGrid()
00500 {
00501   if ( !widget_item_ )
00502   {
00503     widget_item_ = new PropertyWidgetItem( this, name_, hasSetter() );
00504     widget_item_->addToParent();
00505     widget_item_->max_ = max_;
00506     widget_item_->min_ = min_;
00507   }
00508 
00509   widget_item_->setUserData( get() );
00510 
00511   setPropertyHelpText(grid_, widget_item_, help_text_);
00512 }
00513 
00514 void IntProperty::readFromGrid()
00515 {
00516   set( widget_item_->userData().toInt() );
00517 }
00518 
00519 void IntProperty::saveToConfig( Config* config )
00520 {
00521   config->set( prefix_ + name_, (int)get() );
00522 }
00523 
00524 void IntProperty::loadFromConfig( Config* config )
00525 {
00526   int val;
00527   if (!config->get( prefix_ + name_, &val, get() ))
00528   {
00529     V_string::iterator it = legacy_names_.begin();
00530     V_string::iterator end = legacy_names_.end();
00531     for (; it != end; ++it)
00532     {
00533       if (config->get( prefix_ + *it, &val, get() ))
00534       {
00535         break;
00536       }
00537     }
00538   }
00539 
00540   set( val );
00541 }
00542 
00543 void FloatProperty::setMin( float min )
00544 {
00545   if (widget_item_)
00546   {
00547     widget_item_->min_ = min;
00548   }
00549   min_ = min;
00550 }
00551 
00552 void FloatProperty::setMax( float max )
00553 {
00554   if (widget_item_)
00555   {
00556     widget_item_->max_ = max;
00557   }
00558   max_ = max;
00559 }
00560 
00561 void FloatProperty::doWriteToGrid()
00562 {
00563   if( !widget_item_ )
00564   {
00565     widget_item_ = new PropertyWidgetItem( this, name_, hasSetter() );
00566     widget_item_->addToParent();
00567     widget_item_->max_ = max_;
00568     widget_item_->min_ = min_;
00569   }
00570 
00571   widget_item_->setUserData( QVariant( get() ));
00572 
00573   setPropertyHelpText(grid_, widget_item_, help_text_);
00574 }
00575 
00576 void FloatProperty::readFromGrid()
00577 {
00578   set( widget_item_->userData().toFloat() );
00579 }
00580 
00581 void FloatProperty::saveToConfig( Config* config )
00582 {
00583   config->set( prefix_ + name_, (float)get() );
00584 }
00585 
00586 void FloatProperty::loadFromConfig( Config* config )
00587 {
00588   float val;
00589   if (!config->get( prefix_ + name_, &val, get() ))
00590   {
00591     V_string::iterator it = legacy_names_.begin();
00592     V_string::iterator end = legacy_names_.end();
00593     for (; it != end; ++it)
00594     {
00595       if (config->get( prefix_ + *it, &val, get() ))
00596       {
00597         break;
00598       }
00599     }
00600   }
00601 
00602   set( val );
00603 }
00604 
00605 void StringProperty::doWriteToGrid()
00606 {
00607   if( !widget_item_ )
00608   {
00609     widget_item_ = new PropertyWidgetItem( this, name_, hasSetter() );
00610     widget_item_->addToParent();
00611   }
00612 
00613   widget_item_->setUserData( QString::fromStdString( get() ));
00614 
00615   setPropertyHelpText( grid_, widget_item_, help_text_ );
00616 }
00617 
00618 void StringProperty::readFromGrid()
00619 {
00620   set( widget_item_->userData().toString().toStdString() );
00621 }
00622 
00623 void StringProperty::saveToConfig( Config* config )
00624 {
00625   config->set( prefix_ + name_, get() );
00626 }
00627 
00628 void StringProperty::loadFromConfig( Config* config )
00629 {
00630   std::string val;
00631   if (!config->get( prefix_ + name_, &val, get() ))
00632   {
00633     V_string::iterator it = legacy_names_.begin();
00634     V_string::iterator end = legacy_names_.end();
00635     for (; it != end; ++it)
00636     {
00637       if (config->get( prefix_ + *it, &val, get() ))
00638       {
00639         break;
00640       }
00641     }
00642   }
00643 
00644   set( val );
00645 }
00646 
00647 void ROSTopicStringProperty::doWriteToGrid()
00648 {
00649   if ( !widget_item_ )
00650   {
00651     widget_item_ = new PropertyWidgetItem( this, name_, hasSetter() );
00652     widget_item_->addToParent();
00653   }
00654   ros::master::TopicInfo topic;
00655   topic.name = get();
00656   topic.datatype = message_type_;
00657 
00658   widget_item_->setUserData( QVariant::fromValue( topic ));
00659 
00660   setPropertyHelpText(grid_, widget_item_, help_text_);
00661 }
00662 
00663 void ROSTopicStringProperty::readFromGrid()
00664 {
00665   ros::master::TopicInfo topic = widget_item_->userData().value<ros::master::TopicInfo>();
00666   set( topic.name );
00667 }
00668 
00669 void ColorProperty::doWriteToGrid()
00670 {
00671   if( !widget_item_ )
00672   {
00673     widget_item_ = new ColorItem( this );
00674     widget_item_->addToParent();
00675   }
00676 
00677   Color c = get();
00678   widget_item_->setUserData( QVariant::fromValue( QColor( c.r_ * 255, c.g_ * 255, c.b_ * 255 )));
00679 
00680   setPropertyHelpText( grid_, widget_item_, help_text_ );
00681 }
00682 
00683 void ColorProperty::readFromGrid()
00684 {
00685   QColor col = widget_item_->userData().value<QColor>();
00686   set( Color( col.red() / 255.0f, col.green() / 255.0f, col.blue() / 255.0f ) );
00687 }
00688 
00689 void ColorProperty::saveToConfig( Config* config )
00690 {
00691   Color c = get();
00692 
00693   config->set( prefix_ + name_ + "R", c.r_ );
00694   config->set( prefix_ + name_ + "G", c.g_ );
00695   config->set( prefix_ + name_ + "B", c.b_ );
00696 }
00697 
00698 void ColorProperty::loadFromConfig( Config* config )
00699 {
00700   Color c = get();
00701   float r, g, b;
00702   bool found = true;
00703   found &= config->get( prefix_ + name_ + "R", &r, c.r_ );
00704   found &= config->get( prefix_ + name_ + "G", &g, c.g_ );
00705   found &= config->get( prefix_ + name_ + "B", &b, c.b_ );
00706 
00707   if (!found)
00708   {
00709     V_string::iterator it = legacy_names_.begin();
00710     V_string::iterator end = legacy_names_.end();
00711     for (; it != end; ++it)
00712     {
00713       found = true;
00714       found &= config->get( prefix_ + *it + "R", &r, c.r_ );
00715       found &= config->get( prefix_ + *it + "G", &g, c.g_ );
00716       found &= config->get( prefix_ + *it + "B", &b, c.b_ );
00717 
00718       if (found)
00719       {
00720         break;
00721       }
00722     }
00723   }
00724 
00725   set( Color( r, g, b ) );
00726 }
00727 
00728 void EnumProperty::addOption( const std::string& name, int value )
00729 {
00730   boost::mutex::scoped_lock lock(mutex_);
00731   choices_.push_back( Choice( name, value ));
00732   changed();
00733 }
00734 
00735 void EnumProperty::clear ()
00736 {
00737   boost::mutex::scoped_lock lock(mutex_);
00738   choices_.clear();
00739   changed();
00740 }
00741 
00742 void EnumProperty::doWriteToGrid()
00743 {
00744   boost::mutex::scoped_lock lock(mutex_);
00745 
00746   if (isSelected())
00747   {
00748     changed();
00749     return;
00750   }
00751 
00752   if( !widget_item_ )
00753   {
00754     widget_item_ = new EnumItem( this );
00755     widget_item_->addToParent();
00756   }
00757   EnumItem* enum_item = dynamic_cast<EnumItem*>( widget_item_ );
00758   ROS_ASSERT( enum_item );
00759   enum_item->setChoices( choices_ );
00760   enum_item->setChoiceValue( get() );
00761 
00762   setPropertyHelpText( grid_, widget_item_, help_text_ );
00763 }
00764 
00765 void EnumProperty::readFromGrid()
00766 {
00767   EnumItem* enum_item = dynamic_cast<EnumItem*>( widget_item_ );
00768   ROS_ASSERT( enum_item );
00769   set( enum_item->getChoiceValue() );
00770 }
00771 
00772 void EnumProperty::saveToConfig( Config* config )
00773 {
00774   config->set( prefix_ + name_, (int)get() );
00775 }
00776 
00777 void EnumProperty::loadFromConfig( Config* config )
00778 {
00779   int val = INT_MAX;
00780   if( !config->get( prefix_ + name_, &val, get() ))
00781   {
00782     V_string::iterator it = legacy_names_.begin();
00783     V_string::iterator end = legacy_names_.end();
00784     for (; it != end; ++it)
00785     {
00786       if (config->get( prefix_ + *it, &val, get() ))
00787       {
00788         break;
00789       }
00790     }
00791   }
00792 
00793   set( val );
00794 }
00795 
00796 void EditEnumProperty::addOption( const std::string& name )
00797 {
00798   boost::mutex::scoped_lock lock(mutex_);
00799   choices_.push_back( name );
00800   changed();
00801 }
00802 
00803 void EditEnumProperty::setOptionCallback(const EditEnumOptionCallback& cb)
00804 {
00805   option_cb_ = cb;
00806   if( EditEnumItem* ee_item = dynamic_cast<EditEnumItem*>( widget_item_ ))
00807   {
00808     ee_item->setOptionCallback( cb );
00809   }
00810 
00811   changed();
00812 }
00813 
00814 void EditEnumProperty::clear ()
00815 {
00816   boost::mutex::scoped_lock lock(mutex_);
00817   choices_.clear();
00818   changed();
00819 }
00820 
00821 void EditEnumProperty::doWriteToGrid()
00822 {
00823   boost::mutex::scoped_lock lock(mutex_);
00824 
00825   if (isSelected())
00826   {
00827     changed();
00828     return;
00829   }
00830 
00831   if ( !widget_item_ )
00832   {
00833     widget_item_ = new EditEnumItem( this );
00834     widget_item_->addToParent();
00835   }
00836   EditEnumItem* ee_item = dynamic_cast<EditEnumItem*>( widget_item_ );
00837   ROS_ASSERT( ee_item );
00838   ee_item->setOptionCallback( option_cb_ );
00839   ee_item->setChoices( choices_ );
00840   ee_item->setChoice( get() );
00841   
00842   setPropertyHelpText(grid_, widget_item_, help_text_);
00843 }
00844 
00845 void EditEnumProperty::readFromGrid()
00846 {
00847   EditEnumItem* ee_item = dynamic_cast<EditEnumItem*>( widget_item_ );
00848   ROS_ASSERT( ee_item );
00849   set( ee_item->getChoice() );
00850 }
00851 
00852 void EditEnumProperty::saveToConfig( Config* config )
00853 {
00854   config->set( prefix_ + name_, get() );
00855 }
00856 
00857 void EditEnumProperty::loadFromConfig( Config* config )
00858 {
00859   std::string val;
00860   if (!config->get( prefix_ + name_, &val, get() ))
00861   {
00862     V_string::iterator it = legacy_names_.begin();
00863     V_string::iterator end = legacy_names_.end();
00864     for (; it != end; ++it)
00865     {
00866       if (config->get( prefix_ + *it, &val, get() ))
00867       {
00868         break;
00869       }
00870     }
00871   }
00872 
00873   set( val );
00874 }
00875 
00876 void TFFrameProperty::optionCallback( V_string& options_out )
00877 {
00878   typedef std::vector<std::string> V_string;
00879   FrameManager::instance()->getTFClient()->getFrameStrings( options_out );
00880   std::sort(options_out.begin(), options_out.end());
00881 
00882   options_out.insert( options_out.begin(), FIXED_FRAME_STRING );
00883 }
00884 
00885 void TFFrameProperty::doWriteToGrid()
00886 {
00887   EditEnumProperty::doWriteToGrid();
00888 
00889   EditEnumItem* ee_item = dynamic_cast<EditEnumItem*>( widget_item_ );
00890   ROS_ASSERT( ee_item );
00891   ee_item->setOptionCallback( boost::bind( &TFFrameProperty::optionCallback, this, _1 ));
00892 }
00893 
00894 CategoryProperty::~CategoryProperty()
00895 {
00896   if( widget_item_ )
00897   {
00898     // QTreeWidgetItem's destructor deletes all its children, but
00899     // PropertyManager also deletes each property (child or not)
00900     // individually.  Therefore before we destroy a category property
00901     // we need to disconnect (take) all of the widget item's children,
00902     // which will then be deleted by their respective Property
00903     // objects.
00904     widget_item_->takeChildren();
00905   }
00906 }
00907 
00908 void CategoryProperty::reset()
00909 {
00910   if( widget_item_ )
00911   {
00912     // QTreeWidgetItem's destructor deletes all its children, but
00913     // PropertyManager also deletes each property (child or not)
00914     // individually.  Therefore before we destroy a category property
00915     // we need to disconnect (take) all of the widget item's children,
00916     // which will then be deleted by their respective Property
00917     // objects.
00918     widget_item_->takeChildren();
00919   }
00920   Property<bool>::reset(); // manually chain reset() like a virtual destructor
00921 }
00922 
00923 void CategoryProperty::setLabel( const std::string& label )
00924 {
00925   label_ = label;
00926 
00927   if( widget_item_ )
00928   {
00929     widget_item_->setLeftText( label_ );
00930   }
00931 }
00932 
00933 void CategoryProperty::expand()
00934 {
00935   if (widget_item_)
00936   {
00937     widget_item_->setExpanded( true );
00938   }
00939 }
00940 
00941 void CategoryProperty::collapse()
00942 {
00943   if (widget_item_)
00944   {
00945     widget_item_->setExpanded( false );
00946   }
00947 }
00948 
00949 void CategoryProperty::doWriteToGrid()
00950 {
00951   if( !widget_item_ )
00952   {
00953     widget_item_ = new PropertyWidgetItem( this, label_, checkbox_, checkbox_, !checkbox_ );
00954     widget_item_->addToParent();
00955     widget_item_->setExpanded( true );
00956   }
00957   // setData() call must be before any setProperty...() calls, because
00958   // those can trigger the itemChanged() signal which ultimately
00959   // causes readFromGrid() to be called, which calls the Setter and
00960   // clobbers our new data.
00961   if( checkbox_ )
00962   {
00963     widget_item_->setData( 1, Qt::CheckStateRole, get() ? Qt::Checked : Qt::Unchecked );
00964   }
00965 
00966   setPropertyHelpText( grid_, widget_item_, help_text_ );
00967 }
00968 
00969 void CategoryProperty::readFromGrid()
00970 {
00971   if (checkbox_)
00972   {
00973     QVariant check_state = widget_item_->data( 1, Qt::CheckStateRole );
00974     ROS_ASSERT( !check_state.isNull() );
00975     bool new_state = (check_state != Qt::Unchecked);
00976     if( get() != new_state )
00977     {
00978       set( new_state );
00979     }
00980   }
00981 }
00982 
00983 void CategoryProperty::saveToConfig( Config* config )
00984 {
00985   if (checkbox_)
00986   {
00987     config->set( prefix_ + name_, get() );
00988   }
00989 }
00990 
00991 void CategoryProperty::loadFromConfig( Config* config )
00992 {
00993   if (checkbox_)
00994   {
00995     int val;
00996     if (!config->get( prefix_ + name_, &val, get() ))
00997     {
00998       V_string::iterator it = legacy_names_.begin();
00999       V_string::iterator end = legacy_names_.end();
01000       for (; it != end; ++it)
01001       {
01002         if (config->get( prefix_ + *it, &val, get() ))
01003         {
01004           break;
01005         }
01006       }
01007     }
01008 
01009     set( (bool) val );
01010   }
01011 }
01012 
01013 void CategoryProperty::setToOK()
01014 {
01015   if (grid_)
01016   {
01017     setPropertyToColors( grid_, widget_item_, Qt::white, CATEGORY_COLOR);
01018 
01019     if( widget_item_ )
01020     {
01021       QFont font = widget_item_->font( 0 );
01022       font.setBold( true );
01023       widget_item_->setFont( 0, font );
01024     }
01025   }
01026 }
01027 
01028 void Vector3Property::doWriteToGrid()
01029 {
01030   if( !widget_item_ )
01031   {
01032     widget_item_ = new CompoundWidgetItem( this, name_, hasSetter() );
01033     widget_item_->addToParent();
01034     x_ = new PropertyWidgetItem( this, "X", hasSetter() );
01035     x_->addToParent( widget_item_ );
01036     y_ = new PropertyWidgetItem( this, "Y", hasSetter() );
01037     y_->addToParent( widget_item_ );
01038     z_ = new PropertyWidgetItem( this, "Z", hasSetter() );
01039     z_->addToParent( widget_item_ );
01040 
01041     widget_item_->setExpanded( false );
01042   }
01043   
01044   Ogre::Vector3 v = get();
01045   x_->setUserData( QVariant( v.x ));
01046   y_->setUserData( QVariant( v.y ));
01047   z_->setUserData( QVariant( v.z ));
01048 
01049   CompoundWidgetItem* cwi = dynamic_cast<CompoundWidgetItem*>( widget_item_ );
01050   ROS_ASSERT( cwi );
01051   cwi->updateText();
01052 
01053   setPropertyHelpText( grid_, widget_item_, help_text_ );
01054   setPropertyHelpText( grid_, x_, help_text_ );
01055   setPropertyHelpText( grid_, y_, help_text_ );
01056   setPropertyHelpText( grid_, z_, help_text_ );
01057 }
01058 
01059 void Vector3Property::readFromGrid()
01060 {
01061   float x = x_->userData().toFloat();
01062   float y = y_->userData().toFloat();
01063   float z = z_->userData().toFloat();
01064 
01065   CompoundWidgetItem* cwi = dynamic_cast<CompoundWidgetItem*>( widget_item_ );
01066   ROS_ASSERT( cwi );
01067   cwi->updateText();
01068 
01069   set( Ogre::Vector3( x, y, z ));
01070 }
01071 
01072 void Vector3Property::saveToConfig( Config* config )
01073 {
01074   Ogre::Vector3 v = get();
01075 
01076   config->set( prefix_ + name_ + "X", v.x );
01077   config->set( prefix_ + name_ + "Y", v.y );
01078   config->set( prefix_ + name_ + "Z", v.z );
01079 }
01080 
01081 void Vector3Property::loadFromConfig( Config* config )
01082 {
01083   Ogre::Vector3 v = get();
01084   float x, y, z;
01085   bool found = true;
01086   found &= config->get( prefix_ + name_ + "X", &x, v.x );
01087   found &= config->get( prefix_ + name_ + "Y", &y, v.y );
01088   found &= config->get( prefix_ + name_ + "Z", &z, v.z );
01089 
01090   if (!found)
01091   {
01092     V_string::iterator it = legacy_names_.begin();
01093     V_string::iterator end = legacy_names_.end();
01094     for (; it != end; ++it)
01095     {
01096       found = true;
01097       found &= config->get( prefix_ + *it + "X", &x, v.x );
01098       found &= config->get( prefix_ + *it + "Y", &y, v.y );
01099       found &= config->get( prefix_ + *it + "Z", &z, v.z );
01100 
01101       if (found)
01102       {
01103         break;
01104       }
01105     }
01106   }
01107 
01108   set( Ogre::Vector3( x, y, z ) );
01109 }
01110 
01111 void Vector3Property::reset()
01112 {
01113   Property<Ogre::Vector3>::reset();
01114 
01115   // Widget item children of widget_item_ are deleted by their parent,
01116   // in PropertyBase::reset(), so don't need to be deleted here.
01117   x_ = 0;
01118   y_ = 0;
01119   z_ = 0;
01120 }
01121 
01122 void QuaternionProperty::doWriteToGrid()
01123 {
01124   if( !widget_item_ )
01125   {
01126     widget_item_ = new CompoundWidgetItem( this, name_, hasSetter() );
01127     widget_item_->addToParent();
01128     x_ = new PropertyWidgetItem( this, "X", hasSetter() );
01129     x_->addToParent( widget_item_ );
01130     y_ = new PropertyWidgetItem( this, "Y", hasSetter() );
01131     y_->addToParent( widget_item_ );
01132     z_ = new PropertyWidgetItem( this, "Z", hasSetter() );
01133     z_->addToParent( widget_item_ );
01134     w_ = new PropertyWidgetItem( this, "W", hasSetter() );
01135     w_->addToParent( widget_item_ );
01136 
01137     widget_item_->setExpanded( false );
01138   }
01139   
01140   Ogre::Quaternion q = get();
01141   x_->setUserData( QVariant( q.x ));
01142   y_->setUserData( QVariant( q.y ));
01143   z_->setUserData( QVariant( q.z ));
01144   w_->setUserData( QVariant( q.w ));
01145 
01146   CompoundWidgetItem* cwi = dynamic_cast<CompoundWidgetItem*>( widget_item_ );
01147   ROS_ASSERT( cwi );
01148   cwi->updateText();
01149 
01150   setPropertyHelpText( grid_, widget_item_, help_text_ );
01151   setPropertyHelpText( grid_, x_, help_text_ );
01152   setPropertyHelpText( grid_, y_, help_text_ );
01153   setPropertyHelpText( grid_, z_, help_text_ );
01154   setPropertyHelpText( grid_, w_, help_text_ );
01155 }
01156 
01157 void QuaternionProperty::readFromGrid()
01158 {
01159   float x = x_->userData().toFloat();
01160   float y = y_->userData().toFloat();
01161   float z = z_->userData().toFloat();
01162   float w = w_->userData().toFloat();
01163 
01164   CompoundWidgetItem* cwi = dynamic_cast<CompoundWidgetItem*>( widget_item_ );
01165   ROS_ASSERT( cwi );
01166   cwi->updateText();
01167 
01168   set( Ogre::Quaternion( w, x, y, z ));
01169 }
01170 
01171 void QuaternionProperty::saveToConfig( Config* config )
01172 {
01173   Ogre::Quaternion q = get();
01174 
01175   config->set( prefix_ + name_ + "X", q.x );
01176   config->set( prefix_ + name_ + "Y", q.y );
01177   config->set( prefix_ + name_ + "Z", q.z );
01178   config->set( prefix_ + name_ + "W", q.w );
01179 }
01180 
01181 void QuaternionProperty::loadFromConfig( Config* config )
01182 {
01183   Ogre::Quaternion q = get();
01184   float x, y, z, w;
01185   bool found = true;
01186   found &= config->get( prefix_ + name_ + "X", &x, q.x );
01187   found &= config->get( prefix_ + name_ + "Y", &y, q.y );
01188   found &= config->get( prefix_ + name_ + "Z", &z, q.z );
01189   found &= config->get( prefix_ + name_ + "W", &w, q.w );
01190 
01191   if (!found)
01192   {
01193     V_string::iterator it = legacy_names_.begin();
01194     V_string::iterator end = legacy_names_.end();
01195     for (; it != end; ++it)
01196     {
01197       found = true;
01198       found &= config->get( prefix_ + *it + "X", &x, q.x );
01199       found &= config->get( prefix_ + *it + "Y", &y, q.y );
01200       found &= config->get( prefix_ + *it + "Z", &z, q.z );
01201       found &= config->get( prefix_ + *it + "W", &w, q.w );
01202 
01203       if (found)
01204       {
01205         break;
01206       }
01207     }
01208   }
01209 
01210   set( Ogre::Quaternion( w, x, y, z ) );
01211 }
01212 
01213 void QuaternionProperty::reset()
01214 {
01215   Property<Ogre::Quaternion>::reset();
01216 
01217   // Widget item children of widget_item_ are deleted by their parent,
01218   // in PropertyBase::reset(), so don't need to be deleted here.
01219   x_ = 0;
01220   y_ = 0;
01221   z_ = 0;
01222   w_ = 0;
01223 }
01224 
01225 }


rviz
Author(s): Dave Hershberger, Josh Faust
autogenerated on Mon Jan 6 2014 11:54:32