QHeaderView::paintSection(): fix visible index handling

Sections may be hidden => QStyleOptionHeader::position must reflect the
state seen on the screen. Otherwise styles will give wrong visual
results.

Task-number: QTBUG-32203
Change-Id: I7ef86496be092bf6f52ec45f757b501f38c3a431
Reviewed-by: Thorbjørn Lund Martsum <tmartsum@gmail.com>
Reviewed-by: Stephen Kelly <stephen.kelly@kdab.com>
This commit is contained in:
J-P Nurmi 2013-08-06 14:08:47 +02:00 committed by The Qt Project
parent bab29dd76c
commit bff78163f6
3 changed files with 88 additions and 3 deletions

View File

@ -2635,11 +2635,13 @@ void QHeaderView::paintSection(QPainter *painter, const QRect &rect, int logical
// the section position
int visual = visualIndex(logicalIndex);
Q_ASSERT(visual != -1);
if (count() == 1)
bool first = d->isFirstVisibleSection(visual);
bool last = d->isLastVisibleSection(visual);
if (first && last)
opt.position = QStyleOptionHeader::OnlyOneSection;
else if (visual == 0)
else if (first)
opt.position = QStyleOptionHeader::Beginning;
else if (visual == count() - 1)
else if (last)
opt.position = QStyleOptionHeader::End;
else
opt.position = QStyleOptionHeader::Middle;
@ -3062,6 +3064,22 @@ bool QHeaderViewPrivate::isSectionSelected(int section) const
return s;
}
bool QHeaderViewPrivate::isFirstVisibleSection(int section) const
{
if (sectionStartposRecalc)
recalcSectionStartPos();
const SectionItem &item = sectionItems.at(section);
return item.size > 0 && item.calculated_startpos == 0;
}
bool QHeaderViewPrivate::isLastVisibleSection(int section) const
{
if (sectionStartposRecalc)
recalcSectionStartPos();
const SectionItem &item = sectionItems.at(section);
return item.size > 0 && item.calculatedEndPos() == length;
}
/*!
\internal
Returns the last visible (ie. not hidden) visual index

View File

@ -114,6 +114,8 @@ public:
void _q_layoutChanged();
bool isSectionSelected(int section) const;
bool isFirstVisibleSection(int section) const;
bool isLastVisibleSection(int section) const;
inline bool rowIntersectsSelection(int row) const {
return (selectionModel ? selectionModel->rowIntersectsSelection(row, root) : false);

View File

@ -46,6 +46,7 @@
#include <QStringListModel>
#include <QSortFilterProxyModel>
#include <QTableView>
#include <QProxyStyle>
#include <qabstractitemmodel.h>
#include <qapplication.h>
@ -59,6 +60,20 @@ typedef QList<int> IntList;
typedef QList<bool> BoolList;
class TestStyle : public QProxyStyle
{
public:
void drawControl(ControlElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const
{
if (element == CE_HeaderSection) {
if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(option))
lastPosition = header->position;
}
QProxyStyle::drawControl(element, option, painter, widget);
}
mutable QStyleOptionHeader::SectionPosition lastPosition;
};
class protected_QHeaderView : public QHeaderView
{
Q_OBJECT
@ -229,6 +244,7 @@ private slots:
void mixedTests();
void resizeToContentTest();
void testStreamWithHide();
void testStylePosition();
protected:
void setupTestData(bool use_reset_model = false);
@ -2732,5 +2748,54 @@ void tst_QHeaderView::testStreamWithHide()
#endif
}
void tst_QHeaderView::testStylePosition()
{
topLevel->show();
QVERIFY(QTest::qWaitForWindowExposed(topLevel));
protected_QHeaderView *header = static_cast<protected_QHeaderView *>(view);
TestStyle proxy;
header->setStyle(&proxy);
QImage image(1, 1, QImage::Format_ARGB32);
QPainter p(&image);
// 0, 1, 2, 3
header->paintSection(&p, view->rect(), 0);
QCOMPARE(proxy.lastPosition, QStyleOptionHeader::Beginning);
header->paintSection(&p, view->rect(), 1);
QCOMPARE(proxy.lastPosition, QStyleOptionHeader::Middle);
header->paintSection(&p, view->rect(), 2);
QCOMPARE(proxy.lastPosition, QStyleOptionHeader::Middle);
header->paintSection(&p, view->rect(), 3);
QCOMPARE(proxy.lastPosition, QStyleOptionHeader::End);
// (0),2,1,3
view->setSectionHidden(0, true);
view->swapSections(1, 2);
header->paintSection(&p, view->rect(), 1);
QCOMPARE(proxy.lastPosition, QStyleOptionHeader::Middle);
header->paintSection(&p, view->rect(), 2);
QCOMPARE(proxy.lastPosition, QStyleOptionHeader::Beginning);
header->paintSection(&p, view->rect(), 3);
QCOMPARE(proxy.lastPosition, QStyleOptionHeader::End);
// (1),2,0,(3)
view->setSectionHidden(3, true);
view->setSectionHidden(0, false);
view->setSectionHidden(1, true);
view->swapSections(0, 1);
header->paintSection(&p, view->rect(), 0);
QCOMPARE(proxy.lastPosition, QStyleOptionHeader::End);
header->paintSection(&p, view->rect(), 2);
QCOMPARE(proxy.lastPosition, QStyleOptionHeader::Beginning);
// (1),2,(0),(3)
view->setSectionHidden(0, true);
header->paintSection(&p, view->rect(), 2);
QCOMPARE(proxy.lastPosition, QStyleOptionHeader::OnlyOneSection);
}
QTEST_MAIN(tst_QHeaderView)
#include "tst_qheaderview.moc"