displays_panel.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 <QTimer>
00031 #include <QHBoxLayout>
00032 #include <QVBoxLayout>
00033 #include <QPushButton>
00034 #include <QInputDialog>
00035 #include <QApplication>
00036 
00037 #include <boost/bind.hpp>
00038 
00039 #include "rviz/display_factory.h"
00040 #include "rviz/display.h"
00041 #include "rviz/add_display_dialog.h"
00042 #include "rviz/properties/property.h"
00043 #include "rviz/properties/property_tree_widget.h"
00044 #include "rviz/properties/property_tree_with_help.h"
00045 #include "rviz/visualization_manager.h"
00046 
00047 #include "rviz/displays_panel.h"
00048 
00049 namespace rviz
00050 {
00051 
00052 DisplaysPanel::DisplaysPanel( QWidget* parent )
00053   : Panel( parent )
00054 {
00055   tree_with_help_ = new PropertyTreeWithHelp;
00056   property_grid_ = tree_with_help_->getTree();
00057 
00058   QPushButton* add_button = new QPushButton( "Add" );
00059   add_button->setShortcut( QKeySequence( QString( "Ctrl+N" )));
00060   add_button->setToolTip( "Add a new display, Ctrl+N" );
00061   duplicate_button_ = new QPushButton( "Duplicate" );
00062   duplicate_button_->setShortcut( QKeySequence( QString( "Ctrl+D" )));
00063   duplicate_button_->setToolTip( "Duplicate a display, Ctrl+D" );
00064   duplicate_button_->setEnabled( false );
00065   remove_button_ = new QPushButton( "Remove" );
00066   remove_button_->setShortcut( QKeySequence( QString( "Ctrl+X" )));
00067   remove_button_->setToolTip( "Remove displays, Ctrl+X" );
00068   remove_button_->setEnabled( false );
00069   rename_button_ = new QPushButton( "Rename" );
00070   rename_button_->setShortcut( QKeySequence( QString( "Ctrl+R" )));
00071   rename_button_->setToolTip( "Rename a display, Ctrl+R" );
00072   rename_button_->setEnabled( false );
00073 
00074   QHBoxLayout* button_layout = new QHBoxLayout;
00075   button_layout->addWidget( add_button );
00076   button_layout->addWidget( duplicate_button_ );
00077   button_layout->addWidget( remove_button_ );
00078   button_layout->addWidget( rename_button_ );
00079   button_layout->setContentsMargins( 2, 0, 2, 2 );
00080 
00081   QVBoxLayout* layout = new QVBoxLayout;
00082   layout->setContentsMargins( 0, 0, 0, 2 );
00083   layout->addWidget( tree_with_help_ );
00084   layout->addLayout( button_layout );
00085 
00086   setLayout( layout );
00087 
00088   connect( add_button, SIGNAL( clicked( bool )), this, SLOT( onNewDisplay() ));
00089   connect( duplicate_button_, SIGNAL( clicked( bool )), this, SLOT( onDuplicateDisplay() ));
00090   connect( remove_button_, SIGNAL( clicked( bool )), this, SLOT( onDeleteDisplay() ));
00091   connect( rename_button_, SIGNAL( clicked( bool )), this, SLOT( onRenameDisplay() ));
00092   connect( property_grid_, SIGNAL( selectionHasChanged() ), this, SLOT( onSelectionChanged() ));
00093 }
00094 
00095 DisplaysPanel::~DisplaysPanel()
00096 {
00097 }
00098 
00099 void DisplaysPanel::onInitialize()
00100 {
00101   property_grid_->setModel( vis_manager_->getDisplayTreeModel() );
00102 }
00103 
00104 void DisplaysPanel::onNewDisplay()
00105 {
00106   QString lookup_name;
00107   QString display_name;
00108   QString topic;
00109   QString datatype;
00110 
00111   QStringList empty;
00112 
00113   QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
00114   AddDisplayDialog* dialog = new AddDisplayDialog( vis_manager_->getDisplayFactory(),
00115                                                    "Display",
00116                                                    empty, empty,
00117                                                    &lookup_name,
00118                                                    &display_name,
00119                                                    &topic,
00120                                                    &datatype );
00121   QApplication::restoreOverrideCursor();
00122 
00123   vis_manager_->stopUpdate();
00124   if( dialog->exec() == QDialog::Accepted )
00125   {
00126     Display *disp = vis_manager_->createDisplay( lookup_name, display_name, true );
00127     if ( !topic.isEmpty() && !datatype.isEmpty() )
00128     {
00129       disp->setTopic( topic, datatype );
00130     }
00131   }
00132   vis_manager_->startUpdate();
00133   activateWindow(); // Force keyboard focus back on main window.
00134   delete dialog;
00135 }
00136 
00137 void DisplaysPanel::onDuplicateDisplay()
00138 {
00139   QList<Display*> displays_to_duplicate = property_grid_->getSelectedObjects<Display>();
00140 
00141   QList<Display*> duplicated_displays;
00142 
00143   for( int i = 0; i < displays_to_duplicate.size(); i++ )
00144   {
00145     // initialize display
00146     QString lookup_name = displays_to_duplicate[ i ]->getClassId();
00147     QString display_name = displays_to_duplicate[ i ]->getName();
00148     Display *disp = vis_manager_->createDisplay( lookup_name, display_name, true );
00149     // duplicate config
00150     Config config;
00151     displays_to_duplicate[ i ]->save(config);
00152     disp->load(config);
00153     duplicated_displays.push_back(disp);
00154   }
00155   // make sure the newly duplicated displays are selected.
00156   if (duplicated_displays.size() > 0) {
00157     QModelIndex first = property_grid_->getModel()->indexOf(duplicated_displays.front());
00158     QModelIndex last = property_grid_->getModel()->indexOf(duplicated_displays.back());
00159     QItemSelection selection(first, last);
00160     property_grid_->selectionModel()->select(selection, QItemSelectionModel::ClearAndSelect);
00161   }
00162   vis_manager_->startUpdate();
00163   activateWindow(); // Force keyboard focus back on main window.
00164 }
00165 
00166 void DisplaysPanel::onDeleteDisplay()
00167 {
00168   QList<Display*> displays_to_delete = property_grid_->getSelectedObjects<Display>();
00169 
00170   QModelIndex new_selected;
00171 
00172   for( int i = 0; i < displays_to_delete.size(); i++ )
00173   {
00174     if (i == 0) {
00175       QModelIndex first = property_grid_->getModel()->indexOf(displays_to_delete[i]);
00176       // This is safe because the first few rows cannot be deleted (they aren't "displays").
00177       new_selected = first.sibling(first.row() - 1, first.column());
00178     }
00179     // Displays can emit signals from other threads with self pointers.  We're
00180     // freeing the display now, so ensure no one is listening to those signals.
00181     displays_to_delete[ i ]->disconnect();
00182     // Delete display later in case there are pending signals to it.
00183     displays_to_delete[ i ]->deleteLater();
00184   }
00185 
00186   QItemSelection selection(new_selected, new_selected);
00187   property_grid_->selectionModel()->select(selection, QItemSelectionModel::ClearAndSelect);
00188 
00189   vis_manager_->notifyConfigChanged();
00190 }
00191 
00192 void DisplaysPanel::onSelectionChanged()
00193 {
00194   QList<Display*> displays = property_grid_->getSelectedObjects<Display>();
00195 
00196   int num_displays_selected = displays.size();
00197 
00198   duplicate_button_->setEnabled( num_displays_selected > 0 );
00199   remove_button_->setEnabled( num_displays_selected > 0 );
00200   rename_button_->setEnabled( num_displays_selected == 1 );
00201 }
00202 
00203 void DisplaysPanel::onRenameDisplay()
00204 {
00205   QList<Display*> displays = property_grid_->getSelectedObjects<Display>();
00206   if( displays.size() == 0 )
00207   {
00208     return;
00209   }
00210   Display* display_to_rename = displays[ 0 ];
00211 
00212   if( !display_to_rename )
00213   {
00214     return;
00215   }
00216 
00217   QString old_name = display_to_rename->getName();
00218   QString new_name = QInputDialog::getText( this, "Rename Display", "New Name?", QLineEdit::Normal, old_name );
00219 
00220   if( new_name.isEmpty() || new_name == old_name )
00221   {
00222     return;
00223   }
00224 
00225   display_to_rename->setName( new_name );
00226 }
00227 
00228 void DisplaysPanel::save( Config config ) const
00229 {
00230   Panel::save( config );
00231   tree_with_help_->save( config );
00232 }
00233 
00234 void DisplaysPanel::load( const Config& config )
00235 {
00236   Panel::load( config );
00237   tree_with_help_->load( config );
00238 }
00239 
00240 } // namespace rviz


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