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
This commit is contained in:
Cyano Hao 2024-01-18 10:43:10 +08:00 committed by GitHub
parent 3f5996fcc0
commit 5cf21bcc27
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 179 additions and 1047 deletions

View File

@ -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.16.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.16.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:

View File

@ -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:

View File

@ -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 版本:

View File

@ -1,113 +1,127 @@
# for Git Bash
set -xe
# Usage:
# ./build-qt5.6-mingw-static.sh --arch <32|64> [--debug] [--official-qt-dir <path>]
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

View File

@ -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<Enum>::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 <typename... Args>
+struct QNonConstOverload
+{
+ template <typename R, typename T>
+ Q_DECL_CONSTEXPR auto operator()(R (T::*ptr)(Args...)) const Q_DECL_NOTHROW -> decltype(ptr)
+ { return ptr; }
+
+ template <typename R, typename T>
+ static Q_DECL_CONSTEXPR auto of(R (T::*ptr)(Args...)) Q_DECL_NOTHROW -> decltype(ptr)
+ { return ptr; }
+};
+
+template <typename... Args>
+struct QConstOverload
+{
+ template <typename R, typename T>
+ Q_DECL_CONSTEXPR auto operator()(R (T::*ptr)(Args...) const) const Q_DECL_NOTHROW -> decltype(ptr)
+ { return ptr; }
+
+ template <typename R, typename T>
+ static Q_DECL_CONSTEXPR auto of(R (T::*ptr)(Args...) const) Q_DECL_NOTHROW -> decltype(ptr)
+ { return ptr; }
+};
+
+template <typename... Args>
+struct QOverload : QConstOverload<Args...>, QNonConstOverload<Args...>
+{
+ using QConstOverload<Args...>::of;
+ using QConstOverload<Args...>::operator();
+ using QNonConstOverload<Args...>::of;
+ using QNonConstOverload<Args...>::operator();
+
+ template <typename R>
+ Q_DECL_CONSTEXPR auto operator()(R (*ptr)(Args...)) const Q_DECL_NOTHROW -> decltype(ptr)
+ { return ptr; }
+
+ template <typename R>
+ 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 <typename... Args> Q_CONSTEXPR Q_DECL_UNUSED QOverload<Args...> qOverload = {};
+template <typename... Args> Q_CONSTEXPR Q_DECL_UNUSED QConstOverload<Args...> qConstOverload = {};
+template <typename... Args> Q_CONSTEXPR Q_DECL_UNUSED QNonConstOverload<Args...> 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 <QtCore/qstringlist.h>
#include <QtCore/qshareddata.h>
+#include <functional>
+
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<void(CreateProcessArguments *)> 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<LPCWSTR>(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<wchar_t *>(const_cast<ushort *>(args.utf16())),
+ nullptr, nullptr, inheritHandles, dwCreationFlags, envPtr,
+ workingDirectory.isEmpty()
+ ? nullptr : reinterpret_cast<const wchar_t *>(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 <class Char, class Integral>
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 <class Char>
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<QChar*>(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;