src/qt3support/itemviews/q3listview.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 <qplatformdefs.h>
       
    43 #include "q3listview.h"
       
    44 #ifndef QT_NO_LISTVIEW
       
    45 #include "q3tl.h"
       
    46 #include "qapplication.h"
       
    47 #include "qbitmap.h"
       
    48 #include "q3cleanuphandler.h"
       
    49 #include "qcursor.h"
       
    50 #include "qdatetime.h"
       
    51 #include "q3dragobject.h"
       
    52 #include "qevent.h"
       
    53 #include "qhash.h"
       
    54 #include "q3header.h"
       
    55 #include "qicon.h"
       
    56 #include "qlineedit.h"
       
    57 #include "qpainter.h"
       
    58 #include "qpixmapcache.h"
       
    59 #include "qstack.h"
       
    60 #include "qstyle.h"
       
    61 #include "qstyleoption.h"
       
    62 #include "qtimer.h"
       
    63 #include "qtooltip.h"
       
    64 #include "qdebug.h"
       
    65 #ifndef QT_NO_ACCESSIBILITY
       
    66 #include "qaccessible.h"
       
    67 #endif
       
    68 
       
    69 QT_BEGIN_NAMESPACE
       
    70 
       
    71 const int Unsorted = 16383;
       
    72 
       
    73 static Q3CleanupHandler<QBitmap> qlv_cleanup_bitmap;
       
    74 
       
    75 
       
    76 struct Q3ListViewPrivate
       
    77 {
       
    78     // classes that are here to avoid polluting the global name space
       
    79 
       
    80     // the magical hidden mother of all items
       
    81     class Root: public Q3ListViewItem {
       
    82     public:
       
    83         Root(Q3ListView * parent);
       
    84 
       
    85         void setHeight(int);
       
    86         void invalidateHeight();
       
    87         void setup();
       
    88         Q3ListView * theListView() const;
       
    89 
       
    90         Q3ListView * lv;
       
    91     };
       
    92 
       
    93     // to remember what's on screen
       
    94     class DrawableItem {
       
    95     public:
       
    96         DrawableItem() {}
       
    97         DrawableItem(int level, int ypos, Q3ListViewItem * item)
       
    98             : l(level), y(ypos), i(item) {};
       
    99         int l;
       
   100         int y;
       
   101         Q3ListViewItem * i;
       
   102     };
       
   103 
       
   104     // for sorting
       
   105     class SortableItem {
       
   106     public:
       
   107         /*
       
   108           We could be smarter and keep a pointer to the Q3ListView
       
   109           item instead of numCols, col and asc. This would then allow
       
   110           us to use the physical ordering of columns rather than the
       
   111           logical. Microsoft uses the logical ordering, so there is
       
   112           some virtue in doing so, although it prevents the user from
       
   113           choosing the secondary key.
       
   114         */
       
   115         Q3ListViewItem * item;
       
   116         int numCols;
       
   117         int col;
       
   118         bool asc;
       
   119 
       
   120         int cmp(const SortableItem& i) const {
       
   121             int diff = item->compare(i.item, col, asc);
       
   122             if (diff == 0 && numCols != 1) {
       
   123                 for (int j = 0; j < numCols; j++) {
       
   124                     if (j != col) {
       
   125                         diff = item->compare(i.item, j, asc);
       
   126                         if (diff != 0)
       
   127                             break;
       
   128                     }
       
   129                 }
       
   130             }
       
   131             return diff;
       
   132         }
       
   133         bool operator<(const SortableItem& i) const { return cmp(i) < 0; }
       
   134         bool operator<=(const SortableItem& i) const { return cmp(i) <= 0; }
       
   135         bool operator>(const SortableItem& i) const { return cmp(i) > 0; }
       
   136     };
       
   137 
       
   138     class ItemColumnInfo {
       
   139     public:
       
   140         ItemColumnInfo(): pm(0), next(0), truncated(false), dirty(false), allow_rename(false), width(0) {}
       
   141         ~ItemColumnInfo() { delete pm; delete next; }
       
   142         QString text, tmpText;
       
   143         QPixmap * pm;
       
   144         ItemColumnInfo * next;
       
   145         uint truncated : 1;
       
   146         uint dirty : 1;
       
   147         uint allow_rename : 1;
       
   148         int width;
       
   149     };
       
   150 
       
   151     class ViewColumnInfo {
       
   152     public:
       
   153         ViewColumnInfo(): align(Qt::AlignAuto), sortable(true), next(0) {}
       
   154         ~ViewColumnInfo() { delete next; }
       
   155         int align;
       
   156         bool sortable;
       
   157         ViewColumnInfo * next;
       
   158     };
       
   159 
       
   160     // private variables used in Q3ListView
       
   161     ViewColumnInfo * vci;
       
   162     Q3Header * h;
       
   163     Root * r;
       
   164     uint rootIsExpandable : 1;
       
   165     int margin;
       
   166 
       
   167     Q3ListViewItem * focusItem, *highlighted, *oldFocusItem;
       
   168 
       
   169     QTimer * timer;
       
   170     QTimer * dirtyItemTimer;
       
   171     QTimer * visibleTimer;
       
   172     int levelWidth;
       
   173 
       
   174     // the list of drawables, and the range drawables covers entirely
       
   175     // (it may also include a few items above topPixel)
       
   176     QList<DrawableItem> drawables;
       
   177     int topPixel;
       
   178     int bottomPixel;
       
   179 
       
   180     QList<const Q3ListViewItem *> dirtyItems;
       
   181 
       
   182     Q3ListView::SelectionMode selectionMode;
       
   183 
       
   184     // Per-column structure for information not in the Q3Header
       
   185     struct Column {
       
   186         Q3ListView::WidthMode wmode;
       
   187     };
       
   188     QVector<Column> column;
       
   189 
       
   190     // suggested height for the items
       
   191     int fontMetricsHeight;
       
   192     int minLeftBearing, minRightBearing;
       
   193     int ellipsisWidth;
       
   194 
       
   195     // currently typed prefix for the keyboard interface, and the time
       
   196     // of the last key-press
       
   197     QString currentPrefix;
       
   198     QTime currentPrefixTime;
       
   199 
       
   200     // holds a list of iterators
       
   201     QList<Q3ListViewItemIterator *> iterators;
       
   202     Q3ListViewItem *pressedItem, *selectAnchor;
       
   203 
       
   204     QTimer *scrollTimer;
       
   205     QTimer *renameTimer;
       
   206     QTimer *autoopenTimer;
       
   207 
       
   208     // sort column and order   #### may need to move to Q3Header [subclass]
       
   209     int sortcolumn;
       
   210     bool ascending                :1;
       
   211     bool sortIndicator                :1;
       
   212     // whether to select or deselect during this mouse press.
       
   213     bool allColumnsShowFocus        :1;
       
   214     bool select                        :1;
       
   215 
       
   216     // true if the widget should take notice of mouseReleaseEvent
       
   217     bool buttonDown                :1;
       
   218     // true if the widget should ignore a double-click
       
   219     bool ignoreDoubleClick        :1;
       
   220 
       
   221     bool clearing                :1;
       
   222     bool pressedSelected        :1;
       
   223     bool pressedEmptyArea         :1;
       
   224 
       
   225     bool toolTips                :1;
       
   226     bool fullRepaintOnComlumnChange:1;
       
   227     bool updateHeader                :1;
       
   228 
       
   229     bool startEdit : 1;
       
   230     bool ignoreEditAfterFocus : 1;
       
   231     bool inMenuMode :1;
       
   232 
       
   233     Q3ListView::RenameAction defRenameAction;
       
   234 
       
   235     Q3ListViewItem *startDragItem;
       
   236     QPoint dragStartPos;
       
   237     int pressedColumn;
       
   238     Q3ListView::ResizeMode resizeMode;
       
   239 };
       
   240 
       
   241 Q_DECLARE_TYPEINFO(Q3ListViewPrivate::DrawableItem, Q_PRIMITIVE_TYPE);
       
   242 
       
   243 // these should probably be in Q3ListViewPrivate, for future thread safety
       
   244 static bool activatedByClick;
       
   245 static QPoint activatedP;
       
   246 
       
   247 #ifndef QT_NO_ACCESSIBILITY
       
   248 static int indexOfItem(Q3ListViewItem *item)
       
   249 {
       
   250     if (!QAccessible::isActive())
       
   251         return 0;
       
   252 
       
   253     static Q3ListViewItem *lastItem = 0;
       
   254     static int lastIndex = 0;
       
   255 
       
   256     if (!item || !item->listView())
       
   257         return 0;
       
   258 
       
   259     if (item == lastItem)
       
   260         return lastIndex;
       
   261 
       
   262     lastItem = item;
       
   263     int index = 1;
       
   264 
       
   265     Q3ListViewItemIterator it(item->listView());
       
   266     while (it.current()) {
       
   267         if (it.current() == item) {
       
   268             lastIndex = index;
       
   269             return index;
       
   270         }
       
   271         ++it;
       
   272         ++index;
       
   273     }
       
   274     lastIndex = 0;
       
   275     return 0;
       
   276 }
       
   277 #endif
       
   278 
       
   279 /*!
       
   280     Creates a string with ... like "Trollte..." or "...olltech", depending on the alignment.
       
   281 */
       
   282 static QString qEllipsisText(const QString &org, const QFontMetrics &fm, int width, int align)
       
   283 {
       
   284     int ellWidth = fm.width(QLatin1String("..."));
       
   285     QString text = QString::fromLatin1("");
       
   286     int i = 0;
       
   287     int len = org.length();
       
   288     int offset = (align & Qt::AlignRight) ? (len-1) - i : i;
       
   289     while (i < len && fm.width(text + org[offset]) + ellWidth < width) {
       
   290         if (align & Qt::AlignRight)
       
   291             text.prepend(org[offset]);
       
   292         else
       
   293             text += org[offset];
       
   294         offset = (align & Qt::AlignRight) ? (len-1) - ++i : ++i;
       
   295     }
       
   296     if (text.isEmpty())
       
   297         text = (align & Qt::AlignRight) ? org.right(1) : text = org.left(1);
       
   298     if (align & Qt::AlignRight)
       
   299         text.prepend(QLatin1String("..."));
       
   300     else
       
   301         text += QLatin1String("...");
       
   302     return text;
       
   303 }
       
   304 
       
   305 /*!
       
   306     \class Q3ListViewItem
       
   307     \brief The Q3ListViewItem class implements a list view item.
       
   308 
       
   309     \compat
       
   310 
       
   311     A list view item is a multi-column object capable of displaying
       
   312     itself in a Q3ListView.
       
   313 
       
   314     The easiest way to use Q3ListViewItem is to construct one with a
       
   315     few constant strings, and either a Q3ListView or another
       
   316     Q3ListViewItem as parent.
       
   317     \snippet doc/src/snippets/code/src_qt3support_itemviews_q3listview.cpp 0
       
   318     We've discarded the pointers to the items since we can still access
       
   319     them via their parent \e listView. By default, Q3ListView sorts its
       
   320     items; this can be switched off with Q3ListView::setSorting(-1).
       
   321 
       
   322     The parent must be another Q3ListViewItem or a Q3ListView. If the
       
   323     parent is a Q3ListView, the item becomes a top-level item within
       
   324     that Q3ListView. If the parent is another Q3ListViewItem, the item
       
   325     becomes a child of that list view item.
       
   326 
       
   327     If you keep the pointer, you can set or change the texts using
       
   328     setText(), add pixmaps using setPixmap(), change its mode using
       
   329     setSelectable(), setSelected(), setOpen() and setExpandable().
       
   330     You'll also be able to change its height using setHeight(), and
       
   331     traverse its sub-items. You don't have to keep the pointer since
       
   332     you can get a pointer to any Q3ListViewItem in a Q3ListView using
       
   333     Q3ListView::selectedItem(), Q3ListView::currentItem(),
       
   334     Q3ListView::firstChild(), Q3ListView::lastItem() and
       
   335     Q3ListView::findItem().
       
   336 
       
   337     If you call \c delete on a list view item, it will be deleted as
       
   338     expected, and as usual for \l{QObject}s, if it has any child items
       
   339     (to any depth), all these will be deleted too.
       
   340 
       
   341     \l{Q3CheckListItem}s are list view items that have a checkbox or
       
   342     radio button and can be used in place of plain Q3ListViewItems.
       
   343 
       
   344     You can traverse the tree as if it were a doubly-linked list using
       
   345     itemAbove() and itemBelow(); they return pointers to the items
       
   346     directly above and below this item on the screen (even if none of
       
   347     them are actually visible at the moment).
       
   348 
       
   349     Here's how to traverse all of an item's children (but not its
       
   350     children's children, etc.):
       
   351     Example:
       
   352     \snippet doc/src/snippets/code/src_qt3support_itemviews_q3listview.cpp 1
       
   353 
       
   354     If you want to iterate over every item, to any level of depth use
       
   355     an iterator. To iterate over the entire tree, initialize the
       
   356     iterator with the list view itself; to iterate over an item's
       
   357     children (and children's children to any depth), initialize the
       
   358     iterator with the item:
       
   359     \snippet doc/src/snippets/code/src_qt3support_itemviews_q3listview.cpp 2
       
   360 
       
   361     Note that the order of the children will change when the sorting
       
   362     order changes and is undefined if the items are not visible. You
       
   363     can, however, call enforceSortOrder() at any time; Q3ListView will
       
   364     always call it before it needs to show an item.
       
   365 
       
   366     Many programs will need to reimplement Q3ListViewItem. The most
       
   367     commonly reimplemented functions are:
       
   368     \table
       
   369     \header \i Function \i Description
       
   370     \row \i \l text()
       
   371          \i Returns the text in a column. Many subclasses will compute
       
   372             this on the fly.
       
   373     \row \i \l key()
       
   374          \i Used for sorting. The default key() simply calls
       
   375             text(), but judicious use of key() can give you fine
       
   376             control over sorting; for example, QFileDialog
       
   377             reimplements key() to sort by date.
       
   378     \row \i \l setup()
       
   379          \i Called before showing the item and whenever the list
       
   380             view's font changes, for example.
       
   381     \row \i \l activate()
       
   382          \i Called whenever the user clicks on the item or presses
       
   383             Space when the item is the current item.
       
   384     \endtable
       
   385 
       
   386     Some subclasses call setExpandable(true) even when they have no
       
   387     children, and populate themselves when setup() or setOpen(true) is
       
   388     called. The \c dirview/dirview.cpp example program uses this
       
   389     technique to start up quickly: The files and subdirectories in a
       
   390     directory aren't inserted into the tree until they're actually
       
   391     needed.
       
   392 
       
   393     \img qlistviewitems.png List View Items
       
   394 
       
   395     \sa Q3CheckListItem Q3ListView
       
   396 */
       
   397 
       
   398 /*!
       
   399     \fn int Q3CheckListItem::rtti() const
       
   400 
       
   401     Returns 1.
       
   402 
       
   403     Make your derived classes return their own values for rtti(), and
       
   404     you can distinguish between list view items. You should use values
       
   405     greater than 1000, to allow for extensions to this class.
       
   406 */
       
   407 
       
   408 /*!
       
   409     Constructs a new top-level list view item in the Q3ListView \a
       
   410     parent.
       
   411 */
       
   412 
       
   413 Q3ListViewItem::Q3ListViewItem(Q3ListView * parent)
       
   414 {
       
   415     init();
       
   416     parent->insertItem(this);
       
   417 }
       
   418 
       
   419 
       
   420 /*!
       
   421     Constructs a new list view item that is a child of \a parent and
       
   422     first in the parent's list of children.
       
   423 */
       
   424 
       
   425 Q3ListViewItem::Q3ListViewItem(Q3ListViewItem * parent)
       
   426 {
       
   427     init();
       
   428     parent->insertItem(this);
       
   429 }
       
   430 
       
   431 
       
   432 
       
   433 
       
   434 /*!
       
   435     Constructs an empty list view item that is a child of \a parent
       
   436     and is after item \a after in the parent's list of children. Since
       
   437     \a parent is a Q3ListView the item will be a top-level item.
       
   438 */
       
   439 
       
   440 Q3ListViewItem::Q3ListViewItem(Q3ListView * parent, Q3ListViewItem * after)
       
   441 {
       
   442     init();
       
   443     parent->insertItem(this);
       
   444     moveToJustAfter(after);
       
   445 }
       
   446 
       
   447 
       
   448 /*!
       
   449     Constructs an empty list view item that is a child of \a parent
       
   450     and is after item \a after in the parent's list of children.
       
   451 */
       
   452 
       
   453 Q3ListViewItem::Q3ListViewItem(Q3ListViewItem * parent, Q3ListViewItem * after)
       
   454 {
       
   455     init();
       
   456     parent->insertItem(this);
       
   457     moveToJustAfter(after);
       
   458 }
       
   459 
       
   460 
       
   461 
       
   462 /*!
       
   463     Constructs a new top-level list view item in the Q3ListView \a
       
   464     parent, with up to eight constant strings, \a label1, \a label2, \a
       
   465     label3, \a label4, \a label5, \a label6, \a label7 and \a label8
       
   466     defining its columns' contents.
       
   467 
       
   468     \sa setText()
       
   469 */
       
   470 
       
   471 Q3ListViewItem::Q3ListViewItem(Q3ListView * parent,
       
   472                               const QString &label1,
       
   473                               const QString &label2,
       
   474                               const QString &label3,
       
   475                               const QString &label4,
       
   476                               const QString &label5,
       
   477                               const QString &label6,
       
   478                               const QString &label7,
       
   479                               const QString &label8)
       
   480 {
       
   481     init();
       
   482     parent->insertItem(this);
       
   483 
       
   484     setText(0, label1);
       
   485     setText(1, label2);
       
   486     setText(2, label3);
       
   487     setText(3, label4);
       
   488     setText(4, label5);
       
   489     setText(5, label6);
       
   490     setText(6, label7);
       
   491     setText(7, label8);
       
   492 }
       
   493 
       
   494 
       
   495 /*!
       
   496     Constructs a new list view item as a child of the Q3ListViewItem \a
       
   497     parent with up to eight constant strings, \a label1, \a label2, \a
       
   498     label3, \a label4, \a label5, \a label6, \a label7 and \a label8
       
   499     as columns' contents.
       
   500 
       
   501     \sa setText()
       
   502 */
       
   503 
       
   504 Q3ListViewItem::Q3ListViewItem(Q3ListViewItem * parent,
       
   505                               const QString &label1,
       
   506                               const QString &label2,
       
   507                               const QString &label3,
       
   508                               const QString &label4,
       
   509                               const QString &label5,
       
   510                               const QString &label6,
       
   511                               const QString &label7,
       
   512                               const QString &label8)
       
   513 {
       
   514     init();
       
   515     parent->insertItem(this);
       
   516 
       
   517     setText(0, label1);
       
   518     setText(1, label2);
       
   519     setText(2, label3);
       
   520     setText(3, label4);
       
   521     setText(4, label5);
       
   522     setText(5, label6);
       
   523     setText(6, label7);
       
   524     setText(7, label8);
       
   525 }
       
   526 
       
   527 /*!
       
   528     Constructs a new list view item in the Q3ListView \a parent that is
       
   529     included after item \a after and that has up to eight column
       
   530     texts, \a label1, \a label2, \a label3, \a label4, \a label5, \a
       
   531     label6, \a label7 and\a label8.
       
   532 
       
   533     Note that the order is changed according to Q3ListViewItem::key()
       
   534     unless the list view's sorting is disabled using
       
   535     Q3ListView::setSorting(-1).
       
   536 
       
   537     \sa setText()
       
   538 */
       
   539 
       
   540 Q3ListViewItem::Q3ListViewItem(Q3ListView * parent, Q3ListViewItem * after,
       
   541                               const QString &label1,
       
   542                               const QString &label2,
       
   543                               const QString &label3,
       
   544                               const QString &label4,
       
   545                               const QString &label5,
       
   546                               const QString &label6,
       
   547                               const QString &label7,
       
   548                               const QString &label8)
       
   549 {
       
   550     init();
       
   551     parent->insertItem(this);
       
   552     moveToJustAfter(after);
       
   553 
       
   554     setText(0, label1);
       
   555     setText(1, label2);
       
   556     setText(2, label3);
       
   557     setText(3, label4);
       
   558     setText(4, label5);
       
   559     setText(5, label6);
       
   560     setText(6, label7);
       
   561     setText(7, label8);
       
   562 }
       
   563 
       
   564 
       
   565 /*!
       
   566     Constructs a new list view item as a child of the Q3ListViewItem \a
       
   567     parent. It is inserted after item \a after and may contain up to
       
   568     eight strings, \a label1, \a label2, \a label3, \a label4, \a
       
   569     label5, \a label6, \a label7 and \a label8 as column entries.
       
   570 
       
   571     Note that the order is changed according to Q3ListViewItem::key()
       
   572     unless the list view's sorting is disabled using
       
   573     Q3ListView::setSorting(-1).
       
   574 
       
   575     \sa setText()
       
   576 */
       
   577 
       
   578 Q3ListViewItem::Q3ListViewItem(Q3ListViewItem * parent, Q3ListViewItem * after,
       
   579                               const QString &label1,
       
   580                               const QString &label2,
       
   581                               const QString &label3,
       
   582                               const QString &label4,
       
   583                               const QString &label5,
       
   584                               const QString &label6,
       
   585                               const QString &label7,
       
   586                               const QString &label8)
       
   587 {
       
   588     init();
       
   589     parent->insertItem(this);
       
   590     moveToJustAfter(after);
       
   591 
       
   592     setText(0, label1);
       
   593     setText(1, label2);
       
   594     setText(2, label3);
       
   595     setText(3, label4);
       
   596     setText(4, label5);
       
   597     setText(5, label6);
       
   598     setText(6, label7);
       
   599     setText(7, label8);
       
   600 }
       
   601 
       
   602 /*!
       
   603     Sorts all this item's child items using the current sorting
       
   604     configuration (sort column and direction).
       
   605 
       
   606     \sa enforceSortOrder()
       
   607 */
       
   608 
       
   609 void Q3ListViewItem::sort()
       
   610 {
       
   611     if (!listView())
       
   612          return;
       
   613     lsc = Unsorted;
       
   614     enforceSortOrder();
       
   615     listView()->triggerUpdate();
       
   616 }
       
   617 
       
   618 /*!
       
   619     Returns 0.
       
   620 
       
   621     Make your derived classes return their own values for rtti(), so
       
   622     that you can distinguish between different kinds of list view
       
   623     items. You should use values greater than 1000 to allow for
       
   624     extensions to this class.
       
   625 */
       
   626 
       
   627 int Q3ListViewItem::rtti() const
       
   628 {
       
   629     return RTTI;
       
   630 }
       
   631 
       
   632 /*
       
   633     Performs the initializations that's common to the constructors.
       
   634 */
       
   635 
       
   636 void Q3ListViewItem::init()
       
   637 {
       
   638     ownHeight = 0;
       
   639     maybeTotalHeight = -1;
       
   640     open = false;
       
   641 
       
   642     nChildren = 0;
       
   643     parentItem = 0;
       
   644     siblingItem = childItem = 0;
       
   645 
       
   646     columns = 0;
       
   647 
       
   648     selected = 0;
       
   649     selectable = true;
       
   650 
       
   651     lsc = Unsorted;
       
   652     lso = true; // unsorted in ascending order :)
       
   653     configured = false;
       
   654     expandable = false;
       
   655     selectable = true;
       
   656     is_root = false;
       
   657     allow_drag = false;
       
   658     allow_drop = false;
       
   659     visible = true;
       
   660     renameBox = 0;
       
   661     enabled = true;
       
   662     mlenabled = false;
       
   663 }
       
   664 
       
   665 /*!
       
   666     If \a b is true, the item is made visible; otherwise it is hidden.
       
   667 
       
   668     If the item is not visible, itemAbove() and itemBelow() will never
       
   669     return this item, although you still can reach it by using e.g.
       
   670     Q3ListViewItemIterator.
       
   671 */
       
   672 
       
   673 void Q3ListViewItem::setVisible(bool b)
       
   674 {
       
   675     if (b == (bool)visible)
       
   676         return;
       
   677     Q3ListView *lv = listView();
       
   678     if (!lv)
       
   679         return;
       
   680     if (b && parent() && !parent()->isVisible())
       
   681         return;
       
   682     visible = b;
       
   683     configured = false;
       
   684     setHeight(0);
       
   685     invalidateHeight();
       
   686     if (parent())
       
   687         parent()->invalidateHeight();
       
   688     else
       
   689         lv->d->r->invalidateHeight();
       
   690     for (Q3ListViewItem *i = childItem; i; i = i->siblingItem)
       
   691         i->setVisible(b);
       
   692     if (lv)
       
   693         lv->triggerUpdate();
       
   694 }
       
   695 
       
   696 /*!
       
   697     Returns true if the item is visible; otherwise returns false.
       
   698 
       
   699     \sa setVisible()
       
   700 */
       
   701 
       
   702 bool Q3ListViewItem::isVisible() const
       
   703 {
       
   704     return (bool)visible;
       
   705 }
       
   706 
       
   707 /*!
       
   708     If \a b is true, this item can be in-place renamed in the column
       
   709     \a col by the user; otherwise it cannot be renamed in-place.
       
   710 */
       
   711 
       
   712 void Q3ListViewItem::setRenameEnabled(int col, bool b)
       
   713 {
       
   714     Q3ListViewPrivate::ItemColumnInfo * l = (Q3ListViewPrivate::ItemColumnInfo*)columns;
       
   715     if (!l) {
       
   716         l = new Q3ListViewPrivate::ItemColumnInfo;
       
   717         columns = (void*)l;
       
   718     }
       
   719     for(int c = 0; c < col; c++) {
       
   720         if (!l->next)
       
   721             l->next = new Q3ListViewPrivate::ItemColumnInfo;
       
   722         l = l->next;
       
   723     }
       
   724 
       
   725     if (!l)
       
   726         return;
       
   727     l->allow_rename = b;
       
   728 }
       
   729 
       
   730 /*!
       
   731     Returns true if this item can be in-place renamed in column \a
       
   732     col; otherwise returns false.
       
   733 */
       
   734 
       
   735 bool Q3ListViewItem::renameEnabled(int col) const
       
   736 {
       
   737     Q3ListViewPrivate::ItemColumnInfo * l = (Q3ListViewPrivate::ItemColumnInfo*)columns;
       
   738     if (!l)
       
   739         return false;
       
   740 
       
   741     while(col && l) {
       
   742         l = l->next;
       
   743         col--;
       
   744     }
       
   745 
       
   746     if (!l)
       
   747         return false;
       
   748     return (bool)l->allow_rename;
       
   749 }
       
   750 
       
   751 /*!
       
   752     If \a b is true the item is enabled; otherwise it is disabled.
       
   753     Disabled items are drawn differently (e.g. grayed-out) and are not
       
   754     accessible by the user.
       
   755 */
       
   756 
       
   757 void Q3ListViewItem::setEnabled(bool b)
       
   758 {
       
   759     if ((bool)enabled == b)
       
   760         return;
       
   761     enabled = b;
       
   762     if (!enabled)
       
   763         selected = false;
       
   764     Q3ListView *lv = listView();
       
   765     if (lv) {
       
   766         lv->triggerUpdate();
       
   767 
       
   768 #ifndef QT_NO_ACCESSIBILITY
       
   769     QAccessible::updateAccessibility(lv->viewport(), indexOfItem(this), QAccessible::StateChanged);
       
   770 #endif
       
   771     }
       
   772 }
       
   773 
       
   774 /*!
       
   775     Returns true if this item is enabled; otherwise returns false.
       
   776 
       
   777     \sa setEnabled()
       
   778 */
       
   779 
       
   780 bool Q3ListViewItem::isEnabled() const
       
   781 {
       
   782     return (bool)enabled;
       
   783 }
       
   784 
       
   785 /*!
       
   786     If in-place renaming of this item is enabled (see
       
   787     renameEnabled()), this function starts renaming the item in column
       
   788     \a col, by creating and initializing an edit box.
       
   789 */
       
   790 
       
   791 void Q3ListViewItem::startRename(int col)
       
   792 {
       
   793     if (!renameEnabled(col))
       
   794         return;
       
   795     if (renameBox)
       
   796         cancelRename(col);
       
   797     Q3ListView *lv = listView();
       
   798     if (!lv)
       
   799         return;
       
   800 
       
   801     if (lv->d->renameTimer)
       
   802         lv->d->renameTimer->stop();
       
   803 
       
   804     lv->ensureItemVisible(this);
       
   805 
       
   806     if (lv->d->timer->isActive()) {
       
   807         // make sure that pending calculations get finished
       
   808         lv->d->timer->stop();
       
   809         lv->updateContents();
       
   810     }
       
   811 
       
   812     if (lv->currentItem() && lv->currentItem()->renameBox) {
       
   813         if (lv->d->defRenameAction == Q3ListView::Reject)
       
   814             lv->currentItem()->cancelRename(lv->currentItem()->renameCol);
       
   815         else
       
   816             lv->currentItem()->okRename(lv->currentItem()->renameCol);
       
   817     }
       
   818 
       
   819     if (this != lv->currentItem())
       
   820         lv->setCurrentItem(this);
       
   821 
       
   822     QRect r = lv->itemRect(this);
       
   823     r = QRect(lv->viewportToContents(r.topLeft()), r.size());
       
   824     r.setLeft(lv->header()->sectionPos(col));
       
   825     r.setWidth(qMin(lv->header()->sectionSize(col) - 1,
       
   826                     lv->contentsX() + lv->visibleWidth() - r.left()));
       
   827     if (col == 0)
       
   828         r.setLeft(r.left() + lv->itemMargin() + (depth() + (lv->rootIsDecorated() ? 1 : 0)) * lv->treeStepSize() - 1);
       
   829     if (pixmap(col))
       
   830         r.setLeft(r.left() + pixmap(col)->width());
       
   831     if (r.x() - lv->contentsX() < 0) {
       
   832         lv->scrollBy(r.x() - lv->contentsX(), 0);
       
   833         r.setX(lv->contentsX());
       
   834     } else if ((lv->contentsX() + lv->visibleWidth()) < (r.x() + r.width())) {
       
   835         lv->scrollBy((r.x() + r.width()) - (lv->contentsX() + lv->visibleWidth()), 0);
       
   836     }
       
   837     if (r.width() > lv->visibleWidth())
       
   838         r.setWidth(lv->visibleWidth());
       
   839     renameBox = new QLineEdit(lv->viewport(), "qt_renamebox");
       
   840     renameBox->setFrame(false);
       
   841     renameBox->setText(text(col));
       
   842     renameBox->selectAll();
       
   843     renameBox->installEventFilter(lv);
       
   844     lv->addChild(renameBox, r.x(), r.y());
       
   845     renameBox->resize(r.size());
       
   846     lv->viewport()->setFocusProxy(renameBox);
       
   847     renameBox->setFocus();
       
   848     renameBox->show();
       
   849     renameCol = col;
       
   850 }
       
   851 
       
   852 /*!
       
   853     This function removes the rename box.
       
   854 */
       
   855 
       
   856 void Q3ListViewItem::removeRenameBox()
       
   857 {
       
   858     // Sanity, it should be checked by the functions calling this first anyway
       
   859     Q3ListView *lv = listView();
       
   860     if (!lv || !renameBox)
       
   861         return;
       
   862     const bool resetFocus = lv->viewport()->focusProxy() == renameBox;
       
   863     delete renameBox;
       
   864     renameBox = 0;
       
   865     if (resetFocus) {
       
   866         lv->viewport()->setFocusProxy(lv);
       
   867         lv->setFocus();
       
   868     }
       
   869 }
       
   870 
       
   871 /*!
       
   872     This function is called if the user presses Enter during in-place
       
   873     renaming of the item in column \a col.
       
   874 
       
   875     \sa cancelRename()
       
   876 */
       
   877 
       
   878 void Q3ListViewItem::okRename(int col)
       
   879 {
       
   880     Q3ListView *lv = listView();
       
   881     if (!lv || !renameBox)
       
   882         return;
       
   883     setText(col, renameBox->text());
       
   884     removeRenameBox();
       
   885 
       
   886     // we set the parent lsc to Unsorted if that column is the sorted one
       
   887     if (parent() && (int)parent()->lsc == col)
       
   888         parent()->lsc = Unsorted;
       
   889 
       
   890     emit lv->itemRenamed(this, col);
       
   891     emit lv->itemRenamed(this, col, text(col));
       
   892 }
       
   893 
       
   894 /*!
       
   895     This function is called if the user cancels in-place renaming of
       
   896     this item in column \a col (e.g. by pressing Esc).
       
   897 
       
   898     \sa okRename()
       
   899 */
       
   900 
       
   901 void Q3ListViewItem::cancelRename(int)
       
   902 {
       
   903     Q3ListView *lv = listView();
       
   904     if (!lv || !renameBox)
       
   905         return;
       
   906     removeRenameBox();
       
   907 }
       
   908 
       
   909 /*!
       
   910     Destroys the item, deleting all its children and freeing up all
       
   911     allocated resources.
       
   912 */
       
   913 
       
   914 Q3ListViewItem::~Q3ListViewItem()
       
   915 {
       
   916     if (renameBox) {
       
   917         delete renameBox;
       
   918         renameBox = 0;
       
   919     }
       
   920 
       
   921     Q3ListView *lv = listView();
       
   922 
       
   923     if (lv) {
       
   924         if (lv->d->oldFocusItem == this)
       
   925             lv->d->oldFocusItem = 0;
       
   926         if (lv->d->focusItem == this)
       
   927             lv->d->focusItem = 0;
       
   928         if (lv->d->highlighted == this)
       
   929             lv->d->highlighted = 0;
       
   930         if (lv->d->pressedItem == this)
       
   931             lv->d->pressedItem = 0;
       
   932         if (lv->d->selectAnchor == this)
       
   933             lv->d->selectAnchor = 0;
       
   934         for (int j = 0; j < lv->d->iterators.size(); ++j) {
       
   935             Q3ListViewItemIterator *i = lv->d->iterators.at(j);
       
   936             if (i->current() == this)
       
   937                 i->currentRemoved();
       
   938         }
       
   939     }
       
   940 
       
   941     if (parentItem)
       
   942         parentItem->takeItem(this);
       
   943     Q3ListViewItem * i = childItem;
       
   944     childItem = 0;
       
   945     while (i) {
       
   946         i->parentItem = 0;
       
   947         Q3ListViewItem * n = i->siblingItem;
       
   948         delete i;
       
   949         i = n;
       
   950     }
       
   951     delete (Q3ListViewPrivate::ItemColumnInfo *)columns;
       
   952 }
       
   953 
       
   954 
       
   955 /*!
       
   956     If \a b is true each of the item's columns may contain multiple
       
   957     lines of text; otherwise each of them may only contain a single
       
   958     line.
       
   959 */
       
   960 
       
   961 void Q3ListViewItem::setMultiLinesEnabled(bool b)
       
   962 {
       
   963     mlenabled = b;
       
   964 }
       
   965 
       
   966 /*!
       
   967     Returns true if the item can display multiple lines of text in its
       
   968     columns; otherwise returns false.
       
   969 */
       
   970 
       
   971 bool Q3ListViewItem::multiLinesEnabled() const
       
   972 {
       
   973     return mlenabled;
       
   974 }
       
   975 
       
   976 /*!
       
   977     If \a allow is true, the list view starts a drag (see
       
   978     Q3ListView::dragObject()) when the user presses and moves the mouse
       
   979     on this item.
       
   980 */
       
   981 
       
   982 
       
   983 void Q3ListViewItem::setDragEnabled(bool allow)
       
   984 {
       
   985     allow_drag = (uint)allow;
       
   986 }
       
   987 
       
   988 /*!
       
   989     If \a allow is true, the list view accepts drops onto the item;
       
   990     otherwise drops are not allowed.
       
   991 */
       
   992 
       
   993 void Q3ListViewItem::setDropEnabled(bool allow)
       
   994 {
       
   995     allow_drop = (uint)allow;
       
   996 }
       
   997 
       
   998 /*!
       
   999     Returns true if this item can be dragged; otherwise returns false.
       
  1000 
       
  1001     \sa setDragEnabled()
       
  1002 */
       
  1003 
       
  1004 bool Q3ListViewItem::dragEnabled() const
       
  1005 {
       
  1006     return (bool)allow_drag;
       
  1007 }
       
  1008 
       
  1009 /*!
       
  1010     Returns true if this item accepts drops; otherwise returns false.
       
  1011 
       
  1012     \sa setDropEnabled(), acceptDrop()
       
  1013 */
       
  1014 
       
  1015 bool Q3ListViewItem::dropEnabled() const
       
  1016 {
       
  1017     return (bool)allow_drop;
       
  1018 }
       
  1019 
       
  1020 /*!
       
  1021     Returns true if the item can accept drops of type QMimeSource \a
       
  1022     mime; otherwise returns false.
       
  1023 
       
  1024     The default implementation does nothing and returns false. A
       
  1025     subclass must reimplement this to accept drops.
       
  1026 */
       
  1027 
       
  1028 bool Q3ListViewItem::acceptDrop(const QMimeSource *) const
       
  1029 {
       
  1030     return false;
       
  1031 }
       
  1032 
       
  1033 #ifndef QT_NO_DRAGANDDROP
       
  1034 
       
  1035 /*!
       
  1036     This function is called when something was dropped on the item. \a e
       
  1037     contains all the information about the drop.
       
  1038 
       
  1039     The default implementation does nothing, subclasses may need to
       
  1040     reimplement this function.
       
  1041 */
       
  1042 
       
  1043 void Q3ListViewItem::dropped(QDropEvent *e)
       
  1044 {
       
  1045     Q_UNUSED(e);
       
  1046 }
       
  1047 
       
  1048 #endif
       
  1049 
       
  1050 /*!
       
  1051     This function is called when a drag enters the item's bounding
       
  1052     rectangle.
       
  1053 
       
  1054     The default implementation does nothing, subclasses may need to
       
  1055     reimplement this function.
       
  1056 */
       
  1057 
       
  1058 void Q3ListViewItem::dragEntered()
       
  1059 {
       
  1060 }
       
  1061 
       
  1062 /*!
       
  1063     This function is called when a drag leaves the item's bounding
       
  1064     rectangle.
       
  1065 
       
  1066     The default implementation does nothing, subclasses may need to
       
  1067     reimplement this function.
       
  1068 */
       
  1069 
       
  1070 void Q3ListViewItem::dragLeft()
       
  1071 {
       
  1072 }
       
  1073 
       
  1074 /*!
       
  1075     Inserts \a newChild into this list view item's list of children.
       
  1076     You should not need to call this function; it is called
       
  1077     automatically by the constructor of \a newChild.
       
  1078 
       
  1079     \warning If you are using \c Single selection mode, then you
       
  1080     should only insert unselected items.
       
  1081 */
       
  1082 
       
  1083 void Q3ListViewItem::insertItem(Q3ListViewItem * newChild)
       
  1084 {
       
  1085     Q3ListView *lv = listView();
       
  1086     if (lv && lv->currentItem() && lv->currentItem()->renameBox) {
       
  1087         if (lv->d->defRenameAction == Q3ListView::Reject)
       
  1088             lv->currentItem()->cancelRename(lv->currentItem()->renameCol);
       
  1089         else
       
  1090             lv->currentItem()->okRename(lv->currentItem()->renameCol);
       
  1091     }
       
  1092 
       
  1093     if (!newChild || newChild->parentItem == this)
       
  1094         return;
       
  1095     if (newChild->parentItem)
       
  1096         newChild->parentItem->takeItem(newChild);
       
  1097     if (open)
       
  1098         invalidateHeight();
       
  1099     newChild->siblingItem = childItem;
       
  1100     childItem = newChild;
       
  1101     nChildren++;
       
  1102     newChild->parentItem = this;
       
  1103     lsc = Unsorted;
       
  1104     newChild->ownHeight = 0;
       
  1105     newChild->configured = false;
       
  1106 
       
  1107     if (lv && !lv->d->focusItem) {
       
  1108         lv->d->focusItem = lv->firstChild();
       
  1109         lv->d->selectAnchor = lv->d->focusItem;
       
  1110         lv->repaintItem(lv->d->focusItem);
       
  1111     }
       
  1112 }
       
  1113 
       
  1114 
       
  1115 /*!
       
  1116     \fn void Q3ListViewItem::removeItem(Q3ListViewItem *item)
       
  1117 
       
  1118     Removes the given \a item. Use takeItem() instead.
       
  1119 */
       
  1120 
       
  1121 
       
  1122 /*!
       
  1123     Removes \a item from this object's list of children and causes an
       
  1124     update of the screen display. The item is not deleted. You should
       
  1125     not normally need to call this function because
       
  1126     Q3ListViewItem::~Q3ListViewItem() calls it.
       
  1127 
       
  1128     The normal way to delete an item is to use \c delete.
       
  1129 
       
  1130     If you need to move an item from one place in the hierarchy to
       
  1131     another you can use takeItem() to remove the item from the list
       
  1132     view and then insertItem() to put the item back in its new
       
  1133     position.
       
  1134 
       
  1135     If a taken item is part of a selection in \c Single selection
       
  1136     mode, it is unselected and selectionChanged() is emitted. If a
       
  1137     taken item is part of a selection in \c Multi or \c Extended
       
  1138     selection mode, it remains selected.
       
  1139 
       
  1140     \warning This function leaves \a item and its children in a state
       
  1141     where most member functions are unsafe. Only a few functions work
       
  1142     correctly on an item in this state, most notably insertItem(). The
       
  1143     functions that work on taken items are explicitly documented as
       
  1144     such.
       
  1145 
       
  1146     \sa Q3ListViewItem::insertItem()
       
  1147 */
       
  1148 
       
  1149 void Q3ListViewItem::takeItem(Q3ListViewItem * item)
       
  1150 {
       
  1151     if (!item)
       
  1152         return;
       
  1153 
       
  1154     Q3ListView *lv = listView();
       
  1155     if (lv && lv->currentItem() && lv->currentItem()->renameBox) {
       
  1156         if (lv->d->defRenameAction == Q3ListView::Reject)
       
  1157             lv->currentItem()->cancelRename(lv->currentItem()->renameCol);
       
  1158         else
       
  1159             lv->currentItem()->okRename(lv->currentItem()->renameCol);
       
  1160     }
       
  1161     bool emit_changed = false;
       
  1162     if (lv && !lv->d->clearing) {
       
  1163         if (lv->d->oldFocusItem == this)
       
  1164             lv->d->oldFocusItem = 0;
       
  1165 
       
  1166         for (int j = 0; j < lv->d->iterators.size(); ++j) {
       
  1167             Q3ListViewItemIterator *i = lv->d->iterators.at(j);
       
  1168             if (i->current() == item)
       
  1169                 i->currentRemoved();
       
  1170         }
       
  1171 
       
  1172         invalidateHeight();
       
  1173 
       
  1174         if (lv->d && !lv->d->drawables.isEmpty())
       
  1175             lv->d->drawables.clear();
       
  1176 
       
  1177         if (!lv->d->dirtyItems.isEmpty()) {
       
  1178             if (item->childItem) {
       
  1179                 lv->d->dirtyItems.clear();
       
  1180                 lv->d->dirtyItemTimer->stop();
       
  1181                 lv->triggerUpdate();
       
  1182             } else {
       
  1183                 lv->d->dirtyItems.removeAll(item);
       
  1184             }
       
  1185         }
       
  1186 
       
  1187         if (lv->d->focusItem) {
       
  1188             const Q3ListViewItem * c = lv->d->focusItem;
       
  1189             while(c && c != item)
       
  1190                 c = c->parentItem;
       
  1191             if (c == item) {
       
  1192                 if (lv->selectedItem()) {
       
  1193                     // for Single, setSelected(false) when selectedItem() is taken
       
  1194                     lv->selectedItem()->setSelected(false);
       
  1195                     // we don't emit selectionChanged(0)
       
  1196                     emit lv->selectionChanged();
       
  1197                 }
       
  1198                 if (item->nextSibling())
       
  1199                     lv->d->focusItem = item->nextSibling();
       
  1200                 else if (item->itemAbove())
       
  1201                     lv->d->focusItem = item->itemAbove();
       
  1202                 else
       
  1203                     lv->d->focusItem = 0;
       
  1204                 emit_changed = true;
       
  1205             }
       
  1206         }
       
  1207 
       
  1208         // reset anchors etc. if they are set to this or any child
       
  1209         // items
       
  1210         const Q3ListViewItem *ptr = lv->d->selectAnchor;
       
  1211         while (ptr && ptr != item)
       
  1212             ptr = ptr->parentItem;
       
  1213 	if (ptr == item)
       
  1214 	    lv->d->selectAnchor = lv->d->focusItem;
       
  1215 
       
  1216         ptr = lv->d->startDragItem;
       
  1217         while (ptr && ptr != item)
       
  1218             ptr = ptr->parentItem;
       
  1219 	if (ptr == item)
       
  1220 	    lv->d->startDragItem = 0;
       
  1221 
       
  1222         ptr = lv->d->pressedItem;
       
  1223         while (ptr && ptr != item)
       
  1224             ptr = ptr->parentItem;
       
  1225 	if (ptr == item)
       
  1226 	    lv->d->pressedItem = 0;
       
  1227 
       
  1228         ptr = lv->d->highlighted;
       
  1229         while (ptr && ptr != item)
       
  1230             ptr = ptr->parentItem;
       
  1231 	if (ptr == item)
       
  1232 	    lv->d->highlighted = 0;
       
  1233     }
       
  1234 
       
  1235     nChildren--;
       
  1236 
       
  1237     Q3ListViewItem ** nextChild = &childItem;
       
  1238     while(nextChild && *nextChild && item != *nextChild)
       
  1239         nextChild = &((*nextChild)->siblingItem);
       
  1240 
       
  1241     if (nextChild && item == *nextChild)
       
  1242         *nextChild = (*nextChild)->siblingItem;
       
  1243     item->parentItem = 0;
       
  1244     item->siblingItem = 0;
       
  1245     item->ownHeight = 0;
       
  1246     item->maybeTotalHeight = -1;
       
  1247     item->configured = false;
       
  1248 
       
  1249     if (emit_changed) {
       
  1250         emit lv->currentChanged(lv->d->focusItem);
       
  1251 #ifndef QT_NO_ACCESSIBILITY
       
  1252         QAccessible::updateAccessibility(lv->viewport(), 0, QAccessible::Focus);
       
  1253 #endif
       
  1254     }
       
  1255 }
       
  1256 
       
  1257 
       
  1258 /*!
       
  1259     \fn QString Q3ListViewItem::key(int column, bool ascending) const
       
  1260 
       
  1261     Returns a key that can be used for sorting by column \a column.
       
  1262     The default implementation returns text(). Derived classes may
       
  1263     also incorporate the order indicated by \a ascending into this
       
  1264     key, although this is not recommended.
       
  1265 
       
  1266     If you want to sort on non-alphabetical data, e.g. dates, numbers,
       
  1267     etc., it is more efficient to reimplement compare().
       
  1268 
       
  1269     \sa compare(), sortChildItems()
       
  1270 */
       
  1271 
       
  1272 QString Q3ListViewItem::key(int column, bool) const
       
  1273 {
       
  1274     return text(column);
       
  1275 }
       
  1276 
       
  1277 
       
  1278 /*!
       
  1279     Compares this list view item to \a i using the column \a col in \a
       
  1280     ascending order. Returns \< 0 if this item is less than \a i, 0 if
       
  1281     they are equal and \> 0 if this item is greater than \a i.
       
  1282 
       
  1283     This function is used for sorting.
       
  1284 
       
  1285     The default implementation compares the item keys (key()) using
       
  1286     QString::localeAwareCompare(). A reimplementation can use
       
  1287     different values and a different comparison function. Here is a
       
  1288     reimplementation that uses plain Unicode comparison:
       
  1289 
       
  1290     \snippet doc/src/snippets/code/src_qt3support_itemviews_q3listview.cpp 3
       
  1291     We don't recommend using \a ascending so your code can safely
       
  1292     ignore it.
       
  1293 
       
  1294     \sa key() QString::localeAwareCompare() QString::compare()
       
  1295 */
       
  1296 
       
  1297 int Q3ListViewItem::compare(Q3ListViewItem *i, int col, bool ascending) const
       
  1298 {
       
  1299     return key(col, ascending).localeAwareCompare(i->key(col, ascending));
       
  1300 }
       
  1301 
       
  1302 /*!
       
  1303     Sorts this item's children using column \a column. This is done in
       
  1304     ascending order if \a ascending is true and in descending order if
       
  1305     \a ascending is false.
       
  1306 
       
  1307     Asks some of the children to sort their children. (Q3ListView and
       
  1308     Q3ListViewItem ensure that all on-screen objects are properly
       
  1309     sorted but may avoid or defer sorting other objects in order to be
       
  1310     more responsive.)
       
  1311 
       
  1312     \sa key() compare()
       
  1313 */
       
  1314 
       
  1315 void Q3ListViewItem::sortChildItems(int column, bool ascending)
       
  1316 {
       
  1317     // we try HARD not to sort.  if we're already sorted, don't.
       
  1318     if (column == (int)lsc && ascending == (bool)lso)
       
  1319         return;
       
  1320 
       
  1321     if (column < 0)
       
  1322         return;
       
  1323 
       
  1324     lsc = column;
       
  1325     lso = ascending;
       
  1326 
       
  1327     const int nColumns = (listView() ? listView()->columns() : 0);
       
  1328 
       
  1329     // and don't sort if we already have the right sorting order
       
  1330     if (column > nColumns || childItem == 0 || childItem->siblingItem == 0)
       
  1331         return;
       
  1332 
       
  1333     // make an array for qHeapSort()
       
  1334     Q3ListViewPrivate::SortableItem * siblings
       
  1335         = new Q3ListViewPrivate::SortableItem[nChildren];
       
  1336     Q3ListViewItem * s = childItem;
       
  1337     int i = 0;
       
  1338     while (s && i < nChildren) {
       
  1339         siblings[i].numCols = nColumns;
       
  1340         siblings[i].col = column;
       
  1341         siblings[i].asc = ascending;
       
  1342         siblings[i].item = s;
       
  1343         s = s->siblingItem;
       
  1344         i++;
       
  1345     }
       
  1346 
       
  1347     // and sort it.
       
  1348     qHeapSort(siblings, siblings + nChildren);
       
  1349 
       
  1350     // build the linked list of siblings, in the appropriate
       
  1351     // direction, and finally set this->childItem to the new top
       
  1352     // child.
       
  1353     if (ascending) {
       
  1354         for(i = 0; i < nChildren - 1; i++)
       
  1355             siblings[i].item->siblingItem = siblings[i+1].item;
       
  1356         siblings[nChildren-1].item->siblingItem = 0;
       
  1357         childItem = siblings[0].item;
       
  1358     } else {
       
  1359         for(i = nChildren - 1; i > 0; i--)
       
  1360             siblings[i].item->siblingItem = siblings[i-1].item;
       
  1361         siblings[0].item->siblingItem = 0;
       
  1362         childItem = siblings[nChildren-1].item;
       
  1363     }
       
  1364     for (i = 0; i < nChildren; i++) {
       
  1365         if (siblings[i].item->isOpen())
       
  1366             siblings[i].item->sort();
       
  1367     }
       
  1368     delete[] siblings;
       
  1369 }
       
  1370 
       
  1371 
       
  1372 /*!
       
  1373     Sets this item's height to \a height pixels. This implicitly
       
  1374     changes totalHeight(), too.
       
  1375 
       
  1376     Note that a font change causes this height to be overwritten
       
  1377     unless you reimplement setup().
       
  1378 
       
  1379     For best results in Windows style we suggest using an even number
       
  1380     of pixels.
       
  1381 
       
  1382     \sa height() totalHeight() isOpen()
       
  1383 */
       
  1384 
       
  1385 void Q3ListViewItem::setHeight(int height)
       
  1386 {
       
  1387     if (ownHeight != height) {
       
  1388         if (visible)
       
  1389             ownHeight = height;
       
  1390         else
       
  1391             ownHeight = 0;
       
  1392         invalidateHeight();
       
  1393     }
       
  1394 }
       
  1395 
       
  1396 
       
  1397 /*!
       
  1398     Invalidates the cached total height of this item, including all
       
  1399     open children.
       
  1400 
       
  1401     \sa setHeight() height() totalHeight()
       
  1402 */
       
  1403 
       
  1404 void Q3ListViewItem::invalidateHeight()
       
  1405 {
       
  1406     if (maybeTotalHeight < 0)
       
  1407         return;
       
  1408     maybeTotalHeight = -1;
       
  1409     if (parentItem && parentItem->isOpen())
       
  1410         parentItem->invalidateHeight();
       
  1411 }
       
  1412 
       
  1413 
       
  1414 /*!
       
  1415     Opens or closes an item, i.e. shows or hides an item's children.
       
  1416 
       
  1417     If \a o is true all child items are shown initially. The user can
       
  1418     hide them by clicking the \bold{-} icon to the left of the item.
       
  1419     If \a o is false, the children of this item are initially hidden.
       
  1420     The user can show them by clicking the \bold{+} icon to the left
       
  1421     of the item.
       
  1422 
       
  1423     \sa height() totalHeight() isOpen()
       
  1424 */
       
  1425 
       
  1426 void Q3ListViewItem::setOpen(bool o)
       
  1427 {
       
  1428     if (o == (bool)open || !enabled)
       
  1429         return;
       
  1430     open = o;
       
  1431 
       
  1432     // If no children to show simply emit signals and return
       
  1433     if (!nChildren) {
       
  1434         Q3ListView *lv = listView();
       
  1435         if (lv && this != lv->d->r) {
       
  1436             if (o)
       
  1437                 emit lv->expanded(this);
       
  1438             else
       
  1439                 emit lv->collapsed(this);
       
  1440 #ifndef QT_NO_ACCESSIBILITY
       
  1441             QAccessible::updateAccessibility(lv->viewport(), indexOfItem(this), QAccessible::StateChanged);
       
  1442 #endif
       
  1443         }
       
  1444         return;
       
  1445     }
       
  1446     invalidateHeight();
       
  1447 
       
  1448     if (!configured) {
       
  1449         Q3ListViewItem * l = this;
       
  1450         QStack<Q3ListViewItem *> s;
       
  1451         while(l) {
       
  1452             if (l->open && l->childItem) {
       
  1453                 s.push(l->childItem);
       
  1454             } else if (l->childItem) {
       
  1455                 // first invisible child is unconfigured
       
  1456                 Q3ListViewItem * c = l->childItem;
       
  1457                 while(c) {
       
  1458                     c->configured = false;
       
  1459                     c = c->siblingItem;
       
  1460                 }
       
  1461             }
       
  1462             l->configured = true;
       
  1463             l->setup();
       
  1464             l = (l == this) ? 0 : l->siblingItem;
       
  1465             if (!l && !s.isEmpty())
       
  1466                 l = s.pop();
       
  1467         }
       
  1468     }
       
  1469 
       
  1470     Q3ListView *lv = listView();
       
  1471 
       
  1472     if (open && lv)
       
  1473         enforceSortOrder();
       
  1474 
       
  1475     if (isVisible() && lv && lv->d && !lv->d->drawables.isEmpty())
       
  1476         lv->buildDrawableList();
       
  1477 
       
  1478     if (lv && this != lv->d->r) {
       
  1479         if (o)
       
  1480             emit lv->expanded(this);
       
  1481         else
       
  1482             emit lv->collapsed(this);
       
  1483 #ifndef QT_NO_ACCESSIBILITY
       
  1484         QAccessible::updateAccessibility(lv->viewport(), indexOfItem(this), QAccessible::StateChanged);
       
  1485 #endif
       
  1486     }
       
  1487 }
       
  1488 
       
  1489 
       
  1490 /*!
       
  1491     This virtual function is called before the first time Q3ListView
       
  1492     needs to know the height or any other graphical attribute of this
       
  1493     object, and whenever the font, GUI style, or colors of the list
       
  1494     view change.
       
  1495 
       
  1496     The default calls widthChanged() and sets the item's height to the
       
  1497     height of a single line of text in the list view's font. (If you
       
  1498     use icons, multi-line text, etc., you will probably need to call
       
  1499     setHeight() yourself or reimplement it.)
       
  1500 */
       
  1501 
       
  1502 void Q3ListViewItem::setup()
       
  1503 {
       
  1504     widthChanged();
       
  1505     Q3ListView *lv = listView();
       
  1506 
       
  1507     int ph = 0;
       
  1508     int h = 0;
       
  1509     if (lv) {
       
  1510         for (int i = 0; i < lv->d->column.size(); ++i) {
       
  1511             if (pixmap(i))
       
  1512                 ph = qMax(ph, pixmap(i)->height());
       
  1513         }
       
  1514 
       
  1515         if (mlenabled) {
       
  1516             h = ph;
       
  1517             for (int c = 0; c < lv->columns(); ++c) {
       
  1518                 int lines = text(c).count(QLatin1Char('\n')) + 1;
       
  1519                 int tmph = lv->d->fontMetricsHeight
       
  1520                            + lv->fontMetrics().lineSpacing() * (lines - 1);
       
  1521                 h = qMax(h, tmph);
       
  1522             }
       
  1523             h += 2*lv->itemMargin();
       
  1524         } else {
       
  1525             h = qMax(lv->d->fontMetricsHeight, ph) + 2*lv->itemMargin();
       
  1526         }
       
  1527     }
       
  1528 
       
  1529     h = qMax(h, QApplication::globalStrut().height());
       
  1530 
       
  1531     if (h % 2 > 0)
       
  1532         h++;
       
  1533     setHeight(h);
       
  1534 }
       
  1535 
       
  1536 
       
  1537 
       
  1538 
       
  1539 /*!
       
  1540     This virtual function is called whenever the user presses the mouse
       
  1541     on this item or presses Space on it.
       
  1542 
       
  1543     \sa activatedPos()
       
  1544 */
       
  1545 
       
  1546 void Q3ListViewItem::activate()
       
  1547 {
       
  1548 }
       
  1549 
       
  1550 
       
  1551 /*!
       
  1552     When called from a reimplementation of activate(), this function
       
  1553     gives information on how the item was activated. Otherwise the
       
  1554     behavior is undefined.
       
  1555 
       
  1556     If activate() was caused by a mouse press, the function sets \a
       
  1557     pos to where the user clicked and returns true; otherwise it
       
  1558     returns false and does not change \a pos.
       
  1559 
       
  1560     \a pos is relative to the top-left corner of this item.
       
  1561 
       
  1562     \sa activate()
       
  1563 */
       
  1564 
       
  1565 bool Q3ListViewItem::activatedPos(QPoint &pos)
       
  1566 {
       
  1567     if (activatedByClick)
       
  1568         pos = activatedP;
       
  1569     return activatedByClick;
       
  1570 }
       
  1571 
       
  1572 
       
  1573 /*!
       
  1574     \fn bool Q3ListViewItem::isSelectable() const
       
  1575 
       
  1576     Returns true if the item is selectable (as it is by default);
       
  1577     otherwise returns false
       
  1578 
       
  1579     \sa setSelectable()
       
  1580 */
       
  1581 
       
  1582 
       
  1583 /*!
       
  1584     Sets this items to be selectable if \a enable is true (the
       
  1585     default) or not to be selectable if \a enable is false.
       
  1586 
       
  1587     The user is not able to select a non-selectable item using either
       
  1588     the keyboard or the mouse. The application programmer still can
       
  1589     though, e.g. using setSelected().
       
  1590 
       
  1591     \sa isSelectable()
       
  1592 */
       
  1593 
       
  1594 void Q3ListViewItem::setSelectable(bool enable)
       
  1595 {
       
  1596     selectable = enable;
       
  1597 }
       
  1598 
       
  1599 
       
  1600 /*!
       
  1601     \fn bool Q3ListViewItem::isExpandable() const
       
  1602 
       
  1603     Returns true if this item is expandable even when it has no
       
  1604     children; otherwise returns false.
       
  1605 */
       
  1606 
       
  1607 /*!
       
  1608     Sets this item to be expandable even if it has no children if \a
       
  1609     enable is true, and to be expandable only if it has children if \a
       
  1610     enable is false (the default).
       
  1611 
       
  1612     The dirview example uses this in the canonical fashion. It checks
       
  1613     whether the directory is empty in setup() and calls
       
  1614     setExpandable(true) if not; in setOpen() it reads the contents of
       
  1615     the directory and inserts items accordingly. This strategy means
       
  1616     that dirview can display the entire file system without reading
       
  1617     very much at startup.
       
  1618 
       
  1619     Note that root items are not expandable by the user unless
       
  1620     Q3ListView::setRootIsDecorated() is set to true.
       
  1621 
       
  1622     \sa setSelectable()
       
  1623 */
       
  1624 
       
  1625 void Q3ListViewItem::setExpandable(bool enable)
       
  1626 {
       
  1627     expandable = enable;
       
  1628 }
       
  1629 
       
  1630 
       
  1631 /*!
       
  1632     Makes sure that this object's children are sorted appropriately.
       
  1633 
       
  1634     This only works if every item from the root item down to this item
       
  1635     is already sorted.
       
  1636 
       
  1637     \sa sortChildItems()
       
  1638 */
       
  1639 
       
  1640 void Q3ListViewItem::enforceSortOrder() const
       
  1641 {
       
  1642     Q3ListView *lv = listView();
       
  1643     if (!lv || (lv && (lv->d->clearing || lv->d->sortcolumn == Unsorted)))
       
  1644         return;
       
  1645     if (parentItem &&
       
  1646          (parentItem->lsc != lsc || parentItem->lso != lso))
       
  1647         ((Q3ListViewItem *)this)->sortChildItems((int)parentItem->lsc,
       
  1648                                                  (bool)parentItem->lso);
       
  1649     else if (!parentItem &&
       
  1650               ((int)lsc != lv->d->sortcolumn || (bool)lso != lv->d->ascending))
       
  1651         ((Q3ListViewItem *)this)->sortChildItems(lv->d->sortcolumn, lv->d->ascending);
       
  1652 }
       
  1653 
       
  1654 
       
  1655 /*!
       
  1656     \fn bool Q3ListViewItem::isSelected() const
       
  1657 
       
  1658     Returns true if this item is selected; otherwise returns false.
       
  1659 
       
  1660     \sa setSelected() Q3ListView::setSelected() Q3ListView::selectionChanged()
       
  1661 */
       
  1662 
       
  1663 
       
  1664 /*!
       
  1665     If \a s is true this item is selected; otherwise it is deselected.
       
  1666 
       
  1667     This function does not maintain any invariants or repaint anything
       
  1668     -- Q3ListView::setSelected() does that.
       
  1669 
       
  1670     \sa height() totalHeight()
       
  1671 */
       
  1672 
       
  1673 void Q3ListViewItem::setSelected(bool s)
       
  1674 {
       
  1675     bool old = selected;
       
  1676 
       
  1677     Q3ListView *lv = listView();
       
  1678     if (lv && lv->selectionMode() != Q3ListView::NoSelection) {
       
  1679         if (s && isSelectable())
       
  1680             selected = true;
       
  1681         else
       
  1682             selected = false;
       
  1683 
       
  1684 #ifndef QT_NO_ACCESSIBILITY
       
  1685         if (old != (bool)selected) {
       
  1686             int ind = indexOfItem(this);
       
  1687             QAccessible::updateAccessibility(lv->viewport(), ind, QAccessible::StateChanged);
       
  1688             QAccessible::updateAccessibility(lv->viewport(), ind, selected ? QAccessible::SelectionAdd : QAccessible::SelectionRemove);
       
  1689         }
       
  1690 #else
       
  1691         Q_UNUSED(old);
       
  1692 #endif
       
  1693     }
       
  1694 }
       
  1695 
       
  1696 /*!
       
  1697     Returns the total height of this object, including any visible
       
  1698     children. This height is recomputed lazily and cached for as long
       
  1699     as possible.
       
  1700 
       
  1701     Functions which can affect the total height are, setHeight() which
       
  1702     is used to set an item's height, setOpen() to show or hide an
       
  1703     item's children, and invalidateHeight() to invalidate the cached
       
  1704     height.
       
  1705 
       
  1706     \sa height()
       
  1707 */
       
  1708 
       
  1709 int Q3ListViewItem::totalHeight() const
       
  1710 {
       
  1711     if (!visible)
       
  1712         return 0;
       
  1713     if (maybeTotalHeight >= 0)
       
  1714         return maybeTotalHeight;
       
  1715     Q3ListViewItem * that = (Q3ListViewItem *)this;
       
  1716     if (!that->configured) {
       
  1717         that->configured = true;
       
  1718         that->setup(); // ### virtual non-const function called in const
       
  1719     }
       
  1720     that->maybeTotalHeight = that->ownHeight;
       
  1721 
       
  1722     if (!that->isOpen() || !that->childCount())
       
  1723         return that->ownHeight;
       
  1724 
       
  1725     Q3ListViewItem * child = that->childItem;
       
  1726     while (child != 0) {
       
  1727         that->maybeTotalHeight += child->totalHeight();
       
  1728         child = child->siblingItem;
       
  1729     }
       
  1730     return that->maybeTotalHeight;
       
  1731 }
       
  1732 
       
  1733 
       
  1734 /*!
       
  1735     Returns the text in column \a column, or an empty string if there is
       
  1736     no text in that column.
       
  1737 
       
  1738     \sa key() paintCell()
       
  1739 */
       
  1740 
       
  1741 QString Q3ListViewItem::text(int column) const
       
  1742 {
       
  1743     Q3ListViewPrivate::ItemColumnInfo * l
       
  1744         = (Q3ListViewPrivate::ItemColumnInfo*) columns;
       
  1745 
       
  1746     while(column && l) {
       
  1747         l = l->next;
       
  1748         column--;
       
  1749     }
       
  1750 
       
  1751     return l ? l->text : QString();
       
  1752 }
       
  1753 
       
  1754 
       
  1755 /*!
       
  1756     Sets the text in column \a column to \a text, if \a column is a
       
  1757     valid column number and \a text is different from the existing
       
  1758     text.
       
  1759 
       
  1760     If the text() function has been reimplemented, this function may
       
  1761     be a no-op.
       
  1762 
       
  1763     \sa text() key()
       
  1764 */
       
  1765 
       
  1766 void Q3ListViewItem::setText(int column, const QString &text)
       
  1767 {
       
  1768     if (column < 0)
       
  1769         return;
       
  1770 
       
  1771     Q3ListViewPrivate::ItemColumnInfo * l
       
  1772         = (Q3ListViewPrivate::ItemColumnInfo*) columns;
       
  1773     if (!l) {
       
  1774         l = new Q3ListViewPrivate::ItemColumnInfo;
       
  1775         columns = (void*)l;
       
  1776     }
       
  1777     for(int c = 0; c < column; c++) {
       
  1778         if (!l->next)
       
  1779             l->next = new Q3ListViewPrivate::ItemColumnInfo;
       
  1780         l = l->next;
       
  1781     }
       
  1782     if (l->text == text)
       
  1783         return;
       
  1784 
       
  1785     int oldLc = 0;
       
  1786     int newLc = 0;
       
  1787     if (mlenabled) {
       
  1788         if (!l->text.isEmpty())
       
  1789             oldLc = l->text.count(QLatin1Char('\n')) + 1;
       
  1790         if (!text.isEmpty())
       
  1791             newLc = text.count(QLatin1Char('\n')) + 1;
       
  1792     }
       
  1793 
       
  1794     l->dirty = true;
       
  1795     l->text = text;
       
  1796     if (column == (int)lsc)
       
  1797         lsc = Unsorted;
       
  1798 
       
  1799     if (mlenabled && oldLc != newLc)
       
  1800         setup();
       
  1801     else
       
  1802         widthChanged(column);
       
  1803 
       
  1804     Q3ListView * lv = listView();
       
  1805     if (lv) {
       
  1806         lv->triggerUpdate();
       
  1807 #ifndef QT_NO_ACCESSIBILITY
       
  1808         if (lv->isVisible())
       
  1809             QAccessible::updateAccessibility(lv->viewport(), indexOfItem(this), QAccessible::NameChanged);
       
  1810 #endif
       
  1811     }
       
  1812 }
       
  1813 
       
  1814 
       
  1815 /*!
       
  1816     Sets the pixmap in column \a column to \a pm, if \a pm is non-null
       
  1817     and different from the current pixmap, and if \a column is
       
  1818     non-negative.
       
  1819 
       
  1820     \sa pixmap() setText()
       
  1821 */
       
  1822 
       
  1823 void Q3ListViewItem::setPixmap(int column, const QPixmap & pm)
       
  1824 {
       
  1825     if (column < 0)
       
  1826         return;
       
  1827 
       
  1828     int oldW = 0;
       
  1829     int oldH = 0;
       
  1830     if (pixmap(column)) {
       
  1831         oldW = pixmap(column)->width();
       
  1832         oldH = pixmap(column)->height();
       
  1833     }
       
  1834 
       
  1835     Q3ListViewPrivate::ItemColumnInfo * l
       
  1836         = (Q3ListViewPrivate::ItemColumnInfo*) columns;
       
  1837     if (!l) {
       
  1838         l = new Q3ListViewPrivate::ItemColumnInfo;
       
  1839         columns = (void*)l;
       
  1840     }
       
  1841 
       
  1842     for(int c = 0; c < column; c++) {
       
  1843         if (!l->next)
       
  1844             l->next = new Q3ListViewPrivate::ItemColumnInfo;
       
  1845         l = l->next;
       
  1846     }
       
  1847 
       
  1848     if ((pm.isNull() && (!l->pm || l->pm->isNull())) ||
       
  1849          (l->pm && pm.serialNumber() == l->pm->serialNumber()))
       
  1850         return;
       
  1851 
       
  1852     if (pm.isNull()) {
       
  1853         delete l->pm;
       
  1854         l->pm = 0;
       
  1855     } else {
       
  1856         if (l->pm)
       
  1857             *(l->pm) = pm;
       
  1858         else
       
  1859             l->pm = new QPixmap(pm);
       
  1860     }
       
  1861 
       
  1862     int newW = 0;
       
  1863     int newH = 0;
       
  1864     if (pixmap(column)) {
       
  1865         newW = pixmap(column)->width();
       
  1866         newH = pixmap(column)->height();
       
  1867     }
       
  1868 
       
  1869     if (oldW != newW || oldH != newH) {
       
  1870         setup();
       
  1871         widthChanged(column);
       
  1872         invalidateHeight();
       
  1873     }
       
  1874     Q3ListView *lv = listView();
       
  1875     if (lv) {
       
  1876         lv->triggerUpdate();
       
  1877     }
       
  1878 }
       
  1879 
       
  1880 
       
  1881 /*!
       
  1882     Returns the pixmap for \a column, or 0 if there is no pixmap for
       
  1883     \a column.
       
  1884 
       
  1885     \sa setText() setPixmap()
       
  1886 */
       
  1887 
       
  1888 const QPixmap * Q3ListViewItem::pixmap(int column) const
       
  1889 {
       
  1890     Q3ListViewPrivate::ItemColumnInfo * l
       
  1891     = (Q3ListViewPrivate::ItemColumnInfo*) columns;
       
  1892 
       
  1893     while(column && l) {
       
  1894         l = l->next;
       
  1895         column--;
       
  1896     }
       
  1897 
       
  1898     return (l && l->pm) ? l->pm : 0;
       
  1899 }
       
  1900 
       
  1901 
       
  1902 /*
       
  1903     This function paints the contents of one column of an item
       
  1904     and aligns it as described by \a align.
       
  1905 
       
  1906     \a p is a QPainter open on the relevant paint device. \a p is
       
  1907     translated so (0, 0) is the top-left pixel in the cell and \a
       
  1908     width-1, height()-1 is the bottom-right pixel \e in the cell. The
       
  1909     other properties of \a p (pen, brush, etc) are undefined. \a pal is
       
  1910     the color group to use. \a column is the logical column number
       
  1911     within the item that is to be painted; 0 is the column which may
       
  1912     contain a tree.
       
  1913 
       
  1914     This function may use Q3ListView::itemMargin() for readability
       
  1915     spacing on the left and right sides of data such as text, and
       
  1916     should honor isSelected() and Q3ListView::allColumnsShowFocus().
       
  1917 
       
  1918     If you reimplement this function, you should also reimplement
       
  1919     width().
       
  1920 
       
  1921     The rectangle to be painted is in an undefined state when this
       
  1922     function is called, so you \e must draw on all the pixels. The
       
  1923     painter \a p has the right font on entry.
       
  1924 
       
  1925     \sa paintBranches(), Q3ListView::drawContentsOffset()
       
  1926 */
       
  1927 
       
  1928 static QStyleOptionQ3ListView getStyleOption(const Q3ListView *lv, const Q3ListViewItem *item,
       
  1929                                              bool hierarchy = false)
       
  1930 {
       
  1931     QStyleOptionQ3ListView opt;
       
  1932     opt.init(lv);
       
  1933     opt.subControls = QStyle::SC_None;
       
  1934     opt.activeSubControls = QStyle::SC_None;
       
  1935     QWidget *vp = lv->viewport();
       
  1936     opt.viewportPalette = vp->palette();
       
  1937     opt.viewportBGRole = vp->backgroundRole();
       
  1938     opt.itemMargin = lv->itemMargin();
       
  1939     opt.sortColumn = 0;
       
  1940     opt.treeStepSize = lv->treeStepSize();
       
  1941     opt.rootIsDecorated = lv->rootIsDecorated();
       
  1942     bool firstItem = true;
       
  1943     int y = item ? item->itemPos() : 0;
       
  1944     while (item) {
       
  1945         QStyleOptionQ3ListViewItem lvi;
       
  1946         lvi.height = item->height();
       
  1947         lvi.totalHeight = item->totalHeight();
       
  1948         lvi.itemY = y;
       
  1949         lvi.childCount = item->childCount();
       
  1950         lvi.features = QStyleOptionQ3ListViewItem::None;
       
  1951         lvi.state = QStyle::State_None;
       
  1952         if (item->isEnabled())
       
  1953             lvi.state |= QStyle::State_Enabled;
       
  1954         if (item->isOpen())
       
  1955             lvi.state |= QStyle::State_Open;
       
  1956         if (item->isExpandable())
       
  1957             lvi.features |= QStyleOptionQ3ListViewItem::Expandable;
       
  1958         if (item->multiLinesEnabled())
       
  1959             lvi.features |= QStyleOptionQ3ListViewItem::MultiLine;
       
  1960         if (item->isVisible())
       
  1961             lvi.features |= QStyleOptionQ3ListViewItem::Visible;
       
  1962         if (item->parent() && item->parent()->rtti() == 1
       
  1963             && static_cast<Q3CheckListItem *>(item->parent())->type() == Q3CheckListItem::Controller)
       
  1964             lvi.features |= QStyleOptionQ3ListViewItem::ParentControl;
       
  1965         opt.items.append(lvi);
       
  1966         // we only care about the children when we are painting the branches
       
  1967         // this is only enabled by Q3ListViewItem::paintBranches
       
  1968         if (hierarchy) {
       
  1969             if (!firstItem) {
       
  1970                 item = item->nextSibling();
       
  1971             } else {
       
  1972                 firstItem = false;
       
  1973                 item = item->firstChild();
       
  1974             }
       
  1975             y += lvi.height;
       
  1976         } else {
       
  1977             break;
       
  1978         }
       
  1979     }
       
  1980     return opt;
       
  1981 }
       
  1982 
       
  1983 /*!
       
  1984     \fn void Q3ListViewItem::paintCell(QPainter *painter, const QColorGroup & cg, int column, int width, int align)
       
  1985 
       
  1986     This virtual function paints the contents of one column of an item
       
  1987     and aligns it as described by \a align.
       
  1988 
       
  1989     The \a painter is a Q3Painter open on the relevant paint
       
  1990     device. It is translated so (0, 0) is the top-left pixel in the
       
  1991     cell and \a width - 1, height() - 1 is the bottom-right pixel \e
       
  1992     in the cell. The other properties of the \a painter (pen, brush, etc) are
       
  1993     undefined. \a cg is the color group to use. \a column is the
       
  1994     logical column number within the item that is to be painted; 0 is
       
  1995     the column which may contain a tree.
       
  1996 
       
  1997     This function may use Q3ListView::itemMargin() for readability
       
  1998     spacing on the left and right sides of data such as text, and
       
  1999     should honor \l isSelected() and
       
  2000     Q3ListView::allColumnsShowFocus().
       
  2001 
       
  2002     If you reimplement this function, you should also reimplement \l
       
  2003     width().
       
  2004 
       
  2005     The rectangle to be painted is in an undefined state when this
       
  2006     function is called, so you \e must draw on all the pixels. The
       
  2007     \a painter has the right font on entry.
       
  2008 
       
  2009     \sa paintBranches(), Q3ListView::drawContentsOffset()
       
  2010 */
       
  2011 void Q3ListViewItem::paintCell(QPainter * p, const QColorGroup & cg,
       
  2012                                int column, int width, int align)
       
  2013 {
       
  2014     // Change width() if you change this.
       
  2015 
       
  2016     QPalette pal = cg;
       
  2017     if (!p)
       
  2018         return;
       
  2019 
       
  2020     Q3ListView *lv = listView();
       
  2021     if (!lv)
       
  2022         return;
       
  2023     QFontMetrics fm(p->fontMetrics());
       
  2024 
       
  2025     // had, but we _need_ the column info for the ellipsis thingy!!!
       
  2026     if (!columns) {
       
  2027         for (int i = 0; i < lv->d->column.size(); ++i) {
       
  2028             setText(i, text(i));
       
  2029         }
       
  2030     }
       
  2031 
       
  2032     QString t = text(column);
       
  2033 
       
  2034     if (columns) {
       
  2035         Q3ListViewPrivate::ItemColumnInfo *ci = 0;
       
  2036         // try until we have a column info....
       
  2037         while (!ci) {
       
  2038             ci = (Q3ListViewPrivate::ItemColumnInfo*)columns;
       
  2039             for (int i = 0; ci && (i < column); ++i)
       
  2040                 ci = ci->next;
       
  2041 
       
  2042             if (!ci) {
       
  2043                 setText(column, t);
       
  2044                 ci = 0;
       
  2045             }
       
  2046         }
       
  2047 
       
  2048         // if the column width changed and this item was not painted since this change
       
  2049         if (ci && (ci->width != width || ci->text != t || ci->dirty)) {
       
  2050             ci->text = t;
       
  2051             ci->dirty = false;
       
  2052             ci->width = width;
       
  2053             ci->truncated = false;
       
  2054             // if we have to do the ellipsis thingy calc the truncated text
       
  2055             int pw = lv->itemMargin()*2 - lv->d->minLeftBearing - lv->d->minRightBearing;
       
  2056             pw += pixmap(column) ? pixmap(column)->width() + lv->itemMargin() : 0;
       
  2057             if (!mlenabled && fm.width(t) + pw > width) {
       
  2058                 // take care of arabic shaping in width calculation (lars)
       
  2059                 ci->truncated = true;
       
  2060                 ci->tmpText = qEllipsisText(t, fm, width - pw, align);
       
  2061             } else if (mlenabled && fm.width(t) + pw > width) {
       
  2062                 QStringList list = t.split(QLatin1Char('\n'));
       
  2063                 for (QStringList::Iterator it = list.begin(); it != list.end(); ++it) {
       
  2064                     QString z = *it;
       
  2065                     if (fm.width(z) + pw > width) {
       
  2066                         ci->truncated = true;
       
  2067                         *it = qEllipsisText(z, fm, width - pw, align);
       
  2068                     }
       
  2069                 }
       
  2070 
       
  2071                 if (ci->truncated)
       
  2072                     ci->tmpText = list.join(QString(QLatin1Char('\n')));
       
  2073             }
       
  2074         }
       
  2075 
       
  2076         // if we have to draw the ellipsis thingy, use the truncated text
       
  2077         if (ci && ci->truncated)
       
  2078             t = ci->tmpText;
       
  2079     }
       
  2080 
       
  2081     int marg = lv->itemMargin();
       
  2082     int r = marg;
       
  2083     const QPixmap * icon = pixmap(column);
       
  2084 
       
  2085     const QPalette::ColorRole crole = lv->viewport()->backgroundRole();
       
  2086     if (pal.brush(crole) != lv->palette().brush(pal.currentColorGroup(), crole))
       
  2087         p->fillRect(0, 0, width, height(), pal.brush(crole));
       
  2088     else
       
  2089         lv->paintEmptyArea(p, QRect(0, 0, width, height()));
       
  2090 
       
  2091     // (lars) what does this do???
       
  2092 #if 0 // RS: ####
       
  2093     if (align != Qt::AlignLeft)
       
  2094         marg -= lv->d->minRightBearing;
       
  2095 #endif
       
  2096     if (isSelected() &&
       
  2097          (column == 0 || lv->allColumnsShowFocus())) {
       
  2098         p->fillRect(r - marg, 0, qMax(0, width - r + marg), height(),
       
  2099                     pal.brush(QPalette::Highlight));
       
  2100         if (enabled || !lv)
       
  2101             p->setPen(pal.highlightedText().color());
       
  2102         else if (!enabled && lv)
       
  2103             p->setPen(lv->palette().color(QPalette::Disabled, QPalette::HighlightedText));
       
  2104     } else {
       
  2105         if (enabled || !lv)
       
  2106             p->setPen(pal.text().color());
       
  2107         else if (!enabled && lv)
       
  2108             p->setPen(lv->palette().color(QPalette::Disabled, QPalette::Text));
       
  2109     }
       
  2110 
       
  2111 
       
  2112 #if 0
       
  2113     bool reverse = QApplication::reverseLayout();
       
  2114 #else
       
  2115     bool reverse = false;
       
  2116 #endif
       
  2117     int iconWidth = 0;
       
  2118 
       
  2119     if (icon) {
       
  2120         iconWidth = icon->width() + lv->itemMargin();
       
  2121         int xo = r;
       
  2122         // we default to Qt::AlignVCenter.
       
  2123         int yo = (height() - icon->height()) / 2;
       
  2124 
       
  2125         // I guess we may as well always respect vertical alignment.
       
  2126         if (align & Qt::AlignBottom)
       
  2127             yo = height() - icon->height();
       
  2128         else if (align & Qt::AlignTop)
       
  2129             yo = 0;
       
  2130 
       
  2131         // respect horizontal alignment when there is no text for an item.
       
  2132         if (text(column).isEmpty()) {
       
  2133             if (align & Qt::AlignRight)
       
  2134                 xo = width - 2 * marg - iconWidth;
       
  2135             else if (align & Qt::AlignHCenter)
       
  2136                 xo = (width - iconWidth) / 2;
       
  2137         }
       
  2138         if (reverse)
       
  2139                 xo = width - 2 * marg - iconWidth;
       
  2140         p->drawPixmap(xo, yo, *icon);
       
  2141     }
       
  2142 
       
  2143     if (!t.isEmpty()) {
       
  2144         if (!mlenabled) {
       
  2145             if (!(align & Qt::AlignTop || align & Qt::AlignBottom))
       
  2146                 align |= Qt::AlignVCenter;
       
  2147         } else {
       
  2148             if (!(align & Qt::AlignVCenter || align & Qt::AlignBottom))
       
  2149                 align |= Qt::AlignTop;
       
  2150         }
       
  2151         if (!reverse)
       
  2152             r += iconWidth;
       
  2153 
       
  2154         if (!mlenabled) {
       
  2155             p->drawText(r, 0, width-marg-r, height(), align, t);
       
  2156         } else {
       
  2157             p->drawText(r, marg, width-marg-r, height(), align, t);
       
  2158         }
       
  2159     }
       
  2160 
       
  2161     if (mlenabled && column == 0 && isOpen() && childCount()) {
       
  2162         int textheight = fm.size(align, t).height() + 2 * lv->itemMargin();
       
  2163         textheight = qMax(textheight, QApplication::globalStrut().height());
       
  2164         if (textheight % 2 > 0)
       
  2165             textheight++;
       
  2166         if (textheight < height()) {
       
  2167             int w = lv->treeStepSize() / 2;
       
  2168             QStyleOptionQ3ListView opt = getStyleOption(lv, this);
       
  2169             opt.rect.setRect(0, textheight, w + 1, height() - textheight + 1);
       
  2170             opt.palette = pal;
       
  2171             opt.subControls = QStyle::SC_Q3ListViewExpand;
       
  2172             opt.activeSubControls = QStyle::SC_All;
       
  2173             lv->style()->drawComplexControl(QStyle::CC_Q3ListView, &opt, p, lv);
       
  2174         }
       
  2175     }
       
  2176 }
       
  2177 
       
  2178 /*!
       
  2179     Returns the number of pixels of width required to draw column \a c
       
  2180     of list view \a lv, using the metrics \a fm without cropping. The
       
  2181     list view containing this item may use this information depending
       
  2182     on the Q3ListView::WidthMode settings for the column.
       
  2183 
       
  2184     The default implementation returns the width of the bounding
       
  2185     rectangle of the text of column \a c.
       
  2186 
       
  2187     \sa listView() widthChanged() Q3ListView::setColumnWidthMode()
       
  2188     Q3ListView::itemMargin()
       
  2189 */
       
  2190 int Q3ListViewItem::width(const QFontMetrics& fm,
       
  2191                           const Q3ListView* lv, int c) const
       
  2192 {
       
  2193     int w;
       
  2194     if (mlenabled)
       
  2195         w = fm.size(Qt::AlignVCenter, text(c)).width() + lv->itemMargin() * 2
       
  2196             - lv->d->minLeftBearing - lv->d->minRightBearing;
       
  2197     else
       
  2198         w = fm.width(text(c)) + lv->itemMargin() * 2
       
  2199             - lv->d->minLeftBearing - lv->d->minRightBearing;
       
  2200     const QPixmap * pm = pixmap(c);
       
  2201     if (pm)
       
  2202         w += pm->width() + lv->itemMargin(); // ### correct margin stuff?
       
  2203     return qMax(w, QApplication::globalStrut().width());
       
  2204 }
       
  2205 
       
  2206 
       
  2207 /*!
       
  2208     Paints a focus indicator on the rectangle \a r using painter \a p
       
  2209     and colors \a cg.
       
  2210 
       
  2211     \a p is already clipped.
       
  2212 
       
  2213     \sa paintCell() paintBranches() Q3ListView::setAllColumnsShowFocus()
       
  2214 */
       
  2215 
       
  2216 void Q3ListViewItem::paintFocus(QPainter *p, const QColorGroup &cg, const QRect &r)
       
  2217 {
       
  2218     QPalette pal = cg;
       
  2219     Q3ListView *lv = listView();
       
  2220     if (lv) {
       
  2221         QStyleOptionFocusRect opt;
       
  2222         opt.init(lv);
       
  2223         opt.rect = r;
       
  2224         opt.palette = pal;
       
  2225         opt.state |= QStyle::State_KeyboardFocusChange;
       
  2226         if (isSelected()) {
       
  2227             opt.state |= QStyle::State_FocusAtBorder;
       
  2228             opt.backgroundColor = pal.highlight().color();
       
  2229         } else {
       
  2230             opt.state |= QStyle::State_None;
       
  2231             opt.backgroundColor = pal.base().color();
       
  2232         }
       
  2233         lv->style()->drawPrimitive(QStyle::PE_FrameFocusRect, &opt, p, lv);
       
  2234     }
       
  2235 }
       
  2236 
       
  2237 
       
  2238 /*!
       
  2239     Paints a set of branches from this item to (some of) its children.
       
  2240 
       
  2241     Painter \a p is set up with clipping and translation so that you
       
  2242     can only draw in the rectangle that needs redrawing; \a cg is the
       
  2243     color group to use; the update rectangle is at (0, 0) and has size
       
  2244     width \a w by height \a h. The top of the rectangle you own is at
       
  2245     \a y (which is never greater than 0 but can be outside the window
       
  2246     system's allowed coordinate range).
       
  2247 
       
  2248     The update rectangle is in an undefined state when this function
       
  2249     is called; this function must draw on \e all of the pixels.
       
  2250 
       
  2251     \sa paintCell(), Q3ListView::drawContentsOffset()
       
  2252 */
       
  2253 
       
  2254 void Q3ListViewItem::paintBranches(QPainter * p, const QColorGroup & cg,
       
  2255                                    int w, int y, int h)
       
  2256 {
       
  2257     Q3ListView *lv = listView();
       
  2258     if (lv)
       
  2259         lv->paintEmptyArea(p, QRect(0, 0, w, h));
       
  2260     if (!visible || !lv)
       
  2261         return;
       
  2262     QStyleOptionQ3ListView opt = getStyleOption(lv, this, true);
       
  2263     opt.rect.setRect(0, y, w, h);
       
  2264     opt.palette = cg;
       
  2265     opt.subControls = QStyle::SC_Q3ListViewBranch | QStyle::SC_Q3ListViewExpand;
       
  2266     opt.activeSubControls = QStyle::SC_None;
       
  2267     lv->style()->drawComplexControl(QStyle::CC_Q3ListView, &opt, p, lv);
       
  2268 }
       
  2269 
       
  2270 
       
  2271 Q3ListViewPrivate::Root::Root(Q3ListView * parent)
       
  2272     : Q3ListViewItem(parent)
       
  2273 {
       
  2274     lv = parent;
       
  2275     setHeight(0);
       
  2276     setOpen(true);
       
  2277 }
       
  2278 
       
  2279 
       
  2280 void Q3ListViewPrivate::Root::setHeight(int)
       
  2281 {
       
  2282     Q3ListViewItem::setHeight(0);
       
  2283 }
       
  2284 
       
  2285 
       
  2286 void Q3ListViewPrivate::Root::invalidateHeight()
       
  2287 {
       
  2288     Q3ListViewItem::invalidateHeight();
       
  2289     lv->triggerUpdate();
       
  2290 }
       
  2291 
       
  2292 
       
  2293 Q3ListView * Q3ListViewPrivate::Root::theListView() const
       
  2294 {
       
  2295     return lv;
       
  2296 }
       
  2297 
       
  2298 
       
  2299 void Q3ListViewPrivate::Root::setup()
       
  2300 {
       
  2301     // explicitly nothing
       
  2302 }
       
  2303 
       
  2304 
       
  2305 
       
  2306 /*!
       
  2307 \internal
       
  2308 If called after a mouse click, tells the list view to ignore a
       
  2309 following double click. This state is reset after the next mouse click.
       
  2310 */
       
  2311 
       
  2312 void Q3ListViewItem::ignoreDoubleClick()
       
  2313 {
       
  2314     Q3ListView *lv = listView();
       
  2315     if (lv)
       
  2316         lv->d->ignoreDoubleClick = true;
       
  2317 }
       
  2318 
       
  2319 
       
  2320 
       
  2321 /*!
       
  2322     \fn void  Q3ListView::onItem(Q3ListViewItem *i)
       
  2323 
       
  2324     This signal is emitted when the user moves the mouse cursor onto
       
  2325     item \a i, similar to the QWidget::enterEvent() function.
       
  2326 */
       
  2327 
       
  2328 // ### bug here too? see qiconview.cppp onItem/onViewport
       
  2329 
       
  2330 /*!
       
  2331     \fn void  Q3ListView::onViewport()
       
  2332 
       
  2333     This signal is emitted when the user moves the mouse cursor from
       
  2334     an item to an empty part of the list view.
       
  2335 */
       
  2336 
       
  2337 /*!
       
  2338     \enum Q3ListView::SelectionMode
       
  2339 
       
  2340     This enumerated type is used by Q3ListView to indicate how it
       
  2341     reacts to selection by the user.
       
  2342 
       
  2343     \value Single  When the user selects an item, any already-selected
       
  2344     item becomes unselected, and the user cannot unselect the selected
       
  2345     item.
       
  2346 
       
  2347     \value Multi  When the user selects an item in the usual way, the
       
  2348     selection status of that item is toggled and the other items are
       
  2349     left alone.
       
  2350 
       
  2351     \value Extended When the user selects an item in the usual way,
       
  2352     the selection is cleared and the new item selected. However, if
       
  2353     the user presses the Ctrl key when clicking on an item, the
       
  2354     clicked item gets toggled and all other items are left untouched.
       
  2355     And if the user presses the Shift key while clicking on an item,
       
  2356     all items between the current item and the clicked item get
       
  2357     selected or unselected, depending on the state of the clicked
       
  2358     item. Also, multiple items can be selected by dragging the mouse
       
  2359     over them.
       
  2360 
       
  2361     \value NoSelection  Items cannot be selected.
       
  2362 
       
  2363     In other words, \c Single is a real single-selection list view, \c
       
  2364     Multi a real multi-selection list view, \c Extended is a list view
       
  2365     where users can select multiple items but usually want to select
       
  2366     either just one or a range of contiguous items, and \c NoSelection
       
  2367     is a list view where the user can look but not touch.
       
  2368 */
       
  2369 
       
  2370 /*!
       
  2371     \enum Q3ListView::ResizeMode
       
  2372 
       
  2373     This enum describes how the list view's header adjusts to resize
       
  2374     events which affect the width of the list view.
       
  2375 
       
  2376     \value NoColumn The columns do not get resized in resize events.
       
  2377 
       
  2378     \value AllColumns All columns are resized equally to fit the width
       
  2379     of the list view.
       
  2380 
       
  2381     \value LastColumn The last column is resized to fit the width of
       
  2382     the list view.
       
  2383 */
       
  2384 
       
  2385 /*!
       
  2386     \enum Q3ListView::RenameAction
       
  2387 
       
  2388     This enum describes whether a rename operation is accepted if the
       
  2389     rename editor loses focus without the user pressing Enter.
       
  2390 
       
  2391     \value Accept Rename if Enter is pressed or focus is lost.
       
  2392 
       
  2393     \value Reject Discard the rename operation if focus is lost (and
       
  2394     Enter has not been pressed).
       
  2395 */
       
  2396 
       
  2397 /*!
       
  2398     \class Q3ListView
       
  2399     \brief The Q3ListView class implements a list/tree view.
       
  2400 
       
  2401     \compat
       
  2402 
       
  2403     It can display and control a hierarchy of multi-column items, and
       
  2404     provides the ability to add new items at any time. The user may
       
  2405     select one or many items (depending on the \c SelectionMode) and
       
  2406     sort the list in increasing or decreasing order by any column.
       
  2407 
       
  2408     The simplest pattern of use is to create a Q3ListView, add some
       
  2409     column headers using addColumn() and create one or more
       
  2410     Q3ListViewItem or Q3CheckListItem objects with the Q3ListView as
       
  2411     parent.
       
  2412 
       
  2413     Further nodes can be added to the list view object (the root of the
       
  2414     tree) or as child nodes to Q3ListViewItems.
       
  2415 
       
  2416     The main setup functions are:
       
  2417     \table
       
  2418     \header \i Function \i Action
       
  2419     \row \i \l addColumn()
       
  2420          \i Adds a column with a text label and perhaps width. Columns
       
  2421             are counted from the left starting with column 0.
       
  2422     \row \i \l setColumnWidthMode()
       
  2423          \i Sets the column to be resized automatically or not.
       
  2424     \row \i \l setAllColumnsShowFocus()
       
  2425          \i Sets whether items should show keyboard focus using all
       
  2426             columns or just column 0. The default is to show focus
       
  2427             just using column 0.
       
  2428     \row \i \l setRootIsDecorated()
       
  2429          \i Sets whether root items can be opened and closed by the
       
  2430             user and have open/close decoration to their left. The
       
  2431             default is false.
       
  2432     \row \i \l setTreeStepSize()
       
  2433          \i Sets how many pixels an item's children are indented
       
  2434             relative to their parent. The default is 20. This is
       
  2435             mostly a matter of taste.
       
  2436     \row \i \l setSorting()
       
  2437          \i Sets whether the items should be sorted, whether it should
       
  2438             be in ascending or descending order, and by what column
       
  2439             they should be sorted. By default the list view is sorted
       
  2440             by the first column; to switch this off call setSorting(-1).
       
  2441     \endtable
       
  2442 
       
  2443     There are several functions for mapping between items and
       
  2444     coordinates. itemAt() returns the item at a position on-screen,
       
  2445     itemRect() returns the rectangle an item occupies on the screen,
       
  2446     and itemPos() returns the position of any item (whether it is
       
  2447     on-screen or not). firstChild() returns the list view's first item
       
  2448     (not necessarily visible on-screen).
       
  2449 
       
  2450     You can iterate over visible items using
       
  2451     Q3ListViewItem::itemBelow(); over a list view's top-level items
       
  2452     using Q3ListViewItem::firstChild() and
       
  2453     Q3ListViewItem::nextSibling(); or every item using a
       
  2454     Q3ListViewItemIterator. See
       
  2455     the Q3ListViewItem documentation for examples of traversal.
       
  2456 
       
  2457     An item can be moved amongst its siblings using
       
  2458     Q3ListViewItem::moveItem(). To move an item in the hierarchy use
       
  2459     takeItem() and insertItem(). Item's (and all their child items)
       
  2460     are deleted with \c delete; to delete all the list view's items
       
  2461     use clear().
       
  2462 
       
  2463     There are a variety of selection modes described in the
       
  2464     Q3ListView::SelectionMode documentation. The default is \c Single
       
  2465     selection, which you can change using setSelectionMode().
       
  2466 
       
  2467     Because Q3ListView offers multiple selection it must display
       
  2468     keyboard focus and selection state separately. Therefore there are
       
  2469     functions both to set the selection state of an item
       
  2470     (setSelected()) and to set which item displays keyboard focus
       
  2471     (setCurrentItem()).
       
  2472 
       
  2473     Q3ListView emits two groups of signals; one group signals changes
       
  2474     in selection/focus state and one indicates selection. The first
       
  2475     group consists of selectionChanged() (applicable to all list
       
  2476     views), selectionChanged(Q3ListViewItem*) (applicable only to a
       
  2477     \c Single selection list view), and currentChanged(Q3ListViewItem*).
       
  2478     The second group consists of doubleClicked(Q3ListViewItem*),
       
  2479     returnPressed(Q3ListViewItem*),
       
  2480     rightButtonClicked(Q3ListViewItem*, const QPoint&, int), etc.
       
  2481 
       
  2482     Note that changing the state of the list view in a slot connected
       
  2483     to a list view signal may cause unexpected side effects. If you
       
  2484     need to change the list view's state in response to a signal, use
       
  2485     a \link QTimer::singleShot() single shot timer\endlink with a
       
  2486     time out of 0, and connect this timer to a slot that modifies the
       
  2487     list view's state.
       
  2488 
       
  2489     In Motif style, Q3ListView deviates fairly strongly from the look
       
  2490     and feel of the Motif hierarchical tree view. This is done mostly
       
  2491     to provide a usable keyboard interface and to make the list view
       
  2492     look better with a white background.
       
  2493 
       
  2494     If selectionMode() is \c Single (the default) the user can select
       
  2495     one item at a time, e.g. by clicking an item with the mouse, see
       
  2496     \l Q3ListView::SelectionMode for details.
       
  2497 
       
  2498     The list view can be navigated either using the mouse or the
       
  2499     keyboard. Clicking a \bold{-} icon closes an item (hides its
       
  2500     children) and clicking a \bold{+} icon opens an item (shows its
       
  2501     children). The keyboard controls are these:
       
  2502     \table
       
  2503     \header \i Keypress \i Action
       
  2504     \row \i Home
       
  2505          \i Make the first item current and visible.
       
  2506     \row \i End
       
  2507          \i Make the last item current and visible.
       
  2508     \row \i Page Up
       
  2509          \i Make the item above the top visible item current and visible.
       
  2510     \row \i Page Down
       
  2511          \i Make the item below the bottom visible item current and visible.
       
  2512     \row \i Up Arrow
       
  2513          \i Make the item above the current item current and visible.
       
  2514     \row \i Down Arrow
       
  2515          \i Make the item below the current item current and visible.
       
  2516     \row \i Left Arrow
       
  2517          \i If the current item is closed (\bold{+} icon) or has no
       
  2518             children, make its parent item current and visible. If the
       
  2519             current item is open (\bold{-} icon) close it, i.e. hide its
       
  2520             children. Exception: if the current item is the first item
       
  2521             and is closed and the horizontal scroll bar is offset to
       
  2522             the right the list view will be scrolled left.
       
  2523     \row \i Right Arrow
       
  2524          \i If the current item is closed (\bold{+} icon) and has
       
  2525             children, the item is opened. If the current item is
       
  2526             opened (\bold{-} icon) and has children the item's first
       
  2527             child is made current and visible. If the current item has
       
  2528             no children the list view is scrolled right.
       
  2529     \endtable
       
  2530 
       
  2531     If the user starts typing letters with the focus in the list view
       
  2532     an incremental search will occur. For example if the user types
       
  2533     'd' the current item will change to the first item that begins
       
  2534     with the letter 'd'; if they then type 'a', the current item will
       
  2535     change to the first item that begins with 'da', and so on. If no
       
  2536     item begins with the letters they type the current item doesn't
       
  2537     change.
       
  2538 
       
  2539     Note that the list view's size hint is calculated taking into
       
  2540     account the height \e and width to produce a nice aspect ratio.
       
  2541     This may mean that you need to reimplement sizeHint() in some
       
  2542     cases.
       
  2543 
       
  2544     \warning The list view assumes ownership of all list view items
       
  2545     and will delete them when it does not need them any more.
       
  2546 
       
  2547     \sa Q3ListViewItem Q3CheckListItem
       
  2548 */
       
  2549 
       
  2550 /*!
       
  2551     \fn void Q3ListView::itemRenamed(Q3ListViewItem * item, int col)
       
  2552 
       
  2553     \overload
       
  2554 
       
  2555     This signal is emitted when \a item has been renamed, e.g. by
       
  2556     in-place renaming, in column \a col.
       
  2557 
       
  2558     \sa Q3ListViewItem::setRenameEnabled()
       
  2559 */
       
  2560 
       
  2561 /*!
       
  2562     \fn void Q3ListView::itemRenamed(Q3ListViewItem * item, int col, const QString &text)
       
  2563 
       
  2564     This signal is emitted when \a item has been renamed to \a text,
       
  2565     e.g. by in in-place renaming, in column \a col.
       
  2566 
       
  2567     \sa Q3ListViewItem::setRenameEnabled()
       
  2568 */
       
  2569 
       
  2570 /*!
       
  2571     Constructs a new empty list view called \a name with parent \a
       
  2572     parent and widget attributes \a f.
       
  2573 
       
  2574     This constructor sets the \c WA_StaticContent and the \c
       
  2575     Qt::WA_NoBackground attributes to boost performance when drawing
       
  2576     Q3ListViewItems. This may be unsuitable for custom Q3ListViewItem
       
  2577     classes, in which case Qt::WA_StaticContents and Qt::WA_NoBackground
       
  2578     should be cleared on the viewport() after construction.
       
  2579 
       
  2580     \sa QWidget::setAttribute()
       
  2581 */
       
  2582 Q3ListView::Q3ListView(QWidget * parent, const char *name, Qt::WindowFlags f)
       
  2583     : Q3ScrollView(parent, name, f | Qt::WStaticContents | Qt::WNoAutoErase)
       
  2584 {
       
  2585     init();
       
  2586 }
       
  2587 
       
  2588 void Q3ListView::init()
       
  2589 {
       
  2590     d = new Q3ListViewPrivate;
       
  2591     d->vci = 0;
       
  2592     d->timer = new QTimer(this);
       
  2593     d->levelWidth = 20;
       
  2594     d->r = 0;
       
  2595     d->rootIsExpandable = 0;
       
  2596     d->h = new Q3Header(this, "list view header");
       
  2597     d->h->installEventFilter(this);
       
  2598     d->focusItem = 0;
       
  2599     d->oldFocusItem = 0;
       
  2600     d->dirtyItemTimer = new QTimer(this);
       
  2601     d->visibleTimer = new QTimer(this);
       
  2602     d->renameTimer = new QTimer(this);
       
  2603     d->autoopenTimer = new QTimer(this);
       
  2604     d->margin = 1;
       
  2605     d->selectionMode = Q3ListView::Single;
       
  2606     d->sortcolumn = 0;
       
  2607     d->ascending = true;
       
  2608     d->allColumnsShowFocus = false;
       
  2609     d->fontMetricsHeight = fontMetrics().height();
       
  2610     d->h->setTracking(true);
       
  2611     d->buttonDown = false;
       
  2612     d->ignoreDoubleClick = false;
       
  2613     d->scrollTimer = 0;
       
  2614     d->sortIndicator = false;
       
  2615     d->clearing = false;
       
  2616     d->minLeftBearing = fontMetrics().minLeftBearing();
       
  2617     d->minRightBearing = fontMetrics().minRightBearing();
       
  2618     d->ellipsisWidth = fontMetrics().width(QLatin1String("...")) * 2;
       
  2619     d->highlighted = 0;
       
  2620     d->pressedItem = 0;
       
  2621     d->selectAnchor = 0;
       
  2622     d->select = true;
       
  2623     d->startDragItem = 0;
       
  2624     d->toolTips = true;
       
  2625     d->updateHeader = false;
       
  2626     d->fullRepaintOnComlumnChange = false;
       
  2627     d->resizeMode = NoColumn;
       
  2628     d->defRenameAction = Reject;
       
  2629     d->pressedEmptyArea = false;
       
  2630     d->startEdit = true;
       
  2631     d->ignoreEditAfterFocus = false;
       
  2632     d->inMenuMode = false;
       
  2633     d->pressedSelected = false;
       
  2634 
       
  2635     setMouseTracking(true);
       
  2636     viewport()->setMouseTracking(true);
       
  2637 
       
  2638     connect(d->timer, SIGNAL(timeout()),
       
  2639              this, SLOT(updateContents()));
       
  2640     connect(d->dirtyItemTimer, SIGNAL(timeout()),
       
  2641              this, SLOT(updateDirtyItems()));
       
  2642     connect(d->visibleTimer, SIGNAL(timeout()),
       
  2643              this, SLOT(makeVisible()));
       
  2644     connect(d->renameTimer, SIGNAL(timeout()),
       
  2645              this, SLOT(startRename()));
       
  2646     connect(d->autoopenTimer, SIGNAL(timeout()),
       
  2647              this, SLOT(openFocusItem()));
       
  2648 
       
  2649     connect(d->h, SIGNAL(sizeChange(int,int,int)),
       
  2650              this, SLOT(handleSizeChange(int,int,int)));
       
  2651     connect(d->h, SIGNAL(indexChange(int,int,int)),
       
  2652              this, SLOT(handleIndexChange()));
       
  2653     connect(d->h, SIGNAL(sectionClicked(int)),
       
  2654              this, SLOT(changeSortColumn(int)));
       
  2655     connect(d->h, SIGNAL(sectionHandleDoubleClicked(int)),
       
  2656              this, SLOT(adjustColumn(int)));
       
  2657     connect(horizontalScrollBar(), SIGNAL(sliderMoved(int)),
       
  2658              d->h, SLOT(setOffset(int)));
       
  2659     connect(horizontalScrollBar(), SIGNAL(valueChanged(int)),
       
  2660              d->h, SLOT(setOffset(int)));
       
  2661 
       
  2662     // will access d->r
       
  2663     Q3ListViewPrivate::Root * r = new Q3ListViewPrivate::Root(this);
       
  2664     r->is_root = true;
       
  2665     d->r = r;
       
  2666     d->r->setSelectable(false);
       
  2667 
       
  2668     viewport()->setFocusProxy(this);
       
  2669     viewport()->setFocusPolicy(Qt::WheelFocus);
       
  2670     setFocusPolicy(Qt::WheelFocus);
       
  2671     viewport()->setBackgroundRole(QPalette::Base);
       
  2672     setAttribute(Qt::WA_MacShowFocusRect);
       
  2673 }
       
  2674 
       
  2675 /*!
       
  2676     \property Q3ListView::showSortIndicator
       
  2677     \brief whether the list view header should display a sort indicator.
       
  2678 
       
  2679     If this property is true, an arrow is drawn in the header of the
       
  2680     list view to indicate the sort order of the list view contents.
       
  2681     The arrow will be drawn in the correct column and will point up or
       
  2682     down, depending on the current sort direction. The default is
       
  2683     false (don't show an indicator).
       
  2684 
       
  2685     \sa Q3Header::setSortIndicator()
       
  2686 */
       
  2687 
       
  2688 void Q3ListView::setShowSortIndicator(bool show)
       
  2689 {
       
  2690     if (show == d->sortIndicator)
       
  2691         return;
       
  2692 
       
  2693     d->sortIndicator = show;
       
  2694     if (d->sortcolumn != Unsorted && d->sortIndicator)
       
  2695         d->h->setSortIndicator(d->sortcolumn, d->ascending);
       
  2696     else
       
  2697         d->h->setSortIndicator(-1);
       
  2698 }
       
  2699 
       
  2700 bool Q3ListView::showSortIndicator() const
       
  2701 {
       
  2702     return d->sortIndicator;
       
  2703 }
       
  2704 
       
  2705 /*!
       
  2706     \property Q3ListView::showToolTips
       
  2707     \brief whether this list view should show tooltips for truncated column texts
       
  2708 
       
  2709     The default is true.
       
  2710 */
       
  2711 
       
  2712 void Q3ListView::setShowToolTips(bool b)
       
  2713 {
       
  2714     d->toolTips = b;
       
  2715 }
       
  2716 
       
  2717 bool Q3ListView::showToolTips() const
       
  2718 {
       
  2719     return d->toolTips;
       
  2720 }
       
  2721 
       
  2722 /*!
       
  2723     \property Q3ListView::resizeMode
       
  2724     \brief whether all, none or the only the last column should be resized
       
  2725 
       
  2726     Specifies whether all, none or only the last column should be
       
  2727     resized to fit the full width of the list view. The values for this
       
  2728     property can be one of: \c NoColumn (the default), \c AllColumns
       
  2729     or \c LastColumn.
       
  2730 
       
  2731     \warning Setting the resize mode should be done after all necessary
       
  2732     columns have been added to the list view, otherwise the behavior is
       
  2733     undefined.
       
  2734 
       
  2735     \sa Q3Header, header()
       
  2736 */
       
  2737 
       
  2738 void Q3ListView::setResizeMode(ResizeMode m)
       
  2739 {
       
  2740     d->resizeMode = m;
       
  2741     if (m == NoColumn)
       
  2742         header()->setStretchEnabled(false);
       
  2743     else if (m == AllColumns)
       
  2744         header()->setStretchEnabled(true);
       
  2745     else
       
  2746         header()->setStretchEnabled(true, header()->count() - 1);
       
  2747 }
       
  2748 
       
  2749 Q3ListView::ResizeMode Q3ListView::resizeMode() const
       
  2750 {
       
  2751     return d->resizeMode;
       
  2752 }
       
  2753 
       
  2754 /*!
       
  2755     Destroys the list view, deleting all its items, and frees up all
       
  2756     allocated resources.
       
  2757 */
       
  2758 
       
  2759 Q3ListView::~Q3ListView()
       
  2760 {
       
  2761     for (int j = 0; j < d->iterators.size(); ++j) {
       
  2762         Q3ListViewItemIterator *i = d->iterators.at(j);
       
  2763         i->listView = 0;
       
  2764     }
       
  2765 
       
  2766     d->focusItem = 0;
       
  2767     delete d->r;
       
  2768     d->r = 0;
       
  2769     delete d->vci;
       
  2770     d->vci = 0;
       
  2771 #if 0
       
  2772     delete d->toolTip;
       
  2773     d->toolTip = 0;
       
  2774 #endif
       
  2775     delete d;
       
  2776     d = 0;
       
  2777 }
       
  2778 
       
  2779 
       
  2780 /*!
       
  2781     Calls Q3ListViewItem::paintCell() and
       
  2782     Q3ListViewItem::paintBranches() as necessary for all list view
       
  2783     items that require repainting in the \a cw pixels wide and \a ch
       
  2784     pixels high bounding rectangle starting at position \a cx, \a cy
       
  2785     with offset \a ox, \a oy. Uses the painter \a p.
       
  2786 */
       
  2787 
       
  2788 void Q3ListView::drawContentsOffset(QPainter * p, int ox, int oy,
       
  2789                                     int cx, int cy, int cw, int ch)
       
  2790 {
       
  2791     if (columns() == 0) {
       
  2792         paintEmptyArea(p, QRect(cx, cy, cw, ch));
       
  2793         return;
       
  2794     }
       
  2795 
       
  2796     if (d->drawables.isEmpty() ||
       
  2797          d->topPixel > cy ||
       
  2798          d->bottomPixel < cy + ch - 1 ||
       
  2799          d->r->maybeTotalHeight < 0)
       
  2800         buildDrawableList();
       
  2801 
       
  2802     if (!d->dirtyItems.isEmpty()) {
       
  2803         QRect br(cx - ox, cy - oy, cw, ch);
       
  2804         for (int i = 0; i < d->dirtyItems.size(); ++i) {
       
  2805             const Q3ListViewItem * item = d->dirtyItems.at(i);
       
  2806             QRect ir = itemRect(item).intersected(viewport()->visibleRect());
       
  2807             if (ir.isEmpty() || br.contains(ir))
       
  2808                 // we're painting this one, or it needs no painting: forget it
       
  2809                 d->dirtyItems.removeAt(i);
       
  2810         }
       
  2811         if (d->dirtyItems.count()) {
       
  2812             // there are still items left that need repainting
       
  2813             d->dirtyItemTimer->start(0, true);
       
  2814         } else {
       
  2815             // we're painting all items that need to be painted
       
  2816             d->dirtyItems.clear();
       
  2817             d->dirtyItemTimer->stop();
       
  2818         }
       
  2819     }
       
  2820 
       
  2821     p->setFont(font());
       
  2822 
       
  2823     QRect r;
       
  2824     int fx = -1, x, fc = 0, lc = 0;
       
  2825     int tx = -1;
       
  2826 
       
  2827     for (int i = 0; i < d->drawables.size(); ++i) {
       
  2828         Q3ListViewPrivate::DrawableItem current = d->drawables.at(i);
       
  2829         if (!current.i->isVisible())
       
  2830             continue;
       
  2831         int ih = current.i->height();
       
  2832         int ith = current.i->totalHeight();
       
  2833         int c;
       
  2834         int cs;
       
  2835 
       
  2836         // need to paint current?
       
  2837         if (ih > 0 && current.y < cy+ch && current.y+ih > cy) {
       
  2838             if (fx < 0) {
       
  2839                 // find first interesting column, once
       
  2840                 x = 0;
       
  2841                 c = 0;
       
  2842                 cs = d->h->cellSize(0);
       
  2843                 while (x + cs <= cx && c < d->h->count()) {
       
  2844                     x += cs;
       
  2845                     c++;
       
  2846                     if (c < d->h->count())
       
  2847                         cs = d->h->cellSize(c);
       
  2848                 }
       
  2849                 fx = x;
       
  2850                 fc = c;
       
  2851                 while(x < cx + cw && c < d->h->count()) {
       
  2852                     x += cs;
       
  2853                     c++;
       
  2854                     if (c < d->h->count())
       
  2855                         cs = d->h->cellSize(c);
       
  2856                 }
       
  2857                 lc = c;
       
  2858             }
       
  2859 
       
  2860             x = fx;
       
  2861             c = fc;
       
  2862             // draw to last interesting column
       
  2863 
       
  2864             bool drawActiveSelection = hasFocus() || d->inMenuMode ||
       
  2865                             !style()->styleHint(QStyle::SH_ItemView_ChangeHighlightOnFocus, 0, this)
       
  2866                             || (currentItem() && currentItem()->renameBox
       
  2867                                 && currentItem()->renameBox->hasFocus());
       
  2868             QPalette pal = palette();
       
  2869             if(!drawActiveSelection)
       
  2870                 pal.setCurrentColorGroup(QPalette::Inactive);
       
  2871 
       
  2872             while (c < lc) {
       
  2873                 int i = d->h->mapToLogical(c);
       
  2874                 cs = d->h->cellSize(c);
       
  2875                 r.setRect(x - ox, current.y - oy, cs, ih);
       
  2876                 if (i == 0 && current.i->parentItem)
       
  2877                     r.setLeft(r.left() + current.l * treeStepSize());
       
  2878 
       
  2879                 p->save();
       
  2880                 // No need to paint if the cell isn't technically visible
       
  2881                 if (!(r.width() == 0 || r.height() == 0)) {
       
  2882                     p->translate(r.left(), r.top());
       
  2883                     int ac = d->h->mapToLogical(c);
       
  2884                     // map to Left currently. This should change once we
       
  2885                     // can really reverse the listview.
       
  2886                     int align = columnAlignment(ac);
       
  2887                     if (align == Qt::AlignAuto) align = Qt::AlignLeft;
       
  2888                         current.i->paintCell(p, pal, ac, r.width(), align);
       
  2889                 }
       
  2890                 p->restore();
       
  2891                 x += cs;
       
  2892                 c++;
       
  2893             }
       
  2894 
       
  2895             if (current.i == d->focusItem && hasFocus() &&
       
  2896                  !d->allColumnsShowFocus) {
       
  2897                 p->save();
       
  2898                 int cell = d->h->mapToActual(0);
       
  2899                 QRect r(d->h->cellPos(cell) - ox, current.y - oy, d->h->cellSize(cell), ih);
       
  2900                 if (current.i->parentItem)
       
  2901                     r.setLeft(r.left() + current.l * treeStepSize());
       
  2902                 if (r.left() < r.right())
       
  2903                     current.i->paintFocus(p, palette(), r);
       
  2904                 p->restore();
       
  2905             }
       
  2906         }
       
  2907 
       
  2908         const int cell = d->h->mapToActual(0);
       
  2909 
       
  2910         // does current need focus indication?
       
  2911         if (current.i == d->focusItem && hasFocus() &&
       
  2912              d->allColumnsShowFocus) {
       
  2913             p->save();
       
  2914             int x = -contentsX();
       
  2915             int w = header()->cellPos(header()->count() - 1) +
       
  2916                     header()->cellSize(header()->count() - 1);
       
  2917 
       
  2918             r.setRect(x, current.y - oy, w, ih);
       
  2919             if (d->h->mapToActual(0) == 0 || (current.l == 0 && !rootIsDecorated())) {
       
  2920                 int offsetx = qMin(current.l * treeStepSize(), d->h->cellSize(cell));
       
  2921                 r.setLeft(r.left() + offsetx);
       
  2922                 current.i->paintFocus(p, palette(), r);
       
  2923             } else {
       
  2924                 int xdepth = qMin(treeStepSize() * (current.i->depth() + (rootIsDecorated() ? 1 : 0))
       
  2925                              + itemMargin(), d->h->cellSize(cell));
       
  2926                 xdepth += d->h->cellPos(cell);
       
  2927                 QRect r1(r);
       
  2928                 r1.setRight(d->h->cellPos(cell) - 1);
       
  2929                 QRect r2(r);
       
  2930                 r2.setLeft(xdepth - 1);
       
  2931                 current.i->paintFocus(p, palette(), r1);
       
  2932                 current.i->paintFocus(p, palette(), r2);
       
  2933             }
       
  2934             p->restore();
       
  2935         }
       
  2936 
       
  2937         if (tx < 0)
       
  2938             tx = d->h->cellPos(cell);
       
  2939 
       
  2940         // do any children of current need to be painted?
       
  2941         if (ih != ith &&
       
  2942              (current.i != d->r || d->rootIsExpandable) &&
       
  2943              current.y + ith > cy &&
       
  2944              current.y + ih < cy + ch &&
       
  2945              tx + current.l * treeStepSize() < cx + cw &&
       
  2946              tx + (current.l+1) * treeStepSize() > cx) {
       
  2947             // compute the clip rectangle the safe way
       
  2948 
       
  2949             int rtop = current.y + ih;
       
  2950             int rbottom = current.y + ith;
       
  2951             int rleft = tx + current.l*treeStepSize();
       
  2952             int rright = rleft + treeStepSize();
       
  2953 
       
  2954             int crtop = qMax(rtop, cy);
       
  2955             int crbottom = qMin(rbottom, cy+ch);
       
  2956             int crleft = qMax(rleft, cx);
       
  2957             int crright = qMin(rright, cx+cw);
       
  2958 
       
  2959             r.setRect(crleft-ox, crtop-oy,
       
  2960                        crright-crleft, crbottom-crtop);
       
  2961 
       
  2962             if (r.isValid()) {
       
  2963                 p->save();
       
  2964                 p->setClipRect(QRect(d->h->cellPos(cell), 0, d->h->cellSize(cell), height()));
       
  2965                 p->translate(rleft-ox, crtop-oy);
       
  2966 
       
  2967                 current.i->paintBranches(p, palette(), treeStepSize(),
       
  2968                                            rtop - crtop, r.height());
       
  2969                 p->restore();
       
  2970             }
       
  2971         }
       
  2972     }
       
  2973 
       
  2974     if (d->r->totalHeight() < cy + ch)
       
  2975         paintEmptyArea(p, QRect(cx - ox, d->r->totalHeight() - oy,
       
  2976                                   cw, cy + ch - d->r->totalHeight()));
       
  2977 
       
  2978     int c = d->h->count()-1;
       
  2979     if (c >= 0 &&
       
  2980          d->h->cellPos(c) + d->h->cellSize(c) < cx + cw) {
       
  2981         c = d->h->cellPos(c) + d->h->cellSize(c);
       
  2982         paintEmptyArea(p, QRect(c - ox, cy - oy, cx + cw - c, ch));
       
  2983     }
       
  2984 }
       
  2985 
       
  2986 
       
  2987 
       
  2988 /*!
       
  2989     Paints \a rect so that it looks like empty background using
       
  2990     painter \a p. \a rect is in widget coordinates, ready to be fed to
       
  2991     \a p.
       
  2992 
       
  2993     The default function fills \a rect with the
       
  2994     viewport()->backgroundBrush().
       
  2995 */
       
  2996 
       
  2997 void Q3ListView::paintEmptyArea(QPainter * p, const QRect & rect)
       
  2998 {
       
  2999     QStyleOptionQ3ListView opt = getStyleOption(this, 0);
       
  3000     opt.rect = rect;
       
  3001     opt.sortColumn = d->sortcolumn;
       
  3002     opt.subControls = QStyle::SC_Q3ListView;
       
  3003     style()->drawComplexControl(QStyle::CC_Q3ListView, &opt, p, this);
       
  3004 }
       
  3005 
       
  3006 
       
  3007 /*
       
  3008     Rebuilds the list of drawable Q3ListViewItems. This function is
       
  3009     const so that const functions can call it without requiring
       
  3010     d->drawables to be mutable.
       
  3011 */
       
  3012 
       
  3013 void Q3ListView::buildDrawableList() const
       
  3014 {
       
  3015     d->r->enforceSortOrder();
       
  3016 
       
  3017     QStack<Q3ListViewPrivate::DrawableItem> stack;
       
  3018     Q3ListViewPrivate::DrawableItem di(((int)d->rootIsExpandable)-1, 0, d->r);
       
  3019     stack.push(di);
       
  3020 
       
  3021     Q3ListView *that = const_cast<Q3ListView *>(this);
       
  3022 
       
  3023     // could mess with cy and ch in order to speed up vertical
       
  3024     // scrolling
       
  3025     int cy = contentsY();
       
  3026     int ch = that->visibleHeight();
       
  3027     d->topPixel = cy + ch; // one below bottom
       
  3028     d->bottomPixel = cy - 1; // one above top
       
  3029 
       
  3030     that->d->drawables.clear();
       
  3031 
       
  3032     while (!stack.isEmpty()) {
       
  3033         Q3ListViewPrivate::DrawableItem cur = stack.pop();
       
  3034 
       
  3035         int ih = cur.i->height();
       
  3036         int ith = cur.i->totalHeight();
       
  3037 
       
  3038         // is this item, or its branch symbol, inside the viewport?
       
  3039         if (cur.y + ith >= cy && cur.y < cy + ch) {
       
  3040             that->d->drawables.append(cur);
       
  3041             // perhaps adjust topPixel up to this item?  may be adjusted
       
  3042             // down again if any children are not to be painted
       
  3043             if (cur.y < d->topPixel)
       
  3044                 d->topPixel = cur.y;
       
  3045             // bottompixel is easy: the bottom item drawn contains it
       
  3046             d->bottomPixel = cur.y + ih - 1;
       
  3047         }
       
  3048 
       
  3049         // push younger sibling of cur on the stack?
       
  3050         if (cur.y + ith < cy+ch && cur.i->siblingItem)
       
  3051             stack.push(Q3ListViewPrivate::DrawableItem(cur.l, cur.y + ith, cur.i->siblingItem));
       
  3052 
       
  3053         // do any children of cur need to be painted?
       
  3054         if (cur.i->isOpen() && cur.i->childCount() &&
       
  3055              cur.y + ith > cy &&
       
  3056              cur.y + ih < cy + ch) {
       
  3057             cur.i->enforceSortOrder();
       
  3058 
       
  3059             Q3ListViewItem * c = cur.i->childItem;
       
  3060             int y = cur.y + ih;
       
  3061 
       
  3062             // if any of the children are not to be painted, skip them
       
  3063             // and invalidate topPixel
       
  3064             while (c && y + c->totalHeight() <= cy) {
       
  3065                 y += c->totalHeight();
       
  3066                 c = c->siblingItem;
       
  3067                 d->topPixel = cy + ch;
       
  3068             }
       
  3069 
       
  3070             // push one child on the stack, if there is at least one
       
  3071             // needing to be painted
       
  3072             if (c && y < cy+ch)
       
  3073                 stack.push(Q3ListViewPrivate::DrawableItem(cur.l + 1, y, c));
       
  3074         }
       
  3075     }
       
  3076 }
       
  3077 
       
  3078 /*!
       
  3079     \property Q3ListView::treeStepSize
       
  3080     \brief the number of pixels a child is offset from its parent
       
  3081 
       
  3082     The default is 20 pixels.
       
  3083 
       
  3084     Of course, this property is only meaningful for hierarchical list
       
  3085     views.
       
  3086 */
       
  3087 
       
  3088 int Q3ListView::treeStepSize() const
       
  3089 {
       
  3090     return d->levelWidth;
       
  3091 }
       
  3092 
       
  3093 void Q3ListView::setTreeStepSize(int size)
       
  3094 {
       
  3095     if (size != d->levelWidth) {
       
  3096         d->levelWidth = size;
       
  3097         viewport()->repaint();
       
  3098     }
       
  3099 }
       
  3100 
       
  3101 /*!
       
  3102     Inserts item \a i into the list view as a top-level item. You do
       
  3103     not need to call this unless you've called takeItem(\a i) or
       
  3104     Q3ListViewItem::takeItem(\a i) and need to reinsert \a i elsewhere.
       
  3105 
       
  3106     \sa Q3ListViewItem::takeItem() takeItem()
       
  3107 */
       
  3108 
       
  3109 void Q3ListView::insertItem(Q3ListViewItem * i)
       
  3110 {
       
  3111     if (d->r) // not for d->r itself
       
  3112         d->r->insertItem(i);
       
  3113 }
       
  3114 
       
  3115 
       
  3116 /*!
       
  3117     Removes and deletes all the items in this list view and triggers
       
  3118     an update.
       
  3119 
       
  3120     \sa triggerUpdate()
       
  3121 */
       
  3122 
       
  3123 void Q3ListView::clear()
       
  3124 {
       
  3125     bool wasUpdatesEnabled = viewport()->updatesEnabled();
       
  3126     if (wasUpdatesEnabled)
       
  3127         viewport()->setUpdatesEnabled(false);
       
  3128     setContentsPos(0, 0);
       
  3129     if (wasUpdatesEnabled)
       
  3130         viewport()->setUpdatesEnabled(true);
       
  3131 
       
  3132     bool block = signalsBlocked();
       
  3133     blockSignals(true);
       
  3134     d->clearing = true;
       
  3135     clearSelection();
       
  3136     for (int j = 0; j < d->iterators.size(); ++j) {
       
  3137         Q3ListViewItemIterator *i = d->iterators.at(j);
       
  3138             i->curr = 0;
       
  3139     }
       
  3140 
       
  3141     d->drawables.clear();
       
  3142     d->dirtyItems.clear();
       
  3143     d->dirtyItemTimer->stop();
       
  3144 
       
  3145     d->highlighted = 0;
       
  3146     d->focusItem = 0;
       
  3147     d->selectAnchor = 0;
       
  3148     d->pressedItem = 0;
       
  3149     d->startDragItem = 0;
       
  3150 
       
  3151     // if it's down its downness makes no sense, so undown it
       
  3152     d->buttonDown = false;
       
  3153 
       
  3154     Q3ListViewItem *c = (Q3ListViewItem *)d->r->firstChild();
       
  3155     Q3ListViewItem *n;
       
  3156     while(c) {
       
  3157         n = (Q3ListViewItem *)c->nextSibling();
       
  3158         delete c;
       
  3159         c = n;
       
  3160     }
       
  3161     resizeContents(d->h->sizeHint().width(), contentsHeight());
       
  3162     delete d->r;
       
  3163     d->r = 0;
       
  3164     Q3ListViewPrivate::Root * r = new Q3ListViewPrivate::Root(this);
       
  3165     r->is_root = true;
       
  3166     d->r = r;
       
  3167     d->r->setSelectable(false);
       
  3168     blockSignals(block);
       
  3169     triggerUpdate();
       
  3170     d->clearing = false;
       
  3171 }
       
  3172 
       
  3173 /*!
       
  3174     \reimp
       
  3175 */
       
  3176 
       
  3177 void Q3ListView::setContentsPos(int x, int y)
       
  3178 {
       
  3179     updateGeometries();
       
  3180     Q3ScrollView::setContentsPos(x, y);
       
  3181 }
       
  3182 
       
  3183 /*!
       
  3184     Adds a \a width pixels wide column with the column header \a label
       
  3185     to the list view, and returns the index of the new column.
       
  3186 
       
  3187     All columns apart from the first one are inserted to the right of
       
  3188     the existing ones.
       
  3189 
       
  3190     If \a width is negative, the new column's \l WidthMode is set to
       
  3191     \c Maximum instead of \c Manual.
       
  3192 
       
  3193     \sa setColumnText() setColumnWidth() setColumnWidthMode()
       
  3194 */
       
  3195 int Q3ListView::addColumn(const QString &label, int width)
       
  3196 {
       
  3197     int c = d->h->addLabel(label, width);
       
  3198     d->column.resize(c+1);
       
  3199     d->column[c].wmode = (width >= 0 ? Manual : Maximum);
       
  3200     updateGeometries();
       
  3201     updateGeometry();
       
  3202     return c;
       
  3203 }
       
  3204 
       
  3205 /*!
       
  3206     \overload
       
  3207 
       
  3208     Adds a \a width pixels wide new column with the header \a label
       
  3209     and the \a icon to the list view, and returns the index of the
       
  3210     column.
       
  3211 
       
  3212     If \a width is negative, the new column's \l WidthMode is set to
       
  3213     \c Maximum, and to \c Manual otherwise.
       
  3214 
       
  3215     \sa setColumnText() setColumnWidth() setColumnWidthMode()
       
  3216 */
       
  3217 int Q3ListView::addColumn(const QIcon& icon, const QString &label, int width)
       
  3218 {
       
  3219     int c = d->h->addLabel(icon, label, width);
       
  3220     d->column.resize(c+1);
       
  3221     d->column[c].wmode = (width >= 0 ? Manual : Maximum);
       
  3222     updateGeometries();
       
  3223     updateGeometry();
       
  3224     return c;
       
  3225 }
       
  3226 
       
  3227 /*!
       
  3228     \property Q3ListView::columns
       
  3229     \brief the number of columns in this list view
       
  3230 
       
  3231     \sa addColumn(), removeColumn()
       
  3232 */
       
  3233 
       
  3234 int Q3ListView::columns() const
       
  3235 {
       
  3236     return d->column.count();
       
  3237 }
       
  3238 
       
  3239 /*!
       
  3240     Removes the column at position \a index.
       
  3241 */
       
  3242 
       
  3243 void Q3ListView::removeColumn(int index)
       
  3244 {
       
  3245     if (index < 0 || index > (int)d->column.count() - 1)
       
  3246         return;
       
  3247 
       
  3248     if (d->vci) {
       
  3249         Q3ListViewPrivate::ViewColumnInfo *vi = d->vci, *prev = 0, *next = 0;
       
  3250         for (int i = 0; i < index; ++i) {
       
  3251             if (vi) {
       
  3252                 prev = vi;
       
  3253                 vi = vi->next;
       
  3254             }
       
  3255         }
       
  3256         if (vi) {
       
  3257             next = vi->next;
       
  3258             if (prev)
       
  3259                 prev->next = next;
       
  3260             vi->next = 0;
       
  3261             delete vi;
       
  3262             if (index == 0)
       
  3263                 d->vci = next;
       
  3264         }
       
  3265     }
       
  3266 
       
  3267     Q3ListViewItemIterator it(this);
       
  3268     for (; it.current(); ++it) {
       
  3269         Q3ListViewPrivate::ItemColumnInfo *ci = (Q3ListViewPrivate::ItemColumnInfo*)it.current()->columns;
       
  3270         if (ci) {
       
  3271             Q3ListViewPrivate::ItemColumnInfo *prev = 0, *next = 0;
       
  3272             for (int i = 0; i < index; ++i) {
       
  3273                 if (ci) {
       
  3274                     prev = ci;
       
  3275                     ci = ci->next;
       
  3276                 }
       
  3277             }
       
  3278             if (ci) {
       
  3279                 next = ci->next;
       
  3280                 if (prev)
       
  3281                     prev->next = next;
       
  3282                 ci->next = 0;
       
  3283                 delete ci;
       
  3284                 if (index == 0)
       
  3285                     it.current()->columns = next;
       
  3286             }
       
  3287         }
       
  3288     }
       
  3289 
       
  3290     for (int i = index; i < (int)d->column.size() - 1; ++i)
       
  3291         d->column[i] = d->column[i + 1];
       
  3292     d->column.resize(d->column.size() - 1);
       
  3293 
       
  3294     d->h->removeLabel(index);
       
  3295     if (d->resizeMode == LastColumn)
       
  3296         d->h->setStretchEnabled(true, d->h->count() - 1);
       
  3297 
       
  3298     updateGeometries();
       
  3299     if (d->column.count() == 0)
       
  3300         clear();
       
  3301     updateGeometry();
       
  3302     viewport()->update();
       
  3303 }
       
  3304 
       
  3305 /*!
       
  3306     Sets the heading of column \a column to \a label.
       
  3307 
       
  3308     \sa columnText()
       
  3309 */
       
  3310 void Q3ListView::setColumnText(int column, const QString &label)
       
  3311 {
       
  3312     if (column < d->h->count()) {
       
  3313         d->h->setLabel(column, label);
       
  3314         updateGeometries();
       
  3315         updateGeometry();
       
  3316     }
       
  3317 }
       
  3318 
       
  3319 /*!
       
  3320     \overload
       
  3321 
       
  3322     Sets the heading of column \a column to \a icon and \a label.
       
  3323 
       
  3324     \sa columnText()
       
  3325 */
       
  3326 void Q3ListView::setColumnText(int column, const QIcon& icon, const QString &label)
       
  3327 {
       
  3328     if (column < d->h->count()) {
       
  3329         d->h->setLabel(column, icon, label);
       
  3330         updateGeometries();
       
  3331     }
       
  3332 }
       
  3333 
       
  3334 /*!
       
  3335     Sets the width of column \a column to \a w pixels. Note that if
       
  3336     the column has a \c WidthMode other than \c Manual, this width
       
  3337     setting may be subsequently overridden.
       
  3338 
       
  3339     \sa columnWidth()
       
  3340 */
       
  3341 void Q3ListView::setColumnWidth(int column, int w)
       
  3342 {
       
  3343     int oldw = d->h->sectionSize(column);
       
  3344     if (column < d->h->count() && oldw != w) {
       
  3345         d->h->resizeSection(column, w);
       
  3346         disconnect(d->h, SIGNAL(sizeChange(int,int,int)),
       
  3347                  this, SLOT(handleSizeChange(int,int,int)));
       
  3348         emit d->h->sizeChange(column, oldw, w);
       
  3349         connect(d->h, SIGNAL(sizeChange(int,int,int)),
       
  3350                  this, SLOT(handleSizeChange(int,int,int)));
       
  3351         viewport()->update();
       
  3352     }
       
  3353 }
       
  3354 
       
  3355 
       
  3356 /*!
       
  3357     Returns the text of column \a c.
       
  3358 
       
  3359     \sa setColumnText()
       
  3360 */
       
  3361 
       
  3362 QString Q3ListView::columnText(int c) const
       
  3363 {
       
  3364     return d->h->label(c);
       
  3365 }
       
  3366 
       
  3367 /*!
       
  3368     Returns the width of column \a c.
       
  3369 
       
  3370     \sa setColumnWidth()
       
  3371 */
       
  3372 
       
  3373 int Q3ListView::columnWidth(int c) const
       
  3374 {
       
  3375     int actual = d->h->mapToActual(c);
       
  3376     return d->h->cellSize(actual);
       
  3377 }
       
  3378 
       
  3379 
       
  3380 /*!
       
  3381     \enum Q3ListView::WidthMode
       
  3382 
       
  3383     This enum type describes how the width of a column in the view
       
  3384     changes.
       
  3385 
       
  3386     \value Manual the column width does not change automatically.
       
  3387 
       
  3388     \value Maximum  the column is automatically sized according to the
       
  3389     widths of all items in the column. (Note: The column never shrinks
       
  3390     in this case.) This means that the column is always resized to the
       
  3391     width of the item with the largest width in the column.
       
  3392 
       
  3393     \sa setColumnWidth() setColumnWidthMode() columnWidth()
       
  3394 */
       
  3395 
       
  3396 
       
  3397 /*!
       
  3398     Sets column \a{c}'s width mode to \a mode. The default depends on
       
  3399     the original width argument to addColumn().
       
  3400 
       
  3401     \sa Q3ListViewItem::width()
       
  3402 */
       
  3403 
       
  3404 void Q3ListView::setColumnWidthMode(int c, WidthMode mode)
       
  3405 {
       
  3406     if (c >= 0 && c < d->h->count())
       
  3407          d->column[c].wmode = mode;
       
  3408 }
       
  3409 
       
  3410 
       
  3411 /*!
       
  3412     Returns the \c WidthMode for column \a c.
       
  3413 
       
  3414     \sa setColumnWidthMode()
       
  3415 */
       
  3416 
       
  3417 Q3ListView::WidthMode Q3ListView::columnWidthMode(int c) const
       
  3418 {
       
  3419     if (c >= 0 && c < d->h->count())
       
  3420         return d->column[c].wmode;
       
  3421     else
       
  3422         return Manual;
       
  3423 }
       
  3424 
       
  3425 
       
  3426 /*!
       
  3427     Sets column \a{column}'s alignment to \a align. The alignment is
       
  3428     ultimately passed to Q3ListViewItem::paintCell() for each item in
       
  3429     the list view. For horizontally aligned text with Qt::AlignLeft or
       
  3430     Qt::AlignHCenter the ellipsis (...) will be to the right, for
       
  3431     Qt::AlignRight the ellipsis will be to the left.
       
  3432 
       
  3433     \sa Qt::Alignment
       
  3434 */
       
  3435 
       
  3436 void Q3ListView::setColumnAlignment(int column, int align)
       
  3437 {
       
  3438     if (column < 0)
       
  3439         return;
       
  3440     if (!d->vci)
       
  3441         d->vci = new Q3ListViewPrivate::ViewColumnInfo;
       
  3442     Q3ListViewPrivate::ViewColumnInfo * l = d->vci;
       
  3443     while(column) {
       
  3444         if (!l->next)
       
  3445             l->next = new Q3ListViewPrivate::ViewColumnInfo;
       
  3446         l = l->next;
       
  3447         column--;
       
  3448     }
       
  3449     if (l->align == align)
       
  3450         return;
       
  3451     l->align = align;
       
  3452     triggerUpdate();
       
  3453 }
       
  3454 
       
  3455 
       
  3456 /*!
       
  3457     Returns the alignment of column \a column. The default is \c
       
  3458     Qt::AlignAuto.
       
  3459 
       
  3460     \sa Qt::Alignment
       
  3461 */
       
  3462 
       
  3463 int Q3ListView::columnAlignment(int column) const
       
  3464 {
       
  3465     if (column < 0 || !d->vci)
       
  3466         return Qt::AlignAuto;
       
  3467     Q3ListViewPrivate::ViewColumnInfo * l = d->vci;
       
  3468     while(column) {
       
  3469         if (!l->next)
       
  3470             l->next = new Q3ListViewPrivate::ViewColumnInfo;
       
  3471         l = l->next;
       
  3472         column--;
       
  3473     }
       
  3474     return l ? l->align : Qt::AlignAuto;
       
  3475 }
       
  3476 
       
  3477 
       
  3478 
       
  3479 /*!
       
  3480     \internal
       
  3481 */
       
  3482 void Q3ListView::show()
       
  3483 {
       
  3484     // Reimplemented to setx the correct background mode and viewed
       
  3485     // area size.
       
  3486     if (!isVisible()) {
       
  3487         reconfigureItems();
       
  3488         updateGeometries();
       
  3489     }
       
  3490     Q3ScrollView::show();
       
  3491 }
       
  3492 
       
  3493 
       
  3494 /*!
       
  3495     Updates the sizes of the viewport, header, scroll bars and so on.
       
  3496 
       
  3497     \warning Don't call this directly; call triggerUpdate() instead.
       
  3498 */
       
  3499 
       
  3500 void Q3ListView::updateContents()
       
  3501 {
       
  3502     if (d->updateHeader)
       
  3503         header()->adjustHeaderSize();
       
  3504     d->updateHeader = false;
       
  3505     if (!isVisible()) {
       
  3506         // Not in response to a setText/setPixmap any more.
       
  3507         return;
       
  3508     }
       
  3509     d->drawables.clear();
       
  3510     viewport()->setUpdatesEnabled(false);
       
  3511     updateGeometries();
       
  3512     viewport()->setUpdatesEnabled(true);
       
  3513     viewport()->repaint();
       
  3514 }
       
  3515 
       
  3516 
       
  3517 void Q3ListView::updateGeometries()
       
  3518 {
       
  3519     int th = d->r->totalHeight();
       
  3520     int tw = d->h->headerWidth();
       
  3521     if (d->h->offset() &&
       
  3522          tw < d->h->offset() + d->h->width())
       
  3523         horizontalScrollBar()->setValue(tw - Q3ListView::d->h->width());
       
  3524 #if 0
       
  3525     if (QApplication::reverseLayout() && d->h->offset() != horizontalScrollBar()->value())
       
  3526         horizontalScrollBar()->setValue(d->h->offset());
       
  3527 #endif
       
  3528     verticalScrollBar()->raise();
       
  3529     resizeContents(tw, th);
       
  3530     d->drawables.clear();
       
  3531     if (d->h->isHidden()) {
       
  3532         setMargins(0, 0, 0, 0);
       
  3533     } else {
       
  3534         QSize hs(d->h->sizeHint());
       
  3535         setMargins(0, hs.height(), 0, 0);
       
  3536         d->h->setGeometry(viewport()->x(), viewport()->y()-hs.height(),
       
  3537                            visibleWidth(), hs.height());
       
  3538     }
       
  3539 }
       
  3540 
       
  3541 
       
  3542 /*!
       
  3543     Updates the display when the section \a section has changed size
       
  3544     from the old size, \a os, to the new size, \a ns.
       
  3545 */
       
  3546 
       
  3547 void Q3ListView::handleSizeChange(int section, int os, int ns)
       
  3548 {
       
  3549     bool upe = viewport()->updatesEnabled();
       
  3550     if (upe)
       
  3551         viewport()->setUpdatesEnabled(false);
       
  3552     viewport()->setAttribute(Qt::WA_UpdatesDisabled, true);
       
  3553     int sx = horizontalScrollBar()->value();
       
  3554     bool sv = horizontalScrollBar()->isVisible();
       
  3555     updateGeometries();
       
  3556     bool fullRepaint = d->fullRepaintOnComlumnChange || sx != horizontalScrollBar()->value()
       
  3557                        || sv != horizontalScrollBar()->isVisible();
       
  3558     d->fullRepaintOnComlumnChange = false;
       
  3559     if (upe)
       
  3560         viewport()->setUpdatesEnabled(true);
       
  3561 
       
  3562     if (fullRepaint) {
       
  3563         viewport()->repaint();
       
  3564         return;
       
  3565     }
       
  3566 
       
  3567     int actual = d->h->mapToActual(section);
       
  3568     int dx = ns - os;
       
  3569     int left = d->h->cellPos(actual) - contentsX() + d->h->cellSize(actual);
       
  3570     if (dx > 0)
       
  3571         left -= dx;
       
  3572     if (left < visibleWidth())
       
  3573         viewport()->scroll(dx, 0, QRect(left, 0, visibleWidth() - left, visibleHeight()));
       
  3574     viewport()->repaint(left - 4 - d->ellipsisWidth, 0, 4 + d->ellipsisWidth,
       
  3575                         visibleHeight()); // border between the items and ellipses width
       
  3576 
       
  3577     // map auto to left for now. Need to fix this once we support
       
  3578     // reverse layout on the listview.
       
  3579     int align = columnAlignment(section);
       
  3580     if (align == Qt::AlignAuto) align = Qt::AlignLeft;
       
  3581     if (align != Qt::AlignAuto && align != Qt::AlignLeft)
       
  3582         viewport()->repaint(d->h->cellPos(actual) - contentsX(), 0,
       
  3583                              d->h->cellSize(actual), visibleHeight());
       
  3584 
       
  3585     if (currentItem() && currentItem()->renameBox) {
       
  3586         QRect r = itemRect(currentItem());
       
  3587         r = QRect(viewportToContents(r.topLeft()), r.size());
       
  3588         r.setLeft(header()->sectionPos(currentItem()->renameCol));
       
  3589         r.setWidth(header()->sectionSize(currentItem()->renameCol) - 1);
       
  3590         if (currentItem()->renameCol == 0)
       
  3591             r.setLeft(r.left() + itemMargin() + (currentItem()->depth() +
       
  3592                                                    (rootIsDecorated() ? 1 : 0)) * treeStepSize() - 1);
       
  3593         if (currentItem()->pixmap(currentItem()->renameCol))
       
  3594             r.setLeft(r.left() + currentItem()->pixmap(currentItem()->renameCol)->width());
       
  3595         if (r.x() - contentsX() < 0)
       
  3596             r.setX(contentsX());
       
  3597         if (r.width() > visibleWidth())
       
  3598             r.setWidth(visibleWidth());
       
  3599         addChild(currentItem()->renameBox, r.x(), r.y());
       
  3600         currentItem()->renameBox->resize(r.size());
       
  3601     }
       
  3602 }
       
  3603 
       
  3604 
       
  3605 /*
       
  3606     Very smart internal slot that repaints \e only the items that need
       
  3607     to be repainted. Don't use this directly; call repaintItem()
       
  3608     instead.
       
  3609 */
       
  3610 
       
  3611 void Q3ListView::updateDirtyItems()
       
  3612 {
       
  3613     if (d->timer->isActive() || d->dirtyItems.isEmpty())
       
  3614         return;
       
  3615     QRect ir;
       
  3616     for (int i = 0; i < d->dirtyItems.size(); ++i) {
       
  3617         const Q3ListViewItem *item = d->dirtyItems.at(i);
       
  3618         ir = ir.united(itemRect(item));
       
  3619     }
       
  3620     d->dirtyItems.clear();
       
  3621     if (!ir.isEmpty())  {                      // rectangle to be repainted
       
  3622         if (ir.x() < 0)
       
  3623             ir.moveBy(-ir.x(), 0);
       
  3624         viewport()->repaint(ir);
       
  3625     }
       
  3626 }
       
  3627 
       
  3628 
       
  3629 void Q3ListView::makeVisible()
       
  3630 {
       
  3631     if (d->focusItem)
       
  3632         ensureItemVisible(d->focusItem);
       
  3633 }
       
  3634 
       
  3635 
       
  3636 /*!
       
  3637     Ensures that the header is correctly sized and positioned when the
       
  3638     resize event \a e occurs.
       
  3639 */
       
  3640 
       
  3641 void Q3ListView::resizeEvent(QResizeEvent *e)
       
  3642 {
       
  3643     Q3ScrollView::resizeEvent(e);
       
  3644     d->fullRepaintOnComlumnChange = true;
       
  3645     d->h->resize(visibleWidth(), d->h->height());
       
  3646     d->h->adjustHeaderSize();
       
  3647 }
       
  3648 
       
  3649 /*! \reimp */
       
  3650 
       
  3651 void Q3ListView::viewportResizeEvent(QResizeEvent *e)
       
  3652 {
       
  3653     Q3ScrollView::viewportResizeEvent(e);
       
  3654     d->h->resize(visibleWidth(), d->h->height());
       
  3655     if (resizeMode() != NoColumn && currentItem() && currentItem()->renameBox) {
       
  3656         QRect r = itemRect(currentItem());
       
  3657         r = QRect(viewportToContents(r.topLeft()), r.size());
       
  3658         r.setLeft(header()->sectionPos(currentItem()->renameCol));
       
  3659         r.setWidth(header()->sectionSize(currentItem()->renameCol) - 1);
       
  3660         if (currentItem()->renameCol == 0)
       
  3661             r.setLeft(r.left() + itemMargin() + (currentItem()->depth() +
       
  3662                                                    (rootIsDecorated() ? 1 : 0)) * treeStepSize() - 1);
       
  3663         if (currentItem()->pixmap(currentItem()->renameCol))
       
  3664             r.setLeft(r.left() + currentItem()->pixmap(currentItem()->renameCol)->width());
       
  3665         if (r.x() - contentsX() < 0)
       
  3666             r.setX(contentsX());
       
  3667         if (r.width() > visibleWidth())
       
  3668             r.setWidth(visibleWidth());
       
  3669         addChild(currentItem()->renameBox, r.x(), r.y());
       
  3670         currentItem()->renameBox->resize(r.size());
       
  3671     }
       
  3672 }
       
  3673 
       
  3674 /*!
       
  3675     Triggers a size, geometry and content update during the next
       
  3676     iteration of the event loop. Ensures that there'll be just one
       
  3677     update to avoid flicker.
       
  3678 */
       
  3679 
       
  3680 void Q3ListView::triggerUpdate()
       
  3681 {
       
  3682     if (!isVisible() || !updatesEnabled()) {
       
  3683         // Not in response to a setText/setPixmap any more.
       
  3684         return; // it will update when shown, or something.
       
  3685     }
       
  3686 
       
  3687     d->timer->start(0, true);
       
  3688 }
       
  3689 
       
  3690 
       
  3691 /*!
       
  3692     Redirects the event \a e relating to object \a o, for the viewport
       
  3693     to mousePressEvent(), keyPressEvent() and friends.
       
  3694 */
       
  3695 
       
  3696 bool Q3ListView::eventFilter(QObject * o, QEvent * e)
       
  3697 {
       
  3698     if (o == d->h &&
       
  3699          e->type() >= QEvent::MouseButtonPress &&
       
  3700          e->type() <= QEvent::MouseMove) {
       
  3701         QMouseEvent * me = (QMouseEvent *)e;
       
  3702         QMouseEvent me2(me->type(),
       
  3703                          QPoint(me->pos().x(),
       
  3704                                  me->pos().y() - d->h->height()),
       
  3705                          me->button(), me->state());
       
  3706         switch(me2.type()) {
       
  3707         case QEvent::MouseButtonDblClick:
       
  3708             if (me2.button() == Qt::RightButton)
       
  3709                 return true;
       
  3710             break;
       
  3711         case QEvent::MouseMove:
       
  3712             if (me2.state() & Qt::RightButton) {
       
  3713                 viewportMouseMoveEvent(&me2);
       
  3714                 return true;
       
  3715             }
       
  3716             break;
       
  3717         default:
       
  3718             break;
       
  3719         }
       
  3720     } else if (o == viewport()) {
       
  3721         QFocusEvent * fe = (QFocusEvent *)e;
       
  3722 
       
  3723         switch(e->type()) {
       
  3724         case QEvent::FocusIn:
       
  3725             focusInEvent(fe);
       
  3726             return true;
       
  3727         case QEvent::FocusOut:
       
  3728             focusOutEvent(fe);
       
  3729             return true;
       
  3730 #ifndef QT_NO_TOOLTIP
       
  3731         case QEvent::ToolTip:
       
  3732         {
       
  3733             if (!showToolTips())
       
  3734                 return false;
       
  3735 
       
  3736             QHelpEvent *he = static_cast<QHelpEvent *>(e);
       
  3737             Q3ListViewItem *item = itemAt(he->pos());
       
  3738             QPoint contentsPos = viewportToContents(he->pos());
       
  3739             if (!item || !item->columns) {
       
  3740                 QToolTip::showText(he->globalPos(), QString(), viewport());
       
  3741                 return true;
       
  3742             }
       
  3743             int col = header()->sectionAt(contentsPos.x());
       
  3744             Q3ListViewPrivate::ItemColumnInfo *ci = (Q3ListViewPrivate::ItemColumnInfo*)item->columns;
       
  3745             for (int i = 0; ci && (i < col); ++i)
       
  3746                 ci = ci->next;
       
  3747 
       
  3748             if (!ci || !ci->truncated)
       
  3749                 QToolTip::showText(he->globalPos(), QString(), viewport());
       
  3750             else
       
  3751                 QToolTip::showText(he->globalPos(), item->text(col), viewport());
       
  3752             return true;
       
  3753         }
       
  3754 #endif
       
  3755         default:
       
  3756             // nothing
       
  3757             break;
       
  3758         }
       
  3759     } else if (qobject_cast<QLineEdit*>(o)) {
       
  3760         if (currentItem() && currentItem()->renameBox) {
       
  3761             if (e->type() == QEvent::KeyPress) {
       
  3762                 QKeyEvent *ke = (QKeyEvent*)e;
       
  3763                 if (ke->key() == Qt::Key_Return ||
       
  3764                      ke->key() == Qt::Key_Enter) {
       
  3765                     currentItem()->okRename(currentItem()->renameCol);
       
  3766                     return true;
       
  3767                 } else if (ke->key() == Qt::Key_Escape) {
       
  3768                     currentItem()->cancelRename(currentItem()->renameCol);
       
  3769                     return true;
       
  3770                 }
       
  3771             } else if (e->type() == QEvent::FocusOut) {
       
  3772                 if (((QFocusEvent*)e)->reason() != Qt::PopupFocusReason) {
       
  3773                     QCustomEvent *e = new QCustomEvent(9999);
       
  3774                     QApplication::postEvent(o, e);
       
  3775                     return true;
       
  3776                 }
       
  3777             } else if (e->type() == 9999) {
       
  3778                 if (d->defRenameAction == Reject)
       
  3779                     currentItem()->cancelRename(currentItem()->renameCol);
       
  3780                 else
       
  3781                     currentItem()->okRename(currentItem()->renameCol);
       
  3782                 return true;
       
  3783             }
       
  3784         }
       
  3785     }
       
  3786 
       
  3787     return Q3ScrollView::eventFilter(o, e);
       
  3788 }
       
  3789 
       
  3790 
       
  3791 /*!
       
  3792     Returns a pointer to the list view containing this item.
       
  3793 
       
  3794     Note that this function traverses the items to the root to find the
       
  3795     listview. This function will return 0 for taken items - see
       
  3796     Q3ListViewItem::takeItem()
       
  3797 */
       
  3798 
       
  3799 Q3ListView * Q3ListViewItem::listView() const
       
  3800 {
       
  3801     const Q3ListViewItem* c = this;
       
  3802     while (c && !c->is_root)
       
  3803         c = c->parentItem;
       
  3804     if (!c)
       
  3805         return 0;
       
  3806     return ((Q3ListViewPrivate::Root*)c)->theListView();
       
  3807 }
       
  3808 
       
  3809 
       
  3810 /*!
       
  3811     Returns the depth of this item.
       
  3812 */
       
  3813 int Q3ListViewItem::depth() const
       
  3814 {
       
  3815     return parentItem ? parentItem->depth()+1 : -1; // -1 == the hidden root
       
  3816 }
       
  3817 
       
  3818 
       
  3819 /*!
       
  3820     Returns a pointer to the item immediately above this item on the
       
  3821     screen. This is usually the item's closest older sibling, but it
       
  3822     may also be its parent or its next older sibling's youngest child,
       
  3823     or something else if anyoftheabove->height() returns 0. Returns 0
       
  3824     if there is no item immediately above this item.
       
  3825 
       
  3826     This function assumes that all parents of this item are open (i.e.
       
  3827     that this item is visible, or can be made visible by scrolling).
       
  3828 
       
  3829     This function might be relatively slow because of the tree
       
  3830     traversions needed to find the correct item.
       
  3831 
       
  3832     \sa itemBelow() Q3ListView::itemRect()
       
  3833 */
       
  3834 
       
  3835 Q3ListViewItem * Q3ListViewItem::itemAbove() const
       
  3836 {
       
  3837     if (!parentItem)
       
  3838         return 0;
       
  3839 
       
  3840     Q3ListViewItem * c = parentItem;
       
  3841     if (c->childItem != this) {
       
  3842         c = c->childItem;
       
  3843         while(c && c->siblingItem != this)
       
  3844             c = c->siblingItem;
       
  3845         if (!c)
       
  3846             return 0;
       
  3847         while(c->isOpen() && c->childItem) {
       
  3848             c = c->childItem;
       
  3849             while(c->siblingItem)
       
  3850                 c = c->siblingItem;                // assign c's sibling to c
       
  3851         }
       
  3852     }
       
  3853     if (c && (!c->height() || !c->isEnabled()))
       
  3854         return c->itemAbove();
       
  3855     return c;
       
  3856 }
       
  3857 
       
  3858 
       
  3859 /*!
       
  3860     Returns a pointer to the item immediately below this item on the
       
  3861     screen. This is usually the item's eldest child, but it may also
       
  3862     be its next younger sibling, its parent's next younger sibling,
       
  3863     grandparent's, etc., or something else if anyoftheabove->height()
       
  3864     returns 0. Returns 0 if there is no item immediately below this
       
  3865     item.
       
  3866 
       
  3867     This function assumes that all parents of this item are open (i.e.
       
  3868     that this item is visible or can be made visible by scrolling).
       
  3869 
       
  3870     \sa itemAbove() Q3ListView::itemRect()
       
  3871 */
       
  3872 
       
  3873 Q3ListViewItem * Q3ListViewItem::itemBelow() const
       
  3874 {
       
  3875     Q3ListViewItem * c = 0;
       
  3876     if (isOpen() && childItem) {
       
  3877         c = childItem;
       
  3878     } else if (siblingItem) {
       
  3879         c = siblingItem;
       
  3880     } else if (parentItem) {
       
  3881         c = const_cast<Q3ListViewItem*>(this);
       
  3882         do {
       
  3883             c = c->parentItem;
       
  3884         } while(c->parentItem && !c->siblingItem);
       
  3885         if (c)
       
  3886             c = c->siblingItem;
       
  3887     }
       
  3888     if (c && (!c->height() || !c->isEnabled()))
       
  3889         return c->itemBelow();
       
  3890     return c;
       
  3891 }
       
  3892 
       
  3893 
       
  3894 /*!
       
  3895     \fn bool Q3ListViewItem::isOpen() const
       
  3896 
       
  3897     Returns true if this list view item has children \e and they are
       
  3898     not explicitly hidden; otherwise returns false.
       
  3899 
       
  3900     \sa setOpen()
       
  3901 */
       
  3902 
       
  3903 /*!
       
  3904     Returns the first (top) child of this item, or 0 if this item has
       
  3905     no children.
       
  3906 
       
  3907     Note that the children are not guaranteed to be sorted properly.
       
  3908     Q3ListView and Q3ListViewItem try to postpone or avoid sorting to
       
  3909     the greatest degree possible, in order to keep the user interface
       
  3910     snappy.
       
  3911 
       
  3912     \sa nextSibling() sortChildItems()
       
  3913 */
       
  3914 
       
  3915 Q3ListViewItem* Q3ListViewItem::firstChild() const
       
  3916 {
       
  3917     enforceSortOrder();
       
  3918     return childItem;
       
  3919 }
       
  3920 
       
  3921 
       
  3922 /*!
       
  3923     Returns the parent of this item, or 0 if this item has no parent.
       
  3924 
       
  3925     \sa firstChild(), nextSibling()
       
  3926 */
       
  3927 
       
  3928 Q3ListViewItem* Q3ListViewItem::parent() const
       
  3929 {
       
  3930     if (!parentItem || parentItem->is_root) return 0;
       
  3931     return parentItem;
       
  3932 }
       
  3933 
       
  3934 
       
  3935 /*!
       
  3936     \fn Q3ListViewItem* Q3ListViewItem::nextSibling() const
       
  3937 
       
  3938     Returns the sibling item below this item, or 0 if there is no
       
  3939     sibling item after this item.
       
  3940 
       
  3941     Note that the siblings are not guaranteed to be sorted properly.
       
  3942     Q3ListView and Q3ListViewItem try to postpone or avoid sorting to
       
  3943     the greatest degree possible, in order to keep the user interface
       
  3944     snappy.
       
  3945 
       
  3946     \sa firstChild() sortChildItems()
       
  3947 */
       
  3948 
       
  3949 /*!
       
  3950     \fn int Q3ListViewItem::childCount () const
       
  3951 
       
  3952     Returns how many children this item has. The count only includes
       
  3953     the item's immediate children.
       
  3954 */
       
  3955 
       
  3956 
       
  3957 /*!
       
  3958     Returns the height of this item in pixels. This does not include
       
  3959     the height of any children; totalHeight() returns that.
       
  3960 */
       
  3961 int Q3ListViewItem::height() const
       
  3962 {
       
  3963     Q3ListViewItem * that = (Q3ListViewItem *)this;
       
  3964     if (!that->configured) {
       
  3965         that->configured = true;
       
  3966         that->setup(); // ### virtual non-const function called in const
       
  3967     }
       
  3968 
       
  3969     return visible ? ownHeight : 0;
       
  3970 }
       
  3971 
       
  3972 /*!
       
  3973     Call this function when the value of width() may have changed for
       
  3974     column \a c. Normally, you should call this if text(c) changes.
       
  3975     Passing -1 for \a c indicates that all columns may have changed.
       
  3976     It is more efficient to pass -1 if two or more columns have
       
  3977     changed than to call widthChanged() separately for each one.
       
  3978 
       
  3979     \sa width()
       
  3980 */
       
  3981 void Q3ListViewItem::widthChanged(int c) const
       
  3982 {
       
  3983     Q3ListView *lv = listView();
       
  3984     if (lv)
       
  3985         lv->widthChanged(this, c);
       
  3986 }
       
  3987 
       
  3988 /*!
       
  3989     \fn void  Q3ListView::dropped (QDropEvent * e)
       
  3990 
       
  3991     This signal is emitted, when a drop event occurred on the
       
  3992     viewport (not onto an item).
       
  3993 
       
  3994     \a e provides all the information about the drop.
       
  3995 */
       
  3996 
       
  3997 /*!
       
  3998     \fn void Q3ListView::selectionChanged()
       
  3999 
       
  4000     This signal is emitted whenever the set of selected items has
       
  4001     changed (normally before the screen update). It is available both
       
  4002     in \c Single selection and \c Multi selection mode but is most
       
  4003     useful in \c Multi selection mode.
       
  4004 
       
  4005     \warning Do not delete any Q3ListViewItem objects in slots
       
  4006     connected to this signal.
       
  4007 
       
  4008     \sa setSelected() Q3ListViewItem::setSelected()
       
  4009 */
       
  4010 
       
  4011 
       
  4012 /*!
       
  4013     \fn void Q3ListView::pressed(Q3ListViewItem *item)
       
  4014 
       
  4015     This signal is emitted whenever the user presses the mouse button
       
  4016     in a list view. \a item is the list view item on which the user
       
  4017     pressed the mouse button, or 0 if the user didn't press the mouse
       
  4018     on an item.
       
  4019 
       
  4020     \warning Do not delete any Q3ListViewItem objects in slots
       
  4021     connected to this signal.
       
  4022 */
       
  4023 
       
  4024 /*!
       
  4025     \fn void Q3ListView::pressed(Q3ListViewItem *item, const QPoint &pnt, int c)
       
  4026 
       
  4027     \overload
       
  4028 
       
  4029     This signal is emitted whenever the user presses the mouse button
       
  4030     in a list view. \a item is the list view item on which the user
       
  4031     pressed the mouse button, or 0 if the user didn't press the mouse
       
  4032     on an item. \a pnt is the position of the mouse cursor in global
       
  4033     coordinates, and \a c is the column where the mouse cursor was
       
  4034     when the user pressed the mouse button.
       
  4035 
       
  4036     \warning Do not delete any Q3ListViewItem objects in slots
       
  4037     connected to this signal.
       
  4038 */
       
  4039 
       
  4040 /*!
       
  4041     \fn void Q3ListView::clicked(Q3ListViewItem *item)
       
  4042 
       
  4043     This signal is emitted whenever the user clicks (mouse pressed \e
       
  4044     and mouse released) in the list view. \a item is the clicked list
       
  4045     view item, or 0 if the user didn't click on an item.
       
  4046 
       
  4047     \warning Do not delete any Q3ListViewItem objects in slots
       
  4048     connected to this signal.
       
  4049 */
       
  4050 
       
  4051 /*!
       
  4052     \fn void Q3ListView::mouseButtonClicked(int button, Q3ListViewItem * item, const QPoint & pos, int c)
       
  4053 
       
  4054     This signal is emitted whenever the user clicks (mouse pressed \e
       
  4055     and mouse released) in the list view at position \a pos. \a button
       
  4056     is the mouse button that the user pressed, \a item is the clicked
       
  4057     list view item or 0 if the user didn't click on an item. If \a
       
  4058     item is not 0, \a c is the list view column into which the user
       
  4059     pressed; if \a item is 0 \a{c}'s value is undefined.
       
  4060 
       
  4061     \warning Do not delete any Q3ListViewItem objects in slots
       
  4062     connected to this signal.
       
  4063 */
       
  4064 
       
  4065 /*!
       
  4066     \fn void Q3ListView::mouseButtonPressed(int button, Q3ListViewItem * item, const QPoint & pos, int c)
       
  4067 
       
  4068     This signal is emitted whenever the user pressed the mouse button
       
  4069     in the list view at position \a pos. \a button is the mouse button
       
  4070     which the user pressed, \a item is the pressed list view item or 0
       
  4071     if the user didn't press on an item. If \a item is not 0, \a c is
       
  4072     the list view column into which the user pressed; if \a item is 0
       
  4073     \a{c}'s value is undefined.
       
  4074 
       
  4075     \warning Do not delete any Q3ListViewItem objects in slots
       
  4076     connected to this signal.
       
  4077 */
       
  4078 
       
  4079 /*!
       
  4080     \fn void Q3ListView::clicked(Q3ListViewItem *item, const QPoint &pnt, int c)
       
  4081 
       
  4082     \overload
       
  4083 
       
  4084     This signal is emitted whenever the user clicks (mouse pressed \e
       
  4085     and mouse released) in the list view. \a item is the clicked list
       
  4086     view item, or 0 if the user didn't click on an item. \a pnt is the
       
  4087     position where the user has clicked in global coordinates. If \a
       
  4088     item is not 0, \a c is the list view column into which the user
       
  4089     pressed; if \a item is 0 \a{c}'s value is undefined.
       
  4090 
       
  4091     \warning Do not delete any Q3ListViewItem objects in slots
       
  4092     connected to this signal.
       
  4093 */
       
  4094 
       
  4095 /*!
       
  4096     \fn void Q3ListView::selectionChanged(Q3ListViewItem *item)
       
  4097 
       
  4098     \overload
       
  4099 
       
  4100     This signal is emitted whenever the selected item has changed in
       
  4101     \c Single selection mode (normally after the screen update). The
       
  4102     argument is the newly selected \a item.
       
  4103 
       
  4104     In \c Multi selection mode, use the no argument overload of this
       
  4105     signal.
       
  4106 
       
  4107     \warning Do not delete any Q3ListViewItem objects in slots
       
  4108     connected to this signal.
       
  4109 
       
  4110     \sa setSelected() Q3ListViewItem::setSelected() currentChanged()
       
  4111 */
       
  4112 
       
  4113 
       
  4114 /*!
       
  4115     \fn void Q3ListView::currentChanged(Q3ListViewItem *item)
       
  4116 
       
  4117     This signal is emitted whenever the current item has changed
       
  4118     (normally after the screen update). The current item is the item
       
  4119     responsible for indicating keyboard focus.
       
  4120 
       
  4121     The argument is the newly current \a item, or 0 if the change made
       
  4122     no item current. This can happen, for example, if all the items in
       
  4123     the list view are deleted.
       
  4124 
       
  4125     \warning Do not delete any Q3ListViewItem objects in slots
       
  4126     connected to this signal.
       
  4127 
       
  4128     \sa setCurrentItem() currentItem()
       
  4129 */
       
  4130 
       
  4131 
       
  4132 /*!
       
  4133     \fn void Q3ListView::expanded(Q3ListViewItem *item)
       
  4134 
       
  4135     This signal is emitted when \a item has been expanded, i.e. when
       
  4136     the children of \a item are shown.
       
  4137 
       
  4138     \sa setOpen() collapsed()
       
  4139 */
       
  4140 
       
  4141 /*!
       
  4142     \fn void Q3ListView::collapsed(Q3ListViewItem *item)
       
  4143 
       
  4144     This signal is emitted when the \a item has been collapsed, i.e.
       
  4145     when the children of \a item are hidden.
       
  4146 
       
  4147     \sa setOpen() expanded()
       
  4148 */
       
  4149 
       
  4150 /*!
       
  4151     Processes the mouse press event \a e on behalf of the viewed widget.
       
  4152 */
       
  4153 void Q3ListView::contentsMousePressEvent(QMouseEvent * e)
       
  4154 {
       
  4155     contentsMousePressEventEx(e);
       
  4156 }
       
  4157 
       
  4158 void Q3ListView::contentsMousePressEventEx(QMouseEvent * e)
       
  4159 {
       
  4160     if (!e)
       
  4161         return;
       
  4162 
       
  4163     if (!d->ignoreEditAfterFocus)
       
  4164         d->startEdit = true;
       
  4165     d->ignoreEditAfterFocus = false;
       
  4166 
       
  4167     if (currentItem() && currentItem()->renameBox &&
       
  4168          !itemRect(currentItem()).contains(e->pos())) {
       
  4169         d->startEdit = false;
       
  4170         if (d->defRenameAction == Reject)
       
  4171             currentItem()->cancelRename(currentItem()->renameCol);
       
  4172         else
       
  4173             currentItem()->okRename(currentItem()->renameCol);
       
  4174     }
       
  4175 
       
  4176     d->startDragItem = 0;
       
  4177     d->dragStartPos = e->pos();
       
  4178     QPoint vp = contentsToViewport(e->pos());
       
  4179 
       
  4180     d->ignoreDoubleClick = false;
       
  4181     d->buttonDown = true;
       
  4182 
       
  4183     Q3ListViewItem * i = itemAt(vp);
       
  4184     d->pressedEmptyArea = e->y() > contentsHeight();
       
  4185     if (i && !i->isEnabled())
       
  4186         return;
       
  4187     if (d->startEdit && (i != currentItem() || (i && !i->isSelected())))
       
  4188         d->startEdit = false;
       
  4189     Q3ListViewItem *oldCurrent = currentItem();
       
  4190 
       
  4191     if (e->button() == Qt::RightButton && (e->state() & Qt::ControlButton))
       
  4192         goto emit_signals;
       
  4193 
       
  4194     if (!i) {
       
  4195         if (!(e->state() & Qt::ControlButton))
       
  4196             clearSelection();
       
  4197         goto emit_signals;
       
  4198     } else {
       
  4199         // No new anchor when using shift
       
  4200         if (!(e->state() & Qt::ShiftButton))
       
  4201             d->selectAnchor = i;
       
  4202     }
       
  4203 
       
  4204     if ((i->isExpandable() || i->childCount()) &&
       
  4205          d->h->mapToLogical(d->h->cellAt(vp.x())) == 0) {
       
  4206         int x1 = vp.x() +
       
  4207                  d->h->offset() -
       
  4208                  d->h->cellPos(d->h->mapToActual(0));
       
  4209         int draw = 0;
       
  4210         for (; draw < d->drawables.size(); ++draw)
       
  4211             if (d->drawables.at(draw).i == i)
       
  4212                 break;
       
  4213 
       
  4214         if (draw < d->drawables.size()) {
       
  4215             Q3ListViewPrivate::DrawableItem it = d->drawables.at(draw);
       
  4216             QStyleOptionQ3ListView opt = getStyleOption(this, i);
       
  4217             x1 -= treeStepSize() * (it.l - 1);
       
  4218             QStyle::SubControl ctrl = style()->hitTestComplexControl(QStyle::CC_Q3ListView, &opt,
       
  4219                                                                      QPoint(x1, e->pos().y()), this);
       
  4220             if (ctrl == QStyle::SC_Q3ListViewExpand &&
       
  4221                 e->type() == style()->styleHint(QStyle::SH_Q3ListViewExpand_SelectMouseType, 0,
       
  4222                                                this)) {
       
  4223                 d->buttonDown = false;
       
  4224                 if (e->button() == Qt::LeftButton) {
       
  4225                     bool close = i->isOpen();
       
  4226                     setOpen(i, !close);
       
  4227                     // ### Looks dangerous, removed because of reentrance problems
       
  4228                     // qApp->processEvents();
       
  4229                     if (!d->focusItem) {
       
  4230                         d->focusItem = i;
       
  4231                         repaintItem(d->focusItem);
       
  4232                         emit currentChanged(d->focusItem);
       
  4233                     }
       
  4234                     if (close) {
       
  4235                         bool newCurrent = false;
       
  4236                         Q3ListViewItem *ci = d->focusItem;
       
  4237                         while (ci) {
       
  4238                             if (ci->parent() && ci->parent() == i) {
       
  4239                                 newCurrent = true;
       
  4240                                 break;
       
  4241                             }
       
  4242                             ci = ci->parent();
       
  4243                         }
       
  4244                         if (newCurrent) {
       
  4245                             setCurrentItem(i);
       
  4246                         }
       
  4247                     }
       
  4248                 }
       
  4249                 d->ignoreDoubleClick = true;
       
  4250                 d->buttonDown = false;
       
  4251                 goto emit_signals;
       
  4252             }
       
  4253         }
       
  4254     }
       
  4255 
       
  4256     d->select = d->selectionMode == Multi ? !i->isSelected() : true;
       
  4257 
       
  4258     {// calculate activatedP
       
  4259         activatedByClick = true;
       
  4260         QPoint topLeft = itemRect(i).topLeft(); //### inefficient?
       
  4261         activatedP = vp - topLeft;
       
  4262         int xdepth = treeStepSize() * (i->depth() + (rootIsDecorated() ? 1 : 0))
       
  4263                      + itemMargin();
       
  4264         xdepth += d->h->sectionPos(d->h->mapToSection(0));
       
  4265         activatedP.rx() -= xdepth;
       
  4266     }
       
  4267     i->activate();
       
  4268     activatedByClick = false;
       
  4269 
       
  4270     if (i != d->focusItem)
       
  4271         setCurrentItem(i);
       
  4272     else
       
  4273         repaintItem(i);
       
  4274 
       
  4275     d->pressedSelected = i && i->isSelected();
       
  4276 
       
  4277     if (i->isSelectable() && selectionMode() != NoSelection) {
       
  4278         if (selectionMode() == Single)
       
  4279             setSelected(i, true);
       
  4280         else if (selectionMode() == Multi)
       
  4281             setSelected(i, d->select);
       
  4282         else if (selectionMode() == Extended) {
       
  4283             bool changed = false;
       
  4284             if (!(e->state() & (Qt::ControlButton | Qt::ShiftButton))) {
       
  4285                 if (!i->isSelected()) {
       
  4286                     bool blocked = signalsBlocked();
       
  4287                     blockSignals(true);
       
  4288                     clearSelection();
       
  4289                     blockSignals(blocked);
       
  4290                     i->setSelected(true);
       
  4291                     changed = true;
       
  4292                 }
       
  4293             } else {
       
  4294                 if (e->state() & Qt::ShiftButton)
       
  4295                     d->pressedSelected = false;
       
  4296                 if ((e->state() & Qt::ControlButton) && !(e->state() & Qt::ShiftButton) && i) {
       
  4297                     i->setSelected(!i->isSelected());
       
  4298                     changed = true;
       
  4299                     d->pressedSelected = false;
       
  4300                 } else if (!oldCurrent || !i || oldCurrent == i) {
       
  4301                     if ((bool)i->selected != d->select) {
       
  4302                         changed = true;
       
  4303                         i->setSelected(d->select);
       
  4304                     }
       
  4305                 // Shift pressed in Extended mode ---
       
  4306                 } else {
       
  4307                     changed = selectRange(i, oldCurrent, d->selectAnchor);
       
  4308                 }
       
  4309             }
       
  4310             if (changed) {
       
  4311                 triggerUpdate();
       
  4312                 emit selectionChanged();
       
  4313 
       
  4314 #ifndef QT_NO_ACCESSIBILITY
       
  4315                 QAccessible::updateAccessibility(viewport(), 0, QAccessible::Selection);
       
  4316 #endif
       
  4317             }
       
  4318         }
       
  4319     }
       
  4320 
       
  4321  emit_signals:
       
  4322 
       
  4323     if (i && !d->buttonDown &&
       
  4324          vp.x() + contentsX() < itemMargin() + (i->depth() + (rootIsDecorated() ? 1 : 0)) * treeStepSize())
       
  4325         i = 0;
       
  4326     d->pressedItem = i;
       
  4327 
       
  4328     int c = i ? d->h->mapToLogical(d->h->cellAt(vp.x())) : -1;
       
  4329     if (!i || (i && i->isEnabled())) {
       
  4330         emit pressed(i);
       
  4331         emit pressed(i, viewport()->mapToGlobal(vp), c);
       
  4332     }
       
  4333     emit mouseButtonPressed(e->button(), i, viewport()->mapToGlobal(vp), c);
       
  4334 
       
  4335     if (e->button() == Qt::RightButton && i == d->pressedItem) {
       
  4336         if (!i && !(e->state() & Qt::ControlButton))
       
  4337             clearSelection();
       
  4338 
       
  4339         emit rightButtonPressed(i, viewport()->mapToGlobal(vp), c);
       
  4340     }
       
  4341 }
       
  4342 
       
  4343 /*!
       
  4344     \reimp
       
  4345 */
       
  4346 
       
  4347 void Q3ListView::contentsContextMenuEvent(QContextMenuEvent *e)
       
  4348 {
       
  4349     if (!receivers(SIGNAL(contextMenuRequested(Q3ListViewItem*,QPoint,int)))) {
       
  4350         e->ignore();
       
  4351         return;
       
  4352     }
       
  4353     if (e->reason() == QContextMenuEvent::Keyboard) {
       
  4354         Q3ListViewItem *item = currentItem();
       
  4355         if (item) {
       
  4356             QRect r = itemRect(item);
       
  4357             QPoint p = r.topLeft();
       
  4358             if (allColumnsShowFocus())
       
  4359                 p += QPoint(width() / 2, (r.height() / 2));
       
  4360             else
       
  4361                 p += QPoint(columnWidth(0) / 2, (r.height() / 2));
       
  4362             p.rx() = qMax(0, p.x());
       
  4363             p.rx() = qMin(visibleWidth(), p.x());
       
  4364             emit contextMenuRequested(item, viewport()->mapToGlobal(p), -1);
       
  4365         }
       
  4366     } else {
       
  4367         QPoint vp = contentsToViewport(e->pos());
       
  4368         Q3ListViewItem * i = itemAt(vp);
       
  4369         int c = i ? d->h->mapToLogical(d->h->cellAt(vp.x())) : -1;
       
  4370         emit contextMenuRequested(i, viewport()->mapToGlobal(vp), c);
       
  4371     }
       
  4372 }
       
  4373 
       
  4374 /*!
       
  4375     Processes the mouse release event \a e on behalf of the viewed widget.
       
  4376 */
       
  4377 void Q3ListView::contentsMouseReleaseEvent(QMouseEvent * e)
       
  4378 {
       
  4379     contentsMouseReleaseEventEx(e);
       
  4380 }
       
  4381 
       
  4382 void Q3ListView::contentsMouseReleaseEventEx(QMouseEvent * e)
       
  4383 {
       
  4384     d->startDragItem = 0;
       
  4385     bool emitClicked = !d->pressedItem || d->buttonDown;
       
  4386     d->buttonDown = false;
       
  4387     // delete and disconnect autoscroll timer, if we have one
       
  4388     if (d->scrollTimer) {
       
  4389         disconnect(d->scrollTimer, SIGNAL(timeout()),
       
  4390                     this, SLOT(doAutoScroll()));
       
  4391         d->scrollTimer->stop();
       
  4392         delete d->scrollTimer;
       
  4393         d->scrollTimer = 0;
       
  4394     }
       
  4395 
       
  4396     if (!e)
       
  4397         return;
       
  4398 
       
  4399     if (d->selectionMode == Extended &&
       
  4400          d->focusItem == d->pressedItem &&
       
  4401          d->pressedSelected && d->focusItem &&
       
  4402          e->button() == Qt::LeftButton) {
       
  4403         bool block = signalsBlocked();
       
  4404         blockSignals(true);
       
  4405         clearSelection();
       
  4406         blockSignals(block);
       
  4407         d->focusItem->setSelected(true);
       
  4408         emit selectionChanged();
       
  4409 #ifndef QT_NO_ACCESSIBILITY
       
  4410         QAccessible::updateAccessibility(viewport(), 0, QAccessible::Selection);
       
  4411 #endif
       
  4412     }
       
  4413 
       
  4414     QPoint vp = contentsToViewport(e->pos());
       
  4415     Q3ListViewItem *i = itemAt(vp);
       
  4416     if (i && !i->isEnabled())
       
  4417         return;
       
  4418 
       
  4419     if (i && i == d->pressedItem && (i->isExpandable() || i->childCount()) &&
       
  4420          !d->h->mapToLogical(d->h->cellAt(vp.x())) && e->button() == Qt::LeftButton &&
       
  4421          e->type() == style()->styleHint(QStyle::SH_Q3ListViewExpand_SelectMouseType, 0, this)) {
       
  4422         int draw = 0;
       
  4423         for (; draw < d->drawables.size(); ++draw)
       
  4424             if (d->drawables.at(draw).i == i)
       
  4425                 break;
       
  4426         if (draw < d->drawables.size()) {
       
  4427             int x1 = vp.x() + d->h->offset() - d->h->cellPos(d->h->mapToActual(0)) -
       
  4428                      (treeStepSize() * (d->drawables.at(draw).l - 1));
       
  4429             QStyleOptionQ3ListView opt = getStyleOption(this, i);
       
  4430             QStyle::SubControl ctrl = style()->hitTestComplexControl(QStyle::CC_Q3ListView, &opt,
       
  4431                                                                      QPoint(x1, e->pos().y()), this);
       
  4432             if (ctrl == QStyle::SC_Q3ListViewExpand) {
       
  4433                 bool close = i->isOpen();
       
  4434                 setOpen(i, !close);
       
  4435                 // ### Looks dangerous, removed because of reentrance problems
       
  4436                 // qApp->processEvents();
       
  4437                 if (!d->focusItem) {
       
  4438                     d->focusItem = i;
       
  4439                     repaintItem(d->focusItem);
       
  4440                     emit currentChanged(d->focusItem);
       
  4441                 }
       
  4442                 if (close) {
       
  4443                     bool newCurrent = false;
       
  4444                     Q3ListViewItem *ci = d->focusItem;
       
  4445                     while (ci) {
       
  4446                         if (ci->parent() && ci->parent() == i) {
       
  4447                             newCurrent = true;
       
  4448                             break;
       
  4449                         }
       
  4450                         ci = ci->parent();
       
  4451                     }
       
  4452                     if (newCurrent)
       
  4453                         setCurrentItem(i);
       
  4454                     d->ignoreDoubleClick = true;
       
  4455                 }
       
  4456             }
       
  4457         }
       
  4458     }
       
  4459 
       
  4460     if (i == d->pressedItem && i && i->isSelected() && e->button() == Qt::LeftButton && d->startEdit) {
       
  4461         QRect r = itemRect(currentItem());
       
  4462         r = QRect(viewportToContents(r.topLeft()), r.size());
       
  4463         d->pressedColumn = header()->sectionAt( e->pos().x());
       
  4464         r.setLeft(header()->sectionPos(d->pressedColumn));
       
  4465         r.setWidth(header()->sectionSize(d->pressedColumn) - 1);
       
  4466         if (d->pressedColumn == 0)
       
  4467             r.setLeft(r.left() + itemMargin() + (currentItem()->depth() +
       
  4468                                                    (rootIsDecorated() ? 1 : 0)) * treeStepSize() - 1);
       
  4469         if (r.contains(e->pos()) &&
       
  4470              !(e->state() & (Qt::ShiftButton | Qt::ControlButton)))
       
  4471             d->renameTimer->start(QApplication::doubleClickInterval(), true);
       
  4472     }
       
  4473     if (i && vp.x() + contentsX() < itemMargin() + (i->depth() + (rootIsDecorated() ? 1 : 0)) * treeStepSize())
       
  4474         i = 0;
       
  4475     emitClicked = emitClicked && d->pressedItem == i;
       
  4476     d->pressedItem = 0;
       
  4477 
       
  4478     if (emitClicked) {
       
  4479         if (!i || (i && i->isEnabled())) {
       
  4480             emit clicked(i);
       
  4481             emit clicked(i, viewport()->mapToGlobal(vp), d->h->mapToLogical(d->h->cellAt(vp.x())));
       
  4482         }
       
  4483         emit mouseButtonClicked(e->button(), i, viewport()->mapToGlobal(vp),
       
  4484                                  i ? d->h->mapToLogical(d->h->cellAt(vp.x())) : -1);
       
  4485 
       
  4486         if (e->button() == Qt::RightButton) {
       
  4487             if (!i) {
       
  4488                 if (!(e->state() & Qt::ControlButton))
       
  4489                     clearSelection();
       
  4490                 emit rightButtonClicked(0, viewport()->mapToGlobal(vp), -1);
       
  4491                 return;
       
  4492             }
       
  4493 
       
  4494             int c = d->h->mapToLogical(d->h->cellAt(vp.x()));
       
  4495             emit rightButtonClicked(i, viewport()->mapToGlobal(vp), c);
       
  4496         }
       
  4497     }
       
  4498 }
       
  4499 
       
  4500 
       
  4501 /*!
       
  4502     Processes the mouse double-click event \a e on behalf of the viewed widget.
       
  4503 */
       
  4504 void Q3ListView::contentsMouseDoubleClickEvent(QMouseEvent * e)
       
  4505 {
       
  4506     d->renameTimer->stop();
       
  4507     d->startEdit = false;
       
  4508     if (!e || e->button() != Qt::LeftButton)
       
  4509         return;
       
  4510 
       
  4511     // ensure that the following mouse moves and eventual release is
       
  4512     // ignored.
       
  4513     d->buttonDown = false;
       
  4514 
       
  4515     if (d->ignoreDoubleClick) {
       
  4516         d->ignoreDoubleClick = false;
       
  4517         return;
       
  4518     }
       
  4519 
       
  4520     QPoint vp = contentsToViewport(e->pos());
       
  4521 
       
  4522     Q3ListViewItem * i = itemAt(vp);
       
  4523 
       
  4524     // we emit doubleClicked when the item is null (or enabled) to be consistent with
       
  4525     // rightButtonClicked etc.
       
  4526     if (!i || i->isEnabled()) {
       
  4527         int c = d->h->mapToLogical(d->h->cellAt(vp.x()));
       
  4528         emit doubleClicked(i, viewport()->mapToGlobal(vp), c);
       
  4529     }
       
  4530 
       
  4531     if (!i || !i->isEnabled())
       
  4532         return;
       
  4533 
       
  4534     if (!i->isOpen()) {
       
  4535         if (i->isExpandable() || i->childCount())
       
  4536             setOpen(i, true);
       
  4537     } else {
       
  4538         setOpen(i, false);
       
  4539     }
       
  4540 
       
  4541     // we emit the 'old' obsolete doubleClicked only if the item is not null and enabled
       
  4542     emit doubleClicked(i);
       
  4543 }
       
  4544 
       
  4545 
       
  4546 /*!
       
  4547     Processes the mouse move event \a e on behalf of the viewed widget.
       
  4548 */
       
  4549 void Q3ListView::contentsMouseMoveEvent(QMouseEvent * e)
       
  4550 {
       
  4551     if (!e)
       
  4552         return;
       
  4553 
       
  4554     bool needAutoScroll = false;
       
  4555 
       
  4556     QPoint vp = contentsToViewport(e->pos());
       
  4557 
       
  4558     Q3ListViewItem * i = itemAt(vp);
       
  4559     if (i && !i->isEnabled())
       
  4560         return;
       
  4561     if (i != d->highlighted &&
       
  4562          !(d->pressedItem &&
       
  4563            (d->pressedItem->isSelected() || d->selectionMode == NoSelection) &&
       
  4564            d->pressedItem->dragEnabled())) {
       
  4565 
       
  4566         if (i) {
       
  4567             emit onItem(i);
       
  4568         } else {
       
  4569             emit onViewport();
       
  4570         }
       
  4571         d->highlighted = i;
       
  4572     }
       
  4573 
       
  4574     if (d->startDragItem)
       
  4575         i = d->startDragItem;
       
  4576 
       
  4577     if (!d->buttonDown ||
       
  4578          ((e->state() & Qt::LeftButton) != Qt::LeftButton &&
       
  4579            (e->state() & Qt::MidButton) != Qt::MidButton &&
       
  4580            (e->state() & Qt::RightButton) != Qt::RightButton))
       
  4581         return;
       
  4582 
       
  4583     if (d->pressedItem &&
       
  4584          (d->pressedItem->isSelected() || d->selectionMode == NoSelection) &&
       
  4585          d->pressedItem->dragEnabled()) {
       
  4586 
       
  4587         if (!d->startDragItem) {
       
  4588             setSelected(d->pressedItem, true);
       
  4589             d->startDragItem = d->pressedItem;
       
  4590         }
       
  4591         if ((d->dragStartPos - e->pos()).manhattanLength() > QApplication::startDragDistance()) {
       
  4592             d->buttonDown = false;
       
  4593 #ifndef QT_NO_DRAGANDDROP
       
  4594             startDrag();
       
  4595 #endif
       
  4596         }
       
  4597         return;
       
  4598     }
       
  4599 
       
  4600     // check, if we need to scroll
       
  4601     if (vp.y() > visibleHeight() || vp.y() < 0)
       
  4602         needAutoScroll = true;
       
  4603 
       
  4604     // if we need to scroll and no autoscroll timer is started,
       
  4605     // connect the timer
       
  4606     if (needAutoScroll && !d->scrollTimer) {
       
  4607         d->scrollTimer = new QTimer(this);
       
  4608         connect(d->scrollTimer, SIGNAL(timeout()),
       
  4609                  this, SLOT(doAutoScroll()));
       
  4610         d->scrollTimer->start(100, false);
       
  4611         // call it once manually
       
  4612         doAutoScroll(vp);
       
  4613     }
       
  4614 
       
  4615     // if we don't need to autoscroll
       
  4616     if (!needAutoScroll) {
       
  4617         // if there is a autoscroll timer, delete it
       
  4618         if (d->scrollTimer) {
       
  4619             disconnect(d->scrollTimer, SIGNAL(timeout()),
       
  4620                         this, SLOT(doAutoScroll()));
       
  4621             d->scrollTimer->stop();
       
  4622             delete d->scrollTimer;
       
  4623             d->scrollTimer = 0;
       
  4624         }
       
  4625         // call this to select an item (using the pos from the event)
       
  4626         doAutoScroll(vp);
       
  4627     }
       
  4628 }
       
  4629 
       
  4630 
       
  4631 /*!
       
  4632     This slot handles auto-scrolling when the mouse button is pressed
       
  4633     and the mouse is outside the widget.
       
  4634 */
       
  4635 void Q3ListView::doAutoScroll()
       
  4636 {
       
  4637     doAutoScroll(QPoint());
       
  4638 }
       
  4639 
       
  4640 /*
       
  4641   Handles auto-scrolling when the mouse button is pressed
       
  4642   and the mouse is outside the widget.
       
  4643 
       
  4644   If cursorPos is (0,0) (isNull == true) it uses the current QCursor::pos, otherwise it uses cursorPos
       
  4645 */
       
  4646 void Q3ListView::doAutoScroll(const QPoint &cursorPos)
       
  4647 {
       
  4648     QPoint pos = cursorPos.isNull() ? viewport()->mapFromGlobal(QCursor::pos()) :  cursorPos;
       
  4649     if (!d->focusItem || (d->pressedEmptyArea && pos.y() > contentsHeight()))
       
  4650         return;
       
  4651 
       
  4652     bool down = pos.y() > itemRect(d->focusItem).y();
       
  4653 
       
  4654     int g = pos.y() + contentsY();
       
  4655 
       
  4656     if (down && pos.y() > height() )
       
  4657         g = height() + contentsY();
       
  4658     else if (pos.y() < 0)
       
  4659         g = contentsY();
       
  4660 
       
  4661     Q3ListViewItem *c = d->focusItem, *old = 0;
       
  4662     Q3ListViewItem *oldCurrent = c;
       
  4663     if (down) {
       
  4664         int y = itemRect(d->focusItem).y() + contentsY();
       
  4665         while(c && y + c->height() <= g) {
       
  4666             y += c->height();
       
  4667             old = c;
       
  4668             c = c->itemBelow();
       
  4669         }
       
  4670         if (!c && old)
       
  4671             c = old;
       
  4672     } else {
       
  4673         int y = itemRect(d->focusItem).y() + contentsY();
       
  4674         while(c && y >= g) {
       
  4675             old = c;
       
  4676             c = c->itemAbove();
       
  4677             if (c)
       
  4678                 y -= c->height();
       
  4679         }
       
  4680         if (!c && old)
       
  4681             c = old;
       
  4682     }
       
  4683 
       
  4684     if (!c || c == d->focusItem)
       
  4685         return;
       
  4686 
       
  4687     if (d->focusItem) {
       
  4688         if (d->selectionMode == Multi) {
       
  4689             // also (de)select the ones in between
       
  4690             Q3ListViewItem * b = d->focusItem;
       
  4691             bool down = (itemPos(c) > itemPos(b));
       
  4692             while(b && b != c) {
       
  4693                 if (b->isSelectable())
       
  4694                     setSelected(b, d->select);
       
  4695                 b = down ? b->itemBelow() : b->itemAbove();
       
  4696             }
       
  4697             if (c->isSelectable())
       
  4698                 setSelected(c, d->select);
       
  4699         } else if (d->selectionMode == Extended) {
       
  4700             if (selectRange(c, oldCurrent, d->selectAnchor)) {
       
  4701                 triggerUpdate();
       
  4702                 emit selectionChanged();
       
  4703             }
       
  4704         }
       
  4705     }
       
  4706 
       
  4707     setCurrentItem(c);
       
  4708     d->visibleTimer->start(1, true);
       
  4709 }
       
  4710 
       
  4711 /*!
       
  4712     \reimp
       
  4713 */
       
  4714 
       
  4715 void Q3ListView::focusInEvent(QFocusEvent *e)
       
  4716 {
       
  4717     d->inMenuMode = false;
       
  4718     if (d->focusItem) {
       
  4719         repaintItem(d->focusItem);
       
  4720     } else if (firstChild() && e->reason() != Qt::MouseFocusReason) {
       
  4721         d->focusItem = firstChild();
       
  4722         emit currentChanged(d->focusItem);
       
  4723         repaintItem(d->focusItem);
       
  4724     }
       
  4725     if (e->reason() == Qt::MouseFocusReason) {
       
  4726         d->ignoreEditAfterFocus = true;
       
  4727         d->startEdit = false;
       
  4728     }
       
  4729     if (style()->styleHint(QStyle::SH_ItemView_ChangeHighlightOnFocus, 0, this)) {
       
  4730         viewport()->repaint();
       
  4731     }
       
  4732 }
       
  4733 
       
  4734 /*!
       
  4735     \reimp
       
  4736 */
       
  4737 QVariant Q3ListView::inputMethodQuery(Qt::InputMethodQuery query) const
       
  4738 {
       
  4739     if (query == Qt::ImMicroFocus) {
       
  4740         QRect mfrect = itemRect(d->focusItem);
       
  4741         if (mfrect.isValid() && header() && header()->isVisible())
       
  4742             mfrect.moveBy(0, header()->height());
       
  4743         return mfrect;
       
  4744     }
       
  4745     return QWidget::inputMethodQuery(query);
       
  4746 }
       
  4747 
       
  4748 /*!
       
  4749     \reimp
       
  4750 */
       
  4751 
       
  4752 void Q3ListView::focusOutEvent(QFocusEvent *e)
       
  4753 {
       
  4754     if (e->reason() == Qt::PopupFocusReason && d->buttonDown)
       
  4755         d->buttonDown = false;
       
  4756     if (style()->styleHint(QStyle::SH_ItemView_ChangeHighlightOnFocus, 0, this)) {
       
  4757         d->inMenuMode =
       
  4758             e->reason() == Qt::PopupFocusReason
       
  4759             || (qApp->focusWidget() && qApp->focusWidget()->inherits("QMenuBar"));
       
  4760         if (!d->inMenuMode) {
       
  4761             viewport()->repaint();
       
  4762         }
       
  4763     }
       
  4764 
       
  4765     if (d->focusItem)
       
  4766         repaintItem(d->focusItem);
       
  4767 }
       
  4768 
       
  4769 
       
  4770 /*!
       
  4771     \reimp
       
  4772 */
       
  4773 
       
  4774 void Q3ListView::keyPressEvent(QKeyEvent * e)
       
  4775 {
       
  4776     if (currentItem() && currentItem()->renameBox)
       
  4777         return;
       
  4778     if (!firstChild()) {
       
  4779         e->ignore();
       
  4780         return; // subclass bug
       
  4781     }
       
  4782 
       
  4783     Q3ListViewItem* oldCurrent = currentItem();
       
  4784     if (!oldCurrent) {
       
  4785         setCurrentItem(firstChild());
       
  4786         if (d->selectionMode == Single)
       
  4787             setSelected(firstChild(), true);
       
  4788         return;
       
  4789     }
       
  4790 
       
  4791     Q3ListViewItem * i = currentItem();
       
  4792     Q3ListViewItem *old = i;
       
  4793 
       
  4794     QRect r(itemRect(i));
       
  4795     Q3ListViewItem * i2;
       
  4796 
       
  4797     bool singleStep = false;
       
  4798     bool selectCurrent = true;
       
  4799     bool wasNavigation = true;
       
  4800 
       
  4801     switch(e->key()) {
       
  4802     case Qt::Key_Backspace:
       
  4803     case Qt::Key_Delete:
       
  4804         d->currentPrefix.truncate(0);
       
  4805         break;
       
  4806     case Qt::Key_Enter:
       
  4807     case Qt::Key_Return:
       
  4808         d->currentPrefix.truncate(0);
       
  4809         if (i && !i->isSelectable() && i->isEnabled() &&
       
  4810              (i->childCount() || i->isExpandable() || i->isOpen())) {
       
  4811             i->setOpen(!i->isOpen());
       
  4812             return;
       
  4813         }
       
  4814         e->ignore();
       
  4815         if (currentItem() && !currentItem()->isEnabled())
       
  4816             break;
       
  4817         emit returnPressed(currentItem());
       
  4818         // do NOT accept.  QDialog.
       
  4819         return;
       
  4820     case Qt::Key_Down:
       
  4821         selectCurrent = false;
       
  4822         i = i->itemBelow();
       
  4823         d->currentPrefix.truncate(0);
       
  4824         singleStep = true;
       
  4825         break;
       
  4826     case Qt::Key_Up:
       
  4827         selectCurrent = false;
       
  4828         i = i->itemAbove();
       
  4829         d->currentPrefix.truncate(0);
       
  4830         singleStep = true;
       
  4831         break;
       
  4832     case Qt::Key_Home:
       
  4833         selectCurrent = false;
       
  4834         i = firstChild();
       
  4835         if (!i->height() || !i->isEnabled())
       
  4836             i = i->itemBelow();
       
  4837         d->currentPrefix.truncate(0);
       
  4838         break;
       
  4839     case Qt::Key_End:
       
  4840         selectCurrent = false;
       
  4841         i = firstChild();
       
  4842         while (i->nextSibling() && i->nextSibling()->height() && i->nextSibling()->isEnabled())
       
  4843             i = i->nextSibling();
       
  4844         while (i->itemBelow())
       
  4845             i = i->itemBelow();
       
  4846         d->currentPrefix.truncate(0);
       
  4847         break;
       
  4848     case Qt::Key_Next:
       
  4849         selectCurrent = false;
       
  4850         i2 = itemAt(QPoint(0, visibleHeight()-1));
       
  4851         if (i2 == i || !r.isValid() ||
       
  4852              visibleHeight() <= itemRect(i).bottom()) {
       
  4853             if (i2)
       
  4854                 i = i2;
       
  4855             int left = visibleHeight();
       
  4856             while((i2 = i->itemBelow()) != 0 && left > i2->height()) {
       
  4857                 left -= i2->height();
       
  4858                 i = i2;
       
  4859             }
       
  4860         } else {
       
  4861             if (!i2) {
       
  4862                 // list is shorter than the view, goto last item
       
  4863                 while((i2 = i->itemBelow()) != 0)
       
  4864                     i = i2;
       
  4865             } else {
       
  4866                 i = i2;
       
  4867             }
       
  4868         }
       
  4869         d->currentPrefix.truncate(0);
       
  4870         break;
       
  4871     case Qt::Key_Prior:
       
  4872         selectCurrent = false;
       
  4873         i2 = itemAt(QPoint(0, 0));
       
  4874         if (i == i2 || !r.isValid() || r.top() <= 0) {
       
  4875             if (i2)
       
  4876                 i = i2;
       
  4877             int left = visibleHeight();
       
  4878             while((i2 = i->itemAbove()) != 0 && left > i2->height()) {
       
  4879                 left -= i2->height();
       
  4880                 i = i2;
       
  4881             }
       
  4882         } else {
       
  4883             i = i2;
       
  4884         }
       
  4885         d->currentPrefix.truncate(0);
       
  4886         break;
       
  4887     case Qt::Key_Plus:
       
  4888         d->currentPrefix.truncate(0);
       
  4889         if ( !i->isOpen() && (i->isExpandable() || i->childCount()))
       
  4890             setOpen(i, true);
       
  4891         else
       
  4892             return;
       
  4893         break;
       
  4894     case Qt::Key_Right:
       
  4895         d->currentPrefix.truncate(0);
       
  4896         if (i->isOpen() && i->childItem) {
       
  4897             i = i->childItem;
       
  4898         } else if (!i->isOpen() && (i->isExpandable() || i->childCount())) {
       
  4899             setOpen(i, true);
       
  4900         } else if (contentsX() + visibleWidth() < contentsWidth()) {
       
  4901             horizontalScrollBar()->triggerAction(QScrollBar::SliderSingleStepAdd);
       
  4902             return;
       
  4903         } else {
       
  4904             return;
       
  4905         }
       
  4906         break;
       
  4907     case Qt::Key_Minus:
       
  4908         d->currentPrefix.truncate(0);
       
  4909         if (i->isOpen())
       
  4910             setOpen(i, false);
       
  4911         else
       
  4912             return;
       
  4913         break;
       
  4914     case Qt::Key_Left:
       
  4915         d->currentPrefix.truncate(0);
       
  4916         if (i->isOpen()) {
       
  4917             setOpen(i, false);
       
  4918         } else if (i->parentItem && i->parentItem != d->r) {
       
  4919             i = i->parentItem;
       
  4920         } else if (contentsX()) {
       
  4921             horizontalScrollBar()->triggerAction(QScrollBar::SliderSingleStepSub);
       
  4922             return;
       
  4923         } else {
       
  4924             return;
       
  4925         }
       
  4926         break;
       
  4927     case Qt::Key_Space:
       
  4928         activatedByClick = false;
       
  4929         d->currentPrefix.truncate(0);
       
  4930         if (currentItem() && !currentItem()->isEnabled())
       
  4931             break;
       
  4932         i->activate();
       
  4933         if (i->isSelectable() && (d->selectionMode == Multi || d->selectionMode == Extended)) {
       
  4934             setSelected(i, !i->isSelected());
       
  4935             d->currentPrefix.truncate(0);
       
  4936         }
       
  4937         emit spacePressed(currentItem());
       
  4938         break;
       
  4939     case Qt::Key_Escape:
       
  4940         e->ignore(); // For QDialog
       
  4941         return;
       
  4942     case Qt::Key_F2:
       
  4943         if (currentItem() && currentItem()->renameEnabled(0))
       
  4944             currentItem()->startRename(0);
       
  4945     default:
       
  4946         if (e->text().length() > 0 && e->text()[0].isPrint()) {
       
  4947             selectCurrent = false;
       
  4948             wasNavigation = false;
       
  4949             QString input(d->currentPrefix);
       
  4950             Q3ListViewItem * keyItem = i;
       
  4951             QTime now(QTime::currentTime());
       
  4952             bool tryFirst = true;
       
  4953             while(keyItem) {
       
  4954                 // try twice, first with the previous string and this char
       
  4955                 if (d->currentPrefixTime.msecsTo(now) <= 400)
       
  4956                     input = input + e->text().toLower();
       
  4957                 else
       
  4958                     input = e->text().toLower();
       
  4959                 if (input.length() == e->text().length()) {
       
  4960                     if (keyItem->itemBelow()) {
       
  4961                         keyItem = keyItem->itemBelow();
       
  4962                         tryFirst = true;
       
  4963                     } else {
       
  4964                         keyItem = firstChild();
       
  4965                         tryFirst = false;
       
  4966                     }
       
  4967                 }
       
  4968                 QString keyItemKey;
       
  4969                 QString prefix;
       
  4970                 while(keyItem) {
       
  4971                     keyItemKey = QString::null;
       
  4972                     // Look first in the sort column, then left to right
       
  4973 		    if (d->sortcolumn != Unsorted)
       
  4974 			keyItemKey = keyItem->text(d->sortcolumn);
       
  4975                     for (int col = 0; col < d->h->count() && keyItemKey.isNull(); ++col)
       
  4976                         keyItemKey = keyItem->text(d->h->mapToSection(col));
       
  4977                     if (!keyItemKey.isEmpty()) {
       
  4978                         prefix = keyItemKey;
       
  4979                         prefix.truncate(input.length());
       
  4980                         prefix = prefix.toLower();
       
  4981                         if (prefix == input) {
       
  4982                             d->currentPrefix = input;
       
  4983                             d->currentPrefixTime = now;
       
  4984                             i = keyItem;
       
  4985                                 // nonoptimal double-break...
       
  4986                             keyItem = 0;
       
  4987                             input.truncate(0);
       
  4988                             tryFirst = false;
       
  4989                         }
       
  4990                     }
       
  4991                     if (keyItem)
       
  4992                         keyItem = keyItem->itemBelow();
       
  4993                     if (!keyItem && tryFirst) {
       
  4994                         keyItem = firstChild();
       
  4995                         tryFirst = false;
       
  4996                     }
       
  4997                 }
       
  4998                 // then, if appropriate, with just this character
       
  4999                 if (input.length() > e->text().length()) {
       
  5000                     input.truncate(0);
       
  5001                     keyItem = i;
       
  5002                 }
       
  5003             }
       
  5004         } else {
       
  5005             d->currentPrefix.truncate(0);
       
  5006             if (e->state() & Qt::ControlButton) {
       
  5007                 d->currentPrefix.clear();
       
  5008                 switch (e->key()) {
       
  5009                 case Qt::Key_A:
       
  5010                     selectAll(true);
       
  5011                     break;
       
  5012                 }
       
  5013             }
       
  5014             e->ignore();
       
  5015             return;
       
  5016         }
       
  5017     }
       
  5018 
       
  5019     if (!i)
       
  5020         return;
       
  5021 
       
  5022     if (!(e->state() & Qt::ShiftButton) || !d->selectAnchor)
       
  5023         d->selectAnchor = i;
       
  5024 
       
  5025     setCurrentItem(i);
       
  5026     if (i->isSelectable())
       
  5027         handleItemChange(old, wasNavigation && (e->state() & Qt::ShiftButton),
       
  5028                           wasNavigation && (e->state() & Qt::ControlButton));
       
  5029 
       
  5030     if (d->focusItem && !d->focusItem->isSelected() && d->selectionMode == Single && selectCurrent)
       
  5031         setSelected(d->focusItem, true);
       
  5032 
       
  5033     if (singleStep)
       
  5034         d->visibleTimer->start(1, true);
       
  5035     else
       
  5036         ensureItemVisible(i);
       
  5037 }
       
  5038 
       
  5039 
       
  5040 /*!
       
  5041     Returns the list view item at \a viewPos. Note that \a viewPos is
       
  5042     in the viewport()'s coordinate system, not in the list view's own,
       
  5043     much larger, coordinate system.
       
  5044 
       
  5045     itemAt() returns 0 if there is no such item.
       
  5046 
       
  5047     Note that you also get the pointer to the item if \a viewPos
       
  5048     points to the root decoration (see setRootIsDecorated()) of the
       
  5049     item. To check whether or not \a viewPos is on the root decoration
       
  5050     of the item, you can do something like this:
       
  5051 
       
  5052     \snippet doc/src/snippets/code/src_qt3support_itemviews_q3listview.cpp 4
       
  5053 
       
  5054     This might be interesting if you use this function to find out
       
  5055     where the user clicked and if you want to start a drag (which you
       
  5056     do not want to do if the user clicked onto the root decoration of
       
  5057     an item).
       
  5058 
       
  5059     \sa itemPos() itemRect() viewportToContents()
       
  5060 */
       
  5061 
       
  5062 Q3ListViewItem * Q3ListView::itemAt(const QPoint & viewPos) const
       
  5063 {
       
  5064     if (viewPos.x() > contentsWidth() - contentsX())
       
  5065         return 0;
       
  5066 
       
  5067     if (d->drawables.isEmpty())
       
  5068         buildDrawableList();
       
  5069 
       
  5070     int g = viewPos.y() + contentsY();
       
  5071 
       
  5072     for (int i = 0; i < d->drawables.size(); ++i) {
       
  5073         Q3ListViewPrivate::DrawableItem c = d->drawables.at(i);
       
  5074         if (c.y + c.i->height() > g
       
  5075             && c.i->isVisible() && (!c.i->parent() || c.i->parent()->isVisible()))
       
  5076             return c.y <= g ? c.i : 0;
       
  5077     }
       
  5078     return 0;
       
  5079 }
       
  5080 
       
  5081 
       
  5082 /*!
       
  5083     Returns the y-coordinate of \a item in the list view's coordinate
       
  5084     system. This function is normally much slower than itemAt() but it
       
  5085     works for all items, whereas itemAt() normally works only for
       
  5086     items on the screen.
       
  5087 
       
  5088     This is a thin wrapper around Q3ListViewItem::itemPos().
       
  5089 
       
  5090     \sa itemAt() itemRect()
       
  5091 */
       
  5092 
       
  5093 int Q3ListView::itemPos(const Q3ListViewItem * item)
       
  5094 {
       
  5095     return item ? item->itemPos() : 0;
       
  5096 }
       
  5097 
       
  5098 
       
  5099 /*!
       
  5100     \property Q3ListView::multiSelection
       
  5101     \brief whether the list view is in multi-selection or extended-selection mode
       
  5102 
       
  5103     If you enable multi-selection, \c Multi, mode, it is possible to
       
  5104     specify whether or not this mode should be extended. \c Extended
       
  5105     means that the user can select multiple items only when pressing
       
  5106     the Shift or Ctrl key at the same time.
       
  5107 
       
  5108     The default selection mode is \c Single.
       
  5109 
       
  5110     \sa selectionMode()
       
  5111 */
       
  5112 
       
  5113 void Q3ListView::setMultiSelection(bool enable)
       
  5114 {
       
  5115     if (!enable)
       
  5116         d->selectionMode = Q3ListView::Single;
       
  5117     else if ( d->selectionMode != Multi && d->selectionMode != Extended)
       
  5118         d->selectionMode = Q3ListView::Multi;
       
  5119 }
       
  5120 
       
  5121 bool Q3ListView::isMultiSelection() const
       
  5122 {
       
  5123     return d->selectionMode == Q3ListView::Extended || d->selectionMode == Q3ListView::Multi;
       
  5124 }
       
  5125 
       
  5126 /*!
       
  5127     \property Q3ListView::selectionMode
       
  5128     \brief the list view's selection mode
       
  5129 
       
  5130     The mode can be \c Single (the default), \c Extended, \c Multi or
       
  5131     \c NoSelection.
       
  5132 
       
  5133     \sa multiSelection
       
  5134 */
       
  5135 
       
  5136 void Q3ListView::setSelectionMode(SelectionMode mode)
       
  5137 {
       
  5138     if (d->selectionMode == mode)
       
  5139         return;
       
  5140 
       
  5141     if ((d->selectionMode == Multi || d->selectionMode == Extended) &&
       
  5142          (mode == Q3ListView::Single || mode == Q3ListView::NoSelection)){
       
  5143         clearSelection();
       
  5144         if ((mode == Q3ListView::Single) && currentItem())
       
  5145             currentItem()->selected = true;
       
  5146     }
       
  5147 
       
  5148     d->selectionMode = mode;
       
  5149 }
       
  5150 
       
  5151 Q3ListView::SelectionMode Q3ListView::selectionMode() const
       
  5152 {
       
  5153     return d->selectionMode;
       
  5154 }
       
  5155 
       
  5156 
       
  5157 /*!
       
  5158     If \a selected is true the \a item is selected; otherwise it is
       
  5159     unselected.
       
  5160 
       
  5161     If the list view is in \c Single selection mode and \a selected is
       
  5162     true, the currently selected item is unselected and \a item is
       
  5163     made current. Unlike Q3ListViewItem::setSelected(), this function
       
  5164     updates the list view as necessary and emits the
       
  5165     selectionChanged() signals.
       
  5166 
       
  5167     \sa isSelected() setMultiSelection() isMultiSelection()
       
  5168     setCurrentItem(), setSelectionAnchor()
       
  5169 */
       
  5170 
       
  5171 void Q3ListView::setSelected(Q3ListViewItem * item, bool selected)
       
  5172 {
       
  5173     if (!item || item->isSelected() == selected ||
       
  5174          !item->isSelectable() || selectionMode() == NoSelection)
       
  5175         return;
       
  5176 
       
  5177     bool emitHighlighted = false;
       
  5178     if (selectionMode() == Single && d->focusItem != item) {
       
  5179         Q3ListViewItem *o = d->focusItem;
       
  5180         if (d->focusItem && d->focusItem->selected)
       
  5181             d->focusItem->setSelected(false);
       
  5182         d->focusItem = item;
       
  5183         if (o)
       
  5184             repaintItem(o);
       
  5185         emitHighlighted = true;
       
  5186     }
       
  5187 
       
  5188     item->setSelected(selected);
       
  5189 
       
  5190     repaintItem(item);
       
  5191 
       
  5192     if (d->selectionMode == Single && selected)
       
  5193         emit selectionChanged(item);
       
  5194     emit selectionChanged();
       
  5195 
       
  5196     if (emitHighlighted)
       
  5197         emit currentChanged(d->focusItem);
       
  5198 }
       
  5199 
       
  5200 /*!
       
  5201     Sets the selection anchor to \a item, if \a item is selectable.
       
  5202 
       
  5203     The selection anchor is the item that remains selected when
       
  5204     Shift-selecting with either mouse or keyboard in \c Extended
       
  5205     selection mode.
       
  5206 
       
  5207     \sa setSelected()
       
  5208 */
       
  5209 
       
  5210 void Q3ListView::setSelectionAnchor(Q3ListViewItem *item)
       
  5211 {
       
  5212     if (item && item->isSelectable())
       
  5213         d->selectAnchor = item;
       
  5214 }
       
  5215 
       
  5216 /*!
       
  5217     Sets all the items to be not selected, updates the list view as
       
  5218     necessary, and emits the selectionChanged() signals. Note that for
       
  5219     \c Multi selection list views this function needs to iterate over
       
  5220     \e all items.
       
  5221 
       
  5222     \sa setSelected(), setMultiSelection()
       
  5223 */
       
  5224 
       
  5225 void Q3ListView::clearSelection()
       
  5226 {
       
  5227     selectAll(false);
       
  5228 }
       
  5229 
       
  5230 /*!
       
  5231     If \a select is true, all the items get selected; otherwise all
       
  5232     the items get unselected. This only works in the selection modes \c
       
  5233     Multi and \c Extended. In \c Single and \c NoSelection mode the
       
  5234     selection of the current item is just set to \a select.
       
  5235 */
       
  5236 
       
  5237 void Q3ListView::selectAll(bool select)
       
  5238 {
       
  5239     if (d->selectionMode == Multi || d->selectionMode == Extended) {
       
  5240         bool b = signalsBlocked();
       
  5241         blockSignals(true);
       
  5242         bool anything = false;
       
  5243         Q3ListViewItemIterator it(this);
       
  5244         while (it.current()) {
       
  5245             Q3ListViewItem *i = it.current();
       
  5246             if ((bool)i->selected != select) {
       
  5247                 i->setSelected(select);
       
  5248                 anything = true;
       
  5249             }
       
  5250             ++it;
       
  5251         }
       
  5252         blockSignals(b);
       
  5253         if (anything) {
       
  5254             emit selectionChanged();
       
  5255             triggerUpdate();
       
  5256         }
       
  5257     } else if (d->focusItem) {
       
  5258         Q3ListViewItem * i = d->focusItem;
       
  5259         setSelected(i, select);
       
  5260     }
       
  5261 }
       
  5262 
       
  5263 /*!
       
  5264     Inverts the selection. Only works in \c Multi and \c Extended
       
  5265     selection modes.
       
  5266 */
       
  5267 
       
  5268 void Q3ListView::invertSelection()
       
  5269 {
       
  5270     if (d->selectionMode == Single ||
       
  5271          d->selectionMode == NoSelection)
       
  5272         return;
       
  5273 
       
  5274     bool b = signalsBlocked();
       
  5275     blockSignals(true);
       
  5276     Q3ListViewItemIterator it(this);
       
  5277     for (; it.current(); ++it)
       
  5278         it.current()->setSelected(!it.current()->isSelected());
       
  5279     blockSignals(b);
       
  5280     emit selectionChanged();
       
  5281     triggerUpdate();
       
  5282 }
       
  5283 
       
  5284 
       
  5285 /*!
       
  5286     Returns true if the list view item \a i is selected; otherwise
       
  5287     returns false.
       
  5288 
       
  5289     \sa Q3ListViewItem::isSelected()
       
  5290 */
       
  5291 
       
  5292 bool Q3ListView::isSelected(const Q3ListViewItem * i) const
       
  5293 {
       
  5294     return i ? i->isSelected() : false;
       
  5295 }
       
  5296 
       
  5297 
       
  5298 /*!
       
  5299     Returns the selected item if the list view is in \c Single
       
  5300     selection mode and an item is selected.
       
  5301 
       
  5302     If no items are selected or the list view is not in \c Single
       
  5303     selection mode this function returns 0.
       
  5304 
       
  5305     \sa setSelected() setMultiSelection()
       
  5306 */
       
  5307 
       
  5308 Q3ListViewItem * Q3ListView::selectedItem() const
       
  5309 {
       
  5310     if (d->selectionMode != Single)
       
  5311         return 0;
       
  5312     if (d->focusItem && d->focusItem->isSelected())
       
  5313         return d->focusItem;
       
  5314     return 0;
       
  5315 }
       
  5316 
       
  5317 
       
  5318 /*!
       
  5319     Sets item \a i to be the current item and repaints appropriately
       
  5320     (i.e. highlights the item). The current item is used for keyboard
       
  5321     navigation and focus indication; it is independent of any selected
       
  5322     items, although a selected item can also be the current item.
       
  5323 
       
  5324     \sa currentItem() setSelected()
       
  5325 */
       
  5326 
       
  5327 void Q3ListView::setCurrentItem(Q3ListViewItem * i)
       
  5328 {
       
  5329     if (!i || d->focusItem == i || !i->isEnabled())
       
  5330         return;
       
  5331 
       
  5332     if (currentItem() && currentItem()->renameBox) {
       
  5333         if (d->defRenameAction == Reject)
       
  5334             currentItem()->cancelRename(currentItem()->renameCol);
       
  5335         else
       
  5336             currentItem()->okRename(currentItem()->renameCol);
       
  5337     }
       
  5338 
       
  5339     Q3ListViewItem * prev = d->focusItem;
       
  5340     d->focusItem = i;
       
  5341 
       
  5342     if (i != prev) {
       
  5343         if (i && d->selectionMode == Single) {
       
  5344             bool changed = false;
       
  5345             if (prev && prev->selected) {
       
  5346                 changed = true;
       
  5347                 prev->setSelected(false);
       
  5348             }
       
  5349             if (i && !i->selected && d->selectionMode != NoSelection && i->isSelectable()) {
       
  5350                 i->setSelected(true);
       
  5351                 changed = true;
       
  5352                 emit selectionChanged(i);
       
  5353             }
       
  5354             if (changed)
       
  5355                 emit selectionChanged();
       
  5356         }
       
  5357 
       
  5358         if (i)
       
  5359             repaintItem(i);
       
  5360         if (prev)
       
  5361             repaintItem(prev);
       
  5362         emit currentChanged(i);
       
  5363 
       
  5364 #ifndef QT_NO_ACCESSIBILITY
       
  5365         QAccessible::updateAccessibility(viewport(), indexOfItem(i), QAccessible::Focus);
       
  5366 #endif
       
  5367     }
       
  5368 }
       
  5369 
       
  5370 
       
  5371 /*!
       
  5372     Returns the current item, or 0 if there isn't one.
       
  5373 
       
  5374     \sa setCurrentItem()
       
  5375 */
       
  5376 
       
  5377 Q3ListViewItem * Q3ListView::currentItem() const
       
  5378 {
       
  5379     return d->focusItem;
       
  5380 }
       
  5381 
       
  5382 
       
  5383 /*!
       
  5384     Returns the rectangle on the screen that item \a item occupies in
       
  5385     viewport()'s coordinates, or an invalid rectangle if \a item is 0 or
       
  5386     is not currently visible.
       
  5387 
       
  5388     The rectangle returned does not include any children of the
       
  5389     rectangle (i.e. it uses Q3ListViewItem::height(), rather than
       
  5390     Q3ListViewItem::totalHeight()). If you want the rectangle to
       
  5391     include children you can use something like this:
       
  5392 
       
  5393     \snippet doc/src/snippets/code/src_qt3support_itemviews_q3listview.cpp 5
       
  5394 
       
  5395     Note the way it avoids too-high rectangles. totalHeight() can be
       
  5396     much larger than the window system's coordinate system allows.
       
  5397 
       
  5398     itemRect() is comparatively slow. It's best to call it only for
       
  5399     items that are probably on-screen.
       
  5400 */
       
  5401 
       
  5402 QRect Q3ListView::itemRect(const Q3ListViewItem * item) const
       
  5403 {
       
  5404     if (d->drawables.isEmpty())
       
  5405         buildDrawableList();
       
  5406 
       
  5407     for (int i = 0; i < d->drawables.size(); ++i) {
       
  5408         const Q3ListViewPrivate::DrawableItem &c = d->drawables.at(i);
       
  5409         if (c.i == item) {
       
  5410             int y = c.y - contentsY();
       
  5411             if (y + c.i->height() >= 0 && y < ((Q3ListView *)this)->visibleHeight()) {
       
  5412                 return QRect(-contentsX(), y, d->h->width(), c.i->height());;
       
  5413             }
       
  5414         }
       
  5415     }
       
  5416 
       
  5417     return QRect(0, 0, -1, -1);
       
  5418 }
       
  5419 
       
  5420 
       
  5421 /*!
       
  5422     \fn void Q3ListView::doubleClicked(Q3ListViewItem *item)
       
  5423 
       
  5424     This signal is emitted whenever an item is double-clicked. It's
       
  5425     emitted on the second button press, not the second button release.
       
  5426     \a item is the list view item on which the user did the
       
  5427     double-click.
       
  5428 */
       
  5429 
       
  5430 /*!
       
  5431     \fn void Q3ListView::doubleClicked(Q3ListViewItem *item, const
       
  5432     QPoint& point, int column)
       
  5433 
       
  5434     This signal is emitted when a double-click occurs. It's emitted on
       
  5435     the second button press, not the second button release. The \a
       
  5436     item is the Q3ListViewItem the button was double-clicked on (which
       
  5437     could be 0 if it wasn't double-clicked on an item). The \a point
       
  5438     where the double-click occurred is given in global coordinates. If
       
  5439     an item was double-clicked on, \a column is the column within the
       
  5440     item that was double-clicked; otherwise \a column is -1.
       
  5441 
       
  5442     \warning Do not delete any Q3ListViewItem objects in slots
       
  5443     connected to this signal.
       
  5444 */
       
  5445 
       
  5446 
       
  5447 /*!
       
  5448     \fn void Q3ListView::returnPressed(Q3ListViewItem *item)
       
  5449 
       
  5450     This signal is emitted when Enter or Return is pressed. The
       
  5451     \a item parameter is the currentItem().
       
  5452 */
       
  5453 
       
  5454 /*!
       
  5455     \fn void Q3ListView::spacePressed(Q3ListViewItem *item)
       
  5456 
       
  5457     This signal is emitted when Space is pressed. The \a item
       
  5458     parameter is the currentItem().
       
  5459 */
       
  5460 
       
  5461 
       
  5462 /*!
       
  5463     Sets the list view to be sorted by column \a column in ascending
       
  5464     order if \a ascending is true or descending order if it is false.
       
  5465 
       
  5466     If \a column is -1, sorting is disabled and the user cannot sort
       
  5467     columns by clicking on the column headers. If \a column is larger
       
  5468     than the number of columns the user must click on a column
       
  5469     header to sort the list view.
       
  5470 */
       
  5471 
       
  5472 void Q3ListView::setSorting(int column, bool ascending)
       
  5473 {
       
  5474     if (column == -1)
       
  5475         column = Unsorted;
       
  5476 
       
  5477     if (d->sortcolumn == column && d->ascending == ascending)
       
  5478         return;
       
  5479 
       
  5480     d->ascending = ascending;
       
  5481     d->sortcolumn = column;
       
  5482     if (d->sortcolumn != Unsorted && d->sortIndicator)
       
  5483         d->h->setSortIndicator(d->sortcolumn, d->ascending);
       
  5484     else
       
  5485         d->h->setSortIndicator(-1);
       
  5486 
       
  5487     triggerUpdate();
       
  5488 
       
  5489 #ifndef QT_NO_ACCESSIBILITY
       
  5490     QAccessible::updateAccessibility(viewport(), 0, QAccessible::ObjectReorder);
       
  5491 #endif
       
  5492 }
       
  5493 
       
  5494 /*!
       
  5495     Sets the \a column the list view is sorted by.
       
  5496 
       
  5497     Sorting is triggered by choosing a header section.
       
  5498 */
       
  5499 
       
  5500 void Q3ListView::changeSortColumn(int column)
       
  5501 {
       
  5502     if (isRenaming()) {
       
  5503         if (d->defRenameAction == Q3ListView::Reject) {
       
  5504             currentItem()->cancelRename(currentItem()->renameCol);
       
  5505         } else {
       
  5506             currentItem()->okRename(currentItem()->renameCol);
       
  5507         }
       
  5508     }
       
  5509     if (d->sortcolumn != Unsorted) {
       
  5510         int lcol = d->h->mapToLogical(column);
       
  5511         setSorting(lcol, d->sortcolumn == lcol ? !d->ascending : true);
       
  5512     }
       
  5513 }
       
  5514 
       
  5515 /*!
       
  5516   \internal
       
  5517   Handles renaming when sections are being swapped by the user.
       
  5518 */
       
  5519 
       
  5520 void Q3ListView::handleIndexChange()
       
  5521 {
       
  5522     if (isRenaming()) {
       
  5523         if (d->defRenameAction == Q3ListView::Reject) {
       
  5524             currentItem()->cancelRename(currentItem()->renameCol);
       
  5525         } else {
       
  5526             currentItem()->okRename(currentItem()->renameCol);
       
  5527         }
       
  5528     }
       
  5529     triggerUpdate();
       
  5530 }
       
  5531 
       
  5532 /*!
       
  5533     Returns the column by which the list view is sorted, or -1 if
       
  5534     sorting is disabled.
       
  5535 
       
  5536     \sa sortOrder()
       
  5537 */
       
  5538 
       
  5539 int Q3ListView::sortColumn() const
       
  5540 {
       
  5541     return d->sortcolumn;
       
  5542 }
       
  5543 
       
  5544 /*!
       
  5545     Sets the sorting column for the list view.
       
  5546 
       
  5547     If \a column is -1, sorting is disabled and the user cannot sort
       
  5548     columns by clicking on the column headers. If \a column is larger
       
  5549     than the number of columns the user must click on a column header
       
  5550     to sort the list view.
       
  5551 
       
  5552     \sa setSorting()
       
  5553 */
       
  5554 void Q3ListView::setSortColumn(int column)
       
  5555 {
       
  5556     setSorting(column, d->ascending);
       
  5557 }
       
  5558 
       
  5559 /*!
       
  5560     Returns the sorting order of the list view items.
       
  5561 
       
  5562     \sa sortColumn()
       
  5563 */
       
  5564 Qt::SortOrder Q3ListView::sortOrder() const
       
  5565 {
       
  5566     if (d->ascending)
       
  5567         return Qt::AscendingOrder;
       
  5568     return Qt::DescendingOrder;
       
  5569 }
       
  5570 
       
  5571 /*!
       
  5572     Sets the sort order for the items in the list view to \a order.
       
  5573 
       
  5574     \sa setSorting()
       
  5575 */
       
  5576 void Q3ListView::setSortOrder(Qt::SortOrder order)
       
  5577 {
       
  5578     setSorting(d->sortcolumn, order == Qt::AscendingOrder ? true : false);
       
  5579 }
       
  5580 
       
  5581 /*!
       
  5582     Sorts the list view using the last sorting configuration (sort
       
  5583     column and ascending/descending).
       
  5584 */
       
  5585 
       
  5586 void Q3ListView::sort()
       
  5587 {
       
  5588     if (d->r)
       
  5589         d->r->sort();
       
  5590 }
       
  5591 
       
  5592 /*!
       
  5593     \property Q3ListView::itemMargin
       
  5594     \brief the advisory item margin that list items may use
       
  5595 
       
  5596     The item margin defaults to one pixel and is the margin between
       
  5597     the item's edges and the area where it draws its contents.
       
  5598     Q3ListViewItem::paintFocus() draws in the margin.
       
  5599 
       
  5600     \sa Q3ListViewItem::paintCell()
       
  5601 */
       
  5602 
       
  5603 void Q3ListView::setItemMargin(int m)
       
  5604 {
       
  5605     if (d->margin == m)
       
  5606         return;
       
  5607     d->margin = m;
       
  5608     if (isVisible()) {
       
  5609         d->drawables.clear();
       
  5610         triggerUpdate();
       
  5611     }
       
  5612 }
       
  5613 
       
  5614 int Q3ListView::itemMargin() const
       
  5615 {
       
  5616     return d->margin;
       
  5617 }
       
  5618 
       
  5619 
       
  5620 /*!
       
  5621     \fn void Q3ListView::rightButtonClicked(Q3ListViewItem *item,
       
  5622     const QPoint& point, int column)
       
  5623 
       
  5624     This signal is emitted when the right button is clicked. The \a
       
  5625     item is the Q3ListViewItem the button was clicked on (which could
       
  5626     be 0 if it wasn't clicked on an item). The \a point where the
       
  5627     click occurred is given in global coordinates. If an item was
       
  5628     clicked on, \a column is the column within the item that was
       
  5629     clicked; otherwise \a column is -1.
       
  5630 */
       
  5631 
       
  5632 
       
  5633 /*!
       
  5634     \fn void Q3ListView::rightButtonPressed (Q3ListViewItem *item,
       
  5635     const QPoint &point, int column)
       
  5636 
       
  5637     This signal is emitted when the right button is pressed. The \a
       
  5638     item is the Q3ListViewItem the button was pressed on (which could
       
  5639     be 0 if it wasn't pressed on an item). The \a point where the
       
  5640     press occurred is given in global coordinates. If an item was
       
  5641     pressed on, \a column is the column within the item that was
       
  5642     pressed; otherwise \a column is -1.
       
  5643 */
       
  5644 
       
  5645 /*!
       
  5646     \fn void Q3ListView::contextMenuRequested(Q3ListViewItem *item, const QPoint & pos, int col)
       
  5647 
       
  5648     This signal is emitted when the user invokes a context menu with
       
  5649     the right mouse button or with special system keys. If the
       
  5650     keyboard was used \a item is the current item; if the mouse was
       
  5651     used, \a item is the item under the mouse pointer or 0 if there is
       
  5652     no item under the mouse pointer. If no item is clicked, the column
       
  5653     index emitted is -1.
       
  5654 
       
  5655     \a pos is the position for the context menu in the global
       
  5656     coordinate system.
       
  5657 
       
  5658     \a col is the column on which the user pressed, or -1 if the
       
  5659     signal was triggered by a key event.
       
  5660 */
       
  5661 
       
  5662 /*!
       
  5663     \reimp
       
  5664 */
       
  5665 void Q3ListView::changeEvent(QEvent *ev)
       
  5666 {
       
  5667     if(ev->type() == QEvent::StyleChange) {
       
  5668         reconfigureItems();
       
  5669     } else if(ev->type() == QEvent::ActivationChange) {
       
  5670         if (!isActiveWindow() && d->scrollTimer)
       
  5671             d->scrollTimer->stop();
       
  5672         if (!palette().isEqual(QPalette::Active, QPalette::Inactive))
       
  5673             viewport()->update();
       
  5674     }
       
  5675     Q3ScrollView::changeEvent(ev);
       
  5676 
       
  5677     if (ev->type() == QEvent::ApplicationFontChange || ev->type() == QEvent::FontChange
       
  5678         || ev->type() == QEvent::ApplicationPaletteChange || ev->type() == QEvent::PaletteChange)
       
  5679         reconfigureItems();
       
  5680 }
       
  5681 
       
  5682 /*!
       
  5683     Ensures that setup() is called for all currently visible items,
       
  5684     and that it will be called for currently invisible items as soon
       
  5685     as their parents are opened.
       
  5686 
       
  5687     (A visible item, here, is an item whose parents are all open. The
       
  5688     item may happen to be off-screen.)
       
  5689 
       
  5690     \sa Q3ListViewItem::setup()
       
  5691 */
       
  5692 
       
  5693 void Q3ListView::reconfigureItems()
       
  5694 {
       
  5695     d->fontMetricsHeight = fontMetrics().height();
       
  5696     d->minLeftBearing = fontMetrics().minLeftBearing();
       
  5697     d->minRightBearing = fontMetrics().minRightBearing();
       
  5698     d->ellipsisWidth = fontMetrics().width(QLatin1String("...")) * 2;
       
  5699     d->r->setOpen(false);
       
  5700     d->r->configured = false;
       
  5701     d->r->setOpen(true);
       
  5702 }
       
  5703 
       
  5704 /*!
       
  5705     Ensures that the width mode of column \a c is updated according to
       
  5706     the width of \a item.
       
  5707 */
       
  5708 
       
  5709 void Q3ListView::widthChanged(const Q3ListViewItem* item, int c)
       
  5710 {
       
  5711     if (c >= d->h->count())
       
  5712         return;
       
  5713 
       
  5714 
       
  5715     QFontMetrics fm = fontMetrics();
       
  5716     int col = c < 0 ? 0 : c;
       
  5717     while (col == c || (c < 0 && col < d->h->count())) {
       
  5718         if (d->column[col].wmode == Maximum) {
       
  5719             int w = item->width(fm, this, col);
       
  5720             if (showSortIndicator()) {
       
  5721                 int tw = d->h->sectionSizeHint( col, fm ).width();
       
  5722                 tw += 40; //add space for the sort indicator
       
  5723                 w = qMax(w, tw);
       
  5724             }
       
  5725             if (col == 0) {
       
  5726                 int indent = treeStepSize() * item->depth();
       
  5727                 if (rootIsDecorated())
       
  5728                     indent += treeStepSize();
       
  5729                 w += indent;
       
  5730             }
       
  5731             if (w > columnWidth(col) && !d->h->isStretchEnabled() && !d->h->isStretchEnabled(col)) {
       
  5732                 d->updateHeader = true;
       
  5733                 setColumnWidth(col, w);
       
  5734             }
       
  5735         }
       
  5736         col++;
       
  5737     }
       
  5738 }
       
  5739 
       
  5740 /*!
       
  5741     \property Q3ListView::allColumnsShowFocus
       
  5742     \brief whether items should show keyboard focus using all columns
       
  5743 
       
  5744     If this property is true all columns will show focus and selection
       
  5745     states, otherwise only column 0 will show focus.
       
  5746 
       
  5747     The default is false.
       
  5748 
       
  5749     Setting this to true if it's not necessary may cause noticeable
       
  5750     flicker.
       
  5751 */
       
  5752 
       
  5753 void Q3ListView::setAllColumnsShowFocus(bool enable)
       
  5754 {
       
  5755     d->allColumnsShowFocus = enable;
       
  5756 }
       
  5757 
       
  5758 bool Q3ListView::allColumnsShowFocus() const
       
  5759 {
       
  5760     return d->allColumnsShowFocus;
       
  5761 }
       
  5762 
       
  5763 
       
  5764 /*!
       
  5765     Returns the first item in this Q3ListView. Returns 0 if there is no
       
  5766     first item.
       
  5767 
       
  5768     A list view's items can be traversed using firstChild()
       
  5769     and nextSibling() or using a Q3ListViewItemIterator.
       
  5770 
       
  5771     \sa itemAt() Q3ListViewItem::itemBelow() Q3ListViewItem::itemAbove()
       
  5772 */
       
  5773 
       
  5774 Q3ListViewItem * Q3ListView::firstChild() const
       
  5775 {
       
  5776     if (!d->r)
       
  5777         return 0;
       
  5778 
       
  5779     d->r->enforceSortOrder();
       
  5780     return d->r->childItem;
       
  5781 }
       
  5782 
       
  5783 /*!
       
  5784     Returns the last item in the list view tree. Returns 0 if there
       
  5785     are no items in the Q3ListView.
       
  5786 
       
  5787     This function is slow because it traverses the entire tree to find
       
  5788     the last item.
       
  5789 */
       
  5790 
       
  5791 Q3ListViewItem* Q3ListView::lastItem() const
       
  5792 {
       
  5793     Q3ListViewItem* item = firstChild();
       
  5794     if (item) {
       
  5795         while (item->nextSibling() || item->firstChild()) {
       
  5796             if (item->nextSibling())
       
  5797                 item = item->nextSibling();
       
  5798             else
       
  5799                 item = item->firstChild();
       
  5800         }
       
  5801     }
       
  5802     return item;
       
  5803 }
       
  5804 
       
  5805 /*!
       
  5806     Repaints this item on the screen if it is currently visible.
       
  5807 */
       
  5808 
       
  5809 void Q3ListViewItem::repaint() const
       
  5810 {
       
  5811     Q3ListView *lv = listView();
       
  5812     if (lv)
       
  5813         lv->repaintItem(this);
       
  5814 }
       
  5815 
       
  5816 
       
  5817 /*!
       
  5818     Repaints \a item on the screen if \a item is currently visible.
       
  5819     Takes care to avoid multiple repaints.
       
  5820 */
       
  5821 
       
  5822 void Q3ListView::repaintItem(const Q3ListViewItem * item) const
       
  5823 {
       
  5824     if (!item)
       
  5825         return;
       
  5826     d->dirtyItemTimer->start(0, true);
       
  5827     d->dirtyItems.append(item);
       
  5828 }
       
  5829 
       
  5830 
       
  5831 struct Q3CheckListItemPrivate
       
  5832 {
       
  5833     Q3CheckListItemPrivate():
       
  5834         exclusive(0),
       
  5835         currentState(Q3CheckListItem::Off),
       
  5836         tristate(false) {}
       
  5837 
       
  5838     Q3CheckListItem *exclusive;
       
  5839     Q3CheckListItem::ToggleState currentState;
       
  5840     QHash<Q3CheckListItem *, Q3CheckListItem::ToggleState> statesDict;
       
  5841     bool tristate;
       
  5842 };
       
  5843 
       
  5844 
       
  5845 /*!
       
  5846     \class Q3CheckListItem
       
  5847     \brief The Q3CheckListItem class provides checkable list view items.
       
  5848 
       
  5849     \compat
       
  5850 
       
  5851     Q3CheckListItems are used in \l{Q3ListView}s to provide
       
  5852     \l{Q3ListViewItem}s that are checkboxes, radio buttons or
       
  5853     controllers.
       
  5854 
       
  5855     Checkbox and controller check list items may be inserted at any
       
  5856     level in a list view. Radio button check list items must be
       
  5857     children of a controller check list item.
       
  5858 
       
  5859     The item can be checked or unchecked with setOn(). Its type can be
       
  5860     retrieved with type() and its text retrieved with text().
       
  5861 
       
  5862     \img qlistviewitems.png List View Items
       
  5863 
       
  5864     \sa Q3ListViewItem Q3ListView
       
  5865 */
       
  5866 
       
  5867 /*!
       
  5868     \enum Q3CheckListItem::Type
       
  5869 
       
  5870     This enum type specifies a Q3CheckListItem's type:
       
  5871 
       
  5872     \value RadioButton
       
  5873     \value CheckBox
       
  5874     \value RadioButtonController
       
  5875     \value CheckBoxController
       
  5876     \omitvalue Controller
       
  5877 */
       
  5878 
       
  5879 /*!
       
  5880     \enum Q3CheckListItem::ToggleState
       
  5881 
       
  5882     This enum specifies a Q3CheckListItem's toggle state.
       
  5883 
       
  5884     \value Off
       
  5885     \value NoChange
       
  5886     \value On
       
  5887 */
       
  5888 
       
  5889 
       
  5890 /*!
       
  5891     Constructs a checkable item with parent \a parent, text \a text
       
  5892     and of type \a tt. Note that a \c RadioButton must be the child of a
       
  5893     \c RadioButtonController, otherwise it will not toggle.
       
  5894 */
       
  5895 Q3CheckListItem::Q3CheckListItem(Q3CheckListItem *parent, const QString &text,
       
  5896                                 Type tt)
       
  5897     : Q3ListViewItem(parent, text, QString())
       
  5898 {
       
  5899     myType = tt;
       
  5900     init();
       
  5901     if (myType == RadioButton) {
       
  5902         if (parent->type() != RadioButtonController)
       
  5903             qWarning("Q3CheckListItem::Q3CheckListItem(), radio button must be "
       
  5904                       "child of a controller");
       
  5905         else
       
  5906             d->exclusive = parent;
       
  5907     }
       
  5908 }
       
  5909 
       
  5910 /*!
       
  5911     Constructs a checkable item with parent \a parent, which is after
       
  5912     \a after in the parent's list of children, and with text \a text
       
  5913     and of type \a tt. Note that a \c RadioButton must be the child of
       
  5914     a \c RadioButtonController, otherwise it will not toggle.
       
  5915 */
       
  5916 Q3CheckListItem::Q3CheckListItem(Q3CheckListItem *parent, Q3ListViewItem *after,
       
  5917                                 const QString &text, Type tt)
       
  5918     : Q3ListViewItem(parent, after, text)
       
  5919 {
       
  5920     myType = tt;
       
  5921     init();
       
  5922     if (myType == RadioButton) {
       
  5923         if (parent->type() != RadioButtonController)
       
  5924             qWarning("Q3CheckListItem::Q3CheckListItem(), radio button must be "
       
  5925                       "child of a controller");
       
  5926         else
       
  5927             d->exclusive = parent;
       
  5928     }
       
  5929 }
       
  5930 
       
  5931 /*!
       
  5932     Constructs a checkable item with parent \a parent, text \a text
       
  5933     and of type \a tt. Note that this item must \e not be a \c
       
  5934     RadioButton. Radio buttons must be children of a \c
       
  5935     RadioButtonController.
       
  5936 */
       
  5937 Q3CheckListItem::Q3CheckListItem(Q3ListViewItem *parent, const QString &text,
       
  5938                                 Type tt)
       
  5939     : Q3ListViewItem(parent, text, QString())
       
  5940 {
       
  5941     myType = tt;
       
  5942     if (myType == RadioButton) {
       
  5943       qWarning("Q3CheckListItem::Q3CheckListItem(), radio button must be "
       
  5944                "child of a Q3CheckListItem");
       
  5945     }
       
  5946     init();
       
  5947 }
       
  5948 
       
  5949 /*!
       
  5950     Constructs a checkable item with parent \a parent, which is after
       
  5951     \a after in the parent's list of children, with text \a text and
       
  5952     of type \a tt. Note that this item must \e not be a \c
       
  5953     RadioButton. Radio buttons must be children of a \c
       
  5954     RadioButtonController.
       
  5955 */
       
  5956 Q3CheckListItem::Q3CheckListItem(Q3ListViewItem *parent, Q3ListViewItem *after,
       
  5957                                 const QString &text, Type tt)
       
  5958     : Q3ListViewItem(parent, after, text)
       
  5959 {
       
  5960     myType = tt;
       
  5961     if (myType == RadioButton) {
       
  5962         qWarning("Q3CheckListItem::Q3CheckListItem(), radio button must be "
       
  5963                   "child of a Q3CheckListItem");
       
  5964     }
       
  5965     init();
       
  5966 }
       
  5967 
       
  5968 
       
  5969 /*!
       
  5970     Constructs a checkable item with parent \a parent, text \a text
       
  5971     and of type \a tt. Note that \a tt must \e not be \c RadioButton.
       
  5972     Radio buttons must be children of a \c RadioButtonController.
       
  5973 */
       
  5974 Q3CheckListItem::Q3CheckListItem(Q3ListView *parent, const QString &text,
       
  5975                                 Type tt)
       
  5976     : Q3ListViewItem(parent, text)
       
  5977 {
       
  5978     myType = tt;
       
  5979     if (tt == RadioButton)
       
  5980         qWarning("Q3CheckListItem::Q3CheckListItem(), radio button must be "
       
  5981                  "child of a Q3CheckListItem");
       
  5982     init();
       
  5983 }
       
  5984 
       
  5985 /*!
       
  5986     Constructs a checkable item with parent \a parent, which is after
       
  5987     \a after in the parent's list of children, with text \a text and
       
  5988     of type \a tt. Note that \a tt must \e not be \c RadioButton.
       
  5989     Radio buttons must be children of a \c RadioButtonController.
       
  5990 */
       
  5991 Q3CheckListItem::Q3CheckListItem(Q3ListView *parent, Q3ListViewItem *after,
       
  5992                                 const QString &text, Type tt)
       
  5993     : Q3ListViewItem(parent, after, text)
       
  5994 {
       
  5995     myType = tt;
       
  5996     if (tt == RadioButton)
       
  5997         qWarning("Q3CheckListItem::Q3CheckListItem(), radio button must be "
       
  5998                   "child of a Q3CheckListItem");
       
  5999     init();
       
  6000 }
       
  6001 
       
  6002 
       
  6003 /* \reimp */
       
  6004 
       
  6005 int Q3CheckListItem::rtti() const
       
  6006 {
       
  6007     return RTTI;
       
  6008 }
       
  6009 
       
  6010 /*!
       
  6011     Constructs a \c RadioButtonController item with parent \a parent,
       
  6012     text \a text and pixmap \a p.
       
  6013 */
       
  6014 Q3CheckListItem::Q3CheckListItem(Q3ListView *parent, const QString &text,
       
  6015                                 const QPixmap & p)
       
  6016     : Q3ListViewItem(parent, text)
       
  6017 {
       
  6018     myType = RadioButtonController;
       
  6019     setPixmap(0, p);
       
  6020     init();
       
  6021 }
       
  6022 
       
  6023 /*!
       
  6024     Constructs a \c RadioButtonController item with parent \a parent,
       
  6025     text \a text and pixmap \a p.
       
  6026 */
       
  6027 Q3CheckListItem::Q3CheckListItem(Q3ListViewItem *parent, const QString &text,
       
  6028                                 const QPixmap & p)
       
  6029     : Q3ListViewItem(parent, text)
       
  6030 {
       
  6031     myType = RadioButtonController;
       
  6032     setPixmap(0, p);
       
  6033     init();
       
  6034 }
       
  6035 
       
  6036 void Q3CheckListItem::init()
       
  6037 {
       
  6038     d = new Q3CheckListItemPrivate();
       
  6039     on = false;
       
  6040     // CheckBoxControllers by default have tristate set to true
       
  6041     if (myType == CheckBoxController)
       
  6042         setTristate(true);
       
  6043 }
       
  6044 
       
  6045 /*!
       
  6046     Destroys the item, and all its children to any depth, freeing up
       
  6047     all allocated resources.
       
  6048 */
       
  6049 Q3CheckListItem::~Q3CheckListItem()
       
  6050 {
       
  6051     if (myType == RadioButton
       
  6052          && d->exclusive && d->exclusive->d
       
  6053          && d->exclusive->d->exclusive == this)
       
  6054         d->exclusive->turnOffChild();
       
  6055     d->exclusive = 0; // so the children won't try to access us.
       
  6056     delete d;
       
  6057     d = 0;
       
  6058 }
       
  6059 
       
  6060 /*!
       
  6061     \fn Q3CheckListItem::Type Q3CheckListItem::type() const
       
  6062 
       
  6063     Returns the type of this item.
       
  6064 */
       
  6065 
       
  6066 /*!
       
  6067    \fn  bool Q3CheckListItem::isOn() const
       
  6068 
       
  6069     Returns true if the item is toggled on; otherwise returns false.
       
  6070 */
       
  6071 
       
  6072 /*!
       
  6073    Sets tristate to \a b if the \c Type is either a \c CheckBoxController or
       
  6074    a \c CheckBox.
       
  6075 
       
  6076    \c CheckBoxControllers are tristate by default.
       
  6077 
       
  6078    \sa state() isTristate()
       
  6079 */
       
  6080 void Q3CheckListItem::setTristate(bool b)
       
  6081 {
       
  6082     if ((myType != CheckBoxController) && (myType != CheckBox)) {
       
  6083         qWarning("Q3CheckListItem::setTristate(), has no effect on RadioButton "
       
  6084                   "or RadioButtonController.");
       
  6085         return;
       
  6086     }
       
  6087     d->tristate = b;
       
  6088 }
       
  6089 
       
  6090 /*!
       
  6091    Returns true if the item is tristate; otherwise returns false.
       
  6092 
       
  6093    \sa setTristate()
       
  6094 */
       
  6095 bool Q3CheckListItem::isTristate() const
       
  6096 {
       
  6097     return d->tristate;
       
  6098 }
       
  6099 
       
  6100 /*!
       
  6101     Returns the state of the item.
       
  6102 
       
  6103     \sa Q3CheckListItem::ToggleState
       
  6104 */
       
  6105 Q3CheckListItem::ToggleState Q3CheckListItem::state() const
       
  6106 {
       
  6107     if (!isTristate() && internalState() == NoChange)
       
  6108         return Off;
       
  6109     else
       
  6110         return d->currentState;
       
  6111 }
       
  6112 
       
  6113 /*
       
  6114   Same as the public state() except this one does not mask NoChange into Off
       
  6115   when tristate is disabled.
       
  6116 */
       
  6117 Q3CheckListItem::ToggleState Q3CheckListItem::internalState() const
       
  6118 {
       
  6119     return d->currentState;
       
  6120 }
       
  6121 
       
  6122 
       
  6123 
       
  6124 
       
  6125 /*!
       
  6126     Sets the toggle state of the checklistitem to \a s. \a s can be
       
  6127     \c Off, \c NoChange or \c On.
       
  6128 
       
  6129     Tristate can only be enabled for \c CheckBox or \c CheckBoxController,
       
  6130     therefore the \c NoChange only applies to them.
       
  6131 
       
  6132     Setting the state to \c On or \c Off on a \c CheckBoxController
       
  6133     will recursivly set the states of its children to the same state.
       
  6134 
       
  6135     Setting the state to \c NoChange on a \c CheckBoxController will
       
  6136     make it recursivly recall the previous stored state of its
       
  6137     children. If there was no previous stored state the children are
       
  6138     all set to \c On.
       
  6139 */
       
  6140 void Q3CheckListItem::setState(ToggleState s)
       
  6141 {
       
  6142     if (myType == CheckBoxController && state() == NoChange)
       
  6143         updateStoredState(this);
       
  6144     setState(s, true, true);
       
  6145 }
       
  6146 
       
  6147 /*
       
  6148   Sets the toggle state of the checklistitems. \a update tells if the
       
  6149   controller / parent controller should be aware of these changes, \a store
       
  6150   tells if the parent should store its children if certain conditions arise
       
  6151 */
       
  6152 void Q3CheckListItem::setState(ToggleState s, bool update, bool store)
       
  6153 {
       
  6154 
       
  6155     if (s == internalState())
       
  6156         return;
       
  6157 
       
  6158     if (myType == CheckBox) {
       
  6159         setCurrentState(s);
       
  6160         stateChange(state());
       
  6161         if (update && parent() && parent()->rtti() == 1
       
  6162              && ((Q3CheckListItem*)parent())->type() == CheckBoxController)
       
  6163             ((Q3CheckListItem*)parent())->updateController(update, store);
       
  6164     } else if (myType == CheckBoxController) {
       
  6165         if (s == NoChange && childCount()) {
       
  6166             restoreState(this);
       
  6167         } else {
       
  6168             Q3ListViewItem *item = firstChild();
       
  6169             int childCount = 0;
       
  6170             while(item) {
       
  6171                 if (item->rtti() == 1 &&
       
  6172                      (((Q3CheckListItem*)item)->type() == CheckBox ||
       
  6173                        ((Q3CheckListItem*)item)->type() == CheckBoxController)) {
       
  6174                     Q3CheckListItem *checkItem = (Q3CheckListItem*)item;
       
  6175                     checkItem->setState(s, false, false);
       
  6176                     childCount++;
       
  6177                 }
       
  6178                 item = item->nextSibling();
       
  6179             }
       
  6180             if (update) {
       
  6181                 if (childCount > 0) {
       
  6182                     ToggleState oldState = internalState();
       
  6183                     updateController(false, false);
       
  6184                     if (oldState != internalState() &&
       
  6185                          parent() && parent()->rtti() == 1 &&
       
  6186                          ((Q3CheckListItem*)parent())->type() == CheckBoxController)
       
  6187                         ((Q3CheckListItem*)parent())->updateController(update, store);
       
  6188 
       
  6189                         updateController(update, store);
       
  6190                 } else {
       
  6191                     // if there are no children we simply set the CheckBoxController and update its parent
       
  6192                     setCurrentState(s);
       
  6193                     stateChange(state());
       
  6194                     if (parent() && parent()->rtti() == 1
       
  6195                          && ((Q3CheckListItem*)parent())->type() == CheckBoxController)
       
  6196                         ((Q3CheckListItem*)parent())->updateController(update, store);
       
  6197                 }
       
  6198             } else {
       
  6199                 setCurrentState(s);
       
  6200                 stateChange(state());
       
  6201             }
       
  6202 
       
  6203         }
       
  6204     } else if (myType == RadioButton) {
       
  6205         if (s == On) {
       
  6206             if (d->exclusive && d->exclusive->d->exclusive != this)
       
  6207                 d->exclusive->turnOffChild();
       
  6208             setCurrentState(s);
       
  6209             if (d->exclusive)
       
  6210                 d->exclusive->d->exclusive = this;
       
  6211         } else {
       
  6212             if (d->exclusive && d->exclusive->d->exclusive == this)
       
  6213                 d->exclusive->d->exclusive = 0;
       
  6214             setCurrentState(Off);
       
  6215         }
       
  6216         stateChange(state());
       
  6217     }
       
  6218     repaint();
       
  6219 }
       
  6220 
       
  6221 /*
       
  6222   this function is needed because we need to update "on" every time we
       
  6223   update d->currentState. In order to retain binary compatibility the
       
  6224   inline function isOn() needs the "on" bool ### should be changed in
       
  6225   ver 4
       
  6226 */
       
  6227 void Q3CheckListItem::setCurrentState(ToggleState s)
       
  6228 {
       
  6229     ToggleState old = d->currentState;
       
  6230     d->currentState = s;
       
  6231     if (d->currentState == On)
       
  6232         on = true;
       
  6233     else
       
  6234         on = false;
       
  6235 
       
  6236 #ifndef QT_NO_ACCESSIBILITY
       
  6237     if (old != d->currentState && listView())
       
  6238         QAccessible::updateAccessibility(listView()->viewport(), indexOfItem(this), QAccessible::StateChanged);
       
  6239 #else
       
  6240     Q_UNUSED(old);
       
  6241 #endif
       
  6242 }
       
  6243 
       
  6244 
       
  6245 
       
  6246 /*
       
  6247   updates the internally stored state of this item for the parent (key)
       
  6248 */
       
  6249 void Q3CheckListItem::setStoredState(ToggleState newState, Q3CheckListItem *key)
       
  6250 {
       
  6251     if (myType == CheckBox || myType == CheckBoxController)
       
  6252         d->statesDict[key] = newState;
       
  6253 }
       
  6254 
       
  6255 /*
       
  6256   Returns the stored state for this item for the given key.
       
  6257   If the key is not found it returns Off.
       
  6258 */
       
  6259 Q3CheckListItem::ToggleState Q3CheckListItem::storedState(Q3CheckListItem *key) const
       
  6260 {
       
  6261     QHash<Q3CheckListItem *, Q3CheckListItem::ToggleState>::Iterator it = d->statesDict.find(key);
       
  6262     if (it != d->statesDict.end())
       
  6263         return it.value();
       
  6264     else
       
  6265         return Off;
       
  6266 }
       
  6267 
       
  6268 
       
  6269 /*!
       
  6270     \fn QString Q3CheckListItem::text() const
       
  6271 
       
  6272     Returns the item's text.
       
  6273 */
       
  6274 
       
  6275 
       
  6276 /*!
       
  6277     If this is a \c RadioButtonController that has \c RadioButton
       
  6278     children, turn off the child that is on.
       
  6279 */
       
  6280 void Q3CheckListItem::turnOffChild()
       
  6281 {
       
  6282     if (myType == RadioButtonController && d->exclusive)
       
  6283         d->exclusive->setOn(false);
       
  6284 }
       
  6285 
       
  6286 /*!
       
  6287     Toggle check box or set radio button to on.
       
  6288 */
       
  6289 void Q3CheckListItem::activate()
       
  6290 {
       
  6291     Q3ListView * lv = listView();
       
  6292 
       
  6293     if ((lv && !lv->isEnabled()) || !isEnabled())
       
  6294         return;
       
  6295 
       
  6296     QPoint pos;
       
  6297     int boxsize = lv->style()->pixelMetric(QStyle::PM_CheckListButtonSize, 0, lv);
       
  6298     if (activatedPos(pos)) {
       
  6299         bool parentControl = false;
       
  6300         if (parent() && parent()->rtti() == 1  &&
       
  6301             ((Q3CheckListItem*) parent())->type() == RadioButtonController)
       
  6302             parentControl = true;
       
  6303 
       
  6304         int x = parentControl ? 0 : 3;
       
  6305         int align = lv->columnAlignment(0);
       
  6306         int marg = lv->itemMargin();
       
  6307         int y = 0;
       
  6308 
       
  6309         if (align & Qt::AlignVCenter)
       
  6310             y = ((height() - boxsize) / 2) + marg;
       
  6311         else
       
  6312             y = (lv->fontMetrics().height() + 2 + marg - boxsize) / 2;
       
  6313 
       
  6314         QRect r(x, y, boxsize-3, boxsize-3);
       
  6315         // columns might have been swapped
       
  6316         r.moveBy(lv->header()->sectionPos(0), 0);
       
  6317         if (!r.contains(pos))
       
  6318             return;
       
  6319     }
       
  6320     if ((myType == CheckBox) || (myType == CheckBoxController))  {
       
  6321         lv->d->startEdit = FALSE;
       
  6322         switch (internalState()) {
       
  6323         case On:
       
  6324             setState(Off);
       
  6325             break;
       
  6326         case Off:
       
  6327 	    if ( (!isTristate() && myType == CheckBox) ||
       
  6328                  (myType == CheckBoxController && !childCount()) ) {
       
  6329                 setState(On);
       
  6330             } else {
       
  6331                 setState(NoChange);
       
  6332                 if (myType == CheckBoxController && internalState() != NoChange)
       
  6333                     setState(On);
       
  6334             }
       
  6335             break;
       
  6336         case NoChange:
       
  6337             setState(On);
       
  6338             break;
       
  6339         }
       
  6340         ignoreDoubleClick();
       
  6341     } else if (myType == RadioButton) {
       
  6342         setOn(true);
       
  6343         ignoreDoubleClick();
       
  6344     }
       
  6345 }
       
  6346 
       
  6347 /*!
       
  6348     Sets the button on if \a b is true, otherwise sets it off.
       
  6349     Maintains radio button exclusivity.
       
  6350 */
       
  6351 void Q3CheckListItem::setOn(bool b )
       
  6352 {
       
  6353     if (b)
       
  6354         setState(On , true, true);
       
  6355     else
       
  6356         setState(Off , true, true);
       
  6357 }
       
  6358 
       
  6359 
       
  6360 /*!
       
  6361     \fn void Q3CheckListItem::stateChange(bool b)
       
  6362 
       
  6363     This virtual function is called when the item changes its state.
       
  6364     \a b is true if the state is \c On; otherwise the state is \c Off.
       
  6365     \c NoChange (if tristate is enabled and the type is either \c
       
  6366     CheckBox or \c CheckBoxController) reports the same as \c Off, so
       
  6367     use state() to determine if the state is actually \c Off or \c
       
  6368     NoChange.
       
  6369 */
       
  6370 void Q3CheckListItem::stateChange(bool)
       
  6371 {
       
  6372 }
       
  6373 
       
  6374 /*
       
  6375   Calls the public virtual function if the state is changed to either On, NoChange or Off.
       
  6376   NoChange reports the same as Off - ### should be fixed in ver4
       
  6377 */
       
  6378 void Q3CheckListItem::stateChange(ToggleState s)
       
  6379 {
       
  6380     stateChange(s == On);
       
  6381 }
       
  6382 
       
  6383 /*
       
  6384   sets the state of the CheckBox and CheckBoxController back to
       
  6385   previous stored state
       
  6386 */
       
  6387 void Q3CheckListItem::restoreState(Q3CheckListItem *key, int depth)
       
  6388 {
       
  6389     switch (type()) {
       
  6390     case CheckBox:
       
  6391         setCurrentState(storedState(key));
       
  6392         stateChange(state());
       
  6393         repaint();
       
  6394         break;
       
  6395     case CheckBoxController: {
       
  6396         Q3ListViewItem *item = firstChild();
       
  6397         int childCount = 0;
       
  6398         while (item) {
       
  6399             // recursively calling restoreState for children of type CheckBox and CheckBoxController
       
  6400             if (item->rtti() == 1 &&
       
  6401                  (((Q3CheckListItem*)item)->type() == CheckBox ||
       
  6402                    ((Q3CheckListItem*)item)->type() == CheckBoxController)) {
       
  6403                 ((Q3CheckListItem*)item)->restoreState(key , depth+1);
       
  6404                 childCount++;
       
  6405             }
       
  6406             item = item->nextSibling();
       
  6407         }
       
  6408         if (childCount > 0) {
       
  6409             if (depth == 0)
       
  6410                 updateController(true);
       
  6411             else
       
  6412                 updateController(false);
       
  6413         } else {
       
  6414             // if there are no children we retrieve the CheckBoxController state directly.
       
  6415             setState(storedState(key), true, false);
       
  6416         }
       
  6417     }
       
  6418         break;
       
  6419     default:
       
  6420         break;
       
  6421     }
       
  6422 }
       
  6423 
       
  6424 
       
  6425 /*
       
  6426   Checks the childrens state and updates the controllers state
       
  6427   if necessary. If the controllers state change, then his parent again is
       
  6428   called to update itself.
       
  6429 */
       
  6430 void Q3CheckListItem::updateController(bool update , bool store)
       
  6431 {
       
  6432     if (myType != CheckBoxController)
       
  6433         return;
       
  6434 
       
  6435     Q3CheckListItem *controller = 0;
       
  6436     // checks if this CheckBoxController has another CheckBoxController as parent
       
  6437     if (parent() && parent()->rtti() == 1
       
  6438          && ((Q3CheckListItem*)parent())->type() == CheckBoxController)
       
  6439         controller = (Q3CheckListItem*)parent();
       
  6440 
       
  6441     ToggleState theState = Off;
       
  6442     bool first = true;
       
  6443     Q3ListViewItem *item = firstChild();
       
  6444     while(item && theState != NoChange) {
       
  6445         if (item->rtti() == 1 &&
       
  6446              (((Q3CheckListItem*)item)->type() == CheckBox ||
       
  6447                ((Q3CheckListItem*)item)->type() == CheckBoxController)) {
       
  6448             Q3CheckListItem *checkItem = (Q3CheckListItem*)item;
       
  6449             if (first) {
       
  6450                 theState = checkItem->internalState();
       
  6451                 first = false;
       
  6452             } else {
       
  6453                 if (checkItem->internalState() == NoChange ||
       
  6454                      theState != checkItem->internalState())
       
  6455                     theState = NoChange;
       
  6456                 else
       
  6457                     theState = checkItem->internalState();
       
  6458             }
       
  6459         }
       
  6460         item = item->nextSibling();
       
  6461     }
       
  6462     if (internalState() != theState) {
       
  6463         setCurrentState(theState);
       
  6464         if (store && (internalState() == On || internalState() == Off))
       
  6465             updateStoredState(this);
       
  6466         stateChange(state());
       
  6467         if (update && controller) {
       
  6468             controller->updateController(update, store);
       
  6469         }
       
  6470         repaint();
       
  6471     }
       
  6472 }
       
  6473 
       
  6474 
       
  6475 /*
       
  6476   Makes all the children CheckBoxes update their storedState
       
  6477 */
       
  6478 void Q3CheckListItem::updateStoredState(Q3CheckListItem *key)
       
  6479 {
       
  6480     if (myType != CheckBoxController)
       
  6481         return;
       
  6482 
       
  6483     Q3ListViewItem *item = firstChild();
       
  6484     while(item) {
       
  6485         if (item->rtti() == 1) {
       
  6486             Q3CheckListItem *checkItem = (Q3CheckListItem*)item;
       
  6487             if (checkItem->type() == CheckBox)
       
  6488                 checkItem->setStoredState(checkItem->internalState(), key);
       
  6489             else if (checkItem->type() == CheckBoxController)
       
  6490                 checkItem->updateStoredState(key);
       
  6491         }
       
  6492         item = item->nextSibling();
       
  6493     }
       
  6494     // this state is only needed if the CheckBoxController has no CheckBox / CheckBoxController children.
       
  6495     setStoredState(internalState() , key);
       
  6496 }
       
  6497 
       
  6498 
       
  6499 /*!
       
  6500     \reimp
       
  6501 */
       
  6502 void Q3CheckListItem::setup()
       
  6503 {
       
  6504     Q3ListViewItem::setup();
       
  6505     int h = height();
       
  6506     Q3ListView *lv = listView();
       
  6507     if (lv)
       
  6508         h = qMax(lv->style()->pixelMetric(QStyle::PM_CheckListButtonSize, 0, lv),
       
  6509                   h);
       
  6510     h = qMax(h, QApplication::globalStrut().height());
       
  6511     setHeight(h);
       
  6512 }
       
  6513 
       
  6514 /*!
       
  6515     \reimp
       
  6516 */
       
  6517 
       
  6518 int Q3CheckListItem::width(const QFontMetrics& fm, const Q3ListView* lv, int column) const
       
  6519 {
       
  6520     int r = Q3ListViewItem::width(fm, lv, column);
       
  6521     if (column == 0) {
       
  6522         r += lv->itemMargin();
       
  6523         if (myType == RadioButtonController && pixmap(0)) {
       
  6524             //             r += 0;
       
  6525         } else {
       
  6526             r +=  lv->style()->pixelMetric(QStyle::PM_CheckListButtonSize, 0, lv) + 4;
       
  6527         }
       
  6528     }
       
  6529     return qMax(r, QApplication::globalStrut().width());
       
  6530 }
       
  6531 
       
  6532 /*!
       
  6533     Paints the item using the painter \a p and the color group \a cg.
       
  6534     The item is in column \a column, has width \a width and has
       
  6535     alignment \a align. (See \l Qt::Alignment for valid alignments.)
       
  6536 */
       
  6537 void Q3CheckListItem::paintCell(QPainter * p, const QColorGroup & cg,
       
  6538                                int column, int width, int align)
       
  6539 {
       
  6540     if (!p)
       
  6541         return;
       
  6542 
       
  6543     Q3ListView *lv = listView();
       
  6544     if (!lv)
       
  6545         return;
       
  6546 
       
  6547     const QPalette::ColorRole crole = lv->backgroundRole();
       
  6548     if (cg.brush(crole) != lv->palette().brush(cg.currentColorGroup(), crole))
       
  6549         p->fillRect(0, 0, width, height(), cg.brush(crole));
       
  6550     else
       
  6551         lv->paintEmptyArea(p, QRect(0, 0, width, height()));
       
  6552 
       
  6553     if (column != 0) {
       
  6554         // The rest is text, or for subclasses to change.
       
  6555         Q3ListViewItem::paintCell(p, cg, column, width, align);
       
  6556         return;
       
  6557     }
       
  6558 
       
  6559     bool parentControl = false;
       
  6560     if (parent() && parent()->rtti() == 1  &&
       
  6561          ((Q3CheckListItem*) parent())->type() == RadioButtonController)
       
  6562         parentControl = true;
       
  6563 
       
  6564     QFontMetrics fm(lv->fontMetrics());
       
  6565     int boxsize = lv->style()->pixelMetric(myType == RadioButtonController ? QStyle::PM_CheckListControllerSize :
       
  6566                                            QStyle::PM_CheckListButtonSize, 0, lv);
       
  6567     int marg = lv->itemMargin();
       
  6568     int r = marg;
       
  6569 
       
  6570     // Draw controller / check box / radio button ---------------------
       
  6571     QStyle::State styleflags = QStyle::State_None;
       
  6572     if (internalState() == On) {
       
  6573         styleflags |= QStyle::State_On;
       
  6574     } else if (internalState() == NoChange) {
       
  6575         if (myType == CheckBoxController && !isTristate())
       
  6576             styleflags |= QStyle::State_Off;
       
  6577         else
       
  6578             styleflags |= QStyle::State_NoChange;
       
  6579     } else {
       
  6580         styleflags |= QStyle::State_Off;
       
  6581     }
       
  6582     if (isSelected())
       
  6583         styleflags |= QStyle::State_Selected;
       
  6584     if (isEnabled() && lv->isEnabled())
       
  6585         styleflags |= QStyle::State_Enabled;
       
  6586     if (lv->window()->isActiveWindow())
       
  6587         styleflags |= QStyle::State_Active;
       
  6588 
       
  6589     if (myType == RadioButtonController) {
       
  6590         int x = 0;
       
  6591         if(!parentControl)
       
  6592             x += 3;
       
  6593         if (!pixmap(0)) {
       
  6594             QStyleOptionQ3ListView opt = getStyleOption(lv, this);
       
  6595             opt.rect.setRect(x, 0, boxsize, fm.height() + 2 + marg);
       
  6596             opt.palette = cg;
       
  6597             opt.state = styleflags;
       
  6598             lv->style()->drawPrimitive(QStyle::PE_Q3CheckListController, &opt, p, lv);
       
  6599             r += boxsize + 4;
       
  6600         }
       
  6601     } else {
       
  6602         Q_ASSERT(lv); //###
       
  6603         int x = 0;
       
  6604         int y = 0;
       
  6605         if (!parentControl)
       
  6606             x += 3;
       
  6607         if (align & Qt::AlignVCenter)
       
  6608             y = ((height() - boxsize) / 2) + marg;
       
  6609         else
       
  6610             y = (fm.height() + 2 + marg - boxsize) / 2;
       
  6611 
       
  6612         QStyleOptionQ3ListView opt = getStyleOption(lv, this);
       
  6613         opt.rect.setRect(x, y, boxsize, fm.height() + 2 + marg);
       
  6614         opt.palette = cg;
       
  6615         opt.state = styleflags;
       
  6616         lv->style()->drawPrimitive((myType == CheckBox || myType == CheckBoxController)
       
  6617                                     ? QStyle::PE_Q3CheckListIndicator
       
  6618                                     : QStyle::PE_Q3CheckListExclusiveIndicator, &opt, p, lv);
       
  6619         r += boxsize + 4;
       
  6620     }
       
  6621 
       
  6622     // Draw text ----------------------------------------------------
       
  6623     p->translate(r, 0);
       
  6624     p->setPen(QPen(cg.text()));
       
  6625     Q3ListViewItem::paintCell(p, cg, column, width - r, align);
       
  6626 }
       
  6627 
       
  6628 /*!
       
  6629     Draws the focus rectangle \a r using the color group \a cg on the
       
  6630     painter \a p.
       
  6631 */
       
  6632 void Q3CheckListItem::paintFocus(QPainter *p, const QColorGroup & cg,
       
  6633                                  const QRect & r)
       
  6634 {
       
  6635     bool intersect = true;
       
  6636     Q3ListView *lv = listView();
       
  6637     if (lv && lv->header()->mapToActual(0) != 0) {
       
  6638         int xdepth = lv->treeStepSize() * (depth() + (lv->rootIsDecorated() ? 1 : 0)) + lv->itemMargin();
       
  6639         int p = lv->header()->cellPos(lv->header()->mapToActual(0));
       
  6640         xdepth += p;
       
  6641         intersect = r.intersects(QRect(p, r.y(), xdepth - p + 1, r.height()));
       
  6642     }
       
  6643     bool parentControl = false;
       
  6644     if (parent() && parent()->rtti() == 1  &&
       
  6645          ((Q3CheckListItem*) parent())->type() == RadioButtonController)
       
  6646         parentControl = true;
       
  6647     if (myType != RadioButtonController && intersect &&
       
  6648          (lv->rootIsDecorated() || myType == RadioButton ||
       
  6649           (myType == CheckBox && parentControl))) {
       
  6650         QRect rect;
       
  6651         int boxsize = lv->style()->pixelMetric(QStyle::PM_CheckListButtonSize, 0, lv);
       
  6652         if (lv->columnAlignment(0) == Qt::AlignCenter) {
       
  6653             QFontMetrics fm(lv->font());
       
  6654             int bx = (lv->columnWidth(0) - (boxsize + fm.width(text())))/2 + boxsize;
       
  6655             if (bx < 0) bx = 0;
       
  6656             rect.setRect(r.x() + bx + 5, r.y(), r.width() - bx - 5,
       
  6657                           r.height());
       
  6658         } else
       
  6659             rect.setRect(r.x() + boxsize + 5, r.y(), r.width() - boxsize - 5,
       
  6660                           r.height());
       
  6661         Q3ListViewItem::paintFocus(p, cg, rect);
       
  6662     } else {
       
  6663         Q3ListViewItem::paintFocus(p, cg, r);
       
  6664     }
       
  6665 }
       
  6666 
       
  6667 /*!
       
  6668     \reimp
       
  6669 */
       
  6670 QSize Q3ListView::sizeHint() const
       
  6671 {
       
  6672     if (cachedSizeHint().isValid())
       
  6673         return cachedSizeHint();
       
  6674 
       
  6675     ensurePolished();
       
  6676 
       
  6677     if (!isVisible() && d->drawables.isEmpty())
       
  6678         // force the column widths to sanity, if possible
       
  6679         buildDrawableList();
       
  6680 
       
  6681     QSize s(d->h->sizeHint());
       
  6682     if (verticalScrollBar()->isVisible())
       
  6683         s.setWidth(s.width() + style()->pixelMetric(QStyle::PM_ScrollBarExtent));
       
  6684     s += QSize(frameWidth()*2,frameWidth()*2);
       
  6685     Q3ListViewItem * l = d->r;
       
  6686     while(l && !l->height())
       
  6687         l = l->childItem ? l->childItem : l->siblingItem;
       
  6688 
       
  6689     if (l && l->height())
       
  6690         s.setHeight(s.height() + 10 * l->height());
       
  6691     else
       
  6692         s.setHeight(s.height() + 140);
       
  6693 
       
  6694     if (s.width() > s.height() * 3)
       
  6695         s.setHeight(s.width() / 3);
       
  6696     else if (s.width() *3 < s.height())
       
  6697         s.setHeight(s.width() * 3);
       
  6698 
       
  6699     setCachedSizeHint(s);
       
  6700 
       
  6701     return s;
       
  6702 }
       
  6703 
       
  6704 
       
  6705 /*!
       
  6706     \reimp
       
  6707 */
       
  6708 
       
  6709 QSize Q3ListView::minimumSizeHint() const
       
  6710 {
       
  6711     return Q3ScrollView::minimumSizeHint();
       
  6712 }
       
  6713 
       
  6714 
       
  6715 /*!
       
  6716     Sets \a item to be open if \a open is true and \a item is
       
  6717     expandable, and to be closed if \a open is false. Repaints
       
  6718     accordingly.
       
  6719 
       
  6720     \sa Q3ListViewItem::setOpen() Q3ListViewItem::setExpandable()
       
  6721 */
       
  6722 
       
  6723 void Q3ListView::setOpen(Q3ListViewItem * item, bool open)
       
  6724 {
       
  6725     if (!item ||
       
  6726         item->isOpen() == open ||
       
  6727         (open && !item->childCount() && !item->isExpandable()))
       
  6728         return;
       
  6729 
       
  6730     Q3ListViewItem* nextParent = 0;
       
  6731     if (open)
       
  6732         nextParent = item->itemBelow();
       
  6733 
       
  6734     item->setOpen(open);
       
  6735 
       
  6736     if (open) {
       
  6737         Q3ListViewItem* lastChild = item;
       
  6738         Q3ListViewItem* tmp;
       
  6739         while (true) {
       
  6740             tmp = lastChild->itemBelow();
       
  6741             if (!tmp || tmp == nextParent)
       
  6742                 break;
       
  6743             lastChild = tmp;
       
  6744         }
       
  6745         ensureItemVisible(lastChild);
       
  6746         ensureItemVisible(item);
       
  6747     }
       
  6748     buildDrawableList();
       
  6749 
       
  6750     int i = 0;
       
  6751     for (; i < d->drawables.size(); ++i) {
       
  6752         const Q3ListViewPrivate::DrawableItem &c = d->drawables.at(i);
       
  6753         if(c.i == item)
       
  6754             break;
       
  6755     }
       
  6756 
       
  6757     if (i < d->drawables.size()) {
       
  6758         d->dirtyItemTimer->start(0, true);
       
  6759         for (; i < d->drawables.size(); ++i) {
       
  6760             const Q3ListViewPrivate::DrawableItem &c = d->drawables.at(i);
       
  6761             d->dirtyItems.append(c.i);
       
  6762         }
       
  6763     }
       
  6764 }
       
  6765 
       
  6766 
       
  6767 /*!
       
  6768     Returns true if this list view item has children \e and they are
       
  6769     not explicitly hidden; otherwise returns false.
       
  6770 
       
  6771     Identical to \a{item}->isOpen(). Provided for completeness.
       
  6772 
       
  6773     \sa setOpen()
       
  6774 */
       
  6775 
       
  6776 bool Q3ListView::isOpen(const Q3ListViewItem * item) const
       
  6777 {
       
  6778     return item->isOpen();
       
  6779 }
       
  6780 
       
  6781 
       
  6782 /*!
       
  6783     \property Q3ListView::rootIsDecorated
       
  6784     \brief whether the list view shows open/close signs on root items
       
  6785 
       
  6786     Open/close signs are small \bold{+} or \bold{-} symbols in windows
       
  6787     style, or arrows in Motif style. The default is false.
       
  6788 */
       
  6789 
       
  6790 void Q3ListView::setRootIsDecorated(bool enable)
       
  6791 {
       
  6792     if (enable != (bool)d->rootIsExpandable) {
       
  6793         d->rootIsExpandable = enable;
       
  6794         if (isVisible())
       
  6795             triggerUpdate();
       
  6796     }
       
  6797 }
       
  6798 
       
  6799 bool Q3ListView::rootIsDecorated() const
       
  6800 {
       
  6801     return d->rootIsExpandable;
       
  6802 }
       
  6803 
       
  6804 
       
  6805 /*!
       
  6806     Ensures that item \a i is visible, scrolling the list view
       
  6807     vertically if necessary and opening (expanding) any parent items
       
  6808     if this is required to show the item.
       
  6809 
       
  6810     \sa itemRect() Q3ScrollView::ensureVisible()
       
  6811 */
       
  6812 
       
  6813 void Q3ListView::ensureItemVisible(const Q3ListViewItem * i)
       
  6814 {
       
  6815     if (!i || !i->isVisible())
       
  6816         return;
       
  6817 
       
  6818     Q3ListViewItem *parent = i->parent();
       
  6819     while (parent) {
       
  6820         if (!parent->isOpen())
       
  6821             parent->setOpen(true);
       
  6822         parent = parent->parent();
       
  6823     }
       
  6824 
       
  6825     if (d->r->maybeTotalHeight < 0)
       
  6826         updateGeometries();
       
  6827     int y = itemPos(i);
       
  6828     int h = i->height();
       
  6829     if (isVisible() && y + h > contentsY() + visibleHeight())
       
  6830         setContentsPos(contentsX(), y - visibleHeight() + h);
       
  6831     else if (!isVisible() || y < contentsY())
       
  6832         setContentsPos(contentsX(), y);
       
  6833 }
       
  6834 
       
  6835 
       
  6836 /*!
       
  6837     \fn QString Q3CheckListItem::text(int n) const
       
  6838 
       
  6839     \reimp
       
  6840 */
       
  6841 
       
  6842 /*!
       
  6843     Returns the Q3Header object that manages this list view's columns.
       
  6844     Please don't modify the header behind the list view's back.
       
  6845 
       
  6846     You may safely call Q3Header::setClickEnabled(),
       
  6847     Q3Header::setResizeEnabled(), Q3Header::setMovingEnabled(),
       
  6848     Q3Header::hide() and all the const Q3Header functions.
       
  6849 */
       
  6850 
       
  6851 Q3Header * Q3ListView::header() const
       
  6852 {
       
  6853     return d->h;
       
  6854 }
       
  6855 
       
  6856 
       
  6857 /*!
       
  6858     \property Q3ListView::childCount
       
  6859     \brief the number of parentless (top-level) Q3ListViewItem objects in this Q3ListView
       
  6860 
       
  6861     Holds the current number of parentless (top-level) Q3ListViewItem
       
  6862     objects in this Q3ListView.
       
  6863 
       
  6864     \sa Q3ListViewItem::childCount()
       
  6865 */
       
  6866 
       
  6867 int Q3ListView::childCount() const
       
  6868 {
       
  6869     if (d->r)
       
  6870         return d->r->childCount();
       
  6871     return 0;
       
  6872 }
       
  6873 
       
  6874 
       
  6875 /*
       
  6876     Moves this item to just after \a olderSibling. \a olderSibling and
       
  6877     this object must have the same parent.
       
  6878 
       
  6879     If you need to move an item in the hierarchy use takeItem() and
       
  6880     insertItem().
       
  6881 */
       
  6882 
       
  6883 void Q3ListViewItem::moveToJustAfter(Q3ListViewItem * olderSibling)
       
  6884 {
       
  6885     if (parentItem && olderSibling &&
       
  6886          olderSibling->parentItem == parentItem && olderSibling != this) {
       
  6887         if (parentItem->childItem == this) {
       
  6888             parentItem->childItem = siblingItem;
       
  6889         } else {
       
  6890             Q3ListViewItem * i = parentItem->childItem;
       
  6891             while(i && i->siblingItem != this)
       
  6892                 i = i->siblingItem;
       
  6893             if (i)
       
  6894                 i->siblingItem = siblingItem;
       
  6895         }
       
  6896         siblingItem = olderSibling->siblingItem;
       
  6897         olderSibling->siblingItem = this;
       
  6898         parentItem->lsc = Unsorted;
       
  6899     }
       
  6900 }
       
  6901 
       
  6902 /*!
       
  6903     Move the item to be after item \a after, which must be one of the
       
  6904     item's siblings. To move an item in the hierarchy, use takeItem()
       
  6905     and insertItem().
       
  6906 
       
  6907     Note that this function will have no effect if sorting is enabled
       
  6908     in the list view.
       
  6909 */
       
  6910 
       
  6911 void Q3ListViewItem::moveItem(Q3ListViewItem *after)
       
  6912 {
       
  6913     if (!after || after == this)
       
  6914         return;
       
  6915     if (parent() != after->parent()) {
       
  6916         if (parentItem)
       
  6917             parentItem->takeItem(this);
       
  6918         if (after->parentItem) {
       
  6919             int tmpLsc = after->parentItem->lsc;
       
  6920             after->parentItem->insertItem(this);
       
  6921             after->parentItem->lsc = tmpLsc;
       
  6922         }
       
  6923     }
       
  6924     moveToJustAfter(after);
       
  6925     Q3ListView *lv = listView();
       
  6926     if (lv)
       
  6927         lv->triggerUpdate();
       
  6928 }
       
  6929 
       
  6930 /*
       
  6931     Recursively sorts items, from the root to this item.
       
  6932     (enforceSortOrder() won't work the other way around, as
       
  6933     documented.)
       
  6934 */
       
  6935 void Q3ListViewItem::enforceSortOrderBackToRoot()
       
  6936 {
       
  6937     if (parentItem) {
       
  6938         parentItem->enforceSortOrderBackToRoot();
       
  6939         parentItem->enforceSortOrder();
       
  6940     }
       
  6941 }
       
  6942 
       
  6943 /*!
       
  6944     \reimp
       
  6945 */
       
  6946 void Q3ListView::showEvent(QShowEvent *)
       
  6947 {
       
  6948     d->drawables.clear();
       
  6949     d->dirtyItems.clear();
       
  6950     d->dirtyItemTimer->stop();
       
  6951     d->fullRepaintOnComlumnChange = true;
       
  6952 
       
  6953     updateGeometries();
       
  6954 }
       
  6955 
       
  6956 
       
  6957 /*!
       
  6958     Returns the y coordinate of this item in the list view's
       
  6959     coordinate system. This function is normally much slower than
       
  6960     Q3ListView::itemAt(), but it works for all items whereas
       
  6961     Q3ListView::itemAt() normally only works for items on the screen.
       
  6962 
       
  6963     \sa Q3ListView::itemAt() Q3ListView::itemRect() Q3ListView::itemPos()
       
  6964 */
       
  6965 
       
  6966 int Q3ListViewItem::itemPos() const
       
  6967 {
       
  6968     QStack<Q3ListViewItem *> s;
       
  6969     Q3ListViewItem * i = (Q3ListViewItem *)this;
       
  6970     while(i) {
       
  6971         s.push(i);
       
  6972         i = i->parentItem;
       
  6973     }
       
  6974 
       
  6975     int a = 0;
       
  6976     Q3ListViewItem * p = 0;
       
  6977     while(s.count()) {
       
  6978         i = s.pop();
       
  6979         if (p) {
       
  6980             if (!p->configured) {
       
  6981                 p->configured = true;
       
  6982                 p->setup(); // ### virtual non-const function called in const
       
  6983             }
       
  6984             a += p->height();
       
  6985             Q3ListViewItem * s = p->firstChild();
       
  6986             while(s && s != i) {
       
  6987                 a += s->totalHeight();
       
  6988                 s = s->nextSibling();
       
  6989             }
       
  6990         }
       
  6991         p = i;
       
  6992     }
       
  6993     return a;
       
  6994 }
       
  6995 
       
  6996 
       
  6997 /*!
       
  6998   \fn void Q3ListView::removeItem(Q3ListViewItem *item)
       
  6999 
       
  7000     Removes the given \a item. Use takeItem() instead.
       
  7001 */
       
  7002 
       
  7003 /*!
       
  7004     Removes item \a i from the list view; \a i must be a top-level
       
  7005     item. The warnings regarding Q3ListViewItem::takeItem() apply to
       
  7006     this function, too.
       
  7007 
       
  7008     \sa insertItem()
       
  7009 */
       
  7010 void Q3ListView::takeItem(Q3ListViewItem * i)
       
  7011 {
       
  7012     if (d->r)
       
  7013         d->r->takeItem(i);
       
  7014 }
       
  7015 
       
  7016 
       
  7017 void Q3ListView::openFocusItem()
       
  7018 {
       
  7019     d->autoopenTimer->stop();
       
  7020     if (d->focusItem && !d->focusItem->isOpen()) {
       
  7021         d->focusItem->setOpen(true);
       
  7022         d->focusItem->repaint();
       
  7023     }
       
  7024 }
       
  7025 
       
  7026 static const int autoopenTime = 750;
       
  7027 
       
  7028 #ifndef QT_NO_DRAGANDDROP
       
  7029 
       
  7030 /*! \reimp */
       
  7031 
       
  7032 void Q3ListView::contentsDragEnterEvent(QDragEnterEvent *e)
       
  7033 {
       
  7034     d->oldFocusItem = d->focusItem;
       
  7035     Q3ListViewItem *i = d->focusItem;
       
  7036     d->focusItem = itemAt(contentsToViewport(e->pos()));
       
  7037     if (i)
       
  7038         i->repaint();
       
  7039     if (d->focusItem) {
       
  7040         d->autoopenTimer->start(autoopenTime);
       
  7041         d->focusItem->dragEntered();
       
  7042         d->focusItem->repaint();
       
  7043     }
       
  7044     e->accept();
       
  7045 }
       
  7046 
       
  7047 /*! \reimp */
       
  7048 
       
  7049 void Q3ListView::contentsDragMoveEvent(QDragMoveEvent *e)
       
  7050 {
       
  7051     Q3ListViewItem *i = d->focusItem;
       
  7052     d->focusItem = itemAt(contentsToViewport(e->pos()));
       
  7053     if (i) {
       
  7054         if (i != d->focusItem)
       
  7055             i->dragLeft();
       
  7056         i->repaint();
       
  7057     }
       
  7058     if (d->focusItem) {
       
  7059         if (i != d->focusItem) {
       
  7060             d->focusItem->dragEntered();
       
  7061             d->autoopenTimer->stop();
       
  7062             d->autoopenTimer->start(autoopenTime);
       
  7063         }
       
  7064         d->focusItem->repaint();
       
  7065     } else {
       
  7066         d->autoopenTimer->stop();
       
  7067     }
       
  7068     if ((i && i->dropEnabled() && i->acceptDrop(e)) || acceptDrops())
       
  7069         e->accept();
       
  7070     else
       
  7071         e->ignore();
       
  7072 }
       
  7073 
       
  7074 /*! \reimp */
       
  7075 
       
  7076 void Q3ListView::contentsDragLeaveEvent(QDragLeaveEvent *)
       
  7077 {
       
  7078     d->autoopenTimer->stop();
       
  7079 
       
  7080     if (d->focusItem)
       
  7081         d->focusItem->dragLeft();
       
  7082 
       
  7083     setCurrentItem(d->oldFocusItem);
       
  7084     d->oldFocusItem = 0;
       
  7085 }
       
  7086 
       
  7087 /*! \reimp */
       
  7088 
       
  7089 void Q3ListView::contentsDropEvent(QDropEvent *e)
       
  7090 {
       
  7091     d->autoopenTimer->stop();
       
  7092 
       
  7093     setCurrentItem(d->oldFocusItem);
       
  7094     Q3ListViewItem *i = itemAt(contentsToViewport(e->pos()));
       
  7095     if (i && i->dropEnabled() && i->acceptDrop(e)) {
       
  7096         i->dropped(e);
       
  7097         e->accept();
       
  7098     } else if (acceptDrops()) {
       
  7099         emit dropped(e);
       
  7100         e->accept();
       
  7101     }
       
  7102 }
       
  7103 
       
  7104 /*!
       
  7105     If the user presses the mouse on an item and starts moving the
       
  7106     mouse, and the item allow dragging (see
       
  7107     Q3ListViewItem::setDragEnabled()), this function is called to get a
       
  7108     drag object and a drag is started unless dragObject() returns 0.
       
  7109 
       
  7110     By default this function returns 0. You should reimplement it and
       
  7111     create a Q3DragObject depending on the selected items.
       
  7112 */
       
  7113 
       
  7114 Q3DragObject *Q3ListView::dragObject()
       
  7115 {
       
  7116     return 0;
       
  7117 }
       
  7118 
       
  7119 /*!
       
  7120     Starts a drag.
       
  7121 */
       
  7122 
       
  7123 void Q3ListView::startDrag()
       
  7124 {
       
  7125     if (!d->startDragItem)
       
  7126         return;
       
  7127 
       
  7128     d->startDragItem = 0;
       
  7129     d->buttonDown = false;
       
  7130 
       
  7131     Q3DragObject *drag = dragObject();
       
  7132     if (!drag)
       
  7133         return;
       
  7134 
       
  7135     drag->drag();
       
  7136 }
       
  7137 
       
  7138 #endif // QT_NO_DRAGANDDROP
       
  7139 
       
  7140 /*!
       
  7141     \property Q3ListView::defaultRenameAction
       
  7142     \brief What action to perform when the editor loses focus during renaming
       
  7143 
       
  7144     If this property is \c Accept, and the user renames an item and
       
  7145     the editor loses focus (without the user pressing Enter), the
       
  7146     item will still be renamed. If the property's value is \c Reject,
       
  7147     the item will not be renamed unless the user presses Enter. The
       
  7148     default is \c Reject.
       
  7149 */
       
  7150 
       
  7151 void Q3ListView::setDefaultRenameAction(RenameAction a)
       
  7152 {
       
  7153     d->defRenameAction = a;
       
  7154 }
       
  7155 
       
  7156 Q3ListView::RenameAction Q3ListView::defaultRenameAction() const
       
  7157 {
       
  7158     return d->defRenameAction;
       
  7159 }
       
  7160 
       
  7161 /*!
       
  7162     Returns true if an item is being renamed; otherwise returns false.
       
  7163 */
       
  7164 
       
  7165 bool Q3ListView::isRenaming() const
       
  7166 {
       
  7167     return currentItem() && currentItem()->renameBox;
       
  7168 }
       
  7169 
       
  7170 /**********************************************************************
       
  7171  *
       
  7172  * Class Q3ListViewItemIterator
       
  7173  *
       
  7174  **********************************************************************/
       
  7175 
       
  7176 
       
  7177 /*!
       
  7178     \class Q3ListViewItemIterator
       
  7179     \brief The Q3ListViewItemIterator class provides an iterator for collections of Q3ListViewItems.
       
  7180 
       
  7181     \compat
       
  7182 
       
  7183     Construct an instance of a Q3ListViewItemIterator, with either a
       
  7184     Q3ListView* or a Q3ListViewItem* as argument, to operate on the tree
       
  7185     of Q3ListViewItems, starting from the argument.
       
  7186 
       
  7187     A Q3ListViewItemIterator iterates over all the items from its
       
  7188     starting point. This means that it always makes the first child of
       
  7189     the current item the new current item. If there is no child, the
       
  7190     next sibling becomes the new current item; and if there is no next
       
  7191     sibling, the next sibling of the parent becomes current.
       
  7192 
       
  7193     The following example creates a list of all the items that have
       
  7194     been selected by the user, storing pointers to the items in a
       
  7195     QList:
       
  7196     \snippet doc/src/snippets/code/src_qt3support_itemviews_q3listview.cpp 6
       
  7197 
       
  7198     An alternative approach is to use an \c IteratorFlag:
       
  7199     \snippet doc/src/snippets/code/src_qt3support_itemviews_q3listview.cpp 7
       
  7200 
       
  7201     A Q3ListViewItemIterator provides a convenient and easy way to
       
  7202     traverse a hierarchical Q3ListView.
       
  7203 
       
  7204     Multiple Q3ListViewItemIterators can operate on the tree of
       
  7205     Q3ListViewItems. A Q3ListView knows about all iterators operating on
       
  7206     its Q3ListViewItems. So when a Q3ListViewItem gets removed all
       
  7207     iterators that point to this item are updated and point to the
       
  7208     following item if possible, otherwise to a valid item before the
       
  7209     current one or to 0. Note however that deleting the parent item of
       
  7210     an item that an iterator points to is not safe.
       
  7211 
       
  7212     \sa Q3ListView, Q3ListViewItem
       
  7213 */
       
  7214 
       
  7215 /*!
       
  7216     \enum Q3ListViewItemIterator::IteratorFlag
       
  7217 
       
  7218     These flags can be passed to a Q3ListViewItemIterator constructor
       
  7219     (OR-ed together if more than one is used), so that the iterator
       
  7220     will only iterate over items that match the given flags.
       
  7221 
       
  7222     \value Visible
       
  7223     \value Invisible
       
  7224     \value Selected
       
  7225     \value Unselected
       
  7226     \value Selectable
       
  7227     \value NotSelectable
       
  7228     \value DragEnabled
       
  7229     \value DragDisabled
       
  7230     \value DropEnabled
       
  7231     \value DropDisabled
       
  7232     \value Expandable
       
  7233     \value NotExpandable
       
  7234     \value Checked
       
  7235     \value NotChecked
       
  7236 */
       
  7237 
       
  7238 /*!
       
  7239     Constructs an empty iterator.
       
  7240 */
       
  7241 
       
  7242 Q3ListViewItemIterator::Q3ListViewItemIterator()
       
  7243     :  curr(0), listView(0), flags(0)
       
  7244 {
       
  7245 }
       
  7246 
       
  7247 /*!
       
  7248     Constructs an iterator for the Q3ListView that contains the \a
       
  7249     item. The current iterator item is set to point to the \a item.
       
  7250 */
       
  7251 
       
  7252 Q3ListViewItemIterator::Q3ListViewItemIterator(Q3ListViewItem *item)
       
  7253     :  curr(item), listView(0), flags(0)
       
  7254 {
       
  7255     if (item) {
       
  7256         item->enforceSortOrderBackToRoot();
       
  7257         listView = item->listView();
       
  7258     }
       
  7259     if (listView)
       
  7260         listView->d->iterators.append(this);
       
  7261 }
       
  7262 
       
  7263 /*!
       
  7264     Constructs an iterator for the Q3ListView that contains the \a item
       
  7265     using the flags \a iteratorFlags. The current iterator item is set
       
  7266     to point to \a item or the next matching item if \a item doesn't
       
  7267     match the flags.
       
  7268 
       
  7269     \sa Q3ListViewItemIterator::IteratorFlag
       
  7270 */
       
  7271 
       
  7272 Q3ListViewItemIterator::Q3ListViewItemIterator(Q3ListViewItem *item, int iteratorFlags)
       
  7273     :  curr(item), listView(0), flags(iteratorFlags)
       
  7274 {
       
  7275     // go to next matching item if the current don't match
       
  7276     if (curr && !matchesFlags(curr))
       
  7277         ++(*this);
       
  7278 
       
  7279     if (curr) {
       
  7280         curr->enforceSortOrderBackToRoot();
       
  7281         listView = curr->listView();
       
  7282     }
       
  7283     if (listView)
       
  7284         listView->d->iterators.append(this);
       
  7285 }
       
  7286 
       
  7287 
       
  7288 /*!
       
  7289     Constructs an iterator for the same Q3ListView as \a it. The
       
  7290     current iterator item is set to point on the current item of \a
       
  7291     it.
       
  7292 */
       
  7293 
       
  7294 Q3ListViewItemIterator::Q3ListViewItemIterator(const Q3ListViewItemIterator& it)
       
  7295     : curr(it.curr), listView(it.listView), flags(it.flags)
       
  7296 {
       
  7297     if (listView)
       
  7298         listView->d->iterators.append(this);
       
  7299 }
       
  7300 
       
  7301 /*!
       
  7302     Constructs an iterator for the Q3ListView \a lv. The current
       
  7303     iterator item is set to point on the first child (Q3ListViewItem)
       
  7304     of \a lv.
       
  7305 */
       
  7306 
       
  7307 Q3ListViewItemIterator::Q3ListViewItemIterator(Q3ListView *lv)
       
  7308     : curr(lv->firstChild()), listView(lv), flags(0)
       
  7309 {
       
  7310     if (listView)
       
  7311         listView->d->iterators.append(this);
       
  7312 }
       
  7313 
       
  7314 /*!
       
  7315     Constructs an iterator for the Q3ListView \a lv with the flags \a
       
  7316     iteratorFlags. The current iterator item is set to point on the
       
  7317     first child (Q3ListViewItem) of \a lv that matches the flags.
       
  7318 
       
  7319     \sa Q3ListViewItemIterator::IteratorFlag
       
  7320 */
       
  7321 
       
  7322 Q3ListViewItemIterator::Q3ListViewItemIterator(Q3ListView *lv, int iteratorFlags)
       
  7323     : curr (lv->firstChild()), listView(lv), flags(iteratorFlags)
       
  7324 {
       
  7325     if (listView)
       
  7326         listView->d->iterators.append(this);
       
  7327     if (!matchesFlags(curr))
       
  7328         ++(*this);
       
  7329 }
       
  7330 
       
  7331 
       
  7332 
       
  7333 /*!
       
  7334     Assignment. Makes a copy of \a it and returns a reference to its
       
  7335     iterator.
       
  7336 */
       
  7337 
       
  7338 Q3ListViewItemIterator &Q3ListViewItemIterator::operator=(const Q3ListViewItemIterator &it)
       
  7339 {
       
  7340     if (listView)
       
  7341         listView->d->iterators.removeAll(this);
       
  7342 
       
  7343     listView = it.listView;
       
  7344     curr = it.curr;
       
  7345     flags = it.flags;
       
  7346     if (listView)
       
  7347         listView->d->iterators.append(this);
       
  7348 
       
  7349     // go to next matching item if the current don't match
       
  7350     if (curr && !matchesFlags(curr))
       
  7351         ++(*this);
       
  7352 
       
  7353     return *this;
       
  7354 }
       
  7355 
       
  7356 /*!
       
  7357     Destroys the iterator.
       
  7358 */
       
  7359 
       
  7360 Q3ListViewItemIterator::~Q3ListViewItemIterator()
       
  7361 {
       
  7362     if (listView)
       
  7363         listView->d->iterators.removeAll(this);
       
  7364 }
       
  7365 
       
  7366 /*!
       
  7367     Prefix ++. Makes the next item the new current item and returns
       
  7368     it. Returns 0 if the current item is the last item or the
       
  7369     Q3ListView is 0.
       
  7370 */
       
  7371 
       
  7372 Q3ListViewItemIterator &Q3ListViewItemIterator::operator++()
       
  7373 {
       
  7374     if (!curr)
       
  7375         return *this;
       
  7376 
       
  7377     Q3ListViewItem *item = curr->firstChild();
       
  7378     if (!item) {
       
  7379         while ((item = curr->nextSibling()) == 0 ) {
       
  7380             curr = curr->parent();
       
  7381             if (curr == 0)
       
  7382                 break;
       
  7383         }
       
  7384     }
       
  7385     curr = item;
       
  7386     // if the next one doesn't match the flags we try one more ahead
       
  7387     if (curr && !matchesFlags(curr))
       
  7388         ++(*this);
       
  7389     return *this;
       
  7390 }
       
  7391 
       
  7392 /*!
       
  7393     \overload
       
  7394 
       
  7395     Postfix ++. Makes the next item the new current item and returns
       
  7396     the item that \e was the current item.
       
  7397 */
       
  7398 
       
  7399 const Q3ListViewItemIterator Q3ListViewItemIterator::operator++(int)
       
  7400 {
       
  7401     Q3ListViewItemIterator oldValue = *this;
       
  7402     ++(*this);
       
  7403     return oldValue;
       
  7404 }
       
  7405 
       
  7406 /*!
       
  7407     Sets the current item to the item \a j positions after the current
       
  7408     item. If that item is beyond the last item, the current item is
       
  7409     set to 0. Returns the current item.
       
  7410 */
       
  7411 
       
  7412 Q3ListViewItemIterator &Q3ListViewItemIterator::operator+=(int j)
       
  7413 {
       
  7414     while (curr && j--)
       
  7415         ++(*this);
       
  7416 
       
  7417     return *this;
       
  7418 }
       
  7419 
       
  7420 /*!
       
  7421     Prefix --. Makes the previous item the new current item and
       
  7422     returns it. Returns 0 if the current item is the first item or the
       
  7423     Q3ListView is 0.
       
  7424 */
       
  7425 
       
  7426 Q3ListViewItemIterator &Q3ListViewItemIterator::operator--()
       
  7427 {
       
  7428     if (!curr)
       
  7429         return *this;
       
  7430 
       
  7431     if (!curr->parent()) {
       
  7432         // we are in the first depth
       
  7433        if (curr->listView()) {
       
  7434             if (curr->listView()->firstChild() != curr) {
       
  7435                 // go the previous sibling
       
  7436                 Q3ListViewItem *i = curr->listView()->firstChild();
       
  7437                 while (i && i->siblingItem != curr)
       
  7438                     i = i->siblingItem;
       
  7439 
       
  7440                 curr = i;
       
  7441 
       
  7442                 if (i && i->firstChild()) {
       
  7443                     // go to the last child of this item
       
  7444                     Q3ListViewItemIterator it(curr->firstChild());
       
  7445                     for (; it.current() && it.current()->parent(); ++it)
       
  7446                         curr = it.current();
       
  7447                 }
       
  7448 
       
  7449                 if (curr && !matchesFlags(curr))
       
  7450                     --(*this);
       
  7451 
       
  7452                 return *this;
       
  7453             } else {
       
  7454                 //we are already the first child of the list view, so it's over
       
  7455                 curr = 0;
       
  7456                 return *this;
       
  7457             }
       
  7458         } else
       
  7459             return *this;
       
  7460     } else {
       
  7461         Q3ListViewItem *parent = curr->parent();
       
  7462 
       
  7463         if (curr != parent->firstChild()) {
       
  7464             // go to the previous sibling
       
  7465             Q3ListViewItem *i = parent->firstChild();
       
  7466             while (i && i->siblingItem != curr)
       
  7467                 i = i->siblingItem;
       
  7468 
       
  7469             curr = i;
       
  7470 
       
  7471             if (i && i->firstChild()) {
       
  7472                 // go to the last child of this item
       
  7473                 Q3ListViewItemIterator it(curr->firstChild());
       
  7474                 for (; it.current() && it.current()->parent() != parent; ++it)
       
  7475                     curr = it.current();
       
  7476             }
       
  7477 
       
  7478             if (curr && !matchesFlags(curr))
       
  7479                 --(*this);
       
  7480 
       
  7481             return *this;
       
  7482         } else {
       
  7483             // make our parent the current item
       
  7484             curr = parent;
       
  7485 
       
  7486             if (curr && !matchesFlags(curr))
       
  7487                 --(*this);
       
  7488 
       
  7489             return *this;
       
  7490         }
       
  7491     }
       
  7492 }
       
  7493 
       
  7494 /*!
       
  7495     \overload
       
  7496 
       
  7497     Postfix --. Makes the previous item the new current item and
       
  7498     returns the item that \e was the current item.
       
  7499 */
       
  7500 
       
  7501 const Q3ListViewItemIterator Q3ListViewItemIterator::operator--(int)
       
  7502 {
       
  7503     Q3ListViewItemIterator oldValue = *this;
       
  7504     --(*this);
       
  7505     return oldValue;
       
  7506 }
       
  7507 
       
  7508 /*!
       
  7509     Sets the current item to the item \a j positions before the
       
  7510     current item. If that item is before the first item, the current
       
  7511     item is set to 0. Returns the current item.
       
  7512 */
       
  7513 
       
  7514 Q3ListViewItemIterator &Q3ListViewItemIterator::operator-=(int j)
       
  7515 {
       
  7516     while (curr && j--)
       
  7517         --(*this);
       
  7518 
       
  7519     return *this;
       
  7520 }
       
  7521 
       
  7522 /*!
       
  7523     Dereference operator. Returns a reference to the current item. The
       
  7524     same as current().
       
  7525 */
       
  7526 
       
  7527 Q3ListViewItem* Q3ListViewItemIterator::operator*()
       
  7528 {
       
  7529     if (curr != 0 && !matchesFlags(curr))
       
  7530         qWarning("Q3ListViewItemIterator::operator*() curr out of sync");
       
  7531     return curr;
       
  7532 }
       
  7533 
       
  7534 /*!
       
  7535     Returns iterator's current item.
       
  7536 */
       
  7537 
       
  7538 Q3ListViewItem *Q3ListViewItemIterator::current() const
       
  7539 {
       
  7540     if (curr != 0 && !matchesFlags(curr))
       
  7541         qWarning("Q3ListViewItemIterator::current() curr out of sync");
       
  7542     return curr;
       
  7543 }
       
  7544 
       
  7545 /*
       
  7546     This function is called to notify the iterator that the current
       
  7547     item has been deleted, and sets the current item point to another
       
  7548     (valid) item or 0.
       
  7549 */
       
  7550 
       
  7551 void Q3ListViewItemIterator::currentRemoved()
       
  7552 {
       
  7553     if (!curr) return;
       
  7554 
       
  7555     if (curr->parent())
       
  7556         curr = curr->parent();
       
  7557     else if (curr->nextSibling())
       
  7558         curr = curr->nextSibling();
       
  7559     else if (listView && listView->firstChild() &&
       
  7560               listView->firstChild() != curr)
       
  7561         curr = listView->firstChild();
       
  7562     else
       
  7563         curr = 0;
       
  7564 }
       
  7565 
       
  7566 /*
       
  7567   returns true if the item \a item matches all of the flags set for the iterator
       
  7568 */
       
  7569 bool Q3ListViewItemIterator::matchesFlags(const Q3ListViewItem *item) const
       
  7570 {
       
  7571     if (!item)
       
  7572         return false;
       
  7573 
       
  7574     if (flags == 0)
       
  7575         return true;
       
  7576 
       
  7577     if (flags & Visible && !item->isVisible())
       
  7578         return false;
       
  7579     if (flags & Invisible && item->isVisible())
       
  7580         return false;
       
  7581     if (flags & Selected && !item->isSelected())
       
  7582         return false;
       
  7583     if (flags & Unselected && item->isSelected())
       
  7584         return false;
       
  7585     if (flags & Selectable && !item->isSelectable())
       
  7586         return false;
       
  7587     if (flags & NotSelectable && item->isSelectable())
       
  7588         return false;
       
  7589     if (flags & DragEnabled && !item->dragEnabled())
       
  7590         return false;
       
  7591     if (flags & DragDisabled && item->dragEnabled())
       
  7592         return false;
       
  7593     if (flags & DropEnabled && !item->dropEnabled())
       
  7594         return false;
       
  7595     if (flags & DropDisabled && item->dropEnabled())
       
  7596         return false;
       
  7597     if (flags & Expandable && !item->isExpandable())
       
  7598         return false;
       
  7599     if (flags & NotExpandable && item->isExpandable())
       
  7600         return false;
       
  7601     if (flags & Checked && !isChecked(item))
       
  7602         return false;
       
  7603     if (flags & NotChecked && isChecked(item))
       
  7604         return false;
       
  7605 
       
  7606     return true;
       
  7607 }
       
  7608 
       
  7609 /*
       
  7610   we want the iterator to check Q3CheckListItems as well, so we provide this convenience function
       
  7611   that checks if the rtti() is 1 which means Q3CheckListItem and if isOn is true, returns false otherwise.
       
  7612 */
       
  7613 bool Q3ListViewItemIterator::isChecked(const Q3ListViewItem *item) const
       
  7614 {
       
  7615     if (item->rtti() == 1)
       
  7616         return ((const Q3CheckListItem*)item)->isOn();
       
  7617     else return false;
       
  7618 }
       
  7619 
       
  7620 void Q3ListView::handleItemChange(Q3ListViewItem *old, bool shift, bool control)
       
  7621 {
       
  7622     if (d->selectionMode == Single) {
       
  7623         // nothing
       
  7624     } else if (d->selectionMode == Extended) {
       
  7625         if (shift) {
       
  7626             selectRange(d->selectAnchor ? d->selectAnchor : old,
       
  7627                          d->focusItem, false, true, (d->selectAnchor && !control) ? true : false);
       
  7628         } else if (!control) {
       
  7629             bool block = signalsBlocked();
       
  7630             blockSignals(true);
       
  7631             selectAll(false);
       
  7632             blockSignals(block);
       
  7633             setSelected(d->focusItem, true);
       
  7634         }
       
  7635     } else if (d->selectionMode == Multi) {
       
  7636         if (shift)
       
  7637             selectRange(old, d->focusItem, true, false);
       
  7638     }
       
  7639 }
       
  7640 
       
  7641 void Q3ListView::startRename()
       
  7642 {
       
  7643     if (!currentItem())
       
  7644         return;
       
  7645     currentItem()->startRename(d->pressedColumn);
       
  7646     d->buttonDown = false;
       
  7647 }
       
  7648 
       
  7649 /* unselects items from to, including children, returns true if any items were unselected */
       
  7650 bool Q3ListView::clearRange(Q3ListViewItem *from, Q3ListViewItem *to, bool includeFirst)
       
  7651 {
       
  7652     if (!from || !to)
       
  7653         return false;
       
  7654 
       
  7655     // Swap
       
  7656     if (from->itemPos() > to->itemPos()) {
       
  7657         Q3ListViewItem *temp = from;
       
  7658         from = to;
       
  7659         to = temp;
       
  7660     }
       
  7661 
       
  7662     // Start on second?
       
  7663     if (!includeFirst) {
       
  7664         Q3ListViewItem *below = (from == to) ? from : from->itemBelow();
       
  7665         if (below)
       
  7666             from = below;
       
  7667     }
       
  7668 
       
  7669     // Clear items <from, to>
       
  7670     bool changed = false;
       
  7671 
       
  7672     Q3ListViewItemIterator it(from);
       
  7673     while (it.current()) {
       
  7674         if (it.current()->isSelected()) {
       
  7675             it.current()->setSelected(false);
       
  7676             changed = true;
       
  7677         }
       
  7678         if (it.current() == to)
       
  7679             break;
       
  7680         ++it;
       
  7681     }
       
  7682 
       
  7683     // NOTE! This function does _not_ emit
       
  7684     // any signals about selection changed
       
  7685     return changed;
       
  7686 }
       
  7687 
       
  7688 void Q3ListView::selectRange(Q3ListViewItem *from, Q3ListViewItem *to, bool invert, bool includeFirst, bool clearSel)
       
  7689 {
       
  7690     if (!from || !to)
       
  7691         return;
       
  7692     if (from == to && !includeFirst)
       
  7693         return;
       
  7694     bool swap = false;
       
  7695     if (to == from->itemAbove())
       
  7696         swap = true;
       
  7697     if (!swap && from != to && from != to->itemAbove()) {
       
  7698         Q3ListViewItemIterator it(from);
       
  7699         bool found = false;
       
  7700         for (; it.current(); ++it) {
       
  7701             if (it.current() == to) {
       
  7702                 found = true;
       
  7703                 break;
       
  7704             }
       
  7705         }
       
  7706         if (!found)
       
  7707             swap = true;
       
  7708     }
       
  7709     if (swap) {
       
  7710         Q3ListViewItem *i = from;
       
  7711         from = to;
       
  7712         to = i;
       
  7713         if (!includeFirst)
       
  7714             to = to->itemAbove();
       
  7715     } else {
       
  7716         if (!includeFirst)
       
  7717             from = from->itemBelow();
       
  7718     }
       
  7719 
       
  7720     bool changed = false;
       
  7721     if (clearSel) {
       
  7722         Q3ListViewItemIterator it(firstChild());
       
  7723         for (; it.current(); ++it) {
       
  7724             if (it.current()->selected) {
       
  7725                 it.current()->setSelected(false);
       
  7726                 changed = true;
       
  7727             }
       
  7728         }
       
  7729         it = Q3ListViewItemIterator(to);
       
  7730         for (; it.current(); ++it) {
       
  7731             if (it.current()->selected) {
       
  7732                 it.current()->setSelected(false);
       
  7733                 changed = true;
       
  7734             }
       
  7735         }
       
  7736     }
       
  7737 
       
  7738     for (Q3ListViewItem *i = from; i; i = i->itemBelow()) {
       
  7739         if (!invert) {
       
  7740             if (!i->selected && i->isSelectable()) {
       
  7741                 i->setSelected(true);
       
  7742                 changed = true;
       
  7743             }
       
  7744         } else {
       
  7745             bool sel = !i->selected;
       
  7746             if (((bool)i->selected != sel && sel && i->isSelectable()) || !sel) {
       
  7747                 i->setSelected(sel);
       
  7748                 changed = true;
       
  7749             }
       
  7750         }
       
  7751         if (i == to)
       
  7752             break;
       
  7753     }
       
  7754     if (changed) {
       
  7755         triggerUpdate();
       
  7756         emit selectionChanged();
       
  7757     }
       
  7758 }
       
  7759 
       
  7760 /* clears selection from anchor to old, selects from anchor to new, does not emit selectionChanged on change */
       
  7761 bool Q3ListView::selectRange(Q3ListViewItem *newItem, Q3ListViewItem *oldItem, Q3ListViewItem *anchorItem)
       
  7762 {
       
  7763     if (!newItem || !oldItem || !anchorItem)
       
  7764         return false;
       
  7765 
       
  7766     int  anchorPos = anchorItem ? anchorItem->itemPos() : 0,
       
  7767          oldPos    = oldItem ? oldItem->itemPos() : 0,
       
  7768          newPos    = newItem->itemPos();
       
  7769     Q3ListViewItem *top=0, *bottom=0;
       
  7770     if (anchorPos > newPos) {
       
  7771         top = newItem;
       
  7772         bottom = anchorItem;
       
  7773     } else {
       
  7774         top = anchorItem;
       
  7775         bottom = newItem;
       
  7776     }
       
  7777 
       
  7778     // removes the subControls of the old selection that will no longer be selected
       
  7779     bool changed = false;
       
  7780     int topPos    = top ? top->itemPos() : 0,
       
  7781         bottomPos = bottom ? bottom->itemPos() : 0;
       
  7782     if (!(oldPos > topPos && oldPos < bottomPos)) {
       
  7783         if (oldPos < topPos)
       
  7784             changed = clearRange(oldItem, top);
       
  7785         else
       
  7786             changed = clearRange(bottom, oldItem);
       
  7787     }
       
  7788 
       
  7789     // selects the new (not already selected) items
       
  7790     Q3ListViewItemIterator lit(top);
       
  7791     for (; lit.current(); ++lit) {
       
  7792         if ((bool)lit.current()->selected != d->select) {
       
  7793             lit.current()->setSelected(d->select);
       
  7794             changed = true;
       
  7795         }
       
  7796         // Include bottom, then break
       
  7797         if (lit.current() == bottom)
       
  7798             break;
       
  7799     }
       
  7800 
       
  7801     return changed;
       
  7802 }
       
  7803 
       
  7804 
       
  7805 /*!
       
  7806     Finds the first list view item in column \a column, that matches
       
  7807     \a text and returns the item, or returns 0 of no such item could
       
  7808     be found. Pass OR-ed together \l ComparisonFlags values
       
  7809     in the \a compare flag, to control how the matching is performed.
       
  7810     The default comparison mode is case-sensitive, exact match.
       
  7811 */
       
  7812 
       
  7813 Q3ListViewItem *Q3ListView::findItem(const QString& text, int column,
       
  7814                                     ComparisonFlags compare) const
       
  7815 {
       
  7816     if (text.isEmpty() && !(compare & ExactMatch))
       
  7817         return 0;
       
  7818 
       
  7819     if (compare == Qt::CaseSensitive || compare == 0)
       
  7820         compare |= ExactMatch;
       
  7821 
       
  7822     QString itmtxt;
       
  7823     QString comtxt = text;
       
  7824     if (!(compare & Qt::CaseSensitive))
       
  7825         comtxt = comtxt.toLower();
       
  7826 
       
  7827     Q3ListViewItemIterator it(d->focusItem ? d->focusItem : firstChild());
       
  7828     Q3ListViewItem *sentinel = 0;
       
  7829     Q3ListViewItem *item;
       
  7830     Q3ListViewItem *beginsWithItem = 0;
       
  7831     Q3ListViewItem *endsWithItem = 0;
       
  7832     Q3ListViewItem *containsItem = 0;
       
  7833 
       
  7834     for (int pass = 0; pass < 2; pass++) {
       
  7835         while ((item = it.current()) != sentinel) {
       
  7836             itmtxt = item->text(column);
       
  7837             if (!(compare & CaseSensitive))
       
  7838                 itmtxt = itmtxt.toLower();
       
  7839 
       
  7840             if ((compare & ExactMatch)==ExactMatch && itmtxt == comtxt)
       
  7841                 return item;
       
  7842             if (compare & BeginsWith && !beginsWithItem && itmtxt.startsWith(comtxt))
       
  7843                 beginsWithItem = containsItem = item;
       
  7844             if (compare & EndsWith && !endsWithItem && itmtxt.endsWith(comtxt))
       
  7845                 endsWithItem = containsItem = item;
       
  7846             if ((compare & ExactMatch)==0 && !containsItem && itmtxt.contains(comtxt))
       
  7847                 containsItem = item;
       
  7848             ++it;
       
  7849         }
       
  7850 
       
  7851         it = Q3ListViewItemIterator(firstChild());
       
  7852         sentinel = d->focusItem ? d->focusItem : firstChild();
       
  7853     }
       
  7854 
       
  7855     // Obey the priorities
       
  7856     if (beginsWithItem)
       
  7857         return beginsWithItem;
       
  7858     else if (endsWithItem)
       
  7859         return endsWithItem;
       
  7860     else if (containsItem)
       
  7861         return containsItem;
       
  7862     return 0;
       
  7863 }
       
  7864 
       
  7865 /*!
       
  7866     Hides the column specified at \a column. This is a convenience
       
  7867     function that calls setColumnWidth(column, 0).
       
  7868 
       
  7869     Note: The user may still be able to resize the hidden column using
       
  7870     the header handles. To prevent this, call setResizeEnabled(false,
       
  7871     \a column) on the list views header.
       
  7872 
       
  7873     \sa setColumnWidth()
       
  7874 */
       
  7875 
       
  7876 void Q3ListView::hideColumn(int column)
       
  7877 {
       
  7878     setColumnWidth(column, 0);
       
  7879 }
       
  7880 
       
  7881 /*! Adjusts the column \a col to its preferred width */
       
  7882 
       
  7883 void Q3ListView::adjustColumn(int col)
       
  7884 {
       
  7885     if (col < 0 || col > (int)d->column.count() - 1 || d->h->isStretchEnabled(col))
       
  7886         return;
       
  7887 
       
  7888     int oldw = d->h->sectionSize(col);
       
  7889 
       
  7890     int w = d->h->sectionSizeHint(col, fontMetrics()).width();
       
  7891     if (d->h->iconSet(col))
       
  7892         w += d->h->iconSet(col)->pixmap().width();
       
  7893     w = qMax(w, 20);
       
  7894     QFontMetrics fm(fontMetrics());
       
  7895     Q3ListViewItem* item = firstChild();
       
  7896     int rootDepth = rootIsDecorated() ? treeStepSize() : 0;
       
  7897     while (item) {
       
  7898         int iw = item->width(fm, this, col);
       
  7899         if (0 == col)
       
  7900             iw += itemMargin() + rootDepth + item->depth()*treeStepSize() - 1;
       
  7901         w = qMax(w, iw);
       
  7902         item = item->itemBelow();
       
  7903     }
       
  7904     w = qMax(w, QApplication::globalStrut().width());
       
  7905 
       
  7906     d->h->adjustHeaderSize(oldw - w);
       
  7907     if (oldw != w) {
       
  7908         d->fullRepaintOnComlumnChange = true;
       
  7909         d->h->resizeSection(col, w);
       
  7910         emit d->h->sizeChange(col, oldw, w);
       
  7911     }
       
  7912 }
       
  7913 
       
  7914 /*!
       
  7915     \enum Q3ListView::StringComparisonMode
       
  7916 
       
  7917     This enum type is used to set the string comparison mode when
       
  7918     searching for an item. We'll refer to the string being searched
       
  7919     as the 'target' string.
       
  7920 
       
  7921     \value CaseSensitive The strings must match case sensitively.
       
  7922     \value ExactMatch The target and search strings must match exactly.
       
  7923     \value BeginsWith The target string begins with the search string.
       
  7924     \value EndsWith The target string ends with the search string.
       
  7925     \value Contains The target string contains the search string.
       
  7926 
       
  7927     If you OR these flags together (excluding \c CaseSensitive), the
       
  7928     search criteria be applied in the following order: \c ExactMatch,
       
  7929     \c BeginsWith, \c EndsWith, \c Contains.
       
  7930 
       
  7931     Matching is case-insensitive unless \c CaseSensitive is set. \c
       
  7932     CaseSensitive can be OR-ed with any combination of the other
       
  7933     flags.
       
  7934 
       
  7935     \sa ComparisonFlags
       
  7936 */
       
  7937 
       
  7938 /*!
       
  7939     \typedef Q3ListView::ComparisonFlags
       
  7940 
       
  7941     This typedef is used in Q3ListView's API for values that are OR'd
       
  7942     combinations of \l StringComparisonMode values.
       
  7943 
       
  7944     \sa StringComparisonMode
       
  7945 */
       
  7946 
       
  7947 QT_END_NAMESPACE
       
  7948 
       
  7949 #endif // QT_NO_LISTVIEW