From 5cf21bcc2750224ee79099ee643d2c3fc6d5753d Mon Sep 17 00:00:00 2001 From: Cyano Hao Date: Thu, 18 Jan 2024 10:43:10 +0800 Subject: [PATCH] Update Qt 5.6 build instruction and add to CI (#177) * update build instruction for legacy Windows * add CI build for windows legacy * merge mingw CI builds * merge deb CI builds * fix typo * bump qt 5.6 build --- .github/workflows/build.yml | 166 ++-- BUILD.md | 2 +- BUILD_cn.md | 2 +- packages/windows/build-qt5.6-mingw-static.sh | 200 +++-- packages/windows/qtbase-5.6.3-redpanda.patch | 856 ------------------- 5 files changed, 179 insertions(+), 1047 deletions(-) delete mode 100644 packages/windows/qtbase-5.6.3-redpanda.patch diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8d18b7c9..5566d348 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -3,8 +3,20 @@ name: Build on: [push, pull_request] jobs: - windows_mingw64: - name: Windows MSYS2 MINGW64 + windows: + name: Windows MSYS2 + strategy: + matrix: + msystem: [MINGW32, MINGW64, UCRT64, CLANG64] + include: + - msystem: MINGW32 + packagePrefix: mingw-w64-i686 + - msystem: MINGW64 + packagePrefix: mingw-w64-x86_64 + - msystem: UCRT64 + packagePrefix: mingw-w64-ucrt-x86_64 + - msystem: CLANG64 + packagePrefix: mingw-w64-clang-x86_64 runs-on: windows-latest defaults: run: @@ -16,9 +28,9 @@ jobs: - name: Setup uses: msys2/setup-msys2@v2 with: - msystem: MINGW64 + msystem: ${{ matrix.msystem }} update: true - install: mingw-w64-x86_64-toolchain mingw-w64-x86_64-qt5-static + install: ${{ matrix.packagePrefix }}-toolchain ${{ matrix.packagePrefix }}-qt5-static - name: Build run: | @@ -31,69 +43,59 @@ jobs: - name: Upload uses: actions/upload-artifact@v2 with: - name: Windows MSYS2 MINGW64 + name: Windows MSYS2 - msystem=${{ matrix.msystem }} path: pkg/ - windows_ucrt64: - name: Windows MSYS2 UCRT64 - runs-on: windows-latest + windows_legacy: + name: Windows NT 5.1–6.0 MinGW + strategy: + matrix: + arch: [32, 64] + runs-on: windows-2019 defaults: run: - shell: msys2 {0} + shell: bash + env: + _MINGW_TOOLCHAIN: /c/Qt/Tools/mingw810_${{ matrix.arch }} + _QT_INSTALL_PREFIX: /c/Qt/5.6.4/mingw81_${{ matrix.arch }}-redpanda + _REDPANDA_QT_BUILD: "20240116.0" + _REDPANDA_QT_ARCHIVE: qt5.6.4-mingw81_${{ matrix.arch }}-redpanda.7z steps: - uses: actions/checkout@v2 - - name: Setup - uses: msys2/setup-msys2@v2 + - name: Setup toolchain + uses: jurplel/install-qt-action@v3 with: - msystem: UCRT64 - update: true - install: mingw-w64-ucrt-x86_64-toolchain mingw-w64-ucrt-x86_64-qt5-static + version: '5.15.2' + host: windows + target: desktop + arch: win${{ matrix.arch }}_mingw81 + archives: qtbase + tools: tools_mingw,qt.tools.win${{ matrix.arch }}_mingw810 + dir: C:/ + + - name: Setup Qt + run: | + curl -LO https://github.com/redpanda-cpp/qtbase-5.6/releases/download/$_REDPANDA_QT_BUILD/$_REDPANDA_QT_ARCHIVE + 7z x $_REDPANDA_QT_ARCHIVE -oC:/Qt - name: Build run: | + export PATH="$_QT_INSTALL_PREFIX/bin:$_MINGW_TOOLCHAIN/bin:$PATH" + mkdir build && pushd build - $MSYSTEM_PREFIX/qt5-static/bin/qmake PREFIX=$GITHUB_WORKSPACE/pkg $GITHUB_WORKSPACE/Red_Panda_CPP.pro - mingw32-make -j$(nproc) - mingw32-make install + { + qmake PREFIX=$GITHUB_WORKSPACE/pkg $GITHUB_WORKSPACE/Red_Panda_CPP.pro + mingw32-make -j$(nproc) + mingw32-make install + } popd - name: Upload uses: actions/upload-artifact@v2 with: - name: Windows MSYS2 UCRT64 - path: pkg/ - - windows_mingw32: - name: Windows MSYS2 MINGW32 - runs-on: windows-latest - defaults: - run: - shell: msys2 {0} - - steps: - - uses: actions/checkout@v2 - - - name: Setup - uses: msys2/setup-msys2@v2 - with: - msystem: MINGW32 - update: true - install: mingw-w64-i686-toolchain mingw-w64-i686-qt5-static - - - name: Build - run: | - mkdir build && pushd build - $MSYSTEM_PREFIX/qt5-static/bin/qmake PREFIX=$GITHUB_WORKSPACE/pkg $GITHUB_WORKSPACE/Red_Panda_CPP.pro - mingw32-make -j$(nproc) - mingw32-make install - popd - - - name: Upload - uses: actions/upload-artifact@v2 - with: - name: Windows MSYS2 MINGW32 + name: Windows NT 5.1–6.0 MinGW - arch=${{ matrix.arch }} path: pkg/ windows_msvc_x64: @@ -170,8 +172,22 @@ jobs: name: Windows MSVC ARM64EC (do not use) path: pkg/ - deb_oldest_lts: - name: Deb on oldest LTS (Debian 10) + deb: + name: Deb + strategy: + matrix: + image: + - "debian:10" # oldest LTS + - "ubuntu:23.10" # latest stable + - "debian:sid" # rolling + include: + - image: debian:10 + displayImage: debian-10 + - image: ubuntu:23.10 + displayImage: ubuntu-23.10 + - image: debian:sid + displayImage: debian-sid + runs-on: ubuntu-latest steps: @@ -179,58 +195,16 @@ jobs: - name: Fetch container image run: | - podman pull --platform linux/amd64 docker.io/amd64/debian:10 + podman pull --platform linux/amd64 docker.io/amd64/${{ matrix.image }} - name: Build run: | - podman run --rm -e SOURCE_DIR=/src -v $GITHUB_WORKSPACE:/src --platform linux/amd64 docker.io/amd64/debian:10 /src/packages/debian/01-in-docker.sh + podman run --rm -e SOURCE_DIR=/src -v $GITHUB_WORKSPACE:/src --platform linux/amd64 ${{ matrix.image }} /src/packages/debian/01-in-docker.sh - name: Upload uses: actions/upload-artifact@v2 with: - name: Deb on oldest LTS (Debian 10) - path: dist/*.deb - - deb_lastest_stable: - name: Deb on lastest stable (Ubuntu 23.10) - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v2 - - - name: Fetch container image - run: | - podman pull --platform linux/amd64 docker.io/amd64/ubuntu:23.10 - - - name: Build - run: | - podman run --rm -e SOURCE_DIR=/src -v $GITHUB_WORKSPACE:/src --platform linux/amd64 docker.io/amd64/ubuntu:23.10 /src/packages/debian/01-in-docker.sh - - - name: Upload - uses: actions/upload-artifact@v2 - with: - name: Deb on lastest stable (Ubuntu 23.10) - path: dist/*.deb - - deb_rolling: - name: Deb on rolling (Debian sid) - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v2 - - - name: Fetch container image - run: | - podman pull --platform linux/amd64 docker.io/amd64/debian:sid - - - name: Build - run: | - podman run --rm -e SOURCE_DIR=/src -v $GITHUB_WORKSPACE:/src --platform linux/amd64 docker.io/amd64/debian:sid /src/packages/debian/01-in-docker.sh - - - name: Upload - uses: actions/upload-artifact@v2 - with: - name: Deb on rolling (Debian sid) + name: Deb - image=${{ matrix.displayImage }} path: dist/*.deb archlinux: diff --git a/BUILD.md b/BUILD.md index 1ee0b59b..cbb3c11b 100644 --- a/BUILD.md +++ b/BUILD.md @@ -88,7 +88,7 @@ For legacy Windows (NT 5.1 – 6.0): | Library + Toolchain \ Target | x86 | x64 | | ---------------------------- | --- | --- | -| Qt 5.6 from [patched source](packages/windows/qtbase-5.6.3-redpanda.patch) + MinGW | ✔️ | ✔️ | +| Qt 5.6 from [patched source](https://github.com/redpanda-cpp/qtbase-5.6) + MinGW | ✔️ | ✔️ | Notes for legacy Windows: - Supported Windows versions: diff --git a/BUILD_cn.md b/BUILD_cn.md index 3b36efb7..82707ba1 100644 --- a/BUILD_cn.md +++ b/BUILD_cn.md @@ -88,7 +88,7 @@ | 库 + 工具链 \ 目标 | x86 | x64 | | ------------------ | --- | --- | -| 从[打过补丁的源代码](packages/windows/qtbase-5.6.3-redpanda.patch)构建的 Qt 5.6 + MinGW | ✔️ | ✔️ | +| 从[打过补丁的源代码](https://github.com/redpanda-cpp/qtbase-5.6)构建的 Qt 5.6 + MinGW | ✔️ | ✔️ | 关于旧版 Windows 的注记: - 支持的 Windows 版本: diff --git a/packages/windows/build-qt5.6-mingw-static.sh b/packages/windows/build-qt5.6-mingw-static.sh index 40df7c1d..72094517 100644 --- a/packages/windows/build-qt5.6-mingw-static.sh +++ b/packages/windows/build-qt5.6-mingw-static.sh @@ -1,113 +1,127 @@ # for Git Bash -set -xe +# Usage: +# ./build-qt5.6-mingw-static.sh --arch <32|64> [--debug] [--official-qt-dir ] -QT_CONFIGURE_DEBUG_OR_RELEASE="-release" -OFFICIAL_QT_DIRECTORY="/c/Qt" -QT_INSTALL_PREFIX="/c/Qt/5.6.3" +set -euo pipefail -qt-module-directory() { - moduleName="$1" - echo "qt$moduleName-opensource-src-5.6.3" +_ARCH="" +_CLEAN=0 +_DEBUG=0 +_OFFICIAL_QT_DIR="/c/Qt" +while [[ $# -gt 0 ]] ; do + case "$1" in + --arch) + _ARCH="$2" + shift + shift + ;; + --clean) + _CLEAN=1 + shift + ;; + --debug) + _DEBUG=1 + shift + ;; + --official-qt-dir) + _OFFICIAL_QT_DIR="$2" + shift + shift + ;; + *) + echo "Unknown option: $1" + exit 1 + ;; + esac +done + +case "$_ARCH" in + 32|64) + _MINGW_TOOLCHAIN="$_OFFICIAL_QT_DIR/Tools/mingw810_$_ARCH" + _QT_INSTALL_PREFIX="$_OFFICIAL_QT_DIR/5.6.4/mingw81_$_ARCH-redpanda" + ;; + *) + echo "Please specify --arch 32 or --arch 64" + exit 1 + ;; +esac + +if [[ $_DEBUG -eq 1 ]] ; then + _QT_CONFIGURE_DEBUG_OR_RELEASE=-debug-and-release +else + _QT_CONFIGURE_DEBUG_OR_RELEASE=-release +fi + +clean() { + rm -rf build-qt{base,svg,tools}-"$_ARCH" || true + rm -rf "$_QT_INSTALL_PREFIX" || true } -prepare-qt-base-source() { - moduleDirectory="$(qt-module-directory base)" - fileName="$moduleDirectory.tar.xz" - - if ! [[ -d "$moduleDirectory" ]] ; then - patchFileName="qtbase-5.6.3-redpanda.patch" - if ! [[ -f "$patchFileName" ]] ; then - echo -n "Patch file not found. Please copy it to this directory and press enter to continue..." - read -r - fi - if ! [[ -f "$fileName" ]] ; then - downloadUrl="https://download.qt.io/new_archive/qt/5.6/5.6.3/submodules/$fileName" - curl -L -o "$fileName" "$downloadUrl" - fi - tar xf "$fileName" - tar xf "$fileName" "$moduleDirectory/configure.exe" # workaround for MSYS2 tar bug: https://github.com/msys2/MSYS2-packages/issues/4103 - pushd "$moduleDirectory" - patch --forward --strip=1 --input="../$patchFileName" - popd +check-toolchain() { + if ! [[ -x "$_MINGW_TOOLCHAIN/bin/g++.exe" ]] ; then + echo "Please install MinGW 8.1 from Qt Maintenance Tool or download from https://download.qt.io/online/qtsdkrepository/windows_x86/desktop/tools_mingw/ or https://mirrors.ustc.edu.cn/qtproject/online/qtsdkrepository/windows_x86/desktop/tools_mingw/ and extract to $_OFFICAL_QT_DIR." + exit 1 fi } -prepare-qt-module-source() { - moduleName="$1" - moduleDirectory="$(qt-module-directory $moduleName)" - fileName="$moduleDirectory.tar.xz" - - if ! [[ -d "$moduleDirectory" ]] ; then - if ! [[ -f "$fileName" ]] ; then - downloadUrl="https://download.qt.io/new_archive/qt/5.6/5.6.3/submodules/$fileName" - curl -L -o "$fileName" "$downloadUrl" - fi - tar xf "$fileName" - fi -} - -prepare-qt-sources() { - prepare-qt-base-source - prepare-qt-module-source svg - prepare-qt-module-source tools +check-qt-sources() { + while ! [[ -d qtbase ]] ; do + echo "Please clone or link qtbase into this directory. e.g." + echo " git clone https://github.com/redpanda-cpp/qtbase-5.6.git --branch=5.6-redpanda --depth=1 qtbase" + echo " MSYS=winsymlinks:nativestrict ln -s /path/to/qtbase-5.6 qtbase" + echo "Press enter to continue..." + read + done + while ! [[ -d qtsvg ]] ; do + echo "Please clone or link qtsvg into this directory. e.g." + echo " git clone https://github.com/qt/qtsvg.git --branch=5.6 --depth=1" + echo "Press enter to continue..." + read + done + while ! [[ -d qttools ]] ; do + echo "Please clone or link qttools into this directory. e.g." + echo " git clone https://github.com/qt/qttools.git --branch=5.6 --depth=1" + echo "Press enter to continue..." + read + done } build-qt-base() { - configuration="$1" - - buildDir="build-qtbase-$configuration" - mkdir -p "$buildDir" - pushd "$buildDir" - - prefix="$QT_INSTALL_PREFIX/$configuration" - "../$(qt-module-directory base)/configure.bat" \ - -prefix $prefix $QT_CONFIGURE_DEBUG_OR_RELEASE \ - -opensource -confirm-license \ - -no-use-gold-linker -static -static-runtime -platform win32-g++ -target xp \ - -opengl desktop -no-angle -iconv -gnu-iconv -no-icu -qt-zlib -qt-pcre -qt-libpng -qt-libjpeg -qt-freetype -no-fontconfig -qt-harfbuzz -no-ssl -no-openssl \ - -nomake examples -nomake tests -nomake tools - mingw32-make "-j$(nproc)" - mingw32-make install - export PATH="$prefix/bin:$PATH" - + local build_dir="build-qtbase-$_ARCH" + mkdir -p "$build_dir" + pushd "$build_dir" + { + "../qtbase/configure.bat" \ + -prefix "$_QT_INSTALL_PREFIX" "$_QT_CONFIGURE_DEBUG_OR_RELEASE" \ + -opensource -confirm-license \ + -no-use-gold-linker -static -static-runtime -platform win32-g++ -target xp \ + -opengl desktop -no-angle -iconv -gnu-iconv -no-icu -qt-zlib -qt-pcre -qt-libpng -qt-libjpeg -qt-freetype -no-fontconfig -qt-harfbuzz -no-ssl -no-openssl \ + -nomake examples -nomake tests -nomake tools + mingw32-make "-j$(nproc)" + mingw32-make install + } popd } build-qt-module() { - configuration="$1" - moduleName="$2" - - buildDir="build-qt$moduleName-$configuration" - mkdir -p $buildDir - pushd $buildDir - - qmake "../$(qt-module-directory $moduleName)" - mingw32-make "-j$(nproc)" - mingw32-make install - + local module_name="$1" + local build_dir="build-qt$module_name-$_ARCH" + mkdir -p "$build_dir" + pushd "$build_dir" + { + qmake "../qt$module_name" + mingw32-make "-j$(nproc)" + mingw32-make install + } popd } -build-qt() { - configuration="$1" +export PATH="$_QT_INSTALL_PREFIX/bin:$_MINGW_TOOLCHAIN/bin:$PATH" - build-qt-base $configuration - build-qt-module $configuration svg - build-qt-module $configuration tools -} - -main() { - basePath="$PATH" - prepare-qt-sources - - ## 32-bit - export PATH="$OFFICIAL_QT_DIRECTORY/Tools/mingw810_32/bin:$basePath" - build-qt mingw81_32-redpanda - - ## 64-bit - export PATH="$OFFICIAL_QT_DIRECTORY/Tools/mingw810_64/bin:$basePath" - build-qt mingw81_64-redpanda -} - -main +[[ $_CLEAN -eq 1 ]] && clean +check-toolchain +check-qt-sources +build-qt-base +build-qt-module svg +build-qt-module tools diff --git a/packages/windows/qtbase-5.6.3-redpanda.patch b/packages/windows/qtbase-5.6.3-redpanda.patch deleted file mode 100644 index a21a9da8..00000000 --- a/packages/windows/qtbase-5.6.3-redpanda.patch +++ /dev/null @@ -1,856 +0,0 @@ -diff --unified --recursive --text qtbase-opensource-src-5.6.3.orig/src/corelib/global/qflags.h qtbase-opensource-src-5.6.3/src/corelib/global/qflags.h ---- qtbase-opensource-src-5.6.3.orig/src/corelib/global/qflags.h 2017-09-06 20:13:54.000000000 +0800 -+++ qtbase-opensource-src-5.6.3/src/corelib/global/qflags.h 2023-10-17 20:31:37.670315600 +0800 -@@ -139,6 +139,11 @@ - Q_DECL_CONSTEXPR inline bool operator!() const Q_DECL_NOTHROW { return !i; } - - Q_DECL_CONSTEXPR inline bool testFlag(Enum f) const Q_DECL_NOTHROW { return (i & Int(f)) == Int(f) && (Int(f) != 0 || i == Int(f) ); } -+ Q_DECL_RELAXED_CONSTEXPR inline QFlags &setFlag(Enum f, bool on = true) Q_DECL_NOTHROW -+ { -+ return on ? (*this |= f) : (*this &= ~Int(f)); -+ } -+ - private: - #ifdef Q_COMPILER_INITIALIZER_LISTS - Q_DECL_CONSTEXPR static inline Int initializer_list_helper(typename std::initializer_list::const_iterator it, -diff --unified --recursive --text qtbase-opensource-src-5.6.3.orig/src/corelib/global/qglobal.h qtbase-opensource-src-5.6.3/src/corelib/global/qglobal.h ---- qtbase-opensource-src-5.6.3.orig/src/corelib/global/qglobal.h 2017-09-06 20:13:54.000000000 +0800 -+++ qtbase-opensource-src-5.6.3/src/corelib/global/qglobal.h 2023-10-17 14:38:05.801809800 +0800 -@@ -67,6 +67,9 @@ - # define QT_NO_UNSHARABLE_CONTAINERS - #endif - -+// Red Panda C++: workaround. -+#define QT_CONFIG(feature) QT_SUPPORTS(feature) -+ - /* These two macros makes it possible to turn the builtin line expander into a - * string literal. */ - #define QT_STRINGIFY2(x) #x -@@ -1054,6 +1057,53 @@ - - #endif // QT_NO_TRANSLATION - -+template -+struct QNonConstOverload -+{ -+ template -+ Q_DECL_CONSTEXPR auto operator()(R (T::*ptr)(Args...)) const Q_DECL_NOTHROW -> decltype(ptr) -+ { return ptr; } -+ -+ template -+ static Q_DECL_CONSTEXPR auto of(R (T::*ptr)(Args...)) Q_DECL_NOTHROW -> decltype(ptr) -+ { return ptr; } -+}; -+ -+template -+struct QConstOverload -+{ -+ template -+ Q_DECL_CONSTEXPR auto operator()(R (T::*ptr)(Args...) const) const Q_DECL_NOTHROW -> decltype(ptr) -+ { return ptr; } -+ -+ template -+ static Q_DECL_CONSTEXPR auto of(R (T::*ptr)(Args...) const) Q_DECL_NOTHROW -> decltype(ptr) -+ { return ptr; } -+}; -+ -+template -+struct QOverload : QConstOverload, QNonConstOverload -+{ -+ using QConstOverload::of; -+ using QConstOverload::operator(); -+ using QNonConstOverload::of; -+ using QNonConstOverload::operator(); -+ -+ template -+ Q_DECL_CONSTEXPR auto operator()(R (*ptr)(Args...)) const Q_DECL_NOTHROW -> decltype(ptr) -+ { return ptr; } -+ -+ template -+ static Q_DECL_CONSTEXPR auto of(R (*ptr)(Args...)) Q_DECL_NOTHROW -> decltype(ptr) -+ { return ptr; } -+}; -+ -+#if defined(__cpp_variable_templates) && __cpp_variable_templates >= 201304 // C++14 -+template Q_CONSTEXPR Q_DECL_UNUSED QOverload qOverload = {}; -+template Q_CONSTEXPR Q_DECL_UNUSED QConstOverload qConstOverload = {}; -+template Q_CONSTEXPR Q_DECL_UNUSED QNonConstOverload qNonConstOverload = {}; -+#endif -+ - /* - When RTTI is not available, define this macro to force any uses of - dynamic_cast to cause a compile failure. -diff --unified --recursive --text qtbase-opensource-src-5.6.3.orig/src/corelib/global/qsystemdetection.h qtbase-opensource-src-5.6.3/src/corelib/global/qsystemdetection.h ---- qtbase-opensource-src-5.6.3.orig/src/corelib/global/qsystemdetection.h 2017-09-06 20:13:54.000000000 +0800 -+++ qtbase-opensource-src-5.6.3/src/corelib/global/qsystemdetection.h 2023-10-17 22:26:59.822029100 +0800 -@@ -184,6 +184,7 @@ - #endif - - #if defined(Q_OS_WIN32) || defined(Q_OS_WIN64) || defined(Q_OS_WINCE) || defined(Q_OS_WINRT) -+# define Q_OS_WINDOWS - # define Q_OS_WIN - #endif - -diff --unified --recursive --text qtbase-opensource-src-5.6.3.orig/src/corelib/io/qdir.cpp qtbase-opensource-src-5.6.3/src/corelib/io/qdir.cpp ---- qtbase-opensource-src-5.6.3.orig/src/corelib/io/qdir.cpp 2017-09-06 20:13:54.000000000 +0800 -+++ qtbase-opensource-src-5.6.3/src/corelib/io/qdir.cpp 2023-10-17 14:38:05.801809800 +0800 -@@ -1812,6 +1812,13 @@ - return QFile::exists(filePath(name)); - } - -+bool QDir::isEmpty(Filters filters) const -+{ -+ const auto d = d_ptr.constData(); -+ QDirIterator it(d->dirEntry.filePath(), d->nameFilters, filters); -+ return !it.hasNext(); -+} -+ - /*! - Returns a list of the root directories on this system. - -diff --unified --recursive --text qtbase-opensource-src-5.6.3.orig/src/corelib/io/qdir.h qtbase-opensource-src-5.6.3/src/corelib/io/qdir.h ---- qtbase-opensource-src-5.6.3.orig/src/corelib/io/qdir.h 2017-09-06 20:13:54.000000000 +0800 -+++ qtbase-opensource-src-5.6.3/src/corelib/io/qdir.h 2023-10-17 14:38:05.801809800 +0800 -@@ -138,6 +138,8 @@ - void setSorting(SortFlags sort); - - uint count() const; -+ bool isEmpty(Filters filters = Filters(AllEntries | NoDotAndDotDot)) const; -+ - QString operator[](int) const; - - static QStringList nameFiltersFromString(const QString &nameFilter); -diff --unified --recursive --text qtbase-opensource-src-5.6.3.orig/src/corelib/io/qprocess.cpp qtbase-opensource-src-5.6.3/src/corelib/io/qprocess.cpp ---- qtbase-opensource-src-5.6.3.orig/src/corelib/io/qprocess.cpp 2017-09-06 20:13:54.000000000 +0800 -+++ qtbase-opensource-src-5.6.3/src/corelib/io/qprocess.cpp 2023-10-18 09:11:02.546767400 +0800 -@@ -1535,6 +1535,18 @@ - d->nativeArguments = arguments; - } - -+QProcess::CreateProcessArgumentModifier QProcess::createProcessArgumentsModifier() const -+{ -+ Q_D(const QProcess); -+ return d->modifyCreateProcessArgs; -+} -+ -+void QProcess::setCreateProcessArgumentsModifier(CreateProcessArgumentModifier modifier) -+{ -+ Q_D(QProcess); -+ d->modifyCreateProcessArgs = modifier; -+} -+ - #endif - - /*! -@@ -2124,6 +2136,20 @@ - d->start(mode); - } - -+bool QProcess::startDetached(qint64 *pid) -+{ -+ Q_D(QProcess); -+ if (d->processState != NotRunning) { -+ qWarning("QProcess::startDetached: Process is already running"); -+ return false; -+ } -+ if (d->program.isEmpty()) { -+ d->setErrorAndEmit(QProcess::FailedToStart, tr("No program defined")); -+ return false; -+ } -+ return d->startDetached(pid); -+} -+ - /*! - Starts the program set by setProgram() with arguments set by setArguments(). - The OpenMode is set to \a mode. -diff --unified --recursive --text qtbase-opensource-src-5.6.3.orig/src/corelib/io/qprocess.h qtbase-opensource-src-5.6.3/src/corelib/io/qprocess.h ---- qtbase-opensource-src-5.6.3.orig/src/corelib/io/qprocess.h 2017-09-06 20:13:54.000000000 +0800 -+++ qtbase-opensource-src-5.6.3/src/corelib/io/qprocess.h 2023-10-18 09:09:01.053605200 +0800 -@@ -38,6 +38,8 @@ - #include - #include - -+#include -+ - QT_BEGIN_NAMESPACE - - -@@ -48,6 +50,8 @@ - #else - QT_END_NAMESPACE - typedef struct _PROCESS_INFORMATION *Q_PID; -+typedef struct _SECURITY_ATTRIBUTES Q_SECURITY_ATTRIBUTES; -+typedef struct _STARTUPINFOW Q_STARTUPINFO; - QT_BEGIN_NAMESPACE - #endif - -@@ -151,6 +155,7 @@ - void start(const QString &command, OpenMode mode = ReadWrite); - #endif - void start(OpenMode mode = ReadWrite); -+ bool startDetached(qint64 *pid = nullptr); - bool open(OpenMode mode = ReadWrite) Q_DECL_OVERRIDE; - - QString program() const; -@@ -180,6 +185,22 @@ - #if defined(Q_OS_WIN) - QString nativeArguments() const; - void setNativeArguments(const QString &arguments); -+ struct CreateProcessArguments -+ { -+ const wchar_t *applicationName; -+ wchar_t *arguments; -+ Q_SECURITY_ATTRIBUTES *processAttributes; -+ Q_SECURITY_ATTRIBUTES *threadAttributes; -+ bool inheritHandles; -+ unsigned long flags; -+ void *environment; -+ const wchar_t *currentDirectory; -+ Q_STARTUPINFO *startupInfo; -+ Q_PID processInformation; -+ }; -+ typedef std::function CreateProcessArgumentModifier; -+ CreateProcessArgumentModifier createProcessArgumentsModifier() const; -+ void setCreateProcessArgumentsModifier(CreateProcessArgumentModifier modifier); - #endif - - QString workingDirectory() const; -diff --unified --recursive --text qtbase-opensource-src-5.6.3.orig/src/corelib/io/qprocess_p.h qtbase-opensource-src-5.6.3/src/corelib/io/qprocess_p.h ---- qtbase-opensource-src-5.6.3.orig/src/corelib/io/qprocess_p.h 2017-09-06 20:13:54.000000000 +0800 -+++ qtbase-opensource-src-5.6.3/src/corelib/io/qprocess_p.h 2023-10-17 14:38:05.822849000 +0800 -@@ -326,6 +326,7 @@ - QStringList arguments; - #if defined(Q_OS_WIN) - QString nativeArguments; -+ QProcess::CreateProcessArgumentModifier modifyCreateProcessArgs; - #endif - QProcessEnvironment environment; - -@@ -355,6 +356,7 @@ - bool waitForDeadChild(); - #endif - #ifdef Q_OS_WIN -+ bool callCreateProcess(QProcess::CreateProcessArguments *cpargs); - bool drainOutputPipes(); - void flushPipeWriter(); - qint64 pipeWriterBytesToWrite() const; -@@ -363,6 +365,8 @@ - static bool startDetached(const QString &program, const QStringList &arguments, const QString &workingDirectory = QString(), - qint64 *pid = 0); - -+ bool startDetached(qint64 *pPid); -+ - int exitCode; - QProcess::ExitStatus exitStatus; - bool crashed; -diff --unified --recursive --text qtbase-opensource-src-5.6.3.orig/src/corelib/io/qprocess_win.cpp qtbase-opensource-src-5.6.3/src/corelib/io/qprocess_win.cpp ---- qtbase-opensource-src-5.6.3.orig/src/corelib/io/qprocess_win.cpp 2017-09-06 20:13:54.000000000 +0800 -+++ qtbase-opensource-src-5.6.3/src/corelib/io/qprocess_win.cpp 2023-10-18 09:15:27.039781400 +0800 -@@ -330,7 +330,8 @@ - destroyPipe(channel->pipe); - } - --static QString qt_create_commandline(const QString &program, const QStringList &arguments) -+static QString qt_create_commandline(const QString &program, const QStringList &arguments, -+ const QString &nativeArguments = QString()) - { - QString args; - if (!program.isEmpty()) { -@@ -359,6 +360,13 @@ - } - args += QLatin1Char(' ') + tmp; - } -+ -+ if (!nativeArguments.isEmpty()) { -+ if (!args.isEmpty()) -+ args += QLatin1Char(' '); -+ args += nativeArguments; -+ } -+ - return args; - } - -@@ -444,6 +452,30 @@ - return envlist; - } - -+bool QProcessPrivate::callCreateProcess(QProcess::CreateProcessArguments *cpargs) -+{ -+ if (modifyCreateProcessArgs) -+ modifyCreateProcessArgs(cpargs); -+ bool success = CreateProcess(cpargs->applicationName, cpargs->arguments, -+ cpargs->processAttributes, cpargs->threadAttributes, -+ cpargs->inheritHandles, cpargs->flags, cpargs->environment, -+ cpargs->currentDirectory, cpargs->startupInfo, -+ cpargs->processInformation); -+ if (stdinChannel.pipe[0] != INVALID_Q_PIPE) { -+ CloseHandle(stdinChannel.pipe[0]); -+ stdinChannel.pipe[0] = INVALID_Q_PIPE; -+ } -+ if (stdoutChannel.pipe[1] != INVALID_Q_PIPE) { -+ CloseHandle(stdoutChannel.pipe[1]); -+ stdoutChannel.pipe[1] = INVALID_Q_PIPE; -+ } -+ if (stderrChannel.pipe[1] != INVALID_Q_PIPE) { -+ CloseHandle(stderrChannel.pipe[1]); -+ stderrChannel.pipe[1] = INVALID_Q_PIPE; -+ } -+ return success; -+} -+ - void QProcessPrivate::startProcess() - { - Q_Q(QProcess); -@@ -498,11 +530,22 @@ - 0, 0, 0, - stdinChannel.pipe[0], stdoutChannel.pipe[1], stderrChannel.pipe[1] - }; -- success = CreateProcess(0, (wchar_t*)args.utf16(), -- 0, 0, TRUE, dwCreationFlags, -- environment.isEmpty() ? 0 : envlist.data(), -- workingDirectory.isEmpty() ? 0 : (wchar_t*)QDir::toNativeSeparators(workingDirectory).utf16(), -- &startupInfo, pid); -+ -+ const QString nativeWorkingDirectory = QDir::toNativeSeparators(workingDirectory); -+ QProcess::CreateProcessArguments cpargs = { -+ 0, (wchar_t*)args.utf16(), -+ 0, 0, TRUE, dwCreationFlags, -+ environment.isEmpty() ? 0 : envlist.data(), -+ nativeWorkingDirectory.isEmpty() ? Q_NULLPTR : (wchar_t*)nativeWorkingDirectory.utf16(), -+ &startupInfo, pid -+ }; -+ if (modifyCreateProcessArgs) -+ modifyCreateProcessArgs(&cpargs); -+ success = CreateProcess(cpargs.applicationName, cpargs.arguments, cpargs.processAttributes, -+ cpargs.threadAttributes, cpargs.inheritHandles, cpargs.flags, -+ cpargs.environment, cpargs.currentDirectory, cpargs.startupInfo, -+ cpargs.processInformation); -+ - QString errorString; - if (!success) { - // Capture the error string before we do CloseHandle below -@@ -818,6 +861,7 @@ - // Use ShellExecuteEx() to trigger an UAC prompt when CreateProcess()fails - // with ERROR_ELEVATION_REQUIRED. - static bool startDetachedUacPrompt(const QString &programIn, const QStringList &arguments, -+ const QString &nativeArguments, - const QString &workingDir, qint64 *pid) - { - typedef BOOL (WINAPI *ShellExecuteExType)(SHELLEXECUTEINFOW *); -@@ -828,11 +872,13 @@ - if (!shellExecuteEx) - return false; - -- const QString args = qt_create_commandline(QString(), arguments); // needs arguments only -+ const QString args = qt_create_commandline(QString(), // needs arguments only -+ arguments, nativeArguments); - SHELLEXECUTEINFOW shellExecuteExInfo; - memset(&shellExecuteExInfo, 0, sizeof(SHELLEXECUTEINFOW)); - shellExecuteExInfo.cbSize = sizeof(SHELLEXECUTEINFOW); -- shellExecuteExInfo.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_UNICODE | SEE_MASK_FLAG_NO_UI; -+ shellExecuteExInfo.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_UNICODE | SEE_MASK_FLAG_NO_UI | SEE_MASK_CLASSNAME; -+ shellExecuteExInfo.lpClass = L"exefile"; - shellExecuteExInfo.lpVerb = L"runas"; - const QString program = QDir::toNativeSeparators(programIn); - shellExecuteExInfo.lpFile = reinterpret_cast(program.utf16()); -@@ -850,6 +896,12 @@ - return true; - } - -+static bool startDetachedUacPrompt(const QString &programIn, const QStringList &arguments, -+ const QString &workingDir, qint64 *pid) -+{ -+ return startDetachedUacPrompt(programIn, arguments, QString(), workingDir, pid); -+} -+ - bool QProcessPrivate::startDetached(const QString &program, const QStringList &arguments, const QString &workingDir, qint64 *pid) - { - static const DWORD errorElevationRequired = 740; -@@ -880,6 +932,75 @@ - return success; - } - -+bool QProcessPrivate::startDetached(qint64 *pid) -+{ -+ static const DWORD errorElevationRequired = 740; -+ -+ if ((stdinChannel.type == Channel::Redirect && !openChannel(stdinChannel)) -+ || (stdoutChannel.type == Channel::Redirect && !openChannel(stdoutChannel)) -+ || (stderrChannel.type == Channel::Redirect && !openChannel(stderrChannel))) { -+ closeChannel(&stdinChannel); -+ closeChannel(&stdoutChannel); -+ closeChannel(&stderrChannel); -+ return false; -+ } -+ -+ QString args = qt_create_commandline(program, arguments, nativeArguments); -+ bool success = false; -+ PROCESS_INFORMATION pinfo; -+ -+ void *envPtr = nullptr; -+ QByteArray envlist; -+ if (environment.d.constData()) { -+ envlist = qt_create_environment(environment.d.constData()->hash); -+ envPtr = envlist.data(); -+ } -+ -+ DWORD dwCreationFlags = (GetConsoleWindow() ? 0 : CREATE_NO_WINDOW); -+ dwCreationFlags |= CREATE_UNICODE_ENVIRONMENT; -+ STARTUPINFOW startupInfo = { sizeof( STARTUPINFO ), 0, 0, 0, -+ (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT, -+ (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT, -+ 0, 0, 0, -+ STARTF_USESTDHANDLES, -+ 0, 0, 0, -+ stdinChannel.pipe[0], stdoutChannel.pipe[1], stderrChannel.pipe[1] -+ }; -+ -+ const bool inheritHandles = stdinChannel.type == Channel::Redirect -+ || stdoutChannel.type == Channel::Redirect -+ || stderrChannel.type == Channel::Redirect; -+ QProcess::CreateProcessArguments cpargs = { -+ nullptr, reinterpret_cast(const_cast(args.utf16())), -+ nullptr, nullptr, inheritHandles, dwCreationFlags, envPtr, -+ workingDirectory.isEmpty() -+ ? nullptr : reinterpret_cast(workingDirectory.utf16()), -+ &startupInfo, &pinfo -+ }; -+ success = callCreateProcess(&cpargs); -+ -+ if (success) { -+ CloseHandle(pinfo.hThread); -+ CloseHandle(pinfo.hProcess); -+ if (pid) -+ *pid = pinfo.dwProcessId; -+ } else if (GetLastError() == errorElevationRequired) { -+ if (envPtr) -+ qWarning("QProcess: custom environment will be ignored for detached elevated process."); -+ if (!stdinChannel.file.isEmpty() || !stdoutChannel.file.isEmpty() -+ || !stderrChannel.file.isEmpty()) { -+ qWarning("QProcess: file redirection is unsupported for detached elevated processes."); -+ } -+ success = startDetachedUacPrompt(program, arguments, nativeArguments, -+ workingDirectory, pid); -+ } -+ -+ closeChannel(&stdinChannel); -+ closeChannel(&stdoutChannel); -+ closeChannel(&stderrChannel); -+ return success; -+} -+ - QT_END_NAMESPACE - - #endif // QT_NO_PROCESS -diff --unified --recursive --text qtbase-opensource-src-5.6.3.orig/src/corelib/plugin/quuid.cpp qtbase-opensource-src-5.6.3/src/corelib/plugin/quuid.cpp ---- qtbase-opensource-src-5.6.3.orig/src/corelib/plugin/quuid.cpp 2017-09-06 20:13:54.000000000 +0800 -+++ qtbase-opensource-src-5.6.3/src/corelib/plugin/quuid.cpp 2023-10-17 14:38:05.822849000 +0800 -@@ -43,6 +43,8 @@ - #endif - QT_BEGIN_NAMESPACE - -+enum { MaxStringUuidLength = 38 }; -+ - template - void _q_toHex(Char *&dst, Integral value) - { -@@ -91,6 +93,30 @@ - *dst = Char('}'); - } - -+static char *_q_uuidToHex(const QUuid &uuid, char *dst, QUuid::StringFormat mode = QUuid::WithBraces) -+{ -+ if ((mode & QUuid::WithoutBraces) == 0) -+ *dst++ = '{'; -+ _q_toHex(dst, uuid.data1); -+ if ((mode & QUuid::Id128) != QUuid::Id128) -+ *dst++ = '-'; -+ _q_toHex(dst, uuid.data2); -+ if ((mode & QUuid::Id128) != QUuid::Id128) -+ *dst++ = '-'; -+ _q_toHex(dst, uuid.data3); -+ if ((mode & QUuid::Id128) != QUuid::Id128) -+ *dst++ = '-'; -+ for (int i = 0; i < 2; i++) -+ _q_toHex(dst, uuid.data4[i]); -+ if ((mode & QUuid::Id128) != QUuid::Id128) -+ *dst++ = '-'; -+ for (int i = 2; i < 8; i++) -+ _q_toHex(dst, uuid.data4[i]); -+ if ((mode & QUuid::WithoutBraces) == 0) -+ *dst++ = '}'; -+ return dst; -+} -+ - template - bool _q_uuidFromHex(const Char *&src, uint &d1, ushort &d2, ushort &d3, uchar (&d4)[8]) - { -@@ -550,6 +576,13 @@ - return result; - } - -+QString QUuid::toString(QUuid::StringFormat mode) const -+{ -+ char latin1[MaxStringUuidLength]; -+ const auto end = _q_uuidToHex(*this, latin1, mode); -+ return QString::fromLatin1(latin1, end - latin1); -+} -+ - /*! - Returns the binary representation of this QUuid. The byte array is - formatted as five hex fields separated by '-' and enclosed in -diff --unified --recursive --text qtbase-opensource-src-5.6.3.orig/src/corelib/plugin/quuid.h qtbase-opensource-src-5.6.3/src/corelib/plugin/quuid.h ---- qtbase-opensource-src-5.6.3.orig/src/corelib/plugin/quuid.h 2017-09-06 20:13:54.000000000 +0800 -+++ qtbase-opensource-src-5.6.3/src/corelib/plugin/quuid.h 2023-10-17 14:38:05.838486200 +0800 -@@ -74,6 +74,12 @@ - Sha1 = 5 // 0 1 0 1 - }; - -+ enum StringFormat { -+ WithBraces = 0, -+ WithoutBraces = 1, -+ Id128 = 3 -+ }; -+ - #if defined(Q_COMPILER_UNIFORM_INIT) && !defined(Q_QDOC) - Q_DECL_CONSTEXPR QUuid() Q_DECL_NOTHROW : data1(0), data2(0), data3(0), data4{0,0,0,0,0,0,0,0} {} - -@@ -108,6 +114,7 @@ - QUuid(const QString &); - QUuid(const char *); - QString toString() const; -+ QString toString(StringFormat mode) const; - QUuid(const QByteArray &); - QByteArray toByteArray() const; - QByteArray toRfc4122() const; -diff --unified --recursive --text qtbase-opensource-src-5.6.3.orig/src/corelib/tools/qchar.h qtbase-opensource-src-5.6.3/src/corelib/tools/qchar.h ---- qtbase-opensource-src-5.6.3.orig/src/corelib/tools/qchar.h 2017-09-06 20:13:54.000000000 +0800 -+++ qtbase-opensource-src-5.6.3/src/corelib/tools/qchar.h 2023-10-17 14:38:05.838486200 +0800 -@@ -572,6 +572,21 @@ - Q_DECL_CONSTEXPR inline bool operator> (QChar c1, QChar c2) { return operator< (c2, c1); } - Q_DECL_CONSTEXPR inline bool operator<=(QChar c1, QChar c2) { return !operator< (c2, c1); } - -+Q_DECL_CONSTEXPR inline bool operator==(QChar lhs, std::nullptr_t) Q_DECL_NOTHROW { return lhs.isNull(); } -+Q_DECL_CONSTEXPR inline bool operator< (QChar, std::nullptr_t) Q_DECL_NOTHROW { return false; } -+Q_DECL_CONSTEXPR inline bool operator==(std::nullptr_t, QChar rhs) Q_DECL_NOTHROW { return rhs.isNull(); } -+Q_DECL_CONSTEXPR inline bool operator< (std::nullptr_t, QChar rhs) Q_DECL_NOTHROW { return !rhs.isNull(); } -+ -+Q_DECL_CONSTEXPR inline bool operator!=(QChar lhs, std::nullptr_t) Q_DECL_NOTHROW { return !operator==(lhs, nullptr); } -+Q_DECL_CONSTEXPR inline bool operator>=(QChar lhs, std::nullptr_t) Q_DECL_NOTHROW { return !operator< (lhs, nullptr); } -+Q_DECL_CONSTEXPR inline bool operator> (QChar lhs, std::nullptr_t) Q_DECL_NOTHROW { return operator< (nullptr, lhs); } -+Q_DECL_CONSTEXPR inline bool operator<=(QChar lhs, std::nullptr_t) Q_DECL_NOTHROW { return !operator< (nullptr, lhs); } -+ -+Q_DECL_CONSTEXPR inline bool operator!=(std::nullptr_t, QChar rhs) Q_DECL_NOTHROW { return !operator==(nullptr, rhs); } -+Q_DECL_CONSTEXPR inline bool operator>=(std::nullptr_t, QChar rhs) Q_DECL_NOTHROW { return !operator< (nullptr, rhs); } -+Q_DECL_CONSTEXPR inline bool operator> (std::nullptr_t, QChar rhs) Q_DECL_NOTHROW { return operator< (rhs, nullptr); } -+Q_DECL_CONSTEXPR inline bool operator<=(std::nullptr_t, QChar rhs) Q_DECL_NOTHROW { return !operator< (rhs, nullptr); } -+ - #ifndef QT_NO_DATASTREAM - Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, QChar); - Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QChar &); -diff --unified --recursive --text qtbase-opensource-src-5.6.3.orig/src/corelib/tools/qdatetime.cpp qtbase-opensource-src-5.6.3/src/corelib/tools/qdatetime.cpp ---- qtbase-opensource-src-5.6.3.orig/src/corelib/tools/qdatetime.cpp 2017-09-06 20:13:54.000000000 +0800 -+++ qtbase-opensource-src-5.6.3/src/corelib/tools/qdatetime.cpp 2023-10-17 14:38:05.838486200 +0800 -@@ -4135,6 +4135,17 @@ - - julianDayFromDate(1970, 1, 1)) * Q_INT64_C(86400000); - } - -+qint64 QDateTime::currentSecsSinceEpoch() Q_DECL_NOTHROW -+{ -+ SYSTEMTIME st; -+ memset(&st, 0, sizeof(SYSTEMTIME)); -+ GetSystemTime(&st); -+ -+ return st.wHour * SECS_PER_HOUR + st.wMinute * SECS_PER_MIN + st.wSecond + -+ qint64(julianDayFromDate(st.wYear, st.wMonth, st.wDay) -+ - julianDayFromDate(1970, 1, 1)) * Q_INT64_C(86400); -+} -+ - #elif defined(Q_OS_UNIX) - QDate QDate::currentDate() - { -diff --unified --recursive --text qtbase-opensource-src-5.6.3.orig/src/corelib/tools/qdatetime.h qtbase-opensource-src-5.6.3/src/corelib/tools/qdatetime.h ---- qtbase-opensource-src-5.6.3.orig/src/corelib/tools/qdatetime.h 2017-09-06 20:13:54.000000000 +0800 -+++ qtbase-opensource-src-5.6.3/src/corelib/tools/qdatetime.h 2023-10-17 14:38:05.838486200 +0800 -@@ -312,6 +312,7 @@ - static QDateTime fromMSecsSinceEpoch(qint64 msecs, const QTimeZone &timeZone); - #endif - static qint64 currentMSecsSinceEpoch() Q_DECL_NOTHROW; -+ static qint64 currentSecsSinceEpoch() Q_DECL_NOTHROW; - - #if defined(Q_OS_MAC) || defined(Q_QDOC) - static QDateTime fromCFDate(CFDateRef date); -diff --unified --recursive --text qtbase-opensource-src-5.6.3.orig/src/corelib/tools/qlocale.cpp qtbase-opensource-src-5.6.3/src/corelib/tools/qlocale.cpp ---- qtbase-opensource-src-5.6.3.orig/src/corelib/tools/qlocale.cpp 2017-09-06 20:13:54.000000000 +0800 -+++ qtbase-opensource-src-5.6.3/src/corelib/tools/qlocale.cpp 2023-10-17 14:38:05.854106100 +0800 -@@ -3526,6 +3526,48 @@ - return format.arg(str, sym); - } - -+QString QLocale::formattedDataSize(qint64 bytes, int precision, DataSizeFormats format) -+{ -+ int power, base = 1000; -+ if (!bytes) { -+ power = 0; -+ } else if (format & DataSizeBase1000) { -+ power = int(std::log10(qAbs(bytes)) / 3); -+ } else { // Compute log2(bytes) / 10: -+ power = int((63 - qCountLeadingZeroBits(quint64(qAbs(bytes)))) / 10); -+ base = 1024; -+ } -+ // Only go to doubles if we'll be using a quantifier: -+ const QString number = power -+ ? toString(bytes / std::pow(double(base), power), 'f', qMin(precision, 3 * power)) -+ : toString(bytes); -+ -+ // We don't support sizes in units larger than exbibytes because -+ // the number of bytes would not fit into qint64. -+ Q_ASSERT(power <= 6 && power >= 0); -+ // Red Panda C++: use hard-coded unit strings. -+ QString unit; -+ if (power > 0) { -+ if (format & DataSizeSIQuantifiers) { -+ static QString siQuantifiers[] { -+ QStringLiteral("kB"), QStringLiteral("MB"), QStringLiteral("GB"), -+ QStringLiteral("TB"), QStringLiteral("PB"), QStringLiteral("EB") -+ }; -+ unit = siQuantifiers[power - 1]; -+ } else { -+ static QString iecQuantifiers[] { -+ QStringLiteral("KiB"), QStringLiteral("MiB"), QStringLiteral("GiB"), -+ QStringLiteral("TiB"), QStringLiteral("PiB"), QStringLiteral("EiB") -+ }; -+ unit = iecQuantifiers[power - 1]; -+ } -+ } else { -+ unit = QStringLiteral("Bytes"); -+ } -+ -+ return number + QLatin1Char(' ') + unit; -+} -+ - /*! - \since 4.8 - -diff --unified --recursive --text qtbase-opensource-src-5.6.3.orig/src/corelib/tools/qlocale.h qtbase-opensource-src-5.6.3/src/corelib/tools/qlocale.h ---- qtbase-opensource-src-5.6.3.orig/src/corelib/tools/qlocale.h 2017-09-06 20:13:54.000000000 +0800 -+++ qtbase-opensource-src-5.6.3/src/corelib/tools/qlocale.h 2023-10-17 14:38:05.854106100 +0800 -@@ -854,6 +854,19 @@ - CurrencyDisplayName - }; - -+ enum DataSizeFormat { -+ // Single-bit values, for internal use. -+ DataSizeBase1000 = 1, // use factors of 1000 instead of IEC's 1024; -+ DataSizeSIQuantifiers = 2, // use SI quantifiers instead of IEC ones. -+ -+ // Flags values for use in API: -+ DataSizeIecFormat = 0, // base 1024, KiB, MiB, GiB, ... -+ DataSizeTraditionalFormat = DataSizeSIQuantifiers, // base 1024, kB, MB, GB, ... -+ DataSizeSIFormat = DataSizeBase1000 | DataSizeSIQuantifiers // base 1000, kB, MB, GB, ... -+ }; -+ Q_DECLARE_FLAGS(DataSizeFormats, DataSizeFormat) -+ Q_FLAG(DataSizeFormats) -+ - QLocale(); - QLocale(const QString &name); - QLocale(Language language, Country country = AnyCountry); -@@ -955,6 +968,8 @@ - QString toCurrencyString(double, const QString &symbol = QString()) const; - inline QString toCurrencyString(float, const QString &symbol = QString()) const; - -+ QString formattedDataSize(qint64 bytes, int precision = 2, DataSizeFormats format = DataSizeIecFormat); -+ - QStringList uiLanguages() const; - - bool operator==(const QLocale &other) const; -diff --unified --recursive --text qtbase-opensource-src-5.6.3.orig/src/corelib/tools/qstring.h qtbase-opensource-src-5.6.3/src/corelib/tools/qstring.h ---- qtbase-opensource-src-5.6.3.orig/src/corelib/tools/qstring.h 2017-09-06 20:13:54.000000000 +0800 -+++ qtbase-opensource-src-5.6.3/src/corelib/tools/qstring.h 2023-10-17 14:38:05.854106100 +0800 -@@ -258,6 +258,11 @@ - const QChar operator[](uint i) const; - QCharRef operator[](uint i); - -+ Q_REQUIRED_RESULT inline QChar front() const { return at(0); } -+ Q_REQUIRED_RESULT inline QCharRef front(); -+ Q_REQUIRED_RESULT inline QChar back() const { return at(size() - 1); } -+ Q_REQUIRED_RESULT inline QCharRef back(); -+ - QString arg(qlonglong a, int fieldwidth=0, int base=10, - QChar fillChar = QLatin1Char(' ')) const Q_REQUIRED_RESULT; - QString arg(qulonglong a, int fieldwidth=0, int base=10, -@@ -793,6 +798,10 @@ - - Data *d; - -+ friend inline bool operator==(QChar, const QString &) Q_DECL_NOTHROW; -+ friend inline bool operator< (QChar, const QString &) Q_DECL_NOTHROW; -+ friend inline bool operator> (QChar, const QString &) Q_DECL_NOTHROW; -+ - void reallocData(uint alloc, bool grow = false); - void expand(int i); - QString multiArg(int numArgs, const QString **args) const; -@@ -1094,6 +1103,8 @@ - { Q_ASSERT(i >= 0); return QCharRef(*this, i); } - inline QCharRef QString::operator[](uint i) - { return QCharRef(*this, i); } -+inline QCharRef QString::front() { return operator[](0); } -+inline QCharRef QString::back() { return operator[](size() - 1); } - inline QString::iterator QString::begin() - { detach(); return reinterpret_cast(d->data()); } - inline QString::const_iterator QString::begin() const -@@ -1573,6 +1584,25 @@ - inline int QStringRef::compare(const QStringRef &s1, QLatin1String s2, Qt::CaseSensitivity cs) - { return QString::compare_helper(s1.constData(), s1.length(), s2, cs); } - -+// QChar <> QString -+inline bool operator==(QChar lhs, const QString &rhs) Q_DECL_NOTHROW -+{ return rhs.size() == 1 && lhs == rhs.front(); } -+inline bool operator< (QChar lhs, const QString &rhs) Q_DECL_NOTHROW -+{ return QString::compare_helper(&lhs, 1, rhs.data(), rhs.size()) < 0; } -+inline bool operator> (QChar lhs, const QString &rhs) Q_DECL_NOTHROW -+{ return QString::compare_helper(&lhs, 1, rhs.data(), rhs.size()) > 0; } -+ -+inline bool operator!=(QChar lhs, const QString &rhs) Q_DECL_NOTHROW { return !(lhs == rhs); } -+inline bool operator<=(QChar lhs, const QString &rhs) Q_DECL_NOTHROW { return !(lhs > rhs); } -+inline bool operator>=(QChar lhs, const QString &rhs) Q_DECL_NOTHROW { return !(lhs < rhs); } -+ -+inline bool operator==(const QString &lhs, QChar rhs) Q_DECL_NOTHROW { return rhs == lhs; } -+inline bool operator!=(const QString &lhs, QChar rhs) Q_DECL_NOTHROW { return !(rhs == lhs); } -+inline bool operator< (const QString &lhs, QChar rhs) Q_DECL_NOTHROW { return rhs > lhs; } -+inline bool operator> (const QString &lhs, QChar rhs) Q_DECL_NOTHROW { return rhs < lhs; } -+inline bool operator<=(const QString &lhs, QChar rhs) Q_DECL_NOTHROW { return !(rhs < lhs); } -+inline bool operator>=(const QString &lhs, QChar rhs) Q_DECL_NOTHROW { return !(rhs > lhs); } -+ - inline int QString::localeAwareCompare(const QStringRef &s) const - { return localeAwareCompare_helper(constData(), length(), s.constData(), s.length()); } - inline int QString::localeAwareCompare(const QString& s1, const QStringRef& s2) -diff --unified --recursive --text qtbase-opensource-src-5.6.3.orig/src/gui/kernel/qcursor.cpp qtbase-opensource-src-5.6.3/src/gui/kernel/qcursor.cpp ---- qtbase-opensource-src-5.6.3.orig/src/gui/kernel/qcursor.cpp 2017-09-06 20:13:54.000000000 +0800 -+++ qtbase-opensource-src-5.6.3/src/gui/kernel/qcursor.cpp 2023-10-17 14:38:05.869731000 +0800 -@@ -471,6 +471,27 @@ - setShape(shape); - } - -+bool operator==(const QCursor &lhs, const QCursor &rhs) Q_DECL_NOTHROW -+{ -+ if (lhs.d == rhs.d) -+ return true; // Copy or same shape -+ -+ // Check pixmaps or bitmaps cache keys. Notice that having BitmapCursor -+ // shape implies either non-null pixmap or non-null bitmap and mask -+ if (lhs.shape() == Qt::BitmapCursor && rhs.shape() == Qt::BitmapCursor -+ && lhs.hotSpot() == rhs.hotSpot()) { -+ if (!lhs.d->pixmap.isNull()) -+ return lhs.d->pixmap.cacheKey() == rhs.d->pixmap.cacheKey(); -+ -+ if (!rhs.d->pixmap.isNull()) -+ return false; -+ -+ return lhs.d->bm->cacheKey() == rhs.d->bm->cacheKey() -+ && lhs.d->bmm->cacheKey() == rhs.d->bmm->cacheKey(); -+ } -+ -+ return false; -+} - - /*! - Returns the cursor shape identifier. The return value is one of -diff --unified --recursive --text qtbase-opensource-src-5.6.3.orig/src/gui/kernel/qcursor.h qtbase-opensource-src-5.6.3/src/gui/kernel/qcursor.h ---- qtbase-opensource-src-5.6.3.orig/src/gui/kernel/qcursor.h 2017-09-06 20:13:54.000000000 +0800 -+++ qtbase-opensource-src-5.6.3/src/gui/kernel/qcursor.h 2023-10-17 14:38:05.869731000 +0800 -@@ -102,9 +102,13 @@ - inline static void setPos(QScreen *screen, const QPoint &p) { setPos(screen, p.x(), p.y()); } - - private: -+ friend Q_GUI_EXPORT bool operator==(const QCursor &lhs, const QCursor &rhs) Q_DECL_NOTHROW; - QCursorData *d; - }; - -+Q_GUI_EXPORT bool operator==(const QCursor &lhs, const QCursor &rhs) Q_DECL_NOTHROW; -+inline bool operator!=(const QCursor &lhs, const QCursor &rhs) Q_DECL_NOTHROW { return !(lhs == rhs); } -+ - /***************************************************************************** - QCursor stream functions - *****************************************************************************/ -diff --unified --recursive --text qtbase-opensource-src-5.6.3.orig/src/gui/text/qfontmetrics.cpp qtbase-opensource-src-5.6.3/src/gui/text/qfontmetrics.cpp ---- qtbase-opensource-src-5.6.3.orig/src/gui/text/qfontmetrics.cpp 2017-09-06 20:13:54.000000000 +0800 -+++ qtbase-opensource-src-5.6.3/src/gui/text/qfontmetrics.cpp 2023-10-17 14:38:05.869731000 +0800 -@@ -586,6 +586,17 @@ - return qRound(advance); - } - -+// Rdd Panda C++: forward to `width`. -+int QFontMetrics::horizontalAdvance(const QString &text, int len) const -+{ -+ return width(text, len); -+} -+ -+int QFontMetrics::horizontalAdvance(QChar ch) const -+{ -+ return width(ch); -+} -+ - #if QT_VERSION < QT_VERSION_CHECK(6,0,0) - /*! \obsolete - -diff --unified --recursive --text qtbase-opensource-src-5.6.3.orig/src/gui/text/qfontmetrics.h qtbase-opensource-src-5.6.3/src/gui/text/qfontmetrics.h ---- qtbase-opensource-src-5.6.3.orig/src/gui/text/qfontmetrics.h 2017-09-06 20:13:54.000000000 +0800 -+++ qtbase-opensource-src-5.6.3/src/gui/text/qfontmetrics.h 2023-10-17 14:38:05.869731000 +0800 -@@ -86,6 +86,10 @@ - int width(const QString &, int len, int flags) const; - - int width(QChar) const; -+ -+ int horizontalAdvance(const QString &, int len = -1) const; -+ int horizontalAdvance(QChar) const; -+ - #if QT_VERSION < QT_VERSION_CHECK(6,0,0) - QT_DEPRECATED int charWidth(const QString &str, int pos) const; - #endif -diff --unified --recursive --text qtbase-opensource-src-5.6.3.orig/src/widgets/kernel/qaction.h qtbase-opensource-src-5.6.3/src/widgets/kernel/qaction.h ---- qtbase-opensource-src-5.6.3.orig/src/widgets/kernel/qaction.h 2017-09-06 20:13:54.000000000 +0800 -+++ qtbase-opensource-src-5.6.3/src/widgets/kernel/qaction.h 2023-10-18 08:45:39.996548800 +0800 -@@ -84,9 +84,9 @@ - NormalPriority = 128, - HighPriority = 256}; - Q_ENUM(Priority) -- explicit QAction(QObject* parent); -- QAction(const QString &text, QObject* parent); -- QAction(const QIcon &icon, const QString &text, QObject* parent); -+ explicit QAction(QObject* parent = nullptr); -+ QAction(const QString &text, QObject* parent = nullptr); -+ QAction(const QIcon &icon, const QString &text, QObject* parent = nullptr); - - ~QAction(); - -diff --unified --recursive --text qtbase-opensource-src-5.6.3.orig/src/widgets/kernel/qwidget.cpp qtbase-opensource-src-5.6.3/src/widgets/kernel/qwidget.cpp ---- qtbase-opensource-src-5.6.3.orig/src/widgets/kernel/qwidget.cpp 2017-09-06 20:13:54.000000000 +0800 -+++ qtbase-opensource-src-5.6.3/src/widgets/kernel/qwidget.cpp 2023-10-18 07:11:39.982967700 +0800 -@@ -10337,6 +10337,15 @@ - d->setWindowFlags(flags); - } - -+void QWidget::setWindowFlag(Qt::WindowType flag, bool on) -+{ -+ Q_D(QWidget); -+ if (on) -+ d->setWindowFlags(data->window_flags | flag); -+ else -+ d->setWindowFlags(data->window_flags & ~flag); -+} -+ - /*! \internal - - Implemented in QWidgetPrivate so that QMdiSubWindowPrivate can reimplement it. -diff --unified --recursive --text qtbase-opensource-src-5.6.3.orig/src/widgets/kernel/qwidget.h qtbase-opensource-src-5.6.3/src/widgets/kernel/qwidget.h ---- qtbase-opensource-src-5.6.3.orig/src/widgets/kernel/qwidget.h 2017-09-06 20:13:54.000000000 +0800 -+++ qtbase-opensource-src-5.6.3/src/widgets/kernel/qwidget.h 2023-10-18 07:10:13.033316200 +0800 -@@ -554,6 +554,7 @@ - - void setWindowFlags(Qt::WindowFlags type); - inline Qt::WindowFlags windowFlags() const; -+ void setWindowFlag(Qt::WindowType, bool on = true); - void overrideWindowFlags(Qt::WindowFlags type); - - inline Qt::WindowType windowType() const;