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 #include "QtxToolButton.h"
24 #include <QWheelEvent>
28 bool isSeparator( QAction* a )
30 return a->property( "separator" ).toBool();
32 void setSeparator( QAction* a )
34 a->setProperty( "separator", true );
40 \brief Drop-down tool button that behaves like a drop-down combo-box.
42 In contrast to the standard combo box, QtxToolButton can show drop-down
43 menu containing groups of items where each group has a separate title.
48 \param parent Parent widget.
50 QtxToolButton::QtxToolButton( QWidget* parent )
51 : QToolButton( parent )
53 setMenu( new QtxMenu( this ) );
54 setPopupMode( InstantPopup );
55 setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed );
56 connect( this, SIGNAL( triggered( QAction* ) ), this, SLOT( actionTriggered( QAction* ) ) );
62 QtxToolButton::~QtxToolButton()
67 \brief Add an item with the given \a text, and containing the specified \a userData.
68 The item is appended to the list of existing items.
69 \param text Item's text.
70 \param userData Item's data.
71 \return Index of just added item.
73 int QtxToolButton::addItem( const QString& text, const QVariant& userData )
75 QAction* action = menu()->addAction( text );
76 action->setData( userData );
77 bool currentChanged = false;
78 if ( !menu()->defaultAction() ) {
79 menu()->setDefaultAction( action );
80 currentChanged = true;
83 if ( currentChanged ) emitCurrentChanged( false, true );
88 \brief Add an item with the given \a icon and \a text, and containing the specified
89 \a userData. The item is appended to the list of existing items.
90 \param text Item's text.
91 \param icon Item's icon.
92 \param userData Item's data.
93 \return Index of just added item.
95 int QtxToolButton::addItem( const QIcon& icon, const QString& text, const QVariant& userData )
97 QAction* action = menu()->addAction( icon, text );
98 action->setData( userData );
99 bool currentChanged = false;
100 if ( !menu()->defaultAction() ) {
101 menu()->setDefaultAction( action );
102 currentChanged = true;
105 if ( currentChanged ) emitCurrentChanged( false, true );
110 \brief Add items with given \a texts. Each item is appended to the list of existing
112 \param texts Items being added.
114 void QtxToolButton::addItems( const QStringList& texts )
116 Q_FOREACH( QString text, texts )
117 menu()->addAction( text );
118 bool currentChanged = false;
119 if ( !menu()->defaultAction() && menu()->actions().count() > 0 ) {
120 menu()->setDefaultAction( menu()->actions()[0] );
121 currentChanged = true;
123 if ( currentChanged ) emitCurrentChanged( false, true );
128 \brief Add separator to the end of the items list.
129 \param text Separator's text.
130 \return Index of just added item.
132 int QtxToolButton::addSeparator( const QString& text )
134 (qobject_cast<QtxMenu*>(menu()))->addGroup( text );
135 setSeparator( actionAt( count()-1 ) );
140 \brief Add separator to the end of the items list.
141 \param icon Separator's icon.
142 \param text Separator's text.
143 \return Index of just added item.
145 int QtxToolButton::addSeparator( const QIcon& icon, const QString& text )
147 (qobject_cast<QtxMenu*>(menu()))->addGroup( icon, text );
148 setSeparator( actionAt( count()-1 ) );
153 \brief Remove item with given \a index.
154 \param index Index of item to be removed.
156 void QtxToolButton::removeItem( int index )
158 QAction* action = actionAt( index );
159 if ( !action ) return;
160 QAction* current = menu()->defaultAction();
161 menu()->removeAction( action );
162 bool currentChanged = false;
163 if ( action == current ) {
164 for ( int i = index; i < count(); i++ ) {
165 QAction* a = actionAt( i );
166 if ( a && !isSeparator( a ) ) {
167 menu()->setDefaultAction( a );
168 currentChanged = true;
172 for ( int i = index-1; i >= 0; i-- ) {
173 QAction* a = actionAt( i );
174 if ( a && !isSeparator( a ) ) {
175 menu()->setDefaultAction( a );
176 currentChanged = true;
182 if ( currentChanged ) emitCurrentChanged( false, true );
186 \brief Get the number of items.
187 \return Number of items.
189 int QtxToolButton::count() const
191 return menu()->actions().count();
195 \brief Get data of the current item.
196 \return Current item's data (invalid QVariant if list of items is empty
197 or current item doesn't have data).
199 QVariant QtxToolButton::currentData() const
201 QAction* action = menu()->defaultAction();
202 return action == 0 ? QVariant() : action->data();
206 \brief Get index of current item.
207 \return Current item's index; -1 if list of items is empty or if there's no
210 int QtxToolButton::currentIndex() const
212 QAction* action = menu()->defaultAction();
213 return action == 0 ? -1 : menu()->actions().indexOf( action );
217 \brief Get text of current item.
218 \return Current item's text; null sting if list of items is empty or
219 if there's no current item.
221 QString QtxToolButton::currentText() const
223 QAction* action = menu()->defaultAction();
224 return action == 0 ? QString() : action->text();
228 \brief Get custom data of the item at given \a index.
229 \param index Item's index.
230 \return Item's data (invalid QVariant if index is out of range).
232 QVariant QtxToolButton::itemData( int index ) const
234 QAction* action = actionAt( index );
235 return action == 0 ? QVariant() : action->data();
239 \brief Get icon of the item at given \a index.
240 \param index Item's index.
243 QIcon QtxToolButton::itemIcon( int index ) const
245 QAction* action = actionAt( index );
246 return action == 0 ? QIcon() : action->icon();
250 \brief Get text of the item at given \a index.
251 \param index Item's index.
254 QString QtxToolButton::itemText( int index ) const
256 QAction* action = actionAt( index );
257 return action == 0 ? QString() : action->text();
261 \brief Set custom data of the item at given \a index.
262 \param index Item's index.
263 \param value Item's data.
265 void QtxToolButton::setItemData( int index, const QVariant& value )
267 QAction* action = actionAt( index );
268 if ( action ) action->setData( value );
272 \brief Set icon of the item at given \a index.
273 \param index Item's index.
274 \param icon Item's icon.
276 void QtxToolButton::setItemIcon( int index, const QIcon& icon )
278 QAction* action = actionAt( index );
279 if ( action ) action->setIcon( icon );
284 \brief Set text of the item at given \a index.
285 \param index Item's index.
286 \param text Item's text.
288 void QtxToolButton::setItemText( int index, const QString& text )
290 QAction* action = actionAt( index );
291 bool currentChanged = false;
293 currentChanged = menu()->defaultAction() == action && action->text() != text;
294 action->setText( text );
297 if ( currentChanged )
298 emit currentTextChanged( text );
302 \brief Search item with given \a text.
304 \return Item's index; -1 if item is not found.
306 int QtxToolButton::findText( const QString& text )
309 for ( int i = 0; i < count() && index == -1; i++ ) {
310 QAction* action = actionAt( i );
311 if ( isSeparator( action ) ) continue;
312 if ( action->text() == text ) index = i;
320 void QtxToolButton::clear()
322 QAction* action = menu()->defaultAction();
325 if ( action ) emitCurrentChanged( false, true );
329 \brief Set current item by given \a index.
330 \param index Item's index.
332 void QtxToolButton::setCurrentIndex( int index )
334 bool currentChanged = false;
336 currentChanged = currentIndex() != -1;
337 menu()->setDefaultAction( 0 );
339 else if ( index >= count() )
342 QAction* action = actionAt( index );
343 if ( !isSeparator( action ) ) {
344 currentChanged = currentIndex() != index;
345 menu()->setDefaultAction( action );
349 if ( currentChanged ) emitCurrentChanged( false, true );
353 \brief Set current item by given \a text.
354 \param index Item's index.
356 void QtxToolButton::setCurrentText( const QString& text )
358 int index = findText( text );
360 setCurrentIndex( index );
364 \brief Reimplemented from QToolButton::keyPressEvent().
365 Process key press event.
366 \param e Key press event.
368 void QtxToolButton::keyPressEvent( QKeyEvent* e )
371 switch ( e->key() ) {
374 move = ( e->modifiers() & Qt::ControlModifier ) ? MoveFirst : MoveUp;
377 if ( e->modifiers() & Qt::AltModifier ) {
381 case Qt::Key_PageDown:
382 move = ( e->modifiers() & Qt::ControlModifier ) ? MoveLast : MoveDown;
391 if ( !e->modifiers() ) {
408 move = ( e->modifiers() & Qt::ControlModifier ) ? MoveFirst : MoveUp;
411 move = ( e->modifiers() & Qt::ControlModifier ) ? MoveLast : MoveDown;
421 \brief Reimplemented from QToolButton::wheelEvent().
422 Process mouse wheel event.
423 \param e Mouse wheel event.
425 void QtxToolButton::wheelEvent( QWheelEvent* e )
428 if ( e->delta() > 0 )
429 move = ( e->modifiers() & Qt::ControlModifier ) ? MoveFirst : MoveUp;
430 else if ( e->delta() < 0 )
431 move = ( e->modifiers() & Qt::ControlModifier ) ? MoveLast : MoveDown;
436 \brief Called when menu action is triggered.
439 void QtxToolButton::actionTriggered( QAction* action )
441 if ( action && !isSeparator( action ) ) {
442 int index = currentIndex();
443 menu()->setDefaultAction( action );
445 int newIndex = currentIndex();
446 emitCurrentChanged( true, index != newIndex );
451 \brief Update content of the widget.
454 void QtxToolButton::internalUpdate()
456 QAction* action = menu()->defaultAction();
457 setText( action == 0 ? "" : action->text() );
458 setIcon( action == 0 ? QIcon() : action->icon() );
462 \brief Get menu action at given index.
465 QAction* QtxToolButton::actionAt( int index ) const
467 return ( index >=0 && index < count() ) ? menu()->actions()[index] : 0;
471 \brief Move current index.
474 void QtxToolButton::moveIndex( Move move )
476 int index = currentIndex();
477 int newIndex = index;
481 for ( int i = index-1; i >= 0; i-- ) {
482 QAction* a = actionAt( i );
483 if ( a && !isSeparator( a ) ) {
485 if ( move == MoveUp )
492 for ( int i = index+1; i < count(); i++ ) {
493 QAction* a = actionAt( i );
494 if ( a && !isSeparator( a ) ) {
496 if ( move == MoveDown )
504 if ( newIndex != index ) {
505 menu()->setDefaultAction( actionAt( newIndex ) );
507 emitCurrentChanged( true, true );
512 \brief Emit `currentChanged()` signal.
515 void QtxToolButton::emitCurrentChanged( bool activate, bool changed )
517 QAction* action = menu()->defaultAction();
518 int index = action == 0 ? -1 : menu()->actions().indexOf( action );
519 QString text = action == 0 ? QString() : action->text();
521 emit activated( index );
522 emit activated( text );
525 emit currentIndexChanged( index );
526 emit currentIndexChanged( text );
527 emit currentTextChanged( text );