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 <QTimer>
00031 #include <QHash>
00032 #include <QSet>
00033
00034 #include <yaml-cpp/emitter.h>
00035 #include <yaml-cpp/node.h>
00036
00037 #include "rviz/properties/property.h"
00038 #include "rviz/properties/property_tree_delegate.h"
00039 #include "rviz/properties/splitter_handle.h"
00040 #include "rviz/properties/status_list.h"
00041 #include "rviz/properties/yaml_helpers.h"
00042
00043 #include "rviz/properties/property_tree_widget.h"
00044
00045 namespace rviz
00046 {
00047
00048 PropertyTreeWidget::PropertyTreeWidget( QWidget* parent )
00049 : QTreeView( parent )
00050 , model_( NULL )
00051 , splitter_handle_( new SplitterHandle( this ))
00052 {
00053 setItemDelegateForColumn( 1, new PropertyTreeDelegate( this ));
00054 setDropIndicatorShown( true );
00055 setUniformRowHeights( true );
00056 setHeaderHidden( true );
00057 setDragEnabled( true );
00058 setAcceptDrops( true );
00059 setAnimated( true );
00060 setSelectionMode( QAbstractItemView::ExtendedSelection );
00061 setEditTriggers( QAbstractItemView::AllEditTriggers );
00062
00063 QTimer* timer = new QTimer( this );
00064 connect( timer, SIGNAL( timeout() ), this, SLOT( update() ));
00065 timer->start( 100 );
00066 }
00067
00068 void PropertyTreeWidget::currentChanged( const QModelIndex& new_current_index, const QModelIndex& previous_current_index )
00069 {
00070 QTreeView::currentChanged( new_current_index, previous_current_index );
00071 Q_EMIT currentPropertyChanged( static_cast<const Property*>( new_current_index.internalPointer() ));
00072 }
00073
00074 void PropertyTreeWidget::selectionChanged( const QItemSelection& selected, const QItemSelection& deselected )
00075 {
00076 QTreeView::selectionChanged( selected, deselected );
00077 Q_EMIT selectionHasChanged();
00078 }
00079
00080 void PropertyTreeWidget::setModel( PropertyTreeModel* model )
00081 {
00082 if( model_ )
00083 {
00084 disconnect( model_, SIGNAL( propertyHiddenChanged( const Property* )),
00085 this, SLOT( propertyHiddenChanged( const Property* )));
00086 disconnect( model_, SIGNAL( expand( const QModelIndex& )),
00087 this, SLOT( expand( const QModelIndex& )));
00088 }
00089 model_ = model;
00090 QTreeView::setModel( model_ );
00091 connect( model_, SIGNAL( propertyHiddenChanged( const Property* )),
00092 this, SLOT( propertyHiddenChanged( const Property* )));
00093 connect( model_, SIGNAL( expand( const QModelIndex& )),
00094 this, SLOT( expand( const QModelIndex& )));
00095 }
00096
00097 void PropertyTreeWidget::propertyHiddenChanged( const Property* property )
00098 {
00099 setRowHidden( property->rowNumberInParent(), model_->parentIndex( property ), property->getHidden() );
00100 }
00101
00102 void PropertyTreeWidget::save( YAML::Emitter& emitter )
00103 {
00104 emitter << YAML::BeginMap;
00105
00106 emitter << YAML::Key << "Expanded";
00107 emitter << YAML::Value;
00108 {
00109 emitter << YAML::BeginSeq;
00110 saveExpandedEntries( emitter, QModelIndex(), "" );
00111 emitter << YAML::EndSeq;
00112 }
00113
00114 emitter << YAML::Key << "Splitter Ratio";
00115 emitter << YAML::Value << splitter_handle_->getRatio();
00116
00117 emitter << YAML::EndMap;
00118 }
00119
00120 void PropertyTreeWidget::saveExpandedEntries( YAML::Emitter& emitter, const QModelIndex& parent_index, const QString& prefix )
00121 {
00122 int num_children = model_->rowCount( parent_index );
00123 if( num_children > 0 )
00124 {
00125 QHash<QString, int> name_counts;
00126 for( int i = 0; i < num_children; i++ )
00127 {
00128 QModelIndex child_index = model_->index( i, 0, parent_index );
00129 Property* child = model_->getProp( child_index );
00130 QString child_name = child->getName();
00131 if( qobject_cast<StatusList*>( child ))
00132 {
00133
00134
00135 child_name = "Status";
00136 }
00137 int name_occurrence = ++( name_counts[ child_name ]);
00138 QString full_name = prefix + "/" + child_name + QString::number( name_occurrence );
00139 if( isExpanded( child_index ))
00140 {
00141 emitter << full_name;
00142 }
00143 saveExpandedEntries( emitter, child_index, full_name );
00144 }
00145 }
00146 }
00147
00148 void PropertyTreeWidget::load( const YAML::Node& yaml_node )
00149 {
00150 if( const YAML::Node *expanded_node = yaml_node.FindValue( "Expanded" ))
00151 {
00152 QSet<QString> expanded_full_names;
00153 for( unsigned i = 0; i < expanded_node->size(); i++ )
00154 {
00155 QString full_name;
00156 (*expanded_node)[ i ] >> full_name;
00157 expanded_full_names.insert( full_name );
00158 }
00159
00160 expandEntries( expanded_full_names, QModelIndex(), "" );
00161 }
00162
00163 if( const YAML::Node *ratio_node = yaml_node.FindValue( "Splitter Ratio" ))
00164 {
00165 float ratio;
00166 (*ratio_node) >> ratio;
00167 splitter_handle_->setRatio( ratio );
00168 }
00169 }
00170
00171 void PropertyTreeWidget::expandEntries( const QSet<QString>& expanded_full_names,
00172 const QModelIndex& parent_index,
00173 const QString& prefix )
00174 {
00175 int num_children = model_->rowCount( parent_index );
00176 if( num_children > 0 )
00177 {
00178 QHash<QString, int> name_counts;
00179 for( int i = 0; i < num_children; i++ )
00180 {
00181 QModelIndex child_index = model_->index( i, 0, parent_index );
00182 Property* child = model_->getProp( child_index );
00183 QString child_name = child->getName();
00184 if( qobject_cast<StatusList*>( child ))
00185 {
00186 child_name = "Status";
00187 }
00188 int name_occurrence = ++( name_counts[ child_name ]);
00189 QString full_name = prefix + "/" + child_name + QString::number( name_occurrence );
00190 if( expanded_full_names.contains( full_name ))
00191 {
00192 setExpanded( child_index, true );
00193 }
00194 expandEntries( expanded_full_names, child_index, full_name );
00195 }
00196 }
00197 }
00198
00199 }