Skip to content

Commit

Permalink
QHeaderView::paintSection(): fix visible index handling
Browse files Browse the repository at this point in the history
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 <[email protected]>
Reviewed-by: Stephen Kelly <[email protected]>
  • Loading branch information
J-P Nurmi authored and The Qt Project committed Aug 15, 2013
1 parent bab29dd commit bff7816
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 3 deletions.
24 changes: 21 additions & 3 deletions src/widgets/itemviews/qheaderview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions src/widgets/itemviews/qheaderview_p.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ class QHeaderViewPrivate: public QAbstractItemViewPrivate
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);
Expand Down
65 changes: 65 additions & 0 deletions tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
#include <QStringListModel>
#include <QSortFilterProxyModel>
#include <QTableView>
#include <QProxyStyle>

#include <qabstractitemmodel.h>
#include <qapplication.h>
Expand All @@ -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
Expand Down Expand Up @@ -229,6 +244,7 @@ private slots:
void mixedTests();
void resizeToContentTest();
void testStreamWithHide();
void testStylePosition();

protected:
void setupTestData(bool use_reset_model = false);
Expand Down Expand Up @@ -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"

0 comments on commit bff7816

Please sign in to comment.