From 072485048fc8360b822e35b4cc43b0728e04cc1b Mon Sep 17 00:00:00 2001 From: Vyacheslav Grigoryev Date: Mon, 4 Apr 2016 01:03:20 +0300 Subject: QHeaderView: fixing selection of reordered rows and columns MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The old code incorrectly calculated visual region for a selection (specified by QItemSelection object) in case of reordered / swapped rows or columns. It used the leftmost and rightmost (upmost and downmost for vertical mode) logical indexes directly. However some middle logical index (in case of reorder) may be the leftmost or rightmost visual index. In such cases the repainting didn't work properly. This fix first checks whether reordering / swapping is in use. If it isn't (ie visual=logical) we use code similar to the old code. Otherwise the new code scans all selected logical indexes, translates them into visual ones and gets the correct leftmost and rightmost indexes. [ChangeLog][QtWidgets][QHeaderView] Fixed a repainting issue when items had been reordered. Task-number: QTBUG-50171 Change-Id: If6afabebf445cf32a8e0afe262b6ee149e7c4b2b Reviewed-by: Thorbjørn Lund Martsum --- src/widgets/itemviews/qheaderview.cpp | 122 +++++++++++++++++++++------------- 1 file changed, 74 insertions(+), 48 deletions(-) (limited to 'src/widgets/itemviews') diff --git a/src/widgets/itemviews/qheaderview.cpp b/src/widgets/itemviews/qheaderview.cpp index f04d580030..46684d325c 100644 --- a/src/widgets/itemviews/qheaderview.cpp +++ b/src/widgets/itemviews/qheaderview.cpp @@ -2957,31 +2957,43 @@ QRegion QHeaderView::visualRegionForSelection(const QItemSelection &selection) c { Q_D(const QHeaderView); const int max = d->modelSectionCount(); - if (d->orientation == Qt::Horizontal) { - int left = max; - int right = 0; - int rangeLeft, rangeRight; - for (int i = 0; i < selection.count(); ++i) { - QItemSelectionRange r = selection.at(i); - if (r.parent().isValid() || !r.isValid()) - continue; // we only know about toplevel items and we don't want invalid ranges - // FIXME an item inside the range may be the leftmost or rightmost - rangeLeft = visualIndex(r.left()); - if (rangeLeft == -1) // in some cases users may change the selections - continue; // before we have a chance to do the layout - rangeRight = visualIndex(r.right()); - if (rangeRight == -1) // in some cases users may change the selections - continue; // before we have a chance to do the layout - if (rangeLeft < left) - left = rangeLeft; - if (rangeRight > right) - right = rangeRight; + if (d->orientation == Qt::Horizontal) { + int logicalLeft = max; + int logicalRight = 0; + + if (d->visualIndices.empty()) { + // If no reordered sections, skip redundant visual-to-logical transformations + for (int i = 0; i < selection.count(); ++i) { + const QItemSelectionRange &r = selection.at(i); + if (r.parent().isValid() || !r.isValid()) + continue; // we only know about toplevel items and we don't want invalid ranges + if (r.left() < logicalLeft) + logicalLeft = r.left(); + if (r.right() > logicalRight) + logicalRight = r.right(); + } + } else { + int left = max; + int right = 0; + for (int i = 0; i < selection.count(); ++i) { + const QItemSelectionRange &r = selection.at(i); + if (r.parent().isValid() || !r.isValid()) + continue; // we only know about toplevel items and we don't want invalid ranges + for (int k = r.left(); k <= r.right(); ++k) { + int visual = visualIndex(k); + if (visual == -1) // in some cases users may change the selections + continue; // before we have a chance to do the layout + if (visual < left) + left = visual; + if (visual > right) + right = visual; + } + } + logicalLeft = logicalIndex(left); + logicalRight = logicalIndex(right); } - int logicalLeft = logicalIndex(left); - int logicalRight = logicalIndex(right); - if (logicalLeft < 0 || logicalLeft >= count() || logicalRight < 0 || logicalRight >= count()) return QRegion(); @@ -2992,32 +3004,46 @@ QRegion QHeaderView::visualRegionForSelection(const QItemSelection &selection) c return QRect(leftPos, 0, rightPos - leftPos, height()); } // orientation() == Qt::Vertical - int top = max; - int bottom = 0; - int rangeTop, rangeBottom; - - for (int i = 0; i < selection.count(); ++i) { - QItemSelectionRange r = selection.at(i); - if (r.parent().isValid() || !r.isValid()) - continue; // we only know about toplevel items - // FIXME an item inside the range may be the leftmost or rightmost - rangeTop = visualIndex(r.top()); - if (rangeTop == -1) // in some cases users may change the selections - continue; // before we have a chance to do the layout - rangeBottom = visualIndex(r.bottom()); - if (rangeBottom == -1) // in some cases users may change the selections - continue; // before we have a chance to do the layout - if (rangeTop < top) - top = rangeTop; - if (rangeBottom > bottom) - bottom = rangeBottom; - } - - int logicalTop = logicalIndex(top); - int logicalBottom = logicalIndex(bottom); - - if (logicalTop == -1 || logicalBottom == -1) - return QRect(); + int logicalTop = max; + int logicalBottom = 0; + + if (d->visualIndices.empty()) { + // If no reordered sections, skip redundant visual-to-logical transformations + for (int i = 0; i < selection.count(); ++i) { + const QItemSelectionRange &r = selection.at(i); + if (r.parent().isValid() || !r.isValid()) + continue; // we only know about toplevel items and we don't want invalid ranges + if (r.top() < logicalTop) + logicalTop = r.top(); + if (r.bottom() > logicalBottom) + logicalBottom = r.bottom(); + } + } else { + int top = max; + int bottom = 0; + + for (int i = 0; i < selection.count(); ++i) { + const QItemSelectionRange &r = selection.at(i); + if (r.parent().isValid() || !r.isValid()) + continue; // we only know about toplevel items and we don't want invalid ranges + for (int k = r.top(); k <= r.bottom(); ++k) { + int visual = visualIndex(k); + if (visual == -1) // in some cases users may change the selections + continue; // before we have a chance to do the layout + if (visual < top) + top = visual; + if (visual > bottom) + bottom = visual; + } + } + + logicalTop = logicalIndex(top); + logicalBottom = logicalIndex(bottom); + } + + if (logicalTop < 0 || logicalTop >= count() || + logicalBottom < 0 || logicalBottom >= count()) + return QRegion(); int topPos = sectionViewportPosition(logicalTop); int bottomPos = sectionViewportPosition(logicalBottom) + sectionSize(logicalBottom); -- cgit v1.2.3