Back to index

salome-gui  6.5.0
QtxTreeView.cxx
Go to the documentation of this file.
00001 // Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
00002 //
00003 // This library is free software; you can redistribute it and/or
00004 // modify it under the terms of the GNU Lesser General Public
00005 // License as published by the Free Software Foundation; either
00006 // version 2.1 of the License.
00007 //
00008 // This library is distributed in the hope that it will be useful,
00009 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00011 // Lesser General Public License for more details.
00012 //
00013 // You should have received a copy of the GNU Lesser General Public
00014 // License along with this library; if not, write to the Free Software
00015 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00016 //
00017 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
00018 //
00019 
00020 // File:      QtxTreeView.cxx
00021 // Author:    Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com)
00022 //
00023 #include "QtxTreeView.h"
00024 
00025 #include <QHeaderView>
00026 #include <QMenu>
00027 #include <QMouseEvent>
00028 
00035 class QtxTreeView::Header : public QHeaderView
00036 {
00037 public:
00038   Header( const bool, QWidget* = 0 );
00039   ~Header();
00040 
00041   void     setSortMenuEnabled( const bool );
00042   bool     sortMenuEnabled() const;
00043 
00044 protected:
00045   void     contextMenuEvent( QContextMenuEvent* );
00046 
00047 private:
00048   bool     myEnableSortMenu;
00049 };
00050 
00057 QtxTreeView::Header::Header( const bool enableSortMenu, QWidget* parent )
00058 : QHeaderView( Qt::Horizontal, parent ),
00059   myEnableSortMenu( enableSortMenu )
00060 {
00061 }
00062 
00067 QtxTreeView::Header::~Header()
00068 {
00069 }
00070 
00071 /*
00072   \brief Enable/disable "Sorting" popup menu command for the header.
00073   \param enableSortMenu if \c true, enable "Sorting" menu command
00074   \internal
00075 */
00076 void QtxTreeView::Header::setSortMenuEnabled( const bool enableSortMenu )
00077 {
00078   myEnableSortMenu = enableSortMenu;
00079 }
00080 
00081 /*
00082   \brief Check if "Sorting" popup menu command for the header is enabled.
00083   \return \c true if "Sorting" menu command is enabled
00084   \internal
00085 */
00086 bool QtxTreeView::Header::sortMenuEnabled() const
00087 {
00088   return myEnableSortMenu;
00089 }
00090 
00100 void QtxTreeView::Header::contextMenuEvent( QContextMenuEvent* e )
00101 {
00102   QMenu menu;
00103   QMap<QAction*, int> actionMap;
00104   for ( int i = 0; i < count(); i++ ) {
00105     QString  lab         = model()->headerData( i, orientation(), Qt::DisplayRole ).toString();
00106     QVariant iconData    = model()->headerData( i, orientation(), Qt::DecorationRole );
00107     QVariant appropriate = model()->headerData( i, orientation(), Qtx::AppropriateRole );
00108     QIcon icon;
00109     if ( iconData.isValid() ) {
00110       if ( qVariantCanConvert<QIcon>( iconData ) )
00111         icon = qVariantValue<QIcon>( iconData );
00112       else if ( qVariantCanConvert<QPixmap>( iconData ) )
00113         icon = qVariantValue<QPixmap>( iconData );
00114     }
00115     if( ( !lab.isEmpty() || !icon.isNull() ) && 
00116             appropriate.isValid() ? appropriate.toInt()==Qtx::Toggled : true )
00117         {
00118       QAction* a = menu.addAction( icon, lab );
00119       a->setCheckable( true );
00120       a->setChecked( !isSectionHidden( i ) );
00121       actionMap.insert( a, i );
00122     }
00123   }
00124   QAction* sortAction = 0;
00125   if ( count() > 0 && myEnableSortMenu ) {
00126     menu.addSeparator();
00127     sortAction = menu.addAction( QtxTreeView::tr( "Enable sorting" ) );
00128     sortAction->setCheckable( true );
00129     sortAction->setChecked( isSortIndicatorShown() );
00130   }
00131   if ( !menu.isEmpty() ) {
00132     Qtx::simplifySeparators( &menu );
00133     QAction* a = menu.exec( e->globalPos() );
00134     if ( a && actionMap.contains( a ) ) {
00135       setSectionHidden( actionMap[ a ], !isSectionHidden( actionMap[ a ] ) );
00136     }
00137     else if ( a && a == sortAction ) {
00138       setSortIndicatorShown( a->isChecked() );
00139       setClickable( a->isChecked() );
00140       QtxTreeView* view = qobject_cast<QtxTreeView*>( parent() );
00141       if ( view ) {
00142         view->emitSortingEnabled( a->isChecked() );
00143         if ( a->isChecked() ) {
00144           connect( this, SIGNAL( sectionClicked( int ) ), view, SLOT( onHeaderClicked( int ) ) );
00145           view->sortByColumn( sortIndicatorSection(), sortIndicatorOrder() );
00146         }
00147         else {
00148           disconnect( this, SIGNAL( sectionClicked( int ) ), view, SLOT( onHeaderClicked( int ) ) );
00149           view->sortByColumn( 0, Qt::AscendingOrder );
00150         }
00151       }
00152     }
00153   }
00154   e->accept();
00155 }
00156 
00157 
00179 QtxTreeView::QtxTreeView( QWidget* parent )
00180 : QTreeView( parent )
00181 {
00182   setHeader( new Header( false, this ) );
00183   header()->setMovable( true );
00184 }
00185 
00191 QtxTreeView::QtxTreeView( const bool enableSortMenu, QWidget* parent )
00192 : QTreeView( parent )
00193 {
00194   setHeader( new Header( enableSortMenu, this ) );
00195   header()->setMovable( true );
00196 }
00197 
00201 QtxTreeView::~QtxTreeView()
00202 {
00203 }
00204 
00214 void QtxTreeView::expandLevels( const int levels )
00215 {
00216   setOpened( rootIndex(), levels+1, true );
00217 }
00218 
00228 void QtxTreeView::collapseLevels( const int levels )
00229 {
00230   setOpened( rootIndex(), levels+1, false );
00231 }
00232 
00239 void QtxTreeView::expandAll( const QModelIndex& index )
00240 {
00241   setOpened( index, -1, true );
00242 }
00243 
00250 void QtxTreeView::collapseAll( const QModelIndex& index )
00251 {
00252   setOpened( index, -1, false );
00253 }
00254 
00255 /*
00256   \brief Enable/disable "Sorting" popup menu command for the header.
00257   \param enableSortMenu if \c true, enable "Sorting" menu command
00258   \sa sortMenuEnabled()
00259 */
00260 void QtxTreeView::setSortMenuEnabled( const bool enableSortMenu )
00261 {
00262   Header* h = dynamic_cast<Header*>( header() );
00263   if ( h )
00264     h->setSortMenuEnabled( enableSortMenu );
00265 }
00266 
00267 /*
00268   \brief Check if "Sorting" popup menu command for the header is enabled.
00269   \return \c true if "Sorting" menu command is enabled
00270   \sa setSortMenuEnabled()
00271 */
00272 bool QtxTreeView::sortMenuEnabled() const
00273 {
00274   Header* h = dynamic_cast<Header*>( header() );
00275   return h ? h->sortMenuEnabled() : false;
00276 }
00277 
00284 void QtxTreeView::resizeColumnToEncloseContents( int column )
00285 {
00286   if (column < 0 || column >= header()->count())
00287     return;
00288 
00289   int contentsSizeHint = sizeHintForColumn(column);
00290   int headerSizeHint = header()->isHidden() ? 0 : header()->sectionSizeHint(column);
00291   int sizeHint = qMax(contentsSizeHint, headerSizeHint);
00292 
00293   int currentSize = columnWidth( column );
00294   if (currentSize < sizeHint)
00295     setColumnWidth( column, sizeHint );
00296 }
00297 
00298 /*
00299   \brief Called when the header section is clicked.
00300   \param column header column index
00301 */
00302 void QtxTreeView::onHeaderClicked( int column )
00303 {
00304   sortByColumn( column, header()->sortIndicatorOrder() );
00305 }
00306 
00315 void QtxTreeView::selectionChanged( const QItemSelection& selected, 
00316                                     const QItemSelection& deselected )
00317 {
00318   QTreeView::selectionChanged( selected, deselected );
00319   emit( selectionChanged() );
00320 }
00321 
00328 void QtxTreeView::rowsAboutToBeRemoved( const QModelIndex& parent, int start, int end )
00329 {
00330   QModelIndex curIndex = currentIndex();
00331   while ( curIndex.isValid() && curIndex.parent() != parent )
00332     curIndex = curIndex.parent();
00333   if ( curIndex.isValid() && curIndex.row() >= start && curIndex.row() <= end )
00334     setCurrentIndex( QModelIndex() );
00335   QTreeView::rowsAboutToBeRemoved( parent, start, end );
00336 }
00337 
00345 void QtxTreeView::setOpened( const QModelIndex& index, const int levels, bool open )
00346 {
00347   if ( !levels )
00348     return;
00349 
00350   if ( !index.isValid() && index != rootIndex() )
00351     return;
00352 
00353   setExpanded( index, open );
00354 
00355   for ( int i = 0; i < model()->rowCount( index ); i++ ) {
00356     QModelIndex child = model()->index( i, 0, index );
00357     setOpened( child, levels-1, open );
00358   }
00359 }
00360 
00376 void QtxTreeView::emitSortingEnabled( bool enabled )
00377 {
00378   emit( sortingEnabled( enabled ) );
00379 }
00380 
00381 void QtxTreeView::setModel( QAbstractItemModel* m )
00382 {
00383   if( model() )
00384     disconnect( model(), SIGNAL( headerDataChanged( Qt::Orientation, int, int ) ),
00385                 this, SLOT( onAppropriate( Qt::Orientation, int, int ) ) );
00386   QTreeView::setModel( m );
00387   if ( model() )
00388     connect( model(), SIGNAL( headerDataChanged( Qt::Orientation, int, int ) ),
00389              this, SLOT( onAppropriate( Qt::Orientation, int, int ) ) );
00390 }
00391 
00392 void QtxTreeView::onAppropriate( Qt::Orientation orient, int first, int last )
00393 {
00394   if( orient==Qt::Horizontal )
00395     for( int i=first; i<=last; i++ )
00396         {
00397           int appr = model()->headerData( i, orient, Qtx::AppropriateRole ).toInt();
00398           header()->setSectionHidden( i, appr==Qtx::Hidden );
00399         }
00400 }