Back to index

salome-gui  6.5.0
QtxMultiAction.cxx
Go to the documentation of this file.
00001 // Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
00002 //
00003 // This library is free software; you can redistribute it and/or
00004 // modify it under the terms of the GNU Lesser General Public
00005 // License as published by the Free Software Foundation; either
00006 // version 2.1 of the License.
00007 //
00008 // This library is distributed in the hope that it will be useful,
00009 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00011 // Lesser General Public License for more details.
00012 //
00013 // You should have received a copy of the GNU Lesser General Public
00014 // License along with this library; if not, write to the Free Software
00015 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00016 //
00017 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
00018 //
00019 
00020 // File:      QtxMultiAction.cxx
00021 // Author:    Sergey TELKOV
00022 //
00023 #include "QtxMultiAction.h"
00024 
00025 #include <QMenu>
00026 #include <QLayout>
00027 #include <QToolBar>
00028 #include <QPainter>
00029 #include <QHelpEvent>
00030 #include <QToolButton>
00031 #include <QApplication>
00032 #include <QStyleOptionButton>
00033 
00041 class QtxMultiAction::Filter : public QObject
00042 {
00043 public:
00045   Filter( QObject* parent ) : QObject( parent ) {}
00047   ~Filter() {}
00049   bool eventFilter( QObject* o, QEvent* e )
00050   {
00051     if ( e->type() == QEvent::Leave ) {
00052       QToolButton* tb = qobject_cast<QToolButton*>( o );
00053       if ( tb )
00054         tb->setDown( false );
00055     }
00056     return QObject::eventFilter( o, e );
00057   }
00058 };
00059 
00066 class QtxMultiAction::Menu : public QMenu
00067 {
00068 public:
00070   Menu( QWidget* parent = 0 ) : QMenu( parent ) {}
00072   ~Menu() {};
00073 
00074 protected:
00076   virtual bool event( QEvent* e )
00077   {
00078     bool res = false;
00079     switch ( e->type() )
00080     {
00081     case QEvent::ToolTip:
00082     case QEvent::WhatsThis:
00083     case QEvent::QueryWhatsThis:
00084       {
00085         QHelpEvent* help = static_cast<QHelpEvent*>( e );
00086         QWidget* w = QApplication::widgetAt( help->globalPos() );
00087         if ( w && Qtx::isParent( w, this ) )
00088         {
00089           QHelpEvent he( help->type(), w->mapFromGlobal( help->globalPos() ), help->globalPos() );
00090           QApplication::sendEvent( w, &he );
00091           res = true;
00092         }
00093       }
00094       break;
00095     case QEvent::StatusTip:
00096     case QEvent::WhatsThisClicked:
00097       if ( parentWidget() )
00098       {
00099         QApplication::sendEvent( parentWidget(), e );
00100         res = true;
00101       }
00102       break;
00103     default:
00104       res = QMenu::event( e );
00105       break;
00106     }
00107     return res;
00108   }
00109 };
00110 
00117 class QtxMultiAction::Button : public QToolButton
00118 {
00119 public:
00121   Button( QWidget* parent = 0 ) : QToolButton( parent ) {}
00123   ~Button() {};
00124 
00125 protected:
00127   virtual void paintEvent( QPaintEvent* e )
00128   {
00129     QToolButton::paintEvent( e );
00130 
00131     int s = 10;
00132     int m = -2;
00133     int w = width();
00134     int h = height();
00135 
00136     QStyleOptionButton opt;
00137     opt.initFrom( this );
00138     QRect rect = opt.rect;
00139     int x = rect.x(), y = rect.y();
00140     if ( isDown() )
00141       opt.rect = QRect( x + w - s - m, y + h - s - m, s, s );
00142     else
00143       opt.rect = QRect( x + w - s - m - 1, y + h - s - m - 1, s, s );
00144 
00145     QPainter p( this );
00146     style()->drawPrimitive( QStyle::PE_IndicatorSpinDown, &opt, &p );
00147   }
00148 };
00149 
00168 QtxMultiAction::QtxMultiAction( QObject* parent )
00169 : QtxActionSet( parent ),
00170   myCurrent( 0 )
00171 {
00172   setVisible( true );
00173   setMenu( new QMenu( 0 ) );
00174 
00175   connect( this, SIGNAL( triggered( QAction* ) ), this, SLOT( onTriggered( QAction* ) ) );
00176 }
00177 
00183 QtxMultiAction::QtxMultiAction( const QString& txt, QObject* parent )
00184 : QtxActionSet( parent ),
00185   myCurrent( 0 )
00186 {
00187   setText( txt );
00188   setVisible( true );
00189   setMenu( new QMenu( 0 ) );
00190 
00191   connect( this, SIGNAL( triggered( QAction* ) ), this, SLOT( onTriggered( QAction* ) ) );
00192 }
00193 
00200 QtxMultiAction::QtxMultiAction( const QIcon& ico, const QString& txt, QObject* parent )
00201 : QtxActionSet( parent ),
00202   myCurrent( 0 )
00203 {
00204   setIcon( ico );
00205   setText( txt );
00206   setVisible( true );
00207   setMenu( new QMenu( 0 ) );
00208 
00209   connect( this, SIGNAL( triggered( QAction* ) ), this, SLOT( onTriggered( QAction* ) ) );
00210 }
00211 
00215 QtxMultiAction::~QtxMultiAction()
00216 {
00217   // to avoid memory leak
00218   if( QMenu* aMenu = menu() )
00219   {
00220     delete aMenu;
00221     aMenu = 0;
00222   }
00223 }
00224 
00229 void QtxMultiAction::setActiveAction( QAction* a )
00230 {
00231   if ( a && actions().contains( a ) && a != myCurrent && a->isEnabled() )
00232   {
00233     myCurrent = a;
00234     updateAction();
00235   }
00236 }
00237 
00242 QAction* QtxMultiAction::activeAction() const
00243 {
00244   return myCurrent;
00245 }
00246 
00252 void QtxMultiAction::onClicked( bool /*on*/ )
00253 {
00254   if ( myCurrent )
00255     myCurrent->activate( QAction::Trigger );
00256 }
00257 
00263 void QtxMultiAction::onTriggered( QAction* a )
00264 {
00265   if ( !a )
00266     return;
00267 
00268   QList<QWidget*> lst = createdWidgets();
00269   for ( QList<QWidget*>::iterator it = lst.begin(); it != lst.end(); ++it )
00270   {
00271     QToolButton* tb = ::qobject_cast<QToolButton*>( *it );
00272     if ( tb && tb->menu() )
00273       tb->menu()->hide();
00274   }
00275 
00276   if ( myCurrent != a )
00277   {
00278     myCurrent = a;
00279     updateAction();
00280   }
00281 }
00282 
00286 void QtxMultiAction::updateAction()
00287 {
00288   QtxActionSet::updateAction();
00289 
00290   QList<QWidget*> lst = createdWidgets();
00291   for ( QList<QWidget*>::iterator it = lst.begin(); it != lst.end(); ++it )
00292     updateButton( ::qobject_cast<QToolButton*>( *it ) );
00293 }
00294 
00299 void QtxMultiAction::updateAction( QWidget* w )
00300 {
00301   if ( !w )
00302     return;
00303 
00304   if ( w->inherits( "QMenu" ) )
00305   {
00306     QtxActionSet::updateAction( menu() );
00307 
00308     QApplication::instance()->removeEventFilter( this );
00309 
00310     menu()->removeAction( this );
00311 
00312     QApplication::instance()->installEventFilter( this );
00313   }
00314 }
00315 
00321 bool QtxMultiAction::isEmptyAction() const
00322 {
00323   return false;
00324 }
00325 
00331 QWidget* QtxMultiAction::createWidget( QWidget* parent )
00332 {
00333   QToolBar* tb = ::qobject_cast<QToolBar*>( parent );
00334   if ( !tb )
00335     return 0;
00336 
00337   QToolButton* w = new QToolButton( tb );
00338   w->setMenu( new Menu( w ) );
00339   w->setMouseTracking( true );
00340   w->setFocusPolicy( Qt::NoFocus );
00341   w->setIconSize( tb->iconSize() );
00342   w->setToolButtonStyle( tb->toolButtonStyle() );
00343 
00344   connect( w, SIGNAL( clicked( bool ) ), this, SLOT( onClicked( bool ) ) );
00345   connect( tb, SIGNAL( iconSizeChanged( const QSize& ) ), w, SLOT( setIconSize( QSize ) ) );
00346   connect( tb, SIGNAL( toolButtonStyleChanged( Qt::ToolButtonStyle ) ),
00347            w, SLOT( setToolButtonStyle( Qt::ToolButtonStyle ) ) );
00348 
00349   updateButton( w );
00350   return w;
00351 }
00352 
00357 void QtxMultiAction::actionAdded( QAction* a )
00358 {
00359   connect( a, SIGNAL( changed() ), this, SLOT( onActionChanged() ) );
00360   onActionChanged();
00361 }
00362 
00367 void QtxMultiAction::actionRemoved( QAction* a )
00368 {
00369   disconnect( a, SIGNAL( changed() ), this, SLOT( onActionChanged() ) );
00370 
00371   if ( myCurrent != a )
00372     return;
00373 
00374   myCurrent = 0;
00375 
00376   onActionChanged();
00377 
00378   updateAction();
00379 }
00380 
00385 void QtxMultiAction::updateButton( QToolButton* btn )
00386 {
00387   if ( !btn )
00388     return;
00389 
00390   btn->setIcon( myCurrent ? myCurrent->icon() : QIcon() );
00391   btn->setText( myCurrent ? myCurrent->text() : QString() );
00392   btn->setToolTip( myCurrent ? myCurrent->toolTip() : QString() );
00393   btn->setStatusTip( myCurrent ? myCurrent->statusTip() : QString() );
00394 
00395   QMenu* pm = btn->menu();
00396   if ( !pm )
00397     return;
00398 
00399   pm->clear();
00400   for ( int i = 0; pm->layout() && i < pm->layout()->count(); i++ )
00401     delete pm->layout()->widget();
00402 
00403   delete pm->layout();
00404 
00405   QVBoxLayout* vbox = new QVBoxLayout( pm );
00406   vbox->setMargin( 1 );
00407   vbox->setSpacing( 0 );
00408   Filter* filter = new Filter( vbox );
00409   QList<QAction*> actList = actions();
00410   for ( QList<QAction*>::iterator itr = actList.begin(); itr != actList.end(); ++itr )
00411   {
00412     QToolButton* b = new QToolButton( pm );
00413     b->setDefaultAction( *itr );
00414     b->setToolTip( (*itr)->toolTip() );
00415     b->setStatusTip( (*itr)->statusTip() );
00416     b->setAutoRaise( true );
00417     b->setIconSize( btn->iconSize() );
00418     b->setToolButtonStyle( btn->toolButtonStyle() );
00419     b->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
00420     b->installEventFilter( filter );
00421     vbox->addWidget( b );
00422   }
00423 }
00424 
00432 void QtxMultiAction::onActionChanged()
00433 {
00434   if ( myCurrent && myCurrent->isEnabled() )
00435     return;
00436 
00437   QList<QAction*> alist = actions();
00438   QAction* a = 0;
00439   for ( QList<QAction*>::ConstIterator it = alist.begin(); it != alist.end() && !a; ++it ) {
00440     if ( (*it)->isEnabled() )
00441       a = *it;
00442   }
00443 
00444   if ( a )
00445     myCurrent = a;
00446   else
00447     myCurrent = alist.isEmpty() ? 0 : alist.first();
00448 
00449   setEnabled( myCurrent && myCurrent->isEnabled() );
00450   updateAction();
00451 }