src/qt3support/itemviews/q3listbox.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the Qt3Support module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "qglobal.h"
       
    43 #if defined(Q_CC_BOR)
       
    44 // needed for qsort() because of a std namespace problem on Borland
       
    45 #include "qplatformdefs.h"
       
    46 #endif
       
    47 
       
    48 #include "q3listbox.h"
       
    49 #ifndef QT_NO_LISTBOX
       
    50 #include "qapplication.h"
       
    51 #include "qevent.h"
       
    52 #include "qfontmetrics.h"
       
    53 #include "qpainter.h"
       
    54 #include "qpixmap.h"
       
    55 #include "qstringlist.h"
       
    56 #include "qstyle.h"
       
    57 #include "qstyleoption.h"
       
    58 #include "qtimer.h"
       
    59 #include "qvector.h"
       
    60 #include "qpointer.h"
       
    61 #ifndef QT_NO_ACCESSIBILITY
       
    62 #include "qaccessible.h"
       
    63 #endif
       
    64 
       
    65 #include <stdlib.h>
       
    66 
       
    67 QT_BEGIN_NAMESPACE
       
    68 
       
    69 class Q3ListBoxPrivate
       
    70 {
       
    71 public:
       
    72     Q3ListBoxPrivate(Q3ListBox *lb):
       
    73         head(0), last(0), cache(0), cacheIndex(-1), current(0),
       
    74         highlighted(0), tmpCurrent(0), columnPos(1), rowPos(1), rowPosCache(0),
       
    75         columnPosOne(0), rowMode(Q3ListBox::FixedNumber),
       
    76         columnMode(Q3ListBox::FixedNumber), numRows(1), numColumns(1),
       
    77         currentRow(0), currentColumn(0),
       
    78         mousePressRow(-1), mousePressColumn(-1),
       
    79         mouseMoveRow(-1), mouseMoveColumn(-1), mouseInternalPress(false),
       
    80         scrollTimer(0), updateTimer(0), visibleTimer(0),
       
    81         selectionMode(Q3ListBox::Single),
       
    82         count(0),
       
    83         listBox(lb), currInputString(QString()),
       
    84         rowModeWins(false),
       
    85         ignoreMoves(false),
       
    86         layoutDirty(true),
       
    87         mustPaintAll(true),
       
    88         dragging(false),
       
    89         dirtyDrag (false),
       
    90         variableHeight(true /* !!! ### false */),
       
    91         variableWidth(false),
       
    92         inMenuMode(false)
       
    93     {}
       
    94     int findItemByName(int item, const QString &text);
       
    95     ~Q3ListBoxPrivate();
       
    96 
       
    97     Q3ListBoxItem * head, *last, *cache;
       
    98     int cacheIndex;
       
    99     Q3ListBoxItem * current, *highlighted, *tmpCurrent;
       
   100 
       
   101     QVector<int> columnPos;
       
   102     QVector<int> rowPos;
       
   103     int rowPosCache;
       
   104     int columnPosOne;
       
   105 
       
   106     Q3ListBox::LayoutMode rowMode;
       
   107     Q3ListBox::LayoutMode columnMode;
       
   108     int numRows;
       
   109     int numColumns;
       
   110 
       
   111     int currentRow;
       
   112     int currentColumn;
       
   113     int mousePressRow;
       
   114     int mousePressColumn;
       
   115     int mouseMoveRow;
       
   116     int mouseMoveColumn;
       
   117     bool mouseInternalPress;
       
   118 
       
   119     QTimer * scrollTimer;
       
   120     QTimer * updateTimer;
       
   121     QTimer * visibleTimer;
       
   122     QTimer * resizeTimer;
       
   123 
       
   124     QPoint scrollPos;
       
   125 
       
   126     Q3ListBox::SelectionMode selectionMode;
       
   127 
       
   128     int count;
       
   129 
       
   130 
       
   131     Q3ListBox *listBox;
       
   132     QString currInputString;
       
   133     QTimer *inputTimer;
       
   134 
       
   135     Q3ListBoxItem *pressedItem, *selectAnchor;
       
   136 
       
   137     uint select :1;
       
   138     uint pressedSelected :1;
       
   139     uint rowModeWins :1;
       
   140     uint ignoreMoves :1;
       
   141     uint clearing :1;
       
   142     uint layoutDirty :1;
       
   143     uint mustPaintAll :1;
       
   144     uint dragging :1;
       
   145     uint dirtyDrag :1;
       
   146     uint variableHeight :1;
       
   147     uint variableWidth :1;
       
   148     uint inMenuMode :1;
       
   149 
       
   150     QRect *rubber;
       
   151 
       
   152     struct SortableItem {
       
   153         Q3ListBoxItem *item;
       
   154     };
       
   155 };
       
   156 
       
   157 
       
   158 Q3ListBoxPrivate::~Q3ListBoxPrivate()
       
   159 {
       
   160     Q_ASSERT(!head);
       
   161 }
       
   162 
       
   163 
       
   164 /*!
       
   165     \class Q3ListBoxItem
       
   166     \brief The Q3ListBoxItem class is the base class of all list box items.
       
   167 
       
   168     \compat
       
   169 
       
   170     This class is an abstract base class used for all list box items.
       
   171     If you need to insert customized items into a Q3ListBox you must
       
   172     inherit this class and reimplement paint(), height() and width().
       
   173 
       
   174     \sa Q3ListBox
       
   175 */
       
   176 
       
   177 /*!
       
   178     Constructs an empty list box item in the list box \a listbox.
       
   179 */
       
   180 
       
   181 Q3ListBoxItem::Q3ListBoxItem(Q3ListBox* listbox)
       
   182 {
       
   183     lbox = listbox;
       
   184     s = false;
       
   185     dirty = true;
       
   186     custom_highlight = false;
       
   187     selectable = true;
       
   188     p = n = 0;
       
   189 
       
   190     if (listbox)
       
   191         listbox->insertItem(this);
       
   192 }
       
   193 
       
   194 /*!
       
   195     Constructs an empty list box item in the list box \a listbox and
       
   196     inserts it after the item \a after or at the beginning if \a after
       
   197     is 0.
       
   198 */
       
   199 
       
   200 Q3ListBoxItem::Q3ListBoxItem(Q3ListBox* listbox, Q3ListBoxItem *after)
       
   201 {
       
   202     lbox = listbox;
       
   203     s = false;
       
   204     dirty = true;
       
   205     custom_highlight = false;
       
   206     selectable = true;
       
   207     p = n = 0;
       
   208 
       
   209     if (listbox)
       
   210         listbox->insertItem(this, after);
       
   211 }
       
   212 
       
   213 
       
   214 /*!
       
   215     Destroys the list box item.
       
   216 */
       
   217 
       
   218 Q3ListBoxItem::~Q3ListBoxItem()
       
   219 {
       
   220     if (lbox)
       
   221         lbox->takeItem(this);
       
   222 }
       
   223 
       
   224 
       
   225 /*!
       
   226     Defines whether the list box item is responsible for drawing
       
   227     itself in a highlighted state when being selected.
       
   228 
       
   229     If \a b is false (the default), the list box will draw some
       
   230     default highlight indicator before calling paint().
       
   231 
       
   232     \sa isSelected(), paint()
       
   233 */
       
   234 void Q3ListBoxItem::setCustomHighlighting(bool b)
       
   235 {
       
   236     custom_highlight = b;
       
   237 }
       
   238 
       
   239 /*!
       
   240     \fn void Q3ListBoxItem::paint(QPainter *p)
       
   241 
       
   242     Implement this function to draw your item. The painter, \a p, is
       
   243     already open for painting.
       
   244 
       
   245     \sa height(), width()
       
   246 */
       
   247 
       
   248 /*!
       
   249     \fn int Q3ListBoxItem::width(const Q3ListBox* lb) const
       
   250 
       
   251     Reimplement this function to return the width of your item. The \a
       
   252     lb parameter is the same as listBox() and is provided for
       
   253     convenience and compatibility.
       
   254 
       
   255     The default implementation returns
       
   256     \l{QApplication::globalStrut()}'s width.
       
   257 
       
   258     \sa paint(), height()
       
   259 */
       
   260 int Q3ListBoxItem::width(const Q3ListBox*)  const
       
   261 {
       
   262     return QApplication::globalStrut().width();
       
   263 }
       
   264 
       
   265 /*!
       
   266     \fn int Q3ListBoxItem::height(const Q3ListBox* lb) const
       
   267 
       
   268     Implement this function to return the height of your item. The \a
       
   269     lb parameter is the same as listBox() and is provided for
       
   270     convenience and compatibility.
       
   271 
       
   272     The default implementation returns
       
   273     \l{QApplication::globalStrut()}'s height.
       
   274 
       
   275     \sa paint(), width()
       
   276 */
       
   277 int Q3ListBoxItem::height(const Q3ListBox*)  const
       
   278 {
       
   279     return QApplication::globalStrut().height();
       
   280 }
       
   281 
       
   282 
       
   283 /*!
       
   284     Returns the text of the item. This text is also used for sorting.
       
   285 
       
   286     \sa setText()
       
   287 */
       
   288 QString Q3ListBoxItem::text() const
       
   289 {
       
   290     return txt;
       
   291 }
       
   292 
       
   293 /*!
       
   294     Returns the pixmap associated with the item, or 0 if there isn't
       
   295     one.
       
   296 
       
   297     The default implementation returns 0.
       
   298 */
       
   299 const QPixmap *Q3ListBoxItem::pixmap() const
       
   300 {
       
   301     return 0;
       
   302 }
       
   303 
       
   304 /*! \fn void Q3ListBoxItem::setSelectable(bool b)
       
   305 
       
   306     If \a b is true (the default) then this item can be selected by
       
   307     the user; otherwise this item cannot be selected by the user.
       
   308 
       
   309     \sa isSelectable()
       
   310 */
       
   311 
       
   312 /*! \fn bool Q3ListBoxItem::isSelectable() const
       
   313 
       
   314     Returns true if this item is selectable (the default); otherwise
       
   315     returns false.
       
   316 
       
   317     \sa setSelectable()
       
   318 */
       
   319 
       
   320 
       
   321 /*!
       
   322     \fn void Q3ListBoxItem::setText(const QString &text)
       
   323 
       
   324     Sets the text of the Q3ListBoxItem to \a text. This \a text is also
       
   325     used for sorting. The text is not shown unless explicitly drawn in
       
   326     paint().
       
   327 
       
   328     \sa text()
       
   329 */
       
   330 
       
   331 
       
   332 /*!
       
   333     \class Q3ListBoxText
       
   334     \brief The Q3ListBoxText class provides list box items that display text.
       
   335 
       
   336     \compat
       
   337 
       
   338     The text is drawn in the widget's current font. If you need
       
   339     several different fonts, you must implement your own subclass of
       
   340     Q3ListBoxItem.
       
   341 
       
   342     \sa Q3ListBox, Q3ListBoxItem
       
   343 */
       
   344 
       
   345 
       
   346 /*!
       
   347     Constructs a list box item in list box \a listbox showing the text
       
   348     \a text.
       
   349 */
       
   350 Q3ListBoxText::Q3ListBoxText(Q3ListBox *listbox, const QString &text)
       
   351     :Q3ListBoxItem(listbox)
       
   352 {
       
   353     setText(text);
       
   354 }
       
   355 
       
   356 /*!
       
   357     Constructs a list box item showing the text \a text.
       
   358 */
       
   359 
       
   360 Q3ListBoxText::Q3ListBoxText(const QString &text)
       
   361     :Q3ListBoxItem()
       
   362 {
       
   363     setText(text);
       
   364 }
       
   365 
       
   366 /*!
       
   367     Constructs a list box item in list box \a listbox showing the text
       
   368     \a text. The item is inserted after the item \a after, or at the
       
   369     beginning if \a after is 0.
       
   370 */
       
   371 
       
   372 Q3ListBoxText::Q3ListBoxText(Q3ListBox* listbox, const QString &text, Q3ListBoxItem *after)
       
   373     : Q3ListBoxItem(listbox, after)
       
   374 {
       
   375     setText(text);
       
   376 }
       
   377 
       
   378 /*!
       
   379     Destroys the item.
       
   380 */
       
   381 
       
   382 Q3ListBoxText::~Q3ListBoxText()
       
   383 {
       
   384 }
       
   385 
       
   386 /*!
       
   387     Draws the text using \a painter.
       
   388 */
       
   389 
       
   390 void Q3ListBoxText::paint(QPainter *painter)
       
   391 {
       
   392     int itemHeight = height(listBox());
       
   393     QFontMetrics fm = painter->fontMetrics();
       
   394     int yPos = ((itemHeight - fm.height()) / 2) + fm.ascent();
       
   395     painter->drawText(3, yPos, text());
       
   396 }
       
   397 
       
   398 /*!
       
   399     Returns the height of a line of text in list box \a lb.
       
   400 
       
   401     \sa paint(), width()
       
   402 */
       
   403 
       
   404 int Q3ListBoxText::height(const Q3ListBox* lb) const
       
   405 {
       
   406     int h = lb ? lb->fontMetrics().lineSpacing() + 2 : 0;
       
   407     return qMax(h, QApplication::globalStrut().height());
       
   408 }
       
   409 
       
   410 /*!
       
   411     Returns the width of this line in list box \a lb.
       
   412 
       
   413     \sa paint(), height()
       
   414 */
       
   415 
       
   416 int Q3ListBoxText::width(const Q3ListBox* lb) const
       
   417 {
       
   418     int w = lb ? lb->fontMetrics().width(text()) + 6 : 0;
       
   419     return qMax(w, QApplication::globalStrut().width());
       
   420 }
       
   421 
       
   422 /*!
       
   423     \fn int Q3ListBoxText::rtti() const
       
   424 
       
   425     \reimp
       
   426 
       
   427     Returns 1.
       
   428 
       
   429     Make your derived classes return their own values for rtti(), and
       
   430     you can distinguish between listbox items. You should use values
       
   431     greater than 1000 preferably a large random number, to allow for
       
   432     extensions to this class.
       
   433 */
       
   434 
       
   435 int Q3ListBoxText::rtti() const
       
   436 {
       
   437     return RTTI;
       
   438 }
       
   439 
       
   440 /*!
       
   441     \class Q3ListBoxPixmap
       
   442     \brief The Q3ListBoxPixmap class provides list box items with a
       
   443     pixmap and optional text.
       
   444 
       
   445     \compat
       
   446 
       
   447     Items of this class are drawn with the pixmap on the left with the
       
   448     optional text to the right of the pixmap.
       
   449 
       
   450     \sa Q3ListBox, Q3ListBoxItem
       
   451 */
       
   452 
       
   453 
       
   454 /*!
       
   455     Constructs a new list box item in list box \a listbox showing the
       
   456     pixmap \a pixmap.
       
   457 */
       
   458 
       
   459 Q3ListBoxPixmap::Q3ListBoxPixmap(Q3ListBox* listbox, const QPixmap &pixmap)
       
   460     : Q3ListBoxItem(listbox)
       
   461 {
       
   462     pm = pixmap;
       
   463 }
       
   464 
       
   465 /*!
       
   466     Constructs a new list box item showing the pixmap \a pixmap.
       
   467 */
       
   468 
       
   469 Q3ListBoxPixmap::Q3ListBoxPixmap(const QPixmap &pixmap)
       
   470     : Q3ListBoxItem()
       
   471 {
       
   472     pm = pixmap;
       
   473 }
       
   474 
       
   475 /*!
       
   476     Constructs a new list box item in list box \a listbox showing the
       
   477     pixmap \a pixmap. The item gets inserted after the item \a after,
       
   478     or at the beginning if \a after is 0.
       
   479 */
       
   480 
       
   481 Q3ListBoxPixmap::Q3ListBoxPixmap(Q3ListBox* listbox, const QPixmap &pixmap, Q3ListBoxItem *after)
       
   482     : Q3ListBoxItem(listbox, after)
       
   483 {
       
   484     pm = pixmap;
       
   485 }
       
   486 
       
   487 
       
   488 /*!
       
   489     Destroys the item.
       
   490 */
       
   491 
       
   492 Q3ListBoxPixmap::~Q3ListBoxPixmap()
       
   493 {
       
   494 }
       
   495 
       
   496 
       
   497 /*!
       
   498     Constructs a new list box item in list box \a listbox showing the
       
   499     pixmap \a pix and the text \a text.
       
   500 */
       
   501 Q3ListBoxPixmap::Q3ListBoxPixmap(Q3ListBox* listbox, const QPixmap &pix, const QString& text)
       
   502     : Q3ListBoxItem(listbox)
       
   503 {
       
   504     pm = pix;
       
   505     setText(text);
       
   506 }
       
   507 
       
   508 /*!
       
   509     Constructs a new list box item showing the pixmap \a pix and the
       
   510     text to \a text.
       
   511 */
       
   512 Q3ListBoxPixmap::Q3ListBoxPixmap(const QPixmap & pix, const QString& text)
       
   513     : Q3ListBoxItem()
       
   514 {
       
   515     pm = pix;
       
   516     setText(text);
       
   517 }
       
   518 
       
   519 /*!
       
   520     Constructs a new list box item in list box \a listbox showing the
       
   521     pixmap \a pix and the string \a text. The item gets inserted after
       
   522     the item \a after, or at the beginning if \a after is 0.
       
   523 */
       
   524 Q3ListBoxPixmap::Q3ListBoxPixmap(Q3ListBox* listbox, const QPixmap & pix, const QString& text,
       
   525                                 Q3ListBoxItem *after)
       
   526     : Q3ListBoxItem(listbox, after)
       
   527 {
       
   528     pm = pix;
       
   529     setText(text);
       
   530 }
       
   531 
       
   532 /*!
       
   533     \fn const QPixmap *Q3ListBoxPixmap::pixmap() const
       
   534 
       
   535     Returns the pixmap associated with the item.
       
   536 */
       
   537 
       
   538 
       
   539 /*!
       
   540     Draws the pixmap using \a painter.
       
   541 */
       
   542 
       
   543 void Q3ListBoxPixmap::paint(QPainter *painter)
       
   544 {
       
   545     int itemHeight = height(listBox());
       
   546     int yPos;
       
   547 
       
   548     const QPixmap *pm = pixmap();
       
   549     if (pm && ! pm->isNull()) {
       
   550         yPos = (itemHeight - pm->height()) / 2;
       
   551         painter->drawPixmap(3, yPos, *pm);
       
   552     }
       
   553 
       
   554     if (!text().isEmpty()) {
       
   555         QFontMetrics fm = painter->fontMetrics();
       
   556         yPos = ((itemHeight - fm.height()) / 2) + fm.ascent();
       
   557         painter->drawText(pm->width() + 5, yPos, text());
       
   558     }
       
   559 }
       
   560 
       
   561 /*!
       
   562     Returns the height of the pixmap in list box \a lb.
       
   563 
       
   564     \sa paint(), width()
       
   565 */
       
   566 
       
   567 int Q3ListBoxPixmap::height(const Q3ListBox* lb) const
       
   568 {
       
   569     int h;
       
   570     if (text().isEmpty())
       
   571         h = pm.height();
       
   572     else
       
   573         h = qMax(pm.height(), lb->fontMetrics().lineSpacing() + 2);
       
   574     return qMax(h, QApplication::globalStrut().height());
       
   575 }
       
   576 
       
   577 /*!
       
   578     Returns the width of the pixmap plus some margin in list box \a lb.
       
   579 
       
   580     \sa paint(), height()
       
   581 */
       
   582 
       
   583 int Q3ListBoxPixmap::width(const Q3ListBox* lb) const
       
   584 {
       
   585     if (text().isEmpty())
       
   586         return qMax(pm.width() + 6, QApplication::globalStrut().width());
       
   587     return qMax(pm.width() + lb->fontMetrics().width(text()) + 6,
       
   588             QApplication::globalStrut().width());
       
   589 }
       
   590 
       
   591 /*!
       
   592     \fn int Q3ListBoxPixmap::rtti() const
       
   593 
       
   594     \reimp
       
   595 
       
   596     Returns 2.
       
   597 
       
   598     Make your derived classes return their own values for rtti(), and
       
   599     you can distinguish between listbox items. You should use values
       
   600     greater than 1000 preferably a large random number, to allow for
       
   601     extensions to this class.
       
   602 */
       
   603 
       
   604 int Q3ListBoxPixmap::rtti() const
       
   605 {
       
   606     return RTTI;
       
   607 }
       
   608 
       
   609 /*!
       
   610     \class Q3ListBox
       
   611     \brief The Q3ListBox widget provides a list of selectable, read-only items.
       
   612 
       
   613     \compat
       
   614 
       
   615     This is typically a single-column list in which either no item or
       
   616     one item is selected, but it can also be used in many other ways.
       
   617 
       
   618     Q3ListBox will add scroll bars as necessary, but it isn't intended
       
   619     for \e really big lists. If you want more than a few thousand
       
   620     items, it's probably better to use a different widget mainly
       
   621     because the scroll bars won't provide very good navigation, but
       
   622     also because Q3ListBox may become slow with huge lists. (See
       
   623     Q3ListView and Q3Table for possible alternatives.)
       
   624 
       
   625     There are a variety of selection modes described in the
       
   626     Q3ListBox::SelectionMode documentation. The default is \l Single
       
   627     selection mode, but you can change it using setSelectionMode().
       
   628     (setMultiSelection() is still provided for compatibility with Qt
       
   629     1.x. We recommend using setSelectionMode() in all code.)
       
   630 
       
   631     Because Q3ListBox offers multiple selection it must display
       
   632     keyboard focus and selection state separately. Therefore there are
       
   633     functions both to set the selection state of an item, i.e.
       
   634     setSelected(), and to set which item displays keyboard focus, i.e.
       
   635     setCurrentItem().
       
   636 
       
   637     The list box normally arranges its items in a single column and
       
   638     adds a vertical scroll bar if required. It is possible to have a
       
   639     different fixed number of columns (setColumnMode()), or as many
       
   640     columns as will fit in the list box's assigned screen space
       
   641     (setColumnMode(FitToWidth)), or to have a fixed number of rows
       
   642     (setRowMode()) or as many rows as will fit in the list box's
       
   643     assigned screen space (setRowMode(FitToHeight)). In all these
       
   644     cases Q3ListBox will add scroll bars, as appropriate, in at least
       
   645     one direction.
       
   646 
       
   647     If multiple rows are used, each row can be as high as necessary
       
   648     (the normal setting), or you can request that all items will have
       
   649     the same height by calling setVariableHeight(false). The same
       
   650     applies to a column's width, see setVariableWidth().
       
   651 
       
   652     The Q3ListBox's items are Q3ListBoxItem objects. Q3ListBox provides
       
   653     methods to insert new items as strings, as pixmaps, and as
       
   654     Q3ListBoxItem * (insertItem() with various arguments), and to
       
   655     replace an existing item with a new string, pixmap or Q3ListBoxItem
       
   656     (changeItem() with various arguments). You can also remove items
       
   657     singly with removeItem() or clear() the entire list box. Note that
       
   658     if you create a Q3ListBoxItem yourself and insert it, Q3ListBox
       
   659     takes ownership of the item.
       
   660 
       
   661     You can also create a Q3ListBoxItem, such as Q3ListBoxText or
       
   662     Q3ListBoxPixmap, with the list box as first parameter. The item
       
   663     will then append itself. When you delete an item it is
       
   664     automatically removed from the list box.
       
   665 
       
   666     The list of items can be arbitrarily large; Q3ListBox will add
       
   667     scroll bars if necessary. Q3ListBox can display a single-column
       
   668     (the common case) or multiple-columns, and offers both single and
       
   669     multiple selection. Q3ListBox does not support multiple-column
       
   670     items (but Q3ListView and Q3Table do), or tree hierarchies (but
       
   671     Q3ListView does).
       
   672 
       
   673     The list box items can be accessed both as Q3ListBoxItem objects
       
   674     (recommended) and using integer indexes (the original Q3ListBox
       
   675     implementation used an array of strings internally, and the API
       
   676     still supports this mode of operation). Everything can be done
       
   677     using the new objects, and most things can be done using indexes.
       
   678 
       
   679     Each item in a Q3ListBox contains a Q3ListBoxItem. One of the items
       
   680     can be the current item. The currentChanged() signal and the
       
   681     highlighted() signal are emitted when a new item becomes current,
       
   682     e.g. because the user clicks on it or Q3ListBox::setCurrentItem()
       
   683     is called. The selected() signal is emitted when the user
       
   684     double-clicks on an item or presses Enter on the current item.
       
   685 
       
   686     If the user does not select anything, no signals are emitted and
       
   687     currentItem() returns -1.
       
   688 
       
   689     A list box has Qt::WheelFocus as a default focusPolicy(), i.e. it
       
   690     can get keyboard focus by tabbing, clicking and through the use of
       
   691     the mouse wheel.
       
   692 
       
   693     New items can be inserted using insertItem(), insertStrList() or
       
   694     insertStringList().
       
   695 
       
   696     By default, vertical and horizontal scroll bars are added and
       
   697     removed as necessary. setHScrollBarMode() and setVScrollBarMode()
       
   698     can be used to change this policy.
       
   699 
       
   700     If you need to insert types other than strings and pixmaps, you
       
   701     must define new classes which inherit Q3ListBoxItem.
       
   702 
       
   703     \warning The list box assumes ownership of all list box items and
       
   704     will delete them when it does not need them any more.
       
   705 
       
   706     \inlineimage qlistbox-m.png Screenshot in Motif style
       
   707     \inlineimage qlistbox-w.png Screenshot in Windows style
       
   708 
       
   709     \sa Q3ListView, QComboBox, QButtonGroup
       
   710 */
       
   711 
       
   712 /*!
       
   713     \enum Q3ListBox::SelectionMode
       
   714 
       
   715     This enumerated type is used by Q3ListBox to indicate how it reacts
       
   716     to selection by the user.
       
   717 
       
   718     \value Single  When the user selects an item, any already-selected
       
   719     item becomes unselected and the user cannot unselect the selected
       
   720     item. This means that the user can never clear the selection, even
       
   721     though the selection may be cleared by the application programmer
       
   722     using Q3ListBox::clearSelection().
       
   723 
       
   724     \value Multi  When the user selects an item the selection status
       
   725     of that item is toggled and the other items are left alone.
       
   726 
       
   727     \value Extended When the user selects an item the selection is
       
   728     cleared and the new item selected. However, if the user presses
       
   729     the Ctrl key when clicking on an item, the clicked item gets
       
   730     toggled and all other items are left untouched. And if the user
       
   731     presses the Shift key while clicking on an item, all items between
       
   732     the current item and the clicked item get selected or unselected,
       
   733     depending on the state of the clicked item. Also, multiple items
       
   734     can be selected by dragging the mouse while the left mouse button
       
   735     is kept pressed.
       
   736 
       
   737     \value NoSelection  Items cannot be selected.
       
   738 
       
   739     In other words, \c Single is a real single-selection list box, \c
       
   740     Multi is a real multi-selection list box, \c Extended is a list
       
   741     box in which users can select multiple items but usually want to
       
   742     select either just one or a range of contiguous items, and \c
       
   743     NoSelection is for a list box where the user can look but not
       
   744     touch.
       
   745 */
       
   746 
       
   747 
       
   748 /*!
       
   749     \enum Q3ListBox::LayoutMode
       
   750 
       
   751     This enum type is used to specify how Q3ListBox lays out its rows
       
   752     and columns.
       
   753 
       
   754     \value FixedNumber  There is a fixed number of rows (or columns).
       
   755 
       
   756     \value FitToWidth   There are as many columns as will fit
       
   757     on-screen.
       
   758 
       
   759     \value FitToHeight  There are as many rows as will fit on-screen.
       
   760 
       
   761     \value Variable  There are as many rows as are required by the
       
   762     column mode. (Or as many columns as required by the row mode.)
       
   763 
       
   764     Example: When you call setRowMode(FitToHeight), columnMode()
       
   765     automatically becomes \c Variable to accommodate the row mode
       
   766     you've set.
       
   767 */
       
   768 
       
   769 /*!
       
   770     \fn void  Q3ListBox::onItem(Q3ListBoxItem *i)
       
   771 
       
   772     This signal is emitted when the user moves the mouse cursor onto
       
   773     an item, similar to the QWidget::enterEvent() function. \a i is
       
   774     the Q3ListBoxItem that the mouse has moved on.
       
   775 */
       
   776 
       
   777 // ### bug here too? enter/leave event may noit considered. move the
       
   778 // mouse out of the window and back in, to the same item - does it
       
   779 // work?
       
   780 
       
   781 /*!
       
   782     \fn void  Q3ListBox::onViewport()
       
   783 
       
   784     This signal is emitted when the user moves the mouse cursor from
       
   785     an item to an empty part of the list box.
       
   786 */
       
   787 
       
   788 
       
   789 /*!
       
   790     Constructs a new empty list box called \a name and with parent \a
       
   791     parent and widget attributes \a f.
       
   792 
       
   793     This constructor sets the Qt::WA_StaticContent and the
       
   794     Qt::WA_NoBackground attributes to boost performance when drawing
       
   795     Q3ListBoxItems. This may be unsuitable for custom Q3ListBoxItem
       
   796     classes, in which case Qt::WA_StaticContents and Qt::WA_NoBackground
       
   797     should be cleared on the viewport() after construction.
       
   798 */
       
   799 
       
   800 Q3ListBox::Q3ListBox(QWidget *parent, const char *name, Qt::WindowFlags f)
       
   801     : Q3ScrollView(parent, name, f | Qt::WStaticContents | Qt::WNoAutoErase)
       
   802 {
       
   803     d = new Q3ListBoxPrivate(this);
       
   804     d->updateTimer = new QTimer(this, "listbox update timer");
       
   805     d->visibleTimer = new QTimer(this, "listbox visible timer");
       
   806     d->inputTimer = new QTimer(this, "listbox input timer");
       
   807     d->resizeTimer = new QTimer(this, "listbox resize timer");
       
   808     d->clearing = false;
       
   809     d->pressedItem = 0;
       
   810     d->selectAnchor = 0;
       
   811     d->select = false;
       
   812     d->rubber = 0;
       
   813 
       
   814     setMouseTracking(true);
       
   815     viewport()->setMouseTracking(true);
       
   816 
       
   817     connect(d->updateTimer, SIGNAL(timeout()),
       
   818              this, SLOT(refreshSlot()));
       
   819     connect(d->visibleTimer, SIGNAL(timeout()),
       
   820              this, SLOT(ensureCurrentVisible()));
       
   821     connect(d->resizeTimer, SIGNAL(timeout()),
       
   822              this, SLOT(adjustItems()));
       
   823     viewport()->setBackgroundRole(QPalette::Base);
       
   824     viewport()->setFocusProxy(this);
       
   825     viewport()->setFocusPolicy(Qt::WheelFocus);
       
   826     setFocusPolicy(Qt::WheelFocus);
       
   827     setAttribute(Qt::WA_MacShowFocusRect);
       
   828 }
       
   829 
       
   830 
       
   831 Q3ListBox * Q3ListBox::changedListBox = 0;
       
   832 
       
   833 /*!
       
   834     Destroys the list box. Deletes all list box items.
       
   835 */
       
   836 
       
   837 Q3ListBox::~Q3ListBox()
       
   838 {
       
   839     if (changedListBox == this)
       
   840         changedListBox = 0;
       
   841     clear();
       
   842     delete d;
       
   843     d = 0;
       
   844 }
       
   845 
       
   846 /*!
       
   847     \fn void Q3ListBox::pressed(Q3ListBoxItem *item)
       
   848 
       
   849     This signal is emitted when the user presses any mouse button. If
       
   850     \a item is not 0, the cursor is on \a item. If \a item is 0, the
       
   851     mouse cursor isn't on any item.
       
   852 
       
   853     Note that you must not delete any Q3ListBoxItem objects in slots
       
   854     connected to this signal.
       
   855 */
       
   856 
       
   857 /*!
       
   858     \fn void Q3ListBox::pressed(Q3ListBoxItem *item, const QPoint &pnt)
       
   859     \overload
       
   860 
       
   861     This signal is emitted when the user presses any mouse button. If
       
   862     \a item is not 0, the cursor is on \a item. If \a item is 0, the
       
   863     mouse cursor isn't on any item.
       
   864 
       
   865     \a pnt is the position of the mouse cursor in the global
       
   866     coordinate system (QMouseEvent::globalPos()).
       
   867 
       
   868     Note that you must not delete any Q3ListBoxItem objects in slots
       
   869     connected to this signal.
       
   870 
       
   871     \sa mouseButtonPressed() rightButtonPressed() clicked()
       
   872 */
       
   873 
       
   874 /*!
       
   875     \fn void Q3ListBox::clicked(Q3ListBoxItem *item)
       
   876 
       
   877     This signal is emitted when the user clicks any mouse button. If
       
   878     \a item is not 0, the cursor is on \a item. If \a item is 0, the
       
   879     mouse cursor isn't on any item.
       
   880 
       
   881     Note that you must not delete any Q3ListBoxItem objects in slots
       
   882     connected to this signal.
       
   883 */
       
   884 
       
   885 /*!
       
   886     \fn void Q3ListBox::clicked(Q3ListBoxItem *item, const QPoint &pnt)
       
   887     \overload
       
   888 
       
   889     This signal is emitted when the user clicks any mouse button. If
       
   890     \a item is not 0, the cursor is on \a item. If \a item is 0, the
       
   891     mouse cursor isn't on any item.
       
   892 
       
   893     \a pnt is the position of the mouse cursor in the global
       
   894     coordinate system (QMouseEvent::globalPos()). (If the click's
       
   895     press and release differs by a pixel or two, \a pnt is the
       
   896     position at release time.)
       
   897 
       
   898     Note that you must not delete any Q3ListBoxItem objects in slots
       
   899     connected to this signal.
       
   900 */
       
   901 
       
   902 /*!
       
   903     \fn void Q3ListBox::mouseButtonClicked (int button, Q3ListBoxItem * item, const QPoint & pos)
       
   904 
       
   905     This signal is emitted when the user clicks mouse button \a
       
   906     button. If \a item is not 0, the cursor is on \a item. If \a item
       
   907     is 0, the mouse cursor isn't on any item.
       
   908 
       
   909     \a pos is the position of the mouse cursor in the global
       
   910     coordinate system (QMouseEvent::globalPos()). (If the click's
       
   911     press and release differs by a pixel or two, \a pos is the
       
   912     position at release time.)
       
   913 
       
   914     Note that you must not delete any Q3ListBoxItem objects in slots
       
   915     connected to this signal.
       
   916 */
       
   917 
       
   918 /*!
       
   919     \fn void Q3ListBox::mouseButtonPressed (int button, Q3ListBoxItem * item, const QPoint & pos)
       
   920 
       
   921     This signal is emitted when the user presses mouse button \a
       
   922     button. If \a item is not 0, the cursor is on \a item. If \a item
       
   923     is 0, the mouse cursor isn't on any item.
       
   924 
       
   925     \a pos is the position of the mouse cursor in the global
       
   926     coordinate system (QMouseEvent::globalPos()).
       
   927 
       
   928     Note that you must not delete any Q3ListBoxItem objects in slots
       
   929     connected to this signal.
       
   930 */
       
   931 
       
   932 /*!
       
   933     \fn void Q3ListBox::doubleClicked(Q3ListBoxItem *item)
       
   934 
       
   935     This signal is emitted whenever an item is double-clicked. It's
       
   936     emitted on the second button press, not the second button release.
       
   937     If \a item is not 0, the cursor is on \a item. If \a item is 0,
       
   938     the mouse cursor isn't on any item.
       
   939 */
       
   940 
       
   941 
       
   942 /*!
       
   943     \fn void Q3ListBox::returnPressed(Q3ListBoxItem *item)
       
   944 
       
   945     This signal is emitted when Enter or Return is pressed. The
       
   946     \a item passed in the argument is currentItem().
       
   947 */
       
   948 
       
   949 /*!
       
   950     \fn void Q3ListBox::rightButtonClicked(Q3ListBoxItem *item, const QPoint& point)
       
   951 
       
   952     This signal is emitted when the right button is clicked. The \a
       
   953     item is the item that the button was clicked on (which could be
       
   954     0 if no item was clicked on), and the \a point is where the
       
   955     click took place in global coordinates.
       
   956 */
       
   957 
       
   958 
       
   959 /*!
       
   960     \fn void Q3ListBox::rightButtonPressed (Q3ListBoxItem *item, const QPoint &point)
       
   961 
       
   962     This signal is emitted when the right button is pressed. The \a
       
   963     item is the item that the button was pressed over (which could be
       
   964     0 if no item was pressed over), and the \a point is where the
       
   965     press took place in global coordinates.
       
   966 */
       
   967 
       
   968 /*!
       
   969     \fn void Q3ListBox::contextMenuRequested(Q3ListBoxItem *item, const QPoint & pos)
       
   970 
       
   971     This signal is emitted when the user invokes a context menu with
       
   972     the right mouse button or with special system keys, with \a item
       
   973     being the item under the mouse cursor or the current item,
       
   974     respectively.
       
   975 
       
   976     \a pos is the position for the context menu in the global
       
   977     coordinate system.
       
   978 */
       
   979 
       
   980 /*!
       
   981     \fn void Q3ListBox::selectionChanged()
       
   982 
       
   983     This signal is emitted when the selection set of a list box
       
   984     changes. This signal is emitted in each selection mode. If the
       
   985     user selects five items by drag-selecting, Q3ListBox tries to emit
       
   986     just one selectionChanged() signal so the signal can be connected
       
   987     to computationally expensive slots.
       
   988 
       
   989     \sa selected() currentItem()
       
   990 */
       
   991 
       
   992 /*!
       
   993     \fn void Q3ListBox::selectionChanged(Q3ListBoxItem *item)
       
   994     \overload
       
   995 
       
   996     This signal is emitted when the selection in a \l Single selection
       
   997     list box changes. \a item is the newly selected list box item.
       
   998 
       
   999     \sa selected() currentItem()
       
  1000 */
       
  1001 
       
  1002 /*!
       
  1003     \fn void Q3ListBox::currentChanged(Q3ListBoxItem *item)
       
  1004 
       
  1005     This signal is emitted when the user makes a new item the current
       
  1006     item. \a item is the new current list box item.
       
  1007 
       
  1008     \sa setCurrentItem() currentItem()
       
  1009 */
       
  1010 
       
  1011 /*!
       
  1012     \fn void Q3ListBox::highlighted(int index)
       
  1013 
       
  1014     This signal is emitted when the user makes a new item the current
       
  1015     item. \a index is the index of the new current item.
       
  1016 
       
  1017     \sa currentChanged() selected() currentItem() selectionChanged()
       
  1018 */
       
  1019 
       
  1020 /*!
       
  1021     \fn void Q3ListBox::highlighted(Q3ListBoxItem *item)
       
  1022 
       
  1023     \overload
       
  1024 
       
  1025     This signal is emitted when the user makes a new \a item the current
       
  1026     \a item.
       
  1027 
       
  1028     \sa currentChanged() selected() currentItem() selectionChanged()
       
  1029 */
       
  1030 
       
  1031 /*!
       
  1032     \fn void Q3ListBox::highlighted(const QString & text)
       
  1033 
       
  1034     \overload
       
  1035 
       
  1036     This signal is emitted when the user makes a new item the current
       
  1037     item and the item is (or has) as string. The argument is the new
       
  1038     current item's \a text.
       
  1039 
       
  1040     \sa currentChanged() selected() currentItem() selectionChanged()
       
  1041 */
       
  1042 
       
  1043 /*!
       
  1044     \fn void Q3ListBox::selected(int index)
       
  1045 
       
  1046     This signal is emitted when the user double-clicks on an item or
       
  1047     presses Enter on the current item. \a index is the index of the
       
  1048     selected item.
       
  1049 
       
  1050     \sa currentChanged() highlighted() selectionChanged()
       
  1051 */
       
  1052 
       
  1053 /*!
       
  1054     \fn void Q3ListBox::selected(Q3ListBoxItem *item)
       
  1055 
       
  1056     \overload
       
  1057 
       
  1058     This signal is emitted when the user double-clicks on an \a item or
       
  1059     presses Enter on the current \a item.
       
  1060 
       
  1061     \sa currentChanged() highlighted() selectionChanged()
       
  1062 */
       
  1063 
       
  1064 /*!
       
  1065     \fn void Q3ListBox::selected(const QString &text)
       
  1066 
       
  1067     \overload
       
  1068 
       
  1069     This signal is emitted when the user double-clicks on an item or
       
  1070     presses Enter on the current item, and the item is (or has) a
       
  1071     string. The argument is the \a text of the selected item.
       
  1072 
       
  1073     \sa currentChanged() highlighted() selectionChanged()
       
  1074 */
       
  1075 
       
  1076 /*!
       
  1077     \property Q3ListBox::count
       
  1078     \brief the number of items in the list box
       
  1079 */
       
  1080 
       
  1081 uint Q3ListBox::count() const
       
  1082 {
       
  1083     return d->count;
       
  1084 }
       
  1085 
       
  1086 #if 0
       
  1087 /*!
       
  1088     Inserts the string list \a list into the list at position \a
       
  1089     index.
       
  1090 
       
  1091     If \a index is negative, \a list is inserted at the end of the
       
  1092     list. If \a index is too large, the operation is ignored.
       
  1093 
       
  1094     \warning This function uses \c{const char *} rather than QString,
       
  1095     so we recommend against using it. It is provided so that legacy
       
  1096     code will continue to work, and so that programs that certainly
       
  1097     will not need to handle code outside a single 8-bit locale can use
       
  1098     it. See insertStringList() which uses real QStrings.
       
  1099 
       
  1100     \warning This function is never significantly faster than a loop
       
  1101     around insertItem().
       
  1102 
       
  1103     \sa insertItem(), insertStringList()
       
  1104 */
       
  1105 
       
  1106 void Q3ListBox::insertStrList(const QStrList *list, int index)
       
  1107 {
       
  1108     if (!list) {
       
  1109         Q_ASSERT(list != 0);
       
  1110         return;
       
  1111     }
       
  1112     insertStrList(*list, index);
       
  1113 }
       
  1114 #endif
       
  1115 
       
  1116 
       
  1117 /*!
       
  1118     Inserts the string list \a list into the list at position \a
       
  1119     index.
       
  1120 
       
  1121     If \a index is negative, \a list is inserted at the end of the
       
  1122     list. If \a index is too large, the operation is ignored.
       
  1123 
       
  1124     \warning This function is never significantly faster than a loop
       
  1125     around insertItem().
       
  1126 
       
  1127     \sa insertItem(), insertStrList()
       
  1128 */
       
  1129 
       
  1130 void Q3ListBox::insertStringList(const QStringList & list, int index)
       
  1131 {
       
  1132     if (index < 0)
       
  1133         index = count();
       
  1134     for (QStringList::ConstIterator it = list.begin(); it != list.end(); ++it)
       
  1135         insertItem(new Q3ListBoxText(*it), index++);
       
  1136 }
       
  1137 
       
  1138 
       
  1139 #if 0
       
  1140 /*!
       
  1141     \overload
       
  1142 
       
  1143     Inserts the string list \a list into the list at position \a
       
  1144     index.
       
  1145 
       
  1146     If \a index is negative, \a list is inserted at the end of the
       
  1147     list. If \a index is too large, the operation is ignored.
       
  1148 
       
  1149     \warning This function uses \c{const char *} rather than QString,
       
  1150     so we recommend against using it. It is provided so that legacy
       
  1151     code will continue to work, and so that programs that certainly
       
  1152     will not need to handle code outside a single 8-bit locale can use
       
  1153     it. See insertStringList() which uses real QStrings.
       
  1154 
       
  1155     \warning This function is never significantly faster than a loop
       
  1156     around insertItem().
       
  1157 
       
  1158     \sa insertItem(), insertStringList()
       
  1159 */
       
  1160 void Q3ListBox::insertStrList(const QStrList & list, int index)
       
  1161 {
       
  1162     QStrListIterator it(list);
       
  1163     const char* txt;
       
  1164     if (index < 0)
       
  1165         index = count();
       
  1166     while ((txt=it.current())) {
       
  1167         ++it;
       
  1168         insertItem(new Q3ListBoxText(QString::fromLatin1(txt)),
       
  1169                     index++);
       
  1170     }
       
  1171     if (hasFocus() && !d->current)
       
  1172         setCurrentItem(d->head);
       
  1173 }
       
  1174 #endif
       
  1175 
       
  1176 
       
  1177 /*!
       
  1178     Inserts the \a numStrings strings of the array \a strings into the
       
  1179     list at position \a index.
       
  1180 
       
  1181     If \a index is negative, insertStrList() inserts \a strings at the
       
  1182     end of the list. If \a index is too large, the operation is
       
  1183     ignored.
       
  1184 
       
  1185     \warning This function uses \c{const char *} rather than QString,
       
  1186     so we recommend against using it. It is provided so that legacy
       
  1187     code will continue to work, and so that programs that certainly
       
  1188     will not need to handle code outside a single 8-bit locale can use
       
  1189     it. See insertStringList() which uses real QStrings.
       
  1190 
       
  1191     \warning This function is never significantly faster than a loop
       
  1192     around insertItem().
       
  1193 
       
  1194     \sa insertItem(), insertStringList()
       
  1195 */
       
  1196 
       
  1197 void Q3ListBox::insertStrList(const char **strings, int numStrings, int index)
       
  1198 {
       
  1199     if (!strings) {
       
  1200         Q_ASSERT(strings != 0);
       
  1201         return;
       
  1202     }
       
  1203     if (index < 0)
       
  1204         index = count();
       
  1205     int i = 0;
       
  1206     while ((numStrings<0 && strings[i]!=0) || i<numStrings) {
       
  1207         insertItem(new Q3ListBoxText(QString::fromLatin1(strings[i])),
       
  1208                     index + i);
       
  1209         i++;
       
  1210     }
       
  1211     if (hasFocus() && !d->current)
       
  1212         setCurrentItem(d->head);
       
  1213 }
       
  1214 
       
  1215 /*!
       
  1216     Inserts the item \a lbi into the list at position \a index.
       
  1217 
       
  1218     If \a index is negative or larger than the number of items in the
       
  1219     list box, \a lbi is inserted at the end of the list.
       
  1220 
       
  1221     \sa insertStrList()
       
  1222 */
       
  1223 
       
  1224 void Q3ListBox::insertItem(const Q3ListBoxItem *lbi, int index)
       
  1225 {
       
  1226     if (!lbi)
       
  1227         return;
       
  1228 
       
  1229     if (index < 0)
       
  1230         index = d->count;
       
  1231 
       
  1232     if (index >= d->count) {
       
  1233         insertItem(lbi, d->last);
       
  1234         return;
       
  1235     }
       
  1236 
       
  1237     Q3ListBoxItem * item = (Q3ListBoxItem *)lbi;
       
  1238     d->count++;
       
  1239     d->cache = 0;
       
  1240 
       
  1241     item->lbox = this;
       
  1242     if (!d->head || index == 0) {
       
  1243         item->n = d->head;
       
  1244         item->p = 0;
       
  1245         d->head = item;
       
  1246         item->dirty = true;
       
  1247         if (item->n)
       
  1248             item->n->p = item;
       
  1249     } else {
       
  1250         Q3ListBoxItem * i = d->head;
       
  1251         while (i->n && index > 1) {
       
  1252             i = i->n;
       
  1253             index--;
       
  1254         }
       
  1255         if (i->n) {
       
  1256             item->n = i->n;
       
  1257             item->p = i;
       
  1258             item->n->p = item;
       
  1259             item->p->n = item;
       
  1260         } else {
       
  1261             i->n = item;
       
  1262             item->p = i;
       
  1263             item->n = 0;
       
  1264         }
       
  1265     }
       
  1266 
       
  1267     if (hasFocus() && !d->current) {
       
  1268         d->current = d->head;
       
  1269         updateItem(d->current);
       
  1270         emit highlighted(d->current);
       
  1271         emit highlighted(d->current->text());
       
  1272         emit highlighted(index);
       
  1273     }
       
  1274 
       
  1275     triggerUpdate(true);
       
  1276 }
       
  1277 
       
  1278 /*!
       
  1279     \overload
       
  1280 
       
  1281     Inserts the item \a lbi into the list after the item \a after, or
       
  1282     at the beginning if \a after is 0.
       
  1283 
       
  1284     \sa insertStrList()
       
  1285 */
       
  1286 
       
  1287 void Q3ListBox::insertItem(const Q3ListBoxItem *lbi, const Q3ListBoxItem *after)
       
  1288 {
       
  1289     if (!lbi)
       
  1290         return;
       
  1291 
       
  1292     Q3ListBoxItem * item = (Q3ListBoxItem*)lbi;
       
  1293     d->count++;
       
  1294     d->cache = 0;
       
  1295 
       
  1296     item->lbox = this;
       
  1297     if (!d->head || !after) {
       
  1298         item->n = d->head;
       
  1299         item->p = 0;
       
  1300         d->head = item;
       
  1301         item->dirty = true;
       
  1302         if (item->n)
       
  1303             item->n->p = item;
       
  1304     } else {
       
  1305         Q3ListBoxItem * i = (Q3ListBoxItem*) after;
       
  1306         if (i) {
       
  1307             item->n = i->n;
       
  1308             item->p = i;
       
  1309             if (item->n)
       
  1310                 item->n->p = item;
       
  1311             if (item->p)
       
  1312                 item->p->n = item;
       
  1313         }
       
  1314     }
       
  1315 
       
  1316     if (after == d->last)
       
  1317         d->last = (Q3ListBoxItem*) lbi;
       
  1318 
       
  1319     if (hasFocus() && !d->current) {
       
  1320         d->current = d->head;
       
  1321         updateItem(d->current);
       
  1322         emit highlighted(d->current);
       
  1323         emit highlighted(d->current->text());
       
  1324         emit highlighted(index(d->current));
       
  1325     }
       
  1326 
       
  1327     triggerUpdate(true);
       
  1328 }
       
  1329 
       
  1330 /*!
       
  1331     \overload
       
  1332 
       
  1333     Inserts a new list box text item with the text \a text into the
       
  1334     list at position \a index.
       
  1335 
       
  1336     If \a index is negative, \a text is inserted at the end of the
       
  1337     list.
       
  1338 
       
  1339     \sa insertStrList()
       
  1340 */
       
  1341 
       
  1342 void Q3ListBox::insertItem(const QString &text, int index)
       
  1343 {
       
  1344     insertItem(new Q3ListBoxText(text), index);
       
  1345 }
       
  1346 
       
  1347 /*!
       
  1348     \overload
       
  1349 
       
  1350     Inserts a new list box pixmap item with the pixmap \a pixmap into
       
  1351     the list at position \a index.
       
  1352 
       
  1353     If \a index is negative, \a pixmap is inserted at the end of the
       
  1354     list.
       
  1355 
       
  1356     \sa insertStrList()
       
  1357 */
       
  1358 
       
  1359 void Q3ListBox::insertItem(const QPixmap &pixmap, int index)
       
  1360 {
       
  1361     insertItem(new Q3ListBoxPixmap(pixmap), index);
       
  1362 }
       
  1363 
       
  1364 /*!
       
  1365     \overload
       
  1366 
       
  1367     Inserts a new list box pixmap item with the pixmap \a pixmap and
       
  1368     the text \a text into the list at position \a index.
       
  1369 
       
  1370     If \a index is negative, \a pixmap is inserted at the end of the
       
  1371     list.
       
  1372 
       
  1373     \sa insertStrList()
       
  1374 */
       
  1375 
       
  1376 void Q3ListBox::insertItem(const QPixmap &pixmap, const QString &text, int index)
       
  1377 {
       
  1378     insertItem(new Q3ListBoxPixmap(pixmap, text), index);
       
  1379 }
       
  1380 
       
  1381 /*!
       
  1382     Removes and deletes the item at position \a index. If \a index is
       
  1383     equal to currentItem(), a new item becomes current and the
       
  1384     currentChanged() and highlighted() signals are emitted.
       
  1385 
       
  1386     \sa insertItem(), clear()
       
  1387 */
       
  1388 
       
  1389 void Q3ListBox::removeItem(int index)
       
  1390 {
       
  1391     bool wasVisible = itemVisible(currentItem());
       
  1392     delete item(index);
       
  1393     triggerUpdate(true);
       
  1394     if (wasVisible)
       
  1395         ensureCurrentVisible();
       
  1396 }
       
  1397 
       
  1398 
       
  1399 /*!
       
  1400     Deletes all the items in the list.
       
  1401 
       
  1402     \sa removeItem()
       
  1403 */
       
  1404 
       
  1405 void Q3ListBox::clear()
       
  1406 {
       
  1407     setContentsPos(0, 0);
       
  1408     bool blocked = signalsBlocked();
       
  1409     blockSignals(true);
       
  1410     d->clearing = true;
       
  1411     d->current = 0;
       
  1412     d->tmpCurrent = 0;
       
  1413     Q3ListBoxItem * i = d->head;
       
  1414     d->head = 0;
       
  1415     while (i) {
       
  1416         Q3ListBoxItem * n = i->n;
       
  1417         i->n = i->p = 0;
       
  1418         delete i;
       
  1419         i = n;
       
  1420     }
       
  1421     d->count = 0;
       
  1422     d->numRows = 1;
       
  1423     d->numColumns = 1;
       
  1424     d->currentRow = 0;
       
  1425     d->currentColumn = 0;
       
  1426     d->mousePressRow = -1;
       
  1427     d->mousePressColumn = -1;
       
  1428     d->mouseMoveRow = -1;
       
  1429     d->mouseMoveColumn = -1;
       
  1430     clearSelection();
       
  1431     d->selectAnchor = 0;
       
  1432     blockSignals(blocked);
       
  1433     triggerUpdate(true);
       
  1434     d->last = 0;
       
  1435     d->clearing = false;
       
  1436 }
       
  1437 
       
  1438 
       
  1439 /*!
       
  1440     Returns the text at position \a index, or an empty string if there
       
  1441     is no text at that position.
       
  1442 
       
  1443     \sa pixmap()
       
  1444 */
       
  1445 
       
  1446 QString Q3ListBox::text(int index) const
       
  1447 {
       
  1448     Q3ListBoxItem * i = item(index);
       
  1449     if (i)
       
  1450         return i->text();
       
  1451     return QString();
       
  1452 }
       
  1453 
       
  1454 
       
  1455 /*!
       
  1456     Returns a pointer to the pixmap at position \a index, or 0 if
       
  1457     there is no pixmap there.
       
  1458 
       
  1459     \sa text()
       
  1460 */
       
  1461 
       
  1462 const QPixmap *Q3ListBox::pixmap(int index) const
       
  1463 {
       
  1464     Q3ListBoxItem * i = item(index);
       
  1465     if (i)
       
  1466         return i->pixmap();
       
  1467     return 0;
       
  1468 }
       
  1469 
       
  1470 /*!
       
  1471     \overload
       
  1472 
       
  1473     Replaces the item at position \a index with a new list box text
       
  1474     item with text \a text.
       
  1475 
       
  1476     The operation is ignored if \a index is out of range.
       
  1477 
       
  1478     \sa insertItem(), removeItem()
       
  1479 */
       
  1480 
       
  1481 void Q3ListBox::changeItem(const QString &text, int index)
       
  1482 {
       
  1483     if(index >= 0 && index < (int)count())
       
  1484         changeItem(new Q3ListBoxText(text), index);
       
  1485 }
       
  1486 
       
  1487 /*!
       
  1488     \overload
       
  1489 
       
  1490     Replaces the item at position \a index with a new list box pixmap
       
  1491     item with pixmap \a pixmap.
       
  1492 
       
  1493     The operation is ignored if \a index is out of range.
       
  1494 
       
  1495     \sa insertItem(), removeItem()
       
  1496 */
       
  1497 
       
  1498 void Q3ListBox::changeItem(const QPixmap &pixmap, int index)
       
  1499 {
       
  1500     if(index >= 0 && index < (int)count())
       
  1501         changeItem(new Q3ListBoxPixmap(pixmap), index);
       
  1502 }
       
  1503 
       
  1504 /*!
       
  1505     \overload
       
  1506 
       
  1507     Replaces the item at position \a index with a new list box pixmap
       
  1508     item with pixmap \a pixmap and text \a text.
       
  1509 
       
  1510     The operation is ignored if \a index is out of range.
       
  1511 
       
  1512     \sa insertItem(), removeItem()
       
  1513 */
       
  1514 
       
  1515 void Q3ListBox::changeItem(const QPixmap &pixmap, const QString &text, int index)
       
  1516 {
       
  1517     if(index >= 0 && index < (int)count())
       
  1518         changeItem(new Q3ListBoxPixmap(pixmap, text), index);
       
  1519 }
       
  1520 
       
  1521 
       
  1522 
       
  1523 /*!
       
  1524     Replaces the item at position \a index with \a lbi.        If \a index is
       
  1525     negative or too large, changeItem() does nothing.
       
  1526 
       
  1527     The item that has been changed will become selected.
       
  1528 
       
  1529     \sa insertItem(), removeItem()
       
  1530 */
       
  1531 
       
  1532 void Q3ListBox::changeItem(const Q3ListBoxItem *lbi, int index)
       
  1533 {
       
  1534     if (!lbi || index < 0 || index >= (int)count())
       
  1535         return;
       
  1536 
       
  1537     removeItem(index);
       
  1538     insertItem(lbi, index);
       
  1539     setCurrentItem(index);
       
  1540 }
       
  1541 
       
  1542 
       
  1543 /*!
       
  1544     \property Q3ListBox::numItemsVisible
       
  1545     \brief the number of visible items.
       
  1546 
       
  1547     Both partially and entirely visible items are counted.
       
  1548 */
       
  1549 
       
  1550 int Q3ListBox::numItemsVisible() const
       
  1551 {
       
  1552     doLayout();
       
  1553 
       
  1554     int columns = 0;
       
  1555 
       
  1556     int x = contentsX();
       
  1557     int i=0;
       
  1558     while (i < (int)d->columnPos.size()-1 &&
       
  1559            d->columnPos[i] < x)
       
  1560         i++;
       
  1561     if (i < (int)d->columnPos.size()-1 &&
       
  1562          d->columnPos[i] > x)
       
  1563         columns++;
       
  1564     x += visibleWidth();
       
  1565     while (i < (int)d->columnPos.size()-1 &&
       
  1566            d->columnPos[i] < x) {
       
  1567         i++;
       
  1568         columns++;
       
  1569     }
       
  1570 
       
  1571     int y = contentsY();
       
  1572     int rows = 0;
       
  1573     while (i < (int)d->rowPos.size()-1 &&
       
  1574            d->rowPos[i] < y)
       
  1575         i++;
       
  1576     if (i < (int)d->rowPos.size()-1 &&
       
  1577          d->rowPos[i] > y)
       
  1578         rows++;
       
  1579     y += visibleHeight();
       
  1580     while (i < (int)d->rowPos.size()-1 &&
       
  1581            d->rowPos[i] < y) {
       
  1582         i++;
       
  1583         rows++;
       
  1584     }
       
  1585 
       
  1586     return rows*columns;
       
  1587 }
       
  1588 
       
  1589 int Q3ListBox::currentItem() const
       
  1590 {
       
  1591     if (!d->current || !d->head)
       
  1592         return -1;
       
  1593 
       
  1594     return index(d->current);
       
  1595 }
       
  1596 
       
  1597 
       
  1598 /*!
       
  1599     \property Q3ListBox::currentText
       
  1600     \brief the text of the current item.
       
  1601 
       
  1602     This is equivalent to text(currentItem()).
       
  1603 */
       
  1604 
       
  1605 
       
  1606 /*!
       
  1607     \property Q3ListBox::currentItem
       
  1608     \brief the current highlighted item
       
  1609 
       
  1610     When setting this property, the highlighting is moved to the item
       
  1611     and the list box scrolled as necessary.
       
  1612 
       
  1613     If no item is current, currentItem() returns -1.
       
  1614 */
       
  1615 
       
  1616 void Q3ListBox::setCurrentItem(int index)
       
  1617 {
       
  1618     setCurrentItem(item(index));
       
  1619 }
       
  1620 
       
  1621 /*!
       
  1622     \reimp
       
  1623 */
       
  1624 QVariant Q3ListBox::inputMethodQuery(Qt::InputMethodQuery query) const
       
  1625 {
       
  1626     if (query == Qt::ImMicroFocus)
       
  1627         return d->current ? itemRect(d->current) : QRect();
       
  1628     return QWidget::inputMethodQuery(query);
       
  1629 }
       
  1630 
       
  1631 /*!
       
  1632     \overload
       
  1633 
       
  1634     Sets the current item to the Q3ListBoxItem \a i.
       
  1635 */
       
  1636 void Q3ListBox::setCurrentItem(Q3ListBoxItem * i)
       
  1637 {
       
  1638     if (!i || d->current == i)
       
  1639         return;
       
  1640 
       
  1641     Q3ListBoxItem * o = d->current;
       
  1642     d->current = i;
       
  1643     int ind = index(i);
       
  1644 
       
  1645     if (i && selectionMode() == Single) {
       
  1646         bool changed = false;
       
  1647         if (o && o->s) {
       
  1648             changed = true;
       
  1649             o->s = false;
       
  1650         }
       
  1651         if (i && !i->s && d->selectionMode != NoSelection && i->isSelectable()) {
       
  1652             i->s = true;
       
  1653             changed = true;
       
  1654             emit selectionChanged(i);
       
  1655 #ifndef QT_NO_ACCESSIBILITY
       
  1656             QAccessible::updateAccessibility(viewport(), ind+1, QAccessible::StateChanged);
       
  1657 #endif
       
  1658         }
       
  1659         if (changed) {
       
  1660             emit selectionChanged();
       
  1661 #ifndef QT_NO_ACCESSIBILITY
       
  1662             QAccessible::updateAccessibility(viewport(), 0, QAccessible::Selection);
       
  1663 #endif
       
  1664         }
       
  1665     }
       
  1666 
       
  1667     d->currentColumn = ind / numRows();
       
  1668     d->currentRow = ind % numRows();
       
  1669     if (o)
       
  1670         updateItem(o);
       
  1671     if (i)
       
  1672         updateItem(i);
       
  1673     // scroll after the items are redrawn
       
  1674     d->visibleTimer->start(1, true);
       
  1675 
       
  1676     QString tmp;
       
  1677     if (i)
       
  1678         tmp = i->text();
       
  1679     emit highlighted(i);
       
  1680     if (!tmp.isNull())
       
  1681         emit highlighted(tmp);
       
  1682     emit highlighted(ind);
       
  1683     emit currentChanged(i);
       
  1684 
       
  1685 #ifndef QT_NO_ACCESSIBILITY
       
  1686     QAccessible::updateAccessibility(viewport(), ind+1, QAccessible::Focus);
       
  1687 #endif
       
  1688 }
       
  1689 
       
  1690 
       
  1691 /*!
       
  1692     Returns a pointer to the item at position \a index, or 0 if \a
       
  1693     index is out of bounds.
       
  1694 
       
  1695     \sa index()
       
  1696 */
       
  1697 
       
  1698 Q3ListBoxItem *Q3ListBox::item(int index) const
       
  1699 {
       
  1700     if (index < 0 || index > d->count -1)
       
  1701         return 0;
       
  1702 
       
  1703     Q3ListBoxItem * i = d->head;
       
  1704 
       
  1705     if (d->cache && index > 0) {
       
  1706         i = d->cache;
       
  1707         int idx = d->cacheIndex;
       
  1708         while (i && idx < index) {
       
  1709             idx++;
       
  1710             i = i->n;
       
  1711         }
       
  1712         while (i && idx > index) {
       
  1713             idx--;
       
  1714             i = i->p;
       
  1715         }
       
  1716     } else {
       
  1717         int idx = index;
       
  1718         while (i && idx > 0) {
       
  1719             idx--;
       
  1720             i = i->n;
       
  1721         }
       
  1722     }
       
  1723 
       
  1724     if (index > 0) {
       
  1725         d->cache = i;
       
  1726         d->cacheIndex = index;
       
  1727     }
       
  1728 
       
  1729     return i;
       
  1730 }
       
  1731 
       
  1732 
       
  1733 /*!
       
  1734     Returns the index of \a lbi, or -1 if the item is not in this list
       
  1735     box or \a lbi is 0.
       
  1736 
       
  1737     \sa item()
       
  1738 */
       
  1739 
       
  1740 int Q3ListBox::index(const Q3ListBoxItem * lbi) const
       
  1741 {
       
  1742     if (!lbi)
       
  1743         return -1;
       
  1744     Q3ListBoxItem * i_n = d->head;
       
  1745     int c_n = 0;
       
  1746     if (d->cache) {
       
  1747         i_n = d->cache;
       
  1748         c_n = d->cacheIndex;
       
  1749     }
       
  1750     Q3ListBoxItem* i_p = i_n;
       
  1751     int c_p = c_n;
       
  1752     while ((i_n != 0 || i_p != 0) && i_n != lbi && i_p != lbi) {
       
  1753         if (i_n) {
       
  1754             c_n++;
       
  1755             i_n = i_n->n;
       
  1756         }
       
  1757         if (i_p) {
       
  1758             c_p--;
       
  1759             i_p = i_p->p;
       
  1760         }
       
  1761     }
       
  1762     if (i_p == lbi)
       
  1763         return c_p;
       
  1764     if (i_n == lbi)
       
  1765         return c_n;
       
  1766     return -1;
       
  1767 }
       
  1768 
       
  1769 
       
  1770 
       
  1771 /*!
       
  1772     Returns true if the item at position \a index is at least partly
       
  1773     visible; otherwise returns false.
       
  1774 */
       
  1775 
       
  1776 bool Q3ListBox::itemVisible(int index)
       
  1777 {
       
  1778     Q3ListBoxItem * i = item(index);
       
  1779     return i ? itemVisible(i) : false;
       
  1780 }
       
  1781 
       
  1782 
       
  1783 /*!
       
  1784     \overload
       
  1785 
       
  1786     Returns true if \a item is at least partly visible; otherwise
       
  1787     returns false.
       
  1788 */
       
  1789 
       
  1790 bool Q3ListBox::itemVisible(const Q3ListBoxItem * item)
       
  1791 {
       
  1792     if (d->layoutDirty)
       
  1793         doLayout();
       
  1794 
       
  1795     int i = index(item);
       
  1796     int col = i / numRows();
       
  1797     int row = i % numRows();
       
  1798     return (d->columnPos[col] < contentsX()+visibleWidth() &&
       
  1799              d->rowPos[row] < contentsY()+visibleHeight() &&
       
  1800              d->columnPos[col+1] > contentsX() &&
       
  1801              d->rowPos[row+1] > contentsY());
       
  1802 }
       
  1803 
       
  1804 
       
  1805 /*! \reimp */
       
  1806 
       
  1807 void Q3ListBox::mousePressEvent(QMouseEvent *e)
       
  1808 {
       
  1809     mousePressEventEx(e);
       
  1810 }
       
  1811 
       
  1812 void Q3ListBox::mousePressEventEx(QMouseEvent *e)
       
  1813 {
       
  1814     d->mouseInternalPress = true;
       
  1815     Q3ListBoxItem * i = itemAt(e->pos());
       
  1816 
       
  1817     if (!i && !d->current && d->head) {
       
  1818         d->current = d->head;
       
  1819         updateItem(d->head);
       
  1820     }
       
  1821 
       
  1822     if (!i && (d->selectionMode != Single || e->button() == Qt::RightButton)
       
  1823          && !(e->state() & Qt::ControlButton))
       
  1824         clearSelection();
       
  1825 
       
  1826     d->select = d->selectionMode == Multi ? (i ? !i->isSelected() : false) : true;
       
  1827     d->pressedSelected = i && i->s;
       
  1828 
       
  1829     if (i)
       
  1830         d->selectAnchor = i;
       
  1831     if (i) {
       
  1832         switch(selectionMode()) {
       
  1833         default:
       
  1834         case Single:
       
  1835             if (!i->s || i != d->current) {
       
  1836                 if (i->isSelectable())
       
  1837                     setSelected(i, true);
       
  1838                 else
       
  1839                     setCurrentItem(i);
       
  1840             }
       
  1841             break;
       
  1842         case Extended:
       
  1843             if (i) {
       
  1844                 bool shouldBlock = false;
       
  1845                 if (!(e->state() & Qt::ShiftButton) &&
       
  1846                     !(e->state() & Qt::ControlButton)) {
       
  1847                     if (!i->isSelected()) {
       
  1848                         bool b = signalsBlocked();
       
  1849                         blockSignals(true);
       
  1850                         clearSelection();
       
  1851                         blockSignals(b);
       
  1852                     }
       
  1853                     setSelected(i, true);
       
  1854                     d->dragging = true; // always assume dragging
       
  1855                     shouldBlock = true;
       
  1856                 } else if (e->state() & Qt::ShiftButton) {
       
  1857                     d->pressedSelected = false;
       
  1858                     Q3ListBoxItem *oldCurrent = item(currentItem());
       
  1859                     bool down = index(oldCurrent) < index(i);
       
  1860 
       
  1861                     Q3ListBoxItem *lit = down ? oldCurrent : i;
       
  1862                     bool select = d->select;
       
  1863                     bool blocked = signalsBlocked();
       
  1864                     blockSignals(true);
       
  1865                     for (;; lit = lit->n) {
       
  1866                         if (!lit) {
       
  1867                             triggerUpdate(false);
       
  1868                             break;
       
  1869                         }
       
  1870                         if (down && lit == i) {
       
  1871                             setSelected(i, select);
       
  1872                             triggerUpdate(false);
       
  1873                             break;
       
  1874                         }
       
  1875                         if (!down && lit == oldCurrent) {
       
  1876                             setSelected(oldCurrent, select);
       
  1877                             triggerUpdate(false);
       
  1878                             break;
       
  1879                         }
       
  1880                         setSelected(lit, select);
       
  1881                     }
       
  1882                     blockSignals(blocked);
       
  1883                     emit selectionChanged();
       
  1884                 } else if (e->state() & Qt::ControlButton) {
       
  1885                     setSelected(i, !i->isSelected());
       
  1886                     shouldBlock = true;
       
  1887                     d->pressedSelected = false;
       
  1888                 }
       
  1889                 bool blocked = signalsBlocked();
       
  1890                 blockSignals(shouldBlock);
       
  1891                 setCurrentItem(i);
       
  1892                 blockSignals(blocked);
       
  1893             }
       
  1894             break;
       
  1895         case Multi:
       
  1896 	    {
       
  1897                 setSelected(i, !i->s);
       
  1898                 bool b = signalsBlocked();
       
  1899                 blockSignals(true);
       
  1900                 setCurrentItem(i);
       
  1901                 blockSignals(b);
       
  1902                 break;
       
  1903 	    }
       
  1904         case NoSelection:
       
  1905             setCurrentItem(i);
       
  1906             break;
       
  1907         }
       
  1908     } else {
       
  1909         bool unselect = true;
       
  1910         if (e->button() == Qt::LeftButton) {
       
  1911             if (d->selectionMode == Multi ||
       
  1912                  d->selectionMode == Extended) {
       
  1913                 d->tmpCurrent = d->current;
       
  1914                 d->current = 0;
       
  1915                 updateItem(d->tmpCurrent);
       
  1916                 if (d->rubber)
       
  1917                     delete d->rubber;
       
  1918                 d->rubber = 0;
       
  1919                 d->rubber = new QRect(e->x(), e->y(), 0, 0);
       
  1920 
       
  1921                 if (d->selectionMode == Extended && !(e->state() & Qt::ControlButton))
       
  1922                     selectAll(false);
       
  1923                 unselect = false;
       
  1924             }
       
  1925             if (unselect && (e->button() == Qt::RightButton ||
       
  1926                                (selectionMode() == Multi || selectionMode() == Extended)))
       
  1927                 clearSelection();
       
  1928         }
       
  1929     }
       
  1930 
       
  1931     // for sanity, in case people are event-filtering or whatnot
       
  1932     delete d->scrollTimer;
       
  1933     d->scrollTimer = 0;
       
  1934     if (i) {
       
  1935         d->mousePressColumn = d->currentColumn;
       
  1936         d->mousePressRow = d->currentRow;
       
  1937     } else {
       
  1938         d->mousePressColumn = -1;
       
  1939         d->mousePressRow = -1;
       
  1940     }
       
  1941     d->ignoreMoves = false;
       
  1942 
       
  1943     d->pressedItem = i;
       
  1944 
       
  1945     emit pressed(i);
       
  1946     emit pressed(i, e->globalPos());
       
  1947     emit mouseButtonPressed(e->button(), i, e->globalPos());
       
  1948     if (e->button() == Qt::RightButton)
       
  1949         emit rightButtonPressed(i, e->globalPos());
       
  1950 }
       
  1951 
       
  1952 
       
  1953 /*! \reimp */
       
  1954 
       
  1955 void Q3ListBox::mouseReleaseEvent(QMouseEvent *e)
       
  1956 {
       
  1957     if (d->selectionMode == Extended &&
       
  1958         d->dragging) {
       
  1959         d->dragging = false;
       
  1960         if (d->current != d->pressedItem) {
       
  1961             updateSelection(); // when we drag, we get an update after we release
       
  1962         }
       
  1963     }
       
  1964 
       
  1965     if (d->rubber) {
       
  1966         drawRubber();
       
  1967         delete d->rubber;
       
  1968         d->rubber = 0;
       
  1969         d->current = d->tmpCurrent;
       
  1970         updateItem(d->current);
       
  1971     }
       
  1972     if (d->scrollTimer)
       
  1973         mouseMoveEvent(e);
       
  1974     delete d->scrollTimer;
       
  1975     d->scrollTimer = 0;
       
  1976     d->ignoreMoves = false;
       
  1977 
       
  1978     if (d->selectionMode == Extended &&
       
  1979          d->current == d->pressedItem &&
       
  1980          d->pressedSelected && d->current) {
       
  1981         bool block = signalsBlocked();
       
  1982         blockSignals(true);
       
  1983         clearSelection();
       
  1984         blockSignals(block);
       
  1985         d->current->s = true;
       
  1986         emit selectionChanged();
       
  1987     }
       
  1988 
       
  1989     Q3ListBoxItem * i = itemAt(e->pos());
       
  1990     bool emitClicked = (d->mousePressColumn != -1 && d->mousePressRow != -1) || !d->pressedItem;
       
  1991     emitClicked = emitClicked && d->pressedItem == i;
       
  1992     d->pressedItem = 0;
       
  1993     d->mousePressRow = -1;
       
  1994     d->mousePressColumn = -1;
       
  1995     d->mouseInternalPress = false;
       
  1996     if (emitClicked) {
       
  1997         emit clicked(i);
       
  1998         emit clicked(i, e->globalPos());
       
  1999         emit mouseButtonClicked(e->button(), i, e->globalPos());
       
  2000         if (e->button() == Qt::RightButton)
       
  2001             emit rightButtonClicked(i, e->globalPos());
       
  2002     }
       
  2003 }
       
  2004 
       
  2005 
       
  2006 /*! \reimp */
       
  2007 
       
  2008 void Q3ListBox::mouseDoubleClickEvent(QMouseEvent *e)
       
  2009 {
       
  2010     bool ok = true;
       
  2011     Q3ListBoxItem *i = itemAt(e->pos());
       
  2012     if (!i || selectionMode() == NoSelection)
       
  2013         ok = false;
       
  2014 
       
  2015     d->ignoreMoves = true;
       
  2016 
       
  2017     if (d->current && ok) {
       
  2018         Q3ListBoxItem * i = d->current;
       
  2019         QString tmp = d->current->text();
       
  2020         emit selected(currentItem());
       
  2021         emit selected(i);
       
  2022         if (!tmp.isNull())
       
  2023             emit selected(tmp);
       
  2024         emit doubleClicked(i);
       
  2025     }
       
  2026 }
       
  2027 
       
  2028 
       
  2029 /*! \reimp */
       
  2030 
       
  2031 void Q3ListBox::mouseMoveEvent(QMouseEvent *e)
       
  2032 {
       
  2033     Q3ListBoxItem * i = itemAt(e->pos());
       
  2034     if (i != d->highlighted) {
       
  2035         if (i) {
       
  2036             emit onItem(i);
       
  2037         } else {
       
  2038             emit onViewport();
       
  2039         }
       
  2040         d->highlighted = i;
       
  2041     }
       
  2042 
       
  2043     if (d->rubber) {
       
  2044         QRect r = d->rubber->normalized();
       
  2045         drawRubber();
       
  2046         d->rubber->setCoords(d->rubber->x(), d->rubber->y(), e->x(), e->y());
       
  2047         doRubberSelection(r, d->rubber->normalized());
       
  2048         drawRubber();
       
  2049         return;
       
  2050     }
       
  2051 
       
  2052     if (((e->state() & (Qt::RightButton | Qt::LeftButton | Qt::MidButton)) == 0) ||
       
  2053          d->ignoreMoves)
       
  2054         return;
       
  2055 
       
  2056     // hack to keep the combo (and what else?) working: if we get a
       
  2057     // move outside the listbox without having seen a press, discard
       
  2058     // it.
       
  2059     if (!QRect(0, 0, visibleWidth(), visibleHeight()).contains(e->pos()) &&
       
  2060          ((d->mousePressColumn < 0 && d->mousePressRow < 0)
       
  2061           || (e->state() == Qt::NoButton && !d->pressedItem)))
       
  2062         return;
       
  2063 
       
  2064     // figure out in what direction to drag-select and perhaps scroll
       
  2065     int dx = 0;
       
  2066     int x = e->x();
       
  2067     if (x >= visibleWidth()) {
       
  2068         x = visibleWidth()-1;
       
  2069         dx = 1;
       
  2070     } else if (x < 0) {
       
  2071         x = 0;
       
  2072         dx = -1;
       
  2073     }
       
  2074     d->mouseMoveColumn = columnAt(x + contentsX());
       
  2075 
       
  2076     // sanitize mousePressColumn, if we got here without a mouse press event
       
  2077     if (d->mousePressColumn < 0 && d->mouseMoveColumn >= 0)
       
  2078         d->mousePressColumn = d->mouseMoveColumn;
       
  2079     if (d->mousePressColumn < 0 && d->currentColumn >= 0)
       
  2080         d->mousePressColumn = d->currentColumn;
       
  2081 
       
  2082     // if it's beyond the last column, use the last one
       
  2083     if (d->mouseMoveColumn < 0)
       
  2084         d->mouseMoveColumn = dx >= 0 ? numColumns()-1 : 0;
       
  2085 
       
  2086     // repeat for y
       
  2087     int dy = 0;
       
  2088     int y = e->y();
       
  2089     if (y >= visibleHeight()) {
       
  2090         y = visibleHeight()-1;
       
  2091         dy = 1;
       
  2092     } else if (y < 0) {
       
  2093         y = 0;
       
  2094         dy = -1;
       
  2095     }
       
  2096     d->mouseMoveRow = rowAt(y + contentsY());
       
  2097 
       
  2098     if (d->mousePressRow < 0 && d->mouseMoveRow >= 0)
       
  2099         d->mousePressRow = d->mouseMoveRow;
       
  2100     if (d->mousePressRow < 0 && d->currentRow >= 0)
       
  2101         d->mousePressRow = d->currentRow;
       
  2102 
       
  2103     if (d->mousePressRow < 0)
       
  2104         d->mousePressRow = rowAt(x + contentsX());
       
  2105 
       
  2106     d->scrollPos = QPoint(dx, dy);
       
  2107 
       
  2108     if ((dx || dy) && !d->scrollTimer && e->state() == Qt::LeftButton && e->button() != Qt::LeftButton) {
       
  2109         // start autoscrolling if necessary
       
  2110         d->scrollTimer = new QTimer(this);
       
  2111         connect(d->scrollTimer, SIGNAL(timeout()),
       
  2112                  this, SLOT(doAutoScroll()));
       
  2113         d->scrollTimer->start(100, false);
       
  2114         doAutoScroll();
       
  2115     } else if (!d->scrollTimer) {
       
  2116         // or just select the required bits
       
  2117         updateSelection();
       
  2118     }
       
  2119 }
       
  2120 
       
  2121 
       
  2122 
       
  2123 void Q3ListBox::updateSelection()
       
  2124 {
       
  2125     if (d->mouseMoveColumn >= 0 && d->mouseMoveRow >= 0 &&
       
  2126          d->mousePressColumn >= 0 && d->mousePressRow >= 0) {
       
  2127         Q3ListBoxItem * i = item(d->mouseMoveColumn * numRows() +
       
  2128                                  d->mouseMoveRow);
       
  2129 #ifndef QT_NO_ACCESSIBILITY
       
  2130         int ind = index(i);
       
  2131 #endif
       
  2132         if (selectionMode() == Single || selectionMode() == NoSelection) {
       
  2133             if (i && (d->mouseInternalPress || (windowType() == Qt::Popup)))
       
  2134                 setCurrentItem(i);
       
  2135         } else {
       
  2136             if (d->selectionMode == Extended && (
       
  2137                  (d->current == d->pressedItem && d->pressedSelected) ||
       
  2138                 (d->dirtyDrag && !d->dragging))) {
       
  2139                 if (d->dirtyDrag && !d->dragging) // emit after dragging stops
       
  2140                     d->dirtyDrag = false;
       
  2141                 else
       
  2142                     clearSelection(); // don't reset drag-selected items
       
  2143                 d->pressedItem = 0;
       
  2144                 if (i && i->isSelectable()) {
       
  2145                     bool block = signalsBlocked();
       
  2146                     blockSignals(true);
       
  2147                     i->s = true;
       
  2148                     blockSignals(block);
       
  2149                     emit selectionChanged();
       
  2150 #ifndef QT_NO_ACCESSIBILITY
       
  2151                     QAccessible::updateAccessibility(viewport(), ind+1, QAccessible::StateChanged);
       
  2152                     QAccessible::updateAccessibility(viewport(), 0, QAccessible::Selection);
       
  2153                     QAccessible::updateAccessibility(viewport(), ind+1, QAccessible::SelectionAdd);
       
  2154 #endif
       
  2155                 }
       
  2156                 triggerUpdate(false);
       
  2157             } else {
       
  2158                 int c = qMin(d->mouseMoveColumn, d->mousePressColumn);
       
  2159                 int r = qMin(d->mouseMoveRow, d->mousePressRow);
       
  2160                 int c2 = qMax(d->mouseMoveColumn, d->mousePressColumn);
       
  2161                 int r2 = qMax(d->mouseMoveRow, d->mousePressRow);
       
  2162                 bool changed = false;
       
  2163                 while(c <= c2) {
       
  2164                     Q3ListBoxItem * i = item(c*numRows()+r);
       
  2165                     int rtmp = r;
       
  2166                     while(i && rtmp <= r2) {
       
  2167                         if ((bool)i->s != (bool)d->select && i->isSelectable()) {
       
  2168                             i->s = d->select;
       
  2169 #ifndef QT_NO_ACCESSIBILITY
       
  2170                             QAccessible::updateAccessibility(viewport(), ind+1, QAccessible::StateChanged);
       
  2171                             QAccessible::updateAccessibility(viewport(), ind+1, d->select ? QAccessible::SelectionAdd : QAccessible::SelectionRemove);
       
  2172 #endif
       
  2173                             i->dirty = true;
       
  2174                             d->dirtyDrag = changed = true;
       
  2175                         }
       
  2176                         i = i->n;
       
  2177                         rtmp++;
       
  2178                     }
       
  2179                     c++;
       
  2180                 }
       
  2181                 if (changed) {
       
  2182                     if (!d->dragging) // emit after dragging stops instead
       
  2183                         emit selectionChanged();
       
  2184 #ifndef QT_NO_ACCESSIBILITY
       
  2185                     QAccessible::updateAccessibility(viewport(), 0, QAccessible::Selection);
       
  2186 #endif
       
  2187                     triggerUpdate(false);
       
  2188                 }
       
  2189             }
       
  2190             if (i)
       
  2191                 setCurrentItem(i);
       
  2192         }
       
  2193     }
       
  2194 }
       
  2195 
       
  2196 void Q3ListBox::repaintSelection()
       
  2197 {
       
  2198     if (d->numColumns == 1) {
       
  2199         for (uint i = topItem(); itemVisible(i) && i < count(); ++i) {
       
  2200             Q3ListBoxItem *it = item(i);
       
  2201             if (!it)
       
  2202                 break;
       
  2203             if (it->isSelected())
       
  2204                 updateItem(it);
       
  2205         }
       
  2206     } else {
       
  2207         for (uint i = 0; i < count(); ++i) {
       
  2208             Q3ListBoxItem *it = item(i);
       
  2209             if (!it)
       
  2210                 break;
       
  2211             if (it->isSelected())
       
  2212                 updateItem(it);
       
  2213         }
       
  2214     }
       
  2215 }
       
  2216 
       
  2217 /*! \reimp
       
  2218 */
       
  2219 
       
  2220 void Q3ListBox::contentsContextMenuEvent(QContextMenuEvent *e)
       
  2221 {
       
  2222     if (!receivers(SIGNAL(contextMenuRequested(Q3ListBoxItem*,QPoint)))) {
       
  2223         e->ignore();
       
  2224         return;
       
  2225     }
       
  2226     if (e->reason() == QContextMenuEvent::Keyboard) {
       
  2227         Q3ListBoxItem *i = item(currentItem());
       
  2228         if (i) {
       
  2229             QRect r = itemRect(i);
       
  2230             emit contextMenuRequested(i, mapToGlobal(r.topLeft() + QPoint(width() / 2, r.height() / 2)));
       
  2231         }
       
  2232     } else {
       
  2233         Q3ListBoxItem * i = itemAt(contentsToViewport(e->pos()));
       
  2234         emit contextMenuRequested(i, e->globalPos());
       
  2235     }
       
  2236 }
       
  2237 
       
  2238 /*!\reimp
       
  2239 */
       
  2240 void Q3ListBox::keyPressEvent(QKeyEvent *e)
       
  2241 {
       
  2242     if ((e->key() == Qt::Key_Tab || e->key() == Qt::Key_Backtab)
       
  2243          && e->state() & Qt::ControlButton)
       
  2244         e->ignore();
       
  2245 
       
  2246     if (count() == 0) {
       
  2247         e->ignore();
       
  2248         return;
       
  2249     }
       
  2250 
       
  2251     QPointer<Q3ListBox> selfCheck = this;
       
  2252 
       
  2253     Q3ListBoxItem *old = d->current;
       
  2254     if (!old) {
       
  2255         setCurrentItem(d->head);
       
  2256         if (d->selectionMode == Single)
       
  2257             setSelected(d->head, true);
       
  2258         e->ignore();
       
  2259         return;
       
  2260     }
       
  2261 
       
  2262     bool selectCurrent = false;
       
  2263     switch (e->key()) {
       
  2264         case Qt::Key_Up:
       
  2265             {
       
  2266                 d->currInputString.clear();
       
  2267                 if (currentItem() > 0) {
       
  2268                     setCurrentItem(currentItem() - 1);
       
  2269                     handleItemChange(old, e->state() & Qt::ShiftButton, e->state() & Qt::ControlButton);
       
  2270                 }
       
  2271                 if (!(e->state() & Qt::ShiftButton) || !d->selectAnchor)
       
  2272                     d->selectAnchor = d->current;
       
  2273             }
       
  2274             break;
       
  2275         case Qt::Key_Down:
       
  2276             {
       
  2277                 d->currInputString.clear();
       
  2278                 if (currentItem() < (int)count() - 1) {
       
  2279                     setCurrentItem(currentItem() + 1);
       
  2280                     handleItemChange(old, e->state() & Qt::ShiftButton, e->state() & Qt::ControlButton);
       
  2281                 }
       
  2282                 if (!(e->state() & Qt::ShiftButton) || !d->selectAnchor)
       
  2283                     d->selectAnchor = d->current;
       
  2284             }
       
  2285             break;
       
  2286         case Qt::Key_Left:
       
  2287             {
       
  2288                 d->currInputString.clear();
       
  2289                 if (currentColumn() > 0) {
       
  2290                     setCurrentItem(currentItem() - numRows());
       
  2291                     handleItemChange(old, e->state() & Qt::ShiftButton, e->state() & Qt::ControlButton);
       
  2292                 } else if (numColumns() > 1 && currentItem() > 0) {
       
  2293                     int row = currentRow();
       
  2294                     setCurrentItem(currentRow() - 1 + (numColumns() - 1) * numRows());
       
  2295 
       
  2296                     if (currentItem() == -1)
       
  2297                         setCurrentItem(row - 1 + (numColumns() - 2) * numRows());
       
  2298 
       
  2299                     handleItemChange(old, e->state() & Qt::ShiftButton, e->state() & Qt::ControlButton);
       
  2300                 } else {
       
  2301                     QApplication::sendEvent(horizontalScrollBar(), e);
       
  2302                 }
       
  2303                 if (!(e->state() & Qt::ShiftButton) || !d->selectAnchor)
       
  2304                     d->selectAnchor = d->current;
       
  2305             }
       
  2306             break;
       
  2307         case Qt::Key_Right:
       
  2308             {
       
  2309                 d->currInputString.clear();
       
  2310                 if (currentColumn() < numColumns()-1) {
       
  2311                     int row = currentRow();
       
  2312                     int i = currentItem();
       
  2313                     Q3ListBoxItem *it = item(i + numRows());
       
  2314                     if (!it)
       
  2315                         it = item(count()-1);
       
  2316                     setCurrentItem(it);
       
  2317 
       
  2318                     if (currentItem() == -1) {
       
  2319                         if (row < numRows() - 1)
       
  2320                             setCurrentItem(row + 1);
       
  2321                         else
       
  2322                             setCurrentItem(i);
       
  2323                     }
       
  2324 
       
  2325                     handleItemChange(old, e->state() & Qt::ShiftButton, e->state() & Qt::ControlButton);
       
  2326                 } else if (numColumns() > 1 && currentRow() < numRows()) {
       
  2327                     if (currentRow() + 1 < numRows()) {
       
  2328                         setCurrentItem(currentRow() + 1);
       
  2329                         handleItemChange(old, e->state() & Qt::ShiftButton, e->state() & Qt::ControlButton);
       
  2330                     }
       
  2331                 } else {
       
  2332                     QApplication::sendEvent(horizontalScrollBar(), e);
       
  2333                 }
       
  2334                 if (!(e->state() & Qt::ShiftButton) || !d->selectAnchor)
       
  2335                     d->selectAnchor = d->current;
       
  2336             }
       
  2337             break;
       
  2338         case Qt::Key_Next:
       
  2339             {
       
  2340                 d->currInputString.clear();
       
  2341                 int i = 0;
       
  2342                 if (numColumns() == 1) {
       
  2343                     i = currentItem() + numItemsVisible();
       
  2344                     i = i > (int)count() - 1 ? (int)count() - 1 : i;
       
  2345                     setCurrentItem(i);
       
  2346                     setBottomItem(i);
       
  2347                 } else {
       
  2348                     // I'm not sure about this behavior...
       
  2349                     if (currentRow() == numRows() - 1)
       
  2350                         i = currentItem() + numRows();
       
  2351                     else
       
  2352                         i = currentItem() + numRows() - currentRow() - 1;
       
  2353                     i = i > (int)count() - 1 ? (int)count() - 1 : i;
       
  2354                     setCurrentItem(i);
       
  2355                 }
       
  2356                 handleItemChange(old, e->state() & Qt::ShiftButton, e->state() & Qt::ControlButton);
       
  2357                 if (!(e->state() & Qt::ShiftButton) || !d->selectAnchor)
       
  2358                     d->selectAnchor = d->current;
       
  2359             }
       
  2360             break;
       
  2361         case Qt::Key_Prior:
       
  2362             {
       
  2363                 selectCurrent = true;
       
  2364                 d->currInputString.clear();
       
  2365                 int i;
       
  2366                 if (numColumns() == 1) {
       
  2367                     i = currentItem() - numItemsVisible();
       
  2368                     i = i < 0 ? 0 : i;
       
  2369                     setCurrentItem(i);
       
  2370                     setTopItem(i);
       
  2371                 } else {
       
  2372                     // I'm not sure about this behavior...
       
  2373                     if (currentRow() == 0)
       
  2374                         i = currentItem() - numRows();
       
  2375                     else
       
  2376                         i = currentItem() - currentRow();
       
  2377                     i = i < 0 ? 0 : i;
       
  2378                     setCurrentItem(i);
       
  2379                 }
       
  2380                 handleItemChange(old, e->state() & Qt::ShiftButton, e->state() & Qt::ControlButton);
       
  2381                 if (!(e->state() & Qt::ShiftButton) || !d->selectAnchor)
       
  2382                     d->selectAnchor = d->current;
       
  2383             }
       
  2384             break;
       
  2385         case Qt::Key_Space:
       
  2386             {
       
  2387                 selectCurrent = true;
       
  2388                 d->currInputString.clear();
       
  2389                 toggleCurrentItem();
       
  2390                 if (selectionMode() == Extended && d->current->isSelected())
       
  2391                     emit highlighted(currentItem());
       
  2392                 if (selfCheck && (!(e->state() & Qt::ShiftButton) || !d->selectAnchor))
       
  2393                     d->selectAnchor = d->current;
       
  2394             }
       
  2395             break;
       
  2396         case Qt::Key_Return:
       
  2397         case Qt::Key_Enter:
       
  2398             {
       
  2399                 selectCurrent = true;
       
  2400                 d->currInputString.clear();
       
  2401                 if (currentItem() >= 0 && selectionMode() != NoSelection) {
       
  2402                     QString tmp = item(currentItem())->text();
       
  2403                     emit selected(currentItem());
       
  2404                     emit selected(item(currentItem()));
       
  2405                     if (!tmp.isEmpty())
       
  2406                         emit selected(tmp);
       
  2407                     emit returnPressed(item(currentItem()));
       
  2408                 }
       
  2409                 if (selfCheck && (!(e->state() & Qt::ShiftButton) || !d->selectAnchor))
       
  2410                     d->selectAnchor = d->current;
       
  2411             }
       
  2412             break;
       
  2413         case Qt::Key_Home:
       
  2414             {
       
  2415                 selectCurrent = true;
       
  2416                 d->currInputString.clear();
       
  2417                 setCurrentItem(0);
       
  2418                 handleItemChange(old, e->state() & Qt::ShiftButton, e->state() & Qt::ControlButton);
       
  2419                 if (!(e->state() & Qt::ShiftButton) || !d->selectAnchor)
       
  2420                     d->selectAnchor = d->current;
       
  2421             }
       
  2422             break;
       
  2423         case Qt::Key_End:
       
  2424             {
       
  2425                 selectCurrent = true;
       
  2426                 d->currInputString.clear();
       
  2427                 int i = (int)count() - 1;
       
  2428                 setCurrentItem(i);
       
  2429                 handleItemChange(old, e->state() & Qt::ShiftButton, e->state() & Qt::ControlButton);
       
  2430                 if (!(e->state() & Qt::ShiftButton) || !d->selectAnchor)
       
  2431                     d->selectAnchor = d->current;
       
  2432             }
       
  2433             break;
       
  2434         default:
       
  2435             {
       
  2436                 if (!e->text().isEmpty() && e->text()[0].isPrint() && count()) {
       
  2437                     int curItem = currentItem();
       
  2438                     if (curItem == -1)
       
  2439                         curItem = 0;
       
  2440                     if (!d->inputTimer->isActive()) {
       
  2441                         d->currInputString = e->text();
       
  2442                         curItem = d->findItemByName(++curItem, d->currInputString);
       
  2443                     } else {
       
  2444                         d->inputTimer->stop();
       
  2445                         d->currInputString += e->text();
       
  2446                         int oldCurItem = curItem;
       
  2447                         curItem = d->findItemByName(curItem, d->currInputString);
       
  2448                         if (curItem < 0) {
       
  2449                             curItem = d->findItemByName(++oldCurItem, e->text());
       
  2450                             d->currInputString = e->text();
       
  2451                         }
       
  2452                     }
       
  2453                     if (curItem >= 0)
       
  2454                         setCurrentItem(curItem);
       
  2455                     if (curItem >= 0 && selectionMode() == Q3ListBox::Extended) {
       
  2456                         bool changed = false;
       
  2457                         bool block = signalsBlocked();
       
  2458                         blockSignals(true);
       
  2459                         selectAll(false);
       
  2460                         blockSignals(block);
       
  2461                         Q3ListBoxItem *i = item(curItem);
       
  2462                         if (!i->s && i->isSelectable()) {
       
  2463                             changed = true;
       
  2464                             i->s = true;
       
  2465                             updateItem(i);
       
  2466                         }
       
  2467                         if (changed)
       
  2468                             emit selectionChanged();
       
  2469                     }
       
  2470                     d->inputTimer->start(400, true);
       
  2471                 } else {
       
  2472                     d->currInputString.clear();
       
  2473                     if (e->state() & Qt::ControlButton) {
       
  2474                         switch (e->key()) {
       
  2475                             case Qt::Key_A:
       
  2476                                 selectAll(true);
       
  2477                                 break;
       
  2478                         }
       
  2479                     } else {
       
  2480                         e->ignore();
       
  2481                     }
       
  2482                 }
       
  2483             }
       
  2484     }
       
  2485 
       
  2486     if (selfCheck && selectCurrent && selectionMode() == Single &&
       
  2487         d->current && !d->current->s) {
       
  2488             updateItem(d->current);
       
  2489             setSelected(d->current, true);
       
  2490         }
       
  2491 }
       
  2492 
       
  2493 
       
  2494 /*!\reimp
       
  2495 */
       
  2496 void Q3ListBox::focusInEvent(QFocusEvent *e)
       
  2497 {
       
  2498     d->mousePressRow = -1;
       
  2499     d->mousePressColumn = -1;
       
  2500     d->inMenuMode = false;
       
  2501     if (e->reason() != Qt::MouseFocusReason && !d->current && d->head) {
       
  2502         d->current = d->head;
       
  2503         Q3ListBoxItem *i = d->current;
       
  2504         QString tmp;
       
  2505         if (i)
       
  2506             tmp = i->text();
       
  2507         int tmp2 = index(i);
       
  2508         emit highlighted(i);
       
  2509         if (!tmp.isNull())
       
  2510             emit highlighted(tmp);
       
  2511         emit highlighted(tmp2);
       
  2512         emit currentChanged(i);
       
  2513     }
       
  2514     if (style()->styleHint(QStyle::SH_ItemView_ChangeHighlightOnFocus, 0, this))
       
  2515         repaintSelection();
       
  2516 
       
  2517     if (d->current)
       
  2518         updateItem(currentItem());
       
  2519 }
       
  2520 
       
  2521 
       
  2522 /*!\reimp
       
  2523 */
       
  2524 void Q3ListBox::focusOutEvent(QFocusEvent *e)
       
  2525 {
       
  2526     if (style()->styleHint(QStyle::SH_ItemView_ChangeHighlightOnFocus, 0, this)) {
       
  2527         d->inMenuMode =
       
  2528             e->reason() == Qt::PopupFocusReason ||
       
  2529             (qApp->focusWidget() && qApp->focusWidget()->inherits("QMenuBar"));
       
  2530         if (!d->inMenuMode)
       
  2531             repaintSelection();
       
  2532     }
       
  2533 
       
  2534     if (d->current)
       
  2535         updateItem(currentItem());
       
  2536 }
       
  2537 
       
  2538 /*!\reimp
       
  2539 */
       
  2540 bool Q3ListBox::eventFilter(QObject *o, QEvent *e)
       
  2541 {
       
  2542     return Q3ScrollView::eventFilter(o, e);
       
  2543 }
       
  2544 
       
  2545 /*!
       
  2546     Repaints the item at position \a index in the list.
       
  2547 */
       
  2548 
       
  2549 void Q3ListBox::updateItem(int index)
       
  2550 {
       
  2551     if (index >= 0)
       
  2552         updateItem(item(index));
       
  2553 }
       
  2554 
       
  2555 
       
  2556 /*!
       
  2557     \overload
       
  2558 
       
  2559     Repaints the Q3ListBoxItem \a i.
       
  2560 */
       
  2561 
       
  2562 void Q3ListBox::updateItem(Q3ListBoxItem * i)
       
  2563 {
       
  2564     if (!i)
       
  2565         return;
       
  2566     i->dirty = true;
       
  2567     d->updateTimer->start(0, true);
       
  2568 }
       
  2569 
       
  2570 
       
  2571 /*!
       
  2572     \property Q3ListBox::selectionMode
       
  2573     \brief the selection mode of the list box
       
  2574 
       
  2575     Sets the list box's selection mode, which may be one of \c Single
       
  2576     (the default), \c Extended, \c Multi or \c NoSelection.
       
  2577 
       
  2578     \sa SelectionMode
       
  2579 */
       
  2580 
       
  2581 void Q3ListBox::setSelectionMode(SelectionMode mode)
       
  2582 {
       
  2583     if (d->selectionMode == mode)
       
  2584         return;
       
  2585 
       
  2586     if ((selectionMode() == Multi || selectionMode() == Extended)
       
  2587          && (mode == Q3ListBox::Single || mode == Q3ListBox::NoSelection)){
       
  2588         clearSelection();
       
  2589         if ((mode == Q3ListBox::Single) && currentItem())
       
  2590             setSelected(currentItem(), true);
       
  2591     }
       
  2592 
       
  2593     d->selectionMode = mode;
       
  2594     triggerUpdate(true);
       
  2595 }
       
  2596 
       
  2597 
       
  2598 Q3ListBox::SelectionMode Q3ListBox::selectionMode() const
       
  2599 {
       
  2600     return d->selectionMode;
       
  2601 }
       
  2602 
       
  2603 
       
  2604 /*!
       
  2605   \property Q3ListBox::multiSelection
       
  2606   \brief whether or not the list box is in Multi selection mode
       
  2607 
       
  2608   Consider using the \l Q3ListBox::selectionMode property instead of
       
  2609   this property.
       
  2610 
       
  2611   When setting this property, Multi selection mode is used if set to true and
       
  2612   to Single selection mode if set to false.
       
  2613 
       
  2614   When getting this property, true is returned if the list box is in
       
  2615   Multi selection mode or Extended selection mode, and false if it is
       
  2616   in Single selection mode or NoSelection mode.
       
  2617 
       
  2618   \sa selectionMode
       
  2619 */
       
  2620 
       
  2621 bool Q3ListBox::isMultiSelection() const
       
  2622 {
       
  2623     return selectionMode() == Multi || selectionMode() == Extended;
       
  2624 }
       
  2625 
       
  2626 void Q3ListBox::setMultiSelection(bool enable)
       
  2627 {
       
  2628     setSelectionMode(enable ? Multi : Single);
       
  2629 }
       
  2630 
       
  2631 
       
  2632 /*!
       
  2633     Toggles the selection status of currentItem() and repaints if the
       
  2634     list box is a \c Multi selection list box.
       
  2635 
       
  2636     \sa setMultiSelection()
       
  2637 */
       
  2638 
       
  2639 void Q3ListBox::toggleCurrentItem()
       
  2640 {
       
  2641     if (selectionMode() == Single ||
       
  2642          selectionMode() == NoSelection ||
       
  2643          !d->current)
       
  2644         return;
       
  2645 
       
  2646     if (d->current->s || d->current->isSelectable()) {
       
  2647         d->current->s = !d->current->s;
       
  2648         emit selectionChanged();
       
  2649 #ifndef QT_NO_ACCESSIBILITY
       
  2650         int ind = index(d->current);
       
  2651         QAccessible::updateAccessibility(viewport(), 0, QAccessible::Selection);
       
  2652         QAccessible::updateAccessibility(viewport(), ind+1, QAccessible::StateChanged);
       
  2653         QAccessible::updateAccessibility(viewport(), ind+1, d->current->s ? QAccessible::SelectionAdd : QAccessible::SelectionRemove);
       
  2654 #endif
       
  2655     }
       
  2656     updateItem(d->current);
       
  2657 }
       
  2658 
       
  2659 
       
  2660 /*!
       
  2661     \overload
       
  2662 
       
  2663     If \a select is true the item at position \a index is selected;
       
  2664     otherwise the item is deselected.
       
  2665 */
       
  2666 
       
  2667 void Q3ListBox::setSelected(int index, bool select)
       
  2668 {
       
  2669     setSelected(item(index), select);
       
  2670 }
       
  2671 
       
  2672 
       
  2673 /*!
       
  2674     Selects \a item if \a select is true or unselects it if \a select
       
  2675     is false, and repaints the item appropriately.
       
  2676 
       
  2677     If the list box is a \c Single selection list box and \a select is
       
  2678     true, setSelected() calls setCurrentItem().
       
  2679 
       
  2680     If the list box is a \c Single selection list box, \a select is
       
  2681     false, setSelected() calls clearSelection().
       
  2682 
       
  2683     \sa setMultiSelection(), setCurrentItem(), clearSelection(), currentItem()
       
  2684 */
       
  2685 
       
  2686 void Q3ListBox::setSelected(Q3ListBoxItem * item, bool select)
       
  2687 {
       
  2688     if (!item || !item->isSelectable() ||
       
  2689         (bool)item->s == select || d->selectionMode == NoSelection)
       
  2690         return;
       
  2691 
       
  2692     int ind = index(item);
       
  2693     bool emitHighlighted = (d->current != item) || ( select && (item->s != (uint) select) );
       
  2694     if (selectionMode() == Single) {
       
  2695         if (d->current != item) {
       
  2696             Q3ListBoxItem *o = d->current;
       
  2697             if (d->current && d->current->s)
       
  2698                 d->current->s = false;
       
  2699             d->current = item;
       
  2700 #ifndef QT_NO_ACCESSIBILITY
       
  2701             QAccessible::updateAccessibility(viewport(), ind+1, QAccessible::Focus);
       
  2702 #endif
       
  2703             d->currentColumn = ind / numRows();
       
  2704             d->currentRow = ind % numRows();
       
  2705 
       
  2706             if (o)
       
  2707                 updateItem(o);
       
  2708         }
       
  2709     }
       
  2710 
       
  2711     item->s = (uint)select;
       
  2712     updateItem(item);
       
  2713 
       
  2714     if (d->selectionMode == Single && select) {
       
  2715         emit selectionChanged(item);
       
  2716 #ifndef QT_NO_ACCESSIBILITY
       
  2717         QAccessible::updateAccessibility(viewport(), ind+1, QAccessible::StateChanged);
       
  2718 #endif
       
  2719     }
       
  2720     emit selectionChanged();
       
  2721 #ifndef QT_NO_ACCESSIBILITY
       
  2722     QAccessible::updateAccessibility(viewport(), 0, QAccessible::Selection);
       
  2723     if (d->selectionMode != Single)
       
  2724         QAccessible::updateAccessibility(viewport(), ind+1, select ? QAccessible::SelectionAdd : QAccessible::SelectionRemove);
       
  2725 #endif
       
  2726 
       
  2727     if (emitHighlighted) {
       
  2728         QString tmp;
       
  2729         if (item)
       
  2730             tmp = item->text();
       
  2731         int tmp2 = index(item);
       
  2732         emit highlighted(item);
       
  2733         if (!tmp.isNull())
       
  2734             emit highlighted(tmp);
       
  2735         emit highlighted(tmp2);
       
  2736         emit currentChanged(item);
       
  2737     }
       
  2738 }
       
  2739 
       
  2740 
       
  2741 /*!
       
  2742     Returns true if item \a i is selected; otherwise returns false.
       
  2743 */
       
  2744 
       
  2745 bool Q3ListBox::isSelected(int i) const
       
  2746 {
       
  2747     if (selectionMode() == Single && i != currentItem())
       
  2748         return false;
       
  2749 
       
  2750     Q3ListBoxItem * lbi = item(i);
       
  2751     if (!lbi)
       
  2752         return false; // should not happen
       
  2753     return lbi->s;
       
  2754 }
       
  2755 
       
  2756 
       
  2757 /*!
       
  2758     \overload
       
  2759 
       
  2760     Returns true if item \a i is selected; otherwise returns false.
       
  2761 */
       
  2762 
       
  2763 bool Q3ListBox::isSelected(const Q3ListBoxItem * i) const
       
  2764 {
       
  2765     if (!i)
       
  2766         return false;
       
  2767 
       
  2768     return i->s;
       
  2769 }
       
  2770 
       
  2771 /*!  Returns the selected item if the list box is in
       
  2772 single-selection mode and an item is selected.
       
  2773 
       
  2774 If no items are selected or the list box is in another selection mode
       
  2775 this function returns 0.
       
  2776 
       
  2777 \sa setSelected() setMultiSelection()
       
  2778 */
       
  2779 
       
  2780 Q3ListBoxItem* Q3ListBox::selectedItem() const
       
  2781 {
       
  2782     if (d->selectionMode != Single)
       
  2783         return 0;
       
  2784     if (isSelected(currentItem()))
       
  2785         return  d->current;
       
  2786     return 0;
       
  2787 }
       
  2788 
       
  2789 
       
  2790 /*!
       
  2791     Deselects all items, if possible.
       
  2792 
       
  2793     Note that a \c Single selection list box will automatically select
       
  2794     an item if it has keyboard focus.
       
  2795 */
       
  2796 
       
  2797 void Q3ListBox::clearSelection()
       
  2798 {
       
  2799     selectAll(false);
       
  2800 }
       
  2801 
       
  2802 /*!
       
  2803     In \c Multi and \c Extended modes, this function sets all items to
       
  2804     be selected if \a select is true, and to be unselected if \a
       
  2805     select is false.
       
  2806 
       
  2807     In \c Single and \c NoSelection modes, this function only changes
       
  2808     the selection status of currentItem().
       
  2809 */
       
  2810 
       
  2811 void Q3ListBox::selectAll(bool select)
       
  2812 {
       
  2813     if (selectionMode() == Multi || selectionMode() == Extended) {
       
  2814         bool b = signalsBlocked();
       
  2815         blockSignals(true);
       
  2816         for (int i = 0; i < (int)count(); i++)
       
  2817             setSelected(i, select);
       
  2818         blockSignals(b);
       
  2819         emit selectionChanged();
       
  2820     } else if (d->current) {
       
  2821         Q3ListBoxItem * i = d->current;
       
  2822         setSelected(i, select);
       
  2823     }
       
  2824 }
       
  2825 
       
  2826 /*!
       
  2827     Inverts the selection. Only works in \c Multi and \c Extended
       
  2828     selection mode.
       
  2829 */
       
  2830 
       
  2831 void Q3ListBox::invertSelection()
       
  2832 {
       
  2833     if (d->selectionMode == Single ||
       
  2834          d->selectionMode == NoSelection)
       
  2835         return;
       
  2836 
       
  2837     bool b = signalsBlocked();
       
  2838     blockSignals(true);
       
  2839     for (int i = 0; i < (int)count(); i++)
       
  2840         setSelected(i, !item(i)->isSelected());
       
  2841     blockSignals(b);
       
  2842     emit selectionChanged();
       
  2843 }
       
  2844 
       
  2845 
       
  2846 /*!
       
  2847   Not used anymore; provided for compatibility.
       
  2848 */
       
  2849 
       
  2850 void Q3ListBox::emitChangedSignal(bool)
       
  2851 {
       
  2852 }
       
  2853 
       
  2854 
       
  2855 /*! \reimp */
       
  2856 
       
  2857 QSize Q3ListBox::sizeHint() const
       
  2858 {
       
  2859     if (cachedSizeHint().isValid())
       
  2860         return cachedSizeHint();
       
  2861 
       
  2862     ensurePolished();
       
  2863     doLayout();
       
  2864 
       
  2865     int i=0;
       
  2866     while(i < 10 &&
       
  2867            i < (int)d->columnPos.size()-1 &&
       
  2868            d->columnPos[i] < 200)
       
  2869         i++;
       
  2870     int x;
       
  2871     x = qMin(200, d->columnPos[i] +
       
  2872               2 * style()->pixelMetric(QStyle::PM_DefaultFrameWidth));
       
  2873     x = qMax(40, x);
       
  2874 
       
  2875     i = 0;
       
  2876     while(i < 10 &&
       
  2877            i < (int)d->rowPos.size()-1 &&
       
  2878            d->rowPos[i] < 200)
       
  2879         i++;
       
  2880     int y;
       
  2881     y = qMin(200, d->rowPos[i] +
       
  2882               2 * style()->pixelMetric(QStyle::PM_DefaultFrameWidth));
       
  2883     y = qMax(40, y);
       
  2884 
       
  2885     QSize s(x, y);
       
  2886     setCachedSizeHint(s);
       
  2887     return s;
       
  2888 }
       
  2889 
       
  2890 /*!
       
  2891   \reimp
       
  2892 */
       
  2893 
       
  2894 QSize Q3ListBox::minimumSizeHint() const
       
  2895 {
       
  2896     return Q3ScrollView::minimumSizeHint();
       
  2897 }
       
  2898 
       
  2899 
       
  2900 /*!
       
  2901     Ensures that a single paint event will occur at the end of the
       
  2902     current event loop iteration. If \a doLayout is true, the layout
       
  2903     is also redone.
       
  2904 */
       
  2905 
       
  2906 void Q3ListBox::triggerUpdate(bool doLayout)
       
  2907 {
       
  2908     if (doLayout)
       
  2909         d->layoutDirty = d->mustPaintAll = true;
       
  2910     d->updateTimer->start(0, true);
       
  2911 }
       
  2912 
       
  2913 
       
  2914 void Q3ListBox::setColumnMode(LayoutMode mode)
       
  2915 {
       
  2916     if (mode == Variable)
       
  2917         return;
       
  2918     d->rowModeWins = false;
       
  2919     d->columnMode = mode;
       
  2920     triggerUpdate(true);
       
  2921 }
       
  2922 
       
  2923 
       
  2924 void Q3ListBox::setColumnMode(int columns)
       
  2925 {
       
  2926     if (columns < 1)
       
  2927         columns = 1;
       
  2928     d->columnMode = FixedNumber;
       
  2929     d->numColumns = columns;
       
  2930     d->rowModeWins = false;
       
  2931     triggerUpdate(true);
       
  2932 }
       
  2933 
       
  2934 void Q3ListBox::setRowMode(LayoutMode mode)
       
  2935 {
       
  2936     if (mode == Variable)
       
  2937         return;
       
  2938     d->rowModeWins = true;
       
  2939     d->rowMode = mode;
       
  2940     triggerUpdate(true);
       
  2941 }
       
  2942 
       
  2943 
       
  2944 void Q3ListBox::setRowMode(int rows)
       
  2945 {
       
  2946     if (rows < 1)
       
  2947         rows = 1;
       
  2948     d->rowMode = FixedNumber;
       
  2949     d->numRows = rows;
       
  2950     d->rowModeWins = true;
       
  2951     triggerUpdate(true);
       
  2952 }
       
  2953 
       
  2954 /*!
       
  2955     \property Q3ListBox::columnMode
       
  2956     \brief the column layout mode for this list box.
       
  2957 
       
  2958     setColumnMode() sets the layout mode and adjusts the number of
       
  2959     displayed columns. The row layout mode automatically becomes \c
       
  2960     Variable, unless the column mode is \c Variable.
       
  2961 
       
  2962     \sa setRowMode() rowMode numColumns
       
  2963 */
       
  2964 
       
  2965 
       
  2966 Q3ListBox::LayoutMode Q3ListBox::columnMode() const
       
  2967 {
       
  2968     if (d->rowModeWins)
       
  2969         return Variable;
       
  2970     else
       
  2971         return d->columnMode;
       
  2972 }
       
  2973 
       
  2974 
       
  2975 /*!
       
  2976     \property Q3ListBox::rowMode
       
  2977     \brief the row layout mode for this list box
       
  2978 
       
  2979     This property is normally \c Variable.
       
  2980 
       
  2981     setRowMode() sets the layout mode and adjusts the number of
       
  2982     displayed rows. The column layout mode automatically becomes \c
       
  2983     Variable, unless the row mode is \c Variable.
       
  2984 
       
  2985     \sa columnMode
       
  2986 */
       
  2987 
       
  2988 
       
  2989 Q3ListBox::LayoutMode Q3ListBox::rowMode() const
       
  2990 {
       
  2991     if (d->rowModeWins)
       
  2992         return d->rowMode;
       
  2993     else
       
  2994         return Variable;
       
  2995 }
       
  2996 
       
  2997 
       
  2998 /*!
       
  2999     \property Q3ListBox::numColumns
       
  3000     \brief the number of columns in the list box
       
  3001 
       
  3002     This is normally 1, but can be different if \l
       
  3003     Q3ListBox::columnMode or \l Q3ListBox::rowMode has been set.
       
  3004 
       
  3005     \sa columnMode rowMode numRows
       
  3006 */
       
  3007 
       
  3008 int Q3ListBox::numColumns() const
       
  3009 {
       
  3010     if (count() == 0)
       
  3011         return 0;
       
  3012     if (!d->rowModeWins && d->columnMode == FixedNumber)
       
  3013         return d->numColumns;
       
  3014     doLayout();
       
  3015     return d->columnPos.size()-1;
       
  3016 }
       
  3017 
       
  3018 
       
  3019 /*!
       
  3020     \property Q3ListBox::numRows
       
  3021     \brief the number of rows in the list box.
       
  3022 
       
  3023     This is equal to the number of items in the default single-column
       
  3024     layout, but can be different.
       
  3025 
       
  3026     \sa columnMode rowMode numColumns
       
  3027 */
       
  3028 
       
  3029 int Q3ListBox::numRows() const
       
  3030 {
       
  3031     if (count() == 0)
       
  3032         return 0;
       
  3033     if (d->rowModeWins && d->rowMode == FixedNumber)
       
  3034         return d->numRows;
       
  3035     doLayout();
       
  3036     return d->rowPos.size()-1;
       
  3037 }
       
  3038 
       
  3039 
       
  3040 /*!
       
  3041     This function does the hard layout work. You should never need to
       
  3042     call it.
       
  3043 */
       
  3044 
       
  3045 void Q3ListBox::doLayout() const
       
  3046 {
       
  3047     if (!d->layoutDirty || d->resizeTimer->isActive())
       
  3048         return;
       
  3049     ensurePolished();
       
  3050     int c = count();
       
  3051     switch(rowMode()) {
       
  3052     case FixedNumber:
       
  3053         // columnMode() is known to be Variable
       
  3054         tryGeometry(d->numRows, (c+d->numRows-1)/d->numRows);
       
  3055         break;
       
  3056     case FitToHeight:
       
  3057         // columnMode() is known to be Variable
       
  3058         if (d->head) {
       
  3059             // this is basically the FitToWidth code, but edited to use rows.
       
  3060             int maxh = 0;
       
  3061             Q3ListBoxItem * i = d->head;
       
  3062             while (i) {
       
  3063                 int h = i->height(this);
       
  3064                 if (maxh < h)
       
  3065                     maxh = h;
       
  3066                 i = i->n;
       
  3067             }
       
  3068             int vh = viewportSize(1, 1).height();
       
  3069             do {
       
  3070                 int rows = vh / maxh;
       
  3071                 if (rows > c)
       
  3072                     rows = c;
       
  3073                 if (rows < 1)
       
  3074                     rows = 1;
       
  3075                 if (variableHeight() && rows < c) {
       
  3076                     do {
       
  3077                         ++rows;
       
  3078                         tryGeometry(rows, (c+rows-1)/rows);
       
  3079                     } while (rows <= c &&
       
  3080                               d->rowPos[(int)d->rowPos.size()-1] <= vh);
       
  3081                     --rows;
       
  3082                 }
       
  3083                 tryGeometry(rows, (c+rows-1)/rows);
       
  3084                 int nvh = viewportSize(d->columnPos[(int)d->columnPos.size()-1],
       
  3085                                         d->rowPos[(int)d->rowPos.size()-1]).height();
       
  3086                 if (nvh < vh)
       
  3087                     vh = nvh;
       
  3088             } while (d->rowPos.size() > 2 &&
       
  3089                       vh < d->rowPos[(int)d->rowPos.size()-1]);
       
  3090         } else {
       
  3091             tryGeometry(1, 1);
       
  3092         }
       
  3093         break;
       
  3094     case Variable:
       
  3095         if (columnMode() == FixedNumber) {
       
  3096             tryGeometry((count()+d->numColumns-1)/d->numColumns,
       
  3097                          d->numColumns);
       
  3098         } else if (d->head) { // FitToWidth, at least one item
       
  3099             int maxw = 0;
       
  3100             Q3ListBoxItem * i = d->head;
       
  3101             while (i) {
       
  3102                 int w = i->width(this);
       
  3103                 if (maxw < w)
       
  3104                     maxw = w;
       
  3105                 i = i->n;
       
  3106             }
       
  3107             int vw = viewportSize(1, 1).width();
       
  3108             do {
       
  3109                 int cols = vw / maxw;
       
  3110                 if (cols > c)
       
  3111                     cols = c;
       
  3112                 if (cols < 1)
       
  3113                     cols = 1;
       
  3114                 if (variableWidth() && cols < c) {
       
  3115                     do {
       
  3116                         ++cols;
       
  3117                         tryGeometry((c+cols-1)/cols, cols);
       
  3118                     } while (cols <= c &&
       
  3119                               d->columnPos[(int)d->columnPos.size()-1] <= vw);
       
  3120                     --cols;
       
  3121                 }
       
  3122                 tryGeometry((c+cols-1)/cols, cols);
       
  3123                 int nvw = viewportSize(d->columnPos[(int)d->columnPos.size()-1],
       
  3124                                         d->rowPos[(int)d->rowPos.size()-1]).width();
       
  3125                 if (nvw < vw)
       
  3126                     vw = nvw;
       
  3127             } while (d->columnPos.size() > 2 &&
       
  3128                       vw < d->columnPos[(int)d->columnPos.size()-1]);
       
  3129         } else {
       
  3130             tryGeometry(1, 1);
       
  3131         }
       
  3132         break;
       
  3133     }
       
  3134 
       
  3135     d->layoutDirty = false;
       
  3136     int w = d->columnPos[(int)d->columnPos.size()-1];
       
  3137     int h = d->rowPos[(int)d->rowPos.size()-1];
       
  3138     QSize s(viewportSize(w, h));
       
  3139     w = qMax(w, s.width());
       
  3140 
       
  3141     d->columnPosOne = d->columnPos[1];
       
  3142     // extend the column for simple single-column listboxes
       
  3143     if (columnMode() == FixedNumber && d->numColumns == 1 &&
       
  3144          d->columnPos[1] < w)
       
  3145         d->columnPos[1] = w;
       
  3146     ((Q3ListBox *)this)->resizeContents(w, h);
       
  3147 }
       
  3148 
       
  3149 
       
  3150 /*!
       
  3151     Lay the items out in a \a columns by \a rows array. The array may
       
  3152     be too big: doLayout() is expected to call this with the right
       
  3153     values.
       
  3154 */
       
  3155 
       
  3156 void Q3ListBox::tryGeometry(int rows, int columns) const
       
  3157 {
       
  3158     if (columns < 1)
       
  3159         columns = 1;
       
  3160     d->columnPos.resize(columns+1);
       
  3161 
       
  3162     if (rows < 1)
       
  3163         rows = 1;
       
  3164     d->rowPos.resize(rows+1);
       
  3165 
       
  3166     // funky hack I: dump the height/width of each column/row in
       
  3167     // {column,row}Pos for later conversion to positions.
       
  3168     int c;
       
  3169     for(c=0; c<=columns; c++)
       
  3170         d->columnPos[c] = 0;
       
  3171     int r;
       
  3172     for(r=0; r<=rows; r++)
       
  3173         d->rowPos[r] = 0;
       
  3174     r = c = 0;
       
  3175     Q3ListBoxItem * i = d->head;
       
  3176     while (i && c < columns) {
       
  3177         if (i == d->current) {
       
  3178             d->currentRow = r;
       
  3179             d->currentColumn = c;
       
  3180         }
       
  3181 
       
  3182         int w = i->width(this);
       
  3183         if (d->columnPos[c] < w)
       
  3184             d->columnPos[c] = w;
       
  3185         int h = i->height(this);
       
  3186         if (d->rowPos[r] < h)
       
  3187             d->rowPos[r] = h;
       
  3188         i = i->n;
       
  3189         r++;
       
  3190         if (r == rows) {
       
  3191             r = 0;
       
  3192             c++;
       
  3193         }
       
  3194     }
       
  3195     // funky hack II: if not variable {width,height}, unvariablify it.
       
  3196     if (!variableWidth()) {
       
  3197         int w = 0;
       
  3198         for(c=0; c<columns; c++)
       
  3199             if (w < d->columnPos[c])
       
  3200                 w = d->columnPos[c];
       
  3201         for(c=0; c<columns; c++)
       
  3202             d->columnPos[c] = w;
       
  3203     }
       
  3204     if (!variableHeight()) {
       
  3205         int h = 0;
       
  3206         for(r=0; r<rows; r++)
       
  3207             if (h < d->rowPos[r])
       
  3208                 h = d->rowPos[r];
       
  3209         for(r=0; r<rows; r++)
       
  3210             d->rowPos[r] = h;
       
  3211     }
       
  3212     // repair the hacking.
       
  3213     int x = 0;
       
  3214     for(c=0; c<=columns; c++) {
       
  3215         int w = d->columnPos[c];
       
  3216         d->columnPos[c] = x;
       
  3217         x += w;
       
  3218     }
       
  3219     int y = 0;
       
  3220     for(r=0; r<=rows; r++) {
       
  3221         int h = d->rowPos[r];
       
  3222         d->rowPos[r] = y;
       
  3223         y += h;
       
  3224     }
       
  3225 }
       
  3226 
       
  3227 
       
  3228 /*!
       
  3229     Returns the row index of the current item, or -1 if no item is the
       
  3230     current item.
       
  3231 */
       
  3232 
       
  3233 int Q3ListBox::currentRow() const
       
  3234 {
       
  3235     if (!d->current)
       
  3236         return -1;
       
  3237     if (d->currentRow < 0)
       
  3238         d->layoutDirty = true;
       
  3239     if (d->layoutDirty)
       
  3240         doLayout();
       
  3241     return d->currentRow;
       
  3242 }
       
  3243 
       
  3244 
       
  3245 /*!
       
  3246     Returns the column index of the current item, or -1 if no item is
       
  3247     the current item.
       
  3248 */
       
  3249 
       
  3250 int Q3ListBox::currentColumn() const
       
  3251 {
       
  3252     if (!d->current)
       
  3253         return -1;
       
  3254     if (d->currentColumn < 0)
       
  3255         d->layoutDirty = true;
       
  3256     if (d->layoutDirty)
       
  3257         doLayout();
       
  3258     return d->currentColumn;
       
  3259 }
       
  3260 
       
  3261 
       
  3262 void Q3ListBox::setTopItem(int index)
       
  3263 {
       
  3264     if (index >= (int)count() || count() == 0)
       
  3265         return;
       
  3266     int col = index / numRows();
       
  3267     int y = d->rowPos[index-col*numRows()];
       
  3268     if (d->columnPos[col] >= contentsX() &&
       
  3269          d->columnPos[col+1] <= contentsX() + visibleWidth())
       
  3270         setContentsPos(contentsX(), y);
       
  3271     else
       
  3272         setContentsPos(d->columnPos[col], y);
       
  3273 }
       
  3274 
       
  3275 /*!
       
  3276     Scrolls the list box so the item at position \a index in the list
       
  3277     is displayed in the bottom row of the list box.
       
  3278 
       
  3279     \sa setTopItem()
       
  3280 */
       
  3281 
       
  3282 void Q3ListBox::setBottomItem(int index)
       
  3283 {
       
  3284     if (index >= (int)count() || count() == 0)
       
  3285         return;
       
  3286     int col = index / numRows();
       
  3287     int y = d->rowPos[1+index-col*numRows()] - visibleHeight();
       
  3288     if (y < 0)
       
  3289         y = 0;
       
  3290     if (d->columnPos[col] >= contentsX() &&
       
  3291          d->columnPos[col+1] <= contentsX() + visibleWidth())
       
  3292         setContentsPos(contentsX(), y);
       
  3293     else
       
  3294         setContentsPos(d->columnPos[col], y);
       
  3295 }
       
  3296 
       
  3297 
       
  3298 /*!
       
  3299     Returns the item at point \a p, specified in viewport coordinates,
       
  3300     or a 0 if there is no item at \a p.
       
  3301 
       
  3302     Use contentsToViewport() to convert between widget coordinates and
       
  3303     viewport coordinates.
       
  3304 */
       
  3305 
       
  3306 Q3ListBoxItem * Q3ListBox::itemAt(const QPoint& p) const
       
  3307 {
       
  3308     if (d->layoutDirty)
       
  3309         doLayout();
       
  3310     QPoint np = p;
       
  3311 
       
  3312     np -= viewport()->pos();
       
  3313     if (!viewport()->rect().contains(np))
       
  3314         return 0;
       
  3315 
       
  3316     // take into account contents position
       
  3317     np = viewportToContents(np);
       
  3318 
       
  3319     int x = np.x();
       
  3320     int y = np.y();
       
  3321 
       
  3322     // return 0 when y is below the last row
       
  3323     if (y > d->rowPos[numRows()])
       
  3324         return 0;
       
  3325 
       
  3326     int col = columnAt(x);
       
  3327     int row = rowAt(y);
       
  3328 
       
  3329     Q3ListBoxItem *i = item(col * numRows()  + row);
       
  3330     if (i && numColumns() > 1) {
       
  3331         if (d->columnPos[col] + i->width(this) >= x)
       
  3332             return i;
       
  3333     } else {
       
  3334         if (d->columnPos[col + 1] >= x)
       
  3335             return i;
       
  3336     }
       
  3337     return 0;
       
  3338 }
       
  3339 
       
  3340 
       
  3341 /*!
       
  3342     Ensures that the current item is visible.
       
  3343 */
       
  3344 
       
  3345 void Q3ListBox::ensureCurrentVisible()
       
  3346 {
       
  3347     if (!d->current)
       
  3348         return;
       
  3349 
       
  3350     doLayout();
       
  3351 
       
  3352     int row = currentRow();
       
  3353     int column = currentColumn();
       
  3354     int w = (d->columnPos[column+1] - d->columnPos[column]) / 2;
       
  3355     int h = (d->rowPos[row+1] - d->rowPos[row]) / 2;
       
  3356     // next four lines are Bad.  they mean that for pure left-to-right
       
  3357     // languages, textual list box items are displayed better than
       
  3358     // before when there is little space.  for non-textual items, or
       
  3359     // other languages, it means... that you really should have enough
       
  3360     // space in the first place :)
       
  3361     if (numColumns() == 1)
       
  3362         w = 0;
       
  3363     if (w*2 > viewport()->width())
       
  3364         w = viewport()->width()/2;
       
  3365 
       
  3366     ensureVisible(d->columnPos[column] + w, d->rowPos[row] + h, w, h);
       
  3367 }
       
  3368 
       
  3369 
       
  3370 /*! \internal */
       
  3371 
       
  3372 void Q3ListBox::doAutoScroll()
       
  3373 {
       
  3374     if (d->scrollPos.x() < 0) {
       
  3375         // scroll left
       
  3376         int x = contentsX() - horizontalScrollBar()->singleStep();
       
  3377         if (x < 0)
       
  3378             x = 0;
       
  3379         if (x != contentsX()) {
       
  3380             d->mouseMoveColumn = columnAt(x);
       
  3381             updateSelection();
       
  3382             if (x < contentsX())
       
  3383                 setContentsPos(x, contentsY());
       
  3384         }
       
  3385     } else if (d->scrollPos.x() > 0) {
       
  3386         // scroll right
       
  3387         int x = contentsX() + horizontalScrollBar()->singleStep();
       
  3388         if (x + visibleWidth() > contentsWidth())
       
  3389             x = contentsWidth() - visibleWidth();
       
  3390         if (x != contentsX()) {
       
  3391             d->mouseMoveColumn = columnAt(x + visibleWidth() - 1);
       
  3392             updateSelection();
       
  3393             if (x > contentsX())
       
  3394                 setContentsPos(x, contentsY());
       
  3395         }
       
  3396     }
       
  3397 
       
  3398     if (d->scrollPos.y() < 0) {
       
  3399         // scroll up
       
  3400         int y = contentsY() - verticalScrollBar()->singleStep();
       
  3401         if (y < 0)
       
  3402             y = 0;
       
  3403         if (y != contentsY()) {
       
  3404             y = contentsY() - verticalScrollBar()->singleStep();
       
  3405             d->mouseMoveRow = rowAt(y);
       
  3406             updateSelection();
       
  3407         }
       
  3408     } else if (d->scrollPos.y() > 0) {
       
  3409         // scroll down
       
  3410         int y = contentsY() + verticalScrollBar()->singleStep();
       
  3411         if (y + visibleHeight() > contentsHeight())
       
  3412             y = contentsHeight() - visibleHeight();
       
  3413         if (y != contentsY()) {
       
  3414             y = contentsY() + verticalScrollBar()->singleStep();
       
  3415             d->mouseMoveRow = rowAt(y + visibleHeight() - 1);
       
  3416             updateSelection();
       
  3417         }
       
  3418     }
       
  3419 
       
  3420     if (d->scrollPos == QPoint(0, 0)) {
       
  3421         delete d->scrollTimer;
       
  3422         d->scrollTimer = 0;
       
  3423     }
       
  3424 }
       
  3425 
       
  3426 
       
  3427 /*!
       
  3428     \property Q3ListBox::topItem
       
  3429     \brief the index of an item at the top of the screen.
       
  3430 
       
  3431     When getting this property and the listbox has multiple columns,
       
  3432     an arbitrary item is selected and returned.
       
  3433 
       
  3434     When setting this property, the list box is scrolled so the item
       
  3435     at position \e index in the list is displayed in the top row of
       
  3436     the list box.
       
  3437 */
       
  3438 
       
  3439 int Q3ListBox::topItem() const
       
  3440 {
       
  3441     doLayout();
       
  3442 
       
  3443     // move rightwards to the best column
       
  3444     int col = columnAt(contentsX());
       
  3445     int row = rowAt(contentsY());
       
  3446     return col * numRows() + row;
       
  3447 }
       
  3448 
       
  3449 
       
  3450 /*!
       
  3451     \property Q3ListBox::variableHeight
       
  3452     \brief whether this list box has variable-height rows
       
  3453 
       
  3454     When the list box has variable-height rows (the default), each row
       
  3455     is as high as the highest item in that row. When it has same-sized
       
  3456     rows, all rows are as high as the highest item in the list box.
       
  3457 
       
  3458     \sa variableWidth
       
  3459 */
       
  3460 
       
  3461 bool Q3ListBox::variableHeight() const
       
  3462 {
       
  3463     return d->variableHeight;
       
  3464 }
       
  3465 
       
  3466 
       
  3467 void Q3ListBox::setVariableHeight(bool enable)
       
  3468 {
       
  3469     if ((bool)d->variableHeight == enable)
       
  3470         return;
       
  3471 
       
  3472     d->variableHeight = enable;
       
  3473     triggerUpdate(true);
       
  3474 }
       
  3475 
       
  3476 
       
  3477 /*!
       
  3478     \property Q3ListBox::variableWidth
       
  3479     \brief whether this list box has variable-width columns
       
  3480 
       
  3481     When the list box has variable-width columns, each column is as
       
  3482     wide as the widest item in that column. When it has same-sized
       
  3483     columns (the default), all columns are as wide as the widest item
       
  3484     in the list box.
       
  3485 
       
  3486     \sa variableHeight
       
  3487 */
       
  3488 
       
  3489 bool Q3ListBox::variableWidth() const
       
  3490 {
       
  3491     return d->variableWidth;
       
  3492 }
       
  3493 
       
  3494 
       
  3495 void Q3ListBox::setVariableWidth(bool enable)
       
  3496 {
       
  3497     if ((bool)d->variableWidth == enable)
       
  3498         return;
       
  3499 
       
  3500     d->variableWidth = enable;
       
  3501     triggerUpdate(true);
       
  3502 }
       
  3503 
       
  3504 
       
  3505 /*!
       
  3506     Repaints only what really needs to be repainted.
       
  3507 */
       
  3508 void Q3ListBox::refreshSlot()
       
  3509 {
       
  3510     if (d->mustPaintAll ||
       
  3511          d->layoutDirty) {
       
  3512         d->mustPaintAll = false;
       
  3513         bool currentItemVisible = itemVisible(currentItem());
       
  3514         doLayout();
       
  3515         if (hasFocus() &&
       
  3516              currentItemVisible &&
       
  3517              d->currentColumn >= 0 &&
       
  3518              d->currentRow >= 0 &&
       
  3519              (d->columnPos[d->currentColumn] < contentsX() ||
       
  3520                d->columnPos[d->currentColumn+1]>contentsX()+visibleWidth() ||
       
  3521                d->rowPos[d->currentRow] < contentsY() ||
       
  3522                d->rowPos[d->currentRow+1] > contentsY()+visibleHeight()))
       
  3523             ensureCurrentVisible();
       
  3524         viewport()->repaint();
       
  3525         return;
       
  3526     }
       
  3527 
       
  3528     QRegion r;
       
  3529     int x = contentsX();
       
  3530     int y = contentsY();
       
  3531     int col = columnAt(x);
       
  3532     int row = rowAt(y);
       
  3533     int top = row;
       
  3534     while(col < (int)d->columnPos.size()-1 && d->columnPos[col+1] < x)
       
  3535         col++;
       
  3536     while(top < (int)d->rowPos.size()-1 && d->rowPos[top+1] < y)
       
  3537         top++;
       
  3538     Q3ListBoxItem * i = item(col * numRows() + row);
       
  3539 
       
  3540     while (i && (int)col < numColumns() &&
       
  3541             d->columnPos[col] < x + visibleWidth() ) {
       
  3542         int cw = d->columnPos[col+1] - d->columnPos[col];
       
  3543         while (i && row < numRows() && d->rowPos[row] <
       
  3544                 y + visibleHeight()) {
       
  3545             if (i->dirty)
       
  3546                 r = r.united(QRect(d->columnPos[col] - x, d->rowPos[row] - y,
       
  3547                                    cw, d->rowPos[row+1] - d->rowPos[row]));
       
  3548             row++;
       
  3549             i = i->n;
       
  3550         }
       
  3551         col++;
       
  3552         if (numColumns() > 1) {
       
  3553             row = top;
       
  3554             i = item(col *  numRows() + row);
       
  3555         }
       
  3556     }
       
  3557 
       
  3558     if (r.isEmpty())
       
  3559         viewport()->repaint();
       
  3560     else
       
  3561         viewport()->repaint(r);
       
  3562 }
       
  3563 
       
  3564 
       
  3565 /*! \reimp */
       
  3566 
       
  3567 void Q3ListBox::viewportPaintEvent(QPaintEvent * e)
       
  3568 {
       
  3569     doLayout();
       
  3570     QWidget* vp = viewport();
       
  3571     QPainter p(vp);
       
  3572     QRegion r = e->region();
       
  3573 
       
  3574 #if 0
       
  3575     {
       
  3576         // this stuff has been useful enough times that from now I'm
       
  3577         //  leaving it in the source.
       
  3578         uint i = 0;
       
  3579         qDebug("%s/%s: %i rects", className(), name(), r.rects().size());
       
  3580         while(i < r.rects().size()) {
       
  3581             qDebug("rect %d: %d, %d, %d, %d", i,
       
  3582                    r.rects()[i].left(), r.rects()[i].top(),
       
  3583                    r.rects()[i].width(), r.rects()[i].height());
       
  3584             i++;
       
  3585         }
       
  3586         qDebug("");
       
  3587     }
       
  3588 #endif
       
  3589 
       
  3590     int x = contentsX();
       
  3591     int y = contentsY();
       
  3592     int w = vp->width();
       
  3593     int h = vp->height();
       
  3594 
       
  3595     int col = columnAt(x);
       
  3596     int top = rowAt(y);
       
  3597     int row = top;
       
  3598 
       
  3599     Q3ListBoxItem * i = item(col*numRows() + row);
       
  3600 
       
  3601     const QPalette &pal = palette();
       
  3602     p.setPen(pal.text().color());
       
  3603     p.setBackground(palette().brush(backgroundRole()).color());
       
  3604     while (i && (int)col < numColumns() && d->columnPos[col] < x + w) {
       
  3605         int cw = d->columnPos[col+1] - d->columnPos[col];
       
  3606         while (i && (int)row < numRows() && d->rowPos[row] < y + h) {
       
  3607             int ch = d->rowPos[row+1] - d->rowPos[row];
       
  3608             QRect itemRect(d->columnPos[col]-x, d->rowPos[row]-y, cw, ch);
       
  3609             QRegion tempRegion(itemRect);
       
  3610             QRegion itemPaintRegion(tempRegion.intersected(r ));
       
  3611             if (!itemPaintRegion.isEmpty()) {
       
  3612                 p.save();
       
  3613                 p.setClipRegion(itemPaintRegion);
       
  3614                 p.translate(d->columnPos[col]-x, d->rowPos[row]-y);
       
  3615                 paintCell(&p, row, col);
       
  3616                 p.restore();
       
  3617                 r = r.subtracted(itemPaintRegion);
       
  3618             }
       
  3619             row++;
       
  3620             if (i->dirty) {
       
  3621                 // reset dirty flag only if the entire item was painted
       
  3622                 if (itemPaintRegion == QRegion(itemRect))
       
  3623                     i->dirty = false;
       
  3624             }
       
  3625             i = i->n;
       
  3626         }
       
  3627         col++;
       
  3628         if (numColumns() > 1) {
       
  3629             row = top;
       
  3630             i = item(col *  numRows() + row);
       
  3631         }
       
  3632     }
       
  3633 
       
  3634     if (r.isEmpty())
       
  3635         return;
       
  3636     p.setClipRegion(r);
       
  3637     p.fillRect(0, 0, w, h, viewport()->palette().brush(viewport()->backgroundRole()));
       
  3638 
       
  3639     if(d->rubber && d->rubber->width() && d->rubber->height()) {
       
  3640         p.save();
       
  3641         p.setClipping(false);
       
  3642         // p.setRasterOp(NotROP); // ### fix - use qrubberband instead
       
  3643         QStyleOptionRubberBand opt;
       
  3644         opt.rect = d->rubber->normalized();
       
  3645         opt.palette = palette();
       
  3646         opt.shape = QRubberBand::Rectangle;
       
  3647         opt.opaque = false;
       
  3648         style()->drawControl(QStyle::CE_RubberBand, &opt, &p, this);
       
  3649         p.restore();
       
  3650     }
       
  3651 }
       
  3652 
       
  3653 
       
  3654 /*!
       
  3655     Returns the height in pixels of the item with index \a index. \a
       
  3656     index defaults to 0.
       
  3657 
       
  3658     If \a index is too large, this function returns 0.
       
  3659 */
       
  3660 
       
  3661 int Q3ListBox::itemHeight(int index) const
       
  3662 {
       
  3663     if (index >= (int)count() || index < 0)
       
  3664         return 0;
       
  3665     int r = index % numRows();
       
  3666     return d->rowPos[r+1] - d->rowPos[r];
       
  3667 }
       
  3668 
       
  3669 
       
  3670 /*!
       
  3671     Returns the index of the column at \a x, which is in the listbox's
       
  3672     coordinates, not in on-screen coordinates.
       
  3673 
       
  3674     If there is no column that spans \a x, columnAt() returns -1.
       
  3675 */
       
  3676 
       
  3677 int Q3ListBox::columnAt(int x) const
       
  3678 {
       
  3679     if (x < 0)
       
  3680         return -1;
       
  3681     if (!d->columnPos.size())
       
  3682         return -1;
       
  3683     if (x >= d->columnPos[(int)d->columnPos.size()-1])
       
  3684         return numColumns() - 1;
       
  3685 
       
  3686     int col = 0;
       
  3687     while(col < (int)d->columnPos.size()-1 && d->columnPos[col+1] < x)
       
  3688         col++;
       
  3689     return col;
       
  3690 }
       
  3691 
       
  3692 
       
  3693 /*!
       
  3694     Returns the index of the row at \a y, which is in the listbox's
       
  3695     coordinates, not in on-screen coordinates.
       
  3696 
       
  3697     If there is no row that spans \a y, rowAt() returns -1.
       
  3698 */
       
  3699 
       
  3700 int Q3ListBox::rowAt(int y) const
       
  3701 {
       
  3702     if (y < 0)
       
  3703         return -1;
       
  3704 
       
  3705     // find the top item, use bsearch for speed
       
  3706     int l = 0;
       
  3707     int r = d->rowPos.size() - 2;
       
  3708     if (r < 0)
       
  3709         return -1;
       
  3710     if (l <= d->rowPosCache && d->rowPosCache <= r) {
       
  3711         if (d->rowPos[qMax(l, d->rowPosCache - 10)] <= y
       
  3712              && y <= d->rowPos[qMin(r, d->rowPosCache + 10)]) {
       
  3713             l = qMax(l, d->rowPosCache - 10);
       
  3714             r = qMin(r, d->rowPosCache + 10);
       
  3715         }
       
  3716     }
       
  3717     int i = ((l+r+1) / 2);
       
  3718     while (r - l) {
       
  3719         if (d->rowPos[i] > y)
       
  3720             r = i -1;
       
  3721         else
       
  3722             l = i;
       
  3723         i = ((l+r+1) / 2);
       
  3724     }
       
  3725     d->rowPosCache = i;
       
  3726     if (d->rowPos[i] <= y && y <= d->rowPos[i+1] )
       
  3727         return  i;
       
  3728 
       
  3729     return d->count - 1;
       
  3730 }
       
  3731 
       
  3732 
       
  3733 /*!
       
  3734     Returns the rectangle on the screen that \a item occupies in
       
  3735     viewport()'s coordinates, or an invalid rectangle if \a item is 0
       
  3736     or is not currently visible.
       
  3737 */
       
  3738 
       
  3739 QRect Q3ListBox::itemRect(Q3ListBoxItem *item) const
       
  3740 {
       
  3741     if (d->resizeTimer->isActive())
       
  3742         return QRect(0, 0, -1, -1);
       
  3743     if (!item)
       
  3744         return QRect(0, 0, -1, -1);
       
  3745 
       
  3746     int i = index(item);
       
  3747     if (i == -1)
       
  3748         return QRect(0, 0, -1, -1);
       
  3749     
       
  3750     int col = i / numRows();
       
  3751     int row = i % numRows();
       
  3752 
       
  3753     int x = d->columnPos[col] - contentsX();
       
  3754     int y = d->rowPos[row] - contentsY();
       
  3755 
       
  3756     QRect r(x, y, d->columnPos[col + 1] - d->columnPos[col],
       
  3757                   d->rowPos[row + 1] - d->rowPos[row]);
       
  3758     if (r.intersects(QRect(0, 0, visibleWidth(), visibleHeight())))
       
  3759         return r;
       
  3760     return QRect(0, 0, -1, -1);
       
  3761 }
       
  3762 
       
  3763 
       
  3764 /*!
       
  3765   Using this method is quite inefficient. We suggest to use insertItem()
       
  3766   for inserting and sort() afterwards.
       
  3767 
       
  3768   Inserts \a lbi at its sorted position in the list box and returns the
       
  3769   position.
       
  3770 
       
  3771   All items must be inserted with inSort() to maintain the sorting
       
  3772   order. inSort() treats any pixmap (or user-defined type) as
       
  3773   lexicographically less than any string.
       
  3774 
       
  3775   \sa insertItem(), sort()
       
  3776 */
       
  3777 int Q3ListBox::inSort(const Q3ListBoxItem * lbi)
       
  3778 {
       
  3779     if (!lbi)
       
  3780         return -1;
       
  3781 
       
  3782     Q3ListBoxItem * i = d->head;
       
  3783     int c = 0;
       
  3784 
       
  3785     while(i && i->text() < lbi->text()) {
       
  3786         i = i->n;
       
  3787         c++;
       
  3788     }
       
  3789     insertItem(lbi, c);
       
  3790     return c;
       
  3791 }
       
  3792 
       
  3793 /*!
       
  3794   \overload
       
  3795   Using this method is quite inefficient. We suggest to use insertItem()
       
  3796   for inserting and sort() afterwards.
       
  3797 
       
  3798   Inserts a new item of \a text at its sorted position in the list box and
       
  3799   returns the position.
       
  3800 
       
  3801   All items must be inserted with inSort() to maintain the sorting
       
  3802   order. inSort() treats any pixmap (or user-defined type) as
       
  3803   lexicographically less than any string.
       
  3804 
       
  3805   \sa insertItem(), sort()
       
  3806 */
       
  3807 int Q3ListBox::inSort(const QString& text)
       
  3808 {
       
  3809     Q3ListBoxItem *lbi = new Q3ListBoxText(text);
       
  3810 
       
  3811     Q3ListBoxItem * i = d->head;
       
  3812     int c = 0;
       
  3813 
       
  3814     while(i && i->text() < lbi->text()) {
       
  3815         i = i->n;
       
  3816         c++;
       
  3817     }
       
  3818     insertItem(lbi, c);
       
  3819     return c;
       
  3820 }
       
  3821 
       
  3822 
       
  3823 /*! \reimp */
       
  3824 
       
  3825 void Q3ListBox::resizeEvent(QResizeEvent *e)
       
  3826 {
       
  3827     d->layoutDirty = (d->layoutDirty ||
       
  3828                        rowMode() == FitToHeight ||
       
  3829                        columnMode() == FitToWidth);
       
  3830 
       
  3831     if (!d->layoutDirty && columnMode() == FixedNumber &&
       
  3832          d->numColumns == 1) {
       
  3833         int w = d->columnPosOne;
       
  3834         QSize s(viewportSize(w, contentsHeight()));
       
  3835         w = qMax(w, s.width());
       
  3836         d->columnPos[1] = qMax(w, d->columnPosOne);
       
  3837         resizeContents(d->columnPos[1], contentsHeight());
       
  3838     }
       
  3839 
       
  3840     if (d->resizeTimer->isActive())
       
  3841         d->resizeTimer->stop();
       
  3842     if (d->rowMode == FixedNumber && d->columnMode == FixedNumber) {
       
  3843         bool currentItemVisible = itemVisible(currentItem());
       
  3844         doLayout();
       
  3845         Q3ScrollView::resizeEvent(e);
       
  3846         if (currentItemVisible)
       
  3847             ensureCurrentVisible();
       
  3848         if (d->current)
       
  3849             viewport()->repaint(itemRect(d->current));
       
  3850     } else if ((d->columnMode == FitToWidth || d->rowMode == FitToHeight) && !(isVisible())) {
       
  3851         Q3ScrollView::resizeEvent(e);
       
  3852     } else if (d->layoutDirty) {
       
  3853         d->resizeTimer->start(100, true);
       
  3854         resizeContents(contentsWidth() - (e->oldSize().width() - e->size().width()),
       
  3855                         contentsHeight() - (e->oldSize().height() - e->size().height()));
       
  3856         Q3ScrollView::resizeEvent(e);
       
  3857     } else {
       
  3858         Q3ScrollView::resizeEvent(e);
       
  3859     }
       
  3860 }
       
  3861 
       
  3862 /*!
       
  3863   \internal
       
  3864 */
       
  3865 
       
  3866 void Q3ListBox::adjustItems()
       
  3867 {
       
  3868     triggerUpdate(true);
       
  3869     ensureCurrentVisible();
       
  3870 }
       
  3871 
       
  3872 
       
  3873 /*!
       
  3874     Provided for compatibility with the old Q3ListBox. We recommend
       
  3875     using Q3ListBoxItem::paint() instead.
       
  3876 
       
  3877     Repaints the cell at \a row, \a col using painter \a p.
       
  3878 */
       
  3879 
       
  3880 void Q3ListBox::paintCell(QPainter * p, int row, int col)
       
  3881 {
       
  3882     bool drawActiveSelection = hasFocus() || d->inMenuMode ||
       
  3883         !style()->styleHint(QStyle::SH_ItemView_ChangeHighlightOnFocus, 0, this);
       
  3884     QPalette pal = palette();
       
  3885     if(!drawActiveSelection)
       
  3886         pal.setCurrentColorGroup(QPalette::Inactive);
       
  3887 
       
  3888     int cw = d->columnPos[col+1] - d->columnPos[col];
       
  3889     int ch = d->rowPos[row+1] - d->rowPos[row];
       
  3890     Q3ListBoxItem * i = item(col*numRows()+row);
       
  3891     p->save();
       
  3892     if (i->s) {
       
  3893         if (i->custom_highlight) {
       
  3894             p->fillRect(0, 0, cw, ch, pal.brush(viewport()->foregroundRole()));
       
  3895             p->setPen(pal.highlightedText().color());
       
  3896             p->setBackground(pal.highlight());
       
  3897         } else if (numColumns()  == 1) {
       
  3898             p->fillRect(0, 0, cw, ch, pal.brush(QPalette::Highlight));
       
  3899             p->setPen(pal.highlightedText().color());
       
  3900             p->setBackground(pal.highlight());
       
  3901         } else {
       
  3902             int iw = i->width(this);
       
  3903             p->fillRect(0, 0, iw, ch, pal.brush(QPalette::Highlight));
       
  3904             p->fillRect(iw, 0, cw - iw + 1, ch, viewport()->palette().brush(viewport()->backgroundRole()));
       
  3905             p->setPen(pal.highlightedText().color());
       
  3906             p->setBackground(pal.highlight());
       
  3907         }
       
  3908     } else {
       
  3909         p->fillRect(0, 0, cw, ch, viewport()->palette().brush(viewport()->backgroundRole()));
       
  3910     }
       
  3911 
       
  3912     i->paint(p);
       
  3913 
       
  3914     if (d->current == i && hasFocus() && !i->custom_highlight) {
       
  3915         if (numColumns() > 1)
       
  3916             cw = i->width(this);
       
  3917         QStyleOptionFocusRect opt;
       
  3918         opt.rect.setRect(0, 0, cw, ch);
       
  3919         opt.palette = pal;
       
  3920         opt.state = QStyle::State_FocusAtBorder;
       
  3921         if (i->isSelected())
       
  3922             opt.backgroundColor = pal.highlight().color();
       
  3923         else
       
  3924             opt.backgroundColor = pal.base().color();
       
  3925         style()->drawPrimitive(QStyle::PE_FrameFocusRect, &opt, p, this);
       
  3926     }
       
  3927 
       
  3928     p->restore();
       
  3929 }
       
  3930 
       
  3931 /*!
       
  3932     Returns the width of the widest item in the list box.
       
  3933 */
       
  3934 
       
  3935 long Q3ListBox::maxItemWidth() const
       
  3936 {
       
  3937     if (d->layoutDirty)
       
  3938         doLayout();
       
  3939     long m = 0;
       
  3940     int i = d->columnPos.size();
       
  3941     while(i--)
       
  3942         if (m < d->columnPos[i])
       
  3943             m = d->columnPos[i];
       
  3944     return m;
       
  3945 }
       
  3946 
       
  3947 
       
  3948 /*! \reimp */
       
  3949 
       
  3950 void Q3ListBox::showEvent(QShowEvent *)
       
  3951 {
       
  3952     d->ignoreMoves = false;
       
  3953     d->mousePressRow = -1;
       
  3954     d->mousePressColumn = -1;
       
  3955     d->mustPaintAll = false;
       
  3956     ensureCurrentVisible();
       
  3957 }
       
  3958 
       
  3959 /*!
       
  3960     \fn bool Q3ListBoxItem::isSelected() const
       
  3961 
       
  3962     Returns true if the item is selected; otherwise returns false.
       
  3963 
       
  3964     \sa Q3ListBox::isSelected(), isCurrent()
       
  3965 */
       
  3966 
       
  3967 /*!
       
  3968     Returns true if the item is the current item; otherwise returns
       
  3969     false.
       
  3970 
       
  3971     \sa Q3ListBox::currentItem(), Q3ListBox::item(), isSelected()
       
  3972 */
       
  3973 bool Q3ListBoxItem::isCurrent() const
       
  3974 {
       
  3975     return listBox() && listBox()->hasFocus() &&
       
  3976         listBox()->item(listBox()->currentItem()) == this;
       
  3977 }
       
  3978 
       
  3979 /*!
       
  3980     \fn void Q3ListBox::centerCurrentItem()
       
  3981 
       
  3982     If there is a current item, the list box is scrolled so that this
       
  3983     item is displayed centered.
       
  3984 
       
  3985     \sa Q3ListBox::ensureCurrentVisible()
       
  3986 */
       
  3987 
       
  3988 /*!
       
  3989     Returns a pointer to the list box containing this item.
       
  3990 */
       
  3991 
       
  3992 Q3ListBox * Q3ListBoxItem::listBox() const
       
  3993 {
       
  3994     return lbox;
       
  3995 }
       
  3996 
       
  3997 
       
  3998 /*!
       
  3999     Removes \a item from the list box and causes an update of the
       
  4000     screen display. The item is not deleted. You should normally not
       
  4001     need to call this function because Q3ListBoxItem::~Q3ListBoxItem()
       
  4002     calls it. The normal way to delete an item is with \c delete.
       
  4003 
       
  4004     \sa Q3ListBox::insertItem()
       
  4005 */
       
  4006 void Q3ListBox::takeItem(const Q3ListBoxItem * item)
       
  4007 {
       
  4008     if (!item || d->clearing)
       
  4009         return;
       
  4010     d->cache = 0;
       
  4011     d->count--;
       
  4012     if (item == d->last)
       
  4013         d->last = d->last->p;
       
  4014     if (item->p && item->p->n == item)
       
  4015         item->p->n = item->n;
       
  4016     if (item->n && item->n->p == item)
       
  4017         item->n->p = item->p;
       
  4018     if (d->head == item) {
       
  4019         d->head = item->n;
       
  4020         d->currentColumn = d->currentRow = -1;
       
  4021     }
       
  4022 
       
  4023     if (d->current == item) {
       
  4024         d->current = item->n ? item->n : item->p;
       
  4025         Q3ListBoxItem *i = d->current;
       
  4026         QString tmp;
       
  4027         if (i)
       
  4028             tmp = i->text();
       
  4029         int tmp2 = index(i);
       
  4030         emit highlighted(i);
       
  4031         if (!tmp.isNull())
       
  4032             emit highlighted(tmp);
       
  4033         emit highlighted(tmp2);
       
  4034         emit currentChanged(i);
       
  4035     }
       
  4036     if (d->tmpCurrent == item)
       
  4037         d->tmpCurrent = d->current;
       
  4038     if (d->selectAnchor == item)
       
  4039         d->selectAnchor = d->current;
       
  4040 
       
  4041     if (item->s)
       
  4042         emit selectionChanged();
       
  4043     ((Q3ListBoxItem *)item)->lbox = 0;
       
  4044     triggerUpdate(true);
       
  4045 }
       
  4046 
       
  4047 /*!
       
  4048   \internal
       
  4049   Finds the next item after start beginning with \a text.
       
  4050 */
       
  4051 
       
  4052 int Q3ListBoxPrivate::findItemByName(int start, const QString &text)
       
  4053 {
       
  4054     if (start < 0 || (uint)start >= listBox->count())
       
  4055         start = 0;
       
  4056     QString match = text.toLower();
       
  4057     if (match.length() < 1)
       
  4058         return start;
       
  4059     QString curText;
       
  4060     int item = start;
       
  4061     do {
       
  4062         curText = listBox->text(item).toLower();
       
  4063         if (curText.startsWith(match))
       
  4064             return item;
       
  4065         item++;
       
  4066         if ((uint)item == listBox->count())
       
  4067             item = 0;
       
  4068     } while (item != start);
       
  4069     return -1;
       
  4070 }
       
  4071 
       
  4072 /*!
       
  4073   \internal
       
  4074 */
       
  4075 
       
  4076 void Q3ListBox::clearInputString()
       
  4077 {
       
  4078     d->currInputString.clear();
       
  4079 }
       
  4080 
       
  4081 /*!
       
  4082     Finds the first list box item that has the text \a text and
       
  4083     returns it, or returns 0 of no such item could be found. If \c
       
  4084     ComparisonFlags are specified in \a compare then these flags
       
  4085     are used, otherwise the default is a case-insensitive, "begins
       
  4086     with" search.
       
  4087 */
       
  4088 
       
  4089 Q3ListBoxItem *Q3ListBox::findItem(const QString &text, ComparisonFlags compare) const
       
  4090 {
       
  4091     if (text.isEmpty())
       
  4092         return 0;
       
  4093 
       
  4094     if (compare == CaseSensitive || compare == 0)
       
  4095         compare |= ExactMatch;
       
  4096 
       
  4097     QString itmtxt;
       
  4098     QString comtxt = text;
       
  4099     if (!(compare & CaseSensitive))
       
  4100         comtxt = text.toLower();
       
  4101 
       
  4102     Q3ListBoxItem *item;
       
  4103     if (d->current)
       
  4104         item = d->current;
       
  4105     else
       
  4106         item = d->head;
       
  4107 
       
  4108     Q3ListBoxItem *beginsWithItem = 0;
       
  4109     Q3ListBoxItem *endsWithItem = 0;
       
  4110     Q3ListBoxItem *containsItem = 0;
       
  4111 
       
  4112     if (item) {
       
  4113         for (; item; item = item->n) {
       
  4114             if (!(compare & CaseSensitive))
       
  4115                 itmtxt = item->text().toLower();
       
  4116             else
       
  4117                 itmtxt = item->text();
       
  4118 
       
  4119             if ((compare & ExactMatch)==ExactMatch && itmtxt == comtxt)
       
  4120                 return item;
       
  4121             if (compare & BeginsWith && !beginsWithItem && itmtxt.startsWith(comtxt))
       
  4122                 beginsWithItem = containsItem = item;
       
  4123             if (compare & EndsWith && !endsWithItem && itmtxt.endsWith(comtxt))
       
  4124                 endsWithItem = containsItem = item;
       
  4125             if ((compare & ExactMatch)==0 && !containsItem && itmtxt.contains(comtxt))
       
  4126                 containsItem = item;
       
  4127         }
       
  4128 
       
  4129         if (d->current && d->head) {
       
  4130             item = d->head;
       
  4131             for (; item && item != d->current; item = item->n) {
       
  4132                 if (!(compare & CaseSensitive))
       
  4133                     itmtxt = item->text().toLower();
       
  4134                 else
       
  4135                     itmtxt = item->text();
       
  4136 
       
  4137                 if ((compare & ExactMatch)==ExactMatch && itmtxt == comtxt)
       
  4138                     return item;
       
  4139                 if (compare & BeginsWith && !beginsWithItem && itmtxt.startsWith(comtxt))
       
  4140                     beginsWithItem = containsItem = item;
       
  4141                 if (compare & EndsWith && !endsWithItem && itmtxt.endsWith(comtxt))
       
  4142                     endsWithItem = containsItem = item;
       
  4143                 if ((compare & ExactMatch)==0 && !containsItem && itmtxt.contains(comtxt))
       
  4144                     containsItem = item;
       
  4145             }
       
  4146         }
       
  4147     }
       
  4148 
       
  4149     // Obey the priorities
       
  4150     if (beginsWithItem)
       
  4151         return beginsWithItem;
       
  4152     else if (endsWithItem)
       
  4153         return endsWithItem;
       
  4154     else if (containsItem)
       
  4155         return containsItem;
       
  4156     return 0;
       
  4157 }
       
  4158 
       
  4159 /*!
       
  4160   \internal
       
  4161 */
       
  4162 
       
  4163 void Q3ListBox::drawRubber()
       
  4164 {
       
  4165     if (!d->rubber)
       
  4166         return;
       
  4167     if (!d->rubber->width() && !d->rubber->height())
       
  4168         return;
       
  4169     update();
       
  4170 }
       
  4171 
       
  4172 /*!
       
  4173   \internal
       
  4174 */
       
  4175 
       
  4176 void Q3ListBox::doRubberSelection(const QRect &old, const QRect &rubber)
       
  4177 {
       
  4178     Q3ListBoxItem *i = d->head;
       
  4179     QRect ir, pr;
       
  4180     bool changed = false;
       
  4181     for (; i; i = i->n) {
       
  4182         ir = itemRect(i);
       
  4183         if (ir == QRect(0, 0, -1, -1))
       
  4184             continue;
       
  4185         if (i->isSelected() && !ir.intersects(rubber) && ir.intersects(old)) {
       
  4186             i->s = false;
       
  4187             pr = pr.united(ir);
       
  4188             changed = true;
       
  4189         } else if (!i->isSelected() && ir.intersects(rubber)) {
       
  4190             if (i->isSelectable()) {
       
  4191                 i->s = true;
       
  4192                 pr = pr.united(ir);
       
  4193                 changed = true;
       
  4194             }
       
  4195         }
       
  4196     }
       
  4197     if (changed) {
       
  4198         emit selectionChanged();
       
  4199 #ifndef QT_NO_ACCESSIBILITY
       
  4200         QAccessible::updateAccessibility(viewport(), 0, QAccessible::Selection);
       
  4201 #endif
       
  4202     }
       
  4203     viewport()->repaint(pr);
       
  4204 }
       
  4205 
       
  4206 
       
  4207 /*!
       
  4208     Returns true if the user is selecting items using a rubber band
       
  4209     rectangle; otherwise returns false.
       
  4210 */
       
  4211 
       
  4212 bool Q3ListBox::isRubberSelecting() const
       
  4213 {
       
  4214     return d->rubber != 0;
       
  4215 }
       
  4216 
       
  4217 
       
  4218 /*!
       
  4219     Returns the item that comes after this in the list box. If this is
       
  4220     the last item, 0 is returned.
       
  4221 
       
  4222     \sa prev()
       
  4223 */
       
  4224 
       
  4225 Q3ListBoxItem *Q3ListBoxItem::next() const
       
  4226 {
       
  4227     return n;
       
  4228 }
       
  4229 
       
  4230 /*!
       
  4231     Returns the item which comes before this in the list box. If this
       
  4232     is the first item, 0 is returned.
       
  4233 
       
  4234     \sa next()
       
  4235 */
       
  4236 
       
  4237 Q3ListBoxItem *Q3ListBoxItem::prev() const
       
  4238 {
       
  4239     return p;
       
  4240 }
       
  4241 
       
  4242 /*!
       
  4243     Returns the first item in this list box. If the list box is empty,
       
  4244     returns 0.
       
  4245 */
       
  4246 
       
  4247 Q3ListBoxItem *Q3ListBox::firstItem() const
       
  4248 {
       
  4249     return d->head;
       
  4250 }
       
  4251 
       
  4252 #if defined(Q_C_CALLBACKS)
       
  4253 extern "C" {
       
  4254 #endif
       
  4255 
       
  4256 #ifdef Q_OS_WINCE
       
  4257 static int _cdecl cmpListBoxItems(const void *n1, const void *n2)
       
  4258 #else
       
  4259 static int cmpListBoxItems(const void *n1, const void *n2)
       
  4260 #endif
       
  4261 {
       
  4262     if (!n1 || !n2)
       
  4263         return 0;
       
  4264 
       
  4265     Q3ListBoxPrivate::SortableItem *i1 = (Q3ListBoxPrivate::SortableItem *)n1;
       
  4266     Q3ListBoxPrivate::SortableItem *i2 = (Q3ListBoxPrivate::SortableItem *)n2;
       
  4267 
       
  4268     return i1->item->text().localeAwareCompare(i2->item->text());
       
  4269 }
       
  4270 
       
  4271 #if defined(Q_C_CALLBACKS)
       
  4272 }
       
  4273 #endif
       
  4274 
       
  4275 /*!
       
  4276     If \a ascending is true sorts the items in ascending order;
       
  4277     otherwise sorts in descending order.
       
  4278 
       
  4279     To compare the items, the text (Q3ListBoxItem::text()) of the items
       
  4280     is used.
       
  4281 */
       
  4282 
       
  4283 void Q3ListBox::sort(bool ascending)
       
  4284 {
       
  4285     if (count() == 0)
       
  4286         return;
       
  4287 
       
  4288     d->cache = 0;
       
  4289 
       
  4290     Q3ListBoxPrivate::SortableItem *items = new Q3ListBoxPrivate::SortableItem[count()];
       
  4291 
       
  4292     Q3ListBoxItem *item = d->head;
       
  4293     int i = 0;
       
  4294     for (; item; item = item->n)
       
  4295         items[i++].item = item;
       
  4296 
       
  4297     qsort(items, count(), sizeof(Q3ListBoxPrivate::SortableItem), cmpListBoxItems);
       
  4298 
       
  4299     Q3ListBoxItem *prev = 0;
       
  4300     item = 0;
       
  4301     if (ascending) {
       
  4302         for (i = 0; i < (int)count(); ++i) {
       
  4303             item = items[i].item;
       
  4304             if (item) {
       
  4305                 item->p = prev;
       
  4306                 item->dirty = true;
       
  4307                 if (item->p)
       
  4308                     item->p->n = item;
       
  4309                 item->n = 0;
       
  4310             }
       
  4311             if (i == 0)
       
  4312                 d->head = item;
       
  4313             prev = item;
       
  4314         }
       
  4315     } else {
       
  4316         for (i = (int)count() - 1; i >= 0 ; --i) {
       
  4317             item = items[i].item;
       
  4318             if (item) {
       
  4319                 item->p = prev;
       
  4320                 item->dirty = true;
       
  4321                 if (item->p)
       
  4322                     item->p->n = item;
       
  4323                 item->n = 0;
       
  4324             }
       
  4325             if (i == (int)count() - 1)
       
  4326                 d->head = item;
       
  4327             prev = item;
       
  4328         }
       
  4329     }
       
  4330     d->last = item;
       
  4331 
       
  4332     delete [] items;
       
  4333 
       
  4334     // We have to update explicitly in case the current "vieport" overlaps the
       
  4335     // new viewport we set (starting at (0,0)).
       
  4336     bool haveToUpdate = contentsX() < visibleWidth() || contentsY() < visibleHeight();
       
  4337     setContentsPos(0, 0);
       
  4338     if (haveToUpdate)
       
  4339         updateContents(0, 0, visibleWidth(), visibleHeight());
       
  4340 }
       
  4341 
       
  4342 void Q3ListBox::handleItemChange(Q3ListBoxItem *old, bool shift, bool control)
       
  4343 {
       
  4344     if (d->selectionMode == Single) {
       
  4345         // nothing
       
  4346     } else if (d->selectionMode == Extended) {
       
  4347         if (shift) {
       
  4348             selectRange(d->selectAnchor ? d->selectAnchor : old,
       
  4349                          d->current, false, true, (d->selectAnchor && !control) ? true : false);
       
  4350         } else if (!control) {
       
  4351             bool block = signalsBlocked();
       
  4352             blockSignals(true);
       
  4353             selectAll(false);
       
  4354             blockSignals(block);
       
  4355             setSelected(d->current, true);
       
  4356         }
       
  4357     } else if (d->selectionMode == Multi) {
       
  4358         if (shift)
       
  4359             selectRange(old, d->current, true, false);
       
  4360     }
       
  4361 }
       
  4362 
       
  4363 void Q3ListBox::selectRange(Q3ListBoxItem *from, Q3ListBoxItem *to, bool invert, bool includeFirst, bool clearSel)
       
  4364 {
       
  4365     if (!from || !to)
       
  4366         return;
       
  4367     if (from == to && !includeFirst)
       
  4368         return;
       
  4369     Q3ListBoxItem *i = 0;
       
  4370     int index =0;
       
  4371     int f_idx = -1, t_idx = -1;
       
  4372     for (i = d->head; i; i = i->n, index++) {
       
  4373         if (i == from)
       
  4374             f_idx = index;
       
  4375         if (i == to)
       
  4376             t_idx = index;
       
  4377         if (f_idx != -1 && t_idx != -1)
       
  4378             break;
       
  4379     }
       
  4380     if (f_idx > t_idx) {
       
  4381         i = from;
       
  4382         from = to;
       
  4383         to = i;
       
  4384         if (!includeFirst)
       
  4385             to = to->prev();
       
  4386     } else {
       
  4387         if (!includeFirst)
       
  4388             from = from->next();
       
  4389     }
       
  4390 
       
  4391     bool changed = false;
       
  4392     if (clearSel) {
       
  4393         for (i = d->head; i && i != from; i = i->n) {
       
  4394             if (i->s) {
       
  4395                 i->s = false;
       
  4396                 changed = true;
       
  4397                 updateItem(i);
       
  4398             }
       
  4399         }
       
  4400         for (i = to->n; i; i = i->n) {
       
  4401             if (i->s) {
       
  4402                 i->s = false;
       
  4403                 changed = true;
       
  4404                 updateItem(i);
       
  4405             }
       
  4406         }
       
  4407     }
       
  4408 
       
  4409     for (i = from; i; i = i->next()) {
       
  4410         if (!invert) {
       
  4411             if (!i->s && i->isSelectable()) {
       
  4412                 i->s = true;
       
  4413                 changed = true;
       
  4414                 updateItem(i);
       
  4415             }
       
  4416         } else {
       
  4417             bool sel = !i->s;
       
  4418             if (((bool)i->s != sel && sel && i->isSelectable()) || !sel) {
       
  4419                 i->s = sel;
       
  4420                 changed = true;
       
  4421                 updateItem(i);
       
  4422             }
       
  4423         }
       
  4424         if (i == to)
       
  4425             break;
       
  4426     }
       
  4427     if (changed) {
       
  4428         emit selectionChanged();
       
  4429 #ifndef QT_NO_ACCESSIBILITY
       
  4430         QAccessible::updateAccessibility(viewport(), 0, QAccessible::Selection);
       
  4431 #endif
       
  4432     }
       
  4433 }
       
  4434 
       
  4435 /*! \reimp */
       
  4436 void Q3ListBox::changeEvent(QEvent *ev)
       
  4437 {
       
  4438     if (ev->type() == QEvent::ActivationChange) {
       
  4439         if (!isActiveWindow() && d->scrollTimer)
       
  4440             d->scrollTimer->stop();
       
  4441         if (!palette().isEqual(QPalette::Active, QPalette::Inactive))
       
  4442             viewport()->update();
       
  4443     }
       
  4444     Q3ScrollView::changeEvent(ev);
       
  4445 
       
  4446     if (ev->type() == QEvent::ApplicationFontChange || ev->type() == QEvent::FontChange)
       
  4447         triggerUpdate(true);
       
  4448 }
       
  4449 
       
  4450 /*!
       
  4451     Returns 0.
       
  4452 
       
  4453     Make your derived classes return their own values for rtti(), and
       
  4454     you can distinguish between listbox items. You should use values
       
  4455     greater than 1000 preferably a large random number, to allow for
       
  4456     extensions to this class.
       
  4457 */
       
  4458 
       
  4459 int Q3ListBoxItem::rtti() const
       
  4460 {
       
  4461     return RTTI;
       
  4462 }
       
  4463 
       
  4464 /*!
       
  4465     \fn bool Q3ListBox::dragSelect() const
       
  4466 
       
  4467     Returns true. Dragging always selects.
       
  4468 */
       
  4469 
       
  4470 /*!
       
  4471     \fn void Q3ListBox::setDragSelect(bool b)
       
  4472 
       
  4473     Does nothing. Dragging always selects. The \a b parameter is ignored.
       
  4474 */
       
  4475 
       
  4476 /*!
       
  4477     \fn bool Q3ListBox::autoScroll() const
       
  4478 
       
  4479     Use dragAutoScroll() instead. This function always returns true.
       
  4480 */
       
  4481 
       
  4482 /*!
       
  4483     \fn void Q3ListBox::setAutoScroll(bool b)
       
  4484 
       
  4485     Use setDragAutoScroll(\a b) instead.
       
  4486 */
       
  4487 
       
  4488 /*!
       
  4489     \fn bool Q3ListBox::autoScrollBar() const
       
  4490 
       
  4491     Use vScrollBarMode() instead. Returns true if the vertical
       
  4492     scrollbar mode is \c Auto.
       
  4493 */
       
  4494 
       
  4495 /*!
       
  4496     \fn void Q3ListBox::setAutoScrollBar(bool enable)
       
  4497 
       
  4498     Use setVScrollBarMode() instead.
       
  4499 
       
  4500     If \a enable is true, pass \c Auto as the argument to
       
  4501     setVScrollBarMode(); otherwise, pass \c AlwaysOff.
       
  4502 */
       
  4503 
       
  4504 /*!
       
  4505     \fn bool Q3ListBox::scrollBar() const
       
  4506 
       
  4507     Use vScrollBarMode() instead. Returns true if the vertical
       
  4508     scrollbar mode is not \c AlwaysOff.
       
  4509 */
       
  4510 
       
  4511 /*!
       
  4512     \fn void Q3ListBox::setScrollBar(bool enable)
       
  4513 
       
  4514     Use setVScrollBarMode() instead.
       
  4515 
       
  4516     If \a enable is true, pass \c AlwaysOn as the argument to
       
  4517     setVScrollBarMode(); otherwise, pass \c AlwaysOff.
       
  4518 */
       
  4519 
       
  4520 /*!
       
  4521     \fn bool Q3ListBox::autoBottomScrollBar() const
       
  4522 
       
  4523     Use hScrollBarMode() instead. Returns true if the horizontal
       
  4524     scrollbar mode is set to \c Auto.
       
  4525 */
       
  4526 
       
  4527 /*!
       
  4528     \fn void Q3ListBox::setAutoBottomScrollBar(bool enable)
       
  4529 
       
  4530     Use setHScrollBarMode() instead.
       
  4531 
       
  4532     If \a enable is true, pass \c Auto as the argument to
       
  4533     setHScrollBarMode(); otherwise, pass \c AlwaysOff.
       
  4534 */
       
  4535 
       
  4536 /*!
       
  4537     \fn bool Q3ListBox::bottomScrollBar() const
       
  4538 
       
  4539     Use hScrollBarMode() instead. Returns true if the horizontal
       
  4540     scrollbar mode is not \c AlwaysOff.
       
  4541 */
       
  4542 
       
  4543 /*!
       
  4544     \fn void Q3ListBox::setBottomScrollBar(bool enable)
       
  4545 
       
  4546     Use setHScrollBarMode() instead.
       
  4547 
       
  4548     If \a enable is true, pass \c AlwaysOn as the argument to
       
  4549     setHScrollBarMode(); otherwise, pass \c AlwaysOff.
       
  4550 */
       
  4551 
       
  4552 /*!
       
  4553     \fn bool Q3ListBox::smoothScrolling() const
       
  4554 
       
  4555     Returns false. Qt always scrolls smoothly.
       
  4556 */
       
  4557 
       
  4558 /*!
       
  4559     \fn void Q3ListBox::setSmoothScrolling(bool b)
       
  4560 
       
  4561     Does nothing. Qt always scrolls smoothly. The \a b parameter is
       
  4562     ignored.
       
  4563 */
       
  4564 
       
  4565 /*!
       
  4566     \fn bool Q3ListBox::autoUpdate() const
       
  4567 
       
  4568     Returns true. Qt always updates automatically.
       
  4569 */
       
  4570 
       
  4571 /*!
       
  4572     \fn void Q3ListBox::setAutoUpdate(bool b)
       
  4573 
       
  4574     Does nothing. Qt always updates automatically. The \a b parameter
       
  4575     is ignored.
       
  4576 */
       
  4577 
       
  4578 /*!
       
  4579     \fn void Q3ListBox::setFixedVisibleLines(int lines)
       
  4580 
       
  4581     Use setRowMode(\a lines) instead.
       
  4582 */
       
  4583 
       
  4584 /*!
       
  4585     \fn int Q3ListBox::cellHeight(int i) const
       
  4586 
       
  4587     Use itemHeight(\a i) instead.
       
  4588 */
       
  4589 
       
  4590 /*!
       
  4591     \fn int  Q3ListBox::cellHeight() const
       
  4592 
       
  4593     Use itemHeight() instead.
       
  4594 */
       
  4595 
       
  4596 /*!
       
  4597     \fn int  Q3ListBox::cellWidth() const
       
  4598 
       
  4599     Use maxItemWidth() instead.
       
  4600 */
       
  4601 
       
  4602 /*!
       
  4603     \fn int  Q3ListBox::cellWidth(int i) const
       
  4604 
       
  4605     Use maxItemWidth(\a i) instead.
       
  4606 */
       
  4607 
       
  4608 /*!
       
  4609     \fn int  Q3ListBox::numCols() const
       
  4610 
       
  4611     Use numColumns() instead.
       
  4612 */
       
  4613 
       
  4614 /*!
       
  4615     \fn void Q3ListBox::updateCellWidth()
       
  4616 
       
  4617     Does nothing. Qt automatically updates.
       
  4618 */
       
  4619 
       
  4620 /*!
       
  4621     \fn int  Q3ListBox::totalWidth() const
       
  4622 
       
  4623     Use contentsWidth() instead.
       
  4624 */
       
  4625 
       
  4626 /*!
       
  4627     \fn int  Q3ListBox::totalHeight() const
       
  4628 
       
  4629     Use contentsHeight() instead.
       
  4630 */
       
  4631 
       
  4632 /*!
       
  4633     \fn int  Q3ListBox::findItem(int yPos) const
       
  4634 
       
  4635     Use index(itemAt(\a yPos)) instead.
       
  4636 */
       
  4637 
       
  4638 /*!
       
  4639     \fn bool Q3ListBoxItem::selected() const
       
  4640 
       
  4641     Use isSelected() instead. Returns true if isSelected()
       
  4642     returns true.
       
  4643 */
       
  4644 
       
  4645 /*!
       
  4646     \fn bool Q3ListBoxItem::current() const
       
  4647 
       
  4648     Use isCurrent() instead. Returns true if isCurrent()
       
  4649     returns true.
       
  4650 */
       
  4651 
       
  4652 /*!
       
  4653     \enum Q3ListBox::StringComparisonMode
       
  4654 
       
  4655     This enum type is used to set the string comparison mode when
       
  4656     searching for an item. We'll refer to the string being searched
       
  4657     as the 'target' string.
       
  4658 
       
  4659     \value CaseSensitive The strings must match case sensitively.
       
  4660     \value ExactMatch The target and search strings must match exactly.
       
  4661     \value BeginsWith The target string begins with the search string.
       
  4662     \value EndsWith The target string ends with the search string.
       
  4663     \value Contains The target string contains the search string.
       
  4664 
       
  4665     If you OR these flags together (excluding \c CaseSensitive), the
       
  4666     search criteria be applied in the following order: \c ExactMatch,
       
  4667     \c BeginsWith, \c EndsWith, \c Contains.
       
  4668 
       
  4669     Matching is case-insensitive unless \c CaseSensitive is set. \c
       
  4670     CaseSensitive can be OR-ed with any combination of the other
       
  4671     flags.
       
  4672 
       
  4673     \sa ComparisonFlags
       
  4674 */
       
  4675 
       
  4676 /*!
       
  4677     \typedef Q3ListBox::ComparisonFlags
       
  4678 
       
  4679     This typedef is used in Q3IconView's API for values that are OR'd
       
  4680     combinations of \l StringComparisonMode values.
       
  4681 
       
  4682     \sa StringComparisonMode
       
  4683 */
       
  4684 
       
  4685 QT_END_NAMESPACE
       
  4686 
       
  4687 #endif // QT_NO_LISTBOX