1 // Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 // File: QtxTreeView.cxx
21 // Author: Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com)
23 #include "QtxTreeView.h"
25 #include <QHeaderView>
27 #include <QMouseEvent>
30 \class QtxTreeView::Header
31 \brief Custom tree view header class.
35 class QtxTreeView::Header : public QHeaderView
38 Header( const bool, QWidget* = 0 );
41 void setSortMenuEnabled( const bool );
42 bool sortMenuEnabled() const;
45 void contextMenuEvent( QContextMenuEvent* );
48 bool myEnableSortMenu;
53 \param enableSortMenu show "Sorting" menu if \c true
54 \param parent parent widget
57 QtxTreeView::Header::Header( const bool enableSortMenu, QWidget* parent )
58 : QHeaderView( Qt::Horizontal, parent ),
59 myEnableSortMenu( enableSortMenu )
67 QtxTreeView::Header::~Header()
72 \brief Enable/disable "Sorting" popup menu command for the header.
73 \param enableSortMenu if \c true, enable "Sorting" menu command
76 void QtxTreeView::Header::setSortMenuEnabled( const bool enableSortMenu )
78 myEnableSortMenu = enableSortMenu;
82 \brief Check if "Sorting" popup menu command for the header is enabled.
83 \return \c true if "Sorting" menu command is enabled
86 bool QtxTreeView::Header::sortMenuEnabled() const
88 return myEnableSortMenu;
92 \brief Customize context menu event.
95 Shows popup menu with the list of the available columns allowing the user to
96 show/hide the specified column.
98 \param e context menu event
100 void QtxTreeView::Header::contextMenuEvent( QContextMenuEvent* e )
103 QMap<QAction*, int> actionMap;
104 for ( int i = 0; i < count(); i++ ) {
105 QString lab = model()->headerData( i, orientation(), Qt::DisplayRole ).toString();
106 QVariant iconData = model()->headerData( i, orientation(), Qt::DecorationRole );
107 QVariant appropriate = model()->headerData( i, orientation(), Qtx::AppropriateRole );
109 if ( iconData.isValid() ) {
110 if ( qVariantCanConvert<QIcon>( iconData ) )
111 icon = qVariantValue<QIcon>( iconData );
112 else if ( qVariantCanConvert<QPixmap>( iconData ) )
113 icon = qVariantValue<QPixmap>( iconData );
115 if( ( !lab.isEmpty() || !icon.isNull() ) &&
116 appropriate.isValid() ? appropriate.toInt()==Qtx::Toggled : true )
118 QAction* a = menu.addAction( icon, lab );
119 a->setCheckable( true );
120 a->setChecked( !isSectionHidden( i ) );
121 actionMap.insert( a, i );
124 QAction* sortAction = 0;
125 if ( count() > 0 && myEnableSortMenu ) {
127 sortAction = menu.addAction( QtxTreeView::tr( "Enable sorting" ) );
128 sortAction->setCheckable( true );
129 sortAction->setChecked( isSortIndicatorShown() );
131 if ( !menu.isEmpty() ) {
132 Qtx::simplifySeparators( &menu );
133 QAction* a = menu.exec( e->globalPos() );
134 if ( a && actionMap.contains( a ) ) {
135 setSectionHidden( actionMap[ a ], !isSectionHidden( actionMap[ a ] ) );
137 else if ( a && a == sortAction ) {
138 setSortIndicatorShown( a->isChecked() );
139 setClickable( a->isChecked() );
140 QtxTreeView* view = qobject_cast<QtxTreeView*>( parent() );
142 view->emitSortingEnabled( a->isChecked() );
143 if ( a->isChecked() ) {
144 connect( this, SIGNAL( sectionClicked( int ) ), view, SLOT( onHeaderClicked( int ) ) );
145 view->sortByColumn( sortIndicatorSection(), sortIndicatorOrder() );
148 disconnect( this, SIGNAL( sectionClicked( int ) ), view, SLOT( onHeaderClicked( int ) ) );
149 view->sortByColumn( 0, Qt::AscendingOrder );
160 \brief Tree view class with possibility to display columns popup menu.
162 The QtxTreeView class represents a customized tree view class. In addition to the
163 base functionality inherited from the QTreeView class, clicking at the tree view
164 header with the right mouse button displays the popup menu allowing the user
165 to show/hide specified columns.
167 By default the popup menu contains items corresponding to all the tree view columns.
168 In order to disable some columns from being shown in the popup menu one may customize
169 the data model (see QAbstractItemModel class). The custom model should implement
170 headerData() method and return \c true for the Qtx::AppropriateRole role for
171 those columns which should be available in the popup menu and \c false for the columns
172 which should not be added to it.
177 \param parent parent widget
179 QtxTreeView::QtxTreeView( QWidget* parent )
180 : QTreeView( parent )
182 setHeader( new Header( false, this ) );
183 header()->setMovable( true );
188 \param enableSortMenu show "Sorting" header menu command if \c true
189 \param parent parent widget
191 QtxTreeView::QtxTreeView( const bool enableSortMenu, QWidget* parent )
192 : QTreeView( parent )
194 setHeader( new Header( enableSortMenu, this ) );
195 header()->setMovable( true );
201 QtxTreeView::~QtxTreeView()
206 \brief Expand all branches for specified number of levels.
208 If \c levels < 0, all branches are expanded (the same results can
209 be achieved with expandAll() method).
211 \param levels number of levels to be opened
212 \sa collapseLevels(), setOpened()
214 void QtxTreeView::expandLevels( const int levels )
216 setOpened( rootIndex(), levels+1, true );
220 \brief Collapse all branches for specified number of levels.
222 If \c levels < 0, all branches are collapsed (the same results can
223 be achieved with collapseAll() method).
225 \param levels number of levels to be collapsed
226 \sa expandLevels(), setOpened()
228 void QtxTreeView::collapseLevels( const int levels )
230 setOpened( rootIndex(), levels+1, false );
234 \brief Expand the branch specifed by the \index and all its
235 children recursively.
236 \param index model index to be expanded
239 void QtxTreeView::expandAll( const QModelIndex& index )
241 setOpened( index, -1, true );
245 \brief Collapse the branch specifed by the \index and all its
246 children recursively.
247 \param index model index to be collapsed
250 void QtxTreeView::collapseAll( const QModelIndex& index )
252 setOpened( index, -1, false );
256 \brief Enable/disable "Sorting" popup menu command for the header.
257 \param enableSortMenu if \c true, enable "Sorting" menu command
258 \sa sortMenuEnabled()
260 void QtxTreeView::setSortMenuEnabled( const bool enableSortMenu )
262 Header* h = dynamic_cast<Header*>( header() );
264 h->setSortMenuEnabled( enableSortMenu );
268 \brief Check if "Sorting" popup menu command for the header is enabled.
269 \return \c true if "Sorting" menu command is enabled
270 \sa setSortMenuEnabled()
272 bool QtxTreeView::sortMenuEnabled() const
274 Header* h = dynamic_cast<Header*>( header() );
275 return h ? h->sortMenuEnabled() : false;
279 \brief Resizes the given column in order to enclose its contents.
280 The size will be changed only if it is smaller than the size of
282 \param column number of column
284 void QtxTreeView::resizeColumnToEncloseContents( int column )
286 if (column < 0 || column >= header()->count())
289 int contentsSizeHint = sizeHintForColumn(column);
290 int headerSizeHint = header()->isHidden() ? 0 : header()->sectionSizeHint(column);
291 int sizeHint = qMax(contentsSizeHint, headerSizeHint);
293 int currentSize = columnWidth( column );
294 if (currentSize < sizeHint)
295 setColumnWidth( column, sizeHint );
299 \brief Called when the header section is clicked.
300 \param column header column index
302 void QtxTreeView::onHeaderClicked( int column )
304 sortByColumn( column, header()->sortIndicatorOrder() );
308 \brief Called when the selection is changed.
310 Emits selectionChanged() signal.
312 \param selected new selection
313 \param deselected previous selection
315 void QtxTreeView::selectionChanged( const QItemSelection& selected,
316 const QItemSelection& deselected )
318 QTreeView::selectionChanged( selected, deselected );
319 emit( selectionChanged() );
323 \brief Called when rows are about to be removed.
324 \param parent model index
325 \param start first row to remove
326 \param end last row to remove
328 void QtxTreeView::rowsAboutToBeRemoved( const QModelIndex& parent, int start, int end )
330 QModelIndex curIndex = currentIndex();
331 while ( curIndex.isValid() && curIndex.parent() != parent )
332 curIndex = curIndex.parent();
333 if ( curIndex.isValid() && curIndex.row() >= start && curIndex.row() <= end )
334 setCurrentIndex( QModelIndex() );
335 QTreeView::rowsAboutToBeRemoved( parent, start, end );
339 \brief Expand/collapse the specified item (recursively).
340 \param index model index
341 \param levels number of levels to be expanded/collapsed
342 \param open if \c true, item is expanded, otherwise it is collapsed
343 \sa expandLevels(), collapseLevels()
345 void QtxTreeView::setOpened( const QModelIndex& index, const int levels, bool open )
350 if ( !index.isValid() && index != rootIndex() )
353 setExpanded( index, open );
355 for ( int i = 0; i < model()->rowCount( index ); i++ ) {
356 QModelIndex child = model()->index( i, 0, index );
357 setOpened( child, levels-1, open );
362 \fn QtxTreeView::sortingEnabled( bool on );
363 \brief Emitted when "Sorting" commans is enabled/disabled from the popup menu.
364 \param on \c true if sorting is enabled and \c false otherwise
368 \fn QtxTreeView::selectionChanged();
369 \brief Emitted when selection is changed in the tree view.
373 \brief Emit sortingEnabled(bool) signal.
374 \param enabled "enable sorting" flag state
376 void QtxTreeView::emitSortingEnabled( bool enabled )
378 emit( sortingEnabled( enabled ) );
381 void QtxTreeView::setModel( QAbstractItemModel* m )
384 disconnect( model(), SIGNAL( headerDataChanged( Qt::Orientation, int, int ) ),
385 this, SLOT( onAppropriate( Qt::Orientation, int, int ) ) );
386 QTreeView::setModel( m );
388 connect( model(), SIGNAL( headerDataChanged( Qt::Orientation, int, int ) ),
389 this, SLOT( onAppropriate( Qt::Orientation, int, int ) ) );
392 void QtxTreeView::onAppropriate( Qt::Orientation orient, int first, int last )
394 if( orient==Qt::Horizontal )
395 for( int i=first; i<=last; i++ )
397 int appr = model()->headerData( i, orient, Qtx::AppropriateRole ).toInt();
398 header()->setSectionHidden( i, appr==Qtx::Hidden );