src/gui/itemviews/qtreeview.cpp
changeset 3 41300fa6a67c
parent 0 1918ee327afb
child 4 3b1da2848fc7
child 7 f7bc934e204c
child 18 2f34d5167611
equal deleted inserted replaced
2:56cd8111b7f7 3:41300fa6a67c
   213 void QTreeView::setModel(QAbstractItemModel *model)
   213 void QTreeView::setModel(QAbstractItemModel *model)
   214 {
   214 {
   215     Q_D(QTreeView);
   215     Q_D(QTreeView);
   216     if (model == d->model)
   216     if (model == d->model)
   217         return;
   217         return;
       
   218     if (d->model && d->model != QAbstractItemModelPrivate::staticEmptyModel()) {
       
   219         disconnect(d->model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
       
   220                 this, SLOT(rowsRemoved(QModelIndex,int,int)));
       
   221 
       
   222         disconnect(d->model, SIGNAL(modelAboutToBeReset()), this, SLOT(_q_modelAboutToBeReset()));
       
   223     }
       
   224 
   218     if (d->selectionModel) { // support row editing
   225     if (d->selectionModel) { // support row editing
   219         disconnect(d->selectionModel, SIGNAL(currentRowChanged(QModelIndex,QModelIndex)),
   226         disconnect(d->selectionModel, SIGNAL(currentRowChanged(QModelIndex,QModelIndex)),
   220                    d->model, SLOT(submit()));
   227                    d->model, SLOT(submit()));
   221         disconnect(d->model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
   228         disconnect(d->model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
   222                    this, SLOT(rowsRemoved(QModelIndex,int,int)));
   229                    this, SLOT(rowsRemoved(QModelIndex,int,int)));
   836     if (enable) {
   843     if (enable) {
   837         //sortByColumn has to be called before we connect or set the sortingEnabled flag
   844         //sortByColumn has to be called before we connect or set the sortingEnabled flag
   838         // because otherwise it will not call sort on the model.
   845         // because otherwise it will not call sort on the model.
   839         sortByColumn(header()->sortIndicatorSection(), header()->sortIndicatorOrder());
   846         sortByColumn(header()->sortIndicatorSection(), header()->sortIndicatorOrder());
   840         connect(header(), SIGNAL(sortIndicatorChanged(int,Qt::SortOrder)),
   847         connect(header(), SIGNAL(sortIndicatorChanged(int,Qt::SortOrder)),
   841                 this, SLOT(_q_sortIndicatorChanged(int, Qt::SortOrder)), Qt::UniqueConnection);
   848                 this, SLOT(_q_sortIndicatorChanged(int,Qt::SortOrder)), Qt::UniqueConnection);
   842     } else {
   849     } else {
   843         disconnect(header(), SIGNAL(sortIndicatorChanged(int,Qt::SortOrder)),
   850         disconnect(header(), SIGNAL(sortIndicatorChanged(int,Qt::SortOrder)),
   844                    this, SLOT(_q_sortIndicatorChanged(int, Qt::SortOrder)));
   851                    this, SLOT(_q_sortIndicatorChanged(int,Qt::SortOrder)));
   845     }
   852     }
   846     d->sortingEnabled = enable;
   853     d->sortingEnabled = enable;
   847 }
   854 }
   848 
   855 
   849 bool QTreeView::isSortingEnabled() const
   856 bool QTreeView::isSortingEnabled() const
  1224             QModelIndex oldIndex = d->modelIndex(oldBranch),
  1231             QModelIndex oldIndex = d->modelIndex(oldBranch),
  1225                 newIndex = d->modelIndex(d->hoverBranch);
  1232                 newIndex = d->modelIndex(d->hoverBranch);
  1226             if (oldIndex != newIndex) {
  1233             if (oldIndex != newIndex) {
  1227                 QRect oldRect = visualRect(oldIndex);
  1234                 QRect oldRect = visualRect(oldIndex);
  1228                 QRect newRect = visualRect(newIndex);
  1235                 QRect newRect = visualRect(newIndex);
  1229                 viewport()->update(oldRect.left() - d->indent, oldRect.top(), d->indent, oldRect.height());
  1236                 oldRect.setLeft(oldRect.left() - d->indent);
  1230                 viewport()->update(newRect.left() - d->indent, newRect.top(), d->indent, newRect.height());
  1237                 newRect.setLeft(newRect.left() - d->indent);
       
  1238                 //we need to paint the whole items (including the decoration) so that when the user
       
  1239                 //moves the mouse over those elements they are updated
       
  1240                 viewport()->update(oldRect);
       
  1241                 viewport()->update(newRect);
  1231             }
  1242             }
  1232         }
  1243         }
  1233         if (selectionBehavior() == QAbstractItemView::SelectRows) {
  1244         if (selectionBehavior() == QAbstractItemView::SelectRows) {
  1234             QModelIndex newHoverIndex = indexAt(he->pos());
  1245             QModelIndex newHoverIndex = indexAt(he->pos());
  1235             if (d->hover != newHoverIndex) {
  1246             if (d->hover != newHoverIndex) {
  1420 
  1431 
  1421         // paint the visible rows
  1432         // paint the visible rows
  1422         for (; i < viewItems.count() && y <= area.bottom(); ++i) {
  1433         for (; i < viewItems.count() && y <= area.bottom(); ++i) {
  1423             const int itemHeight = d->itemHeight(i);
  1434             const int itemHeight = d->itemHeight(i);
  1424             option.rect.setRect(0, y, viewportWidth, itemHeight);
  1435             option.rect.setRect(0, y, viewportWidth, itemHeight);
  1425             option.state = state | (viewItems.at(i).expanded
  1436             option.state = state | (viewItems.at(i).expanded ? QStyle::State_Open : QStyle::State_None)
  1426                                     ? QStyle::State_Open : QStyle::State_None);
  1437                                  | (viewItems.at(i).hasChildren ? QStyle::State_Children : QStyle::State_None)
       
  1438                                  | (viewItems.at(i).hasMoreSiblings ? QStyle::State_Sibling : QStyle::State_None);
  1427             d->current = i;
  1439             d->current = i;
  1428             d->spanning = viewItems.at(i).spanning;
  1440             d->spanning = viewItems.at(i).spanning;
  1429             if (!multipleRects || !drawn.contains(i)) {
  1441             if (!multipleRects || !drawn.contains(i)) {
  1430                 drawRow(painter, option, viewItems.at(i).index);
  1442                 drawRow(painter, option, viewItems.at(i).index);
  1431                 if (multipleRects)   // even if the rect only intersects the item,
  1443                 if (multipleRects)   // even if the rect only intersects the item,
  1746         // start with the innermost branch
  1758         // start with the innermost branch
  1747         primitive.moveLeft(reverse ? primitive.left() : primitive.left() - indent);
  1759         primitive.moveLeft(reverse ? primitive.left() : primitive.left() - indent);
  1748         opt.rect = primitive;
  1760         opt.rect = primitive;
  1749 
  1761 
  1750         const bool expanded = viewItem.expanded;
  1762         const bool expanded = viewItem.expanded;
  1751         const bool children = (((expanded && viewItem.total > 0)) // already laid out and has children
  1763         const bool children = viewItem.hasChildren;
  1752                                 || d->hasVisibleChildren(index)); // not laid out yet, so we don't know
  1764         bool moreSiblings = viewItem.hasMoreSiblings;
  1753         bool moreSiblings = false;
       
  1754         if (d->hiddenIndexes.isEmpty())
       
  1755             moreSiblings = (d->model->rowCount(parent) - 1 > index.row());
       
  1756         else
       
  1757             moreSiblings = ((d->viewItems.size() > item +1)
       
  1758                             && (d->viewItems.at(item + 1).index.parent() == parent));
       
  1759 
  1765 
  1760         opt.state = QStyle::State_Item | extraFlags
  1766         opt.state = QStyle::State_Item | extraFlags
  1761                     | (moreSiblings ? QStyle::State_Sibling : QStyle::State_None)
  1767                     | (moreSiblings ? QStyle::State_Sibling : QStyle::State_None)
  1762                     | (children ? QStyle::State_Children : QStyle::State_None)
  1768                     | (children ? QStyle::State_Children : QStyle::State_None)
  1763                     | (expanded ? QStyle::State_Open : QStyle::State_None);
  1769                     | (expanded ? QStyle::State_Open : QStyle::State_None);
  1843         i = d->itemAtCoordinate(event->y());
  1849         i = d->itemAtCoordinate(event->y());
  1844         if (i == -1)
  1850         if (i == -1)
  1845             return; // user clicked outside the items
  1851             return; // user clicked outside the items
  1846 
  1852 
  1847         const QPersistentModelIndex firstColumnIndex = d->viewItems.at(i).index;
  1853         const QPersistentModelIndex firstColumnIndex = d->viewItems.at(i).index;
  1848 
  1854         const QPersistentModelIndex persistent = indexAt(event->pos());
  1849         int column = d->header->logicalIndexAt(event->x());
       
  1850         QPersistentModelIndex persistent = firstColumnIndex.sibling(firstColumnIndex.row(), column);
       
  1851 
  1855 
  1852         if (d->pressedIndex != persistent) {
  1856         if (d->pressedIndex != persistent) {
  1853             mousePressEvent(event);
  1857             mousePressEvent(event);
  1854             return;
  1858             return;
  1855         }
  1859         }
  2114     }
  2118     }
  2115 #endif
  2119 #endif
  2116     if (vi < 0)
  2120     if (vi < 0)
  2117         vi = qMax(0, d->viewIndex(current));
  2121         vi = qMax(0, d->viewIndex(current));
  2118 
  2122 
       
  2123     if (isRightToLeft()) {
       
  2124         if (cursorAction == MoveRight)
       
  2125             cursorAction = MoveLeft;
       
  2126         else if (cursorAction == MoveLeft)
       
  2127             cursorAction = MoveRight;
       
  2128     }
  2119     switch (cursorAction) {
  2129     switch (cursorAction) {
  2120     case MoveNext:
  2130     case MoveNext:
  2121     case MoveDown:
  2131     case MoveDown:
  2122 #ifdef QT_KEYPAD_NAVIGATION
  2132 #ifdef QT_KEYPAD_NAVIGATION
  2123         if (vi == d->viewItems.count()-1 && QApplication::keypadNavigationEnabled())
  2133         if (vi == d->viewItems.count()-1 && QApplication::keypadNavigationEnabled())
  2435     if (parent.column() != 0 && parent.isValid()) {
  2445     if (parent.column() != 0 && parent.isValid()) {
  2436         QAbstractItemView::rowsInserted(parent, start, end);
  2446         QAbstractItemView::rowsInserted(parent, start, end);
  2437         return;
  2447         return;
  2438     }
  2448     }
  2439 
  2449 
  2440     if (parent != d->root && !d->isIndexExpanded(parent) && d->model->rowCount(parent) > (end - start) + 1) {
  2450     const int parentRowCount = d->model->rowCount(parent);
       
  2451     const int delta = end - start + 1;
       
  2452     if (parent != d->root && !d->isIndexExpanded(parent) && parentRowCount > delta) {
  2441         QAbstractItemView::rowsInserted(parent, start, end);
  2453         QAbstractItemView::rowsInserted(parent, start, end);
  2442         return;
  2454         return;
  2443     }
  2455     }
  2444 
  2456 
  2445     const int parentItem = d->viewIndex(parent);
  2457     const int parentItem = d->viewIndex(parent);
  2450         const int firstChildItem = parentItem + 1;
  2462         const int firstChildItem = parentItem + 1;
  2451         const int lastChildItem = firstChildItem + ((parentItem == -1)
  2463         const int lastChildItem = firstChildItem + ((parentItem == -1)
  2452                                                     ? d->viewItems.count()
  2464                                                     ? d->viewItems.count()
  2453                                                     : d->viewItems.at(parentItem).total) - 1;
  2465                                                     : d->viewItems.at(parentItem).total) - 1;
  2454 
  2466 
  2455         const int delta = end - start + 1;
  2467         if (parentRowCount == end + 1 && start > 0) {
       
  2468             //need to Update hasMoreSiblings
       
  2469             int previousRow = start - 1;
       
  2470             QModelIndex previousSibilingModelIndex = d->model->index(previousRow, 0, parent);
       
  2471             bool isHidden = d->isRowHidden(previousSibilingModelIndex);
       
  2472             while (isHidden && previousRow > 0) {
       
  2473                 previousRow--;
       
  2474                 previousSibilingModelIndex = d->model->index(previousRow, 0, parent);
       
  2475                 isHidden = d->isRowHidden(previousSibilingModelIndex);
       
  2476             }
       
  2477             if (!isHidden) {
       
  2478                 const int previousSibilling = d->viewIndex(previousSibilingModelIndex);
       
  2479                 if(previousSibilling != -1)
       
  2480                     d->viewItems[previousSibilling].hasMoreSiblings = true;
       
  2481             }
       
  2482         }
       
  2483 
  2456         QVector<QTreeViewItem> insertedItems(delta);
  2484         QVector<QTreeViewItem> insertedItems(delta);
  2457         for (int i = 0; i < delta; ++i) {
  2485         for (int i = 0; i < delta; ++i) {
  2458             insertedItems[i].index = d->model->index(i + start, 0, parent);
  2486             insertedItems[i].index = d->model->index(i + start, 0, parent);
  2459             insertedItems[i].level = childLevel;
  2487             insertedItems[i].level = childLevel;
       
  2488             insertedItems[i].hasChildren = d->hasVisibleChildren(insertedItems[i].index);
       
  2489             insertedItems[i].hasMoreSiblings = !((i == delta - 1) && (parentRowCount == end +1));
  2460         }
  2490         }
  2461         if (d->viewItems.isEmpty())
  2491         if (d->viewItems.isEmpty())
  2462             d->defaultItemHeight = indexRowSizeHint(insertedItems[0].index);
  2492             d->defaultItemHeight = indexRowSizeHint(insertedItems[0].index);
  2463 
  2493 
  2464         int insertPos;
  2494         int insertPos;
  2496         if (delta > 1) {
  2526         if (delta > 1) {
  2497             qCopy(insertedItems.begin() + 1, insertedItems.end(),
  2527             qCopy(insertedItems.begin() + 1, insertedItems.end(),
  2498                   d->viewItems.begin() + insertPos + 1);
  2528                   d->viewItems.begin() + insertPos + 1);
  2499         }
  2529         }
  2500 
  2530 
       
  2531         if (parentItem != -1)
       
  2532             d->viewItems[parentItem].hasChildren = true;
  2501         d->updateChildCount(parentItem, delta);
  2533         d->updateChildCount(parentItem, delta);
       
  2534 
  2502         updateGeometries();
  2535         updateGeometries();
  2503         viewport()->update();
  2536         viewport()->update();
  2504     } else if ((parentItem != -1) && d->viewItems.at(parentItem).expanded) {
  2537     } else if ((parentItem != -1) && d->viewItems.at(parentItem).expanded) {
  2505         d->doDelayedItemsLayout();
  2538         d->doDelayedItemsLayout();
  2506     } else if (parentItem != -1 && (d->model->rowCount(parent) == end - start + 1)) {
  2539     } else if (parentItem != -1 && (d->model->rowCount(parent) == end - start + 1)) {
  2507         // the parent just went from 0 children to having some update to re-paint the decoration
  2540         // the parent just went from 0 children to more. update to re-paint the decoration
       
  2541         d->viewItems[parentItem].hasChildren = true;
  2508         viewport()->update();
  2542         viewport()->update();
  2509     }
  2543     }
  2510     QAbstractItemView::rowsInserted(parent, start, end);
  2544     QAbstractItemView::rowsInserted(parent, start, end);
  2511 }
  2545 }
  2512 
  2546 
  2738 {
  2772 {
  2739     Q_D(const QTreeView);
  2773     Q_D(const QTreeView);
  2740     d->executePostedLayout();
  2774     d->executePostedLayout();
  2741     if (d->viewItems.isEmpty())
  2775     if (d->viewItems.isEmpty())
  2742         return -1;
  2776         return -1;
       
  2777     ensurePolished();
  2743     int w = 0;
  2778     int w = 0;
  2744     QStyleOptionViewItemV4 option = d->viewOptionsV4();
  2779     QStyleOptionViewItemV4 option = d->viewOptionsV4();
  2745     const QVector<QTreeViewItem> viewItems = d->viewItems;
  2780     const QVector<QTreeViewItem> viewItems = d->viewItems;
  2746 
  2781 
  2747     int start = 0;
  2782     int start = 0;
  3125     int first = i + 1;
  3160     int first = i + 1;
  3126     int level = (i >= 0 ? viewItems.at(i).level + 1 : 0);
  3161     int level = (i >= 0 ? viewItems.at(i).level + 1 : 0);
  3127     int hidden = 0;
  3162     int hidden = 0;
  3128     int last = 0;
  3163     int last = 0;
  3129     int children = 0;
  3164     int children = 0;
  3130 
  3165     QTreeViewItem *item = 0;
  3131     for (int j = first; j < first + count; ++j) {
  3166     for (int j = first; j < first + count; ++j) {
  3132         current = model->index(j - first, 0, parent);
  3167         current = model->index(j - first, 0, parent);
  3133         if (isRowHidden(current)) {
  3168         if (isRowHidden(current)) {
  3134             ++hidden;
  3169             ++hidden;
  3135             last = j - hidden + children;
  3170             last = j - hidden + children;
  3136         } else {
  3171         } else {
  3137             last = j - hidden + children;
  3172             last = j - hidden + children;
  3138             viewItems[last].index = current;
  3173             if (item)
  3139             viewItems[last].level = level;
  3174                 item->hasMoreSiblings = true;
  3140             viewItems[last].height = 0;
  3175             item = &viewItems[last];
  3141             viewItems[last].spanning = q->isFirstColumnSpanned(current.row(), parent);
  3176             item->index = current;
  3142             viewItems[last].expanded = false;
  3177             item->level = level;
  3143             viewItems[last].total = 0;
  3178             item->height = 0;
       
  3179             item->spanning = q->isFirstColumnSpanned(current.row(), parent);
       
  3180             item->expanded = false;
       
  3181             item->total = 0;
       
  3182             item->hasMoreSiblings = false;
  3144             if (isIndexExpanded(current)) {
  3183             if (isIndexExpanded(current)) {
  3145                 viewItems[last].expanded = true;
  3184                 item->expanded = true;
  3146                 layout(last);
  3185                 layout(last);
  3147                 children += viewItems[last].total;
  3186                 item = &viewItems[last];
       
  3187                 children += item->total;
       
  3188                 item->hasChildren = item->total > 0;
  3148                 last = j - hidden + children;
  3189                 last = j - hidden + children;
       
  3190             } else {
       
  3191                 item->hasChildren = hasVisibleChildren(current);
  3149             }
  3192             }
  3150         }
  3193         }
  3151     }
  3194     }
  3152 
  3195 
  3153     // remove hidden items
  3196     // remove hidden items
  3699                                               ? viewItems.count()
  3742                                               ? viewItems.count()
  3700                                               : viewItems.at(parentItem).total) - 1;
  3743                                               : viewItems.at(parentItem).total) - 1;
  3701 
  3744 
  3702         const int delta = end - start + 1;
  3745         const int delta = end - start + 1;
  3703 
  3746 
       
  3747         int previousSibiling = -1;
  3704         int removedCount = 0;
  3748         int removedCount = 0;
  3705         for (int item = firstChildItem; item <= lastChildItem; ) {
  3749         for (int item = firstChildItem; item <= lastChildItem; ) {
  3706             Q_ASSERT(viewItems.at(item).level == childLevel);
  3750             Q_ASSERT(viewItems.at(item).level == childLevel);
  3707             const QModelIndex modelIndex = viewItems.at(item).index;
  3751             const QModelIndex modelIndex = viewItems.at(item).index;
  3708             //Q_ASSERT(modelIndex.parent() == parent);
  3752             //Q_ASSERT(modelIndex.parent() == parent);
  3709             const int count = viewItems.at(item).total + 1;
  3753             const int count = viewItems.at(item).total + 1;
  3710             if (modelIndex.row() < start) {
  3754             if (modelIndex.row() < start) {
       
  3755                 previousSibiling = item;
  3711                 // not affected by the removal
  3756                 // not affected by the removal
  3712                 item += count;
  3757                 item += count;
  3713             } else if (modelIndex.row() <= end) {
  3758             } else if (modelIndex.row() <= end) {
  3714                 // removed
  3759                 // removed
  3715                 viewItems.remove(item, count);
  3760                 viewItems.remove(item, count);
  3723                 }
  3768                 }
  3724                 item += count;
  3769                 item += count;
  3725             }
  3770             }
  3726         }
  3771         }
  3727 
  3772 
       
  3773         if (previousSibiling != -1 && after && model->rowCount(parent) == start)
       
  3774             viewItems[previousSibiling].hasMoreSiblings = false;
       
  3775 
       
  3776 
  3728         updateChildCount(parentItem, -removedCount);
  3777         updateChildCount(parentItem, -removedCount);
       
  3778         if (parentItem != -1 && viewItems.at(parentItem).total == 0)
       
  3779             viewItems[parentItem].hasChildren = false; //every children have been removed;
  3729         if (after) {
  3780         if (after) {
  3730             q->updateGeometries();
  3781             q->updateGeometries();
  3731             viewport->update();
  3782             viewport->update();
  3732         } else {
  3783         } else {
  3733             //we have removed items: we should at least update the scroll bar values.
  3784             //we have removed items: we should at least update the scroll bar values.