1 // File: QtxMRUAction.cxx
2 // Author: Sergey TELKOV
4 #include "QtxMRUAction.h"
6 #include "QtxResourceMgr.h"
8 #include <qpopupmenu.h>
11 Name: QtxMRUAction [public]
12 Desc: Constructs an MRU action with given parent and name.
15 QtxMRUAction::QtxMRUAction( QObject* parent, const char* name )
16 : QtxAction( "Most Recently Used", "Most Recently Used", 0, parent, name ),
18 myPopupMode( SubMenu ),
19 myInsertMode( MoveFirst )
24 Name: QtxMRUAction [public]
25 Desc: This constructor creates an action with the following properties: the
26 description text, the menu text and. It is a child of given parent and
30 QtxMRUAction::QtxMRUAction( const QString& text, const QString& menuText, QObject* parent, const char* name )
31 : QtxAction( text, menuText, 0, parent, name ),
33 myPopupMode( SubMenu ),
34 myInsertMode( MoveFirst )
39 Name: QtxMRUAction [public]
40 Desc: This constructor creates an action with the following properties: the
41 description text, the menu text, the icon or iconset icon and keyboard
42 accelerator. It is a child of given parent and named specified name.
45 QtxMRUAction::QtxMRUAction( const QString& text, const QIconSet& icon, const QString& menuText, QObject* parent, const char* name )
46 : QtxAction( text, icon, menuText, 0, parent, name ),
48 myPopupMode( SubMenu ),
49 myInsertMode( MoveFirst )
54 Name: ~QtxMRUAction [public]
55 Desc: This destructor removes all added popup items.
58 QtxMRUAction::~QtxMRUAction()
60 for ( ItemsMap::ConstIterator iIt = myItems.begin(); iIt != myItems.end(); ++iIt )
61 removeFrom( iIt.key() );
63 for ( MenusMap::ConstIterator mIt = myMenus.begin(); mIt != myMenus.end(); ++mIt )
64 removeFrom( mIt.key() );
68 Name: insertMode [public]
69 Desc: Returns the insert mode.
72 int QtxMRUAction::insertMode() const
78 Name: setInsertMode [public]
79 Desc: Returns the insert mode. Can be following values:
80 MoveFirst - place the specified link to the first position in any case
81 MoveLast - place the specified link to the last position in any case
82 AddFirst - if inserted link doesn't exist then add to the first position
83 AddLast - if inserted link doesn't exist then add to the lase position
86 void QtxMRUAction::setInsertMode( const int mode )
92 Name: popupMode [public]
93 Desc: Returns the popup mode.
96 int QtxMRUAction::popupMode() const
102 Name: setPopupMode [public]
103 Desc: Set the popup mode. If this mode is 'Items' then method "addTo" creates the
104 items in the specified popup menu. If mode is 'SubMenu' then items will be
105 create in sub popup menu which will be placed in specified popup.
108 void QtxMRUAction::setPopupMode( const int mode )
115 Desc: Returns the number of links.
118 int QtxMRUAction::count() const
120 return myLinks.count();
124 Name: isEmpty [public]
125 Desc: Returns 'true' if there is no links.
128 bool QtxMRUAction::isEmpty() const
130 return myLinks.isEmpty();
134 Name: visibleCount [public]
135 Desc: Returns the number of first links which will be added to popup menu.
136 If 'visibleCount' less than 1 then all links will be used.
139 int QtxMRUAction::visibleCount() const
145 Name: setVisibleCount [public]
146 Desc: Sets the number of links which will be used in popup menu.
149 void QtxMRUAction::setVisibleCount( int num )
151 if ( myVisCount == num )
160 Name: insert [public]
161 Desc: Insert the link according to the insert mode.
164 void QtxMRUAction::insert( const QString& link )
166 if ( myLinks.contains( link ) && ( insertMode() == AddFirst || insertMode() == AddLast ) )
169 myLinks.remove( link );
171 switch ( insertMode() )
175 myLinks.prepend( link );
179 myLinks.append( link );
187 Name: remove [public]
188 Desc: Removes link with specified index.
191 void QtxMRUAction::remove( const int idx )
193 if ( idx < 0 || idx >= (int)myLinks.count() )
196 myLinks.remove( myLinks.at( idx ) );
202 Name: remove [public]
203 Desc: Removes specified link.
206 void QtxMRUAction::remove( const QString& link )
208 if ( myLinks.remove( link ) )
214 Desc: Returns the link with specified index.
217 QString QtxMRUAction::item( const int idx ) const
220 if ( idx >= 0 && idx < (int)myLinks.count() )
227 Desc: Find specified link. If link exists then returns index otherwise -1 returned.
230 int QtxMRUAction::find( const QString& link ) const
232 return myLinks.findIndex( link );
236 Name: contains [public]
237 Desc: Returns 'true' if given link exist.
240 bool QtxMRUAction::contains( const QString& link ) const
242 return myLinks.contains( link );
247 Desc: Add the MRU links to the end of specified popup according to the popup mode.
250 bool QtxMRUAction::addTo( QWidget* wid )
252 if ( !wid || !wid->inherits( "QPopupMenu" ) )
255 QPopupMenu* pm = (QPopupMenu*)wid;
258 int mode = popupMode();
260 if ( ( mode == Items && myItems.contains( pm ) ) ||
261 ( mode == SubMenu && myMenus.contains( pm ) ) )
264 bool exist = myItems.contains( pm ) || myMenus.contains( pm );
266 if ( mode == SubMenu && !QtxAction::addTo( wid ) )
271 myItems.insert( pm, Item() );
272 myItems[pm].pId = myItems[pm].nId -1;
273 connect( pm, SIGNAL( activated( int ) ), this, SLOT( onActivated( int ) ) );
275 else if ( mode == SubMenu )
277 myMenus.insert( pm, new QPopupMenu( pm ) );
278 setPopup( pm, pm->idAt( pm->count() - 1 ), myMenus[pm] );
279 connect( myMenus[pm], SIGNAL( activated( int ) ), this, SLOT( onActivated( int ) ) );
284 connect( pm, SIGNAL( aboutToShow() ), this, SLOT( onAboutToShow() ) );
285 connect( pm, SIGNAL( destroyed( QObject* ) ), this, SLOT( onDestroyed( QObject* ) ) );
288 return insertLinks( pm, mode );
293 Desc: Add the MRU links to the specified popup at given index according to the popup mode.
296 bool QtxMRUAction::addTo( QWidget* wid, const int idx )
298 if ( !QtxAction::addTo( wid, idx ) )
301 QPopupMenu* pm = (QPopupMenu*)wid;
303 removeLinks( pm, popupMode() );
304 insertLinks( pm, popupMode(), idx );
310 Name: removeFrom [public]
311 Desc: Removes all MRU links from specified popup.
314 bool QtxMRUAction::removeFrom( QWidget* wid )
316 QtxAction::removeFrom( wid );
318 QPopupMenu* pm = (QPopupMenu*)wid;
319 if ( !wid || !wid->inherits( "QPopupMenu" ) )
322 if ( myItems.contains( pm ) )
324 removeLinks( pm, Items );
325 myItems.remove( pm );
326 disconnect( pm, SIGNAL( activated( int ) ), this, SLOT( onActivated( int ) ) );
328 if ( myMenus.contains( pm ) )
330 removeLinks( pm, SubMenu );
332 myMenus.remove( pm );
335 disconnect( pm, SIGNAL( aboutToShow() ), this, SLOT( onAboutToShow() ) );
336 disconnect( pm, SIGNAL( destroyed( QObject* ) ), this, SLOT( onDestroyed( QObject* ) ) );
342 Name: loadLinks [public]
343 Desc: Load the MRU links from specified resource manager section.
344 If parameter 'clear' is 'true' then link list will be cleared first.
347 void QtxMRUAction::loadLinks( QtxResourceMgr* resMgr, const QString& section, const bool clear )
349 if ( !resMgr || section.isEmpty() )
355 QString itemPrefix( "item_" );
357 QMap<QString, int> map;
358 for ( QStringList::const_iterator itr = myLinks.begin(); itr != myLinks.end(); ++ itr )
359 map.insert( *itr, 0 );
361 QStringList items = resMgr->parameters( section );
362 for ( QStringList::const_iterator it = items.begin(); it != items.end(); ++it )
364 if ( !(*it).startsWith( itemPrefix ) )
367 QString link = resMgr->stringValue( section, *it, QString::null );
368 if ( link.isEmpty() || map.contains( link ) )
371 myLinks.append( link );
372 map.insert( link, 0 );
379 Name: saveLinks [public]
380 Desc: Save the MRU links into specified resource manager section.
381 If parameter 'clear' is 'true' then section will be cleared first.
384 void QtxMRUAction::saveLinks( QtxResourceMgr* resMgr, const QString& section, const bool clear ) const
386 if ( !resMgr || section.isEmpty() )
390 resMgr->removeSection( section );
393 QMap<QString, int> map;
394 for ( QStringList::const_iterator itr = myLinks.begin(); itr != myLinks.end(); ++itr )
395 map.insert( *lst.append( *itr ), 0 );
397 QString itemPrefix( "item_" );
398 QStringList items = resMgr->parameters( section );
399 for ( QStringList::const_iterator it = items.begin(); it != items.end(); ++it )
401 if ( !(*it).startsWith( itemPrefix ) )
404 QString link = resMgr->stringValue( section, *it, QString::null );
405 if ( !link.isEmpty() && !map.contains( link ) )
406 map.insert( *lst.append( link ), 0 );
408 resMgr->remove( section, *it );
412 for ( QStringList::const_iterator iter = lst.begin(); iter != lst.end(); ++iter, counter++ )
413 resMgr->setValue( section, itemPrefix + QString().sprintf( "%03d", counter ), *iter );
417 Name: setEnabled [public slot]
418 Desc: Enable or disable all popup items with MRU links.
421 void QtxMRUAction::setEnabled( bool on )
423 QtxAction::setEnabled( on );
425 for ( ItemsMap::ConstIterator iter = myItems.begin(); iter != myItems.end(); ++iter )
426 for ( QIntList::const_iterator it = iter.data().idList.begin(); it != iter.data().idList.end(); ++it )
427 iter.key()->setItemEnabled( *it, on );
431 Name: onAboutToShow [private slots]
432 Desc: Enable or disable sub menu item according to number of MRU links
433 in sub popup when parent popup is shown.
436 void QtxMRUAction::onAboutToShow()
438 const QObject* obj = sender();
439 if ( obj && obj->inherits( "QPopupMenu" ) )
441 QPopupMenu* pm = (QPopupMenu*)obj;
442 if ( myMenus.contains( pm ) )
443 pm->setItemEnabled( findId( pm, myMenus[pm]), isEnabled() && myMenus[pm] && myMenus[pm]->count() );
448 Name: onActivated [private slot]
449 Desc: Process popup item activation and emit signal activated with selected MRU link.
452 void QtxMRUAction::onActivated( int id )
454 const QObject* obj = sender();
455 if ( !obj->inherits( "QPopupMenu" ) )
458 QPopupMenu* pm = (QPopupMenu*)obj;
461 if ( ( myItems.contains( pm ) && myItems[pm].idList.contains( id ) ) ||
462 ( myMenus.contains( (QPopupMenu*)pm->parent() ) && myMenus[(QPopupMenu*)pm->parent()] == pm ) )
463 link = pm->text( id );
465 if ( !link.isEmpty() )
466 emit activated( link );
470 Name: onDestroyed [private slot]
471 Desc: Removes deleted popup menu from internal data structures.
474 void QtxMRUAction::onDestroyed( QObject* obj )
476 if ( !obj || !obj->inherits( "QPopupMenu" ) )
479 myItems.remove( (QPopupMenu*)obj );
480 myMenus.remove( (QPopupMenu*)obj );
484 Name: updateState [private]
485 Desc: Updates the state of all popup menus which contains MRU link items.
488 void QtxMRUAction::updateState()
490 for ( ItemsMap::ConstIterator iIt = myItems.begin(); iIt != myItems.end(); ++iIt )
491 updatePopup( iIt.key(), Items );
493 for ( MenusMap::ConstIterator mIt = myMenus.begin(); mIt != myMenus.end(); ++mIt )
494 updatePopup( mIt.key(), SubMenu );
498 Name: checkPopup [private]
499 Desc: Check consistency the popup content and internal datas.
500 Synchronize internal data structures with popup content.
503 void QtxMRUAction::checkPopup( QPopupMenu* pm )
505 if ( myItems.contains( pm ) )
508 for ( QIntList::const_iterator it = myItems[pm].idList.begin(); it != myItems[pm].idList.end() && found; ++it )
509 found = pm->indexOf( *it ) != -1;
512 removeLinks( pm, Items );
513 myItems.remove( pm );
514 disconnect( pm, SIGNAL( activated( int ) ), this, SLOT( onActivated( int ) ) );
517 if ( myMenus.contains( pm ) )
519 int id = findId( pm, myMenus[pm] );
523 myMenus.remove( pm );
527 if ( !myItems.contains( pm ) && !myMenus.contains( pm ) )
528 disconnect( pm, SIGNAL( destroyed( QObject* ) ), this, SLOT( onDestroyed( QObject* ) ) );
532 Name: updatePopup [private]
533 Desc: Updates the MRU link items state in the specified popup menu.
536 void QtxMRUAction::updatePopup( QPopupMenu* pm, const int mode )
542 if ( mode == Items && myItems.contains( pm ) )
544 if ( !myItems[pm].idList.isEmpty() )
545 idx = pm->indexOf( myItems[pm].idList.first() );
548 int pIdx = pm->indexOf( myItems[pm].pId );
549 int nIdx = pm->indexOf( myItems[pm].nId );
552 else if ( nIdx != -1 )
557 removeLinks( pm, mode );
558 insertLinks( pm, mode, idx );
562 Name: removeLinks [private]
563 Desc: Removes MRU link items from specified popup.
566 bool QtxMRUAction::removeLinks( QPopupMenu* pm, const int mode )
571 if ( mode == SubMenu && myMenus.contains( pm ) )
572 myMenus[pm]->clear();
573 else if ( mode == Items && myItems.contains( pm ) )
575 for ( QIntList::const_iterator it = myItems[pm].idList.begin(); it != myItems[pm].idList.end(); ++it )
576 pm->removeItem( *it );
577 myItems[pm].idList.clear();
584 Name: insertLinks [private]
585 Desc: Inserts MRU link items to the specified popup.
588 bool QtxMRUAction::insertLinks( QPopupMenu* pm, const int mode, const int idx )
593 int count = visibleCount() < 0 ? myLinks.count() : visibleCount();
594 bool isOn = isEnabled();
595 if ( mode == SubMenu && myMenus.contains( pm ) )
597 for ( QStringList::const_iterator it = myLinks.begin(); it != myLinks.end() && count > 0; ++it, count-- )
599 int id = myMenus[pm]->insertItem( *it, -1 );
600 myMenus[pm]->setItemEnabled( id, isOn );
603 else if ( mode == Items )
607 for ( QStringList::const_iterator it = myLinks.begin(); it != myLinks.end() && count > 0; ++it, count-- )
609 ids.append( pm->insertItem( *it, -1, index ) );
610 pm->setItemEnabled( ids.last(), isOn );
614 myItems[pm].idList = ids;
615 if ( !myItems[pm].idList.isEmpty() )
617 myItems[pm].pId = pm->idAt( pm->indexOf( myItems[pm].idList.first() ) - 1 );
618 myItems[pm].nId = pm->idAt( pm->indexOf( myItems[pm].idList.first() ) + 1 );
625 Name: findId [private]
626 Desc: Returns identificator of popup item which contains sub popup 'pm' in the popup 'cont'.
629 int QtxMRUAction::findId( QPopupMenu* cont, QPopupMenu* pm ) const
636 for ( int i = 0; i < (int)cont->count() && id == -1; i++ )
639 QMenuItem* item = cont->findItem( cont->idAt( i ), &md );
640 if ( item && md == cont && item->popup() == pm )