diff --git a/doc/global/template/scripts/main.js b/doc/global/template/scripts/main.js index 823cebec..7d99e00b 100644 --- a/doc/global/template/scripts/main.js +++ b/doc/global/template/scripts/main.js @@ -94,11 +94,6 @@ $(document).ready(function($) { }); $( window ).load(function() { - load_sdk('script', 'facebook-jssdk','//connect.facebook.net/en_US/sdk.js#xfbml=1&appId=207346529386114&version=v2.0'); - load_sdk('script', 'twitter-wjs', '//platform.twitter.com/widgets.js'); - $.getScript("//www.google.com/jsapi", function(){ - google.load("feeds", "1", {"callback": oneQt.liveFeeds}); - }); }); var oneQt = { diff --git a/examples/xml/xml.pro b/examples/xml/xml.pro index b0750574..1c78e6b5 100644 --- a/examples/xml/xml.pro +++ b/examples/xml/xml.pro @@ -1,6 +1,5 @@ TEMPLATE = subdirs -SUBDIRS = htmlinfo \ - xmlstreamlint +SUBDIRS = xmlstreamlint qtHaveModule(widgets) { SUBDIRS += dombookmarks \ diff --git a/mkspecs/features/qt_docs.prf b/mkspecs/features/qt_docs.prf index 095bf15d..5178a7d8 100644 --- a/mkspecs/features/qt_docs.prf +++ b/mkspecs/features/qt_docs.prf @@ -98,6 +98,10 @@ doc_command = $$QDOC $$QMAKE_DOCS prepare_docs { prepare_docs.commands += $$doc_command -prepare $$PREP_DOC_INDEXES -no-link-errors $$QDOC_INCLUDE_PATHS generate_docs.commands += $$doc_command -generate $$DOC_INDEXES $$QDOC_INCLUDE_PATHS + for (incdir, QMAKE_DEFAULT_INCDIRS) { + prepare_docs.commands += -I$$shell_quote($$incdir) + generate_docs.commands += -I$$shell_quote($$incdir) + } prepare_docs.depends += qtattributionsscanner } else { html_docs.commands += $$doc_command $$DOC_INDEXES $(QDOC_INCLUDE_PATHS) diff --git a/mkspecs/features/qt_functions.prf b/mkspecs/features/qt_functions.prf index 7777e615..87f054a0 100644 --- a/mkspecs/features/qt_functions.prf +++ b/mkspecs/features/qt_functions.prf @@ -215,6 +215,8 @@ defineTest(qtAddTargetEnv) { deppath.name = PATH } else:contains(QMAKE_HOST.os, Linux|FreeBSD|OpenBSD|NetBSD|DragonFly|SunOS|HP-UX|QNX|GNU) { deppath.name = LD_LIBRARY_PATH + } else:contains(QMAKE_HOST.os, ^GNU/.*) { + deppath.name = LD_LIBRARY_PATH } else:contains(QMAKE_HOST.os, Haiku) { deppath.name = LIBRARY_PATH } else:equals(QMAKE_HOST.os, Darwin) { diff --git a/mkspecs/gnukfreebsd-g++/qmake.conf b/mkspecs/gnukfreebsd-g++/qmake.conf new file mode 100644 index 00000000..5637201d --- /dev/null +++ b/mkspecs/gnukfreebsd-g++/qmake.conf @@ -0,0 +1,54 @@ +# +# qmake configuration for gnukfreebsd-g++ +# + +MAKEFILE_GENERATOR = UNIX +QMAKE_PLATFORM += gnukfreebsd +CONFIG += incremental +QMAKE_INCREMENTAL_STYLE = sublib + +QMAKE_CFLAGS_THREAD += -D_REENTRANT +QMAKE_CXXFLAGS_THREAD += $$QMAKE_CFLAGS_THREAD +QMAKE_LFLAGS_GCSECTIONS = -Wl,--gc-sections + +QMAKE_INCDIR = +QMAKE_LIBDIR = +QMAKE_INCDIR_X11 = +QMAKE_LIBDIR_X11 = +QMAKE_INCDIR_OPENGL = +QMAKE_LIBDIR_OPENGL = +QMAKE_INCDIR_OPENGL_ES2 = $$QMAKE_INCDIR_OPENGL +QMAKE_LIBDIR_OPENGL_ES2 = $$QMAKE_LIBDIR_OPENGL +QMAKE_INCDIR_EGL = +QMAKE_LIBDIR_EGL = +QMAKE_INCDIR_OPENVG = +QMAKE_LIBDIR_OPENVG = + +QMAKE_LIBS = +QMAKE_LIBS_DYNLOAD = -ldl +QMAKE_LIBS_X11 = -lXext -lX11 -lm +QMAKE_LIBS_NIS = -lnsl +QMAKE_LIBS_EGL = -lEGL +QMAKE_LIBS_OPENGL = -lGL +QMAKE_LIBS_OPENGL_ES2 = -lGLESv2 +QMAKE_LIBS_OPENVG = -lOpenVG +QMAKE_LIBS_THREAD = -lpthread + +QMAKE_CFLAGS_XCB = +QMAKE_LIBS_XCB = +QMAKE_DEFINES_XCB = + +QMAKE_AR = ar cqs +QMAKE_OBJCOPY = objcopy +QMAKE_NM = nm -P +QMAKE_RANLIB = + +QMAKE_STRIP = strip +QMAKE_STRIPFLAGS_LIB += --strip-unneeded +QMAKE_INSTALL_FILE = install -m 644 -p +QMAKE_INSTALL_PROGRAM = install -m 755 -p + +include(../common/unix.conf) +include(../common/gcc-base-unix.conf) +include(../common/g++-unix.conf) +load(qt_config) diff --git a/mkspecs/gnukfreebsd-g++/qplatformdefs.h b/mkspecs/gnukfreebsd-g++/qplatformdefs.h new file mode 100644 index 00000000..90aeac29 --- /dev/null +++ b/mkspecs/gnukfreebsd-g++/qplatformdefs.h @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the qmake spec of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPLATFORMDEFS_H +#define QPLATFORMDEFS_H + +// Get Qt defines/settings + +#include "qglobal.h" + +// Set any POSIX/XOPEN defines at the top of this file to turn on specific APIs + +// 1) need to reset default environment if _BSD_SOURCE is defined +// 2) need to specify POSIX thread interfaces explicitly in glibc 2.0 +// 3) it seems older glibc need this to include the X/Open stuff +#ifndef _GNU_SOURCE +# define _GNU_SOURCE +#endif + +#include + + +// We are hot - unistd.h should have turned on the specific APIs we requested + + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef QT_NO_IPV6IFNAME +#include +#endif + +#include "../common/posix/qplatformdefs.h" + +#if defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE >= 500) +#define QT_SNPRINTF ::snprintf +#define QT_VSNPRINTF ::vsnprintf +#endif + +#endif // QPLATFORMDEFS_H diff --git a/qmake/library/ioutils.cpp b/qmake/library/ioutils.cpp index d2171274..6fada000 100644 --- a/qmake/library/ioutils.cpp +++ b/qmake/library/ioutils.cpp @@ -228,7 +228,7 @@ bool IoUtils::touchFile(const QString &targetFileName, const QString &referenceF *errorString = fL1S("Cannot stat() reference file %1: %2.").arg(referenceFileName, fL1S(strerror(errno))); return false; } -# if defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L +# if defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L && defined(UTIME_NOW) const struct timespec times[2] = { { 0, UTIME_NOW }, st.st_mtim }; const bool utimeError = utimensat(AT_FDCWD, targetFileName.toLocal8Bit().constData(), times, 0) < 0; # else diff --git a/src/concurrent/qtconcurrentthreadengine.h b/src/concurrent/qtconcurrentthreadengine.h index af413707..a4c8548c 100644 --- a/src/concurrent/qtconcurrentthreadengine.h +++ b/src/concurrent/qtconcurrentthreadengine.h @@ -247,8 +247,8 @@ template <> class ThreadEngineStarter : public ThreadEngineStarterBase { public: - ThreadEngineStarter(ThreadEngine *_threadEngine) - :ThreadEngineStarterBase(_threadEngine) {} + ThreadEngineStarter(ThreadEngine *_threadEngine) + : ThreadEngineStarterBase(_threadEngine) {} void startBlocking() { diff --git a/src/corelib/configure.json b/src/corelib/configure.json index 9b5d19d4..3cf77dc6 100644 --- a/src/corelib/configure.json +++ b/src/corelib/configure.json @@ -331,6 +331,7 @@ "label": "O_CLOEXEC", "type": "compile", "test": { + "qmake": "QMAKE_LFLAGS += -Wl,--fatal-warnings", "head": "#define _GNU_SOURCE 1", "include": [ "sys/types.h", "sys/socket.h", "fcntl.h", "unistd.h" ], "main": [ @@ -386,6 +387,7 @@ "include": "sys/stat.h", "main": "futimens(-1, 0);", "qmake": [ + "QMAKE_LFLAGS += -Wl,--fatal-warnings", "# Block futimens() on Apple platforms unless it's available on ALL", "# deployment targets. This simplifies the logic at the call site", "# dramatically, as it isn't strictly needed compared to futimes().", @@ -414,6 +416,7 @@ "label": "getentropy()", "type": "compile", "test": { + "qmake": "QMAKE_LFLAGS += -Wl,--fatal-warnings", "include": "unistd.h", "main": [ "char buf[32];", diff --git a/src/corelib/global/qprocessordetection.h b/src/corelib/global/qprocessordetection.h index 8d657208..a6ead549 100644 --- a/src/corelib/global/qprocessordetection.h +++ b/src/corelib/global/qprocessordetection.h @@ -132,6 +132,8 @@ # elif defined(__ARM_ARCH_5TEJ__) \ || defined(__ARM_ARCH_5TE__) # define Q_PROCESSOR_ARM 5 +# elif defined(__ARM_ARCH_4T__) +# define Q_PROCESSOR_ARM 4 # else # define Q_PROCESSOR_ARM 0 # endif @@ -146,6 +148,9 @@ # endif # if Q_PROCESSOR_ARM >= 5 # define Q_PROCESSOR_ARM_V5 +# endif +# if Q_PROCESSOR_ARM >= 4 +# define Q_PROCESSOR_ARM_V4 # else # error "ARM architecture too old" # endif diff --git a/src/corelib/io/qfilesystemengine_unix.cpp b/src/corelib/io/qfilesystemengine_unix.cpp index 231e5cb0..24321714 100644 --- a/src/corelib/io/qfilesystemengine_unix.cpp +++ b/src/corelib/io/qfilesystemengine_unix.cpp @@ -689,7 +689,11 @@ QFileSystemEntry QFileSystemEngine::canonicalName(const QFileSystemEntry &entry, Q_UNUSED(data); return QFileSystemEntry(slowCanonicalized(absoluteName(entry).filePath())); #else +#ifdef PATH_MAX char stack_result[PATH_MAX+1]; +#else + char stack_result[4096+1]; +#endif char *resolved_name = nullptr; # if defined(Q_OS_DARWIN) || defined(Q_OS_ANDROID) // On some Android and macOS versions, realpath() will return a path even if @@ -1595,7 +1599,7 @@ bool QFileSystemEngine::setFileTime(int fd, const QDateTime &newDate, QAbstractF return false; } -#if QT_CONFIG(futimens) +#if QT_CONFIG(futimens) && defined(UTIME_OMIT) struct timespec ts[2]; ts[0].tv_sec = ts[1].tv_sec = 0; diff --git a/src/corelib/io/qprocess_unix.cpp b/src/corelib/io/qprocess_unix.cpp index 50390e57..15c8f307 100644 --- a/src/corelib/io/qprocess_unix.cpp +++ b/src/corelib/io/qprocess_unix.cpp @@ -1,7 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2016 Intel Corporation. +** Copyright (C) 2022 Intel Corporation. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -422,14 +422,15 @@ void QProcessPrivate::startProcess() // Add the program name to the argument list. argv[0] = nullptr; if (!program.contains(QLatin1Char('/'))) { + // findExecutable() returns its argument if it's an absolute path, + // otherwise it searches $PATH; returns empty if not found (we handle + // that case much later) const QString &exeFilePath = QStandardPaths::findExecutable(program); - if (!exeFilePath.isEmpty()) { - const QByteArray &tmp = QFile::encodeName(exeFilePath); - argv[0] = ::strdup(tmp.constData()); - } - } - if (!argv[0]) + const QByteArray &tmp = QFile::encodeName(exeFilePath); + argv[0] = ::strdup(tmp.constData()); + } else { argv[0] = ::strdup(encodedProgramName.constData()); + } // Add every argument to the list for (int i = 0; i < arguments.count(); ++i) @@ -983,15 +984,16 @@ bool QProcessPrivate::startDetached(qint64 *pid) envp = _q_dupEnvironment(environment.d.constData()->vars, &envc); } - QByteArray tmp; if (!program.contains(QLatin1Char('/'))) { + // findExecutable() returns its argument if it's an absolute path, + // otherwise it searches $PATH; returns empty if not found (we handle + // that case much later) const QString &exeFilePath = QStandardPaths::findExecutable(program); - if (!exeFilePath.isEmpty()) - tmp = QFile::encodeName(exeFilePath); + const QByteArray &tmp = QFile::encodeName(exeFilePath); + argv[0] = ::strdup(tmp.constData()); + } else { + argv[0] = ::strdup(QFile::encodeName(program)); } - if (tmp.isEmpty()) - tmp = QFile::encodeName(program); - argv[0] = tmp.data(); if (envp) qt_safe_execve(argv[0], argv, envp); diff --git a/src/corelib/io/qstorageinfo_unix.cpp b/src/corelib/io/qstorageinfo_unix.cpp index 698c4ddf..45570eee 100644 --- a/src/corelib/io/qstorageinfo_unix.cpp +++ b/src/corelib/io/qstorageinfo_unix.cpp @@ -566,6 +566,7 @@ inline QByteArray QStorageIterator::fileSystemType() const inline QByteArray QStorageIterator::device() const { +#ifdef Q_OS_LINUX // check that the device exists if (mnt.mnt_fsname[0] == '/' && access(mnt.mnt_fsname, F_OK) != 0) { // It doesn't, so let's try to resolve the dev_t from /dev/block. @@ -581,6 +582,7 @@ inline QByteArray QStorageIterator::device() const return dev; } } +#endif return QByteArray(mnt.mnt_fsname); } diff --git a/src/corelib/mimetypes/qmimedatabase.cpp b/src/corelib/mimetypes/qmimedatabase.cpp index 9de22cef..ff868a32 100644 --- a/src/corelib/mimetypes/qmimedatabase.cpp +++ b/src/corelib/mimetypes/qmimedatabase.cpp @@ -389,20 +389,23 @@ QMimeType QMimeDatabasePrivate::mimeTypeForFileNameAndData(const QString &fileNa // Disambiguate conflicting extensions (if magic matching found something) if (candidateByData.isValid() && magicAccuracy > 0) { const QString sniffedMime = candidateByData.name(); - // If the sniffedMime matches a glob match, use it + // If the sniffedMime matches a highest-weight glob match, use it if (candidatesByName.m_matchingMimeTypes.contains(sniffedMime)) { *accuracyPtr = 100; return candidateByData; } - for (const QString &m : qAsConst(candidatesByName.m_matchingMimeTypes)) { + for (const QString &m : qAsConst(candidatesByName.m_allMatchingMimeTypes)) { if (inherits(m, sniffedMime)) { // We have magic + pattern pointing to this, so it's a pretty good match *accuracyPtr = 100; return mimeTypeForName(m); } } - *accuracyPtr = magicAccuracy; - return candidateByData; + if (candidatesByName.m_allMatchingMimeTypes.isEmpty()) { + // No glob, use magic + *accuracyPtr = magicAccuracy; + return candidateByData; + } } } diff --git a/src/corelib/mimetypes/qmimeglobpattern.cpp b/src/corelib/mimetypes/qmimeglobpattern.cpp index 10168844..943eb84b 100644 --- a/src/corelib/mimetypes/qmimeglobpattern.cpp +++ b/src/corelib/mimetypes/qmimeglobpattern.cpp @@ -83,7 +83,10 @@ void QMimeGlobMatchResult::addMatch(const QString &mimeType, int weight, const Q } if (!m_matchingMimeTypes.contains(mimeType)) { m_matchingMimeTypes.append(mimeType); - m_allMatchingMimeTypes.append(mimeType); + if (replace) + m_allMatchingMimeTypes.prepend(mimeType); // highest-weight first + else + m_allMatchingMimeTypes.append(mimeType); m_knownSuffixLength = knownSuffixLength; } } diff --git a/src/corelib/text/qbytearraymatcher.h b/src/corelib/text/qbytearraymatcher.h index 0eedfc1d..f5f9bef7 100644 --- a/src/corelib/text/qbytearraymatcher.h +++ b/src/corelib/text/qbytearraymatcher.h @@ -42,6 +42,8 @@ #include +#include + QT_BEGIN_NAMESPACE diff --git a/src/gui/configure.json b/src/gui/configure.json index 1f08795c..f159568f 100644 --- a/src/gui/configure.json +++ b/src/gui/configure.json @@ -838,9 +838,9 @@ ], "include": [ "EGL/egl.h", "X11/Xlib.h" ], "main": [ - "Display *dpy = EGL_DEFAULT_DISPLAY;", + "Display *dpy = reinterpret_cast(EGL_DEFAULT_DISPLAY);", "EGLNativeDisplayType egldpy = XOpenDisplay(\"\");", - "dpy = egldpy;", + "dpy = reinterpret_cast(egldpy);", "EGLNativeWindowType w = XCreateWindow(dpy, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);", "XDestroyWindow(dpy, w);", "XCloseDisplay(dpy);" diff --git a/src/gui/painting/qpaintengineex.cpp b/src/gui/painting/qpaintengineex.cpp index 5d8f89ea..a7d2e7a9 100644 --- a/src/gui/painting/qpaintengineex.cpp +++ b/src/gui/painting/qpaintengineex.cpp @@ -385,10 +385,10 @@ QPainterState *QPaintEngineEx::createState(QPainterState *orig) const Q_GUI_EXPORT extern bool qt_scaleForTransform(const QTransform &transform, qreal *scale); // qtransform.cpp -void QPaintEngineEx::stroke(const QVectorPath &path, const QPen &pen) +void QPaintEngineEx::stroke(const QVectorPath &path, const QPen &inPen) { #ifdef QT_DEBUG_DRAW - qDebug() << "QPaintEngineEx::stroke()" << pen; + qDebug() << "QPaintEngineEx::stroke()" << inPen; #endif Q_D(QPaintEngineEx); @@ -403,6 +403,38 @@ void QPaintEngineEx::stroke(const QVectorPath &path, const QPen &pen) d->stroker.setCubicToHook(qpaintengineex_cubicTo); } + QRectF clipRect; + QPen pen = inPen; + if (pen.style() > Qt::SolidLine) { + QRectF cpRect = path.controlPointRect(); + const QTransform &xf = state()->matrix; + if (qt_pen_is_cosmetic(pen, state()->renderHints)) { + clipRect = d->exDeviceRect; + cpRect.translate(xf.dx(), xf.dy()); + } else { + clipRect = xf.inverted().mapRect(QRectF(d->exDeviceRect)); + } + // Check to avoid generating unwieldy amount of dashes that will not be visible anyway + qreal pw = pen.widthF() ? pen.widthF() : 1; + QRectF extentRect = cpRect.adjusted(-pw, -pw, pw, pw) & clipRect; + qreal extent = qMax(extentRect.width(), extentRect.height()); + qreal patternLength = 0; + const QVector pattern = pen.dashPattern(); + const int patternSize = qMin(pattern.size(), 32); + for (int i = 0; i < patternSize; i++) + patternLength += qMax(pattern.at(i), qreal(0)); + patternLength *= pw; + if (qFuzzyIsNull(patternLength)) { + pen.setStyle(Qt::NoPen); + } else if (extent / patternLength > 10000) { + // approximate stream of tiny dashes with semi-transparent solid line + pen.setStyle(Qt::SolidLine); + QColor color(pen.color()); + color.setAlpha(color.alpha() / 2); + pen.setColor(color); + } + } + if (!qpen_fast_equals(pen, d->strokerPen)) { d->strokerPen = pen; d->stroker.setJoinStyle(pen.joinStyle()); @@ -430,14 +462,8 @@ void QPaintEngineEx::stroke(const QVectorPath &path, const QPen &pen) return; } - if (pen.style() > Qt::SolidLine) { - if (qt_pen_is_cosmetic(pen, state()->renderHints)){ - d->activeStroker->setClipRect(d->exDeviceRect); - } else { - QRectF clipRect = state()->matrix.inverted().mapRect(QRectF(d->exDeviceRect)); - d->activeStroker->setClipRect(clipRect); - } - } + if (!clipRect.isNull()) + d->activeStroker->setClipRect(clipRect); if (d->activeStroker == &d->stroker) d->stroker.setForceOpen(path.hasExplicitOpen()); diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp index 5ae41d94..a82d0615 100644 --- a/src/gui/text/qtextlayout.cpp +++ b/src/gui/text/qtextlayout.cpp @@ -1173,10 +1173,17 @@ void QTextLayout::draw(QPainter *p, const QPointF &pos, const QVectorisRightToLeft(); + + if (!selectionEndInLine) { + region.addRect(clipIfValid(rightToLeft ? QRectF(fullLineRect.topLeft(), lineRect.bottomLeft()) + : QRectF(lineRect.topRight(), fullLineRect.bottomRight()), clip)); + } + if (!selectionStartInLine) { + region.addRect(clipIfValid(rightToLeft ? QRectF(lineRect.topRight(), fullLineRect.bottomRight()) + : QRectF(fullLineRect.topLeft(), lineRect.bottomLeft()), clip)); + } } else if (!selectionEndInLine && isLastLineInBlock &&!(d->option.flags() & QTextOption::ShowLineAndParagraphSeparators)) { diff --git a/src/network/ssl/qsslcontext_openssl.cpp b/src/network/ssl/qsslcontext_openssl.cpp index c9f202f5..d0a428c2 100644 --- a/src/network/ssl/qsslcontext_openssl.cpp +++ b/src/network/ssl/qsslcontext_openssl.cpp @@ -409,7 +409,7 @@ init_context: break; case QSsl::DtlsV1_0OrLater: minVersion = DTLS1_VERSION; - maxVersion = DTLS_MAX_VERSION; + maxVersion = 0; break; case QSsl::DtlsV1_2: minVersion = DTLS1_2_VERSION; @@ -417,7 +417,7 @@ init_context: break; case QSsl::DtlsV1_2OrLater: minVersion = DTLS1_2_VERSION; - maxVersion = DTLS_MAX_VERSION; + maxVersion = 0; break; case QSsl::TlsV1_3OrLater: #ifdef TLS1_3_VERSION diff --git a/src/network/ssl/qssldiffiehellmanparameters_openssl.cpp b/src/network/ssl/qssldiffiehellmanparameters_openssl.cpp index aaf87411..b5893537 100644 --- a/src/network/ssl/qssldiffiehellmanparameters_openssl.cpp +++ b/src/network/ssl/qssldiffiehellmanparameters_openssl.cpp @@ -59,57 +59,6 @@ QT_BEGIN_NAMESPACE -#ifdef OPENSSL_NO_DEPRECATED_3_0 - -static int q_DH_check(DH *dh, int *status) -{ - // DH_check was first deprecated in OpenSSL 3.0.0, as low-level - // API; the EVP_PKEY family of functions was advised as an alternative. - // As of now EVP_PKEY_params_check ends up calling ... DH_check, - // which is good enough. - - Q_ASSERT(dh); - Q_ASSERT(status); - - EVP_PKEY *key = q_EVP_PKEY_new(); - if (!key) { - qCWarning(lcSsl, "EVP_PKEY_new failed"); - QSslSocketBackendPrivate::logAndClearErrorQueue(); - return 0; - } - const auto keyDeleter = qScopeGuard([key](){ - q_EVP_PKEY_free(key); - }); - if (!q_EVP_PKEY_set1_DH(key, dh)) { - qCWarning(lcSsl, "EVP_PKEY_set1_DH failed"); - QSslSocketBackendPrivate::logAndClearErrorQueue(); - return 0; - } - - EVP_PKEY_CTX *keyCtx = q_EVP_PKEY_CTX_new(key, nullptr); - if (!keyCtx) { - qCWarning(lcSsl, "EVP_PKEY_CTX_new failed"); - QSslSocketBackendPrivate::logAndClearErrorQueue(); - return 0; - } - const auto ctxDeleter = qScopeGuard([keyCtx]{ - q_EVP_PKEY_CTX_free(keyCtx); - }); - - const int result = q_EVP_PKEY_param_check(keyCtx); - QSslSocketBackendPrivate::logAndClearErrorQueue(); - // Note: unlike DH_check, we cannot obtain the 'status', - // if the 'result' is 0 (actually the result is 1 only - // if this 'status' was 0). We could probably check the - // errors from the error queue, but it's not needed anyway - // - see the 'isSafeDH' below, how it returns immediately - // on 0. - Q_UNUSED(status) - - return result; -} -#endif // OPENSSL_NO_DEPRECATED_3_0 - static bool isSafeDH(DH *dh) { int status = 0; diff --git a/src/network/ssl/qsslsocket_openssl_symbols.cpp b/src/network/ssl/qsslsocket_openssl_symbols.cpp index 94aa5a5c..f89f5206 100644 --- a/src/network/ssl/qsslsocket_openssl_symbols.cpp +++ b/src/network/ssl/qsslsocket_openssl_symbols.cpp @@ -148,7 +148,6 @@ DEFINEFUNC(int, EVP_PKEY_up_ref, EVP_PKEY *a, a, return 0, return) DEFINEFUNC2(EVP_PKEY_CTX *, EVP_PKEY_CTX_new, EVP_PKEY *pkey, pkey, ENGINE *e, e, return nullptr, return) DEFINEFUNC(int, EVP_PKEY_param_check, EVP_PKEY_CTX *ctx, ctx, return 0, return) DEFINEFUNC(void, EVP_PKEY_CTX_free, EVP_PKEY_CTX *ctx, ctx, return, return) -DEFINEFUNC(int, EVP_PKEY_base_id, EVP_PKEY *a, a, return NID_undef, return) DEFINEFUNC(int, RSA_bits, RSA *a, a, return 0, return) DEFINEFUNC(int, DSA_bits, DSA *a, a, return 0, return) DEFINEFUNC(int, OPENSSL_sk_num, OPENSSL_STACK *a, a, return -1, return) @@ -368,7 +367,15 @@ DEFINEFUNC(const SSL_CIPHER *, SSL_get_current_cipher, SSL *a, a, return nullptr DEFINEFUNC(int, SSL_version, const SSL *a, a, return 0, return) DEFINEFUNC2(int, SSL_get_error, SSL *a, a, int b, b, return -1, return) DEFINEFUNC(STACK_OF(X509) *, SSL_get_peer_cert_chain, SSL *a, a, return nullptr, return) + +#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 +DEFINEFUNC(X509 *, SSL_get1_peer_certificate, SSL *a, a, return nullptr, return) +DEFINEFUNC(int, EVP_PKEY_get_base_id, const EVP_PKEY *pkey, pkey, return -1, return) +#else DEFINEFUNC(X509 *, SSL_get_peer_certificate, SSL *a, a, return nullptr, return) +DEFINEFUNC(int, EVP_PKEY_base_id, EVP_PKEY *a, a, return NID_undef, return) +#endif // OPENSSL_VERSION_MAJOR >= 3 + DEFINEFUNC(long, SSL_get_verify_result, const SSL *a, a, return -1, return) DEFINEFUNC(SSL *, SSL_new, SSL_CTX *a, a, return nullptr, return) DEFINEFUNC(SSL_CTX *, SSL_get_SSL_CTX, SSL *a, a, return nullptr, return) @@ -489,9 +496,7 @@ DEFINEFUNC(DH *, DH_new, DUMMYARG, DUMMYARG, return nullptr, return) DEFINEFUNC(void, DH_free, DH *dh, dh, return, DUMMYARG) DEFINEFUNC3(DH *, d2i_DHparams, DH**a, a, const unsigned char **pp, pp, long length, length, return nullptr, return) DEFINEFUNC2(int, i2d_DHparams, DH *a, a, unsigned char **p, p, return -1, return) -#ifndef OPENSSL_NO_DEPRECATED_3_0 DEFINEFUNC2(int, DH_check, DH *dh, dh, int *codes, codes, return 0, return) -#endif // OPENSSL_NO_DEPRECATED_3_0 DEFINEFUNC3(BIGNUM *, BN_bin2bn, const unsigned char *s, s, int len, len, BIGNUM *ret, ret, return nullptr, return) #ifndef OPENSSL_NO_EC @@ -852,7 +857,6 @@ bool q_resolveOpenSslSymbols() RESOLVEFUNC(EVP_PKEY_CTX_new) RESOLVEFUNC(EVP_PKEY_param_check) RESOLVEFUNC(EVP_PKEY_CTX_free) - RESOLVEFUNC(EVP_PKEY_base_id) RESOLVEFUNC(RSA_bits) RESOLVEFUNC(OPENSSL_sk_new_null) RESOLVEFUNC(OPENSSL_sk_push) @@ -1077,7 +1081,15 @@ bool q_resolveOpenSslSymbols() RESOLVEFUNC(SSL_version) RESOLVEFUNC(SSL_get_error) RESOLVEFUNC(SSL_get_peer_cert_chain) + +#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 + RESOLVEFUNC(SSL_get1_peer_certificate) + RESOLVEFUNC(EVP_PKEY_get_base_id) +#else RESOLVEFUNC(SSL_get_peer_certificate) + RESOLVEFUNC(EVP_PKEY_base_id) +#endif // OPENSSL_VERSION_MAJOR >= 3 + RESOLVEFUNC(SSL_get_verify_result) RESOLVEFUNC(SSL_new) RESOLVEFUNC(SSL_get_SSL_CTX) @@ -1176,9 +1188,7 @@ bool q_resolveOpenSslSymbols() RESOLVEFUNC(DH_free) RESOLVEFUNC(d2i_DHparams) RESOLVEFUNC(i2d_DHparams) -#ifndef OPENSSL_NO_DEPRECATED_3_0 RESOLVEFUNC(DH_check) -#endif // OPENSSL_NO_DEPRECATED_3_0 RESOLVEFUNC(BN_bin2bn) #ifndef OPENSSL_NO_EC diff --git a/src/network/ssl/qsslsocket_openssl_symbols_p.h b/src/network/ssl/qsslsocket_openssl_symbols_p.h index c46afcf5..b36d0bc1 100644 --- a/src/network/ssl/qsslsocket_openssl_symbols_p.h +++ b/src/network/ssl/qsslsocket_openssl_symbols_p.h @@ -236,7 +236,6 @@ Q_AUTOTEST_EXPORT int q_EVP_PKEY_up_ref(EVP_PKEY *a); EVP_PKEY_CTX *q_EVP_PKEY_CTX_new(EVP_PKEY *pkey, ENGINE *e); void q_EVP_PKEY_CTX_free(EVP_PKEY_CTX *ctx); int q_EVP_PKEY_param_check(EVP_PKEY_CTX *ctx); -int q_EVP_PKEY_base_id(EVP_PKEY *a); int q_RSA_bits(RSA *a); Q_AUTOTEST_EXPORT int q_OPENSSL_sk_num(OPENSSL_STACK *a); Q_AUTOTEST_EXPORT void q_OPENSSL_sk_pop_free(OPENSSL_STACK *a, void (*b)(void *)); @@ -509,7 +508,6 @@ const SSL_CIPHER *q_SSL_get_current_cipher(SSL *a); int q_SSL_version(const SSL *a); int q_SSL_get_error(SSL *a, int b); STACK_OF(X509) *q_SSL_get_peer_cert_chain(SSL *a); -X509 *q_SSL_get_peer_certificate(SSL *a); long q_SSL_get_verify_result(const SSL *a); SSL *q_SSL_new(SSL_CTX *a); SSL_CTX *q_SSL_get_SSL_CTX(SSL *a); @@ -581,10 +579,7 @@ DH *q_DH_new(); void q_DH_free(DH *dh); DH *q_d2i_DHparams(DH **a, const unsigned char **pp, long length); int q_i2d_DHparams(DH *a, unsigned char **p); - -#ifndef OPENSSL_NO_DEPRECATED_3_0 int q_DH_check(DH *dh, int *codes); -#endif // OPENSSL_NO_DEPRECATED_3_0 BIGNUM *q_BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret); #define q_SSL_CTX_set_tmp_dh(ctx, dh) q_SSL_CTX_ctrl((ctx), SSL_CTRL_SET_TMP_DH, 0, (char *)dh) @@ -751,6 +746,17 @@ void *q_CRYPTO_malloc(size_t num, const char *file, int line); int q_SSL_CTX_get_security_level(const SSL_CTX *ctx); void q_SSL_CTX_set_security_level(SSL_CTX *ctx, int level); +// Here we have the ones that make difference between OpenSSL pre/post v3: +#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 +X509 *q_SSL_get1_peer_certificate(SSL *a); +#define q_SSL_get_peer_certificate q_SSL_get1_peer_certificate +int q_EVP_PKEY_get_base_id(const EVP_PKEY *pkey); +#define q_EVP_PKEY_base_id q_EVP_PKEY_get_base_id +#else +X509 *q_SSL_get_peer_certificate(SSL *a); +int q_EVP_PKEY_base_id(EVP_PKEY *a); +#endif // OPENSSL_VERSION_MAJOR >= 3 + QT_END_NAMESPACE #endif diff --git a/src/plugins/platforms/xcb/qxcbclipboard.cpp b/src/plugins/platforms/xcb/qxcbclipboard.cpp index 0a4d6756..dabdfcb6 100644 --- a/src/plugins/platforms/xcb/qxcbclipboard.cpp +++ b/src/plugins/platforms/xcb/qxcbclipboard.cpp @@ -835,6 +835,8 @@ QByteArray QXcbClipboard::clipboardReadIncrementalProperty(xcb_window_t win, xcb alloc_error = buf.size() != nbytes+1; } + QElapsedTimer timer; + timer.start(); for (;;) { connection()->flush(); xcb_generic_event_t *ge = waitForClipboardEvent(win, XCB_PROPERTY_NOTIFY); @@ -870,9 +872,11 @@ QByteArray QXcbClipboard::clipboardReadIncrementalProperty(xcb_window_t win, xcb tmp_buf.resize(0); offset += length; } - } else { - break; } + + const auto elapsed = timer.elapsed(); + if (elapsed > clipboard_timeout) + break; } // timed out ... create a new requestor window, otherwise the requestor diff --git a/src/plugins/sqldrivers/configure.json b/src/plugins/sqldrivers/configure.json index 28ccbead..5c35cd9f 100644 --- a/src/plugins/sqldrivers/configure.json +++ b/src/plugins/sqldrivers/configure.json @@ -52,7 +52,7 @@ "headers": "ibase.h", "sources": [ { "libs": "-lgds32_ms", "condition": "config.win32" }, - { "libs": "-lgds", "condition": "!config.win32" } + { "libs": "-lfbclient", "condition": "!config.win32" } ] }, "mysql": { @@ -67,6 +67,7 @@ }, "headers": "mysql.h", "sources": [ + { "type": "pkgConfig", "args": "mysqlclient" }, { "type": "mysqlConfig", "query": "--libs_r", "cleanlibs": true }, { "type": "mysqlConfig", "query": "--libs", "cleanlibs": true }, { "type": "mysqlConfig", "query": "--libs_r", "cleanlibs": false }, diff --git a/src/plugins/sqldrivers/mysql/qsql_mysql.cpp b/src/plugins/sqldrivers/mysql/qsql_mysql.cpp index a641935d..49a6ae5b 100644 --- a/src/plugins/sqldrivers/mysql/qsql_mysql.cpp +++ b/src/plugins/sqldrivers/mysql/qsql_mysql.cpp @@ -158,6 +158,20 @@ static inline QVariant qDateTimeFromString(QString &val) #endif } +// check if this client and server version of MySQL/MariaDB support prepared statements +static inline bool checkPreparedQueries(MYSQL *mysql) +{ + std::unique_ptr stmt(mysql_stmt_init(mysql), &mysql_stmt_close); + if (!stmt) + return false; + + static const char dummyQuery[] = "SELECT ? + ?"; + if (mysql_stmt_prepare(stmt.get(), dummyQuery, sizeof(dummyQuery) - 1)) + return false; + + return mysql_stmt_param_count(stmt.get()) == 2; +} + class QMYSQLResultPrivate; class QMYSQLResult : public QSqlResult @@ -209,7 +223,7 @@ public: struct QMyField { char *outField = nullptr; - MYSQL_FIELD *myField = nullptr; + const MYSQL_FIELD *myField = nullptr; QMetaType::Type type = QMetaType::UnknownType; my_bool nullIndicator = false; ulong bufLength = 0ul; @@ -347,11 +361,10 @@ static bool qIsInteger(int t) void QMYSQLResultPrivate::bindBlobs() { int i; - MYSQL_FIELD *fieldInfo; MYSQL_BIND *bind; for(i = 0; i < fields.count(); ++i) { - fieldInfo = fields.at(i).myField; + const MYSQL_FIELD *fieldInfo = fields.at(i).myField; if (qIsBlob(inBinds[i].buffer_type) && meta && fieldInfo) { bind = &inBinds[i]; bind->buffer_length = fieldInfo->max_length; @@ -378,35 +391,34 @@ bool QMYSQLResultPrivate::bindInValues() inBinds = new MYSQL_BIND[fields.size()]; memset(inBinds, 0, fields.size() * sizeof(MYSQL_BIND)); - MYSQL_FIELD *fieldInfo; + const MYSQL_FIELD *fieldInfo; while((fieldInfo = mysql_fetch_field(meta))) { + MYSQL_BIND *bind = &inBinds[i]; + QMyField &f = fields[i]; f.myField = fieldInfo; - + bind->buffer_length = f.bufLength = fieldInfo->length + 1; + bind->buffer_type = fieldInfo->type; f.type = qDecodeMYSQLType(fieldInfo->type, fieldInfo->flags); if (qIsBlob(fieldInfo->type)) { // the size of a blob-field is available as soon as we call // mysql_stmt_store_result() // after mysql_stmt_exec() in QMYSQLResult::exec() - fieldInfo->length = 0; + bind->buffer_length = f.bufLength = 0; hasBlobs = true; } else if (qIsInteger(f.type)) { - fieldInfo->length = 8; + bind->buffer_length = f.bufLength = 8; } else { - fieldInfo->type = MYSQL_TYPE_STRING; + bind->buffer_type = MYSQL_TYPE_STRING; } - bind = &inBinds[i]; - field = new char[fieldInfo->length + 1]; - memset(field, 0, fieldInfo->length + 1); - bind->buffer_type = fieldInfo->type; - bind->buffer = field; - bind->buffer_length = f.bufLength = fieldInfo->length + 1; bind->is_null = &f.nullIndicator; bind->length = &f.bufLength; bind->is_unsigned = fieldInfo->flags & UNSIGNED_FLAG ? 1 : 0; - f.outField=field; + + char *field = new char[bind->buffer_length + 1]{}; + bind->buffer = f.outField = field; ++i; } @@ -1371,8 +1383,7 @@ bool QMYSQLDriver::open(const QString& db, } #endif // MYSQL_VERSION_ID >= 50007 - d->preparedQuerysEnabled = mysql_get_client_version() >= 40108 - && mysql_get_server_version(d->mysql) >= 40100; + d->preparedQuerysEnabled = checkPreparedQueries(d->mysql); #if QT_CONFIG(thread) mysql_thread_init(); diff --git a/src/tools/moc/moc.cpp b/src/tools/moc/moc.cpp index 73899199..28c7a43c 100644 --- a/src/tools/moc/moc.cpp +++ b/src/tools/moc/moc.cpp @@ -305,10 +305,9 @@ bool Moc::parseEnum(EnumDef *def) return IncludeState::NoInclude; }; do { + handleInclude(); if (lookup() == RBRACE) // accept trailing comma break; - if ( handleInclude() == IncludeState::IncludeEnd) - continue; next(IDENTIFIER); def->values += lexem(); handleInclude(); diff --git a/src/widgets/kernel/qgridlayout.cpp b/src/widgets/kernel/qgridlayout.cpp index b4e85411..e2777b65 100644 --- a/src/widgets/kernel/qgridlayout.cpp +++ b/src/widgets/kernel/qgridlayout.cpp @@ -149,14 +149,14 @@ public: QRect cellRect(int row, int col) const; inline QLayoutItem *itemAt(int index) const { - if (index < things.count()) + if (index >= 0 && index < things.count()) return things.at(index)->item(); else return nullptr; } inline QLayoutItem *takeAt(int index) { Q_Q(QGridLayout); - if (index < things.count()) { + if (index >= 0 && index < things.count()) { if (QGridBox *b = things.takeAt(index)) { QLayoutItem *item = b->takeItem(); if (QLayout *l = item->layout()) { @@ -184,7 +184,7 @@ public: } void getItemPosition(int index, int *row, int *column, int *rowSpan, int *columnSpan) const { - if (index < things.count()) { + if (index >= 0 && index < things.count()) { const QGridBox *b = things.at(index); int toRow = b->toRow(rr); int toCol = b->toCol(cc); diff --git a/src/widgets/styles/qfusionstyle.cpp b/src/widgets/styles/qfusionstyle.cpp index f4345d97..962912c8 100644 --- a/src/widgets/styles/qfusionstyle.cpp +++ b/src/widgets/styles/qfusionstyle.cpp @@ -1772,14 +1772,6 @@ void QFusionStyle::drawControl(ControlElement element, const QStyleOption *optio proxy()->drawControl(CE_PushButtonLabel, &subopt, painter, widget); } break; - case CE_PushButtonLabel: - if (const QStyleOptionButton *button = qstyleoption_cast(option)) { - QStyleOptionButton b(*button); - // no PM_ButtonShiftHorizontal and PM_ButtonShiftVertical for fusion style - b.state &= ~(State_On | State_Sunken); - QCommonStyle::drawControl(element, &b, painter, widget); - } - break; case CE_MenuBarEmptyArea: painter->save(); { diff --git a/src/widgets/styles/qstylesheetstyle.cpp b/src/widgets/styles/qstylesheetstyle.cpp index 53fff294..f9ab5589 100644 --- a/src/widgets/styles/qstylesheetstyle.cpp +++ b/src/widgets/styles/qstylesheetstyle.cpp @@ -2640,6 +2640,9 @@ void QStyleSheetStyle::setProperties(QWidget *w) default: v = decl.d->values.at(0).variant; break; } + if (propertyL1 == QByteArray("styleSheet") && value == v) + continue; + w->setProperty(propertyL1, v); } } diff --git a/src/widgets/widgets/qlineedit_p.cpp b/src/widgets/widgets/qlineedit_p.cpp index b854d9d2..bad36fd2 100644 --- a/src/widgets/widgets/qlineedit_p.cpp +++ b/src/widgets/widgets/qlineedit_p.cpp @@ -407,8 +407,9 @@ void QLineEditIconButton::setHideWithText(bool hide) void QLineEditIconButton::onAnimationFinished() { - if (shouldHideWithText() && isVisible() && !m_wasHidden) { + if (shouldHideWithText() && isVisible() && m_fadingOut) { hide(); + m_fadingOut = false; // Invalidate previous geometry to take into account new size of side widgets if (auto le = lineEditPrivate()) @@ -418,7 +419,7 @@ void QLineEditIconButton::onAnimationFinished() void QLineEditIconButton::animateShow(bool visible) { - m_wasHidden = visible; + m_fadingOut = !visible; if (shouldHideWithText() && !isVisible()) { show(); @@ -664,10 +665,18 @@ static int effectiveTextMargin(int defaultMargin, const QLineEditPrivate::SideWi if (widgets.empty()) return defaultMargin; - return defaultMargin + (parameters.margin + parameters.widgetWidth) * - int(std::count_if(widgets.begin(), widgets.end(), + const auto visibleSideWidgetCount = std::count_if(widgets.begin(), widgets.end(), [](const QLineEditPrivate::SideWidgetEntry &e) { - return e.widget->isVisibleTo(e.widget->parentWidget()); })); +#if QT_CONFIG(animation) + // a button that's fading out doesn't get any space + if (auto* iconButton = qobject_cast(e.widget)) + return iconButton->needsSpace(); + +#endif + return e.widget->isVisibleTo(e.widget->parentWidget()); + }); + + return defaultMargin + (parameters.margin + parameters.widgetWidth) * visibleSideWidgetCount; } QMargins QLineEditPrivate::effectiveTextMargins() const diff --git a/src/widgets/widgets/qlineedit_p.h b/src/widgets/widgets/qlineedit_p.h index 5ae402b9..f55210fc 100644 --- a/src/widgets/widgets/qlineedit_p.h +++ b/src/widgets/widgets/qlineedit_p.h @@ -95,6 +95,11 @@ public: bool shouldHideWithText() const; void setHideWithText(bool hide); + bool needsSpace() const { + if (m_fadingOut) + return false; + return isVisibleTo(parentWidget()); + } #endif protected: @@ -118,7 +123,7 @@ private: #if QT_CONFIG(animation) bool m_hideWithText = false; - bool m_wasHidden = false; + bool m_fadingOut = false; #endif }; diff --git a/tests/auto/tools/moc/enum_with_include.h b/tests/auto/tools/moc/enum_with_include.h index b8abf77f..cd53ba6a 100644 --- a/tests/auto/tools/moc/enum_with_include.h +++ b/tests/auto/tools/moc/enum_with_include.h @@ -34,6 +34,11 @@ class Foo : public QObject { enum en { #include }; + + enum class en2 { + #include + reference = 42 + }; Q_OBJECT }; #endif diff --git a/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp b/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp index 69a81bde..8e814255 100644 --- a/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp +++ b/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp @@ -1493,7 +1493,7 @@ void tst_QApplication::desktopSettingsAware() { #if QT_CONFIG(process) QProcess testProcess; - testProcess.start("desktopsettingsaware_helper"); + testProcess.start("./desktopsettingsaware_helper"); QVERIFY2(testProcess.waitForStarted(), qPrintable(QString::fromLatin1("Cannot start 'desktopsettingsaware_helper': %1").arg(testProcess.errorString()))); QVERIFY(testProcess.waitForFinished(10000)); @@ -2447,7 +2447,7 @@ void tst_QApplication::qtbug_12673() #if QT_CONFIG(process) QProcess testProcess; QStringList arguments; - testProcess.start("modal_helper", arguments); + testProcess.start("./modal_helper", arguments); QVERIFY2(testProcess.waitForStarted(), qPrintable(QString::fromLatin1("Cannot start 'modal_helper': %1").arg(testProcess.errorString()))); QVERIFY(testProcess.waitForFinished(20000)); diff --git a/tests/auto/widgets/kernel/qgridlayout/tst_qgridlayout.cpp b/tests/auto/widgets/kernel/qgridlayout/tst_qgridlayout.cpp index 1d63d140..d57da3c7 100644 --- a/tests/auto/widgets/kernel/qgridlayout/tst_qgridlayout.cpp +++ b/tests/auto/widgets/kernel/qgridlayout/tst_qgridlayout.cpp @@ -75,6 +75,7 @@ private slots: void taskQTBUG_40609_addingWidgetToItsOwnLayout(); void taskQTBUG_40609_addingLayoutToItself(); void taskQTBUG_52357_spacingWhenItemIsHidden(); + void taskQTBUG_91261_itemIndexRange(); void replaceWidget(); void dontCrashWhenExtendsToEnd(); }; @@ -1666,6 +1667,56 @@ void tst_QGridLayout::taskQTBUG_52357_spacingWhenItemIsHidden() QTRY_COMPARE_WITH_TIMEOUT(tempWidth, button1.width() + button3.width() + layout.spacing(), 1000); } +void tst_QGridLayout::taskQTBUG_91261_itemIndexRange() +{ + QWidget widget; + QGridLayout lay(&widget); + QPushButton *btn = new QPushButton(&widget); + lay.addWidget(btn, 0, 0); + + { + auto ptr = lay.itemAt(-1); + QCOMPARE(ptr, nullptr); + + ptr = lay.itemAt(0); + QCOMPARE(ptr->widget(), btn); + + ptr = lay.itemAt(1); + QCOMPARE(ptr, nullptr); + } + + { + int row = -1; + int column = -1; + int rowSpan; + int columnSpan; + + lay.getItemPosition(-1, &row, &column, &rowSpan, &columnSpan); + QCOMPARE(row, -1); + QCOMPARE(column, -1); + + lay.getItemPosition(1, &row, &column, &rowSpan, &columnSpan); + QCOMPARE(row, -1); + QCOMPARE(column, -1); + + lay.getItemPosition(0, &row, &column, &rowSpan, &columnSpan); + QCOMPARE(row, 0); + QCOMPARE(column, 0); + } + + { + auto ptr = lay.takeAt(-1); + QCOMPARE(ptr, nullptr); + + ptr = lay.takeAt(1); + QCOMPARE(ptr, nullptr); + + ptr = lay.takeAt(0); + QCOMPARE(ptr->widget(), btn); + delete ptr; + } +} + void tst_QGridLayout::replaceWidget() { QWidget wdg; diff --git a/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp b/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp index 26868a76..5d67ce5a 100644 --- a/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp +++ b/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp @@ -94,6 +94,7 @@ private slots: void layoutSpacing(); #endif void qproperty(); + void qproperty_styleSheet(); void palettePropagation_data(); void palettePropagation(); void fontPropagation_data(); @@ -678,6 +679,23 @@ void tst_QStyleSheetStyle::qproperty() QCOMPARE(pb.isChecked(), false); } +void tst_QStyleSheetStyle::qproperty_styleSheet() +{ + QWidget w; + auto checkBox = new QCheckBox("check", &w); + QString sheet = R"(QCheckBox { qproperty-styleSheet: "QCheckBox { qproperty-text: foobar; }"; })"; + + QVERIFY(w.property("styleSheet").toString().isEmpty()); + + w.setStyleSheet(sheet); + QCOMPARE(checkBox->text(), "check"); + + //recursion crash + w.ensurePolished(); + QCOMPARE(w.property("styleSheet").toString(), sheet); + QCOMPARE(checkBox->text(), "foobar"); +} + namespace ns { class PushButton1 : public QPushButton { Q_OBJECT diff --git a/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp b/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp index 6408df3f..7c2203de 100644 --- a/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp +++ b/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp @@ -292,6 +292,7 @@ private slots: void clearButtonVisibleAfterSettingText_QTBUG_45518(); void sideWidgets(); void sideWidgetsActionEvents(); + void sideWidgetsEffectiveMargins(); void shouldShowPlaceholderText_data(); void shouldShowPlaceholderText(); @@ -4646,6 +4647,71 @@ void tst_QLineEdit::sideWidgetsActionEvents() QCOMPARE(toolButton2->x(), toolButton1X); } +/*! + Verify that side widgets are positioned correctly and result in + correct effective text margins. +*/ +void tst_QLineEdit::sideWidgetsEffectiveMargins() +{ +#ifndef QT_BUILD_INTERNAL + QSKIP("This test requires a developer build."); +#else + QLineEdit edit; + edit.setPlaceholderText("placeholder"); + edit.setClearButtonEnabled(true); + edit.show(); + QLineEditPrivate *priv = QLineEditPrivate::get(&edit); + const auto sideWidgetParameters = priv->sideWidgetParameters(); + const int sideWidgetWidth = sideWidgetParameters.widgetWidth + sideWidgetParameters.margin; + QVERIFY(QTest::qWaitForWindowExposed(&edit)); + + QCOMPARE(priv->effectiveTextMargins().left(), 0); + QCOMPARE(priv->effectiveTextMargins().right(), 0); + + edit.setText("Left to right"); // clear button fades in on the right + QCOMPARE(priv->effectiveTextMargins().left(), 0); + QCOMPARE(priv->effectiveTextMargins().right(), sideWidgetWidth); + edit.clear(); + QCOMPARE(priv->effectiveTextMargins().left(), 0); + QCOMPARE(priv->effectiveTextMargins().right(), 0); + + edit.setLayoutDirection(Qt::RightToLeft); + edit.setText("ئۇيغۇر تىلى"); // clear button fades in on the left + QCOMPARE(priv->effectiveTextMargins().left(), sideWidgetWidth); + QCOMPARE(priv->effectiveTextMargins().right(), 0); + edit.clear(); + QCOMPARE(priv->effectiveTextMargins().left(), 0); + QCOMPARE(priv->effectiveTextMargins().right(), 0); + + edit.setLayoutDirection(Qt::LeftToRight); + + const QIcon leftIcon = edit.style()->standardIcon(QStyle::SP_FileIcon); + const QIcon rightIcon = edit.style()->standardIcon(QStyle::SP_DirIcon); + edit.addAction(leftIcon, QLineEdit::ActionPosition::LeadingPosition); + QCOMPARE(priv->effectiveTextMargins().left(), sideWidgetWidth); + QCOMPARE(priv->effectiveTextMargins().right(), 0); + + edit.addAction(rightIcon, QLineEdit::ActionPosition::TrailingPosition); + QCOMPARE(priv->effectiveTextMargins().left(), sideWidgetWidth); + QCOMPARE(priv->effectiveTextMargins().right(), sideWidgetWidth); + + edit.setText("Left to right"); // clear button on the right + QCOMPARE(priv->effectiveTextMargins().left(), sideWidgetWidth); + QCOMPARE(priv->effectiveTextMargins().right(), 2 * sideWidgetWidth); + edit.clear(); + QCOMPARE(priv->effectiveTextMargins().left(), sideWidgetWidth); + QCOMPARE(priv->effectiveTextMargins().right(), sideWidgetWidth); + + edit.setLayoutDirection(Qt::RightToLeft); + edit.setText("ئۇيغۇر تىلى"); // clear button fades in on the left + QCOMPARE(priv->effectiveTextMargins().left(), 2 * sideWidgetWidth); + QCOMPARE(priv->effectiveTextMargins().right(), sideWidgetWidth); + edit.clear(); + QCOMPARE(priv->effectiveTextMargins().left(), sideWidgetWidth); + QCOMPARE(priv->effectiveTextMargins().right(), sideWidgetWidth); +#endif +} + Q_DECLARE_METATYPE(Qt::AlignmentFlag) void tst_QLineEdit::shouldShowPlaceholderText_data() {