diff options
Diffstat (limited to 'src/gui/util')
37 files changed, 1419 insertions, 1341 deletions
diff --git a/src/gui/util/qabstractlayoutstyleinfo.cpp b/src/gui/util/qabstractlayoutstyleinfo.cpp index 40ad51452a..51d569f814 100644 --- a/src/gui/util/qabstractlayoutstyleinfo.cpp +++ b/src/gui/util/qabstractlayoutstyleinfo.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/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 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qabstractlayoutstyleinfo_p.h" diff --git a/src/gui/util/qabstractlayoutstyleinfo_p.h b/src/gui/util/qabstractlayoutstyleinfo_p.h index bf1e1fc852..42578c58ca 100644 --- a/src/gui/util/qabstractlayoutstyleinfo_p.h +++ b/src/gui/util/qabstractlayoutstyleinfo_p.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/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 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QABSTRACTLAYOUTSTYLEINFO_P_H #define QABSTRACTLAYOUTSTYLEINFO_P_H diff --git a/src/gui/util/qastchandler.cpp b/src/gui/util/qastchandler.cpp index 94cb42e29b..ec8b92f557 100644 --- a/src/gui/util/qastchandler.cpp +++ b/src/gui/util/qastchandler.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2019 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/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 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2019 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qastchandler_p.h" #include "qtexturefiledata_p.h" @@ -59,6 +23,8 @@ struct AstcHeader quint8 zSize[3]; }; +QAstcHandler::~QAstcHandler() = default; + bool QAstcHandler::canRead(const QByteArray &suffix, const QByteArray &block) { Q_UNUSED(suffix); @@ -71,7 +37,7 @@ quint32 QAstcHandler::astcGLFormat(quint8 xBlockDim, quint8 yBlockDim) const static const quint32 glFormatRGBABase = 0x93B0; // GL_COMPRESSED_RGBA_ASTC_4x4_KHR static const quint32 glFormatSRGBBase = 0x93D0; // GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR - static QSize dims[14] = { + Q_CONSTINIT static QSize dims[14] = { { 4, 4 }, // GL_COMPRESSED_xxx_ASTC_4x4_KHR { 5, 4 }, // GL_COMPRESSED_xxx_ASTC_5x4_KHR { 5, 5 }, // GL_COMPRESSED_xxx_ASTC_5x5_KHR @@ -143,9 +109,9 @@ QTextureFileData QAstcHandler::read() int zBlocks = (zSz + header->blockDimZ - 1) / header->blockDimZ; int byteCount = 0; - bool oob = mul_overflow(xBlocks, yBlocks, &byteCount) - || mul_overflow(byteCount, zBlocks, &byteCount) - || mul_overflow(byteCount, 16, &byteCount); + bool oob = qMulOverflow(xBlocks, yBlocks, &byteCount) + || qMulOverflow(byteCount, zBlocks, &byteCount) + || qMulOverflow(byteCount, 16, &byteCount); res.setDataOffset(sizeof(AstcHeader)); diff --git a/src/gui/util/qastchandler_p.h b/src/gui/util/qastchandler_p.h index 398f1833b6..5dd7f7a524 100644 --- a/src/gui/util/qastchandler_p.h +++ b/src/gui/util/qastchandler_p.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2019 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/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 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2019 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QASTCHANDLER_H #define QASTCHANDLER_H @@ -59,6 +23,7 @@ class QAstcHandler : public QTextureFileHandler { public: using QTextureFileHandler::QTextureFileHandler; + ~QAstcHandler() override; static bool canRead(const QByteArray &suffix, const QByteArray &block); diff --git a/src/gui/util/qdesktopservices.cpp b/src/gui/util/qdesktopservices.cpp index 7a728cf692..4a12f6db6f 100644 --- a/src/gui/util/qdesktopservices.cpp +++ b/src/gui/util/qdesktopservices.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/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 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qdesktopservices.h" @@ -54,11 +18,12 @@ #include <qpa/qplatformintegration.h> #include <qdir.h> +#include <QtCore/private/qlocking_p.h> + QT_BEGIN_NAMESPACE -class QOpenUrlHandlerRegistry : public QObject +class QOpenUrlHandlerRegistry { - Q_OBJECT public: QOpenUrlHandlerRegistry() = default; @@ -72,24 +37,34 @@ public: typedef QHash<QString, Handler> HandlerHash; HandlerHash handlers; -public Q_SLOTS: +#if QT_VERSION < QT_VERSION_CHECK(6, 6, 0) + QObject context; + void handlerDestroyed(QObject *handler); +#endif }; Q_GLOBAL_STATIC(QOpenUrlHandlerRegistry, handlerRegistry) +#if QT_VERSION < QT_VERSION_CHECK(6, 6, 0) void QOpenUrlHandlerRegistry::handlerDestroyed(QObject *handler) { + const auto lock = qt_scoped_lock(mutex); HandlerHash::Iterator it = handlers.begin(); while (it != handlers.end()) { if (it->receiver == handler) { it = handlers.erase(it); + qWarning("Please call QDesktopServices::unsetUrlHandler() before destroying a " + "registered URL handler object.\n" + "Support for destroying a registered URL handler object is deprecated, " + "and will be removed in Qt 6.6."); } else { ++it; } } } +#endif /*! \class QDesktopServices @@ -187,6 +162,13 @@ void QOpenUrlHandlerRegistry::handlerDestroyed(QObject *handler) \snippet code/src_gui_util_qdesktopservices.cpp 3 + \note For Android Nougat (SDK 24) and above, URLs with a \c file scheme + are opened using \l {Android: FileProvider}{FileProvider} which tries to obtain + a shareable \c content scheme URI first. For that reason, Qt for Android defines + a file provider with the authority \c ${applicationId}.qtprovider, with \c applicationId + being the app's package name to avoid name conflicts. For more information, also see + \l {Android: Setting up file sharing}{Setting up file sharing}. + \sa setUrlHandler() */ bool QDesktopServices::openUrl(const QUrl &url) @@ -252,6 +234,10 @@ bool QDesktopServices::openUrl(const QUrl &url) Note that the handler will always be called from within the same thread that calls QDesktopServices::openUrl(). + You must call unsetUrlHandler() before destroying the handler object, so + the destruction of the handler object does not overlap with concurrent + invocations of openUrl() using it. + \section1 iOS To use this function for receiving data from other apps on iOS you also need to @@ -320,13 +306,20 @@ void QDesktopServices::setUrlHandler(const QString &scheme, QObject *receiver, c h.receiver = receiver; h.name = method; registry->handlers.insert(scheme.toLower(), h); - QObject::connect(receiver, SIGNAL(destroyed(QObject*)), - registry, SLOT(handlerDestroyed(QObject*))); +#if QT_VERSION < QT_VERSION_CHECK(6, 6, 0) + QObject::connect(receiver, &QObject::destroyed, ®istry->context, + [registry](QObject *obj) { registry->handlerDestroyed(obj); }, + Qt::DirectConnection); +#endif } /*! Removes a previously set URL handler for the specified \a scheme. + Call this function before the handler object that was registered for \a scheme + is destroyed, to prevent concurrent openUrl() calls from continuing to call + the destroyed handler object. + \sa setUrlHandler() */ void QDesktopServices::unsetUrlHandler(const QString &scheme) @@ -336,6 +329,4 @@ void QDesktopServices::unsetUrlHandler(const QString &scheme) QT_END_NAMESPACE -#include "qdesktopservices.moc" - #endif // QT_NO_DESKTOPSERVICES diff --git a/src/gui/util/qdesktopservices.h b/src/gui/util/qdesktopservices.h index 658b601532..476b84691e 100644 --- a/src/gui/util/qdesktopservices.h +++ b/src/gui/util/qdesktopservices.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2020 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/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 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2020 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QDESKTOPSERVICES_H #define QDESKTOPSERVICES_H diff --git a/src/gui/util/qedidparser.cpp b/src/gui/util/qedidparser.cpp index db5ccf1772..4dae151e6a 100644 --- a/src/gui/util/qedidparser.cpp +++ b/src/gui/util/qedidparser.cpp @@ -1,42 +1,6 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com> -** Copyright (C) 2021 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/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 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2017 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com> +// Copyright (C) 2021 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include <QtCore/QFile> #include <QtCore/QByteArrayView> @@ -48,6 +12,7 @@ #define EDID_DESCRIPTOR_PRODUCT_NAME 0xfc #define EDID_DESCRIPTOR_SERIAL_NUMBER 0xff +#define EDID_DATA_BLOCK_COUNT 4 #define EDID_OFFSET_DATA_BLOCKS 0x36 #define EDID_OFFSET_LAST_BLOCK 0x6c #define EDID_OFFSET_PNP_ID 0x08 @@ -60,11 +25,13 @@ QT_BEGIN_NAMESPACE +using namespace Qt::StringLiterals; + static QString lookupVendorIdInSystemDatabase(QByteArrayView id) { QString result; - const QString fileName = QLatin1String("/usr/share/hwdata/pnp.ids"); + const QString fileName = "/usr/share/hwdata/pnp.ids"_L1; QFile file(fileName); if (!file.open(QFile::ReadOnly)) return result; @@ -105,7 +72,7 @@ static QString lookupVendorIdInSystemDatabase(QByteArrayView id) bool QEdidParser::parse(const QByteArray &blob) { const quint8 *data = reinterpret_cast<const quint8 *>(blob.constData()); - const size_t length = blob.length(); + const size_t length = blob.size(); // Verify header if (length < 128) @@ -138,7 +105,7 @@ bool QEdidParser::parse(const QByteArray &blob) serialNumber = QString(); // Parse EDID data - for (int i = 0; i < 5; ++i) { + for (int i = 0; i < EDID_DATA_BLOCK_COUNT; ++i) { const uint offset = EDID_OFFSET_DATA_BLOCKS + i * 18; if (data[offset] != 0 || data[offset + 1] != 0 || data[offset + 2] != 0) @@ -268,16 +235,22 @@ QString QEdidParser::parseEdidString(const quint8 *data) { QByteArray buffer(reinterpret_cast<const char *>(data), 13); - // Erase carriage return and line feed - buffer = buffer.replace('\r', '\0').replace('\n', '\0'); + for (int i = 0; i < buffer.size(); ++i) { + // If there are less than 13 characters in the string, the string + // is terminated with the ASCII code ‘0Ah’ (line feed) and padded + // with ASCII code ‘20h’ (space). See EDID 1.4, sections 3.10.3.1, + // 3.10.3.2, and 3.10.3.4. + if (buffer[i] == '\n') { + buffer.truncate(i); + break; + } - // Replace non-printable characters with dash - for (int i = 0; i < buffer.count(); ++i) { + // Replace non-printable characters with dash if (buffer[i] < '\040' || buffer[i] > '\176') buffer[i] = '-'; } - return QString::fromLatin1(buffer.trimmed()); + return QString::fromLatin1(buffer); } QT_END_NAMESPACE diff --git a/src/gui/util/qedidparser_p.h b/src/gui/util/qedidparser_p.h index f18c2f1ad1..99352b03b0 100644 --- a/src/gui/util/qedidparser_p.h +++ b/src/gui/util/qedidparser_p.h @@ -1,42 +1,6 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com> -** Copyright (C) 2021 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/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 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2017 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com> +// Copyright (C) 2021 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QEDIDPARSER_P_H #define QEDIDPARSER_P_H @@ -61,6 +25,7 @@ #include <QtCore/qpoint.h> #include <QtCore/qsize.h> #include <QtCore/qstring.h> +#include <QtCore/private/qglobal_p.h> QT_BEGIN_NAMESPACE diff --git a/src/gui/util/qedidvendortable_p.h b/src/gui/util/qedidvendortable_p.h index e6bbb8f87e..0a6132e4d7 100644 --- a/src/gui/util/qedidvendortable_p.h +++ b/src/gui/util/qedidvendortable_p.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/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 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2017 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only /* * This lookup table was generated from https://github.com/vcrhonek/hwdata/raw/master/pnp.ids @@ -58,6 +22,8 @@ // We mean it. // +#include <QtCore/private/qglobal_p.h> + QT_BEGIN_NAMESPACE struct VendorTable { diff --git a/src/gui/util/qgraphicsframecapture.cpp b/src/gui/util/qgraphicsframecapture.cpp new file mode 100644 index 0000000000..e49fb83008 --- /dev/null +++ b/src/gui/util/qgraphicsframecapture.cpp @@ -0,0 +1,123 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qgraphicsframecapture_p.h" +#if (defined (Q_OS_WIN) || defined(Q_OS_LINUX)) && QT_CONFIG(library) +#include "qgraphicsframecapturerenderdoc_p_p.h" +#elif QT_CONFIG(metal) +#include "qgraphicsframecapturemetal_p_p.h" +#else +#include "qgraphicsframecapture_p_p.h" +#endif + +#include <QtCore/qstandardpaths.h> +#include <QtCore/qcoreapplication.h> + +QT_BEGIN_NAMESPACE + +QGraphicsFrameCapturePrivate::QGraphicsFrameCapturePrivate() + : m_capturePath(QStandardPaths::writableLocation(QStandardPaths::TempLocation) + + QStringLiteral("/") + QCoreApplication::applicationName() + + QStringLiteral("/captures")), + m_capturePrefix(QCoreApplication::applicationName()) +{ + +} + +QGraphicsFrameCapture::QGraphicsFrameCapture() +{ +#if (defined (Q_OS_WIN) || defined(Q_OS_LINUX)) && QT_CONFIG(library) + d.reset(new QGraphicsFrameCaptureRenderDoc); +#elif QT_CONFIG(metal) + d.reset(new QGraphicsFrameCaptureMetal); +#endif +} + +QGraphicsFrameCapture::~QGraphicsFrameCapture() +{ + +} + +void QGraphicsFrameCapture::setRhi(QRhi *rhi) +{ + if (!d.isNull()) + d->setRhi(rhi); +} + +void QGraphicsFrameCapture::startCaptureFrame() +{ + if (!d.isNull()) + d->startCaptureFrame(); +} + +void QGraphicsFrameCapture::endCaptureFrame() +{ + if (!d.isNull()) + d->endCaptureFrame(); +} + +QString QGraphicsFrameCapture::capturePath() const +{ + if (!d.isNull()) + return d->capturePath(); + return QString(); +} + +void QGraphicsFrameCapture::setCapturePath(const QString &path) +{ + if (!d.isNull()) + d->setCapturePath(path); +} + +QString QGraphicsFrameCapture::capturePrefix() const +{ + if (!d.isNull()) + return d->capturePrefix(); + return QString(); +} + +void QGraphicsFrameCapture::setCapturePrefix(const QString &prefix) +{ + if (!d.isNull()) + d->setCapturePrefix(prefix); +} + +QString QGraphicsFrameCapture::capturedFileName() +{ + if (!d.isNull()) + return d->capturedFileName(); + + return QString(); +} + +QStringList QGraphicsFrameCapture::capturedFilesNames() +{ + if (!d.isNull()) + return d->capturedFilesNames(); + + return QStringList(); +} + +bool QGraphicsFrameCapture::isLoaded() const +{ + if (!d.isNull()) + return d->initialized(); + + return false; +} + +bool QGraphicsFrameCapture::isCapturing() const +{ + if (!d.isNull()) + return d->isCapturing(); + + return false; +} + +void QGraphicsFrameCapture::openCapture() const +{ + if (!d.isNull()) + d->openCapture(); +} + +QT_END_NAMESPACE diff --git a/src/gui/util/qgraphicsframecapture_p.h b/src/gui/util/qgraphicsframecapture_p.h new file mode 100644 index 0000000000..fef37d2869 --- /dev/null +++ b/src/gui/util/qgraphicsframecapture_p.h @@ -0,0 +1,55 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QGRAPHICSFRAMECAPTURE_P_H +#define QGRAPHICSFRAMECAPTURE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtCore/qscopedpointer.h> +#include <QtGui/qtguiglobal.h> + +QT_BEGIN_NAMESPACE + +class QGraphicsFrameCapturePrivate; +class QRhi; + +class Q_GUI_EXPORT QGraphicsFrameCapture +{ +public: + QGraphicsFrameCapture(); + ~QGraphicsFrameCapture(); + + void setRhi(QRhi *rhi); + void startCaptureFrame(); + void endCaptureFrame(); + + QString capturePath() const; + void setCapturePath(const QString &path); + + QString capturePrefix() const; + void setCapturePrefix(const QString &prefix); + + QString capturedFileName(); + QStringList capturedFilesNames(); + + bool isLoaded() const; + bool isCapturing() const; + void openCapture() const; + +private: + QScopedPointer<QGraphicsFrameCapturePrivate> d; +}; + +QT_END_NAMESPACE + +#endif // QGRAPHICSFRAMECAPTURE_P_H diff --git a/src/gui/util/qgraphicsframecapture_p_p.h b/src/gui/util/qgraphicsframecapture_p_p.h new file mode 100644 index 0000000000..f8dbd2ca1d --- /dev/null +++ b/src/gui/util/qgraphicsframecapture_p_p.h @@ -0,0 +1,67 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QGRAPHICSFRAMECAPTURE_P_P_H +#define QGRAPHICSFRAMECAPTURE_P_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtCore/qnamespace.h> +#include <QtCore/qstring.h> +#include <QtCore/qloggingcategory.h> +#include <QtCore/qstringlist.h> + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(lcGraphicsFrameCapture) + +class QRhi; +struct QRhiNativeHandles; + +class QGraphicsFrameCapturePrivate +{ +public: + QGraphicsFrameCapturePrivate() ; + virtual ~QGraphicsFrameCapturePrivate() = default; + + virtual void setRhi(QRhi *rhi) = 0; + virtual void startCaptureFrame() = 0; + virtual void endCaptureFrame() = 0; + + QString capturePath() const { return m_capturePath; }; + virtual void setCapturePath(const QString &path) { m_capturePath = path; } + + QString capturePrefix() const { return m_capturePrefix; } + virtual void setCapturePrefix(const QString &prefix) { m_capturePrefix = prefix; } + + virtual QString capturedFileName() const + { + return !m_capturedFilesNames.isEmpty() ? m_capturedFilesNames.last() : QString(); + } + virtual QStringList capturedFilesNames() const { return m_capturedFilesNames; } + + virtual bool initialized() const = 0; + virtual bool isCapturing() const = 0; + virtual void openCapture() = 0; + +protected: + QRhi *m_rhi = nullptr; + QRhiNativeHandles *m_rhiHandles = nullptr; + void *m_nativeHandle = nullptr; + QString m_capturePath; + QString m_capturePrefix; + QStringList m_capturedFilesNames; +}; + +QT_END_NAMESPACE + +#endif // QGRAPHICSFRAMECAPTURE_P_P_H diff --git a/src/gui/util/qgraphicsframecapturemetal.mm b/src/gui/util/qgraphicsframecapturemetal.mm new file mode 100644 index 0000000000..b0ff0bab2b --- /dev/null +++ b/src/gui/util/qgraphicsframecapturemetal.mm @@ -0,0 +1,169 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qgraphicsframecapturemetal_p_p.h" +#include <QtCore/qurl.h> +#include "Metal/Metal.h" +#include "qglobal.h" +#include <QtGui/rhi/qrhi.h> +#include <QtGui/rhi/qrhi_platform.h> + +QT_BEGIN_NAMESPACE + +Q_LOGGING_CATEGORY(lcGraphicsFrameCapture, "qt.gui.graphicsframecapture") + +#if __has_feature(objc_arc) +#error ARC not supported +#endif + +uint QGraphicsFrameCaptureMetal::frameNumber = 0; + +QGraphicsFrameCaptureMetal::QGraphicsFrameCaptureMetal() +{ + qputenv("METAL_CAPTURE_ENABLED", QByteArrayLiteral("1")); + + m_captureDescriptor = [MTLCaptureDescriptor new]; +} + +QGraphicsFrameCaptureMetal::~QGraphicsFrameCaptureMetal() +{ +#if defined(Q_OS_MACOS) && QT_CONFIG(process) + if (m_process) { + m_process->terminate(); + delete m_process; + } +#endif + [m_captureDescriptor release]; +} + +void QGraphicsFrameCaptureMetal::setRhi(QRhi *rhi) +{ + if (!rhi) + return; + + QRhi::Implementation backend = rhi->backend(); + const QRhiNativeHandles *nh = rhi->nativeHandles(); + + switch (backend) { + case QRhi::Implementation::Metal: { + const QRhiMetalNativeHandles *mtlnh = static_cast<const QRhiMetalNativeHandles *>(nh); + if (mtlnh->cmdQueue) { + m_captureDescriptor.captureObject = mtlnh->cmdQueue; + } else if (mtlnh->dev) { + m_captureDescriptor.captureObject = mtlnh->dev; + } else { + qCWarning(lcGraphicsFrameCapture) << "No valid Metal Device or Metal Command Queue found"; + m_initialized = false; + return; + } + break; + } + default: { + qCWarning(lcGraphicsFrameCapture) << "Invalid handles were provided. MTLCaptureManager works only with Metal API"; + m_initialized = false; + return; + break; + } + } + + if (!m_captureManager) { + m_captureManager = MTLCaptureManager.sharedCaptureManager; + bool supportDocs = [m_captureManager supportsDestination:MTLCaptureDestinationGPUTraceDocument]; + if (supportDocs) { + m_captureDescriptor.destination = MTLCaptureDestinationGPUTraceDocument; + m_initialized = true; + } + } +} + +void QGraphicsFrameCaptureMetal::startCaptureFrame() +{ + if (!initialized()) { + qCWarning(lcGraphicsFrameCapture) << "Capturing on Metal was not initialized. Starting capturing can not be done."; + return; + } + + if (isCapturing()) { + qCWarning(lcGraphicsFrameCapture) << "A frame capture is already in progress," + "will not initiate another one until QGraphicsFrameCapture::endCaptureFrame is called."; + return; + } + + updateCaptureFileName(); + NSError *error; + if (![m_captureManager startCaptureWithDescriptor:m_captureDescriptor error:&error]) { + QString errorMsg = QString::fromNSString(error.localizedDescription); + qCWarning(lcGraphicsFrameCapture, "Failed to start capture : %s", qPrintable(errorMsg)); + } +} + +void QGraphicsFrameCaptureMetal::endCaptureFrame() +{ + if (!initialized()) { + qCWarning(lcGraphicsFrameCapture) << "Capturing on Metal was not initialized. End capturing can not be done."; + return; + } + + if (!isCapturing()) { + qCWarning(lcGraphicsFrameCapture) << "A call to QGraphicsFrameCapture::endCaptureFrame can not be done" + " without a call to QGraphicsFrameCapture::startCaptureFrame"; + return; + } + + [m_captureManager stopCapture]; + m_capturedFilesNames.append(QString::fromNSString(m_traceURL.path)); + frameNumber++; +} + +bool QGraphicsFrameCaptureMetal::initialized() const +{ + return m_initialized; +} + +bool QGraphicsFrameCaptureMetal::isCapturing() const +{ + if (!initialized()) { + qCWarning(lcGraphicsFrameCapture) << "Capturing on Metal was not initialized. Can not query if capturing is in progress or not."; + return false; + } + + return [m_captureManager isCapturing]; +} + +void QGraphicsFrameCaptureMetal::openCapture() +{ +#if defined(Q_OS_MACOS) +#if !QT_CONFIG(process) + qFatal("QGraphicsFrameCapture requires QProcess on macOS"); +#else + if (!initialized()) { + qCWarning(lcGraphicsFrameCapture) << "Capturing on Metal was not initialized. Can not open XCode with a valid capture."; + return; + } + + if (!m_process) { + m_process = new QProcess(); + m_process->setProgram(QStringLiteral("xed")); + QStringList args; + args.append(QUrl::fromNSURL(m_traceURL).toLocalFile()); + m_process->setArguments(args); + } + + m_process->kill(); + m_process->start(); +#endif +#endif +} + +void QGraphicsFrameCaptureMetal::updateCaptureFileName() +{ + m_traceURL = QUrl::fromLocalFile(m_capturePath + "/" + m_capturePrefix + "_" + QString::number(frameNumber) + ".gputrace").toNSURL(); + // We need to remove the trace file if it already existed else MTLCaptureManager + // will fail to. + if ([NSFileManager.defaultManager fileExistsAtPath:m_traceURL.path]) + [NSFileManager.defaultManager removeItemAtURL:m_traceURL error:nil]; + + m_captureDescriptor.outputURL = m_traceURL; +} + +QT_END_NAMESPACE diff --git a/src/gui/util/qgraphicsframecapturemetal_p_p.h b/src/gui/util/qgraphicsframecapturemetal_p_p.h new file mode 100644 index 0000000000..d703949de2 --- /dev/null +++ b/src/gui/util/qgraphicsframecapturemetal_p_p.h @@ -0,0 +1,57 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QGRAPHICSFRAMEDECAPTUREMETAL_P_P_H +#define QGRAPHICSFRAMEDECAPTUREMETAL_P_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qgraphicsframecapture_p_p.h" +#include <QtCore/qmutex.h> +#ifdef Q_OS_MACOS +#include <QtCore/qprocess.h> +#endif + +Q_FORWARD_DECLARE_OBJC_CLASS(MTLCaptureManager); +Q_FORWARD_DECLARE_OBJC_CLASS(MTLCaptureDescriptor); +Q_FORWARD_DECLARE_OBJC_CLASS(NSURL); + +QT_BEGIN_NAMESPACE + +class QGraphicsFrameCaptureMetal : public QGraphicsFrameCapturePrivate +{ +public: + QGraphicsFrameCaptureMetal(); + ~QGraphicsFrameCaptureMetal(); + + void setRhi(QRhi *rhi) override; + void startCaptureFrame() override; + void endCaptureFrame() override; + bool initialized() const override; + bool isCapturing() const override; + void openCapture() override; + +private: + void updateCaptureFileName(); +#if defined(Q_OS_MACOS) && QT_CONFIG(process) + QProcess *m_process = nullptr; +#endif + MTLCaptureManager *m_captureManager = nullptr; + MTLCaptureDescriptor *m_captureDescriptor = nullptr; + NSURL *m_traceURL = nullptr; + bool m_initialized = false; + static uint frameNumber; +}; + +QT_END_NAMESPACE + +#endif // QGRAPHICSFRAMEDECAPTUREMETAL_P_P_H diff --git a/src/gui/util/qgraphicsframecapturerenderdoc.cpp b/src/gui/util/qgraphicsframecapturerenderdoc.cpp new file mode 100644 index 0000000000..88ba9d839f --- /dev/null +++ b/src/gui/util/qgraphicsframecapturerenderdoc.cpp @@ -0,0 +1,310 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qgraphicsframecapturerenderdoc_p_p.h" +#include <QtCore/qcoreapplication.h> +#include <QtCore/qfile.h> +#include <QtCore/qlibrary.h> +#include <QtCore/qmutex.h> +#include "QtGui/rhi/qrhi.h" +#include "QtGui/rhi/qrhi_platform.h" +#include "QtGui/qopenglcontext.h" + +QT_BEGIN_NAMESPACE + +Q_LOGGING_CATEGORY(lcGraphicsFrameCapture, "qt.gui.graphicsframecapture") + +RENDERDOC_API_1_6_0 *QGraphicsFrameCaptureRenderDoc::s_rdocApi = nullptr; +#if QT_CONFIG(thread) +QBasicMutex QGraphicsFrameCaptureRenderDoc::s_frameCaptureMutex; +#endif + +#if QT_CONFIG(opengl) +static void *glNativeContext(QOpenGLContext *context) { + void *nctx = nullptr; + if (context != nullptr && context->isValid()) { +#ifdef Q_OS_WIN + nctx = context->nativeInterface<QNativeInterface::QWGLContext>()->nativeContext(); +#endif + +#ifdef Q_OS_LINUX +#if QT_CONFIG(egl) + QNativeInterface::QEGLContext *eglItf = context->nativeInterface<QNativeInterface::QEGLContext>(); + if (eglItf) + nctx = eglItf->nativeContext(); +#endif + +#if QT_CONFIG(xcb_glx_plugin) + QNativeInterface::QGLXContext *glxItf = context->nativeInterface<QNativeInterface::QGLXContext>(); + if (glxItf) + nctx = glxItf->nativeContext(); +#endif +#endif + +#if QT_CONFIG(metal) + nctx = context->nativeInterface<QNativeInterface::QCocoaGLContext>()->nativeContext(); +#endif + } + return nctx; +} +#endif // QT_CONFIG(opengl) + +/*! + \class QGraphicsFrameCaptureRenderDoc + \internal + \brief The QGraphicsFrameCaptureRenderDoc class provides a way to capture a record of draw calls + for different graphics APIs. + \since 6.6 + \inmodule QtGui + + For applications that render using graphics APIs like Vulkan or OpenGL, it would be + convenient to have a way to check the draw calls done by the application. Specially + for applications that make a large amount of draw calls and the output is different + from what is expected. + + This class acts as a wrapper over \l {https://renderdoc.org/}{RenderDoc} that allows + applications to capture a rendered frame either programmatically, by clicking a key + on the keyboard or both. The captured frame could be viewed later using RenderDoc GUI. + + Read the \l {https://renderdoc.org/docs/index.html} {RenderDoc Documentation} + for more information. + + \section1 API device handle + + The functions that capture a frame like QGraphicsFrameCaptureRenderDoc::startCaptureFrame takes a device + pointer as argument. This pointer is unique for each graphics API and is associated + with the window that will be captured. This pointer has a default value of \c nullptr. + If no value is passed to the function the underlying API will try to find the device to + use, but it is not guaranteed specially in a multi-window applications. + + For OpenGL, the pointer should be the OpenGL context on the platform OpenGL is being + used. For example, on Windows it should be \c HGLRC. + + For Vulkan, the pointer should point to the dispatch table within the \c VkInstance. +*/ + + + +/*! + Creates a new object of this class. The constructor will load RenderDoc library + from the default path. + + Only one instance of RenderDoc library is loaded at runtime which means creating + several instances of this class will not affect the RenderDoc initialization. +*/ + +QGraphicsFrameCaptureRenderDoc::QGraphicsFrameCaptureRenderDoc() + : m_nativeHandlesSet(false) +{ + if (!s_rdocApi) + init(); +} + +void QGraphicsFrameCaptureRenderDoc::setRhi(QRhi *rhi) +{ + if (!rhi) + return; + + QRhi::Implementation backend = rhi->backend(); + const QRhiNativeHandles *nh = rhi->nativeHandles(); + + switch (backend) { + case QRhi::Implementation::D3D11: { +#ifdef Q_OS_WIN + const QRhiD3D11NativeHandles *d3d11nh = static_cast<const QRhiD3D11NativeHandles *>(nh); + m_nativeHandle = d3d11nh->dev; + break; +#endif + qCWarning(lcGraphicsFrameCapture) << "Could not find valid handles for D3D11. Check platform support"; + break; + } + case QRhi::Implementation::D3D12: { +#ifdef Q_OS_WIN + const QRhiD3D12NativeHandles *d3d12nh = static_cast<const QRhiD3D12NativeHandles *>(nh); + m_nativeHandle = d3d12nh->dev; + break; +#endif + qCWarning(lcGraphicsFrameCapture) << "Could not find valid handles for D3D12. Check platform support"; + break; + } + case QRhi::Implementation::Vulkan: { +#if QT_CONFIG(vulkan) + const QRhiVulkanNativeHandles *vknh = static_cast<const QRhiVulkanNativeHandles *>(nh); + m_nativeHandle = RENDERDOC_DEVICEPOINTER_FROM_VKINSTANCE(vknh->inst->vkInstance()); + break; +#endif + qCWarning(lcGraphicsFrameCapture) << "Could not find valid handles for Vulkan. Check platform support"; + break; + } + case QRhi::Implementation::OpenGLES2: { +#ifndef QT_NO_OPENGL + const QRhiGles2NativeHandles *glnh = static_cast<const QRhiGles2NativeHandles *>(nh); + m_nativeHandle = glNativeContext(glnh->context); + if (m_nativeHandle) + break; +#endif + qCWarning(lcGraphicsFrameCapture) << "Could not find valid handles for OpenGL. Check platform support"; + break; + } + case QRhi::Implementation::Metal: + case QRhi::Implementation::Null: + qCWarning(lcGraphicsFrameCapture) << "Invalid handles were provided." + " Metal and Null backends are not supported with RenderDoc"; + break; + } + + if (m_nativeHandle) + m_nativeHandlesSet = true; +} + +/*! + Starts a frame capture using the set native handles provided through QGraphicsFrameCaptureRenderDoc::setRhi + \a device. This function must be called before QGraphicsFrameCaptureRenderDoc::endCaptureFrame. + \sa {API device handle} +*/ +void QGraphicsFrameCaptureRenderDoc::startCaptureFrame() +{ + + if (!initialized()) { + qCWarning(lcGraphicsFrameCapture) << "RenderDoc was not initialized." + " Starting capturing can not be done."; + return; + } + +#if QT_CONFIG(thread) + // There is a single instance of RenderDoc library and it needs mutex for multithreading access. + QMutexLocker locker(&s_frameCaptureMutex); +#endif + if (s_rdocApi->IsFrameCapturing()) { + qCWarning(lcGraphicsFrameCapture) << "A frame capture is already in progress, " + "will not initiate another one until" + " QGraphicsFrameCapture::endCaptureFrame is called."; + return; + } + + qCInfo(lcGraphicsFrameCapture) << "A frame capture is going to start."; + updateCapturePathAndTemplate(); + s_rdocApi->StartFrameCapture(m_nativeHandle, nullptr); +} + +/*! + Ends a frame capture started by a call to QGraphicsFrameCaptureRenderDoc::startCaptureFrame + using the set native handles provided through QGraphicsFrameCaptureRenderDoc::setRhi. + This function must be called after QGraphicsFrameCaptureRenderDoc::startCaptureFrame. + Otherwise, a warning message will be printend and nothing will happen. + \sa {API device handle} +*/ +void QGraphicsFrameCaptureRenderDoc::endCaptureFrame() +{ + if (!initialized()) { + qCWarning(lcGraphicsFrameCapture) << "RenderDoc was not initialized." + " End capturing can not be done."; + return; + } + +#if QT_CONFIG(thread) + // There is a single instance of RenderDoc library and it needs mutex for multithreading access. + QMutexLocker locker(&s_frameCaptureMutex); +#endif + if (!s_rdocApi->IsFrameCapturing()) { + qCWarning(lcGraphicsFrameCapture) << "A call to QGraphicsFrameCapture::endCaptureFrame can not be done" + " without a call to QGraphicsFrameCapture::startCaptureFrame"; + return; + } + + qCInfo(lcGraphicsFrameCapture) << "A frame capture is going to end."; + uint32_t result = s_rdocApi->EndFrameCapture(m_nativeHandle, nullptr); + + if (result) { + uint32_t count = s_rdocApi->GetNumCaptures(); + uint32_t pathLength = 0; + s_rdocApi->GetCapture(count - 1, nullptr, &pathLength, nullptr); + if (pathLength > 0) { + QVarLengthArray<char> name(pathLength, 0); + s_rdocApi->GetCapture(count - 1, name.data(), &pathLength, nullptr); + m_capturedFilesNames.append(QString::fromUtf8(name.data(), -1)); + } + } +} + +void QGraphicsFrameCaptureRenderDoc::updateCapturePathAndTemplate() +{ + if (!initialized()) { + qCWarning(lcGraphicsFrameCapture) << "RenderDoc was not initialized." + " Updating save location can not be done."; + return; + } + + + QString rdocFilePathTemplate = m_capturePath + QStringLiteral("/") + m_capturePrefix; + s_rdocApi->SetCaptureFilePathTemplate(rdocFilePathTemplate.toUtf8().constData()); +} + +/*! + Returns true if the API is loaded and can capture frames or not. +*/ +bool QGraphicsFrameCaptureRenderDoc::initialized() const +{ + return s_rdocApi && m_nativeHandlesSet; +} + +bool QGraphicsFrameCaptureRenderDoc::isCapturing() const +{ + if (!initialized()) { + qCWarning(lcGraphicsFrameCapture) << "RenderDoc was not initialized." + " Can not query if capturing is in progress or not."; + return false; + } + + return s_rdocApi->IsFrameCapturing(); +} + +void QGraphicsFrameCaptureRenderDoc::openCapture() +{ + if (!initialized()) { + qCWarning(lcGraphicsFrameCapture) << "RenderDoc was not initialized." + " Can not open RenderDoc UI tool."; + return; + } + +#if QT_CONFIG(thread) + // There is a single instance of RenderDoc library and it needs mutex for multithreading access. + QMutexLocker locker(&s_frameCaptureMutex); +#endif + if (s_rdocApi->IsTargetControlConnected()) + s_rdocApi->ShowReplayUI(); + else + s_rdocApi->LaunchReplayUI(1, nullptr); +} + +void QGraphicsFrameCaptureRenderDoc::init() +{ +#if QT_CONFIG(thread) + // There is a single instance of RenderDoc library and it needs mutex for multithreading access. + QMutexLocker locker(&s_frameCaptureMutex); +#endif + + QLibrary renderDocLib(QStringLiteral("renderdoc")); + pRENDERDOC_GetAPI RENDERDOC_GetAPI = (pRENDERDOC_GetAPI) renderDocLib.resolve("RENDERDOC_GetAPI"); + if (!renderDocLib.isLoaded() || (RENDERDOC_GetAPI == nullptr)) { + qCWarning(lcGraphicsFrameCapture) << renderDocLib.errorString().toLatin1(); + return; + } + + int ret = RENDERDOC_GetAPI(eRENDERDOC_API_Version_1_6_0, static_cast<void **>(static_cast<void *>(&s_rdocApi))); + + if (ret == 0) { + qCWarning(lcGraphicsFrameCapture) << "The requested RenderDoc API is invalid or not supported"; + return; + } + + s_rdocApi->MaskOverlayBits(RENDERDOC_OverlayBits::eRENDERDOC_Overlay_None, + RENDERDOC_OverlayBits::eRENDERDOC_Overlay_None); + s_rdocApi->SetCaptureKeys(nullptr, 0); + s_rdocApi->SetFocusToggleKeys(nullptr, 0); + + QString rdocFilePathTemplate = m_capturePath + QStringLiteral("/") + m_capturePrefix; + s_rdocApi->SetCaptureFilePathTemplate(rdocFilePathTemplate.toUtf8().constData()); +} + +QT_END_NAMESPACE diff --git a/src/gui/util/qgraphicsframecapturerenderdoc_p_p.h b/src/gui/util/qgraphicsframecapturerenderdoc_p_p.h new file mode 100644 index 0000000000..c0d92ea733 --- /dev/null +++ b/src/gui/util/qgraphicsframecapturerenderdoc_p_p.h @@ -0,0 +1,53 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QGRAPHICSFRAMECAPTURERENDERDOC_P_P_H +#define QGRAPHICSFRAMECAPTURERENDERDOC_P_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + + +#include <renderdoc_app.h> +#include "qgraphicsframecapture_p_p.h" + +QT_BEGIN_NAMESPACE + +#if QT_CONFIG(thread) +class QBasicMutex; +#endif + +class QGraphicsFrameCaptureRenderDoc : public QGraphicsFrameCapturePrivate +{ +public: + QGraphicsFrameCaptureRenderDoc(); + ~QGraphicsFrameCaptureRenderDoc() = default; + + void setRhi(QRhi *rhi) override; + void startCaptureFrame() override; + void endCaptureFrame() override; + bool initialized() const override; + bool isCapturing() const override; + void openCapture() override; + +private: + void init(); + void updateCapturePathAndTemplate(); + static RENDERDOC_API_1_5_0 *s_rdocApi; +#if QT_CONFIG(thread) + static QBasicMutex s_frameCaptureMutex; +#endif + bool m_nativeHandlesSet; +}; + +QT_END_NAMESPACE + +#endif // QGRAPHICSFRAMECAPTURERENDERDOC_P_P_H diff --git a/src/gui/util/qgridlayoutengine.cpp b/src/gui/util/qgridlayoutengine.cpp index d875db0da6..07981e8388 100644 --- a/src/gui/util/qgridlayoutengine.cpp +++ b/src/gui/util/qgridlayoutengine.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/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 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qglobal.h" @@ -47,10 +11,14 @@ QT_BEGIN_NAMESPACE +using namespace Qt::StringLiterals; + +#define LAYOUTITEMSIZE_MAX (1 << 24) + template<typename T> static void insertOrRemoveItems(QList<T> &items, int index, int delta) { - int count = items.count(); + int count = items.size(); if (index < count) { if (delta > 0) { items.insert(index, delta, T()); @@ -228,7 +196,8 @@ void QGridLayoutRowData::calculateGeometries(int start, int end, qreal targetSiz sumAvailable = targetSize - totalBox.q_minimumSize; if (sumAvailable > 0.0) { - qreal sumDesired = totalBox.q_preferredSize - totalBox.q_minimumSize; + const qreal totalBox_preferredSize = qMin(totalBox.q_preferredSize, qreal(LAYOUTITEMSIZE_MAX)); + qreal sumDesired = totalBox_preferredSize - totalBox.q_minimumSize; for (int i = 0; i < n; ++i) { if (ignore.testBit(start + i)) { @@ -237,7 +206,8 @@ void QGridLayoutRowData::calculateGeometries(int start, int end, qreal targetSiz } const QGridLayoutBox &box = boxes.at(start + i); - qreal desired = box.q_preferredSize - box.q_minimumSize; + const qreal box_preferredSize = qMin(box.q_preferredSize, qreal(LAYOUTITEMSIZE_MAX)); + qreal desired = box_preferredSize - box.q_minimumSize; factors[i] = growthFactorBelowPreferredSize(desired, sumAvailable, sumDesired); sumFactors += factors[i]; } @@ -750,7 +720,7 @@ void QGridLayoutItem::dump(int indent) const if (q_alignment != 0) qDebug("%*s Alignment: %x", indent, "", uint(q_alignment)); qDebug("%*s Horizontal size policy: %x Vertical size policy: %x", - indent, "", sizePolicy(Qt::Horizontal), sizePolicy(Qt::Vertical)); + indent, "", (unsigned int)sizePolicy(Qt::Horizontal), (unsigned int)sizePolicy(Qt::Vertical)); } #endif @@ -792,6 +762,8 @@ QGridLayoutEngine::QGridLayoutEngine(Qt::Alignment defaultAlignment, bool snapTo m_visualDirection = Qt::LeftToRight; m_defaultAlignment = defaultAlignment; m_snapToPixelGrid = snapToPixelGrid; + m_uniformCellWidths = false; + m_uniformCellHeights = false; invalidate(); } @@ -807,7 +779,7 @@ int QGridLayoutEngine::columnCount(Qt::Orientation orientation) const int QGridLayoutEngine::itemCount() const { - return q_items.count(); + return q_items.size(); } QGridLayoutItem *QGridLayoutEngine::itemAt(int index) const @@ -852,7 +824,7 @@ void QGridLayoutEngine::setRowSpacing(int row, qreal spacing, Qt::Orientation or Q_ASSERT(row >= 0); QGridLayoutRowInfo &rowInfo = q_infos[orientation]; - if (row >= rowInfo.spacings.count()) + if (row >= rowInfo.spacings.size()) rowInfo.spacings.resize(row + 1); if (spacing >= 0) rowInfo.spacings[row].setUserValue(spacing); @@ -877,7 +849,7 @@ void QGridLayoutEngine::setRowStretchFactor(int row, int stretch, Qt::Orientatio maybeExpandGrid(row, -1, orientation); QGridLayoutRowInfo &rowInfo = q_infos[orientation]; - if (row >= rowInfo.stretches.count()) + if (row >= rowInfo.stretches.size()) rowInfo.stretches.resize(row + 1); rowInfo.stretches[row].setUserValue(stretch); } @@ -899,7 +871,7 @@ void QGridLayoutEngine::setRowSizeHint(Qt::SizeHint which, int row, qreal size, maybeExpandGrid(row, -1, orientation); QGridLayoutRowInfo &rowInfo = q_infos[orientation]; - if (row >= rowInfo.boxes.count()) + if (row >= rowInfo.boxes.size()) rowInfo.boxes.resize(row + 1); rowInfo.boxes[row].q_sizes(which) = size; } @@ -909,6 +881,34 @@ qreal QGridLayoutEngine::rowSizeHint(Qt::SizeHint which, int row, Qt::Orientatio return q_infos[orientation].boxes.value(row).q_sizes(which); } +bool QGridLayoutEngine::uniformCellWidths() const +{ + return m_uniformCellWidths; +} + +void QGridLayoutEngine::setUniformCellWidths(bool uniformCellWidths) +{ + if (m_uniformCellWidths == uniformCellWidths) + return; + + m_uniformCellWidths = uniformCellWidths; + invalidate(); +} + +bool QGridLayoutEngine::uniformCellHeights() const +{ + return m_uniformCellHeights; +} + +void QGridLayoutEngine::setUniformCellHeights(bool uniformCellHeights) +{ + if (m_uniformCellHeights == uniformCellHeights) + return; + + m_uniformCellHeights = uniformCellHeights; + invalidate(); +} + void QGridLayoutEngine::setRowAlignment(int row, Qt::Alignment alignment, Qt::Orientation orientation) { @@ -917,7 +917,7 @@ void QGridLayoutEngine::setRowAlignment(int row, Qt::Alignment alignment, maybeExpandGrid(row, -1, orientation); QGridLayoutRowInfo &rowInfo = q_infos[orientation]; - if (row >= rowInfo.alignments.count()) + if (row >= rowInfo.alignments.size()) rowInfo.alignments.resize(row + 1); rowInfo.alignments[row] = alignment; } @@ -964,8 +964,11 @@ void QGridLayoutEngine::insertItem(QGridLayoutItem *item, int index) for (int i = item->firstRow(); i <= item->lastRow(); ++i) { for (int j = item->firstColumn(); j <= item->lastColumn(); ++j) { - if (itemAt(i, j)) - qWarning("QGridLayoutEngine::addItem: Cell (%d, %d) already taken", i, j); + const auto existingItem = itemAt(i, j); + if (existingItem) { + qWarning("QGridLayoutEngine::addItem: Can't add %s at cell (%d, %d) because it's already taken by %s", + qPrintable(item->toString()), i, j, qPrintable(existingItem->toString())); + } setItemAt(i, j, item); } } @@ -1026,7 +1029,7 @@ void QGridLayoutEngine::setGeometries(const QRectF &contentsGeometry, const QAbs ensureGeometries(contentsGeometry.size(), styleInfo); - for (int i = q_items.count() - 1; i >= 0; --i) { + for (int i = q_items.size() - 1; i >= 0; --i) { QGridLayoutItem *item = q_items.at(i); qreal x = q_xx.at(item->firstColumn()); @@ -1155,7 +1158,7 @@ void QGridLayoutEngine::transpose() { invalidate(); - for (int i = q_items.count() - 1; i >= 0; --i) + for (int i = q_items.size() - 1; i >= 0; --i) q_items.at(i)->transpose(); q_defaultSpacings.transpose(); @@ -1179,7 +1182,7 @@ void QGridLayoutEngine::dump(int indent) const { qDebug("%*sEngine", indent, ""); - qDebug("%*s Items (%d)", indent, "", q_items.count()); + qDebug("%*s Items (%lld)", indent, "", q_items.count()); int i; for (i = 0; i < q_items.count(); ++i) q_items.at(i)->dump(indent + 2); @@ -1187,12 +1190,12 @@ void QGridLayoutEngine::dump(int indent) const qDebug("%*s Grid (%d x %d)", indent, "", internalGridRowCount(), internalGridColumnCount()); for (int row = 0; row < internalGridRowCount(); ++row) { - QString message = QLatin1String("[ "); + QString message = "[ "_L1; for (int column = 0; column < internalGridColumnCount(); ++column) { message += QString::number(q_items.indexOf(itemAt(row, column))).rightJustified(3); - message += QLatin1Char(' '); + message += u' '; } - message += QLatin1Char(']'); + message += u']'; qDebug("%*s %s", indent, "", qPrintable(message)); } @@ -1214,10 +1217,10 @@ void QGridLayoutEngine::dump(int indent) const for (int pass = 0; pass < 2; ++pass) { QString message; for (i = 0; i < cellPos->count(); ++i) { - message += QLatin1String((message.isEmpty() ? "[" : ", ")); + message += (message.isEmpty() ? "["_L1 : ", "_L1); message += QString::number(cellPos->at(i)); } - message += QLatin1Char(']'); + message += u']'; qDebug("%*s %s %s", indent, "", (pass == 0 ? "rows:" : "columns:"), qPrintable(message)); cellPos = &q_xx; } @@ -1244,7 +1247,7 @@ void QGridLayoutEngine::maybeExpandGrid(int row, int column, Qt::Orientation ori int newGridColumnCount = internalGridColumnCount(); int newGridSize = newGridRowCount * newGridColumnCount; - if (newGridSize != q_grid.count()) { + if (newGridSize != q_grid.size()) { q_grid.resize(newGridSize); if (newGridColumnCount != oldGridColumnCount) { @@ -1266,7 +1269,7 @@ void QGridLayoutEngine::regenerateGrid() { q_grid.fill(nullptr); - for (int i = q_items.count() - 1; i >= 0; --i) { + for (int i = q_items.size() - 1; i >= 0; --i) { QGridLayoutItem *item = q_items.at(i); for (int j = item->firstRow(); j <= item->lastRow(); ++j) { @@ -1299,7 +1302,7 @@ void QGridLayoutEngine::insertOrRemoveRows(int row, int delta, Qt::Orientation o q_infos[orientation].insertOrRemoveRows(row, delta); - for (int i = q_items.count() - 1; i >= 0; --i) + for (int i = q_items.size() - 1; i >= 0; --i) q_items.at(i)->insertOrRemoveRows(row, delta, orientation); q_grid.resize(internalGridRowCount() * internalGridColumnCount()); @@ -1440,7 +1443,7 @@ void QGridLayoutEngine::fillRowData(QGridLayoutRowData *rowData, } } } - if (row < rowInfo.boxes.count()) { + if (row < rowInfo.boxes.size()) { QGridLayoutBox rowBoxInfo = rowInfo.boxes.at(row); rowBoxInfo.normalize(); rowBox.q_minimumSize = qMax(rowBox.q_minimumSize, rowBoxInfo.q_minimumSize); @@ -1533,6 +1536,27 @@ void QGridLayoutEngine::fillRowData(QGridLayoutRowData *rowData, rowSpacing = qMax(windowMargin, rowSpacing); } } + + if (rowData->boxes.size() > 1 && + ((orientation == Qt::Horizontal && m_uniformCellWidths) || + (orientation == Qt::Vertical && m_uniformCellHeights))) { + qreal averagePreferredSize = 0.; + qreal minimumMaximumSize = std::numeric_limits<qreal>::max(); + qreal maximumMinimumSize = 0.; + for (const auto &box : rowData->boxes) { + averagePreferredSize += box.q_preferredSize; + minimumMaximumSize = qMin(minimumMaximumSize, box.q_maximumSize); + maximumMinimumSize = qMax(maximumMinimumSize, box.q_minimumSize); + } + averagePreferredSize /= rowData->boxes.size(); + minimumMaximumSize = qMax(minimumMaximumSize, maximumMinimumSize); + averagePreferredSize = qBound(maximumMinimumSize, averagePreferredSize, minimumMaximumSize); + for (auto &box : rowData->boxes) { + box.q_preferredSize = averagePreferredSize; + box.q_minimumSize = maximumMinimumSize; + box.q_maximumSize = minimumMaximumSize; + } + } } void QGridLayoutEngine::ensureEffectiveFirstAndLastRows() const @@ -1544,7 +1568,7 @@ void QGridLayoutEngine::ensureEffectiveFirstAndLastRows() const q_cachedEffectiveFirstRows = {columnCount, rowCount}; q_cachedEffectiveLastRows = {-1, -1}; - for (int i = q_items.count() - 1; i >= 0; --i) { + for (int i = q_items.size() - 1; i >= 0; --i) { const QGridLayoutItem *item = q_items.at(i); for (Qt::Orientation o : {Qt::Horizontal, Qt::Vertical}) { @@ -1590,7 +1614,7 @@ void QGridLayoutEngine::ensureColumnAndRowData(QGridLayoutRowData *rowData, QGri bool QGridLayoutEngine::ensureDynamicConstraint() const { if (q_cachedConstraintOrientation == UnknownConstraint) { - for (int i = q_items.count() - 1; i >= 0; --i) { + for (int i = q_items.size() - 1; i >= 0; --i) { QGridLayoutItem *item = q_items.at(i); if (item->hasDynamicConstraint()) { Qt::Orientation itemConstraintOrientation = item->dynamicConstraintOrientation(); diff --git a/src/gui/util/qgridlayoutengine_p.h b/src/gui/util/qgridlayoutengine_p.h index 329202571b..2f60cb99fd 100644 --- a/src/gui/util/qgridlayoutengine_p.h +++ b/src/gui/util/qgridlayoutengine_p.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/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 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QGRIDLAYOUTENGINE_P_H #define QGRIDLAYOUTENGINE_P_H @@ -60,6 +24,7 @@ #include <QtCore/qpair.h> #include <QtCore/qsize.h> #include <QtCore/qrect.h> +#include <QtCore/qdebug.h> #include <float.h> #include "qlayoutpolicy_p.h" @@ -319,6 +284,8 @@ public: virtual QLayoutPolicy::ControlTypes controlTypes(LayoutSide side) const; + inline virtual QString toString() const { return QDebug::toString(this); } + QRectF geometryWithin(qreal x, qreal y, qreal width, qreal height, qreal rowDescent, Qt::Alignment align, bool snapToPixelGrid) const; QGridLayoutBox box(Qt::Orientation orientation, bool snapToPixelGrid, qreal constraint = -1.0) const; @@ -370,6 +337,12 @@ public: qreal rowSizeHint(Qt::SizeHint which, int row, Qt::Orientation orientation = Qt::Vertical) const; + bool uniformCellWidths() const; + void setUniformCellWidths(bool uniformCellWidths); + + bool uniformCellHeights() const; + void setUniformCellHeights(bool uniformCellHeights); + void setRowAlignment(int row, Qt::Alignment alignment, Qt::Orientation orientation); Qt::Alignment rowAlignment(int row, Qt::Orientation orientation) const; @@ -451,6 +424,8 @@ private: // Configuration Qt::Alignment m_defaultAlignment; unsigned m_snapToPixelGrid : 1; + unsigned m_uniformCellWidths : 1; + unsigned m_uniformCellHeights : 1; // Lazily computed from the above user input mutable QHVContainer<int> q_cachedEffectiveFirstRows; diff --git a/src/gui/util/qhexstring_p.h b/src/gui/util/qhexstring_p.h index 2afbf3a42b..2b42e6c43e 100644 --- a/src/gui/util/qhexstring_p.h +++ b/src/gui/util/qhexstring_p.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/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 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include <QtGui/private/qtguiglobal_p.h> #include <QtCore/qpoint.h> diff --git a/src/gui/util/qktxhandler.cpp b/src/gui/util/qktxhandler.cpp index 9f4545f3af..35f1df1185 100644 --- a/src/gui/util/qktxhandler.cpp +++ b/src/gui/util/qktxhandler.cpp @@ -1,46 +1,11 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/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 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qktxhandler_p.h" #include "qtexturefiledata_p.h" #include <QtEndian> #include <QSize> +#include <QMap> #include <QtCore/qiodevice.h> //#define KTX_DEBUG @@ -52,6 +17,8 @@ QT_BEGIN_NAMESPACE +using namespace Qt::StringLiterals; + #define KTX_IDENTIFIER_LENGTH 12 static const char ktxIdentifier[KTX_IDENTIFIER_LENGTH] = { '\xAB', 'K', 'T', 'X', ' ', '1', '1', '\xBB', '\r', '\n', '\x1A', '\n' }; static const quint32 platformEndianIdentifier = 0x04030201; @@ -74,7 +41,7 @@ struct KTXHeader { quint32 bytesOfKeyValueData; }; -static const quint32 headerSize = sizeof(KTXHeader); +static constexpr quint32 qktxh_headerSize = sizeof(KTXHeader); // Currently unused, declared for future reference struct KTXKeyValuePairItem { @@ -104,18 +71,32 @@ struct KTXMipmapLevel { */ }; -// Returns the nearest multiple of 'rounding' greater than or equal to 'value' -constexpr quint32 withPadding(quint32 value, quint32 rounding) +// Returns the nearest multiple of 4 greater than or equal to 'value' +static const std::optional<quint32> nearestMultipleOf4(quint32 value) +{ + constexpr quint32 rounding = 4; + quint32 result = 0; + if (qAddOverflow(value, rounding - 1, &result)) + return std::nullopt; + result &= ~(rounding - 1); + return result; +} + +// Returns a view with prechecked bounds +static QByteArrayView safeView(QByteArrayView view, quint32 start, quint32 length) { - Q_ASSERT(rounding > 1); - return value + (rounding - 1) - ((value + (rounding - 1)) % rounding); + quint32 end = 0; + if (qAddOverflow(start, length, &end) || end > quint32(view.length())) + return {}; + return view.sliced(start, length); } +QKtxHandler::~QKtxHandler() = default; + bool QKtxHandler::canRead(const QByteArray &suffix, const QByteArray &block) { Q_UNUSED(suffix); - - return (qstrncmp(block.constData(), ktxIdentifier, KTX_IDENTIFIER_LENGTH) == 0); + return block.startsWith(ktxIdentifier); } QTextureFileData QKtxHandler::read() @@ -123,56 +104,123 @@ QTextureFileData QKtxHandler::read() if (!device()) return QTextureFileData(); - QByteArray buf = device()->readAll(); - const quint32 dataSize = quint32(buf.size()); - if (dataSize < headerSize || !canRead(QByteArray(), buf)) { - qCDebug(lcQtGuiTextureIO, "Invalid KTX file %s", logName().constData()); + const QByteArray buf = device()->readAll(); + if (static_cast<size_t>(buf.size()) > std::numeric_limits<quint32>::max()) { + qWarning(lcQtGuiTextureIO, "Too big KTX file %s", logName().constData()); return QTextureFileData(); } - const KTXHeader *header = reinterpret_cast<const KTXHeader *>(buf.constData()); - if (!checkHeader(*header)) { - qCDebug(lcQtGuiTextureIO, "Unsupported KTX file format in %s", logName().constData()); + if (!canRead(QByteArray(), buf)) { + qWarning(lcQtGuiTextureIO, "Invalid KTX file %s", logName().constData()); + return QTextureFileData(); + } + + if (buf.size() < qsizetype(qktxh_headerSize)) { + qWarning(lcQtGuiTextureIO, "Invalid KTX header size in %s", logName().constData()); + return QTextureFileData(); + } + + KTXHeader header; + memcpy(&header, buf.data(), qktxh_headerSize); + if (!checkHeader(header)) { + qWarning(lcQtGuiTextureIO, "Unsupported KTX file format in %s", logName().constData()); return QTextureFileData(); } QTextureFileData texData; texData.setData(buf); - texData.setSize(QSize(decode(header->pixelWidth), decode(header->pixelHeight))); - texData.setGLFormat(decode(header->glFormat)); - texData.setGLInternalFormat(decode(header->glInternalFormat)); - texData.setGLBaseInternalFormat(decode(header->glBaseInternalFormat)); + texData.setSize(QSize(decode(header.pixelWidth), decode(header.pixelHeight))); + texData.setGLFormat(decode(header.glFormat)); + texData.setGLInternalFormat(decode(header.glInternalFormat)); + texData.setGLBaseInternalFormat(decode(header.glBaseInternalFormat)); + + texData.setNumLevels(decode(header.numberOfMipmapLevels)); + texData.setNumFaces(decode(header.numberOfFaces)); - texData.setNumLevels(decode(header->numberOfMipmapLevels)); - texData.setNumFaces(decode(header->numberOfFaces)); + const quint32 bytesOfKeyValueData = decode(header.bytesOfKeyValueData); + quint32 headerKeyValueSize; + if (qAddOverflow(qktxh_headerSize, bytesOfKeyValueData, &headerKeyValueSize)) { + qWarning(lcQtGuiTextureIO, "Overflow in size of key value data in header of KTX file %s", + logName().constData()); + return QTextureFileData(); + } + + if (headerKeyValueSize >= quint32(buf.size())) { + qWarning(lcQtGuiTextureIO, "OOB request in KTX file %s", logName().constData()); + return QTextureFileData(); + } + + // File contains key/values + if (bytesOfKeyValueData > 0) { + auto keyValueDataView = safeView(buf, qktxh_headerSize, bytesOfKeyValueData); + if (keyValueDataView.isEmpty()) { + qWarning(lcQtGuiTextureIO, "Invalid view in KTX file %s", logName().constData()); + return QTextureFileData(); + } - const quint32 bytesOfKeyValueData = decode(header->bytesOfKeyValueData); - if (headerSize + bytesOfKeyValueData < quint64(buf.length())) // oob check - texData.setKeyValueMetadata( - decodeKeyValues(QByteArrayView(buf.data() + headerSize, bytesOfKeyValueData))); - quint32 offset = headerSize + bytesOfKeyValueData; + auto keyValues = decodeKeyValues(keyValueDataView); + if (!keyValues) { + qWarning(lcQtGuiTextureIO, "Could not parse key values in KTX file %s", + logName().constData()); + return QTextureFileData(); + } + + texData.setKeyValueMetadata(*keyValues); + } + + // Technically, any number of levels is allowed but if the value is bigger than + // what is possible in KTX V2 (and what makes sense) we return an error. + // maxLevels = log2(max(width, height, depth)) + const int maxLevels = (sizeof(quint32) * 8) + - qCountLeadingZeroBits(std::max( + { header.pixelWidth, header.pixelHeight, header.pixelDepth })); + + if (texData.numLevels() > maxLevels) { + qWarning(lcQtGuiTextureIO, "Too many levels in KTX file %s", logName().constData()); + return QTextureFileData(); + } - constexpr int MAX_ITERATIONS = 32; // cap iterations in case of corrupt data + if (texData.numFaces() != 1 && texData.numFaces() != 6) { + qWarning(lcQtGuiTextureIO, "Invalid number of faces in KTX file %s", logName().constData()); + return QTextureFileData(); + } - for (int level = 0; level < qMin(texData.numLevels(), MAX_ITERATIONS); level++) { - if (offset + sizeof(quint32) > dataSize) // Corrupt file; avoid oob read - break; + quint32 offset = headerKeyValueSize; + for (int level = 0; level < texData.numLevels(); level++) { + const auto imageSizeView = safeView(buf, offset, sizeof(quint32)); + if (imageSizeView.isEmpty()) { + qWarning(lcQtGuiTextureIO, "OOB request in KTX file %s", logName().constData()); + return QTextureFileData(); + } - const quint32 imageSize = decode(qFromUnaligned<quint32>(buf.constData() + offset)); - offset += sizeof(quint32); + const quint32 imageSize = decode(qFromUnaligned<quint32>(imageSizeView.data())); + offset += sizeof(quint32); // overflow checked indirectly above - for (int face = 0; face < qMin(texData.numFaces(), MAX_ITERATIONS); face++) { + for (int face = 0; face < texData.numFaces(); face++) { texData.setDataOffset(offset, level, face); texData.setDataLength(imageSize, level, face); // Add image data and padding to offset - offset += withPadding(imageSize, 4); + const auto padded = nearestMultipleOf4(imageSize); + if (!padded) { + qWarning(lcQtGuiTextureIO, "Overflow in KTX file %s", logName().constData()); + return QTextureFileData(); + } + + quint32 offsetNext; + if (qAddOverflow(offset, *padded, &offsetNext)) { + qWarning(lcQtGuiTextureIO, "OOB request in KTX file %s", logName().constData()); + return QTextureFileData(); + } + + offset = offsetNext; } } if (!texData.isValid()) { - qCDebug(lcQtGuiTextureIO, "Invalid values in header of KTX file %s", logName().constData()); + qWarning(lcQtGuiTextureIO, "Invalid values in header of KTX file %s", + logName().constData()); return QTextureFileData(); } @@ -218,33 +266,83 @@ bool QKtxHandler::checkHeader(const KTXHeader &header) return is2D && (isCubeMap || isCompressedImage); } -QMap<QByteArray, QByteArray> QKtxHandler::decodeKeyValues(QByteArrayView view) const +std::optional<QMap<QByteArray, QByteArray>> QKtxHandler::decodeKeyValues(QByteArrayView view) const { QMap<QByteArray, QByteArray> output; quint32 offset = 0; - while (offset < view.size() + sizeof(quint32)) { + while (offset < quint32(view.size())) { + const auto keyAndValueByteSizeView = safeView(view, offset, sizeof(quint32)); + if (keyAndValueByteSizeView.isEmpty()) { + qWarning(lcQtGuiTextureIO, "Invalid view in KTX key-value"); + return std::nullopt; + } + const quint32 keyAndValueByteSize = - decode(qFromUnaligned<quint32>(view.constData() + offset)); - offset += sizeof(quint32); + decode(qFromUnaligned<quint32>(keyAndValueByteSizeView.data())); - if (offset + keyAndValueByteSize > quint64(view.size())) - break; // oob read + quint32 offsetKeyAndValueStart; + if (qAddOverflow(offset, quint32(sizeof(quint32)), &offsetKeyAndValueStart)) { + qWarning(lcQtGuiTextureIO, "Overflow in KTX key-value"); + return std::nullopt; + } + + quint32 offsetKeyAndValueEnd; + if (qAddOverflow(offsetKeyAndValueStart, keyAndValueByteSize, &offsetKeyAndValueEnd)) { + qWarning(lcQtGuiTextureIO, "Overflow in KTX key-value"); + return std::nullopt; + } + + const auto keyValueView = safeView(view, offsetKeyAndValueStart, keyAndValueByteSize); + if (keyValueView.isEmpty()) { + qWarning(lcQtGuiTextureIO, "Invalid view in KTX key-value"); + return std::nullopt; + } // 'key' is a UTF-8 string ending with a null terminator, 'value' is the rest. // To separate the key and value we convert the complete data to utf-8 and find the first // null terminator from the left, here we split the data into two. - const auto str = QString::fromUtf8(view.constData() + offset, keyAndValueByteSize); - const int idx = str.indexOf(QLatin1Char('\0')); - if (idx == -1) - continue; - - const QByteArray key = str.left(idx).toUtf8(); - const size_t keySize = key.size() + 1; // Actual data size - const QByteArray value = QByteArray::fromRawData(view.constData() + offset + keySize, - keyAndValueByteSize - keySize); - - offset = withPadding(offset + keyAndValueByteSize, 4); - output.insert(key, value); + + const int idx = keyValueView.indexOf('\0'); + if (idx == -1) { + qWarning(lcQtGuiTextureIO, "Invalid key in KTX key-value"); + return std::nullopt; + } + + const QByteArrayView keyView = safeView(view, offsetKeyAndValueStart, idx); + if (keyView.isEmpty()) { + qWarning(lcQtGuiTextureIO, "Overflow in KTX key-value"); + return std::nullopt; + } + + const quint32 keySize = idx + 1; // Actual data size + + quint32 offsetValueStart; + if (qAddOverflow(offsetKeyAndValueStart, keySize, &offsetValueStart)) { + qWarning(lcQtGuiTextureIO, "Overflow in KTX key-value"); + return std::nullopt; + } + + quint32 valueSize; + if (qSubOverflow(keyAndValueByteSize, keySize, &valueSize)) { + qWarning(lcQtGuiTextureIO, "Underflow in KTX key-value"); + return std::nullopt; + } + + const QByteArrayView valueView = safeView(view, offsetValueStart, valueSize); + if (valueView.isEmpty()) { + qWarning(lcQtGuiTextureIO, "Invalid view in KTX key-value"); + return std::nullopt; + } + + output.insert(keyView.toByteArray(), valueView.toByteArray()); + + const auto offsetNext = nearestMultipleOf4(offsetKeyAndValueEnd); + if (!offsetNext) { + qWarning(lcQtGuiTextureIO, "Overflow in KTX key-value"); + return std::nullopt; + } + + offset = *offsetNext; } return output; diff --git a/src/gui/util/qktxhandler_p.h b/src/gui/util/qktxhandler_p.h index 4298433f36..3a0b8fcf7e 100644 --- a/src/gui/util/qktxhandler_p.h +++ b/src/gui/util/qktxhandler_p.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/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 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QKTXHANDLER_H #define QKTXHANDLER_H @@ -53,6 +17,8 @@ #include "qtexturefilehandler_p.h" +#include <optional> + QT_BEGIN_NAMESPACE struct KTXHeader; @@ -61,6 +27,7 @@ class QKtxHandler : public QTextureFileHandler { public: using QTextureFileHandler::QTextureFileHandler; + ~QKtxHandler() override; static bool canRead(const QByteArray &suffix, const QByteArray &block); @@ -68,7 +35,7 @@ public: private: bool checkHeader(const KTXHeader &header); - QMap<QByteArray, QByteArray> decodeKeyValues(QByteArrayView view) const; + std::optional<QMap<QByteArray, QByteArray>> decodeKeyValues(QByteArrayView view) const; quint32 decode(quint32 val) const; bool inverseEndian = false; diff --git a/src/gui/util/qlayoutpolicy.cpp b/src/gui/util/qlayoutpolicy.cpp index 507df44a45..2e3a0b32cb 100644 --- a/src/gui/util/qlayoutpolicy.cpp +++ b/src/gui/util/qlayoutpolicy.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/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 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qlayoutpolicy_p.h" #include <QtCore/qdebug.h> @@ -133,3 +97,5 @@ QDebug operator<<(QDebug dbg, const QLayoutPolicy &p) #endif QT_END_NAMESPACE + +#include "moc_qlayoutpolicy_p.cpp" diff --git a/src/gui/util/qlayoutpolicy_p.h b/src/gui/util/qlayoutpolicy_p.h index 40a1dfa867..bbdabd0c7b 100644 --- a/src/gui/util/qlayoutpolicy_p.h +++ b/src/gui/util/qlayoutpolicy_p.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/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 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QLAYOUTPOLICY_H #define QLAYOUTPOLICY_H diff --git a/src/gui/util/qpkmhandler.cpp b/src/gui/util/qpkmhandler.cpp index 0ad0a54a79..d84ce2ce7f 100644 --- a/src/gui/util/qpkmhandler.cpp +++ b/src/gui/util/qpkmhandler.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/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 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qpkmhandler_p.h" #include "qtexturefiledata_p.h" @@ -49,7 +13,7 @@ QT_BEGIN_NAMESPACE -static const int headerSize = 16; +static const int qpkmh_headerSize = 16; struct PkmType { @@ -57,7 +21,7 @@ struct PkmType quint32 bytesPerBlock; }; -static PkmType typeMap[5] = { +static constexpr PkmType typeMap[5] = { { 0x8D64, 8 }, // GL_ETC1_RGB8_OES { 0x9274, 8 }, // GL_COMPRESSED_RGB8_ETC2 { 0, 0 }, // unused (obsolete) @@ -65,6 +29,8 @@ static PkmType typeMap[5] = { { 0x9276, 8 } // GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 }; +QPkmHandler::~QPkmHandler() = default; + bool QPkmHandler::canRead(const QByteArray &suffix, const QByteArray &block) { Q_UNUSED(suffix); @@ -80,7 +46,7 @@ QTextureFileData QPkmHandler::read() return texData; QByteArray fileData = device()->readAll(); - if (fileData.size() < headerSize || !canRead(QByteArray(), fileData)) { + if (fileData.size() < qpkmh_headerSize || !canRead(QByteArray(), fileData)) { qCDebug(lcQtGuiTextureIO, "Invalid PKM file %s", logName().constData()); return QTextureFileData(); } @@ -109,7 +75,7 @@ QTextureFileData QPkmHandler::read() QSize texSize(qFromBigEndian<quint16>(rawData + 12), qFromBigEndian<quint16>(rawData + 14)); texData.setSize(texSize); - texData.setDataOffset(headerSize); + texData.setDataOffset(qpkmh_headerSize); if (!texData.isValid()) { qCDebug(lcQtGuiTextureIO, "Invalid values in header of PKM file %s", logName().constData()); diff --git a/src/gui/util/qpkmhandler_p.h b/src/gui/util/qpkmhandler_p.h index 2f7618bc53..a773b44fb2 100644 --- a/src/gui/util/qpkmhandler_p.h +++ b/src/gui/util/qpkmhandler_p.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/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 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QPKMHANDLER_H #define QPKMHANDLER_H @@ -59,6 +23,7 @@ class QPkmHandler : public QTextureFileHandler { public: using QTextureFileHandler::QTextureFileHandler; + ~QPkmHandler() override; static bool canRead(const QByteArray &suffix, const QByteArray &block); diff --git a/src/gui/util/qtexturefiledata.cpp b/src/gui/util/qtexturefiledata.cpp index 6549206a26..e1fa900b84 100644 --- a/src/gui/util/qtexturefiledata.cpp +++ b/src/gui/util/qtexturefiledata.cpp @@ -1,44 +1,11 @@ -/**************************************************************************** -** -** Copyright (C) 2018 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/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 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +#include "QtGui/qimage.h" #include "qtexturefiledata_p.h" -#include <QSize> +#include <QtCore/qsize.h> +#include <QtCore/qvarlengtharray.h> +#include <QtCore/qmap.h> QT_BEGIN_NAMESPACE @@ -55,14 +22,17 @@ public: QTextureFileDataPrivate(const QTextureFileDataPrivate &other) : QSharedData(other), + mode(other.mode), logName(other.logName), data(other.data), offsets(other.offsets), lengths(other.lengths), + images(other.images), size(other.size), format(other.format), numFaces(other.numFaces), - numLevels(other.numLevels) + numLevels(other.numLevels), + keyValues(other.keyValues) { } @@ -74,13 +44,18 @@ public: { numLevels = force ? levels : qMax(numLevels, levels); numFaces = force ? faces : qMax(numFaces, faces); - - offsets.resize(numFaces); - lengths.resize(numFaces); - - for (auto faceList : { &offsets, &lengths }) - for (auto &levelList : *faceList) + if (mode == QTextureFileData::ByteArrayMode) { + offsets.resize(numFaces); + lengths.resize(numFaces); + + for (auto faceList : { &offsets, &lengths }) + for (auto &levelList : *faceList) + levelList.resize(numLevels); + } else { + images.resize(numFaces); + for (auto &levelList : images) levelList.resize(numLevels); + } } bool isValid(int level, int face) const { return level < numLevels && face < numFaces; } @@ -90,10 +65,12 @@ public: int getLength(int level, int face) const { return lengths[face][level]; } void setLength(int value, int level, int face) { lengths[face][level] = value; } + QTextureFileData::Mode mode = QTextureFileData::ByteArrayMode; QByteArray logName; QByteArray data; QVarLengthArray<QList<int>, MAX_FACES> offsets; // [Face][Level] = offset QVarLengthArray<QList<int>, MAX_FACES> lengths; // [Face][Level] = length + QVarLengthArray<QList<QImage>, MAX_FACES> images; // [Face][Level] = length QSize size; quint32 format = 0; quint32 internalFormat = 0; @@ -103,8 +80,10 @@ public: QMap<QByteArray, QByteArray> keyValues; }; -QTextureFileData::QTextureFileData() +QTextureFileData::QTextureFileData(Mode mode) { + d = new QTextureFileDataPrivate; + d->mode = mode; } QTextureFileData::QTextureFileData(const QTextureFileData &other) @@ -132,11 +111,14 @@ bool QTextureFileData::isValid() const if (!d) return false; + if (d->mode == ImageMode) + return true; // Manually populated: the caller needs to do verification at that time. + if (d->data.isEmpty() || d->size.isEmpty() || (!d->format && !d->internalFormat)) return false; - const int numFacesOffset = d->offsets.length(); - const int numFacesLength = d->lengths.length(); + const int numFacesOffset = d->offsets.size(); + const int numFacesLength = d->lengths.size(); if (numFacesOffset == 0 || numFacesLength == 0 || d->numFaces != numFacesOffset || d->numFaces != numFacesLength) return false; @@ -173,19 +155,26 @@ QByteArray QTextureFileData::data() const void QTextureFileData::setData(const QByteArray &data) { - if (!d.constData()) //### uh think about this design, this is the only way to create; should be constructor instead at least - d = new QTextureFileDataPrivate; - + Q_ASSERT(d->mode == ByteArrayMode); d->data = data; } +void QTextureFileData::setData(const QImage &image, int level, int face) +{ + Q_ASSERT(d->mode == ImageMode); + d->ensureSize(level + 1, face + 1); + d->images[face][level] = image; +} + int QTextureFileData::dataOffset(int level, int face) const { + Q_ASSERT(d->mode == ByteArrayMode); return (d && d->isValid(level, face)) ? d->getOffset(level, face) : 0; } void QTextureFileData::setDataOffset(int offset, int level, int face) { + Q_ASSERT(d->mode == ByteArrayMode); if (d.constData() && level >= 0) { d->ensureSize(level + 1, face + 1); d->setOffset(offset, level, face); @@ -194,22 +183,31 @@ void QTextureFileData::setDataOffset(int offset, int level, int face) int QTextureFileData::dataLength(int level, int face) const { + Q_ASSERT(d->mode == ByteArrayMode); return (d && d->isValid(level, face)) ? d->getLength(level, face) : 0; } QByteArrayView QTextureFileData::getDataView(int level, int face) const { - const int dataLength = this->dataLength(level, face); - const int dataOffset = this->dataOffset(level, face); + if (d->mode == ByteArrayMode) { + const int dataLength = this->dataLength(level, face); + const int dataOffset = this->dataOffset(level, face); - if (d == nullptr || dataLength == 0) - return QByteArrayView(); + if (d == nullptr || dataLength == 0) + return QByteArrayView(); - return QByteArrayView(d->data.constData() + dataOffset, dataLength); + return QByteArrayView(d->data.constData() + dataOffset, dataLength); + } else { + if (!d->isValid(level, face)) + return QByteArrayView(); + const QImage &img = d->images[face][level]; + return img.isNull() ? QByteArrayView() : QByteArrayView(img.constBits(), img.sizeInBytes()); + } } void QTextureFileData::setDataLength(int length, int level, int face) { + Q_ASSERT(d->mode == ByteArrayMode); if (d.constData() && level >= 0) { d->ensureSize(level + 1, face + 1); d->setLength(length, level, face); @@ -320,9 +318,11 @@ QDebug operator<<(QDebug dbg, const QTextureFileData &d) dbg << "glInternalFormat:" << glFormatName(d.glInternalFormat()); dbg << "glBaseInternalFormat:" << glFormatName(d.glBaseInternalFormat()); dbg.nospace() << "Levels: " << d.numLevels(); + dbg.nospace() << "Faces: " << d.numFaces(); if (!d.isValid()) dbg << " {Invalid}"; dbg << ")"; + dbg << (d.d->mode ? "[bytearray-based]" : "[image-based]"); } else { dbg << "null)"; } diff --git a/src/gui/util/qtexturefiledata_p.h b/src/gui/util/qtexturefiledata_p.h index e553733d69..cd0dbe171c 100644 --- a/src/gui/util/qtexturefiledata_p.h +++ b/src/gui/util/qtexturefiledata_p.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2018 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/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 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QTEXTUREFILEDATA_P_H #define QTEXTUREFILEDATA_P_H @@ -55,6 +19,7 @@ #include <QSharedDataPointer> #include <QLoggingCategory> #include <QDebug> +#include <private/qglobal_p.h> QT_BEGIN_NAMESPACE @@ -65,7 +30,9 @@ class QTextureFileDataPrivate; class Q_GUI_EXPORT QTextureFileData { public: - QTextureFileData(); + enum Mode { ByteArrayMode, ImageMode }; + + QTextureFileData(Mode mode = ByteArrayMode); QTextureFileData(const QTextureFileData &other); QTextureFileData &operator=(const QTextureFileData &other); ~QTextureFileData(); @@ -77,6 +44,7 @@ public: QByteArray data() const; void setData(const QByteArray &data); + void setData(const QImage &image, int level = 0, int face = 0); int dataOffset(int level = 0, int face = 0) const; void setDataOffset(int offset, int level = 0, int face = 0); @@ -112,6 +80,7 @@ public: private: QSharedDataPointer<QTextureFileDataPrivate> d; + friend Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QTextureFileData &d); }; Q_DECLARE_TYPEINFO(QTextureFileData, Q_RELOCATABLE_TYPE); diff --git a/src/gui/util/qtexturefilehandler_p.h b/src/gui/util/qtexturefilehandler_p.h index 3d4f42526f..9fb3130f0b 100644 --- a/src/gui/util/qtexturefilehandler_p.h +++ b/src/gui/util/qtexturefilehandler_p.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/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 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QTEXTUREFILEHANDLER_P_H #define QTEXTUREFILEHANDLER_P_H @@ -63,7 +27,7 @@ public: { m_logName = !logName.isEmpty() ? logName : QByteArrayLiteral("(unknown)"); } - virtual ~QTextureFileHandler() {} + virtual ~QTextureFileHandler(); virtual QTextureFileData read() = 0; QIODevice *device() const { return m_device; } diff --git a/src/gui/util/qtexturefilereader.cpp b/src/gui/util/qtexturefilereader.cpp index fefb957323..596c30d2f7 100644 --- a/src/gui/util/qtexturefilereader.cpp +++ b/src/gui/util/qtexturefilereader.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2018 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/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 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qtexturefilereader_p.h" @@ -47,6 +11,8 @@ QT_BEGIN_NAMESPACE +QTextureFileHandler::~QTextureFileHandler() = default; + QTextureFileReader::QTextureFileReader(QIODevice *device, const QString &fileName) : m_device(device), m_fileName(fileName) { diff --git a/src/gui/util/qtexturefilereader_p.h b/src/gui/util/qtexturefilereader_p.h index 2ec0b0cc49..5f7b31ee32 100644 --- a/src/gui/util/qtexturefilereader_p.h +++ b/src/gui/util/qtexturefilereader_p.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2018 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/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 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QTEXTUREFILEREADER_H #define QTEXTUREFILEREADER_H diff --git a/src/gui/util/qundogroup.cpp b/src/gui/util/qundogroup.cpp index 6efebce94d..db5d009ca6 100644 --- a/src/gui/util/qundogroup.cpp +++ b/src/gui/util/qundogroup.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2020 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtWidgets module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/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 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2020 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qundogroup.h" #include "qundostack.h" diff --git a/src/gui/util/qundogroup.h b/src/gui/util/qundogroup.h index ef5b053610..e92f4f46b0 100644 --- a/src/gui/util/qundogroup.h +++ b/src/gui/util/qundogroup.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2020 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtWidgets module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/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 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2020 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QUNDOGROUP_H #define QUNDOGROUP_H diff --git a/src/gui/util/qundostack.cpp b/src/gui/util/qundostack.cpp index f5757c1704..403833d421 100644 --- a/src/gui/util/qundostack.cpp +++ b/src/gui/util/qundostack.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2020 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtWidgets module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/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 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2020 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include <QtCore/qdebug.h> #include "qundostack.h" @@ -302,7 +266,7 @@ QString QUndoCommand::actionText() const void QUndoCommand::setText(const QString &text) { - int cdpos = text.indexOf(QLatin1Char('\n')); + int cdpos = text.indexOf(u'\n'); if (cdpos > 0) { d->text = text.left(cdpos); d->actionText = text.mid(cdpos + 1); @@ -322,7 +286,7 @@ void QUndoCommand::setText(const QString &text) int QUndoCommand::childCount() const { - return d->child_list.count(); + return d->child_list.size(); } /*! @@ -335,7 +299,7 @@ int QUndoCommand::childCount() const const QUndoCommand *QUndoCommand::child(int index) const { - if (index < 0 || index >= d->child_list.count()) + if (index < 0 || index >= d->child_list.size()) return nullptr; return d->child_list.at(index); } @@ -480,10 +444,10 @@ void QUndoStackPrivate::setIndex(int idx, bool clean) bool QUndoStackPrivate::checkUndoLimit() { - if (undo_limit <= 0 || !macro_stack.isEmpty() || undo_limit >= command_list.count()) + if (undo_limit <= 0 || !macro_stack.isEmpty() || undo_limit >= command_list.size()) return false; - int del_count = command_list.count() - undo_limit; + int del_count = command_list.size() - undo_limit; for (int i = 0; i < del_count; ++i) delete command_list.takeFirst(); @@ -1044,7 +1008,7 @@ void QUndoStackPrivate::setPrefixedText(QAction *action, const QString &prefix, if (defaultText.isEmpty()) { QString s = prefix; if (!prefix.isEmpty() && !text.isEmpty()) - s.append(QLatin1Char(' ')); + s.append(u' '); s.append(text); action->setText(s); } else { @@ -1178,7 +1142,7 @@ void QUndoStack::beginMacro(const QString &text) } d->macro_stack.append(cmd); - if (d->macro_stack.count() == 1) { + if (d->macro_stack.size() == 1) { emit canUndoChanged(false); emit undoTextChanged(QString()); emit canRedoChanged(false); @@ -1227,7 +1191,7 @@ const QUndoCommand *QUndoStack::command(int index) const { Q_D(const QUndoStack); - if (index < 0 || index >= d->command_list.count()) + if (index < 0 || index >= d->command_list.size()) return nullptr; return d->command_list.at(index); } diff --git a/src/gui/util/qundostack.h b/src/gui/util/qundostack.h index c137e7d942..7b18485509 100644 --- a/src/gui/util/qundostack.h +++ b/src/gui/util/qundostack.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2020 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtWidgets module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/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 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2020 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QUNDOSTACK_H #define QUNDOSTACK_H diff --git a/src/gui/util/qundostack_p.h b/src/gui/util/qundostack_p.h index 5f2c438a83..d655d5fdf5 100644 --- a/src/gui/util/qundostack_p.h +++ b/src/gui/util/qundostack_p.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2020 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/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 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2020 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QUNDOSTACK_P_H #define QUNDOSTACK_P_H diff --git a/src/gui/util/qvalidator.cpp b/src/gui/util/qvalidator.cpp index 14d9c01503..2a81006657 100644 --- a/src/gui/util/qvalidator.cpp +++ b/src/gui/util/qvalidator.cpp @@ -1,42 +1,6 @@ -/**************************************************************************** -** -** Copyright (C) 2021 The Qt Company Ltd. -** Copyright (C) 2012 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/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 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2021 The Qt Company Ltd. +// Copyright (C) 2012 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include <qdebug.h> @@ -367,12 +331,12 @@ QIntValidator::~QIntValidator() or is a prefix of an integer in the valid range, returns \l Intermediate. Otherwise, returns \l Invalid. - If the valid range consists of just positive integers (e.g., 32 to 100) - and \a input is a negative integer, then Invalid is returned. (On the other - hand, if the range consists of negative integers (e.g., -100 to -32) and - \a input is a positive integer, then Intermediate is returned, because - the user might be just about to type the minus (especially for right-to-left - languages). + If the valid range consists of just positive integers (e.g., 32 to 100) and + \a input is a negative integer, then Invalid is returned. (On the other + hand, if the range consists of negative integers (e.g., -100 to -32) and \a + input is a positive integer without leading plus sign, then Intermediate is + returned, because the user might be just about to type the minus (especially + for right-to-left languages). Similarly, if the valid range is between 46 and 53, then 41 and 59 will be evaluated as \l Intermediate, as otherwise the user wouldn't be able to @@ -398,34 +362,45 @@ static qlonglong pow10(int exp) return result; } -QValidator::State QIntValidator::validate(QString & input, int&) const +template <typename T> static inline +std::optional<QValidator::State> initialResultCheck(T min, T max, const ParsingResult &result) { - QByteArray buff; - if (!locale().d->m_data->validateChars(input, QLocaleData::IntegerMode, &buff, -1, - locale().numberOptions())) { - return Invalid; - } + if (result.state == ParsingResult::Invalid) + return QValidator::Invalid; + const CharBuff &buff = result.buff; if (buff.isEmpty()) - return Intermediate; + return QValidator::Intermediate; - const bool startsWithMinus(buff[0] == '-'); - if (b >= 0 && startsWithMinus) - return Invalid; + char ch = buff[0]; + const bool signConflicts = (min >= 0 && ch == '-') || (max < 0 && ch == '+'); + if (signConflicts) + return QValidator::Invalid; - const bool startsWithPlus(buff[0] == '+'); - if (t < 0 && startsWithPlus) - return Invalid; + if (result.state == ParsingResult::Intermediate) + return QValidator::Intermediate; - if (buff.size() == 1 && (startsWithPlus || startsWithMinus)) - return Intermediate; + return std::nullopt; +} - bool ok; - qlonglong entered = QLocaleData::bytearrayToLongLong(buff, 10, &ok); - if (!ok) +QValidator::State QIntValidator::validate(QString & input, int&) const +{ + ParsingResult result = + locale().d->m_data->validateChars(input, QLocaleData::IntegerMode, -1, + locale().numberOptions()); + + std::optional<State> opt = initialResultCheck(b, t, result); + if (opt) + return *opt; + + const CharBuff &buff = result.buff; + QSimpleParsedNumber r = QLocaleData::bytearrayToLongLong(buff, 10); + if (!r.ok()) return Invalid; + qint64 entered = r.result; if (entered >= b && entered <= t) { + bool ok = false; locale().toInt(input, &ok); return ok ? Acceptable : Intermediate; } @@ -437,7 +412,7 @@ QValidator::State QIntValidator::validate(QString & input, int&) const // of a number of digits equal to or less than the max value as intermediate. int buffLength = buff.size(); - if (startsWithPlus) + if (buff[0] == '+') buffLength--; const int tLength = t != 0 ? static_cast<int>(std::log10(qAbs(t))) + 1 : 1; @@ -450,15 +425,15 @@ QValidator::State QIntValidator::validate(QString & input, int&) const /*! \reimp */ void QIntValidator::fixup(QString &input) const { - QByteArray buff; - if (!locale().d->m_data->validateChars(input, QLocaleData::IntegerMode, &buff, -1, - locale().numberOptions())) { + auto [parseState, buff] = + locale().d->m_data->validateChars(input, QLocaleData::IntegerMode, -1, + locale().numberOptions()); + if (parseState == ParsingResult::Invalid) return; - } - bool ok; - qlonglong entered = QLocaleData::bytearrayToLongLong(buff, 10, &ok); - if (ok) - input = locale().toString(entered); + + QSimpleParsedNumber r = QLocaleData::bytearrayToLongLong(buff, 10); + if (r.ok()) + input = locale().toString(r.result); } /*! @@ -491,7 +466,7 @@ void QIntValidator::setRange(int bottom, int top) \brief the validator's lowest acceptable value By default, this property's value is derived from the lowest signed - integer available (typically -2147483647). + integer available (-2147483648). \sa setRange() */ @@ -505,7 +480,7 @@ void QIntValidator::setBottom(int bottom) \brief the validator's highest acceptable value By default, this property's value is derived from the highest signed - integer available (typically 2147483647). + integer available (2147483647). \sa setRange() */ @@ -567,10 +542,11 @@ public: in the German locale, "1,234" will be accepted as the fractional number 1.234. In Arabic locales, QDoubleValidator will accept Arabic digits. - \note The QLocale::NumberOptions set on the locale() also affect the - way the number is interpreted. For example, since QLocale::RejectGroupSeparator - is not set by default, the validator will accept group separators. It is thus - recommended to use QLocale::toDouble() to obtain the numeric value. + \note The QLocale::NumberOptions set on the locale() also affect the way the + number is interpreted. For example, since QLocale::RejectGroupSeparator is + not set by default (except on the \c "C" locale), the validator will accept + group separators. If the string passes validation, pass it to + locale().toDouble() to obtain its numeric value. \sa QIntValidator, QRegularExpressionValidator, QLocale::toDouble(), {Line Edits Example} */ @@ -580,10 +556,23 @@ public: \since 4.3 This enum defines the allowed notations for entering a double. - \value StandardNotation The string is written as a standard number - (i.e. 0.015). - \value ScientificNotation The string is written in scientific - form. It may have an exponent part(i.e. 1.5E-2). + \value StandardNotation The string is written in the standard format, a + whole number part optionally followed by a separator + and fractional part, for example \c{"0.015"}. + + \value ScientificNotation The string is written in scientific form, which + optionally appends an exponent part to the + standard format, for example \c{"1.5E-2"}. + + The whole number part may, as usual, include a sign. This, along with the + separators for fractional part, exponent and any digit-grouping, depend on + locale. QDoubleValidator doesn't check the placement (which would also + depend on locale) of any digit-grouping separators it finds, but it will + reject input that contains them if \l QLocale::RejectGroupSeparator is set + in \c locale().numberOptions(). + + \sa QLocale::numberOptions(), QLocale::decimalPoint(), + QLocale::exponential(), QLocale::negativeSign() */ /*! @@ -625,14 +614,14 @@ QDoubleValidator::~QDoubleValidator() /*! \fn QValidator::State QDoubleValidator::validate(QString &input, int &pos) const - Returns \l Acceptable if the string \a input contains a double - that is within the valid range and is in the correct format. + Returns \l Acceptable if the string \a input is in the correct format and + contains a double within the valid range. - Returns \l Intermediate if \a input contains a double that is - outside the range or is in the wrong format; e.g. is empty. + Returns \l Intermediate if \a input is in the wrong format or contains a + double outside the range. - Returns \l Invalid if the \a input is not a double or with too many - digits after the decimal point. + Returns \l Invalid if the \a input doesn't represent a double or has too + many digits after the decimal point. Note: If the valid range consists of just positive doubles (e.g. 0.0 to 100.0) and \a input is a negative double then \l Invalid is returned. If notation() @@ -668,19 +657,12 @@ QValidator::State QDoubleValidator::validate(QString & input, int &) const QValidator::State QDoubleValidatorPrivate::validateWithLocale(QString &input, QLocaleData::NumberMode numMode, const QLocale &locale) const { Q_Q(const QDoubleValidator); - QByteArray buff; - if (!locale.d->m_data->validateChars(input, numMode, &buff, q->dec, locale.numberOptions())) { - return QValidator::Invalid; - } + ParsingResult result = + locale.d->m_data->validateChars(input, numMode, q->dec, locale.numberOptions()); - if (buff.isEmpty()) - return QValidator::Intermediate; - - if (q->b >= 0 && buff.startsWith('-')) - return QValidator::Invalid; - - if (q->t < 0 && buff.startsWith('+')) - return QValidator::Invalid; + std::optional<QValidator::State> opt = initialResultCheck(q->b, q->t, result); + if (opt) + return *opt; bool ok = false; double i = locale.toDouble(input, &ok); // returns 0.0 if !ok @@ -694,7 +676,11 @@ QValidator::State QDoubleValidatorPrivate::validateWithLocale(QString &input, QL if (notation == QDoubleValidator::StandardNotation) { double max = qMax(qAbs(q->b), qAbs(q->t)); qlonglong v; - if (convertDoubleTo(max, &v)) { + // Need a whole number to pass to convertDoubleTo() or it fails. Use + // floor, as max is positive so this has the same number of digits + // before the decimal point, where qCeil() might take us up to a power + // of ten, adding a digit. + if (convertDoubleTo(qFloor(max), &v)) { qlonglong n = pow10(numDigits(v)); // In order to get the highest possible number in the intermediate // range we need to get 10 to the power of the number of digits @@ -755,15 +741,16 @@ void QDoubleValidatorPrivate::fixupWithLocale(QString &input, QLocaleData::Numbe const QLocale &locale) const { Q_Q(const QDoubleValidator); - QByteArray buff; // Passing -1 as the number of decimals, because fixup() exists to improve // an Intermediate value, if it can. - if (!locale.d->m_data->validateChars(input, numMode, &buff, -1, locale.numberOptions())) + auto [parseState, buff] = + locale.d->m_data->validateChars(input, numMode, -1, locale.numberOptions()); + if (parseState == ParsingResult::Invalid) return; - // buff now contains data in C locale. + // buff contains data in C locale. bool ok = false; - const double entered = buff.toDouble(&ok); + const double entered = QByteArrayView(buff).toDouble(&ok); if (ok) { // Here we need to adjust the output format accordingly char mode; @@ -787,7 +774,7 @@ void QDoubleValidatorPrivate::fixupWithLocale(QString &input, QLocaleData::Numbe if (eIndex < 0) eIndex = buff.size(); precision = eIndex - (buff.contains('.') ? 1 : 0) - - (buff.startsWith('-') || buff.startsWith('+') ? 1 : 0); + - (buff[0] == '-' || buff[0] == '+' ? 1 : 0); } // Use q->dec to limit the number of decimals, because we want the // fixup() result to pass validate(). @@ -915,6 +902,7 @@ QDoubleValidator::Notation QDoubleValidator::notation() const /*! \class QRegularExpressionValidator + \inmodule QtGui \brief The QRegularExpressionValidator class is used to check a string against a regular expression. @@ -1066,4 +1054,6 @@ void QRegularExpressionValidatorPrivate::setRegularExpression(const QRegularExpr QT_END_NAMESPACE +#include "moc_qvalidator.cpp" + #endif // QT_NO_VALIDATOR diff --git a/src/gui/util/qvalidator.h b/src/gui/util/qvalidator.h index 7728857672..cd757c612d 100644 --- a/src/gui/util/qvalidator.h +++ b/src/gui/util/qvalidator.h @@ -1,42 +1,6 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2012 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/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 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// Copyright (C) 2012 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QVALIDATOR_H #define QVALIDATOR_H |