/src/qt3support/itemviews/q3listbox.cpp

https://bitbucket.org/ultra_iter/qt-vtl · C++ · 4687 lines · 2611 code · 575 blank · 1501 comment · 854 complexity · f544e93302cca8e745ac1e355f7324e9 MD5 · raw file

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