src/gui/itemviews/qabstractitemview.cpp
changeset 3 41300fa6a67c
parent 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
2:56cd8111b7f7 3:41300fa6a67c
    68 QAbstractItemViewPrivate::QAbstractItemViewPrivate()
    68 QAbstractItemViewPrivate::QAbstractItemViewPrivate()
    69     :   model(QAbstractItemModelPrivate::staticEmptyModel()),
    69     :   model(QAbstractItemModelPrivate::staticEmptyModel()),
    70         itemDelegate(0),
    70         itemDelegate(0),
    71         selectionModel(0),
    71         selectionModel(0),
    72         ctrlDragSelectionFlag(QItemSelectionModel::NoUpdate),
    72         ctrlDragSelectionFlag(QItemSelectionModel::NoUpdate),
       
    73         noSelectionOnMousePress(false),
    73         selectionMode(QAbstractItemView::ExtendedSelection),
    74         selectionMode(QAbstractItemView::ExtendedSelection),
    74         selectionBehavior(QAbstractItemView::SelectItems),
    75         selectionBehavior(QAbstractItemView::SelectItems),
    75         currentlyCommittingEditor(0),
    76         currentlyCommittingEditor(0),
    76         pressedModifiers(Qt::NoModifier),
    77         pressedModifiers(Qt::NoModifier),
    77         pressedPosition(QPoint(-1, -1)),
    78         pressedPosition(QPoint(-1, -1)),
    94 #endif
    95 #endif
    95         autoScroll(true),
    96         autoScroll(true),
    96         autoScrollMargin(16),
    97         autoScrollMargin(16),
    97         autoScrollCount(0),
    98         autoScrollCount(0),
    98         shouldScrollToCurrentOnShow(false),
    99         shouldScrollToCurrentOnShow(false),
       
   100         shouldClearStatusTip(false),
    99         alternatingColors(false),
   101         alternatingColors(false),
   100         textElideMode(Qt::ElideRight),
   102         textElideMode(Qt::ElideRight),
   101         verticalScrollMode(QAbstractItemView::ScrollPerItem),
   103         verticalScrollMode(QAbstractItemView::ScrollPerItem),
   102         horizontalScrollMode(QAbstractItemView::ScrollPerItem),
   104         horizontalScrollMode(QAbstractItemView::ScrollPerItem),
   103         currentIndexSet(false),
   105         currentIndexSet(false),
   136 #ifdef QT_SOFTKEYS_ENABLED
   138 #ifdef QT_SOFTKEYS_ENABLED
   137     doneSoftKey = QSoftKeyManager::createKeyedAction(QSoftKeyManager::DoneSoftKey, Qt::Key_Back, q);
   139     doneSoftKey = QSoftKeyManager::createKeyedAction(QSoftKeyManager::DoneSoftKey, Qt::Key_Back, q);
   138 #endif
   140 #endif
   139 }
   141 }
   140 
   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 
   141 void QAbstractItemViewPrivate::checkMouseMove(const QPersistentModelIndex &index)
   154 void QAbstractItemViewPrivate::checkMouseMove(const QPersistentModelIndex &index)
   142 {
   155 {
   143     //we take a persistent model index because the model might change by emitting signals
   156     //we take a persistent model index because the model might change by emitting signals
   144     Q_Q(QAbstractItemView);
   157     Q_Q(QAbstractItemView);
       
   158     setHoverIndex(index);
   145     if (viewportEnteredNeeded || enteredIndex != index) {
   159     if (viewportEnteredNeeded || enteredIndex != index) {
   146         viewportEnteredNeeded = false;
   160         viewportEnteredNeeded = false;
   147 
   161 
   148         if (index.isValid()) {
   162         if (index.isValid()) {
   149             emit q->entered(index);
   163             emit q->entered(index);
   150 #ifndef QT_NO_STATUSTIP
   164 #ifndef QT_NO_STATUSTIP
   151             QString statustip = model->data(index, Qt::StatusTipRole).toString();
   165             QString statustip = model->data(index, Qt::StatusTipRole).toString();
   152             if (parent && !statustip.isEmpty()) {
   166             if (parent && (shouldClearStatusTip || !statustip.isEmpty())) {
   153                 QStatusTipEvent tip(statustip);
   167                 QStatusTipEvent tip(statustip);
   154                 QApplication::sendEvent(parent, &tip);
   168                 QApplication::sendEvent(parent, &tip);
       
   169                 shouldClearStatusTip = !statustip.isEmpty();
   155             }
   170             }
   156 #endif
   171 #endif
   157         } else {
   172         } else {
   158 #ifndef QT_NO_STATUSTIP
   173 #ifndef QT_NO_STATUSTIP
   159             if (parent) {
   174             if (parent && shouldClearStatusTip) {
   160                 QString emptyString;
   175                 QString emptyString;
   161                 QStatusTipEvent tip( emptyString );
   176                 QStatusTipEvent tip( emptyString );
   162                 QApplication::sendEvent(parent, &tip);
   177                 QApplication::sendEvent(parent, &tip);
   163             }
   178             }
   164 #endif
   179 #endif
   603     if (d->model && d->model != QAbstractItemModelPrivate::staticEmptyModel()) {
   618     if (d->model && d->model != QAbstractItemModelPrivate::staticEmptyModel()) {
   604         disconnect(d->model, SIGNAL(destroyed()),
   619         disconnect(d->model, SIGNAL(destroyed()),
   605                    this, SLOT(_q_modelDestroyed()));
   620                    this, SLOT(_q_modelDestroyed()));
   606         disconnect(d->model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
   621         disconnect(d->model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
   607                    this, SLOT(dataChanged(QModelIndex,QModelIndex)));
   622                    this, SLOT(dataChanged(QModelIndex,QModelIndex)));
       
   623         disconnect(d->model, SIGNAL(headerDataChanged(Qt::Orientation,int,int)),
       
   624                    this, SLOT(_q_headerDataChanged()));
   608         disconnect(d->model, SIGNAL(rowsInserted(QModelIndex,int,int)),
   625         disconnect(d->model, SIGNAL(rowsInserted(QModelIndex,int,int)),
   609                    this, SLOT(rowsInserted(QModelIndex,int,int)));
   626                    this, SLOT(rowsInserted(QModelIndex,int,int)));
   610         disconnect(d->model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
   627         disconnect(d->model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
   611                    this, SLOT(rowsAboutToBeRemoved(QModelIndex,int,int)));
   628                    this, SLOT(rowsAboutToBeRemoved(QModelIndex,int,int)));
   612         disconnect(d->model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
   629         disconnect(d->model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
   635     if (d->model != QAbstractItemModelPrivate::staticEmptyModel()) {
   652     if (d->model != QAbstractItemModelPrivate::staticEmptyModel()) {
   636         connect(d->model, SIGNAL(destroyed()),
   653         connect(d->model, SIGNAL(destroyed()),
   637                 this, SLOT(_q_modelDestroyed()));
   654                 this, SLOT(_q_modelDestroyed()));
   638         connect(d->model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
   655         connect(d->model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
   639                 this, SLOT(dataChanged(QModelIndex,QModelIndex)));
   656                 this, SLOT(dataChanged(QModelIndex,QModelIndex)));
       
   657         connect(d->model, SIGNAL(headerDataChanged(Qt::Orientation,int,int)),
       
   658                 this, SLOT(_q_headerDataChanged()));
   640         connect(d->model, SIGNAL(rowsInserted(QModelIndex,int,int)),
   659         connect(d->model, SIGNAL(rowsInserted(QModelIndex,int,int)),
   641                 this, SLOT(rowsInserted(QModelIndex,int,int)));
   660                 this, SLOT(rowsInserted(QModelIndex,int,int)));
   642         connect(d->model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
   661         connect(d->model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
   643                 this, SLOT(rowsAboutToBeRemoved(QModelIndex,int,int)));
   662                 this, SLOT(rowsAboutToBeRemoved(QModelIndex,int,int)));
   644         connect(d->model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
   663         connect(d->model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
  1530 */
  1549 */
  1531 bool QAbstractItemView::viewportEvent(QEvent *event)
  1550 bool QAbstractItemView::viewportEvent(QEvent *event)
  1532 {
  1551 {
  1533     Q_D(QAbstractItemView);
  1552     Q_D(QAbstractItemView);
  1534     switch (event->type()) {
  1553     switch (event->type()) {
  1535     case QEvent::HoverEnter: {
  1554     case QEvent::HoverMove:
  1536         QHoverEvent *he = static_cast<QHoverEvent*>(event);
  1555     case QEvent::HoverEnter:
  1537         d->hover = indexAt(he->pos());
  1556         d->setHoverIndex(indexAt(static_cast<QHoverEvent*>(event)->pos()));
  1538         update(d->hover);
  1557         break;
  1539         break; }
  1558     case QEvent::HoverLeave:
  1540     case QEvent::HoverLeave: {
  1559         d->setHoverIndex(QModelIndex());
  1541         update(d->hover); // update old
  1560         break;
  1542         d->hover = QModelIndex();
       
  1543         break; }
       
  1544     case QEvent::HoverMove: {
       
  1545         QHoverEvent *he = static_cast<QHoverEvent*>(event);
       
  1546         QModelIndex old = d->hover;
       
  1547         d->hover = indexAt(he->pos());
       
  1548         if (d->hover != old)
       
  1549             d->viewport->update(visualRect(old)|visualRect(d->hover));
       
  1550         break; }
       
  1551     case QEvent::Enter:
  1561     case QEvent::Enter:
  1552         d->viewportEnteredNeeded = true;
  1562         d->viewportEnteredNeeded = true;
  1553         break;
  1563         break;
  1554     case QEvent::Leave:
  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
  1555         d->enteredIndex = QModelIndex();
  1573         d->enteredIndex = QModelIndex();
  1556         break;
  1574         break;
  1557     case QEvent::ToolTip:
  1575     case QEvent::ToolTip:
  1558     case QEvent::QueryWhatsThis:
  1576     case QEvent::QueryWhatsThis:
  1559     case QEvent::WhatsThis: {
  1577     case QEvent::WhatsThis: {
  1603 
  1621 
  1604     d->pressedAlreadySelected = d->selectionModel->isSelected(index);
  1622     d->pressedAlreadySelected = d->selectionModel->isSelected(index);
  1605     d->pressedIndex = index;
  1623     d->pressedIndex = index;
  1606     d->pressedModifiers = event->modifiers();
  1624     d->pressedModifiers = event->modifiers();
  1607     QItemSelectionModel::SelectionFlags command = selectionCommand(index, event);
  1625     QItemSelectionModel::SelectionFlags command = selectionCommand(index, event);
       
  1626     d->noSelectionOnMousePress = command == QItemSelectionModel::NoUpdate || !index.isValid();
  1608     QPoint offset = d->offset();
  1627     QPoint offset = d->offset();
  1609     if ((command & QItemSelectionModel::Current) == 0)
  1628     if ((command & QItemSelectionModel::Current) == 0)
  1610         d->pressedPosition = pos + offset;
  1629         d->pressedPosition = pos + offset;
  1611     else if (!indexAt(d->pressedPosition).isValid())
  1630     else if (!indexAt(d->pressedPosition - offset).isValid())
  1612         d->pressedPosition = visualRect(currentIndex()).center() + offset;
  1631         d->pressedPosition = visualRect(currentIndex()).center() + offset;
  1613 
  1632 
  1614     if (edit(index, NoEditTriggers, event))
  1633     if (edit(index, NoEditTriggers, event))
  1615         return;
  1634         return;
  1616 
  1635 
  1741     EditTrigger trigger = (selectedClicked ? SelectedClicked : NoEditTriggers);
  1760     EditTrigger trigger = (selectedClicked ? SelectedClicked : NoEditTriggers);
  1742     bool edited = edit(index, trigger, event);
  1761     bool edited = edit(index, trigger, event);
  1743 
  1762 
  1744     d->ctrlDragSelectionFlag = QItemSelectionModel::NoUpdate;
  1763     d->ctrlDragSelectionFlag = QItemSelectionModel::NoUpdate;
  1745 
  1764 
  1746     //in the case the user presses on no item we might decide to clear the selection
  1765     if (d->selectionModel && d->noSelectionOnMousePress) {
  1747     if (d->selectionModel && !index.isValid())
  1766         d->noSelectionOnMousePress = false;
  1748         d->selectionModel->select(QModelIndex(), selectionCommand(index, event));
  1767         d->selectionModel->select(index, selectionCommand(index, event));
       
  1768     }
  1749 
  1769 
  1750     setState(NoState);
  1770     setState(NoState);
  1751 
  1771 
  1752     if (click) {
  1772     if (click) {
  1753         emit clicked(index);
  1773         emit clicked(index);
  2046 */
  2066 */
  2047 void QAbstractItemView::focusInEvent(QFocusEvent *event)
  2067 void QAbstractItemView::focusInEvent(QFocusEvent *event)
  2048 {
  2068 {
  2049     Q_D(QAbstractItemView);
  2069     Q_D(QAbstractItemView);
  2050     QAbstractScrollArea::focusInEvent(event);
  2070     QAbstractScrollArea::focusInEvent(event);
  2051     if (selectionModel()
  2071 
       
  2072     const QItemSelectionModel* model = selectionModel();
       
  2073     const bool currentIndexValid = currentIndex().isValid();
       
  2074 
       
  2075     if (model
  2052         && !d->currentIndexSet
  2076         && !d->currentIndexSet
  2053         && !currentIndex().isValid()) {
  2077         && !currentIndexValid) {
  2054         bool autoScroll = d->autoScroll;
  2078         bool autoScroll = d->autoScroll;
  2055         d->autoScroll = false;
  2079         d->autoScroll = false;
  2056         QModelIndex index = moveCursor(MoveNext, Qt::NoModifier); // first visible index
  2080         QModelIndex index = moveCursor(MoveNext, Qt::NoModifier); // first visible index
  2057         if (index.isValid() && d->isIndexEnabled(index))
  2081         if (index.isValid() && d->isIndexEnabled(index))
  2058             selectionModel()->setCurrentIndex(index, QItemSelectionModel::NoUpdate);
  2082             selectionModel()->setCurrentIndex(index, QItemSelectionModel::NoUpdate);
  2059         d->autoScroll = autoScroll;
  2083         d->autoScroll = autoScroll;
  2060     }
  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 
  2061     d->viewport->update();
  2096     d->viewport->update();
  2062 }
  2097 }
  2063 
  2098 
  2064 /*!
  2099 /*!
  2065     This function is called with the given \a event when the widget
  2100     This function is called with the given \a event when the widget
  2176         if (command != QItemSelectionModel::NoUpdate
  2211         if (command != QItemSelectionModel::NoUpdate
  2177              || style()->styleHint(QStyle::SH_ItemView_MovementWithoutUpdatingSelection, 0, this)) {
  2212              || style()->styleHint(QStyle::SH_ItemView_MovementWithoutUpdatingSelection, 0, this)) {
  2178             // note that we don't check if the new current index is enabled because moveCursor() makes sure it is
  2213             // note that we don't check if the new current index is enabled because moveCursor() makes sure it is
  2179             if (command & QItemSelectionModel::Current) {
  2214             if (command & QItemSelectionModel::Current) {
  2180                 d->selectionModel->setCurrentIndex(newCurrent, QItemSelectionModel::NoUpdate);
  2215                 d->selectionModel->setCurrentIndex(newCurrent, QItemSelectionModel::NoUpdate);
  2181                 if (!indexAt(d->pressedPosition).isValid())
  2216                 if (!indexAt(d->pressedPosition - d->offset()).isValid())
  2182                     d->pressedPosition = visualRect(oldCurrent).center() + d->offset();
  2217                     d->pressedPosition = visualRect(oldCurrent).center() + d->offset();
  2183                 QRect rect(d->pressedPosition - d->offset(), visualRect(newCurrent).center());
  2218                 QRect rect(d->pressedPosition - d->offset(), visualRect(newCurrent).center());
  2184                 setSelection(rect, command);
  2219                 setSelection(rect, command);
  2185             } else {
  2220             } else {
  2186                 d->selectionModel->setCurrentIndex(newCurrent, command);
  2221                 d->selectionModel->setCurrentIndex(newCurrent, command);
  2533 void QAbstractItemView::verticalScrollbarValueChanged(int value)
  2568 void QAbstractItemView::verticalScrollbarValueChanged(int value)
  2534 {
  2569 {
  2535     Q_D(QAbstractItemView);
  2570     Q_D(QAbstractItemView);
  2536     if (verticalScrollBar()->maximum() == value && d->model->canFetchMore(d->root))
  2571     if (verticalScrollBar()->maximum() == value && d->model->canFetchMore(d->root))
  2537         d->model->fetchMore(d->root);
  2572         d->model->fetchMore(d->root);
  2538     d->checkMouseMove(viewport()->mapFromGlobal(QCursor::pos()));
  2573     QPoint posInVp = viewport()->mapFromGlobal(QCursor::pos());
       
  2574     if (viewport()->rect().contains(posInVp))
       
  2575         d->checkMouseMove(posInVp);
  2539 }
  2576 }
  2540 
  2577 
  2541 /*!
  2578 /*!
  2542     \internal
  2579     \internal
  2543 */
  2580 */
  2544 void QAbstractItemView::horizontalScrollbarValueChanged(int value)
  2581 void QAbstractItemView::horizontalScrollbarValueChanged(int value)
  2545 {
  2582 {
  2546     Q_D(QAbstractItemView);
  2583     Q_D(QAbstractItemView);
  2547     if (horizontalScrollBar()->maximum() == value && d->model->canFetchMore(d->root))
  2584     if (horizontalScrollBar()->maximum() == value && d->model->canFetchMore(d->root))
  2548         d->model->fetchMore(d->root);
  2585         d->model->fetchMore(d->root);
  2549     d->checkMouseMove(viewport()->mapFromGlobal(QCursor::pos()));
  2586     QPoint posInVp = viewport()->mapFromGlobal(QCursor::pos());
       
  2587     if (viewport()->rect().contains(posInVp))
       
  2588         d->checkMouseMove(posInVp);
  2550 }
  2589 }
  2551 
  2590 
  2552 /*!
  2591 /*!
  2553     \internal
  2592     \internal
  2554 */
  2593 */
  2844     Q_D(const QAbstractItemView);
  2883     Q_D(const QAbstractItemView);
  2845 
  2884 
  2846     if (row < 0 || row >= d->model->rowCount() || !model())
  2885     if (row < 0 || row >= d->model->rowCount() || !model())
  2847         return -1;
  2886         return -1;
  2848 
  2887 
       
  2888     ensurePolished();
       
  2889 
  2849     QStyleOptionViewItemV4 option = d->viewOptionsV4();
  2890     QStyleOptionViewItemV4 option = d->viewOptionsV4();
  2850     int height = 0;
  2891     int height = 0;
  2851     int colCount = d->model->columnCount(d->root);
  2892     int colCount = d->model->columnCount(d->root);
  2852     QModelIndex index;
  2893     QModelIndex index;
  2853     for (int c = 0; c < colCount; ++c) {
  2894     for (int c = 0; c < colCount; ++c) {
  2872 {
  2913 {
  2873     Q_D(const QAbstractItemView);
  2914     Q_D(const QAbstractItemView);
  2874 
  2915 
  2875     if (column < 0 || column >= d->model->columnCount() || !model())
  2916     if (column < 0 || column >= d->model->columnCount() || !model())
  2876         return -1;
  2917         return -1;
       
  2918 
       
  2919     ensurePolished();
  2877 
  2920 
  2878     QStyleOptionViewItemV4 option = d->viewOptionsV4();
  2921     QStyleOptionViewItemV4 option = d->viewOptionsV4();
  2879     int width = 0;
  2922     int width = 0;
  2880     int rows = d->model->rowCount(d->root);
  2923     int rows = d->model->rowCount(d->root);
  2881     QModelIndex index;
  2924     QModelIndex index;
  3635             const bool rightButtonPressed = button & Qt::RightButton;
  3678             const bool rightButtonPressed = button & Qt::RightButton;
  3636             const bool shiftKeyPressed = modifiers & Qt::ShiftModifier;
  3679             const bool shiftKeyPressed = modifiers & Qt::ShiftModifier;
  3637             const bool controlKeyPressed = modifiers & Qt::ControlModifier;
  3680             const bool controlKeyPressed = modifiers & Qt::ControlModifier;
  3638             if (((index == pressedIndex && selectionModel->isSelected(index))
  3681             if (((index == pressedIndex && selectionModel->isSelected(index))
  3639                 || !index.isValid()) && state != QAbstractItemView::DragSelectingState
  3682                 || !index.isValid()) && state != QAbstractItemView::DragSelectingState
  3640                 && !shiftKeyPressed && !controlKeyPressed && !rightButtonPressed)
  3683                 && !shiftKeyPressed && !controlKeyPressed && (!rightButtonPressed || !index.isValid()))
  3641                 return QItemSelectionModel::ClearAndSelect|selectionBehaviorFlags();
  3684                 return QItemSelectionModel::ClearAndSelect|selectionBehaviorFlags();
  3642             return QItemSelectionModel::NoUpdate;
  3685             return QItemSelectionModel::NoUpdate;
  3643         }
  3686         }
  3644         case QEvent::KeyPress: {
  3687         case QEvent::KeyPress: {
  3645             // NoUpdate on Key movement and Ctrl
  3688             // NoUpdate on Key movement and Ctrl