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: QtxListAction.cxx
20 // Author: Sergey TELKOV (Based on code by Eugene AKSENOV)
22 #include "QtxListAction.h"
31 #include <qpopupmenu.h>
32 #include <qtoolbutton.h>
33 #include <qobjectlist.h>
34 #include <qapplication.h>
36 static const char* list_arrow_icon[] = {
49 Class: QtxListAction::ToolButton
53 class QtxListAction::ToolButton : public QToolButton
56 ToolButton( QtxListAction*, QWidget* = 0, const char* = 0 );
57 virtual ~ToolButton();
59 virtual QSize sizeHint() const;
62 QtxListAction* myAction;
65 QtxListAction::ToolButton::ToolButton( QtxListAction* a, QWidget* parent, const char* name )
66 : QToolButton( parent, name ),
69 setIconSet( QPixmap( list_arrow_icon ) );
72 QtxListAction::ToolButton::~ToolButton()
75 myAction->controlDeleted( this );
78 QSize QtxListAction::ToolButton::sizeHint() const
80 QSize sz = iconSet().pixmap().size();
81 return QSize( sz.width() + 2, sz.height() + 2 );
90 Name: QtxListAction [public]
91 Desc: Constructs an list action with given parent and name. If toggle is true the
92 action will be a toggle action, otherwise it will be a command action.
95 QtxListAction::QtxListAction( QObject* parent, const char* name, bool toggle )
96 : QtxAction( parent, name, toggle ),
105 Name: QtxListAction [public]
106 Desc: This constructor creates an action with the following properties: the
107 description text, the icon or iconset icon, the menu text and keyboard
108 accelerator. It is a child of given parent and named specified name.
109 If toggle is true the action will be a toggle action, otherwise it will
113 QtxListAction::QtxListAction( const QString& text, const QIconSet& icon,
114 const QString& menuText, int accel,
115 QObject* parent, const char* name, bool toggle )
116 : QtxAction( text, icon, menuText, accel, parent, name, toggle ),
125 Name: QtxListAction [public]
126 Desc: This constructor creates an action with the following properties: the
127 description text, the menu text and keyboard accelerator. It is a child
128 of given parent and named specified name. If toggle is true the action
129 will be a toggle action, otherwise it will be a command action.
132 QtxListAction::QtxListAction( const QString& text, const QString& menuText,
133 int accel, QObject* parent, const char* name, bool toggle )
134 : QtxAction( text, menuText, accel, parent, name, toggle ),
143 Name: ~QtxListAction [virtual public]
147 QtxListAction::~QtxListAction()
150 myFrame->myAction = 0;
154 Name: popupMode [public]
155 Desc: Returns popup mode. If popup mode "Item" (default) then action will
156 be added into popup menu as menu item. If popup mode "SubMenu" then
157 action will be added into popup menu as sub menu with list of items.
160 int QtxListAction::popupMode() const
166 Name: setPopupMode [public]
167 Desc: Set the popup mode. Popup mode define way in this action will be
168 added into popup menu. This function should be used before addTo.
171 void QtxListAction::setPopupMode( const int mode )
176 QStringList QtxListAction::names() const
180 lst = myFrame->names();
185 Name: addNames [public]
186 Desc: Fills the list of actions. Removes the old contents from
187 the list if 'clear' is true.
190 void QtxListAction::addNames( const QStringList& names, bool clear )
198 myFrame->addNames( names );
200 QStringList lst = myFrame->names();
201 for ( PopupsMap::Iterator pit = myPopups.begin(); pit != myPopups.end(); ++pit )
204 QPopupMenu* pm = (QPopupMenu*)pit.key();
205 for ( QStringList::ConstIterator it = lst.begin(); it != lst.end(); ++it )
206 pit.data().popup->insertItem( *it, i++ );
207 pm->setItemEnabled( pit.data().id, isEnabled() && pit.data().popup->count() );
210 for ( ButtonsMap::Iterator bit = myButtons.begin(); bit != myButtons.end(); ++bit )
212 bit.data().drop->setEnabled( isEnabled() && !lst.isEmpty() );
213 bit.data().main->setEnabled( isEnabled() && !lst.isEmpty() );
218 Name: addTo [virtual public]
219 Desc: Adds this control to 'popup' or 'toolbar'.
222 bool QtxListAction::addTo( QWidget* w )
224 if ( myButtons.contains( w ) || myPopups.contains( w ) )
227 if ( !w->inherits( "QPopupMenu" ) || popupMode() != SubMenu )
228 if ( !QtxAction::addTo( w ) )
233 addedTo( (QWidget*)w->children()->getLast(), w );
236 if ( w->inherits( "QToolBar" ) )
238 Buttons& entry = myButtons[w];
239 QHBox* dropWrap = new QHBox( w );
240 entry.drop = new ToolButton( this, dropWrap, "qt_dockwidget_internal" );
242 entry.drop->setTextLabel( text() );
243 entry.drop->setToggleButton( true );
244 entry.drop->setAutoRaise( entry.main->autoRaise() );
246 entry.main->setEnabled( isEnabled() && !myFrame->names().isEmpty() );
247 entry.drop->setEnabled( isEnabled() && !myFrame->names().isEmpty() );
249 entry.main->installEventFilter( this );
250 entry.drop->installEventFilter( this );
252 QToolTip::add( entry.drop, toolTip(), myTipGroup, statusTip() );
254 connect( entry.drop, SIGNAL( toggled( bool ) ), this, SLOT( onExpand( bool ) ) );
256 else if ( w->inherits( "QPopupMenu" ) && popupMode() == SubMenu )
259 QPopupMenu* pm = (QPopupMenu*)w;
261 entry.popup = new QPopupMenu( pm );
262 entry.id = pm->insertItem( text(), entry.popup );
265 QStringList lst = myFrame->names();
266 for ( QStringList::ConstIterator it = lst.begin(); it != lst.end(); ++it )
268 int id = entry.popup->insertItem( *it );
269 entry.popup->setItemParameter( id, i++ );
271 pm->setItemEnabled( entry.id, isEnabled() && entry.popup->count() );
272 myPopups.insert( w, entry );
274 connect( entry.popup, SIGNAL( activated( int ) ), this, SLOT( onActivated( int ) ) );
278 connect( w, SIGNAL( destroyed( QObject* ) ), this, SLOT( onDestroyed( QObject* ) ) );
285 Name: addTo [virtual public]
286 Desc: Adds this control to 'popup' or 'toolbar'. Allow to specify index
287 for adding into 'popup'.
290 bool QtxListAction::addTo( QWidget* w, const int idx )
292 return QtxAction::addTo( w, idx );
296 Name: removeFrom [virtual public]
297 Desc: Removes this control from 'popup' or 'toolbar'.
300 bool QtxListAction::removeFrom( QWidget* w )
302 if ( !QtxAction::removeFrom( w ) )
305 if ( w->inherits( "QToolBar" ) )
310 if ( myButtons.contains( w ) )
312 Buttons& entry = myButtons[w];
314 if ( entry.drop->parent() && entry.drop->parent()->parent() == w )
315 delete entry.drop->parent();
319 myButtons.remove( w );
321 else if ( w->inherits( "QPopupMenu" ) )
322 myPopups.remove( w );
325 disconnect( w, SIGNAL( destroyed( QObject* ) ), this, SLOT( onDestroyed( QObject* ) ) );
332 Name: setEnabled [virtual public slot]
333 Desc: Enables/disables this control.
336 void QtxListAction::setEnabled( bool enable )
338 QtxAction::setEnabled( enable );
340 bool isOn = enable && !myFrame->names().isEmpty();
342 for ( ButtonsMap::Iterator bit = myButtons.begin(); bit != myButtons.end(); ++bit )
344 bit.data().drop->setEnabled( isOn );
345 bit.data().main->setEnabled( isOn );
348 for ( PopupsMap::Iterator pit = myPopups.begin(); pit != myPopups.end(); ++pit )
350 QPopupMenu* cont = (QPopupMenu*)pit.key();
351 cont->setItemEnabled( pit.data().id, isOn );
356 Name: setMaxLines [public]
357 Desc: Sets max number of lines that list frame shows
358 without vertical scroll bar. Default value is 5.
361 void QtxListAction::setMaxLines( int nlines )
363 myFrame->setMaxLines( nlines );
367 Name: setMaxLineChars [public]
368 Desc: Sets max number of characters in a line which list frame shows
369 without truncation. Default value is 12 (the widest char size is used).
372 void QtxListAction::setMaxLineChars( int nchars )
374 myFrame->setMaxLineChars( nchars );
378 Name: setComment [public]
379 Desc: Sets the format Qt string for comments displayed under the list
380 of actions for one action and for several actions.
381 Ex. "Undo %1 actions" format string will work as "Undo 3 actions"
382 when 3 actions are selected. The default format string is "%1".
385 void QtxListAction::setComment( const QString& c, const QString& sc )
390 myFrame->setSingleComment( sc.isEmpty() ? c : sc );
391 myFrame->setMultipleComment( c );
395 Name: eventFilter [virtual public]
396 Desc: Reimplemented to paint the tool buttons in 2D/3D.
399 bool QtxListAction::eventFilter( QObject* o, QEvent* e )
401 if ( !myRaise && ( e->type() == QEvent::Enter || e->type() == QEvent::Leave ) )
404 QWidget* wid = widget( (QWidget*)o );
405 if ( o == mainButton( wid ) )
406 obj = dropButton( wid );
407 else if ( o == dropButton( wid ) )
408 obj = mainButton( wid );
413 QApplication::sendEvent( obj, e );
418 return QObject::eventFilter( o, e );
422 Name: addedTo [protected]
423 Desc: Reimplemented for internal reasons.
426 void QtxListAction::addedTo( QWidget* actionWidget, QWidget* container )
429 QtxAction::addedTo( actionWidget, container );
432 if ( !container->inherits( "QToolBar" ) )
436 entry.main = (QToolButton*)actionWidget;
438 myButtons.insert( container, entry );
442 Name: initialize [private]
443 Desc: Initialization of object QtxListAction.
446 void QtxListAction::initialize()
448 myTipGroup = new QToolTipGroup( this );
450 myFrame = new QtxListFrame( this, qApp->mainWidget() );
451 myFrame->setMaxLines( 5 );
452 myFrame->setMaxLineChars( 7 );
456 connect( myFrame, SIGNAL( hided() ), this, SLOT( onHided() ) );
457 connect( this, SIGNAL( activated() ), this, SLOT( onSingle() ) );
458 connect( myFrame, SIGNAL( selected( int ) ), this, SLOT( onMultiple( int ) ) );
460 connect( myTipGroup, SIGNAL( removeTip() ), this, SLOT( clearStatusText() ) );
461 connect( myTipGroup, SIGNAL( showTip( const QString& ) ), this, SLOT( showStatusText( const QString& ) ) );
465 Name: onSingle [private slot]
466 Desc: Called when a single action is selected.
469 void QtxListAction::onSingle()
475 Name: onMultiple [private slot]
476 Desc: Called when multiple actions are selected.
479 void QtxListAction::onMultiple( int numActions )
484 if ( numActions > 0 )
485 emit activated( numActions );
489 Name: onExpand [private slot]
490 Desc: Activates the list of actions.
493 void QtxListAction::onExpand( bool on )
495 const QObject* obj = sender();
498 QWidget* wid = widget( (QToolButton*)obj );
499 QToolButton* main = mainButton( wid );
500 myFrame->setOwner( main );
508 void QtxListAction::onHided()
510 for ( ButtonsMap::Iterator bit = myButtons.begin(); bit != myButtons.end(); ++bit )
512 bool block = bit.data().drop->signalsBlocked();
513 bit.data().drop->blockSignals( true );
514 bit.data().drop->setOn( false );
515 bit.data().drop->blockSignals( block );
520 Name: onActivated [private slot]
521 Desc: Called when a sub menu item is activated.
524 void QtxListAction::onActivated( int id )
526 QPopupMenu* pm = (QPopupMenu*)sender();
527 int num = pm->itemParameter( id );
529 emit activated( num );
533 Name: onDestroyed [private slot]
534 Desc: Called when a container widget is destroyed.
537 void QtxListAction::onDestroyed( QObject* obj )
539 if ( !obj->isWidgetType() )
542 myPopups.remove( (QWidget*)obj );
543 myButtons.remove( (QWidget*)obj );
547 Name: widget [private]
548 Desc: Returns container widget for specified control.
551 QWidget* QtxListAction::widget( QWidget* obj ) const
554 for ( PopupsMap::ConstIterator pit = myPopups.begin(); pit != myPopups.end() && !wid; ++pit )
555 if ( pit.data().popup == obj )
558 for ( ButtonsMap::ConstIterator bit = myButtons.begin(); bit != myButtons.end() && !wid; ++bit )
559 if ( bit.data().main == obj || bit.data().drop == obj )
566 Name: listPopup [private]
567 Desc: Returns sub popup menu widget for specified container.
570 QPopupMenu* QtxListAction::listPopup( QWidget* wid ) const
573 if ( myPopups.contains( wid ) )
574 p = myPopups[wid].popup;
579 Name: mainButton [private]
580 Desc: Returns main tool button for specified container.
583 QToolButton* QtxListAction::mainButton( QWidget* wid ) const
586 if ( myButtons.contains( wid ) )
587 mb = myButtons[wid].main;
592 Name: dropButton [private]
593 Desc: Returns drop tool button for specified container.
596 QToolButton* QtxListAction::dropButton( QWidget* wid ) const
599 if ( myButtons.contains( wid ) )
600 db = myButtons[wid].drop;
605 Name: controlDeleted [private]
606 Desc: Called when action child controls deleted.
609 void QtxListAction::controlDeleted( QWidget* wid )
612 for ( ButtonsMap::Iterator it = myButtons.begin(); it != myButtons.end() && !w; ++it )
614 if ( it.data().main == wid || it.data().drop == wid )
623 myButtons.remove( w );
627 /**********************************************************************
628 ** Class: QtxListFrame
629 ** Descr: Frame for the list of actions
631 ***********************************************************************/
633 class QtxListFrame::ScrollEvent : public QCustomEvent
636 enum { Scroll = User + 1 };
638 ScrollEvent( bool down ) : QCustomEvent( Scroll ), myDown( down ) {};
639 virtual ~ScrollEvent() {};
641 bool isDown() const { return myDown; };
655 QtxListFrame::QtxListFrame( QtxListAction* a, QWidget* parent, WFlags f )
656 : QFrame( parent, 0, WStyle_Customize | WStyle_NoBorderEx | WType_Popup | WStyle_Tool | WStyle_StaysOnTop ),
662 myMaxLineChars( 10 ),
664 myScrollBlock( false )
666 QVBoxLayout* theLayout = new QVBoxLayout( this, 3 );
667 theLayout->setResizeMode( QLayout::FreeResize );
669 myList = new QListBox( this );
670 myList->setSelectionMode( QListBox::Multi );
671 myList->setHScrollBarMode( QScrollView::AlwaysOff );
672 myList->setFocusPolicy( NoFocus );
674 QPalette p = myList->palette();
675 p.setColor( QPalette::Inactive, QColorGroup::Highlight,
676 p.color( QPalette::Active, QColorGroup::Highlight ) );
677 p.setColor( QPalette::Inactive, QColorGroup::HighlightedText,
678 p.color( QPalette::Active, QColorGroup::HighlightedText ) );
679 myList->setPalette( p );
681 /* We'll have the vertical scroll bar only and
682 truncate the names which are too wide */
683 connect( myList, SIGNAL( contentsMoving( int, int ) ), this, SLOT( onScroll( int, int ) ) );
685 myComment = new QLabel( this );
686 myComment->setFrameStyle( Panel | Sunken );
687 myComment->setAlignment( AlignCenter );
688 myMultipleComment = "%1";
690 theLayout->addWidget( myList );
691 theLayout->addWidget( myComment );
693 setFrameStyle( Panel | Raised );
696 QtxListFrame::~QtxListFrame()
699 myAction->myFrame = 0;
703 Clears list of names [ public ]
706 void QtxListFrame::clear()
712 void QtxListFrame::addNames( const QStringList& names )
714 for ( QStringList::ConstIterator it = names.begin(); it != names.end(); ++it )
715 myNames.append( *it );
720 Sets a names to the list. Truncates the name to fit to the frame width.
721 Use QtxListAction::setMaxLineChar( int ) to set the width in characters. [ public ]
724 void QtxListFrame::setNames( const QStringList& names )
731 for ( QStringList::ConstIterator it = names.begin(); it != names.end(); ++it )
734 QFontMetrics fm = myList->fontMetrics();
735 int maxW = myMaxLineChars * fm.maxWidth();
736 int w = fm.width( s );
739 QString extra( "..." );
740 int len = s.length();
741 int extraLen = fm.width( extra ) + 1;
744 w = fm.width( s, --len );
745 if ( w + extraLen < maxW )
753 myList->insertItem( s );
757 const QStringList QtxListFrame::names() const
763 Sets max number of lines shown without activation of vertical scroll bar. [ public ]
766 void QtxListFrame::setMaxLines( int maxLines )
768 myMaxLines = maxLines;
772 Sets max number of chars in line ( the rest will be truncated ). [ public ]
775 void QtxListFrame::setMaxLineChars( int maxChars )
777 if ( myMaxLineChars == maxChars )
780 myMaxLineChars = maxChars;
785 Sets the format of single comment. [ public ]
788 void QtxListFrame::setSingleComment( const QString& comment )
790 mySingleComment = comment;
796 Sets the format of multiple comment. [ public ]
799 void QtxListFrame::setMultipleComment( const QString& comment )
801 myMultipleComment = comment;
807 Updates comment display. [ public ]
810 void QtxListFrame::updateComment()
813 int selNum = selected();
815 com = myMultipleComment;
816 else if ( selNum > 0 && !mySingleComment.isEmpty() )
817 com = mySingleComment;
819 if ( !com.isEmpty() )
820 com = com.arg( selNum );
822 myComment->setText( com );
825 void QtxListFrame::setOwner( QWidget* wo )
831 if ( myOwner->parentWidget() && myOwner->parentWidget()->inherits( "QToolBar" ) &&
832 ((QToolBar*)myOwner->parentWidget())->orientation() == Qt::Vertical )
833 lpos = QPoint( myOwner->x() + myOwner->width() + 2, myOwner->y() );
835 lpos = QPoint( myOwner->x(), myOwner->y() + myOwner->height() + 2 );
836 QPoint gpos = myOwner->parentWidget() ? myOwner->parentWidget()->mapToGlobal( lpos )
837 : myOwner->mapToGlobal( lpos );
838 if ( parentWidget() )
839 move( parentWidget()->mapFromGlobal( gpos ) );
846 Validates the action. [ private slot ]
849 void QtxListFrame::accept()
851 emit selected( selected() );
855 Cancels the action. [ private slot ]
858 void QtxListFrame::reject()
864 Initializes / shows the frame. [ virtual public slot ]
867 void QtxListFrame::show()
869 int cnt = (int)myList->count();
873 myList->setTopItem( 0 );
874 myList->clearSelection();
875 myList->setMinimumSize( 0, ( QMIN( cnt + 1, myMaxLines ) ) * myList->itemHeight() + 1 );
878 int linstep = myList->itemHeight();
879 myList->verticalScrollBar()->setLineStep( linstep );
880 myList->verticalScrollBar()->setPageStep( myMaxLines * linstep );
882 QFontMetrics fm = myList->fontMetrics();
883 layout()->invalidate();
884 int maxHeight = layout()->minimumSize().height() + layout()->margin();
885 int maxWidth = myMaxLineChars * fm.maxWidth();
886 for ( uint i = 0; i <= myList->count(); i++ )
887 maxWidth = QMAX( maxWidth, fm.width( myList->text( i ) ) );
889 resize( width(), maxHeight );
891 myList->updateGeometry();
893 QApplication::sendPostedEvents();
895 myList->resizeContents( myList->contentsWidth(),
896 myList->itemHeight() * cnt );
897 if ( myList->contentsHeight() > myList->visibleHeight() )
898 maxWidth += myList->verticalScrollBar()->width();
900 QString single = mySingleComment.arg( cnt );
901 QString multi = myMultipleComment.arg( cnt );
902 int comWidth = QMAX( myComment->fontMetrics().width( single ), myComment->fontMetrics().width( multi ) );
903 if ( myComment->frameWidth() )
904 comWidth += myComment->fontMetrics().width( "x" );
906 maxWidth = QMAX( maxWidth, comWidth );
908 resize( maxWidth, maxHeight );
911 qApp->installEventFilter( this );
918 Cleanup. [ virtual public slot ]
921 void QtxListFrame::hide()
923 qApp->removeEventFilter( this );
929 Processes KeyUp/KeyDown, PageUp/PageDown, CR and Esc keys.
930 Returns 'true' if event is eaten, 'false' otherwise. [ private ]
933 bool QtxListFrame::handleKeyEvent( QObject* , QKeyEvent* e )
935 if ( e->type() == QEvent::KeyRelease )
938 int selNum = selected();
942 setSelected( QMAX( 1, selNum - 1 ) );
945 setSelected( QMAX( 1, selNum + 1 ) );
948 setSelected( QMAX( 1, selNum - myMaxLines ) );
951 setSelected( selNum += myMaxLines );
957 setSelected( myList->count() );
970 Selects items on move, validates on button release. If object 'o' is not our name list,
971 we close the frame. Returns 'true' if event is eaten, 'false' otherwise. [ private ]
974 bool QtxListFrame::handleMouseEvent( QObject* o, QMouseEvent* e )
978 case QEvent::MouseButtonPress:
980 if ( o != myList->viewport() && !isPopup() )
984 case QEvent::MouseMove:
986 if ( o == myList->viewport() )
988 QListBoxItem* lbi = myList->itemAt( e->pos() );
990 setSelected( myList->index( lbi ) + 1 );
994 case QEvent::MouseButtonRelease:
996 if ( o == myList->viewport() )
1008 bool QtxListFrame::event( QEvent* e )
1010 if ( e->type() != (int)ScrollEvent::Scroll )
1011 return QFrame::event( e );
1013 ScrollEvent* se = (ScrollEvent*)e;
1015 setSelected( myList->topItem() + myList->numItemsVisible() );
1017 setSelected( myList->topItem() + 1 );
1023 Watches mouse events on the viewport of the list. [ virtual public ]
1026 bool QtxListFrame::eventFilter( QObject* o, QEvent* e )
1028 bool isKeyEvent = ( e->type() == QEvent::KeyPress ||
1029 e->type() == QEvent::KeyRelease );
1030 bool isMouseEvent = ( e->type() == QEvent::MouseMove ||
1031 e->type() == QEvent::MouseButtonPress ||
1032 e->type() == QEvent::MouseButtonRelease ||
1033 e->type() == QEvent::MouseButtonDblClick );
1037 if ( handleKeyEvent( o, ( QKeyEvent* )e ) )
1040 else if ( isMouseEvent && o != myList->verticalScrollBar() )
1042 if ( handleMouseEvent( o, ( QMouseEvent*)e ) )
1046 if ( o != this && ( e->type() == QEvent::Resize || e->type() == QEvent::Move ) )
1047 setOwner( myOwner );
1049 return QFrame::eventFilter( o, e );
1053 Selects operations while scrolling the list. [ private slot ]
1056 void QtxListFrame::onScroll( int x, int y )
1058 int dx = y - myScrollVal;
1059 if ( !myScrollBlock )
1060 QApplication::postEvent( this, new ScrollEvent( dx > 0 ) );
1065 Selects the actions [ 0 - lastSel ]. [ public ]
1068 void QtxListFrame::setSelected( const int lastSel )
1070 int last = QMIN( lastSel, (int)myList->count() );
1072 for ( int i = 0; i < (int)myList->count(); i++ )
1073 myList->setSelected( i, i < last );
1075 int item = last - 1;
1077 myScrollBlock = true;
1079 if ( item < myList->topItem() )
1080 myList->setTopItem( item );
1082 if ( item >= myList->topItem() + myList->numItemsVisible() )
1083 myList->setTopItem( item - myList->numItemsVisible() + 1 );
1085 myScrollBlock = false;
1087 myList->clearFocus();
1092 int QtxListFrame::selected() const
1095 while ( sel < myList->count() && myList->isSelected( sel ) )