1 // Copyright (C) 2007-2023 CEA, EDF, 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>
31 \class QtxTreeView::Header
32 \brief Custom tree view header class.
36 class QtxTreeView::Header : public QHeaderView
39 Header( const bool, QWidget* = 0 );
42 void setSortMenuEnabled( const bool );
43 bool sortMenuEnabled() const;
46 void contextMenuEvent( QContextMenuEvent* );
49 bool myEnableSortMenu;
54 \param enableSortMenu show "Sorting" menu if \c true
55 \param parent parent widget
58 QtxTreeView::Header::Header( const bool enableSortMenu, QWidget* parent )
59 : QHeaderView( Qt::Horizontal, parent ),
60 myEnableSortMenu( enableSortMenu )
68 QtxTreeView::Header::~Header()
73 \brief Enable/disable "Sorting" popup menu command for the header.
74 \param enableSortMenu if \c true, enable "Sorting" menu command
77 void QtxTreeView::Header::setSortMenuEnabled( const bool enableSortMenu )
79 myEnableSortMenu = enableSortMenu;
83 \brief Check if "Sorting" popup menu command for the header is enabled.
84 \return \c true if "Sorting" menu command is enabled
87 bool QtxTreeView::Header::sortMenuEnabled() const
89 return myEnableSortMenu;
93 \brief Customize context menu event.
96 Shows popup menu with the list of the available columns allowing the user to
97 show/hide the specified column.
99 \param e context menu event
101 void QtxTreeView::Header::contextMenuEvent( QContextMenuEvent* e )
104 QMap<QAction*, int> actionMap;
105 for ( int i = 0; i < count(); i++ ) {
106 QString lab = model()->headerData( i, orientation(), Qt::DisplayRole ).toString();
107 QVariant iconData = model()->headerData( i, orientation(), Qt::DecorationRole );
108 QVariant appropriate = model()->headerData( i, orientation(), Qtx::AppropriateRole );
110 if ( iconData.isValid() ) {
111 if ( iconData.canConvert( QMetaType::QIcon ) )
112 icon = iconData.value<QIcon>();
113 else if ( iconData.canConvert( QMetaType::QPixmap ) )
114 icon = iconData.value<QPixmap>();
116 if( ( !lab.isEmpty() || !icon.isNull() ) &&
117 appropriate.isValid() ? appropriate.toInt()==Qtx::Toggled : true )
119 QAction* a = menu.addAction( icon, lab );
120 a->setCheckable( true );
121 a->setChecked( !isSectionHidden( i ) );
122 actionMap.insert( a, i );
125 QAction* sortAction = 0;
126 if ( count() > 0 && myEnableSortMenu ) {
128 sortAction = menu.addAction( QtxTreeView::tr( "Enable sorting" ) );
129 sortAction->setCheckable( true );
130 sortAction->setChecked( isSortIndicatorShown() );
132 if ( !menu.isEmpty() ) {
133 Qtx::simplifySeparators( &menu );
134 QAction* a = menu.exec( e->globalPos() );
135 if ( a && actionMap.contains( a ) ) {
136 setSectionHidden( actionMap[ a ], !isSectionHidden( actionMap[ a ] ) );
138 else if ( a && a == sortAction ) {
139 setSortIndicatorShown( a->isChecked() );
140 setSectionsClickable( a->isChecked() );
141 QtxTreeView* view = qobject_cast<QtxTreeView*>( parent() );
143 view->emitSortingEnabled( a->isChecked() );
144 if ( a->isChecked() ) {
145 connect( this, SIGNAL( sectionClicked( int ) ), view, SLOT( onHeaderClicked( int ) ) );
146 setSortIndicator( 0, Qt::AscendingOrder );
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()->setSectionsMovable( 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()->setSectionsMovable( 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 QModelIndex curIndex = currentIndex();
333 while ( curIndex.isValid() && curIndex.parent() != parent )
334 curIndex = curIndex.parent();
335 if ( curIndex.isValid() && curIndex.row() >= start && curIndex.row() <= end )
336 setCurrentIndex( QModelIndex() );
337 QTreeView::rowsAboutToBeRemoved( parent, start, end );
341 \brief Expand/collapse the specified item (recursively).
342 \param index model index
343 \param levels number of levels to be expanded/collapsed
344 \param open if \c true, item is expanded, otherwise it is collapsed
345 \sa expandLevels(), collapseLevels()
347 void QtxTreeView::setOpened( const QModelIndex& index, const int levels, bool open )
352 if ( !index.isValid() && index != rootIndex() )
355 setExpanded( index, open );
357 for ( int i = 0; i < model()->rowCount( index ); i++ ) {
358 QModelIndex child = model()->index( i, 0, index );
359 setOpened( child, levels-1, open );
364 \fn QtxTreeView::sortingEnabled( bool on );
365 \brief Emitted when "Sorting" commans is enabled/disabled from the popup menu.
366 \param on \c true if sorting is enabled and \c false otherwise
370 \fn QtxTreeView::selectionChanged();
371 \brief Emitted when selection is changed in the tree view.
375 \brief Emit sortingEnabled(bool) signal.
376 \param enabled "enable sorting" flag state
378 void QtxTreeView::emitSortingEnabled( bool enabled )
380 emit( sortingEnabled( enabled ) );
383 void QtxTreeView::setModel( QAbstractItemModel* m )
386 disconnect( model(), SIGNAL( headerDataChanged( Qt::Orientation, int, int ) ),
387 this, SLOT( onAppropriate( Qt::Orientation, int, int ) ) );
388 QTreeView::setModel( m );
390 connect( model(), SIGNAL( headerDataChanged( Qt::Orientation, int, int ) ),
391 this, SLOT( onAppropriate( Qt::Orientation, int, int ) ) );
394 // This method fixes problem with Object Browser horizontal scrollbar automatic scrolling to the right
395 void QtxTreeView::scrollTo(const QModelIndex &index,
396 QAbstractItemView::ScrollHint hint)
398 QScrollBar* aScrollBar = horizontalScrollBar();
400 int horPos = aScrollBar->value();
401 QTreeView::scrollTo(index, hint);
402 aScrollBar->setValue(horPos);
405 QTreeView::scrollTo(index, hint);
409 void QtxTreeView::onAppropriate( Qt::Orientation orient, int first, int last )
411 if( orient==Qt::Horizontal )
412 for( int i=first; i<=last; i++ )
414 int appr = model()->headerData( i, orient, Qtx::AppropriateRole ).toInt();
415 header()->setSectionHidden( i, appr==Qtx::Hidden );