QAbstractScrollArea - add SizeAdjustPolicy and viewportSizeHint

This patch adds SizeAdjustPolicy to QAbstractScrollArea.
If it is set to AdjustToContents it will make use of the new
protected viewportSizeHint() (BC since it was reserved in Qt5).
This function returns a suggested size based on contents.

Change-Id: I5d8aa517e88b8b21c5712e62b4d574c3aad99d3b
Reviewed-by: Stephen Kelly <stephen.kelly@kdab.com>
This commit is contained in:
Christoph Schleifenbaum 2011-12-22 19:33:28 +01:00 committed by The Qt Project
parent 7df16fb4cc
commit ae0fd6884d
17 changed files with 262 additions and 28 deletions

27
dist/changes-5.2.0 vendored Normal file
View File

@ -0,0 +1,27 @@
Qt 5.2 introduces many new features and improvements as well as bugfixes
over the 5.1.x series. For more details, refer to the online documentation
included in this distribution. The documentation is also available online:
http://qt-project.org/doc/qt-5.2
The Qt version 5.2 series is binary compatible with the 5.1.x series.
Applications compiled for 5.1 will continue to run with 5.2.
Some of the changes listed in this file include issue tracking numbers
corresponding to tasks in the Qt Bug Tracker:
http://bugreports.qt-project.org/
Each of these identifiers can be entered in the bug tracker to obtain more
information about a particular change.
****************************************************************************
* Library *
****************************************************************************
QtWidgets
---------
- QAbstractScrollArea now has a SizeAdjustPolicy. If it is set to AdjustToContents
it will make use of the new protected viewportSizeHint() (binary compatible since it
was reserved in Qt5). This function returns a suggested size based on contents.

View File

@ -42,14 +42,15 @@
#include "spreadsheet.h"
#include <QApplication>
#include <QLayout>
int main(int argc, char** argv) {
Q_INIT_RESOURCE(spreadsheet);
QApplication app(argc, argv);
SpreadSheet sheet(10, 6);
sheet.setWindowIcon(QPixmap(":/images/interview.png"));
sheet.resize(640, 420);
sheet.show();
sheet.layout()->setSizeConstraint(QLayout::SetFixedSize);
return app.exec();
}

View File

@ -64,6 +64,7 @@ SpreadSheet::SpreadSheet(int rows, int cols, QWidget *parent)
toolBar->addWidget(formulaInput);
table = new QTableWidget(rows, cols, this);
table->setSizeAdjustPolicy(QTableWidget::AdjustToContents);
for (int c = 0; c < cols; ++c) {
QString character(QChar('A' + c));
table->setHorizontalHeaderItem(c, new QTableWidgetItem(character));

View File

@ -1108,6 +1108,7 @@ void QAbstractItemView::reset()
QAccessible::updateAccessibility(&accessibleEvent);
}
#endif
d->updateGeometry();
}
/*!
@ -1124,6 +1125,7 @@ void QAbstractItemView::setRootIndex(const QModelIndex &index)
}
d->root = index;
d->doDelayedItemsLayout();
d->updateGeometry();
}
/*!
@ -2668,8 +2670,10 @@ void QAbstractItemView::updateEditorGeometries()
*/
void QAbstractItemView::updateGeometries()
{
Q_D(QAbstractItemView);
updateEditorGeometries();
d_func()->fetchMoreTimer.start(0, this); //fetch more later
d->fetchMoreTimer.start(0, this); //fetch more later
d->updateGeometry();
}
/*!
@ -3231,6 +3235,7 @@ void QAbstractItemView::dataChanged(const QModelIndex &topLeft, const QModelInde
QAccessible::updateAccessibility(&accessibleEvent);
}
#endif
d->updateGeometry();
}
/*!
@ -3332,6 +3337,7 @@ void QAbstractItemViewPrivate::_q_rowsRemoved(const QModelIndex &index, int star
QAccessible::updateAccessibility(&accessibleEvent);
}
#endif
updateGeometry();
}
/*!
@ -3412,6 +3418,7 @@ void QAbstractItemViewPrivate::_q_columnsRemoved(const QModelIndex &index, int s
QAccessible::updateAccessibility(&accessibleEvent);
}
#endif
updateGeometry();
}
@ -3435,6 +3442,7 @@ void QAbstractItemViewPrivate::_q_rowsInserted(const QModelIndex &index, int sta
QAccessible::updateAccessibility(&accessibleEvent);
}
#endif
updateGeometry();
}
/*!
@ -3459,6 +3467,7 @@ void QAbstractItemViewPrivate::_q_columnsInserted(const QModelIndex &index, int
QAccessible::updateAccessibility(&accessibleEvent);
}
#endif
updateGeometry();
}
/*!
@ -4084,7 +4093,14 @@ void QAbstractItemViewPrivate::interruptDelayedItemsLayout() const
delayedPendingLayout = false;
}
void QAbstractItemViewPrivate::updateGeometry()
{
Q_Q(QAbstractItemView);
if (sizeAdjustPolicy == QAbstractScrollArea::AdjustIgnored)
return;
if (sizeAdjustPolicy == QAbstractScrollArea::AdjustToContents || !shownOnce)
q->updateGeometry();
}
QWidget *QAbstractItemViewPrivate::editor(const QModelIndex &index,
const QStyleOptionViewItem &options)

View File

@ -127,6 +127,8 @@ public:
void doDelayedItemsLayout(int delay = 0);
void interruptDelayedItemsLayout() const;
void updateGeometry();
void startAutoScroll()
{ // ### it would be nice to make this into a style hint one day
int scrollInterval = (verticalScrollMode == QAbstractItemView::ScrollPerItem) ? 150 : 50;

View File

@ -549,6 +549,22 @@ QSize QHeaderView::sizeHint() const
return d->cachedSizeHint;
}
/*!
\reimp
*/
void QHeaderView::setVisible(bool v)
{
bool actualChange = (v != isVisible());
QAbstractItemView::setVisible(v);
if (actualChange) {
QAbstractScrollArea *parent = qobject_cast<QAbstractScrollArea*>(parentWidget());
if (parent)
parent->updateGeometry();
}
}
/*!
Returns a suitable size hint for the section specified by \a logicalIndex.
@ -918,6 +934,18 @@ void QHeaderView::resizeSection(int logical, int size)
d->doDelayedResizeSections();
r = d->viewport->rect();
}
// If the parent is a QAbstractScrollArea with QAbstractScrollArea::AdjustToContents
// then we want to change the geometry on that widget. Not doing it at once can/will
// cause scrollbars flicker as they would be shown at first but then removed.
// In the same situation it will also allow shrinking the whole view when stretchLastSection is set
// (It is default on QTreeViews - and it wouldn't shrink since the last stretch was made before the
// viewport was resized)
QAbstractScrollArea *parent = qobject_cast<QAbstractScrollArea *>(parentWidget());
if (parent && parent->sizeAdjustPolicy() == QAbstractScrollArea::AdjustToContents)
parent->updateGeometry();
d->viewport->update(r.normalized());
emit sectionResized(logical, oldSize, size);
}

View File

@ -84,6 +84,7 @@ public:
int offset() const;
int length() const;
QSize sizeHint() const;
void setVisible(bool v);
int sectionSizeHint(int logicalIndex) const;
int visualIndexAt(int position) const;

View File

@ -1053,6 +1053,19 @@ QTableView::~QTableView()
{
}
/*!
\reimp
*/
QSize QTableView::viewportSizeHint() const
{
Q_D(const QTableView);
QSize result( (d->verticalHeader->isHidden() ? 0 : d->verticalHeader->width()) + d->horizontalHeader->length(),
(d->horizontalHeader->isHidden() ? 0 : d->horizontalHeader->height()) + d->verticalHeader->length());
result += QSize(verticalScrollBar()->isVisible() ? verticalScrollBar()->width() : 0,
horizontalScrollBar()->isVisible() ? horizontalScrollBar()->height() : 0);
return result;
}
/*!
\reimp
*/

View File

@ -118,6 +118,8 @@ public:
void sortByColumn(int column, Qt::SortOrder order);
QSize viewportSizeHint() const;
public Q_SLOTS:
void selectRow(int row);
void selectColumn(int column);

View File

@ -335,6 +335,7 @@ void QTreeView::setHeader(QHeaderView *header)
this, SLOT(updateGeometries()));
setSortingEnabled(d->sortingEnabled);
d->updateGeometry();
}
/*!
@ -2618,6 +2619,35 @@ void QTreeView::selectAll()
}
}
/*!
\reimp
*/
QSize QTreeView::viewportSizeHint() const
{
Q_D(const QTreeView);
d->executePostedLayout(); // Make sure that viewItems are up to date.
if (d->viewItems.size() == 0)
return QAbstractItemView::viewportSizeHint();
// Get rect for last item
const QRect deepestRect = visualRect(d->viewItems.last().index);
if (!deepestRect.isValid())
return QAbstractItemView::viewportSizeHint();
QSize result = QSize(d->header->length(), deepestRect.bottom() + 1);
// add size for header
result += QSize(0, d->header->isVisible() ? d->header->height() : 0);
// add size for scrollbars
result += QSize(verticalScrollBar()->isVisible() ? verticalScrollBar()->width() : 0,
horizontalScrollBar()->isVisible() ? horizontalScrollBar()->height() : 0);
return result;
}
/*!
\since 4.2
Expands all expandable items.

View File

@ -144,6 +144,8 @@ public:
void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles = QVector<int>());
void selectAll();
QSize viewportSizeHint() const;
Q_SIGNALS:
void expanded(const QModelIndex &index);
void collapsed(const QModelIndex &index);

View File

@ -167,6 +167,7 @@ QT_BEGIN_NAMESPACE
QAbstractScrollAreaPrivate::QAbstractScrollAreaPrivate()
:hbar(0), vbar(0), vbarpolicy(Qt::ScrollBarAsNeeded), hbarpolicy(Qt::ScrollBarAsNeeded),
shownOnce(false), sizeAdjustPolicy(QAbstractScrollArea::AdjustIgnored),
viewport(0), cornerWidget(0), left(0), top(0), right(0), bottom(0),
xoffset(0), yoffset(0), viewportFilter(0)
#ifdef Q_WS_WIN
@ -526,6 +527,19 @@ void QAbstractScrollAreaPrivate::layoutChildren()
viewport->setGeometry(QStyle::visualRect(opt.direction, opt.rect, viewportRect)); // resize the viewport last
}
/*!
\enum QAbstractScrollArea::SizeAdjustPolicy
\since 5.2
This enum specifies how the size hint of the QAbstractScrollArea should
adjust when the size of the viewport changes.
\value AdjustIgnored The scroll area will behave like before - and not do any adjust.
\value AdjustToContents The scroll area will always adjust to the viewport
\value AdjustToContentsOnFirstShow The scroll area will adjust to its viewport the first time it is shown.
*/
/*!
\internal
@ -983,6 +997,13 @@ bool QAbstractScrollArea::event(QEvent *e)
case QEvent::Resize:
d->layoutChildren();
break;
case QEvent::Show:
if (!d->shownOnce && d->sizeAdjustPolicy == QAbstractScrollArea::AdjustToContentsOnFirstShow) {
d->sizeHint = QSize();
updateGeometry();
}
d->shownOnce = true;
return QFrame::event(e);
case QEvent::Paint: {
QStyleOption option;
option.initFrom(this);
@ -1533,17 +1554,70 @@ QSize QAbstractScrollArea::minimumSizeHint() const
}
/*!
Returns the sizeHint property of the scroll area. The size is determined by using
viewportSizeHint() plus some extra space for scroll bars, if needed.
\reimp
*/
QSize QAbstractScrollArea::sizeHint() const
{
return QSize(256, 192);
#if 0
Q_D(const QAbstractScrollArea);
int h = qMax(10, fontMetrics().height());
int f = 2 * d->frameWidth;
return QSize((6 * h) + f, (4 * h) + f);
#endif
if (d->sizeAdjustPolicy == QAbstractScrollArea::AdjustIgnored)
return QSize(256, 192);
if (!d->sizeHint.isValid() || d->sizeAdjustPolicy == QAbstractScrollArea::AdjustToContents) {
const int f = 2 * d->frameWidth;
const QSize frame( f, f );
const QSize scrollbars(d->vbarpolicy == Qt::ScrollBarAlwaysOn ? d->vbar->sizeHint().width() : 0,
d->hbarpolicy == Qt::ScrollBarAlwaysOn ? d->hbar->sizeHint().height() : 0);
d->sizeHint = frame + scrollbars + viewportSizeHint();
}
return d->sizeHint;
}
/*!
\since 5.2
Returns the recommended size for the viewport.
The default implementation returns viewport()->sizeHint().
Note that the size is just the viewport's size, without any scroll bars visible.
*/
QSize QAbstractScrollArea::viewportSizeHint() const
{
Q_D(const QAbstractScrollArea);
if (d->viewport) {
const QSize sh = d->viewport->sizeHint();
if (sh.isValid()) {
return sh;
}
}
const int h = qMax(10, fontMetrics().height());
return QSize(6 * h, 4 * h);
}
/*!
\since 5.2
\property QAbstractScrollArea::sizeAdjustPolicy
This property holds the policy describing how the size of the scroll area changes when the
size of the viewport changes.
The default policy is QAbstractScrollArea::AdjustIgnored.
Changing this property might actually resize the scrollarea.
*/
QAbstractScrollArea::SizeAdjustPolicy QAbstractScrollArea::sizeAdjustPolicy() const
{
Q_D(const QAbstractScrollArea);
return d->sizeAdjustPolicy;
}
void QAbstractScrollArea::setSizeAdjustPolicy(SizeAdjustPolicy policy)
{
Q_D(QAbstractScrollArea);
if (d->sizeAdjustPolicy == policy)
return;
d->sizeAdjustPolicy = policy;
d->sizeHint = QSize();
updateGeometry();
}
/*!
@ -1559,16 +1633,6 @@ void QAbstractScrollArea::setupViewport(QWidget *viewport)
Q_UNUSED(viewport);
}
/*!
\internal
This method is reserved for future use.
*/
QSize QAbstractScrollArea::viewportSizeHint() const
{
return QSize();
}
QT_END_NAMESPACE
#include "moc_qabstractscrollarea.cpp"

View File

@ -56,13 +56,22 @@ class QAbstractScrollAreaPrivate;
class Q_WIDGETS_EXPORT QAbstractScrollArea : public QFrame
{
Q_OBJECT
Q_ENUMS(SizeAdjustPolicy)
Q_PROPERTY(Qt::ScrollBarPolicy verticalScrollBarPolicy READ verticalScrollBarPolicy WRITE setVerticalScrollBarPolicy)
Q_PROPERTY(Qt::ScrollBarPolicy horizontalScrollBarPolicy READ horizontalScrollBarPolicy WRITE setHorizontalScrollBarPolicy)
Q_PROPERTY(SizeAdjustPolicy sizeAdjustPolicy READ sizeAdjustPolicy WRITE setSizeAdjustPolicy)
public:
explicit QAbstractScrollArea(QWidget* parent=0);
~QAbstractScrollArea();
enum SizeAdjustPolicy {
AdjustIgnored,
AdjustToContentsOnFirstShow,
AdjustToContents
};
Qt::ScrollBarPolicy verticalScrollBarPolicy() const;
void setVerticalScrollBarPolicy(Qt::ScrollBarPolicy);
QScrollBar *verticalScrollBar() const;
@ -89,6 +98,9 @@ public:
virtual void setupViewport(QWidget *viewport);
SizeAdjustPolicy sizeAdjustPolicy() const;
void setSizeAdjustPolicy(SizeAdjustPolicy policy);
protected:
QAbstractScrollArea(QAbstractScrollAreaPrivate &dd, QWidget *parent = 0);
void setViewportMargins(int left, int top, int right, int bottom);

View File

@ -75,6 +75,10 @@ public:
QScrollBar *hbar, *vbar;
Qt::ScrollBarPolicy vbarpolicy, hbarpolicy;
bool shownOnce;
mutable QSize sizeHint;
QAbstractScrollArea::SizeAdjustPolicy sizeAdjustPolicy;
QWidget *viewport;
QWidget *cornerWidget;
QRect cornerPaintingRect;

View File

@ -407,6 +407,18 @@ QSize QScrollArea::sizeHint() const
return sz.boundedTo(QSize(36 * h, 24 * h));
}
/*!
\reimp
*/
QSize QScrollArea::viewportSizeHint() const
{
Q_D(const QScrollArea);
if (d->widget) {
return d->resizable ? d->widget->sizeHint() : d->widget->size();
}
const int h = fontMetrics().height();
return QSize(6 * h, 4 * h);
}
/*!

View File

@ -69,6 +69,8 @@ public:
void setWidgetResizable(bool resizable);
QSize sizeHint() const;
QSize viewportSizeHint() const;
bool focusNextPrevChild(bool next);
Qt::Alignment alignment() const;

View File

@ -39,17 +39,34 @@
**
****************************************************************************/
#include <QtWidgets/QFileSystemModel>
#include <QtWidgets/QtWidgets>
#include <QtWidgets>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QFileSystemModel *model = new QFileSystemModel;
model->setRootPath(QDir::currentPath());
QTreeView *tree = new QTreeView();
tree->setModel(model);
tree->show();
app.exec();
QFileSystemModel model;
QWidget window;
QTreeView *tree = new QTreeView(&window);
tree->setMaximumSize(1000, 600);
QHBoxLayout *layout = new QHBoxLayout;
layout->setSizeConstraint(QLayout::SetFixedSize);
layout->addWidget(tree);
window.setLayout(layout);
model.setRootPath("");
tree->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents);
tree->setModel(&model);
tree->setAnimated(false);
tree->setIndentation(20);
tree->setSortingEnabled(true);
tree->header()->setStretchLastSection(false);
window.setWindowTitle(QObject::tr("Dir View"));
tree->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
window.show();
return app.exec();
}