1 // Copyright (C) 2007-2023 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 ) {
382 case Qt::Key_PageDown:
383 move = ( e->modifiers() & Qt::ControlModifier ) ? MoveLast : MoveDown;
392 if ( !e->modifiers() ) {
409 move = ( e->modifiers() & Qt::ControlModifier ) ? MoveFirst : MoveUp;
412 move = ( e->modifiers() & Qt::ControlModifier ) ? MoveLast : MoveDown;
422 \brief Reimplemented from QToolButton::wheelEvent().
423 Process mouse wheel event.
424 \param e Mouse wheel event.
426 void QtxToolButton::wheelEvent( QWheelEvent* e )
429 if ( e->delta() > 0 )
430 move = ( e->modifiers() & Qt::ControlModifier ) ? MoveFirst : MoveUp;
431 else if ( e->delta() < 0 )
432 move = ( e->modifiers() & Qt::ControlModifier ) ? MoveLast : MoveDown;
437 \brief Called when menu action is triggered.
440 void QtxToolButton::actionTriggered( QAction* action )
442 if ( action && !isSeparator( action ) ) {
443 int index = currentIndex();
444 menu()->setDefaultAction( action );
446 int newIndex = currentIndex();
447 emitCurrentChanged( true, index != newIndex );
452 \brief Update content of the widget.
455 void QtxToolButton::internalUpdate()
457 QAction* action = menu()->defaultAction();
458 setText( action == 0 ? "" : action->text() );
459 setIcon( action == 0 ? QIcon() : action->icon() );
463 \brief Get menu action at given index.
466 QAction* QtxToolButton::actionAt( int index ) const
468 return ( index >=0 && index < count() ) ? menu()->actions()[index] : 0;
472 \brief Move current index.
475 void QtxToolButton::moveIndex( Move move )
477 int index = currentIndex();
478 int newIndex = index;
482 for ( int i = index-1; i >= 0; i-- ) {
483 QAction* a = actionAt( i );
484 if ( a && !isSeparator( a ) ) {
486 if ( move == MoveUp )
493 for ( int i = index+1; i < count(); i++ ) {
494 QAction* a = actionAt( i );
495 if ( a && !isSeparator( a ) ) {
497 if ( move == MoveDown )
505 if ( newIndex != index ) {
506 menu()->setDefaultAction( actionAt( newIndex ) );
508 emitCurrentChanged( true, true );
513 \brief Emit `currentChanged()` signal.
516 void QtxToolButton::emitCurrentChanged( bool activate, bool changed )
518 QAction* action = menu()->defaultAction();
519 int index = action == 0 ? -1 : menu()->actions().indexOf( action );
520 QString text = action == 0 ? QString() : action->text();
522 emit activated( index );
523 emit activated( text );
526 emit currentIndexChanged( index );
527 emit currentIndexChanged( text );
528 emit currentTextChanged( text );