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 "rviz/properties/property.h"
00035 #include "rviz/properties/property_tree_delegate.h"
00036 #include "rviz/properties/splitter_handle.h"
00037 #include "rviz/properties/status_list.h"
00038
00039 #include "rviz/properties/property_tree_widget.h"
00040
00041 namespace rviz
00042 {
00043
00044 PropertyTreeWidget::PropertyTreeWidget( QWidget* parent )
00045 : QTreeView( parent )
00046 , model_( NULL )
00047 , splitter_handle_( new SplitterHandle( this ))
00048 {
00049 setItemDelegateForColumn( 1, new PropertyTreeDelegate( this ));
00050 setDropIndicatorShown( true );
00051 setUniformRowHeights( true );
00052 setHeaderHidden( true );
00053 setDragEnabled( true );
00054 setAcceptDrops( true );
00055 setAnimated( true );
00056 setSelectionMode( QAbstractItemView::ExtendedSelection );
00057 setEditTriggers( QAbstractItemView::AllEditTriggers );
00058 setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
00059
00060 QTimer* timer = new QTimer( this );
00061 connect( timer, SIGNAL( timeout() ), this, SLOT( update() ));
00062 timer->start( 100 );
00063 }
00064
00065 void PropertyTreeWidget::currentChanged( const QModelIndex& new_current_index, const QModelIndex& previous_current_index )
00066 {
00067 QTreeView::currentChanged( new_current_index, previous_current_index );
00068 Q_EMIT currentPropertyChanged( static_cast<const Property*>( new_current_index.internalPointer() ));
00069 }
00070
00071 void PropertyTreeWidget::selectionChanged( const QItemSelection& selected, const QItemSelection& deselected )
00072 {
00073 QTreeView::selectionChanged( selected, deselected );
00074 Q_EMIT selectionHasChanged();
00075 }
00076
00077 void PropertyTreeWidget::setModel( PropertyTreeModel* model )
00078 {
00079 if( model_ )
00080 {
00081 disconnect( model_, SIGNAL( propertyHiddenChanged( const Property* )),
00082 this, SLOT( propertyHiddenChanged( const Property* )));
00083 disconnect( model_, SIGNAL( expand( const QModelIndex& )),
00084 this, SLOT( expand( const QModelIndex& )));
00085 disconnect( model_, SIGNAL( collapse( const QModelIndex& )),
00086 this, SLOT( collapse( const QModelIndex& )));
00087 }
00088 model_ = model;
00089 QTreeView::setModel( model_ );
00090 if( model_ )
00091 {
00092 connect( model_, SIGNAL( propertyHiddenChanged( const Property* )),
00093 this, SLOT( propertyHiddenChanged( const Property* )), Qt::QueuedConnection );
00094 connect( model_, SIGNAL( expand( const QModelIndex& )),
00095 this, SLOT( expand( const QModelIndex& )));
00096 connect( model_, SIGNAL( collapse( const QModelIndex& )),
00097 this, SLOT( collapse( const QModelIndex& )));
00098
00099
00100 model_->getRoot()->setModel( model_->getRoot()->getModel() );
00101 }
00102
00103 }
00104
00105 void PropertyTreeWidget::propertyHiddenChanged( const Property* property )
00106 {
00107 if( model_ )
00108 {
00109 setRowHidden( property->rowNumberInParent(), model_->parentIndex( property ), property->getHidden() );
00110 }
00111 }
00112
00113 void PropertyTreeWidget::save( Config config ) const
00114 {
00115 saveExpandedEntries( config.mapMakeChild( "Expanded" ), QModelIndex(), "" );
00116
00117 config.mapSetValue( "Splitter Ratio", splitter_handle_->getRatio() );
00118 }
00119
00120 void PropertyTreeWidget::saveExpandedEntries( Config config, const QModelIndex& parent_index, const QString& prefix ) const
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 config.listAppendNew().setValue( full_name );
00142 }
00143 saveExpandedEntries( config, child_index, full_name );
00144 }
00145 }
00146 }
00147
00148 void PropertyTreeWidget::load( const Config& config )
00149 {
00150 Config expanded_list_config = config.mapGetChild( "Expanded" );
00151 QSet<QString> expanded_full_names;
00152 int num_expanded = expanded_list_config.listLength();
00153 for( int i = 0; i < num_expanded; i++ )
00154 {
00155 expanded_full_names.insert( expanded_list_config.listChildAt( i ).getValue().toString() );
00156 }
00157 expandEntries( expanded_full_names, QModelIndex(), "" );
00158
00159 float ratio;
00160 if( config.mapGetFloat( "Splitter Ratio", &ratio ))
00161 {
00162 splitter_handle_->setRatio( ratio );
00163 }
00164 }
00165
00166 void PropertyTreeWidget::expandEntries( const QSet<QString>& expanded_full_names,
00167 const QModelIndex& parent_index,
00168 const QString& prefix )
00169 {
00170 int num_children = model_->rowCount( parent_index );
00171 if( num_children > 0 )
00172 {
00173 QHash<QString, int> name_counts;
00174 for( int i = 0; i < num_children; i++ )
00175 {
00176 QModelIndex child_index = model_->index( i, 0, parent_index );
00177 Property* child = model_->getProp( child_index );
00178 QString child_name = child->getName();
00179 if( qobject_cast<StatusList*>( child ))
00180 {
00181 child_name = "Status";
00182 }
00183 int name_occurrence = ++( name_counts[ child_name ]);
00184 QString full_name = prefix + "/" + child_name + QString::number( name_occurrence );
00185 if( expanded_full_names.contains( full_name ))
00186 {
00187 setExpanded( child_index, true );
00188 }
00189 expandEntries( expanded_full_names, child_index, full_name );
00190 }
00191 }
00192 }
00193
00194 }