diff options
author | Liang Qi <liang.qi@qt.io> | 2016-09-16 23:16:25 +0200 |
---|---|---|
committer | Liang Qi <liang.qi@qt.io> | 2016-09-16 23:16:25 +0200 |
commit | d148019f16e3c95916731e59e0324e7c470cc1fc (patch) | |
tree | d9c0640c9055f24379468b8f55b3419f30a37c47 | |
parent | 8ceab12814a7437a01d917c83ec28fd6e81c459e (diff) | |
parent | 6b9c57f8cd3df65702db327616913fa9d8172237 (diff) |
Merge remote-tracking branch 'origin/5.6' into 5.7
Conflicts:
src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp
Change-Id: I0af32ee55936d523cbd259b6fe82eb9c409f9074
44 files changed, 821 insertions, 227 deletions
diff --git a/config.tests/unix/libjpeg/libjpeg.cpp b/config.tests/unix/libjpeg/libjpeg.cpp index 9187133393..106043c608 100644 --- a/config.tests/unix/libjpeg/libjpeg.cpp +++ b/config.tests/unix/libjpeg/libjpeg.cpp @@ -43,9 +43,10 @@ extern "C" { #include <jpeglib.h> } +j_compress_ptr cinfo; + int main(int, char **) { - j_compress_ptr cinfo; jpeg_create_compress(cinfo); return 0; } diff --git a/dist/changes-5.6.2 b/dist/changes-5.6.2 new file mode 100644 index 0000000000..7b62a018f3 --- /dev/null +++ b/dist/changes-5.6.2 @@ -0,0 +1,339 @@ +Qt 5.6.2 is a bug-fix release. It maintains both forward and backward +compatibility (source and binary) with Qt 5.6.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.6 series is binary compatible with the 5.5.x series. +Applications compiled for 5.5 will continue to run with 5.6. + +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 * +****************************************************************************** + + - [QTBUG-45031] The NSURLConnection backend of QNetworkAccessManager has + been removed, since SecureTransport is the default SSL backend on iOS + and is enabled by default. This means that building with -no-openssl + -no-securetransport will no longer provide SSL capabilities on iOS. + + - QUrl::resolved() no longer treats a URL with a scheme as a relative URL + if it matches this URL's scheme. For now it still treats "file:name.txt" + as relative for compatibility, but be warned that in Qt 5.8 it will no + longer consider those to be relative. Both isRelative() and RFC 3986 say + that such URLs are not relative, so starting from Qt 5.8, resolved() will + return them as is. + + - [QTBUG-47815] QDateTime now uses QLocale to get the "AM" and "PM" strings + when parsing times, instead of strings obtained from the loaded + translations. + +****************************************************************************** +* Library * +****************************************************************************** + +QtCore +------ + + - Optimized toLatin1()/toUtf8() called on a QStringBuilder expression. + - [QTBUG-18729][QTBUG-32457] Fixed a bug that caused Windows to show + dialogs prompting the user to insert media when certain operations were + made with Qt I/O classes, particularly QStorageInfo::mountedVolumes(). + + - QCommandLineParser: + * The methods that exit() the application will now call cleanup routines + registered with qAddPostRoutine. + + - QDataStream: + * Fixed compatibility of QTime serialization with Qt 3. + + - QDebug: + * Fixed streaming of QChars. + + - QJsonObject: + * Optimized equality operator. + + - QJsonValue: + * Fixed use-after-free in assignment operator. + + - QLockFile: + * Fixed permissions on lock files on Unix to allow for adjustments via + umask. + * [QTBUG-53392] Improved the robustness of detecting stale lock files on + Windows. + + - QMutex: + * [QTBUG-54831] Fixed a bug that caused some applications to crash on + exit, depending on the order of creation of certain statics inside Qt. + + - QObject: + * Fixed a crash when connecting a signal to a lambda or functor while + using Qt::UniqueConnection (note: the connection is still not unique). + + - QStringListModel: + * Fixed dataChanged()'s 'roles' parameter to always contain both + Qt::EditRole and Qt::DisplayRole. + + - QTemporaryFile: + * [QTBUG-54810] Fixed a bug that caused QTemporaryFile to fail when the + file name contained non-ASCII characters, on Windows. + + - QTimeZone: + * [QTBUG-53071] Fixed a bug that caused QTimeZone to mis-parse time zones + whose names were not simple letter and digit combinations. + + - QUrl: + * Made QUrl stricter in what it accepts for schemes, to comply with the + relevant standards. QUrl will no longer accept schemes starting with a + plus (+), a dash (-) or a dot (.). + + - QVariant: + * [QTBUG-53384] Fixed QVariant::canConvert and conversion from integer + types to enumeration types. + * [QTBUG-54893] Fixed a bug that caused QVariants not to compare properly + if they contained QStringLists. + + - QVector: + * [QTBUG-51758] Fixed a bug that would cause QVector to crash if one + called reserve(0). + + - QXmlStreamReader: + * Fixed a bug in the XML parser that prevented to load XML that + contained invalid characters for XML 1.0. + + - QXmlStreamWriter: + * Fixed a bug that prevented the generation of valid XML files when + using encoding with 8 bit per character but not ASCII compatible. + QXMLStreamWriter generated XML markup using always ASCII in this case. + +QtGui +----- + + - Fixed UBSan errors in + * QColor + * QGrayRaster + * QRasterizer + + - Removed a total of 1610 relocations from the library. + + - QGuiApplication: + * [QTBUG-51703] Fixed a bug that would cause QGuiApplication::sync() to + be left undefined for Qt builds without session management support. + + - QIconLoaderEngine: + * Fixed theme lookup for scalable entries. + + - Text: + * [QTBUG-42033] Fixed bug where a QTextLayout with + ShowLineAndParagraphSeparators would modify the layout's input string. + * [QTBUG-49452] Fixed a performance regression in Freetype engine that + was introduced in Qt 5.5. + * [QTBUG-54180] Fixed performance regression when rapidly switching + between a large set of fonts. + + - Windows: + * [QTBUG-54494] Fixed stretch when combined with either no or vertical + hinting preference or a device pixel ratio different from 1. + * [QTBUG-51024] Fixed height of text bounding box when using no or + vertical hinting preference, or when the device pixel ratio is + different from 1. + +QtNetwork +--------- + + - QAuthenticator: + * [QTBUG-53338] Fixed crash when comparing an initialized QAuthenticator + with an uninitialized QAuthenticator. + +QtSql +----- + + - [QTBUG-53969][QTBUG-53237] Fixed QSqlQuery::prepare value truncation + error when using UNSIGNED values in a MySQL database. + +QtWidgets +--------- + + - Fixed UBSan/Coverity errors in: + * QAbstractItemView + * QDataWidgetMapper + * QTreeWidget + * QWidgetLineControl + + - Removed a total of 167 relocations from the library. + + - QAbstractItemDelegate: + * [QTBUG-16469] Show localized detailed tooltips and "What's this?" + texts. + +- QAbstractItemView: + * [QTBUG-53541] Fixed a bug involving drawing the drop indicator + where it shouldn't be drawn. + * Fixed a bug in setSelectionModel() which could lead to model indexes + from a different model be reused on a new model. + + - QAbstractSpinBox: + * [QTBUG-55249] Fixed a bug related to first key press. + + - QColorDialog: + * Fixed ignored alpha channel in getRgb(). + + - QComboBox: + * [QTBUG-54191] Fixed a crash on setEditable(false) called from + editTextChanged(). + + - QCompleter: + * [QTBUG-54642] Fixed wrong completion role after a QFileSystemModel + has been used. + + - QDesktopWidget: + * [QTBUG-52101] Fixed tracking of QScreens. + * [QTBUG-52606] Fixed a bug related to DPI-scaling in screenNumber(). + + - QDialog: + * [QTBUG-52735] Fixed a bug involving moves between screens with + different DPI-scaling factors. + + - QDockWidget: + * [QTBUG-52107][QTBUG-53754] Fixed bugs related to floating group tab + window title. + * [QTBUG-52108] A QDockWidgetGroupWindow can now be dragged into one of + its QDockWidgets. + * [QTBUG-53808] Fixed a bug that caused an undocked dock widget to lose + its decoration. + * [QTBUG-54185] Unbroke drag-and-drop. + + - QGraphicsProxyWidget: + * [QTBUG-55112] Fixed a bug that caused the widget to receive events + during construction. + + - QLineEdit: + * [QTBUG-49374] Fixed icons being too small on a High DPI screen + without scaling. + * [QTBUG-52796] Fixed QKeySequence::MoveToStartOfLine shortcut + being ignored. + * [QTBUG-54425] Fixed missing clear button on macOS. + + - QMainWindow: + * [QTBUG-50491] Fixed a bug related to restoring dock widgets with + GroupedDragging. + * [QTBUG-52108] Fixed a bug related to context menus in the presence of + floating tabs. + + - QMenu: + * [QTBUG-53054] Submenus can now be opened on left mouse button + press, too. + + - QMenuBar: + * [QTBUG-53205] Fixed bugs (incl. crashes) involving reparented + menu bars. + + - QOpenGLWidget: + * [QTBUG-50818][QTBUG-51815][QTBUG-54241][QTBUG-52419] Fixed several + repainting bugs and other drawing artifacts. + + - QSideBar: + * Fixed a nullptr dereference on platforms that do not support + QFileSystemWatcher. + + - QSystemTrayIcon: + * [QTBUG-53591] Use large icon for balloon message on Windows systems. + + - QTabBar: + * Fixed a performance problem involving font metrics. + + - QTreeView: + * [QTBUG-52793] Fixed a key navigation bug when the columns were + reordered. + +- QTreeWidget: + * [QTBUG-50207] Now handles device pixel ratio in animations correctly. + +- QWidget: + * [QTBUG-39887] Restored documented behavior for the + WA_X11NetWmWindowType* attributes. + * [QTBUG-41135][QTBUG-50030][QTBUG-50136][QTBUG-52507] Fixed + mapTo/FromGlobal() in case of widget hierarchies embedded into + QGraphicsView with transformations. + * [QTBUG-45484] Fixed setWindowRole(). + * [QTBUG-50796] Reduced paint-events when resizing native widgets. + * [QTBUG-52123] Fixed a bug by which opaque texture-based widgets + were not always shown. + * [QTBUG-53515] Added a workaround for render-to-texture widgets in + fullscreen windows. + * [QTBUG-54734] Worked around an issue with translucent GL windows + on Windows. + * [QTBUG-54906] Fixed a bug relaed to fullscreen handling on Windows. + + - Styles: + * Fixed several cases of QStyleOptions being created with null + version. + * [QTBUG-51266] Fixed painting of small progress bars on Vista+. + * [QTBUG-54630] Fixed a crash in QMacStyle::styleHint(). + * [QTBUG-49374] The Windows style now takes the monitor's differing + logical DPI into account when calculating native metrics. + +****************************************************************************** +* Platform-specific Changes * +****************************************************************************** + +Android +------- + + - [QTBUG-50724] Added support for clang compiler. + - [QTBUG-53511] Fixed CJK font resolution on Android 7. + +BSDs +---- + + - The freebsd-g++ mkspec was moved back and no longer requires the + "unsupported/" prefix, matching the FreeBSD ports tree, as FreeBSD 9.3 + still defaults to using GCC. Users of GCC that did not previously use + the ports patch will need to adapt their build scripts and drop the + "unsupported/" prefix. + - Fixed a number of compilation issues on FreeBSD, NetBSD and OpenBSD. Qt + should now build out-of-the-box (no patches needed) on those systems. + +Linux +----- + + - [QTBUG-54733] It is now possible to opt out from installing signal + handlers when running with eglfs and linuxfb by setting the + QT_QPA_NO_SIGNAL_HANDLER environment variable to a non-zero value. + - Fixed the value of the 'defined' field in ATSPI GetAttributeValue + results. + +macOS +----- + + - [QTBUG-48953] Pasting text from Qt applications to Apple Mail now works. + - [QTBUG-48953] “text/vcard” is now required as the mime type when + placing vCards on the clipboard. + - OS X => macOS rename in Q_OS_ macros/docs, qmake scopes, + file selectors, etc. + - Add new QSysInfo values and MAC_OS_X / __MAC_ / __IPHONE_ values for + macOS 10.12 and iOS 9.1 through 10.0. + - Update prettyProductName with new macOS "Sierra" codename. + +Windows +------- + + - Fixed a new[]/delete mismatch in Windows tablet support. + +**************************************************************************** +* Tools * +**************************************************************************** + +moc +--- + - [QTBUG-53441] Fixed crash on file ending with a backslash followed by + carriage return diff --git a/examples/widgets/dialogs/findfiles/window.cpp b/examples/widgets/dialogs/findfiles/window.cpp index 05e160ed87..f2ce853d99 100644 --- a/examples/widgets/dialogs/findfiles/window.cpp +++ b/examples/widgets/dialogs/findfiles/window.cpp @@ -304,15 +304,19 @@ void Window::contextMenu(const QPoint &pos) if (!item) return; QMenu menu; +#ifndef QT_NO_CLIPBOARD QAction *copyAction = menu.addAction("Copy Name"); +#endif QAction *openAction = menu.addAction("Open"); QAction *action = menu.exec(filesTable->mapToGlobal(pos)); if (!action) return; const QString fileName = fileNameOfItem(item); - if (action == copyAction) - QGuiApplication::clipboard()->setText(QDir::toNativeSeparators(fileName)); - else if (action == openAction) + if (action == openAction) openFile(fileName); +#ifndef QT_NO_CLIPBOARD + else if (action == copyAction) + QGuiApplication::clipboard()->setText(QDir::toNativeSeparators(fileName)); +#endif } //! [16] diff --git a/mkspecs/features/qt.prf b/mkspecs/features/qt.prf index 71e96b4651..bb52f23378 100644 --- a/mkspecs/features/qt.prf +++ b/mkspecs/features/qt.prf @@ -203,10 +203,10 @@ contains(qt_module_deps, qml): \ # run qmlimportscanner qtPrepareTool(QMLIMPORTSCANNER, qmlimportscanner, , system) for (QMLPATH, QMLPATHS): \ - IMPORTPATHS += -importPath $$QMLPATH + IMPORTPATHS += -importPath $$system_quote($$QMLPATH) #message(run $$QMLIMPORTSCANNER $$_PRO_FILE_PWD_ $$IMPORTPATHS) - JSON = $$system($$QMLIMPORTSCANNER $$_PRO_FILE_PWD_ $$IMPORTPATHS) + JSON = $$system($$QMLIMPORTSCANNER $$system_quote($$_PRO_FILE_PWD_) $$IMPORTPATHS) parseJson(JSON, IMPORTS)| error("Failed to parse qmlimportscanner output.") @@ -267,13 +267,13 @@ contains(qt_module_deps, qml): \ # But strip away archives and other files that are not needed: !isEmpty(QMAKE_POST_LINK): QMAKE_POST_LINK += ";" QMAKE_POST_LINK += \ - "cp $$OUT_PWD/qt.conf $$qtconfTargetPath; " \ - "test -d $$qmlTargetPath && rm -r $$qmlTargetPath; " \ - "mkdir -p $$qmlTargetPath && " \ + "cp $$shell_quote($$OUT_PWD/qt.conf) \"$$qtconfTargetPath\"; " \ + "test -d \"$$qmlTargetPath\" && rm -r \"$$qmlTargetPath\"; " \ + "mkdir -p \"$$qmlTargetPath\" && " \ "for p in $$QMLPATHS; do" \ "rsync -r --exclude='*.a' --exclude='*.prl' --exclude='*.qmltypes' " - macx-xcode: QMAKE_POST_LINK += "$p/ $$qmlTargetPath; done" - else: QMAKE_POST_LINK += "\$\$p/ $$qmlTargetPath; done" + macx-xcode: QMAKE_POST_LINK += "$p/ \"$$qmlTargetPath\"; done" + else: QMAKE_POST_LINK += "\$\$p/ \"$$qmlTargetPath\"; done" } } } diff --git a/qmake/generators/mac/pbuilder_pbx.cpp b/qmake/generators/mac/pbuilder_pbx.cpp index 147c03a92d..ad729fb915 100644 --- a/qmake/generators/mac/pbuilder_pbx.cpp +++ b/qmake/generators/mac/pbuilder_pbx.cpp @@ -33,6 +33,7 @@ #include <qregexp.h> #include <qcryptographichash.h> #include <qdebug.h> +#include <qsettings.h> #include <qstring.h> #include <stdlib.h> #include <time.h> @@ -1403,6 +1404,28 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t) QString configName = (as_release ? "Release" : "Debug"); QMap<QString, QString> settings; + if (!project->isActiveConfig("no_xcode_development_team")) { + const QSettings xcodeSettings( + QDir::homePath() + QLatin1String("/Library/Preferences/com.apple.dt.Xcode.plist"), + QSettings::NativeFormat); + const QVariantMap teams = xcodeSettings.value(QLatin1String("IDEProvisioningTeams")).toMap(); + if (!teams.isEmpty()) { + for (QVariantMap::const_iterator it = teams.begin(), end = teams.end(); it != end; ++it) { + const QVariantMap team = it.value().toMap(); + const QString teamType = team.value(QLatin1String("teamType")).toString(); + + // Skip Company teams because signing permissions may not be available under all + // circumstances for users who are not the Team Agent + if (teamType != QLatin1String("Company")) { + const QString teamId = team.value(QLatin1String("teamID")).toString(); + settings.insert("DEVELOPMENT_TEAM", teamId); + + // first suitable team we found is the one we'll use by default + break; + } + } + } + } settings.insert("COPY_PHASE_STRIP", (as_release ? "YES" : "NO")); // Bitcode is only supported with a deployment target >= iOS 6.0. // Disable it for now, and consider switching it on when later diff --git a/src/corelib/kernel/qobjectdefs.h b/src/corelib/kernel/qobjectdefs.h index 3660d1c0e1..a40614bd31 100644 --- a/src/corelib/kernel/qobjectdefs.h +++ b/src/corelib/kernel/qobjectdefs.h @@ -180,7 +180,7 @@ inline void qYouForgotTheQ_OBJECT_Macro(T1, T2) {} #if defined(Q_CC_CLANG) && Q_CC_CLANG >= 306 # define Q_OBJECT_NO_OVERRIDE_WARNING QT_WARNING_DISABLE_CLANG("-Winconsistent-missing-override") -#elif defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && Q_CC_GNU >= 510 +#elif defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && Q_CC_GNU >= 501 # define Q_OBJECT_NO_OVERRIDE_WARNING QT_WARNING_DISABLE_GCC("-Wsuggest-override") #else # define Q_OBJECT_NO_OVERRIDE_WARNING diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp index 19e00b6762..bfc7e1ca0e 100644 --- a/src/corelib/tools/qdatetime.cpp +++ b/src/corelib/tools/qdatetime.cpp @@ -850,7 +850,7 @@ static QString toStringIsoDate(qint64 jd) range 0 to 9999. This restriction may apply to locale-aware formats as well, depending on the locale settings. - \sa shortDayName(), shortMonthName() + \sa fromString(), shortDayName(), shortMonthName(), QLocale::toString() */ QString QDate::toString(Qt::DateFormat format) const { @@ -926,7 +926,7 @@ QString QDate::toString(Qt::DateFormat format) const If the datetime is invalid, an empty string will be returned. - \sa QDateTime::toString(), QTime::toString(), QLocale::toString() + \sa fromString(), QDateTime::toString(), QTime::toString(), QLocale::toString() */ QString QDate::toString(const QString& format) const @@ -1206,6 +1206,8 @@ qint64 QDate::daysTo(const QDate &d) const Note for Qt::TextDate: It is recommended that you use the English short month names (e.g. "Jan"). Although localized month names can also be used, they depend on the user's locale settings. + + \sa toString(), QLocale::toDate() */ QDate QDate::fromString(const QString& string, Qt::DateFormat format) { @@ -1324,8 +1326,8 @@ QDate QDate::fromString(const QString& string, Qt::DateFormat format) \snippet code/src_corelib_tools_qdatetime.cpp 3 - \sa QDateTime::fromString(), QTime::fromString(), QDate::toString(), - QDateTime::toString(), QTime::toString() + \sa toString(), QDateTime::fromString(), QTime::fromString(), + QLocale::toDate() */ QDate QDate::fromString(const QString &string, const QString &format) @@ -1592,7 +1594,7 @@ int QTime::msec() const If the time is invalid, an empty string will be returned. - \sa QDate::toString(), QDateTime::toString() + \sa fromString(), QDate::toString(), QDateTime::toString(), QLocale::toString() */ QString QTime::toString(Qt::DateFormat format) const @@ -1665,7 +1667,7 @@ QString QTime::toString(Qt::DateFormat format) const If the time is invalid, an empty string will be returned. If \a format is empty, the default format "hh:mm:ss" is used. - \sa QDate::toString(), QDateTime::toString(), QLocale::toString() + \sa fromString(), QDate::toString(), QDateTime::toString(), QLocale::toString() */ QString QTime::toString(const QString& format) const { @@ -1950,6 +1952,8 @@ static QTime fromIsoTimeString(const QStringRef &string, Qt::DateFormat format, this may result in two conversion attempts (if the conversion fails for the default locale). This should be considered an implementation detail. + + \sa toString(), QLocale::toTime() */ QTime QTime::fromString(const QString& string, Qt::DateFormat format) { @@ -2023,8 +2027,8 @@ QTime QTime::fromString(const QString& string, Qt::DateFormat format) \snippet code/src_corelib_tools_qdatetime.cpp 8 - \sa QDateTime::fromString(), QDate::fromString(), QDate::toString(), - QDateTime::toString(), QTime::toString() + \sa toString(), QDateTime::fromString(), QDate::fromString(), + QLocale::toTime() */ QTime QTime::fromString(const QString &string, const QString &format) @@ -3542,7 +3546,8 @@ void QDateTime::setTime_t(uint secsSince1Jan1970UTC) range 0 to 9999. This restriction may apply to locale-aware formats as well, depending on the locale settings. - \sa QDate::toString(), QTime::toString(), Qt::DateFormat + \sa fromString(), QDate::toString(), QTime::toString(), + QLocale::toString() */ QString QDateTime::toString(Qt::DateFormat format) const @@ -3682,7 +3687,7 @@ QString QDateTime::toString(Qt::DateFormat format) const If the datetime is invalid, an empty string will be returned. - \sa QDate::toString(), QTime::toString(), QLocale::toString() + \sa fromString(), QDate::toString(), QTime::toString(), QLocale::toString() */ QString QDateTime::toString(const QString& format) const { @@ -4378,6 +4383,8 @@ int QDateTime::utcOffset() const Note for Qt::TextDate: It is recommended that you use the English short month names (e.g. "Jan"). Although localized month names can also be used, they depend on the user's locale settings. + + \sa toString(), QLocale::toDateTime() */ QDateTime QDateTime::fromString(const QString& string, Qt::DateFormat format) { @@ -4679,8 +4686,8 @@ QDateTime QDateTime::fromString(const QString& string, Qt::DateFormat format) \snippet code/src_corelib_tools_qdatetime.cpp 14 - \sa QDate::fromString(), QTime::fromString(), QDate::toString(), - QDateTime::toString(), QTime::toString() + \sa toString(), QDate::fromString(), QTime::fromString(), + QLocale::toDateTime() */ QDateTime QDateTime::fromString(const QString &string, const QString &format) diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h index 3dda382dd5..ce09582ef9 100644 --- a/src/corelib/tools/qstring.h +++ b/src/corelib/tools/qstring.h @@ -958,6 +958,7 @@ inline QString QString::section(QChar asep, int astart, int aend, SectionFlags a QT_WARNING_PUSH QT_WARNING_DISABLE_MSVC(4127) // "conditional expression is constant" +QT_WARNING_DISABLE_INTEL(111) // "statement is unreachable" inline int QString::toWCharArray(wchar_t *array) const { @@ -1139,21 +1140,21 @@ inline bool operator!=(QString::Null, const QString &s) { return !s.isNull(); } inline bool operator!=(const QString &s, QString::Null) { return !s.isNull(); } inline bool operator==(QLatin1String s1, QLatin1String s2) Q_DECL_NOTHROW -{ return (s1.size() == s2.size() && !memcmp(s1.latin1(), s2.latin1(), s1.size())); } +{ return s1.size() == s2.size() && (!s1.size() || !memcmp(s1.latin1(), s2.latin1(), s1.size())); } inline bool operator!=(QLatin1String s1, QLatin1String s2) Q_DECL_NOTHROW -{ return (s1.size() != s2.size() || memcmp(s1.latin1(), s2.latin1(), s1.size())); } +{ return !operator==(s1, s2); } inline bool operator<(QLatin1String s1, QLatin1String s2) Q_DECL_NOTHROW -{ int r = memcmp(s1.latin1(), s2.latin1(), qMin(s1.size(), s2.size())); - return (r < 0) || (r == 0 && s1.size() < s2.size()); } -inline bool operator<=(QLatin1String s1, QLatin1String s2) Q_DECL_NOTHROW -{ int r = memcmp(s1.latin1(), s2.latin1(), qMin(s1.size(), s2.size())); - return (r < 0) || (r == 0 && s1.size() <= s2.size()); } +{ + const int len = qMin(s1.size(), s2.size()); + const int r = len ? memcmp(s1.latin1(), s2.latin1(), len) : 0; + return r < 0 || (r == 0 && s1.size() < s2.size()); +} inline bool operator>(QLatin1String s1, QLatin1String s2) Q_DECL_NOTHROW -{ int r = memcmp(s1.latin1(), s2.latin1(), qMin(s1.size(), s2.size())); - return (r > 0) || (r == 0 && s1.size() > s2.size()); } +{ return operator<(s2, s1); } +inline bool operator<=(QLatin1String s1, QLatin1String s2) Q_DECL_NOTHROW +{ return !operator>(s1, s2); } inline bool operator>=(QLatin1String s1, QLatin1String s2) Q_DECL_NOTHROW -{ int r = memcmp(s1.latin1(), s2.latin1(), qMin(s1.size(), s2.size())); - return (r > 0) || (r == 0 && s1.size() >= s2.size()); } +{ return !operator<(s1, s2); } inline bool QLatin1String::operator==(const QString &s) const Q_DECL_NOTHROW { return s == *this; } diff --git a/src/dbus/qdbusconnection.cpp b/src/dbus/qdbusconnection.cpp index bd25d8a6bf..da7557d7e8 100644 --- a/src/dbus/qdbusconnection.cpp +++ b/src/dbus/qdbusconnection.cpp @@ -75,24 +75,6 @@ static void preventDllUnload(); Q_GLOBAL_STATIC(QDBusConnectionManager, _q_manager) -// can be replaced with a lambda in Qt 5.7 -class QDBusConnectionDispatchEnabler : public QObject -{ - Q_OBJECT - QDBusConnectionPrivate *con; -public: - QDBusConnectionDispatchEnabler(QDBusConnectionPrivate *con) : con(con) {} - -public slots: - void execute() - { - con->setDispatchEnabled(true); - if (!con->ref.deref()) - con->deleteLater(); - deleteLater(); - } -}; - struct QDBusConnectionManager::ConnectionRequestData { enum RequestType { @@ -1288,8 +1270,6 @@ QByteArray QDBusConnection::localMachineId() QT_END_NAMESPACE -#include "qdbusconnection.moc" - #ifdef Q_OS_WIN # include <qt_windows.h> diff --git a/src/dbus/qdbusconnection_p.h b/src/dbus/qdbusconnection_p.h index b710bfd2aa..ef8946f9e8 100644 --- a/src/dbus/qdbusconnection_p.h +++ b/src/dbus/qdbusconnection_p.h @@ -380,6 +380,25 @@ extern QDBusMessage qDBusPropertySet(const QDBusConnectionPrivate::ObjectTreeNod const QDBusMessage &msg); extern QDBusMessage qDBusPropertyGetAll(const QDBusConnectionPrivate::ObjectTreeNode &node, const QDBusMessage &msg); + +// can be replaced with a lambda in Qt 5.7 +class QDBusConnectionDispatchEnabler : public QObject +{ + Q_OBJECT + QDBusConnectionPrivate *con; +public: + QDBusConnectionDispatchEnabler(QDBusConnectionPrivate *con) : con(con) {} + +public slots: + void execute() + { + con->setDispatchEnabled(true); + if (!con->ref.deref()) + con->deleteLater(); + deleteLater(); + } +}; + #endif // QT_BOOTSTRAPPED QT_END_NAMESPACE diff --git a/src/dbus/qdbuserror.h b/src/dbus/qdbuserror.h index bd7014bdf9..6bb1e2241f 100644 --- a/src/dbus/qdbuserror.h +++ b/src/dbus/qdbuserror.h @@ -100,8 +100,8 @@ public: QDBusError(const QDBusError &other); #ifdef Q_COMPILER_RVALUE_REFS QDBusError(QDBusError &&other) Q_DECL_NOTHROW - : code(other.code), msg(std::move(other.msg)), nm(std::move(other.nm)), unused(other.unused) - { other.unused = Q_NULLPTR; } + : code(other.code), msg(std::move(other.msg)), nm(std::move(other.nm)) + {} QDBusError &operator=(QDBusError &&other) Q_DECL_NOTHROW { swap(other); return *this; } #endif QDBusError &operator=(const QDBusError &other); @@ -114,7 +114,6 @@ public: qSwap(code, other.code); qSwap(msg, other.msg); qSwap(nm, other.nm); - qSwap(unused, other.unused); } ErrorType type() const; @@ -128,6 +127,8 @@ private: ErrorType code; QString msg; QString nm; + // ### This class has an implicit (therefore inline) destructor + // so the following field cannot be used: void *unused; }; Q_DECLARE_SHARED_NOT_MOVABLE_UNTIL_QT6(QDBusError) diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp index 54418c213a..d9e7720a06 100644 --- a/src/dbus/qdbusintegrator.cpp +++ b/src/dbus/qdbusintegrator.cpp @@ -315,9 +315,21 @@ static void qDBusNewConnection(DBusServer *server, DBusConnection *connection, v // setPeer does the error handling for us QDBusErrorInternal error; newConnection->setPeer(connection, error); + newConnection->setDispatchEnabled(false); // this is a queued connection and will resume in the QDBusServer's thread emit serverConnection->newServerConnection(newConnection); + + // we've disabled dispatching of events, so now we post an event to the + // QDBusServer's thread in order to enable it after the + // QDBusServer::newConnection() signal has been received by the + // application's code + newConnection->ref.ref(); + QReadLocker serverLock(&serverConnection->lock); + QDBusConnectionDispatchEnabler *o = new QDBusConnectionDispatchEnabler(newConnection); + QTimer::singleShot(0, o, SLOT(execute())); + if (serverConnection->serverObject) + o->moveToThread(serverConnection->serverObject->thread()); } void QDBusConnectionPrivate::_q_newConnection(QDBusConnectionPrivate *newConnection) @@ -1250,6 +1262,7 @@ void QDBusConnectionPrivate::relaySignal(QObject *obj, const QMetaObject *mo, in break; } + checkThread(); QDBusReadLocker locker(RelaySignalAction, this); QDBusMessage message = QDBusMessage::createSignal(QLatin1String("/"), interface, QLatin1String(memberName)); @@ -2361,12 +2374,9 @@ void QDBusConnectionPrivate::registerObject(const ObjectTreeNode *node) connector->connectAllSignals(node->obj); } - // disconnect and reconnect to avoid duplicates - connector->disconnect(SIGNAL(relaySignal(QObject*,const QMetaObject*,int,QVariantList)), - this, SLOT(relaySignal(QObject*,const QMetaObject*,int,QVariantList))); connect(connector, SIGNAL(relaySignal(QObject*,const QMetaObject*,int,QVariantList)), this, SLOT(relaySignal(QObject*,const QMetaObject*,int,QVariantList)), - Qt::DirectConnection); + Qt::ConnectionType(Qt::QueuedConnection | Qt::UniqueConnection)); } } diff --git a/src/dbus/qdbusserver.cpp b/src/dbus/qdbusserver.cpp index a242ad984c..a59496bce8 100644 --- a/src/dbus/qdbusserver.cpp +++ b/src/dbus/qdbusserver.cpp @@ -103,12 +103,14 @@ QDBusServer::QDBusServer(QObject *parent) */ QDBusServer::~QDBusServer() { + QWriteLocker locker(&d->lock); if (QDBusConnectionManager::instance()) { QMutexLocker locker(&QDBusConnectionManager::instance()->mutex); for (const QString &name : qAsConst(d->serverConnectionNames)) QDBusConnectionManager::instance()->removeConnection(name); d->serverConnectionNames.clear(); } + d->serverObject = nullptr; d->ref.store(0); d->deleteLater(); } diff --git a/src/gui/kernel/qhighdpiscaling.cpp b/src/gui/kernel/qhighdpiscaling.cpp index d5bc51a7e3..fccd81f8e8 100644 --- a/src/gui/kernel/qhighdpiscaling.cpp +++ b/src/gui/kernel/qhighdpiscaling.cpp @@ -169,11 +169,11 @@ static inline qreal initialGlobalScaleFactor() The QT_SCALE_FACTOR environment variable can be used to set a global scale factor for all windows in the processs. This is useful for testing and debugging (you can simulate any - devicePixelRatio without needing access to sepcial hardware), + devicePixelRatio without needing access to special hardware), and perhaps also for targeting a specific application to a specific display type (embedded use cases). - 2) A per-screen scale factors + 2) Per-screen scale factors Some platform plugins support providing a per-screen scale factor based on display density information. These platforms include X11, Windows, and Android. @@ -186,13 +186,13 @@ static inline qreal initialGlobalScaleFactor() Enabling either will make QHighDpiScaling call QPlatformScreen::pixelDensity() and use the value provided as the scale factor for the screen in question. Disabling is done on a 'veto' basis where either the - environment or the application source can disable. The intended use + environment or the application can disable the scaling. The intended use cases are 'My system is not providing correct display density information' and 'My application needs to work in display pixels', respectively. The QT_SCREEN_SCALE_FACTORS environment variable can be used to set the screen - scale factors manually.Set this to a semicolon-separated + scale factors manually. Set this to a semicolon-separated list of scale factors (matching the order of QGuiApplications::screens()), or to a list of name=value pairs (where name matches QScreen::name()). diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index 7378b129a9..2f069a9abd 100644 --- a/src/gui/text/qtextengine.cpp +++ b/src/gui/text/qtextengine.cpp @@ -928,7 +928,7 @@ void QTextEngine::shapeLine(const QScriptLine &line) if (item == -1) return; - const int end = findItem(line.from + line.length - 1, item); + const int end = findItem(line.from + line.length + line.trailingSpaces - 1, item); for ( ; item <= end; ++item) { QScriptItem &si = layoutData->items[item]; if (si.analysis.flags == QScriptAnalysis::Tab) { diff --git a/src/platformsupport/dbusmenu/qdbusplatformmenu.cpp b/src/platformsupport/dbusmenu/qdbusplatformmenu.cpp index e2bde442af..446c3dfa83 100644 --- a/src/platformsupport/dbusmenu/qdbusplatformmenu.cpp +++ b/src/platformsupport/dbusmenu/qdbusplatformmenu.cpp @@ -67,6 +67,8 @@ QDBusPlatformMenuItem::QDBusPlatformMenuItem(quintptr tag) QDBusPlatformMenuItem::~QDBusPlatformMenuItem() { menuItemsByID.remove(m_dbusID); + if (m_subMenu) + static_cast<QDBusPlatformMenu *>(m_subMenu)->setContainingMenuItem(Q_NULLPTR); } void QDBusPlatformMenuItem::setTag(quintptr tag) @@ -174,6 +176,8 @@ QDBusPlatformMenu::QDBusPlatformMenu(quintptr tag) QDBusPlatformMenu::~QDBusPlatformMenu() { + if (m_containingMenuItem) + m_containingMenuItem->setMenu(Q_NULLPTR); } void QDBusPlatformMenu::insertMenuItem(QPlatformMenuItem *menuItem, QPlatformMenuItem *before) diff --git a/src/platformsupport/dbustray/qdbustrayicon.cpp b/src/platformsupport/dbustray/qdbustrayicon.cpp index 33e320ad6d..1d8e430f3e 100644 --- a/src/platformsupport/dbustray/qdbustrayicon.cpp +++ b/src/platformsupport/dbustray/qdbustrayicon.cpp @@ -124,6 +124,8 @@ void QDBusTrayIcon::cleanup() dBusConnection()->unregisterTrayIcon(this); delete m_dbusConnection; m_dbusConnection = Q_NULLPTR; + delete m_notifier; + m_notifier = Q_NULLPTR; m_registered = false; } diff --git a/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.cpp b/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.cpp index d507751d5e..f8fe671a2b 100644 --- a/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.cpp +++ b/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.cpp @@ -112,15 +112,15 @@ static QByteArray localHostName() */ static QComposeCacheFileHeader readFileMetadata(const QString &path) { - QComposeCacheFileHeader info; - info.reserved = 0; - info.fileSize = 0; + quint64 fileSize = 0; + qint64 lastModified = 0; const QByteArray pathBytes = QFile::encodeName(path); QT_STATBUF st; - if (QT_STAT(pathBytes.data(), &st) != 0) - return info; - info.lastModified = st.st_mtime; - info.fileSize = st.st_size; + if (QT_STAT(pathBytes.data(), &st) == 0) { + lastModified = st.st_mtime; + fileSize = st.st_size; + } + QComposeCacheFileHeader info = { 0, 0, fileSize, lastModified }; return info; } diff --git a/src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontext.cpp b/src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontext.cpp index d17abbb65a..857f437661 100644 --- a/src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontext.cpp +++ b/src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontext.cpp @@ -168,11 +168,19 @@ bool QComposeInputContext::checkComposeTable() TableGenerator reader; m_tableState = reader.tableState(); - if ((m_tableState & TableGenerator::NoErrors) == TableGenerator::NoErrors) - m_composeTable = reader.composeTable(); - m_compositionTableInitialized = true; + if ((m_tableState & TableGenerator::NoErrors) == TableGenerator::NoErrors) { + m_composeTable = reader.composeTable(); + } else { +#ifdef DEBUG_COMPOSING + qDebug( "### FAILED_PARSING ###" ); +#endif + // if we have errors, don' try to look things up anyways. + reset(); + return false; + } } + Q_ASSERT(!m_composeTable.isEmpty()); QVector<QComposeTableElement>::const_iterator it = std::lower_bound(m_composeTable.constBegin(), m_composeTable.constEnd(), m_composeBuffer, Compare()); diff --git a/src/plugins/platforms/android/qandroidplatformwindow.cpp b/src/plugins/platforms/android/qandroidplatformwindow.cpp index fa768e64d3..97a1f30a35 100644 --- a/src/plugins/platforms/android/qandroidplatformwindow.cpp +++ b/src/plugins/platforms/android/qandroidplatformwindow.cpp @@ -155,7 +155,7 @@ void QAndroidPlatformWindow::updateStatusBarVisibility() if (!isNonRegularWindow) { if (m_windowState & Qt::WindowFullScreen) QtAndroid::hideStatusBar(); - else if (m_windowState & Qt::WindowMaximized) + else QtAndroid::showStatusBar(); } } diff --git a/src/plugins/platforms/qnx/qqnxintegration.cpp b/src/plugins/platforms/qnx/qqnxintegration.cpp index 3a0e97af6e..e06d9a25c4 100644 --- a/src/plugins/platforms/qnx/qqnxintegration.cpp +++ b/src/plugins/platforms/qnx/qqnxintegration.cpp @@ -112,7 +112,7 @@ static inline QQnxIntegration::Options parseOptions(const QStringList ¶mList options |= QQnxIntegration::FullScreenApplication; } - if (!paramList.contains(QLatin1String("flush-screen-context"))) { + if (paramList.contains(QLatin1String("flush-screen-context"))) { options |= QQnxIntegration::AlwaysFlushScreenContext; } diff --git a/src/plugins/platforms/qnx/qqnxscreen.h b/src/plugins/platforms/qnx/qqnxscreen.h index 3fa511e6df..b7264d0973 100644 --- a/src/plugins/platforms/qnx/qqnxscreen.h +++ b/src/plugins/platforms/qnx/qqnxscreen.h @@ -49,6 +49,17 @@ #include <screen/screen.h> +// For pre-7.0 SDPs, map some screen property names to the old +// names. +#include <sys/neutrino.h> +#if _NTO_VERSION < 700 +const int SCREEN_PROPERTY_FLAGS = SCREEN_PROPERTY_KEY_FLAGS; +const int SCREEN_PROPERTY_FOCUS = SCREEN_PROPERTY_KEYBOARD_FOCUS; +const int SCREEN_PROPERTY_MODIFIERS = SCREEN_PROPERTY_KEY_MODIFIERS; +const int SCREEN_PROPERTY_SCAN = SCREEN_PROPERTY_KEY_SCAN; +const int SCREEN_PROPERTY_SYM = SCREEN_PROPERTY_KEY_SYM; +#endif + QT_BEGIN_NAMESPACE class QQnxWindow; diff --git a/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp b/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp index 599d43a8c8..f7a87b6073 100644 --- a/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp +++ b/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp @@ -239,20 +239,20 @@ void QQnxScreenEventHandler::handleKeyboardEvent(screen_event_t event) { // get flags of key event int flags; - Q_SCREEN_CHECKERROR(screen_get_event_property_iv(event, SCREEN_PROPERTY_KEY_FLAGS, &flags), + Q_SCREEN_CHECKERROR(screen_get_event_property_iv(event, SCREEN_PROPERTY_FLAGS, &flags), "Failed to query event flags"); // get key code int sym; - Q_SCREEN_CHECKERROR(screen_get_event_property_iv(event, SCREEN_PROPERTY_KEY_SYM, &sym), + Q_SCREEN_CHECKERROR(screen_get_event_property_iv(event, SCREEN_PROPERTY_SYM, &sym), "Failed to query event sym"); int modifiers; - Q_SCREEN_CHECKERROR(screen_get_event_property_iv(event, SCREEN_PROPERTY_KEY_MODIFIERS, &modifiers), + Q_SCREEN_CHECKERROR(screen_get_event_property_iv(event, SCREEN_PROPERTY_MODIFIERS, &modifiers), "Failed to query event modifieres"); int scan; - Q_SCREEN_CHECKERROR(screen_get_event_property_iv(event, SCREEN_PROPERTY_KEY_SCAN, &scan), + Q_SCREEN_CHECKERROR(screen_get_event_property_iv(event, SCREEN_PROPERTY_SCAN, &scan), "Failed to query event scan"); int cap; @@ -594,7 +594,7 @@ void QQnxScreenEventHandler::handlePropertyEvent(screen_event_t event) qFatal("QQnx: failed to query window property, errno=%d", errno); switch (property) { - case SCREEN_PROPERTY_KEYBOARD_FOCUS: + case SCREEN_PROPERTY_FOCUS: handleKeyboardFocusPropertyEvent(window); break; default: @@ -607,7 +607,7 @@ void QQnxScreenEventHandler::handleKeyboardFocusPropertyEvent(screen_window_t wi { errno = 0; int focus = 0; - if (Q_UNLIKELY(window && screen_get_window_property_iv(window, SCREEN_PROPERTY_KEYBOARD_FOCUS, &focus) != 0)) + if (Q_UNLIKELY(window && screen_get_window_property_iv(window, SCREEN_PROPERTY_FOCUS, &focus) != 0)) qFatal("QQnx: failed to query keyboard focus property, errno=%d", errno); QWindow *focusWindow = QQnxIntegration::window(window); diff --git a/src/plugins/platforms/qnx/qqnxwindow.cpp b/src/plugins/platforms/qnx/qqnxwindow.cpp index f4e6ca9804..7b3a5ec70c 100644 --- a/src/plugins/platforms/qnx/qqnxwindow.cpp +++ b/src/plugins/platforms/qnx/qqnxwindow.cpp @@ -581,7 +581,7 @@ void QQnxWindow::setFocus(screen_window_t newFocusWindow) screen_get_window_property_pv(nativeHandle(), SCREEN_PROPERTY_GROUP, reinterpret_cast<void**>(&screenGroup)); if (screenGroup) { - screen_set_group_property_pv(screenGroup, SCREEN_PROPERTY_KEYBOARD_FOCUS, + screen_set_group_property_pv(screenGroup, SCREEN_PROPERTY_FOCUS, reinterpret_cast<void**>(&newFocusWindow)); } } diff --git a/src/plugins/platforms/winrt/qwinrtscreen.cpp b/src/plugins/platforms/winrt/qwinrtscreen.cpp index 849acc2d3f..c120de9d8f 100644 --- a/src/plugins/platforms/winrt/qwinrtscreen.cpp +++ b/src/plugins/platforms/winrt/qwinrtscreen.cpp @@ -770,7 +770,7 @@ void QWinRTScreen::addWindow(QWindow *window) updateWindowTitle(window->title()); QWindowSystemInterface::handleWindowActivated(window, Qt::OtherFocusReason); handleExpose(); - QWindowSystemInterface::flushWindowSystemEvents(); + QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ExcludeUserInputEvents); #if _MSC_VER >= 1900 && !defined(QT_NO_DRAGANDDROP) QWinRTDrag::instance()->setDropTarget(window); @@ -788,7 +788,7 @@ void QWinRTScreen::removeWindow(QWindow *window) if (wasTopWindow) QWindowSystemInterface::handleWindowActivated(Q_NULLPTR, Qt::OtherFocusReason); handleExpose(); - QWindowSystemInterface::flushWindowSystemEvents(); + QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ExcludeUserInputEvents); #if _MSC_VER >= 1900 && !defined(QT_NO_DRAGANDDROP) if (wasTopWindow) QWinRTDrag::instance()->setDropTarget(topWindow()); diff --git a/src/plugins/platforms/xcb/qxcbdrag.cpp b/src/plugins/platforms/xcb/qxcbdrag.cpp index fb006ec0f1..dd0c557de6 100644 --- a/src/plugins/platforms/xcb/qxcbdrag.cpp +++ b/src/plugins/platforms/xcb/qxcbdrag.cpp @@ -966,6 +966,9 @@ void QXcbDrag::handleDrop(QPlatformWindow *, const xcb_client_message_event_t *e } else { dropData = platformDropData(); supported_drop_actions = accepted_drop_action; + + // Drop coming from another app? Update keyboard modifiers. + QGuiApplicationPrivate::modifier_buttons = QGuiApplication::queryKeyboardModifiers(); } if (!dropData) diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 6dda005bd9..8b13a90d74 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -2537,8 +2537,13 @@ void QXcbWindow::handlePropertyNotifyEvent(const xcb_property_notify_event_t *ev if (reply && reply->format == 32 && reply->type == atom(QXcbAtom::WM_STATE)) { const quint32 *data = (const quint32 *)xcb_get_property_value(reply); - if (reply->length != 0 && XCB_WM_STATE_ICONIC == data[0]) - newState = Qt::WindowMinimized; + if (reply->length != 0) { + if (data[0] == XCB_WM_STATE_ICONIC + || (data[0] == XCB_WM_STATE_WITHDRAWN + && m_lastWindowStateEvent == Qt::WindowMinimized)) { + newState = Qt::WindowMinimized; + } + } } free(reply); } else { // _NET_WM_STATE can't change minimized state diff --git a/src/sql/drivers/mysql/qsql_mysql.cpp b/src/sql/drivers/mysql/qsql_mysql.cpp index b13e10e3a5..f6b2e74986 100644 --- a/src/sql/drivers/mysql/qsql_mysql.cpp +++ b/src/sql/drivers/mysql/qsql_mysql.cpp @@ -640,8 +640,15 @@ QVariant QMYSQLResult::data(int field) if (f.nullIndicator) return QVariant(f.type); - if (qIsInteger(f.type)) - return QVariant(f.type, f.outField); + if (qIsInteger(f.type)) { + QVariant variant(f.type, f.outField); + // we never want to return char variants here, see QTBUG-53397 + if (static_cast<int>(f.type) == QMetaType::UChar) + return variant.toUInt(); + else if (static_cast<int>(f.type) == QMetaType::Char) + return variant.toInt(); + return variant; + } if (f.type != QVariant::ByteArray) val = toUnicode(d->drv_d_func()->tc, f.outField, f.bufLength); @@ -1371,7 +1378,7 @@ bool QMYSQLDriver::open(const QString& db, : sslCipher.toLocal8Bit().constData()); } -#if MYSQL_VERSION_ID >= 50000 +#if MYSQL_VERSION_ID >= 50100 if (connectTimeout != 0) mysql_options(d->mysql, MYSQL_OPT_CONNECT_TIMEOUT, &connectTimeout); if (readTimeout != 0) @@ -1400,7 +1407,7 @@ bool QMYSQLDriver::open(const QString& db, setOpenError(true); return false; } -#if MYSQL_VERSION_ID >= 50000 +#if MYSQL_VERSION_ID >= 50100 if (reconnect) mysql_options(d->mysql, MYSQL_OPT_RECONNECT, &reconnect); #endif diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index 0d9cff01c4..293dafd932 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -283,6 +283,8 @@ QWidgetPrivate::QWidgetPrivate(int version) , renderToTextureReallyDirty(1) , renderToTextureComposeActive(0) #endif + , childrenHiddenByWState(0) + , childrenShownByExpose(0) #if defined(Q_OS_WIN) , noPaintOnScreen(0) #endif @@ -9035,13 +9037,23 @@ bool QWidget::event(QEvent *event) case QEvent::WindowStateChange: { const bool wasMinimized = static_cast<const QWindowStateChangeEvent *>(event)->oldState() & Qt::WindowMinimized; if (wasMinimized != isMinimized()) { + QWidget *widget = const_cast<QWidget *>(this); if (wasMinimized) { - QShowEvent showEvent; - QCoreApplication::sendEvent(const_cast<QWidget *>(this), &showEvent); + // Always send the spontaneous events here, otherwise it can break the application! + if (!d->childrenShownByExpose) { + // Show widgets only when they are not yet shown by the expose event + d->showChildren(true); + QShowEvent showEvent; + QCoreApplication::sendSpontaneousEvent(widget, &showEvent); + } + d->childrenHiddenByWState = false; // Set it always to "false" when window is restored } else { QHideEvent hideEvent; - QCoreApplication::sendEvent(const_cast<QWidget *>(this), &hideEvent); + QCoreApplication::sendSpontaneousEvent(widget, &hideEvent); + d->hideChildren(true); + d->childrenHiddenByWState = true; } + d->childrenShownByExpose = false; // Set it always to "false" when window state changes } changeEvent(event); } diff --git a/src/widgets/kernel/qwidget_p.h b/src/widgets/kernel/qwidget_p.h index 5f50315df5..f44c0aff21 100644 --- a/src/widgets/kernel/qwidget_p.h +++ b/src/widgets/kernel/qwidget_p.h @@ -752,6 +752,8 @@ public: uint renderToTextureReallyDirty : 1; uint renderToTextureComposeActive : 1; #endif + uint childrenHiddenByWState : 1; + uint childrenShownByExpose : 1; // *************************** Platform specific ************************************ #if defined(Q_OS_WIN) diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp index 2a4f31babf..f3fbe13763 100644 --- a/src/widgets/kernel/qwidgetwindow.cpp +++ b/src/widgets/kernel/qwidgetwindow.cpp @@ -387,7 +387,14 @@ void QWidgetWindow::handleEnterLeaveEvent(QEvent *event) const QEnterEvent *ee = static_cast<QEnterEvent *>(event); QWidget *child = m_widget->childAt(ee->pos()); QWidget *receiver = child ? child : m_widget.data(); - QApplicationPrivate::dispatchEnterLeave(receiver, 0, ee->screenPos()); + QWidget *leave = Q_NULLPTR; + if (QApplicationPrivate::inPopupMode() && receiver == m_widget + && qt_last_mouse_receiver != m_widget) { + // This allows to deliver the leave event to the native widget + // action on first-level menu. + leave = qt_last_mouse_receiver; + } + QApplicationPrivate::dispatchEnterLeave(receiver, leave, ee->screenPos()); qt_last_mouse_receiver = receiver; } } @@ -477,34 +484,31 @@ void QWidgetWindow::handleMouseEvent(QMouseEvent *event) receiver = popupChild; if (receiver != activePopupWidget) widgetPos = receiver->mapFromGlobal(event->globalPos()); - QWidget *alien = receiver; #if !defined(Q_OS_OSX) && !defined(Q_OS_IOS) // Cocoa tracks popups const bool reallyUnderMouse = activePopupWidget->rect().contains(mapped); const bool underMouse = activePopupWidget->underMouse(); - if (activePopupWidget != m_widget || (!underMouse && qt_button_down)) { - // If active popup menu is not the first-level popup menu then we must emulate enter/leave events, - // because first-level popup menu grabs the mouse and enter/leave events are delivered only to it - // by QPA. Make an exception for first-level popup menu when the mouse button is pressed on widget. - if (underMouse != reallyUnderMouse) { - if (reallyUnderMouse) { + if (underMouse != reallyUnderMouse) { + if (reallyUnderMouse) { + const QPoint receiverMapped = receiver->mapFromGlobal(event->screenPos().toPoint()); + // Prevent negative mouse position on enter event - this event + // should be properly handled in "handleEnterLeaveEvent()". + if (receiverMapped.x() >= 0 && receiverMapped.y() >= 0) { QApplicationPrivate::dispatchEnterLeave(receiver, Q_NULLPTR, event->screenPos()); qt_last_mouse_receiver = receiver; - } else { - QApplicationPrivate::dispatchEnterLeave(Q_NULLPTR, qt_last_mouse_receiver, event->screenPos()); - qt_last_mouse_receiver = receiver; - receiver = activePopupWidget; } + } else { + QApplicationPrivate::dispatchEnterLeave(Q_NULLPTR, qt_last_mouse_receiver, event->screenPos()); + qt_last_mouse_receiver = receiver; + receiver = activePopupWidget; } - } else if (!reallyUnderMouse) { - alien = Q_NULLPTR; } #endif QMouseEvent e(event->type(), widgetPos, event->windowPos(), event->screenPos(), event->button(), event->buttons(), event->modifiers(), event->source()); e.setTimestamp(event->timestamp()); - QApplicationPrivate::sendMouseEvent(receiver, &e, alien, receiver->window(), &qt_button_down, qt_last_mouse_receiver); + QApplicationPrivate::sendMouseEvent(receiver, &e, receiver, receiver->window(), &qt_button_down, qt_last_mouse_receiver); qt_last_mouse_receiver = receiver; } else { // close disabled popups when a mouse button is pressed or released @@ -881,10 +885,40 @@ void QWidgetWindow::handleDropEvent(QDropEvent *event) void QWidgetWindow::handleExposeEvent(QExposeEvent *event) { - if (isExposed()) { + QWidgetPrivate *wPriv = m_widget->d_func(); + const bool exposed = isExposed(); + + if (wPriv->childrenHiddenByWState) { + // If widgets has been previously hidden by window state change event + // and they aren't yet shown... + if (exposed) { + // If the window becomes exposed... + if (!wPriv->childrenShownByExpose) { + // ... and they haven't been shown by this function yet - show it. + wPriv->showChildren(true); + QShowEvent showEvent; + QCoreApplication::sendSpontaneousEvent(m_widget, &showEvent); + wPriv->childrenShownByExpose = true; + } + } else { + // If the window becomes not exposed... + if (wPriv->childrenShownByExpose) { + // ... and child widgets was previously shown by the expose event - hide widgets again. + // This is a workaround, because sometimes when window is minimized programatically, + // the QPA can notify that the window is exposed after changing window state to minimized + // and then, the QPA can send next expose event with null exposed region (not exposed). + wPriv->hideChildren(true); + QHideEvent hideEvent; + QCoreApplication::sendSpontaneousEvent(m_widget, &hideEvent); + wPriv->childrenShownByExpose = false; + } + } + } + + if (exposed) { m_widget->setAttribute(Qt::WA_Mapped); if (!event->region().isNull()) - m_widget->d_func()->syncBackingStore(event->region()); + wPriv->syncBackingStore(event->region()); } else { m_widget->setAttribute(Qt::WA_Mapped, false); } diff --git a/src/widgets/styles/qstyleoption.h b/src/widgets/styles/qstyleoption.h index b03e2cc860..8f41f379bc 100644 --- a/src/widgets/styles/qstyleoption.h +++ b/src/widgets/styles/qstyleoption.h @@ -670,7 +670,7 @@ T qstyleoption_cast(const QStyleOption *opt) || (int(Opt::Type) == QStyleOption::SO_Complex && opt->type > QStyleOption::SO_Complex))) return static_cast<T>(opt); - return 0; + return Q_NULLPTR; } template <typename T> @@ -682,7 +682,7 @@ T qstyleoption_cast(QStyleOption *opt) || (int(Opt::Type) == QStyleOption::SO_Complex && opt->type > QStyleOption::SO_Complex))) return static_cast<T>(opt); - return 0; + return Q_NULLPTR; } // -------------------------- QStyleHintReturn ------------------------------- @@ -731,7 +731,7 @@ T qstyleoption_cast(const QStyleHintReturn *hint) if (hint && hint->version <= Opt::Version && (hint->type == Opt::Type || int(Opt::Type) == QStyleHintReturn::SH_Default)) return static_cast<T>(hint); - return 0; + return Q_NULLPTR; } template <typename T> @@ -741,7 +741,7 @@ T qstyleoption_cast(QStyleHintReturn *hint) if (hint && hint->version <= Opt::Version && (hint->type == Opt::Type || int(Opt::Type) == QStyleHintReturn::SH_Default)) return static_cast<T>(hint); - return 0; + return Q_NULLPTR; } #if !defined(QT_NO_DEBUG_STREAM) diff --git a/src/widgets/widgets/qmenu.cpp b/src/widgets/widgets/qmenu.cpp index 95e9a0916a..eba17783ec 100644 --- a/src/widgets/widgets/qmenu.cpp +++ b/src/widgets/widgets/qmenu.cpp @@ -76,22 +76,6 @@ QT_BEGIN_NAMESPACE QMenu *QMenuPrivate::mouseDown = 0; -QPointer<QMenu> QMenuPrivate::previousMouseMenu(Q_NULLPTR); -static void handleEnterLeaveEvents(QPointer<QMenu> *previous_ptr, QMenu *next) -{ - QWidget *previous = previous_ptr->data(); - if (previous != next) { - if (previous) { - QEvent leaveEvent(QEvent::Leave); - QApplication::sendEvent(previous, &leaveEvent); - } - if (next) { - QEvent enterEvent(QEvent::Enter); - QApplication::sendEvent(next, &enterEvent); - } - } - *previous_ptr = next; -} /* QMenu code */ // internal class used for the torn off popup @@ -510,8 +494,6 @@ void QMenuPrivate::hideMenu(QMenu *menu) menu->d_func()->causedPopup.action = 0; menu->close(); menu->d_func()->causedPopup.widget = 0; - if (previousMouseMenu.data() == menu) - handleEnterLeaveEvents(&previousMouseMenu, Q_NULLPTR); } void QMenuPrivate::popupAction(QAction *action, int delay, bool activateFirst) @@ -677,10 +659,26 @@ void QMenuSloppyState::enter() m_parent->childEnter(); } +void QMenuSloppyState::childEnter() +{ + stopTimer(); + if (m_parent) + m_parent->childEnter(); +} + +void QMenuSloppyState::leave() +{ + if (!m_dont_start_time_on_leave) { + if (m_parent) + m_parent->childLeave(); + startTimerIfNotRunning(); + } +} + void QMenuSloppyState::childLeave() { if (m_enabled && !QMenuPrivate::get(m_menu)->hasReceievedEnter) { - startTimer(); + startTimerIfNotRunning(); if (m_parent) m_parent->childLeave(); } @@ -726,8 +724,17 @@ public: void QMenuSloppyState::timeout() { QMenuPrivate *menu_priv = QMenuPrivate::get(m_menu); + + bool reallyHasMouse = menu_priv->hasReceievedEnter; + if (!reallyHasMouse) { + // Check whether the menu really has a mouse, because only active popup + // menu gets the enter/leave events. Currently Cocoa is an exception. + const QPoint lastCursorPos = QGuiApplicationPrivate::lastCursorPosition.toPoint(); + reallyHasMouse = m_menu->frameGeometry().contains(lastCursorPos); + } + if (menu_priv->currentAction == m_reset_action - && menu_priv->hasReceievedEnter + && reallyHasMouse && (menu_priv->currentAction && menu_priv->currentAction->menu() == menu_priv->activeMenu)) { return; @@ -735,13 +742,13 @@ void QMenuSloppyState::timeout() ResetOnDestroy resetState(this, &m_init_guard); - if (hasParentActiveDelayTimer() || !m_menu || !m_menu->isVisible()) + if (hasParentActiveDelayTimer() || !m_menu->isVisible()) return; if (m_sub_menu) menu_priv->hideMenu(m_sub_menu); - if (menu_priv->hasReceievedEnter) + if (reallyHasMouse) menu_priv->setCurrentAction(m_reset_action,0); else menu_priv->setCurrentAction(Q_NULLPTR, 0); @@ -1095,10 +1102,8 @@ bool QMenuPrivate::mouseEventTaken(QMouseEvent *e) tearoffHighlighted = 0; } - if (q->frameGeometry().contains(e->globalPos())) { //otherwise if the event is in our rect we want it.. - handleEnterLeaveEvents(&previousMouseMenu, q); - return false; - } + if (q->frameGeometry().contains(e->globalPos())) + return false; //otherwise if the event is in our rect we want it.. for(QWidget *caused = causedPopup.widget; caused;) { bool passOnEvent = false; @@ -1114,17 +1119,16 @@ bool QMenuPrivate::mouseEventTaken(QMouseEvent *e) next_widget = m->d_func()->causedPopup.widget; } if (passOnEvent) { - handleEnterLeaveEvents(&previousMouseMenu,qobject_cast<QMenu *>(caused)); - if(e->type() != QEvent::MouseButtonRelease || mouseDown == caused) { - QMouseEvent new_e(e->type(), cpos, caused->mapTo(caused->topLevelWidget(), cpos), e->screenPos(), - e->button(), e->buttons(), e->modifiers(), e->source()); - QApplication::sendEvent(caused, &new_e); - return true; + if (e->type() != QEvent::MouseButtonRelease || mouseDown == caused) { + QMouseEvent new_e(e->type(), cpos, caused->mapTo(caused->topLevelWidget(), cpos), e->screenPos(), + e->button(), e->buttons(), e->modifiers(), e->source()); + QApplication::sendEvent(caused, &new_e); + return true; } } caused = next_widget; if (!caused) - handleEnterLeaveEvents(&previousMouseMenu, Q_NULLPTR); + sloppyState.leave(); // Start timers } return false; } @@ -3211,7 +3215,6 @@ void QMenu::enterEvent(QEvent *) Q_D(QMenu); d->hasReceievedEnter = true; d->sloppyState.enter(); - d->sloppyState.startTimer(); d->motions = -1; // force us to ignore the generate mouse move in mouseMoveEvent() } @@ -3222,7 +3225,6 @@ void QMenu::leaveEvent(QEvent *) { Q_D(QMenu); d->hasReceievedEnter = false; - d->sloppyState.leave(); if (!d->activeMenu && d->currentAction) setActiveAction(0); } @@ -3395,10 +3397,18 @@ void QMenu::internalDelayedPopup() const QRect actionRect(d->actionRect(d->currentAction)); const QPoint rightPos(mapToGlobal(QPoint(actionRect.right() + subMenuOffset + 1, actionRect.top()))); - QPoint pos(rightPos); - - d->activeMenu->popup(pos); + d->activeMenu->popup(rightPos); d->sloppyState.setSubMenuPopup(actionRect, d->currentAction, d->activeMenu); + +#if !defined(Q_OS_DARWIN) + // Send the leave event to the current menu - only active popup menu gets + // mouse enter/leave events. Currently Cocoa is an exception, so disable + // it there to avoid event duplication. + if (underMouse()) { + QEvent leaveEvent(QEvent::Leave); + QCoreApplication::sendEvent(this, &leaveEvent); + } +#endif } /*! diff --git a/src/widgets/widgets/qmenu_p.h b/src/widgets/widgets/qmenu_p.h index 0705cd12ea..56904f51d6 100644 --- a/src/widgets/widgets/qmenu_p.h +++ b/src/widgets/widgets/qmenu_p.h @@ -128,8 +128,6 @@ public: void reset(); bool enabled() const { return m_enabled; } - void setResetAction(QAction *action) { m_reset_action = action; } - enum MouseEventResult { EventIsProcessed, EventShouldBePropagated, @@ -154,22 +152,9 @@ public: } void enter(); + void childEnter(); - void childEnter() - { - stopTimer(); - if (m_parent) - m_parent->childEnter(); - } - - void leave() - { - if (m_dont_start_time_on_leave) - return; - if (m_parent) - m_parent->childLeave(); - startTimer(); - } + void leave(); void childLeave(); static float slope(const QPointF &p1, const QPointF &p2) @@ -195,8 +180,7 @@ public: if (!m_enabled) return EventShouldBePropagated; - if (!m_time.isActive()) - startTimer(); + startTimerIfNotRunning(); if (!m_sub_menu) { reset(); @@ -499,7 +483,6 @@ public: QAction* wceCommands(uint command); #endif QPointer<QWidget> noReplayFor; - static QPointer<QMenu> previousMouseMenu; }; #endif // QT_NO_MENU diff --git a/src/widgets/widgets/qmenubar.cpp b/src/widgets/widgets/qmenubar.cpp index 0e7b25f65d..8b5f370fc3 100644 --- a/src/widgets/widgets/qmenubar.cpp +++ b/src/widgets/widgets/qmenubar.cpp @@ -1010,13 +1010,11 @@ void QMenuBar::paintEvent(QPaintEvent *e) */ void QMenuBar::setVisible(bool visible) { -#if defined(Q_OS_MAC) || defined(Q_OS_WINCE) if (isNativeMenuBar()) { if (!visible) QWidget::setVisible(false); return; } -#endif QWidget::setVisible(visible); } @@ -1566,11 +1564,7 @@ QRect QMenuBar::actionGeometry(QAction *act) const QSize QMenuBar::minimumSizeHint() const { Q_D(const QMenuBar); -#if defined(Q_OS_MAC) || defined(Q_OS_WINCE) const bool as_gui_menubar = !isNativeMenuBar(); -#else - const bool as_gui_menubar = true; -#endif ensurePolished(); QSize ret(0, 0); @@ -1622,12 +1616,7 @@ QSize QMenuBar::minimumSizeHint() const QSize QMenuBar::sizeHint() const { Q_D(const QMenuBar); -#if defined(Q_OS_MAC) || defined(Q_OS_WINCE) const bool as_gui_menubar = !isNativeMenuBar(); -#else - const bool as_gui_menubar = true; -#endif - ensurePolished(); QSize ret(0, 0); @@ -1680,11 +1669,7 @@ QSize QMenuBar::sizeHint() const int QMenuBar::heightForWidth(int) const { Q_D(const QMenuBar); -#if defined(Q_OS_MAC) || defined(Q_OS_WINCE) const bool as_gui_menubar = !isNativeMenuBar(); -#else - const bool as_gui_menubar = true; -#endif const_cast<QMenuBarPrivate*>(d)->updateGeometries(); int height = 0; @@ -1830,10 +1815,8 @@ QWidget *QMenuBar::cornerWidget(Qt::Corner corner) const void QMenuBar::setNativeMenuBar(bool nativeMenuBar) { Q_D(QMenuBar); - if (d->nativeMenuBar == -1 || (nativeMenuBar != bool(d->nativeMenuBar))) { - d->nativeMenuBar = nativeMenuBar; - - if (!d->nativeMenuBar) { + if (nativeMenuBar != bool(d->platformMenuBar)) { + if (!nativeMenuBar) { delete d->platformMenuBar; d->platformMenuBar = 0; } else { @@ -1842,7 +1825,7 @@ void QMenuBar::setNativeMenuBar(bool nativeMenuBar) } updateGeometry(); - if (!d->nativeMenuBar && parentWidget()) + if (!nativeMenuBar && parentWidget()) setVisible(true); } } @@ -1850,10 +1833,7 @@ void QMenuBar::setNativeMenuBar(bool nativeMenuBar) bool QMenuBar::isNativeMenuBar() const { Q_D(const QMenuBar); - if (d->nativeMenuBar == -1) { - return !QApplication::instance()->testAttribute(Qt::AA_DontUseNativeMenuBar); - } - return d->nativeMenuBar; + return bool(d->platformMenuBar); } /*! diff --git a/src/widgets/widgets/qmenubar_p.h b/src/widgets/widgets/qmenubar_p.h index c88e4af836..bdff169451 100644 --- a/src/widgets/widgets/qmenubar_p.h +++ b/src/widgets/widgets/qmenubar_p.h @@ -65,7 +65,7 @@ class QMenuBarPrivate : public QWidgetPrivate public: QMenuBarPrivate() : itemsDirty(0), currentAction(0), mouseDown(0), closePopupMode(0), defaultPopDown(1), popupState(0), keyboardState(0), altPressed(0), - nativeMenuBar(-1), doChildEffects(false), platformMenuBar(0) + doChildEffects(false), platformMenuBar(0) #ifdef Q_OS_WINCE , wce_menubar(0), wceClassicMenu(false) @@ -108,8 +108,6 @@ public: uint keyboardState : 1, altPressed : 1; QPointer<QWidget> keyboardFocusWidget; - - int nativeMenuBar : 3; // Only has values -1, 0, and 1 //firing of events void activateAction(QAction *, QAction::ActionEvent); diff --git a/src/widgets/widgets/qtabbar.cpp b/src/widgets/widgets/qtabbar.cpp index 11700fe6f1..e51f484f6f 100644 --- a/src/widgets/widgets/qtabbar.cpp +++ b/src/widgets/widgets/qtabbar.cpp @@ -1958,9 +1958,8 @@ void QTabBar::mouseMoveEvent(QMouseEvent *event) } } - int offset = (event->pos() - d->dragStartPosition).manhattanLength(); if (event->buttons() == Qt::LeftButton - && offset > QApplication::startDragDistance() + && d->dragInProgress && d->validIndex(d->pressedIndex)) { bool vertical = verticalTabs(d->shape); int dragDistance; diff --git a/src/widgets/widgets/qtoolbutton.cpp b/src/widgets/widgets/qtoolbutton.cpp index 8b40325a24..80a061e6d5 100644 --- a/src/widgets/widgets/qtoolbutton.cpp +++ b/src/widgets/widgets/qtoolbutton.cpp @@ -196,7 +196,6 @@ QToolButton::QToolButton(QWidget * parent) void QToolButtonPrivate::init() { Q_Q(QToolButton); - delay = q->style()->styleHint(QStyle::SH_ToolButton_PopupDelay, 0, q); defaultAction = 0; #ifndef QT_NO_TOOLBAR if (qobject_cast<QToolBar*>(parent)) @@ -222,7 +221,7 @@ void QToolButtonPrivate::init() #endif setLayoutItemMargins(QStyle::SE_ToolButtonLayoutItem); - + delay = q->style()->styleHint(QStyle::SH_ToolButton_PopupDelay, 0, q); } /*! diff --git a/tests/auto/corelib/tools/qlatin1string/tst_qlatin1string.cpp b/tests/auto/corelib/tools/qlatin1string/tst_qlatin1string.cpp index 1295a36c1a..878b4b52b6 100644 --- a/tests/auto/corelib/tools/qlatin1string/tst_qlatin1string.cpp +++ b/tests/auto/corelib/tools/qlatin1string/tst_qlatin1string.cpp @@ -30,6 +30,15 @@ #include <QString> +// Preserve QLatin1String-ness (QVariant(QLatin1String) creates a QVariant::String): +struct QLatin1StringContainer { + QLatin1String l1; +}; +QT_BEGIN_NAMESPACE +Q_DECLARE_TYPEINFO(QLatin1StringContainer, Q_MOVABLE_TYPE); +QT_END_NAMESPACE +Q_DECLARE_METATYPE(QLatin1StringContainer) + class tst_QLatin1String : public QObject { Q_OBJECT @@ -37,6 +46,8 @@ class tst_QLatin1String : public QObject private Q_SLOTS: void nullString(); void emptyString(); + void relationalOperators_data(); + void relationalOperators(); }; void tst_QLatin1String::nullString() @@ -114,7 +125,53 @@ void tst_QLatin1String::emptyString() } } +void tst_QLatin1String::relationalOperators_data() +{ + QTest::addColumn<QLatin1StringContainer>("lhs"); + QTest::addColumn<int>("lhsOrderNumber"); + QTest::addColumn<QLatin1StringContainer>("rhs"); + QTest::addColumn<int>("rhsOrderNumber"); + struct Data { + QLatin1String l1; + int order; + } data[] = { + { QLatin1String(), 0 }, + { QLatin1String(""), 0 }, + { QLatin1String("a"), 1 }, + { QLatin1String("aa"), 2 }, + { QLatin1String("b"), 3 }, + }; + + for (Data *lhs = data; lhs != data + sizeof data / sizeof *data; ++lhs) { + for (Data *rhs = data; rhs != data + sizeof data / sizeof *data; ++rhs) { + QLatin1StringContainer l = { lhs->l1 }, r = { rhs->l1 }; + QTest::newRow(qPrintable(QString::asprintf("\"%s\" <> \"%s\"", + lhs->l1.data() ? lhs->l1.data() : "nullptr", + rhs->l1.data() ? rhs->l1.data() : "nullptr"))) + << l << lhs->order << r << rhs->order; + } + } +} + +void tst_QLatin1String::relationalOperators() +{ + QFETCH(QLatin1StringContainer, lhs); + QFETCH(int, lhsOrderNumber); + QFETCH(QLatin1StringContainer, rhs); + QFETCH(int, rhsOrderNumber); + +#define CHECK(op) \ + QCOMPARE(lhs.l1 op rhs.l1, lhsOrderNumber op rhsOrderNumber) \ + /*end*/ + CHECK(==); + CHECK(!=); + CHECK(< ); + CHECK(> ); + CHECK(<=); + CHECK(>=); +#undef CHECK +} QTEST_APPLESS_MAIN(tst_QLatin1String) diff --git a/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp b/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp index 078a629df5..84e9643e77 100644 --- a/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp +++ b/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp @@ -4002,12 +4002,14 @@ void runIntegralTypesMysqlTest(QSqlDatabase &db, const QString &tableName, const QVERIFY_SQL(q, exec("DROP TABLE IF EXISTS " + tableName)); QVERIFY_SQL(q, exec("CREATE TABLE " + tableName + " (id " + type + ')')); - const int steps = 20; - const T increment = max / steps - min / steps; + const int steps = (max == min + 1) ? 2 : 20; + const T increment = (max == min + 1) ? 1 : (max / steps - min / steps); // insert some values QVector<T> values; + QVector<QVariant> variantValues; values.resize(steps); + variantValues.resize(steps); T v = min; if (withPreparedStatement) { QVERIFY_SQL(q, prepare("INSERT INTO " + tableName + " (id) VALUES (?)")); @@ -4020,17 +4022,30 @@ void runIntegralTypesMysqlTest(QSqlDatabase &db, const QString &tableName, const QVERIFY_SQL(q, exec("INSERT INTO " + tableName + " (id) VALUES (" + QString::number(v) + QLatin1Char(')'))); } values[i] = v; + variantValues[i] = QVariant::fromValue(v); v += increment; } // ensure we can read them back properly - QVERIFY_SQL(q, exec("SELECT id FROM " + tableName)); + if (withPreparedStatement) { + QVERIFY_SQL(q, prepare("SELECT id FROM " + tableName)); + QVERIFY_SQL(q, exec()); + } else { + QVERIFY_SQL(q, exec("SELECT id FROM " + tableName)); + } QVector<T> actualValues; + QVector<QVariant> actualVariantValues; actualValues.reserve(values.size()); while (q.next()) { - actualValues << q.value(0).value<T>(); + QVariant value = q.value(0); + actualVariantValues << value; + actualValues << value.value<T>(); + QVERIFY(actualVariantValues.last().userType() != qMetaTypeId<char>()); + QVERIFY(actualVariantValues.last().userType() != qMetaTypeId<signed char>()); + QVERIFY(actualVariantValues.last().userType() != qMetaTypeId<unsigned char>()); } QCOMPARE(actualValues, values); + QCOMPARE(actualVariantValues, variantValues); } void tst_QSqlQuery::integralTypesMysql() @@ -4041,16 +4056,18 @@ void tst_QSqlQuery::integralTypesMysql() for (int i = 0; i < 2; ++i) { const bool withPreparedStatement = (i == 1); - runIntegralTypesMysqlTest<char>(db, "tinyIntTest", "TINYINT", withPreparedStatement); - runIntegralTypesMysqlTest<unsigned char>(db, "unsignedTinyIntTest", "TINYINT UNSIGNED", withPreparedStatement); - runIntegralTypesMysqlTest<char>(db, "smallIntTest", "SMALLINT", withPreparedStatement); - runIntegralTypesMysqlTest<unsigned char>(db, "unsignedSmallIntTest", "SMALLINT UNSIGNED", withPreparedStatement); - runIntegralTypesMysqlTest<int>(db, "mediumIntTest", "MEDIUMINT", withPreparedStatement, -(1 << 23), (1 << 23) - 1); - runIntegralTypesMysqlTest<unsigned int>(db, "unsignedMediumIntTest", "MEDIUMINT UNSIGNED", withPreparedStatement, 0, (1 << 24) - 1); - runIntegralTypesMysqlTest<int>(db, "intTest", "INT", withPreparedStatement); - runIntegralTypesMysqlTest<unsigned int>(db, "unsignedIntTest", "INT UNSIGNED", withPreparedStatement); - runIntegralTypesMysqlTest<long long>(db, "bigIntTest", "BIGINT", withPreparedStatement); - runIntegralTypesMysqlTest<unsigned long long>(db, "unsignedBigIntTest", "BIGINT UNSIGNED", withPreparedStatement); + runIntegralTypesMysqlTest<bool>(db, "tinyInt1Test", "TINYINT(1)", withPreparedStatement); + runIntegralTypesMysqlTest<bool>(db, "unsignedTinyInt1Test", "TINYINT(1) UNSIGNED", withPreparedStatement); + runIntegralTypesMysqlTest<qint8>(db, "tinyIntTest", "TINYINT", withPreparedStatement); + runIntegralTypesMysqlTest<quint8>(db, "unsignedTinyIntTest", "TINYINT UNSIGNED", withPreparedStatement); + runIntegralTypesMysqlTest<qint16>(db, "smallIntTest", "SMALLINT", withPreparedStatement); + runIntegralTypesMysqlTest<quint16>(db, "unsignedSmallIntTest", "SMALLINT UNSIGNED", withPreparedStatement); + runIntegralTypesMysqlTest<qint32>(db, "mediumIntTest", "MEDIUMINT", withPreparedStatement, -(1 << 23), (1 << 23) - 1); + runIntegralTypesMysqlTest<quint32>(db, "unsignedMediumIntTest", "MEDIUMINT UNSIGNED", withPreparedStatement, 0, (1 << 24) - 1); + runIntegralTypesMysqlTest<qint32>(db, "intTest", "INT", withPreparedStatement); + runIntegralTypesMysqlTest<quint32>(db, "unsignedIntTest", "INT UNSIGNED", withPreparedStatement); + runIntegralTypesMysqlTest<qint64>(db, "bigIntTest", "BIGINT", withPreparedStatement); + runIntegralTypesMysqlTest<quint64>(db, "unsignedBigIntTest", "BIGINT UNSIGNED", withPreparedStatement); } } diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp index 98b630b49d..bbff9f0e50 100644 --- a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp +++ b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp @@ -289,6 +289,7 @@ private slots: void showHideEvent_data(); void showHideEvent(); void showHideEventWhileMinimize(); + void showHideChildrenWhileMinimize_QTBUG50589(); void lostUpdatesOnHide(); @@ -4073,19 +4074,30 @@ class ShowHideEventWidget : public QWidget { public: int numberOfShowEvents, numberOfHideEvents; + int numberOfSpontaneousShowEvents, numberOfSpontaneousHideEvents; ShowHideEventWidget(QWidget *parent = 0) - : QWidget(parent), numberOfShowEvents(0), numberOfHideEvents(0) + : QWidget(parent) + , numberOfShowEvents(0), numberOfHideEvents(0) + , numberOfSpontaneousShowEvents(0), numberOfSpontaneousHideEvents(0) { } void create() { QWidget::create(); } - void showEvent(QShowEvent *) - { ++numberOfShowEvents; } + void showEvent(QShowEvent *e) + { + ++numberOfShowEvents; + if (e->spontaneous()) + ++numberOfSpontaneousShowEvents; + } - void hideEvent(QHideEvent *) - { ++numberOfHideEvents; } + void hideEvent(QHideEvent *e) + { + ++numberOfHideEvents; + if (e->spontaneous()) + ++numberOfSpontaneousHideEvents; + } }; void tst_QWidget::showHideEvent_data() @@ -4177,6 +4189,32 @@ void tst_QWidget::showHideEventWhileMinimize() QTRY_COMPARE(widget.numberOfShowEvents, showEventsBeforeMinimize + 1); } +void tst_QWidget::showHideChildrenWhileMinimize_QTBUG50589() +{ + const QPlatformIntegration *pi = QGuiApplicationPrivate::platformIntegration(); + if (!pi->hasCapability(QPlatformIntegration::MultipleWindows) + || !pi->hasCapability(QPlatformIntegration::NonFullScreenWindows) + || !pi->hasCapability(QPlatformIntegration::WindowManagement)) { + QSKIP("This test requires window management capabilities"); + } + + QWidget parent; + ShowHideEventWidget child(&parent); + + parent.setWindowTitle(QTest::currentTestFunction()); + parent.resize(m_testWidgetSize); + centerOnScreen(&parent); + parent.show(); + QVERIFY(QTest::qWaitForWindowExposed(&parent)); + + const int showEventsBeforeMinimize = child.numberOfSpontaneousShowEvents; + const int hideEventsBeforeMinimize = child.numberOfSpontaneousHideEvents; + parent.showMinimized(); + QTRY_COMPARE(child.numberOfSpontaneousHideEvents, hideEventsBeforeMinimize + 1); + parent.showNormal(); + QTRY_COMPARE(child.numberOfSpontaneousShowEvents, showEventsBeforeMinimize + 1); +} + void tst_QWidget::update() { #ifdef Q_OS_OSX @@ -10315,8 +10353,11 @@ void tst_QWidget::underMouse() QCOMPARE(childWidget2.leaves, 0); // Mouse leaves popup and enters topLevelWidget, should cause leave for popup - // but no enter to topLevelWidget. Again, artificial leave event needed. + // but no enter to topLevelWidget. +#ifdef Q_OS_DARWIN + // Artificial leave event needed for Cocoa. QWindowSystemInterface::handleLeaveEvent(popupWindow); +#endif QTest::mouseMove(popupWindow, popupWindow->mapFromGlobal(window->mapToGlobal(inWindowPoint))); QApplication::processEvents(); QVERIFY(!topLevelWidget.underMouse()); diff --git a/tools/configure/configureapp.cpp b/tools/configure/configureapp.cpp index 0fa205bd98..263cd6e78c 100644 --- a/tools/configure/configureapp.cpp +++ b/tools/configure/configureapp.cpp @@ -304,6 +304,12 @@ Configure::Configure(int& argc, char** argv) : verbose(0) dictionary["QT_GCC_MAJOR_VERSION"] = parts.value(0, zero); dictionary["QT_GCC_MINOR_VERSION"] = parts.value(1, zero); dictionary["QT_GCC_PATCH_VERSION"] = parts.value(2, zero); + } else if (dictionary["QMAKESPEC"].contains(QString("msvc"))) { + const QString zero = QStringLiteral("0"); + const QStringList parts = Environment::msvcVersion().split(QLatin1Char('.')); + dictionary["QT_CL_MAJOR_VERSION"] = parts.value(0, zero); + dictionary["QT_CL_MINOR_VERSION"] = parts.value(1, zero); + dictionary["QT_CL_PATCH_VERSION"] = parts.value(2, zero); } } @@ -3553,6 +3559,10 @@ void Configure::generateQConfigPri() configStream << "QT_GCC_MAJOR_VERSION = " << dictionary["QT_GCC_MAJOR_VERSION"] << endl << "QT_GCC_MINOR_VERSION = " << dictionary["QT_GCC_MINOR_VERSION"] << endl << "QT_GCC_PATCH_VERSION = " << dictionary["QT_GCC_PATCH_VERSION"] << endl; + } else if (!dictionary["QT_CL_MAJOR_VERSION"].isEmpty()) { + configStream << "QT_CL_MAJOR_VERSION = " << dictionary["QT_CL_MAJOR_VERSION"] << endl + << "QT_CL_MINOR_VERSION = " << dictionary["QT_CL_MINOR_VERSION"] << endl + << "QT_CL_PATCH_VERSION = " << dictionary["QT_CL_PATCH_VERSION"] << endl; } if (dictionary.value("XQMAKESPEC").startsWith("wince")) { diff --git a/tools/configure/environment.cpp b/tools/configure/environment.cpp index 5189883901..1a05c9ce62 100644 --- a/tools/configure/environment.cpp +++ b/tools/configure/environment.cpp @@ -147,6 +147,30 @@ QString Environment::gccVersion() return version; } +QString Environment::msvcVersion() +{ + int returnValue = 0; + // Extract version from standard error output of "cl /?" + const QString command = QFile::decodeName(qgetenv("ComSpec")) + + QLatin1String(" /c ") + QLatin1String(compilerInfo(CC_MSVC2015)->executable) + + QLatin1String(" /? 2>&1"); + QString version = execute(command, &returnValue); + if (returnValue != 0) { + cout << "Could not get cl version" << returnValue << qPrintable(version) << '\n';; + version.clear(); + } else { + QRegExp versionRegexp(QStringLiteral("^.*Compiler Version ([0-9.]+) for.*$")); + Q_ASSERT(versionRegexp.isValid()); + if (versionRegexp.exactMatch(version)) { + version = versionRegexp.cap(1); + } else { + cout << "Unable to determine cl version from the output of \"" + << qPrintable(command) << "\"\n"; + } + } + return version; +} + /*! Returns the enum of the compiler which was detected on the system. The compilers are detected in the order as entered into the diff --git a/tools/configure/environment.h b/tools/configure/environment.h index 893e33c76f..344404505e 100644 --- a/tools/configure/environment.h +++ b/tools/configure/environment.h @@ -52,6 +52,7 @@ public: static QString detectQMakeSpec(); static Compiler compilerFromQMakeSpec(const QString &qmakeSpec); static QString gccVersion(); + static QString msvcVersion(); static int execute(QStringList arguments, const QStringList &additionalEnv, const QStringList &removeEnv); static QString execute(const QString &command, int *returnCode = 0); |