Merge remote-tracking branch 'origin/5.12.1' into 5.12

Change-Id: Icebd151eae0cf9d400319a42573290d1a911ce26
This commit is contained in:
Qt Forward Merge Bot 2019-01-23 10:13:28 +01:00
commit e3da05f39a
75 changed files with 104138 additions and 902 deletions

167
dist/changes-5.12.1 vendored Normal file
View File

@ -0,0 +1,167 @@
Qt 5.12.1 is a bug-fix release. It maintains both forward and backward
compatibility (source and binary) with Qt 5.12.0.
For more details, refer to the online documentation included in this
distribution. The documentation is also available online:
http://doc.qt.io/qt-5/index.html
The Qt version 5.12 series is binary compatible with the 5.11.x series.
Applications compiled for 5.11 will continue to run with 5.12.
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 Behavior Changes *
****************************************************************************
- qmake / WinRT:
* Cross-builds will now ignore pre-set values of %INCLUDE% and %LIB%
when building target executables. If necessary, use configure's -I and
-L switches when building Qt, and pass QMAKE_INCDIR and QMAKE_LIBDIR
on qmake's command line when building own projects.
****************************************************************************
* Documentation *
****************************************************************************
- Fixed the icons for the "file save" action that were inaccurate
representations of a 3.5-inch floppy disk (the cut edge was on the wrong
side). Now all floppy representations are physically accurate.
****************************************************************************
* QtCore *
****************************************************************************
- [QTBUG-71256] QString, QByteArray and QLocale's toDouble return an infinity
on overflow (since 5.7), while setting ok to false; this was at odds with
their documented behavior of returning 0 on failure. The documentation now
reflects the actual behavior.
- [QTBUG-71868] QString, QByteArray and QLocale's toFloat returned an
infinity on double-overflow (since 5.7) but returned 0 on a finite double
outside float's range, while setting ok to false; this was at odds with
their documented behavior of returning 0 on any failure. They also
succeeded, returning zero, on underflow of float's range, unless double
underflowed, where they failed. Changed the handling of values outside
float's range to match that of values outside double's range: fail,
returning an infinity on overflow or zero on underflow. The documentation
now reflects the revised behavior, which matches toDouble().
- QCborStreamReader:
* [QTBUG-71426] Made setDevice() clear the last error.
- QCollator:
* [QTBUG-58621] Added support for collation in the C locale, albeit this is
only well-defined for ASCII. Collation sort keys remain unsupported on
Darwin.
- QContiguousCache:
* [QTBUG-52125] Fixed a memory leak.
- QObject:
* [QTBUG-32340] Fixed a bug that caused isSignalConnected() to return
true if the signal was connected and later disconnected.
* [QTBUG-71550] Fixed a bug that caused isSignalConnected() not to
report signals that were connected by the QML engine.
- QPluginLoader:
* [QTBUG-71443] Fixed the parsing of ELF headers (Linux, FreeBSD, Solaris,
etc.), which could cause certain valid plugins to not be deteced as
valid.
- QRegularExpression:
* [QTBUG-72539] The wildcardToRegularExpression method now returns a
properly anchored pattern.
- QSettings:
* [QTBUG-72007] Fixed QSettings parsing of blank spaces after comment lines
in INI-style configuration files.
- QStringListModel:
* setData will now emit the dataChanged() signal only if the string set
is different from the one already contained in the model
- QSysInfo:
* [QTBUG-72489] Now returns "Mojave" in prettyProductName() for macOS
10.14.
- QUrl:
* [QTBUG-71973] Changed the normalization done by
QUrl::NormalizePathSegments) to match what web browsers do for non-local
URLs.
****************************************************************************
* QtGui *
****************************************************************************
- Text:
* Fixed a bug where eliding text could change the height of its bounding
rectangle for certain fonts.
* Improved appearance of monochrome text on some platforms.
* Fixed so ShowTabsAndSpaces will use the correct font.
****************************************************************************
* QtSql *
****************************************************************************
- PostgreSQL:
* Added support for PostgreSQL 11
****************************************************************************
* QtWidgets *
****************************************************************************
- Reverted a Qt 5.12.0 behavior change in QToolTip that made plain tooltip
text be wrapped automatically.
- [QTBUG-72844] Fixed a regression related to accepting a Drag'n'Drop event.
- [QTBUG-27110] Reverted a change that caused a regression related to
styling a QListView using CSS.
- QWidgetLineControl/security:
* Zero-out the string that contains a password entered into the
QLineEdit
* Preallocate a buffer for the string that contains the entered value
when the QLineEdit serves as a password input field to minimize
reallocations.
****************************************************************************
* Platform Specific Changes *
****************************************************************************
- Android:
* QClipboard now supports HTML and URI data.
- Windows:
* Reduced the number of font engines that are created when loading new
fonts, fixing crashes in some special cases where a large number of
fonts are created during a short period of time.
- X11:
* [QTBUG-71296] Fixed a bug with open/close hand cursors not being shown
correctly.
* [QTBUG-46626][QTBUG-70756] Fixed a bug with dialogs hidden by other
windows in certain use cases.
****************************************************************************
* Third-Party Code *
****************************************************************************
- [QTBUG-65503] Removed xkbcommon from bundled sources. This library is
present on all supported platforms. The minimal required version now is
0.5.0.
- Updated bundled SQLite to version 3.26.0.
****************************************************************************
* Tools *
****************************************************************************
- moc now parses enum struct the same way as enum class therefore that
keyword can be used with the Q_ENUM macro as well as Q_FLAG and
Q_DECLARE_FLAGS.

View File

@ -3,7 +3,7 @@
dita.metadata.default.author = Qt Project dita.metadata.default.author = Qt Project
dita.metadata.default.permissions = all dita.metadata.default.permissions = all
dita.metadata.default.publisher = Qt Project dita.metadata.default.publisher = Qt Project
dita.metadata.default.copyryear = 2018 dita.metadata.default.copyryear = 2019
dita.metadata.default.copyrholder = The Qt Company Ltd dita.metadata.default.copyrholder = The Qt Company Ltd
dita.metadata.default.audience = programmer dita.metadata.default.audience = programmer

View File

@ -78,7 +78,7 @@ HTML.footer += \
" <ul id=\"menu-footer-submenu\" class=\"right clearfix\"><li id=\"menu-item-1795\" class=\"menu-item menu-item-type-custom menu-item-object-custom menu-item-1795\"><a title=\"Sign into your account.\" href=\"https://account.qt.io/login\">Sign In</a></li>\n" \ " <ul id=\"menu-footer-submenu\" class=\"right clearfix\"><li id=\"menu-item-1795\" class=\"menu-item menu-item-type-custom menu-item-object-custom menu-item-1795\"><a title=\"Sign into your account.\" href=\"https://account.qt.io/login\">Sign In</a></li>\n" \
" <li id=\"menu-item-10375\" class=\"menu-item menu-item-type-custom menu-item-object-custom menu-item-10375\"><a href=\"mailto:feedback@theqtcompany.com?Subject=Feedback%20about%20doc.qt.io%20site\">Feedback</a></li>\n" \ " <li id=\"menu-item-10375\" class=\"menu-item menu-item-type-custom menu-item-object-custom menu-item-10375\"><a href=\"mailto:feedback@theqtcompany.com?Subject=Feedback%20about%20doc.qt.io%20site\">Feedback</a></li>\n" \
" <li id=\"menu-item-1494\" class=\"menu-item menu-item-type-post_type menu-item-object-page menu-item-1494\"><a href=\"http://qt.io/contact-us/\">Contact us</a></li>\n" \ " <li id=\"menu-item-1494\" class=\"menu-item menu-item-type-post_type menu-item-object-page menu-item-1494\"><a href=\"http://qt.io/contact-us/\">Contact us</a></li>\n" \
" <li id=\"menu-item-4472\" class=\"menu-item menu-item-type-custom menu-item-object-custom menu-item-4472\"><a href=\"http://qt.io/about-us/\">© 2018 The Qt Company</a></li>\n" \ " <li id=\"menu-item-4472\" class=\"menu-item menu-item-type-custom menu-item-object-custom menu-item-4472\"><a href=\"http://qt.io/about-us/\">© 2019 The Qt Company</a></li>\n" \
" </ul>\n" \ " </ul>\n" \
"</div>\n" \ "</div>\n" \
"</div>\n" \ "</div>\n" \

View File

@ -8,7 +8,7 @@ HTML.footer = \
"</div>\n" \ "</div>\n" \
"<div class=\"footer\">\n" \ "<div class=\"footer\">\n" \
" <p>\n" \ " <p>\n" \
" <acronym title=\"Copyright\">&copy;</acronym> 2018 The Qt Company Ltd.\n" \ " <acronym title=\"Copyright\">&copy;</acronym> 2019 The Qt Company Ltd.\n" \
" Documentation contributions included herein are the copyrights of\n" \ " Documentation contributions included herein are the copyrights of\n" \
" their respective owners.<br/>" \ " their respective owners.<br/>" \
" The documentation provided herein is licensed under the terms of the" \ " The documentation provided herein is licensed under the terms of the" \

View File

@ -5,7 +5,7 @@
HTML.footer = \ HTML.footer = \
" </div>\n" \ " </div>\n" \
" <p class=\"copy-notice\">\n" \ " <p class=\"copy-notice\">\n" \
" <acronym title=\"Copyright\">&copy;</acronym> 2018 The Qt Company Ltd.\n" \ " <acronym title=\"Copyright\">&copy;</acronym> 2019 The Qt Company Ltd.\n" \
" Documentation contributions included herein are the copyrights of\n" \ " Documentation contributions included herein are the copyrights of\n" \
" their respective owners. " \ " their respective owners. " \
" The documentation provided herein is licensed under the terms of the" \ " The documentation provided herein is licensed under the terms of the" \

View File

@ -14,6 +14,7 @@ include(unix.conf)
QMAKE_RESOURCE = /Developer/Tools/Rez QMAKE_RESOURCE = /Developer/Tools/Rez
QMAKE_EXTENSION_SHLIB = dylib QMAKE_EXTENSION_SHLIB = dylib
QMAKE_EXTENSIONS_AUX_SHLIB = tbd
QMAKE_LIBDIR = QMAKE_LIBDIR =
# sdk.prf will prefix the proper SDK sysroot # sdk.prf will prefix the proper SDK sysroot

View File

@ -531,8 +531,11 @@ defineTest(qtConfResolveLibs) {
unix { unix {
# Under UNIX, we look for actual shared libraries, in addition # Under UNIX, we look for actual shared libraries, in addition
# to static ones. # to static ones.
shexts = $$QMAKE_EXTENSION_SHLIB $$QMAKE_EXTENSIONS_AUX_SHLIB
for (ext, shexts) {
lcan += $${QMAKE_PREFIX_SHLIB}$${lib}.$${ext}
}
lcan += \ lcan += \
$${QMAKE_PREFIX_SHLIB}$${lib}.$${QMAKE_EXTENSION_SHLIB} \
$${QMAKE_PREFIX_STATICLIB}$${lib}.$${QMAKE_EXTENSION_STATICLIB} $${QMAKE_PREFIX_STATICLIB}$${lib}.$${QMAKE_EXTENSION_STATICLIB}
} else { } else {
# Under Windows, we look only for static libraries, as even for DLLs # Under Windows, we look only for static libraries, as even for DLLs

View File

@ -1,4 +1,4 @@
QMAKE_TARGET_COMPANY = The Qt Company Ltd. QMAKE_TARGET_COMPANY = The Qt Company Ltd.
isEmpty(QMAKE_TARGET_PRODUCT): QMAKE_TARGET_PRODUCT = Qt5 isEmpty(QMAKE_TARGET_PRODUCT): QMAKE_TARGET_PRODUCT = Qt5
isEmpty(QMAKE_TARGET_DESCRIPTION): QMAKE_TARGET_DESCRIPTION = C++ Application Development Framework isEmpty(QMAKE_TARGET_DESCRIPTION): QMAKE_TARGET_DESCRIPTION = C++ Application Development Framework
QMAKE_TARGET_COPYRIGHT = Copyright (C) 2018 The Qt Company Ltd. QMAKE_TARGET_COPYRIGHT = Copyright (C) 2019 The Qt Company Ltd.

View File

@ -10,7 +10,6 @@ build_pass {
windeployqt.commands = $$QMAKE_WINDEPLOYQT $$WINDEPLOYQT_OPTIONS -list target $$WINDEPLOYQT_TARGET > $$WINDEPLOYQT_OUTPUT windeployqt.commands = $$QMAKE_WINDEPLOYQT $$WINDEPLOYQT_OPTIONS -list target $$WINDEPLOYQT_TARGET > $$WINDEPLOYQT_OUTPUT
windeployqt_clean.commands = if exist $$WINDEPLOYQT_OUTPUT for /f %i in ($$WINDEPLOYQT_OUTPUT) do $$QMAKE_DEL_FILE %~fi && $$QMAKE_DEL_DIR %~pi windeployqt_clean.commands = if exist $$WINDEPLOYQT_OUTPUT for /f %i in ($$WINDEPLOYQT_OUTPUT) do $$QMAKE_DEL_FILE %~fi && $$QMAKE_DEL_DIR %~pi
QMAKE_EXTRA_TARGETS += windeployqt_clean
DISTCLEAN_DEPS += windeployqt_clean DISTCLEAN_DEPS += windeployqt_clean
QMAKE_DISTCLEAN += $$WINDEPLOYQT_OUTPUT QMAKE_DISTCLEAN += $$WINDEPLOYQT_OUTPUT
} else { } else {

View File

@ -424,6 +424,9 @@ MakefileGenerator::init()
} }
incs.append(project->specDir()); incs.append(project->specDir());
const auto platform = v["QMAKE_PLATFORM"];
resolveDependenciesInFrameworks = platform.contains("darwin");
const char * const cacheKeys[] = { "_QMAKE_STASH_", "_QMAKE_SUPER_CACHE_", nullptr }; const char * const cacheKeys[] = { "_QMAKE_STASH_", "_QMAKE_SUPER_CACHE_", nullptr };
for (int i = 0; cacheKeys[i]; ++i) { for (int i = 0; cacheKeys[i]; ++i) {
if (v[cacheKeys[i]].isEmpty()) if (v[cacheKeys[i]].isEmpty())
@ -1839,6 +1842,33 @@ static QStringList splitDeps(const QString &indeps, bool lineMode)
return deps; return deps;
} }
QString MakefileGenerator::resolveDependency(const QDir &outDir, const QString &file)
{
const QList<QMakeLocalFileName> &depdirs = QMakeSourceFileInfo::dependencyPaths();
for (const auto &depdir : depdirs) {
const QString &local = depdir.local();
QString lf = outDir.absoluteFilePath(local + '/' + file);
if (exists(lf))
return lf;
if (resolveDependenciesInFrameworks) {
// Given a file like "QtWidgets/QWidget", try to resolve it
// as framework header "QtWidgets.framework/Headers/QWidget".
int cut = file.indexOf('/');
if (cut < 0 || cut + 1 >= file.size())
continue;
QStringRef framework = file.leftRef(cut);
QStringRef include = file.midRef(cut + 1);
if (local.endsWith('/' + framework + ".framework/Headers")) {
lf = outDir.absoluteFilePath(local + '/' + include);
if (exists(lf))
return lf;
}
}
}
return {};
}
void void
MakefileGenerator::writeExtraCompilerTargets(QTextStream &t) MakefileGenerator::writeExtraCompilerTargets(QTextStream &t)
{ {
@ -1991,16 +2021,7 @@ MakefileGenerator::writeExtraCompilerTargets(QTextStream &t)
} else if (exists(absFile)) { } else if (exists(absFile)) {
file = absFile; file = absFile;
} else { } else {
QString localFile; QString localFile = resolveDependency(outDir, file);
QList<QMakeLocalFileName> depdirs = QMakeSourceFileInfo::dependencyPaths();
for (QList<QMakeLocalFileName>::Iterator dit = depdirs.begin();
dit != depdirs.end(); ++dit) {
QString lf = outDir.absoluteFilePath((*dit).local() + '/' + file);
if (exists(lf)) {
localFile = lf;
break;
}
}
if (localFile.isEmpty()) { if (localFile.isEmpty()) {
if (exists(file)) if (exists(file))
warn_msg(WarnDeprecated, ".depend_command for extra compiler %s" warn_msg(WarnDeprecated, ".depend_command for extra compiler %s"
@ -2088,16 +2109,7 @@ MakefileGenerator::writeExtraCompilerTargets(QTextStream &t)
} else if (exists(absFile)) { } else if (exists(absFile)) {
file = absFile; file = absFile;
} else { } else {
QString localFile; QString localFile = resolveDependency(outDir, file);
QList<QMakeLocalFileName> depdirs = QMakeSourceFileInfo::dependencyPaths();
for (QList<QMakeLocalFileName>::Iterator dit = depdirs.begin();
dit != depdirs.end(); ++dit) {
QString lf = outDir.absoluteFilePath((*dit).local() + '/' + file);
if (exists(lf)) {
localFile = lf;
break;
}
}
if (localFile.isEmpty()) { if (localFile.isEmpty()) {
if (exists(file)) if (exists(file))
warn_msg(WarnDeprecated, ".depend_command for extra compiler %s" warn_msg(WarnDeprecated, ".depend_command for extra compiler %s"

View File

@ -55,6 +55,7 @@ class MakefileGenerator : protected QMakeSourceFileInfo
{ {
QString spec; QString spec;
bool no_io; bool no_io;
bool resolveDependenciesInFrameworks = false;
QHash<QString, bool> init_compiler_already; QHash<QString, bool> init_compiler_already;
QString makedir, chkexists; QString makedir, chkexists;
QString build_args(); QString build_args();
@ -82,6 +83,7 @@ protected:
void writeExportedVariables(QTextStream &t); void writeExportedVariables(QTextStream &t);
void writeExtraVariables(QTextStream &t); void writeExtraVariables(QTextStream &t);
void writeExtraTargets(QTextStream &t); void writeExtraTargets(QTextStream &t);
QString resolveDependency(const QDir &outDir, const QString &file);
void writeExtraCompilerTargets(QTextStream &t); void writeExtraCompilerTargets(QTextStream &t);
void writeExtraCompilerVariables(QTextStream &t); void writeExtraCompilerVariables(QTextStream &t);
bool writeDummyMakefile(QTextStream &t); bool writeDummyMakefile(QTextStream &t);

View File

@ -84,6 +84,8 @@ Win32MakefileGenerator::findLibraries(bool linkPrl, bool mergeLflags)
if (impexts.isEmpty()) if (impexts.isEmpty())
impexts = project->values("QMAKE_EXTENSION_STATICLIB"); impexts = project->values("QMAKE_EXTENSION_STATICLIB");
QList<QMakeLocalFileName> dirs; QList<QMakeLocalFileName> dirs;
for (const ProString &dlib : project->values("QMAKE_DEFAULT_LIBDIRS"))
dirs.append(QMakeLocalFileName(dlib.toQString()));
static const char * const lflags[] = { "LIBS", "LIBS_PRIVATE", static const char * const lflags[] = { "LIBS", "LIBS_PRIVATE",
"QMAKE_LIBS", "QMAKE_LIBS_PRIVATE", nullptr }; "QMAKE_LIBS", "QMAKE_LIBS_PRIVATE", nullptr };
for (int i = 0; lflags[i]; i++) { for (int i = 0; lflags[i]; i++) {

View File

@ -7,7 +7,7 @@
"Description": "strtoll() and strtoull() are functions for converting a string to (unsigned) long long integer.", "Description": "strtoll() and strtoull() are functions for converting a string to (unsigned) long long integer.",
"Homepage": "https://github.com/freebsd/freebsd/", "Homepage": "https://github.com/freebsd/freebsd/",
"Upstream": "https://raw.githubusercontent.com/freebsd/freebsd/raw/tree/master/lib/libc/stdlib/$file", "DownloadLocation": "https://github.com/freebsd/freebsd/tree/master/lib/libc/stdlib",
"Version": "upstream has complicated with std locales; do not update", "Version": "upstream has complicated with std locales; do not update",
"Version": "18b29f3fb8abee5d57ed8f4a44f806bec7e0eeff", "Version": "18b29f3fb8abee5d57ed8f4a44f806bec7e0eeff",
"License": "BSD 3-clause \"New\" or \"Revised\" License", "License": "BSD 3-clause \"New\" or \"Revised\" License",

View File

@ -69,8 +69,11 @@ DEFINES += FT2_BUILD_LIBRARY
DEFINES += FT_CONFIG_OPTION_SYSTEM_ZLIB DEFINES += FT_CONFIG_OPTION_SYSTEM_ZLIB
include(../zlib_dependency.pri) include(../zlib_dependency.pri)
DEFINES += FT_CONFIG_OPTION_USE_PNG
include($$OUT_PWD/../../gui/qtgui-config.pri) include($$OUT_PWD/../../gui/qtgui-config.pri)
QMAKE_USE_PRIVATE += libpng QT_FOR_CONFIG += gui-private
qtConfig(png) {
DEFINES += FT_CONFIG_OPTION_USE_PNG
QMAKE_USE_PRIVATE += libpng
}
DEFINES += TT_CONFIG_OPTION_SUBPIXEL_HINTING DEFINES += TT_CONFIG_OPTION_SUBPIXEL_HINTING

View File

@ -6,8 +6,8 @@
"Description": "SQLite is a small C library that implements a self-contained, embeddable, zero-configuration SQL database engine.", "Description": "SQLite is a small C library that implements a self-contained, embeddable, zero-configuration SQL database engine.",
"Homepage": "https://www.sqlite.org/", "Homepage": "https://www.sqlite.org/",
"Version": "3.24.0", "Version": "3.26.0",
"DownloadLocation": "https://www.sqlite.org/2018/sqlite-amalgamation-3240000.zip", "DownloadLocation": "https://www.sqlite.org/2018/sqlite-amalgamation-3260000.zip",
"License": "Public Domain", "License": "Public Domain",
"Copyright": "The authors disclaim copyright to the source code. However, a license can be obtained if needed." "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()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()]. ** [sqlite_version()] and [sqlite_source_id()].
*/ */
#define SQLITE_VERSION "3.25.2" #define SQLITE_VERSION "3.26.0"
#define SQLITE_VERSION_NUMBER 3025002 #define SQLITE_VERSION_NUMBER 3026000
#define SQLITE_SOURCE_ID "2018-09-25 19:08:10 fb90e7189ae6d62e77ba3a308ca5d683f90bbe633cf681865365b8e92792d1c7" #define SQLITE_SOURCE_ID "2018-12-01 12:34:55 bf8c1b2b7a5960c282e543b9c293686dccff272512d08865f4600fb58238b4f9"
/* /*
** CAPI3REF: Run-Time Library Version Numbers ** CAPI3REF: Run-Time Library Version Numbers
@ -2017,6 +2017,7 @@ struct sqlite3_mem_methods {
** is invoked. ** is invoked.
** **
** <dl> ** <dl>
** [[SQLITE_DBCONFIG_LOOKASIDE]]
** <dt>SQLITE_DBCONFIG_LOOKASIDE</dt> ** <dt>SQLITE_DBCONFIG_LOOKASIDE</dt>
** <dd> ^This option takes three additional arguments that determine the ** <dd> ^This option takes three additional arguments that determine the
** [lookaside memory allocator] configuration for the [database connection]. ** [lookaside memory allocator] configuration for the [database connection].
@ -2039,6 +2040,7 @@ struct sqlite3_mem_methods {
** memory is in use leaves the configuration unchanged and returns ** memory is in use leaves the configuration unchanged and returns
** [SQLITE_BUSY].)^</dd> ** [SQLITE_BUSY].)^</dd>
** **
** [[SQLITE_DBCONFIG_ENABLE_FKEY]]
** <dt>SQLITE_DBCONFIG_ENABLE_FKEY</dt> ** <dt>SQLITE_DBCONFIG_ENABLE_FKEY</dt>
** <dd> ^This option is used to enable or disable the enforcement of ** <dd> ^This option is used to enable or disable the enforcement of
** [foreign key constraints]. There should be two additional arguments. ** [foreign key constraints]. There should be two additional arguments.
@ -2049,6 +2051,7 @@ struct sqlite3_mem_methods {
** following this call. The second parameter may be a NULL pointer, in ** following this call. The second parameter may be a NULL pointer, in
** which case the FK enforcement setting is not reported back. </dd> ** which case the FK enforcement setting is not reported back. </dd>
** **
** [[SQLITE_DBCONFIG_ENABLE_TRIGGER]]
** <dt>SQLITE_DBCONFIG_ENABLE_TRIGGER</dt> ** <dt>SQLITE_DBCONFIG_ENABLE_TRIGGER</dt>
** <dd> ^This option is used to enable or disable [CREATE TRIGGER | triggers]. ** <dd> ^This option is used to enable or disable [CREATE TRIGGER | triggers].
** There should be two additional arguments. ** There should be two additional arguments.
@ -2059,6 +2062,7 @@ struct sqlite3_mem_methods {
** following this call. The second parameter may be a NULL pointer, in ** following this call. The second parameter may be a NULL pointer, in
** which case the trigger setting is not reported back. </dd> ** which case the trigger setting is not reported back. </dd>
** **
** [[SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER]]
** <dt>SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER</dt> ** <dt>SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER</dt>
** <dd> ^This option is used to enable or disable the two-argument ** <dd> ^This option is used to enable or disable the two-argument
** version of the [fts3_tokenizer()] function which is part of the ** version of the [fts3_tokenizer()] function which is part of the
@ -2072,6 +2076,7 @@ struct sqlite3_mem_methods {
** following this call. The second parameter may be a NULL pointer, in ** following this call. The second parameter may be a NULL pointer, in
** which case the new setting is not reported back. </dd> ** which case the new setting is not reported back. </dd>
** **
** [[SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION]]
** <dt>SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION</dt> ** <dt>SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION</dt>
** <dd> ^This option is used to enable or disable the [sqlite3_load_extension()] ** <dd> ^This option is used to enable or disable the [sqlite3_load_extension()]
** interface independently of the [load_extension()] SQL function. ** interface independently of the [load_extension()] SQL function.
@ -2089,7 +2094,7 @@ struct sqlite3_mem_methods {
** be a NULL pointer, in which case the new setting is not reported back. ** be a NULL pointer, in which case the new setting is not reported back.
** </dd> ** </dd>
** **
** <dt>SQLITE_DBCONFIG_MAINDBNAME</dt> ** [[SQLITE_DBCONFIG_MAINDBNAME]] <dt>SQLITE_DBCONFIG_MAINDBNAME</dt>
** <dd> ^This option is used to change the name of the "main" database ** <dd> ^This option is used to change the name of the "main" database
** schema. ^The sole argument is a pointer to a constant UTF8 string ** schema. ^The sole argument is a pointer to a constant UTF8 string
** which will become the new schema name in place of "main". ^SQLite ** which will become the new schema name in place of "main". ^SQLite
@ -2098,6 +2103,7 @@ struct sqlite3_mem_methods {
** until after the database connection closes. ** until after the database connection closes.
** </dd> ** </dd>
** **
** [[SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE]]
** <dt>SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE</dt> ** <dt>SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE</dt>
** <dd> Usually, when a database in wal mode is closed or detached from a ** <dd> Usually, when a database in wal mode is closed or detached from a
** database handle, SQLite checks if this will mean that there are now no ** database handle, SQLite checks if this will mean that there are now no
@ -2111,7 +2117,7 @@ struct sqlite3_mem_methods {
** have been disabled - 0 if they are not disabled, 1 if they are. ** have been disabled - 0 if they are not disabled, 1 if they are.
** </dd> ** </dd>
** **
** <dt>SQLITE_DBCONFIG_ENABLE_QPSG</dt> ** [[SQLITE_DBCONFIG_ENABLE_QPSG]] <dt>SQLITE_DBCONFIG_ENABLE_QPSG</dt>
** <dd>^(The SQLITE_DBCONFIG_ENABLE_QPSG option activates or deactivates ** <dd>^(The SQLITE_DBCONFIG_ENABLE_QPSG option activates or deactivates
** the [query planner stability guarantee] (QPSG). When the QPSG is active, ** the [query planner stability guarantee] (QPSG). When the QPSG is active,
** a single SQL query statement will always use the same algorithm regardless ** a single SQL query statement will always use the same algorithm regardless
@ -2127,7 +2133,7 @@ struct sqlite3_mem_methods {
** following this call. ** following this call.
** </dd> ** </dd>
** **
** <dt>SQLITE_DBCONFIG_TRIGGER_EQP</dt> ** [[SQLITE_DBCONFIG_TRIGGER_EQP]] <dt>SQLITE_DBCONFIG_TRIGGER_EQP</dt>
** <dd> By default, the output of EXPLAIN QUERY PLAN commands does not ** <dd> By default, the output of EXPLAIN QUERY PLAN commands does not
** include output for any operations performed by trigger programs. This ** include output for any operations performed by trigger programs. This
** option is used to set or clear (the default) a flag that governs this ** option is used to set or clear (the default) a flag that governs this
@ -2139,7 +2145,7 @@ struct sqlite3_mem_methods {
** it is not disabled, 1 if it is. ** it is not disabled, 1 if it is.
** </dd> ** </dd>
** **
** <dt>SQLITE_DBCONFIG_RESET_DATABASE</dt> ** [[SQLITE_DBCONFIG_RESET_DATABASE]] <dt>SQLITE_DBCONFIG_RESET_DATABASE</dt>
** <dd> Set the SQLITE_DBCONFIG_RESET_DATABASE flag and then run ** <dd> Set the SQLITE_DBCONFIG_RESET_DATABASE flag and then run
** [VACUUM] in order to reset a database back to an empty database ** [VACUUM] in order to reset a database back to an empty database
** with no schema and no content. The following process works even for ** with no schema and no content. The following process works even for
@ -2158,6 +2164,18 @@ struct sqlite3_mem_methods {
** Because resetting a database is destructive and irreversible, the ** Because resetting a database is destructive and irreversible, the
** process requires the use of this obscure API and multiple steps to help ** process requires the use of this obscure API and multiple steps to help
** ensure that it does not happen by accident. ** ensure that it does not happen by accident.
**
** [[SQLITE_DBCONFIG_DEFENSIVE]] <dt>SQLITE_DBCONFIG_DEFENSIVE</dt>
** <dd>The SQLITE_DBCONFIG_DEFENSIVE option activates or deactivates the
** "defensive" flag for a database connection. When the defensive
** flag is enabled, language features that allow ordinary SQL to
** deliberately corrupt the database file are disabled. The disabled
** features include but are not limited to the following:
** <ul>
** <li> The [PRAGMA writable_schema=ON] statement.
** <li> Writes to the [sqlite_dbpage] virtual table.
** <li> Direct writes to [shadow tables].
** </ul>
** </dd> ** </dd>
** </dl> ** </dl>
*/ */
@ -2171,7 +2189,8 @@ struct sqlite3_mem_methods {
#define SQLITE_DBCONFIG_ENABLE_QPSG 1007 /* int int* */ #define SQLITE_DBCONFIG_ENABLE_QPSG 1007 /* int int* */
#define SQLITE_DBCONFIG_TRIGGER_EQP 1008 /* int int* */ #define SQLITE_DBCONFIG_TRIGGER_EQP 1008 /* int int* */
#define SQLITE_DBCONFIG_RESET_DATABASE 1009 /* int int* */ #define SQLITE_DBCONFIG_RESET_DATABASE 1009 /* int int* */
#define SQLITE_DBCONFIG_MAX 1009 /* Largest DBCONFIG */ #define SQLITE_DBCONFIG_DEFENSIVE 1010 /* int int* */
#define SQLITE_DBCONFIG_MAX 1010 /* Largest DBCONFIG */
/* /*
** CAPI3REF: Enable Or Disable Extended Result Codes ** CAPI3REF: Enable Or Disable Extended Result Codes
@ -3609,9 +3628,19 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal);
** on this hint by avoiding the use of [lookaside memory] so as not to ** on this hint by avoiding the use of [lookaside memory] so as not to
** deplete the limited store of lookaside memory. Future versions of ** deplete the limited store of lookaside memory. Future versions of
** SQLite may act on this hint differently. ** SQLite may act on this hint differently.
**
** [[SQLITE_PREPARE_NORMALIZE]] ^(<dt>SQLITE_PREPARE_NORMALIZE</dt>
** <dd>The SQLITE_PREPARE_NORMALIZE flag indicates that a normalized
** representation of the SQL statement should be calculated and then
** associated with the prepared statement, which can be obtained via
** the [sqlite3_normalized_sql()] interface.)^ The semantics used to
** normalize a SQL statement are unspecified and subject to change.
** At a minimum, literal values will be replaced with suitable
** placeholders.
** </dl> ** </dl>
*/ */
#define SQLITE_PREPARE_PERSISTENT 0x01 #define SQLITE_PREPARE_PERSISTENT 0x01
#define SQLITE_PREPARE_NORMALIZE 0x02
/* /*
** CAPI3REF: Compiling An SQL Statement ** CAPI3REF: Compiling An SQL Statement
@ -3769,6 +3798,11 @@ SQLITE_API int sqlite3_prepare16_v3(
** ^The sqlite3_expanded_sql(P) interface returns a pointer to a UTF-8 ** ^The sqlite3_expanded_sql(P) interface returns a pointer to a UTF-8
** string containing the SQL text of prepared statement P with ** string containing the SQL text of prepared statement P with
** [bound parameters] expanded. ** [bound parameters] expanded.
** ^The sqlite3_normalized_sql(P) interface returns a pointer to a UTF-8
** string containing the normalized SQL text of prepared statement P. The
** semantics used to normalize a SQL statement are unspecified and subject
** to change. At a minimum, literal values will be replaced with suitable
** placeholders.
** **
** ^(For example, if a prepared statement is created using the SQL ** ^(For example, if a prepared statement is created using the SQL
** text "SELECT $abc,:xyz" and if parameter $abc is bound to integer 2345 ** text "SELECT $abc,:xyz" and if parameter $abc is bound to integer 2345
@ -3784,14 +3818,16 @@ SQLITE_API int sqlite3_prepare16_v3(
** bound parameter expansions. ^The [SQLITE_OMIT_TRACE] compile-time ** bound parameter expansions. ^The [SQLITE_OMIT_TRACE] compile-time
** option causes sqlite3_expanded_sql() to always return NULL. ** option causes sqlite3_expanded_sql() to always return NULL.
** **
** ^The string returned by sqlite3_sql(P) is managed by SQLite and is ** ^The strings returned by sqlite3_sql(P) and sqlite3_normalized_sql(P)
** automatically freed when the prepared statement is finalized. ** are managed by SQLite and are automatically freed when the prepared
** statement is finalized.
** ^The string returned by sqlite3_expanded_sql(P), on the other hand, ** ^The string returned by sqlite3_expanded_sql(P), on the other hand,
** is obtained from [sqlite3_malloc()] and must be free by the application ** is obtained from [sqlite3_malloc()] and must be free by the application
** by passing it to [sqlite3_free()]. ** by passing it to [sqlite3_free()].
*/ */
SQLITE_API const char *sqlite3_sql(sqlite3_stmt *pStmt); SQLITE_API const char *sqlite3_sql(sqlite3_stmt *pStmt);
SQLITE_API char *sqlite3_expanded_sql(sqlite3_stmt *pStmt); SQLITE_API char *sqlite3_expanded_sql(sqlite3_stmt *pStmt);
SQLITE_API const char *sqlite3_normalized_sql(sqlite3_stmt *pStmt);
/* /*
** CAPI3REF: Determine If An SQL Statement Writes The Database ** CAPI3REF: Determine If An SQL Statement Writes The Database
@ -6281,6 +6317,9 @@ struct sqlite3_module {
int (*xSavepoint)(sqlite3_vtab *pVTab, int); int (*xSavepoint)(sqlite3_vtab *pVTab, int);
int (*xRelease)(sqlite3_vtab *pVTab, int); int (*xRelease)(sqlite3_vtab *pVTab, int);
int (*xRollbackTo)(sqlite3_vtab *pVTab, int); int (*xRollbackTo)(sqlite3_vtab *pVTab, int);
/* The methods above are in versions 1 and 2 of the sqlite_module object.
** Those below are for version 3 and greater. */
int (*xShadowName)(const char*);
}; };
/* /*
@ -7203,6 +7242,7 @@ SQLITE_API int sqlite3_test_control(int op, ...);
#define SQLITE_TESTCTRL_OPTIMIZATIONS 15 #define SQLITE_TESTCTRL_OPTIMIZATIONS 15
#define SQLITE_TESTCTRL_ISKEYWORD 16 /* NOT USED */ #define SQLITE_TESTCTRL_ISKEYWORD 16 /* NOT USED */
#define SQLITE_TESTCTRL_SCRATCHMALLOC 17 /* NOT USED */ #define SQLITE_TESTCTRL_SCRATCHMALLOC 17 /* NOT USED */
#define SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 17
#define SQLITE_TESTCTRL_LOCALTIME_FAULT 18 #define SQLITE_TESTCTRL_LOCALTIME_FAULT 18
#define SQLITE_TESTCTRL_EXPLAIN_STMT 19 /* NOT USED */ #define SQLITE_TESTCTRL_EXPLAIN_STMT 19 /* NOT USED */
#define SQLITE_TESTCTRL_ONCE_RESET_THRESHOLD 19 #define SQLITE_TESTCTRL_ONCE_RESET_THRESHOLD 19
@ -8615,6 +8655,7 @@ SQLITE_API int sqlite3_vtab_config(sqlite3*, int op, ...);
** can use to customize and optimize their behavior. ** can use to customize and optimize their behavior.
** **
** <dl> ** <dl>
** [[SQLITE_VTAB_CONSTRAINT_SUPPORT]]
** <dt>SQLITE_VTAB_CONSTRAINT_SUPPORT ** <dt>SQLITE_VTAB_CONSTRAINT_SUPPORT
** <dd>Calls of the form ** <dd>Calls of the form
** [sqlite3_vtab_config](db,SQLITE_VTAB_CONSTRAINT_SUPPORT,X) are supported, ** [sqlite3_vtab_config](db,SQLITE_VTAB_CONSTRAINT_SUPPORT,X) are supported,
@ -9384,7 +9425,7 @@ struct sqlite3_rtree_query_info {
sqlite3_int64 iRowid; /* Rowid for current entry */ sqlite3_int64 iRowid; /* Rowid for current entry */
sqlite3_rtree_dbl rParentScore; /* Score of parent node */ sqlite3_rtree_dbl rParentScore; /* Score of parent node */
int eParentWithin; /* Visibility of parent node */ int eParentWithin; /* Visibility of parent node */
int eWithin; /* OUT: Visiblity */ int eWithin; /* OUT: Visibility */
sqlite3_rtree_dbl rScore; /* OUT: Write the score here */ sqlite3_rtree_dbl rScore; /* OUT: Write the score here */
/* The following fields are only available in 3.8.11 and later */ /* The following fields are only available in 3.8.11 and later */
sqlite3_value **apSqlParam; /* Original SQL values of parameters */ sqlite3_value **apSqlParam; /* Original SQL values of parameters */
@ -9880,12 +9921,38 @@ SQLITE_API int sqlite3session_isempty(sqlite3_session *pSession);
** consecutively. There is no chance that the iterator will visit a change ** consecutively. There is no chance that the iterator will visit a change
** the applies to table X, then one for table Y, and then later on visit ** the applies to table X, then one for table Y, and then later on visit
** another change for table X. ** another change for table X.
**
** The behavior of sqlite3changeset_start_v2() and its streaming equivalent
** may be modified by passing a combination of
** [SQLITE_CHANGESETSTART_INVERT | supported flags] as the 4th parameter.
**
** Note that the sqlite3changeset_start_v2() API is still <b>experimental</b>
** and therefore subject to change.
*/ */
SQLITE_API int sqlite3changeset_start( SQLITE_API int sqlite3changeset_start(
sqlite3_changeset_iter **pp, /* OUT: New changeset iterator handle */ sqlite3_changeset_iter **pp, /* OUT: New changeset iterator handle */
int nChangeset, /* Size of changeset blob in bytes */ int nChangeset, /* Size of changeset blob in bytes */
void *pChangeset /* Pointer to blob containing changeset */ void *pChangeset /* Pointer to blob containing changeset */
); );
SQLITE_API int sqlite3changeset_start_v2(
sqlite3_changeset_iter **pp, /* OUT: New changeset iterator handle */
int nChangeset, /* Size of changeset blob in bytes */
void *pChangeset, /* Pointer to blob containing changeset */
int flags /* SESSION_CHANGESETSTART_* flags */
);
/*
** CAPI3REF: Flags for sqlite3changeset_start_v2
**
** The following flags may passed via the 4th parameter to
** [sqlite3changeset_start_v2] and [sqlite3changeset_start_v2_strm]:
**
** <dt>SQLITE_CHANGESETAPPLY_INVERT <dd>
** Invert the changeset while iterating through it. This is equivalent to
** inverting a changeset using sqlite3changeset_invert() before applying it.
** It is an error to specify this flag with a patchset.
*/
#define SQLITE_CHANGESETSTART_INVERT 0x0002
/* /*
@ -10540,7 +10607,7 @@ SQLITE_API int sqlite3changeset_apply_v2(
), ),
void *pCtx, /* First argument passed to xConflict */ void *pCtx, /* First argument passed to xConflict */
void **ppRebase, int *pnRebase, /* OUT: Rebase data */ void **ppRebase, int *pnRebase, /* OUT: Rebase data */
int flags /* Combination of SESSION_APPLY_* flags */ int flags /* SESSION_CHANGESETAPPLY_* flags */
); );
/* /*
@ -10558,8 +10625,14 @@ SQLITE_API int sqlite3changeset_apply_v2(
** causes the sessions module to omit this savepoint. In this case, if the ** causes the sessions module to omit this savepoint. In this case, if the
** caller has an open transaction or savepoint when apply_v2() is called, ** caller has an open transaction or savepoint when apply_v2() is called,
** it may revert the partially applied changeset by rolling it back. ** it may revert the partially applied changeset by rolling it back.
**
** <dt>SQLITE_CHANGESETAPPLY_INVERT <dd>
** Invert the changeset before applying it. This is equivalent to inverting
** a changeset using sqlite3changeset_invert() before applying it. It is
** an error to specify this flag with a patchset.
*/ */
#define SQLITE_CHANGESETAPPLY_NOSAVEPOINT 0x0001 #define SQLITE_CHANGESETAPPLY_NOSAVEPOINT 0x0001
#define SQLITE_CHANGESETAPPLY_INVERT 0x0002
/* /*
** CAPI3REF: Constants Passed To The Conflict Handler ** CAPI3REF: Constants Passed To The Conflict Handler
@ -10953,6 +11026,12 @@ SQLITE_API int sqlite3changeset_start_strm(
int (*xInput)(void *pIn, void *pData, int *pnData), int (*xInput)(void *pIn, void *pData, int *pnData),
void *pIn void *pIn
); );
SQLITE_API int sqlite3changeset_start_v2_strm(
sqlite3_changeset_iter **pp,
int (*xInput)(void *pIn, void *pData, int *pnData),
void *pIn,
int flags
);
SQLITE_API int sqlite3session_changeset_strm( SQLITE_API int sqlite3session_changeset_strm(
sqlite3_session *pSession, sqlite3_session *pSession,
int (*xOutput)(void *pOut, const void *pData, int nData), int (*xOutput)(void *pOut, const void *pData, int nData),
@ -10979,6 +11058,45 @@ SQLITE_API int sqlite3rebaser_rebase_strm(
void *pOut void *pOut
); );
/*
** CAPI3REF: Configure global parameters
**
** The sqlite3session_config() interface is used to make global configuration
** changes to the sessions module in order to tune it to the specific needs
** of the application.
**
** The sqlite3session_config() interface is not threadsafe. If it is invoked
** while any other thread is inside any other sessions method then the
** results are undefined. Furthermore, if it is invoked after any sessions
** related objects have been created, the results are also undefined.
**
** The first argument to the sqlite3session_config() function must be one
** of the SQLITE_SESSION_CONFIG_XXX constants defined below. The
** interpretation of the (void*) value passed as the second parameter and
** the effect of calling this function depends on the value of the first
** parameter.
**
** <dl>
** <dt>SQLITE_SESSION_CONFIG_STRMSIZE<dd>
** By default, the sessions module streaming interfaces attempt to input
** and output data in approximately 1 KiB chunks. This operand may be used
** to set and query the value of this configuration setting. The pointer
** passed as the second argument must point to a value of type (int).
** If this value is greater than 0, it is used as the new streaming data
** chunk size for both input and output. Before returning, the (int) value
** pointed to by pArg is set to the final value of the streaming interface
** chunk size.
** </dl>
**
** This function returns SQLITE_OK if successful, or an SQLite error code
** otherwise.
*/
SQLITE_API int sqlite3session_config(int op, void *pArg);
/*
** CAPI3REF: Values for sqlite3session_config().
*/
#define SQLITE_SESSION_CONFIG_STRMSIZE 1
/* /*
** Make sure we can call this stuff from C++. ** Make sure we can call this stuff from C++.

View File

@ -612,7 +612,7 @@ public abstract class QtLoader {
} }
if (m_qtLibs != null) { if (m_qtLibs != null) {
String libPrefix = apkDeployFromSystem ? libsDir + "lib" : localPrefix + "lib/lib"; String libPrefix = libsDir + "lib";
for (int i = 0; i < m_qtLibs.length; i++) for (int i = 0; i < m_qtLibs.length; i++)
libraryList.add(libPrefix + m_qtLibs[i] + ".so"); libraryList.add(libPrefix + m_qtLibs[i] + ".so");
} }

View File

@ -83,8 +83,12 @@ QString QWindowsLocalCodec::convertToUnicode(const char *chars, int length, Conv
len = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, len = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED,
prev, 2, wc.data(), wc.length()); prev, 2, wc.data(), wc.length());
if (len) { if (len) {
prepend = true;
sp.append(QChar(wc[0])); sp.append(QChar(wc[0]));
if (mblen == 1) {
state->remainingChars = 0;
return sp;
}
prepend = true;
mb++; mb++;
mblen--; mblen--;
wc[0] = 0; wc[0] = 0;

View File

@ -45,6 +45,9 @@ excludedirs += snippets
excludefiles += ../../../examples/widgets/tools/customcompleter/doc/src/customcompleter.qdoc \ excludefiles += ../../../examples/widgets/tools/customcompleter/doc/src/customcompleter.qdoc \
../../../examples/widgets/tools/codecs/doc/src/codecs.qdoc ../../../examples/widgets/tools/codecs/doc/src/codecs.qdoc
# Included in qttestlib.qdocconf instead
excludefiles += ../kernel/qtestsupport_core.cpp
manifestmeta.highlighted.names = "QtCore/JSON Save Game Example" \ manifestmeta.highlighted.names = "QtCore/JSON Save Game Example" \
"QtCore/Local Fortune*" "QtCore/Local Fortune*"

View File

@ -2025,6 +2025,8 @@ static const char *osVer_helper(QOperatingSystemVersion version = QOperatingSyst
return "Sierra"; return "Sierra";
case 13: case 13:
return "High Sierra"; return "High Sierra";
case 14:
return "Mojave";
} }
} }
// unknown, future version // unknown, future version

View File

@ -348,7 +348,7 @@ template <> inline bool mul_overflow(qint64 v1, qint64 v2, qint64 *r)
// as signed for the low bits and use a signed right shift to verify that // as signed for the low bits and use a signed right shift to verify that
// 'high' is nothing but sign bits that match the sign of 'low'. // 'high' is nothing but sign bits that match the sign of 'low'.
qint64 high = __mulh(v1, v2); qint64 high = Q_SMULH(v1, v2);
*r = qint64(quint64(v1) * quint64(v2)); *r = qint64(quint64(v1) * quint64(v2));
return (*r >> 63) != high; return (*r >> 63) != high;
} }

View File

@ -748,6 +748,21 @@ static int drivePrefixLength(const QString &path)
} }
#endif // Q_OS_WIN #endif // Q_OS_WIN
static bool treatAsAbsolute(const QString &path)
{
// ### Qt 6: be consistent about absolute paths
// QFileInfo will use the right FS-engine for virtual file-systems
// (e.g. resource paths). Unfortunately, for real file-systems, it relies
// on QFileSystemEntry's isRelative(), which is flawed on MS-Win, ignoring
// its (correct) isAbsolute(). So only use that isAbsolute() unless there's
// a colon in the path.
// FIXME: relies on virtual file-systems having colons in their prefixes.
// The case of an MS-absolute C:/... path happens to work either way.
return (path.contains(QLatin1Char(':')) && QFileInfo(path).isAbsolute())
|| QFileSystemEntry(path).isAbsolute();
}
/*! /*!
Returns the path name of a file in the directory. Does \e not Returns the path name of a file in the directory. Does \e not
check if the file actually exists in the directory; but see check if the file actually exists in the directory; but see
@ -759,13 +774,10 @@ static int drivePrefixLength(const QString &path)
*/ */
QString QDir::filePath(const QString &fileName) const QString QDir::filePath(const QString &fileName) const
{ {
const QDirPrivate* d = d_ptr.constData(); if (treatAsAbsolute(fileName))
// Mistrust our own isAbsolutePath() for real files; Q_OS_WIN needs a drive.
if (fileName.startsWith(QLatin1Char(':')) // i.e. resource path
? isAbsolutePath(fileName) : QFileSystemEntry(fileName).isAbsolute()) {
return fileName; return fileName;
}
const QDirPrivate* d = d_ptr.constData();
QString ret = d->dirEntry.filePath(); QString ret = d->dirEntry.filePath();
if (fileName.isEmpty()) if (fileName.isEmpty())
return ret; return ret;
@ -793,13 +805,10 @@ QString QDir::filePath(const QString &fileName) const
*/ */
QString QDir::absoluteFilePath(const QString &fileName) const QString QDir::absoluteFilePath(const QString &fileName) const
{ {
const QDirPrivate* d = d_ptr.constData(); if (treatAsAbsolute(fileName))
// Mistrust our own isAbsolutePath() for real files; Q_OS_WIN needs a drive.
if (fileName.startsWith(QLatin1Char(':')) // i.e. resource path
? isAbsolutePath(fileName) : QFileSystemEntry(fileName).isAbsolute()) {
return fileName; return fileName;
}
const QDirPrivate* d = d_ptr.constData();
d->resolveAbsoluteEntry(); d->resolveAbsoluteEntry();
const QString absoluteDirPath = d->absoluteDirEntry.filePath(); const QString absoluteDirPath = d->absoluteDirEntry.filePath();
if (fileName.isEmpty()) if (fileName.isEmpty())
@ -2160,9 +2169,10 @@ bool QDir::match(const QString &filter, const QString &fileName)
This method is shared with QUrl, so it doesn't deal with QDir::separator(), This method is shared with QUrl, so it doesn't deal with QDir::separator(),
nor does it remove the trailing slash, if any. nor does it remove the trailing slash, if any.
*/ */
Q_AUTOTEST_EXPORT QString qt_normalizePathSegments(const QString &name, bool allowUncPaths, QString qt_normalizePathSegments(const QString &name, QDirPrivate::PathNormalizations flags, bool *ok)
bool *ok = nullptr)
{ {
const bool allowUncPaths = QDirPrivate::AllowUncPaths & flags;
const bool isRemote = QDirPrivate::RemotePath & flags;
const int len = name.length(); const int len = name.length();
if (ok) if (ok)
@ -2184,14 +2194,30 @@ Q_AUTOTEST_EXPORT QString qt_normalizePathSegments(const QString &name, bool all
i -= prefixLength; i -= prefixLength;
// replicate trailing slash (i > 0 checks for emptiness of input string p) // replicate trailing slash (i > 0 checks for emptiness of input string p)
if (i > 0 && p[i] == '/') { // except for remote paths because there can be /../ or /./ ending
if (i > 0 && p[i] == '/' && !isRemote) {
out[--used] = '/'; out[--used] = '/';
--i; --i;
} }
auto isDot = [](const ushort *p, int i) {
return i > 1 && p[i - 1] == '.' && p[i - 2] == '/';
};
auto isDotDot = [](const ushort *p, int i) {
return i > 2 && p[i - 1] == '.' && p[i - 2] == '.' && p[i - 3] == '/';
};
while (i >= 0) { while (i >= 0) {
// remove trailing slashes // copy trailing slashes for remote urls
if (p[i] == '/') { if (p[i] == '/') {
if (isRemote && !up) {
if (isDot(p, i)) {
i -= 2;
continue;
}
out[--used] = p[i];
}
--i; --i;
continue; continue;
} }
@ -2203,10 +2229,17 @@ Q_AUTOTEST_EXPORT QString qt_normalizePathSegments(const QString &name, bool all
} }
// detect up dir // detect up dir
if (i >= 1 && p[i] == '.' && p[i-1] == '.' if (i >= 1 && p[i] == '.' && p[i-1] == '.' && (i < 2 || p[i - 2] == '/')) {
&& (i == 1 || (i >= 2 && p[i-2] == '/'))) {
++up; ++up;
i -= 2; i -= i >= 2 ? 3 : 2;
if (isRemote) {
// moving up should consider empty path segments too (/path//../ -> /path/)
while (i > 0 && up && p[i] == '/') {
--up;
--i;
}
}
continue; continue;
} }
@ -2216,7 +2249,27 @@ Q_AUTOTEST_EXPORT QString qt_normalizePathSegments(const QString &name, bool all
// skip or copy // skip or copy
while (i >= 0) { while (i >= 0) {
if (p[i] == '/') { // do not copy slashes if (p[i] == '/') {
// copy all slashes as is for remote urls if they are not part of /./ or /../
if (isRemote && !up) {
while (i > 0 && p[i] == '/' && !isDotDot(p, i)) {
if (isDot(p, i)) {
i -= 2;
continue;
}
out[--used] = p[i];
--i;
}
// in case of /./, jump over
if (isDot(p, i))
i -= 2;
break;
}
--i; --i;
break; break;
} }
@ -2237,7 +2290,7 @@ Q_AUTOTEST_EXPORT QString qt_normalizePathSegments(const QString &name, bool all
*ok = prefixLength == 0 || up == 0; *ok = prefixLength == 0 || up == 0;
// add remaining '..' // add remaining '..'
while (up) { while (up && !isRemote) {
if (used != len && out[used] != '/') // is not empty and there isn't already a '/' if (used != len && out[used] != '/') // is not empty and there isn't already a '/'
out[--used] = '/'; out[--used] = '/';
out[--used] = '.'; out[--used] = '.';
@ -2283,7 +2336,7 @@ static QString qt_cleanPath(const QString &path, bool *ok)
if (dir_separator != QLatin1Char('/')) if (dir_separator != QLatin1Char('/'))
name.replace(dir_separator, QLatin1Char('/')); name.replace(dir_separator, QLatin1Char('/'));
QString ret = qt_normalizePathSegments(name, OSSupportsUncPaths, ok); QString ret = qt_normalizePathSegments(name, OSSupportsUncPaths ? QDirPrivate::AllowUncPaths : QDirPrivate::DefaultNormalization, ok);
// Strip away last slash except for root directories // Strip away last slash except for root directories
if (ret.length() > 1 && ret.endsWith(QLatin1Char('/'))) { if (ret.length() > 1 && ret.endsWith(QLatin1Char('/'))) {

View File

@ -59,6 +59,14 @@ QT_BEGIN_NAMESPACE
class QDirPrivate : public QSharedData class QDirPrivate : public QSharedData
{ {
public: public:
enum PathNormalization {
DefaultNormalization = 0x00,
AllowUncPaths = 0x01,
RemotePath = 0x02
};
Q_DECLARE_FLAGS(PathNormalizations, PathNormalization)
Q_FLAGS(PathNormalizations)
explicit QDirPrivate(const QString &path, const QStringList &nameFilters_ = QStringList(), explicit QDirPrivate(const QString &path, const QStringList &nameFilters_ = QStringList(),
QDir::SortFlags sort_ = QDir::SortFlags(QDir::Name | QDir::IgnoreCase), QDir::SortFlags sort_ = QDir::SortFlags(QDir::Name | QDir::IgnoreCase),
QDir::Filters filters_ = QDir::AllEntries); QDir::Filters filters_ = QDir::AllEntries);
@ -97,6 +105,10 @@ public:
mutable QFileSystemMetaData metaData; mutable QFileSystemMetaData metaData;
}; };
Q_DECLARE_OPERATORS_FOR_FLAGS(QDirPrivate::PathNormalizations)
Q_AUTOTEST_EXPORT QString qt_normalizePathSegments(const QString &name, QDirPrivate::PathNormalizations flags, bool *ok = nullptr);
QT_END_NAMESPACE QT_END_NAMESPACE
#endif #endif

View File

@ -253,7 +253,8 @@
and contains no query or fragment, a local file path is returned. and contains no query or fragment, a local file path is returned.
\value StripTrailingSlash The trailing slash is removed from the path, if one is present. \value StripTrailingSlash The trailing slash is removed from the path, if one is present.
\value NormalizePathSegments Modifies the path to remove redundant directory separators, \value NormalizePathSegments Modifies the path to remove redundant directory separators,
and to resolve "."s and ".."s (as far as possible). and to resolve "."s and ".."s (as far as possible). For non-local paths, adjacent
slashes are preserved.
Note that the case folding rules in \l{RFC 3491}{Nameprep}, which QUrl Note that the case folding rules in \l{RFC 3491}{Nameprep}, which QUrl
conforms to, require host names to always be converted to lower case, conforms to, require host names to always be converted to lower case,
@ -419,10 +420,9 @@
#endif #endif
#include "private/qipaddress_p.h" #include "private/qipaddress_p.h"
#include "qurlquery.h" #include "qurlquery.h"
#include "private/qdir_p.h"
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
extern QString qt_normalizePathSegments(const QString &name, bool allowUncPaths,
bool *ok = nullptr); // qdir.cpp
inline static bool isHex(char c) inline static bool isHex(char c)
{ {
@ -930,7 +930,7 @@ inline void QUrlPrivate::appendPath(QString &appendTo, QUrl::FormattingOptions o
{ {
QString thePath = path; QString thePath = path;
if (options & QUrl::NormalizePathSegments) { if (options & QUrl::NormalizePathSegments) {
thePath = qt_normalizePathSegments(path, false); thePath = qt_normalizePathSegments(path, isLocalFile() ? QDirPrivate::DefaultNormalization : QDirPrivate::RemotePath);
} }
QStringRef thePathRef(&thePath); QStringRef thePathRef(&thePath);

View File

@ -59,8 +59,7 @@ Q_CORE_EXPORT void QTestPrivate::qSleep(int ms)
#endif #endif
} }
/*! \fn template <typename Functor> bool qWaitFor(Functor predicate, int timeout) /*! \fn template <typename Functor> bool QTest::qWaitFor(Functor predicate, int timeout)
\relates QTest
Waits for \a timeout milliseconds or until the \a predicate returns true. Waits for \a timeout milliseconds or until the \a predicate returns true.
@ -77,8 +76,7 @@ Q_CORE_EXPORT void QTestPrivate::qSleep(int ms)
*/ */
/*! \fn void qWait(int ms) /*! \fn void QTest::qWait(int ms)
\relates QTest
Waits for \a ms milliseconds. While waiting, events will be processed and Waits for \a ms milliseconds. While waiting, events will be processed and
your test will stay responsive to user interface events or network communication. your test will stay responsive to user interface events or network communication.

View File

@ -54,7 +54,10 @@ exampledirs += ../../../examples/gui \
imagedirs += images \ imagedirs += images \
../../../examples/gui/doc/images \ ../../../examples/gui/doc/images \
../../../doc/src/images \ ../../../doc/src/images
# Included in qttestlib.qdocconf instead
excludefiles += ../kernel/qtestsupport_gui.cpp
manifestmeta.highlighted.names = "QtGui/Analog Clock Window Example" manifestmeta.highlighted.names = "QtGui/Analog Clock Window Example"

View File

@ -188,7 +188,7 @@ static bool read_dib_infoheader(QDataStream &s, BMP_INFOHDR &bi)
if (!(comp == BMP_RGB || (nbits == 4 && comp == BMP_RLE4) || if (!(comp == BMP_RGB || (nbits == 4 && comp == BMP_RLE4) ||
(nbits == 8 && comp == BMP_RLE8) || ((nbits == 16 || nbits == 32) && comp == BMP_BITFIELDS))) (nbits == 8 && comp == BMP_RLE8) || ((nbits == 16 || nbits == 32) && comp == BMP_BITFIELDS)))
return false; // weird compression type return false; // weird compression type
if (bi.biWidth < 0 || quint64(bi.biWidth) * qAbs(bi.biHeight) > 16384 * 16384) if (bi.biWidth <= 0 || !bi.biHeight || quint64(bi.biWidth) * qAbs(bi.biHeight) > 16384 * 16384)
return false; return false;
return true; return true;

View File

@ -3543,7 +3543,7 @@ void QImage::rgbSwapped_inplace()
The loader attempts to read the image using the specified \a format, e.g., The loader attempts to read the image using the specified \a format, e.g.,
PNG or JPG. If \a format is not specified (which is the default), it is PNG or JPG. If \a format is not specified (which is the default), it is
auto-detected based on the file's suffix and header. For details, see auto-detected based on the file's suffix and header. For details, see
{QImageReader::setAutoDetectImageFormat()}{QImageReader}. QImageReader::setAutoDetectImageFormat().
The file name can either refer to an actual file on disk or to one The file name can either refer to an actual file on disk or to one
of the application's embedded resources. See the of the application's embedded resources. See the

View File

@ -108,7 +108,7 @@ public:
virtual bool isActive() const; virtual bool isActive() const;
virtual bool isAncestorOf(const QPlatformWindow *child) const; virtual bool isAncestorOf(const QPlatformWindow *child) const;
virtual bool isEmbedded() const; virtual bool isEmbedded() const;
virtual bool isForeignWindow() const { return window()->type() == Qt::ForeignWindow; }; virtual bool isForeignWindow() const { return false; };
virtual QPoint mapToGlobal(const QPoint &pos) const; virtual QPoint mapToGlobal(const QPoint &pos) const;
virtual QPoint mapFromGlobal(const QPoint &pos) const; virtual QPoint mapFromGlobal(const QPoint &pos) const;

View File

@ -44,23 +44,21 @@
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
/*! \fn bool qWaitForWindowActive(QWindow *window, int timeout) /*!
\relates QTest
\since 5.0 \since 5.0
Waits for \a timeout milliseconds or until the \a window is active. Waits for \a timeout milliseconds or until the \a window is active.
Returns \c true if \c window is active within \a timeout milliseconds, otherwise returns \c false. Returns \c true if \c window is active within \a timeout milliseconds, otherwise returns \c false.
\sa QTest::qWaitForWindowExposed(), QWindow::isActive() \sa qWaitForWindowExposed(), QWindow::isActive()
*/ */
Q_GUI_EXPORT bool QTest::qWaitForWindowActive(QWindow *window, int timeout) Q_GUI_EXPORT bool QTest::qWaitForWindowActive(QWindow *window, int timeout)
{ {
return QTest::qWaitFor([&]() { return window->isActive(); }, timeout); return QTest::qWaitFor([&]() { return window->isActive(); }, timeout);
} }
/*! \fn bool qWaitForWindowExposed(QWindow *window, int timeout) /*!
\relates QTest
\since 5.0 \since 5.0
Waits for \a timeout milliseconds or until the \a window is exposed. Waits for \a timeout milliseconds or until the \a window is exposed.
@ -73,7 +71,7 @@ Q_GUI_EXPORT bool QTest::qWaitForWindowActive(QWindow *window, int timeout)
area is completely covered by other windows, or if the window is otherwise not visible. This function area is completely covered by other windows, or if the window is otherwise not visible. This function
will then time out when waiting for such a window. will then time out when waiting for such a window.
\sa QTest::qWaitForWindowActive(), QWindow::isExposed() \sa qWaitForWindowActive(), QWindow::isExposed()
*/ */
Q_GUI_EXPORT bool QTest::qWaitForWindowExposed(QWindow *window, int timeout) Q_GUI_EXPORT bool QTest::qWaitForWindowExposed(QWindow *window, int timeout)
{ {

View File

@ -919,8 +919,7 @@ void QWindow::setFlag(Qt::WindowType flag, bool on)
*/ */
Qt::WindowType QWindow::type() const Qt::WindowType QWindow::type() const
{ {
Q_D(const QWindow); return static_cast<Qt::WindowType>(int(flags() & Qt::WindowType_Mask));
return static_cast<Qt::WindowType>(int(d->windowFlags & Qt::WindowType_Mask));
} }
/*! /*!

View File

@ -1953,13 +1953,14 @@ void QPdfEnginePrivate::writePage()
"/Contents %d 0 R\n" "/Contents %d 0 R\n"
"/Resources %d 0 R\n" "/Resources %d 0 R\n"
"/Annots %d 0 R\n" "/Annots %d 0 R\n"
"/MediaBox [0 0 %f %f]\n", "/MediaBox [0 0 %s %s]\n",
pageRoot, pageStream, resources, annots, pageRoot, pageStream, resources, annots,
// make sure we use the pagesize from when we started the page, since the user may have changed it // make sure we use the pagesize from when we started the page, since the user may have changed it
currentPage->pageSize.width() / userUnit, currentPage->pageSize.height() / userUnit); QByteArray::number(currentPage->pageSize.width() / userUnit, 'f').constData(),
QByteArray::number(currentPage->pageSize.height() / userUnit, 'f').constData());
if (pdfVersion >= QPdfEngine::Version_1_6) if (pdfVersion >= QPdfEngine::Version_1_6)
xprintf("/UserUnit %f\n", userUnit); xprintf("/UserUnit %s\n", QByteArray::number(userUnit, 'f').constData());
xprintf(">>\n" xprintf(">>\n"
"endobj\n"); "endobj\n");

View File

@ -1972,14 +1972,18 @@ void QTextEngine::shape(int item) const
} }
// fix log clusters to point to the previous glyph, as the object doesn't have a glyph of it's own. // fix log clusters to point to the previous glyph, as the object doesn't have a glyph of it's own.
// This is required so that all entries in the array get initialized and are ordered correctly. // This is required so that all entries in the array get initialized and are ordered correctly.
ushort *lc = logClusters(&li); if (layoutData->logClustersPtr) {
*lc = item ? lc[-1] : 0; ushort *lc = logClusters(&li);
*lc = (lc != layoutData->logClustersPtr) ? lc[-1] : 0;
}
} else if (li.analysis.flags == QScriptAnalysis::Tab) { } else if (li.analysis.flags == QScriptAnalysis::Tab) {
// set up at least the ascent/descent/leading of the script item for the tab // set up at least the ascent/descent/leading of the script item for the tab
fontEngine(li, &li.ascent, &li.descent, &li.leading); fontEngine(li, &li.ascent, &li.descent, &li.leading);
// see the comment above // see the comment above
ushort *lc = logClusters(&li); if (layoutData->logClustersPtr) {
*lc = item ? lc[-1] : 0; ushort *lc = logClusters(&li);
*lc = (lc != layoutData->logClustersPtr) ? lc[-1] : 0;
}
} else { } else {
shapeText(item); shapeText(item);
} }

View File

@ -464,8 +464,10 @@ static QNetworkInterface::InterfaceType probeIfType(int socket, int iftype, stru
case IFM_ETHER: case IFM_ETHER:
return QNetworkInterface::Ethernet; return QNetworkInterface::Ethernet;
#ifdef IFM_FDDI
case IFM_FDDI: case IFM_FDDI:
return QNetworkInterface::Fddi; return QNetworkInterface::Fddi;
#endif
case IFM_IEEE80211: case IFM_IEEE80211:
return QNetworkInterface::Ieee80211; return QNetworkInterface::Ieee80211;

View File

@ -75,7 +75,7 @@ namespace QPasswordDigestor {
\a salt must always be 8 bytes long! \a salt must always be 8 bytes long!
\note This function is provided for use with legacy applications and all \note This function is provided for use with legacy applications and all
new applications are recommended to use \l {pbkdf2} {PBKDF2}. new applications are recommended to use \l {deriveKeyPbkdf2} {PBKDF2}.
\sa deriveKeyPbkdf2, QCryptographicHash, QCryptographicHash::hashLength \sa deriveKeyPbkdf2, QCryptographicHash, QCryptographicHash::hashLength
*/ */

View File

@ -99,13 +99,12 @@ static jfieldID m_selectionStartFieldID = 0;
static jfieldID m_startOffsetFieldID = 0; static jfieldID m_startOffsetFieldID = 0;
static jfieldID m_textFieldID = 0; static jfieldID m_textFieldID = 0;
Q_DECLARE_METATYPE(std::function<void()>)
static void runOnQtThread(const std::function<void()> &func) static void runOnQtThread(const std::function<void()> &func)
{ {
const bool block = QGuiApplication::applicationState() >= Qt::ApplicationInactive; AndroidDeadlockProtector protector;
QMetaObject::invokeMethod(m_androidInputContext, "safeCall", if (!protector.acquire())
block ? Qt::BlockingQueuedConnection : Qt::QueuedConnection, Q_ARG(std::function<void()>, func)); return;
QMetaObject::invokeMethod(m_androidInputContext, "safeCall", Qt::BlockingQueuedConnection, Q_ARG(std::function<void()>, func));
} }
static jboolean beginBatchEdit(JNIEnv */*env*/, jobject /*thiz*/) static jboolean beginBatchEdit(JNIEnv */*env*/, jobject /*thiz*/)
@ -116,7 +115,7 @@ static jboolean beginBatchEdit(JNIEnv */*env*/, jobject /*thiz*/)
#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL #ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
qDebug("@@@ BEGINBATCH"); qDebug("@@@ BEGINBATCH");
#endif #endif
jboolean res; jboolean res = JNI_FALSE;
runOnQtThread([&res]{res = m_androidInputContext->beginBatchEdit();}); runOnQtThread([&res]{res = m_androidInputContext->beginBatchEdit();});
return res; return res;
} }
@ -130,7 +129,7 @@ static jboolean endBatchEdit(JNIEnv */*env*/, jobject /*thiz*/)
qDebug("@@@ ENDBATCH"); qDebug("@@@ ENDBATCH");
#endif #endif
jboolean res; jboolean res = JNI_FALSE;
runOnQtThread([&res]{res = m_androidInputContext->endBatchEdit();}); runOnQtThread([&res]{res = m_androidInputContext->endBatchEdit();});
return res; return res;
} }
@ -149,7 +148,7 @@ static jboolean commitText(JNIEnv *env, jobject /*thiz*/, jstring text, jint new
#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL #ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
qDebug() << "@@@ COMMIT" << str << newCursorPosition; qDebug() << "@@@ COMMIT" << str << newCursorPosition;
#endif #endif
jboolean res; jboolean res = JNI_FALSE;
runOnQtThread([&]{res = m_androidInputContext->commitText(str, newCursorPosition);}); runOnQtThread([&]{res = m_androidInputContext->commitText(str, newCursorPosition);});
return res; return res;
} }
@ -162,7 +161,7 @@ static jboolean deleteSurroundingText(JNIEnv */*env*/, jobject /*thiz*/, jint le
#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL #ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
qDebug() << "@@@ DELETE" << leftLength << rightLength; qDebug() << "@@@ DELETE" << leftLength << rightLength;
#endif #endif
jboolean res; jboolean res = JNI_FALSE;
runOnQtThread([&]{res = m_androidInputContext->deleteSurroundingText(leftLength, rightLength);}); runOnQtThread([&]{res = m_androidInputContext->deleteSurroundingText(leftLength, rightLength);});
return res; return res;
} }
@ -175,7 +174,7 @@ static jboolean finishComposingText(JNIEnv */*env*/, jobject /*thiz*/)
#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL #ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
qDebug("@@@ FINISH"); qDebug("@@@ FINISH");
#endif #endif
jboolean res; jboolean res = JNI_FALSE;
runOnQtThread([&]{res = m_androidInputContext->finishComposingText();}); runOnQtThread([&]{res = m_androidInputContext->finishComposingText();});
return res; return res;
} }
@ -185,7 +184,7 @@ static jint getCursorCapsMode(JNIEnv */*env*/, jobject /*thiz*/, jint reqModes)
if (!m_androidInputContext) if (!m_androidInputContext)
return 0; return 0;
jboolean res; jint res = 0;
runOnQtThread([&]{res = m_androidInputContext->getCursorCapsMode(reqModes);}); runOnQtThread([&]{res = m_androidInputContext->getCursorCapsMode(reqModes);});
return res; return res;
} }
@ -270,7 +269,7 @@ static jboolean setComposingText(JNIEnv *env, jobject /*thiz*/, jstring text, ji
#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL #ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
qDebug() << "@@@ SET" << str << newCursorPosition; qDebug() << "@@@ SET" << str << newCursorPosition;
#endif #endif
jboolean res; jboolean res = JNI_FALSE;
runOnQtThread([&]{res = m_androidInputContext->setComposingText(str, newCursorPosition);}); runOnQtThread([&]{res = m_androidInputContext->setComposingText(str, newCursorPosition);});
return res; return res;
} }
@ -283,7 +282,7 @@ static jboolean setComposingRegion(JNIEnv */*env*/, jobject /*thiz*/, jint start
#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL #ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
qDebug() << "@@@ SETR" << start << end; qDebug() << "@@@ SETR" << start << end;
#endif #endif
jboolean res; jboolean res = JNI_FALSE;
runOnQtThread([&]{res = m_androidInputContext->setComposingRegion(start, end);}); runOnQtThread([&]{res = m_androidInputContext->setComposingRegion(start, end);});
return res; return res;
} }
@ -297,7 +296,7 @@ static jboolean setSelection(JNIEnv */*env*/, jobject /*thiz*/, jint start, jint
#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL #ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
qDebug() << "@@@ SETSEL" << start << end; qDebug() << "@@@ SETSEL" << start << end;
#endif #endif
jboolean res; jboolean res = JNI_FALSE;
runOnQtThread([&]{res = m_androidInputContext->setSelection(start, end);}); runOnQtThread([&]{res = m_androidInputContext->setSelection(start, end);});
return res; return res;
@ -311,7 +310,7 @@ static jboolean selectAll(JNIEnv */*env*/, jobject /*thiz*/)
#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL #ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
qDebug("@@@ SELALL"); qDebug("@@@ SELALL");
#endif #endif
jboolean res; jboolean res = JNI_FALSE;
runOnQtThread([&]{res = m_androidInputContext->selectAll();}); runOnQtThread([&]{res = m_androidInputContext->selectAll();});
return res; return res;
} }
@ -324,7 +323,7 @@ static jboolean cut(JNIEnv */*env*/, jobject /*thiz*/)
#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL #ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
qDebug("@@@"); qDebug("@@@");
#endif #endif
jboolean res; jboolean res = JNI_FALSE;
runOnQtThread([&]{res = m_androidInputContext->cut();}); runOnQtThread([&]{res = m_androidInputContext->cut();});
return res; return res;
} }
@ -337,7 +336,7 @@ static jboolean copy(JNIEnv */*env*/, jobject /*thiz*/)
#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL #ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
qDebug("@@@"); qDebug("@@@");
#endif #endif
jboolean res; jboolean res = JNI_FALSE;
runOnQtThread([&]{res = m_androidInputContext->copy();}); runOnQtThread([&]{res = m_androidInputContext->copy();});
return res; return res;
} }
@ -350,7 +349,7 @@ static jboolean copyURL(JNIEnv */*env*/, jobject /*thiz*/)
#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL #ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
qDebug("@@@"); qDebug("@@@");
#endif #endif
jboolean res; jboolean res = JNI_FALSE;
runOnQtThread([&]{res = m_androidInputContext->copyURL();}); runOnQtThread([&]{res = m_androidInputContext->copyURL();});
return res; return res;
} }
@ -363,7 +362,7 @@ static jboolean paste(JNIEnv */*env*/, jobject /*thiz*/)
#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL #ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
qDebug("@@@ PASTE"); qDebug("@@@ PASTE");
#endif #endif
jboolean res; jboolean res = JNI_FALSE;
runOnQtThread([&]{res = m_androidInputContext->paste();}); runOnQtThread([&]{res = m_androidInputContext->paste();});
return res; return res;
} }
@ -516,7 +515,6 @@ QAndroidInputContext::QAndroidInputContext()
m_handleMode = Hidden; m_handleMode = Hidden;
updateSelectionHandles(); updateSelectionHandles();
}); });
qRegisterMetaType<std::function<void()>>();
} }
QAndroidInputContext::~QAndroidInputContext() QAndroidInputContext::~QAndroidInputContext()

View File

@ -65,7 +65,7 @@ void QEglFSVivIntegration::platformInit()
VivanteInit(); VivanteInit();
mNativeDisplay = fbGetDisplay(); mNativeDisplay = fbGetDisplay();
#else #else
mNativeDisplay = fbGetDisplayByIndex(framebufferIndex()); mNativeDisplay = static_cast<EGLNativeDisplayType>(fbGetDisplayByIndex(framebufferIndex()));
#endif #endif
fbGetDisplayGeometry(mNativeDisplay, &width, &height); fbGetDisplayGeometry(mNativeDisplay, &width, &height);
@ -88,7 +88,7 @@ EGLNativeWindowType QEglFSVivIntegration::createNativeWindow(QPlatformWindow *wi
Q_UNUSED(window) Q_UNUSED(window)
Q_UNUSED(format) Q_UNUSED(format)
EGLNativeWindowType eglWindow = fbCreateWindow(mNativeDisplay, 0, 0, size.width(), size.height()); EGLNativeWindowType eglWindow = static_cast<EGLNativeWindowType>(fbCreateWindow(mNativeDisplay, 0, 0, size.width(), size.height()));
return eglWindow; return eglWindow;
} }

View File

@ -60,7 +60,7 @@ void QEglFSVivWaylandIntegration::platformInit()
} }
mWaylandDisplay = wl_display_create(); mWaylandDisplay = wl_display_create();
mNativeDisplay = fbGetDisplay(mWaylandDisplay); mNativeDisplay = static_cast<EGLNativeDisplayType>(fbGetDisplay(mWaylandDisplay));
fbGetDisplayGeometry(mNativeDisplay, &width, &height); fbGetDisplayGeometry(mNativeDisplay, &width, &height);
mScreenSize.setHeight(height); mScreenSize.setHeight(height);
mScreenSize.setWidth(width); mScreenSize.setWidth(width);
@ -81,7 +81,7 @@ EGLNativeWindowType QEglFSVivWaylandIntegration::createNativeWindow(QPlatformWin
Q_UNUSED(window) Q_UNUSED(window)
Q_UNUSED(format) Q_UNUSED(format)
EGLNativeWindowType eglWindow = fbCreateWindow(mNativeDisplay, 0, 0, size.width(), size.height()); EGLNativeWindowType eglWindow = static_cast<EGLNativeWindowType>(fbCreateWindow(mNativeDisplay, 0, 0, size.width(), size.height()));
return eglWindow; return eglWindow;
} }

View File

@ -54,7 +54,6 @@
# include "qwindowsdrag.h" # include "qwindowsdrag.h"
#endif #endif
#include <qpa/qwindowsysteminterface.h>
#include <QtGui/qguiapplication.h> #include <QtGui/qguiapplication.h>
#include <QtGui/qscreen.h> #include <QtGui/qscreen.h>
#include <QtGui/qtouchdevice.h> #include <QtGui/qtouchdevice.h>
@ -201,6 +200,8 @@ bool QWindowsPointerHandler::translatePointerEvent(QWindow *window, HWND hwnd, Q
return false; return false;
} }
m_lastPointerType = pointerType;
// Handle non-client pen/touch as generic mouse events for compatibility with QDockWindow. // Handle non-client pen/touch as generic mouse events for compatibility with QDockWindow.
if ((pointerType == QT_PT_TOUCH || pointerType == QT_PT_PEN) && (et & QtWindows::NonClientEventFlag)) { if ((pointerType == QT_PT_TOUCH || pointerType == QT_PT_PEN) && (et & QtWindows::NonClientEventFlag)) {
POINTER_INFO pointerInfo; POINTER_INFO pointerInfo;
@ -427,6 +428,15 @@ static bool isValidWheelReceiver(QWindow *candidate)
return false; return false;
} }
static bool isMenuWindow(QWindow *window)
{
if (window)
if (QObject *fo = window->focusObject())
if (fo->inherits("QMenu"))
return true;
return false;
}
static QTouchDevice *createTouchDevice() static QTouchDevice *createTouchDevice()
{ {
const int digitizers = GetSystemMetrics(SM_DIGITIZER); const int digitizers = GetSystemMetrics(SM_DIGITIZER);
@ -455,6 +465,103 @@ QTouchDevice *QWindowsPointerHandler::ensureTouchDevice()
return m_touchDevice; return m_touchDevice;
} }
void QWindowsPointerHandler::handleCaptureRelease(QWindow *window,
QWindow *currentWindowUnderPointer,
HWND hwnd,
QEvent::Type eventType,
Qt::MouseButtons mouseButtons)
{
QWindowsWindow *platformWindow = static_cast<QWindowsWindow *>(window->handle());
// Qt expects the platform plugin to capture the mouse on any button press until release.
if (!platformWindow->hasMouseCapture() && eventType == QEvent::MouseButtonPress) {
platformWindow->setMouseGrabEnabled(true);
platformWindow->setFlag(QWindowsWindow::AutoMouseCapture);
qCDebug(lcQpaEvents) << "Automatic mouse capture " << window;
// Implement "Click to focus" for native child windows (unless it is a native widget window).
if (!window->isTopLevel() && !window->inherits("QWidgetWindow") && QGuiApplication::focusWindow() != window)
window->requestActivate();
} else if (platformWindow->hasMouseCapture()
&& platformWindow->testFlag(QWindowsWindow::AutoMouseCapture)
&& eventType == QEvent::MouseButtonRelease
&& !mouseButtons) {
platformWindow->setMouseGrabEnabled(false);
qCDebug(lcQpaEvents) << "Releasing automatic mouse capture " << window;
}
// Enter new window: track to generate leave event.
// If there is an active capture, only track if the current window is capturing,
// so we don't get extra leave when cursor leaves the application.
if (window != m_currentWindow &&
(!platformWindow->hasMouseCapture() || currentWindowUnderPointer == window)) {
trackLeave(hwnd);
m_currentWindow = window;
}
}
void QWindowsPointerHandler::handleEnterLeave(QWindow *window,
QWindow *currentWindowUnderPointer,
QPoint globalPos)
{
QWindowsWindow *platformWindow = static_cast<QWindowsWindow *>(window->handle());
const bool hasCapture = platformWindow->hasMouseCapture();
// No enter or leave events are sent as long as there is an autocapturing window.
if (!hasCapture || !platformWindow->testFlag(QWindowsWindow::AutoMouseCapture)) {
// Leave is needed if:
// 1) There is no capture and we move from a window to another window.
// Note: Leaving the application entirely is handled in translateMouseEvent(WM_MOUSELEAVE).
// 2) There is capture and we move out of the capturing window.
// 3) There is a new capture and we were over another window.
if ((m_windowUnderPointer && m_windowUnderPointer != currentWindowUnderPointer
&& (!hasCapture || window == m_windowUnderPointer))
|| (hasCapture && m_previousCaptureWindow != window && m_windowUnderPointer
&& m_windowUnderPointer != window)) {
qCDebug(lcQpaEvents) << "Leaving window " << m_windowUnderPointer;
QWindowSystemInterface::handleLeaveEvent(m_windowUnderPointer);
if (hasCapture && currentWindowUnderPointer != window) {
// Clear tracking if capturing and current window is not the capturing window
// to avoid leave when mouse actually leaves the application.
m_currentWindow = nullptr;
// We are not officially in any window, but we need to set some cursor to clear
// whatever cursor the left window had, so apply the cursor of the capture window.
platformWindow->applyCursor();
}
}
// Enter is needed if:
// 1) There is no capture and we move to a new window.
// 2) There is capture and we move into the capturing window.
// 3) The capture just ended and we are over non-capturing window.
if ((currentWindowUnderPointer && m_windowUnderPointer != currentWindowUnderPointer
&& (!hasCapture || currentWindowUnderPointer == window))
|| (m_previousCaptureWindow && !hasCapture && currentWindowUnderPointer
&& currentWindowUnderPointer != m_previousCaptureWindow)) {
QPoint wumLocalPos;
if (QWindowsWindow *wumPlatformWindow = QWindowsWindow::windowsWindowOf(currentWindowUnderPointer)) {
wumLocalPos = wumPlatformWindow->mapFromGlobal(globalPos);
wumPlatformWindow->applyCursor();
}
qCDebug(lcQpaEvents) << "Entering window " << currentWindowUnderPointer;
QWindowSystemInterface::handleEnterEvent(currentWindowUnderPointer, wumLocalPos, globalPos);
}
// We need to track m_windowUnderPointer separately from m_currentWindow, as Windows
// mouse tracking will not trigger WM_MOUSELEAVE for leaving window when mouse capture is set.
m_windowUnderPointer = currentWindowUnderPointer;
}
m_previousCaptureWindow = hasCapture ? window : nullptr;
}
bool QWindowsPointerHandler::translateMouseTouchPadEvent(QWindow *window, HWND hwnd, bool QWindowsPointerHandler::translateMouseTouchPadEvent(QWindow *window, HWND hwnd,
QtWindows::WindowsEventType et, QtWindows::WindowsEventType et,
MSG msg, PVOID vPointerInfo) MSG msg, PVOID vPointerInfo)
@ -464,9 +571,7 @@ bool QWindowsPointerHandler::translateMouseTouchPadEvent(QWindow *window, HWND h
const QPoint localPos = QWindowsGeometryHint::mapFromGlobal(hwnd, globalPos); const QPoint localPos = QWindowsGeometryHint::mapFromGlobal(hwnd, globalPos);
const Qt::KeyboardModifiers keyModifiers = QWindowsKeyMapper::queryKeyboardModifiers(); const Qt::KeyboardModifiers keyModifiers = QWindowsKeyMapper::queryKeyboardModifiers();
const Qt::MouseButtons mouseButtons = mouseButtonsFromPointerFlags(pointerInfo->pointerFlags); const Qt::MouseButtons mouseButtons = mouseButtonsFromPointerFlags(pointerInfo->pointerFlags);
QWindow *currentWindowUnderPointer = getWindowUnderPointer(window, globalPos); QWindow *currentWindowUnderPointer = getWindowUnderPointer(window, globalPos);
QWindowsWindow *platformWindow = static_cast<QWindowsWindow *>(window->handle());
switch (msg.message) { switch (msg.message) {
case WM_NCPOINTERDOWN: case WM_NCPOINTERDOWN:
@ -485,38 +590,17 @@ bool QWindowsPointerHandler::translateMouseTouchPadEvent(QWindow *window, HWND h
keyModifiers, Qt::MouseEventNotSynthesized); keyModifiers, Qt::MouseEventNotSynthesized);
return false; // To allow window dragging, etc. return false; // To allow window dragging, etc.
} else { } else {
if (eventType == QEvent::MouseButtonPress) {
// Implement "Click to focus" for native child windows (unless it is a native widget window).
if (!window->isTopLevel() && !window->inherits("QWidgetWindow") && QGuiApplication::focusWindow() != window)
window->requestActivate();
}
if (currentWindowUnderPointer != m_windowUnderPointer) {
if (m_windowUnderPointer && m_windowUnderPointer == m_currentWindow) {
QWindowSystemInterface::handleLeaveEvent(m_windowUnderPointer);
m_currentWindow = nullptr;
}
if (currentWindowUnderPointer) { handleCaptureRelease(window, currentWindowUnderPointer, hwnd, eventType, mouseButtons);
if (currentWindowUnderPointer != m_currentWindow) { handleEnterLeave(window, currentWindowUnderPointer, globalPos);
QWindowSystemInterface::handleEnterEvent(currentWindowUnderPointer, localPos, globalPos);
m_currentWindow = currentWindowUnderPointer;
if (QWindowsWindow *wumPlatformWindow = QWindowsWindow::windowsWindowOf(currentWindowUnderPointer))
wumPlatformWindow->applyCursor();
trackLeave(hwnd);
}
} else {
platformWindow->applyCursor();
}
m_windowUnderPointer = currentWindowUnderPointer;
}
QWindowSystemInterface::handleMouseEvent(window, localPos, globalPos, mouseButtons, button, eventType, QWindowSystemInterface::handleMouseEvent(window, localPos, globalPos, mouseButtons, button, eventType,
keyModifiers, Qt::MouseEventNotSynthesized); keyModifiers, Qt::MouseEventNotSynthesized);
// The initial down click over the QSizeGrip area, which posts a resize WM_SYSCOMMAND // The initial down click over the QSizeGrip area, which posts a resize WM_SYSCOMMAND
// has go to through DefWindowProc() for resizing to work, so we return false here, // has go to through DefWindowProc() for resizing to work, so we return false here,
// unless the mouse is captured, as it would mess with menu processing. // unless the click was on a menu, as it would mess with menu processing.
return msg.message != WM_POINTERDOWN || GetCapture(); return msg.message != WM_POINTERDOWN || isMenuWindow(window);
} }
} }
case WM_POINTERHWHEEL: case WM_POINTERHWHEEL:
@ -641,6 +725,7 @@ bool QWindowsPointerHandler::translateTouchEvent(QWindow *window, HWND hwnd,
// Only the primary pointer will generate mouse messages. // Only the primary pointer will generate mouse messages.
enqueueTouchEvent(window, touchPoints, QWindowsKeyMapper::queryKeyboardModifiers()); enqueueTouchEvent(window, touchPoints, QWindowsKeyMapper::queryKeyboardModifiers());
} else { } else {
flushTouchEvents(m_touchDevice);
QWindowSystemInterface::handleTouchEvent(window, m_touchDevice, touchPoints, QWindowSystemInterface::handleTouchEvent(window, m_touchDevice, touchPoints,
QWindowsKeyMapper::queryKeyboardModifiers()); QWindowsKeyMapper::queryKeyboardModifiers());
} }
@ -755,6 +840,16 @@ bool QWindowsPointerHandler::translatePenEvent(QWindow *window, HWND hwnd, QtWin
#endif #endif
} }
static inline bool isMouseEventSynthesizedFromPenOrTouch()
{
// For details, see
// https://docs.microsoft.com/en-us/windows/desktop/tablet/system-events-and-mouse-messages
const LONG_PTR SIGNATURE_MASK = 0xFFFFFF00;
const LONG_PTR MI_WP_SIGNATURE = 0xFF515700;
return ((::GetMessageExtraInfo() & SIGNATURE_MASK) == MI_WP_SIGNATURE);
}
// Process old-style mouse messages here. // Process old-style mouse messages here.
bool QWindowsPointerHandler::translateMouseEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, LRESULT *result) bool QWindowsPointerHandler::translateMouseEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, LRESULT *result)
{ {
@ -763,8 +858,6 @@ bool QWindowsPointerHandler::translateMouseEvent(QWindow *window, HWND hwnd, QtW
flushTabletEvents(); flushTabletEvents();
*result = 0; *result = 0;
if (et != QtWindows::MouseWheelEvent && msg.message != WM_MOUSELEAVE && msg.message != WM_MOUSEMOVE)
return false;
const QPoint eventPos(GET_X_LPARAM(msg.lParam), GET_Y_LPARAM(msg.lParam)); const QPoint eventPos(GET_X_LPARAM(msg.lParam), GET_Y_LPARAM(msg.lParam));
QPoint localPos; QPoint localPos;
@ -778,7 +871,26 @@ bool QWindowsPointerHandler::translateMouseEvent(QWindow *window, HWND hwnd, QtW
} }
const Qt::KeyboardModifiers keyModifiers = QWindowsKeyMapper::queryKeyboardModifiers(); const Qt::KeyboardModifiers keyModifiers = QWindowsKeyMapper::queryKeyboardModifiers();
QWindowsWindow *platformWindow = static_cast<QWindowsWindow *>(window->handle()); const Qt::MouseButtons mouseButtons = mouseButtonsFromKeyState(msg.wParam);
// Handle "press and hold for right-clicking".
// We have to synthesize it here as it only comes from Windows as a fake RMB.
// MS docs say we could use bit 7 from extraInfo to distinguish pen from touch,
// but on the Surface it is set for both. So we use the last pointer type.
if (isMouseEventSynthesizedFromPenOrTouch()) {
if ((msg.message == WM_RBUTTONDOWN || msg.message == WM_RBUTTONUP)
&& (((m_lastPointerType == QT_PT_PEN)
&& QCoreApplication::testAttribute(Qt::AA_SynthesizeMouseForUnhandledTabletEvents))
|| ((m_lastPointerType == QT_PT_TOUCH)
&& QCoreApplication::testAttribute(Qt::AA_SynthesizeMouseForUnhandledTouchEvents)))) {
QWindowSystemInterface::handleMouseEvent(window, localPos, globalPos, mouseButtons, Qt::RightButton,
(msg.message == WM_RBUTTONDOWN) ? QEvent::MouseButtonPress
: QEvent::MouseButtonRelease,
keyModifiers, Qt::MouseEventSynthesizedBySystem);
}
// Messages synthesized from touch/pen are only used for flushing queues and press&hold.
return false;
}
if (et == QtWindows::MouseWheelEvent) { if (et == QtWindows::MouseWheelEvent) {
@ -799,50 +911,21 @@ bool QWindowsPointerHandler::translateMouseEvent(QWindow *window, HWND hwnd, QtW
} }
if (msg.message == WM_MOUSELEAVE) { if (msg.message == WM_MOUSELEAVE) {
if (window == m_currentWindow) { if (window == m_currentWindow) {
QWindowSystemInterface::handleLeaveEvent(window); QWindow *leaveTarget = m_windowUnderPointer ? m_windowUnderPointer : m_currentWindow;
qCDebug(lcQpaEvents) << "Leaving window " << leaveTarget;
QWindowSystemInterface::handleLeaveEvent(leaveTarget);
m_windowUnderPointer = nullptr; m_windowUnderPointer = nullptr;
m_currentWindow = nullptr; m_currentWindow = nullptr;
platformWindow->applyCursor();
} }
return false;
} else if (msg.message == WM_MOUSEMOVE) {
QWindow *currentWindowUnderPointer = getWindowUnderPointer(window, globalPos);
handleCaptureRelease(window, currentWindowUnderPointer, hwnd, QEvent::MouseMove, mouseButtons);
handleEnterLeave(window, currentWindowUnderPointer, globalPos);
} }
// Windows sends a mouse move with no buttons pressed to signal "Enter"
// when a window is shown over the cursor. Discard the event and only use
// it for generating QEvent::Enter to be consistent with other platforms -
// X11 and macOS.
static QPoint lastMouseMovePos;
const bool discardEvent = msg.wParam == 0 && (m_windowUnderPointer.isNull() || globalPos == lastMouseMovePos);
lastMouseMovePos = globalPos;
QWindow *currentWindowUnderPointer = getWindowUnderPointer(window, globalPos);
if (currentWindowUnderPointer != m_windowUnderPointer) {
if (m_windowUnderPointer && m_windowUnderPointer == m_currentWindow) {
QWindowSystemInterface::handleLeaveEvent(m_windowUnderPointer);
m_currentWindow = nullptr;
}
if (currentWindowUnderPointer) {
if (currentWindowUnderPointer != m_currentWindow) {
QWindowSystemInterface::handleEnterEvent(currentWindowUnderPointer, localPos, globalPos);
m_currentWindow = currentWindowUnderPointer;
if (QWindowsWindow *wumPlatformWindow = QWindowsWindow::windowsWindowOf(currentWindowUnderPointer))
wumPlatformWindow->applyCursor();
trackLeave(hwnd);
}
} else {
platformWindow->applyCursor();
}
m_windowUnderPointer = currentWindowUnderPointer;
}
const Qt::MouseButtons mouseButtons = mouseButtonsFromKeyState(msg.wParam);
if (!discardEvent)
QWindowSystemInterface::handleMouseEvent(window, localPos, globalPos, mouseButtons, Qt::NoButton, QEvent::MouseMove,
keyModifiers, Qt::MouseEventNotSynthesized);
return false; return false;
} }

View File

@ -46,6 +46,7 @@
#include <QtCore/qpointer.h> #include <QtCore/qpointer.h>
#include <QtCore/qscopedpointer.h> #include <QtCore/qscopedpointer.h>
#include <QtCore/qhash.h> #include <QtCore/qhash.h>
#include <qpa/qwindowsysteminterface.h>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
@ -68,12 +69,16 @@ private:
bool translateMouseTouchPadEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, PVOID vPointerInfo); bool translateMouseTouchPadEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, PVOID vPointerInfo);
bool translateTouchEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, PVOID vTouchInfo, unsigned int count); bool translateTouchEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, PVOID vTouchInfo, unsigned int count);
bool translatePenEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, PVOID vPenInfo); bool translatePenEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, PVOID vPenInfo);
void handleCaptureRelease(QWindow *window, QWindow *currentWindowUnderPointer, HWND hwnd, QEvent::Type eventType, Qt::MouseButtons mouseButtons);
void handleEnterLeave(QWindow *window, QWindow *currentWindowUnderPointer, QPoint globalPos);
QTouchDevice *m_touchDevice = nullptr; QTouchDevice *m_touchDevice = nullptr;
QHash<int, QPointF> m_lastTouchPositions; QHash<int, QPointF> m_lastTouchPositions;
QPointer<QWindow> m_windowUnderPointer; QPointer<QWindow> m_windowUnderPointer;
QPointer<QWindow> m_currentWindow; QPointer<QWindow> m_currentWindow;
QWindow *m_previousCaptureWindow = nullptr;
bool m_needsEnterOnPointerUpdate = false; bool m_needsEnterOnPointerUpdate = false;
DWORD m_lastPointerType = 0;
}; };
QT_END_NAMESPACE QT_END_NAMESPACE

View File

@ -287,7 +287,7 @@ void QXcbBasicConnection::initializeShm()
logging->setEnabled(QtMsgType::QtWarningMsg, true); logging->setEnabled(QtMsgType::QtWarningMsg, true);
} }
void QXcbBasicConnection::initializeXRandr() void QXcbBasicConnection::initializeXRender()
{ {
const xcb_query_extension_reply_t *reply = xcb_get_extension_data(m_xcbConnection, &xcb_render_id); const xcb_query_extension_reply_t *reply = xcb_get_extension_data(m_xcbConnection, &xcb_render_id);
if (!reply || !reply->present) { if (!reply || !reply->present) {
@ -303,7 +303,7 @@ void QXcbBasicConnection::initializeXRandr()
return; return;
} }
m_hasXRandr = true; m_hasXRender = true;
m_xrenderVersion.first = xrenderQuery->major_version; m_xrenderVersion.first = xrenderQuery->major_version;
m_xrenderVersion.second = xrenderQuery->minor_version; m_xrenderVersion.second = xrenderQuery->minor_version;
} }
@ -337,7 +337,7 @@ void QXcbBasicConnection::initializeXFixes()
m_xfixesFirstEvent = reply->first_event; m_xfixesFirstEvent = reply->first_event;
} }
void QXcbBasicConnection::initializeXRender() void QXcbBasicConnection::initializeXRandr()
{ {
const xcb_query_extension_reply_t *reply = xcb_get_extension_data(m_xcbConnection, &xcb_randr_id); const xcb_query_extension_reply_t *reply = xcb_get_extension_data(m_xcbConnection, &xcb_randr_id);
if (!reply || !reply->present) if (!reply || !reply->present)
@ -352,7 +352,7 @@ void QXcbBasicConnection::initializeXRender()
return; return;
} }
m_hasXRender = true; m_hasXRandr = true;
m_xrandrFirstEvent = reply->first_event; m_xrandrFirstEvent = reply->first_event;
} }

View File

@ -112,4 +112,8 @@ qtConfig(xkb) {
qtConfig(dlopen): QMAKE_USE += libdl qtConfig(dlopen): QMAKE_USE += libdl
# qxcbkeyboard.cpp's KeyTbl has more than 256 levels of expansion and older
# Clang uses that as a limit (it's 1024 in current versions).
clang:!intel_icc: QMAKE_CXXFLAGS += -ftemplate-depth=1024
load(qt_module) load(qt_module)

View File

@ -31,8 +31,16 @@ depends += qtcore qtdoc qtwidgets qtgui qmake qtquick
headerdirs += .. headerdirs += ..
headers += ../../corelib/kernel/qtestsupport_core.h \
../../gui/kernel/qtestsupport_gui.h \
../../widgets/kernel/qtestsupport_widgets.h
sourcedirs += .. sourcedirs += ..
sources += ../../corelib/kernel/qtestsupport_core.cpp \
../../gui/kernel/qtestsupport_gui.cpp \
../../widgets/kernel/qtestsupport_widgets.cpp
exampledirs += ../../../examples/qtestlib \ exampledirs += ../../../examples/qtestlib \
../ \ ../ \
snippets snippets

View File

@ -2419,7 +2419,7 @@ bool QTest::currentTestFailed()
Sleeps for \a ms milliseconds, blocking execution of the Sleeps for \a ms milliseconds, blocking execution of the
test. qSleep() will not do any event processing and leave your test test. qSleep() will not do any event processing and leave your test
unresponsive. Network communication might time out while unresponsive. Network communication might time out while
sleeping. Use \l qWait() to do non-blocking sleeping. sleeping. Use \l {QTest::qWait()} to do non-blocking sleeping.
\a ms must be greater than 0. \a ms must be greater than 0.
@ -2430,7 +2430,7 @@ bool QTest::currentTestFailed()
Example: Example:
\snippet code/src_qtestlib_qtestcase.cpp 23 \snippet code/src_qtestlib_qtestcase.cpp 23
\sa qWait() \sa {QTest::qWait()}
*/ */
void QTest::qSleep(int ms) void QTest::qSleep(int ms)
{ {

View File

@ -994,6 +994,22 @@
\sa QTest::toHexRepresentation() \sa QTest::toHexRepresentation()
*/ */
/*!
\fn char *QTest::toString(const QCborError &c)
\overload
\since 5.12
Returns a textual representation of the given CBOR error \a c.
*/
/*!
\fn template <class... Types> char *QTest::toString(const std::tuple<Types...> &tuple)
\overload
\since 5.12
Returns a textual representation of the given \a tuple.
*/
/*! /*!
\fn char *QTest::toString(const QTime &time) \fn char *QTest::toString(const QTime &time)
\overload \overload
@ -1112,6 +1128,12 @@
Returns a textual representation of size policy \a sp. Returns a textual representation of size policy \a sp.
*/ */
/*!
\fn template <typename Tuple, int... I> char *QTest::toString(const Tuple &tuple, QtPrivate::IndexesList<I...> )
\internal
\since 5.12
*/
/*! /*!
\fn QTouchDevice *QTest::createTouchDevice(QTouchDevice::DeviceType devType = QTouchDevice::TouchScreen) \fn QTouchDevice *QTest::createTouchDevice(QTouchDevice::DeviceType devType = QTouchDevice::TouchScreen)
\since 5.8 \since 5.8

View File

@ -133,7 +133,7 @@
Adds a \a msecs milliseconds delay. Adds a \a msecs milliseconds delay.
\sa QTest::qWait() \sa {QTest::qWait()}
*/ */
/*! \fn void QTestEventList::simulate(QWidget *w) /*! \fn void QTestEventList::simulate(QWidget *w)

View File

@ -62,7 +62,7 @@ static const char docTypeHeader[] =
#define PROGRAMNAME "qdbuscpp2xml" #define PROGRAMNAME "qdbuscpp2xml"
#define PROGRAMVERSION "0.2" #define PROGRAMVERSION "0.2"
#define PROGRAMCOPYRIGHT "Copyright (C) 2018 The Qt Company Ltd." #define PROGRAMCOPYRIGHT "Copyright (C) 2019 The Qt Company Ltd."
static QString outputFile; static QString outputFile;
static int flags; static int flags;

View File

@ -46,7 +46,7 @@
#define PROGRAMNAME "qdbusxml2cpp" #define PROGRAMNAME "qdbusxml2cpp"
#define PROGRAMVERSION "0.8" #define PROGRAMVERSION "0.8"
#define PROGRAMCOPYRIGHT "Copyright (C) 2018 The Qt Company Ltd." #define PROGRAMCOPYRIGHT "Copyright (C) 2019 The Qt Company Ltd."
#define ANNOTATION_NO_WAIT "org.freedesktop.DBus.Method.NoReply" #define ANNOTATION_NO_WAIT "org.freedesktop.DBus.Method.NoReply"

View File

@ -1890,7 +1890,7 @@ void QMessageBox::aboutQt(QWidget *parent, const QString &title)
"<p>Qt and the Qt logo are trademarks of The Qt Company Ltd.</p>" "<p>Qt and the Qt logo are trademarks of The Qt Company Ltd.</p>"
"<p>Qt is The Qt Company Ltd product developed as an open source " "<p>Qt is The Qt Company Ltd product developed as an open source "
"project. See <a href=\"http://%3/\">%3</a> for more information.</p>" "project. See <a href=\"http://%3/\">%3</a> for more information.</p>"
).arg(QStringLiteral("2018"), ).arg(QStringLiteral("2019"),
QStringLiteral("qt.io/licensing"), QStringLiteral("qt.io/licensing"),
QStringLiteral("qt.io")); QStringLiteral("qt.io"));
QMessageBox *msgBox = new QMessageBox(parent); QMessageBox *msgBox = new QMessageBox(parent);

View File

@ -40,6 +40,9 @@ exampledirs += ../../../examples/widgets \
excludedirs += snippets excludedirs += snippets
# Included in qttestlib.qdocconf instead
excludefiles += ../kernel/qtestsupport_widgets.cpp
imagedirs += images \ imagedirs += images \
../../../doc/src/images \ ../../../doc/src/images \
../../../examples/widgets/doc/images \ ../../../examples/widgets/doc/images \

View File

@ -982,18 +982,9 @@ void QListView::paintEvent(QPaintEvent *e)
? qMax(viewport()->size().width(), d->contentsSize().width()) - 2 * d->spacing() ? qMax(viewport()->size().width(), d->contentsSize().width()) - 2 * d->spacing()
: qMax(viewport()->size().height(), d->contentsSize().height()) - 2 * d->spacing(); : qMax(viewport()->size().height(), d->contentsSize().height()) - 2 * d->spacing();
const int rowCount = d->commonListView->rowCount();
QVector<QModelIndex>::const_iterator end = toBeRendered.constEnd(); QVector<QModelIndex>::const_iterator end = toBeRendered.constEnd();
for (QVector<QModelIndex>::const_iterator it = toBeRendered.constBegin(); it != end; ++it) { for (QVector<QModelIndex>::const_iterator it = toBeRendered.constBegin(); it != end; ++it) {
Q_ASSERT((*it).isValid()); Q_ASSERT((*it).isValid());
if (rowCount == 1)
option.viewItemPosition = QStyleOptionViewItem::OnlyOne;
else if ((*it).row() == 0)
option.viewItemPosition = QStyleOptionViewItem::Beginning;
else if ((*it).row() == rowCount - 1)
option.viewItemPosition = QStyleOptionViewItem::End;
else
option.viewItemPosition = QStyleOptionViewItem::Middle;
option.rect = visualRect(*it); option.rect = visualRect(*it);
if (flow() == TopToBottom) if (flow() == TopToBottom)

View File

@ -46,15 +46,14 @@
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
/*! \fn bool qWaitForWindowActive(QWidget *widget, int timeout) /*!
\relates QTest
\since 5.0 \since 5.0
Waits for \a timeout milliseconds or until the \a widget's window is active. Waits for \a timeout milliseconds or until the \a widget's window is active.
Returns \c true if \c widget's window is active within \a timeout milliseconds, otherwise returns \c false. Returns \c true if \c widget's window is active within \a timeout milliseconds, otherwise returns \c false.
\sa QTest::qWaitForWindowExposed(), QWidget::isActiveWindow() \sa qWaitForWindowExposed(), QWidget::isActiveWindow()
*/ */
Q_WIDGETS_EXPORT Q_REQUIRED_RESULT bool QTest::qWaitForWindowActive(QWidget *widget, int timeout) Q_WIDGETS_EXPORT Q_REQUIRED_RESULT bool QTest::qWaitForWindowActive(QWidget *widget, int timeout)
{ {
@ -63,8 +62,7 @@ Q_WIDGETS_EXPORT Q_REQUIRED_RESULT bool QTest::qWaitForWindowActive(QWidget *wid
return false; return false;
} }
/*! \fn bool qWaitForWindowExposed(QWidget *widget, int timeout) /*!
\relates QTest
\since 5.0 \since 5.0
Waits for \a timeout milliseconds or until the \a widget's window is exposed. Waits for \a timeout milliseconds or until the \a widget's window is exposed.
@ -80,7 +78,7 @@ Q_WIDGETS_EXPORT Q_REQUIRED_RESULT bool QTest::qWaitForWindowActive(QWidget *wid
A specific configuration where this happens is when using QGLWidget as a viewport widget on macOS: A specific configuration where this happens is when using QGLWidget as a viewport widget on macOS:
The viewport widget gets the expose event, not the parent widget. The viewport widget gets the expose event, not the parent widget.
\sa QTest::qWaitForWindowActive() \sa qWaitForWindowActive()
*/ */
Q_WIDGETS_EXPORT Q_REQUIRED_RESULT bool QTest::qWaitForWindowExposed(QWidget *widget, int timeout) Q_WIDGETS_EXPORT Q_REQUIRED_RESULT bool QTest::qWaitForWindowExposed(QWidget *widget, int timeout)
{ {
@ -89,11 +87,12 @@ Q_WIDGETS_EXPORT Q_REQUIRED_RESULT bool QTest::qWaitForWindowExposed(QWidget *wi
return false; return false;
} }
/*! \fn bool qWaitForWindowShown(QWidget *widget, int timeout) /*! \fn bool QTest::qWaitForWindowShown(QWidget *widget, int timeout)
\relates QTest
\since 5.0 \since 5.0
\deprecated \deprecated
Use qWaitForWindowExposed() instead.
Waits for \a timeout milliseconds or until the \a widget's window is exposed. Waits for \a timeout milliseconds or until the \a widget's window is exposed.
Returns \c true if \c widget's window is exposed within \a timeout milliseconds, otherwise returns \c false. Returns \c true if \c widget's window is exposed within \a timeout milliseconds, otherwise returns \c false.
@ -107,7 +106,7 @@ Q_WIDGETS_EXPORT Q_REQUIRED_RESULT bool QTest::qWaitForWindowExposed(QWidget *wi
QTest::qWaitForWindowShown(&widget); QTest::qWaitForWindowShown(&widget);
\endcode \endcode
\sa QTest::qWaitForWindowActive(), QTest::qWaitForWindowExposed() \sa qWaitForWindowActive(), qWaitForWindowExposed()
*/ */
QT_END_NAMESPACE QT_END_NAMESPACE

View File

@ -216,7 +216,6 @@ void QTipLabel::reuseTip(const QString &text, int msecDisplayTime, const QPoint
} }
#endif #endif
setWordWrap(true);
setText(text); setText(text);
updateSize(pos); updateSize(pos);
restartExpireTimer(msecDisplayTime); restartExpireTimer(msecDisplayTime);
@ -235,20 +234,17 @@ void QTipLabel::updateSize(const QPoint &pos)
// Make it look good with the default ToolTip font on Mac, which has a small descent. // Make it look good with the default ToolTip font on Mac, which has a small descent.
if (fm.descent() == 2 && fm.ascent() >= 11) if (fm.descent() == 2 && fm.ascent() >= 11)
++extra.rheight(); ++extra.rheight();
setWordWrap(Qt::mightBeRichText(text()));
QSize sh = sizeHint(); QSize sh = sizeHint();
if (wordWrap()) { // ### When the above WinRT code is fixed, windowhandle should be used to find the screen.
// ### When the above WinRT code is fixed, windowhandle should be used to find the screen. QScreen *screen = QGuiApplication::screenAt(pos);
QScreen *screen = QGuiApplication::screenAt(pos); if (!screen)
if (!screen) screen = QGuiApplication::primaryScreen();
screen = QGuiApplication::primaryScreen(); if (screen) {
if (screen) { const qreal screenWidth = screen->geometry().width();
const qreal screenWidth = screen->geometry().width(); if (!wordWrap() && sh.width() > screenWidth) {
if (sh.width() > screenWidth) { setWordWrap(true);
// Try to use widely accepted 75chars max length or 80% of the screen width else. sh = sizeHint();
// See https://en.wikipedia.org/wiki/Line_length
sh.setWidth(qMin(fm.averageCharWidth() * 75, static_cast<int>(screenWidth * .8)));
sh.setHeight(heightForWidth(sh.width()));
}
} }
} }
resize(sh + extra); resize(sh + extra);

View File

@ -4517,7 +4517,7 @@ void QWidget::setForegroundRole(QPalette::ColorRole role)
the "color", "background-color", "selection-color", the "color", "background-color", "selection-color",
"selection-background-color" and "alternate-background-color". "selection-background-color" and "alternate-background-color".
\sa QApplication::palette(), QWidget::font(), \l {Qt Style Sheets} \sa QApplication::palette(), QWidget::font(), {Qt Style Sheets}
*/ */
const QPalette &QWidget::palette() const const QPalette &QWidget::palette() const
{ {

View File

@ -899,10 +899,10 @@ void QWidgetWindow::handleDragMoveEvent(QDragMoveEvent *event)
const QPoint mapped = widget->mapFromGlobal(m_widget->mapToGlobal(event->pos())); const QPoint mapped = widget->mapFromGlobal(m_widget->mapToGlobal(event->pos()));
QDragMoveEvent translated(mapped, event->possibleActions(), event->mimeData(), QDragMoveEvent translated(mapped, event->possibleActions(), event->mimeData(),
event->mouseButtons(), event->keyboardModifiers()); event->mouseButtons(), event->keyboardModifiers());
translated.setDropAction(event->dropAction());
translated.setAccepted(event->isAccepted());
if (widget == m_dragTarget) { // Target widget unchanged: Send DragMove if (widget == m_dragTarget) { // Target widget unchanged: Send DragMove
translated.setDropAction(event->dropAction());
translated.setAccepted(event->isAccepted());
QGuiApplication::forwardEvent(m_dragTarget, &translated, event); QGuiApplication::forwardEvent(m_dragTarget, &translated, event);
} else { } else {
if (m_dragTarget) { // Send DragLeave to previous if (m_dragTarget) { // Send DragLeave to previous
@ -912,6 +912,9 @@ void QWidgetWindow::handleDragMoveEvent(QDragMoveEvent *event)
} }
// Send DragEnter to new widget. // Send DragEnter to new widget.
handleDragEnterEvent(static_cast<QDragEnterEvent*>(event), widget); handleDragEnterEvent(static_cast<QDragEnterEvent*>(event), widget);
// Handling 'DragEnter' should suffice for the application.
translated.setDropAction(event->dropAction());
translated.setAccepted(event->isAccepted());
// The drag enter event is always immediately followed by a drag move event, // The drag enter event is always immediately followed by a drag move event,
// see QDragEnterEvent documentation. // see QDragEnterEvent documentation.
QGuiApplication::forwardEvent(m_dragTarget, &translated, event); QGuiApplication::forwardEvent(m_dragTarget, &translated, event);

View File

@ -1681,6 +1681,7 @@ void QLineEdit::mouseDoubleClickEvent(QMouseEvent* e)
/*! /*!
\fn void QLineEdit::inputRejected() \fn void QLineEdit::inputRejected()
\since 5.12
This signal is emitted when the user presses a key that is not This signal is emitted when the user presses a key that is not
considered to be acceptable input. For example, if a key press considered to be acceptable input. For example, if a key press

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDisplayName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleGetInfoString</key>
<string>Created by Qt/QMake</string>
<key>CFBundleIconFile</key>
<string>${ASSETCATALOG_COMPILER_APPICON_NAME}</string>
<key>CFBundleIdentifier</key>
<string>${PRODUCT_BUNDLE_IDENTIFIER}</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>${QMAKE_SHORT_VERSION}</string>
<key>CFBundleSignature</key>
<string>${QMAKE_PKGINFO_TYPEINFO}</string>
<key>CFBundleVersion</key>
<string>${QMAKE_FULL_VERSION}</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>MinimumOSVersion</key>
<string>${IPHONEOS_DEPLOYMENT_TARGET}</string>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>NSPhotoLibraryUsageDescription</key>
<string>Enables use of assets file engine</string>
</dict>
</plist>

View File

@ -3,6 +3,7 @@ TARGET = tst_qdir
QT = core core-private testlib QT = core core-private testlib
SOURCES = tst_qdir.cpp SOURCES = tst_qdir.cpp
RESOURCES += qdir.qrc RESOURCES += qdir.qrc
ios: QMAKE_INFO_PLIST = Info.plist
TESTDATA += testdir testData searchdir resources entrylist types tst_qdir.cpp TESTDATA += testdir testData searchdir resources entrylist types tst_qdir.cpp

View File

@ -62,12 +62,7 @@
#endif #endif
#ifdef QT_BUILD_INTERNAL #ifdef QT_BUILD_INTERNAL
#include "private/qdir_p.h"
QT_BEGIN_NAMESPACE
extern Q_AUTOTEST_EXPORT QString
qt_normalizePathSegments(const QString &path, bool allowUncPaths, bool *ok = nullptr);
QT_END_NAMESPACE
#endif #endif
static QByteArray msgDoesNotExist(const QString &name) static QByteArray msgDoesNotExist(const QString &name)
@ -1376,7 +1371,7 @@ void tst_QDir::normalizePathSegments()
QFETCH(QString, path); QFETCH(QString, path);
QFETCH(UncHandling, uncHandling); QFETCH(UncHandling, uncHandling);
QFETCH(QString, expected); QFETCH(QString, expected);
QString cleaned = qt_normalizePathSegments(path, uncHandling == HandleUnc); QString cleaned = qt_normalizePathSegments(path, uncHandling == HandleUnc ? QDirPrivate::AllowUncPaths : QDirPrivate::DefaultNormalization);
QCOMPARE(cleaned, expected); QCOMPARE(cleaned, expected);
if (path == expected) if (path == expected)
QVERIFY2(path.isSharedWith(cleaned), "Strings are same but data is not shared"); QVERIFY2(path.isSharedWith(cleaned), "Strings are same but data is not shared");
@ -1528,6 +1523,11 @@ void tst_QDir::filePath_data()
QTest::newRow("rel-rel") << "relative" << "path" << "relative/path"; QTest::newRow("rel-rel") << "relative" << "path" << "relative/path";
QTest::newRow("empty-empty") << "" << "" << "."; QTest::newRow("empty-empty") << "" << "" << ".";
QTest::newRow("resource") << ":/prefix" << "foo.bar" << ":/prefix/foo.bar"; QTest::newRow("resource") << ":/prefix" << "foo.bar" << ":/prefix/foo.bar";
#ifdef Q_OS_IOS
QTest::newRow("assets-rel") << "assets-library:/" << "foo/bar.baz" << "assets-library:/foo/bar.baz";
QTest::newRow("assets-abs") << "assets-library:/" << "/foo/bar.baz" << "/foo/bar.baz";
QTest::newRow("abs-assets") << "/some/path" << "assets-library:/foo/bar.baz" << "assets-library:/foo/bar.baz";
#endif
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
QTest::newRow("abs-LTUNC") << "Q:/path" << "\\/leaning\\tooth/pick" << "\\/leaning\\tooth/pick"; QTest::newRow("abs-LTUNC") << "Q:/path" << "\\/leaning\\tooth/pick" << "\\/leaning\\tooth/pick";
QTest::newRow("LTUNC-slash") << "\\/leaning\\tooth/pick" << "/path" << "//leaning/tooth/path"; QTest::newRow("LTUNC-slash") << "\\/leaning\\tooth/pick" << "/path" << "//leaning/tooth/path";

View File

@ -182,6 +182,8 @@ private slots:
void matches(); void matches();
void ipv6_zoneId_data(); void ipv6_zoneId_data();
void ipv6_zoneId(); void ipv6_zoneId();
void normalizeRemotePaths_data();
void normalizeRemotePaths();
private: private:
void testThreadingHelper(); void testThreadingHelper();
@ -323,7 +325,7 @@ void tst_QUrl::comparison()
QUrl url3bis = QUrl::fromEncoded("example://a/b/c/%7Bfoo%7D/"); QUrl url3bis = QUrl::fromEncoded("example://a/b/c/%7Bfoo%7D/");
QUrl url3bisNoSlash = QUrl::fromEncoded("example://a/b/c/%7Bfoo%7D"); QUrl url3bisNoSlash = QUrl::fromEncoded("example://a/b/c/%7Bfoo%7D");
QUrl url4bis = QUrl::fromEncoded("example://a/.//b/../b/c//%7Bfoo%7D/"); QUrl url4bis = QUrl::fromEncoded("example://a/./b/../b/c/%7Bfoo%7D/");
QCOMPARE(url4bis.adjusted(QUrl::NormalizePathSegments), url3bis); QCOMPARE(url4bis.adjusted(QUrl::NormalizePathSegments), url3bis);
QCOMPARE(url4bis.adjusted(QUrl::NormalizePathSegments | QUrl::StripTrailingSlash), url3bisNoSlash); QCOMPARE(url4bis.adjusted(QUrl::NormalizePathSegments | QUrl::StripTrailingSlash), url3bisNoSlash);
QVERIFY(url3bis.matches(url4bis, QUrl::NormalizePathSegments)); QVERIFY(url3bis.matches(url4bis, QUrl::NormalizePathSegments));
@ -335,7 +337,7 @@ void tst_QUrl::comparison()
QCOMPARE(url4EncodedDots.path(QUrl::FullyDecoded), QString("/.//b/..//b/c/")); QCOMPARE(url4EncodedDots.path(QUrl::FullyDecoded), QString("/.//b/..//b/c/"));
QCOMPARE(QString::fromLatin1(url4EncodedDots.toEncoded()), QString::fromLatin1("example://a/.//b/..%2F/b/c/")); QCOMPARE(QString::fromLatin1(url4EncodedDots.toEncoded()), QString::fromLatin1("example://a/.//b/..%2F/b/c/"));
QCOMPARE(url4EncodedDots.toString(), QString("example://a/.//b/..%2F/b/c/")); QCOMPARE(url4EncodedDots.toString(), QString("example://a/.//b/..%2F/b/c/"));
QCOMPARE(url4EncodedDots.adjusted(QUrl::NormalizePathSegments).toString(), QString("example://a/b/..%2F/b/c/")); QCOMPARE(url4EncodedDots.adjusted(QUrl::NormalizePathSegments).toString(), QString("example://a//b/..%2F/b/c/"));
// 6.2.2.1 Make sure hexdecimal characters in percent encoding are // 6.2.2.1 Make sure hexdecimal characters in percent encoding are
// treated case-insensitively // treated case-insensitively
@ -4201,6 +4203,36 @@ void tst_QUrl::ipv6_zoneId()
QCOMPARE(url.toString(QUrl::FullyEncoded), "x://[" + encodedHost + "]"); QCOMPARE(url.toString(QUrl::FullyEncoded), "x://[" + encodedHost + "]");
} }
void tst_QUrl::normalizeRemotePaths_data()
{
QTest::addColumn<QUrl>("url");
QTest::addColumn<QString>("expected");
QTest::newRow("dotdot-slashslash") << QUrl("http://qt-project.org/some/long/..//path") << "http://qt-project.org/some//path";
QTest::newRow("slashslash-dotdot") << QUrl("http://qt-project.org/some//../path") << "http://qt-project.org/some/path";
QTest::newRow("slashslash-dotdot2") << QUrl("http://qt-project.org/some//path/../") << "http://qt-project.org/some//";
QTest::newRow("dot-slash") << QUrl("http://qt-project.org/some/./path") << "http://qt-project.org/some/path";
QTest::newRow("slashslash-dot-slashslash") << QUrl("http://qt-project.org/some//.//path") << "http://qt-project.org/some///path";
QTest::newRow("dot-slashslash") << QUrl("http://qt-project.org/some/.//path") << "http://qt-project.org/some//path";
QTest::newRow("multiple-slashes") << QUrl("http://qt-project.org/some//path") << "http://qt-project.org/some//path";
QTest::newRow("multiple-slashes4") << QUrl("http://qt-project.org/some////path") << "http://qt-project.org/some////path";
QTest::newRow("slashes-at-end") << QUrl("http://qt-project.org/some//") << "http://qt-project.org/some//";
QTest::newRow("dot-dotdot") << QUrl("http://qt-project.org/path/./../") << "http://qt-project.org/";
QTest::newRow("slash-dot-slash-dot-slash") << QUrl("http://qt-project.org/path//.//.//") << "http://qt-project.org/path////";
QTest::newRow("dotdot") << QUrl("http://qt-project.org/../") << "http://qt-project.org/";
QTest::newRow("dotdot-dotdot") << QUrl("http://qt-project.org/path/../../") << "http://qt-project.org/";
QTest::newRow("dot-dotdot-tail") << QUrl("http://qt-project.org/stem/path/./../tail") << "http://qt-project.org/stem/tail";
QTest::newRow("slash-dotdot-slash-tail") << QUrl("http://qt-project.org/stem/path//..//tail") << "http://qt-project.org/stem/path//tail";
}
void tst_QUrl::normalizeRemotePaths()
{
QFETCH(QUrl, url);
QFETCH(QString, expected);
QCOMPARE(url.adjusted(QUrl::NormalizePathSegments).toString(), expected);
}
QTEST_MAIN(tst_QUrl) QTEST_MAIN(tst_QUrl)
#include "tst_qurl.moc" #include "tst_qurl.moc"

View File

@ -727,6 +727,16 @@ void tst_QItemDelegate::dateTimeEditor_data()
<< QDate(2006, 10, 31); << QDate(2006, 10, 31);
} }
static QDateTimeEdit *findDateTimeEdit(const QWidget *widget)
{
const auto dateTimeEditors = widget->findChildren<QDateTimeEdit *>();
for (auto dateTimeEditor : dateTimeEditors) {
if (qstrcmp(dateTimeEditor->metaObject()->className(), "QDateTimeEdit") == 0)
return dateTimeEditor;
}
return nullptr;
}
void tst_QItemDelegate::dateTimeEditor() void tst_QItemDelegate::dateTimeEditor()
{ {
QFETCH(QTime, time); QFETCH(QTime, time);
@ -742,17 +752,24 @@ void tst_QItemDelegate::dateTimeEditor()
item3->setData(Qt::DisplayRole, QDateTime(date, time)); item3->setData(Qt::DisplayRole, QDateTime(date, time));
QTableWidget widget(1, 3); QTableWidget widget(1, 3);
widget.setWindowTitle(QLatin1String(QTest::currentTestFunction())
+ QLatin1String("::")
+ QLatin1String(QTest::currentDataTag()));
widget.setItem(0, 0, item1); widget.setItem(0, 0, item1);
widget.setItem(0, 1, item2); widget.setItem(0, 1, item2);
widget.setItem(0, 2, item3); widget.setItem(0, 2, item3);
widget.show(); widget.show();
QVERIFY(QTest::qWaitForWindowExposed(&widget));
QApplication::setActiveWindow(&widget);
widget.editItem(item1); widget.editItem(item1);
QTestEventLoop::instance().enterLoop(1); QTestEventLoop::instance().enterLoop(1);
QTimeEdit *timeEditor = widget.viewport()->findChild<QTimeEdit *>();
QVERIFY(timeEditor); QTimeEdit *timeEditor = nullptr;
auto viewport = widget.viewport();
QTRY_VERIFY( (timeEditor = viewport->findChild<QTimeEdit *>()) );
QCOMPARE(timeEditor->time(), time); QCOMPARE(timeEditor->time(), time);
// The data must actually be different in order for the model // The data must actually be different in order for the model
// to be updated. // to be updated.
@ -763,8 +780,8 @@ void tst_QItemDelegate::dateTimeEditor()
widget.setFocus(); widget.setFocus();
widget.editItem(item2); widget.editItem(item2);
QTRY_VERIFY(widget.viewport()->findChild<QDateEdit *>()); QDateEdit *dateEditor = nullptr;
QDateEdit *dateEditor = widget.viewport()->findChild<QDateEdit *>(); QTRY_VERIFY( (dateEditor = viewport->findChild<QDateEdit *>()) );
QCOMPARE(dateEditor->date(), date); QCOMPARE(dateEditor->date(), date);
dateEditor->setDate(date.addDays(60)); dateEditor->setDate(date.addDays(60));
@ -774,12 +791,8 @@ void tst_QItemDelegate::dateTimeEditor()
QTestEventLoop::instance().enterLoop(1); QTestEventLoop::instance().enterLoop(1);
QList<QDateTimeEdit *> dateTimeEditors = widget.findChildren<QDateTimeEdit *>(); QDateTimeEdit *dateTimeEditor = nullptr;
QDateTimeEdit *dateTimeEditor = 0; QTRY_VERIFY( (dateTimeEditor = findDateTimeEdit(viewport)) );
foreach(dateTimeEditor, dateTimeEditors)
if (dateTimeEditor->metaObject()->className() == QLatin1String("QDateTimeEdit"))
break;
QVERIFY(dateTimeEditor);
QCOMPARE(dateTimeEditor->date(), date); QCOMPARE(dateTimeEditor->date(), date);
QCOMPARE(dateTimeEditor->time(), time); QCOMPARE(dateTimeEditor->time(), time);
dateTimeEditor->setTime(time.addSecs(600)); dateTimeEditor->setTime(time.addSecs(600));

View File

@ -470,6 +470,10 @@ static const char *expectedLogC[] = {
"Event at 11,241 accepted", "Event at 11,241 accepted",
"acceptingDropsWidget2::dropEvent at 1,51 action=1 MIME_DATA_ADDRESS 'testmimetext'", "acceptingDropsWidget2::dropEvent at 1,51 action=1 MIME_DATA_ADDRESS 'testmimetext'",
"Event at 11,261 accepted", "Event at 11,261 accepted",
"acceptingDropsWidget3::dragEnterEvent at 1,21 action=1 MIME_DATA_ADDRESS 'testmimetext'",
"Event at 11,281 accepted",
"acceptingDropsWidget3::dragLeaveEvent QDragLeaveEvent",
"Event at 11,301 ignored",
"acceptingDropsWidget1::dragEnterEvent at 10,10 action=1 MIME_DATA_ADDRESS 'testmimetext'", "acceptingDropsWidget1::dragEnterEvent at 10,10 action=1 MIME_DATA_ADDRESS 'testmimetext'",
"Event at 0,0 accepted", "Event at 0,0 accepted",
"acceptingDropsWidget1::dragMoveEvent at 11,11 action=1 MIME_DATA_ADDRESS 'testmimetext'", "acceptingDropsWidget1::dragMoveEvent at 11,11 action=1 MIME_DATA_ADDRESS 'testmimetext'",
@ -482,8 +486,9 @@ static const char *expectedLogC[] = {
class DnDEventLoggerWidget : public QWidget class DnDEventLoggerWidget : public QWidget
{ {
public: public:
DnDEventLoggerWidget(QStringList *log, QWidget *w = 0) : QWidget(w), m_log(log) {} DnDEventLoggerWidget(QStringList *log, QWidget *w = nullptr, bool ignoreDragMove = false)
: QWidget(w), m_log(log), m_ignoreDragMove(ignoreDragMove)
{}
protected: protected:
void dragEnterEvent(QDragEnterEvent *); void dragEnterEvent(QDragEnterEvent *);
void dragMoveEvent(QDragMoveEvent *); void dragMoveEvent(QDragMoveEvent *);
@ -493,6 +498,7 @@ protected:
private: private:
void formatDropEvent(const char *function, const QDropEvent *e, QTextStream &str) const; void formatDropEvent(const char *function, const QDropEvent *e, QTextStream &str) const;
QStringList *m_log; QStringList *m_log;
bool m_ignoreDragMove;
}; };
void DnDEventLoggerWidget::formatDropEvent(const char *function, const QDropEvent *e, QTextStream &str) const void DnDEventLoggerWidget::formatDropEvent(const char *function, const QDropEvent *e, QTextStream &str) const
@ -513,6 +519,8 @@ void DnDEventLoggerWidget::dragEnterEvent(QDragEnterEvent *e)
void DnDEventLoggerWidget::dragMoveEvent(QDragMoveEvent *e) void DnDEventLoggerWidget::dragMoveEvent(QDragMoveEvent *e)
{ {
if (m_ignoreDragMove)
return;
e->accept(); e->accept();
QString message; QString message;
QTextStream str(&message); QTextStream str(&message);
@ -580,7 +588,17 @@ void tst_QWidget_window::tst_dnd()
dropsRefusingWidget2->resize(160, 60); dropsRefusingWidget2->resize(160, 60);
dropsRefusingWidget2->move(10, 10); dropsRefusingWidget2->move(10, 10);
QWidget *dropsAcceptingWidget3 = new DnDEventLoggerWidget(&log, &dndTestWidget, true);
dropsAcceptingWidget3->setAcceptDrops(true);
dropsAcceptingWidget3->setObjectName(QLatin1String("acceptingDropsWidget3"));
// 260 + 40 = 300 = widget size, must not be more than that.
// otherwise it will break WinRT because there the tlw is maximized every time
// and this window will receive one more event
dropsAcceptingWidget3->resize(180, 40);
dropsAcceptingWidget3->move(10, 260);
dndTestWidget.show(); dndTestWidget.show();
QVERIFY(QTest::qWaitForWindowExposed(&dndTestWidget));
qApp->setActiveWindow(&dndTestWidget); qApp->setActiveWindow(&dndTestWidget);
QVERIFY(QTest::qWaitForWindowActive(&dndTestWidget)); QVERIFY(QTest::qWaitForWindowActive(&dndTestWidget));
@ -595,16 +613,17 @@ void tst_QWidget_window::tst_dnd()
log.push_back(msgEventAccepted(e)); log.push_back(msgEventAccepted(e));
while (true) { while (true) {
position.ry() += 20; position.ry() += 20;
if (position.y() >= 250) { if (position.y() >= 250 && position.y() < 270) {
QDropEvent e(position, Qt::CopyAction, &mimeData, Qt::LeftButton, Qt::NoModifier); QDropEvent e(position, Qt::CopyAction, &mimeData, Qt::LeftButton, Qt::NoModifier);
qApp->sendEvent(window, &e); qApp->sendEvent(window, &e);
log.push_back(msgEventAccepted(e)); log.push_back(msgEventAccepted(e));
break;
} else { } else {
QDragMoveEvent e(position, Qt::CopyAction, &mimeData, Qt::LeftButton, Qt::NoModifier); QDragMoveEvent e(position, Qt::CopyAction, &mimeData, Qt::LeftButton, Qt::NoModifier);
qApp->sendEvent(window, &e); qApp->sendEvent(window, &e);
log.push_back(msgEventAccepted(e)); log.push_back(msgEventAccepted(e));
} }
if (position.y() > 290)
break;
} }
window = nativeWidget->windowHandle(); window = nativeWidget->windowHandle();
@ -628,6 +647,15 @@ void tst_QWidget_window::tst_dnd()
for (int i= 0; i < expectedLogSize; ++i) for (int i= 0; i < expectedLogSize; ++i)
expectedLog.push_back(QString::fromLatin1(expectedLogC[i]).replace(mimeDataAddressPlaceHolder, mimeDataAddress)); expectedLog.push_back(QString::fromLatin1(expectedLogC[i]).replace(mimeDataAddressPlaceHolder, mimeDataAddress));
if (log.size() != expectedLog.size()) {
for (int i = 0; i < log.size() && i < expectedLog.size(); ++i)
QCOMPARE(log.at(i), expectedLog.at(i));
const int iMin = std::min(log.size(), expectedLog.size());
for (int i = iMin; i < log.size(); ++i)
qDebug() << "log[" << i << "]:" << log.at(i);
for (int i = iMin; i < expectedLog.size(); ++i)
qDebug() << "exp[" << i << "]:" << log.at(i);
}
QCOMPARE(log, expectedLog); QCOMPARE(log, expectedLog);
} }