diff options
Diffstat (limited to 'src/gui/util')
53 files changed, 1424 insertions, 4216 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..7ca138b1b7 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" @@ -56,9 +20,8 @@ QT_BEGIN_NAMESPACE -class QOpenUrlHandlerRegistry : public QObject +class QOpenUrlHandlerRegistry { - Q_OBJECT public: QOpenUrlHandlerRegistry() = default; @@ -71,26 +34,10 @@ public: }; typedef QHash<QString, Handler> HandlerHash; HandlerHash handlers; - -public Q_SLOTS: - void handlerDestroyed(QObject *handler); - }; Q_GLOBAL_STATIC(QOpenUrlHandlerRegistry, handlerRegistry) -void QOpenUrlHandlerRegistry::handlerDestroyed(QObject *handler) -{ - HandlerHash::Iterator it = handlers.begin(); - while (it != handlers.end()) { - if (it->receiver == handler) { - it = handlers.erase(it); - } else { - ++it; - } - } -} - /*! \class QDesktopServices \brief The QDesktopServices class provides methods for accessing common desktop services. @@ -187,6 +134,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,10 +206,16 @@ bool QDesktopServices::openUrl(const QUrl &url) Note that the handler will always be called from within the same thread that calls QDesktopServices::openUrl(). - \section1 iOS + 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. + + \target configuring qdesktopservices url handler on ios and macos + \section1 iOS and \macos - To use this function for receiving data from other apps on iOS you also need to - add the custom scheme to the \c CFBundleURLSchemes list in your Info.plist file: + To use this function for receiving data from other apps on iOS/\macos + you also need to add the custom scheme to the \c CFBundleURLSchemes + list in your Info.plist file: \snippet code/src_gui_util_qdesktopservices.cpp 4 @@ -270,7 +230,7 @@ bool QDesktopServices::openUrl(const QUrl &url) \snippet code/src_gui_util_qdesktopservices.cpp 7 - iOS will search for /.well-known/apple-app-site-association on your domain, + iOS/\macos will search for /.well-known/apple-app-site-association on your domain, when the application is installed. If you want to listen to \c{https://your.domain.com/help?topic=ABCDEF} you need to provide the following content there: @@ -280,6 +240,7 @@ bool QDesktopServices::openUrl(const QUrl &url) For more information, see the Apple Developer Documentation for \l {iOS: Supporting Associated Domains}{Supporting Associated Domains}. + \target configuring qdesktopservices url handler on android \section1 Android To use this function for receiving data from other apps on Android, you @@ -320,13 +281,15 @@ 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*))); } /*! 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 +299,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 341d159fb1..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" @@ -100,7 +65,7 @@ enum { Minimal container to store Qt::Orientation-discriminated values. The salient feature is the indexing operator, which takes - Qt::Orientation (and assumes it's passed only Qt::Horizonal or Qt::Vertical). + Qt::Orientation (and assumes it's passed only Qt::Horizontal or Qt::Vertical). */ template <typename T> class QHVContainer { @@ -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 6457aeb653..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 @@ -64,10 +28,9 @@ QT_BEGIN_NAMESPACE class QVariant; -class Q_GUI_EXPORT QLayoutPolicy +class QLayoutPolicy { - Q_GADGET - Q_ENUMS(Policy) + Q_GADGET_EXPORT(Q_GUI_EXPORT) public: enum PolicyFlag { @@ -76,16 +39,16 @@ public: ShrinkFlag = 4, IgnoreFlag = 8 }; + Q_DECLARE_FLAGS(Policy, PolicyFlag) + Q_FLAG(Policy) - enum Policy { - Fixed = 0, - Minimum = GrowFlag, - Maximum = ShrinkFlag, - Preferred = GrowFlag | ShrinkFlag, - MinimumExpanding = GrowFlag | ExpandFlag, - Expanding = GrowFlag | ShrinkFlag | ExpandFlag, - Ignored = ShrinkFlag | GrowFlag | IgnoreFlag - }; + static constexpr inline Policy Fixed = {}; + static constexpr inline Policy Minimum = GrowFlag; + static constexpr inline Policy Maximum = ShrinkFlag; + static constexpr inline Policy Preferred = Minimum | Maximum; + static constexpr inline Policy MinimumExpanding = Minimum | ExpandFlag; + static constexpr inline Policy Expanding = Preferred | ExpandFlag; + static constexpr inline Policy Ignored = Preferred | IgnoreFlag; enum ControlType { DefaultType = 0x00000001, @@ -116,11 +79,11 @@ public: } Policy horizontalPolicy() const { return static_cast<Policy>(bits.horPolicy); } Policy verticalPolicy() const { return static_cast<Policy>(bits.verPolicy); } - ControlType controlType() const; + Q_GUI_EXPORT ControlType controlType() const; void setHorizontalPolicy(Policy d) { bits.horPolicy = d; } void setVerticalPolicy(Policy d) { bits.verPolicy = d; } - void setControlType(ControlType type); + Q_GUI_EXPORT void setControlType(ControlType type); Qt::Orientations expandingDirections() const { Qt::Orientations result; @@ -144,7 +107,7 @@ public: void setHorizontalStretch(int stretchFactor) { bits.horStretch = static_cast<quint32>(qBound(0, stretchFactor, 255)); } void setVerticalStretch(int stretchFactor) { bits.verStretch = static_cast<quint32>(qBound(0, stretchFactor, 255)); } - void transpose(); + inline void transpose(); private: @@ -169,6 +132,7 @@ private: }; }; +Q_DECLARE_OPERATORS_FOR_FLAGS(QLayoutPolicy::Policy) Q_DECLARE_OPERATORS_FOR_FLAGS(QLayoutPolicy::ControlTypes) #ifndef QT_NO_DATASTREAM 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/qshaderformat.cpp b/src/gui/util/qshaderformat.cpp deleted file mode 100644 index d56dfc413e..0000000000 --- a/src/gui/util/qshaderformat.cpp +++ /dev/null @@ -1,145 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). -** 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$ -** -****************************************************************************/ - -#include "qshaderformat_p.h" - -QT_BEGIN_NAMESPACE - -QShaderFormat::QShaderFormat() noexcept - : m_api(NoApi) - , m_shaderType(Fragment) -{ -} - -QShaderFormat::Api QShaderFormat::api() const noexcept -{ - return m_api; -} - -void QShaderFormat::setApi(QShaderFormat::Api api) noexcept -{ - m_api = api; -} - -QVersionNumber QShaderFormat::version() const noexcept -{ - return m_version; -} - -void QShaderFormat::setVersion(const QVersionNumber &version) noexcept -{ - m_version = version; -} - -QStringList QShaderFormat::extensions() const noexcept -{ - return m_extensions; -} - -void QShaderFormat::setExtensions(const QStringList &extensions) noexcept -{ - m_extensions = extensions; - m_extensions.sort(); -} - -QString QShaderFormat::vendor() const noexcept -{ - return m_vendor; -} - -void QShaderFormat::setVendor(const QString &vendor) noexcept -{ - m_vendor = vendor; -} - -bool QShaderFormat::isValid() const noexcept -{ - return m_api != NoApi && m_version.majorVersion() > 0; -} - -bool QShaderFormat::supports(const QShaderFormat &other) const noexcept -{ - if (!isValid() || !other.isValid()) - return false; - - if (m_api == OpenGLES && m_api != other.m_api) - return false; - - if (m_api == OpenGLCoreProfile && m_api != other.m_api) - return false; - - if (m_version < other.m_version) - return false; - - if (m_shaderType != other.m_shaderType) - return false; - - const auto containsAllExtensionsFromOther = std::includes(m_extensions.constBegin(), - m_extensions.constEnd(), - other.m_extensions.constBegin(), - other.m_extensions.constEnd()); - if (!containsAllExtensionsFromOther) - return false; - - if (!other.m_vendor.isEmpty() && m_vendor != other.m_vendor) - return false; - - return true; -} - -QShaderFormat::ShaderType QShaderFormat::shaderType() const noexcept -{ - return m_shaderType; -} - -void QShaderFormat::setShaderType(QShaderFormat::ShaderType shaderType) noexcept -{ - m_shaderType = shaderType; -} - -bool operator==(const QShaderFormat &lhs, const QShaderFormat &rhs) noexcept -{ - return lhs.api() == rhs.api() - && lhs.version() == rhs.version() - && lhs.extensions() == rhs.extensions() - && lhs.vendor() == rhs.vendor() - && lhs.shaderType() == rhs.shaderType(); -} - -QT_END_NAMESPACE diff --git a/src/gui/util/qshaderformat_p.h b/src/gui/util/qshaderformat_p.h deleted file mode 100644 index e47fbb8a03..0000000000 --- a/src/gui/util/qshaderformat_p.h +++ /dev/null @@ -1,123 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). -** 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$ -** -****************************************************************************/ - -#ifndef QSHADERFORMAT_P_H -#define QSHADERFORMAT_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 <QtGui/private/qtguiglobal_p.h> - -#include <QtCore/qstringlist.h> -#include <QtCore/qversionnumber.h> - -QT_BEGIN_NAMESPACE - -class QShaderFormat -{ -public: - enum Api : int { - NoApi, - OpenGLNoProfile, - OpenGLCoreProfile, - OpenGLCompatibilityProfile, - OpenGLES, - VulkanFlavoredGLSL - }; - - enum ShaderType : int { - Vertex = 0, - TessellationControl, - TessellationEvaluation, - Geometry, - Fragment, - Compute - }; - - Q_GUI_EXPORT QShaderFormat() noexcept; - - Q_GUI_EXPORT Api api() const noexcept; - Q_GUI_EXPORT void setApi(Api api) noexcept; - - Q_GUI_EXPORT QVersionNumber version() const noexcept; - Q_GUI_EXPORT void setVersion(const QVersionNumber &version) noexcept; - - Q_GUI_EXPORT QStringList extensions() const noexcept; - Q_GUI_EXPORT void setExtensions(const QStringList &extensions) noexcept; - - Q_GUI_EXPORT QString vendor() const noexcept; - Q_GUI_EXPORT void setVendor(const QString &vendor) noexcept; - - Q_GUI_EXPORT bool isValid() const noexcept; - Q_GUI_EXPORT bool supports(const QShaderFormat &other) const noexcept; - - Q_GUI_EXPORT ShaderType shaderType() const noexcept; - Q_GUI_EXPORT void setShaderType(ShaderType shaderType) noexcept; - -private: - Api m_api; - QVersionNumber m_version; - QStringList m_extensions; - QString m_vendor; - ShaderType m_shaderType; -}; - -Q_GUI_EXPORT bool operator==(const QShaderFormat &lhs, const QShaderFormat &rhs) noexcept; - -inline bool operator!=(const QShaderFormat &lhs, const QShaderFormat &rhs) noexcept -{ - return !(lhs == rhs); -} - -Q_DECLARE_TYPEINFO(QShaderFormat, Q_RELOCATABLE_TYPE); - -QT_END_NAMESPACE - -Q_DECLARE_METATYPE(QShaderFormat) - -#endif // QSHADERFORMAT_P_H diff --git a/src/gui/util/qshadergenerator.cpp b/src/gui/util/qshadergenerator.cpp deleted file mode 100644 index 4933e913a3..0000000000 --- a/src/gui/util/qshadergenerator.cpp +++ /dev/null @@ -1,638 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). -** 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$ -** -****************************************************************************/ - -#include "qshadergenerator_p.h" - -#include "qshaderlanguage_p.h" -#include <QRegularExpression> - -#include <cctype> - -QT_BEGIN_NAMESPACE - -Q_LOGGING_CATEGORY(ShaderGenerator, "ShaderGenerator", QtWarningMsg) - -namespace -{ - QByteArray toGlsl(QShaderLanguage::StorageQualifier qualifier, const QShaderFormat &format) - { - if (format.version().majorVersion() <= 2) { - // Note we're assuming fragment shader only here, it'd be different - // values for vertex shader, will need to be fixed properly at some - // point but isn't necessary yet (this problem already exists in past - // commits anyway) - switch (qualifier) { - case QShaderLanguage::Const: - return "const"; - case QShaderLanguage::Input: - if (format.shaderType() == QShaderFormat::Vertex) - return "attribute"; - else - return "varying"; - case QShaderLanguage::Output: - return ""; // Although fragment shaders for <=2 only have fixed outputs - case QShaderLanguage::Uniform: - return "uniform"; - case QShaderLanguage::BuiltIn: - return "//"; - } - } else { - switch (qualifier) { - case QShaderLanguage::Const: - return "const"; - case QShaderLanguage::Input: - return "in"; - case QShaderLanguage::Output: - return "out"; - case QShaderLanguage::Uniform: - return "uniform"; - case QShaderLanguage::BuiltIn: - return "//"; - } - } - - Q_UNREACHABLE(); - } - - QByteArray toGlsl(QShaderLanguage::VariableType type) - { - switch (type) { - case QShaderLanguage::Bool: - return "bool"; - case QShaderLanguage::Int: - return "int"; - case QShaderLanguage::Uint: - return "uint"; - case QShaderLanguage::Float: - return "float"; - case QShaderLanguage::Double: - return "double"; - case QShaderLanguage::Vec2: - return "vec2"; - case QShaderLanguage::Vec3: - return "vec3"; - case QShaderLanguage::Vec4: - return "vec4"; - case QShaderLanguage::DVec2: - return "dvec2"; - case QShaderLanguage::DVec3: - return "dvec3"; - case QShaderLanguage::DVec4: - return "dvec4"; - case QShaderLanguage::BVec2: - return "bvec2"; - case QShaderLanguage::BVec3: - return "bvec3"; - case QShaderLanguage::BVec4: - return "bvec4"; - case QShaderLanguage::IVec2: - return "ivec2"; - case QShaderLanguage::IVec3: - return "ivec3"; - case QShaderLanguage::IVec4: - return "ivec4"; - case QShaderLanguage::UVec2: - return "uvec2"; - case QShaderLanguage::UVec3: - return "uvec3"; - case QShaderLanguage::UVec4: - return "uvec4"; - case QShaderLanguage::Mat2: - return "mat2"; - case QShaderLanguage::Mat3: - return "mat3"; - case QShaderLanguage::Mat4: - return "mat4"; - case QShaderLanguage::Mat2x2: - return "mat2x2"; - case QShaderLanguage::Mat2x3: - return "mat2x3"; - case QShaderLanguage::Mat2x4: - return "mat2x4"; - case QShaderLanguage::Mat3x2: - return "mat3x2"; - case QShaderLanguage::Mat3x3: - return "mat3x3"; - case QShaderLanguage::Mat3x4: - return "mat3x4"; - case QShaderLanguage::Mat4x2: - return "mat4x2"; - case QShaderLanguage::Mat4x3: - return "mat4x3"; - case QShaderLanguage::Mat4x4: - return "mat4x4"; - case QShaderLanguage::DMat2: - return "dmat2"; - case QShaderLanguage::DMat3: - return "dmat3"; - case QShaderLanguage::DMat4: - return "dmat4"; - case QShaderLanguage::DMat2x2: - return "dmat2x2"; - case QShaderLanguage::DMat2x3: - return "dmat2x3"; - case QShaderLanguage::DMat2x4: - return "dmat2x4"; - case QShaderLanguage::DMat3x2: - return "dmat3x2"; - case QShaderLanguage::DMat3x3: - return "dmat3x3"; - case QShaderLanguage::DMat3x4: - return "dmat3x4"; - case QShaderLanguage::DMat4x2: - return "dmat4x2"; - case QShaderLanguage::DMat4x3: - return "dmat4x3"; - case QShaderLanguage::DMat4x4: - return "dmat4x4"; - case QShaderLanguage::Sampler1D: - return "sampler1D"; - case QShaderLanguage::Sampler2D: - return "sampler2D"; - case QShaderLanguage::Sampler3D: - return "sampler3D"; - case QShaderLanguage::SamplerCube: - return "samplerCube"; - case QShaderLanguage::Sampler2DRect: - return "sampler2DRect"; - case QShaderLanguage::Sampler2DMs: - return "sampler2DMS"; - case QShaderLanguage::SamplerBuffer: - return "samplerBuffer"; - case QShaderLanguage::Sampler1DArray: - return "sampler1DArray"; - case QShaderLanguage::Sampler2DArray: - return "sampler2DArray"; - case QShaderLanguage::Sampler2DMsArray: - return "sampler2DMSArray"; - case QShaderLanguage::SamplerCubeArray: - return "samplerCubeArray"; - case QShaderLanguage::Sampler1DShadow: - return "sampler1DShadow"; - case QShaderLanguage::Sampler2DShadow: - return "sampler2DShadow"; - case QShaderLanguage::Sampler2DRectShadow: - return "sampler2DRectShadow"; - case QShaderLanguage::Sampler1DArrayShadow: - return "sampler1DArrayShadow"; - case QShaderLanguage::Sampler2DArrayShadow: - return "sample2DArrayShadow"; - case QShaderLanguage::SamplerCubeShadow: - return "samplerCubeShadow"; - case QShaderLanguage::SamplerCubeArrayShadow: - return "samplerCubeArrayShadow"; - case QShaderLanguage::ISampler1D: - return "isampler1D"; - case QShaderLanguage::ISampler2D: - return "isampler2D"; - case QShaderLanguage::ISampler3D: - return "isampler3D"; - case QShaderLanguage::ISamplerCube: - return "isamplerCube"; - case QShaderLanguage::ISampler2DRect: - return "isampler2DRect"; - case QShaderLanguage::ISampler2DMs: - return "isampler2DMS"; - case QShaderLanguage::ISamplerBuffer: - return "isamplerBuffer"; - case QShaderLanguage::ISampler1DArray: - return "isampler1DArray"; - case QShaderLanguage::ISampler2DArray: - return "isampler2DArray"; - case QShaderLanguage::ISampler2DMsArray: - return "isampler2DMSArray"; - case QShaderLanguage::ISamplerCubeArray: - return "isamplerCubeArray"; - case QShaderLanguage::USampler1D: - return "usampler1D"; - case QShaderLanguage::USampler2D: - return "usampler2D"; - case QShaderLanguage::USampler3D: - return "usampler3D"; - case QShaderLanguage::USamplerCube: - return "usamplerCube"; - case QShaderLanguage::USampler2DRect: - return "usampler2DRect"; - case QShaderLanguage::USampler2DMs: - return "usampler2DMS"; - case QShaderLanguage::USamplerBuffer: - return "usamplerBuffer"; - case QShaderLanguage::USampler1DArray: - return "usampler1DArray"; - case QShaderLanguage::USampler2DArray: - return "usampler2DArray"; - case QShaderLanguage::USampler2DMsArray: - return "usampler2DMSArray"; - case QShaderLanguage::USamplerCubeArray: - return "usamplerCubeArray"; - } - - Q_UNREACHABLE(); - } - - QByteArray replaceParameters(const QByteArray &original, const QShaderNode &node, const QShaderFormat &format) - { - QByteArray result = original; - - const QStringList parameterNames = node.parameterNames(); - for (const QString ¶meterName : parameterNames) { - const QByteArray placeholder = QByteArray(QByteArrayLiteral("$") + parameterName.toUtf8()); - const QVariant parameter = node.parameter(parameterName); - if (parameter.userType() == qMetaTypeId<QShaderLanguage::StorageQualifier>()) { - const QShaderLanguage::StorageQualifier qualifier = qvariant_cast<QShaderLanguage::StorageQualifier>(parameter); - const QByteArray value = toGlsl(qualifier, format); - result.replace(placeholder, value); - } else if (parameter.userType() == qMetaTypeId<QShaderLanguage::VariableType>()) { - const QShaderLanguage::VariableType type = qvariant_cast<QShaderLanguage::VariableType>(parameter); - const QByteArray value = toGlsl(type); - result.replace(placeholder, value); - } else { - const QByteArray value = parameter.toString().toUtf8(); - result.replace(placeholder, value); - } - } - - return result; - } -} - -QByteArray QShaderGenerator::createShaderCode(const QStringList &enabledLayers) const -{ - auto code = QByteArrayList(); - - if (format.isValid()) { - const bool isGLES = format.api() == QShaderFormat::OpenGLES; - const int major = format.version().majorVersion(); - const int minor = format.version().minorVersion(); - - const int version = major == 2 && isGLES ? 100 - : major == 3 && isGLES ? 300 - : major == 2 ? 100 + 10 * (minor + 1) - : major == 3 && minor <= 2 ? 100 + 10 * (minor + 3) - : major * 100 + minor * 10; - - const QByteArray profile = isGLES && version > 100 ? QByteArrayLiteral(" es") - : version >= 150 && format.api() == QShaderFormat::OpenGLCoreProfile ? QByteArrayLiteral(" core") - : version >= 150 && format.api() == QShaderFormat::OpenGLCompatibilityProfile ? QByteArrayLiteral(" compatibility") - : QByteArray(); - - code << (QByteArrayLiteral("#version ") + QByteArray::number(version) + profile); - code << QByteArray(); - } - - const auto intersectsEnabledLayers = [enabledLayers] (const QStringList &layers) { - return layers.isEmpty() - || std::any_of(layers.cbegin(), layers.cend(), - [enabledLayers] (const QString &s) { return enabledLayers.contains(s); }); - }; - - QList<QString> globalInputVariables; - const QRegularExpression globalInputExtractRegExp(QStringLiteral("^.*\\s+(\\w+).*;$")); - - const QList<QShaderNode> nodes = graph.nodes(); - for (const QShaderNode &node : nodes) { - if (intersectsEnabledLayers(node.layers())) { - const QByteArrayList headerSnippets = node.rule(format).headerSnippets; - for (const QByteArray &snippet : headerSnippets) { - code << replaceParameters(snippet, node, format); - - // If node is an input, record the variable name into the globalInputVariables list - if (node.type() == QShaderNode::Input) { - const QRegularExpressionMatch match = globalInputExtractRegExp.match(QString::fromUtf8(code.last())); - if (match.hasMatch()) - globalInputVariables.push_back(match.captured(1)); - } - } - } - } - - code << QByteArray(); - code << QByteArrayLiteral("void main()"); - code << QByteArrayLiteral("{"); - - const QRegularExpression temporaryVariableToAssignmentRegExp(QStringLiteral("([^;]*\\s+(v\\d+))\\s*=\\s*([^;]*);")); - const QRegularExpression temporaryVariableInAssignmentRegExp(QStringLiteral("\\W*(v\\d+)\\W*")); - const QRegularExpression statementRegExp(QStringLiteral("\\s*(\\w+)\\s*=\\s*([^;]*);")); - - struct Variable; - - struct Assignment - { - QString expression; - QList<Variable *> referencedVariables; - }; - - struct Variable - { - enum Type { - GlobalInput, - TemporaryAssignment, - Output - }; - - QString name; - QString declaration; - int referenceCount = 0; - Assignment assignment; - Type type = TemporaryAssignment; - bool substituted = false; - - static void substitute(Variable *v) - { - if (v->substituted) - return; - - qCDebug(ShaderGenerator) << "Begin Substituting " << v->name << " = " << v->assignment.expression; - for (Variable *ref : qAsConst(v->assignment.referencedVariables)) { - // Recursively substitute - Variable::substitute(ref); - - // Replace all variables referenced only once in the assignment - // by their actual expression - if (ref->referenceCount == 1 || ref->type == Variable::GlobalInput) { - const QRegularExpression r(QStringLiteral("(.*\\b)(%1)(\\b.*)").arg(ref->name)); - if (v->assignment.referencedVariables.size() == 1) - v->assignment.expression.replace(r, - QStringLiteral("\\1%2\\3").arg(ref->assignment.expression)); - else - v->assignment.expression.replace(r, - QStringLiteral("(\\1%2\\3)").arg(ref->assignment.expression)); - } - } - qCDebug(ShaderGenerator) << "Done Substituting " << v->name << " = " << v->assignment.expression; - v->substituted = true; - } - }; - - struct LineContent - { - QByteArray rawContent; - Variable *var = nullptr; - }; - - // Table to store temporary variables that should be replaced: - // - If variable references a a global variables - // -> we will use the global variable directly - // - If variable references a function results - // -> will be kept only if variable is referenced more than once. - // This avoids having vec3 v56 = vertexPosition; when we could - // just use vertexPosition directly. - // The added benefit is when having arrays, we don't try to create - // mat4 v38 = skinningPalelette[100] which would be invalid - QList<Variable> temporaryVariables; - // Reserve more than enough space to ensure no reallocation will take place - temporaryVariables.reserve(nodes.size() * 8); - - QList<LineContent> lines; - - auto createVariable = [&] () -> Variable * { - Q_ASSERT(temporaryVariables.capacity() > 0); - temporaryVariables.resize(temporaryVariables.size() + 1); - return &temporaryVariables.last(); - }; - - auto findVariable = [&] (const QString &name) -> Variable * { - const auto end = temporaryVariables.end(); - auto it = std::find_if(temporaryVariables.begin(), end, - [=] (const Variable &a) { return a.name == name; }); - if (it != end) - return &(*it); - return nullptr; - }; - - auto gatherTemporaryVariablesFromAssignment = [&] (Variable *v, const QString &assignmentContent) { - QRegularExpressionMatchIterator subMatchIt = temporaryVariableInAssignmentRegExp.globalMatch(assignmentContent); - while (subMatchIt.hasNext()) { - const QRegularExpressionMatch subMatch = subMatchIt.next(); - const QString variableName = subMatch.captured(1); - - // Variable we care about should already exists -> an expression cannot reference a variable that hasn't been defined - Variable *u = findVariable(variableName); - Q_ASSERT(u); - - // Increase reference count for u - ++u->referenceCount; - // Insert u as reference for variable v - v->assignment.referencedVariables.push_back(u); - } - }; - - for (const QShaderGraph::Statement &statement : graph.createStatements(enabledLayers)) { - const QShaderNode node = statement.node; - QByteArray line = node.rule(format).substitution; - const QList<QShaderNodePort> ports = node.ports(); - - struct VariableReplacement { - QByteArray placeholder; - QByteArray variable; - }; - - QList<VariableReplacement> variableReplacements; - - // Generate temporary variable names vN - for (const QShaderNodePort &port : ports) { - const QString portName = port.name; - const QShaderNodePort::Direction portDirection = port.direction; - const bool isInput = port.direction == QShaderNodePort::Input; - - const int portIndex = statement.portIndex(portDirection, portName); - - Q_ASSERT(portIndex >= 0); - - const int variableIndex = isInput ? statement.inputs.at(portIndex) - : statement.outputs.at(portIndex); - if (variableIndex < 0) - continue; - - VariableReplacement replacement; - replacement.placeholder = QByteArrayLiteral("$") + portName.toUtf8(); - replacement.variable = QByteArrayLiteral("v") + QByteArray::number(variableIndex); - - variableReplacements.append(std::move(replacement)); - } - - int begin = 0; - while ((begin = line.indexOf('$', begin)) != -1) { - int end = begin + 1; - char endChar = line.at(end); - const int size = line.size(); - while (end < size && (std::isalnum(endChar) || endChar == '_')) { - ++end; - endChar = line.at(end); - } - - const int placeholderLength = end - begin; - - const QByteArray variableName = line.mid(begin, placeholderLength); - const auto replacementIt = std::find_if(variableReplacements.cbegin(), variableReplacements.cend(), - [&variableName](const VariableReplacement &replacement) { - return variableName == replacement.placeholder; - }); - - if (replacementIt != variableReplacements.cend()) { - line.replace(begin, placeholderLength, replacementIt->variable); - begin += replacementIt->variable.length(); - } else { - begin = end; - } - } - - // Substitute variable names by generated vN variable names - const QByteArray substitutionedLine = replaceParameters(line, node, format); - - QRegularExpressionMatchIterator matches; - - switch (node.type()) { - case QShaderNode::Input: - case QShaderNode::Output: - matches = statementRegExp.globalMatch(QString::fromUtf8(substitutionedLine)); - break; - case QShaderNode::Function: - matches = temporaryVariableToAssignmentRegExp.globalMatch(QString::fromUtf8(substitutionedLine)); - break; - case QShaderNode::Invalid: - break; - } - - while (matches.hasNext()) { - QRegularExpressionMatch match = matches.next(); - - Variable *v = nullptr; - - switch (node.type()) { - // Record name of temporary variable that possibly references a global input - // We will replace the temporary variables by the matching global variables later - case QShaderNode::Input: { - const QString localVariable = match.captured(1); - const QString globalVariable = match.captured(2); - - v = createVariable(); - v->name = localVariable; - v->type = Variable::GlobalInput; - - Assignment assignment; - assignment.expression = globalVariable; - v->assignment = assignment; - break; - } - - case QShaderNode::Function: { - const QString localVariableDeclaration = match.captured(1); - const QString localVariableName = match.captured(2); - const QString assignmentContent = match.captured(3); - - // Add new variable -> it cannot exist already - v = createVariable(); - v->name = localVariableName; - v->declaration = localVariableDeclaration; - v->assignment.expression = assignmentContent; - - // Find variables that may be referenced in the assignment - gatherTemporaryVariablesFromAssignment(v, assignmentContent); - break; - } - - case QShaderNode::Output: { - const QString outputDeclaration = match.captured(1); - const QString assignmentContent = match.captured(2); - - v = createVariable(); - v->name = outputDeclaration; - v->declaration = outputDeclaration; - v->type = Variable::Output; - - Assignment assignment; - assignment.expression = assignmentContent; - v->assignment = assignment; - - // Find variables that may be referenced in the assignment - gatherTemporaryVariablesFromAssignment(v, assignmentContent); - break; - } - case QShaderNode::Invalid: - break; - } - - LineContent lineContent; - lineContent.rawContent = QByteArray(QByteArrayLiteral(" ") + substitutionedLine); - lineContent.var = v; - lines << lineContent; - } - } - - // Go through all lines - // Perform substitution of line with temporary variables substitution - for (LineContent &lineContent : lines) { - Variable *v = lineContent.var; - qCDebug(ShaderGenerator) << lineContent.rawContent; - if (v != nullptr) { - Variable::substitute(v); - - qCDebug(ShaderGenerator) << "Line " << lineContent.rawContent << "is assigned to temporary" << v->name; - - // Check number of occurrences a temporary variable is referenced - if (v->referenceCount == 1 || v->type == Variable::GlobalInput) { - // If it is referenced only once, no point in creating a temporary - // Clear content for current line - lineContent.rawContent.clear(); - // We assume expression that were referencing vN will have vN properly substituted - } else { - lineContent.rawContent = QStringLiteral(" %1 = %2;").arg(v->declaration) - .arg(v->assignment.expression) - .toUtf8(); - } - - qCDebug(ShaderGenerator) << "Updated Line is " << lineContent.rawContent; - } - } - - // Go throug all lines and insert content - for (const LineContent &lineContent : qAsConst(lines)) { - if (!lineContent.rawContent.isEmpty()) { - code << lineContent.rawContent; - } - } - - code << QByteArrayLiteral("}"); - code << QByteArray(); - - return code.join('\n'); -} - -QT_END_NAMESPACE diff --git a/src/gui/util/qshadergenerator_p.h b/src/gui/util/qshadergenerator_p.h deleted file mode 100644 index 4d3a09c92f..0000000000 --- a/src/gui/util/qshadergenerator_p.h +++ /dev/null @@ -1,79 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). -** 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$ -** -****************************************************************************/ - -#ifndef QSHADERGENERATOR_P_H -#define QSHADERGENERATOR_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 <QtGui/private/qtguiglobal_p.h> - -#include <QtGui/private/qshadergraph_p.h> -#include <QtCore/QLoggingCategory> - - -QT_BEGIN_NAMESPACE - -Q_DECLARE_LOGGING_CATEGORY(ShaderGenerator) - -class QShaderGenerator -{ -public: - Q_GUI_EXPORT QByteArray createShaderCode(const QStringList &enabledLayers = QStringList()) const; - - QShaderGraph graph; - QShaderFormat format; -}; - -Q_DECLARE_TYPEINFO(QShaderGenerator, Q_RELOCATABLE_TYPE); - -QT_END_NAMESPACE - -Q_DECLARE_METATYPE(QShaderGenerator) - -#endif // QSHADERGENERATOR_P_H diff --git a/src/gui/util/qshadergraph.cpp b/src/gui/util/qshadergraph.cpp deleted file mode 100644 index 5d2d7f3627..0000000000 --- a/src/gui/util/qshadergraph.cpp +++ /dev/null @@ -1,316 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). -** 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$ -** -****************************************************************************/ - -#include "qshadergraph_p.h" - -QT_BEGIN_NAMESPACE - - -namespace -{ - QList<QShaderNode> copyOutputNodes(const QList<QShaderNode> &nodes, const QList<QShaderGraph::Edge> &edges) - { - auto res = QList<QShaderNode>(); - std::copy_if(nodes.cbegin(), nodes.cend(), - std::back_inserter(res), - [&edges] (const QShaderNode &node) { - return node.type() == QShaderNode::Output || - (node.type() == QShaderNode::Function && - !std::any_of(edges.cbegin(), - edges.cend(), - [&node] (const QShaderGraph::Edge &edge) { - return edge.sourceNodeUuid == - node.uuid(); - })); - }); - return res; - } - - QList<QShaderGraph::Edge> incomingEdges(const QList<QShaderGraph::Edge> &edges, const QUuid &uuid) - { - auto res = QList<QShaderGraph::Edge>(); - std::copy_if(edges.cbegin(), edges.cend(), - std::back_inserter(res), - [uuid] (const QShaderGraph::Edge &edge) { - return edge.sourceNodeUuid == uuid; - }); - return res; - } - - QList<QShaderGraph::Edge> outgoingEdges(const QList<QShaderGraph::Edge> &edges, const QUuid &uuid) - { - auto res = QList<QShaderGraph::Edge>(); - std::copy_if(edges.cbegin(), edges.cend(), - std::back_inserter(res), - [uuid] (const QShaderGraph::Edge &edge) { - return edge.targetNodeUuid == uuid; - }); - return res; - } - - QShaderGraph::Statement nodeToStatement(const QShaderNode &node, int &nextVarId) - { - auto statement = QShaderGraph::Statement(); - statement.node = node; - - const QList<QShaderNodePort> ports = node.ports(); - for (const QShaderNodePort &port : ports) { - if (port.direction == QShaderNodePort::Input) { - statement.inputs.append(-1); - } else { - statement.outputs.append(nextVarId); - nextVarId++; - } - } - return statement; - } - - QShaderGraph::Statement completeStatement(const QHash<QUuid, QShaderGraph::Statement> &idHash, - const QList<QShaderGraph::Edge> edges, - const QUuid &uuid) - { - auto targetStatement = idHash.value(uuid); - for (const QShaderGraph::Edge &edge : edges) { - if (edge.targetNodeUuid != uuid) - continue; - - const QShaderGraph::Statement sourceStatement = idHash.value(edge.sourceNodeUuid); - const int sourcePortIndex = sourceStatement.portIndex(QShaderNodePort::Output, edge.sourcePortName); - const int targetPortIndex = targetStatement.portIndex(QShaderNodePort::Input, edge.targetPortName); - - if (sourcePortIndex < 0 || targetPortIndex < 0) - continue; - - const QList<int> sourceOutputs = sourceStatement.outputs; - QList<int> &targetInputs = targetStatement.inputs; - targetInputs[targetPortIndex] = sourceOutputs[sourcePortIndex]; - } - return targetStatement; - } - - void removeNodesWithUnboundInputs(QList<QShaderGraph::Statement> &statements, - const QList<QShaderGraph::Edge> &allEdges) - { - // A node is invalid if any of its input ports is disconected - // or connected to the output port of another invalid node. - - // Keeps track of the edges from the nodes we know to be valid - // to unvisited nodes - auto currentEdges = QList<QShaderGraph::Edge>(); - - statements.erase(std::remove_if(statements.begin(), - statements.end(), - [¤tEdges, &allEdges] (const QShaderGraph::Statement &statement) { - const QShaderNode &node = statement.node; - const QList<QShaderGraph::Edge> outgoing = outgoingEdges(currentEdges, node.uuid()); - const QList<QShaderNodePort> ports = node.ports(); - - bool allInputsConnected = true; - for (const QShaderNodePort &port : node.ports()) { - if (port.direction == QShaderNodePort::Output) - continue; - - const auto edgeIt = std::find_if(outgoing.cbegin(), - outgoing.cend(), - [&port] (const QShaderGraph::Edge &edge) { - return edge.targetPortName == port.name; - }); - - if (edgeIt != outgoing.cend()) - currentEdges.removeAll(*edgeIt); - else - allInputsConnected = false; - } - - if (allInputsConnected) { - const QList<QShaderGraph::Edge> incoming = incomingEdges(allEdges, node.uuid()); - currentEdges.append(incoming); - } - - return !allInputsConnected; - }), - statements.end()); - } -} - -QUuid QShaderGraph::Statement::uuid() const noexcept -{ - return node.uuid(); -} - -int QShaderGraph::Statement::portIndex(QShaderNodePort::Direction direction, const QString &portName) const noexcept -{ - const QList<QShaderNodePort> ports = node.ports(); - int index = 0; - for (const QShaderNodePort &port : ports) { - if (port.name == portName && port.direction == direction) - return index; - else if (port.direction == direction) - index++; - } - return -1; -} - -void QShaderGraph::addNode(const QShaderNode &node) -{ - removeNode(node); - m_nodes.append(node); -} - -void QShaderGraph::removeNode(const QShaderNode &node) -{ - const auto it = std::find_if(m_nodes.begin(), m_nodes.end(), - [node] (const QShaderNode &n) { return n.uuid() == node.uuid(); }); - if (it != m_nodes.end()) - m_nodes.erase(it); -} - -QList<QShaderNode> QShaderGraph::nodes() const noexcept -{ - return m_nodes; -} - -void QShaderGraph::addEdge(const QShaderGraph::Edge &edge) -{ - if (m_edges.contains(edge)) - return; - m_edges.append(edge); -} - -void QShaderGraph::removeEdge(const QShaderGraph::Edge &edge) -{ - m_edges.removeAll(edge); -} - -QList<QShaderGraph::Edge> QShaderGraph::edges() const noexcept -{ - return m_edges; -} - -QList<QShaderGraph::Statement> QShaderGraph::createStatements(const QStringList &enabledLayers) const -{ - const auto intersectsEnabledLayers = [enabledLayers] (const QStringList &layers) { - return layers.isEmpty() - || std::any_of(layers.cbegin(), layers.cend(), - [enabledLayers] (const QString &s) { return enabledLayers.contains(s); }); - }; - - const QList<QShaderNode> enabledNodes = [this, intersectsEnabledLayers] { - auto res = QList<QShaderNode>(); - std::copy_if(m_nodes.cbegin(), m_nodes.cend(), - std::back_inserter(res), - [intersectsEnabledLayers] (const QShaderNode &node) { - return intersectsEnabledLayers(node.layers()); - }); - return res; - }(); - - const QList<Edge> enabledEdges = [this, intersectsEnabledLayers] { - auto res = QList<Edge>(); - std::copy_if(m_edges.cbegin(), m_edges.cend(), - std::back_inserter(res), - [intersectsEnabledLayers] (const Edge &edge) { - return intersectsEnabledLayers(edge.layers); - }); - return res; - }(); - - const QHash<QUuid, Statement> idHash = [enabledNodes] { - auto nextVarId = 0; - auto res = QHash<QUuid, Statement>(); - for (const QShaderNode &node : enabledNodes) - res.insert(node.uuid(), nodeToStatement(node, nextVarId)); - return res; - }(); - - auto result = QList<Statement>(); - QList<Edge> currentEdges = enabledEdges; - QList<QUuid> currentUuids = [enabledNodes, enabledEdges] { - const QList<QShaderNode> inputs = copyOutputNodes(enabledNodes, enabledEdges); - auto res = QList<QUuid>(); - std::transform(inputs.cbegin(), inputs.cend(), - std::back_inserter(res), - [](const QShaderNode &node) { return node.uuid(); }); - return res; - }(); - - // Implements Kahn's algorithm to flatten the graph - // https://en.wikipedia.org/wiki/Topological_sorting#Kahn.27s_algorithm - // - // We implement it with a small twist though, we follow the edges backward - // because we want to track the dependencies from the output nodes and not the - // input nodes - while (!currentUuids.isEmpty()) { - const QUuid uuid = currentUuids.takeFirst(); - result.append(completeStatement(idHash, enabledEdges, uuid)); - - const QList<QShaderGraph::Edge> outgoing = outgoingEdges(currentEdges, uuid); - for (const QShaderGraph::Edge &outgoingEdge : outgoing) { - currentEdges.removeAll(outgoingEdge); - const QUuid nextUuid = outgoingEdge.sourceNodeUuid; - const QList<QShaderGraph::Edge> incoming = incomingEdges(currentEdges, nextUuid); - if (incoming.isEmpty()) { - currentUuids.append(nextUuid); - } - } - } - - std::reverse(result.begin(), result.end()); - - removeNodesWithUnboundInputs(result, enabledEdges); - - return result; -} - -bool operator==(const QShaderGraph::Edge &lhs, const QShaderGraph::Edge &rhs) noexcept -{ - return lhs.sourceNodeUuid == rhs.sourceNodeUuid - && lhs.sourcePortName == rhs.sourcePortName - && lhs.targetNodeUuid == rhs.targetNodeUuid - && lhs.targetPortName == rhs.targetPortName; -} - -bool operator==(const QShaderGraph::Statement &lhs, const QShaderGraph::Statement &rhs) noexcept -{ - return lhs.inputs == rhs.inputs - && lhs.outputs == rhs.outputs - && lhs.node.uuid() == rhs.node.uuid(); -} - -QT_END_NAMESPACE diff --git a/src/gui/util/qshadergraph_p.h b/src/gui/util/qshadergraph_p.h deleted file mode 100644 index dbc5f3fab7..0000000000 --- a/src/gui/util/qshadergraph_p.h +++ /dev/null @@ -1,124 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). -** 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$ -** -****************************************************************************/ - -#ifndef QSHADERGRAPH_P_H -#define QSHADERGRAPH_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 <QtGui/private/qtguiglobal_p.h> - -#include <QtGui/private/qshadernode_p.h> - -QT_BEGIN_NAMESPACE - -class QShaderGraph -{ -public: - class Edge - { - public: - QStringList layers; - QUuid sourceNodeUuid; - QString sourcePortName; - QUuid targetNodeUuid; - QString targetPortName; - }; - - class Statement - { - public: - Q_GUI_EXPORT QUuid uuid() const noexcept; - Q_GUI_EXPORT int portIndex(QShaderNodePort::Direction direction, const QString &portName) const noexcept; - - QShaderNode node; - QList<int> inputs; - QList<int> outputs; - }; - - Q_GUI_EXPORT void addNode(const QShaderNode &node); - Q_GUI_EXPORT void removeNode(const QShaderNode &node); - Q_GUI_EXPORT QList<QShaderNode> nodes() const noexcept; - - Q_GUI_EXPORT void addEdge(const Edge &edge); - Q_GUI_EXPORT void removeEdge(const Edge &edge); - Q_GUI_EXPORT QList<Edge> edges() const noexcept; - - Q_GUI_EXPORT QList<Statement> - createStatements(const QStringList &enabledLayers = QStringList()) const; - -private: - QList<QShaderNode> m_nodes; - QList<Edge> m_edges; -}; - -Q_GUI_EXPORT bool operator==(const QShaderGraph::Edge &lhs, const QShaderGraph::Edge &rhs) noexcept; - -inline bool operator!=(const QShaderGraph::Edge &lhs, const QShaderGraph::Edge &rhs) noexcept -{ - return !(lhs == rhs); -} - -Q_GUI_EXPORT bool operator==(const QShaderGraph::Statement &lhs, const QShaderGraph::Statement &rhs) noexcept; - -inline bool operator!=(const QShaderGraph::Statement &lhs, const QShaderGraph::Statement &rhs) noexcept -{ - return !(lhs == rhs); -} - -Q_DECLARE_TYPEINFO(QShaderGraph, Q_RELOCATABLE_TYPE); -Q_DECLARE_TYPEINFO(QShaderGraph::Edge, Q_RELOCATABLE_TYPE); -Q_DECLARE_TYPEINFO(QShaderGraph::Statement, Q_RELOCATABLE_TYPE); - -QT_END_NAMESPACE - -Q_DECLARE_METATYPE(QShaderGraph) -Q_DECLARE_METATYPE(QShaderGraph::Edge) -Q_DECLARE_METATYPE(QShaderGraph::Statement) - -#endif // QSHADERGRAPH_P_H diff --git a/src/gui/util/qshadergraphloader.cpp b/src/gui/util/qshadergraphloader.cpp deleted file mode 100644 index defa88b9d3..0000000000 --- a/src/gui/util/qshadergraphloader.cpp +++ /dev/null @@ -1,269 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). -** 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$ -** -****************************************************************************/ - -#include "qshadergraphloader_p.h" - -#include "qshadernodesloader_p.h" - -#include <QtCore/qdebug.h> -#include <QtCore/qiodevice.h> -#include <QtCore/qjsonarray.h> -#include <QtCore/qjsondocument.h> -#include <QtCore/qjsonobject.h> -#include <QtCore/qmetaobject.h> - -QT_BEGIN_NAMESPACE - -void qt_register_ShaderLanguage_enums(); - -QShaderGraphLoader::QShaderGraphLoader() noexcept - : m_status(Null), - m_device(nullptr) -{ - qt_register_ShaderLanguage_enums(); -} - -QShaderGraphLoader::Status QShaderGraphLoader::status() const noexcept -{ - return m_status; -} - -QShaderGraph QShaderGraphLoader::graph() const noexcept -{ - return m_graph; -} - -QIODevice *QShaderGraphLoader::device() const noexcept -{ - return m_device; -} - -void QShaderGraphLoader::setDevice(QIODevice *device) noexcept -{ - m_device = device; - m_graph = QShaderGraph(); - m_status = !m_device ? Null - : (m_device->openMode() & QIODevice::ReadOnly) ? Waiting - : Error; -} - -QHash<QString, QShaderNode> QShaderGraphLoader::prototypes() const noexcept -{ - return m_prototypes; -} - -void QShaderGraphLoader::setPrototypes(const QHash<QString, QShaderNode> &prototypes) noexcept -{ - m_prototypes = prototypes; -} - -void QShaderGraphLoader::load() -{ - if (m_status == Error) - return; - - auto error = QJsonParseError(); - const QJsonDocument document = QJsonDocument::fromJson(m_device->readAll(), &error); - - if (error.error != QJsonParseError::NoError) { - qWarning() << "Invalid JSON document:" << error.errorString(); - m_status = Error; - return; - } - - if (document.isEmpty() || !document.isObject()) { - qWarning() << "Invalid JSON document, root should be an object"; - m_status = Error; - return; - } - - const QJsonObject root = document.object(); - - const QJsonValue nodesValue = root.value(QStringLiteral("nodes")); - if (!nodesValue.isArray()) { - qWarning() << "Invalid nodes property, should be an array"; - m_status = Error; - return; - } - - const QJsonValue edgesValue = root.value(QStringLiteral("edges")); - if (!edgesValue.isArray()) { - qWarning() << "Invalid edges property, should be an array"; - m_status = Error; - return; - } - - bool hasError = false; - - const QJsonValue prototypesValue = root.value(QStringLiteral("prototypes")); - if (!prototypesValue.isUndefined()) { - if (prototypesValue.isObject()) { - QShaderNodesLoader loader; - loader.load(prototypesValue.toObject()); - m_prototypes.insert(loader.nodes()); - } else { - qWarning() << "Invalid prototypes property, should be an object"; - m_status = Error; - return; - } - } - - const QJsonArray nodes = nodesValue.toArray(); - for (const QJsonValue nodeValue : nodes) { - if (!nodeValue.isObject()) { - qWarning() << "Invalid node found"; - hasError = true; - continue; - } - - const QJsonObject nodeObject = nodeValue.toObject(); - - const QString uuidString = nodeObject.value(QStringLiteral("uuid")).toString(); - const QUuid uuid = QUuid(uuidString); - if (uuid.isNull()) { - qWarning() << "Invalid UUID found in node:" << uuidString; - hasError = true; - continue; - } - - const QString type = nodeObject.value(QStringLiteral("type")).toString(); - if (!m_prototypes.contains(type)) { - qWarning() << "Unsupported node type found:" << type; - hasError = true; - continue; - } - - const QJsonArray layersArray = nodeObject.value(QStringLiteral("layers")).toArray(); - auto layers = QStringList(); - for (const QJsonValue layerValue : layersArray) { - layers.append(layerValue.toString()); - } - - QShaderNode node = m_prototypes.value(type); - node.setUuid(uuid); - node.setLayers(layers); - - const QJsonValue parametersValue = nodeObject.value(QStringLiteral("parameters")); - if (parametersValue.isObject()) { - const QJsonObject parametersObject = parametersValue.toObject(); - for (const QString ¶meterName : parametersObject.keys()) { - const QJsonValue parameterValue = parametersObject.value(parameterName); - if (parameterValue.isObject()) { - const QJsonObject parameterObject = parameterValue.toObject(); - const QString type = parameterObject.value(QStringLiteral("type")).toString(); - const auto metaType = QMetaType::fromName(type.toUtf8()); - - const QString value = parameterObject.value(QStringLiteral("value")).toString(); - auto variant = QVariant(value); - - if (metaType.flags() & QMetaType::IsEnumeration) { - const QMetaObject *metaObject = metaType.metaObject(); - const char *className = metaObject->className(); - const QByteArray enumName = type.mid(static_cast<int>(qstrlen(className)) + 2).toUtf8(); - const QMetaEnum metaEnum = metaObject->enumerator(metaObject->indexOfEnumerator(enumName)); - const int enumValue = metaEnum.keyToValue(value.toUtf8()); - variant = QVariant(enumValue); - variant.convert(metaType); - } else { - variant.convert(metaType); - } - node.setParameter(parameterName, variant); - } else { - node.setParameter(parameterName, parameterValue.toVariant()); - } - } - } - - m_graph.addNode(node); - } - - const QJsonArray edges = edgesValue.toArray(); - for (const QJsonValue edgeValue : edges) { - if (!edgeValue.isObject()) { - qWarning() << "Invalid edge found"; - hasError = true; - continue; - } - - const QJsonObject edgeObject = edgeValue.toObject(); - - const QString sourceUuidString = edgeObject.value(QStringLiteral("sourceUuid")).toString(); - const QUuid sourceUuid = QUuid(sourceUuidString); - if (sourceUuid.isNull()) { - qWarning() << "Invalid source UUID found in edge:" << sourceUuidString; - hasError = true; - continue; - } - - const QString sourcePort = edgeObject.value(QStringLiteral("sourcePort")).toString(); - - const QString targetUuidString = edgeObject.value(QStringLiteral("targetUuid")).toString(); - const QUuid targetUuid = QUuid(targetUuidString); - if (targetUuid.isNull()) { - qWarning() << "Invalid target UUID found in edge:" << targetUuidString; - hasError = true; - continue; - } - - const QString targetPort = edgeObject.value(QStringLiteral("targetPort")).toString(); - - const QJsonArray layersArray = edgeObject.value(QStringLiteral("layers")).toArray(); - auto layers = QStringList(); - for (const QJsonValue layerValue : layersArray) { - layers.append(layerValue.toString()); - } - - auto edge = QShaderGraph::Edge(); - edge.sourceNodeUuid = sourceUuid; - edge.sourcePortName = sourcePort; - edge.targetNodeUuid = targetUuid; - edge.targetPortName = targetPort; - edge.layers = layers; - m_graph.addEdge(edge); - } - - if (hasError) { - m_status = Error; - m_graph = QShaderGraph(); - } else { - m_status = Ready; - } -} - -QT_END_NAMESPACE diff --git a/src/gui/util/qshadergraphloader_p.h b/src/gui/util/qshadergraphloader_p.h deleted file mode 100644 index bdd02799f7..0000000000 --- a/src/gui/util/qshadergraphloader_p.h +++ /dev/null @@ -1,99 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). -** 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$ -** -****************************************************************************/ - -#ifndef QSHADERGRAPHLOADER_P_H -#define QSHADERGRAPHLOADER_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 <QtGui/private/qtguiglobal_p.h> - -#include <QtGui/private/qshadergraph_p.h> - -QT_BEGIN_NAMESPACE - -class QIODevice; - -class QShaderGraphLoader -{ -public: - enum Status : char { - Null, - Waiting, - Ready, - Error - }; - - Q_GUI_EXPORT QShaderGraphLoader() noexcept; - - Q_GUI_EXPORT Status status() const noexcept; - Q_GUI_EXPORT QShaderGraph graph() const noexcept; - - Q_GUI_EXPORT QIODevice *device() const noexcept; - Q_GUI_EXPORT void setDevice(QIODevice *device) noexcept; - - Q_GUI_EXPORT QHash<QString, QShaderNode> prototypes() const noexcept; - Q_GUI_EXPORT void setPrototypes(const QHash<QString, QShaderNode> &prototypes) noexcept; - - Q_GUI_EXPORT void load(); - -private: - Status m_status; - QIODevice *m_device; - QHash<QString, QShaderNode> m_prototypes; - QShaderGraph m_graph; -}; - -Q_DECLARE_TYPEINFO(QShaderGraphLoader, Q_RELOCATABLE_TYPE); - -QT_END_NAMESPACE - -Q_DECLARE_METATYPE(QShaderGraphLoader) -Q_DECLARE_METATYPE(QShaderGraphLoader::Status) - -#endif // QSHADERGRAPHLOADER_P_H diff --git a/src/gui/util/qshaderlanguage.cpp b/src/gui/util/qshaderlanguage.cpp deleted file mode 100644 index efd607ba60..0000000000 --- a/src/gui/util/qshaderlanguage.cpp +++ /dev/null @@ -1,54 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). -** 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$ -** -****************************************************************************/ - -#include "qshaderlanguage_p.h" - -#include <QtCore/qcoreapplication.h> - -QT_BEGIN_NAMESPACE - -// Note: to be invoked explicitly. Relying for example on -// Q_COREAPP_STARTUP_FUNCTION would not be acceptable in static builds. -void qt_register_ShaderLanguage_enums() -{ - qRegisterMetaType<QShaderLanguage::StorageQualifier>(); - qRegisterMetaType<QShaderLanguage::VariableType>(); -} - -QT_END_NAMESPACE diff --git a/src/gui/util/qshaderlanguage_p.h b/src/gui/util/qshaderlanguage_p.h deleted file mode 100644 index 193f797cc3..0000000000 --- a/src/gui/util/qshaderlanguage_p.h +++ /dev/null @@ -1,164 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). -** 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$ -** -****************************************************************************/ - -#ifndef QSHADERLANGUAGE_P_H -#define QSHADERLANGUAGE_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 <QtGui/private/qtguiglobal_p.h> - -#include <QtCore/qmetatype.h> - -QT_BEGIN_NAMESPACE - -namespace QShaderLanguage -{ - Q_NAMESPACE_EXPORT(Q_GUI_EXPORT) - - enum StorageQualifier : char { - Const = 1, - Input, - BuiltIn, - Output, - Uniform - }; - Q_ENUM_NS(StorageQualifier) - - enum VariableType : int { - Bool = 1, - Int, - Uint, - Float, - Double, - Vec2, - Vec3, - Vec4, - DVec2, - DVec3, - DVec4, - BVec2, - BVec3, - BVec4, - IVec2, - IVec3, - IVec4, - UVec2, - UVec3, - UVec4, - Mat2, - Mat3, - Mat4, - Mat2x2, - Mat2x3, - Mat2x4, - Mat3x2, - Mat3x3, - Mat3x4, - Mat4x2, - Mat4x3, - Mat4x4, - DMat2, - DMat3, - DMat4, - DMat2x2, - DMat2x3, - DMat2x4, - DMat3x2, - DMat3x3, - DMat3x4, - DMat4x2, - DMat4x3, - DMat4x4, - Sampler1D, - Sampler2D, - Sampler3D, - SamplerCube, - Sampler2DRect, - Sampler2DMs, - SamplerBuffer, - Sampler1DArray, - Sampler2DArray, - Sampler2DMsArray, - SamplerCubeArray, - Sampler1DShadow, - Sampler2DShadow, - Sampler2DRectShadow, - Sampler1DArrayShadow, - Sampler2DArrayShadow, - SamplerCubeShadow, - SamplerCubeArrayShadow, - ISampler1D, - ISampler2D, - ISampler3D, - ISamplerCube, - ISampler2DRect, - ISampler2DMs, - ISamplerBuffer, - ISampler1DArray, - ISampler2DArray, - ISampler2DMsArray, - ISamplerCubeArray, - USampler1D, - USampler2D, - USampler3D, - USamplerCube, - USampler2DRect, - USampler2DMs, - USamplerBuffer, - USampler1DArray, - USampler2DArray, - USampler2DMsArray, - USamplerCubeArray - }; - Q_ENUM_NS(VariableType) -} - -QT_END_NAMESPACE - -#endif // QSHADERLANGUAGE_P_H diff --git a/src/gui/util/qshadernode.cpp b/src/gui/util/qshadernode.cpp deleted file mode 100644 index 3e53c35037..0000000000 --- a/src/gui/util/qshadernode.cpp +++ /dev/null @@ -1,172 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). -** 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$ -** -****************************************************************************/ - -#include "qshadernode_p.h" - -QT_BEGIN_NAMESPACE - -QShaderNode::Type QShaderNode::type() const noexcept -{ - int inputCount = 0; - int outputCount = 0; - for (const auto &port : qAsConst(m_ports)) { - switch (port.direction) { - case QShaderNodePort::Input: - inputCount++; - break; - case QShaderNodePort::Output: - outputCount++; - break; - } - } - - return (inputCount == 0 && outputCount == 0) ? Invalid - : (inputCount > 0 && outputCount == 0) ? Output - : (inputCount == 0 && outputCount > 0) ? Input - : Function; -} - -QUuid QShaderNode::uuid() const noexcept -{ - return m_uuid; -} - -void QShaderNode::setUuid(const QUuid &uuid) noexcept -{ - m_uuid = uuid; -} - -QStringList QShaderNode::layers() const noexcept -{ - return m_layers; -} - -void QShaderNode::setLayers(const QStringList &layers) noexcept -{ - m_layers = layers; -} - -QList<QShaderNodePort> QShaderNode::ports() const noexcept -{ - return m_ports; -} - -void QShaderNode::addPort(const QShaderNodePort &port) -{ - removePort(port); - m_ports.append(port); -} - -void QShaderNode::removePort(const QShaderNodePort &port) -{ - const auto it = std::find_if(m_ports.begin(), m_ports.end(), - [port](const QShaderNodePort &p) { - return p.name == port.name; - }); - if (it != m_ports.end()) - m_ports.erase(it); -} - -QStringList QShaderNode::parameterNames() const -{ - return m_parameters.keys(); -} - -QVariant QShaderNode::parameter(const QString &name) const -{ - return m_parameters.value(name); -} - -void QShaderNode::setParameter(const QString &name, const QVariant &value) -{ - m_parameters.insert(name, value); -} - -void QShaderNode::clearParameter(const QString &name) -{ - m_parameters.remove(name); -} - -void QShaderNode::addRule(const QShaderFormat &format, const QShaderNode::Rule &rule) -{ - removeRule(format); - m_rules << qMakePair(format, rule); -} - -void QShaderNode::removeRule(const QShaderFormat &format) -{ - const auto it = std::find_if(m_rules.begin(), m_rules.end(), - [format](const QPair<QShaderFormat, Rule> &entry) { - return entry.first == format; - }); - if (it != m_rules.end()) - m_rules.erase(it); -} - -QList<QShaderFormat> QShaderNode::availableFormats() const -{ - auto res = QList<QShaderFormat>(); - std::transform(m_rules.cbegin(), m_rules.cend(), - std::back_inserter(res), - [](const QPair<QShaderFormat, Rule> &entry) { return entry.first; }); - return res; -} - -QShaderNode::Rule QShaderNode::rule(const QShaderFormat &format) const -{ - const auto it = std::find_if(m_rules.crbegin(), m_rules.crend(), - [format](const QPair<QShaderFormat, Rule> &entry) { - return format.supports(entry.first); - }); - return it != m_rules.crend() ? it->second : Rule(); -} - -QShaderNode::Rule::Rule(const QByteArray &subs, const QByteArrayList &snippets) noexcept - : substitution(subs), - headerSnippets(snippets) -{ -} - -bool operator==(const QShaderNode::Rule &lhs, const QShaderNode::Rule &rhs) noexcept -{ - return lhs.substitution == rhs.substitution - && lhs.headerSnippets == rhs.headerSnippets; -} - -QT_END_NAMESPACE diff --git a/src/gui/util/qshadernode_p.h b/src/gui/util/qshadernode_p.h deleted file mode 100644 index 303a404165..0000000000 --- a/src/gui/util/qshadernode_p.h +++ /dev/null @@ -1,128 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). -** 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$ -** -****************************************************************************/ - -#ifndef QSHADERNODE_P_H -#define QSHADERNODE_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 <QtGui/private/qtguiglobal_p.h> - -#include <QtGui/private/qshaderformat_p.h> -#include <QtGui/private/qshadernodeport_p.h> - -#include <QtCore/quuid.h> - -QT_BEGIN_NAMESPACE - -class QShaderNode -{ -public: - enum Type : char { - Invalid, - Input, - Output, - Function - }; - - class Rule - { - public: - Q_GUI_EXPORT Rule(const QByteArray &substitution = QByteArray(), const QByteArrayList &headerSnippets = QByteArrayList()) noexcept; - - QByteArray substitution; - QByteArrayList headerSnippets; - }; - - Q_GUI_EXPORT Type type() const noexcept; - - Q_GUI_EXPORT QUuid uuid() const noexcept; - Q_GUI_EXPORT void setUuid(const QUuid &uuid) noexcept; - - Q_GUI_EXPORT QStringList layers() const noexcept; - Q_GUI_EXPORT void setLayers(const QStringList &layers) noexcept; - - Q_GUI_EXPORT QList<QShaderNodePort> ports() const noexcept; - Q_GUI_EXPORT void addPort(const QShaderNodePort &port); - Q_GUI_EXPORT void removePort(const QShaderNodePort &port); - - Q_GUI_EXPORT QStringList parameterNames() const; - Q_GUI_EXPORT QVariant parameter(const QString &name) const; - Q_GUI_EXPORT void setParameter(const QString &name, const QVariant &value); - Q_GUI_EXPORT void clearParameter(const QString &name); - - Q_GUI_EXPORT void addRule(const QShaderFormat &format, const Rule &rule); - Q_GUI_EXPORT void removeRule(const QShaderFormat &format); - - Q_GUI_EXPORT QList<QShaderFormat> availableFormats() const; - Q_GUI_EXPORT Rule rule(const QShaderFormat &format) const; - -private: - QUuid m_uuid; - QStringList m_layers; - QList<QShaderNodePort> m_ports; - QHash<QString, QVariant> m_parameters; - QList<QPair<QShaderFormat, QShaderNode::Rule>> m_rules; -}; - -Q_GUI_EXPORT bool operator==(const QShaderNode::Rule &lhs, const QShaderNode::Rule &rhs) noexcept; - -inline bool operator!=(const QShaderNode::Rule &lhs, const QShaderNode::Rule &rhs) noexcept -{ - return !(lhs == rhs); -} - -Q_DECLARE_TYPEINFO(QShaderNode, Q_RELOCATABLE_TYPE); -Q_DECLARE_TYPEINFO(QShaderNode::Rule, Q_RELOCATABLE_TYPE); - -QT_END_NAMESPACE - -Q_DECLARE_METATYPE(QShaderNode) -Q_DECLARE_METATYPE(QShaderNode::Rule) - -#endif // QSHADERNODE_P_H diff --git a/src/gui/util/qshadernodeport.cpp b/src/gui/util/qshadernodeport.cpp deleted file mode 100644 index 15dbc4160e..0000000000 --- a/src/gui/util/qshadernodeport.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). -** 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$ -** -****************************************************************************/ - -#include "qshadernodeport_p.h" - -QT_BEGIN_NAMESPACE - -QShaderNodePort::QShaderNodePort() noexcept - : direction(Output) -{ -} - -bool operator==(const QShaderNodePort &lhs, const QShaderNodePort &rhs) noexcept -{ - return lhs.direction == rhs.direction - && lhs.name == rhs.name; -} - -QT_END_NAMESPACE diff --git a/src/gui/util/qshadernodeport_p.h b/src/gui/util/qshadernodeport_p.h deleted file mode 100644 index e4e11f6826..0000000000 --- a/src/gui/util/qshadernodeport_p.h +++ /dev/null @@ -1,88 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). -** 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$ -** -****************************************************************************/ - -#ifndef QSHADERNODEPORT_P_H -#define QSHADERNODEPORT_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 <QtGui/private/qtguiglobal_p.h> - -#include <QtCore/qstring.h> -#include <QtCore/qvariant.h> - -QT_BEGIN_NAMESPACE - -class QShaderNodePort -{ -public: - enum Direction : char { - Input, - Output - }; - - Q_GUI_EXPORT QShaderNodePort() noexcept; - - QShaderNodePort::Direction direction; - QString name; -}; - -Q_GUI_EXPORT bool operator==(const QShaderNodePort &lhs, const QShaderNodePort &rhs) noexcept; - -inline bool operator!=(const QShaderNodePort &lhs, const QShaderNodePort &rhs) noexcept -{ - return !(lhs == rhs); -} - -Q_DECLARE_TYPEINFO(QShaderNodePort, Q_RELOCATABLE_TYPE); - -QT_END_NAMESPACE - -Q_DECLARE_METATYPE(QShaderNodePort) - -#endif // QSHADERNODEPORT_P_H diff --git a/src/gui/util/qshadernodesloader.cpp b/src/gui/util/qshadernodesloader.cpp deleted file mode 100644 index db1755e33a..0000000000 --- a/src/gui/util/qshadernodesloader.cpp +++ /dev/null @@ -1,290 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). -** 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$ -** -****************************************************************************/ - -#include "qshadernodesloader_p.h" - -#include <QtCore/qdebug.h> -#include <QtCore/qiodevice.h> -#include <QtCore/qjsonarray.h> -#include <QtCore/qjsondocument.h> -#include <QtCore/qjsonobject.h> -#include <QtCore/qmetaobject.h> - -QT_BEGIN_NAMESPACE - -QShaderNodesLoader::QShaderNodesLoader() noexcept - : m_status(Null), - m_device(nullptr) -{ -} - -QShaderNodesLoader::Status QShaderNodesLoader::status() const noexcept -{ - return m_status; -} - -QHash<QString, QShaderNode> QShaderNodesLoader::nodes() const noexcept -{ - return m_nodes; -} - -QIODevice *QShaderNodesLoader::device() const noexcept -{ - return m_device; -} - -void QShaderNodesLoader::setDevice(QIODevice *device) noexcept -{ - m_device = device; - m_nodes.clear(); - m_status = !m_device ? Null - : (m_device->openMode() & QIODevice::ReadOnly) ? Waiting - : Error; -} - -void QShaderNodesLoader::load() -{ - if (m_status == Error) - return; - - auto error = QJsonParseError(); - const QJsonDocument document = QJsonDocument::fromJson(m_device->readAll(), &error); - - if (error.error != QJsonParseError::NoError) { - qWarning() << "Invalid JSON document:" << error.errorString(); - m_status = Error; - return; - } - - if (document.isEmpty() || !document.isObject()) { - qWarning() << "Invalid JSON document, root should be an object"; - m_status = Error; - return; - } - - const QJsonObject root = document.object(); - load(root); -} - -void QShaderNodesLoader::load(const QJsonObject &prototypesObject) -{ - bool hasError = false; - - for (const QString &property : prototypesObject.keys()) { - const QJsonValue nodeValue = prototypesObject.value(property); - if (!nodeValue.isObject()) { - qWarning() << "Invalid node found"; - hasError = true; - break; - } - - const QJsonObject nodeObject = nodeValue.toObject(); - - auto node = QShaderNode(); - - const QJsonValue inputsValue = nodeObject.value(QStringLiteral("inputs")); - if (inputsValue.isArray()) { - const QJsonArray inputsArray = inputsValue.toArray(); - for (const QJsonValue inputValue : inputsArray) { - if (!inputValue.isString()) { - qWarning() << "Non-string value in inputs"; - hasError = true; - break; - } - - auto input = QShaderNodePort(); - input.direction = QShaderNodePort::Input; - input.name = inputValue.toString(); - node.addPort(input); - } - } - - const QJsonValue outputsValue = nodeObject.value(QStringLiteral("outputs")); - if (outputsValue.isArray()) { - const QJsonArray outputsArray = outputsValue.toArray(); - for (const QJsonValue outputValue : outputsArray) { - if (!outputValue.isString()) { - qWarning() << "Non-string value in outputs"; - hasError = true; - break; - } - - auto output = QShaderNodePort(); - output.direction = QShaderNodePort::Output; - output.name = outputValue.toString(); - node.addPort(output); - } - } - - const QJsonValue parametersValue = nodeObject.value(QStringLiteral("parameters")); - if (parametersValue.isObject()) { - const QJsonObject parametersObject = parametersValue.toObject(); - for (const QString ¶meterName : parametersObject.keys()) { - const QJsonValue parameterValue = parametersObject.value(parameterName); - if (parameterValue.isObject()) { - const QJsonObject parameterObject = parameterValue.toObject(); - const QString type = parameterObject.value(QStringLiteral("type")).toString(); - const auto metaType = QMetaType::fromName(type.toUtf8()); - - const QString value = parameterObject.value(QStringLiteral("value")).toString(); - auto variant = QVariant(value); - - if (metaType.flags() & QMetaType::IsEnumeration) { - const QMetaObject *metaObject = metaType.metaObject(); - const char *className = metaObject->className(); - const QByteArray enumName = type.mid(static_cast<int>(qstrlen(className)) + 2).toUtf8(); - const QMetaEnum metaEnum = metaObject->enumerator(metaObject->indexOfEnumerator(enumName)); - const int enumValue = metaEnum.keyToValue(value.toUtf8()); - variant = QVariant(enumValue); - variant.convert(metaType); - } else { - variant.convert(metaType); - } - node.setParameter(parameterName, variant); - } else { - node.setParameter(parameterName, parameterValue.toVariant()); - } - } - } - - const QJsonValue rulesValue = nodeObject.value(QStringLiteral("rules")); - if (rulesValue.isArray()) { - const QJsonArray rulesArray = rulesValue.toArray(); - for (const QJsonValue ruleValue : rulesArray) { - if (!ruleValue.isObject()) { - qWarning() << "Rules should be objects"; - hasError = true; - break; - } - - const QJsonObject ruleObject = ruleValue.toObject(); - - const QJsonValue formatValue = ruleObject.value(QStringLiteral("format")); - if (!formatValue.isObject()) { - qWarning() << "Format is mandatory in rules and should be an object"; - hasError = true; - break; - } - - const QJsonObject formatObject = formatValue.toObject(); - auto format = QShaderFormat(); - - const QJsonValue apiValue = formatObject.value(QStringLiteral("api")); - if (!apiValue.isString()) { - qWarning() << "Format API must be a string"; - hasError = true; - break; - } - - const QString api = apiValue.toString(); - format.setApi(api == QStringLiteral("OpenGLES") ? QShaderFormat::OpenGLES - : api == QStringLiteral("OpenGLNoProfile") ? QShaderFormat::OpenGLNoProfile - : api == QStringLiteral("OpenGLCoreProfile") ? QShaderFormat::OpenGLCoreProfile - : api == QStringLiteral("OpenGLCompatibilityProfile") ? QShaderFormat::OpenGLCompatibilityProfile - : api == QStringLiteral("VulkanFlavoredGLSL") ? QShaderFormat::VulkanFlavoredGLSL - : QShaderFormat::NoApi); - if (format.api() == QShaderFormat::NoApi) { - qWarning() << "Format API must be one of: OpenGLES, OpenGLNoProfile, OpenGLCoreProfile or OpenGLCompatibilityProfile, VulkanFlavoredGLSL"; - hasError = true; - break; - } - - const QJsonValue majorValue = formatObject.value(QStringLiteral("major")); - const QJsonValue minorValue = formatObject.value(QStringLiteral("minor")); - if (!majorValue.isDouble() || !minorValue.isDouble()) { - qWarning() << "Format major and minor version must be values"; - hasError = true; - break; - } - format.setVersion(QVersionNumber(majorValue.toInt(), minorValue.toInt())); - - const QJsonValue extensionsValue = formatObject.value(QStringLiteral("extensions")); - const QJsonArray extensionsArray = extensionsValue.toArray(); - auto extensions = QStringList(); - std::transform(extensionsArray.constBegin(), extensionsArray.constEnd(), - std::back_inserter(extensions), - [] (const QJsonValue &extensionValue) { return extensionValue.toString(); }); - format.setExtensions(extensions); - - const QString vendor = formatObject.value(QStringLiteral("vendor")).toString(); - format.setVendor(vendor); - - const QJsonValue substitutionValue = ruleObject.value(QStringLiteral("substitution")); - if (!substitutionValue.isString()) { - qWarning() << "Substitution needs to be a string"; - hasError = true; - break; - } - - // We default out to a Fragment ShaderType if nothing is specified - // as that was the initial behavior we introduced - const QString shaderType = formatObject.value(QStringLiteral("shaderType")).toString(); - format.setShaderType(shaderType == QStringLiteral("Fragment") ? QShaderFormat::Fragment - : shaderType == QStringLiteral("Vertex") ? QShaderFormat::Vertex - : shaderType == QStringLiteral("TessellationControl") ? QShaderFormat::TessellationControl - : shaderType == QStringLiteral("TessellationEvaluation") ? QShaderFormat::TessellationEvaluation - : shaderType == QStringLiteral("Geometry") ? QShaderFormat::Geometry - : shaderType == QStringLiteral("Compute") ? QShaderFormat::Compute - : QShaderFormat::Fragment); - - const QByteArray substitution = substitutionValue.toString().toUtf8(); - - const QJsonValue snippetsValue = ruleObject.value(QStringLiteral("headerSnippets")); - const QJsonArray snippetsArray = snippetsValue.toArray(); - auto snippets = QByteArrayList(); - std::transform(snippetsArray.constBegin(), snippetsArray.constEnd(), - std::back_inserter(snippets), - [] (const QJsonValue &snippetValue) { return snippetValue.toString().toUtf8(); }); - - node.addRule(format, QShaderNode::Rule(substitution, snippets)); - } - } - - m_nodes.insert(property, node); - } - - if (hasError) { - m_status = Error; - m_nodes.clear(); - } else { - m_status = Ready; - } -} - -QT_END_NAMESPACE diff --git a/src/gui/util/qshadernodesloader_p.h b/src/gui/util/qshadernodesloader_p.h deleted file mode 100644 index 8afdd294ca..0000000000 --- a/src/gui/util/qshadernodesloader_p.h +++ /dev/null @@ -1,96 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). -** 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$ -** -****************************************************************************/ - -#ifndef QSHADERNODESLOADER_P_H -#define QSHADERNODESLOADER_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 <QtGui/private/qtguiglobal_p.h> - -#include <QtGui/private/qshadergraph_p.h> - -QT_BEGIN_NAMESPACE - -class QIODevice; - -class QShaderNodesLoader -{ -public: - enum Status : char { - Null, - Waiting, - Ready, - Error - }; - - Q_GUI_EXPORT QShaderNodesLoader() noexcept; - - Q_GUI_EXPORT Status status() const noexcept; - Q_GUI_EXPORT QHash<QString, QShaderNode> nodes() const noexcept; - - Q_GUI_EXPORT QIODevice *device() const noexcept; - Q_GUI_EXPORT void setDevice(QIODevice *device) noexcept; - - Q_GUI_EXPORT void load(); - Q_GUI_EXPORT void load(const QJsonObject &prototypesObject); - -private: - Status m_status; - QIODevice *m_device; - QHash<QString, QShaderNode> m_nodes; -}; - -Q_DECLARE_TYPEINFO(QShaderNodesLoader, Q_RELOCATABLE_TYPE); - -QT_END_NAMESPACE - -Q_DECLARE_METATYPE(QShaderNodesLoader) -Q_DECLARE_METATYPE(QShaderNodesLoader::Status) - -#endif // QSHADERNODESLOADER_P_H 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 |