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 QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
111 if ( iconData.canConvert( QVariant::Icon ) )
112 icon = iconData.value<QIcon>();
113 else if ( iconData.canConvert( QVariant::Pixmap ) )
114 icon = iconData.value<QPixmap>();
116 if ( iconData.canConvert( QMetaType::QIcon ) )
117 icon = iconData.value<QIcon>();
118 else if ( iconData.canConvert( QMetaType::QPixmap ) )
119 icon = iconData.value<QPixmap>();
122 if( ( !lab.isEmpty() || !icon.isNull() ) &&
123 appropriate.isValid() ? appropriate.toInt()==Qtx::Toggled : true )
125 QAction* a = menu.addAction( icon, lab );
126 a->setCheckable( true );
127 a->setChecked( !isSectionHidden( i ) );
128 actionMap.insert( a, i );
131 QAction* sortAction = 0;
132 if ( count() > 0 && myEnableSortMenu ) {
134 sortAction = menu.addAction( QtxTreeView::tr( "Enable sorting" ) );
135 sortAction->setCheckable( true );
136 sortAction->setChecked( isSortIndicatorShown() );
138 if ( !menu.isEmpty() ) {
139 Qtx::simplifySeparators( &menu );
140 QAction* a = menu.exec( e->globalPos() );
141 if ( a && actionMap.contains( a ) ) {
142 setSectionHidden( actionMap[ a ], !isSectionHidden( actionMap[ a ] ) );
144 else if ( a && a == sortAction ) {
145 setSortIndicatorShown( a->isChecked() );
146 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
147 setClickable( a->isChecked() );
149 setSectionsClickable( a->isChecked() );
151 QtxTreeView* view = qobject_cast<QtxTreeView*>( parent() );
153 view->emitSortingEnabled( a->isChecked() );
154 if ( a->isChecked() ) {
155 connect( this, SIGNAL( sectionClicked( int ) ), view, SLOT( onHeaderClicked( int ) ) );
156 setSortIndicator( 0, Qt::AscendingOrder );
157 view->sortByColumn( sortIndicatorSection(), sortIndicatorOrder() );
160 disconnect( this, SIGNAL( sectionClicked( int ) ), view, SLOT( onHeaderClicked( int ) ) );
161 view->sortByColumn( 0, Qt::AscendingOrder );
172 \brief Tree view class with possibility to display columns popup menu.
174 The QtxTreeView class represents a customized tree view class. In addition to the
175 base functionality inherited from the QTreeView class, clicking at the tree view
176 header with the right mouse button displays the popup menu allowing the user
177 to show/hide specified columns.
179 By default the popup menu contains items corresponding to all the tree view columns.
180 In order to disable some columns from being shown in the popup menu one may customize
181 the data model (see QAbstractItemModel class). The custom model should implement
182 headerData() method and return \c true for the Qtx::AppropriateRole role for
183 those columns which should be available in the popup menu and \c false for the columns
184 which should not be added to it.
189 \param parent parent widget
191 QtxTreeView::QtxTreeView( QWidget* parent )
192 : QTreeView( parent )
194 setHeader( new Header( false, this ) );
195 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
196 header()->setMovable( true );
198 header()->setSectionsMovable( true );
204 \param enableSortMenu show "Sorting" header menu command if \c true
205 \param parent parent widget
207 QtxTreeView::QtxTreeView( const bool enableSortMenu, QWidget* parent )
208 : QTreeView( parent )
210 setHeader( new Header( enableSortMenu, this ) );
211 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
212 header()->setMovable( true );
214 header()->setSectionsMovable( true );
221 QtxTreeView::~QtxTreeView()
226 \brief Expand all branches for specified number of levels.
228 If \c levels < 0, all branches are expanded (the same results can
229 be achieved with expandAll() method).
231 \param levels number of levels to be opened
232 \sa collapseLevels(), setOpened()
234 void QtxTreeView::expandLevels( const int levels )
236 setOpened( rootIndex(), levels+1, true );
240 \brief Collapse all branches for specified number of levels.
242 If \c levels < 0, all branches are collapsed (the same results can
243 be achieved with collapseAll() method).
245 \param levels number of levels to be collapsed
246 \sa expandLevels(), setOpened()
248 void QtxTreeView::collapseLevels( const int levels )
250 setOpened( rootIndex(), levels+1, false );
254 \brief Expand the branch specifed by the \index and all its
255 children recursively.
256 \param index model index to be expanded
259 void QtxTreeView::expandAll( const QModelIndex& index )
261 setOpened( index, -1, true );
265 \brief Collapse the branch specifed by the \index and all its
266 children recursively.
267 \param index model index to be collapsed
270 void QtxTreeView::collapseAll( const QModelIndex& index )
272 setOpened( index, -1, false );
276 \brief Enable/disable "Sorting" popup menu command for the header.
277 \param enableSortMenu if \c true, enable "Sorting" menu command
278 \sa sortMenuEnabled()
280 void QtxTreeView::setSortMenuEnabled( const bool enableSortMenu )
282 Header* h = dynamic_cast<Header*>( header() );
284 h->setSortMenuEnabled( enableSortMenu );
288 \brief Check if "Sorting" popup menu command for the header is enabled.
289 \return \c true if "Sorting" menu command is enabled
290 \sa setSortMenuEnabled()
292 bool QtxTreeView::sortMenuEnabled() const
294 Header* h = dynamic_cast<Header*>( header() );
295 return h ? h->sortMenuEnabled() : false;
299 \brief Resizes the given column in order to enclose its contents.
300 The size will be changed only if it is smaller than the size of
302 \param column number of column
304 void QtxTreeView::resizeColumnToEncloseContents( int column )
306 if (column < 0 || column >= header()->count())
309 int contentsSizeHint = sizeHintForColumn(column);
310 int headerSizeHint = header()->isHidden() ? 0 : header()->sectionSizeHint(column);
311 int sizeHint = qMax(contentsSizeHint, headerSizeHint);
313 int currentSize = columnWidth( column );
314 if (currentSize < sizeHint)
315 setColumnWidth( column, sizeHint );
319 \brief Called when the header section is clicked.
320 \param column header column index
322 void QtxTreeView::onHeaderClicked( int column )
324 sortByColumn( column, header()->sortIndicatorOrder() );
328 \brief Called when the selection is changed.
330 Emits selectionChanged() signal.
332 \param selected new selection
333 \param deselected previous selection
335 void QtxTreeView::selectionChanged( const QItemSelection& selected,
336 const QItemSelection& deselected )
338 QTreeView::selectionChanged( selected, deselected );
339 emit( selectionChanged() );
343 \brief Called when rows are about to be removed.
344 \param parent model index
345 \param start first row to remove
346 \param end last row to remove
348 void QtxTreeView::rowsAboutToBeRemoved( const QModelIndex& parent, int start, int end )
350 QModelIndex curIndex = currentIndex();
351 while ( curIndex.isValid() && curIndex.parent() != parent )
352 curIndex = curIndex.parent();
353 if ( curIndex.isValid() && curIndex.row() >= start && curIndex.row() <= end )
354 setCurrentIndex( QModelIndex() );
355 QTreeView::rowsAboutToBeRemoved( parent, start, end );
359 \brief Expand/collapse the specified item (recursively).
360 \param index model index
361 \param levels number of levels to be expanded/collapsed
362 \param open if \c true, item is expanded, otherwise it is collapsed
363 \sa expandLevels(), collapseLevels()
365 void QtxTreeView::setOpened( const QModelIndex& index, const int levels, bool open )
370 if ( !index.isValid() && index != rootIndex() )
373 setExpanded( index, open );
375 for ( int i = 0; i < model()->rowCount( index ); i++ ) {
376 QModelIndex child = model()->index( i, 0, index );
377 setOpened( child, levels-1, open );
382 \fn QtxTreeView::sortingEnabled( bool on );
383 \brief Emitted when "Sorting" commans is enabled/disabled from the popup menu.
384 \param on \c true if sorting is enabled and \c false otherwise
388 \fn QtxTreeView::selectionChanged();
389 \brief Emitted when selection is changed in the tree view.
393 \brief Emit sortingEnabled(bool) signal.
394 \param enabled "enable sorting" flag state
396 void QtxTreeView::emitSortingEnabled( bool enabled )
398 emit( sortingEnabled( enabled ) );
401 void QtxTreeView::setModel( QAbstractItemModel* m )
404 disconnect( model(), SIGNAL( headerDataChanged( Qt::Orientation, int, int ) ),
405 this, SLOT( onAppropriate( Qt::Orientation, int, int ) ) );
406 QTreeView::setModel( m );
408 connect( model(), SIGNAL( headerDataChanged( Qt::Orientation, int, int ) ),
409 this, SLOT( onAppropriate( Qt::Orientation, int, int ) ) );
412 void QtxTreeView::onAppropriate( Qt::Orientation orient, int first, int last )
414 if( orient==Qt::Horizontal )
415 for( int i=first; i<=last; i++ )
417 int appr = model()->headerData( i, orient, Qtx::AppropriateRole ).toInt();
418 header()->setSectionHidden( i, appr==Qtx::Hidden );