diff options
42 files changed, 330 insertions, 171 deletions
diff --git a/dist/changes-5.2.0 b/dist/changes-5.2.0 index 0e3f18929a..56997a11d4 100644 --- a/dist/changes-5.2.0 +++ b/dist/changes-5.2.0 @@ -768,3 +768,10 @@ X11 * [QTBUG-34392][MSVS] Fixed /SAFESEH:NO with VS2010+. * [QTBUG-34357][MSVS] Fixed breakage with multiple VS versions in PATH. * [MSVS] Fixed sub-project dependency generation. + +- moc + * Porting moc to QCommandLineParser has changed one specific option in its + command line handling: using the -f option without argument + is not supported anymore (it wasn't necessary, since including the header + file is the default behavior). + diff --git a/examples/widgets/widgets/styles/styles.pro b/examples/widgets/widgets/styles/styles.pro index e326991535..235642f270 100644 --- a/examples/widgets/widgets/styles/styles.pro +++ b/examples/widgets/widgets/styles/styles.pro @@ -7,8 +7,6 @@ SOURCES = main.cpp \ widgetgallery.cpp RESOURCES = styles.qrc -REQUIRES += "contains(styles, windows)" - # install target.path = $$[QT_INSTALL_EXAMPLES]/widgets/widgets/styles INSTALLS += target diff --git a/examples/widgets/widgets/widgets.pro b/examples/widgets/widgets/widgets.pro index 8d9e15a7e8..fe3e289944 100644 --- a/examples/widgets/widgets/widgets.pro +++ b/examples/widgets/widgets/widgets.pro @@ -16,6 +16,7 @@ SUBDIRS = analogclock \ shapedclock \ sliders \ spinboxes \ + styles \ stylesheet \ tablet \ tetrix \ @@ -23,5 +24,3 @@ SUBDIRS = analogclock \ validators \ wiggly \ windowflags - -contains(styles, windows): SUBDIRS += styles diff --git a/mkspecs/linux-icc/qmake.conf b/mkspecs/linux-icc/qmake.conf index d0ca604f07..6c5cbe496d 100644 --- a/mkspecs/linux-icc/qmake.conf +++ b/mkspecs/linux-icc/qmake.conf @@ -45,7 +45,8 @@ QMAKE_CXXFLAGS_SHLIB = $$QMAKE_CFLAGS_SHLIB QMAKE_CXXFLAGS_STATIC_LIB = $$QMAKE_CFLAGS_STATIC_LIB QMAKE_CXXFLAGS_YACC = $$QMAKE_CFLAGS_YACC QMAKE_CXXFLAGS_THREAD = $$QMAKE_CFLAGS_THREAD -QMAKE_CXXFLAGS_EXCEPTIONS_OFF = -fno-exceptions +# Disabling exceptions disabled - workaround for QTBUG-36577 +#QMAKE_CXXFLAGS_EXCEPTIONS_OFF = -fno-exceptions QMAKE_CXXFLAGS_CXX11 = -std=c++0x QMAKE_INCDIR = diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index 6a6656a6f6..2a74801c42 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -870,7 +870,7 @@ public: }; #define Q_FOREACH(variable, container) \ -for (QForeachContainer<__typeof__(container)> _container_(container); \ +for (QForeachContainer<__typeof__((container))> _container_((container)); \ !_container_.brk && _container_.i != _container_.e; \ __extension__ ({ ++_container_.brk; ++_container_.i; })) \ for (variable = *_container_.i;; __extension__ ({--_container_.brk; break;})) diff --git a/src/corelib/io/qdebug.cpp b/src/corelib/io/qdebug.cpp index 05920f4575..3370cce6d5 100644 --- a/src/corelib/io/qdebug.cpp +++ b/src/corelib/io/qdebug.cpp @@ -383,7 +383,7 @@ QDebugStateSaver::QDebugStateSaver(QDebug &dbg) } /*! - Destroyes a QDebugStateSaver instance, which restores the settings + Destroys a QDebugStateSaver instance, which restores the settings used when the QDebugStateSaver instance was created. \sa QDebug::setAutoInsertSpaces(), QDebug::autoInsertSpaces() diff --git a/src/corelib/io/qdir.cpp b/src/corelib/io/qdir.cpp index 909143ecf3..ec7d89fa87 100644 --- a/src/corelib/io/qdir.cpp +++ b/src/corelib/io/qdir.cpp @@ -1944,8 +1944,9 @@ QString QDir::homePath() On Unix/Linux systems this is the path in the \c TMPDIR environment variable or \c{/tmp} if \c TMPDIR is not defined. On Windows this is usually the path in the \c TEMP or \c TMP environment - variable. Whether a directory separator is added to the end or - not, depends on the operating system. + variable. + The path returned by this method doesn't end with a directory separator + unless it is the root directory (of a drive). \sa temp(), currentPath(), homePath(), rootPath() */ diff --git a/src/corelib/io/qfilesystemengine_unix.cpp b/src/corelib/io/qfilesystemengine_unix.cpp index e6b4e5f754..2327c11c69 100644 --- a/src/corelib/io/qfilesystemengine_unix.cpp +++ b/src/corelib/io/qfilesystemengine_unix.cpp @@ -721,13 +721,13 @@ QString QFileSystemEngine::tempPath() if (temp.isEmpty()) { qWarning("Neither the TEMP nor the TMPDIR environment variable is set, falling back to /tmp."); - temp = QLatin1String("/tmp/"); + temp = QLatin1String("/tmp"); } return QDir::cleanPath(temp); #else QString temp = QFile::decodeName(qgetenv("TMPDIR")); if (temp.isEmpty()) - temp = QLatin1String("/tmp/"); + temp = QLatin1String("/tmp"); return QDir::cleanPath(temp); #endif } diff --git a/src/corelib/io/qstandardpaths_unix.cpp b/src/corelib/io/qstandardpaths_unix.cpp index 1b9078f712..e2ed7c3766 100644 --- a/src/corelib/io/qstandardpaths_unix.cpp +++ b/src/corelib/io/qstandardpaths_unix.cpp @@ -205,6 +205,8 @@ QString QStandardPaths::writableLocation(StandardLocation type) // value can start with $HOME if (value.startsWith(QLatin1String("$HOME"))) value = QDir::homePath() + value.mid(5); + if (value.length() > 1 && value.endsWith(QLatin1Char('/'))) + value.chop(1); return value; } } @@ -257,10 +259,17 @@ static QStringList xdgDataDirs() dirs.append(QString::fromLatin1("/usr/local/share")); dirs.append(QString::fromLatin1("/usr/share")); } else { - dirs = xdgDataDirsEnv.split(QLatin1Char(':')); - // Normalize paths - for (int i = 0; i < dirs.count(); i++) - dirs[i] = QDir::cleanPath(dirs.at(i)); + dirs = xdgDataDirsEnv.split(QLatin1Char(':'), QString::SkipEmptyParts); + + // Normalize paths, skip relative paths + QMutableListIterator<QString> it(dirs); + while (it.hasNext()) { + const QString dir = it.next(); + if (!dir.startsWith(QLatin1Char('/'))) + it.remove(); + else + it.setValue(QDir::cleanPath(dir)); + } // Remove duplicates from the list, there's no use for duplicated // paths in XDG_DATA_DIRS - if it's not found in the given diff --git a/src/corelib/io/qurl.cpp b/src/corelib/io/qurl.cpp index eac5a0b738..f17215964f 100644 --- a/src/corelib/io/qurl.cpp +++ b/src/corelib/io/qurl.cpp @@ -414,10 +414,16 @@ static inline QString fileScheme() return QStringLiteral("file"); } +#ifdef Q_COMPILER_CLASS_ENUM +# define colon_uchar : uchar +#else +# define colon_uchar +#endif + class QUrlPrivate { public: - enum Section { + enum Section colon_uchar { Scheme = 0x01, UserName = 0x02, Password = 0x04, @@ -432,6 +438,10 @@ public: FullUrl = 0xff }; + enum Flags colon_uchar { + IsLocalFile = 0x01 + }; + enum ErrorCode { // the high byte of the error code matches the Section // the first item in each value must be the generic "Invalid xxx Error" @@ -519,6 +529,8 @@ public: inline bool hasQuery() const { return sectionIsPresent & Query; } inline bool hasFragment() const { return sectionIsPresent & Fragment; } + inline bool isLocalFile() const { return flags & IsLocalFile; } + QString mergePaths(const QString &relativePath) const; QAtomicInt ref; @@ -539,12 +551,18 @@ public: // - Path (there's no path delimiter, so we optimize its use out of existence) // Schemes are never supposed to be empty, but we keep the flag anyway uchar sectionIsPresent; + uchar flags; + + // 32-bit: 2 bytes tail padding available + // 64-bit: 6 bytes tail padding available }; +#undef colon_uchar inline QUrlPrivate::QUrlPrivate() : ref(1), port(-1), error(0), - sectionIsPresent(0) + sectionIsPresent(0), + flags(0) { } @@ -558,7 +576,8 @@ inline QUrlPrivate::QUrlPrivate(const QUrlPrivate ©) query(copy.query), fragment(copy.fragment), error(copy.cloneError()), - sectionIsPresent(copy.sectionIsPresent) + sectionIsPresent(copy.sectionIsPresent), + flags(copy.flags) { } @@ -956,6 +975,12 @@ inline bool QUrlPrivate::setScheme(const QString &value, int len, bool doSetErro schemeData[i] = c + 0x20; } } + + // did we set to the file protocol? + if (scheme == fileScheme()) + flags |= IsLocalFile; + else + flags &= ~IsLocalFile; return true; } @@ -1312,6 +1337,7 @@ inline void QUrlPrivate::parse(const QString &url, QUrl::ParsingMode parsingMode // / other path types here sectionIsPresent = 0; + flags = 0; clearError(); // find the important delimiters @@ -1867,6 +1893,7 @@ void QUrl::setScheme(const QString &scheme) if (scheme.isEmpty()) { // schemes are not allowed to be empty d->sectionIsPresent &= ~QUrlPrivate::Scheme; + d->flags &= ~QUrlPrivate::IsLocalFile; d->scheme.clear(); } else { d->setScheme(scheme, scheme.length(), /* do set error */ true); @@ -3104,6 +3131,7 @@ QUrl QUrl::resolved(const QUrl &relative) const t.d->sectionIsPresent |= QUrlPrivate::Scheme; else t.d->sectionIsPresent &= ~QUrlPrivate::Scheme; + t.d->flags |= d->flags & QUrlPrivate::IsLocalFile; } t.d->fragment = relative.d->fragment; if (relative.d->hasFragment()) @@ -3177,7 +3205,6 @@ QString QUrl::toString(FormattingOptions options) const // - there's no query or fragment to return // that is, either they aren't present, or we're removing them // - it's a local file - // (test done last since it's the most expensive) if (options.testFlag(QUrl::PreferLocalFile) && !options.testFlag(QUrl::RemovePath) && (!d->hasQuery() || options.testFlag(QUrl::RemoveQuery)) && (!d->hasFragment() || options.testFlag(QUrl::RemoveFragment)) @@ -3201,6 +3228,7 @@ QString QUrl::toString(FormattingOptions options) const url += QLatin1String("//"); d->appendAuthority(url, options, QUrlPrivate::FullUrl); } else if (isLocalFile() && pathIsAbsolute) { + // Comply with the XDG file URI spec, which requires triple slashes. url += QLatin1String("//"); } @@ -3755,11 +3783,7 @@ QString QUrl::toLocalFile() const */ bool QUrl::isLocalFile() const { - if (!d) return false; - - if (d->scheme != fileScheme()) - return false; // not file - return true; + return d && d->isLocalFile(); } /*! diff --git a/src/corelib/io/qurlidna.cpp b/src/corelib/io/qurlidna.cpp index bf2c07e0e0..4e9b257c7b 100644 --- a/src/corelib/io/qurlidna.cpp +++ b/src/corelib/io/qurlidna.cpp @@ -2603,7 +2603,7 @@ QStringList QUrl::idnWhitelist() Note that if you call this function, you need to do so \e before you start any threads that might access idnWhitelist(). - Qt has comes a default list that contains the Internet top-level domains + Qt comes with a default list that contains the Internet top-level domains that have published support for Internationalized Domain Names (IDNs) and rules to guarantee that no deception can happen between similarly-looking characters (such as the Latin lowercase letter \c 'a' and the Cyrillic diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 876ed8f27b..262d259136 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -3663,9 +3663,15 @@ void QMetaObject::activate(QObject *sender, int signalOffset, int local_signal_i const int method_relative = c->method_relative; if (c->isSlotObject) { c->slotObj->ref(); - const QScopedPointer<QtPrivate::QSlotObjectBase, QSlotObjectBaseDeleter> obj(c->slotObj); + QScopedPointer<QtPrivate::QSlotObjectBase, QSlotObjectBaseDeleter> obj(c->slotObj); locker.unlock(); obj->call(receiver, argv ? argv : empty_argv); + + // Make sure the slot object gets destroyed before the mutex is locked again, as the + // destructor of the slot object might also lock a mutex from the signalSlotLock() mutex pool, + // and that would deadlock if the pool happens to return the same mutex. + obj.reset(); + locker.relock(); } else if (callFunction && c->method_offset <= receiver->metaObject()->methodOffset()) { //we compare the vtable to make sure we are not in the destructor of the object. diff --git a/src/gui/image/qimage_conversions.cpp b/src/gui/image/qimage_conversions.cpp index e856959d51..629a7c9b69 100644 --- a/src/gui/image/qimage_conversions.cpp +++ b/src/gui/image/qimage_conversions.cpp @@ -1894,7 +1894,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat 0, convert_RGBA_to_RGB, convert_RGBA_to_ARGB, - convert_RGBA_to_ARGB_PM, + convert_RGBA_to_ARGB, 0, 0, 0, diff --git a/src/gui/opengl/qopengltexture.cpp b/src/gui/opengl/qopengltexture.cpp index 9a9f277b1b..61b0f3b637 100644 --- a/src/gui/opengl/qopengltexture.cpp +++ b/src/gui/opengl/qopengltexture.cpp @@ -1111,6 +1111,17 @@ QOpenGLTexture *QOpenGLTexturePrivate::createTextureView(QOpenGLTexture::Target */ /*! + \enum QOpenGLTexture::Filter + This enum defines the filtering parameters for a QOpenGLTexture object. + \value Nearest Equivalent to GL_NEAREST + \value Linear Equivalent to GL_LINEAR + \value NearestMipMapNearest Equivalent to GL_NEAREST_MIPMAP_NEAREST + \value NearestMipMapLinear Equivalent to GL_NEAREST_MIPMAP_LINEAR + \value LinearMipMapNearest Equivalent to GL_LINEAR_MIPMAP_NEAREST + \value LinearMipMapLinear Equivalent to GL_LINEAR_MIPMAP_LINEAR +*/ + +/*! \enum QOpenGLTexture::Target This enum defines the texture target of a QOpenGLTexture object. @@ -1164,7 +1175,7 @@ QOpenGLTexture *QOpenGLTexturePrivate::createTextureView(QOpenGLTexture::Target */ /*! - \enum TextureUnitReset + \enum QOpenGLTexture::TextureUnitReset This enum defines options ot control texture unit activation. \value ResetTextureUnit The previous active texture unit will be reset @@ -1320,7 +1331,7 @@ QOpenGLTexture *QOpenGLTexturePrivate::createTextureView(QOpenGLTexture::Target */ /*! - \enum PixelType + \enum QOpenGLTexture::PixelType This enum defines the possible pixel data types for a pixel transfer operation \value NoPixelType Equivalent to GL_NONE @@ -1394,7 +1405,7 @@ QOpenGLTexture *QOpenGLTexturePrivate::createTextureView(QOpenGLTexture::Target */ /*! - \enum WrapMode + \enum QOpenGLTexture::WrapMode This enum defines the possible texture coordinate wrapping modes. \value Repeat Texture coordinate is repeated. Equivalent to GL_REPEAT @@ -1405,7 +1416,7 @@ QOpenGLTexture *QOpenGLTexturePrivate::createTextureView(QOpenGLTexture::Target */ /*! - \enum CoordinateDirection + \enum QOpenGLTexture::CoordinateDirection This enum defines the possible texture coordinate directions \value DirectionS The horizontal direction. Equivalent to GL_TEXTURE_WRAP_S diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index 52a6b5d211..928ff4e670 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -5841,7 +5841,7 @@ inline void qt_bitmapblit_template(QRasterBuffer *rasterBuffer, } } -static void qt_gradient_quint32(int count, const QSpan *spans, void *userData) +static void qt_gradient_argb32(int count, const QSpan *spans, void *userData) { QSpanData *data = reinterpret_cast<QSpanData *>(userData); @@ -6298,7 +6298,7 @@ DrawHelper qDrawHelper[QImage::NImageFormats] = // Format_RGB32, { blend_color_argb, - qt_gradient_quint32, + qt_gradient_argb32, qt_bitmapblit_quint32, qt_alphamapblit_quint32, qt_alphargbblit_quint32, @@ -6307,7 +6307,7 @@ DrawHelper qDrawHelper[QImage::NImageFormats] = // Format_ARGB32, { blend_color_generic, - qt_gradient_quint32, + qt_gradient_argb32, qt_bitmapblit_quint32, qt_alphamapblit_quint32, qt_alphargbblit_quint32, @@ -6316,7 +6316,7 @@ DrawHelper qDrawHelper[QImage::NImageFormats] = // Format_ARGB32_Premultiplied { blend_color_argb, - qt_gradient_quint32, + qt_gradient_argb32, qt_bitmapblit_quint32, qt_alphamapblit_quint32, qt_alphargbblit_quint32, @@ -6382,7 +6382,7 @@ DrawHelper qDrawHelper[QImage::NImageFormats] = // Format_RGBX8888 { blend_color_generic, - qt_gradient_quint32, + blend_src_generic, qt_bitmapblit_quint32, #if Q_BYTE_ORDER == Q_LITTLE_ENDIAN qt_alphamapblit_quint32, @@ -6396,7 +6396,7 @@ DrawHelper qDrawHelper[QImage::NImageFormats] = // Format_RGBA8888 { blend_color_generic, - qt_gradient_quint32, + blend_src_generic, qt_bitmapblit_quint32, #if Q_BYTE_ORDER == Q_LITTLE_ENDIAN qt_alphamapblit_quint32, @@ -6410,7 +6410,7 @@ DrawHelper qDrawHelper[QImage::NImageFormats] = // Format_RGB8888_Premultiplied { blend_color_generic, - qt_gradient_quint32, + blend_src_generic, qt_bitmapblit_quint32, #if Q_BYTE_ORDER == Q_LITTLE_ENDIAN qt_alphamapblit_quint32, diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index 8a1096c269..ea61f257a2 100644 --- a/src/gui/text/qtextengine.cpp +++ b/src/gui/text/qtextengine.cpp @@ -919,12 +919,9 @@ void QTextEngine::shapeText(int item) const QFontEngine *fontEngine = this->fontEngine(si, &si.ascent, &si.descent, &si.leading); // split up the item into parts that come from different font engines + // k * 3 entries, array[k] == index in string, array[k + 1] == index in glyphs, array[k + 2] == engine index QVector<uint> itemBoundaries; - itemBoundaries.reserve(16); - // k * 2 entries, array[k] == index in string, array[k + 1] == index in glyphs - itemBoundaries.append(0); - itemBoundaries.append(0); - + itemBoundaries.reserve(24); if (fontEngine->type() == QFontEngine::Multi) { // ask the font engine to find out which glyphs (as an index in the specific font) // to use for the text in one item. @@ -935,22 +932,31 @@ void QTextEngine::shapeText(int item) const if (!fontEngine->stringToCMap(reinterpret_cast<const QChar *>(string), itemLength, &initialGlyphs, &nGlyphs, shaperFlags)) Q_UNREACHABLE(); - uint lastEngine = 0; + uint lastEngine = ~0u; for (int i = 0, glyph_pos = 0; i < itemLength; ++i, ++glyph_pos) { const uint engineIdx = initialGlyphs.glyphs[glyph_pos] >> 24; - if (lastEngine != engineIdx && glyph_pos > 0) { + if (lastEngine != engineIdx) { itemBoundaries.append(i); itemBoundaries.append(glyph_pos); + itemBoundaries.append(engineIdx); + + if (engineIdx != 0) { + QFontEngine *actualFontEngine = static_cast<QFontEngineMulti *>(fontEngine)->engine(engineIdx); + si.ascent = qMax(actualFontEngine->ascent(), si.ascent); + si.descent = qMax(actualFontEngine->descent(), si.descent); + si.leading = qMax(actualFontEngine->leading(), si.leading); + } - QFontEngine *actualFontEngine = static_cast<QFontEngineMulti *>(fontEngine)->engine(engineIdx); - si.ascent = qMax(actualFontEngine->ascent(), si.ascent); - si.descent = qMax(actualFontEngine->descent(), si.descent); - si.leading = qMax(actualFontEngine->leading(), si.leading); + lastEngine = engineIdx; } - lastEngine = engineIdx; + if (QChar::isHighSurrogate(string[i]) && i + 1 < itemLength && QChar::isLowSurrogate(string[i + 1])) ++i; } + } else { + itemBoundaries.append(0); + itemBoundaries.append(0); + itemBoundaries.append(0); } bool kerningEnabled; @@ -1027,16 +1033,6 @@ void QTextEngine::shapeText(int item) const si.width += glyphs.advances[i] * !glyphs.attributes[i].dontPrint; } -static inline void moveGlyphData(const QGlyphLayout &destination, const QGlyphLayout &source, int num) -{ - if (num > 0 && destination.glyphs != source.glyphs) { - memmove(destination.glyphs, source.glyphs, num * sizeof(glyph_t)); - memmove(destination.attributes, source.attributes, num * sizeof(QGlyphAttributes)); - memmove(destination.advances, source.advances, num * sizeof(QFixed)); - memmove(destination.offsets, source.offsets, num * sizeof(QFixedPoint)); - } -} - #ifdef QT_ENABLE_HARFBUZZ_NG QT_BEGIN_INCLUDE_NAMESPACE @@ -1063,20 +1059,15 @@ int QTextEngine::shapeTextWithHarfbuzzNG(const QScriptItem &si, const ushort *st uint glyphs_shaped = 0; int remaining_glyphs = itemLength; - for (int k = 0; k < itemBoundaries.size(); k += 2) { // for the +2, see the comment at the definition of itemBoundaries + for (int k = 0; k < itemBoundaries.size(); k += 3) { uint item_pos = itemBoundaries[k]; - uint item_length = itemLength; + uint item_length = (k + 4 < itemBoundaries.size() ? itemBoundaries[k + 3] : itemLength) - item_pos; uint item_glyph_pos = itemBoundaries[k + 1]; - if (k + 3 < itemBoundaries.size()) - item_length = itemBoundaries[k + 2]; - item_length -= item_pos; + uint engineIdx = itemBoundaries[k + 2]; QFontEngine *actualFontEngine = fontEngine; - uint engineIdx = 0; - if (fontEngine->type() == QFontEngine::Multi) { - engineIdx = availableGlyphs(&si).glyphs[glyphs_shaped] >> 24; + if (fontEngine->type() == QFontEngine::Multi) actualFontEngine = static_cast<QFontEngineMulti *>(fontEngine)->engine(engineIdx); - } // prepare buffer @@ -1093,18 +1084,6 @@ int QTextEngine::shapeTextWithHarfbuzzNG(const QScriptItem &si, const ushort *st buffer_flags |= HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES; hb_buffer_set_flags(buffer, hb_buffer_flags_t(buffer_flags)); - const uint num_codes = hb_buffer_get_length(buffer); - { - // adjust clusters - hb_glyph_info_t *infos = hb_buffer_get_glyph_infos(buffer, 0); - const ushort *uc = string + item_pos; - for (uint i = 0, code_pos = 0; i < item_length; ++i, ++code_pos) { - if (QChar::isHighSurrogate(uc[i]) && i + 1 < item_length && QChar::isLowSurrogate(uc[i + 1])) - ++i; - infos[code_pos].cluster = code_pos + item_glyph_pos; - } - } - // shape bool shapedOk = false; @@ -1127,8 +1106,7 @@ int QTextEngine::shapeTextWithHarfbuzzNG(const QScriptItem &si, const ushort *st if (si.analysis.bidiLevel % 2) hb_buffer_reverse(buffer); - - remaining_glyphs -= num_codes; + remaining_glyphs -= item_glyph_pos; // ensure we have enough space for shaped glyphs and metrics const uint num_glyphs = hb_buffer_get_length(buffer); @@ -1139,43 +1117,33 @@ int QTextEngine::shapeTextWithHarfbuzzNG(const QScriptItem &si, const ushort *st // fetch the shaped glyphs and metrics QGlyphLayout g = availableGlyphs(&si).mid(glyphs_shaped, num_glyphs); - if (num_glyphs > num_codes) - moveGlyphData(g.mid(num_glyphs), g.mid(num_codes), remaining_glyphs); ushort *log_clusters = logClusters(&si) + item_pos; hb_glyph_info_t *infos = hb_buffer_get_glyph_infos(buffer, 0); hb_glyph_position_t *positions = hb_buffer_get_glyph_positions(buffer, 0); - uint last_cluster = -1; + uint str_pos = 0; + uint last_cluster = ~0u; + uint last_glyph_pos = glyphs_shaped; for (uint i = 0; i < num_glyphs; ++i) { g.glyphs[i] = infos[i].codepoint; - log_clusters[i] = infos[i].cluster; g.advances[i] = QFixed::fromFixed(positions[i].x_advance); g.offsets[i].x = QFixed::fromFixed(positions[i].x_offset); g.offsets[i].y = QFixed::fromFixed(positions[i].y_offset); - if (infos[i].cluster != last_cluster) { - last_cluster = infos[i].cluster; + uint cluster = infos[i].cluster; + if (last_cluster != cluster) { + // fix up clusters so that the cluster indices will be monotonic + // and thus we never return out-of-order indices + while (last_cluster++ < cluster && str_pos < item_length) + log_clusters[str_pos++] = last_glyph_pos; + last_glyph_pos = i + glyphs_shaped; + last_cluster = cluster; g.attributes[i].clusterStart = true; } } - - { - // adjust clusters - uint glyph_pos = 0; - for (uint i = 0; i < item_length; ++i) { - if (i + item_pos != infos[glyph_pos].cluster) { - for (uint j = glyph_pos + 1; j < num_glyphs; ++j) { - if (i + item_pos <= infos[j].cluster) { - if (i + item_pos == infos[j].cluster) - glyph_pos = j; - break; - } - } - } - log_clusters[i] = glyph_pos + item_glyph_pos; - } - } + while (str_pos < item_length) + log_clusters[str_pos++] = last_glyph_pos; if (engineIdx != 0) { for (quint32 i = 0; i < num_glyphs; ++i) @@ -1211,6 +1179,12 @@ Q_STATIC_ASSERT(sizeof(HB_GlyphAttributes) == sizeof(QGlyphAttributes)); Q_STATIC_ASSERT(sizeof(HB_Fixed) == sizeof(QFixed)); Q_STATIC_ASSERT(sizeof(HB_FixedPoint) == sizeof(QFixedPoint)); +static inline void moveGlyphData(const QGlyphLayout &destination, const QGlyphLayout &source, int num) +{ + if (num > 0 && destination.glyphs != source.glyphs) + memmove(destination.glyphs, source.glyphs, num * sizeof(glyph_t)); +} + int QTextEngine::shapeTextWithHarfbuzz(const QScriptItem &si, const ushort *string, int itemLength, QFontEngine *fontEngine, const QVector<uint> &itemBoundaries, bool kerningEnabled) const { HB_ShaperItem entire_shaper_item; @@ -1239,14 +1213,12 @@ int QTextEngine::shapeTextWithHarfbuzz(const QScriptItem &si, const ushort *stri int remaining_glyphs = entire_shaper_item.num_glyphs; int glyph_pos = 0; // for each item shape using harfbuzz and store the results in our layoutData's glyphs array. - for (int k = 0; k < itemBoundaries.size(); k += 2) { // for the +2, see the comment at the definition of itemBoundaries - + for (int k = 0; k < itemBoundaries.size(); k += 3) { HB_ShaperItem shaper_item = entire_shaper_item; - shaper_item.item.pos = itemBoundaries[k]; - if (k < itemBoundaries.size() - 3) { - shaper_item.item.length = itemBoundaries[k + 2] - shaper_item.item.pos; - shaper_item.num_glyphs = itemBoundaries[k + 3] - itemBoundaries[k + 1]; + if (k + 4 < itemBoundaries.size()) { + shaper_item.item.length = itemBoundaries[k + 3] - shaper_item.item.pos; + shaper_item.num_glyphs = itemBoundaries[k + 4] - itemBoundaries[k + 1]; } else { // last combo in the list, avoid out of bounds access. shaper_item.item.length -= shaper_item.item.pos - entire_shaper_item.item.pos; shaper_item.num_glyphs -= itemBoundaries[k + 1]; @@ -1255,10 +1227,9 @@ int QTextEngine::shapeTextWithHarfbuzz(const QScriptItem &si, const ushort *stri if (shaper_item.num_glyphs < shaper_item.item.length) shaper_item.num_glyphs = shaper_item.item.length; + uint engineIdx = itemBoundaries[k + 2]; QFontEngine *actualFontEngine = fontEngine; - uint engineIdx = 0; if (fontEngine->type() == QFontEngine::Multi) { - engineIdx = uint(availableGlyphs(&si).glyphs[glyph_pos] >> 24); actualFontEngine = static_cast<QFontEngineMulti *>(fontEngine)->engine(engineIdx); if ((si.analysis.bidiLevel % 2) == 0) @@ -1275,7 +1246,7 @@ int QTextEngine::shapeTextWithHarfbuzz(const QScriptItem &si, const ushort *stri return 0; const QGlyphLayout g = availableGlyphs(&si).mid(glyph_pos); - if (shaper_item.num_glyphs > shaper_item.item.length) + if (fontEngine->type() == QFontEngine::Multi && shaper_item.num_glyphs > shaper_item.item.length) moveGlyphData(g.mid(shaper_item.num_glyphs), g.mid(shaper_item.initialGlyphCount), remaining_glyphs); shaper_item.glyphs = reinterpret_cast<HB_Glyph *>(g.glyphs); @@ -1292,7 +1263,8 @@ int QTextEngine::shapeTextWithHarfbuzz(const QScriptItem &si, const ushort *stri } while (!qShapeItem(&shaper_item)); // this does the actual shaping via harfbuzz. QGlyphLayout g = availableGlyphs(&si).mid(glyph_pos, shaper_item.num_glyphs); - moveGlyphData(g.mid(shaper_item.num_glyphs), g.mid(shaper_item.initialGlyphCount), remaining_glyphs); + if (fontEngine->type() == QFontEngine::Multi) + moveGlyphData(g.mid(shaper_item.num_glyphs), g.mid(shaper_item.initialGlyphCount), remaining_glyphs); for (quint32 i = 0; i < shaper_item.item.length; ++i) shaper_item.log_clusters[i] += glyph_pos; diff --git a/src/network/ssl/qsslcertificate.cpp b/src/network/ssl/qsslcertificate.cpp index b4c593fa73..3b7fa4da09 100644 --- a/src/network/ssl/qsslcertificate.cpp +++ b/src/network/ssl/qsslcertificate.cpp @@ -341,8 +341,9 @@ static QByteArray _q_SubjectInfoToString(QSslCertificate::SubjectInfo info) \fn QString QSslCertificate::issuerInfo(SubjectInfo subject) const Returns the issuer information for the \a subject from the - certificate, or an empty string if there is no information for - \a subject in the certificate. + certificate, or an empty list if there is no information for + \a subject in the certificate. There can be more than one entry + of each type. \sa subjectInfo() */ @@ -359,8 +360,8 @@ QStringList QSslCertificate::issuerInfo(SubjectInfo info) const /*! Returns the issuer information for \a attribute from the certificate, - or an empty string if there is no information for \a attribute in the - certificate. + or an empty list if there is no information for \a attribute in the + certificate. There can be more than one entry for an attribute. \sa subjectInfo() */ @@ -379,8 +380,9 @@ QStringList QSslCertificate::issuerInfo(const QByteArray &attribute) const \fn QString QSslCertificate::subjectInfo(SubjectInfo subject) const - Returns the information for the \a subject, or an empty string if - there is no information for \a subject in the certificate. + Returns the information for the \a subject, or an empty list if + there is no information for \a subject in the certificate. There + can be more than one entry of each type. \sa issuerInfo() */ @@ -396,8 +398,9 @@ QStringList QSslCertificate::subjectInfo(SubjectInfo info) const } /*! - Returns the subject information for \a attribute, or an empty string if - there is no information for \a attribute in the certificate. + Returns the subject information for \a attribute, or an empty list if + there is no information for \a attribute in the certificate. There + can be more than one entry for an attribute. \sa issuerInfo() */ diff --git a/src/opengl/qgraphicsshadereffect.cpp b/src/opengl/qgraphicsshadereffect.cpp index 739be17ef3..736bf10f2e 100644 --- a/src/opengl/qgraphicsshadereffect.cpp +++ b/src/opengl/qgraphicsshadereffect.cpp @@ -40,6 +40,9 @@ ****************************************************************************/ #include "qgraphicsshadereffect_p.h" + +#ifndef QT_NO_GRAPHICSEFFECT + #include "qglshaderprogram.h" #include "gl2paintengineex/qglcustomshaderstage_p.h" #define QGL_HAVE_CUSTOM_SHADERS 1 @@ -311,3 +314,5 @@ void QGraphicsShaderEffect::setUniforms(QGLShaderProgram *program) } QT_END_NAMESPACE + +#endif // QT_NO_GRAPHICSEFFECT diff --git a/src/opengl/qgraphicsshadereffect_p.h b/src/opengl/qgraphicsshadereffect_p.h index 8a7c082afa..3f879fc2d2 100644 --- a/src/opengl/qgraphicsshadereffect_p.h +++ b/src/opengl/qgraphicsshadereffect_p.h @@ -54,6 +54,9 @@ // #include <QtWidgets/qgraphicseffect.h> + +#ifndef QT_NO_GRAPHICSEFFECT + #include <QtOpenGL/qtopenglglobal.h> QT_BEGIN_NAMESPACE @@ -87,4 +90,6 @@ private: QT_END_NAMESPACE +#endif // QT_NO_GRAPHICSEFFECT + #endif // QGRAPHICSSHADEREFFECT_P_H diff --git a/src/platformsupport/linuxaccessibility/atspiadaptor.cpp b/src/platformsupport/linuxaccessibility/atspiadaptor.cpp index 8850f18bab..1ccab0a859 100644 --- a/src/platformsupport/linuxaccessibility/atspiadaptor.cpp +++ b/src/platformsupport/linuxaccessibility/atspiadaptor.cpp @@ -1391,13 +1391,6 @@ bool AtSpiAdaptor::accessibleInterface(QAccessibleInterface *interface, const QS if (interface->tableInterface()) { setSpiStateBit(&spiState, ATSPI_STATE_MANAGES_DESCENDANTS); } -// FIXME: figure out if this is a top level window and set its active state accordingly -// if (interface->object() && interface->object()->isWidgetType()) { -// QWidget *w = qobject_cast<QWidget*>(interface->object()); -// if (w->topLevelWidget() && w->isActiveWindow()) { -// setSpiStateBit(&spiState, ATSPI_STATE_ACTIVE); -// } -// } QAccessible::Role role = interface->role(); if (role == QAccessible::TreeItem || role == QAccessible::ListItem) { diff --git a/src/platformsupport/linuxaccessibility/constant_mappings.cpp b/src/platformsupport/linuxaccessibility/constant_mappings.cpp index f8bfaf4753..9de667158b 100644 --- a/src/platformsupport/linuxaccessibility/constant_mappings.cpp +++ b/src/platformsupport/linuxaccessibility/constant_mappings.cpp @@ -61,6 +61,8 @@ quint64 spiStatesFromQState(QAccessible::State state) { quint64 spiState = 0; + if (state.active) + setSpiStateBit(&spiState, ATSPI_STATE_ACTIVE); if (state.editable) setSpiStateBit(&spiState, ATSPI_STATE_EDITABLE); if (!state.disabled) { diff --git a/src/plugins/accessible/widgets/itemviews.cpp b/src/plugins/accessible/widgets/itemviews.cpp index 7cd47f3fec..7d3668ee5a 100644 --- a/src/plugins/accessible/widgets/itemviews.cpp +++ b/src/plugins/accessible/widgets/itemviews.cpp @@ -1069,7 +1069,6 @@ QString QAccessibleTableCell::text(QAccessible::Text t) const QAbstractItemModel *model = view->model(); QString value; switch (t) { - case QAccessible::Value: case QAccessible::Name: value = model->data(m_index, Qt::AccessibleTextRole).toString(); if (value.isEmpty()) @@ -1161,7 +1160,6 @@ QString QAccessibleTableHeaderCell::text(QAccessible::Text t) const QAbstractItemModel *model = view->model(); QString value; switch (t) { - case QAccessible::Value: case QAccessible::Name: value = model->headerData(index, orientation, Qt::AccessibleTextRole).toString(); if (value.isEmpty()) diff --git a/src/plugins/accessible/widgets/qaccessiblewidgets.cpp b/src/plugins/accessible/widgets/qaccessiblewidgets.cpp index 79a5c82fe0..71d22eabc4 100644 --- a/src/plugins/accessible/widgets/qaccessiblewidgets.cpp +++ b/src/plugins/accessible/widgets/qaccessiblewidgets.cpp @@ -631,7 +631,7 @@ QDockWidget *QAccessibleDockWidget::dockWidget() const QString QAccessibleDockWidget::text(QAccessible::Text t) const { - if (t == QAccessible::Name || t == QAccessible::Value) { + if (t == QAccessible::Name) { return qt_accStripAmp(dockWidget()->windowTitle()); } return QString(); diff --git a/src/plugins/accessible/widgets/simplewidgets.cpp b/src/plugins/accessible/widgets/simplewidgets.cpp index c275ec071d..893be2df04 100644 --- a/src/plugins/accessible/widgets/simplewidgets.cpp +++ b/src/plugins/accessible/widgets/simplewidgets.cpp @@ -507,8 +507,10 @@ QString QAccessibleGroupBox::text(QAccessible::Text t) const switch (t) { case QAccessible::Name: txt = qt_accStripAmp(groupBox()->title()); + break; case QAccessible::Description: - txt = qt_accStripAmp(groupBox()->title()); + txt = qt_accStripAmp(groupBox()->toolTip()); + break; default: break; } diff --git a/src/plugins/generic/tslib/qtslib.cpp b/src/plugins/generic/tslib/qtslib.cpp index 773939b485..9905d9cc9e 100644 --- a/src/plugins/generic/tslib/qtslib.cpp +++ b/src/plugins/generic/tslib/qtslib.cpp @@ -48,8 +48,6 @@ #include <QPoint> #include <qpa/qwindowsysteminterface.h> -#include <Qt> - #include <errno.h> #include <tslib.h> @@ -65,21 +63,21 @@ QTsLibMouseHandler::QTsLibMouseHandler(const QString &key, setObjectName(QLatin1String("TSLib Mouse Handler")); QByteArray device = qgetenv("TSLIB_TSDEVICE"); - if (device.isEmpty()) - device = QByteArrayLiteral("/dev/input/event1"); if (specification.startsWith("/dev/")) device = specification.toLocal8Bit(); + if (device.isEmpty()) + device = QByteArrayLiteral("/dev/input/event1"); + m_dev = ts_open(device.constData(), 1); if (!m_dev) { qErrnoWarning(errno, "ts_open() failed"); return; } - if (ts_config(m_dev)) { + if (ts_config(m_dev)) perror("Error configuring\n"); - } m_rawMode = !key.compare(QLatin1String("TslibRaw"), Qt::CaseInsensitive); @@ -89,7 +87,6 @@ QTsLibMouseHandler::QTsLibMouseHandler(const QString &key, connect(m_notify, SIGNAL(activated(int)), this, SLOT(readMouseData())); } else { qWarning("Cannot open mouse input device '%s': %s", device.constData(), strerror(errno)); - return; } } @@ -103,12 +100,10 @@ QTsLibMouseHandler::~QTsLibMouseHandler() static bool get_sample(struct tsdev *dev, struct ts_sample *sample, bool rawMode) { - if (rawMode) { + if (rawMode) return (ts_read_raw(dev, sample, 1) == 1); - } else { - int ret = ts_read(dev, sample, 1); - return ( ret == 1); - } + else + return (ts_read(dev, sample, 1) == 1); } diff --git a/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.cpp b/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.cpp index 121e734ec1..e2810c8448 100644 --- a/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.cpp +++ b/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.cpp @@ -347,7 +347,7 @@ ushort TableGenerator::keysymToUtf8(quint32 sym) qDebug() << QString("keysym - 0x%1 : utf8 - %2").arg(QString::number(sym, 16)) .arg(codec->toUnicode(chars)); #endif - return QString::fromLocal8Bit(chars).at(0).unicode(); + return QString::fromUtf8(chars).at(0).unicode(); } static inline int fromBase8(const char *s, const char *end) diff --git a/src/plugins/platforms/linuxfb/qlinuxfbscreen.cpp b/src/plugins/platforms/linuxfb/qlinuxfbscreen.cpp index c0691a38fc..5af84918d9 100644 --- a/src/plugins/platforms/linuxfb/qlinuxfbscreen.cpp +++ b/src/plugins/platforms/linuxfb/qlinuxfbscreen.cpp @@ -335,6 +335,8 @@ bool QLinuxFbScreen::initialize() QRegularExpressionMatch match; if (arg == QLatin1String("nographicsmodeswitch")) doSwitchToGraphicsMode = false; + else if (arg.contains(mmSizeRx, &match)) + userMmSize = QSize(match.captured(1).toInt(), match.captured(2).toInt()); else if (arg.contains(sizeRx, &match)) userGeometry.setSize(QSize(match.captured(1).toInt(), match.captured(2).toInt())); else if (arg.contains(offsetRx, &match)) @@ -343,8 +345,6 @@ bool QLinuxFbScreen::initialize() ttyDevice = match.captured(1); else if (arg.contains(fbRx, &match)) fbDevice = match.captured(1); - else if (arg.contains(mmSizeRx, &match)) - userMmSize = QSize(match.captured(1).toInt(), match.captured(2).toInt()); } if (fbDevice.isEmpty()) { diff --git a/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp index 49d4a712d8..bda806d102 100644 --- a/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp +++ b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp @@ -1012,6 +1012,8 @@ HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accState(VARIANT varID, VA st |= STATE_SYSTEM_SIZEABLE; if (state.traversed) st |= STATE_SYSTEM_TRAVERSED; + if (state.disabled) + st |= STATE_SYSTEM_UNAVAILABLE; (*pvarState).vt = VT_I4; (*pvarState).lVal = st; diff --git a/src/printsupport/kernel/qprintengine_win.cpp b/src/printsupport/kernel/qprintengine_win.cpp index da328418b7..74484bfc8c 100644 --- a/src/printsupport/kernel/qprintengine_win.cpp +++ b/src/printsupport/kernel/qprintengine_win.cpp @@ -1993,13 +1993,17 @@ static void draw_text_item_win(const QPointF &pos, const QTextItemInt &ti, HDC h void QWin32PrintEnginePrivate::updateCustomPaperSize() { const uint paperSize = devMode->dmPaperSize; + const double multiplier = qt_multiplierForUnit(QPrinter::Millimeter, resolution); has_custom_paper_size = false; - if (paperSize > 0 && mapDevmodePaperSize(paperSize) == QPrinter::Custom) { + if (paperSize == DMPAPER_USER) { + has_custom_paper_size = true; + paper_size = QSizeF((devMode->dmPaperWidth / 10.0) * multiplier, (devMode->dmPaperLength / 10.0) * multiplier); + } else if (mapDevmodePaperSize(paperSize) == QPrinter::Custom) { has_custom_paper_size = true; const QList<QPair<QSizeF, int> > paperSizes = printerPaperSizes(name); for (int i=0; i<paperSizes.size(); i++) { if ((uint)paperSizes.at(i).second == paperSize) { - paper_size = paperSizes.at(i).first; + paper_size = paperSizes.at(i).first * multiplier; has_custom_paper_size = false; break; } diff --git a/src/tools/moc/main.cpp b/src/tools/moc/main.cpp index 5ab1fcd100..bdeb5477a7 100644 --- a/src/tools/moc/main.cpp +++ b/src/tools/moc/main.cpp @@ -258,7 +258,7 @@ int runMoc(int argc, char **argv) parser.addOption(pathPrefixOption); QCommandLineOption forceIncludeOption(QStringLiteral("f")); - forceIncludeOption.setDescription(QStringLiteral("Force #include [optional <file>] (overwrite default).")); + forceIncludeOption.setDescription(QStringLiteral("Force #include <file> (overwrite default).")); forceIncludeOption.setValueName(QStringLiteral("file")); parser.addOption(forceIncludeOption); diff --git a/src/tools/qdoc/generator.cpp b/src/tools/qdoc/generator.cpp index b14a79dfab..71c550d4ab 100644 --- a/src/tools/qdoc/generator.cpp +++ b/src/tools/qdoc/generator.cpp @@ -246,16 +246,15 @@ QMultiMap<QString,QString> outFileNames; */ void Generator::writeOutFileNames() { - QFile* files = new QFile("/Users/msmith/depot/qt5/qtdoc/outputlist.txt"); - files->open(QFile::WriteOnly); - QTextStream* filesout = new QTextStream(files); + QFile files("outputlist.txt"); + if (!files.open(QFile::WriteOnly)) + return; + QTextStream filesout(&files); QMultiMap<QString,QString>::ConstIterator i = outFileNames.begin(); while (i != outFileNames.end()) { - (*filesout) << i.key() << "\n"; + filesout << i.key() << "\n"; ++i; } - filesout->flush(); - files->close(); } /*! diff --git a/src/widgets/accessible/qaccessiblewidget.cpp b/src/widgets/accessible/qaccessiblewidget.cpp index 7b32cae54f..4e5fade3f4 100644 --- a/src/widgets/accessible/qaccessiblewidget.cpp +++ b/src/widgets/accessible/qaccessiblewidget.cpp @@ -425,10 +425,9 @@ QString QAccessibleWidget::text(QAccessible::Text t) const } break; case QAccessible::Description: - if (!widget()->accessibleDescription().isEmpty()) - str = widget()->accessibleDescription(); + str = widget()->accessibleDescription(); #ifndef QT_NO_TOOLTIP - else + if (str.isEmpty()) str = widget()->toolTip(); #endif break; diff --git a/src/widgets/dialogs/qfiledialog.cpp b/src/widgets/dialogs/qfiledialog.cpp index 804331b1cd..1c580ce143 100644 --- a/src/widgets/dialogs/qfiledialog.cpp +++ b/src/widgets/dialogs/qfiledialog.cpp @@ -627,7 +627,8 @@ void QFileDialogPrivate::helperPrepareShow(QPlatformDialogHelper *) options->setInitialDirectory(directory.exists() ? QUrl::fromLocalFile(directory.absolutePath()) : QUrl()); - options->setInitiallySelectedNameFilter(q->selectedNameFilter()); + if (options->initiallySelectedNameFilter().isEmpty()) + options->setInitiallySelectedNameFilter(q->selectedNameFilter()); if (options->initiallySelectedFiles().isEmpty()) options->setInitiallySelectedFiles(userSelectedFiles()); } @@ -1450,6 +1451,7 @@ QStringList QFileDialog::nameFilters() const void QFileDialog::selectNameFilter(const QString &filter) { Q_D(QFileDialog); + d->options->setInitiallySelectedNameFilter(filter); if (!d->usingWidgets()) { d->selectNameFilter_sys(filter); return; diff --git a/src/widgets/itemviews/qtablewidget.cpp b/src/widgets/itemviews/qtablewidget.cpp index 71034f6165..bec690d0d0 100644 --- a/src/widgets/itemviews/qtablewidget.cpp +++ b/src/widgets/itemviews/qtablewidget.cpp @@ -2515,7 +2515,9 @@ void QTableWidget::removeColumn(int column) /*! Removes all items in the view. - This will also remove all selections. + This will also remove all selections and headers. + If you don't want to remove the headers, use + QTableWidget::clearContents(). The table dimensions stay the same. */ diff --git a/src/widgets/widgets/qtextedit.cpp b/src/widgets/widgets/qtextedit.cpp index e4a705464a..cc7b44d082 100644 --- a/src/widgets/widgets/qtextedit.cpp +++ b/src/widgets/widgets/qtextedit.cpp @@ -755,8 +755,8 @@ Qt::Alignment QTextEdit::alignment() const \note The editor \e{does not take ownership of the document} unless it is the document's parent object. The parent object of the provided document - remains the owner of the object. The editor does not delete any previously - assigned document, even if it is a child of the editor. + remains the owner of the object. If the previously assigned document is a + child of the editor then it will be deleted. */ void QTextEdit::setDocument(QTextDocument *document) { diff --git a/src/widgets/widgets/qtoolbutton.cpp b/src/widgets/widgets/qtoolbutton.cpp index f08689cb9b..497bc52109 100644 --- a/src/widgets/widgets/qtoolbutton.cpp +++ b/src/widgets/widgets/qtoolbutton.cpp @@ -778,15 +778,16 @@ void QToolButtonPrivate::popupTimerDone() actualMenu->d_func()->causedPopup.action = defaultAction; actionsCopy = q->actions(); //(the list of action may be modified in slots) actualMenu->exec(p); + + if (!that) + return; + QObject::disconnect(actualMenu, SIGNAL(aboutToHide()), q, SLOT(_q_updateButtonDown())); if (mustDeleteActualMenu) delete actualMenu; else QObject::disconnect(actualMenu, SIGNAL(triggered(QAction*)), q, SLOT(_q_menuTriggered(QAction*))); - if (!that) - return; - actionsCopy.clear(); if (repeat) diff --git a/tests/auto/corelib/global/qglobal/tst_qglobal.cpp b/tests/auto/corelib/global/qglobal/tst_qglobal.cpp index 0d08e912f8..4eb3e4fc98 100644 --- a/tests/auto/corelib/global/qglobal/tst_qglobal.cpp +++ b/tests/auto/corelib/global/qglobal/tst_qglobal.cpp @@ -101,6 +101,13 @@ void tst_QGlobal::for_each() QCOMPARE(i, counter++); } QCOMPARE(counter, list.count()); + + // check whether we can pass a constructor as container argument + counter = 0; + foreach (int i, QList<int>(list)) { + QCOMPARE(i, counter++); + } + QCOMPARE(counter, list.count()); } void tst_QGlobal::qassert() diff --git a/tests/auto/corelib/io/qstandardpaths/tst_qstandardpaths.cpp b/tests/auto/corelib/io/qstandardpaths/tst_qstandardpaths.cpp index 20a31fc98f..7247b02498 100644 --- a/tests/auto/corelib/io/qstandardpaths/tst_qstandardpaths.cpp +++ b/tests/auto/corelib/io/qstandardpaths/tst_qstandardpaths.cpp @@ -77,6 +77,7 @@ private slots: void testAllWritableLocations_data(); void testAllWritableLocations(); void testCleanPath(); + void testXdgPathCleanup(); private: #ifdef Q_XDG_PLATFORM @@ -477,6 +478,8 @@ void tst_qstandardpaths::testAllWritableLocations() QString loc = QStandardPaths::writableLocation(location); if (loc.size() > 1) // workaround for unlikely case of locations that return '/' QCOMPARE(loc.endsWith(QLatin1Char('/')), false); + QVERIFY(loc.contains(QLatin1Char('/'))); + QVERIFY(!loc.contains(QLatin1Char('\\'))); } void tst_qstandardpaths::testCleanPath() @@ -491,6 +494,19 @@ void tst_qstandardpaths::testCleanPath() } } +void tst_qstandardpaths::testXdgPathCleanup() +{ +#ifdef Q_XDG_PLATFORM + setCustomLocations(); + const QString uncleanGlobalAppDir = "/./" + QFile::encodeName(m_globalAppDir); + qputenv("XDG_DATA_DIRS", QFile::encodeName(uncleanGlobalAppDir) + "::relative/path"); + const QStringList appsDirs = QStandardPaths::standardLocations(QStandardPaths::ApplicationsLocation); + QVERIFY(!appsDirs.contains("/applications")); + QVERIFY(!appsDirs.contains(uncleanGlobalAppDir + "/applications")); + QVERIFY(!appsDirs.contains("relative/path/applications")); +#endif +} + QTEST_MAIN(tst_qstandardpaths) #include "tst_qstandardpaths.moc" diff --git a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp index ac8aae8d3a..1c0a495116 100644 --- a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp +++ b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp @@ -147,6 +147,7 @@ private slots: void connectFunctorOverloads(); void connectFunctorQueued(); void connectFunctorWithContext(); + void connectFunctorDeadlock(); void connectStaticSlotWithObject(); void disconnectDoesNotLeakFunctor(); void contextDoesNotLeakFunctor(); @@ -5740,6 +5741,47 @@ void tst_QObject::connectFunctorWithContext() context->deleteLater(); } +class MyFunctor +{ +public: + explicit MyFunctor(QObject *objectToDisconnect) + : m_objectToDisconnect(objectToDisconnect) + {} + + ~MyFunctor() { + // Do operations that will lock the internal signalSlotLock mutex on many QObjects. + // The more QObjects, the higher the chance that the signalSlotLock mutex used + // is already in use. If the number of objects is higher than the number of mutexes in + // the pool (currently 131), the deadlock should always trigger. Use an even higher number + // to be on the safe side. + const int objectCount = 1024; + SenderObject lotsOfObjects[objectCount]; + for (int i = 0; i < objectCount; ++i) { + QObject::connect(&lotsOfObjects[i], &SenderObject::signal1, + &lotsOfObjects[i], &SenderObject::aPublicSlot); + } + } + + void operator()() { + // This will cause the slot object associated with this functor to be destroyed after + // this function returns. That in turn will destroy this functor. + // If our dtor runs with the signalSlotLock held, the bunch of connect() + // performed there will deadlock trying to lock that lock again. + m_objectToDisconnect->disconnect(); + } + +private: + QObject *m_objectToDisconnect; +}; + +void tst_QObject::connectFunctorDeadlock() +{ + SenderObject sender; + MyFunctor functor(&sender); + QObject::connect(&sender, &SenderObject::signal1, functor); + sender.emitSignal1(); +} + static int s_static_slot_checker = 1; class StaticSlotChecker : public QObject diff --git a/tests/auto/gui/painting/qpainter/tst_qpainter.cpp b/tests/auto/gui/painting/qpainter/tst_qpainter.cpp index 91c06ab0b2..e4340451ce 100644 --- a/tests/auto/gui/painting/qpainter/tst_qpainter.cpp +++ b/tests/auto/gui/painting/qpainter/tst_qpainter.cpp @@ -202,6 +202,9 @@ private slots: void linearGradientSymmetry(); void gradientInterpolation(); + void gradientPixelFormat_data(); + void gradientPixelFormat(); + void fpe_pixmapTransform(); void fpe_zeroLengthLines(); void fpe_divByZero(); @@ -3727,6 +3730,49 @@ void tst_QPainter::linearGradientSymmetry() QCOMPARE(a, b); } +void tst_QPainter::gradientPixelFormat_data() +{ + QTest::addColumn<QImage::Format>("format"); + + QTest::newRow("argb32") << QImage::Format_ARGB32; + QTest::newRow("rgb32") << QImage::Format_RGB32; + QTest::newRow("rgb888") << QImage::Format_RGB888; + QTest::newRow("rgbx8888") << QImage::Format_RGBX8888; + QTest::newRow("rgba8888") << QImage::Format_RGBA8888; + QTest::newRow("rgba8888_pm") << QImage::Format_RGBA8888_Premultiplied; +} + +void tst_QPainter::gradientPixelFormat() +{ + QFETCH(QImage::Format, format); + + QImage a(8, 64, QImage::Format_ARGB32_Premultiplied); + QImage b(8, 64, format); + + + QGradientStops stops; + stops << qMakePair(qreal(0.0), QColor(Qt::blue)); + stops << qMakePair(qreal(0.3), QColor(Qt::red)); + stops << qMakePair(qreal(0.6), QColor(Qt::green)); + stops << qMakePair(qreal(1.0), QColor(Qt::black)); + + a.fill(0); + b.fill(0); + + QLinearGradient gradient(QRectF(b.rect()).topLeft(), QRectF(b.rect()).bottomLeft()); + gradient.setStops(stops); + + QPainter pa(&a); + pa.fillRect(a.rect(), gradient); + pa.end(); + + QPainter pb(&b); + pb.fillRect(b.rect(), gradient); + pb.end(); + + QCOMPARE(a, b.convertToFormat(QImage::Format_ARGB32_Premultiplied)); +} + void tst_QPainter::gradientInterpolation() { QImage image(256, 8, QImage::Format_ARGB32_Premultiplied); diff --git a/tests/auto/network/access/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp b/tests/auto/network/access/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp index 47ab7c2e99..8e0090e486 100644 --- a/tests/auto/network/access/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp +++ b/tests/auto/network/access/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp @@ -160,7 +160,6 @@ void tst_QHttpNetworkConnection::head_data() QTest::addColumn<int>("contentLength"); QTest::newRow("success-internal") << "http://" << QtNetworkSettings::serverName() << "/qtest/rfc3252.txt" << ushort(80) << false << 200 << "OK" << 25962; - QTest::newRow("success-external") << "http://" << "www.ietf.org" << "/rfc/rfc3252.txt" << ushort(80) << false << 200 << "OK" << 25962; QTest::newRow("failure-path") << "http://" << QtNetworkSettings::serverName() << "/t" << ushort(80) << false << 404 << "Not Found" << -1; QTest::newRow("failure-protocol") << "" << QtNetworkSettings::serverName() << "/qtest/rfc3252.txt" << ushort(80) << false << 400 << "Bad Request" << -1; @@ -217,7 +216,6 @@ void tst_QHttpNetworkConnection::get_data() QTest::addColumn<int>("downloadSize"); QTest::newRow("success-internal") << "http://" << QtNetworkSettings::serverName() << "/qtest/rfc3252.txt" << ushort(80) << false << 200 << "OK" << 25962 << 25962; - QTest::newRow("success-external") << "http://" << "www.ietf.org" << "/rfc/rfc3252.txt" << ushort(80) << false << 200 << "OK" << 25962 << 25962; QTest::newRow("failure-path") << "http://" << QtNetworkSettings::serverName() << "/t" << ushort(80) << false << 404 << "Not Found" << -1 << -1; QTest::newRow("failure-protocol") << "" << QtNetworkSettings::serverName() << "/qtest/rfc3252.txt" << ushort(80) << false << 400 << "Bad Request" << -1 << -1; diff --git a/tests/auto/widgets/widgets/qtoolbutton/tst_qtoolbutton.cpp b/tests/auto/widgets/widgets/qtoolbutton/tst_qtoolbutton.cpp index cebd4883a4..aaff322c4b 100644 --- a/tests/auto/widgets/widgets/qtoolbutton/tst_qtoolbutton.cpp +++ b/tests/auto/widgets/widgets/qtoolbutton/tst_qtoolbutton.cpp @@ -63,6 +63,7 @@ private slots: void collapseTextOnPriority(); void task230994_iconSize(); void task176137_autoRepeatOfAction(); + void qtbug_26956_popupTimerDone(); protected slots: void sendMouseClick(); @@ -223,5 +224,14 @@ void tst_QToolButton::sendMouseClick() QTest::mouseClick(w, Qt::LeftButton, 0, QPoint(7,7)); } +void tst_QToolButton::qtbug_26956_popupTimerDone() +{ + QToolButton *tb = new QToolButton; + tb->setMenu(new QMenu(tb)); + tb->menu()->addAction("Qt"); + tb->deleteLater(); + tb->showMenu(); +} + QTEST_MAIN(tst_QToolButton) #include "tst_qtoolbutton.moc" |