1 // Copyright (C) 2007-2016 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, or (at your option) any later version.
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 ( iconData.canConvert( QVariant::Icon ) )
111 icon = iconData.value<QIcon>();
112 else if ( iconData.canConvert( QVariant::Pixmap ) )
113 icon = iconData.value<QPixmap>();
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 setSortIndicator( 0, Qt::AscendingOrder );
146 view->sortByColumn( sortIndicatorSection(), sortIndicatorOrder() );
149 disconnect( this, SIGNAL( sectionClicked( int ) ), view, SLOT( onHeaderClicked( int ) ) );
150 view->sortByColumn( 0, Qt::AscendingOrder );
161 \brief Tree view class with possibility to display columns popup menu.
163 The QtxTreeView class represents a customized tree view class. In addition to the
164 base functionality inherited from the QTreeView class, clicking at the tree view
165 header with the right mouse button displays the popup menu allowing the user
166 to show/hide specified columns.
168 By default the popup menu contains items corresponding to all the tree view columns.
169 In order to disable some columns from being shown in the popup menu one may customize
170 the data model (see QAbstractItemModel class). The custom model should implement
171 headerData() method and return \c true for the Qtx::AppropriateRole role for
172 those columns which should be available in the popup menu and \c false for the columns
173 which should not be added to it.
178 \param parent parent widget
180 QtxTreeView::QtxTreeView( QWidget* parent )
181 : QTreeView( parent )
183 setHeader( new Header( false, this ) );
184 header()->setMovable( true );
189 \param enableSortMenu show "Sorting" header menu command if \c true
190 \param parent parent widget
192 QtxTreeView::QtxTreeView( const bool enableSortMenu, QWidget* parent )
193 : QTreeView( parent )
195 setHeader( new Header( enableSortMenu, this ) );
196 header()->setMovable( true );
202 QtxTreeView::~QtxTreeView()
207 \brief Expand all branches for specified number of levels.
209 If \c levels < 0, all branches are expanded (the same results can
210 be achieved with expandAll() method).
212 \param levels number of levels to be opened
213 \sa collapseLevels(), setOpened()
215 void QtxTreeView::expandLevels( const int levels )
217 setOpened( rootIndex(), levels+1, true );
221 \brief Collapse all branches for specified number of levels.
223 If \c levels < 0, all branches are collapsed (the same results can
224 be achieved with collapseAll() method).
226 \param levels number of levels to be collapsed
227 \sa expandLevels(), setOpened()
229 void QtxTreeView::collapseLevels( const int levels )
231 setOpened( rootIndex(), levels+1, false );
235 \brief Expand the branch specifed by the \index and all its
236 children recursively.
237 \param index model index to be expanded
240 void QtxTreeView::expandAll( const QModelIndex& index )
242 setOpened( index, -1, true );
246 \brief Collapse the branch specifed by the \index and all its
247 children recursively.
248 \param index model index to be collapsed
251 void QtxTreeView::collapseAll( const QModelIndex& index )
253 setOpened( index, -1, false );
257 \brief Enable/disable "Sorting" popup menu command for the header.
258 \param enableSortMenu if \c true, enable "Sorting" menu command
259 \sa sortMenuEnabled()
261 void QtxTreeView::setSortMenuEnabled( const bool enableSortMenu )
263 Header* h = dynamic_cast<Header*>( header() );
265 h->setSortMenuEnabled( enableSortMenu );
269 \brief Check if "Sorting" popup menu command for the header is enabled.
270 \return \c true if "Sorting" menu command is enabled
271 \sa setSortMenuEnabled()
273 bool QtxTreeView::sortMenuEnabled() const
275 Header* h = dynamic_cast<Header*>( header() );
276 return h ? h->sortMenuEnabled() : false;
280 \brief Resizes the given column in order to enclose its contents.
281 The size will be changed only if it is smaller than the size of
283 \param column number of column
285 void QtxTreeView::resizeColumnToEncloseContents( int column )
287 if (column < 0 || column >= header()->count())
290 int contentsSizeHint = sizeHintForColumn(column);
291 int headerSizeHint = header()->isHidden() ? 0 : header()->sectionSizeHint(column);
292 int sizeHint = qMax(contentsSizeHint, headerSizeHint);
294 int currentSize = columnWidth( column );
295 if (currentSize < sizeHint)
296 setColumnWidth( column, sizeHint );
300 \brief Called when the header section is clicked.
301 \param column header column index
303 void QtxTreeView::onHeaderClicked( int column )
305 sortByColumn( column, header()->sortIndicatorOrder() );
309 \brief Called when the selection is changed.
311 Emits selectionChanged() signal.
313 \param selected new selection
314 \param deselected previous selection
316 void QtxTreeView::selectionChanged( const QItemSelection& selected,
317 const QItemSelection& deselected )
319 QTreeView::selectionChanged( selected, deselected );
320 emit( selectionChanged() );
324 \brief Called when rows are about to be removed.
325 \param parent model index
326 \param start first row to remove
327 \param end last row to remove
329 void QtxTreeView::rowsAboutToBeRemoved( const QModelIndex& parent, int start, int end )
331 QModelIndex curIndex = currentIndex();
332 while ( curIndex.isValid() && curIndex.parent() != parent )
333 curIndex = curIndex.parent();
334 if ( curIndex.isValid() && curIndex.row() >= start && curIndex.row() <= end )
335 setCurrentIndex( QModelIndex() );
336 QTreeView::rowsAboutToBeRemoved( parent, start, end );
340 \brief Expand/collapse the specified item (recursively).
341 \param index model index
342 \param levels number of levels to be expanded/collapsed
343 \param open if \c true, item is expanded, otherwise it is collapsed
344 \sa expandLevels(), collapseLevels()
346 void QtxTreeView::setOpened( const QModelIndex& index, const int levels, bool open )
351 if ( !index.isValid() && index != rootIndex() )
354 setExpanded( index, open );
356 for ( int i = 0; i < model()->rowCount( index ); i++ ) {
357 QModelIndex child = model()->index( i, 0, index );
358 setOpened( child, levels-1, open );
363 \fn QtxTreeView::sortingEnabled( bool on );
364 \brief Emitted when "Sorting" commans is enabled/disabled from the popup menu.
365 \param on \c true if sorting is enabled and \c false otherwise
369 \fn QtxTreeView::selectionChanged();
370 \brief Emitted when selection is changed in the tree view.
374 \brief Emit sortingEnabled(bool) signal.
375 \param enabled "enable sorting" flag state
377 void QtxTreeView::emitSortingEnabled( bool enabled )
379 emit( sortingEnabled( enabled ) );
382 void QtxTreeView::setModel( QAbstractItemModel* m )
385 disconnect( model(), SIGNAL( headerDataChanged( Qt::Orientation, int, int ) ),
386 this, SLOT( onAppropriate( Qt::Orientation, int, int ) ) );
387 QTreeView::setModel( m );
389 connect( model(), SIGNAL( headerDataChanged( Qt::Orientation, int, int ) ),
390 this, SLOT( onAppropriate( Qt::Orientation, int, int ) ) );
393 void QtxTreeView::onAppropriate( Qt::Orientation orient, int first, int last )
395 if( orient==Qt::Horizontal )
396 for( int i=first; i<=last; i++ )
398 int appr = model()->headerData( i, orient, Qtx::AppropriateRole ).toInt();
399 header()->setSectionHidden( i, appr==Qtx::Hidden );