Changeset 561 for trunk/src/gui/itemviews/qabstractitemview.cpp
- Timestamp:
- Feb 11, 2010, 11:19:06 PM (15 years ago)
- Location:
- trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk
-
Property svn:mergeinfo
set to (toggle deleted branches)
/branches/vendor/nokia/qt/4.6.1 merged eligible /branches/vendor/nokia/qt/current merged eligible /branches/vendor/trolltech/qt/current 3-149
-
Property svn:mergeinfo
set to (toggle deleted branches)
-
trunk/src/gui/itemviews/qabstractitemview.cpp
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the QtGui module of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 24 ** In addition, as a special exception, Nokia gives you certain additional 25 ** rights. These rights are described in the Nokia Qt LGPL Exception 26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 27 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** … … 62 62 #include <qaccessible.h> 63 63 #endif 64 #include <private/qsoftkeymanager_p.h> 64 65 65 66 QT_BEGIN_NAMESPACE … … 69 70 itemDelegate(0), 70 71 selectionModel(0), 72 ctrlDragSelectionFlag(QItemSelectionModel::NoUpdate), 73 noSelectionOnMousePress(false), 71 74 selectionMode(QAbstractItemView::ExtendedSelection), 72 75 selectionBehavior(QAbstractItemView::SelectItems), … … 74 77 pressedModifiers(Qt::NoModifier), 75 78 pressedPosition(QPoint(-1, -1)), 79 pressedAlreadySelected(false), 76 80 viewportEnteredNeeded(false), 77 81 state(QAbstractItemView::NoState), … … 85 89 overwrite(false), 86 90 dropIndicatorPosition(QAbstractItemView::OnItem), 91 defaultDropAction(Qt::IgnoreAction), 92 #endif 93 #ifdef QT_SOFTKEYS_ENABLED 94 doneSoftKey(0), 87 95 #endif 88 96 autoScroll(true), 89 97 autoScrollMargin(16), 90 98 autoScrollCount(0), 99 shouldScrollToCurrentOnShow(false), 100 shouldClearStatusTip(false), 91 101 alternatingColors(false), 92 102 textElideMode(Qt::ElideRight), … … 108 118 q->setItemDelegate(new QStyledItemDelegate(q)); 109 119 110 q->verticalScrollBar()->setRange(0, 0);111 q->horizontalScrollBar()->setRange(0, 0);112 113 QObject::connect( q->verticalScrollBar(), SIGNAL(actionTriggered(int)),120 vbar->setRange(0, 0); 121 hbar->setRange(0, 0); 122 123 QObject::connect(vbar, SIGNAL(actionTriggered(int)), 114 124 q, SLOT(verticalScrollbarAction(int))); 115 QObject::connect( q->horizontalScrollBar(), SIGNAL(actionTriggered(int)),125 QObject::connect(hbar, SIGNAL(actionTriggered(int)), 116 126 q, SLOT(horizontalScrollbarAction(int))); 117 QObject::connect( q->verticalScrollBar(), SIGNAL(valueChanged(int)),127 QObject::connect(vbar, SIGNAL(valueChanged(int)), 118 128 q, SLOT(verticalScrollbarValueChanged(int))); 119 QObject::connect( q->horizontalScrollBar(), SIGNAL(valueChanged(int)),129 QObject::connect(hbar, SIGNAL(valueChanged(int)), 120 130 q, SLOT(horizontalScrollbarValueChanged(int))); 121 131 … … 125 135 126 136 q->setAttribute(Qt::WA_InputMethodEnabled); 127 } 137 138 #ifdef QT_SOFTKEYS_ENABLED 139 doneSoftKey = QSoftKeyManager::createKeyedAction(QSoftKeyManager::DoneSoftKey, Qt::Key_Back, q); 140 #endif 141 } 142 143 void QAbstractItemViewPrivate::setHoverIndex(const QPersistentModelIndex &index) 144 { 145 Q_Q(QAbstractItemView); 146 if (hover == index) 147 return; 148 149 q->update(hover); //update the old one 150 hover = index; 151 q->update(hover); //update the new one 152 } 153 154 void QAbstractItemViewPrivate::checkMouseMove(const QPersistentModelIndex &index) 155 { 156 //we take a persistent model index because the model might change by emitting signals 157 Q_Q(QAbstractItemView); 158 setHoverIndex(index); 159 if (viewportEnteredNeeded || enteredIndex != index) { 160 viewportEnteredNeeded = false; 161 162 if (index.isValid()) { 163 emit q->entered(index); 164 #ifndef QT_NO_STATUSTIP 165 QString statustip = model->data(index, Qt::StatusTipRole).toString(); 166 if (parent && (shouldClearStatusTip || !statustip.isEmpty())) { 167 QStatusTipEvent tip(statustip); 168 QApplication::sendEvent(parent, &tip); 169 shouldClearStatusTip = !statustip.isEmpty(); 170 } 171 #endif 172 } else { 173 #ifndef QT_NO_STATUSTIP 174 if (parent && shouldClearStatusTip) { 175 QString emptyString; 176 QStatusTipEvent tip( emptyString ); 177 QApplication::sendEvent(parent, &tip); 178 } 179 #endif 180 emit q->viewportEntered(); 181 } 182 enteredIndex = index; 183 } 184 } 185 128 186 129 187 /*! … … 134 192 135 193 \ingroup model-view 136 \mainclass 194 137 195 138 196 QAbstractItemView class is the base class for every standard view … … 143 201 changes to their models. This class provides standard support for 144 202 keyboard and mouse navigation, viewport scrolling, item editing, 145 and selections. 203 and selections. The keyboard navigation implements this 204 functionality: 205 206 \table 207 \header 208 \o Keys 209 \o Functionality 210 \row 211 \o Arrow keys 212 \o Changes the current item and selects it. 213 \row 214 \o Ctrl+Arrow keys 215 \o Changes the current item but does not select it. 216 \row 217 \o Shift+Arrow keys 218 \o Changes the current item and selects it. The previously 219 selected item(s) is not deselected. 220 \row 221 \o Ctr+Space 222 \o Toggles selection of the current item. 223 \row 224 \o Tab/Backtab 225 \o Changes the current item to the next/previous item. 226 \row 227 \o Home/End 228 \o Selects the first/last item in the model. 229 \row 230 \o Page up/Page down 231 \o Scrolls the rows shown up/down by the number of 232 visible rows in the view. 233 \row 234 \o Ctrl+A 235 \o Selects all items in the model. 236 \endtable 237 238 Note that the above table assumes that the 239 \l{selectionMode}{selection mode} allows the operations. For 240 instance, you cannot select items if the selection mode is 241 QAbstractItemView::NoSelection. 146 242 147 243 The QAbstractItemView class is one of the \l{Model/View Classes} … … 525 621 disconnect(d->model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), 526 622 this, SLOT(dataChanged(QModelIndex,QModelIndex))); 623 disconnect(d->model, SIGNAL(headerDataChanged(Qt::Orientation,int,int)), 624 this, SLOT(_q_headerDataChanged())); 527 625 disconnect(d->model, SIGNAL(rowsInserted(QModelIndex,int,int)), 528 626 this, SLOT(rowsInserted(QModelIndex,int,int))); … … 552 650 "The parent of a top level index should be invalid"); 553 651 554 if (d->model && d->model!= QAbstractItemModelPrivate::staticEmptyModel()) {652 if (d->model != QAbstractItemModelPrivate::staticEmptyModel()) { 555 653 connect(d->model, SIGNAL(destroyed()), 556 654 this, SLOT(_q_modelDestroyed())); 557 655 connect(d->model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), 558 656 this, SLOT(dataChanged(QModelIndex,QModelIndex))); 657 connect(d->model, SIGNAL(headerDataChanged(Qt::Orientation,int,int)), 658 this, SLOT(_q_headerDataChanged())); 559 659 connect(d->model, SIGNAL(rowsInserted(QModelIndex,int,int)), 560 660 this, SLOT(rowsInserted(QModelIndex,int,int))); … … 671 771 } 672 772 673 674 773 if (delegate) { 675 774 if (d->delegateRefCount(delegate) == 0) { … … 682 781 } 683 782 d->itemDelegate = delegate; 783 viewport()->update(); 684 784 } 685 785 … … 746 846 d->rowDelegates.insert(row, delegate); 747 847 } 848 viewport()->update(); 748 849 } 749 850 … … 802 903 d->columnDelegates.insert(column, delegate); 803 904 } 905 viewport()->update(); 804 906 } 805 907 … … 820 922 821 923 /*! 822 Returns the item delegate used by this view and model for823 the given \a index.924 Returns the item delegate used by this view and model for 925 the given \a index. 824 926 */ 825 927 QAbstractItemDelegate *QAbstractItemView::itemDelegate(const QModelIndex &index) const … … 830 932 831 933 /*! 832 \property QAbstractItemView::selectionMode833 \brief which selection mode the view operates in834 835 This property controls whether the user can select one or many items836 and, in many-item selections, whether the selection must be a837 continuous range of items.838 839 \sa SelectionMode SelectionBehavior934 \property QAbstractItemView::selectionMode 935 \brief which selection mode the view operates in 936 937 This property controls whether the user can select one or many items 938 and, in many-item selections, whether the selection must be a 939 continuous range of items. 940 941 \sa SelectionMode SelectionBehavior 840 942 */ 841 943 void QAbstractItemView::setSelectionMode(SelectionMode mode) … … 852 954 853 955 /*! 854 \property QAbstractItemView::selectionBehavior855 \brief which selection behavior the view uses856 857 This property holds whether selections are done858 in terms of single items, rows or columns.859 860 \sa SelectionMode SelectionBehavior956 \property QAbstractItemView::selectionBehavior 957 \brief which selection behavior the view uses 958 959 This property holds whether selections are done 960 in terms of single items, rows or columns. 961 962 \sa SelectionMode SelectionBehavior 861 963 */ 862 964 … … 875 977 /*! 876 978 Sets the current item to be the item at \a index. 877 Depending on the current selection mode, the item may also be selected. 979 980 Unless the current selection mode is 981 \l{QAbstractItemView::}{NoSelection}, the item is also be selected. 878 982 Note that this function also updates the starting position for any 879 983 new selections the user performs. … … 921 1025 { 922 1026 Q_D(QAbstractItemView); 1027 d->delayedReset.stop(); //make sure we stop the timer 923 1028 QList<QEditorInfo>::const_iterator it = d->editors.constBegin(); 924 1029 for (; it != d->editors.constEnd(); ++it) … … 929 1034 setState(NoState); 930 1035 setRootIndex(QModelIndex()); 1036 if (d->selectionModel) 1037 d->selectionModel->reset(); 931 1038 } 932 1039 … … 959 1066 960 1067 /*! 961 Selects all itemin the view.962 This function wil use the selectionselection behavior963 set on the view when selecting.964 965 \sa setSelection(), selectedIndexes(), clearSelection()1068 Selects all items in the view. 1069 This function will use the selection behavior 1070 set on the view when selecting. 1071 1072 \sa setSelection(), selectedIndexes(), clearSelection() 966 1073 */ 967 1074 void QAbstractItemView::selectAll() … … 1192 1299 #ifndef QT_NO_DRAGANDDROP 1193 1300 /*! 1194 \property QAbstractItemView::showDropIndicator1195 \brief whether the drop indicator is shown when dragging items and dropping.1196 1197 \sa dragEnabled DragDropMode dragDropOverwriteMode acceptDrops1301 \property QAbstractItemView::showDropIndicator 1302 \brief whether the drop indicator is shown when dragging items and dropping. 1303 1304 \sa dragEnabled DragDropMode dragDropOverwriteMode acceptDrops 1198 1305 */ 1199 1306 … … 1211 1318 1212 1319 /*! 1213 \property QAbstractItemView::dragEnabled1214 \brief whether the view supports dragging of its own items1215 1216 \sa showDropIndicator DragDropMode dragDropOverwriteMode acceptDrops1320 \property QAbstractItemView::dragEnabled 1321 \brief whether the view supports dragging of its own items 1322 1323 \sa showDropIndicator DragDropMode dragDropOverwriteMode acceptDrops 1217 1324 */ 1218 1325 … … 1250 1357 1251 1358 /*! 1252 \property QAbstractItemView::dragDropMode1253 \brief the drag and drop event the view will act upon1254 1255 \since 4.21256 \sa showDropIndicator dragDropOverwriteMode1359 \property QAbstractItemView::dragDropMode 1360 \brief the drag and drop event the view will act upon 1361 1362 \since 4.2 1363 \sa showDropIndicator dragDropOverwriteMode 1257 1364 */ 1258 1365 void QAbstractItemView::setDragDropMode(DragDropMode behavior) … … 1287 1394 } 1288 1395 1396 /*! 1397 \property QAbstractItemView::defaultDropAction 1398 \brief the drop action that will be used by default in QAbstractItemView::drag() 1399 1400 If the property is not set, the drop action is CopyAction when the supported 1401 actions support CopyAction. 1402 1403 \since 4.6 1404 \sa showDropIndicator dragDropOverwriteMode 1405 */ 1406 void QAbstractItemView::setDefaultDropAction(Qt::DropAction dropAction) 1407 { 1408 Q_D(QAbstractItemView); 1409 d->defaultDropAction = dropAction; 1410 } 1411 1412 Qt::DropAction QAbstractItemView::defaultDropAction() const 1413 { 1414 Q_D(const QAbstractItemView); 1415 return d->defaultDropAction; 1416 } 1417 1289 1418 #endif // QT_NO_DRAGANDDROP 1290 1419 1291 1420 /*! 1292 \property QAbstractItemView::alternatingRowColors1293 \brief whether to draw the background using alternating colors1294 1295 If this property is true, the item background will be drawn using1296 QPalette::Base and QPalette::AlternateBase; otherwise the background1297 will be drawn using the QPalette::Base color.1298 1299 By default, this property is false.1421 \property QAbstractItemView::alternatingRowColors 1422 \brief whether to draw the background using alternating colors 1423 1424 If this property is true, the item background will be drawn using 1425 QPalette::Base and QPalette::AlternateBase; otherwise the background 1426 will be drawn using the QPalette::Base color. 1427 1428 By default, this property is false. 1300 1429 */ 1301 1430 void QAbstractItemView::setAlternatingRowColors(bool enable) … … 1338 1467 \property QAbstractItemView::textElideMode 1339 1468 1340 \brief the theposition of the "..." in elided text.1469 \brief the position of the "..." in elided text. 1341 1470 1342 1471 The default value for all item views is Qt::ElideRight. … … 1381 1510 break; 1382 1511 case QEvent::Show: 1383 { 1384 d->executePostedLayout(); //make sure we set the layout properly 1512 d->executePostedLayout(); //make sure we set the layout properly 1513 if (d->shouldScrollToCurrentOnShow) { 1514 d->shouldScrollToCurrentOnShow = false; 1385 1515 const QModelIndex current = currentIndex(); 1386 1516 if (current.isValid() && (d->state == QAbstractItemView::EditingState || d->autoScroll)) … … 1401 1531 d->checkPersistentEditorFocus(); 1402 1532 break; 1533 case QEvent::FontChange: 1534 d->doDelayedItemsLayout(); // the size of the items will change 1535 break; 1403 1536 default: 1404 1537 break; … … 1419 1552 Q_D(QAbstractItemView); 1420 1553 switch (event->type()) { 1421 case QEvent::HoverEnter: { 1422 QHoverEvent *he = static_cast<QHoverEvent*>(event); 1423 d->hover = indexAt(he->pos()); 1424 d->viewport->update(visualRect(d->hover)); 1425 break; } 1426 case QEvent::HoverLeave: { 1427 d->viewport->update(visualRect(d->hover)); // update old 1428 d->hover = QModelIndex(); 1429 break; } 1430 case QEvent::HoverMove: { 1431 QHoverEvent *he = static_cast<QHoverEvent*>(event); 1432 QModelIndex old = d->hover; 1433 d->hover = indexAt(he->pos()); 1434 if (d->hover != old) 1435 d->viewport->update(visualRect(old)|visualRect(d->hover)); 1436 break; } 1554 case QEvent::HoverMove: 1555 case QEvent::HoverEnter: 1556 d->setHoverIndex(indexAt(static_cast<QHoverEvent*>(event)->pos())); 1557 break; 1558 case QEvent::HoverLeave: 1559 d->setHoverIndex(QModelIndex()); 1560 break; 1437 1561 case QEvent::Enter: 1438 1562 d->viewportEnteredNeeded = true; 1439 1563 break; 1440 1564 case QEvent::Leave: 1565 #ifndef QT_NO_STATUSTIP 1566 if (d->shouldClearStatusTip && d->parent) { 1567 QString empty; 1568 QStatusTipEvent tip(empty); 1569 QApplication::sendEvent(d->parent, &tip); 1570 d->shouldClearStatusTip = false; 1571 } 1572 #endif 1441 1573 d->enteredIndex = QModelIndex(); 1442 1574 break; … … 1492 1624 d->pressedModifiers = event->modifiers(); 1493 1625 QItemSelectionModel::SelectionFlags command = selectionCommand(index, event); 1626 d->noSelectionOnMousePress = command == QItemSelectionModel::NoUpdate || !index.isValid(); 1494 1627 QPoint offset = d->offset(); 1495 1628 if ((command & QItemSelectionModel::Current) == 0) 1496 1629 d->pressedPosition = pos + offset; 1497 1498 if (d->pressedPosition == QPoint(-1, -1)) 1630 else if (!indexAt(d->pressedPosition - offset).isValid()) 1499 1631 d->pressedPosition = visualRect(currentIndex()).center() + offset; 1500 1632 … … 1510 1642 d->autoScroll = autoScroll; 1511 1643 QRect rect(d->pressedPosition - offset, pos); 1644 if (command.testFlag(QItemSelectionModel::Toggle)) { 1645 command &= ~QItemSelectionModel::Toggle; 1646 d->ctrlDragSelectionFlag = d->selectionModel->isSelected(index) ? QItemSelectionModel::Deselect : QItemSelectionModel::Select; 1647 command |= d->ctrlDragSelectionFlag; 1648 } 1512 1649 setSelection(rect, command); 1513 1650 … … 1553 1690 #endif // QT_NO_DRAGANDDROP 1554 1691 1555 Q ModelIndex index = indexAt(bottomRight);1692 QPersistentModelIndex index = indexAt(bottomRight); 1556 1693 QModelIndex buddy = d->model->buddy(d->pressedIndex); 1557 1694 if ((state() == EditingState && d->hasEditor(buddy)) … … 1564 1701 topLeft = bottomRight; 1565 1702 1566 if (d->viewportEnteredNeeded || d->enteredIndex != index) { 1567 d->viewportEnteredNeeded = false; 1568 1569 // signal handlers may change the model 1570 QPersistentModelIndex persistent = index; 1571 if (persistent.isValid()) { 1572 emit entered(persistent); 1573 #ifndef QT_NO_STATUSTIP 1574 QString statustip = d->model->data(persistent, Qt::StatusTipRole).toString(); 1575 if (parent() && !statustip.isEmpty()) { 1576 QStatusTipEvent tip(statustip); 1577 QApplication::sendEvent(parent(), &tip); 1578 } 1579 #endif 1580 } else { 1581 #ifndef QT_NO_STATUSTIP 1582 if (parent()) { 1583 QString emptyString; 1584 QStatusTipEvent tip(emptyString); 1585 QApplication::sendEvent(parent(), &tip); 1586 } 1587 #endif 1588 emit viewportEntered(); 1589 } 1590 d->enteredIndex = persistent; 1591 index = persistent; 1592 } 1703 d->checkMouseMove(index); 1593 1704 1594 1705 #ifndef QT_NO_DRAGANDDROP 1595 if ( index.isValid()1706 if (d->pressedIndex.isValid() 1596 1707 && d->dragEnabled 1597 1708 && (state() != DragSelectingState) … … 1606 1717 setState(DragSelectingState); 1607 1718 QItemSelectionModel::SelectionFlags command = selectionCommand(index, event); 1719 if (d->ctrlDragSelectionFlag != QItemSelectionModel::NoUpdate && command.testFlag(QItemSelectionModel::Toggle)) { 1720 command &= ~QItemSelectionModel::Toggle; 1721 command |= d->ctrlDragSelectionFlag; 1722 } 1608 1723 1609 1724 // Do the normalize ourselves, since QRect::normalized() is flawed 1610 1725 QRect selectionRect = QRect(topLeft, bottomRight); 1611 QPersistentModelIndex persistent = index;1612 1726 setSelection(selectionRect, command); 1613 1727 1614 1728 // set at the end because it might scroll the view 1615 if ( persistent.isValid()1616 && ( persistent!= d->selectionModel->currentIndex())1617 && d->isIndexEnabled( persistent))1618 d->selectionModel->setCurrentIndex( persistent, QItemSelectionModel::NoUpdate);1729 if (index.isValid() 1730 && (index != d->selectionModel->currentIndex()) 1731 && d->isIndexEnabled(index)) 1732 d->selectionModel->setCurrentIndex(index, QItemSelectionModel::NoUpdate); 1619 1733 } 1620 1734 } … … 1638 1752 && d->isIndexEnabled(index) 1639 1753 && d->sendDelegateEvent(index, event)) 1640 d->viewport->update(visualRect(index));1754 update(index); 1641 1755 return; 1642 1756 } … … 1647 1761 bool edited = edit(index, trigger, event); 1648 1762 1649 if (d->selectionModel) 1763 d->ctrlDragSelectionFlag = QItemSelectionModel::NoUpdate; 1764 1765 if (d->selectionModel && d->noSelectionOnMousePress) { 1766 d->noSelectionOnMousePress = false; 1650 1767 d->selectionModel->select(index, selectionCommand(index, event)); 1768 } 1651 1769 1652 1770 setState(NoState); … … 1951 2069 Q_D(QAbstractItemView); 1952 2070 QAbstractScrollArea::focusInEvent(event); 1953 if (selectionModel() 2071 2072 const QItemSelectionModel* model = selectionModel(); 2073 const bool currentIndexValid = currentIndex().isValid(); 2074 2075 if (model 1954 2076 && !d->currentIndexSet 1955 && !currentIndex ().isValid()) {2077 && !currentIndexValid) { 1956 2078 bool autoScroll = d->autoScroll; 1957 2079 d->autoScroll = false; … … 1961 2083 d->autoScroll = autoScroll; 1962 2084 } 2085 2086 if (model && currentIndexValid) { 2087 if (currentIndex().flags() != Qt::ItemIsEditable) 2088 setAttribute(Qt::WA_InputMethodEnabled, false); 2089 else 2090 setAttribute(Qt::WA_InputMethodEnabled); 2091 } 2092 2093 if (!currentIndexValid) 2094 setAttribute(Qt::WA_InputMethodEnabled, false); 2095 1963 2096 d->viewport->update(); 1964 2097 } … … 1999 2132 if (!hasEditFocus()) { 2000 2133 setEditFocus(true); 2134 #ifdef QT_SOFTKEYS_ENABLED 2135 addAction(d->doneSoftKey); 2136 #endif 2001 2137 return; 2002 2138 } … … 2004 2140 break; 2005 2141 case Qt::Key_Back: 2006 if (QApplication::keypadNavigationEnabled() && hasEditFocus()) 2142 if (QApplication::keypadNavigationEnabled() && hasEditFocus()) { 2143 #ifdef QT_SOFTKEYS_ENABLED 2144 removeAction(d->doneSoftKey); 2145 #endif 2007 2146 setEditFocus(false); 2008 else2147 } else { 2009 2148 event->ignore(); 2149 } 2010 2150 return; 2011 2151 default: … … 2074 2214 if (command & QItemSelectionModel::Current) { 2075 2215 d->selectionModel->setCurrentIndex(newCurrent, QItemSelectionModel::NoUpdate); 2076 if ( d->pressedPosition == QPoint(-1, -1))2077 d->pressedPosition = visualRect(oldCurrent).center() ;2216 if (!indexAt(d->pressedPosition - d->offset()).isValid()) 2217 d->pressedPosition = visualRect(oldCurrent).center() + d->offset(); 2078 2218 QRect rect(d->pressedPosition - d->offset(), visualRect(newCurrent).center()); 2079 2219 setSelection(rect, command); … … 2081 2221 d->selectionModel->setCurrentIndex(newCurrent, command); 2082 2222 d->pressedPosition = visualRect(newCurrent).center() + d->offset(); 2223 // We copy the same behaviour as for mousePressEvent(). 2224 QRect rect(d->pressedPosition - d->offset(), QSize(1, 1)); 2225 setSelection(rect, command); 2083 2226 } 2084 2227 return; … … 2098 2241 case Qt::Key_Left: 2099 2242 case Qt::Key_Right: 2243 #ifdef QT_KEYPAD_NAVIGATION 2244 if (QApplication::navigationMode() == Qt::NavigationModeKeypadDirectional) { 2245 event->accept(); // don't change horizontal focus in directional mode 2246 break; 2247 } 2248 #endif // QT_KEYPAD_NAVIGATION 2100 2249 case Qt::Key_Home: 2101 2250 case Qt::Key_End: … … 2161 2310 #endif 2162 2311 bool modified = (event->modifiers() & (Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier)); 2163 if (!event->text().isEmpty() && !modified) { 2164 if (!edit(currentIndex(), AnyKeyPressed, event)) 2165 keyboardSearch(event->text()); 2166 } 2167 event->ignore(); 2312 if (!event->text().isEmpty() && !modified && !edit(currentIndex(), AnyKeyPressed, event)) { 2313 keyboardSearch(event->text()); 2314 event->accept(); 2315 } else { 2316 event->ignore(); 2317 } 2168 2318 break; } 2169 2319 } … … 2191 2341 { 2192 2342 Q_D(QAbstractItemView); 2193 if (event->timerId() == d->autoScrollTimer.timerId()) 2343 if (event->timerId() == d->fetchMoreTimer.timerId()) 2344 d->fetchMore(); 2345 else if (event->timerId() == d->delayedReset.timerId()) 2346 reset(); 2347 else if (event->timerId() == d->autoScrollTimer.timerId()) 2194 2348 doAutoScroll(); 2195 2349 else if (event->timerId() == d->updateTimer.timerId()) … … 2246 2400 2247 2401 \value OnViewport The item will be dropped onto a region of the viewport with 2248 no items. The way each view handles items dropped onto the viewport depends on2249 the behavior of the underlying model in use.2402 no items. The way each view handles items dropped onto the viewport depends on 2403 the behavior of the underlying model in use. 2250 2404 */ 2251 2405 … … 2264 2418 2265 2419 /*! 2266 This convenience function returns a list of all selected and2267 non-hidden item indexes in the view. The list contains no2268 duplicates, and is not sorted.2269 2270 \sa QItemSelectionModel::selectedIndexes()2420 This convenience function returns a list of all selected and 2421 non-hidden item indexes in the view. The list contains no 2422 duplicates, and is not sorted. 2423 2424 \sa QItemSelectionModel::selectedIndexes() 2271 2425 */ 2272 2426 QModelIndexList QAbstractItemView::selectedIndexes() const … … 2321 2475 2322 2476 if (d->sendDelegateEvent(index, event)) { 2323 d->viewport->update(visualRect(index));2477 update(index); 2324 2478 return true; 2325 2479 } … … 2350 2504 2351 2505 /*! 2352 \internal2353 Updates the data shown in the open editor widgets in the view.2506 \internal 2507 Updates the data shown in the open editor widgets in the view. 2354 2508 */ 2355 2509 void QAbstractItemView::updateEditorData() … … 2360 2514 2361 2515 /*! 2362 \internal2363 Updates the geometry of the open editor widgets in the view.2516 \internal 2517 Updates the geometry of the open editor widgets in the view. 2364 2518 */ 2365 2519 void QAbstractItemView::updateEditorGeometries() … … 2393 2547 //we release the editor outside of the loop because it might change the focus and try 2394 2548 //to change the d->editors list. 2395 for each(QWidget *editor, editorsToRelease) {2396 d->releaseEditor(editor );2549 for (int i = 0; i < editorsToRelease.count(); ++i) { 2550 d->releaseEditor(editorsToRelease.at(i)); 2397 2551 } 2398 2552 } … … 2406 2560 { 2407 2561 updateEditorGeometries(); 2408 QMetaObject::invokeMethod(this, "_q_fetchMore", Qt::QueuedConnection);2409 } 2410 2411 /*! 2412 \internal2562 d_func()->fetchMoreTimer.start(0, this); //fetch more later 2563 } 2564 2565 /*! 2566 \internal 2413 2567 */ 2414 2568 void QAbstractItemView::verticalScrollbarValueChanged(int value) … … 2417 2571 if (verticalScrollBar()->maximum() == value && d->model->canFetchMore(d->root)) 2418 2572 d->model->fetchMore(d->root); 2419 } 2420 2421 /*! 2422 \internal 2573 QPoint posInVp = viewport()->mapFromGlobal(QCursor::pos()); 2574 if (viewport()->rect().contains(posInVp)) 2575 d->checkMouseMove(posInVp); 2576 } 2577 2578 /*! 2579 \internal 2423 2580 */ 2424 2581 void QAbstractItemView::horizontalScrollbarValueChanged(int value) … … 2427 2584 if (horizontalScrollBar()->maximum() == value && d->model->canFetchMore(d->root)) 2428 2585 d->model->fetchMore(d->root); 2586 QPoint posInVp = viewport()->mapFromGlobal(QCursor::pos()); 2587 if (viewport()->rect().contains(posInVp)) 2588 d->checkMouseMove(posInVp); 2429 2589 } 2430 2590 … … 2521 2681 2522 2682 /*! 2523 Commit the data in the \a editor to the model.2524 2525 \sa closeEditor()2683 Commit the data in the \a editor to the model. 2684 2685 \sa closeEditor() 2526 2686 */ 2527 2687 void QAbstractItemView::commitData(QWidget *editor) … … 2542 2702 2543 2703 /*! 2544 This function is called when the given \a editor has been destroyed.2545 2546 \sa closeEditor()2704 This function is called when the given \a editor has been destroyed. 2705 2706 \sa closeEditor() 2547 2707 */ 2548 2708 void QAbstractItemView::editorDestroyed(QObject *editor) … … 2615 2775 2616 2776 /*! 2617 Moves to and selects the item best matching the string \a search.2618 If no item is found nothing happens.2619 2620 In the default implementation, the search is reset if \a search is empty, or2621 the time interval since the last search has exceeded2622 QApplication::keyboardInputInterval().2777 Moves to and selects the item best matching the string \a search. 2778 If no item is found nothing happens. 2779 2780 In the default implementation, the search is reset if \a search is empty, or 2781 the time interval since the last search has exceeded 2782 QApplication::keyboardInputInterval(). 2623 2783 */ 2624 2784 void QAbstractItemView::keyboardSearch(const QString &search) … … 2635 2795 || (d->keyboardInputTime.msecsTo(now) > QApplication::keyboardInputInterval())) { 2636 2796 d->keyboardInput = search; 2637 skipRow = true;2797 skipRow = currentIndex().isValid(); //if it is not valid we should really start at QModelIndex(0,0) 2638 2798 } else { 2639 2799 d->keyboardInput += search; … … 2662 2822 QModelIndexList match; 2663 2823 QModelIndex firstMatch; 2824 QModelIndex startMatch; 2664 2825 QModelIndexList previous; 2665 2826 do { … … 2674 2835 break; 2675 2836 } 2676 2677 2678 2837 int row = firstMatch.row() + 1; 2838 if (row >= d->model->rowCount(firstMatch.parent())) 2839 row = 0; 2679 2840 current = firstMatch.sibling(row, firstMatch.column()); 2841 2842 //avoid infinite loop if all the matching items are disabled. 2843 if (!startMatch.isValid()) 2844 startMatch = firstMatch; 2845 else if (startMatch == firstMatch) 2846 break; 2680 2847 } 2681 2848 } while (current != start && firstMatch.isValid()); … … 2718 2885 if (row < 0 || row >= d->model->rowCount() || !model()) 2719 2886 return -1; 2887 2888 ensurePolished(); 2720 2889 2721 2890 QStyleOptionViewItemV4 option = d->viewOptionsV4(); … … 2748 2917 return -1; 2749 2918 2919 ensurePolished(); 2920 2750 2921 QStyleOptionViewItemV4 option = d->viewOptionsV4(); 2751 2922 int width = 0; … … 2783 2954 2784 2955 /*! 2785 Closes the persistent editor for the item at the given \a index.2786 2787 \sa openPersistentEditor()2956 Closes the persistent editor for the item at the given \a index. 2957 2958 \sa openPersistentEditor() 2788 2959 */ 2789 2960 void QAbstractItemView::closePersistentEditor(const QModelIndex &index) … … 2840 3011 d->addEditor(index, widget, true); 2841 3012 widget->show(); 3013 dataChanged(index, index); // update the geometry 2842 3014 if (!d->delayedPendingLayout) 2843 3015 widget->setGeometry(visualRect(index)); 2844 dataChanged(index, index); // update the geometry2845 3016 } 2846 3017 } … … 2897 3068 { 2898 3069 Q_D(QAbstractItemView); 2899 if (index.isValid()) 2900 d->viewport->update(visualRect(index)); 3070 if (index.isValid()) { 3071 const QRect rect = visualRect(index); 3072 //this test is important for peformance reason 3073 //For example in dataChanged we simply update all the cells without checking 3074 //it can be a major bottleneck to update rects that aren't even part of the viewport 3075 if (d->viewport->rect().intersects(rect)) 3076 d->viewport->update(rect); 3077 } 2901 3078 } 2902 3079 … … 2922 3099 if (isVisible() && !d->delayedPendingLayout) { 2923 3100 // otherwise the items will be update later anyway 2924 d->viewport->update(visualRect(topLeft));3101 update(topLeft); 2925 3102 } 2926 3103 return; … … 2943 3120 { 2944 3121 if (!isVisible()) 2945 QMetaObject::invokeMethod(this, "_q_fetchMore", Qt::QueuedConnection);3122 d_func()->fetchMoreTimer.start(0, this); //fetch more later 2946 3123 else 2947 3124 updateEditorGeometries(); … … 3100 3277 void QAbstractItemViewPrivate::_q_modelDestroyed() 3101 3278 { 3102 Q_Q(QAbstractItemView);3103 3279 model = QAbstractItemModelPrivate::staticEmptyModel(); 3104 QMetaObject::invokeMethod(q, "reset", Qt::QueuedConnection);3280 doDelayedReset(); 3105 3281 } 3106 3282 … … 3127 3303 Q_D(QAbstractItemView); 3128 3304 if (isVisible() && updatesEnabled()) { 3129 d->setDirtyRegion(visualRegionForSelection(deselected)); 3130 d->setDirtyRegion(visualRegionForSelection(selected)); 3131 d->updateDirtyRegion(); 3305 d->viewport->update(visualRegionForSelection(deselected) | visualRegionForSelection(selected)); 3132 3306 } 3133 3307 } … … 3157 3331 } 3158 3332 if (isVisible()) { 3159 d->setDirtyRegion(visualRect(previous)); 3160 d->updateDirtyRegion(); 3161 } 3162 } 3163 if (isVisible() && current.isValid() && !d->autoScrollTimer.isActive()) { 3164 if (d->autoScroll) 3165 scrollTo(current); 3166 d->setDirtyRegion(visualRect(current)); 3167 d->updateDirtyRegion(); 3168 edit(current, CurrentChanged, 0); 3169 if (current.row() == (d->model->rowCount(d->root) - 1)) 3170 d->_q_fetchMore(); 3333 update(previous); 3334 } 3335 } 3336 3337 if (current.isValid() && !d->autoScrollTimer.isActive()) { 3338 if (isVisible()) { 3339 if (d->autoScroll) 3340 scrollTo(current); 3341 update(current); 3342 edit(current, CurrentChanged, 0); 3343 if (current.row() == (d->model->rowCount(d->root) - 1)) 3344 d->fetchMore(); 3345 } else { 3346 d->shouldScrollToCurrentOnShow = d->autoScroll; 3347 } 3171 3348 } 3172 3349 } … … 3192 3369 drag->setHotSpot(d->pressedPosition - rect.topLeft()); 3193 3370 Qt::DropAction defaultDropAction = Qt::IgnoreAction; 3194 if (supportedActions & Qt::CopyAction && dragDropMode() != QAbstractItemView::InternalMove) 3371 if (d->defaultDropAction != Qt::IgnoreAction && (supportedActions & d->defaultDropAction)) 3372 defaultDropAction = d->defaultDropAction; 3373 else if (supportedActions & Qt::CopyAction && dragDropMode() != QAbstractItemView::InternalMove) 3195 3374 defaultDropAction = Qt::CopyAction; 3196 3375 if (drag->exec(supportedActions, defaultDropAction) == Qt::MoveAction) … … 3212 3391 option.font = font(); 3213 3392 3214 #if def Q_WS_WIN3215 // Note this is currently required on Windows3216 // do give non-focused item views inactive appearance3393 #ifndef Q_WS_MAC 3394 // On mac the focus appearance follows window activation 3395 // not widget activation 3217 3396 if (!hasFocus()) 3218 3397 option.state &= ~QStyle::State_Active; … … 3313 3492 3314 3493 /*! 3315 Prepares the view for scrolling by (\a{dx},\a{dy}) pixels by moving the dirty regions in the3316 opposite direction. You only need to call this function if you are implementing a scrolling3317 viewport in your view subclass.3318 3319 If you implement scrollContentsBy() in a subclass of QAbstractItemView, call this function3320 before you call QWidget::scroll() on the viewport. Alternatively, just call update().3321 3322 \sa scrollContentsBy(), dirtyRegionOffset(), setDirtyRegion()3494 Prepares the view for scrolling by (\a{dx},\a{dy}) pixels by moving the dirty regions in the 3495 opposite direction. You only need to call this function if you are implementing a scrolling 3496 viewport in your view subclass. 3497 3498 If you implement scrollContentsBy() in a subclass of QAbstractItemView, call this function 3499 before you call QWidget::scroll() on the viewport. Alternatively, just call update(). 3500 3501 \sa scrollContentsBy(), dirtyRegionOffset(), setDirtyRegion() 3323 3502 */ 3324 3503 void QAbstractItemView::scrollDirtyRegion(int dx, int dy) … … 3329 3508 3330 3509 /*! 3331 Returns the offset of the dirty regions in the view.3332 3333 If you use scrollDirtyRegion() and implement a paintEvent() in a subclass of3334 QAbstractItemView, you should translate the area given by the paint event with3335 the offset returned from this function.3336 3337 \sa scrollDirtyRegion(), setDirtyRegion()3510 Returns the offset of the dirty regions in the view. 3511 3512 If you use scrollDirtyRegion() and implement a paintEvent() in a subclass of 3513 QAbstractItemView, you should translate the area given by the paint event with 3514 the offset returned from this function. 3515 3516 \sa scrollDirtyRegion(), setDirtyRegion() 3338 3517 */ 3339 3518 QPoint QAbstractItemView::dirtyRegionOffset() const … … 3348 3527 void QAbstractItemView::startAutoScroll() 3349 3528 { 3350 Q_D(QAbstractItemView); 3351 // ### it would be nice to make this into a style hint one day 3352 int scrollInterval = (verticalScrollMode() == QAbstractItemView::ScrollPerItem) ? 150 : 50; 3353 d->autoScrollTimer.start(scrollInterval, this); 3354 d->autoScrollCount = 0; 3529 d_func()->startAutoScroll(); 3355 3530 } 3356 3531 … … 3360 3535 void QAbstractItemView::stopAutoScroll() 3361 3536 { 3362 Q_D(QAbstractItemView); 3363 d->autoScrollTimer.stop(); 3364 d->autoScrollCount = 0; 3537 d_func()->stopAutoScroll(); 3365 3538 } 3366 3539 … … 3507 3680 const bool controlKeyPressed = modifiers & Qt::ControlModifier; 3508 3681 if (((index == pressedIndex && selectionModel->isSelected(index)) 3509 3510 && !shiftKeyPressed && !controlKeyPressed && !rightButtonPressed)3682 || !index.isValid()) && state != QAbstractItemView::DragSelectingState 3683 && !shiftKeyPressed && !controlKeyPressed && (!rightButtonPressed || !index.isValid())) 3511 3684 return QItemSelectionModel::ClearAndSelect|selectionBehaviorFlags(); 3512 3685 return QItemSelectionModel::NoUpdate; … … 3527 3700 case Qt::Key_PageDown: 3528 3701 case Qt::Key_Tab: 3702 if (modifiers & Qt::ControlModifier 3529 3703 #ifdef QT_KEYPAD_NAVIGATION 3530 return QItemSelectionModel::NoUpdate; 3531 #else 3532 if (modifiers & Qt::ControlModifier) 3704 // Preserve historical tab order navigation behavior 3705 || QApplication::navigationMode() == Qt::NavigationModeKeypadTabOrder 3706 #endif 3707 ) 3533 3708 return QItemSelectionModel::NoUpdate; 3534 #endif3535 3709 break; 3536 3710 case Qt::Key_Select: … … 3586 3760 } 3587 3761 3588 void QAbstractItemViewPrivate::_q_fetchMore() 3589 { 3762 void QAbstractItemViewPrivate::fetchMore() 3763 { 3764 fetchMoreTimer.stop(); 3590 3765 if (!model->canFetchMore(root)) 3591 3766 return; … … 3738 3913 3739 3914 Either remove the selected rows or clear them 3740 3915 */ 3741 3916 void QAbstractItemViewPrivate::clearOrRemove() 3742 3917 { … … 3774 3949 When persistent aeditor gets/loses focus, we need to check 3775 3950 and setcorrectly the current index. 3776 3951 */ 3777 3952 void QAbstractItemViewPrivate::checkPersistentEditorFocus() 3778 3953 { 3779 3954 Q_Q(QAbstractItemView); 3780 if (QWidget *widget = qApp->focusWidget()) {3955 if (QWidget *widget = QApplication::focusWidget()) { 3781 3956 if (persistent.contains(widget)) { 3782 3957 //a persistent editor has gained the focus … … 3860 4035 } 3861 4036 4037 /* 4038 \internal 4039 4040 returns the pair QRect/QModelIndex that should be painted on the viewports's rect 4041 */ 4042 4043 QItemViewPaintPairs QAbstractItemViewPrivate::draggablePaintPairs(const QModelIndexList &indexes, QRect *r) const 4044 { 4045 Q_ASSERT(r); 4046 Q_Q(const QAbstractItemView); 4047 QRect &rect = *r; 4048 const QRect viewportRect = viewport->rect(); 4049 QItemViewPaintPairs ret; 4050 for (int i = 0; i < indexes.count(); ++i) { 4051 const QModelIndex &index = indexes.at(i); 4052 const QRect current = q->visualRect(index); 4053 if (current.intersects(viewportRect)) { 4054 ret += qMakePair(current, index); 4055 rect |= current; 4056 } 4057 } 4058 rect &= viewportRect; 4059 return ret; 4060 } 4061 3862 4062 QPixmap QAbstractItemViewPrivate::renderToPixmap(const QModelIndexList &indexes, QRect *r) const 3863 4063 { 3864 Q_Q(const QAbstractItemView); 3865 QRect rect = q->visualRect(indexes.at(0)); 3866 QList<QRect> rects; 3867 for (int i = 0; i < indexes.count(); ++i) { 3868 rects.append(q->visualRect(indexes.at(i))); 3869 rect |= rects.at(i); 3870 } 3871 rect = rect.intersected(viewport->rect()); 3872 if (rect.width() <= 0 || rect.height() <= 0) 4064 Q_ASSERT(r); 4065 QItemViewPaintPairs paintPairs = draggablePaintPairs(indexes, r); 4066 if (paintPairs.isEmpty()) 3873 4067 return QPixmap(); 3874 Q Image image(rect.size(), QImage::Format_ARGB32_Premultiplied);3875 image.fill(0);3876 QPainter painter(& image);4068 QPixmap pixmap(r->size()); 4069 pixmap.fill(Qt::transparent); 4070 QPainter painter(&pixmap); 3877 4071 QStyleOptionViewItemV4 option = viewOptionsV4(); 3878 4072 option.state |= QStyle::State_Selected; 3879 for (int j = 0; j < indexes.count(); ++j) { 3880 option.rect = QRect(rects.at(j).topLeft() - rect.topLeft(), rects.at(j).size()); 3881 delegateForIndex(indexes.at(j))->paint(&painter, option, indexes.at(j)); 3882 } 3883 painter.end(); 3884 if (r) *r = rect; 3885 return QPixmap::fromImage(image); 4073 for (int j = 0; j < paintPairs.count(); ++j) { 4074 option.rect = paintPairs.at(j).first.translated(-r->topLeft()); 4075 const QModelIndex ¤t = paintPairs.at(j).second; 4076 delegateForIndex(current)->paint(&painter, option, current); 4077 } 4078 return pixmap; 3886 4079 } 3887 4080
Note:
See TracChangeset
for help on using the changeset viewer.