Ignore:
Timestamp:
Feb 11, 2010, 11:19:06 PM (15 years ago)
Author:
Dmitry A. Kuminov
Message:

trunk: Merged in qt 4.6.1 sources.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk

  • trunk/src/gui/itemviews/qabstractitemview.cpp

    r2 r561  
    22**
    33** 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)
    56**
    67** This file is part of the QtGui module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    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.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** 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.
    3838** $QT_END_LICENSE$
    3939**
     
    6262#include <qaccessible.h>
    6363#endif
     64#include <private/qsoftkeymanager_p.h>
    6465
    6566QT_BEGIN_NAMESPACE
     
    6970        itemDelegate(0),
    7071        selectionModel(0),
     72        ctrlDragSelectionFlag(QItemSelectionModel::NoUpdate),
     73        noSelectionOnMousePress(false),
    7174        selectionMode(QAbstractItemView::ExtendedSelection),
    7275        selectionBehavior(QAbstractItemView::SelectItems),
     
    7477        pressedModifiers(Qt::NoModifier),
    7578        pressedPosition(QPoint(-1, -1)),
     79        pressedAlreadySelected(false),
    7680        viewportEnteredNeeded(false),
    7781        state(QAbstractItemView::NoState),
     
    8589        overwrite(false),
    8690        dropIndicatorPosition(QAbstractItemView::OnItem),
     91        defaultDropAction(Qt::IgnoreAction),
     92#endif
     93#ifdef QT_SOFTKEYS_ENABLED
     94        doneSoftKey(0),
    8795#endif
    8896        autoScroll(true),
    8997        autoScrollMargin(16),
    9098        autoScrollCount(0),
     99        shouldScrollToCurrentOnShow(false),
     100        shouldClearStatusTip(false),
    91101        alternatingColors(false),
    92102        textElideMode(Qt::ElideRight),
     
    108118    q->setItemDelegate(new QStyledItemDelegate(q));
    109119
    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)),
    114124                     q, SLOT(verticalScrollbarAction(int)));
    115     QObject::connect(q->horizontalScrollBar(), SIGNAL(actionTriggered(int)),
     125    QObject::connect(hbar, SIGNAL(actionTriggered(int)),
    116126                     q, SLOT(horizontalScrollbarAction(int)));
    117     QObject::connect(q->verticalScrollBar(), SIGNAL(valueChanged(int)),
     127    QObject::connect(vbar, SIGNAL(valueChanged(int)),
    118128                     q, SLOT(verticalScrollbarValueChanged(int)));
    119     QObject::connect(q->horizontalScrollBar(), SIGNAL(valueChanged(int)),
     129    QObject::connect(hbar, SIGNAL(valueChanged(int)),
    120130                     q, SLOT(horizontalScrollbarValueChanged(int)));
    121131
     
    125135
    126136    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
     143void 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
     154void 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
    128186
    129187/*!
     
    134192
    135193    \ingroup model-view
    136     \mainclass
     194
    137195
    138196    QAbstractItemView class is the base class for every standard view
     
    143201    changes to their models.  This class provides standard support for
    144202    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.
    146242
    147243    The QAbstractItemView class is one of the \l{Model/View Classes}
     
    525621        disconnect(d->model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
    526622                   this, SLOT(dataChanged(QModelIndex,QModelIndex)));
     623        disconnect(d->model, SIGNAL(headerDataChanged(Qt::Orientation,int,int)),
     624                   this, SLOT(_q_headerDataChanged()));
    527625        disconnect(d->model, SIGNAL(rowsInserted(QModelIndex,int,int)),
    528626                   this, SLOT(rowsInserted(QModelIndex,int,int)));
     
    552650               "The parent of a top level index should be invalid");
    553651
    554     if (d->model && d->model != QAbstractItemModelPrivate::staticEmptyModel()) {
     652    if (d->model != QAbstractItemModelPrivate::staticEmptyModel()) {
    555653        connect(d->model, SIGNAL(destroyed()),
    556654                this, SLOT(_q_modelDestroyed()));
    557655        connect(d->model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
    558656                this, SLOT(dataChanged(QModelIndex,QModelIndex)));
     657        connect(d->model, SIGNAL(headerDataChanged(Qt::Orientation,int,int)),
     658                this, SLOT(_q_headerDataChanged()));
    559659        connect(d->model, SIGNAL(rowsInserted(QModelIndex,int,int)),
    560660                this, SLOT(rowsInserted(QModelIndex,int,int)));
     
    671771    }
    672772
    673 
    674773    if (delegate) {
    675774        if (d->delegateRefCount(delegate) == 0) {
     
    682781    }
    683782    d->itemDelegate = delegate;
     783    viewport()->update();
    684784}
    685785
     
    746846        d->rowDelegates.insert(row, delegate);
    747847    }
     848    viewport()->update();
    748849}
    749850
     
    802903        d->columnDelegates.insert(column, delegate);
    803904    }
     905    viewport()->update();
    804906}
    805907
     
    820922
    821923/*!
    822    Returns the item delegate used by this view and model for
    823    the given \a index.
     924    Returns the item delegate used by this view and model for
     925    the given \a index.
    824926*/
    825927QAbstractItemDelegate *QAbstractItemView::itemDelegate(const QModelIndex &index) const
     
    830932
    831933/*!
    832   \property QAbstractItemView::selectionMode
    833   \brief which selection mode the view operates in
    834 
    835   This property controls whether the user can select one or many items
    836   and, in many-item selections, whether the selection must be a
    837   continuous range of items.
    838 
    839   \sa SelectionMode SelectionBehavior
     934    \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
    840942*/
    841943void QAbstractItemView::setSelectionMode(SelectionMode mode)
     
    852954
    853955/*!
    854   \property QAbstractItemView::selectionBehavior
    855   \brief which selection behavior the view uses
    856 
    857   This property holds whether selections are done
    858   in terms of single items, rows or columns.
    859 
    860   \sa SelectionMode SelectionBehavior
     956    \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
    861963*/
    862964
     
    875977/*!
    876978    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.
    878982    Note that this function also updates the starting position for any
    879983    new selections the user performs.
     
    9211025{
    9221026    Q_D(QAbstractItemView);
     1027    d->delayedReset.stop(); //make sure we stop the timer
    9231028    QList<QEditorInfo>::const_iterator it = d->editors.constBegin();
    9241029    for (; it != d->editors.constEnd(); ++it)
     
    9291034    setState(NoState);
    9301035    setRootIndex(QModelIndex());
     1036    if (d->selectionModel)
     1037        d->selectionModel->reset();
    9311038}
    9321039
     
    9591066
    9601067/*!
    961   Selects all item in the view.
    962   This function wil use the selection selection behavior
    963   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()
    9661073*/
    9671074void QAbstractItemView::selectAll()
     
    11921299#ifndef QT_NO_DRAGANDDROP
    11931300/*!
    1194   \property QAbstractItemView::showDropIndicator
    1195   \brief whether the drop indicator is shown when dragging items and dropping.
    1196 
    1197   \sa dragEnabled DragDropMode dragDropOverwriteMode acceptDrops
     1301    \property QAbstractItemView::showDropIndicator
     1302    \brief whether the drop indicator is shown when dragging items and dropping.
     1303
     1304    \sa dragEnabled DragDropMode dragDropOverwriteMode acceptDrops
    11981305*/
    11991306
     
    12111318
    12121319/*!
    1213   \property QAbstractItemView::dragEnabled
    1214   \brief whether the view supports dragging of its own items
    1215 
    1216   \sa showDropIndicator DragDropMode dragDropOverwriteMode acceptDrops
     1320    \property QAbstractItemView::dragEnabled
     1321    \brief whether the view supports dragging of its own items
     1322
     1323    \sa showDropIndicator DragDropMode dragDropOverwriteMode acceptDrops
    12171324*/
    12181325
     
    12501357
    12511358/*!
    1252   \property QAbstractItemView::dragDropMode
    1253   \brief the drag and drop event the view will act upon
    1254 
    1255   \since 4.2
    1256   \sa showDropIndicator dragDropOverwriteMode
     1359    \property QAbstractItemView::dragDropMode
     1360    \brief the drag and drop event the view will act upon
     1361
     1362    \since 4.2
     1363    \sa showDropIndicator dragDropOverwriteMode
    12571364*/
    12581365void QAbstractItemView::setDragDropMode(DragDropMode behavior)
     
    12871394}
    12881395
     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*/
     1406void QAbstractItemView::setDefaultDropAction(Qt::DropAction dropAction)
     1407{
     1408    Q_D(QAbstractItemView);
     1409    d->defaultDropAction = dropAction;
     1410}
     1411
     1412Qt::DropAction QAbstractItemView::defaultDropAction() const
     1413{
     1414    Q_D(const QAbstractItemView);
     1415    return d->defaultDropAction;
     1416}
     1417
    12891418#endif // QT_NO_DRAGANDDROP
    12901419
    12911420/*!
    1292   \property QAbstractItemView::alternatingRowColors
    1293   \brief whether to draw the background using alternating colors
    1294 
    1295   If this property is true, the item background will be drawn using
    1296   QPalette::Base and QPalette::AlternateBase; otherwise the background
    1297   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.
    13001429*/
    13011430void QAbstractItemView::setAlternatingRowColors(bool enable)
     
    13381467    \property QAbstractItemView::textElideMode
    13391468
    1340     \brief the the position of the "..." in elided text.
     1469    \brief the position of the "..." in elided text.
    13411470
    13421471    The default value for all item views is Qt::ElideRight.
     
    13811510        break;
    13821511    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;
    13851515            const QModelIndex current = currentIndex();
    13861516            if (current.isValid() && (d->state == QAbstractItemView::EditingState || d->autoScroll))
     
    14011531        d->checkPersistentEditorFocus();
    14021532        break;
     1533    case QEvent::FontChange:
     1534        d->doDelayedItemsLayout(); // the size of the items will change
     1535        break;
    14031536    default:
    14041537        break;
     
    14191552    Q_D(QAbstractItemView);
    14201553    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;
    14371561    case QEvent::Enter:
    14381562        d->viewportEnteredNeeded = true;
    14391563        break;
    14401564    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
    14411573        d->enteredIndex = QModelIndex();
    14421574        break;
     
    14921624    d->pressedModifiers = event->modifiers();
    14931625    QItemSelectionModel::SelectionFlags command = selectionCommand(index, event);
     1626    d->noSelectionOnMousePress = command == QItemSelectionModel::NoUpdate || !index.isValid();
    14941627    QPoint offset = d->offset();
    14951628    if ((command & QItemSelectionModel::Current) == 0)
    14961629        d->pressedPosition = pos + offset;
    1497 
    1498     if (d->pressedPosition == QPoint(-1, -1))
     1630    else if (!indexAt(d->pressedPosition - offset).isValid())
    14991631        d->pressedPosition = visualRect(currentIndex()).center() + offset;
    15001632
     
    15101642        d->autoScroll = autoScroll;
    15111643        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        }
    15121649        setSelection(rect, command);
    15131650
     
    15531690#endif // QT_NO_DRAGANDDROP
    15541691
    1555     QModelIndex index = indexAt(bottomRight);
     1692    QPersistentModelIndex index = indexAt(bottomRight);
    15561693    QModelIndex buddy = d->model->buddy(d->pressedIndex);
    15571694    if ((state() == EditingState && d->hasEditor(buddy))
     
    15641701        topLeft = bottomRight;
    15651702
    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);
    15931704
    15941705#ifndef QT_NO_DRAGANDDROP
    1595     if (index.isValid()
     1706    if (d->pressedIndex.isValid()
    15961707        && d->dragEnabled
    15971708        && (state() != DragSelectingState)
     
    16061717        setState(DragSelectingState);
    16071718        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        }
    16081723
    16091724        // Do the normalize ourselves, since QRect::normalized() is flawed
    16101725        QRect selectionRect = QRect(topLeft, bottomRight);
    1611         QPersistentModelIndex persistent = index;
    16121726        setSelection(selectionRect, command);
    16131727
    16141728        // 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);
    16191733    }
    16201734}
     
    16381752            && d->isIndexEnabled(index)
    16391753            && d->sendDelegateEvent(index, event))
    1640             d->viewport->update(visualRect(index));
     1754            update(index);
    16411755        return;
    16421756    }
     
    16471761    bool edited = edit(index, trigger, event);
    16481762
    1649     if (d->selectionModel)
     1763    d->ctrlDragSelectionFlag = QItemSelectionModel::NoUpdate;
     1764
     1765    if (d->selectionModel && d->noSelectionOnMousePress) {
     1766        d->noSelectionOnMousePress = false;
    16501767        d->selectionModel->select(index, selectionCommand(index, event));
     1768    }
    16511769
    16521770    setState(NoState);
     
    19512069    Q_D(QAbstractItemView);
    19522070    QAbstractScrollArea::focusInEvent(event);
    1953     if (selectionModel()
     2071
     2072    const QItemSelectionModel* model = selectionModel();
     2073    const bool currentIndexValid = currentIndex().isValid();
     2074
     2075    if (model
    19542076        && !d->currentIndexSet
    1955         && !currentIndex().isValid()) {
     2077        && !currentIndexValid) {
    19562078        bool autoScroll = d->autoScroll;
    19572079        d->autoScroll = false;
     
    19612083        d->autoScroll = autoScroll;
    19622084    }
     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
    19632096    d->viewport->update();
    19642097}
     
    19992132            if (!hasEditFocus()) {
    20002133                setEditFocus(true);
     2134#ifdef QT_SOFTKEYS_ENABLED
     2135                addAction(d->doneSoftKey);
     2136#endif
    20012137                return;
    20022138            }
     
    20042140        break;
    20052141    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
    20072146            setEditFocus(false);
    2008         else
     2147        } else {
    20092148            event->ignore();
     2149        }
    20102150        return;
    20112151    default:
     
    20742214            if (command & QItemSelectionModel::Current) {
    20752215                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();
    20782218                QRect rect(d->pressedPosition - d->offset(), visualRect(newCurrent).center());
    20792219                setSelection(rect, command);
     
    20812221                d->selectionModel->setCurrentIndex(newCurrent, command);
    20822222                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);
    20832226            }
    20842227            return;
     
    20982241    case Qt::Key_Left:
    20992242    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
    21002249    case Qt::Key_Home:
    21012250    case Qt::Key_End:
     
    21612310#endif
    21622311        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        }
    21682318        break; }
    21692319    }
     
    21912341{
    21922342    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())
    21942348        doAutoScroll();
    21952349    else if (event->timerId() == d->updateTimer.timerId())
     
    22462400
    22472401    \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 on
    2249 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.
    22502404*/
    22512405
     
    22642418
    22652419/*!
    2266   This convenience function returns a list of all selected and
    2267   non-hidden item indexes in the view. The list contains no
    2268   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()
    22712425*/
    22722426QModelIndexList QAbstractItemView::selectedIndexes() const
     
    23212475
    23222476    if (d->sendDelegateEvent(index, event)) {
    2323         d->viewport->update(visualRect(index));
     2477        update(index);
    23242478        return true;
    23252479    }
     
    23502504
    23512505/*!
    2352   \internal
    2353   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.
    23542508*/
    23552509void QAbstractItemView::updateEditorData()
     
    23602514
    23612515/*!
    2362   \internal
    2363    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.
    23642518*/
    23652519void QAbstractItemView::updateEditorGeometries()
     
    23932547    //we release the editor outside of the loop because it might change the focus and try
    23942548    //to change the d->editors list.
    2395     foreach(QWidget *editor, editorsToRelease) {
    2396         d->releaseEditor(editor);
     2549    for (int i = 0; i < editorsToRelease.count(); ++i) {
     2550        d->releaseEditor(editorsToRelease.at(i));
    23972551    }
    23982552}
     
    24062560{
    24072561    updateEditorGeometries();
    2408     QMetaObject::invokeMethod(this, "_q_fetchMore", Qt::QueuedConnection);
    2409 }
    2410 
    2411 /*!
    2412   \internal
     2562    d_func()->fetchMoreTimer.start(0, this); //fetch more later
     2563}
     2564
     2565/*!
     2566    \internal
    24132567*/
    24142568void QAbstractItemView::verticalScrollbarValueChanged(int value)
     
    24172571    if (verticalScrollBar()->maximum() == value && d->model->canFetchMore(d->root))
    24182572        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
    24232580*/
    24242581void QAbstractItemView::horizontalScrollbarValueChanged(int value)
     
    24272584    if (horizontalScrollBar()->maximum() == value && d->model->canFetchMore(d->root))
    24282585        d->model->fetchMore(d->root);
     2586    QPoint posInVp = viewport()->mapFromGlobal(QCursor::pos());
     2587    if (viewport()->rect().contains(posInVp))
     2588        d->checkMouseMove(posInVp);
    24292589}
    24302590
     
    25212681
    25222682/*!
    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()
    25262686*/
    25272687void QAbstractItemView::commitData(QWidget *editor)
     
    25422702
    25432703/*!
    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()
    25472707*/
    25482708void QAbstractItemView::editorDestroyed(QObject *editor)
     
    26152775
    26162776/*!
    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, or
    2621   the time interval since the last search has exceeded
    2622   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().
    26232783*/
    26242784void QAbstractItemView::keyboardSearch(const QString &search)
     
    26352795        || (d->keyboardInputTime.msecsTo(now) > QApplication::keyboardInputInterval())) {
    26362796        d->keyboardInput = search;
    2637         skipRow = true;
     2797        skipRow = currentIndex().isValid(); //if it is not valid we should really start at QModelIndex(0,0)
    26382798    } else {
    26392799        d->keyboardInput += search;
     
    26622822    QModelIndexList match;
    26632823    QModelIndex firstMatch;
     2824    QModelIndex startMatch;
    26642825    QModelIndexList previous;
    26652826    do {
     
    26742835                break;
    26752836            }
    2676             int row = firstMatch.row() + 1;
    2677             if (row >= d->model->rowCount(firstMatch.parent()))
    2678                 row = 0;
     2837            int row = firstMatch.row() + 1;
     2838            if (row >= d->model->rowCount(firstMatch.parent()))
     2839                row = 0;
    26792840            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;
    26802847        }
    26812848    } while (current != start && firstMatch.isValid());
     
    27182885    if (row < 0 || row >= d->model->rowCount() || !model())
    27192886        return -1;
     2887
     2888    ensurePolished();
    27202889
    27212890    QStyleOptionViewItemV4 option = d->viewOptionsV4();
     
    27482917        return -1;
    27492918
     2919    ensurePolished();
     2920
    27502921    QStyleOptionViewItemV4 option = d->viewOptionsV4();
    27512922    int width = 0;
     
    27832954
    27842955/*!
    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()
    27882959*/
    27892960void QAbstractItemView::closePersistentEditor(const QModelIndex &index)
     
    28403011        d->addEditor(index, widget, true);
    28413012        widget->show();
     3013        dataChanged(index, index); // update the geometry
    28423014        if (!d->delayedPendingLayout)
    28433015            widget->setGeometry(visualRect(index));
    2844         dataChanged(index, index); // update the geometry
    28453016    }
    28463017}
     
    28973068{
    28983069    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    }
    29013078}
    29023079
     
    29223099        if (isVisible() && !d->delayedPendingLayout) {
    29233100            // otherwise the items will be update later anyway
    2924             d->viewport->update(visualRect(topLeft));
     3101            update(topLeft);
    29253102        }
    29263103        return;
     
    29433120{
    29443121    if (!isVisible())
    2945         QMetaObject::invokeMethod(this, "_q_fetchMore", Qt::QueuedConnection);
     3122        d_func()->fetchMoreTimer.start(0, this); //fetch more later
    29463123    else
    29473124        updateEditorGeometries();
     
    31003277void QAbstractItemViewPrivate::_q_modelDestroyed()
    31013278{
    3102     Q_Q(QAbstractItemView);
    31033279    model = QAbstractItemModelPrivate::staticEmptyModel();
    3104     QMetaObject::invokeMethod(q, "reset", Qt::QueuedConnection);
     3280    doDelayedReset();
    31053281}
    31063282
     
    31273303    Q_D(QAbstractItemView);
    31283304    if (isVisible() && updatesEnabled()) {
    3129         d->setDirtyRegion(visualRegionForSelection(deselected));
    3130         d->setDirtyRegion(visualRegionForSelection(selected));
    3131         d->updateDirtyRegion();
     3305        d->viewport->update(visualRegionForSelection(deselected) | visualRegionForSelection(selected));
    31323306    }
    31333307}
     
    31573331        }
    31583332        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        }
    31713348    }
    31723349}
     
    31923369        drag->setHotSpot(d->pressedPosition - rect.topLeft());
    31933370        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)
    31953374            defaultDropAction = Qt::CopyAction;
    31963375        if (drag->exec(supportedActions, defaultDropAction) == Qt::MoveAction)
     
    32123391    option.font = font();
    32133392
    3214 #ifdef Q_WS_WIN
    3215     // Note this is currently required on Windows
    3216     // do give non-focused item views inactive appearance
     3393#ifndef Q_WS_MAC
     3394    // On mac the focus appearance follows window activation
     3395    // not widget activation
    32173396    if (!hasFocus())
    32183397        option.state &= ~QStyle::State_Active;
     
    33133492
    33143493/*!
    3315   Prepares the view for scrolling by (\a{dx},\a{dy}) pixels by moving the dirty regions in the
    3316   opposite direction. You only need to call this function if you are implementing a scrolling
    3317   viewport in your view subclass.
    3318 
    3319   If you implement scrollContentsBy() in a subclass of QAbstractItemView, call this function
    3320   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()
    33233502*/
    33243503void QAbstractItemView::scrollDirtyRegion(int dx, int dy)
     
    33293508
    33303509/*!
    3331   Returns the offset of the dirty regions in the view.
    3332 
    3333   If you use scrollDirtyRegion() and implement a paintEvent() in a subclass of
    3334   QAbstractItemView, you should translate the area given by the paint event with
    3335   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()
    33383517*/
    33393518QPoint QAbstractItemView::dirtyRegionOffset() const
     
    33483527void QAbstractItemView::startAutoScroll()
    33493528{
    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();
    33553530}
    33563531
     
    33603535void QAbstractItemView::stopAutoScroll()
    33613536{
    3362     Q_D(QAbstractItemView);
    3363     d->autoScrollTimer.stop();
    3364     d->autoScrollCount = 0;
     3537    d_func()->stopAutoScroll();
    33653538}
    33663539
     
    35073680            const bool controlKeyPressed = modifiers & Qt::ControlModifier;
    35083681            if (((index == pressedIndex && selectionModel->isSelected(index))
    3509                 || !index.isValid()) && state != QAbstractItemView::DragSelectingState
    3510                 && !shiftKeyPressed && !controlKeyPressed && !rightButtonPressed)
     3682                || !index.isValid()) && state != QAbstractItemView::DragSelectingState
     3683                && !shiftKeyPressed && !controlKeyPressed && (!rightButtonPressed || !index.isValid()))
    35113684                return QItemSelectionModel::ClearAndSelect|selectionBehaviorFlags();
    35123685            return QItemSelectionModel::NoUpdate;
     
    35273700            case Qt::Key_PageDown:
    35283701            case Qt::Key_Tab:
     3702                if (modifiers & Qt::ControlModifier
    35293703#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                    )
    35333708                    return QItemSelectionModel::NoUpdate;
    3534 #endif
    35353709                break;
    35363710            case Qt::Key_Select:
     
    35863760}
    35873761
    3588 void QAbstractItemViewPrivate::_q_fetchMore()
    3589 {
     3762void QAbstractItemViewPrivate::fetchMore()
     3763{
     3764    fetchMoreTimer.stop();
    35903765    if (!model->canFetchMore(root))
    35913766        return;
     
    37383913
    37393914    Either remove the selected rows or clear them
    3740   */
     3915*/
    37413916void QAbstractItemViewPrivate::clearOrRemove()
    37423917{
     
    37743949    When persistent aeditor gets/loses focus, we need to check
    37753950    and setcorrectly the current index.
    3776   */
     3951*/
    37773952void QAbstractItemViewPrivate::checkPersistentEditorFocus()
    37783953{
    37793954    Q_Q(QAbstractItemView);
    3780     if (QWidget *widget = qApp->focusWidget()) {
     3955    if (QWidget *widget = QApplication::focusWidget()) {
    37813956        if (persistent.contains(widget)) {
    37823957            //a persistent editor has gained the focus
     
    38604035}
    38614036
     4037/*
     4038    \internal
     4039
     4040    returns the pair QRect/QModelIndex that should be painted on the viewports's rect
     4041*/
     4042
     4043QItemViewPaintPairs 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
    38624062QPixmap QAbstractItemViewPrivate::renderToPixmap(const QModelIndexList &indexes, QRect *r) const
    38634063{
    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())
    38734067        return QPixmap();
    3874     QImage 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);
    38774071    QStyleOptionViewItemV4 option = viewOptionsV4();
    38784072    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 &current = paintPairs.at(j).second;
     4076        delegateForIndex(current)->paint(&painter, option, current);
     4077    }
     4078    return pixmap;
    38864079}
    38874080
Note: See TracChangeset for help on using the changeset viewer.