1 // Copyright (C) 2007-2008 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
22 // File: QtxTreeView.cxx
23 // Author: Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com)
25 #include "QtxTreeView.h"
27 #include <QHeaderView>
29 #include <QMouseEvent>
32 \class QtxTreeView::Header
33 \brief Custom tree view header class.
37 class QtxTreeView::Header : public QHeaderView
40 Header( const bool, QWidget* = 0 );
43 void setSortMenuEnabled( const bool );
44 bool sortMenuEnabled() const;
47 void contextMenuEvent( QContextMenuEvent* );
50 bool myEnableSortMenu;
55 \param enableSortMenu show "Sorting" menu if \c true
56 \param parent parent widget
59 QtxTreeView::Header::Header( const bool enableSortMenu, QWidget* parent )
60 : QHeaderView( Qt::Horizontal, parent ),
61 myEnableSortMenu( enableSortMenu )
69 QtxTreeView::Header::~Header()
74 \brief Enable/disable "Sorting" popup menu command for the header.
75 \param enableSortMenu if \c true, enable "Sorting" menu command
78 void QtxTreeView::Header::setSortMenuEnabled( const bool enableSortMenu )
80 myEnableSortMenu = enableSortMenu;
84 \brief Check if "Sorting" popup menu command for the header is enabled.
85 \return \c true if "Sorting" menu command is enabled
88 bool QtxTreeView::Header::sortMenuEnabled() const
90 return myEnableSortMenu;
94 \brief Customize context menu event.
97 Shows popup menu with the list of the available columns allowing the user to
98 show/hide the specified column.
100 \param e context menu event
102 void QtxTreeView::Header::contextMenuEvent( QContextMenuEvent* e )
105 QMap<QAction*, int> actionMap;
106 for ( int i = 0; i < count(); i++ ) {
107 QString lab = model()->headerData( i, orientation(), Qt::DisplayRole ).toString();
108 QVariant iconData = model()->headerData( i, orientation(), Qt::DecorationRole );
109 QVariant appropriate = model()->headerData( i, orientation(), Qtx::AppropriateRole );
111 if ( iconData.isValid() ) {
112 if ( qVariantCanConvert<QIcon>( iconData ) )
113 icon = qVariantValue<QIcon>( iconData );
114 else if ( qVariantCanConvert<QPixmap>( iconData ) )
115 icon = qVariantValue<QPixmap>( iconData );
117 if( ( !lab.isEmpty() || !icon.isNull() ) &&
118 appropriate.isValid() ? appropriate.toInt()==Qtx::Toggled : true )
120 QAction* a = menu.addAction( icon, lab );
121 a->setCheckable( true );
122 a->setChecked( !isSectionHidden( i ) );
123 actionMap.insert( a, i );
126 QAction* sortAction = 0;
127 if ( count() > 0 && myEnableSortMenu ) {
129 sortAction = menu.addAction( tr( "Enable sorting" ) );
130 sortAction->setCheckable( true );
131 sortAction->setChecked( isSortIndicatorShown() );
133 if ( !menu.isEmpty() ) {
134 Qtx::simplifySeparators( &menu );
135 QAction* a = menu.exec( e->globalPos() );
136 if ( a && actionMap.contains( a ) ) {
137 setSectionHidden( actionMap[ a ], !isSectionHidden( actionMap[ a ] ) );
139 else if ( a && a == sortAction ) {
140 setSortIndicatorShown( a->isChecked() );
141 setClickable( a->isChecked() );
142 QtxTreeView* view = qobject_cast<QtxTreeView*>( parent() );
144 view->emitSortingEnabled( a->isChecked() );
145 if ( a->isChecked() ) {
146 connect( this, SIGNAL( sectionClicked( int ) ), view, SLOT( onHeaderClicked( int ) ) );
147 view->sortByColumn( sortIndicatorSection(), sortIndicatorOrder() );
150 disconnect( this, SIGNAL( sectionClicked( int ) ), view, SLOT( onHeaderClicked( int ) ) );
151 view->sortByColumn( 0, Qt::AscendingOrder );
162 \brief Tree view class with possibility to display columns popup menu.
164 The QtxTreeView class represents a customized tree view class. In addition to the
165 base functionality inherited from the QTreeView class, clicking at the tree view
166 header with the right mouse button displays the popup menu allowing the user
167 to show/hide specified columns.
169 By default the popup menu contains items corresponding to all the tree view columns.
170 In order to disable some columns from being shown in the popup menu one may customize
171 the data model (see QAbstractItemModel class). The custom model should implement
172 headerData() method and return \c true for the Qtx::AppropriateRole role for
173 those columns which should be available in the popup menu and \c false for the columns
174 which should not be added to it.
179 \param parent parent widget
181 QtxTreeView::QtxTreeView( QWidget* parent )
182 : QTreeView( parent )
184 setHeader( new Header( false, this ) );
185 header()->setMovable( true );
190 \param enableSortMenu show "Sorting" header menu command if \c true
191 \param parent parent widget
193 QtxTreeView::QtxTreeView( const bool enableSortMenu, QWidget* parent )
194 : QTreeView( parent )
196 setHeader( new Header( enableSortMenu, this ) );
197 header()->setMovable( true );
203 QtxTreeView::~QtxTreeView()
208 \brief Expand all branches for specified number of levels.
210 If \c levels < 0, all branches are expanded (the same results can
211 be achieved with expandAll() method).
213 \param levels number of levels to be opened
214 \sa collapseLevels(), setOpened()
216 void QtxTreeView::expandLevels( const int levels )
218 setOpened( rootIndex(), levels+1, true );
222 \brief Collapse all branches for specified number of levels.
224 If \c levels < 0, all branches are collapsed (the same results can
225 be achieved with collapseAll() method).
227 \param levels number of levels to be collapsed
228 \sa expandLevels(), setOpened()
230 void QtxTreeView::collapseLevels( const int levels )
232 setOpened( rootIndex(), levels+1, false );
236 \brief Expand the branch specifed by the \index and all its
237 children recursively.
238 \param index model index to be expanded
241 void QtxTreeView::expandAll( const QModelIndex& index )
243 setOpened( index, -1, true );
247 \brief Collapse the branch specifed by the \index and all its
248 children recursively.
249 \param index model index to be collapsed
252 void QtxTreeView::collapseAll( const QModelIndex& index )
254 setOpened( index, -1, false );
258 \brief Enable/disable "Sorting" popup menu command for the header.
259 \param enableSortMenu if \c true, enable "Sorting" menu command
260 \sa sortMenuEnabled()
262 void QtxTreeView::setSortMenuEnabled( const bool enableSortMenu )
264 Header* h = dynamic_cast<Header*>( header() );
266 h->setSortMenuEnabled( enableSortMenu );
270 \brief Check if "Sorting" popup menu command for the header is enabled.
271 \return \c true if "Sorting" menu command is enabled
272 \sa setSortMenuEnabled()
274 bool QtxTreeView::sortMenuEnabled() const
276 Header* h = dynamic_cast<Header*>( header() );
277 return h ? h->sortMenuEnabled() : false;
281 \brief Resizes the given column in order to enclose its contents.
282 The size will be changed only if it is smaller than the size of
284 \param column number of column
286 void QtxTreeView::resizeColumnToEncloseContents( int column )
288 if (column < 0 || column >= header()->count())
291 int contentsSizeHint = sizeHintForColumn(column);
292 int headerSizeHint = header()->isHidden() ? 0 : header()->sectionSizeHint(column);
293 int sizeHint = qMax(contentsSizeHint, headerSizeHint);
295 int currentSize = columnWidth( column );
296 if (currentSize < sizeHint)
297 setColumnWidth( column, sizeHint );
301 \brief Called when the header section is clicked.
302 \param column header column index
304 void QtxTreeView::onHeaderClicked( int column )
306 sortByColumn( column, header()->sortIndicatorOrder() );
310 \brief Called when the selection is changed.
312 Emits selectionChanged() signal.
314 \param selected new selection
315 \param deselected previous selection
317 void QtxTreeView::selectionChanged( const QItemSelection& selected,
318 const QItemSelection& deselected )
320 QTreeView::selectionChanged( selected, deselected );
321 emit( selectionChanged() );
325 \brief Called when rows are about to be removed.
326 \param parent model index
327 \param start first row to remove
328 \param end last row to remove
330 void QtxTreeView::rowsAboutToBeRemoved( const QModelIndex& parent, int start, int end )
332 setCurrentIndex( QModelIndex() );
333 QTreeView::rowsAboutToBeRemoved( parent, start, end );
337 \brief Expand/collapse the specified item (recursively).
338 \param index model index
339 \param levels number of levels to be expanded/collapsed
340 \param open if \c true, item is expanded, otherwise it is collapsed
341 \sa expandLevels(), collapseLevels()
343 void QtxTreeView::setOpened( const QModelIndex& index, const int levels, bool open )
348 if ( !index.isValid() && index != rootIndex() )
351 setExpanded( index, open );
353 for ( int i = 0; i < model()->rowCount( index ); i++ ) {
354 QModelIndex child = model()->index( i, 0, index );
355 setOpened( child, levels-1, open );
360 \fn QtxTreeView::sortingEnabled( bool on );
361 \brief Emitted when "Sorting" commans is enabled/disabled from the popup menu.
362 \param on \c true if sorting is enabled and \c false otherwise
366 \fn QtxTreeView::selectionChanged();
367 \brief Emitted when selection is changed in the tree view.
371 \brief Emit sortingEnabled(bool) signal.
372 \param enabled "enable sorting" flag state
374 void QtxTreeView::emitSortingEnabled( bool enabled )
376 emit( sortingEnabled( enabled ) );
379 void QtxTreeView::setModel( QAbstractItemModel* m )
382 disconnect( model(), SIGNAL( headerDataChanged( Qt::Orientation, int, int ) ),
383 this, SLOT( onAppropriate( Qt::Orientation, int, int ) ) );
384 QTreeView::setModel( m );
386 connect( model(), SIGNAL( headerDataChanged( Qt::Orientation, int, int ) ),
387 this, SLOT( onAppropriate( Qt::Orientation, int, int ) ) );
390 void QtxTreeView::onAppropriate( Qt::Orientation orient, int first, int last )
392 if( orient==Qt::Horizontal )
393 for( int i=first; i<=last; i++ )
395 int appr = model()->headerData( i, orient, Qtx::AppropriateRole ).toInt();
396 header()->setSectionHidden( i, appr==Qtx::Hidden );