~oif-team/ubuntu/natty/qt4-x11/xi2.1

« back to all changes in this revision

Viewing changes to src/qt3support/itemviews/q3listbox.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Adam Conrad
  • Date: 2005-08-24 04:09:09 UTC
  • Revision ID: james.westby@ubuntu.com-20050824040909-xmxe9jfr4a0w5671
Tags: upstream-4.0.0
ImportĀ upstreamĀ versionĀ 4.0.0

Show diffs side-by-side

added added

removed removed

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