Merge remote-tracking branch 'origin/5.13' into dev

Conflicts:
	qmake/generators/makefile.cpp
	qmake/generators/unix/unixmake2.cpp
	src/corelib/thread/qthread_unix.cpp
	tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp

Change-Id: I1df0d4ba20685de7f9300bf07458c13376493408
This commit is contained in:
Liang Qi 2019-06-14 11:56:56 +02:00
commit b1a216649e
130 changed files with 7034 additions and 4588 deletions

View File

@ -705,6 +705,7 @@
},
"optimize_debug": {
"label": "Optimize debug build",
"autoDetect": "!features.developer-build",
"condition": "!config.msvc && !config.clang && (features.debug || features.debug_and_release) && tests.optimize_debug",
"output": [ "privateConfig" ]
},

301
dist/changes-5.13.0 vendored
View File

@ -1,3 +1,20 @@
Qt 5.13 introduces many new features and improvements as well as bugfixes
over the 5.12.x series. For more details, refer to the online documentation
included in this distribution. The documentation is also available online:
https://doc.qt.io/qt-5/index.html
The Qt version 5.13 series is binary compatible with the 5.12.x series.
Applications compiled for 5.12 will continue to run with 5.13.
Some of the changes listed in this file include issue tracking numbers
corresponding to tasks in the Qt Bug Tracker:
https://bugreports.qt.io/
Each of these identifiers can be entered in the bug tracker to obtain more
information about a particular change.
****************************************************************************
* Important Source Incompatible Changes *
****************************************************************************
@ -5,3 +22,287 @@
- Moc generated files include the standard <memory> header file now.
A side effect of this is that code including the Moc output from within
a namespace will fail to compile.
****************************************************************************
* Important Behavior Changes *
****************************************************************************
- The Qt resource system now supports compressing content using the
Zstandard (https://zstd.net) algorithm. Compared to zlib, it compresses
better for the same CPU time, so this algorithm is the default.
QResource::isCompressed() returns true for either compression algorithm.
Use QResource::compressionAlgorithm() to find out which algorithm to
decompress. QFile will automatically decompress using the correct
algorithm.
- QDataStream version bumped up to 19 to account for changes in the
serialization of QFont.
- [QTBUG-73048] Qt now enables by default warnings when using APIs
marked as deprecated. It is possible to disable such warnings by
defining the QT_NO_DEPRECATED_WARNINGS macro. The old
QT_DEPRECATED_WARNINGS macro which was used to enable this warning
now has no effect (warnings are automatically enabled).
****************************************************************************
* Third-Party Code *
****************************************************************************
- Updated bundled SQLite to version 3.28.0.
- [QTBUG-72623] Updated DNS public suffix list
- [QTBUG-73883] libjpeg-turbo was updated to version 2.0.2
- Bundled libpng was updated to version 1.6.37
****************************************************************************
* Platform-Specific Changes *
****************************************************************************
- X11 / XCB:
* [QTBUG-45375] QTabletEvent coordinates now come from AbsX/AbsY
valuators in the X11 event, in more precise 32.32 fixed-point format,
scaled to fit the virtual desktop. It's possible to revert to using
the legacy 16.16-format event_x/event_y coordinates as in previous
releases by setting the QT_XCB_TABLET_LEGACY_COORDINATES environment
variable.
* [plugins] platforminputcontexts now use libxkbcommon-compose APIs for
compose key input, instead of Qt's own implementation.
- Android
* Increased the minimum supported Android version to Android 5.0
(API level 21).
- Windows
* [QTBUG-47247][QTBUG-71855] Add a default setting for
hasBorderInFullScreen in QtPlatformHeaders, QWindowsWindowFunctions
* [QTBUG-57180] Removed confusing DirectWrite warning when loading
bitmap fonts.
- macOS
* Accessibility: VoiceOver now reads all lines in multiline text
components when navigating by lines.
****************************************************************************
* Tools *
****************************************************************************
- configure & build system:
* Added --linker=[bfg,lld,gold] configure flag.
* The default OpenGL configuration changed from ANGLE to dynamic OpenGL.
* Added -schannel option to enable Schannel support on Desktop Windows.
* Added -coverage option for recording coverage data during execution
- CMake
* Added support for automatic linking of transitive dependencies in
static builds
- qmake
* [QTBUG-53654] Introduced the variables WINDOWS_TARGET_PLATFORM_VERSION
and WINDOWS_TARGET_PLATFORM_MIN_VERSION for overriding the default
values of WindowsTargetPlatformVersion and
WindowsTargetPlatformMinVersion in Visual Studio project files.
- RCC now supports compressing content using the Zstandard
(https://zstd.net) algorithm. Compared to zlib, it compresses better for
the same CPU time, so this algorithm is the default. To go back to the
previous algorithm, pass command-line option --compress-algo=zlib.
Compression levels range from 1 (fastest, least compression) to 19
(slowest, best compression). Level 0 tells the library to choose an
implementation-defined default. The default compression level is
"heuristic" (level -1): under this mode, RCC will attempt a very fast
compression (level 1) and check if the file was sufficiently compressed.
If it was, then RCC will compress again using an implementation-defined
level.
****************************************************************************
* QtCore *
****************************************************************************
- New class QConcatenateTablesProxyModel, to concatenate the rows from
multiple source models.
- New class QTransposeProxyModel to swap rows and columns of the source
model.
- Added macros Q_DISABLE_MOVE and Q_DISABLE_COPY_MOVE complementing
Q_DISABLE_COPY.
- Qt Containers and meta type system now use C++11 type traits
(std::is_trivial, std::is_trivially_copyable and
std::is_trivially_destructible) to detect the class of a type not
explicitly set by Q_DECLARE_TYPEINFO. (Q_DECLARE_TYPEINFO is still
needed for QList.)
- QCommandLineParser:
* [QTBUG-58490] The application name (if set in QCoreApplication) is now
shown in error messages.
- QDateTime:
* [QTBUG-71030] Fixed race conditions in getting the local time zone. Qt now
has a mutex lock around all calls to tzset() and mktime(). Application
code should avoid calling those functions directly.
- QFile:
* Made QFile::copy() issue a filesystem-synchronization system call,
which would make it less likely to result in incomplete or corrupt
files if the system reboots or uncleanly shuts down soon after the
function returns. New code is advised to use QSaveFile instead, which
also allows display of a progress report while copying.
- QFileInfo:
* [QTBUG-63970][QTBUG-30401][QTBUG-20791] Fixed resolving of symbolic
links to UNC shares on NTFS file systems.
- QJsonArray:
* [QTBUG-32793] Added cbegin() and cend() methods for compatibility with
the Standard Library container concepts.
- QJsonDocument:
* [QTBUG-71445] Added the ability to stream QJsonDocument into and from
QDataStream if it is contained in a QVariant.
- QLocale:
* Added support for Western Balochi, Ido, Lojban, Sicilian and
Southern Kurdish.
* [QTBUG-71445] Added a const overload for formattedDataSize().
* [QTBUG-782] Added toLong() and toULong().
- QMetaObject:
* Non-copyable lambdas can now be used with invokeMethod(). For
consistency reasons, the functor object is now always moved.
- QMimeDatabase:
* Added configure option -no-mimetype-database that tells Qt not to
bundle its own copy of the XDG MIME database. If this option is
passed, QMimeDatabase will only work if there's a system copy in
$XDG_DATA_DIRS/mime. This option is useful for Linux distributions
that ensure the data is always present.
- QSettings:
* Added QSettings(Scope...) constructor to avoid using #ifdef in Qt
applications.
- QStringListModel:
* [QTBUG-69807] Implemented moveRows
- QUrlQuery:
* QUrlQuery now provides an initializer list constructor. It can be
created using a list of key/value pairs.
- QVector:
* QVector no longer requires a default constructor for its template
argument.
****************************************************************************
* QtDBus *
****************************************************************************
- Matching namespace prefixes using QDBusServiceWatcher (instead of full
service names) is now possible. For example, "com.example.backend1*"
will match "com.example.backend1", "com.example.backend1.foo" and
"com.example.backend1.foo.bar", but not "com.example.backend12".
****************************************************************************
* QtGui *
****************************************************************************
- CSS:
* Added support for HSL/HSLA colors.
* Fix the range of the hue parameter when parsing a color given in HSL
or HSV.
- QFont:
* Add setFamilies()/families() to support use of font families with
commas and quotes in their name.
- QImage:
* [QTBUG-41176] Added support for 16-bit grayscale format.
* A new method convertTo has been added to change the format of a QImage
in place.
- QPainterPath:
* Added clear(), reserve(), capacity(). clear() removes allocated
QPainterPath elements but preserves allocated memory, which can be
useful for application with complex paths that are often recreated.
reserve() and capacity() follow QVector semantics.
- QWindow:
* [QTBUG-67903][QTBUG-52944] QWindow::transientParent is now a property.
- Text:
* [QTBUG-60813] Deprecated QFont::lastResortFamily() and
QFont::lastResortFont() which are not in use in Qt 5 and did not
provide any useful information.
* [QTBUG-22813] Added support for setting the font's style name in
QTextCharFormat.
****************************************************************************
* QtNetwork *
****************************************************************************
- TLS (SSL):
* Support for SSLv2 and SSLv3 sockets has been dropped, as per RFC 6176
(2011) and RFC 7568 (2015).
* The Schannel backend now supports ALPN and thus HTTP/2.
* [QTBUG-62637] Added support for Schannel on Desktop Windows. To build
Qt with Schannel support use '-schannel' during configure.
* Added class QOcspResponse as a part of OCSP stapling support.
* [QTBUG-12812][QTBUG-17158] Added OCSP-stapling support for OpenSSL
backend
* [QTBUG-71828][QTBUG-73289] Fixed SSL verification when connecting to IP
address (no host name) if that IP address is listed in the certificate.
****************************************************************************
* QtTestLib *
****************************************************************************
- Added QTest::toString(const QModelIndex &idx)
- Removed support for GPU_BLACKLIST files. Reimplementations or
equivalents of QTEST_MAIN() should remove their uses of
QTEST_ADD_GPU_BLACKLIST_SUPPORT and its _DEFS; they are still vacuously
defined, but serve no remaining purpose and shall be undefined in due
course.
****************************************************************************
* QtWidgets *
****************************************************************************
- QAbstractScrollArea:
* [QTBUG-69120] QTableView/QTreeView, when reporting their
viewportSizeHint(), now correctly take into account their scroll
bars' visibility and visibilityPolicy.
- QHeaderView:
* dataChanged now respects the given roles to avoid useless
recomputations.
- QLabel:
* Minor performance improvement when painting a label with an image.
- QListWidget:
* [QTBUG-69807] Implemented moveRows in model
* [QTBUG-68977] Sped up handling of hidden items when working with large
data sets.
- QPlainTextEdit:
* Added QRegularExpression find() method overload.
- QTextEdit:
* Added QRegularExpression find() method overload.
- QTreeView:
* Added expandRecursively() to expand all items below a given index.
- QWidgetTextControlPrivate:
* [QTBUG-69735] Moved cursor selection to start.
****************************************************************************
* QtSql *
****************************************************************************
- SQLite:
* [QTBUG-63498] The json1-extension for the SQLite3 plugin is now enabled
by default.
- PostgreSQL:
* QSqlDatabase is now stricter about table names when used with record()
and primaryIndex(). If the tablename was not quoted when it was
created, then the table name passed to record() and primaryIndex()
needs to be in lower case so that PostgreSQL is able to find it.

View File

@ -27,7 +27,7 @@ else: equals(ANDROID_TARGET_ARCH, x86_64): \
QMAKE_CFLAGS += -gcc-toolchain $$NDK_TOOLCHAIN_PATH -fno-limit-debug-info
QMAKE_LINK = $$QMAKE_CXX $$QMAKE_CFLAGS -Wl,--exclude-libs,libgcc.a -Wl,--exclude-libs,libatomic.a
QMAKE_LINK = $$QMAKE_CXX $$QMAKE_CFLAGS -Wl,--exclude-libs,libgcc.a -Wl,--exclude-libs,libatomic.a -nostdlib++
equals(ANDROID_TARGET_ARCH, armeabi-v7a): QMAKE_LINK += -Wl,--exclude-libs,libunwind.a
QMAKE_CFLAGS += -DANDROID_HAS_WSTRING --sysroot=$$NDK_ROOT/sysroot \

View File

@ -20,7 +20,7 @@
# output check that "EGLFS GBM .......... yes" is present, otherwise
# eglfs will not be functional.
#
# ./configure -release -opengl es2 -device linux-rpi3-vc4-g++ \
# ./configure -release -opengl es2 -device linux-rasp-pi3-vc4-g++ \
# -device-option CROSS_COMPILE=~/raspbian/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin/arm-linux-gnueabihf- \
# -sysroot ~/raspbian/sysroot \
# -prefix /usr/local/qt5pi -extprefix ~/raspbian/qt5pi -hostprefix ~/raspbian/qt5 \

View File

@ -59,6 +59,7 @@ function(_qt5_$${CMAKE_MODULE_NAME}_process_prl_file prl_file_location Configura
file(STRINGS \"${prl_file_location}\" _prl_strings REGEX \"QMAKE_PRL_LIBS[ \\t]*=\")
string(REGEX REPLACE \"QMAKE_PRL_LIBS[ \\t]*=[ \\t]*([^\\n]*)\" \"\\\\1\" _static_depends ${_prl_strings})
string(REGEX REPLACE \"[ \\t]+\" \";\" _static_depends ${_static_depends})
string(REGEX REPLACE \"[ \\t]+\" \";\" _standard_libraries ${CMAKE_CXX_STANDARD_LIBRARIES})
set(_search_paths)
string(REPLACE \"\\$\\$[QT_INSTALL_LIBS]\" \"${_qt5_install_libs}\" _static_depends \"${_static_depends}\")
foreach(_flag ${_static_depends})
@ -66,7 +67,15 @@ function(_qt5_$${CMAKE_MODULE_NAME}_process_prl_file prl_file_location Configura
if(_flag MATCHES \"^-l(.*)$\")
# Handle normal libraries passed as -lfoo
set(_lib \"${CMAKE_MATCH_1}\")
if(_lib MATCHES \"^pthread$\")
foreach(_standard_library ${_standard_libraries})
if(_standard_library MATCHES \"^${_lib}(\\.lib)?$\")
set(_lib_is_default_linked TRUE)
break()
endif()
endforeach()
if (_lib_is_default_linked)
unset(_lib_is_default_linked)
elseif(_lib MATCHES \"^pthread$\")
find_package(Threads REQUIRED)
list(APPEND _lib_deps Threads::Threads)
else()

View File

@ -37,8 +37,10 @@ intel_icl {
QMAKE_DIR_REPLACE_SANE = PRECOMPILED_DIR OBJECTS_DIR MOC_DIR RCC_DIR UI_DIR
load(qt_prefix_build_check)
# force_independent can be set externally. prefix_build not.
!exists($$[QT_HOST_DATA]/.qmake.cache): \
qtIsPrefixBuild($$[QT_HOST_DATA]): \
CONFIG += prefix_build force_independent
!build_pass:!isEmpty(_QMAKE_SUPER_CACHE_):force_independent {

View File

@ -51,6 +51,12 @@ contains(TEMPLATE, .*lib) {
}
lib_replace.CONFIG = path
QMAKE_PRL_INSTALL_REPLACE += lib_replace
!equals(qt_libdir, $$rplbase/lib) {
qtlibdir_replace.match = $$qt_libdir
qtlibdir_replace.replace = $$qqt_libdir
qtlibdir_replace.CONFIG = path
QMAKE_PRL_INSTALL_REPLACE += qtlibdir_replace
}
}
# The remainder of this file must not apply to host tools/libraries,

View File

@ -2517,17 +2517,19 @@ logn("Configure summary:")
logn()
qtConfPrintReport()
load(qt_prefix_build_check)
# final notes for the user
logn()
logn("Qt is now configured for building. Just run '$$QMAKE_MAKE_NAME'.")
pfx = $$[QT_INSTALL_PREFIX]
exists($$pfx/.qmake.cache) {
qtIsPrefixBuild($$pfx) {
logn("Once everything is built, you must run '$$QMAKE_MAKE_NAME install'.")
logn("Qt will be installed into '$$system_path($$pfx)'.")
} else {
logn("Once everything is built, Qt is installed.")
logn("You should NOT run '$$QMAKE_MAKE_NAME install'.")
logn("Note that this build cannot be deployed to other machines or devices.")
} else {
logn("Once everything is built, you must run '$$QMAKE_MAKE_NAME install'.")
logn("Qt will be installed into '$$system_path($$pfx)'.")
}
logn()
logn("Prior to reconfiguration, make sure you remove any leftovers from")

View File

@ -82,6 +82,11 @@ header_module {
CONFIG += force_qt # Needed for the headers_clean tests.
!lib_bundle: \
CONFIG += qt_no_install_library
# Allow creation of .prl, .la and .pc files.
target.path = $$[QT_INSTALL_LIBS]
target.CONFIG += dummy_install
INSTALLS += target
} else {
TEMPLATE = lib
}

View File

@ -0,0 +1,21 @@
#
# W A R N I N G
# -------------
#
# This file is not part of the Qt API. It exists purely as an
# implementation detail. It may change from version to version
# without notice, or even be removed.
#
# We mean it.
#
defineTest(qtIsPrefixBuild) {
prefixdir = $$1
# qtbase non-prefix build?
exists($$prefixdir/.qmake.cache): \
return(false)
# top-level non-prefix build?
contains(prefixdir, .*/qtbase):exists($$dirname(prefixdir)/.qmake.super): \
return(false)
return(true)
}

View File

@ -94,6 +94,12 @@ QMAKE_PREFIX_STATICLIB = lib
QMAKE_EXTENSION_STATICLIB = a # llvm bitcode
QMAKE_AR = emar cqs
equals(QMAKE_HOST.os, Windows) {
QMAKE_AR_CMD = \
"$(file >$(OBJECTS_DIR)/$(TARGET).rsp, $(subst \\,/,$(OBJECTS)))$$escape_expand(\\n\\t)" \
"$(AR) $(DESTDIR)$(TARGET) @$(OBJECTS_DIR)/$(TARGET).rsp"
}
QMAKE_DISTCLEAN += *.html *.js *.wasm
load(qt_config)

View File

@ -513,7 +513,6 @@ bool
ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
{
ProStringList tmp;
bool did_preprocess = false;
//HEADER
const int pbVersion = pbuilderVersion();
@ -731,7 +730,6 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
QFile mkf(mkfile);
if(mkf.open(QIODevice::WriteOnly | QIODevice::Text)) {
writingUnixMakefileGenerator = true;
did_preprocess = true;
debug_msg(1, "pbuilder: Creating file: %s", mkfile.toLatin1().constData());
QTextStream mkt(&mkf);
writeHeader(mkt);

View File

@ -892,7 +892,7 @@ MakefileGenerator::processPrlFile(QString &file, bool baseOnly)
bool
MakefileGenerator::processPrlFileBase(QString &origFile, const QStringRef &origName,
const QStringRef &fixedBase, int slashOff)
const QStringRef &fixedBase, int /*slashOff*/)
{
return processPrlFileCore(origFile, origName, fixedBase + Option::prl_ext);
}
@ -1112,7 +1112,8 @@ MakefileGenerator::writePrlFile()
&& project->values("QMAKE_FAILED_REQUIREMENTS").isEmpty()
&& project->isActiveConfig("create_prl")
&& (project->first("TEMPLATE") == "lib"
|| project->first("TEMPLATE") == "vclib")
|| project->first("TEMPLATE") == "vclib"
|| project->first("TEMPLATE") == "aux")
&& (!project->isActiveConfig("plugin") || project->isActiveConfig("static"))) { //write prl file
QString local_prl = prlFileName();
QString prl = fileFixify(local_prl);
@ -2369,8 +2370,15 @@ MakefileGenerator::findSubDirsSubTargets() const
st->profile = file;
}
} else {
if(!file.isEmpty() && !project->isActiveConfig("subdir_first_pro"))
st->profile = file.section(Option::dir_sep, -1) + Option::pro_ext;
if (!file.isEmpty() && !project->isActiveConfig("subdir_first_pro")) {
const QString baseName = file.section(Option::dir_sep, -1);
if (baseName.isEmpty()) {
warn_msg(WarnLogic, "Ignoring invalid SUBDIRS entry %s",
subdirs[subdir].toLatin1().constData());
continue;
}
st->profile = baseName + Option::pro_ext;
}
st->in_directory = file;
}
while(st->in_directory.endsWith(Option::dir_sep))
@ -3355,42 +3363,44 @@ MakefileGenerator::writePkgConfigFile()
if (!version.isEmpty())
t << "Version: " << version << Qt::endl;
// libs
t << "Libs: ";
QString pkgConfiglibName;
if (target_mode == TARG_MAC_MODE && project->isActiveConfig("lib_bundle")) {
if (libDir != QLatin1String("/Library/Frameworks"))
t << "-F${libdir} ";
ProString bundle;
if (!project->isEmpty("QMAKE_FRAMEWORK_BUNDLE_NAME"))
bundle = project->first("QMAKE_FRAMEWORK_BUNDLE_NAME");
else
bundle = project->first("TARGET");
int suffix = bundle.lastIndexOf(".framework");
if (suffix != -1)
bundle = bundle.left(suffix);
t << "-framework ";
pkgConfiglibName = bundle.toQString();
} else {
if (!project->values("QMAKE_DEFAULT_LIBDIRS").contains(libDir))
t << "-L${libdir} ";
pkgConfiglibName = "-l" + project->first("QMAKE_ORIG_TARGET");
if (project->isActiveConfig("shared"))
pkgConfiglibName += project->first("TARGET_VERSION_EXT").toQString();
}
t << shellQuote(pkgConfiglibName) << " \n";
if (project->first("TEMPLATE") == "lib") {
// libs
t << "Libs: ";
QString pkgConfiglibName;
if (target_mode == TARG_MAC_MODE && project->isActiveConfig("lib_bundle")) {
if (libDir != QLatin1String("/Library/Frameworks"))
t << "-F${libdir} ";
ProString bundle;
if (!project->isEmpty("QMAKE_FRAMEWORK_BUNDLE_NAME"))
bundle = project->first("QMAKE_FRAMEWORK_BUNDLE_NAME");
else
bundle = project->first("TARGET");
int suffix = bundle.lastIndexOf(".framework");
if (suffix != -1)
bundle = bundle.left(suffix);
t << "-framework ";
pkgConfiglibName = bundle.toQString();
} else {
if (!project->values("QMAKE_DEFAULT_LIBDIRS").contains(libDir))
t << "-L${libdir} ";
pkgConfiglibName = "-l" + project->first("QMAKE_ORIG_TARGET");
if (project->isActiveConfig("shared"))
pkgConfiglibName += project->first("TARGET_VERSION_EXT").toQString();
}
t << shellQuote(pkgConfiglibName) << " \n";
if (project->isActiveConfig("staticlib")) {
ProStringList libs;
libs << "LIBS"; // FIXME: this should not be conditional on staticlib
libs << "LIBS_PRIVATE";
libs << "QMAKE_LIBS"; // FIXME: this should not be conditional on staticlib
libs << "QMAKE_LIBS_PRIVATE";
libs << "QMAKE_LFLAGS_THREAD"; //not sure about this one, but what about things like -pthread?
t << "Libs.private:";
for (ProStringList::ConstIterator it = libs.cbegin(); it != libs.cend(); ++it)
t << ' ' << fixLibFlags((*it).toKey()).join(' ');
t << Qt::endl;
if (project->isActiveConfig("staticlib")) {
ProStringList libs;
libs << "LIBS"; // FIXME: this should not be conditional on staticlib
libs << "LIBS_PRIVATE";
libs << "QMAKE_LIBS"; // FIXME: this should not be conditional on staticlib
libs << "QMAKE_LIBS_PRIVATE";
libs << "QMAKE_LFLAGS_THREAD"; //not sure about this one, but what about things like -pthread?
t << "Libs.private:";
for (ProStringList::ConstIterator it = libs.cbegin(); it != libs.cend(); ++it)
t << ' ' << fixLibFlags((*it).toKey()).join(' ');
t << Qt::endl;
}
}
// flags
@ -3433,19 +3443,23 @@ QString MakefileGenerator::installMetaFile(const ProKey &replace_rule, const QSt
|| project->isActiveConfig("no_sed_meta_install")) {
ret += "-$(INSTALL_FILE) " + escapeFilePath(src) + ' ' + escapeFilePath(dst);
} else {
ret += "-$(SED)";
QString sedargs;
const ProStringList &replace_rules = project->values(replace_rule);
for (int r = 0; r < replace_rules.size(); ++r) {
const ProString match = project->first(ProKey(replace_rules.at(r) + ".match")),
replace = project->first(ProKey(replace_rules.at(r) + ".replace"));
if (!match.isEmpty() /*&& match != replace*/) {
ret += " -e " + shellQuote("s," + match + "," + replace + ",g");
sedargs += " -e " + shellQuote("s," + match + "," + replace + ",g");
if (isWindowsShell() && project->first(ProKey(replace_rules.at(r) + ".CONFIG")).contains("path"))
ret += " -e " + shellQuote("s," + windowsifyPath(match.toQString())
sedargs += " -e " + shellQuote("s," + windowsifyPath(match.toQString())
+ "," + windowsifyPath(replace.toQString()) + ",gi");
}
}
ret += ' ' + escapeFilePath(src) + " > " + escapeFilePath(dst);
if (sedargs.isEmpty()) {
ret += "-$(INSTALL_FILE) " + escapeFilePath(src) + ' ' + escapeFilePath(dst);
} else {
ret += "-$(SED) " + sedargs + ' ' + escapeFilePath(src) + " > " + escapeFilePath(dst);
}
}
return ret;
}

View File

@ -815,7 +815,7 @@ bool QMakeSourceFileInfo::findDeps(SourceFile *file)
break;
}
cpp_state = InCode;
// ... and fall through to handle buffer[x] as such.
Q_FALLTHROUGH(); // to handle buffer[x] as such.
case InCode:
// matching quotes (string literals and character literals)
if (buffer[x] == '\'' || buffer[x] == '"') {

View File

@ -43,7 +43,7 @@ protected:
void init() override;
bool writeMakefile(QTextStream &) override;
QString escapeFilePath(const QString &path) const override { Q_ASSERT(false); return QString(); }
QString escapeFilePath(const QString &) const override { Q_ASSERT(false); return QString(); }
public:
bool supportsMetaBuild() override { return false; }

View File

@ -725,7 +725,7 @@ UnixMakefileGenerator::defaultInstall(const QString &t)
}
}
}
if(project->first("TEMPLATE") == "lib") {
if (isAux || project->first("TEMPLATE") == "lib") {
QStringList types;
types << "prl" << "libtool" << "pkgconfig";
for(int i = 0; i < types.size(); ++i) {

View File

@ -43,12 +43,15 @@ void
UnixMakefileGenerator::writePrlFile(QTextStream &t)
{
MakefileGenerator::writePrlFile(t);
const ProString tmplt = project->first("TEMPLATE");
if (tmplt != "lib" && tmplt != "aux")
return;
// libtool support
if(project->isActiveConfig("create_libtool") && project->first("TEMPLATE") == "lib") { //write .la
if (project->isActiveConfig("create_libtool")) {
writeLibtoolFile();
}
// pkg-config support
if(project->isActiveConfig("create_pc") && project->first("TEMPLATE") == "lib")
if (project->isActiveConfig("create_pc"))
writePkgConfigFile();
}
@ -164,6 +167,16 @@ static QString rfc1034Identifier(const QString &str)
return s;
}
static QString escapeDir(const QString &dir)
{
// When building on non-MSys MinGW, the path ends with a backslash, which
// GNU make will interpret that as a line continuation. Doubling the backslash
// avoids the problem, at the cost of the variable containing *both* backslashes.
if (dir.endsWith('\\'))
return dir + '\\';
return dir;
}
void
UnixMakefileGenerator::writeMakeParts(QTextStream &t)
{
@ -226,7 +239,7 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t)
t << "####### Output directory\n\n";
// This is used in commands by some .prf files.
if (! project->values("OBJECTS_DIR").isEmpty())
t << "OBJECTS_DIR = " << fileVar("OBJECTS_DIR") << Qt::endl;
t << "OBJECTS_DIR = " << escapeDir(fileVar("OBJECTS_DIR")) << Qt::endl;
else
t << "OBJECTS_DIR = ./\n";
t << Qt::endl;
@ -272,13 +285,7 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t)
t << "DIST = " << valList(fileFixify(project->values("DISTFILES").toQStringList())) << " "
<< fileVarList("HEADERS") << ' ' << fileVarList("SOURCES") << Qt::endl;
t << "QMAKE_TARGET = " << fileVar("QMAKE_ORIG_TARGET") << Qt::endl;
QString destd = fileVar("DESTDIR");
// When building on non-MSys MinGW, the path ends with a backslash, which
// GNU make will interpret that as a line continuation. Doubling the backslash
// avoids the problem, at the cost of the variable containing *both* backslashes.
if (destd.endsWith('\\'))
destd += '\\';
t << "DESTDIR = " << destd << Qt::endl;
t << "DESTDIR = " << escapeDir(fileVar("DESTDIR")) << Qt::endl;
t << "TARGET = " << fileVar("TARGET") << Qt::endl;
if(project->isActiveConfig("plugin")) {
t << "TARGETD = " << fileVar("TARGET") << Qt::endl;
@ -1194,7 +1201,8 @@ void UnixMakefileGenerator::init2()
project->values("QMAKE_FRAMEWORK_VERSION").append(project->first("VER_MAJ"));
if (project->first("TEMPLATE") == "aux") {
// nothing
project->values("PRL_TARGET") =
project->values("TARGET").first().prepend(project->first("QMAKE_PREFIX_STATICLIB"));
} else if (!project->values("QMAKE_APP_FLAG").isEmpty()) {
if(!project->isEmpty("QMAKE_BUNDLE")) {
ProString bundle_loc = project->first("QMAKE_BUNDLE_LOCATION");

View File

@ -1991,6 +1991,7 @@ bool VCMIDLTool::parseOption(const char* option)
break;
case 0x5eb7af2: // /header filename
offset = 5;
Q_FALLTHROUGH();
case 0x0000358: // /h filename
HeaderFileName = option + offset + 3;
break;

View File

@ -1521,6 +1521,18 @@ void VcprojGenerator::initDistributionFiles()
vcProject.DistributionFiles.Config = &(vcProject.Configuration);
}
QString VcprojGenerator::extraCompilerName(const ProString &extraCompiler,
const QStringList &inputs,
const QStringList &outputs)
{
QString name = project->values(ProKey(extraCompiler + ".name")).join(' ');
if (name.isEmpty())
name = extraCompiler.toQString();
else
name = replaceExtraCompilerVariables(name, inputs, outputs, NoShell);
return name;
}
void VcprojGenerator::initExtraCompilerOutputs()
{
ProStringList otherFilters;
@ -1538,13 +1550,16 @@ void VcprojGenerator::initExtraCompilerOutputs()
<< "YACCSOURCES";
const ProStringList &quc = project->values("QMAKE_EXTRA_COMPILERS");
for (ProStringList::ConstIterator it = quc.begin(); it != quc.end(); ++it) {
ProString extracompilerName = project->first(ProKey(*it + ".name"));
if (extracompilerName.isEmpty())
extracompilerName = (*it);
const ProStringList &inputVars = project->values(ProKey(*it + ".input"));
ProStringList inputFiles;
for (auto var : inputVars)
inputFiles.append(project->values(var.toKey()));
const ProStringList &outputs = project->values(ProKey(*it + ".output"));
// Create an extra compiler filter and add the files
VCFilter extraCompile;
extraCompile.Name = extracompilerName.toQString();
extraCompile.Name = extraCompilerName(it->toQString(), inputFiles.toQStringList(),
outputs.toQStringList());
extraCompile.ParseFiles = _False;
extraCompile.Filter = "";
extraCompile.Guid = QString(_GUIDExtraCompilerFiles) + "-" + (*it);
@ -1557,14 +1572,14 @@ void VcprojGenerator::initExtraCompilerOutputs()
if (!outputVar.isEmpty() && otherFilters.contains(outputVar))
continue;
QString tmp_out = project->first(ProKey(*it + ".output")).toQString();
QString tmp_out = project->first(outputs.first().toKey()).toQString();
if (project->values(ProKey(*it + ".CONFIG")).indexOf("combine") != -1) {
// Combined output, only one file result
extraCompile.addFile(Option::fixPathToTargetOS(
replaceExtraCompilerVariables(tmp_out, QString(), QString(), NoShell), false));
} else {
// One output file per input
const ProStringList &tmp_in = project->values(project->first(ProKey(*it + ".input")).toKey());
const ProStringList &tmp_in = project->values(inputVars.first().toKey());
for (int i = 0; i < tmp_in.count(); ++i) {
const QString &filename = tmp_in.at(i).toQString();
if (extraCompilerSources.contains(filename) && !otherFiltersContain(filename))
@ -1577,7 +1592,6 @@ void VcprojGenerator::initExtraCompilerOutputs()
// build steps there. So, we turn it around and add it to the input files instead,
// provided that the input file variable is not handled already (those in otherFilters
// are handled, so we avoid them).
const ProStringList &inputVars = project->values(ProKey(*it + ".input"));
for (const ProString &inputVar : inputVars) {
if (!otherFilters.contains(inputVar)) {
const ProStringList &tmp_in = project->values(inputVar.toKey());

View File

@ -74,6 +74,8 @@ protected:
bool doDepends() const override { return false; } // Never necessary
using Win32MakefileGenerator::replaceExtraCompilerVariables;
QString replaceExtraCompilerVariables(const QString &, const QStringList &, const QStringList &, ReplaceFor) override;
QString extraCompilerName(const ProString &extraCompiler, const QStringList &inputs,
const QStringList &outputs);
bool supportsMetaBuild() override { return true; }
bool supportsMergedBuilds() override { return true; }
bool mergeBuildProject(MakefileGenerator *other) override;

View File

@ -645,7 +645,7 @@ void Win32MakefileGenerator::writeObjectsPart(QTextStream &t)
t << "OBJECTS = " << valList(escapeDependencyPaths(project->values("OBJECTS"))) << Qt::endl;
}
void Win32MakefileGenerator::writeImplicitRulesPart(QTextStream &t)
void Win32MakefileGenerator::writeImplicitRulesPart(QTextStream &)
{
}

View File

@ -1130,35 +1130,48 @@ bool QMakeEvaluator::prepareProject(const QString &inDir)
}
superdir = qdfi.path();
}
QString sdir = inDir;
QString dir = m_outputDir;
forever {
conffile = sdir + QLatin1String("/.qmake.conf");
if (!m_vfs->exists(conffile, flags))
conffile.clear();
cachefile = dir + QLatin1String("/.qmake.cache");
if (!m_vfs->exists(cachefile, flags))
cachefile.clear();
if (!conffile.isEmpty() || !cachefile.isEmpty()) {
if (dir != sdir)
m_sourceRoot = sdir;
if (!cachefile.isEmpty()) {
m_buildRoot = dir;
break;
}
if (dir == superdir)
goto no_cache;
QFileInfo qsdfi(sdir);
QFileInfo qdfi(dir);
if (qsdfi.isRoot() || qdfi.isRoot())
goto no_cache;
sdir = qsdfi.path();
if (qdfi.isRoot()) {
cachefile.clear();
break;
}
dir = qdfi.path();
}
QString sdir = inDir;
forever {
conffile = sdir + QLatin1String("/.qmake.conf");
if (!m_vfs->exists(conffile, flags))
conffile.clear();
if (!conffile.isEmpty()) {
if (sdir != m_buildRoot)
m_sourceRoot = sdir;
break;
}
QFileInfo qsdfi(sdir);
if (qsdfi.isRoot()) {
conffile.clear();
break;
}
sdir = qsdfi.path();
}
} else {
m_buildRoot = QFileInfo(cachefile).path();
}
m_conffile = QDir::cleanPath(conffile);
m_cachefile = QDir::cleanPath(cachefile);
if (!conffile.isEmpty())
m_conffile = QDir::cleanPath(conffile);
if (!cachefile.isEmpty())
m_cachefile = QDir::cleanPath(cachefile);
}
no_cache:

View File

@ -6,8 +6,8 @@
"Description": "SQLite is a small C library that implements a self-contained, embeddable, zero-configuration SQL database engine.",
"Homepage": "https://www.sqlite.org/",
"Version": "3.27.1",
"DownloadLocation": "https://www.sqlite.org/2018/sqlite-amalgamation-3270100.zip",
"Version": "3.28.0",
"DownloadLocation": "https://www.sqlite.org/2019/sqlite-amalgamation-3280000.zip",
"License": "Public Domain",
"Copyright": "The authors disclaim copyright to the source code. However, a license can be obtained if needed."
}

File diff suppressed because it is too large Load Diff

View File

@ -123,9 +123,9 @@ extern "C" {
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
#define SQLITE_VERSION "3.27.1"
#define SQLITE_VERSION_NUMBER 3027001
#define SQLITE_SOURCE_ID "2019-02-08 13:17:39 0eca3dd3d38b31c92b49ca2d311128b74584714d9e7de895b1a6286ef959a1dd"
#define SQLITE_VERSION "3.28.0"
#define SQLITE_VERSION_NUMBER 3028000
#define SQLITE_SOURCE_ID "2019-04-16 19:49:53 884b4b7e502b4e991677b53971277adfaf0a04a284f8e483e2553d0f83156b50"
/*
** CAPI3REF: Run-Time Library Version Numbers
@ -189,6 +189,9 @@ SQLITE_API int sqlite3_libversion_number(void);
#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
SQLITE_API int sqlite3_compileoption_used(const char *zOptName);
SQLITE_API const char *sqlite3_compileoption_get(int N);
#else
# define sqlite3_compileoption_used(X) 0
# define sqlite3_compileoption_get(X) ((void*)0)
#endif
/*
@ -2086,8 +2089,8 @@ struct sqlite3_mem_methods {
**
** [[SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER]]
** <dt>SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER</dt>
** <dd> ^This option is used to enable or disable the two-argument
** version of the [fts3_tokenizer()] function which is part of the
** <dd> ^This option is used to enable or disable the
** [fts3_tokenizer()] function which is part of the
** [FTS3] full-text search engine extension.
** There should be two additional arguments.
** The first argument is an integer which is 0 to disable fts3_tokenizer() or
@ -2199,6 +2202,17 @@ struct sqlite3_mem_methods {
** <li> Direct writes to [shadow tables].
** </ul>
** </dd>
**
** [[SQLITE_DBCONFIG_WRITABLE_SCHEMA]] <dt>SQLITE_DBCONFIG_WRITABLE_SCHEMA</dt>
** <dd>The SQLITE_DBCONFIG_WRITABLE_SCHEMA option activates or deactivates the
** "writable_schema" flag. This has the same effect and is logically equivalent
** to setting [PRAGMA writable_schema=ON] or [PRAGMA writable_schema=OFF].
** The first argument to this setting is an integer which is 0 to disable
** the writable_schema, positive to enable writable_schema, or negative to
** leave the setting unchanged. The second parameter is a pointer to an
** integer into which is written 0 or 1 to indicate whether the writable_schema
** is enabled or disabled following this call.
** </dd>
** </dl>
*/
#define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */
@ -2212,7 +2226,8 @@ struct sqlite3_mem_methods {
#define SQLITE_DBCONFIG_TRIGGER_EQP 1008 /* int int* */
#define SQLITE_DBCONFIG_RESET_DATABASE 1009 /* int int* */
#define SQLITE_DBCONFIG_DEFENSIVE 1010 /* int int* */
#define SQLITE_DBCONFIG_MAX 1010 /* Largest DBCONFIG */
#define SQLITE_DBCONFIG_WRITABLE_SCHEMA 1011 /* int int* */
#define SQLITE_DBCONFIG_MAX 1011 /* Largest DBCONFIG */
/*
** CAPI3REF: Enable Or Disable Extended Result Codes
@ -2369,7 +2384,7 @@ SQLITE_API int sqlite3_changes(sqlite3*);
** not. ^Changes to a view that are intercepted by INSTEAD OF triggers
** are not counted.
**
** This the [sqlite3_total_changes(D)] interface only reports the number
** The [sqlite3_total_changes(D)] interface only reports the number
** of rows that changed due to SQL statement run against database
** connection D. Any changes by other database connections are ignored.
** To detect changes against a database file from other database
@ -3894,6 +3909,18 @@ SQLITE_API const char *sqlite3_normalized_sql(sqlite3_stmt *pStmt);
*/
SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt);
/*
** CAPI3REF: Query The EXPLAIN Setting For A Prepared Statement
** METHOD: sqlite3_stmt
**
** ^The sqlite3_stmt_isexplain(S) interface returns 1 if the
** prepared statement S is an EXPLAIN statement, or 2 if the
** statement S is an EXPLAIN QUERY PLAN.
** ^The sqlite3_stmt_isexplain(S) interface returns 0 if S is
** an ordinary statement or a NULL pointer.
*/
SQLITE_API int sqlite3_stmt_isexplain(sqlite3_stmt *pStmt);
/*
** CAPI3REF: Determine If A Prepared Statement Has Been Reset
** METHOD: sqlite3_stmt
@ -4033,7 +4060,9 @@ typedef struct sqlite3_context sqlite3_context;
** ^The fifth argument to the BLOB and string binding interfaces
** is a destructor used to dispose of the BLOB or
** string after SQLite has finished with it. ^The destructor is called
** to dispose of the BLOB or string even if the call to bind API fails.
** to dispose of the BLOB or string even if the call to the bind API fails,
** except the destructor is not called if the third parameter is a NULL
** pointer or the fourth parameter is negative.
** ^If the fifth argument is
** the special value [SQLITE_STATIC], then SQLite assumes that the
** information is in static, unmanaged space and does not need to be freed.
@ -4950,6 +4979,8 @@ SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int6
** <tr><td><b>sqlite3_value_nochange&nbsp;&nbsp;</b>
** <td>&rarr;&nbsp;&nbsp;<td>True if the column is unchanged in an UPDATE
** against a virtual table.
** <tr><td><b>sqlite3_value_frombind&nbsp;&nbsp;</b>
** <td>&rarr;&nbsp;&nbsp;<td>True if value originated from a [bound parameter]
** </table></blockquote>
**
** <b>Details:</b>
@ -5011,6 +5042,11 @@ SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int6
** than within an [xUpdate] method call for an UPDATE statement, then
** the return value is arbitrary and meaningless.
**
** ^The sqlite3_value_frombind(X) interface returns non-zero if the
** value X originated from one of the [sqlite3_bind_int|sqlite3_bind()]
** interfaces. ^If X comes from an SQL literal value, or a table column,
** and expression, then sqlite3_value_frombind(X) returns zero.
**
** Please pay particular attention to the fact that the pointer returned
** from [sqlite3_value_blob()], [sqlite3_value_text()], or
** [sqlite3_value_text16()] can be invalidated by a subsequent call to
@ -5056,6 +5092,7 @@ SQLITE_API int sqlite3_value_bytes16(sqlite3_value*);
SQLITE_API int sqlite3_value_type(sqlite3_value*);
SQLITE_API int sqlite3_value_numeric_type(sqlite3_value*);
SQLITE_API int sqlite3_value_nochange(sqlite3_value*);
SQLITE_API int sqlite3_value_frombind(sqlite3_value*);
/*
** CAPI3REF: Finding The Subtype Of SQL Values
@ -5791,7 +5828,7 @@ SQLITE_API sqlite3 *sqlite3_db_handle(sqlite3_stmt*);
** associated with database N of connection D. ^The main database file
** has the name "main". If there is no attached database N on the database
** connection D, or if database N is a temporary or in-memory database, then
** a NULL pointer is returned.
** this function will return either a NULL pointer or an empty string.
**
** ^The filename returned by this function is the output of the
** xFullPathname method of the [VFS]. ^In other words, the filename
@ -10892,7 +10929,7 @@ SQLITE_API int sqlite3rebaser_configure(
** in size. This function allocates and populates a buffer with a copy
** of the changeset rebased rebased according to the configuration of the
** rebaser object passed as the first argument. If successful, (*ppOut)
** is set to point to the new buffer containing the rebased changset and
** is set to point to the new buffer containing the rebased changeset and
** (*pnOut) to its size in bytes and SQLITE_OK returned. It is the
** responsibility of the caller to eventually free the new buffer using
** sqlite3_free(). Otherwise, if an error occurs, (*ppOut) and (*pnOut)
@ -11301,7 +11338,7 @@ struct Fts5PhraseIter {
** Save the pointer passed as the second argument as the extension functions
** "auxiliary data". The pointer may then be retrieved by the current or any
** future invocation of the same fts5 extension function made as part of
** of the same MATCH query using the xGetAuxdata() API.
** the same MATCH query using the xGetAuxdata() API.
**
** Each extension function is allocated a single auxiliary data slot for
** each FTS query (MATCH expression). If the extension function is invoked
@ -11316,7 +11353,7 @@ struct Fts5PhraseIter {
** The xDelete callback, if one is specified, is also invoked on the
** auxiliary data pointer after the FTS5 query has finished.
**
** If an error (e.g. an OOM condition) occurs within this function, an
** If an error (e.g. an OOM condition) occurs within this function,
** the auxiliary data is set to NULL and an error code returned. If the
** xDelete parameter was not NULL, it is invoked on the auxiliary data
** pointer before returning.

View File

@ -296,6 +296,9 @@ endfunction()
# qt5_add_big_resources(outfiles inputfile ... )
function(QT5_ADD_BIG_RESOURCES outfiles )
if (CMAKE_VERSION VERSION_LESS 3.9)
message(FATAL_ERROR, "qt5_add_big_resources requires CMake 3.9 or newer")
endif()
set(options)
set(oneValueArgs)
@ -326,6 +329,8 @@ function(QT5_ADD_BIG_RESOURCES outfiles )
set_target_properties(rcc_object_${outfilename} PROPERTIES AUTOMOC OFF)
set_target_properties(rcc_object_${outfilename} PROPERTIES AUTOUIC OFF)
add_dependencies(rcc_object_${outfilename} big_resources_${outfilename})
# The modification of TARGET_OBJECTS needs the following change in cmake
# https://gitlab.kitware.com/cmake/cmake/commit/93c89bc75ceee599ba7c08b8fe1ac5104942054f
add_custom_command(OUTPUT ${outfile}
COMMAND ${Qt5Core_RCC_EXECUTABLE}
ARGS ${rcc_options} --name ${outfilename} --pass 2 --temp $<TARGET_OBJECTS:rcc_object_${outfilename}> --output ${outfile} ${infile}

View File

@ -1067,6 +1067,8 @@ QAbstractAnimation::~QAbstractAnimation()
if (oldState == QAbstractAnimation::Running)
QAnimationTimer::unregisterAnimation(this);
}
if (d->group)
d->group->removeAnimation(this);
}
/*!

View File

@ -113,6 +113,11 @@ QAnimationGroup::QAnimationGroup(QAnimationGroupPrivate &dd, QObject *parent)
*/
QAnimationGroup::~QAnimationGroup()
{
Q_D(QAnimationGroup);
// We need to clear the animations now while we are still a valid QAnimationGroup.
// If we wait until ~QObject() the QAbstractAnimation's pointer back to us would
// point to a QObject, not a valid QAnimationGroup.
d->clear(true);
}
/*!
@ -256,7 +261,7 @@ QAbstractAnimation *QAnimationGroup::takeAnimation(int index)
void QAnimationGroup::clear()
{
Q_D(QAnimationGroup);
qDeleteAll(d->animations);
d->clear(false);
}
/*!
@ -284,6 +289,24 @@ bool QAnimationGroup::event(QEvent *event)
return QAbstractAnimation::event(event);
}
void QAnimationGroupPrivate::clear(bool onDestruction)
{
const QList<QAbstractAnimation *> animationsCopy = animations; // taking a copy
animations.clear();
// Clearing backwards so the indices doesn't change while we remove animations.
for (int i = animationsCopy.count() - 1; i >= 0; --i) {
QAbstractAnimation *animation = animationsCopy.at(i);
animation->setParent(nullptr);
QAbstractAnimationPrivate::get(animation)->group = nullptr;
// If we are in ~QAnimationGroup() it is not safe to called the virtual
// animationRemoved method, which can still be a method in a
// QAnimationGroupPrivate derived class that assumes q_ptr is still
// a valid derived class of QAnimationGroup.
if (!onDestruction)
animationRemoved(i, animation);
delete animation;
}
}
void QAnimationGroupPrivate::animationRemoved(int index, QAbstractAnimation *)
{

View File

@ -73,6 +73,8 @@ public:
virtual void animationInsertedAt(int) { }
virtual void animationRemoved(int, QAbstractAnimation *);
void clear(bool onDestruction);
void disconnectUncontrolledAnimation(QAbstractAnimation *anim)
{
//0 for the signal here because we might be called from the animation destructor

View File

@ -532,7 +532,8 @@ void QSequentialAnimationGroupPrivate::animationRemoved(int index, QAbstractAnim
Q_Q(QSequentialAnimationGroup);
QAnimationGroupPrivate::animationRemoved(index, anim);
Q_ASSERT(currentAnimation); // currentAnimation should always be set
if (!currentAnimation)
return;
if (actualDuration.size() > index)
actualDuration.removeAt(index);

View File

@ -131,6 +131,8 @@ files (\c .o, \c .obj) files instead of C++ source code. This allows to
embed bigger resources, where compiling to C++ sources and then to
binaries would be too time consuming or memory intensive.
Note that this macro is only available if using \c{CMake} 3.9 or later.
\section1 Arguments
You can set additional \c{OPTIONS} that should be added to the \c{rcc} calls.

View File

@ -0,0 +1,41 @@
/****************************************************************************
**
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the documentation of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:FDL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Free Documentation License Usage
** Alternatively, this file may be used under the terms of the GNU Free
** Documentation License version 1.3 as published by the Free Software
** Foundation and appearing in the file included in the packaging of
** this file. Please review the following information to ensure
** the GNU Free Documentation License version 1.3 requirements
** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
** $QT_END_LICENSE$
**
****************************************************************************/
/*!
\dontdocument (QMacAutoReleasePool QIncompatibleFlag QGenericAtomicOps QAtomicTraits
QAtomicOps QBasicAtomicInteger QBasicAtomicPointer QBasicMutex QInternal
QArgument QReturnArgument QArrayData QTypedArrayData QStaticByteArrayData
QByteRef QStaticStringData QListSpecialMethods QListData QScopedPointerDeleter
QScopedPointerArrayDeleter QScopedPointerPodDeleter QScopedPointerObjectDeleteLater
QMetaTypeId2 QObjectData QObjectUserData QMapNodeBase QMapNode QMapDataBase
QMapData QHashData QHashNode QArrayDataPointer QTextStreamManipulator
QContiguousCacheData QContiguousCacheTypedData QNoDebug QUrlTwoFlags
QCborValueRef qfloat16 QDeferredDeleteEvent QSpecialInteger QLittleEndianStorageType
QBigEndianStorageType QFactoryInterface QFutureWatcherBase QJsonValuePtr
QJsonValueRefPtr QLinkedListNode QAbstractConcatenable QStringBuilderCommon
QTextCodec::ConverterState QThreadStorageData)
*/

View File

@ -1552,6 +1552,13 @@ bool qSharedBuild() noexcept
Defined on Any UNIX BSD/SYSV system.
*/
/*!
\macro Q_OS_WASM
\relates <QtGlobal>
Defined on Web Assembly.
*/
/*!
\macro Q_CC_SYM
\relates <QtGlobal>

View File

@ -432,7 +432,24 @@ void QLibraryInfo::reload()
{
QLibraryInfoPrivate::reload();
}
#endif
void QLibraryInfo::sysrootify(QString *path)
{
if (!QVariant::fromValue(rawLocation(SysrootifyPrefixPath, FinalPaths)).toBool())
return;
const QString sysroot = rawLocation(SysrootPath, FinalPaths);
if (sysroot.isEmpty())
return;
if (path->length() > 2 && path->at(1) == QLatin1Char(':')
&& (path->at(2) == QLatin1Char('/') || path->at(2) == QLatin1Char('\\'))) {
path->replace(0, 2, sysroot); // Strip out the drive on Windows targets
} else {
path->prepend(sysroot);
}
}
#endif // QT_BUILD_QMAKE
/*!
Returns the location specified by \a loc.
@ -444,18 +461,8 @@ QLibraryInfo::location(LibraryLocation loc)
QString ret = rawLocation(loc, FinalPaths);
// Automatically prepend the sysroot to target paths
if (loc < SysrootPath || loc > LastHostPath) {
QString sysroot = rawLocation(SysrootPath, FinalPaths);
if (!sysroot.isEmpty()
&& QVariant::fromValue(rawLocation(SysrootifyPrefixPath, FinalPaths)).toBool()) {
if (ret.length() > 2 && ret.at(1) == QLatin1Char(':')
&& (ret.at(2) == QLatin1Char('/') || ret.at(2) == QLatin1Char('\\'))) {
ret.replace(0, 2, sysroot); // Strip out the drive on Windows targets
} else {
ret.prepend(sysroot);
}
}
}
if (loc < SysrootPath || loc > LastHostPath)
sysrootify(&ret);
return ret;
}
@ -598,6 +605,8 @@ QLibraryInfo::rawLocation(LibraryLocation loc, PathGroup group)
} else {
// we make any other path absolute to the prefix directory
baseDir = rawLocation(PrefixPath, group);
if (group == EffectivePaths)
sysrootify(&baseDir);
}
#else
if (loc == PrefixPath) {

View File

@ -107,6 +107,7 @@ public:
enum PathGroup { FinalPaths, EffectivePaths, EffectiveSourcePaths, DevicePaths };
static QString rawLocation(LibraryLocation, PathGroup);
static void reload();
static void sysrootify(QString *path);
#endif
static QStringList platformPluginArguments(const QString &platformName);

View File

@ -228,7 +228,18 @@ QUrl QFileSelector::select(const QUrl &filePath) const
QString selectedPath = d->select(equivalentPath);
ret.setPath(selectedPath.remove(0, scheme.size()));
} else {
// we need to store the original query and fragment, since toLocalFile() will strip it off
QString frag;
if (ret.hasFragment())
frag = ret.fragment();
QString query;
if (ret.hasQuery())
query= ret.query();
ret = QUrl::fromLocalFile(d->select(ret.toLocalFile()));
if (!frag.isNull())
ret.setFragment(frag);
if (!query.isNull())
ret.setQuery(query);
}
return ret;
}

View File

@ -514,5 +514,36 @@ Q_CONSTRUCTOR_FUNCTION(qt_apple_check_os_version);
// -------------------------------------------------------------------------
void QMacKeyValueObserver::addObserver()
{
[object addObserver:observer forKeyPath:keyPath
options:NSKeyValueObservingOptionNew context:callback.get()];
}
void QMacKeyValueObserver::removeObserver() {
if (object)
[object removeObserver:observer forKeyPath:keyPath context:callback.get()];
object = nil;
}
KeyValueObserver *QMacKeyValueObserver::observer = [[KeyValueObserver alloc] init];
QT_END_NAMESPACE
@implementation KeyValueObserver
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object
change:(NSDictionary<NSKeyValueChangeKey, id> *)change context:(void *)context
{
Q_UNUSED(keyPath);
Q_UNUSED(object);
Q_UNUSED(change);
(*reinterpret_cast<QMacKeyValueObserver::Callback*>(context))();
}
@end
QT_BEGIN_NAMESPACE
// -------------------------------------------------------------------------
QT_END_NAMESPACE

View File

@ -67,6 +67,7 @@
#ifdef __OBJC__
#include <Foundation/Foundation.h>
#include <functional>
#endif
#include "qstring.h"
@ -295,13 +296,13 @@ QT_MAC_WEAK_IMPORT(_os_activity_current);
// -------------------------------------------------------------------------
#if defined( __OBJC__)
class QMacScopedObserver
class QMacNotificationObserver
{
public:
QMacScopedObserver() {}
QMacNotificationObserver() {}
template<typename Functor>
QMacScopedObserver(id object, NSNotificationName name, Functor callback) {
QMacNotificationObserver(id object, NSNotificationName name, Functor callback) {
observer = [[NSNotificationCenter defaultCenter] addObserverForName:name
object:object queue:nil usingBlock:^(NSNotification *) {
callback();
@ -309,13 +310,13 @@ public:
];
}
QMacScopedObserver(const QMacScopedObserver& other) = delete;
QMacScopedObserver(QMacScopedObserver&& other) : observer(other.observer) {
QMacNotificationObserver(const QMacNotificationObserver& other) = delete;
QMacNotificationObserver(QMacNotificationObserver&& other) : observer(other.observer) {
other.observer = nil;
}
QMacScopedObserver &operator=(const QMacScopedObserver& other) = delete;
QMacScopedObserver &operator=(QMacScopedObserver&& other) {
QMacNotificationObserver &operator=(const QMacNotificationObserver& other) = delete;
QMacNotificationObserver &operator=(QMacNotificationObserver&& other) {
if (this != &other) {
remove();
observer = other.observer;
@ -329,11 +330,65 @@ public:
[[NSNotificationCenter defaultCenter] removeObserver:observer];
observer = nil;
}
~QMacScopedObserver() { remove(); }
~QMacNotificationObserver() { remove(); }
private:
id observer = nil;
};
QT_END_NAMESPACE
@interface QT_MANGLE_NAMESPACE(KeyValueObserver) : NSObject
@end
QT_NAMESPACE_ALIAS_OBJC_CLASS(KeyValueObserver);
QT_BEGIN_NAMESPACE
class Q_CORE_EXPORT QMacKeyValueObserver
{
public:
using Callback = std::function<void()>;
QMacKeyValueObserver() {}
// Note: QMacKeyValueObserver must not outlive the object observed!
QMacKeyValueObserver(id object, NSString *keyPath, Callback callback)
: object(object), keyPath(keyPath), callback(new Callback(callback)) { addObserver(); }
QMacKeyValueObserver(const QMacKeyValueObserver &other)
: QMacKeyValueObserver(other.object, other.keyPath, *other.callback.get()) {}
QMacKeyValueObserver(QMacKeyValueObserver &&other) { swap(other, *this); }
~QMacKeyValueObserver() { removeObserver(); }
QMacKeyValueObserver &operator=(const QMacKeyValueObserver &other) {
QMacKeyValueObserver tmp(other);
swap(tmp, *this);
return *this;
}
QMacKeyValueObserver &operator=(QMacKeyValueObserver &&other) {
QMacKeyValueObserver tmp(std::move(other));
swap(tmp, *this);
return *this;
}
void removeObserver();
private:
void swap(QMacKeyValueObserver &first, QMacKeyValueObserver &second) {
std::swap(first.object, second.object);
std::swap(first.keyPath, second.keyPath);
std::swap(first.callback, second.callback);
}
void addObserver();
id object = nil;
NSString *keyPath = nullptr;
std::unique_ptr<Callback> callback;
static KeyValueObserver *observer;
};
#endif
// -------------------------------------------------------------------------

View File

@ -120,6 +120,7 @@
#ifdef Q_OS_WASM
#include <emscripten.h>
#include <emscripten/val.h>
#endif
#ifdef QT_BOOTSTRAPPED
@ -799,6 +800,10 @@ void QCoreApplicationPrivate::init()
Module.print(err);
});
);
#if QT_CONFIG(thread)
QThreadPrivate::idealThreadCount = emscripten::val::global("navigator")["hardwareConcurrency"].as<int>();
#endif
#endif
// Store app name/version (so they're still available after QCoreApplication is destroyed)

View File

@ -119,6 +119,7 @@ public:
class Q_CORE_EXPORT QObject
{
Q_OBJECT
Q_PROPERTY(QString objectName READ objectName WRITE setObjectName NOTIFY objectNameChanged)
Q_DECLARE_PRIVATE(QObject)
@ -129,7 +130,7 @@ public:
virtual bool event(QEvent *event);
virtual bool eventFilter(QObject *watched, QEvent *event);
#if defined(QT_NO_TRANSLATION)
#if defined(QT_NO_TRANSLATION) || defined(Q_CLANG_QDOC)
static QString tr(const char *sourceText, const char * = nullptr, int = -1)
{ return QString::fromUtf8(sourceText); }
#if QT_DEPRECATED_SINCE(5, 0)

View File

@ -138,6 +138,10 @@ class QString;
# define QT_TR_FUNCTIONS
#endif
#ifdef Q_CLANG_QDOC
#define QT_TR_FUNCTIONS
#endif
// ### Qt6: remove
#define Q_OBJECT_CHECK /* empty, unused since Qt 5.2 */

View File

@ -195,6 +195,9 @@ public:
int waiters;
bool terminationEnabled, terminatePending;
#endif // Q_OS_WIN
#ifdef Q_OS_WASM
static int idealThreadCount;
#endif
QThreadData *data;
static QAbstractEventDispatcher *createEventDispatcher(QThreadData *data);

View File

@ -100,10 +100,6 @@
#include <sys/neutrino.h>
#endif
#if defined(Q_OS_WASM)
#include <emscripten/val.h>
#endif
QT_BEGIN_NAMESPACE
#if QT_CONFIG(thread)
@ -457,6 +453,10 @@ Qt::HANDLE QThread::currentThreadId() noexcept
# define _SC_NPROCESSORS_ONLN 84
#endif
#ifdef Q_OS_WASM
int QThreadPrivate::idealThreadCount = 1;
#endif
int QThread::idealThreadCount() noexcept
{
int cores = 1;
@ -506,7 +506,7 @@ int QThread::idealThreadCount() noexcept
cores = 1;
# endif
#elif defined(Q_OS_WASM)
cores = emscripten::val::global("navigator")["hardwareConcurrency"].as<int>();
cores = QThreadPrivate::idealThreadCount;
#else
// the rest: Linux, Solaris, AIX, Tru64
cores = (int)sysconf(_SC_NPROCESSORS_ONLN);

View File

@ -334,19 +334,17 @@ static constexpr int daysInUsualMonth(int month) // (February isn't usual.)
\brief The QDate class provides date functions.
A QDate object encodes a calendar date, i.e. year, month, and day numbers,
in the proleptic Gregorian calendar by default. It can read the current date
from the system clock. It provides functions for comparing dates, and for
manipulating dates. For example, it is possible to add and subtract days,
months, and years to dates.
A QDate object represents a particular date. This can be expressed as a
calendar date, i.e. year, month, and day numbers, in the proleptic Gregorian
calendar.
A QDate object is typically created by giving the year, month, and day
numbers explicitly. Note that QDate interprets two digit years as presented,
i.e., as years 0 through 99, without adding any offset. A QDate can also be
constructed with the static function currentDate(), which creates a QDate
object containing the system clock's date. An explicit date can also be set
using setDate(). The fromString() function returns a QDate given a string
and a date format which is used to interpret the date within the string.
numbers explicitly. Note that QDate interprets year numbers less than 100 as
presented, i.e., as years 1 through 99, without adding any offset. The
static function currentDate() creates a QDate object containing the date
read from the system clock. An explicit date can also be set using
setDate(). The fromString() function returns a QDate given a string and a
date format which is used to interpret the date within the string.
The year(), month(), and day() functions provide access to the
year, month, and day numbers. Also, dayOfWeek() and dayOfYear()
@ -380,7 +378,7 @@ static constexpr int daysInUsualMonth(int month) // (February isn't usual.)
every day in a contiguous range, with 24 November 4714 BCE in the Gregorian
calendar being Julian Day 0 (1 January 4713 BCE in the Julian calendar).
As well as being an efficient and accurate way of storing an absolute date,
it is suitable for converting a Date into other calendar systems such as
it is suitable for converting a date into other calendar systems such as
Hebrew, Islamic or Chinese. The Julian Day number can be obtained using
QDate::toJulianDay() and can be set using QDate::fromJulianDay().
@ -1693,12 +1691,10 @@ bool QDate::isLeapYear(int y)
Unlike QDateTime, QTime knows nothing about time zones or
daylight-saving time (DST).
A QTime object is typically created either by giving the number
of hours, minutes, seconds, and milliseconds explicitly, or by
using the static function currentTime(), which creates a QTime
object that contains the system's local time. Note that the
accuracy depends on the accuracy of the underlying operating
system; not all systems provide 1-millisecond accuracy.
A QTime object is typically created either by giving the number of hours,
minutes, seconds, and milliseconds explicitly, or by using the static
function currentTime(), which creates a QTime object that represents the
system's local time.
The hour(), minute(), second(), and msec() functions provide
access to the number of hours, minutes, seconds, and milliseconds
@ -2155,6 +2151,12 @@ int QTime::msecsTo(const QTime &t) const
Note that the accuracy depends on the accuracy of the underlying
operating system; not all systems provide 1-millisecond accuracy.
Furthermore, currentTime() only increases within each day; it shall drop by
24 hours each time midnight passes; and, beside this, changes in it may not
correspond to elapsed time, if a daylight-saving transition intervenes.
\sa QDateTime::currentDateTime(), QDateTime::currentDateTimeUtc()
*/
#if QT_CONFIG(datestring)
@ -3270,15 +3272,30 @@ inline qint64 QDateTimePrivate::zoneMSecsToEpochMSecs(qint64 zoneMSecs, const QT
provides functions for comparing datetimes and for manipulating a
datetime by adding a number of seconds, days, months, or years.
A QDateTime object is typically created either by giving a date
and time explicitly in the constructor, or by using the static
function currentDateTime() that returns a QDateTime object set
to the system clock's time. The date and time can be changed with
setDate() and setTime(). A datetime can also be set using the
setTime_t() function that takes a POSIX-standard "number of
seconds since 00:00:00 on January 1, 1970" value. The fromString()
function returns a QDateTime, given a string and a date format
used to interpret the date within the string.
QDateTime can describe datetimes with respect to \l{Qt::LocalTime}{local
time}, to \l{Qt::UTC}{UTC}, to a specified \l{Qt::OffsetFromUTC}{offset
from UTC} or to a specified \l{{Qt::TimeZone}{time zone}, in conjunction
with the QTimeZone class. For example, a time zone of "Europe/Berlin" will
apply the daylight-saving rules as used in Germany since 1970. In contrast,
an offset from UTC of +3600 seconds is one hour ahead of UTC (usually
written in ISO standard notation as "UTC+01:00"), with no daylight-saving
offset or changes. When using either local time or a specified time zone,
time-zone transitions such as the starts and ends of daylight-saving time
(DST) are taken into account. The choice of system used to represent a
datetime is described as its "timespec".
A QDateTime object is typically created either by giving a date and time
explicitly in the constructor, or by using a static function such as
currentDateTime() or fromMSecsSinceEpoch(). The date and time can be changed
with setDate() and setTime(). A datetime can also be set using the
setMSecsSinceEpoch() function that takes the time, in milliseconds, since
00:00:00 on January 1, 1970. The fromString() function returns a QDateTime,
given a string and a date format used to interpret the date within the
string.
QDateTime::currentDateTime() returns a QDateTime that expresses the current
time with respect to local time. QDateTime::currentDateTimeUtc() returns a
QDateTime that expresses the current time with respect to UTC.
The date() and time() functions provide access to the date and
time parts of the datetime. The same information is provided in
@ -3289,18 +3306,20 @@ inline qint64 QDateTimePrivate::zoneMSecsToEpochMSecs(qint64 zoneMSecs, const QT
later.
You can increment (or decrement) a datetime by a given number of
milliseconds using addMSecs(), seconds using addSecs(), or days
using addDays(). Similarly, you can use addMonths() and addYears().
The daysTo() function returns the number of days between two datetimes,
secsTo() returns the number of seconds between two datetimes, and
msecsTo() returns the number of milliseconds between two datetimes.
milliseconds using addMSecs(), seconds using addSecs(), or days using
addDays(). Similarly, you can use addMonths() and addYears(). The daysTo()
function returns the number of days between two datetimes, secsTo() returns
the number of seconds between two datetimes, and msecsTo() returns the
number of milliseconds between two datetimes. These operations are aware of
daylight-saving time (DST) and other time-zone transitions, where
applicable.
QDateTime can store datetimes as \l{Qt::LocalTime}{local time} or
as \l{Qt::UTC}{UTC}. QDateTime::currentDateTime() returns a
QDateTime expressed as local time; use toUTC() to convert it to
UTC. You can also use timeSpec() to find out if a QDateTime
object stores a UTC time or a local time. Operations such as
addSecs() and secsTo() are aware of daylight-saving time (DST).
Use toTimeSpec() to express a datetime in local time or UTC,
toOffsetFromUtc() to express in terms of an offset from UTC, or toTimeZone()
to express it with respect to a general time zone. You can use timeSpec() to
find out what time-spec a QDateTime object stores its time relative to. When
that is Qt::TimeZone, you can use timeZone() to find out which zone it is
using.
\note QDateTime does not account for leap seconds.
@ -3314,67 +3333,55 @@ inline qint64 QDateTimePrivate::zoneMSecsToEpochMSecs(qint64 zoneMSecs, const QT
\section2 Range of Valid Dates
The range of valid values able to be stored in QDateTime is dependent on
the internal storage implementation. QDateTime is currently stored in a
qint64 as a serial msecs value encoding the date and time. This restricts
the date range to about +/- 292 million years, compared to the QDate range
of +/- 2 billion years. Care must be taken when creating a QDateTime with
extreme values that you do not overflow the storage. The exact range of
supported values varies depending on the Qt::TimeSpec and time zone.
The range of values that QDateTime can represent is dependent on the
internal storage implementation. QDateTime is currently stored in a qint64
as a serial msecs value encoding the date and time. This restricts the date
range to about +/- 292 million years, compared to the QDate range of +/- 2
billion years. Care must be taken when creating a QDateTime with extreme
values that you do not overflow the storage. The exact range of supported
values varies depending on the Qt::TimeSpec and time zone.
\section2 Use of System Timezone
\section2 Use of Timezones
QDateTime uses the system's time zone information to determine the
offset of local time from UTC. If the system is not configured
correctly or not up-to-date, QDateTime will give wrong results as
well.
QDateTime uses the system's time zone information to determine the current
local time zone and its offset from UTC. If the system is not configured
correctly or not up-to-date, QDateTime will give wrong results.
QDateTime likewise uses system-provided information to determine the offsets
of other timezones from UTC. If this information is incomplete or out of
date, QDateTime will give wrong results. See the QTimeZone documentation for
more details.
On modern Unix systems, this means QDateTime usually has accurate
information about historical transitions (including DST, see below) whenever
possible. On Windows, where the system doesn't support historical timezone
data, historical accuracy is not maintained with respect to timezone
transitions, notably including DST.
\section2 Daylight-Saving Time (DST)
QDateTime takes into account the system's time zone information
when dealing with DST. On modern Unix systems, this means it
applies the correct historical DST data whenever possible. On
Windows, where the system doesn't support historical DST data,
historical accuracy is not maintained with respect to DST.
QDateTime takes into account transitions between Standard Time and
Daylight-Saving Time. For example, if the transition is at 2am and the clock
goes forward to 3am, then there is a "missing" hour from 02:00:00 to
02:59:59.999 which QDateTime considers to be invalid. Any date arithmetic
performed will take this missing hour into account and return a valid
result. For example, adding one minute to 01:59:59 will get 03:00:00.
The range of valid dates taking DST into account is 1970-01-01 to
the present, and rules are in place for handling DST correctly
until 2037-12-31, but these could change. For dates falling
outside that range, QDateTime makes a \e{best guess} using the
rules for year 1970 or 2037, but we can't guarantee accuracy. This
means QDateTime doesn't take into account changes in a locale's
time zone before 1970, even if the system's time zone database
supports that information.
The range of valid dates taking DST into account is 1970-01-01 to the
present, and rules are in place for handling DST correctly until 2037-12-31,
but these could change. For dates falling outside that range, QDateTime
makes a \e{best guess} using the rules for year 1970 or 2037, but we can't
guarantee accuracy. This means QDateTime doesn't take into account changes
in a time zone before 1970, even if the system's time zone database provides
that information.
QDateTime takes into consideration the Standard Time to Daylight-Saving Time
transition. For example if the transition is at 2am and the clock goes
forward to 3am, then there is a "missing" hour from 02:00:00 to 02:59:59.999
which QDateTime considers to be invalid. Any date maths performed
will take this missing hour into account and return a valid result.
\section2 Offsets From UTC
\section2 Offset From UTC
A Qt::TimeSpec of Qt::OffsetFromUTC is also supported. This allows you
to define a QDateTime relative to UTC at a fixed offset of a given number
of seconds from UTC. For example, an offset of +3600 seconds is one hour
ahead of UTC and is usually written in ISO standard notation as
"UTC+01:00". Daylight-Saving Time never applies with this TimeSpec.
There is no explicit size restriction to the offset seconds, but there is
an implicit limit imposed when using the toString() and fromString()
methods which use a format of [+|-]hh:mm, effectively limiting the range
to +/- 99 hours and 59 minutes and whole minutes only. Note that currently
no time zone lies outside the range of +/- 14 hours.
\section2 Time Zone Support
A Qt::TimeSpec of Qt::TimeZone is also supported in conjunction with the
QTimeZone class. This allows you to define a datetime in a named time zone
adhering to a consistent set of daylight-saving transition rules. For
example a time zone of "Europe/Berlin" will apply the daylight-saving
rules as used in Germany since 1970. Note that the transition rules
applied depend on the platform support. See the QTimeZone documentation
for more details.
There is no explicit size restriction on an offset from UTC, but there is an
implicit limit imposed when using the toString() and fromString() methods
which use a [+|-]hh:mm format, effectively limiting the range to +/- 99
hours and 59 minutes and whole minutes only. Note that currently no time
zone lies outside the range of +/- 14 hours.
\sa QDate, QTime, QDateTimeEdit, QTimeZone
*/
@ -4497,7 +4504,7 @@ qint64 QDateTime::msecsTo(const QDateTime &other) const
Example:
\snippet code/src_corelib_tools_qdatetime.cpp 16
\sa timeSpec(), toTimeZone(), toUTC(), toLocalTime()
\sa timeSpec(), toTimeZone(), toOffsetFromUtc()
*/
QDateTime QDateTime::toTimeSpec(Qt::TimeSpec spec) const

View File

@ -50,6 +50,12 @@
#include <qdebug.h>
#include <algorithm>
#include <errno.h>
#include <limits.h>
#if !defined(Q_OS_INTEGRITY)
#include <sys/param.h> // to use MAXSYMLINKS constant
#endif
#include <unistd.h> // to use _SC_SYMLOOP_MAX constant
QT_BEGIN_NAMESPACE
@ -1057,6 +1063,27 @@ QTimeZonePrivate::Data QTzTimeZonePrivate::previousTransition(qint64 beforeMSecs
return last > m_tranTimes.cbegin() ? dataForTzTransition(*--last) : invalidData();
}
static long getSymloopMax()
{
#if defined(SYMLOOP_MAX)
return SYMLOOP_MAX; // if defined, at runtime it can only be greater than this, so this is a safe bet
#else
errno = 0;
long result = sysconf(_SC_SYMLOOP_MAX);
if (result >= 0)
return result;
// result is -1, meaning either error or no limit
Q_ASSERT(!errno); // ... but it can't be an error, POSIX mandates _SC_SYMLOOP_MAX
// therefore we can make up our own limit
# if defined(MAXSYMLINKS)
return MAXSYMLINKS;
# else
return 8;
# endif
#endif
}
// TODO Could cache the value and monitor the required files for any changes
QByteArray QTzTimeZonePrivate::systemTimeZoneId() const
{
@ -1074,12 +1101,18 @@ QByteArray QTzTimeZonePrivate::systemTimeZoneId() const
// On most distros /etc/localtime is a symlink to a real file so extract name from the path
if (ianaId.isEmpty()) {
const QString path = QFile::symLinkTarget(QStringLiteral("/etc/localtime"));
if (!path.isEmpty()) {
const QLatin1String zoneinfo("/zoneinfo/");
QString path = QFile::symLinkTarget(QStringLiteral("/etc/localtime"));
int index = -1;
long iteration = getSymloopMax();
// Symlink may point to another symlink etc. before being under zoneinfo/
// We stop on the first path under /zoneinfo/, even if it is itself a
// symlink, like America/Montreal pointing to America/Toronto
while (iteration-- > 0 && !path.isEmpty() && (index = path.indexOf(zoneinfo)) < 0)
path = QFile::symLinkTarget(path);
if (index >= 0) {
// /etc/localtime is a symlink to the current TZ file, so extract from path
int index = path.indexOf(QLatin1String("/zoneinfo/"));
if (index != -1)
ianaId = path.mid(index + 10).toUtf8();
ianaId = path.mid(index + zoneinfo.size()).toUtf8();
}
}

View File

@ -822,7 +822,7 @@ static QString wc2rx(const QString &wc_str, const bool enableEscaping)
if (wc[i] == QLatin1Char('^'))
rx += wc[i++];
if (i < wclen) {
if (rx[i] == QLatin1Char(']'))
if (wc[i] == QLatin1Char(']'))
rx += wc[i++];
while (i < wclen && wc[i] != QLatin1Char(']')) {
if (wc[i] == QLatin1Char('\\'))

View File

@ -0,0 +1,30 @@
/****************************************************************************
**
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the documentation of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:FDL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Free Documentation License Usage
** Alternatively, this file may be used under the terms of the GNU Free
** Documentation License version 1.3 as published by the Free Software
** Foundation and appearing in the file included in the packaging of
** this file. Please review the following information to ensure
** the GNU Free Documentation License version 1.3 requirements
** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
** $QT_END_LICENSE$
**
****************************************************************************/
/*!
\dontdocument (QTypeInfo QMetaTypeId QDBusAbstractInterfaceBase QDBusPendingReplyData QMetaTypeId2)
*/

View File

@ -52,6 +52,7 @@
QPainter painter(this);
painter.setPen(Qt::darkGreen);
// Using the (x y w h) overload
painter.drawRect(1, 2, 6, 4);
//! [0]
@ -69,6 +70,7 @@ QPainter painter(this);
painter.setRenderHint(
QPainter::Antialiasing);
painter.setPen(Qt::darkGreen);
// Using the (x y w h) overload
painter.drawRect(1, 2, 6, 4);
//! [2]

View File

@ -70,8 +70,15 @@
\li \inlineimage coordinatesystem-rect.png
\li \inlineimage coordinatesystem-line.png
\row
\li QRect(1, 2, 6, 4)
\li QRect(QPoint(1, 2), QPoint(7, 6))
\li QLine(QPoint(2, 7), QPoint(6, 1))
\row
\li
\li QLine(2, 7, 6, 1)
\row
\li QRect(QPoint(1, 2), QSize(6, 4))
\row
\li QRect(1, 2, 6, 4)
\endtable
\section2 Aliased Painting

View File

@ -0,0 +1,66 @@
/****************************************************************************
**
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the documentation of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:FDL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Free Documentation License Usage
** Alternatively, this file may be used under the terms of the GNU Free
** Documentation License version 1.3 as published by the Free Software
** Foundation and appearing in the file included in the packaging of
** this file. Please review the following information to ensure
** the GNU Free Documentation License version 1.3 requirements
** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
** $QT_END_LICENSE$
**
****************************************************************************/
/*!
\dontdocument (QTypeInfo QScreenOrientationChangeEvent QApplicationStateChangeEvent
QImageTextKeyLang QMetaTypeId QAbstractUndoItem
QOpenGLVersionStatus
QOpenGLVersionFunctionsBackend
QOpenGLVersionFunctionsStorage
QOpenGLFunctions_1_0_CoreBackend
QOpenGLFunctions_1_1_CoreBackend
QOpenGLFunctions_1_2_CoreBackend
QOpenGLFunctions_1_3_CoreBackend
QOpenGLFunctions_1_4_CoreBackend
QOpenGLFunctions_1_5_CoreBackend
QOpenGLFunctions_2_0_CoreBackend
QOpenGLFunctions_2_1_CoreBackend
QOpenGLFunctions_3_0_CoreBackend
QOpenGLFunctions_3_1_CoreBackend
QOpenGLFunctions_3_2_CoreBackend
QOpenGLFunctions_3_3_CoreBackend
QOpenGLFunctions_4_0_CoreBackend
QOpenGLFunctions_4_1_CoreBackend
QOpenGLFunctions_4_2_CoreBackend
QOpenGLFunctions_4_3_CoreBackend
QOpenGLFunctions_4_4_CoreBackend
QOpenGLFunctions_4_5_CoreBackend
QOpenGLFunctions_1_0_DeprecatedBackend
QOpenGLFunctions_1_1_DeprecatedBackend
QOpenGLFunctions_1_2_DeprecatedBackend
QOpenGLFunctions_1_3_DeprecatedBackend
QOpenGLFunctions_1_4_DeprecatedBackend
QOpenGLFunctions_2_0_DeprecatedBackend
QOpenGLFunctions_3_0_DeprecatedBackend
QOpenGLFunctions_3_3_DeprecatedBackend
QOpenGLFunctions_4_5_DeprecatedBackend
QTextFrameLayoutData QPlatformDropQtResponse QPlatformDragQtResponse
QPlatformOffscreenSurface QColorDialogOptions QFontDialogOptions
QFileDialogOptions QMessageDialogOptions QMessageDialogOptions::CustomButton
QPlatformSessionManager QPlatformIntegrationPlugin QPlatformMenuItem
QPlatformMenu QPlatformMenuBar QPlatformTextureList)
*/

View File

@ -97,35 +97,35 @@ QEnterEvent::~QEnterEvent()
/*!
\fn QPoint QEnterEvent::globalPos() const
Returns the global position of the widget \e{at the time of the event}.
Returns the global position of the mouse cursor \e{at the time of the event}.
*/
/*!
\fn int QEnterEvent::globalX() const
Returns the global position on the X-axis of the mouse cursor relative to the the widget.
Returns the global position on the X-axis of the mouse cursor \e{at the time of the event}.
*/
/*!
\fn int QEnterEvent::globalY() const
Returns the global position on the Y-axis of the mouse cursor relative to the the widget.
Returns the global position on the Y-axis of the mouse cursor \e{at the time of the event}.
*/
/*!
\fn QPoint QEnterEvent::localPos() const
\fn QPointF QEnterEvent::localPos() const
Returns the mouse cursor's position relative to the receiving widget.
*/
/*!
\fn QPoint QEnterEvent::pos() const
Returns the position of the mouse cursor in global screen coordinates.
Returns the position of the mouse cursor relative to the receiving widget.
*/
/*!
\fn QPoint QEnterEvent::screenPos() const
\fn QPointF QEnterEvent::screenPos() const
Returns the position of the mouse cursor relative to the receiving screen.
*/
/*!
\fn QPoint QEnterEvent::windowPos() const
\fn QPointF QEnterEvent::windowPos() const
Returns the position of the mouse cursor relative to the receiving window.
*/

View File

@ -440,7 +440,7 @@ void QOpenGLWindow::makeCurrent()
d->context->makeCurrent(this);
} else {
if (!d->offscreenSurface) {
d->offscreenSurface.reset(new QOffscreenSurface);
d->offscreenSurface.reset(new QOffscreenSurface(screen()));
d->offscreenSurface->setFormat(d->context->format());
d->offscreenSurface->create();
}

View File

@ -1008,6 +1008,8 @@ QDataStream &operator<<(QDataStream &s, const QPalette &p)
max = QPalette::HighlightedText + 1;
else if (s.version() <= QDataStream::Qt_4_3)
max = QPalette::AlternateBase + 1;
else if (s.version() <= QDataStream::Qt_5_11)
max = QPalette::ToolTipText + 1;
for (int r = 0; r < max; r++)
s << p.d->br[grp][r];
}
@ -1048,6 +1050,9 @@ QDataStream &operator>>(QDataStream &s, QPalette &p)
} else if (s.version() <= QDataStream::Qt_4_3) {
p = QPalette();
max = QPalette::AlternateBase + 1;
} else if (s.version() <= QDataStream::Qt_5_11) {
p = QPalette();
max = QPalette::ToolTipText + 1;
}
QBrush tmp;

View File

@ -218,6 +218,12 @@ QWindow::~QWindow()
QGuiApplicationPrivate::window_list.removeAll(this);
if (!QGuiApplicationPrivate::is_app_closing)
QGuiApplicationPrivate::instance()->modalWindowList.removeOne(this);
// focus_window is normally cleared in destroy(), but the window may in
// some cases end up becoming the focus window again. Clear it again
// here as a workaround. See QTBUG-75326.
if (QGuiApplicationPrivate::focus_window == this)
QGuiApplicationPrivate::focus_window = 0;
}
void QWindowPrivate::init(QScreen *targetScreen)

View File

@ -71,6 +71,24 @@
QT_BEGIN_NAMESPACE
static inline bool isValidCoord(qreal c)
{
if (sizeof(qreal) >= sizeof(double))
return qIsFinite(c) && fabs(c) < 1e128;
else
return qIsFinite(c) && fabsf(float(c)) < 1e16f;
}
static bool hasValidCoords(QPointF p)
{
return isValidCoord(p.x()) && isValidCoord(p.y());
}
static bool hasValidCoords(QRectF r)
{
return isValidCoord(r.x()) && isValidCoord(r.y()) && isValidCoord(r.width()) && isValidCoord(r.height());
}
struct QPainterPathPrivateDeleter
{
static inline void cleanup(QPainterPathPrivate *d)
@ -724,9 +742,9 @@ void QPainterPath::moveTo(const QPointF &p)
printf("QPainterPath::moveTo() (%.2f,%.2f)\n", p.x(), p.y());
#endif
if (!qt_is_finite(p.x()) || !qt_is_finite(p.y())) {
if (!hasValidCoords(p)) {
#ifndef QT_NO_DEBUG
qWarning("QPainterPath::moveTo: Adding point where x or y is NaN or Inf, ignoring call");
qWarning("QPainterPath::moveTo: Adding point with invalid coordinates, ignoring call");
#endif
return;
}
@ -774,9 +792,9 @@ void QPainterPath::lineTo(const QPointF &p)
printf("QPainterPath::lineTo() (%.2f,%.2f)\n", p.x(), p.y());
#endif
if (!qt_is_finite(p.x()) || !qt_is_finite(p.y())) {
if (!hasValidCoords(p)) {
#ifndef QT_NO_DEBUG
qWarning("QPainterPath::lineTo: Adding point where x or y is NaN or Inf, ignoring call");
qWarning("QPainterPath::lineTo: Adding point with invalid coordinates, ignoring call");
#endif
return;
}
@ -833,10 +851,9 @@ void QPainterPath::cubicTo(const QPointF &c1, const QPointF &c2, const QPointF &
c1.x(), c1.y(), c2.x(), c2.y(), e.x(), e.y());
#endif
if (!qt_is_finite(c1.x()) || !qt_is_finite(c1.y()) || !qt_is_finite(c2.x()) || !qt_is_finite(c2.y())
|| !qt_is_finite(e.x()) || !qt_is_finite(e.y())) {
if (!hasValidCoords(c1) || !hasValidCoords(c2) || !hasValidCoords(e)) {
#ifndef QT_NO_DEBUG
qWarning("QPainterPath::cubicTo: Adding point where x or y is NaN or Inf, ignoring call");
qWarning("QPainterPath::cubicTo: Adding point with invalid coordinates, ignoring call");
#endif
return;
}
@ -890,9 +907,9 @@ void QPainterPath::quadTo(const QPointF &c, const QPointF &e)
c.x(), c.y(), e.x(), e.y());
#endif
if (!qt_is_finite(c.x()) || !qt_is_finite(c.y()) || !qt_is_finite(e.x()) || !qt_is_finite(e.y())) {
if (!hasValidCoords(c) || !hasValidCoords(e)) {
#ifndef QT_NO_DEBUG
qWarning("QPainterPath::quadTo: Adding point where x or y is NaN or Inf, ignoring call");
qWarning("QPainterPath::quadTo: Adding point with invalid coordinates, ignoring call");
#endif
return;
}
@ -961,10 +978,9 @@ void QPainterPath::arcTo(const QRectF &rect, qreal startAngle, qreal sweepLength
rect.x(), rect.y(), rect.width(), rect.height(), startAngle, sweepLength);
#endif
if ((!qt_is_finite(rect.x()) && !qt_is_finite(rect.y())) || !qt_is_finite(rect.width()) || !qt_is_finite(rect.height())
|| !qt_is_finite(startAngle) || !qt_is_finite(sweepLength)) {
if (!hasValidCoords(rect) || !isValidCoord(startAngle) || !isValidCoord(sweepLength)) {
#ifndef QT_NO_DEBUG
qWarning("QPainterPath::arcTo: Adding arc where a parameter is NaN or Inf, ignoring call");
qWarning("QPainterPath::arcTo: Adding point with invalid coordinates, ignoring call");
#endif
return;
}
@ -1067,9 +1083,9 @@ QPointF QPainterPath::currentPosition() const
*/
void QPainterPath::addRect(const QRectF &r)
{
if (!qt_is_finite(r.x()) || !qt_is_finite(r.y()) || !qt_is_finite(r.width()) || !qt_is_finite(r.height())) {
if (!hasValidCoords(r)) {
#ifndef QT_NO_DEBUG
qWarning("QPainterPath::addRect: Adding rect where a parameter is NaN or Inf, ignoring call");
qWarning("QPainterPath::addRect: Adding point with invalid coordinates, ignoring call");
#endif
return;
}
@ -1147,10 +1163,9 @@ void QPainterPath::addPolygon(const QPolygonF &polygon)
*/
void QPainterPath::addEllipse(const QRectF &boundingRect)
{
if (!qt_is_finite(boundingRect.x()) || !qt_is_finite(boundingRect.y())
|| !qt_is_finite(boundingRect.width()) || !qt_is_finite(boundingRect.height())) {
if (!hasValidCoords(boundingRect)) {
#ifndef QT_NO_DEBUG
qWarning("QPainterPath::addEllipse: Adding ellipse where a parameter is NaN or Inf, ignoring call");
qWarning("QPainterPath::addEllipse: Adding point with invalid coordinates, ignoring call");
#endif
return;
}
@ -2501,6 +2516,7 @@ QDataStream &operator<<(QDataStream &s, const QPainterPath &p)
*/
QDataStream &operator>>(QDataStream &s, QPainterPath &p)
{
bool errorDetected = false;
int size;
s >> size;
@ -2519,10 +2535,11 @@ QDataStream &operator>>(QDataStream &s, QPainterPath &p)
s >> x;
s >> y;
Q_ASSERT(type >= 0 && type <= 3);
if (!qt_is_finite(x) || !qt_is_finite(y)) {
if (!isValidCoord(qreal(x)) || !isValidCoord(qreal(y))) {
#ifndef QT_NO_DEBUG
qWarning("QDataStream::operator>>: NaN or Inf element found in path, skipping it");
qWarning("QDataStream::operator>>: Invalid QPainterPath coordinates read, skipping it");
#endif
errorDetected = true;
continue;
}
QPainterPath::Element elm = { qreal(x), qreal(y), QPainterPath::ElementType(type) };
@ -2535,6 +2552,8 @@ QDataStream &operator>>(QDataStream &s, QPainterPath &p)
p.d_func()->fillRule = Qt::FillRule(fillRule);
p.d_func()->dirtyBounds = true;
p.d_func()->dirtyControlBounds = true;
if (errorDetected)
p = QPainterPath(); // Better than to return path with possibly corrupt datastructure, which would likely cause crash
return s;
}
#endif // QT_NO_DATASTREAM

View File

@ -3044,7 +3044,7 @@ void QFontCache::decreaseCache()
it.value().data->ref.load(), engineCacheCount.value(it.value().data),
it.value().data->cache_cost);
if (it.value().data->ref.load() != 0)
if (it.value().data->ref.load() > engineCacheCount.value(it.value().data))
in_use_cost += it.value().data->cache_cost / engineCacheCount.value(it.value().data);
}

View File

@ -695,7 +695,8 @@ static QStringList familyList(const QFontDef &req)
if ((str.startsWith(QLatin1Char('"')) && str.endsWith(QLatin1Char('"')))
|| (str.startsWith(QLatin1Char('\'')) && str.endsWith(QLatin1Char('\''))))
str = str.mid(1, str.length() - 2);
family_list << str.toString();
if (!family_list.contains(str))
family_list << str.toString();
}
}
// append the substitute list for each family in family_list

View File

@ -1364,6 +1364,8 @@ QTextCursor QTextDocument::find(const QString &subString, int from, FindFlags op
blockOffset = 0;
}
} else {
if (blockOffset == block.length() - 1)
--blockOffset; // make sure to skip end-of-paragraph character
while (block.isValid()) {
if (findInBlock(block, subString, blockOffset, options, &cursor))
return cursor;

View File

@ -973,8 +973,14 @@ void QTextDocumentLayoutPrivate::drawFrame(const QPointF &offset, QPainter *pain
if (pageHeight <= 0)
pageHeight = QFIXED_MAX;
const int tableStartPage = (td->position.y / pageHeight).truncate();
const int tableEndPage = ((td->position.y + td->size.height) / pageHeight).truncate();
QFixed absYPos = td->position.y;
QTextFrame *parentFrame = table->parentFrame();
while (parentFrame) {
absYPos += data(parentFrame)->position.y;
parentFrame = parentFrame->parentFrame();
}
const int tableStartPage = (absYPos / pageHeight).truncate();
const int tableEndPage = ((absYPos + td->size.height) / pageHeight).truncate();
qreal border = td->border.toReal();
drawFrameDecoration(painter, frame, fd, context.clip, frameRect);

View File

@ -59,6 +59,9 @@ using namespace emscripten;
static void q_requestErrorCallback(val event)
{
if (event.isNull() || event.isUndefined())
return;
val xhr = event["target"];
quintptr func = xhr["data-handler"].as<quintptr>();
@ -77,19 +80,24 @@ static void q_requestErrorCallback(val event)
static void q_progressCallback(val event)
{
if (event.isNull() || event.isUndefined())
return;
val xhr = event["target"];
QNetworkReplyWasmImplPrivate *reply =
reinterpret_cast<QNetworkReplyWasmImplPrivate*>(xhr["data-handler"].as<quintptr>());
Q_ASSERT(reply);
if (xhr["lengthComputable"].as<bool>() && xhr["status"].as<int>() < 400)
reply->emitDataReadProgress(xhr["loaded"].as<qint64>(), xhr["total"].as<qint64>());
if (xhr["status"].as<int>() < 400)
reply->emitDataReadProgress(event["loaded"].as<int>(), event["total"].as<int>());
}
static void q_loadCallback(val event)
{
if (event.isNull() || event.isUndefined())
return;
val xhr = event["target"];
QNetworkReplyWasmImplPrivate *reply =
@ -121,6 +129,7 @@ static void q_loadCallback(val event)
reader.set("data-handler", xhr["data-handler"]);
reader.call<void>("readAsArrayBuffer", blob);
val::global("Module").delete_(reader);
}
@ -136,6 +145,9 @@ static void q_loadCallback(val event)
static void q_responseHeadersCallback(val event)
{
if (event.isNull() || event.isUndefined())
return;
val xhr = event["target"];
if (xhr["readyState"].as<int>() == 2) { // HEADERS_RECEIVED
@ -152,12 +164,18 @@ static void q_responseHeadersCallback(val event)
static void q_readBinary(val event)
{
if (event.isNull() || event.isUndefined())
return;
val fileReader = event["target"];
QNetworkReplyWasmImplPrivate *reply =
reinterpret_cast<QNetworkReplyWasmImplPrivate*>(fileReader["data-handler"].as<quintptr>());
Q_ASSERT(reply);
if (reply->state == QNetworkReplyPrivate::Finished || reply->state == QNetworkReplyPrivate::Aborted)
return;
// Set up source typed array
val result = fileReader["result"]; // ArrayBuffer
val Uint8Array = val::global("Uint8Array");
@ -171,6 +189,10 @@ static void q_readBinary(val event)
reinterpret_cast<quintptr>(buffer.data()), size);
destinationTypedArray.call<void>("set", sourceTypedArray);
reply->dataReceived(buffer, buffer.size());
event.delete_(fileReader);
Uint8Array.delete_(sourceTypedArray);
QCoreApplication::processEvents();
}
@ -194,14 +216,21 @@ QNetworkReplyWasmImplPrivate::QNetworkReplyWasmImplPrivate()
QNetworkReplyWasmImplPrivate::~QNetworkReplyWasmImplPrivate()
{
}
QNetworkReplyWasmImpl::~QNetworkReplyWasmImpl()
{
m_xhr.set("onerror", val::null());
m_xhr.set("onload", val::null());
m_xhr.set("onprogress", val::null());
m_xhr.set("onreadystatechange", val::null());
m_xhr.set("data-handler", val::null());
}
QNetworkReplyWasmImpl::QNetworkReplyWasmImpl(QObject *parent)
: QNetworkReply(*new QNetworkReplyWasmImplPrivate(), parent)
{
Q_D( QNetworkReplyWasmImpl);
d->state = QNetworkReplyPrivate::Idle;
}
QNetworkReplyWasmImpl::~QNetworkReplyWasmImpl()
{
}
@ -226,19 +255,23 @@ QByteArray QNetworkReplyWasmImpl::methodName() const
void QNetworkReplyWasmImpl::close()
{
QNetworkReply::close();
setFinished(true);
emit finished();
QNetworkReply::close();
}
void QNetworkReplyWasmImpl::abort()
{
Q_D(const QNetworkReplyWasmImpl);
setError( QNetworkReply::OperationCanceledError, QStringLiteral("Operation canceled"));
Q_D( QNetworkReplyWasmImpl);
if (d->state == QNetworkReplyPrivate::Finished || d->state == QNetworkReplyPrivate::Aborted)
return;
setError(QNetworkReply::OperationCanceledError, QStringLiteral("Operation canceled"));
d->doAbort();
close();
d->state = QNetworkReplyPrivate::Aborted;
}
qint64 QNetworkReplyWasmImpl::bytesAvailable() const

View File

@ -0,0 +1,30 @@
/****************************************************************************
**
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the documentation of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:FDL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Free Documentation License Usage
** Alternatively, this file may be used under the terms of the GNU Free
** Documentation License version 1.3 as published by the Free Software
** Foundation and appearing in the file included in the packaging of
** this file. Please review the following information to ensure
** the GNU Free Documentation License version 1.3 requirements
** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
** $QT_END_LICENSE$
**
****************************************************************************/
/*!
\dontdocument (QTypeInfo QMetaTypeId QIPv6Address)
*/

View File

@ -77,11 +77,12 @@
\section1 Import and Export Restrictions
Due to import and export restrictions in some parts of the world, we
are unable to supply the OpenSSL Toolkit with Qt packages. Developers wishing
to use SSL communication in their deployed applications should either ensure
that their users have the appropriate libraries installed, or they should
consult a suitably qualified legal professional to ensure that applications
using code from the OpenSSL project are correctly certified for import
and export in relevant regions of the world.
Qt binary installers include the OpenSSL libraries used by QtNetwork. However,
those are not automatically deployed with applications that are built with Qt.
Import and export restrictions apply for some types of software, and for
some parts of the world. Developers wishing to use SSL communication in their
deployed applications should either ensure that their users have the appropriate
libraries installed, or they should consult a suitably qualified legal
professional to ensure that applications using code from the OpenSSL project
are correctly certified for import and export in relevant regions of the world.
*/

View File

@ -0,0 +1,30 @@
/****************************************************************************
**
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the documentation of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:FDL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Free Documentation License Usage
** Alternatively, this file may be used under the terms of the GNU Free
** Documentation License version 1.3 as published by the Free Software
** Foundation and appearing in the file included in the packaging of
** this file. Please review the following information to ensure
** the GNU Free Documentation License version 1.3 requirements
** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
** $QT_END_LICENSE$
**
****************************************************************************/
/*!
\dontdocument (QMetaTypeId)
*/

View File

@ -1845,7 +1845,7 @@ LOGFONT QWindowsFontDatabase::fontDefToLOGFONT(const QFontDef &request, const QS
QString fam = faceName;
if (fam.isEmpty())
fam = request.family;
fam = request.families.size() > 0 ? request.families.at(0) : request.family;
if (Q_UNLIKELY(fam.size() >= LF_FACESIZE)) {
qCritical("%s: Family name '%s' is too long.", __FUNCTION__, qPrintable(fam));
fam.truncate(LF_FACESIZE - 1);

View File

@ -80,7 +80,7 @@ private:
NSOpenGLContext *m_shareContext = nil;
QSurfaceFormat m_format;
bool m_didCheckForSoftwareContext = false;
QVarLengthArray<QMacScopedObserver, 3> m_updateObservers;
QVarLengthArray<QMacNotificationObserver, 3> m_updateObservers;
QAtomicInt m_needsUpdate = false;
};

View File

@ -404,13 +404,13 @@ bool QCocoaGLContext::setDrawable(QPlatformSurface *surface)
m_updateObservers.clear();
if (view.layer) {
m_updateObservers.append(QMacScopedObserver(view, NSViewFrameDidChangeNotification, updateCallback));
m_updateObservers.append(QMacScopedObserver(view.window, NSWindowDidChangeScreenNotification, updateCallback));
m_updateObservers.append(QMacNotificationObserver(view, NSViewFrameDidChangeNotification, updateCallback));
m_updateObservers.append(QMacNotificationObserver(view.window, NSWindowDidChangeScreenNotification, updateCallback));
} else {
m_updateObservers.append(QMacScopedObserver(view, NSViewGlobalFrameDidChangeNotification, updateCallback));
m_updateObservers.append(QMacNotificationObserver(view, NSViewGlobalFrameDidChangeNotification, updateCallback));
}
m_updateObservers.append(QMacScopedObserver([NSApplication sharedApplication],
m_updateObservers.append(QMacNotificationObserver([NSApplication sharedApplication],
NSApplicationDidChangeScreenParametersNotification, updateCallback));
// If any of the observers fire at this point it's fine. We check the

View File

@ -297,13 +297,12 @@ Qt::MouseButton cocoaButton2QtButton(NSInteger buttonNum)
*/
Qt::MouseButton cocoaButton2QtButton(NSEvent *event)
{
switch (event.type) {
case NSEventTypeMouseMoved:
if (cocoaEvent2QtMouseEvent(event) == QEvent::MouseMove)
return Qt::NoButton;
switch (event.type) {
case NSEventTypeRightMouseUp:
case NSEventTypeRightMouseDown:
case NSEventTypeRightMouseDragged:
return Qt::RightButton;
default:

View File

@ -45,6 +45,8 @@
Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(QCocoaThemeAppAppearanceObserver));
#include <QtCore/private/qcore_mac_p.h>
QT_BEGIN_NAMESPACE
class QPalette;
@ -82,9 +84,10 @@ public:
private:
mutable QPalette *m_systemPalette;
QMacNotificationObserver m_systemColorObserver;
mutable QHash<QPlatformTheme::Palette, QPalette*> m_palettes;
mutable QHash<QPlatformTheme::Font, QFont*> m_fonts;
QT_MANGLE_NAMESPACE(QCocoaThemeAppAppearanceObserver) *m_appearanceObserver;
QMacKeyValueObserver m_appearanceObserver;
};
QT_END_NAMESPACE

View File

@ -80,70 +80,32 @@
#include <CoreServices/CoreServices.h>
#if QT_MACOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_14)
@interface QT_MANGLE_NAMESPACE(QCocoaThemeAppAppearanceObserver) : NSObject
@property (readonly, nonatomic) QCocoaTheme *theme;
- (instancetype)initWithTheme:(QCocoaTheme *)theme;
@end
QT_NAMESPACE_ALIAS_OBJC_CLASS(QCocoaThemeAppAppearanceObserver);
@implementation QCocoaThemeAppAppearanceObserver
- (instancetype)initWithTheme:(QCocoaTheme *)theme
{
if ((self = [super init])) {
_theme = theme;
[NSApp addObserver:self forKeyPath:@"effectiveAppearance" options:NSKeyValueObservingOptionNew context:nullptr];
}
return self;
}
- (void)dealloc
{
[NSApp removeObserver:self forKeyPath:@"effectiveAppearance"];
[super dealloc];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object
change:(NSDictionary<NSKeyValueChangeKey, id> *)change context:(void *)context
{
Q_UNUSED(change);
Q_UNUSED(context);
Q_ASSERT(object == NSApp);
Q_ASSERT([keyPath isEqualToString:@"effectiveAppearance"]);
if (__builtin_available(macOS 10.14, *))
NSAppearance.currentAppearance = NSApp.effectiveAppearance;
self.theme->handleSystemThemeChange();
}
@end
#endif // QT_MACOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_14)
QT_BEGIN_NAMESPACE
const char *QCocoaTheme::name = "cocoa";
QCocoaTheme::QCocoaTheme()
: m_systemPalette(nullptr), m_appearanceObserver(nil)
: m_systemPalette(nullptr)
{
#if QT_MACOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_14)
if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::MacOSMojave)
m_appearanceObserver = [[QCocoaThemeAppAppearanceObserver alloc] initWithTheme:this];
if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::MacOSMojave) {
m_appearanceObserver = QMacKeyValueObserver(NSApp, @"effectiveAppearance", [this] {
if (__builtin_available(macOS 10.14, *))
NSAppearance.currentAppearance = NSApp.effectiveAppearance;
handleSystemThemeChange();
});
}
#endif
[[NSNotificationCenter defaultCenter] addObserverForName:NSSystemColorsDidChangeNotification
object:nil queue:nil usingBlock:^(NSNotification *) {
m_systemColorObserver = QMacNotificationObserver(nil,
NSSystemColorsDidChangeNotification, [this] {
handleSystemThemeChange();
}];
});
}
QCocoaTheme::~QCocoaTheme()
{
if (m_appearanceObserver)
[m_appearanceObserver release];
reset();
qDeleteAll(m_fonts);
}

View File

@ -54,7 +54,7 @@ QCocoaVulkanInstance::~QCocoaVulkanInstance()
void QCocoaVulkanInstance::createOrAdoptInstance()
{
initInstance(m_instance, QByteArrayList());
initInstance(m_instance, QByteArrayList() << QByteArrayLiteral("VK_MVK_macos_surface"));
}
VkSurfaceKHR *QCocoaVulkanInstance::createSurface(QWindow *window)

View File

@ -282,20 +282,19 @@
nativeDrag->setLastMouseEvent(theEvent, self);
const auto modifiers = [QNSView convertKeyModifiers:theEvent.modifierFlags];
const auto buttons = currentlyPressedMouseButtons();
auto button = cocoaButton2QtButton(theEvent);
if (button == Qt::LeftButton && m_sendUpAsRightButton)
button = Qt::RightButton;
const auto eventType = cocoaEvent2QtMouseEvent(theEvent);
if (eventType == QEvent::MouseMove)
qCDebug(lcQpaMouse) << eventType << "at" << qtWindowPoint << "with" << buttons;
qCDebug(lcQpaMouse) << eventType << "at" << qtWindowPoint << "with" << m_buttons;
else
qCInfo(lcQpaMouse) << eventType << "of" << button << "at" << qtWindowPoint << "with" << buttons;
qCInfo(lcQpaMouse) << eventType << "of" << button << "at" << qtWindowPoint << "with" << m_buttons;
QWindowSystemInterface::handleMouseEvent(targetView->m_platformWindow->window(),
timestamp, qtWindowPoint, qtScreenPoint,
buttons, button, eventType, modifiers);
m_buttons, button, eventType, modifiers);
}
- (bool)handleMouseDownEvent:(NSEvent *)theEvent

View File

@ -69,12 +69,15 @@ inline D2D1_RECT_F to_d2d_rect_f(const QRectF &qrect)
inline D2D1_SIZE_U to_d2d_size_u(const QSizeF &qsize)
{
return D2D1::SizeU(qsize.width(), qsize.height());
return D2D1::SizeU(UINT32(qRound(qsize.width())),
UINT32(qRound(qsize.height())));
}
inline D2D1_SIZE_U to_d2d_size_u(const QSize &qsize)
{
return D2D1::SizeU(qsize.width(), qsize.height());
return D2D1::SizeU(UINT32(qsize.width()),
UINT32(qsize.height()));
}
inline D2D1_POINT_2F to_d2d_point_2f(const QPointF &qpoint)

View File

@ -55,6 +55,12 @@ QWasmBackingStore::~QWasmBackingStore()
{
}
void QWasmBackingStore::destroy()
{
if (m_texture->isCreated())
m_texture->destroy();
}
QPaintDevice *QWasmBackingStore::paintDevice()
{
return &m_image;

View File

@ -44,6 +44,7 @@ class QWasmBackingStore : public QPlatformBackingStore
public:
QWasmBackingStore(QWasmCompositor *compositor, QWindow *window);
~QWasmBackingStore();
void destroy();
QPaintDevice *paintDevice() override;

View File

@ -37,6 +37,7 @@
#include <QtGui/qopenglcontext.h>
#include <QtGui/qopenglfunctions.h>
#include <QtGui/qopengltextureblitter.h>
#include <QtGui/qoffscreensurface.h>
#include <QtGui/qpainter.h>
#include <private/qpixmapcache_p.h>
@ -71,6 +72,28 @@ QWasmCompositor::QWasmCompositor(QWasmScreen *screen)
QWasmCompositor::~QWasmCompositor()
{
delete m_frameBuffer;
destroy();
}
void QWasmCompositor::destroy()
{
// Destroy OpenGL resources. This is done here in a separate function
// which can be called while screen() still returns a valid screen
// (which it might not, during destruction). A valid QScreen is
// a requirement for QOffscreenSurface on Wasm since the native
// context is tied to a single canvas.
if (m_context) {
QOffscreenSurface offScreenSurface(screen()->screen());
offScreenSurface.setFormat(m_context->format());
offScreenSurface.create();
m_context->makeCurrent(&offScreenSurface);
for (QWasmWindow *window : m_windowStack)
window->destroy();
m_blitter.reset(nullptr);
m_context.reset(nullptr);
}
m_isEnabled = false; // prevent frame() from creating a new m_context
}
void QWasmCompositor::setEnabled(bool enabled)
@ -251,10 +274,13 @@ void QWasmCompositor::blit(QOpenGLTextureBlitter *blitter, QWasmScreen *screen,
void QWasmCompositor::drawWindowContent(QOpenGLTextureBlitter *blitter, QWasmScreen *screen, QWasmWindow *window)
{
QWasmBackingStore *backingStore = window->backingStore();
if (!backingStore)
return;
QOpenGLTexture const *texture = backingStore->getUpdatedTexture();
blit(blitter, screen, texture, window->geometry());
QPoint windowCanvasPosition = window->geometry().topLeft() - screen->geometry().topLeft();
QRect windowCanvasGeometry = QRect(windowCanvasPosition, window->geometry().size());
blit(blitter, screen, texture, windowCanvasGeometry);
}
QPalette QWasmCompositor::makeWindowPalette()
@ -650,7 +676,7 @@ void QWasmCompositor::frame()
m_needComposit = false;
if (m_windowStack.empty() || !screen())
if (!m_isEnabled || m_windowStack.empty() || !screen())
return;
QWasmWindow *someWindow = nullptr;
@ -673,7 +699,9 @@ void QWasmCompositor::frame()
m_context->create();
}
m_context->makeCurrent(someWindow->window());
bool ok = m_context->makeCurrent(someWindow->window());
if (!ok)
return;
if (!m_blitter->isCreated())
m_blitter->create();

View File

@ -64,6 +64,7 @@ class QWasmCompositor : public QObject
public:
QWasmCompositor(QWasmScreen *screen);
~QWasmCompositor();
void destroy();
enum QWasmSubControl {
SC_None = 0x00000000,

View File

@ -337,8 +337,6 @@ QWasmEventTranslator::QWasmEventTranslator(QWasmScreen *screen)
void QWasmEventTranslator::initEventHandlers()
{
qDebug() << "QWasmEventTranslator::initEventHandlers";
QByteArray _canvasId = screen()->canvasId().toUtf8();
const char *canvasId = _canvasId.constData();
@ -377,9 +375,6 @@ void QWasmEventTranslator::initEventHandlers()
emscripten_set_touchend_callback(canvasId, (void *)this, 1, &touchCallback);
emscripten_set_touchmove_callback(canvasId, (void *)this, 1, &touchCallback);
emscripten_set_touchcancel_callback(canvasId, (void *)this, 1, &touchCallback);
emscripten_set_resize_callback(nullptr, (void *)this, 1, uiEvent_cb); // Note: handles browser window resize
}
template <typename Event>
@ -557,9 +552,12 @@ void QWasmEventTranslator::processMouse(int eventType, const EmscriptenMouseEven
Qt::KeyboardModifiers modifiers = translateMouseEventModifier(mouseEvent);
QWindow *window2 = screen()->compositor()->windowAt(globalPoint, 5);
if (window2 == nullptr)
return;
lastWindow = window2;
if (window2 == nullptr) {
window2 = lastWindow;
} else {
lastWindow = window2;
}
QPoint localPoint = window2->mapFromGlobal(globalPoint);
bool interior = window2->geometry().contains(globalPoint);
@ -621,7 +619,7 @@ void QWasmEventTranslator::processMouse(int eventType, const EmscriptenMouseEven
}
if (resizeMode != QWasmWindow::ResizeNone && !(htmlWindow->m_windowState & Qt::WindowFullScreen)) {
QPoint delta = QPoint(mouseEvent->canvasX, mouseEvent->canvasY) - resizePoint;
QPoint delta = QPoint(mouseEvent->targetX, mouseEvent->targetY) - resizePoint;
resizeWindow(draggedWindow, resizeMode, resizeStartRect, delta);
}
}
@ -911,19 +909,4 @@ bool QWasmEventTranslator::processKeyboard(int eventType, const EmscriptenKeyboa
return accepted;
}
int QWasmEventTranslator::uiEvent_cb(int eventType, const EmscriptenUiEvent *e, void *userData)
{
Q_UNUSED(e)
QWasmEventTranslator *eventTranslator = static_cast<QWasmEventTranslator *>(userData);
if (eventType == EMSCRIPTEN_EVENT_RESIZE) {
// This resize event is called when the HTML window is resized. Depending
// on the page layout the the canvas might also have been resized, so we
// update the Qt screen size (and canvas render size).
eventTranslator->screen()->updateQScreenAndCanvasRenderSize();
}
return 0;
}
QT_END_NAMESPACE

View File

@ -57,8 +57,6 @@ public:
static int touchCallback(int eventType, const EmscriptenTouchEvent *ev, void *userData);
static int uiEvent_cb(int eventType, const EmscriptenUiEvent *e, void *userData);
void processEvents();
void initEventHandlers();
int handleTouch(int eventType, const EmscriptenTouchEvent *touchEvent);

View File

@ -35,6 +35,7 @@
#include "qwasmtheme.h"
#include "qwasmclipboard.h"
#include "qwasmservices.h"
#include "qwasmoffscreensurface.h"
#include "qwasmwindow.h"
#ifndef QT_NO_OPENGL
@ -123,6 +124,21 @@ QWasmIntegration::QWasmIntegration()
}
emscripten::val::global("window").set("onbeforeunload", val::module_property("qtBrowserBeforeUnload"));
// install browser window resize handler
auto onWindowResize = [](int eventType, const EmscriptenUiEvent *e, void *userData) -> int {
Q_UNUSED(eventType);
Q_UNUSED(e);
Q_UNUSED(userData);
// This resize event is called when the HTML window is resized. Depending
// on the page layout the the canvas(es) might also have been resized, so we
// update the Qt screen sizes (and canvas render sizes).
if (QWasmIntegration *integration = QWasmIntegration::get())
integration->resizeAllScreens();
return 0;
};
emscripten_set_resize_callback(nullptr, nullptr, 1, onWindowResize);
}
QWasmIntegration::~QWasmIntegration()
@ -193,6 +209,11 @@ QPlatformInputContext *QWasmIntegration::inputContext() const
return m_inputContext.data();
}
QPlatformOffscreenSurface *QWasmIntegration::createPlatformOffscreenSurface(QOffscreenSurface *surface) const
{
return new QWasmOffscrenSurface(surface);
}
QPlatformFontDatabase *QWasmIntegration::fontDatabase() const
{
if (m_fontDb == nullptr)
@ -257,7 +278,9 @@ void QWasmIntegration::addScreen(const QString &canvasId)
void QWasmIntegration::removeScreen(const QString &canvasId)
{
QWindowSystemInterface::handleScreenRemoved(m_screens.take(canvasId));
QWasmScreen *exScreen = m_screens.take(canvasId);
exScreen->destroy(); // clean up before deleting the screen
QWindowSystemInterface::handleScreenRemoved(exScreen);
}
void QWasmIntegration::resizeScreen(const QString &canvasId)
@ -275,4 +298,11 @@ void QWasmIntegration::updateDpi()
QWindowSystemInterface::handleScreenLogicalDotsPerInchChange(screen->screen(), dpiValue, dpiValue);
}
void QWasmIntegration::resizeAllScreens()
{
qDebug() << "resizeAllScreens";
for (QWasmScreen *screen : m_screens)
screen->updateQScreenAndCanvasRenderSize();
}
QT_END_NAMESPACE

View File

@ -66,6 +66,7 @@ public:
#ifndef QT_NO_OPENGL
QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const override;
#endif
QPlatformOffscreenSurface *createPlatformOffscreenSurface(QOffscreenSurface *surface) const override;
QPlatformFontDatabase *fontDatabase() const override;
QAbstractEventDispatcher *createEventDispatcher() const override;
QVariant styleHint(QPlatformIntegration::StyleHint hint) const override;
@ -85,6 +86,7 @@ public:
void addScreen(const QString &canvasId);
void removeScreen(const QString &canvasId);
void resizeScreen(const QString &canvasId);
void resizeAllScreens();
void updateDpi();
private:

View File

@ -0,0 +1,41 @@
/****************************************************************************
**
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:GPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 or (at your option) any later version
** approved by the KDE Free Qt Foundation. The licenses are as published by
** the Free Software Foundation and appearing in the file LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qwasmoffscreensurface.h"
QWasmOffscrenSurface::QWasmOffscrenSurface(QOffscreenSurface *offscreenSurface)
:QPlatformOffscreenSurface(offscreenSurface)
{
}
QWasmOffscrenSurface::~QWasmOffscrenSurface()
{
}

View File

@ -0,0 +1,49 @@
/****************************************************************************
**
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:GPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 or (at your option) any later version
** approved by the KDE Free Qt Foundation. The licenses are as published by
** the Free Software Foundation and appearing in the file LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QWASMOFFSCREENSURFACE_H
#define QWASMOFFSCREENSURFACE_H
#include <qpa/qplatformoffscreensurface.h>
QT_BEGIN_NAMESPACE
class QOffscreenSurface;
class QWasmOffscrenSurface : public QPlatformOffscreenSurface
{
public:
explicit QWasmOffscrenSurface(QOffscreenSurface *offscreenSurface);
~QWasmOffscrenSurface();
private:
};
QT_END_NAMESPACE
#endif

View File

@ -49,40 +49,31 @@ QWasmOpenGLContext::QWasmOpenGLContext(const QSurfaceFormat &format)
QWasmOpenGLContext::~QWasmOpenGLContext()
{
if (m_context)
if (m_context) {
emscripten_webgl_destroy_context(m_context);
m_context = 0;
}
}
void QWasmOpenGLContext::maybeRecreateEmscriptenContext(QPlatformSurface *surface)
bool QWasmOpenGLContext::maybeCreateEmscriptenContext(QPlatformSurface *surface)
{
// Native emscripten contexts are tied to a single surface. Recreate
// the context if the surface is changed.
if (surface != m_surface) {
m_surface = surface;
// Native emscripten/WebGL contexts are tied to a single screen/canvas. The first
// call to this function creates a native canvas for the given screen, subsequent
// calls verify that the surface is on/off the same screen.
QPlatformScreen *screen = surface->screen();
if (m_context && !screen)
return false; // Alternative: return true to support makeCurrent on QOffScreenSurface with
// no screen. However, Qt likes to substitute QGuiApplication::primaryScreen()
// for null screens, which foils this plan.
if (!screen)
return false;
if (m_context)
return m_screen == screen;
// Destroy existing context
if (m_context)
emscripten_webgl_destroy_context(m_context);
// Create new context
const QString canvasId = QWasmScreen::get(surface->screen())->canvasId();
m_context = createEmscriptenContext(canvasId, m_requestedFormat);
// Register context-lost callback.
auto callback = [](int eventType, const void *reserved, void *userData) -> EM_BOOL
{
Q_UNUSED(eventType);
Q_UNUSED(reserved);
// The application may get contex-lost if e.g. moved to the background. Set
// m_contextLost which will make isValid() return false. Application code will
// then detect this and recrate the the context, resulting in a new QWasmOpenGLContext
// instance.
reinterpret_cast<QWasmOpenGLContext *>(userData)->m_contextLost = true;
return true;
};
bool capture = true;
emscripten_set_webglcontextlost_callback(canvasId.toLocal8Bit().constData(), this, capture, callback);
}
QString canvasId = QWasmScreen::get(screen)->canvasId();
m_context = createEmscriptenContext(canvasId, m_requestedFormat);
m_screen = screen;
return true;
}
EMSCRIPTEN_WEBGL_CONTEXT_HANDLE QWasmOpenGLContext::createEmscriptenContext(const QString &canvasId, QSurfaceFormat format)
@ -125,7 +116,9 @@ GLuint QWasmOpenGLContext::defaultFramebufferObject(QPlatformSurface *surface) c
bool QWasmOpenGLContext::makeCurrent(QPlatformSurface *surface)
{
maybeRecreateEmscriptenContext(surface);
bool ok = maybeCreateEmscriptenContext(surface);
if (!ok)
return false;
return emscripten_webgl_make_context_current(m_context) == EMSCRIPTEN_RESULT_SUCCESS;
}
@ -148,7 +141,9 @@ bool QWasmOpenGLContext::isSharing() const
bool QWasmOpenGLContext::isValid() const
{
return (m_contextLost == false);
// Note: we get isValid() calls before we see the surface and can
// create a native context, so no context is also a valid state.
return !m_context || !emscripten_is_webgl_context_lost(m_context);
}
QFunctionPointer QWasmOpenGLContext::getProcAddress(const char *procName)

View File

@ -34,6 +34,7 @@
QT_BEGIN_NAMESPACE
class QPlatformScreen;
class QWasmOpenGLContext : public QPlatformOpenGLContext
{
public:
@ -50,12 +51,11 @@ public:
QFunctionPointer getProcAddress(const char *procName) override;
private:
void maybeRecreateEmscriptenContext(QPlatformSurface *surface);
bool maybeCreateEmscriptenContext(QPlatformSurface *surface);
static EMSCRIPTEN_WEBGL_CONTEXT_HANDLE createEmscriptenContext(const QString &canvasId, QSurfaceFormat format);
bool m_contextLost = false;
QSurfaceFormat m_requestedFormat;
QPlatformSurface *m_surface = nullptr;
QPlatformScreen *m_screen = nullptr;
EMSCRIPTEN_WEBGL_CONTEXT_HANDLE m_context = 0;
};

View File

@ -58,7 +58,12 @@ QWasmScreen::QWasmScreen(const QString &canvasId)
QWasmScreen::~QWasmScreen()
{
destroy();
}
void QWasmScreen::destroy()
{
m_compositor->destroy();
}
QWasmScreen *QWasmScreen::get(QPlatformScreen *screen)

View File

@ -52,6 +52,7 @@ class QWasmScreen : public QObject, public QPlatformScreen
public:
QWasmScreen(const QString &canvasId);
~QWasmScreen();
void destroy();
static QWasmScreen *get(QPlatformScreen *screen);
static QWasmScreen *get(QScreen *screen);

View File

@ -65,6 +65,12 @@ QWasmWindow::~QWasmWindow()
m_compositor->removeWindow(this);
}
void QWasmWindow::destroy()
{
if (m_backingStore)
m_backingStore->destroy();
}
void QWasmWindow::initialize()
{
QRect rect = windowGeometry();

View File

@ -58,6 +58,7 @@ public:
QWasmWindow(QWindow *w, QWasmCompositor *compositor, QWasmBackingStore *backingStore);
~QWasmWindow();
void destroy();
void initialize() override;

View File

@ -20,7 +20,8 @@ SOURCES = \
qwasmopenglcontext.cpp \
qwasmtheme.cpp \
qwasmclipboard.cpp \
qwasmservices.cpp
qwasmservices.cpp \
qwasmoffscreensurface.cpp
HEADERS = \
qwasmintegration.h \
@ -35,7 +36,8 @@ HEADERS = \
qwasmopenglcontext.h \
qwasmtheme.h \
qwasmclipboard.h \
qwasmservices.h
qwasmservices.h \
qwasmoffscreensurface.h
wasmfonts.files = \
../../../3rdparty/wasm/Vera.ttf \

View File

@ -317,6 +317,8 @@ QWindowsContext::~QWindowsContext()
OleUninitialize();
d->m_screenManager.clearScreens(); // Order: Potentially calls back to the windows.
if (d->m_displayContext)
ReleaseDC(nullptr, d->m_displayContext);
m_instance = nullptr;
}
@ -749,6 +751,12 @@ QWindowsWindow *QWindowsContext::findPlatformWindowAt(HWND parent,
QWindowsWindow *result = nullptr;
const POINT screenPoint = { screenPointIn.x(), screenPointIn.y() };
while (findPlatformWindowHelper(screenPoint, cwex_flags, this, &parent, &result)) {}
// QTBUG-40815: ChildWindowFromPointEx() can hit on special windows from
// screen recorder applications like ScreenToGif. Fall back to WindowFromPoint().
if (result == nullptr) {
if (const HWND window = WindowFromPoint(screenPoint))
result = findPlatformWindow(window);
}
return result;
}
@ -925,7 +933,7 @@ bool QWindowsContext::systemParametersInfo(unsigned action, unsigned param, void
bool QWindowsContext::systemParametersInfoForScreen(unsigned action, unsigned param, void *out,
const QPlatformScreen *screen)
{
return systemParametersInfo(action, param, out, screen ? screen->logicalDpi().first : 0);
return systemParametersInfo(action, param, out, screen ? unsigned(screen->logicalDpi().first) : 0u);
}
bool QWindowsContext::systemParametersInfoForWindow(unsigned action, unsigned param, void *out,
@ -944,7 +952,8 @@ bool QWindowsContext::nonClientMetrics(NONCLIENTMETRICS *ncm, unsigned dpi)
bool QWindowsContext::nonClientMetricsForScreen(NONCLIENTMETRICS *ncm,
const QPlatformScreen *screen)
{
return nonClientMetrics(ncm, screen ? screen->logicalDpi().first : 0);
const int dpi = screen ? qRound(screen->logicalDpi().first) : 0;
return nonClientMetrics(ncm, unsigned(dpi));
}
bool QWindowsContext::nonClientMetricsForWindow(NONCLIENTMETRICS *ncm, const QPlatformWindow *win)

View File

@ -269,7 +269,10 @@ static Qt::MouseButtons queryMouseButtons()
static QWindow *getWindowUnderPointer(QWindow *window, QPoint globalPos)
{
QWindow *currentWindowUnderPointer = QWindowsScreen::windowAt(globalPos, CWP_SKIPINVISIBLE | CWP_SKIPTRANSPARENT);
QWindowsWindow *platformWindow = static_cast<QWindowsWindow *>(window->handle());
QWindow *currentWindowUnderPointer = platformWindow->hasMouseCapture() ?
QWindowsScreen::windowAt(globalPos, CWP_SKIPINVISIBLE | CWP_SKIPTRANSPARENT) : window;
while (currentWindowUnderPointer && currentWindowUnderPointer->flags() & Qt::WindowTransparentForInput)
currentWindowUnderPointer = currentWindowUnderPointer->parent();

View File

@ -91,7 +91,7 @@ static bool monitorData(HMONITOR hMonitor, QWindowsScreenData *data)
} else {
if (const HDC hdc = CreateDC(info.szDevice, nullptr, nullptr, nullptr)) {
const QDpi dpi = monitorDPI(hMonitor);
data->dpi = dpi.first ? dpi : deviceDPI(hdc);
data->dpi = dpi.first > 0 ? dpi : deviceDPI(hdc);
data->depth = GetDeviceCaps(hdc, BITSPIXEL);
data->format = data->depth == 16 ? QImage::Format_RGB16 : QImage::Format_RGB32;
data->physicalSizeMM = QSizeF(GetDeviceCaps(hdc, HORZSIZE), GetDeviceCaps(hdc, VERTSIZE));

View File

@ -883,10 +883,12 @@ static QSize toNativeSizeConstrained(QSize dip, const QWindow *w)
{
if (QHighDpiScaling::isActive()) {
const qreal factor = QHighDpiScaling::factor(w);
if (dip.width() > 0 && dip.width() < QWINDOWSIZE_MAX)
dip.rwidth() *= factor;
if (dip.height() > 0 && dip.height() < QWINDOWSIZE_MAX)
dip.rheight() *= factor;
if (!qFuzzyCompare(factor, qreal(1))) {
if (dip.width() > 0 && dip.width() < QWINDOWSIZE_MAX)
dip.setWidth(qRound(qreal(dip.width()) * factor));
if (dip.height() > 0 && dip.height() < QWINDOWSIZE_MAX)
dip.setHeight(qRound(qreal(dip.height()) * factor));
}
}
return dip;
}

View File

@ -114,7 +114,7 @@ void setVariantBool(bool value, VARIANT *variant)
void setVariantDouble(double value, VARIANT *variant)
{
variant->vt = VT_R8;
variant->boolVal = value;
variant->dblVal = value;
}
BSTR bStrFromQString(const QString &value)

View File

@ -82,53 +82,6 @@ static QWindow *qt_getWindow(const QWidget *widget)
return widget ? widget->window()->windowHandle() : 0;
}
@interface QT_MANGLE_NAMESPACE(NotificationReceiver) : NSObject
@end
QT_NAMESPACE_ALIAS_OBJC_CLASS(NotificationReceiver);
@implementation NotificationReceiver
{
QMacStylePrivate *privateStyle;
}
- (instancetype)initWithPrivateStyle:(QMacStylePrivate *)style
{
if (self = [super init])
privateStyle = style;
return self;
}
- (void)scrollBarStyleDidChange:(NSNotification *)notification
{
Q_UNUSED(notification);
// purge destroyed scroll bars:
QMacStylePrivate::scrollBars.removeAll(QPointer<QObject>());
QEvent event(QEvent::StyleChange);
for (const auto &o : QMacStylePrivate::scrollBars)
QCoreApplication::sendEvent(o, &event);
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object
change:(NSDictionary<NSKeyValueChangeKey, id> *)change context:(void *)context
{
Q_UNUSED(keyPath);
Q_UNUSED(object);
Q_UNUSED(change);
Q_UNUSED(context);
Q_ASSERT([keyPath isEqualToString:@"effectiveAppearance"]);
Q_ASSERT(object == NSApp);
for (NSView *b : privateStyle->cocoaControls)
[b release];
privateStyle->cocoaControls.clear();
}
@end
@interface QT_MANGLE_NAMESPACE(QIndeterminateProgressIndicator) : NSProgressIndicator
@property (readonly, nonatomic) NSInteger animators;
@ -2032,33 +1985,33 @@ void QMacStylePrivate::resolveCurrentNSView(QWindow *window) const
QMacStyle::QMacStyle()
: QCommonStyle(*new QMacStylePrivate)
{
Q_D(QMacStyle);
QMacAutoReleasePool pool;
d->receiver = [[NotificationReceiver alloc] initWithPrivateStyle:d];
[[NSNotificationCenter defaultCenter] addObserver:d->receiver
selector:@selector(scrollBarStyleDidChange:)
name:NSPreferredScrollerStyleDidChangeNotification
object:nil];
static QMacNotificationObserver scrollbarStyleObserver(nil,
NSPreferredScrollerStyleDidChangeNotification, []() {
// Purge destroyed scroll bars
QMacStylePrivate::scrollBars.removeAll(QPointer<QObject>());
QEvent event(QEvent::StyleChange);
for (const auto &o : QMacStylePrivate::scrollBars)
QCoreApplication::sendEvent(o, &event);
});
#if QT_MACOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_14)
Q_D(QMacStyle);
// FIXME: Tie this logic into theme change, or even polish/unpolish
if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::MacOSMojave) {
[NSApplication.sharedApplication addObserver:d->receiver forKeyPath:@"effectiveAppearance"
options:NSKeyValueObservingOptionNew context:nullptr];
d->appearanceObserver = QMacKeyValueObserver(NSApp, @"effectiveAppearance", [&d] {
for (NSView *b : d->cocoaControls)
[b release];
d->cocoaControls.clear();
});
}
#endif
}
QMacStyle::~QMacStyle()
{
Q_D(QMacStyle);
QMacAutoReleasePool pool;
[[NSNotificationCenter defaultCenter] removeObserver:d->receiver];
#if QT_MACOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_14)
if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::MacOSMojave)
[NSApplication.sharedApplication removeObserver:d->receiver forKeyPath:@"effectiveAppearance"];
#endif
[d->receiver release];
}
void QMacStyle::polish(QPalette &)
@ -3094,7 +3047,9 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai
theStroker.setCapStyle(Qt::FlatCap);
theStroker.setDashPattern(QVector<qreal>() << 1 << 2);
path = theStroker.createStroke(path);
p->fillPath(path, QColor(0, 0, 0, 119));
const auto dark = qt_mac_applicationIsInDarkMode() ? opt->palette.dark().color().darker()
: QColor(0, 0, 0, 119);
p->fillPath(path, dark);
}
break;
case PE_FrameWindow:

View File

@ -156,7 +156,6 @@ Q_FORWARD_DECLARE_MUTABLE_CG_TYPE(CGContext);
Q_FORWARD_DECLARE_OBJC_CLASS(NSView);
Q_FORWARD_DECLARE_OBJC_CLASS(NSCell);
Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(NotificationReceiver));
QT_BEGIN_NAMESPACE
@ -295,13 +294,14 @@ public:
static QVector<QPointer<QObject> > scrollBars;
mutable QPointer<QFocusFrame> focusWidget;
QT_MANGLE_NAMESPACE(NotificationReceiver) *receiver;
mutable NSView *backingStoreNSView;
mutable QHash<CocoaControl, NSView *> cocoaControls;
mutable QHash<CocoaControl, NSCell *> cocoaCells;
QFont smallSystemFont;
QFont miniSystemFont;
QMacKeyValueObserver appearanceObserver;
};
QT_END_NAMESPACE

View File

@ -0,0 +1,30 @@
/****************************************************************************
**
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the documentation of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:FDL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Free Documentation License Usage
** Alternatively, this file may be used under the terms of the GNU Free
** Documentation License version 1.3 as published by the Free Software
** Foundation and appearing in the file included in the packaging of
** this file. Please review the following information to ensure
** the GNU Free Documentation License version 1.3 requirements
** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
** $QT_END_LICENSE$
**
****************************************************************************/
/*!
\dontdocument (QMetaTypeId QPlatformPrintDevice QPlatformPrinterSupportPlugin)
*/

View File

@ -0,0 +1,30 @@
/****************************************************************************
**
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the documentation of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:FDL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Free Documentation License Usage
** Alternatively, this file may be used under the terms of the GNU Free
** Documentation License version 1.3 as published by the Free Software
** Foundation and appearing in the file included in the packaging of
** this file. Please review the following information to ensure
** the GNU Free Documentation License version 1.3 requirements
** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
** $QT_END_LICENSE$
**
****************************************************************************/
/*!
\dontdocument (QTypeInfo)
*/

View File

@ -0,0 +1,32 @@
/****************************************************************************
**
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the documentation of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:FDL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Free Documentation License Usage
** Alternatively, this file may be used under the terms of the GNU Free
** Documentation License version 1.3 as published by the Free Software
** Foundation and appearing in the file included in the packaging of
** this file. Please review the following information to ensure
** the GNU Free Documentation License version 1.3 requirements
** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
** $QT_END_LICENSE$
**
****************************************************************************/
/*!
\dontdocument (QTestEventLoop QTestData QEventSizeOfChecker QSpontaneKeyEvent
QTestEvent QTestKeyEvent QTestKeyClicksEvent QTestMouseEvent
QTestDelayEvent QMetaTypeId)
*/

View File

@ -1001,7 +1001,7 @@ void Generator::generateMetacall()
needUser |= p.user.endsWith(')');
}
fprintf(out, "\n#ifndef QT_NO_PROPERTIES\n ");
fprintf(out, "\n#ifndef QT_NO_PROPERTIES\n ");
if (needElse)
fprintf(out, "else ");
fprintf(out,

Some files were not shown because too many files have changed in this diff Show More