1 // Copyright (C) 2005 OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D
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.
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/
19 // File: QtxActionMenuMgr.cxx
20 // Author: Alexander SOLOVYEV, Sergey TELKOV
22 #include "QtxActionMenuMgr.h"
24 #include "QtxAction.h"
28 #include <qpopupmenu.h>
29 #include <qwidgetlist.h>
30 #include <qobjectlist.h>
31 #include <qmainwindow.h>
36 Class: QtxActionMenuMgr::MenuAction
40 class QtxActionMenuMgr::MenuAction : public QtxAction
43 MenuAction( const QString&, const QString&, QObject* );
44 virtual ~MenuAction();
46 virtual bool addTo( QWidget* );
48 virtual bool removeFrom( QWidget* );
50 QPopupMenu* popup() const;
57 QtxActionMenuMgr::MenuAction::MenuAction( const QString& text, const QString& menuText, QObject* parent )
58 : QtxAction( text, menuText, 0, parent ),
62 myPopup = new QPopupMenu();
65 QtxActionMenuMgr::MenuAction::~MenuAction()
70 bool QtxActionMenuMgr::MenuAction::addTo( QWidget* w )
72 if ( myId != -1 || !w )
75 if ( !w->inherits( "QPopupMenu" ) && !w->inherits( "QMenuBar" ) )
78 if ( w->inherits( "QPopupMenu" ) && QAction::addTo( w ) )
80 QPopupMenu* pm = (QPopupMenu*)w;
81 myId = pm->idAt( pm->count() - 1 );
82 setPopup( pm, myId, myPopup );
84 else if ( w->inherits( "QMenuBar" ) )
86 QMenuBar* mb = (QMenuBar*)w;
87 myId = iconSet().isNull() ? mb->insertItem( menuText(), myPopup ) :
88 mb->insertItem( iconSet(), menuText(), myPopup );
89 mb->setItemEnabled( myId, isEnabled() );
97 bool QtxActionMenuMgr::MenuAction::removeFrom( QWidget* w )
99 if ( w->inherits( "QPopupMenu" ) && QAction::removeFrom( w ) )
101 else if ( w->inherits( "QMenuBar" ) )
103 QMenuBar* mb = (QMenuBar*)w;
104 mb->removeItem( myId );
111 QPopupMenu* QtxActionMenuMgr::MenuAction::popup() const
117 Class: QtxActionMenuMgr
122 QtxActionMenuMgr::QtxActionMenuMgr( QMainWindow* p )
124 myMenu( p ? p->menuBar() : 0 )
130 connect( myMenu, SIGNAL( destroyed( QObject* ) ), this, SLOT( onDestroyed( QObject* ) ) );
133 QtxActionMenuMgr::QtxActionMenuMgr( QWidget* mw, QObject* p )
141 connect( myMenu, SIGNAL( destroyed( QObject* ) ), this, SLOT( onDestroyed( QObject* ) ) );
144 QtxActionMenuMgr::~QtxActionMenuMgr()
146 for ( NodeListIterator it( myRoot.children ); it.current(); ++it )
148 QAction* a = itemAction( it.current()->id );
150 a = menuAction( it.current()->id );
153 a->removeFrom( myMenu );
156 for ( MenuMap::Iterator itr = myMenus.begin(); itr != myMenus.end(); ++itr )
160 bool QtxActionMenuMgr::isVisible( const int actId, const int place ) const
162 MenuNode* node = find( actId, place );
163 return node && node->visible;
166 void QtxActionMenuMgr::setVisible( const int actId, const int place, const bool v )
168 MenuNode* node = find( actId, place );
173 int QtxActionMenuMgr::insert( const int id, const QString& menus, const int group, const int idx )
175 return insert( id, QStringList::split( "|", menus ), group, idx );
178 int QtxActionMenuMgr::insert( QAction* a, const QString& menus, const int group, const int idx )
180 return insert( a, QStringList::split( "|", menus ), group, idx );
183 int QtxActionMenuMgr::insert( const int id, const QStringList& menus, const int group, const int idx )
185 int pId = createMenu( menus, -1 );
189 return insert( id, pId, group, idx );
192 int QtxActionMenuMgr::insert( QAction* a, const QStringList& menus, const int group, const int idx )
194 int pId = createMenu( menus, -1 );
198 return insert( a, pId, group, idx );
201 int QtxActionMenuMgr::insert( const int id, const int pId, const int group, const int idx )
206 MenuNode* pNode = pId == -1 ? &myRoot : find( pId );
210 MenuNode* node = new MenuNode( pNode );
214 if ( idx < 0 || idx >= (int)pNode->children.count() )
215 pNode->children.append( node );
217 pNode->children.insert( idx, node );
219 updateMenu( pNode, false );
224 int QtxActionMenuMgr::insert( QAction* a, const int pId, const int group, const int idx )
226 return insert( registerAction( a ), pId, group, idx );
229 int QtxActionMenuMgr::insert( const QString& title, const int pId, const int group, const int idx )
231 MenuNode* pNode = pId == -1 ? &myRoot : find( pId );
236 for ( NodeListIterator it( pNode->children ); it.current() && id == -1; ++it )
238 if ( myMenus.contains( it.current()->id ) &&
239 clearTitle( myMenus[it.current()->id]->menuText() ) == clearTitle( title ) )
240 id = it.current()->id;
246 MenuAction* ma = new MenuAction( clearTitle( title ), title, this );
248 MenuNode* node = new MenuNode( pNode );
250 node->id = myMenus.insert( generateId(), ma ).key();
252 if ( idx < 0 || idx >= (int)pNode->children.count() )
253 pNode->children.append( node );
255 pNode->children.insert( idx, node );
257 updateMenu( pNode, false );
262 int QtxActionMenuMgr::insert( const QString& title, const QString& menus, const int group, const int idx )
264 return insert( title, QStringList::split( "|", menus ), group, idx );
267 int QtxActionMenuMgr::insert( const QString& title, const QStringList& menus, const int group, const int idx )
269 int pId = createMenu( menus, -1 );
270 return insert( title, pId, group, idx );
273 int QtxActionMenuMgr::append( const QString& title, const int pId, const int group )
275 return insert( title, pId, group );
278 int QtxActionMenuMgr::append( const int id, const int pId, const int group )
280 return insert( id, pId, group );
283 int QtxActionMenuMgr::append( QAction* a, const int pId, const int group )
285 return insert( a, pId, group );
288 int QtxActionMenuMgr::prepend( const QString& title, const int pId, const int group )
290 return insert( title, pId, group, 0 );
293 int QtxActionMenuMgr::prepend( const int id, const int pId, const int group )
295 return insert( id, pId, group, 0 );
298 int QtxActionMenuMgr::prepend( QAction* a, const int pId, const int group )
300 return insert( a, pId, group, 0 );
303 void QtxActionMenuMgr::remove( const int id )
309 void QtxActionMenuMgr::remove( const int id, const int pId, const int group )
311 MenuNode* pNode = find( pId );
316 for ( NodeListIterator it( pNode->children ); it.current(); ++it )
318 if ( it.current()->id == id && ( it.current()->group == group || group == -1 ) )
319 delNodes.append( it.current() );
322 for ( NodeListIterator itr( delNodes ); itr.current(); ++itr )
323 pNode->children.remove( itr.current() );
325 updateMenu( pNode, false );
328 void QtxActionMenuMgr::show( const int id )
330 setShown( id, true );
333 void QtxActionMenuMgr::hide( const int id )
335 setShown( id, false );
338 bool QtxActionMenuMgr::isShown( const int id ) const
341 MenuNode* node = find( id );
347 void QtxActionMenuMgr::setShown( const int id, const bool on )
352 QMap<MenuNode*, int> updMap;
353 for ( NodeListIterator it( aNodes ); it.current(); ++it )
355 if ( it.current()->visible != on )
357 it.current()->visible = on;
358 updMap.insert( it.current()->parent, 0 );
362 for ( QMap<MenuNode*, int>::ConstIterator itr = updMap.begin(); itr != updMap.end(); ++itr )
363 updateMenu( itr.key(), false );
366 void QtxActionMenuMgr::onDestroyed( QObject* obj )
372 void QtxActionMenuMgr::setWidget( QWidget* mw )
378 disconnect( myMenu, SIGNAL( destroyed( QObject* ) ), this, SLOT( onDestroyed( QObject* ) ) );
383 connect( myMenu, SIGNAL( destroyed( QObject* ) ), this, SLOT( onDestroyed( QObject* ) ) );
386 QtxActionMenuMgr::MenuNode* QtxActionMenuMgr::find( const int actId, const int pId ) const
388 return find( actId, find( pId ) );
391 QtxActionMenuMgr::MenuNode* QtxActionMenuMgr::find( const int id, MenuNode* startNode ) const
394 MenuNode* start = startNode ? startNode : (MenuNode*)&myRoot;
395 for ( NodeListIterator it( start->children ); it.current() && !node; ++it )
397 if ( it.current()->id == id )
400 node = find( id, it.current() );
405 bool QtxActionMenuMgr::find( const int id, NodeList& lst, MenuNode* startNode ) const
407 MenuNode* start = startNode ? startNode : (MenuNode*)&myRoot;
408 for ( NodeListIterator it( start->children ); it.current(); ++it )
410 if ( it.current()->id == id )
411 lst.prepend( it.current() );
413 find( id, lst, it.current() );
415 return !lst.isEmpty();
418 void QtxActionMenuMgr::removeMenu( const int id, MenuNode* startNode )
420 MenuNode* start = startNode ? startNode : &myRoot;
421 for ( NodeListIterator it( start->children ); it.current(); ++it )
423 if ( it.current()->id == id )
424 start->children.remove( it.current() );
426 removeMenu( id, it.current() );
430 QAction* QtxActionMenuMgr::itemAction( const int id ) const
435 QtxActionMenuMgr::MenuAction* QtxActionMenuMgr::menuAction( const int id ) const
439 if ( myMenus.contains( id ) )
445 void QtxActionMenuMgr::updateMenu( MenuNode* startNode, const bool rec, const bool updParent )
447 if ( !isUpdatesEnabled() )
450 MenuNode* node = startNode ? startNode : &myRoot;
452 QWidget* mw = menuWidget( node );
456 bool filled = checkWidget( mw );
458 for ( NodeListIterator it1( node->children ); it1.current(); ++it1 )
460 QAction* a = itemAction( it1.current()->id );
462 a = menuAction( it1.current()->id );
468 if ( node != &myRoot )
470 if ( mw->inherits( "QMenuBar" ) )
471 ((QMenuBar*)mw)->clear();
472 else if ( mw->inherits( "QPopupMenu" ) )
473 ((QPopupMenu*)mw)->clear();
476 QMap<int, NodeList> idMap;
477 for ( NodeListIterator it2( node->children ); it2.current(); ++it2 )
479 MenuNode* par = it2.current()->parent;
480 if ( isVisible( it2.current()->id, par ? par->id : -1 ) )
482 NodeList& lst = idMap[it2.current()->group];
483 lst.append( it2.current() );
487 QIntList groups = idMap.keys();
493 for ( QIntList::const_iterator gIt = groups.begin(); gIt != groups.end(); ++gIt )
495 if ( !idMap.contains( *gIt ) )
498 const NodeList& lst = idMap[*gIt];
499 for ( NodeListIterator iter( lst ); iter.current(); ++iter )
502 updateMenu( iter.current(), rec, false );
504 QAction* a = itemAction( iter.current()->id );
509 MenuAction* ma = menuAction( iter.current()->id );
510 if ( ma && ma->popup() && ma->popup()->count() )
516 simplifySeparators( mw );
518 if ( updParent && node->parent && filled != checkWidget( mw ) )
519 updateMenu( node->parent, false );
522 void QtxActionMenuMgr::internalUpdate()
524 if ( isUpdatesEnabled() )
528 bool QtxActionMenuMgr::checkWidget( QWidget* wid ) const
534 if ( wid->inherits( "QPopupMenu" ) )
535 md = (QPopupMenu*)wid;
536 else if ( wid->inherits( "QMenuBar" ) )
542 QWidget* QtxActionMenuMgr::menuWidget( MenuNode* node) const
544 if ( !node || node == &myRoot )
547 if ( !myMenus.contains( node->id ) || !myMenus[node->id] )
550 return myMenus[node->id]->popup();
553 void QtxActionMenuMgr::simplifySeparators( QWidget* wid )
555 if ( wid && wid->inherits( "QPopupMenu" ) )
556 Qtx::simplifySeparators( (QPopupMenu*)wid, false );
559 QString QtxActionMenuMgr::clearTitle( const QString& txt ) const
563 for ( int i = 0; i < (int)res.length(); i++ )
565 if ( res.at( i ) == '&' )
566 res.remove( i--, 1 );
572 int QtxActionMenuMgr::createMenu( const QStringList& lst, const int pId )
577 QStringList sl( lst );
579 QString title = sl.last().stripWhiteSpace();
580 sl.remove( sl.fromLast() );
582 int parentId = sl.isEmpty() ? pId : createMenu( sl, pId );
584 return insert( title, parentId, -1 );
587 bool QtxActionMenuMgr::load( const QString& fname, QtxActionMgr::Reader& r )
589 MenuCreator cr( &r, this );
590 return r.read( fname, cr );
595 Class: QtxActionMenuMgr::MenuCreator
599 QtxActionMenuMgr::MenuCreator::MenuCreator( QtxActionMgr::Reader* r,
600 QtxActionMenuMgr* mgr )
601 : QtxActionMgr::Creator( r ),
606 QtxActionMenuMgr::MenuCreator::~MenuCreator()
610 int QtxActionMenuMgr::MenuCreator::append( const QString& tag, const bool subMenu,
611 const ItemAttributes& attr, const int pId )
613 if( !myMgr || !reader() )
616 QString label = reader()->option( "label", "label" ),
617 id = reader()->option( "id", "id" ),
618 pos = reader()->option( "pos", "pos" ),
619 group = reader()->option( "group", "group" ),
620 tooltip = reader()->option( "tooltip", "tooltip" ),
621 sep = reader()->option( "separator", "separator" ),
622 accel = reader()->option( "accel", "accel" ),
623 icon = reader()->option( "icon", "icon" ),
624 toggle = reader()->option( "toggle", "toggle" );
626 int res = -1, actId = intValue( attr, id, -1 );
629 res = myMgr->insert( strValue( attr, label ), pId, intValue( attr, group, 0 ), intValue( attr, pos, -1 ) );
631 res = myMgr->insert( separator(), pId, intValue( attr, group, 0 ), intValue( attr, pos, -1 ) );
634 QPixmap pix; QIconSet set;
635 QString name = strValue( attr, icon );
636 if( !name.isEmpty() && loadPixmap( name, pix ) )
637 set = QIconSet( pix );
639 QtxAction* newAct = new QtxAction( strValue( attr, tooltip ), set,
640 strValue( attr, label ),
641 QKeySequence( strValue( attr, accel ) ),
643 newAct->setToolTip( strValue( attr, tooltip ) );
644 QString toggleact = strValue( attr, toggle );
645 newAct->setToggleAction( !toggleact.isEmpty() );
646 newAct->setOn( toggleact.lower()=="true" );
649 int aid = myMgr->registerAction( newAct, actId );
650 res = myMgr->insert( aid, pId, intValue( attr, group, 0 ), intValue( attr, pos, -1 ) );