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. |