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: QtxMRUAction.cxx
20 // Author: Sergey TELKOV
22 #include "QtxMRUAction.h"
24 #include "QtxResourceMgr.h"
26 #include <qpopupmenu.h>
29 Name: QtxMRUAction [public]
30 Desc: Constructs an MRU action with given parent and name.
33 QtxMRUAction::QtxMRUAction( QObject* parent, const char* name )
34 : QtxAction( "Most Recently Used", "Most Recently Used", 0, parent, name ),
36 myPopupMode( SubMenu ),
37 myInsertMode( MoveFirst )
42 Name: QtxMRUAction [public]
43 Desc: This constructor creates an action with the following properties: the
44 description text, the menu text and. It is a child of given parent and
48 QtxMRUAction::QtxMRUAction( const QString& text, const QString& menuText, QObject* parent, const char* name )
49 : QtxAction( text, menuText, 0, parent, name ),
51 myPopupMode( SubMenu ),
52 myInsertMode( MoveFirst )
57 Name: QtxMRUAction [public]
58 Desc: This constructor creates an action with the following properties: the
59 description text, the menu text, the icon or iconset icon and keyboard
60 accelerator. It is a child of given parent and named specified name.
63 QtxMRUAction::QtxMRUAction( const QString& text, const QIconSet& icon, const QString& menuText, QObject* parent, const char* name )
64 : QtxAction( text, icon, menuText, 0, parent, name ),
66 myPopupMode( SubMenu ),
67 myInsertMode( MoveFirst )
72 Name: ~QtxMRUAction [public]
73 Desc: This destructor removes all added popup items.
76 QtxMRUAction::~QtxMRUAction()
78 for ( ItemsMap::ConstIterator iIt = myItems.begin(); iIt != myItems.end(); ++iIt )
79 removeFrom( iIt.key() );
81 for ( MenusMap::ConstIterator mIt = myMenus.begin(); mIt != myMenus.end(); ++mIt )
82 removeFrom( mIt.key() );
86 Name: insertMode [public]
87 Desc: Returns the insert mode.
90 int QtxMRUAction::insertMode() const
96 Name: setInsertMode [public]
97 Desc: Returns the insert mode. Can be following values:
98 MoveFirst - place the specified link to the first position in any case
99 MoveLast - place the specified link to the last position in any case
100 AddFirst - if inserted link doesn't exist then add to the first position
101 AddLast - if inserted link doesn't exist then add to the lase position
104 void QtxMRUAction::setInsertMode( const int mode )
110 Name: popupMode [public]
111 Desc: Returns the popup mode.
114 int QtxMRUAction::popupMode() const
120 Name: setPopupMode [public]
121 Desc: Set the popup mode. If this mode is 'Items' then method "addTo" creates the
122 items in the specified popup menu. If mode is 'SubMenu' then items will be
123 create in sub popup menu which will be placed in specified popup.
126 void QtxMRUAction::setPopupMode( const int mode )
133 Desc: Returns the number of links.
136 int QtxMRUAction::count() const
138 return myLinks.count();
142 Name: isEmpty [public]
143 Desc: Returns 'true' if there is no links.
146 bool QtxMRUAction::isEmpty() const
148 return myLinks.isEmpty();
152 Name: visibleCount [public]
153 Desc: Returns the number of first links which will be added to popup menu.
154 If 'visibleCount' less than 1 then all links will be used.
157 int QtxMRUAction::visibleCount() const
163 Name: setVisibleCount [public]
164 Desc: Sets the number of links which will be used in popup menu.
167 void QtxMRUAction::setVisibleCount( int num )
169 if ( myVisCount == num )
178 Name: insert [public]
179 Desc: Insert the link according to the insert mode.
182 void QtxMRUAction::insert( const QString& link )
184 if ( myLinks.contains( link ) && ( insertMode() == AddFirst || insertMode() == AddLast ) )
187 myLinks.remove( link );
189 switch ( insertMode() )
193 myLinks.prepend( link );
197 myLinks.append( link );
205 Name: remove [public]
206 Desc: Removes link with specified index.
209 void QtxMRUAction::remove( const int idx )
211 if ( idx < 0 || idx >= (int)myLinks.count() )
214 myLinks.remove( myLinks.at( idx ) );
220 Name: remove [public]
221 Desc: Removes specified link.
224 void QtxMRUAction::remove( const QString& link )
226 if ( myLinks.remove( link ) )
232 Desc: Returns the link with specified index.
235 QString QtxMRUAction::item( const int idx ) const
238 if ( idx >= 0 && idx < (int)myLinks.count() )
245 Desc: Find specified link. If link exists then returns index otherwise -1 returned.
248 int QtxMRUAction::find( const QString& link ) const
250 return myLinks.findIndex( link );
254 Name: contains [public]
255 Desc: Returns 'true' if given link exist.
258 bool QtxMRUAction::contains( const QString& link ) const
260 return myLinks.contains( link );
265 Desc: Add the MRU links to the end of specified popup according to the popup mode.
268 bool QtxMRUAction::addTo( QWidget* wid )
270 if ( !wid || !wid->inherits( "QPopupMenu" ) )
273 QPopupMenu* pm = (QPopupMenu*)wid;
276 int mode = popupMode();
278 if ( ( mode == Items && myItems.contains( pm ) ) ||
279 ( mode == SubMenu && myMenus.contains( pm ) ) )
282 bool exist = myItems.contains( pm ) || myMenus.contains( pm );
284 if ( mode == SubMenu && !QtxAction::addTo( wid ) )
289 myItems.insert( pm, Item() );
290 myItems[pm].pId = myItems[pm].nId -1;
291 connect( pm, SIGNAL( activated( int ) ), this, SLOT( onActivated( int ) ) );
293 else if ( mode == SubMenu )
295 myMenus.insert( pm, new QPopupMenu( pm ) );
296 setPopup( pm, pm->idAt( pm->count() - 1 ), myMenus[pm] );
297 connect( myMenus[pm], SIGNAL( activated( int ) ), this, SLOT( onActivated( int ) ) );
302 connect( pm, SIGNAL( aboutToShow() ), this, SLOT( onAboutToShow() ) );
303 connect( pm, SIGNAL( destroyed( QObject* ) ), this, SLOT( onDestroyed( QObject* ) ) );
306 return insertLinks( pm, mode );
311 Desc: Add the MRU links to the specified popup at given index according to the popup mode.
314 bool QtxMRUAction::addTo( QWidget* wid, const int idx )
316 if ( !QtxAction::addTo( wid, idx ) )
319 QPopupMenu* pm = (QPopupMenu*)wid;
321 removeLinks( pm, popupMode() );
322 insertLinks( pm, popupMode(), idx );
328 Name: removeFrom [public]
329 Desc: Removes all MRU links from specified popup.
332 bool QtxMRUAction::removeFrom( QWidget* wid )
334 QtxAction::removeFrom( wid );
336 QPopupMenu* pm = (QPopupMenu*)wid;
337 if ( !wid || !wid->inherits( "QPopupMenu" ) )
340 if ( myItems.contains( pm ) )
342 removeLinks( pm, Items );
343 myItems.remove( pm );
344 disconnect( pm, SIGNAL( activated( int ) ), this, SLOT( onActivated( int ) ) );
346 if ( myMenus.contains( pm ) )
348 removeLinks( pm, SubMenu );
350 myMenus.remove( pm );
353 disconnect( pm, SIGNAL( aboutToShow() ), this, SLOT( onAboutToShow() ) );
354 disconnect( pm, SIGNAL( destroyed( QObject* ) ), this, SLOT( onDestroyed( QObject* ) ) );
360 Name: loadLinks [public]
361 Desc: Load the MRU links from specified resource manager section.
362 If parameter 'clear' is 'true' then link list will be cleared first.
365 void QtxMRUAction::loadLinks( QtxResourceMgr* resMgr, const QString& section, const bool clear )
367 if ( !resMgr || section.isEmpty() )
373 QString itemPrefix( "item_" );
375 QMap<QString, int> map;
376 for ( QStringList::const_iterator itr = myLinks.begin(); itr != myLinks.end(); ++ itr )
377 map.insert( *itr, 0 );
379 QStringList items = resMgr->parameters( section );
380 for ( QStringList::const_iterator it = items.begin(); it != items.end(); ++it )
382 if ( !(*it).startsWith( itemPrefix ) )
385 QString link = resMgr->stringValue( section, *it, QString::null );
386 if ( link.isEmpty() || map.contains( link ) )
389 myLinks.append( link );
390 map.insert( link, 0 );
397 Name: saveLinks [public]
398 Desc: Save the MRU links into specified resource manager section.
399 If parameter 'clear' is 'true' then section will be cleared first.
402 void QtxMRUAction::saveLinks( QtxResourceMgr* resMgr, const QString& section, const bool clear ) const
404 if ( !resMgr || section.isEmpty() )
408 resMgr->remove( section );
411 QMap<QString, int> map;
412 for ( QStringList::const_iterator itr = myLinks.begin(); itr != myLinks.end(); ++itr )
413 map.insert( *lst.append( *itr ), 0 );
415 QString itemPrefix( "item_" );
416 QStringList items = resMgr->parameters( section );
417 for ( QStringList::const_iterator it = items.begin(); it != items.end(); ++it )
419 if ( !(*it).startsWith( itemPrefix ) )
422 QString link = resMgr->stringValue( section, *it, QString::null );
423 if ( !link.isEmpty() && !map.contains( link ) )
424 map.insert( *lst.append( link ), 0 );
426 resMgr->remove( section, *it );
430 for ( QStringList::const_iterator iter = lst.begin(); iter != lst.end(); ++iter, counter++ )
431 resMgr->setValue( section, itemPrefix + QString().sprintf( "%03d", counter ), *iter );
435 Name: setEnabled [public slot]
436 Desc: Enable or disable all popup items with MRU links.
439 void QtxMRUAction::setEnabled( bool on )
441 QtxAction::setEnabled( on );
443 for ( ItemsMap::ConstIterator iter = myItems.begin(); iter != myItems.end(); ++iter )
444 for ( QIntList::const_iterator it = iter.data().idList.begin(); it != iter.data().idList.end(); ++it )
445 iter.key()->setItemEnabled( *it, on );
449 Name: onAboutToShow [private slots]
450 Desc: Enable or disable sub menu item according to number of MRU links
451 in sub popup when parent popup is shown.
454 void QtxMRUAction::onAboutToShow()
456 const QObject* obj = sender();
457 if ( obj && obj->inherits( "QPopupMenu" ) )
459 QPopupMenu* pm = (QPopupMenu*)obj;
460 if ( myMenus.contains( pm ) )
461 pm->setItemEnabled( findId( pm, myMenus[pm]), isEnabled() && myMenus[pm] && myMenus[pm]->count() );
466 Name: onActivated [private slot]
467 Desc: Process popup item activation and emit signal activated with selected MRU link.
470 void QtxMRUAction::onActivated( int id )
472 const QObject* obj = sender();
473 if ( !obj->inherits( "QPopupMenu" ) )
476 QPopupMenu* pm = (QPopupMenu*)obj;
479 if ( ( myItems.contains( pm ) && myItems[pm].idList.contains( id ) ) ||
480 ( myMenus.contains( (QPopupMenu*)pm->parent() ) && myMenus[(QPopupMenu*)pm->parent()] == pm ) )
481 link = pm->text( id );
483 if ( !link.isEmpty() )
484 emit activated( link );
488 Name: onDestroyed [private slot]
489 Desc: Removes deleted popup menu from internal data structures.
492 void QtxMRUAction::onDestroyed( QObject* obj )
497 myItems.remove( (QPopupMenu*)obj );
498 myMenus.remove( (QPopupMenu*)obj );
502 Name: updateState [private]
503 Desc: Updates the state of all popup menus which contains MRU link items.
506 void QtxMRUAction::updateState()
508 for ( ItemsMap::ConstIterator iIt = myItems.begin(); iIt != myItems.end(); ++iIt )
509 updatePopup( iIt.key(), Items );
511 for ( MenusMap::ConstIterator mIt = myMenus.begin(); mIt != myMenus.end(); ++mIt )
512 updatePopup( mIt.key(), SubMenu );
516 Name: checkPopup [private]
517 Desc: Check consistency the popup content and internal datas.
518 Synchronize internal data structures with popup content.
521 void QtxMRUAction::checkPopup( QPopupMenu* pm )
523 if ( myItems.contains( pm ) )
526 for ( QIntList::const_iterator it = myItems[pm].idList.begin(); it != myItems[pm].idList.end() && found; ++it )
527 found = pm->indexOf( *it ) != -1;
530 removeLinks( pm, Items );
531 myItems.remove( pm );
532 disconnect( pm, SIGNAL( activated( int ) ), this, SLOT( onActivated( int ) ) );
535 if ( myMenus.contains( pm ) )
537 int id = findId( pm, myMenus[pm] );
541 myMenus.remove( pm );
545 if ( !myItems.contains( pm ) && !myMenus.contains( pm ) )
546 disconnect( pm, SIGNAL( destroyed( QObject* ) ), this, SLOT( onDestroyed( QObject* ) ) );
550 Name: updatePopup [private]
551 Desc: Updates the MRU link items state in the specified popup menu.
554 void QtxMRUAction::updatePopup( QPopupMenu* pm, const int mode )
560 if ( mode == Items && myItems.contains( pm ) )
562 if ( !myItems[pm].idList.isEmpty() )
563 idx = pm->indexOf( myItems[pm].idList.first() );
566 int pIdx = pm->indexOf( myItems[pm].pId );
567 int nIdx = pm->indexOf( myItems[pm].nId );
570 else if ( nIdx != -1 )
575 removeLinks( pm, mode );
576 insertLinks( pm, mode, idx );
580 Name: removeLinks [private]
581 Desc: Removes MRU link items from specified popup.
584 bool QtxMRUAction::removeLinks( QPopupMenu* pm, const int mode )
589 if ( mode == SubMenu && myMenus.contains( pm ) )
590 myMenus[pm]->clear();
591 else if ( mode == Items && myItems.contains( pm ) )
593 for ( QIntList::const_iterator it = myItems[pm].idList.begin(); it != myItems[pm].idList.end(); ++it )
594 pm->removeItem( *it );
595 myItems[pm].idList.clear();
602 Name: insertLinks [private]
603 Desc: Inserts MRU link items to the specified popup.
606 bool QtxMRUAction::insertLinks( QPopupMenu* pm, const int mode, const int idx )
611 int count = visibleCount() < 0 ? myLinks.count() : visibleCount();
612 bool isOn = isEnabled();
613 if ( mode == SubMenu && myMenus.contains( pm ) )
615 for ( QStringList::const_iterator it = myLinks.begin(); it != myLinks.end() && count > 0; ++it, count-- )
617 int id = myMenus[pm]->insertItem( *it, -1 );
618 myMenus[pm]->setItemEnabled( id, isOn );
621 else if ( mode == Items )
625 for ( QStringList::const_iterator it = myLinks.begin(); it != myLinks.end() && count > 0; ++it, count-- )
627 ids.append( pm->insertItem( *it, -1, index ) );
628 pm->setItemEnabled( ids.last(), isOn );
632 myItems[pm].idList = ids;
633 if ( !myItems[pm].idList.isEmpty() )
635 myItems[pm].pId = pm->idAt( pm->indexOf( myItems[pm].idList.first() ) - 1 );
636 myItems[pm].nId = pm->idAt( pm->indexOf( myItems[pm].idList.first() ) + 1 );
643 Name: findId [private]
644 Desc: Returns identificator of popup item which contains sub popup 'pm' in the popup 'cont'.
647 int QtxMRUAction::findId( QPopupMenu* cont, QPopupMenu* pm ) const
654 for ( int i = 0; i < (int)cont->count() && id == -1; i++ )
657 QMenuItem* item = cont->findItem( cont->idAt( i ), &md );
658 if ( item && md == cont && item->popup() == pm )