diff options
28 files changed, 371 insertions, 128 deletions
diff --git a/dist/changes-5.2.0 b/dist/changes-5.2.0 new file mode 100644 index 0000000000..59ea4f9985 --- /dev/null +++ b/dist/changes-5.2.0 @@ -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. diff --git a/examples/widgets/itemviews/spreadsheet/main.cpp b/examples/widgets/itemviews/spreadsheet/main.cpp index 1cc9205d7e..f518986bc5 100644 --- a/examples/widgets/itemviews/spreadsheet/main.cpp +++ b/examples/widgets/itemviews/spreadsheet/main.cpp @@ -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(); } diff --git a/examples/widgets/itemviews/spreadsheet/spreadsheet.cpp b/examples/widgets/itemviews/spreadsheet/spreadsheet.cpp index 59d29f0e61..6fab0c2aae 100644 --- a/examples/widgets/itemviews/spreadsheet/spreadsheet.cpp +++ b/examples/widgets/itemviews/spreadsheet/spreadsheet.cpp @@ -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)); diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h index 4add02f805..c5eae7a83e 100644 --- a/src/corelib/kernel/qmetatype.h +++ b/src/corelib/kernel/qmetatype.h @@ -563,11 +563,16 @@ namespace QtPrivate { { return -1; } }; +#ifndef Q_COMPILER_VARIADIC_TEMPLATES // Function pointers don't derive from QObject template <class Result> struct IsPointerToTypeDerivedFromQObject<Result(*)()> { enum { Value = false }; }; template <class Result, class Arg0> struct IsPointerToTypeDerivedFromQObject<Result(*)(Arg0)> { enum { Value = false }; }; template <class Result, class Arg0, class Arg1> struct IsPointerToTypeDerivedFromQObject<Result(*)(Arg0, Arg1)> { enum { Value = false }; }; template <class Result, class Arg0, class Arg1, class Arg2> struct IsPointerToTypeDerivedFromQObject<Result(*)(Arg0, Arg1, Arg2)> { enum { Value = false }; }; +#else + template <typename Result, typename... Args> + struct IsPointerToTypeDerivedFromQObject<Result(*)(Args...)> { enum { Value = false }; }; +#endif template<typename T> struct QMetaTypeTypeFlags diff --git a/src/gui/image/qicon.cpp b/src/gui/image/qicon.cpp index d73cd0aa57..ea35da54dc 100644 --- a/src/gui/image/qicon.cpp +++ b/src/gui/image/qicon.cpp @@ -1063,7 +1063,6 @@ void QIcon::setThemeName(const QString &name) */ QString QIcon::themeName() { - QIconLoader::instance()->ensureInitialized(); return QIconLoader::instance()->themeName(); } diff --git a/src/gui/image/qiconloader.cpp b/src/gui/image/qiconloader.cpp index c2e5161bd3..6303f5cbe1 100644 --- a/src/gui/image/qiconloader.cpp +++ b/src/gui/image/qiconloader.cpp @@ -127,6 +127,7 @@ void QIconLoader::ensureInitialized() QIconLoader *QIconLoader::instance() { + iconLoaderInstance()->ensureInitialized(); return iconLoaderInstance(); } @@ -367,17 +368,14 @@ bool QIconLoaderEngine::hasIcon() const // Lazily load the icon void QIconLoaderEngine::ensureLoaded() { - - iconLoaderInstance()->ensureInitialized(); - - if (!(iconLoaderInstance()->themeKey() == m_key)) { + if (!(QIconLoader::instance()->themeKey() == m_key)) { while (!m_entries.isEmpty()) delete m_entries.takeLast(); Q_ASSERT(m_entries.size() == 0); - m_entries = iconLoaderInstance()->loadIcon(m_iconName); - m_key = iconLoaderInstance()->themeKey(); + m_entries = QIconLoader::instance()->loadIcon(m_iconName); + m_key = QIconLoader::instance()->themeKey(); } } @@ -564,7 +562,7 @@ void QIconLoaderEngine::virtual_hook(int id, void *data) { QIconEngine::AvailableSizesArgument &arg = *reinterpret_cast<QIconEngine::AvailableSizesArgument*>(data); - const QList<QIconDirInfo> directoryKey = iconLoaderInstance()->theme().keyList(); + const QList<QIconDirInfo> directoryKey = QIconLoader::instance()->theme().keyList(); arg.sizes.clear(); // Gets all sizes from the DirectoryInfo entries diff --git a/src/gui/kernel/qplatformservices.cpp b/src/gui/kernel/qplatformservices.cpp index f2cade0a35..d09b74c6fe 100644 --- a/src/gui/kernel/qplatformservices.cpp +++ b/src/gui/kernel/qplatformservices.cpp @@ -74,7 +74,10 @@ bool QPlatformServices::openDocument(const QUrl &url) /*! * \brief QPlatformServices::desktopEnvironment returns the active desktop environment. * - * On Unix this function returns KDE, GNOME or UNKNOWN. + * On Unix this function returns the uppercase desktop environment name, such as + * KDE, GNOME, UNITY, XFCE, LXDE etc. or UNKNOWN if none was detected. + * The primary way to detect the desktop environment is the environment variable + * XDG_CURRENT_DESKTOP. */ QByteArray QPlatformServices::desktopEnvironment() const { diff --git a/src/platformsupport/services/genericunix/qgenericunixservices.cpp b/src/platformsupport/services/genericunix/qgenericunixservices.cpp index fedaa3a655..77ea0f1db8 100644 --- a/src/platformsupport/services/genericunix/qgenericunixservices.cpp +++ b/src/platformsupport/services/genericunix/qgenericunixservices.cpp @@ -54,16 +54,24 @@ enum { debug = 0 }; static inline QByteArray detectDesktopEnvironment() { - if (!qEnvironmentVariableIsEmpty("KDE_FULL_SESSION")) - return QByteArray("KDE"); - // Check Unity first, whose older versions also have "GNOME_DESKTOP_SESSION_ID" set. const QByteArray xdgCurrentDesktop = qgetenv("XDG_CURRENT_DESKTOP"); - if (xdgCurrentDesktop == "Unity") - return QByteArrayLiteral("UNITY"); - // GNOME_DESKTOP_SESSION_ID is deprecated for some reason, but still check it - if (qgetenv("DESKTOP_SESSION") == "gnome" || !qEnvironmentVariableIsEmpty("GNOME_DESKTOP_SESSION_ID")) - return QByteArray("GNOME"); - return QByteArray("UNKNOWN"); + if (!xdgCurrentDesktop.isEmpty()) + return xdgCurrentDesktop.toUpper(); // KDE, GNOME, UNITY, LXDE, MATE, XFCE... + + // Classic fallbacks + if (!qEnvironmentVariableIsEmpty("KDE_FULL_SESSION")) + return QByteArrayLiteral("KDE"); + if (!qEnvironmentVariableIsEmpty("GNOME_DESKTOP_SESSION_ID")) + return QByteArrayLiteral("GNOME"); + + // Fallback to checking $DESKTOP_SESSION (unreliable) + const QByteArray desktopSession = qgetenv("DESKTOP_SESSION"); + if (desktopSession == "gnome") + return QByteArrayLiteral("GNOME"); + if (desktopSession == "xfce") + return QByteArrayLiteral("XFCE"); + + return QByteArrayLiteral("UNKNOWN"); } static inline bool checkExecutable(const QString &candidate, QString *result) diff --git a/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp b/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp index cabddcc815..bf5131f393 100644 --- a/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp +++ b/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp @@ -492,7 +492,11 @@ QStringList QGenericUnixTheme::themeNames() #ifndef QT_NO_SETTINGS result.push_back(QLatin1String(QKdeTheme::name)); #endif - } else { // Gnome, Unity, other Gtk-based desktops like XFCE. + } else if (desktopEnvironment == QByteArrayLiteral("GNOME") || + desktopEnvironment == QByteArrayLiteral("UNITY") || + desktopEnvironment == QByteArrayLiteral("MATE") || + desktopEnvironment == QByteArrayLiteral("XFCE") || + desktopEnvironment == QByteArrayLiteral("LXDE")) { // Gtk-based desktops // prefer the GTK2 theme implementation with native dialogs etc. result.push_back(QStringLiteral("gtk2")); // fallback to the generic Gnome theme if loading the GTK2 theme fails diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index 5ff1bf83ae..fc8eb0c503 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -118,7 +118,7 @@ static bool isMouseEvent(NSEvent *ev) // Windows with a transient parent (such as combobox popup windows) // cannot become the main window: - if (m_cocoaPlatformWindow->window()->transientParent()) + if (m_cocoaPlatformWindow && m_cocoaPlatformWindow->window()->transientParent()) canBecomeMain = NO; return canBecomeMain; @@ -155,6 +155,9 @@ static bool isMouseEvent(NSEvent *ev) - (BOOL)canBecomeKeyWindow { + if (!m_cocoaPlatformWindow) + return NO; + // Only tool or dialog windows should become key: if (m_cocoaPlatformWindow->window()->type() == Qt::Tool || m_cocoaPlatformWindow->window()->type() == Qt::Dialog) return YES; diff --git a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp index c0f1b3a000..7407d88f8b 100644 --- a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp +++ b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp @@ -215,7 +215,9 @@ QWindowsFontEngineDirectWrite::QWindowsFontEngineDirectWrite(IDWriteFontFace *di if (QWindowsContext::verboseFonts) qDebug("%s %g", __FUNCTION__, pixelSize); - d->directWriteFactory->AddRef(); + Q_ASSERT(m_directWriteFontFace); + + m_fontEngineData->directWriteFactory->AddRef(); m_directWriteFontFace->AddRef(); fontDef.pixelSize = pixelSize; @@ -237,19 +239,17 @@ QWindowsFontEngineDirectWrite::~QWindowsFontEngineDirectWrite() void QWindowsFontEngineDirectWrite::collectMetrics() { - if (m_directWriteFontFace != 0) { - DWRITE_FONT_METRICS metrics; - - m_directWriteFontFace->GetMetrics(&metrics); - m_unitsPerEm = metrics.designUnitsPerEm; - - m_lineThickness = DESIGN_TO_LOGICAL(metrics.underlineThickness); - m_ascent = DESIGN_TO_LOGICAL(metrics.ascent); - m_descent = DESIGN_TO_LOGICAL(metrics.descent); - m_xHeight = DESIGN_TO_LOGICAL(metrics.xHeight); - m_lineGap = DESIGN_TO_LOGICAL(metrics.lineGap); - m_underlinePosition = DESIGN_TO_LOGICAL(metrics.underlinePosition); - } + DWRITE_FONT_METRICS metrics; + + m_directWriteFontFace->GetMetrics(&metrics); + m_unitsPerEm = metrics.designUnitsPerEm; + + m_lineThickness = DESIGN_TO_LOGICAL(metrics.underlineThickness); + m_ascent = DESIGN_TO_LOGICAL(metrics.ascent); + m_descent = DESIGN_TO_LOGICAL(metrics.descent); + m_xHeight = DESIGN_TO_LOGICAL(metrics.xHeight); + m_lineGap = DESIGN_TO_LOGICAL(metrics.lineGap); + m_underlinePosition = DESIGN_TO_LOGICAL(metrics.underlinePosition); } QFixed QWindowsFontEngineDirectWrite::underlinePosition() const @@ -272,31 +272,24 @@ bool QWindowsFontEngineDirectWrite::getSfntTableData(uint tag, uchar *buffer, ui { bool ret = false; - if (m_directWriteFontFace) { - DWORD t = qbswap<quint32>(tag); - - const void *tableData = 0; - void *tableContext = 0; - UINT32 tableSize; - BOOL exists; - HRESULT hr = m_directWriteFontFace->TryGetFontTable( - t, &tableData, &tableSize, &tableContext, &exists - ); - - if (SUCCEEDED(hr)) { - if (exists) { - if (!buffer) { - *length = tableSize; - ret = true; - } else if (*length >= tableSize) { - memcpy(buffer, tableData, tableSize); - ret = true; - } - } - m_directWriteFontFace->ReleaseFontTable(tableContext); - } else { - qErrnoWarning("%s: TryGetFontTable failed", __FUNCTION__); + const void *tableData = 0; + UINT32 tableSize; + void *tableContext = 0; + BOOL exists; + HRESULT hr = m_directWriteFontFace->TryGetFontTable(qbswap<quint32>(tag) + &tableData, &tableSize, + &tableContext, &exists); + if (SUCCEEDED(hr)) { + if (exists) { + ret = true; + if (buffer && *length >= tableSize) + memcpy(buffer, tableData, tableSize); + else + *length = tableSize; } + m_directWriteFontFace->ReleaseFontTable(tableContext); + } else { + qErrnoWarning("%s: TryGetFontTable failed", __FUNCTION__); } return ret; @@ -327,43 +320,43 @@ inline unsigned int getChar(const QChar *str, int &i, const int len) bool QWindowsFontEngineDirectWrite::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QFontEngine::ShaperFlags flags) const { - if (m_directWriteFontFace != 0) { - QVarLengthArray<UINT32> codePoints(len); - for (int i=0; i<len; ++i) { - codePoints[i] = getChar(str, i, len); - if (flags & QFontEngine::RightToLeft) - codePoints[i] = QChar::mirroredChar(codePoints[i]); - } + if (*nglyphs < len) { + *nglyphs = len; + return false; + } - QVarLengthArray<UINT16> glyphIndices(len); - HRESULT hr = m_directWriteFontFace->GetGlyphIndicesW(codePoints.data(), - len, - glyphIndices.data()); + QVarLengthArray<UINT32> codePoints(len); + int actualLength = 0; + if (flags & QFontEngine::RightToLeft) { + for (int i = 0; i < len; ++i) + codePoints[actualLength++] = QChar::mirroredChar(getChar(str, i, len)); + } else { + for (int i = 0; i < len; ++i) + codePoints[actualLength++] = getChar(str, i, len); + } - if (SUCCEEDED(hr)) { - for (int i=0; i<len; ++i) - glyphs->glyphs[i] = glyphIndices[i]; + QVarLengthArray<UINT16> glyphIndices(actualLength); + HRESULT hr = m_directWriteFontFace->GetGlyphIndicesW(codePoints.data(), actualLength, + glyphIndices.data()); + if (FAILED(hr)) { + qErrnoWarning("%s: GetGlyphIndicesW failed", __FUNCTION__); + return false; + } - *nglyphs = len; - glyphs->numGlyphs = len; + for (int i = 0; i < actualLength; ++i) + glyphs->glyphs[i] = glyphIndices.at(i); - if (!(flags & GlyphIndicesOnly)) - recalcAdvances(glyphs, 0); + *nglyphs = actualLength; + glyphs->numGlyphs = actualLength; - return true; - } else { - qErrnoWarning("%s: GetGlyphIndicesW failed", __FUNCTION__); - } - } + if (!(flags & GlyphIndicesOnly)) + recalcAdvances(glyphs, 0); - return false; + return true; } void QWindowsFontEngineDirectWrite::recalcAdvances(QGlyphLayout *glyphs, QFontEngine::ShaperFlags) const { - if (m_directWriteFontFace == 0) - return; - QVarLengthArray<UINT16> glyphIndices(glyphs->numGlyphs); // ### Caching? @@ -391,9 +384,6 @@ void QWindowsFontEngineDirectWrite::recalcAdvances(QGlyphLayout *glyphs, QFontEn void QWindowsFontEngineDirectWrite::addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int nglyphs, QPainterPath *path, QTextItem::RenderFlags flags) { - if (m_directWriteFontFace == 0) - return; - QVarLengthArray<UINT16> glyphIndices(nglyphs); QVarLengthArray<DWRITE_GLYPH_OFFSET> glyphOffsets(nglyphs); QVarLengthArray<FLOAT> glyphAdvances(nglyphs); @@ -439,9 +429,6 @@ glyph_metrics_t QWindowsFontEngineDirectWrite::boundingBox(const QGlyphLayout &g glyph_metrics_t QWindowsFontEngineDirectWrite::boundingBox(glyph_t g) { - if (m_directWriteFontFace == 0) - return glyph_metrics_t(); - UINT16 glyphIndex = g; DWRITE_GLYPH_METRICS glyphMetrics; @@ -668,14 +655,14 @@ bool QWindowsFontEngineDirectWrite::canRender(const QChar *string, int len) if (FAILED(hr)) { qErrnoWarning("%s: GetGlyphIndices failed", __FUNCTION__); return false; - } else { - for (int i=0; i<glyphIndices.size(); ++i) { - if (glyphIndices.at(i) == 0) - return false; - } + } - return true; + for (int i = 0; i < actualLength; ++i) { + if (glyphIndices.at(i) == 0) + return false; } + + return true; } QFontEngine::Type QWindowsFontEngineDirectWrite::type() const diff --git a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h index 106087f757..ab14cb49eb 100644 --- a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h +++ b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h @@ -107,8 +107,6 @@ public: static QString fontNameSubstitute(const QString &familyName); private: - friend class QRawFontPrivate; - QImage imageForGlyph(glyph_t t, QFixed subPixelPosition, int margin, const QTransform &xform); void collectMetrics(); diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.cpp b/src/plugins/platforms/xcb/qxcbkeyboard.cpp index 4ac60f6077..02f10bba89 100644 --- a/src/plugins/platforms/xcb/qxcbkeyboard.cpp +++ b/src/plugins/platforms/xcb/qxcbkeyboard.cpp @@ -736,7 +736,7 @@ Qt::KeyboardModifiers QXcbKeyboard::translateModifiers(int s) int QXcbKeyboard::translateKeySym(uint key) const { - int code = -1; + int code = Qt::Key_unknown; int i = 0; // any other keys while (KeyTbl[i]) { if (key == KeyTbl[i]) { diff --git a/src/widgets/itemviews/qabstractitemview.cpp b/src/widgets/itemviews/qabstractitemview.cpp index 70c8f44a73..b79525b9df 100644 --- a/src/widgets/itemviews/qabstractitemview.cpp +++ b/src/widgets/itemviews/qabstractitemview.cpp @@ -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) diff --git a/src/widgets/itemviews/qabstractitemview_p.h b/src/widgets/itemviews/qabstractitemview_p.h index 86eab174ed..5da22615e2 100644 --- a/src/widgets/itemviews/qabstractitemview_p.h +++ b/src/widgets/itemviews/qabstractitemview_p.h @@ -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; diff --git a/src/widgets/itemviews/qheaderview.cpp b/src/widgets/itemviews/qheaderview.cpp index edfbc5c8f1..0dbf0a6a76 100644 --- a/src/widgets/itemviews/qheaderview.cpp +++ b/src/widgets/itemviews/qheaderview.cpp @@ -550,6 +550,22 @@ QSize QHeaderView::sizeHint() const } /*! + \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. \sa sizeHint(), defaultSectionSize(), minimumSectionSize(), @@ -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); } diff --git a/src/widgets/itemviews/qheaderview.h b/src/widgets/itemviews/qheaderview.h index 8fcd8d7a36..0b94eedf78 100644 --- a/src/widgets/itemviews/qheaderview.h +++ b/src/widgets/itemviews/qheaderview.h @@ -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; diff --git a/src/widgets/itemviews/qtableview.cpp b/src/widgets/itemviews/qtableview.cpp index 573df1db6a..37c52948b0 100644 --- a/src/widgets/itemviews/qtableview.cpp +++ b/src/widgets/itemviews/qtableview.cpp @@ -1056,6 +1056,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 +*/ void QTableView::setModel(QAbstractItemModel *model) { Q_D(QTableView); diff --git a/src/widgets/itemviews/qtableview.h b/src/widgets/itemviews/qtableview.h index 824348dbe8..db956480d6 100644 --- a/src/widgets/itemviews/qtableview.h +++ b/src/widgets/itemviews/qtableview.h @@ -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); diff --git a/src/widgets/itemviews/qtreeview.cpp b/src/widgets/itemviews/qtreeview.cpp index 70523815e8..962ed97762 100644 --- a/src/widgets/itemviews/qtreeview.cpp +++ b/src/widgets/itemviews/qtreeview.cpp @@ -335,6 +335,7 @@ void QTreeView::setHeader(QHeaderView *header) this, SLOT(updateGeometries())); setSortingEnabled(d->sortingEnabled); + d->updateGeometry(); } /*! @@ -2619,6 +2620,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. diff --git a/src/widgets/itemviews/qtreeview.h b/src/widgets/itemviews/qtreeview.h index 73f11f1a48..fae814c6f6 100644 --- a/src/widgets/itemviews/qtreeview.h +++ b/src/widgets/itemviews/qtreeview.h @@ -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); diff --git a/src/widgets/widgets/qabstractscrollarea.cpp b/src/widgets/widgets/qabstractscrollarea.cpp index 900e95f4da..e7827055fb 100644 --- a/src/widgets/widgets/qabstractscrollarea.cpp +++ b/src/widgets/widgets/qabstractscrollarea.cpp @@ -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 @@ -527,6 +528,19 @@ void QAbstractScrollAreaPrivate::layoutChildren() } /*! + \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 Creates a new QAbstractScrollAreaPrivate, \a dd with the given \a parent. @@ -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" diff --git a/src/widgets/widgets/qabstractscrollarea.h b/src/widgets/widgets/qabstractscrollarea.h index ccf16b5e5c..fb9562db1b 100644 --- a/src/widgets/widgets/qabstractscrollarea.h +++ b/src/widgets/widgets/qabstractscrollarea.h @@ -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); diff --git a/src/widgets/widgets/qabstractscrollarea_p.h b/src/widgets/widgets/qabstractscrollarea_p.h index 34d767fe29..3093c2f812 100644 --- a/src/widgets/widgets/qabstractscrollarea_p.h +++ b/src/widgets/widgets/qabstractscrollarea_p.h @@ -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; diff --git a/src/widgets/widgets/qscrollarea.cpp b/src/widgets/widgets/qscrollarea.cpp index 93c335c56b..2a6d4620d7 100644 --- a/src/widgets/widgets/qscrollarea.cpp +++ b/src/widgets/widgets/qscrollarea.cpp @@ -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); +} /*! diff --git a/src/widgets/widgets/qscrollarea.h b/src/widgets/widgets/qscrollarea.h index 576c9bc9e0..70af5fbbd7 100644 --- a/src/widgets/widgets/qscrollarea.h +++ b/src/widgets/widgets/qscrollarea.h @@ -69,6 +69,8 @@ public: void setWidgetResizable(bool resizable); QSize sizeHint() const; + QSize viewportSizeHint() const; + bool focusNextPrevChild(bool next); Qt::Alignment alignment() const; diff --git a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp index f412ee2970..3e569814c9 100644 --- a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp +++ b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp @@ -1825,11 +1825,15 @@ typedef Undefined (*UndefinedFunction0)(); typedef Undefined (*UndefinedFunction1)(Undefined); typedef Undefined (*UndefinedFunction2)(Undefined, Undefined); typedef Undefined (*UndefinedFunction3)(Undefined, Undefined, Undefined); +typedef Undefined (*UndefinedFunction4)(Undefined, Undefined, Undefined, Undefined, Undefined, Undefined, Undefined, Undefined); Q_DECLARE_METATYPE(UndefinedFunction0); Q_DECLARE_METATYPE(UndefinedFunction1); Q_DECLARE_METATYPE(UndefinedFunction2); Q_DECLARE_METATYPE(UndefinedFunction3); +#ifdef Q_COMPILER_VARIADIC_TEMPLATES +Q_DECLARE_METATYPE(UndefinedFunction4); +#endif QTEST_MAIN(tst_QMetaType) #include "tst_qmetatype.moc" diff --git a/tests/manual/widgets/itemviews/qtreeview/main.cpp b/tests/manual/widgets/itemviews/qtreeview/main.cpp index 296ba6bcbf..22b4e07f75 100644 --- a/tests/manual/widgets/itemviews/qtreeview/main.cpp +++ b/tests/manual/widgets/itemviews/qtreeview/main.cpp @@ -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(); } |