diff options
115 files changed, 1382 insertions, 463 deletions
@@ -1,10 +1,10 @@ INSTALLING Qt Source Package Version %VERSION%. -For full installation instructions for each supported platform, please -see http://qt-project.org/doc/qt-%SHORTVERSION%/qtdoc/installation.html, +For instructions on building and installing Qt for each supported platform, +please see http://qt-project.org/doc/qt-%SHORTVERSION%/build-sources.html, or follow one of these links: -Mac OS X: http://qt-project.org/doc/qt-%SHORTVERSION%/qtdoc/install-mac.html -Windows: http://qt-project.org/doc/qt-%SHORTVERSION%/qtdoc/install-win.html -Windows CE: http://qt-project.org/doc/qt-%SHORTVERSION%/qtdoc/install-wince.html -X11 Platforms: http://qt-project.org/doc/qt-%SHORTVERSION%/qtdoc/install-x11.html +Mac OS X: http://qt-project.org/doc/qt-%SHORTVERSION%/macosx-building.html +Windows: http://qt-project.org/doc/qt-%SHORTVERSION%/windows-building.html +X11 Platforms: http://qt-project.org/doc/qt-%SHORTVERSION%/linux-building.html +Windows CE: http://qt-project.org/doc/qt-%SHORTVERSION%/install-wince.html diff --git a/config.tests/unix/evdev/evdev.cpp b/config.tests/unix/evdev/evdev.cpp index 475c54a363..3fbce565ce 100644 --- a/config.tests/unix/evdev/evdev.cpp +++ b/config.tests/unix/evdev/evdev.cpp @@ -40,6 +40,7 @@ ****************************************************************************/ #include <linux/input.h> +#include <linux/kd.h> enum { e1 = ABS_PRESSURE, @@ -95,7 +95,7 @@ if [ x"$1" = x"-top-level" ]; then fi # later cache the command line in config.status -OPT_CMDLINE=`echo $@ | sed "s,-v ,,g; s,-v$,,g"` +OPT_CMDLINE=`echo $@ | sed 's,-v ,,g; s,-v$,,g'` # initialize global variables QMAKE_SWITCHES= @@ -170,7 +170,7 @@ expandQMakeConf() { while read line; do case "$line" in include*) - inc_file=`echo "$line" | sed -n -e "/^include.*(.*)/s/include.*(\(.*\)).*$/\1/p"` + inc_file=`echo "$line" | sed -n -e '/^include.*(.*)/s/include.*(\(.*\)).*$/\1/p'` current_dir=`dirname "$1"` conf_file="$current_dir/$inc_file" if [ ! -f "$conf_file" ]; then @@ -450,7 +450,7 @@ resolveDeviceMkspec() match_count=$(echo "$result" | wc -w) if [ "$match_count" -gt 1 ]; then echo >&2 "Error: Multiple matches for device '$1'. Candidates are:" - tabbed_result=$(echo "$result" | sed "s,^, ,") + tabbed_result=$(echo "$result" | sed 's,^, ,') echo >&2 "$tabbed_result" echo "undefined" elif [ "$match_count" -eq 0 ]; then @@ -828,33 +828,33 @@ while [ "$#" -gt 0 ]; do case "$1" in #Autoconf style options --enable-*) - VAR=`echo $1 | sed "s,^--enable-\(.*\),\1,"` + VAR=`echo $1 | sed 's,^--enable-\(.*\),\1,'` VAL=yes ;; --disable-*) - VAR=`echo $1 | sed "s,^--disable-\(.*\),\1,"` + VAR=`echo $1 | sed 's,^--disable-\(.*\),\1,'` VAL=no ;; --*=*) - VAR=`echo $1 | sed "s,^--\(.*\)=.*,\1,"` - VAL=`echo $1 | sed "s,^--.*=\(.*\),\1,"` + VAR=`echo $1 | sed 's,^--\(.*\)=.*,\1,'` + VAL=`echo $1 | sed 's,^--.*=\(.*\),\1,'` ;; --no-*) - VAR=`echo $1 | sed "s,^--no-\(.*\),\1,"` + VAR=`echo $1 | sed 's,^--no-\(.*\),\1,'` VAL=no ;; --*) - VAR=`echo $1 | sed "s,^--\(.*\),\1,"` + VAR=`echo $1 | sed 's,^--\(.*\),\1,'` VAL=yes ;; #Qt plugin options -no-*-*|-plugin-*-*|-qt-*-*) - VAR=`echo $1 | sed "s,^-[^-]*-\(.*\),\1,"` - VAL=`echo $1 | sed "s,^-\([^-]*\).*,\1,"` + VAR=`echo $1 | sed 's,^-[^-]*-\(.*\),\1,'` + VAL=`echo $1 | sed 's,^-\([^-]*\).*,\1,'` ;; #Qt style no options -no-*) - VAR=`echo $1 | sed "s,^-no-\(.*\),\1,"` + VAR=`echo $1 | sed 's,^-no-\(.*\),\1,'` VAL=no ;; #Qt style options that pass an argument @@ -899,14 +899,14 @@ while [ "$#" -gt 0 ]; do -android-ndk-host| \ -android-arch| \ -android-toolchain-version) - VAR=`echo $1 | sed "s,^-\(.*\),\1,"` + VAR=`echo $1 | sed 's,^-\(.*\),\1,'` shift VAL="$1" ;; #Qt style complex options in one command -enable-*|-disable-*) - VAR=`echo $1 | sed "s,^-\([^-]*\)-.*,\1,"` - VAL=`echo $1 | sed "s,^-[^-]*-\(.*\),\1,"` + VAR=`echo $1 | sed 's,^-\([^-]*\)-.*,\1,'` + VAL=`echo $1 | sed 's,^-[^-]*-\(.*\),\1,'` ;; -system-proxies) VAR=system-proxies @@ -918,8 +918,8 @@ while [ "$#" -gt 0 ]; do ;; #Qt Builtin/System style options -no-*|-system-*|-qt-*) - VAR=`echo $1 | sed "s,^-[^-]*-\(.*\),\1,"` - VAL=`echo $1 | sed "s,^-\([^-]*\)-.*,\1,"` + VAR=`echo $1 | sed 's,^-[^-]*-\(.*\),\1,'` + VAL=`echo $1 | sed 's,^-\([^-]*\)-.*,\1,'` ;; #Options that cannot be generalized -k|-continue) @@ -947,7 +947,7 @@ while [ "$#" -gt 0 ]; do fi ;; -hostprefix) - VAR=`echo $1 | sed "s,^-\(.*\),\1,"` + VAR=`echo $1 | sed 's,^-\(.*\),\1,'` # this option may or may not be followed by an argument if [ -z "$2" ] || echo "$2" | grep '^-' >/dev/null 2>&1; then VAL=$outpath @@ -1037,7 +1037,7 @@ while [ "$#" -gt 0 ]; do ;; #General options, including Qt style yes options -*) - VAR=`echo $1 | sed "s,^-\(.*\),\1,"` + VAR=`echo $1 | sed 's,^-\(.*\),\1,'` VAL="yes" ;; *) @@ -1395,7 +1395,7 @@ while [ "$#" -gt 0 ]; do fi ;; feature-*) - FEATURE=`echo $VAR | sed "s,^[^-]*-\([^-]*\),\1," | tr 'abcdefghijklmnopqrstuvwxyz-' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ_'` + FEATURE=`echo $VAR | sed 's,^[^-]*-\([^-]*\),\1,' | tr 'abcdefghijklmnopqrstuvwxyz-' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ_'` if [ "$VAL" = "no" ]; then QCONFIG_FLAGS="$QCONFIG_FLAGS QT_NO_$FEATURE" elif [ "$VAL" = "yes" ] || [ "$VAL" = "unknown" ]; then @@ -1907,8 +1907,8 @@ while [ "$#" -gt 0 ]; do fi # now $VAL is "no", "qt", or "plugin" OPT="$VAL" - VAL=`echo $VAR | sed "s,^[^-]*-\([^-]*\).*,\1,"` - VAR=`echo $VAR | sed "s,^\([^-]*\).*,\1,"` + VAL=`echo $VAR | sed 's,^[^-]*-\([^-]*\).*,\1,'` + VAR=`echo $VAR | sed 's,^\([^-]*\).*,\1,'` # Grab the available values case "$VAR" in @@ -1974,7 +1974,7 @@ while [ "$#" -gt 0 ]; do fi elif [ "$VAL" = "no" ]; then if [ "$OPT_VERBOSE" = "$VAL" ] && echo "$QMAKE_SWITCHES" | grep ' -d' >/dev/null 2>&1; then - QMAKE_SWITCHES=`echo $QMAKE_SWITCHES | sed "s, -d,,"` + QMAKE_SWITCHES=`echo $QMAKE_SWITCHES | sed 's, -d,,'` else OPT_VERBOSE=no fi @@ -3044,7 +3044,7 @@ elif [ "$Edition" = "Preview" ]; then done elif [ "$Edition" != "OpenSource" ]; then if [ -n "$ExpiryDate" ]; then - ExpiryDate=`echo $ExpiryDate | sed -e "s,-,,g" | tr -d "\n\r"` + ExpiryDate=`echo $ExpiryDate | sed -e 's,-,,g' | tr -d '\n\r'` [ -z "$ExpiryDate" ] && ExpiryDate="0" Today=`date +%Y%m%d` if [ "$Today" -gt "$ExpiryDate" ]; then @@ -3508,7 +3508,7 @@ function normalize(dir) { do { odir = dir - gsub(/\/[^\/]+\/\.\./, "", dir) + sub(/\/[^\/]+\/\.\./, "", dir) } while (dir != odir); do { odir = dir @@ -3564,7 +3564,7 @@ if [ -z "$CFG_BUILD_PARTS" ]; then # don't build tools by default when cross-compiling if [ "$PLATFORM" != "$XPLATFORM" ]; then - CFG_BUILD_PARTS=`echo "$CFG_BUILD_PARTS" | sed "s, tools,,g"` + CFG_BUILD_PARTS=`echo "$CFG_BUILD_PARTS" | sed 's, tools,,g'` fi fi for nobuild in $CFG_NOBUILD_PARTS; do @@ -4015,7 +4015,7 @@ if true; then ###[ '!' -f "$outpath/bin/qmake" ]; if "$WHICH" makedepend >/dev/null 2>&1 && grep 'depend:' "$mkfile" >/dev/null 2>&1; then (cd "$outpath/qmake" && "$MAKE" -f "$mkfile" depend) >/dev/null 2>&1 - sed "s,^.*/\([^/]*.o\):,\1:,g" "$mkfile" >"$mkfile.tmp" + sed 's,^.*/\([^/]*.o\):,\1:,g' "$mkfile" >"$mkfile.tmp" sed "s,$outpath,$adjoutpath,g" "$mkfile.tmp" >"$mkfile" rm "$mkfile.tmp" fi @@ -5120,6 +5120,42 @@ if compileTest x11/xlib "XLib"; then QT_CONFIG="$QT_CONFIG xlib" fi +# auto-detect Xrender support +if [ "$CFG_XRENDER" != "no" ]; then + if compileTest x11/xrender "Xrender"; then + CFG_XRENDER=yes + QT_CONFIG="$QT_CONFIG xrender" + else + if [ "$CFG_XRENDER" = "yes" ] && [ "$CFG_CONFIGURE_EXIT_ON_ERROR" = "yes" ]; then + echo "Xrender support cannot be enabled due to functionality tests!" + echo " Turn on verbose messaging (-v) to $0 to see the final report." + echo " If you believe this message is in error you may use the continue" + echo " switch (-continue) to $0 to continue." + exit 101 + else + CFG_XRENDER=no + fi + fi +fi + +# auto-detect XInput2 support +if [ "$CFG_XINPUT2" != "no" ]; then + if compileTest x11/xinput2 "XInput2"; then + CFG_XINPUT2=yes + CFG_XINPUT=no + else + if [ "$CFG_XINPUT2" = "yes" ] && [ "$CFG_CONFIGURE_EXIT_ON_ERROR" = "yes" ]; then + echo "XInput2 support cannot be enabled due to functionality tests!" + echo " Turn on verbose messaging (-v) to $0 to see the final report." + echo " If you believe this message is in error you may use the continue" + echo " switch (-continue) to $0 to continue." + exit 101 + else + CFG_XINPUT2=no + fi + fi +fi + if [ "$CFG_XCB" != "no" ]; then if [ -n "$PKG_CONFIG" ] && $PKG_CONFIG --exists "xcb >= 1.5" 2>/dev/null; then QMAKE_CFLAGS_XCB="`$PKG_CONFIG --cflags xcb 2>/dev/null`" @@ -5179,42 +5215,6 @@ if [ "$CFG_XCB" != "no" ]; then QT_CONFIG="$QT_CONFIG xcb-sm" fi fi - - # auto-detect Xrender support - if [ "$CFG_XRENDER" != "no" ]; then - if compileTest x11/xrender "Xrender"; then - CFG_XRENDER=yes - QT_CONFIG="$QT_CONFIG xrender" - else - if [ "$CFG_XRENDER" = "yes" ] && [ "$CFG_CONFIGURE_EXIT_ON_ERROR" = "yes" ]; then - echo "Xrender support cannot be enabled due to functionality tests!" - echo " Turn on verbose messaging (-v) to $0 to see the final report." - echo " If you believe this message is in error you may use the continue" - echo " switch (-continue) to $0 to continue." - exit 101 - else - CFG_XRENDER=no - fi - fi - fi - - # auto-detect XInput2 support. Needed by xcb too. - if [ "$CFG_XINPUT2" != "no" ]; then - if compileTest x11/xinput2 "XInput2"; then - CFG_XINPUT2=yes - CFG_XINPUT=no - else - if [ "$CFG_XINPUT2" = "yes" ] && [ "$CFG_CONFIGURE_EXIT_ON_ERROR" = "yes" ]; then - echo "XInput2 support cannot be enabled due to functionality tests!" - echo " Turn on verbose messaging (-v) to $0 to see the final report." - echo " If you believe this message is in error you may use the continue" - echo " switch (-continue) to $0 to continue." - exit 101 - else - CFG_XINPUT2=no - fi - fi - fi else if [ "$CFG_XCB" != "auto" ]; then echo "The test for linking against libxcb failed!" @@ -6322,10 +6322,10 @@ EOF cfgdNeg= if [ true ] && echo "$cfgd" | grep 'QT_NO_' >/dev/null 2>&1; then # QT_NO_option can be forcefully turned on by QT_option - cfgdNeg=`echo $cfgd | sed "s,QT_NO_,QT_,"` + cfgdNeg=`echo $cfgd | sed 's,QT_NO_,QT_,'` elif [ true ] && echo "$cfgd" | grep 'QT_' >/dev/null 2>&1; then # QT_option can be forcefully turned off by QT_NO_option - cfgdNeg=`echo $cfgd | sed "s,QT_,QT_NO_,"` + cfgdNeg=`echo $cfgd | sed 's,QT_,QT_NO_,'` fi if [ -z $cfgdNeg ]; then diff --git a/dist/changes-5.2.1 b/dist/changes-5.2.1 new file mode 100644 index 0000000000..7762952b26 --- /dev/null +++ b/dist/changes-5.2.1 @@ -0,0 +1,164 @@ +Qt 5.2.1 is a bug-fix release. It maintains both forward and backward +compatibility (source and binary) with Qt 5.2.0. + +For more details, refer to the online documentation included in this +distribution. The documentation is also available online: + + http://qt-project.org/doc/qt-5.2 + +The Qt version 5.2 series is binary compatible with the 5.1.x series. +Applications compiled for 5.1 will continue to run with 5.2. + +Some of the changes listed in this file include issue tracking numbers +corresponding to tasks in the Qt Bug Tracker: + + http://bugreports.qt-project.org/ + +Each of these identifiers can be entered in the bug tracker to obtain more +information about a particular change. + +**************************************************************************** +* Important Behavior Changes * +**************************************************************************** + + - [QTBUG-34345][QTBUG-26008][QTBUG-26430] QPrinter no longer allows you to + set an invalid printer name. + - [QTBUG-34141] Parsing of Qt::ISODate by QDate::fromString() and + QDateTime()::fromString() is not as lenient as before, the date + component separators are now required to be non-numeric. This means a + string like "2000901901" will no longer be recognized as a valid ISO + Date, but "2000/01/01" will still be even though it doesn't strictly + meet the ISO format of "2000-01-01". + +**************************************************************************** +* Library * +**************************************************************************** + +QtCore +------ + + - [QTBUG-35069] Fixed a bug that caused negative number input using '-' to + be rejected because the current locale uses U+2212. QLocale::toString() + as well as QIntValidator and QDoubleValidator now accept both '-' and + U+2212, as well as the locale minus sign. QString also accepts '-' and + U+2212. + - Fixed sign conversion warnings in code using QMetaTypeId. + + - QTemporaryDir: + * Fixed a bug in QTemporaryDir name generator that dramatically reduced + randomness of the name. + + - QThread: + * [QTBUG-34840] Fixed handle leaks on Windows. + +QtGui +----- + + - [QTBUG-35421] Fixed crash when sending accessibility updates when the + corresponding widget does not have a corresponding QAccessibleInterface. + This showed on Mac for example with QStatusBar. + - Qt's generic font database now adds OpenType fonts (.otf). + + - Accessibility + * On Linux action names were returned as empty strings in AT-SPI + getActions, now returns the proper names. + + - QKeySequence: + * [QTBUG-24406] return Qt::Key_unknown with invalid modifiers on OS X + + - Text: + * [QTBUG-35740] Fixed regression when shaping some strings containing + characters from multiple fonts. + +QtPrintSupport +-------------- + + - [QTBUG-34700][QTBUG-35500] Fixed bugs that caused QtPrintSupport + not to report the correct the paper sizes on Windows and on OS X. + +QtSql +----- + + - IBase support: + * [QTBUG-33345] Custom port numbers are now supported. + * [QTBUG-13435] Fixed the internal state of IBase driver after a failed + open call. + + - MySQL / MariaDB support: + * [QTBUG-31124] Fixed handling of fractions of second. + + - Oracle support: + * [QTBUG-34794] Fixed the compilation + + - Sqlite support: + * [QTBUG-24200] Fixed handling of fractions of second. + * [QTBUG-35186] Fixed evaluation of driver options + +QtTestLib +--------- + + - [QTBUG-34630] The (default) plain text logger on Windows now logs to + either the system debug log (in case no console is open), or stdout, not + both. + +QtWidgets +--------- + + - QSpinBox: + * [QTBUG-20691] Entering positive values with the '+' prefix is now + allowed. + +**************************************************************************** +* Platform Specific Changes * +**************************************************************************** + +Android +------- + + - [QTBUG-34984] Added workarounds for OpenGL bugs on Samsung Galaxy + Tab 3. + +OS X +---- + + - [QTBUG-34411] Implemented QMainWindow::setUnifiedTitleAndToolBarOnMac. + +X11 / XCB +--------- + +- [QTBUG-32683] Fixed a bug that caused Qt applications to think the + screen DPI had changed when it had not, after connecting or + disconnecting monitors. + +Windows +------- + + - [QTBUG-8361] Maximizing frameless windows will no longer cover the + taskbar + - [QTBUG-34799] Updated QWidgetBackingStore and the Windows + implementation to support Qt::WA_StaticContents. + - [QTBUG-35357] Fixed a regression from Qt4 in QProcess that + prevented altering the pipe modes of stdin in the child process. + + +**************************************************************************** +* Tools * +**************************************************************************** + +configure & build system +------------------------ + + - [QTBUG-34949] EGL works with desktop OpenGL now + - A build from source will not install the Qt DLLs into lib/ any more. + The canonical location is bin/. + +qmake +----- + + - [QTBUG-35530] Fixed the detection of multiple VS installations. + - [QTBUG-35610] Fixed the generation of VS 2010 project files. + - [QTBUG-32412] Numerous fixes to Windows PDB file handling. + - [QTBUG-3883] Fixed make distclean not removing static library targets. + - Added makespec for clang using libc++ on Linux. + - qmake will not look for mkspecs/ directories in project trees any more. + Use .qmake.conf and/or .qmake.cache to "anchor" project roots. diff --git a/doc/global/manifest-meta.qdocconf b/doc/global/manifest-meta.qdocconf index fb0f5c200b..516e810c21 100644 --- a/doc/global/manifest-meta.qdocconf +++ b/doc/global/manifest-meta.qdocconf @@ -77,12 +77,9 @@ manifestmeta.android.names = "QtQuick/Qt Quick Demo - Maroon*" \ "QtWidgets/Stickman Example" \ "QtWidgets/Move Blocks Example" \ "QtWidgets/Border Layout Example" \ - "QtWidgets/Dynamic Layouts Example" \ "QtWidgets/Flow Layout Example" \ - "QtWidgets/MDI Example" \ "QtWidgets/Dock Widgets Example" \ "QtWidgets/Recent Files Example" \ - "QtWidgets/Menus Example" \ "QtWidgets/Concentric Circles Example" \ "QtWidgets/Gradients" \ "QtWidgets/Font Sampler Example" \ @@ -90,38 +87,23 @@ manifestmeta.android.names = "QtQuick/Qt Quick Demo - Maroon*" \ "QtWidgets/Transformations Example" \ "QtWidgets/Syntax Highlighter Example" \ "QtWidgets/Calendar Example" \ - "QtWidgets/Movie Example" \ - "QtWidgets/Validators Example" \ "QtWidgets/Analog Clock Example" \ "QtWidgets/Calculator Example" \ "QtWidgets/Mouse Button Tester" \ "QtWidgets/Character Map Example" \ - "QtWidgets/Wiggly Example" \ "QtWidgets/Digital Clock Example" \ "QtWidgets/Elided Label Example" \ - "QtWidgets/Image Viewer Example" \ "QtWidgets/Sliders Example" \ "QtWidgets/Tetrix Example" \ "QtWidgets/Group Box Example" \ - "QtWidgets/Spin Boxes Example" \ "QtWidgets/Undo Framework" \ - "QtWidgets/Regular Expressions Example" \ "QtWidgets/Colliding Mice Example" \ - "QtWidgets/Basic Graphics Layouts Example" \ - "QtWidgets/40000 Chips" \ "QtWidgets/Diagram Scene Example" \ - "QtWidgets/Drag and Drop Robot Example" \ "QtWidgets/Elastic Nodes Example" \ - "QtWidgets/Pad Navigator Example" \ - "QtWidgets/Anchor Layout Example" \ "QtWidgets/Weather Anchor Layout Example" \ - "QtConcurrent/Image Scaling Example" \ - "QtConcurrent/QtConcurrent Progress Dialog Example" \ "QtNetwork/Torrent Example" \ "QtNetwork/Network Chat Example" \ "QtSQL/Master Detail Example" \ - "QtOpenGL/Cube OpenGL ES 2.0 example" \ - "QtOpenGL/Textures Example" \ "QtLinguist/Arrow Pad Example" \ "QtGui/Raster Window Example" \ "QtGui/Analog Clock Window Example" \ @@ -129,12 +111,16 @@ manifestmeta.android.names = "QtQuick/Qt Quick Demo - Maroon*" \ "QtMultimedia/QML Video Shader Effects Example" \ "QtMultimedia/QML Video Example" \ "QtMultimedia/QML Camera Example" \ - "QtMultimedia/Audio Output Example" \ "QtSVG/Text Object Example" \ "QtQML/Qt Quick Examples - XMLHttpRequest" \ "QtQuick/Qt Quick Particles Examples - *" \ "QtQuick/Qt Quick Examples - Touch Interaction" \ - "QtQuick/Scene Graph - *" \ + "QtQuick/Scene Graph - Custom Geometry" \ + "QtQuick/Scene Graph - Graph" \ + "QtQuick/Scene Graph - OpenGL Under QML" \ + "QtQuick/Scene Graph - Painted Item" \ + "QtQuick/Scene Graph - Rendering FBOs" \ + "QtQuick/Scene Graph - Simple Material" \ "QtQuick/Qt Quick Examples - Image Elements" \ "QtQuick/Qt Quick Examples - Key Interaction" \ "QtQuick/Qt Quick Examples - Text" \ @@ -147,21 +133,15 @@ manifestmeta.android.names = "QtQuick/Qt Quick Demo - Maroon*" \ "QtWidgets/Interview" \ "QtWidgets/Spreadsheet" \ "QtWidgets/Pixelator Example" \ - "QtWidgets/Class Wizard Example" \ "QtWidgets/Animated Tiles Example" \ - "QtWidgets/Basic Layouts Example" \ - "QtWidgets/Application Example" \ "QtWidgets/Affine Transformations" \ "QtWidgets/Image Composition Example" \ "QtWidgets/Basic Drawing Example" \ "QtWidgets/Vector Deformation" \ "QtWidgets/Painter Paths Example" \ - "QtWidgets/Text Edit" \ "QtWidgets/Style Sheet Example" \ "QtWidgets/Code Editor Example" \ - "QtWidgets/Window Flags Example" \ "QtWidgets/Scribble Example" \ - "QtWidgets/Shaped Clock Example" \ "QtWidgets/Line Edits Example" \ "QtWidgets/Calendar Widget Example" \ "QtWidgets/Completer Example" \ @@ -169,8 +149,7 @@ manifestmeta.android.names = "QtQuick/Qt Quick Demo - Maroon*" \ "QtQML/Extending QML - Grouped Properties Example" \ "QtQML/Extending QML - Methods Example" \ "QtQML/Extending QML - Signal Support Example" \ - "QtQML/Extending QML - Attached Properties Example" \ - "QtWidgets/Address Book Example" + "QtQML/Extending QML - Attached Properties Example" manifestmeta.android.tags = android diff --git a/doc/global/qt-cpp-defines.qdocconf b/doc/global/qt-cpp-defines.qdocconf index 37fa5dbdcf..bbf1dda2e6 100644 --- a/doc/global/qt-cpp-defines.qdocconf +++ b/doc/global/qt-cpp-defines.qdocconf @@ -111,12 +111,6 @@ Cpp.ignoretokens += \ QT_FASTCALL \ QT_MUTEX_LOCK_NOEXCEPT \ QT_WIDGET_PLUGIN_EXPORT \ - QT_BEGIN_NAMESPACE_NFC \ - QT_END_NAMESPACE_NFC \ - QT_USE_NAMESPACE_NFC \ - QT_BEGIN_NAMESPACE_BLUETOOTH \ - QT_END_NAMESPACE_BLUETOOTH \ - QT_USE_NAMESPACE_BLUETOOTH \ QWEBKIT_EXPORT Cpp.ignoredirectives += \ diff --git a/doc/src/examples/imagegestures.qdoc b/examples/gestures/imagegestures/doc/src/imagegestures.qdoc index cb76ee83b1..cb76ee83b1 100644 --- a/doc/src/examples/imagegestures.qdoc +++ b/examples/gestures/imagegestures/doc/src/imagegestures.qdoc diff --git a/examples/widgets/doc/src/fademessage.qdoc b/examples/widgets/doc/src/fademessage.qdoc index 2a88c80ff2..d3c2494556 100644 --- a/examples/widgets/doc/src/fademessage.qdoc +++ b/examples/widgets/doc/src/fademessage.qdoc @@ -29,7 +29,7 @@ \example effects/fademessage \title Fade Message Effect Example \ingroup examples-graphicsview-graphicseffects - \brief Demonstrates how to appliy effects on items in the view + \brief Demonstrates how to apply effects on items in the view \div { style="text-align: left"} \inlineimage fademessageeffect-example.png diff --git a/examples/widgets/doc/src/plugandpaint.qdoc b/examples/widgets/doc/src/plugandpaint.qdoc index bfb763b7d1..5098d892ef 100644 --- a/examples/widgets/doc/src/plugandpaint.qdoc +++ b/examples/widgets/doc/src/plugandpaint.qdoc @@ -47,9 +47,9 @@ If you want to learn how to make your own application extensible through plugins, we recommend that you start by reading this overview, which explains how to make an application use plugins. - Afterward, you can read the + Afterwards, you can read the \l{tools/plugandpaintplugins/basictools}{Basic Tools} and - \l{plugandpaintplugins/extrafilters}{Extra Filters} + \l{tools/plugandpaintplugins/extrafilters}{Extra Filters} overviews, which show how to implement static and dynamic plugins, respectively. @@ -126,8 +126,8 @@ a good idea to include a version number in the string, as we did above. - The \l{plugandpaintplugins/basictools}{Basic Tools} plugin - and the \l{plugandpaintplugins/extrafilters}{Extra Filters} + The \l{tools/plugandpaintplugins/basictools}{Basic Tools} plugin + and the \l{tools/plugandpaintplugins/extrafilters}{Extra Filters} plugin shows how to derive from \c BrushInterface, \c ShapeInterface, and \c FilterInterface. @@ -275,7 +275,7 @@ \section1 Importing Static Plugins - The \l{plugandpaintplugins/basictools}{Basic Tools} plugin + The \l{tools/plugandpaintplugins/basictools}{Basic Tools} plugin is built as a static plugin, to ensure that it is always available to the application. This requires using the Q_IMPORT_PLUGIN() macro somewhere in the application (in a \c @@ -307,7 +307,7 @@ This completes our review of the Plug & Paint application. At this point, you might want to take a look at the - \l{plugandpaintplugins/basictools}{Basic Tools} example + \l{tools/plugandpaintplugins/basictools}{Basic Tools} example plugin. */ @@ -473,7 +473,7 @@ To make the plugin a static plugin, all that is required is to specify \c static in addition to \c plugin. The - \l{plugandpaintplugins/extrafilters}{Extra Filters} plugin, + \l{tools/plugandpaintplugins/extrafilters}{Extra Filters} plugin, which is compiled as a dynamic plugin, doesn't specify \c static in its \c .pro file. @@ -503,13 +503,13 @@ The Extra Filters example is a plugin for the \l{plugandpaint}{Plug & Paint} example. It provides a set of filters in addition to those provided by the - \l{plugandpaintplugins/basictools}{Basic Tools} plugin. + \l{tools/plugandpaintplugins/basictools}{Basic Tools} plugin. Since the approach is identical to - \l{plugandpaintplugins/basictools}{Basic Tools}, we won't + \l{tools/plugandpaintplugins/basictools}{Basic Tools}, we won't review the code here. The only part of interest is the \c .pro file, since Extra Filters is a dynamic plugin - (\l{plugandpaintplugins/basictools}{Basic Tools} is + (\l{tools/plugandpaintplugins/basictools}{Basic Tools} is linked statically into the Plug & Paint executable). Here's the project file for building the Extra Filters plugin: diff --git a/mkspecs/common/gcc-base-mac.conf b/mkspecs/common/gcc-base-mac.conf index e0469f31cc..cb1e17bc90 100644 --- a/mkspecs/common/gcc-base-mac.conf +++ b/mkspecs/common/gcc-base-mac.conf @@ -12,10 +12,6 @@ include(gcc-base.conf) QMAKE_COMPILER_DEFINES += __APPLE__ __GNUC__=4 -QMAKE_CFLAGS_DEBUG += -gdwarf-2 - -QMAKE_CXXFLAGS_DEBUG += -gdwarf-2 - QMAKE_OBJECTIVE_CFLAGS = $$QMAKE_CFLAGS QMAKE_OBJECTIVE_CFLAGS_WARN_ON = $$QMAKE_CFLAGS_WARN_ON QMAKE_OBJECTIVE_CFLAGS_WARN_OFF = $$QMAKE_CFLAGS_WARN_OFF diff --git a/mkspecs/devices/linux-imx6-g++/qeglfshooks_imx6.cpp b/mkspecs/devices/linux-imx6-g++/qeglfshooks_imx6.cpp index c351e3dbc4..91c29b5ea9 100644 --- a/mkspecs/devices/linux-imx6-g++/qeglfshooks_imx6.cpp +++ b/mkspecs/devices/linux-imx6-g++/qeglfshooks_imx6.cpp @@ -72,7 +72,7 @@ QEglFSImx6Hooks::QEglFSImx6Hooks() qputenv("FB_MULTI_BUFFER", "2"); } - mNativeDisplay = fbGetDisplayByIndex(0); + mNativeDisplay = fbGetDisplayByIndex(framebufferIndex()); fbGetDisplayGeometry(mNativeDisplay, &width, &height); mScreenSize.setHeight(height); mScreenSize.setWidth(width); diff --git a/mkspecs/features/android/android.prf b/mkspecs/features/android/android.prf index 5e21f0b845..9e86110da6 100644 --- a/mkspecs/features/android/android.prf +++ b/mkspecs/features/android/android.prf @@ -8,4 +8,7 @@ contains(TEMPLATE, ".*app") { INSTALLS *= target } } +} else: contains(TEMPLATE, "lib"):!QTDIR_build:android_install { + target.path = /libs/$$ANDROID_TARGET_ARCH/ + INSTALLS *= target } diff --git a/mkspecs/features/qt_example_installs.prf b/mkspecs/features/qt_example_installs.prf index 2db752c1e4..ff842ca754 100644 --- a/mkspecs/features/qt_example_installs.prf +++ b/mkspecs/features/qt_example_installs.prf @@ -97,6 +97,7 @@ probase = $$relative_path($$_PRO_FILE_PWD_, $$dirname(_QMAKE_CONF_)/examples) TEMPLATE = aux CONFIG -= have_target qt staticlib dll SOURCES = + OBJECTIVE_SOURCES = INSTALLS -= target } } diff --git a/mkspecs/features/qt_module.prf b/mkspecs/features/qt_module.prf index 11509eeb40..c6369732c1 100644 --- a/mkspecs/features/qt_module.prf +++ b/mkspecs/features/qt_module.prf @@ -119,6 +119,14 @@ DEFINES += QT_BUILDING_QT win32 { INCLUDEPATH += tmp CONFIG += skip_target_version_ext + # If the code is really "unsafe" then it is unsafe on + # other platforms as well; so fixing these warnings just + # for MSVC builds, would clutter the code and wouldn't help + # in fixing issues that might exist on other platforms. + # Using the same functions across all supported platforms + # keeps the code clean and helps in writing code that is + # safe across all platforms. + DEFINES *= _CRT_SECURE_NO_WARNINGS } aix-g++* { diff --git a/qmake/doc/qmake.qdocconf b/qmake/doc/qmake.qdocconf index a5bd089a5d..d8f970048c 100644 --- a/qmake/doc/qmake.qdocconf +++ b/qmake/doc/qmake.qdocconf @@ -65,7 +65,6 @@ depends += \ qtsvg \ qtsysteminfo \ qttestlib \ - qttools \ qtuitools \ qtversit \ qtwebkit \ diff --git a/qmake/generators/mac/pbuilder_pbx.cpp b/qmake/generators/mac/pbuilder_pbx.cpp index fa4a844a5d..da64c33cf2 100644 --- a/qmake/generators/mac/pbuilder_pbx.cpp +++ b/qmake/generators/mac/pbuilder_pbx.cpp @@ -795,7 +795,7 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t) mkt << "\\\n\t"; ++added; const QString file_name = fileFixify(fn, Option::output_dir, Option::output_dir); - mkt << " " << replaceExtraCompilerVariables(tmp_out.first().toQString(), file_name, QString()); + mkt << " " << replaceExtraCompilerVariables(Option::fixPathToTargetOS(tmp_out.first().toQString(), false), file_name, QString()); } } } diff --git a/qmake/generators/unix/unixmake2.cpp b/qmake/generators/unix/unixmake2.cpp index 7ed89e23d7..bc4c167744 100644 --- a/qmake/generators/unix/unixmake2.cpp +++ b/qmake/generators/unix/unixmake2.cpp @@ -722,11 +722,15 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) QString::fromLatin1("????") : project->first("QMAKE_PKGINFO_TYPEINFO").left(4)) << ",g\" "; if(project->first("TEMPLATE") == "app") { QString icon = fileFixify(var("ICON")); + QString bundleIdentifier = "com.yourcompany." + var("QMAKE_BUNDLE"); + if (bundleIdentifier.endsWith(".app")) + bundleIdentifier.chop(4); t << "@$(DEL_FILE) " << info_plist_out << "\n\t" << "@sed "; foreach (const ProString &arg, commonSedArgs) t << arg; t << "-e \"s,@ICON@," << icon.section(Option::dir_sep, -1) << ",g\" " + << "-e \"s,@BUNDLEIDENTIFIER@," << bundleIdentifier << ",g\" " << "-e \"s,@EXECUTABLE@," << var("QMAKE_ORIG_TARGET") << ",g\" " << "-e \"s,@TYPEINFO@,"<< (project->isEmpty("QMAKE_PKGINFO_TYPEINFO") ? QString::fromLatin1("????") : project->first("QMAKE_PKGINFO_TYPEINFO").left(4)) << ",g\" " diff --git a/qmake/generators/win32/msbuild_objectmodel.cpp b/qmake/generators/win32/msbuild_objectmodel.cpp index d1420e95f6..3ec70c1f58 100644 --- a/qmake/generators/win32/msbuild_objectmodel.cpp +++ b/qmake/generators/win32/msbuild_objectmodel.cpp @@ -910,13 +910,15 @@ static inline QString toString(compileAsManagedOptions option) return QString(); } -static inline QString toString(debugOption option) +static inline QString toString(debugOption option, DotNET compilerVersion) { switch (option) { case debugUnknown: case debugLineInfoOnly: break; case debugDisabled: + if (compilerVersion <= NET2010) + break; return "None"; case debugOldStyleInfo: return "OldStyle"; @@ -1401,7 +1403,8 @@ void VCXProjectWriter::write(XmlOutput &xml, const VCCLCompilerTool &tool) << attrTagS(_CompileAsManaged, toString(tool.CompileAsManaged)) << attrTagT(_CompileAsWinRT, tool.CompileAsWinRT) << attrTagT(_CreateHotpatchableImage, tool.CreateHotpatchableImage) - << attrTagS(_DebugInformationFormat, toString(tool.DebugInformationFormat)) + << attrTagS(_DebugInformationFormat, toString(tool.DebugInformationFormat, + tool.config->CompilerVersion)) << attrTagT(_DisableLanguageExtensions, tool.DisableLanguageExtensions) << attrTagX(_DisableSpecificWarnings, tool.DisableSpecificWarnings, ";") << attrTagS(_EnableEnhancedInstructionSet, toString(tool.EnableEnhancedInstructionSet)) diff --git a/qmake/library/qmakeevaluator.cpp b/qmake/library/qmakeevaluator.cpp index e17ac16e96..2ea5ffd45e 100644 --- a/qmake/library/qmakeevaluator.cpp +++ b/qmake/library/qmakeevaluator.cpp @@ -889,30 +889,9 @@ void QMakeEvaluator::visitProVariable( default: // whatever - cannot happen case TokAssign: // = zipEmpty(&varVal); - if (!m_cumulative) { - // FIXME: add check+warning about accidental value removal. - // This may be a bit too noisy, though. - m_valuemapStack.top()[varName] = varVal; - } else { - if (!varVal.isEmpty()) { - // We are greedy for values. But avoid exponential growth. - ProStringList &v = valuesRef(varName); - if (v.isEmpty()) { - v = varVal; - } else { - ProStringList old = v; - v = varVal; - QSet<ProString> has; - has.reserve(v.size()); - foreach (const ProString &s, v) - has.insert(s); - v.reserve(v.size() + old.size()); - foreach (const ProString &s, old) - if (!has.contains(s)) - v << s; - } - } - } + // FIXME: add check+warning about accidental value removal. + // This may be a bit too noisy, though. + m_valuemapStack.top()[varName] = varVal; debugMsg(2, "assigning"); break; case TokAppendUnique: // *= @@ -928,7 +907,7 @@ void QMakeEvaluator::visitProVariable( if (!m_cumulative) { removeEach(&valuesRef(varName), varVal); } else { - // We are stingy with our values, too. + // We are stingy with our values. } debugMsg(2, "removing"); break; @@ -1850,14 +1829,12 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateFile( VisitReturn ok = visitProFile(pro, type, flags); m_current = m_locationStack.pop(); pro->deref(); -#ifdef PROEVALUATOR_FULL if (ok == ReturnTrue && !(flags & LoadHidden)) { ProStringList &iif = m_valuemapStack.first()[ProKey("QMAKE_INTERNAL_INCLUDED_FILES")]; ProString ifn(fileName); if (!iif.contains(ifn)) iif << ifn; } -#endif return ok; } else { return ReturnFalse; @@ -1970,13 +1947,11 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateFileInto( if (ret != ReturnTrue) return ret; *values = visitor.m_valuemapStack.top(); -#ifdef PROEVALUATOR_FULL ProKey qiif("QMAKE_INTERNAL_INCLUDED_FILES"); ProStringList &iif = m_valuemapStack.first()[qiif]; foreach (const ProString &ifn, values->value(qiif)) if (!iif.contains(ifn)) iif << ifn; -#endif return ReturnTrue; } diff --git a/src/3rdparty/angle/src/libEGL/Display.cpp b/src/3rdparty/angle/src/libEGL/Display.cpp index a382c3b1eb..82b48cedcf 100644 --- a/src/3rdparty/angle/src/libEGL/Display.cpp +++ b/src/3rdparty/angle/src/libEGL/Display.cpp @@ -523,7 +523,7 @@ void Display::initVendorString() if (mRenderer && mRenderer->getLUID(&adapterLuid)) { char adapterLuidString[64]; - sprintf_s(adapterLuidString, sizeof(adapterLuidString), " (adapter LUID: %08x%08x)", adapterLuid.HighPart, adapterLuid.LowPart); + snprintf(adapterLuidString, sizeof(adapterLuidString), " (adapter LUID: %08l%08l)", adapterLuid.HighPart, adapterLuid.LowPart); mVendorString += adapterLuidString; } diff --git a/src/angle/patches/0001-Fix-compilation-of-ANGLE-with-mingw-tdm64-gcc-4.8.1.patch b/src/angle/patches/0001-Fix-compilation-of-ANGLE-with-mingw-tdm64-gcc-4.8.1.patch new file mode 100644 index 0000000000..498cce1b7c --- /dev/null +++ b/src/angle/patches/0001-Fix-compilation-of-ANGLE-with-mingw-tdm64-gcc-4.8.1.patch @@ -0,0 +1,33 @@ +From 58a797397378aff3aa039a8b2a2d7011fe788737 Mon Sep 17 00:00:00 2001 +From: Kai Koehne <kai.koehne@digia.com> +Date: Tue, 21 Jan 2014 10:23:38 +0100 +Subject: [PATCH] Fix compilation of ANGLE with mingw-tdm64 gcc 4.8.1 + +Do not rely on sprintf_s being declared/defined. This also fixes +deployment to Windows XP. + +See https://chromium-review.googlesource.com/#/c/182975/ for a similar +commit proposed upstream. + +Task-number: QTBUG-36242 +Change-Id: I520e2f61aeab34963e7a57baafd413c7db93f110 +--- + src/3rdparty/angle/src/libEGL/Display.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/3rdparty/angle/src/libEGL/Display.cpp b/src/3rdparty/angle/src/libEGL/Display.cpp +index a382c3b..82b48ce 100644 +--- a/src/3rdparty/angle/src/libEGL/Display.cpp ++++ b/src/3rdparty/angle/src/libEGL/Display.cpp +@@ -523,7 +523,7 @@ void Display::initVendorString() + if (mRenderer && mRenderer->getLUID(&adapterLuid)) + { + char adapterLuidString[64]; +- sprintf_s(adapterLuidString, sizeof(adapterLuidString), " (adapter LUID: %08x%08x)", adapterLuid.HighPart, adapterLuid.LowPart); ++ snprintf(adapterLuidString, sizeof(adapterLuidString), " (adapter LUID: %08l%08l)", adapterLuid.HighPart, adapterLuid.LowPart); + + mVendorString += adapterLuidString; + } +-- +1.8.5.2.msysgit.0 + diff --git a/src/corelib/animation/qabstractanimation_p.h b/src/corelib/animation/qabstractanimation_p.h index 322de22caf..39d9cf0fe6 100644 --- a/src/corelib/animation/qabstractanimation_p.h +++ b/src/corelib/animation/qabstractanimation_p.h @@ -46,8 +46,8 @@ // W A R N I N G // ------------- // -// This file is not part of the Qt API. It exists for the convenience -// of QIODevice. This header file may change from version to +// This file is not part of the Qt API. +// This header file may change from version to // version without notice, or even be removed. // // We mean it. diff --git a/src/corelib/global/qcompilerdetection.h b/src/corelib/global/qcompilerdetection.h index 44077132d4..d526d40398 100644 --- a/src/corelib/global/qcompilerdetection.h +++ b/src/corelib/global/qcompilerdetection.h @@ -251,7 +251,7 @@ # if defined(__EDG__) # define Q_CC_EDG # endif -/* Compaq have disabled EDG's _BOOL macro and use _BOOL_EXISTS instead +/* Compaq has disabled EDG's _BOOL macro and uses _BOOL_EXISTS instead - observed on Compaq C++ V6.3-002. In any case versions prior to Compaq C++ V6.0-005 do not have bool. */ # if !defined(_BOOL_EXISTS) @@ -722,13 +722,13 @@ # define Q_COMPILER_DECLTYPE # define Q_COMPILER_RVALUE_REFS # define Q_COMPILER_STATIC_ASSERT -// MSVC's library has std::initilizer_list, but the compiler does not support the braces initialization +// MSVC's library has std::initializer_list, but the compiler does not support the braces initialization //# define Q_COMPILER_INITIALIZER_LISTS //# define Q_COMPILER_UNIFORM_INIT # endif # if _MSC_VER >= 1700 /* C++11 features supported in VC11 = VC2012: */ -# undef Q_DECL_OVERRIDE /* undo 2005/2098 settings... */ +# undef Q_DECL_OVERRIDE /* undo 2005/2008 settings... */ # undef Q_DECL_FINAL /* undo 2005/2008 settings... */ # define Q_COMPILER_EXPLICIT_OVERRIDES /* ...and use std C++11 now */ # define Q_COMPILER_RANGE_FOR diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index d8c987d2e0..30db4e75cf 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -45,11 +45,11 @@ #include <stddef.h> -#define QT_VERSION_STR "5.2.1" +#define QT_VERSION_STR "5.2.2" /* QT_VERSION is (major << 16) + (minor << 8) + patch. */ -#define QT_VERSION 0x050201 +#define QT_VERSION 0x050202 /* can be used like #if (QT_VERSION >= QT_VERSION_CHECK(4, 4, 0)) */ @@ -826,9 +826,13 @@ Q_CORE_EXPORT void qFreeAligned(void *ptr); # pragma warning(disable: 4800) /* 'type' : forcing value to bool 'true' or 'false' (performance warning) */ # pragma warning(disable: 4097) /* typedef-name 'identifier1' used as synonym for class-name 'identifier2' */ # pragma warning(disable: 4706) /* assignment within conditional expression */ -# pragma warning(disable: 4786) /* 'identifier' : identifier was truncated to 'number' characters in the debug information */ +# if _MSC_VER <= 1310 // MSVC 2003 +# pragma warning(disable: 4786) /* 'identifier' : identifier was truncated to 'number' characters in the debug information */ +# endif # pragma warning(disable: 4355) /* 'this' : used in base member initializer list */ -# pragma warning(disable: 4231) /* nonstandard extension used : 'identifier' before template explicit instantiation */ +# if _MSC_VER < 1800 // MSVC 2013 +# pragma warning(disable: 4231) /* nonstandard extension used : 'identifier' before template explicit instantiation */ +# endif # pragma warning(disable: 4710) /* function not inlined */ # pragma warning(disable: 4530) /* C++ exception handler used, but unwind semantics are not enabled. Specify /EHsc */ # elif defined(Q_CC_BOR) diff --git a/src/corelib/io/io.pri b/src/corelib/io/io.pri index f06bf61b09..649493f8b7 100644 --- a/src/corelib/io/io.pri +++ b/src/corelib/io/io.pri @@ -142,6 +142,8 @@ win32 { } } else:blackberry { SOURCES += io/qstandardpaths_blackberry.cpp + } else:android { + SOURCES += io/qstandardpaths_android.cpp } else { SOURCES += io/qstandardpaths_unix.cpp } diff --git a/src/corelib/io/qdir.cpp b/src/corelib/io/qdir.cpp index 43db2ec1fe..b704126efa 100644 --- a/src/corelib/io/qdir.cpp +++ b/src/corelib/io/qdir.cpp @@ -716,11 +716,12 @@ QString QDir::absoluteFilePath(const QString &fileName) const return fileName; d->resolveAbsoluteEntry(); + const QString absoluteDirPath = d->absoluteDirEntry.filePath(); if (fileName.isEmpty()) - return d->absoluteDirEntry.filePath(); - if (!d->absoluteDirEntry.isRoot()) - return d->absoluteDirEntry.filePath() % QLatin1Char('/') % fileName; - return d->absoluteDirEntry.filePath() % fileName; + return absoluteDirPath; + if (!absoluteDirPath.endsWith(QLatin1Char('/'))) + return absoluteDirPath % QLatin1Char('/') % fileName; + return absoluteDirPath % fileName; } /*! @@ -855,7 +856,7 @@ QString QDir::fromNativeSeparators(const QString &pathName) /*! Changes the QDir's directory to \a dirName. - Returns \c true if the new directory exists and is readable; + Returns \c true if the new directory exists; otherwise returns \c false. Note that the logical cd() operation is not performed if the new directory does not exist. @@ -923,7 +924,7 @@ bool QDir::cd(const QString &dirName) Changes directory by moving one directory up from the QDir's current directory. - Returns \c true if the new directory exists and is readable; + Returns \c true if the new directory exists; otherwise returns \c false. Note that the logical cdUp() operation is not performed if the new directory does not exist. diff --git a/src/corelib/io/qiodevice.cpp b/src/corelib/io/qiodevice.cpp index a81b8580c4..53019e1ff4 100644 --- a/src/corelib/io/qiodevice.cpp +++ b/src/corelib/io/qiodevice.cpp @@ -259,9 +259,10 @@ QIODevicePrivate::~QIODevicePrivate() \value NotOpen The device is not open. \value ReadOnly The device is open for reading. - \value WriteOnly The device is open for writing. + \value WriteOnly The device is open for writing. Note that this mode implies + Truncate. \value ReadWrite The device is open for reading and writing. - \value Append The device is opened in append mode, so that all data is + \value Append The device is opened in append mode so that all data is written to the end of the file. \value Truncate If possible, the device is truncated before it is opened. All earlier contents of the device are lost. diff --git a/src/corelib/io/qstandardpaths_android.cpp b/src/corelib/io/qstandardpaths_android.cpp new file mode 100644 index 0000000000..60b285a3d6 --- /dev/null +++ b/src/corelib/io/qstandardpaths_android.cpp @@ -0,0 +1,331 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qstandardpaths.h" + +#ifndef QT_NO_STANDARDPATHS + +#include <QtCore/private/qjni_p.h> +#include <QtCore/private/qjnihelpers_p.h> +#include <QtCore/qmap.h> +#include <QDir> + +QT_BEGIN_NAMESPACE + +typedef QMap<QString, QString> AndroidDirCache; +Q_GLOBAL_STATIC(AndroidDirCache, androidDirCache) + +static QString testDir() +{ + return QStandardPaths::isTestModeEnabled() ? QLatin1String("/qttest") + : QLatin1String(""); +} + +static QJNIObjectPrivate applicationContext() +{ + static QJNIObjectPrivate appCtx; + if (appCtx.isValid()) + return appCtx; + + QJNIObjectPrivate activity = QtAndroidPrivate::activity(); + if (!activity.isValid()) + return appCtx; + + appCtx = activity.callObjectMethod("getApplicationContext", + "()Landroid/content/Context;"); + return appCtx; +} + +static inline QString getAbsolutePath(const QJNIObjectPrivate &file) +{ + QJNIObjectPrivate path = file.callObjectMethod("getAbsolutePath", + "()Ljava/lang/String;"); + if (!path.isValid()) + return QString(); + + return path.toString(); +} + +/* + * The root of the external storage + * + */ +static QString getExternalStorageDirectory() +{ + QString &path = (*androidDirCache)[QStringLiteral("EXT_ROOT")]; + if (!path.isEmpty()) + return path; + + QJNIObjectPrivate file = QJNIObjectPrivate::callStaticObjectMethod("android/os/Environment", + "getExternalStorageDirectory", + "()Ljava/io/File;"); + if (!file.isValid()) + return QString(); + + return (path = getAbsolutePath(file)); +} + +/* + * Locations where applications can place user files (public). + * E.g., /storage/Music + */ +static QString getExternalStoragePublicDirectory(const char *directoryField) +{ + QString &path = (*androidDirCache)[QLatin1String(directoryField)]; + if (!path.isEmpty()) + return path; + + QJNIObjectPrivate dirField = QJNIObjectPrivate::getStaticObjectField("android/os/Environment", + directoryField, + "Ljava/lang/String;"); + if (!dirField.isValid()) + return QString(); + + QJNIObjectPrivate file = QJNIObjectPrivate::callStaticObjectMethod("android/os/Environment", + "getExternalStoragePublicDirectory", + "(Ljava/lang/String;)Ljava/io/File;", + dirField.object()); + if (!file.isValid()) + return QString(); + + return (path = getAbsolutePath(file)); +} + +/* + * Locations where applications can place persistent files it owns. + * E.g., /storage/org.app/Music + */ +static QString getExternalFilesDir(const char *directoryField = 0) +{ + QString &path = (*androidDirCache)[QString(QLatin1String("APPNAME_%1")).arg(QLatin1String(directoryField))]; + if (!path.isEmpty()) + return path; + + QJNIObjectPrivate activity = QtAndroidPrivate::activity(); + if (!activity.isValid()) + return QString(); + + QJNIObjectPrivate appCtx = applicationContext(); + if (!appCtx.isValid()) + return QString(); + + QJNIObjectPrivate dirField = QJNIObjectPrivate::fromString(QLatin1String("")); + if (directoryField) { + dirField = QJNIObjectPrivate::getStaticObjectField("android/os/Environment", + directoryField, + "Ljava/lang/String;"); + if (!dirField.isValid()) + return QString(); + } + + QJNIObjectPrivate file = appCtx.callObjectMethod("getExternalFilesDir", + "(Ljava/lang/String;)Ljava/io/File;", + dirField.object()); + + if (!file.isValid()) + return QString(); + + return (path = getAbsolutePath(file)); +} + +/* + * Directory where applications can store cache files it owns (public). + * E.g., /storage/org.app/ + */ +static QString getExternalCacheDir() +{ + QString &path = (*androidDirCache)[QStringLiteral("APPNAME_CACHE")]; + if (!path.isEmpty()) + return path; + + QJNIObjectPrivate appCtx = applicationContext(); + if (!appCtx.isValid()) + return QString(); + + QJNIObjectPrivate file = appCtx.callObjectMethod("getExternalCacheDir", + "()Ljava/io/File;"); + + if (!file.isValid()) + return QString(); + + return (path = getAbsolutePath(file)); +} + +/* + * Directory where applications can store cache files it owns (private). + */ +static QString getCacheDir() +{ + QString &path = (*androidDirCache)[QStringLiteral("APPROOT_CACHE")]; + if (!path.isEmpty()) + return path; + + QJNIObjectPrivate appCtx = applicationContext(); + if (!appCtx.isValid()) + return QString(); + + QJNIObjectPrivate file = appCtx.callObjectMethod("getCacheDir", + "()Ljava/io/File;"); + if (!file.isValid()) + return QString(); + + return (path = getAbsolutePath(file)); +} + +/* + * Directory where applications can store files it owns (private). + * (Same location as $HOME) + */ +static QString getFilesDir() +{ + QString &path = (*androidDirCache)[QStringLiteral("APPROOT_FILES")]; + if (!path.isEmpty()) + return path; + + return (path = QDir::homePath()); +} + +QString QStandardPaths::writableLocation(StandardLocation type) +{ + switch (type) { + case QStandardPaths::MusicLocation: + return getExternalStoragePublicDirectory("DIRECTORY_MUSIC"); + case QStandardPaths::MoviesLocation: + return getExternalStoragePublicDirectory("DIRECTORY_MOVIES"); + case QStandardPaths::PicturesLocation: + return getExternalStoragePublicDirectory("DIRECTORY_PICTURES"); + case QStandardPaths::DocumentsLocation: + if (QtAndroidPrivate::androidSdkVersion() > 18) + return getExternalStoragePublicDirectory("DIRECTORY_DOCUMENTS"); + else + return getExternalStorageDirectory() + QLatin1String("/Documents"); + case QStandardPaths::DownloadLocation: + return getExternalStoragePublicDirectory("DIRECTORY_DOWNLOADS"); + case QStandardPaths::GenericConfigLocation: + case QStandardPaths::ConfigLocation: + return getFilesDir() + testDir() + QLatin1String("/settings"); + case QStandardPaths::GenericDataLocation: + return getExternalStorageDirectory() + testDir(); + case QStandardPaths::DataLocation: + return getFilesDir() + testDir(); + case QStandardPaths::GenericCacheLocation: + case QStandardPaths::RuntimeLocation: + case QStandardPaths::TempLocation: + case QStandardPaths::CacheLocation: + return getCacheDir() + testDir(); + case QStandardPaths::DesktopLocation: + case QStandardPaths::HomeLocation: + return getFilesDir(); + case QStandardPaths::ApplicationsLocation: + case QStandardPaths::FontsLocation: + default: + break; + } + + return QString(); +} + +QStringList QStandardPaths::standardLocations(StandardLocation type) +{ + if (type == MusicLocation) { + return QStringList() << writableLocation(type) + << getExternalFilesDir("DIRECTORY_MUSIC") + << getExternalStoragePublicDirectory("DIRECTORY_PODCASTS") + << getExternalFilesDir("DIRECTORY_PODCASTS") + << getExternalStoragePublicDirectory("DIRECTORY_NOTIFICATIONS") + << getExternalFilesDir("DIRECTORY_NOTIFICATIONS") + << getExternalStoragePublicDirectory("DIRECTORY_ALARMS") + << getExternalFilesDir("DIRECTORY_ALARMS"); + } + + if (type == MoviesLocation) { + return QStringList() << writableLocation(type) + << getExternalFilesDir("DIRECTORY_MOVIES"); + } + + if (type == PicturesLocation) { + return QStringList() << writableLocation(type) + << getExternalFilesDir("DIRECTORY_PICTURES"); + } + + if (type == DocumentsLocation) { + if (QtAndroidPrivate::androidSdkVersion() > 18) { + return QStringList() << writableLocation(type) + << getExternalFilesDir("DIRECTORY_DOCUMENTS"); + } else { + return QStringList() << writableLocation(type) + << getExternalFilesDir() + QLatin1String("/Documents"); + } + } + + if (type == DownloadLocation) { + return QStringList() << writableLocation(type) + << getExternalFilesDir("DIRECTORY_DOWNLOADS"); + } + + if (type == DataLocation) { + return QStringList() << writableLocation(type) + << getExternalFilesDir(); + } + + if (type == CacheLocation) { + return QStringList() << writableLocation(type) + << getExternalCacheDir(); + } + + if (type == FontsLocation) { + QString &fontLocation = (*androidDirCache)[QStringLiteral("FONT_LOCATION")]; + if (!fontLocation.isEmpty()) + return QStringList(fontLocation); + + const QByteArray ba = qgetenv("QT_ANDROID_FONT_LOCATION"); + if (!ba.isEmpty()) + return QStringList((fontLocation = QDir::cleanPath(QString::fromLocal8Bit(ba)))); + + return QStringList((fontLocation = QLatin1String("/system/fonts"))); + } + + return QStringList(writableLocation(type)); +} + +QT_END_NAMESPACE + +#endif // QT_NO_STANDARDPATHS diff --git a/src/corelib/io/qurl.cpp b/src/corelib/io/qurl.cpp index 77aa3c4821..eac5a0b738 100644 --- a/src/corelib/io/qurl.cpp +++ b/src/corelib/io/qurl.cpp @@ -3437,7 +3437,7 @@ QString QUrl::fromAce(const QByteArray &domain) (like \c "example.com") to be written using international characters. - This function return an empty QByteArra if \a domain is not a valid + This function returns an empty QByteArray if \a domain is not a valid hostname. Note, in particular, that IPv6 literals are not valid domain names. */ diff --git a/src/corelib/itemmodels/qabstractitemmodel.cpp b/src/corelib/itemmodels/qabstractitemmodel.cpp index ab257a996d..4241fe08ca 100644 --- a/src/corelib/itemmodels/qabstractitemmodel.cpp +++ b/src/corelib/itemmodels/qabstractitemmodel.cpp @@ -2334,6 +2334,31 @@ void QAbstractItemModel::doSetRoleNames(const QHash<int,QByteArray> &roleNames) Returns the model's role names. + The default role names set by Qt are: + + \table + \header + \li Qt Role + \li QML Role Name + \row + \li Qt::DisplayRole + \li display + \row + \li Qt::DecorationRole + \li decoration + \row + \li Qt::EditRole + \li edit + \row + \li Qt::ToolTipRole + \li toolTip + \row + \li Qt::StatusTipRole + \li statusTip + \row + \li Qt::WhatsThisRole + \li whatsThis + \endtable */ QHash<int,QByteArray> QAbstractItemModel::roleNames() const { @@ -3378,6 +3403,9 @@ Qt::ItemFlags QAbstractTableModel::flags(const QModelIndex &index) const of the rowCount() and data() functions. Well behaved models also provide a headerData() implementation. + If your model is used within QML and requires roles other than the + default ones provided by the roleNames() function, you must override it. + For editable list models, you must also provide an implementation of setData(), implement the flags() function so that it returns a value containing \l{Qt::ItemFlags}{Qt::ItemIsEditable}. diff --git a/src/corelib/kernel/qjnihelpers.cpp b/src/corelib/kernel/qjnihelpers.cpp index 9ec491f6a9..74eb6f5b27 100644 --- a/src/corelib/kernel/qjnihelpers.cpp +++ b/src/corelib/kernel/qjnihelpers.cpp @@ -46,6 +46,7 @@ QT_BEGIN_NAMESPACE static JavaVM *g_javaVM = Q_NULLPTR; static jobject g_jActivity = Q_NULLPTR; static jobject g_jClassLoader = Q_NULLPTR; +static jint g_androidSdkVersion = 0; static inline bool exceptionCheck(JNIEnv *env) { @@ -60,6 +61,19 @@ static inline bool exceptionCheck(JNIEnv *env) return false; } +static void setAndroidSdkVersion(JNIEnv *env) +{ + jclass androidVersionClass = env->FindClass("android/os/Build$VERSION"); + if (exceptionCheck(env)) + return; + + jfieldID androidSDKFieldID = env->GetStaticFieldID(androidVersionClass, "SDK_INT", "I"); + if (exceptionCheck(env)) + return; + + g_androidSdkVersion = env->GetStaticIntField(androidVersionClass, androidSDKFieldID); +} + jint QtAndroidPrivate::initJNI(JavaVM *vm, JNIEnv *env) { jclass jQtNative = env->FindClass("org/qtproject/qt5/android/QtNative"); @@ -93,6 +107,8 @@ jint QtAndroidPrivate::initJNI(JavaVM *vm, JNIEnv *env) if (exceptionCheck(env)) return JNI_ERR; + setAndroidSdkVersion(env); + g_jClassLoader = env->NewGlobalRef(classLoader); env->DeleteLocalRef(classLoader); g_jActivity = env->NewGlobalRef(activity); @@ -118,4 +134,9 @@ jobject QtAndroidPrivate::classLoader() return g_jClassLoader; } +jint QtAndroidPrivate::androidSdkVersion() +{ + return g_androidSdkVersion; +} + QT_END_NAMESPACE diff --git a/src/corelib/kernel/qjnihelpers_p.h b/src/corelib/kernel/qjnihelpers_p.h index 39059db215..c92dbdde7f 100644 --- a/src/corelib/kernel/qjnihelpers_p.h +++ b/src/corelib/kernel/qjnihelpers_p.h @@ -64,6 +64,7 @@ namespace QtAndroidPrivate Q_CORE_EXPORT JavaVM *javaVM(); Q_CORE_EXPORT jint initJNI(JavaVM *vm, JNIEnv *env); jobject classLoader(); + jint androidSdkVersion(); } QT_END_NAMESPACE diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index f1351f5a07..43b88d21b5 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -2086,7 +2086,9 @@ void QObject::deleteLater() const char *qFlagLocation(const char *method) { - QThreadData::current()->flaggedSignatures.store(method); + QThreadData *currentThreadData = QThreadData::current(false); + if (currentThreadData != 0) + currentThreadData->flaggedSignatures.store(method); return method; } @@ -3451,8 +3453,11 @@ void QMetaObject::activate(QObject *sender, int signalOffset, int local_signal_i { int signal_index = signalOffset + local_signal_index; - if (!sender->d_func()->isSignalConnected(signal_index)) + if (!sender->d_func()->isSignalConnected(signal_index) + && !qt_signal_spy_callback_set.signal_begin_callback + && !qt_signal_spy_callback_set.signal_end_callback) { return; // nothing connected to these signals, and no spy + } if (sender->d_func()->blockSig) return; diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h index 011e140e3b..8cbb244451 100644 --- a/src/corelib/kernel/qobject_p.h +++ b/src/corelib/kernel/qobject_p.h @@ -248,7 +248,7 @@ public: Returns \c true if the signal with index \a signal_index from object \a sender is connected. Signals with indices above a certain range are always considered connected (see connectedSignals - in QObjectPrivate). If a signal spy is installed, all signals are considered connected. + in QObjectPrivate). \a signal_index must be the index returned by QObjectPrivate::signalIndex; */ @@ -257,9 +257,7 @@ inline bool QObjectPrivate::isSignalConnected(uint signal_index) const return signal_index >= sizeof(connectedSignals) * 8 || (connectedSignals[signal_index >> 5] & (1 << (signal_index & 0x1f)) || (declarativeData && QAbstractDeclarativeData::isSignalConnected - && QAbstractDeclarativeData::isSignalConnected(declarativeData, q_func(), signal_index)) - || qt_signal_spy_callback_set.signal_begin_callback - || qt_signal_spy_callback_set.signal_end_callback); + && QAbstractDeclarativeData::isSignalConnected(declarativeData, q_func(), signal_index))); } inline QObjectPrivate::Sender *QObjectPrivate::setCurrentSender(QObject *receiver, diff --git a/src/corelib/plugin/qlibrary.cpp b/src/corelib/plugin/qlibrary.cpp index 468f759189..9736950c89 100644 --- a/src/corelib/plugin/qlibrary.cpp +++ b/src/corelib/plugin/qlibrary.cpp @@ -374,6 +374,7 @@ private: static QBasicMutex qt_library_mutex; static QLibraryStore *qt_library_data = 0; +static bool qt_library_data_once; QLibraryStore::~QLibraryStore() { @@ -429,8 +430,11 @@ Q_DESTRUCTOR_FUNCTION(qlibraryCleanup) // must be called with a locked mutex QLibraryStore *QLibraryStore::instance() { - if (Q_UNLIKELY(!qt_library_data)) + if (Q_UNLIKELY(!qt_library_data_once && !qt_library_data)) { + // only create once per process lifetime qt_library_data = new QLibraryStore; + qt_library_data_once = true; + } return qt_library_data; } @@ -440,12 +444,15 @@ inline QLibraryPrivate *QLibraryStore::findOrCreate(const QString &fileName, con QLibraryStore *data = instance(); // check if this library is already loaded - QLibraryPrivate *lib = data->libraryMap.value(fileName); + QLibraryPrivate *lib = 0; + if (Q_LIKELY(data)) + lib = data->libraryMap.value(fileName); if (!lib) lib = new QLibraryPrivate(fileName, version); // track this library - data->libraryMap.insert(fileName, lib); + if (Q_LIKELY(data)) + data->libraryMap.insert(fileName, lib); lib->libraryRefCount.ref(); return lib; @@ -464,9 +471,11 @@ inline void QLibraryStore::releaseLibrary(QLibraryPrivate *lib) // no one else is using Q_ASSERT(lib->libraryUnloadCount.load() == 0); - QLibraryPrivate *that = data->libraryMap.take(lib->fileName); - Q_ASSERT(lib == that); - Q_UNUSED(that); + if (Q_LIKELY(data)) { + QLibraryPrivate *that = data->libraryMap.take(lib->fileName); + Q_ASSERT(lib == that); + Q_UNUSED(that); + } delete lib; } diff --git a/src/corelib/thread/qthread_p.h b/src/corelib/thread/qthread_p.h index 8429e41433..fce84e881b 100644 --- a/src/corelib/thread/qthread_p.h +++ b/src/corelib/thread/qthread_p.h @@ -223,7 +223,7 @@ public: QThreadData(int initialRefCount = 1); ~QThreadData(); - static QThreadData *current(); + static QThreadData *current(bool createIfNecessary = true); static void clearCurrentThreadData(); static QThreadData *get2(QThread *thread) { Q_ASSERT_X(thread != 0, "QThread", "internal error"); return thread->d_func()->data; } diff --git a/src/corelib/thread/qthread_unix.cpp b/src/corelib/thread/qthread_unix.cpp index 15558cb148..b838cb4b28 100644 --- a/src/corelib/thread/qthread_unix.cpp +++ b/src/corelib/thread/qthread_unix.cpp @@ -215,10 +215,10 @@ void QThreadData::clearCurrentThreadData() clear_thread_data(); } -QThreadData *QThreadData::current() +QThreadData *QThreadData::current(bool createIfNecessary) { QThreadData *data = get_thread_data(); - if (!data) { + if (!data && createIfNecessary) { data = new QThreadData; QT_TRY { set_thread_data(data); diff --git a/src/corelib/thread/qthread_win.cpp b/src/corelib/thread/qthread_win.cpp index 037343c996..865b1e6af5 100644 --- a/src/corelib/thread/qthread_win.cpp +++ b/src/corelib/thread/qthread_win.cpp @@ -101,11 +101,11 @@ void QThreadData::clearCurrentThreadData() TlsSetValue(qt_current_thread_data_tls_index, 0); } -QThreadData *QThreadData::current() +QThreadData *QThreadData::current(bool createIfNecessary) { qt_create_tls(); QThreadData *threadData = reinterpret_cast<QThreadData *>(TlsGetValue(qt_current_thread_data_tls_index)); - if (!threadData) { + if (!threadData && createIfNecessary) { threadData = new QThreadData; // This needs to be called prior to new AdoptedThread() to // avoid recursion. diff --git a/src/corelib/tools/qalgorithms.qdoc b/src/corelib/tools/qalgorithms.qdoc index 40eb2ed41d..8feb180248 100644 --- a/src/corelib/tools/qalgorithms.qdoc +++ b/src/corelib/tools/qalgorithms.qdoc @@ -662,9 +662,6 @@ This function requires the item type (in the example above, QString) to implement \c operator<(). - See the \l{<QtAlgorithms>#binaryFind example}{detailed - description} for an example usage. - \sa qLowerBound(), qUpperBound(), {random access iterators} */ diff --git a/src/corelib/tools/qcommandlineparser.cpp b/src/corelib/tools/qcommandlineparser.cpp index db4c2961f0..c860b4d155 100644 --- a/src/corelib/tools/qcommandlineparser.cpp +++ b/src/corelib/tools/qcommandlineparser.cpp @@ -720,7 +720,8 @@ QStringList QCommandLineParser::values(const QString &optionName) const */ bool QCommandLineParser::isSet(const QCommandLineOption &option) const { - return isSet(option.names().first()); + // option.names() might be empty if the constructor failed + return !option.names().isEmpty() && isSet(option.names().first()); } /*! diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp index 5438f00c67..6177012e4b 100644 --- a/src/corelib/tools/qdatetime.cpp +++ b/src/corelib/tools/qdatetime.cpp @@ -1902,7 +1902,7 @@ int QTime::msecsTo(const QTime &t) const #ifndef QT_NO_DATESTRING -static QTime fromIsoTimeString(const QString &string, Qt::DateFormat format, bool *isMidnight24) +static QTime fromIsoTimeString(const QStringRef &string, Qt::DateFormat format, bool *isMidnight24) { if (isMidnight24) *isMidnight24 = false; @@ -1935,9 +1935,13 @@ static QTime fromIsoTimeString(const QString &string, Qt::DateFormat format, boo // the maximum amount of millisecond digits it will expand to once converted to // seconds is 4. E.g. 12:34,99999 will expand to 12:34:59.9994. The milliseconds // will then be rounded up AND clamped to 999. - const float minuteFraction = QString::fromUtf8("0.%1").arg(string.mid(6, 5)).toFloat(&ok); + + const QStringRef minuteFractionStr = string.mid(6, 5); + const long minuteFractionInt = minuteFractionStr.toLong(&ok); if (!ok) return QTime(); + const float minuteFraction = double(minuteFractionInt) / (std::pow(double(10), minuteFractionStr.count())); + const float secondWithMs = minuteFraction * 60; const float secondNoMs = std::floor(secondWithMs); const float secondFraction = secondWithMs - secondNoMs; @@ -1949,9 +1953,11 @@ static QTime fromIsoTimeString(const QString &string, Qt::DateFormat format, boo if (!ok) return QTime(); if (size > 8 && (string.at(8) == QLatin1Char(',') || string.at(8) == QLatin1Char('.'))) { - const double secondFraction = QString::fromUtf8("0.%1").arg(string.mid(9, 4)).toDouble(&ok); + const QStringRef msecStr(string.mid(9, 4)); + int msecInt = msecStr.isEmpty() ? 0 : msecStr.toInt(&ok); if (!ok) return QTime(); + const double secondFraction(msecInt / (std::pow(double(10), msecStr.count()))); msec = qMin(qRound(secondFraction * 1000.0), 999); } } @@ -2001,7 +2007,7 @@ QTime QTime::fromString(const QString& string, Qt::DateFormat format) case Qt::ISODate: case Qt::TextDate: default: - return fromIsoTimeString(string, format, 0); + return fromIsoTimeString(&string, format, 0); } } @@ -4383,26 +4389,40 @@ QDateTime QDateTime::fromString(const QString& string, Qt::DateFormat format) if (size < 10) return QDateTime(); - QString isoString = string; + QStringRef isoString(&string); Qt::TimeSpec spec = Qt::LocalTime; - QDate date = QDate::fromString(isoString.left(10), Qt::ISODate); + QDate date = QDate::fromString(string.left(10), Qt::ISODate); if (!date.isValid()) return QDateTime(); if (size == 10) return QDateTime(date); - isoString.remove(0, 11); + isoString = isoString.right(11); int offset = 0; // Check end of string for Time Zone definition, either Z for UTC or [+-]HH:MM for Offset if (isoString.endsWith(QLatin1Char('Z'))) { spec = Qt::UTC; - isoString.chop(1); + isoString = isoString.left(isoString.size() - 1); } else { - const int signIndex = isoString.indexOf(QRegExp(QStringLiteral("[+-]"))); - if (signIndex >= 0) { + // the loop below is faster but functionally equal to: + // const int signIndex = isoString.indexOf(QRegExp(QStringLiteral("[+-]"))); + const int sizeOfTimeZoneString = 4; + int signIndex = isoString.size() - sizeOfTimeZoneString - 1; + bool found = false; + { + const QChar plus = QLatin1Char('+'); + const QChar minus = QLatin1Char('-'); + do { + QChar character(isoString.at(signIndex)); + found = character == plus || character == minus; + } while (--signIndex >= 0 && !found); + ++signIndex; + } + + if (found) { bool ok; - offset = fromOffsetString(isoString.mid(signIndex), &ok); + offset = fromOffsetString(isoString.mid(signIndex).toString(), &ok); if (!ok) return QDateTime(); isoString = isoString.left(signIndex); diff --git a/src/corelib/tools/qrect.h b/src/corelib/tools/qrect.h index 62ebdd10cd..22696f9edf 100644 --- a/src/corelib/tools/qrect.h +++ b/src/corelib/tools/qrect.h @@ -512,7 +512,7 @@ public: Q_DECL_CONSTEXPR inline QRectF translated(qreal dx, qreal dy) const; Q_DECL_CONSTEXPR inline QRectF translated(const QPointF &p) const; - inline void moveTo(qreal x, qreal t); + inline void moveTo(qreal x, qreal y); inline void moveTo(const QPointF &p); inline void setRect(qreal x, qreal y, qreal w, qreal h); diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h index 0a0a609728..9778d42c1d 100644 --- a/src/corelib/tools/qstring.h +++ b/src/corelib/tools/qstring.h @@ -1029,13 +1029,13 @@ inline QT_ASCII_CAST_WARN bool operator==(const char *s1, const QString &s2) inline QT_ASCII_CAST_WARN bool operator!=(const char *s1, const QString &s2) { return QString::compare_helper(s2.constData(), s2.size(), s1, -1) != 0; } inline QT_ASCII_CAST_WARN bool operator<(const char *s1, const QString &s2) -{ return QString::compare_helper(s2.constData(), s2.size(), s1, -1) < 0; } -inline QT_ASCII_CAST_WARN bool operator>(const char *s1, const QString &s2) { return QString::compare_helper(s2.constData(), s2.size(), s1, -1) > 0; } +inline QT_ASCII_CAST_WARN bool operator>(const char *s1, const QString &s2) +{ return QString::compare_helper(s2.constData(), s2.size(), s1, -1) < 0; } inline QT_ASCII_CAST_WARN bool operator<=(const char *s1, const QString &s2) -{ return QString::compare_helper(s2.constData(), s2.size(), s1, -1) <= 0; } -inline QT_ASCII_CAST_WARN bool operator>=(const char *s1, const QString &s2) { return QString::compare_helper(s2.constData(), s2.size(), s1, -1) >= 0; } +inline QT_ASCII_CAST_WARN bool operator>=(const char *s1, const QString &s2) +{ return QString::compare_helper(s2.constData(), s2.size(), s1, -1) <= 0; } inline QT_ASCII_CAST_WARN bool operator==(const char *s1, QLatin1String s2) { return QString::fromUtf8(s1) == s2; } diff --git a/src/corelib/tools/qvector.h b/src/corelib/tools/qvector.h index f56511edbf..075e8e83e8 100644 --- a/src/corelib/tools/qvector.h +++ b/src/corelib/tools/qvector.h @@ -254,7 +254,10 @@ private: }; #ifdef Q_CC_MSVC -# pragma warning ( disable : 4345 ) // behavior change: an object of POD type constructed with an initializer of the form () will be default-initialized +// behavior change: an object of POD type constructed with an initializer of the form () +// will be default-initialized +# pragma warning ( push ) +# pragma warning ( disable : 4345 ) #endif template <typename T> @@ -270,7 +273,7 @@ void QVector<T>::defaultConstruct(T *from, T *to) } #ifdef Q_CC_MSVC -# pragma warning ( default: 4345 ) +# pragma warning ( pop ) #endif template <typename T> @@ -438,11 +441,15 @@ QVector<T>::QVector(int asize, const T &t) template <typename T> QVector<T>::QVector(std::initializer_list<T> args) { - d = Data::allocate(args.size()); - // std::initializer_list<T>::iterator is guaranteed to be - // const T* ([support.initlist]/1), so can be memcpy'ed away from by copyConstruct - copyConstruct(args.begin(), args.end(), d->begin()); - d->size = int(args.size()); + if (args.size() > 0) { + d = Data::allocate(args.size()); + // std::initializer_list<T>::iterator is guaranteed to be + // const T* ([support.initlist]/1), so can be memcpy'ed away from by copyConstruct + copyConstruct(args.begin(), args.end(), d->begin()); + d->size = int(args.size()); + } else { + d = Data::sharedNull(); + } } #endif diff --git a/src/gui/image/qiconloader.cpp b/src/gui/image/qiconloader.cpp index d202d62957..9e979023cd 100644 --- a/src/gui/image/qiconloader.cpp +++ b/src/gui/image/qiconloader.cpp @@ -519,10 +519,11 @@ QPixmap PixmapEntry::pixmap(const QSize &size, QIcon::Mode mode, QIcon::State st return cachedPixmap; } else { if (basePixmap.size() != actualSize) - basePixmap = basePixmap.scaled(actualSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); - cachedPixmap = basePixmap; + cachedPixmap = basePixmap.scaled(actualSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); + else + cachedPixmap = basePixmap; if (QGuiApplication *guiApp = qobject_cast<QGuiApplication *>(qApp)) - cachedPixmap = static_cast<QGuiApplicationPrivate*>(QObjectPrivate::get(guiApp))->applyQIconStyleHelper(mode, basePixmap); + cachedPixmap = static_cast<QGuiApplicationPrivate*>(QObjectPrivate::get(guiApp))->applyQIconStyleHelper(mode, cachedPixmap); QPixmapCache::insert(key, cachedPixmap); } return cachedPixmap; diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index ee4817e4ec..fafcd9edb0 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -59,6 +59,7 @@ #include <QtCore/qmutex.h> #include <QtCore/private/qthread_p.h> #include <QtCore/qdir.h> +#include <QtCore/qnumeric.h> #include <QtDebug> #ifndef QT_NO_ACCESSIBILITY #include "qaccessible.h" @@ -110,7 +111,7 @@ Q_GUI_EXPORT bool qt_is_gui_used = true; Qt::MouseButtons QGuiApplicationPrivate::mouse_buttons = Qt::NoButton; Qt::KeyboardModifiers QGuiApplicationPrivate::modifier_buttons = Qt::NoModifier; -QPointF QGuiApplicationPrivate::lastCursorPosition(0.0, 0.0); +QPointF QGuiApplicationPrivate::lastCursorPosition(qInf(), qInf()); bool QGuiApplicationPrivate::tabletState = false; QWindow *QGuiApplicationPrivate::tabletPressTarget = 0; diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index cc28076b7c..d3e5b645c4 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -374,12 +374,6 @@ inline void QT_FASTCALL storePixel<QPixelLayout::BPP24>(uchar *dest, int index, reinterpret_cast<quint24 *>(dest)[index] = quint24(pixel); } -template <> -inline void QT_FASTCALL storePixel<QPixelLayout::BPP32>(uchar *dest, int index, uint pixel) -{ - reinterpret_cast<uint *>(dest)[index] = pixel; -} - template <QPixelLayout::BPP width> inline void QT_FASTCALL storePixels(uchar *dest, const uint *src, int index, int count) { diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index 424ed554a2..41a2e39fc9 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -62,6 +62,7 @@ #include "qglyphrun.h" #include <qpa/qplatformtheme.h> +#include <qpa/qplatformintegration.h> #include <private/qfontengine_p.h> #include <private/qpaintengine_p.h> @@ -155,7 +156,9 @@ static bool qt_painter_thread_test(int devType, const char *what) // can be drawn onto these devices safely from any thread break; default: - if (QThread::currentThread() != qApp->thread()) { + if (QThread::currentThread() != qApp->thread() + && (devType!=QInternal::Pixmap || !QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::ThreadedPixmaps)) + && (devType!=QInternal::OpenGL || !QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::ThreadedOpenGL))) { qWarning("QPainter: It is not safe to use %s outside the GUI thread", what); return false; } diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp index 303c85ce75..9eea2e786f 100644 --- a/src/gui/text/qfontengine.cpp +++ b/src/gui/text/qfontengine.cpp @@ -171,7 +171,8 @@ static const HB_FontClass hb_fontClass = { static HB_Error hb_getSFntTable(void *font, HB_Tag tableTag, HB_Byte *buffer, HB_UInt *length) { QFontEngine *fe = (QFontEngine *)font; - if (!fe->getSfntTableData(tableTag, buffer, length)) + Q_ASSERT(fe->faceData.get_font_table); + if (!fe->faceData.get_font_table(fe->faceData.user_data, tableTag, buffer, length)) return HB_Err_Invalid_Argument; return HB_Err_Ok; } @@ -182,6 +183,13 @@ static void hb_freeFace(void *face) } +static bool qt_get_font_table_default(void *user_data, uint tag, uchar *buffer, uint *length) +{ + QFontEngine *fe = (QFontEngine *)user_data; + return fe->getSfntTableData(tag, buffer, length); +} + + #ifdef QT_BUILD_INTERNAL // for testing purpose only, not thread-safe! static QList<QFontEngine *> *enginesCollector = 0; @@ -210,6 +218,9 @@ QFontEngine::QFontEngine() font_(0), font_destroy_func(0), face_(0), face_destroy_func(0) { + faceData.user_data = this; + faceData.get_font_table = qt_get_font_table_default; + cache_cost = 0; fsType = 0; symbol = false; diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp index 42cf15ee3b..05bd014bd7 100644 --- a/src/gui/text/qfontengine_ft.cpp +++ b/src/gui/text/qfontengine_ft.cpp @@ -116,6 +116,21 @@ QT_BEGIN_NAMESPACE #define TRUNC(x) ((x) >> 6) #define ROUND(x) (((x)+32) & -64) +static bool ft_getSfntTable(void *user_data, uint tag, uchar *buffer, uint *length) +{ + FT_Face face = (FT_Face)user_data; + + bool result = false; + if (FT_IS_SFNT(face)) { + FT_ULong len = *length; + result = FT_Load_Sfnt_Table(face, tag, 0, buffer, &len) == FT_Err_Ok; + *length = len; + } + + return result; +} + + // -------------------------- Freetype support ------------------------------ class QtFreetypeData @@ -408,15 +423,7 @@ QFontEngine::Properties QFreetypeFace::properties() const bool QFreetypeFace::getSfntTable(uint tag, uchar *buffer, uint *length) const { - bool result = false; -#if (FREETYPE_MAJOR*10000 + FREETYPE_MINOR*100 + FREETYPE_PATCH) > 20103 - if (FT_IS_SFNT(face)) { - FT_ULong len = *length; - result = FT_Load_Sfnt_Table(face, tag, 0, buffer, &len) == FT_Err_Ok; - *length = len; - } -#endif - return result; + return ft_getSfntTable(face, tag, buffer, length); } /* Some fonts (such as MingLiu rely on hinting to scale different @@ -761,6 +768,8 @@ bool QFontEngineFT::init(FaceId faceId, bool antialias, GlyphFormat format, fontDef.styleName = QString::fromUtf8(face->style_name); if (!freetype->hbFace) { + faceData.user_data = face; + faceData.get_font_table = ft_getSfntTable; freetype->hbFace = harfbuzzFace(); freetype->hbFace_destroy_func = face_destroy_func; } else { @@ -1179,7 +1188,7 @@ QFixed QFontEngineFT::emSquareSize() const bool QFontEngineFT::getSfntTableData(uint tag, uchar *buffer, uint *length) const { - return freetype->getSfntTable(tag, buffer, length); + return ft_getSfntTable(freetype->face, tag, buffer, length); } int QFontEngineFT::synthesized() const diff --git a/src/gui/text/qfontengine_p.h b/src/gui/text/qfontengine_p.h index c181d61d73..a04f4bd0ac 100644 --- a/src/gui/text/qfontengine_p.h +++ b/src/gui/text/qfontengine_p.h @@ -85,6 +85,7 @@ enum HB_Compat_Error { }; typedef void (*qt_destroy_func_t) (void *user_data); +typedef bool (*qt_get_font_table_func_t) (void *user_data, uint tag, uchar *buffer, uint *length); class Q_GUI_EXPORT QFontEngine { @@ -280,6 +281,10 @@ public: mutable qt_destroy_func_t font_destroy_func; mutable void *face_; mutable qt_destroy_func_t face_destroy_func; + struct FaceData { + void *user_data; + qt_get_font_table_func_t get_font_table; + } faceData; uint cache_cost; // amount of mem used in kb by the font uint fsType : 16; diff --git a/src/gui/text/qharfbuzzng.cpp b/src/gui/text/qharfbuzzng.cpp index b4ab5856df..d2e7df9c10 100644 --- a/src/gui/text/qharfbuzzng.cpp +++ b/src/gui/text/qharfbuzzng.cpp @@ -623,19 +623,22 @@ hb_font_funcs_t *hb_qt_get_font_funcs() static hb_blob_t * -_hb_qt_get_font_table(hb_face_t * /*face*/, hb_tag_t tag, void *user_data) +_hb_qt_reference_table(hb_face_t * /*face*/, hb_tag_t tag, void *user_data) { - QFontEngine *fe = (QFontEngine *)user_data; - Q_ASSERT(fe); + QFontEngine::FaceData *data = (QFontEngine::FaceData *)user_data; + Q_ASSERT(data); + + qt_get_font_table_func_t get_font_table = data->get_font_table; + Q_ASSERT(get_font_table); uint length = 0; - if (Q_UNLIKELY(!fe->getSfntTableData(tag, 0, &length) || length == 0)) + if (Q_UNLIKELY(!get_font_table(data->user_data, tag, 0, &length) || length == 0)) return hb_blob_get_empty(); char *buffer = (char *)malloc(length); Q_CHECK_PTR(buffer); - if (Q_UNLIKELY(!fe->getSfntTableData(tag, reinterpret_cast<uchar *>(buffer), &length))) + if (Q_UNLIKELY(!get_font_table(data->user_data, tag, reinterpret_cast<uchar *>(buffer), &length))) length = 0; return hb_blob_create(const_cast<const char *>(buffer), length, @@ -646,9 +649,14 @@ _hb_qt_get_font_table(hb_face_t * /*face*/, hb_tag_t tag, void *user_data) static inline hb_face_t * _hb_qt_face_create(QFontEngine *fe) { - hb_face_t *face; + Q_ASSERT(fe); + + QFontEngine::FaceData *data = (QFontEngine::FaceData *)malloc(sizeof(QFontEngine::FaceData)); + Q_CHECK_PTR(data); + data->user_data = fe->faceData.user_data; + data->get_font_table = fe->faceData.get_font_table; - face = hb_face_create_for_tables(_hb_qt_get_font_table, (void *)fe, NULL); + hb_face_t *face = hb_face_create_for_tables(_hb_qt_reference_table, (void *)data, free); if (Q_UNLIKELY(hb_face_is_immutable(face))) { hb_face_destroy(face); return NULL; diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp index 980b19b7e4..c89419091f 100644 --- a/src/network/access/qnetworkaccessmanager.cpp +++ b/src/network/access/qnetworkaccessmanager.cpp @@ -224,12 +224,7 @@ static void ensureInitialized() \note The network and roaming support in QNetworkAccessManager is conditional upon the platform supporting connection management. The \l QNetworkConfigurationManager::NetworkSessionRequired can be used to - detect whether QNetworkAccessManager utilizes this feature. Currently only - Meego/Harmattan platforms provide connection management support. - - \note This feature cannot be used in combination with the Bearer Management - API as provided by QtMobility. Applications have to migrate to the Qt version - of Bearer Management. + detect whether QNetworkAccessManager utilizes this feature. \sa QNetworkRequest, QNetworkReply, QNetworkProxy */ diff --git a/src/network/kernel/qdnslookup_unix.cpp b/src/network/kernel/qdnslookup_unix.cpp index 052c492f07..9fb488cee6 100644 --- a/src/network/kernel/qdnslookup_unix.cpp +++ b/src/network/kernel/qdnslookup_unix.cpp @@ -52,7 +52,7 @@ #include <arpa/nameser_compat.h> #include <resolv.h> -#ifdef __GNU_LIBRARY__ +#if defined(__GNU_LIBRARY__) && !defined(__UCLIBC__) # include <gnu/lib-names.h> #endif diff --git a/src/network/kernel/qhostinfo_unix.cpp b/src/network/kernel/qhostinfo_unix.cpp index dc2702b552..32b7318335 100644 --- a/src/network/kernel/qhostinfo_unix.cpp +++ b/src/network/kernel/qhostinfo_unix.cpp @@ -63,7 +63,7 @@ # include <resolv.h> #endif -#ifdef __GNU_LIBRARY__ +#if defined(__GNU_LIBRARY__) && !defined(__UCLIBC__) # include <gnu/lib-names.h> #endif diff --git a/src/network/socket/qabstractsocket.cpp b/src/network/socket/qabstractsocket.cpp index 47fec38283..bebdf728a7 100644 --- a/src/network/socket/qabstractsocket.cpp +++ b/src/network/socket/qabstractsocket.cpp @@ -578,8 +578,7 @@ QAbstractSocketPrivate::~QAbstractSocketPrivate() /*! \internal - Resets the socket layer, clears the read and write buffers and - deletes any socket notifiers. + Resets the socket layer and deletes any socket notifiers. */ void QAbstractSocketPrivate::resetSocketLayer() { @@ -1821,6 +1820,7 @@ qintptr QAbstractSocket::socketDescriptor() const as a valid socket descriptor; otherwise returns \c false. The socket is opened in the mode specified by \a openMode, and enters the socket state specified by \a socketState. + Read and write buffers are cleared, discarding any pending data. \b{Note:} It is not possible to initialize two abstract sockets with the same native socket descriptor. @@ -1833,6 +1833,8 @@ bool QAbstractSocket::setSocketDescriptor(qintptr socketDescriptor, SocketState Q_D(QAbstractSocket); d->resetSocketLayer(); + d->writeBuffer.clear(); + d->buffer.clear(); d->socketEngine = QAbstractSocketEngine::createSocketEngine(socketDescriptor, this); if (!d->socketEngine) { d->socketError = UnsupportedSocketOperationError; @@ -2190,7 +2192,7 @@ bool QAbstractSocket::waitForBytesWritten(int msecs) if (readyToWrite) { if (d->canWriteNotification()) { #if defined (QABSTRACTSOCKET_DEBUG) - qDebug("QAbstractSocket::waitForBytesWritten returns \c true"); + qDebug("QAbstractSocket::waitForBytesWritten returns true"); #endif return true; } @@ -2281,6 +2283,7 @@ void QAbstractSocket::abort() #if defined (QABSTRACTSOCKET_DEBUG) qDebug("QAbstractSocket::abort()"); #endif + d->writeBuffer.clear(); if (d->state == UnconnectedState) return; #ifndef QT_NO_SSL @@ -2295,7 +2298,6 @@ void QAbstractSocket::abort() d->connectTimer = 0; } - d->writeBuffer.clear(); d->abortCalled = true; close(); } diff --git a/src/network/ssl/qsslcontext.cpp b/src/network/ssl/qsslcontext.cpp index 037ee8c672..adf42fb79a 100644 --- a/src/network/ssl/qsslcontext.cpp +++ b/src/network/ssl/qsslcontext.cpp @@ -189,9 +189,6 @@ init_context: q_SSL_CTX_load_verify_locations(sslContext->ctx, 0, unixDirs.at(a).constData()); } - // Register a custom callback to get all verification errors. - X509_STORE_set_verify_cb_func(sslContext->ctx->cert_store, q_X509Callback); - if (!sslContext->sslConfiguration.localCertificate().isNull()) { // Require a private key as well. if (sslContext->sslConfiguration.privateKey().isNull()) { diff --git a/src/platformsupport/input/evdevtouch/qevdevtouch.cpp b/src/platformsupport/input/evdevtouch/qevdevtouch.cpp index d9468ae1b8..b4ebf8179c 100644 --- a/src/platformsupport/input/evdevtouch/qevdevtouch.cpp +++ b/src/platformsupport/input/evdevtouch/qevdevtouch.cpp @@ -345,40 +345,61 @@ QEvdevTouchScreenHandler::~QEvdevTouchScreenHandler() void QEvdevTouchScreenHandler::readData() { ::input_event buffer[32]; - int n = 0; - for (; ;) { + int events = 0; + #if !defined(QT_NO_MTDEV) - int result = mtdev_get(m_mtdev, m_fd, buffer, sizeof(buffer) / sizeof(::input_event)); - if (result > 0) - result *= sizeof(::input_event); + forever { + do { + events = mtdev_get(m_mtdev, m_fd, buffer, sizeof(buffer) / sizeof(::input_event)); + // keep trying mtdev_get if we get interrupted. note that we do not + // (and should not) handle EAGAIN; EAGAIN means that reading would + // block and we'll get back here later to try again anyway. + } while (events == -1 && errno == EINTR); + + // 0 events is EOF, -1 means error, handle both in the same place + if (events <= 0) + goto err; + + // process our shiny new events + for (int i = 0; i < events; ++i) + d->processInputEvent(&buffer[i]); + + // and try to get more + } #else - int result = QT_READ(m_fd, reinterpret_cast<char*>(buffer) + n, sizeof(buffer) - n); -#endif - if (!result) { - qWarning("evdevtouch: Got EOF from input device"); - return; - } else if (result < 0) { - if (errno != EINTR && errno != EAGAIN) { - qErrnoWarning(errno, "evdevtouch: Could not read from input device"); - if (errno == ENODEV) { // device got disconnected -> stop reading - delete m_notify; - m_notify = 0; - QT_CLOSE(m_fd); - m_fd = -1; - } - return; - } - } else { - n += result; - if (n % sizeof(::input_event) == 0) - break; - } + int n = 0; + for (; ;) { + events = QT_READ(m_fd, reinterpret_cast<char*>(buffer) + n, sizeof(buffer) - n); + if (events <= 0) + goto err; + n += events; + if (n % sizeof(::input_event) == 0) + break; } n /= sizeof(::input_event); for (int i = 0; i < n; ++i) d->processInputEvent(&buffer[i]); +#endif + return; + +err: + if (!events) { + qWarning("evdevtouch: Got EOF from input device"); + return; + } else if (events < 0) { + if (errno != EINTR && errno != EAGAIN) { + qErrnoWarning(errno, "evdevtouch: Could not read from input device"); + if (errno == ENODEV) { // device got disconnected -> stop reading + delete m_notify; + m_notify = 0; + QT_CLOSE(m_fd); + m_fd = -1; + } + return; + } + } } void QEvdevTouchScreenData::addTouchPoint(const Contact &contact, Qt::TouchPointStates *combinedStates) @@ -412,19 +433,31 @@ void QEvdevTouchScreenData::processInputEvent(input_event *data) if (data->code == ABS_MT_POSITION_X || (m_singleTouch && data->code == ABS_X)) { m_currentData.x = qBound(hw_range_x_min, data->value, hw_range_x_max); - if (m_typeB || m_singleTouch) + if (m_singleTouch) + m_contacts[m_currentSlot].x = m_currentData.x; + if (m_typeB) { m_contacts[m_currentSlot].x = m_currentData.x; + if (m_contacts[m_currentSlot].state == Qt::TouchPointStationary) + m_contacts[m_currentSlot].state = Qt::TouchPointMoved; + } } else if (data->code == ABS_MT_POSITION_Y || (m_singleTouch && data->code == ABS_Y)) { m_currentData.y = qBound(hw_range_y_min, data->value, hw_range_y_max); - if (m_typeB || m_singleTouch) + if (m_singleTouch) m_contacts[m_currentSlot].y = m_currentData.y; + if (m_typeB) { + m_contacts[m_currentSlot].y = m_currentData.y; + if (m_contacts[m_currentSlot].state == Qt::TouchPointStationary) + m_contacts[m_currentSlot].state = Qt::TouchPointMoved; + } } else if (data->code == ABS_MT_TRACKING_ID) { m_currentData.trackingId = data->value; if (m_typeB) { - if (m_currentData.trackingId == -1) + if (m_currentData.trackingId == -1) { m_contacts[m_currentSlot].state = Qt::TouchPointReleased; - else + } else { + m_contacts[m_currentSlot].state = Qt::TouchPointPressed; m_contacts[m_currentSlot].trackingId = m_currentData.trackingId; + } } } else if (data->code == ABS_MT_TOUCH_MAJOR) { m_currentData.maj = data->value; @@ -468,8 +501,11 @@ void QEvdevTouchScreenData::processInputEvent(input_event *data) it.next(); Contact &contact(it.value()); + if (!contact.state) + continue; + int key = m_typeB ? it.key() : contact.trackingId; - if (m_lastContacts.contains(key)) { + if (!m_typeB && m_lastContacts.contains(key)) { const Contact &prev(m_lastContacts.value(key)); if (contact.state == Qt::TouchPointReleased) { // Copy over the previous values for released points, just in case. @@ -483,7 +519,7 @@ void QEvdevTouchScreenData::processInputEvent(input_event *data) } // Avoid reporting a contact in released state more than once. - if (contact.state == Qt::TouchPointReleased + if (!m_typeB && contact.state == Qt::TouchPointReleased && !m_lastContacts.contains(key)) { it.remove(); continue; @@ -509,8 +545,14 @@ void QEvdevTouchScreenData::processInputEvent(input_event *data) while (it.hasNext()) { it.next(); Contact &contact(it.value()); - if (contact.state == Qt::TouchPointReleased) - it.remove(); + if (contact.state == Qt::TouchPointReleased) { + if (m_typeB) + contact.state = static_cast<Qt::TouchPointState>(0); + else + it.remove(); + } else { + contact.state = Qt::TouchPointStationary; + } } m_lastContacts = m_contacts; diff --git a/src/plugins/platforms/android/src/androidjnimain.cpp b/src/plugins/platforms/android/src/androidjnimain.cpp index 3064e5d4e2..6461fa4733 100644 --- a/src/plugins/platforms/android/src/androidjnimain.cpp +++ b/src/plugins/platforms/android/src/androidjnimain.cpp @@ -418,7 +418,15 @@ namespace QtAndroid { return m_qtTag; } -} + + QString deviceName() + { + QString manufacturer = QJNIObjectPrivate::getStaticObjectField("android/os/Build", "MANUFACTURER", "Ljava/lang/String;").toString(); + QString model = QJNIObjectPrivate::getStaticObjectField("android/os/Build", "MODEL", "Ljava/lang/String;").toString(); + + return manufacturer + QStringLiteral(" ") + model; + } +} // namespace QtAndroid static jboolean startQtAndroidPlugin(JNIEnv* /*env*/, jobject /*object*//*, jobject applicationAssetManager*/) { diff --git a/src/plugins/platforms/android/src/androidjnimain.h b/src/plugins/platforms/android/src/androidjnimain.h index 11d3573404..a7b7072ba3 100644 --- a/src/plugins/platforms/android/src/androidjnimain.h +++ b/src/plugins/platforms/android/src/androidjnimain.h @@ -120,5 +120,6 @@ namespace QtAndroid const char *methodErrorMsgFmt(); const char *qtTagText(); + QString deviceName(); } #endif // ANDROID_APP_H diff --git a/src/plugins/platforms/android/src/opengl/qandroidopenglcontext.cpp b/src/plugins/platforms/android/src/opengl/qandroidopenglcontext.cpp index 6431914812..d94bb241f7 100644 --- a/src/plugins/platforms/android/src/opengl/qandroidopenglcontext.cpp +++ b/src/plugins/platforms/android/src/opengl/qandroidopenglcontext.cpp @@ -82,12 +82,14 @@ void QAndroidOpenGLContext::swapBuffers(QPlatformSurface *surface) bool QAndroidOpenGLContext::makeCurrent(QPlatformSurface *surface) { bool ret = QEglFSContext::makeCurrent(surface); + QOpenGLContextPrivate *ctx_d = QOpenGLContextPrivate::get(context()); const char *rendererString = reinterpret_cast<const char *>(glGetString(GL_RENDERER)); - if (rendererString != 0 && qstrncmp(rendererString, "Android Emulator", 16) == 0) { - QOpenGLContextPrivate *ctx_d = QOpenGLContextPrivate::get(context()); + if (rendererString != 0 && qstrncmp(rendererString, "Android Emulator", 16) == 0) ctx_d->workaround_missingPrecisionQualifiers = true; - } + + if (!ctx_d->workaround_brokenFBOReadBack && QAndroidPlatformIntegration::needsWorkaround()) + ctx_d->workaround_brokenFBOReadBack = true; return ret; } diff --git a/src/plugins/platforms/android/src/qandroidplatformintegration.cpp b/src/plugins/platforms/android/src/qandroidplatformintegration.cpp index ae3e257d3c..9bfb6e9a70 100644 --- a/src/plugins/platforms/android/src/qandroidplatformintegration.cpp +++ b/src/plugins/platforms/android/src/qandroidplatformintegration.cpp @@ -89,6 +89,10 @@ void *QAndroidPlatformNativeInterface::nativeResourceForIntegration(const QByteA return &m_palettes; if (resource == "AndroidStyleFonts") return &m_fonts; + if (resource == "AndroidDeviceName") { + static QString deviceName = QtAndroid::deviceName(); + return &deviceName; + } return 0; } @@ -114,17 +118,34 @@ QAndroidPlatformIntegration::QAndroidPlatformIntegration(const QStringList ¶ m_androidFDB = new QAndroidPlatformFontDatabase(); m_androidPlatformServices = new QAndroidPlatformServices(); + +#ifndef QT_NO_CLIPBOARD m_androidPlatformClipboard = new QAndroidPlatformClipboard(); +#endif m_androidSystemLocale = new QAndroidSystemLocale; } +bool QAndroidPlatformIntegration::needsWorkaround() +{ + static bool needsWorkaround = + QtAndroid::deviceName().compare(QStringLiteral("samsung SM-T211"), Qt::CaseInsensitive) == 0 + || QtAndroid::deviceName().compare(QStringLiteral("samsung SM-T210"), Qt::CaseInsensitive) == 0 + || QtAndroid::deviceName().compare(QStringLiteral("samsung SM-T215"), Qt::CaseInsensitive) == 0; + return needsWorkaround; +} + bool QAndroidPlatformIntegration::hasCapability(Capability cap) const { switch (cap) { case ThreadedPixmaps: return true; case ApplicationState: return true; case NativeWidgets: return false; + + case ThreadedOpenGL: + if (needsWorkaround()) + return false; + // fall through default: #ifndef ANDROID_PLUGIN_OPENGL return QPlatformIntegration::hasCapability(cap); @@ -199,6 +220,11 @@ QAndroidPlatformIntegration::~QAndroidPlatformIntegration() delete m_androidPlatformNativeInterface; delete m_androidFDB; delete m_androidSystemLocale; + +#ifndef QT_NO_CLIPBOARD + delete m_androidPlatformClipboard; +#endif + QtAndroid::setAndroidPlatformIntegration(NULL); } QPlatformFontDatabase *QAndroidPlatformIntegration::fontDatabase() const @@ -209,11 +235,7 @@ QPlatformFontDatabase *QAndroidPlatformIntegration::fontDatabase() const #ifndef QT_NO_CLIPBOARD QPlatformClipboard *QAndroidPlatformIntegration::clipboard() const { -static QAndroidPlatformClipboard *clipboard = 0; - if (!clipboard) - clipboard = new QAndroidPlatformClipboard; - - return clipboard; + return m_androidPlatformClipboard; } #endif diff --git a/src/plugins/platforms/android/src/qandroidplatformintegration.h b/src/plugins/platforms/android/src/qandroidplatformintegration.h index bd08ad694c..c5476128a5 100644 --- a/src/plugins/platforms/android/src/qandroidplatformintegration.h +++ b/src/plugins/platforms/android/src/qandroidplatformintegration.h @@ -145,8 +145,9 @@ public: QEglFSScreen *createScreen() const; #endif -private: + static bool needsWorkaround(); +private: friend class QEglFSAndroidHooks; QTouchDevice *m_touchDevice; @@ -170,7 +171,11 @@ private: QPainter *m_compositePainter; QAndroidPlatformNativeInterface *m_androidPlatformNativeInterface; QAndroidPlatformServices *m_androidPlatformServices; + +#ifndef QT_NO_CLIPBOARD QPlatformClipboard *m_androidPlatformClipboard; +#endif + QAndroidSystemLocale *m_androidSystemLocale; #ifndef QT_NO_ACCESSIBILITY mutable QPlatformAccessibility *m_accessibility; diff --git a/src/plugins/platforms/cocoa/qcocoasystemsettings.mm b/src/plugins/platforms/cocoa/qcocoasystemsettings.mm index 194394d11a..1c08d4bcb7 100644 --- a/src/plugins/platforms/cocoa/qcocoasystemsettings.mm +++ b/src/plugins/platforms/cocoa/qcocoasystemsettings.mm @@ -254,6 +254,7 @@ QHash<QPlatformTheme::Font, QFont *> qt_mac_createRoleFonts() fonts.insert(QPlatformTheme::ListBoxFont, qt_mac_qfontForThemeFont(kThemeViewsFont)); fonts.insert(QPlatformTheme::TitleBarFont, qt_mac_qfontForThemeFont(kThemeWindowTitleFont)); fonts.insert(QPlatformTheme::MenuFont, qt_mac_qfontForThemeFont(kThemeMenuItemFont)); + fonts.insert(QPlatformTheme::MenuBarFont, qt_mac_qfontForThemeFont(kThemeMenuItemFont)); fonts.insert(QPlatformTheme::ComboMenuItemFont, qt_mac_qfontForThemeFont(kThemeSystemFont)); fonts.insert(QPlatformTheme::HeaderViewFont, qt_mac_qfontForThemeFont(kThemeSmallSystemFont)); fonts.insert(QPlatformTheme::TipLabelFont, qt_mac_qfontForThemeFont(kThemeSmallSystemFont)); diff --git a/src/plugins/platforms/cocoa/qcocoatheme.mm b/src/plugins/platforms/cocoa/qcocoatheme.mm index 1484ae2ba3..d863861288 100644 --- a/src/plugins/platforms/cocoa/qcocoatheme.mm +++ b/src/plugins/platforms/cocoa/qcocoatheme.mm @@ -258,13 +258,17 @@ QPixmap QCocoaTheme::fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &siz NSImage *iconImage = [[NSWorkspace sharedWorkspace] iconForFile:QCFString::toNSString(fileInfo.canonicalFilePath())]; if (!iconImage) return QPixmap(); - - NSRect iconRect = NSMakeRect(0, 0, size.width(), size.height()); - NSGraphicsContext *gc = [NSGraphicsContext currentContext]; - CGImageRef cgImage = [iconImage CGImageForProposedRect:&iconRect - context:([gc graphicsPort] ? gc : nil) - hints:nil]; - QPixmap pixmap = QPixmap::fromImage(qt_mac_toQImage(cgImage)); + NSSize pixmapSize = NSMakeSize(size.width(), size.height()); + QPixmap pixmap(pixmapSize.width, pixmapSize.height); + pixmap.fill(Qt::transparent); + [iconImage setSize:pixmapSize]; + NSRect iconRect = NSMakeRect(0, 0, pixmapSize.width, pixmapSize.height); + CGContextRef ctx = qt_mac_cg_context(&pixmap); + NSGraphicsContext *gc = [NSGraphicsContext graphicsContextWithGraphicsPort:ctx flipped:YES]; + [NSGraphicsContext saveGraphicsState]; + [NSGraphicsContext setCurrentContext:gc]; + [iconImage drawInRect:iconRect fromRect:iconRect operation:NSCompositeSourceOver fraction:1.0 respectFlipped:YES hints:nil]; + [NSGraphicsContext restoreGraphicsState]; return pixmap; } @@ -280,8 +284,12 @@ QVariant QCocoaTheme::themeHint(ThemeHint hint) const case TabAllWidgets: return QVariant(bool([[NSApplication sharedApplication] isFullKeyboardAccessEnabled])); case IconPixmapSizes: { + qreal devicePixelRatio = qGuiApp->devicePixelRatio(); QList<int> sizes; - sizes << 16 << 32 << 64 << 128; + sizes << 16 * devicePixelRatio + << 32 * devicePixelRatio + << 64 * devicePixelRatio + << 128 * devicePixelRatio; return QVariant::fromValue(sizes); } case QPlatformTheme::PasswordMaskCharacter: diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h index 66c3241b3d..452be90108 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.h +++ b/src/plugins/platforms/cocoa/qcocoawindow.h @@ -211,7 +211,6 @@ public: // for QNSView QRect m_exposedGeometry; int m_registerTouchCount; bool m_resizableTransientParent; - bool m_overrideBecomeKey; static const int NoAlertRequest; NSInteger m_alertRequest; diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index 8e977236fa..bf5e0cfbc4 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -160,9 +160,7 @@ static bool isMouseEvent(NSEvent *ev) // Only tool or dialog windows should become key: if (m_cocoaPlatformWindow - && (m_cocoaPlatformWindow->m_overrideBecomeKey || - m_cocoaPlatformWindow->window()->type() == Qt::Tool || - m_cocoaPlatformWindow->window()->type() == Qt::Dialog)) + && (m_cocoaPlatformWindow->window()->type() == Qt::Tool || m_cocoaPlatformWindow->window()->type() == Qt::Dialog)) return YES; return NO; } @@ -217,7 +215,6 @@ QCocoaWindow::QCocoaWindow(QWindow *tlw) , m_isExposed(false) , m_registerTouchCount(0) , m_resizableTransientParent(false) - , m_overrideBecomeKey(false) , m_alertRequest(NoAlertRequest) , monitor(nil) , m_drawContentBorderGradient(false) @@ -267,6 +264,7 @@ QCocoaWindow::~QCocoaWindow() [m_contentView release]; [m_nsWindow release]; [m_nsWindowDelegate release]; + [m_windowCursor release]; } QSurfaceFormat QCocoaWindow::format() const @@ -705,8 +703,6 @@ bool QCocoaWindow::setKeyboardGrabEnabled(bool grab) if (!m_nsWindow) return false; - m_overrideBecomeKey = grab; - if (grab && ![m_nsWindow isKeyWindow]) [m_nsWindow makeKeyWindow]; else if (!grab && [m_nsWindow isKeyWindow]) @@ -719,8 +715,6 @@ bool QCocoaWindow::setMouseGrabEnabled(bool grab) if (!m_nsWindow) return false; - m_overrideBecomeKey = grab; - if (grab && ![m_nsWindow isKeyWindow]) [m_nsWindow makeKeyWindow]; else if (!grab && [m_nsWindow isKeyWindow]) @@ -1066,7 +1060,10 @@ void QCocoaWindow::setWindowCursor(NSCursor *cursor) [cursor set]; // or we can set the cursor on mouse enter/leave using tracking // areas. This is done in QNSView, save the cursor: - m_windowCursor = cursor; + if (m_windowCursor != cursor) { + [m_windowCursor release]; + m_windowCursor = [cursor retain]; + } } void QCocoaWindow::registerTouch(bool enable) diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index f7b129aea1..e75b835d58 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -830,6 +830,12 @@ Q_GLOBAL_STATIC(QCocoaTabletDeviceDataHash, tabletDeviceDataHash) uint deviceId = [theEvent deviceID]; if (!tabletDeviceDataHash->contains(deviceId)) { + // 10.6 sends tablet events for trackpad interaction, but + // not proximity events. Silence the warning to prevent + // flooding the console. + if (QSysInfo::QSysInfo::MacintoshVersion == QSysInfo::MV_10_6) + return; + qWarning("QNSView handleTabletEvent: This tablet device is unknown" " (received no proximity event for it). Discarding event."); return; @@ -1346,6 +1352,11 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent) { Q_UNUSED(replacementRange) + if (m_sendKeyEvent && m_composingText.isEmpty()) { + // don't send input method events for simple text input (let handleKeyEvent send key events instead) + return; + } + QString commitString; if ([aString length]) { if ([aString isKindOfClass:[NSAttributedString class]]) { diff --git a/src/plugins/platforms/eglfs/qeglfshooks.h b/src/plugins/platforms/eglfs/qeglfshooks.h index 1cd1380994..0251e27f96 100644 --- a/src/plugins/platforms/eglfs/qeglfshooks.h +++ b/src/plugins/platforms/eglfs/qeglfshooks.h @@ -77,7 +77,8 @@ public: virtual bool filterConfig(EGLDisplay display, EGLConfig config) const; virtual void waitForVSync() const; - virtual const char *fbDeviceName() const; + virtual QByteArray fbDeviceName() const; + virtual int framebufferIndex() const; static QEglFSHooks *hooks() { diff --git a/src/plugins/platforms/eglfs/qeglfshooks_stub.cpp b/src/plugins/platforms/eglfs/qeglfshooks_stub.cpp index 4dc0783d43..4368f37e50 100644 --- a/src/plugins/platforms/eglfs/qeglfshooks_stub.cpp +++ b/src/plugins/platforms/eglfs/qeglfshooks_stub.cpp @@ -41,6 +41,7 @@ #include "qeglfshooks.h" #include "qeglfscursor.h" +#include <QtCore/QRegularExpression> #include <fcntl.h> #include <unistd.h> @@ -56,17 +57,34 @@ QT_BEGIN_NAMESPACE // this is a global static to keep the QEglFSHooks interface as clean as possible static int framebuffer = -1; -const char *QEglFSHooks::fbDeviceName() const +QByteArray QEglFSHooks::fbDeviceName() const { - return "/dev/fb0"; + QByteArray fbDev = qgetenv("QT_QPA_EGLFS_FB"); + if (fbDev.isEmpty()) + fbDev = QByteArrayLiteral("/dev/fb0"); + + return fbDev; +} + +int QEglFSHooks::framebufferIndex() const +{ + int fbIndex = 0; + QRegularExpression fbIndexRx(QLatin1String("fb(\\d+)")); + QRegularExpressionMatch match = fbIndexRx.match(fbDeviceName()); + if (match.hasMatch()) + fbIndex = match.captured(1).toInt(); + + return fbIndex; } void QEglFSHooks::platformInit() { - framebuffer = qt_safe_open(fbDeviceName(), O_RDONLY); + QByteArray fbDev = fbDeviceName(); + + framebuffer = qt_safe_open(fbDev, O_RDONLY); if (framebuffer == -1) - qWarning("EGLFS: Failed to open %s", fbDeviceName()); + qWarning("EGLFS: Failed to open %s", qPrintable(fbDev)); } void QEglFSHooks::platformDestroy() diff --git a/src/plugins/platforms/qnx/qqnxeglwindow.cpp b/src/plugins/platforms/qnx/qqnxeglwindow.cpp index b57227a60b..984de67d7d 100644 --- a/src/plugins/platforms/qnx/qqnxeglwindow.cpp +++ b/src/plugins/platforms/qnx/qqnxeglwindow.cpp @@ -63,6 +63,13 @@ QQnxEglWindow::QQnxEglWindow(QWindow *window, screen_context_t context, bool nee m_eglSurface(EGL_NO_SURFACE) { initWindow(); + + // Set window usage + const int val = SCREEN_USAGE_OPENGL_ES2; + const int result = screen_set_window_property_iv(nativeHandle(), SCREEN_PROPERTY_USAGE, &val); + if (result != 0) + qFatal("QQnxEglWindow: failed to set window alpha usage, errno=%d", errno); + m_requestedBufferSize = screen()->rootWindow() == this ? screen()->geometry().size() : window->geometry().size(); } diff --git a/src/plugins/platforms/qnx/qqnxrasterwindow.cpp b/src/plugins/platforms/qnx/qqnxrasterwindow.cpp index 1f974b268d..0d8daac0ee 100644 --- a/src/plugins/platforms/qnx/qqnxrasterwindow.cpp +++ b/src/plugins/platforms/qnx/qqnxrasterwindow.cpp @@ -60,6 +60,12 @@ QQnxRasterWindow::QQnxRasterWindow(QWindow *window, screen_context_t context, bo m_previousBufferIndex(-1) { initWindow(); + + // Set window usage + const int val = SCREEN_USAGE_NATIVE | SCREEN_USAGE_READ | SCREEN_USAGE_WRITE; + const int result = screen_set_window_property_iv(nativeHandle(), SCREEN_PROPERTY_USAGE, &val); + if (result != 0) + qFatal("QQnxEglWindow: failed to set window alpha usage, errno=%d", errno); } void QQnxRasterWindow::post(const QRegion &dirty) diff --git a/src/plugins/platforms/windows/qwindowskeymapper.cpp b/src/plugins/platforms/windows/qwindowskeymapper.cpp index 1baea6faff..334df17026 100644 --- a/src/plugins/platforms/windows/qwindowskeymapper.cpp +++ b/src/plugins/platforms/windows/qwindowskeymapper.cpp @@ -743,10 +743,10 @@ bool QWindowsKeyMapper::translateKeyEvent(QWindow *widget, HWND hwnd, return true; } - // WM_CHAR messages already contain the character in question so there is + // WM_(IME_)CHAR messages already contain the character in question so there is // no need to fiddle with our key map. In any other case add this key to the // keymap if it is not present yet. - if (msg.message != WM_CHAR) + if (msg.message != WM_CHAR && msg.message != WM_IME_CHAR) updateKeyMap(msg); MSG peekedMsg; diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp index a571f16eb6..a2ef8bf20f 100644 --- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp @@ -287,12 +287,14 @@ XInput2DeviceData *QXcbConnection::deviceForId(int id) return dev; } -#ifdef XCB_USE_XINPUT22 +#if defined(XCB_USE_XINPUT22) || !defined(QT_NO_TABLETEVENT) static qreal fixed1616ToReal(FP1616 val) { return (qreal(val >> 16)) + (val & 0xFF) / (qreal)0xFF; } +#endif +#ifdef XCB_USE_XINPUT22 static qreal valuatorNormalized(double value, XIValuatorClassInfo *vci) { if (value > vci->max) diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 59a81bcee9..45d8328997 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -1556,7 +1556,7 @@ void QXcbWindow::handleClientMessageEvent(const xcb_client_message_event_t *even handleXEmbedMessage(event); } else if (event->type == atom(QXcbAtom::_NET_ACTIVE_WINDOW)) { connection()->setFocusWindow(this); - QWindowSystemInterface::handleWindowActivated(window()); + QWindowSystemInterface::handleWindowActivated(window(), Qt::ActiveWindowFocusReason); } else if (event->type == atom(QXcbAtom::MANAGER) || event->type == atom(QXcbAtom::_NET_WM_STATE) || event->type == atom(QXcbAtom::WM_CHANGE_STATE)) { @@ -1865,14 +1865,14 @@ void QXcbWindow::handleFocusInEvent(const xcb_focus_in_event_t *) QWindow *w = window(); w = static_cast<QWindowPrivate *>(QObjectPrivate::get(w))->eventReceiver(); connection()->setFocusWindow(static_cast<QXcbWindow *>(w->handle())); - QWindowSystemInterface::handleWindowActivated(w); + QWindowSystemInterface::handleWindowActivated(w, Qt::ActiveWindowFocusReason); } static bool focusInPeeker(QXcbConnection *connection, xcb_generic_event_t *event) { if (!event) { // FocusIn event is not in the queue, proceed with FocusOut normally. - QWindowSystemInterface::handleWindowActivated(0); + QWindowSystemInterface::handleWindowActivated(0, Qt::ActiveWindowFocusReason); return true; } uint response_type = event->response_type & ~0x80; diff --git a/src/sql/doc/src/sql-driver.qdoc b/src/sql/doc/src/sql-driver.qdoc index 849cdcd544..f1fd2f6e90 100644 --- a/src/sql/doc/src/sql-driver.qdoc +++ b/src/sql/doc/src/sql-driver.qdoc @@ -175,73 +175,6 @@ built in release mode only. If you are expecting a debug version to be built as well, don't use the \c{"-o Makefile"} option. - \section3 How to build the MySQL driver for MinGW users - - The following steps have been used successfully for WinXP SP3. In - this example, Qt 4.6.2 is shown. - - \list - - \li Download the following components: - \list - \li \c{MinGW-5.1.6.exe} - \li \c{mingw-utils-0.3.tar.gz} - \li Qt sources, e.g. \c{qt-everywhere-opensource-src-4.6.2.zip} - \li \c{mysql-5.1.35-win32.msi} - \endlist - - \li Install \c{MinGW-5.1.6.exe} in, e.g. \c{C:\MinGW}. - - \li Extract \c{mingw-utils-0.3.tar.gz} into, e.g. \c{C:\MinGW}. - - \li Add the path for \c{MinGW-5.1.6.exe} to your \c{PATH} variable, - e.g. \c{C:\MinGW\bin;} - - \li Extract the Qt sources, (\c{qt-everywhere-opensource-src-4.6.2.zip}), - into, e.g. \c{C:\Qt}. - - \li Add the path for the eventual Qt binary to your \c{PATH} variable, - e.g. \c{C:\Qt\4.6.2\bin;}. - - \li Install MySQL (\c{mysql-5.1.35-win32.msi}), customizing the - components. Select only the headers and libraries. Install in, - e.g. \c{C:\MySQL\MySQL51}. - - \li Open the DOS prompt, go to \c{C:\MySQL\MySQL51\lib\opt}, and run - the following commands: - \list - \li \c{reimp -d libmysql.lib} - \li \c{dlltool -k -d libmysql.def -l libmysql.a} - \endlist - - \li Open the DOS prompt, go to \c{C:\Qt\4.6.2} and run the following commands: - \list - \li \c{configure.exe -debug-and-release -platform win32-g++ -qt-sql-mysql - -l mysql -I C:\MySQL\MySQL51\include -L C:\MySQL\MySQL51\lib\opt} - \li \c{mingw32-make sub-src} - \endlist - This step takes a long time. - - \li Open the DOS prompt, go to - \c{C:\Qt\4.6.2\src\plugins\sqldrivers\mysql} and run the - following command: - \list - \li \c{qmake "INCLUDEPATH+=C:/MySQL/MySQL51/include" "LIBS+=-L. mysql" mysql.pro} - \endlist - - \li Now the following libraries are ready in \c{C:\Qt\4.6.2\plugins\sqldrivers}. - \list - \li \c{libqsqlmysql4.a} - \li \c{libqsqlmysqld4.a} - \li \c{qsqlmysql4.dll} - \li \c{qsqlmysqld4.dll} - \endlist - To use the SDK and QtCreator directly, copy these libraries to - your \c{C:\Qt\...\qt\plugins\sqldrivers\}, and copy - \c{C:\MySQL\MySQL51\lib\opt\libmysql.dll} to your \c{C:\Qt\...\qt\bin\}. - - \endlist - \target QOCI \section2 QOCI for the Oracle Call Interface (OCI) diff --git a/src/sql/drivers/sqlite/qsql_sqlite.cpp b/src/sql/drivers/sqlite/qsql_sqlite.cpp index c98d6438fc..0b0731399e 100644 --- a/src/sql/drivers/sqlite/qsql_sqlite.cpp +++ b/src/sql/drivers/sqlite/qsql_sqlite.cpp @@ -609,7 +609,7 @@ bool QSQLiteDriver::open(const QString & db, const QString &, const QString &, c foreach (const QString &option, opts) { if (option.startsWith(QLatin1String("QSQLITE_BUSY_TIMEOUT="))) { bool ok; - const int nt = option.mid(21).toInt(&ok); + const int nt = option.midRef(21).toInt(&ok); if (ok) timeOut = nt; } else if (option == QLatin1String("QSQLITE_OPEN_READONLY")) { diff --git a/src/testlib/doc/qttestlib.qdocconf b/src/testlib/doc/qttestlib.qdocconf index 250d237f12..92e5c97aab 100644 --- a/src/testlib/doc/qttestlib.qdocconf +++ b/src/testlib/doc/qttestlib.qdocconf @@ -27,7 +27,7 @@ qhp.QtTestLib.subprojects.classes.sortPages = true tagfile = ../../../doc/qttestlib/qttestlib.tags -depends += qtcore qtdoc qtwidgets qtgui qtquick +depends += qtcore qtdoc qtwidgets qtgui qmake qtquick headerdirs += .. diff --git a/src/testlib/doc/src/qttestlib-manual.qdoc b/src/testlib/doc/src/qttestlib-manual.qdoc index 613d2c220c..bdd9769175 100644 --- a/src/testlib/doc/src/qttestlib-manual.qdoc +++ b/src/testlib/doc/src/qttestlib-manual.qdoc @@ -120,7 +120,7 @@ \snippet code/doc_src_qtestlib.pro 2 - See \l{qmake Common Projects#building-a-testcase}{the qmake manual} for + See the \l{Building a Testcase}{qmake manual} for more information about \c{make check}. If you are using other build tools, make sure that you add the location diff --git a/src/testlib/qtestkeyboard.h b/src/testlib/qtestkeyboard.h index 878806737e..d693d66db4 100644 --- a/src/testlib/qtestkeyboard.h +++ b/src/testlib/qtestkeyboard.h @@ -151,17 +151,17 @@ namespace QTest Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1) { sendKeyEvent(action, window, key, keyToAscii(key), modifier, delay); } - inline static void keyClick(QWindow *window, Qt::Key key, Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1) + Q_DECL_UNUSED inline static void keyClick(QWindow *window, Qt::Key key, Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1) { keyEvent(Click, window, key, modifier, delay); } - inline static void keyClick(QWindow *window, char key, Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1) + Q_DECL_UNUSED inline static void keyClick(QWindow *window, char key, Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1) { keyEvent(Click, window, key, modifier, delay); } - inline static void keyRelease(QWindow *window, char key, Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1) + Q_DECL_UNUSED inline static void keyRelease(QWindow *window, char key, Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1) { keyEvent(Release, window, key, modifier, delay); } - inline static void keyRelease(QWindow *window, Qt::Key key, Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1) + Q_DECL_UNUSED inline static void keyRelease(QWindow *window, Qt::Key key, Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1) { keyEvent(Release, window, key, modifier, delay); } - inline static void keyPress(QWindow *window, char key, Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1) + Q_DECL_UNUSED inline static void keyPress(QWindow *window, char key, Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1) { keyEvent(Press, window, key, modifier, delay); } - inline static void keyPress(QWindow *window, Qt::Key key, Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1) + Q_DECL_UNUSED inline static void keyPress(QWindow *window, Qt::Key key, Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1) { keyEvent(Press, window, key, modifier, delay); } #ifdef QT_WIDGETS_LIB diff --git a/src/testlib/qtestresult.cpp b/src/testlib/qtestresult.cpp index d94b2bf85c..a9abca0ef8 100644 --- a/src/testlib/qtestresult.cpp +++ b/src/testlib/qtestresult.cpp @@ -46,8 +46,10 @@ #include <QtTest/qtestdata.h> #include <QtTest/qtestassert.h> +#include <stdlib.h> #include <stdio.h> #include <string.h> +#include <wchar.h> QT_BEGIN_NAMESPACE @@ -268,8 +270,8 @@ bool QTestResult::compare(bool success, const char *failureMsg, if (success && QTest::expectFailMode) { qsnprintf(msg, 1024, "QCOMPARE(%s, %s) returned TRUE unexpectedly.", actual, expected); } else if (val1 || val2) { - size_t len1 = strlen(actual); - size_t len2 = strlen(expected); + size_t len1 = mbstowcs(NULL, actual, 0); + size_t len2 = mbstowcs(NULL, expected, 0); qsnprintf(msg, 1024, "%s\n Actual (%s)%*s %s\n Expected (%s)%*s %s", failureMsg, actual, qMax(len1, len2) - len1 + 1, ":", val1 ? val1 : "<null>", diff --git a/src/testlib/qtestsystem.h b/src/testlib/qtestsystem.h index 2a719e96f1..f859ff164d 100644 --- a/src/testlib/qtestsystem.h +++ b/src/testlib/qtestsystem.h @@ -56,7 +56,7 @@ QT_BEGIN_NAMESPACE namespace QTest { - inline static void qWait(int ms) + Q_DECL_UNUSED inline static void qWait(int ms) { Q_ASSERT(QCoreApplication::instance()); diff --git a/src/tools/moc/main.cpp b/src/tools/moc/main.cpp index 3ae6445093..0a5f6ec241 100644 --- a/src/tools/moc/main.cpp +++ b/src/tools/moc/main.cpp @@ -343,7 +343,8 @@ int runMoc(int argc, char **argv) parser.showHelp(1); } Macro macro; - macro.symbols += Symbol(0, PP_IDENTIFIER, value); + macro.symbols = Preprocessor::tokenize(value, 1, Preprocessor::TokenizeDefine); + macro.symbols.removeLast(); // remove the EOF symbol pp.macros.insert(name, macro); } foreach (const QString &arg, parser.values(undefineOption)) { diff --git a/src/tools/moc/preprocessor.cpp b/src/tools/moc/preprocessor.cpp index 3615262b67..2de495f010 100644 --- a/src/tools/moc/preprocessor.cpp +++ b/src/tools/moc/preprocessor.cpp @@ -158,8 +158,7 @@ bool Preprocessor::skipBranch() } -enum TokenizeMode { TokenizeCpp, TokenizePreprocessor, PreparePreprocessorStatement, TokenizePreprocessorStatement, TokenizeInclude, PrepareDefine, TokenizeDefine }; -static Symbols tokenize(const QByteArray &input, int lineNum = 1, TokenizeMode mode = TokenizeCpp) +Symbols Preprocessor::tokenize(const QByteArray& input, int lineNum, Preprocessor::TokenizeMode mode) { Symbols symbols; const char *begin = input.constData(); diff --git a/src/tools/moc/preprocessor.h b/src/tools/moc/preprocessor.h index dc7c98de85..6403955c1b 100644 --- a/src/tools/moc/preprocessor.h +++ b/src/tools/moc/preprocessor.h @@ -89,6 +89,8 @@ public: int evaluateCondition(); + enum TokenizeMode { TokenizeCpp, TokenizePreprocessor, PreparePreprocessorStatement, TokenizePreprocessorStatement, TokenizeInclude, PrepareDefine, TokenizeDefine }; + static Symbols tokenize(const QByteArray &input, int lineNum = 1, TokenizeMode mode = TokenizeCpp); private: void until(Token); diff --git a/src/tools/qdoc/doc/config/qdoc.qdocconf b/src/tools/qdoc/doc/config/qdoc.qdocconf index 992cec65dc..0f4ad07711 100644 --- a/src/tools/qdoc/doc/config/qdoc.qdocconf +++ b/src/tools/qdoc/doc/config/qdoc.qdocconf @@ -62,7 +62,6 @@ depends += \ qtsql \ qtsvg \ qttestlib \ - qttools \ qtuitools \ qtversit \ qtwidgets \ diff --git a/src/tools/qdoc/generator.cpp b/src/tools/qdoc/generator.cpp index 3cbba788c8..b14a79dfab 100644 --- a/src/tools/qdoc/generator.cpp +++ b/src/tools/qdoc/generator.cpp @@ -1013,12 +1013,13 @@ void Generator::generateInnerNode(InnerNode* node) } } - NodeList::ConstIterator c = node->childNodes().constBegin(); - while (c != node->childNodes().constEnd()) { - if ((*c)->isInnerNode() && (*c)->access() != Node::Private) { - generateInnerNode((InnerNode*)*c); + int i = 0; + while (i < node->childNodes().count()) { + Node *c = node->childNodes().at(i); + if (c->isInnerNode() && c->access() != Node::Private) { + generateInnerNode((InnerNode*)c); } - ++c; + ++i; } } diff --git a/src/widgets/doc/snippets/code/src_gui_kernel_qwidget.cpp b/src/widgets/doc/snippets/code/src_gui_kernel_qwidget.cpp index 338817ea74..70e3090cde 100644 --- a/src/widgets/doc/snippets/code/src_gui_kernel_qwidget.cpp +++ b/src/widgets/doc/snippets/code/src_gui_kernel_qwidget.cpp @@ -44,7 +44,7 @@ w->setWindowState(w->windowState() ^ Qt::WindowFullScreen); //! [1] -w->setWindowState(w->windowState() & ~Qt::WindowMinimized | Qt::WindowActive); +w->setWindowState((w->windowState() & ~Qt::WindowMinimized) | Qt::WindowActive); //! [1] diff --git a/src/widgets/graphicsview/qgraphicswidget.cpp b/src/widgets/graphicsview/qgraphicswidget.cpp index ccc51120a9..40d32ea1d5 100644 --- a/src/widgets/graphicsview/qgraphicswidget.cpp +++ b/src/widgets/graphicsview/qgraphicswidget.cpp @@ -2274,7 +2274,7 @@ void QGraphicsWidget::paintWindowFrame(QPainter *painter, const QStyleOptionGrap const QPointF styleOrigin = this->windowFrameRect().topLeft(); painter->translate(styleOrigin); -#ifdef Q_WS_MAC +#ifdef Q_OS_MAC const QSize pixmapSize = windowFrameRect.size(); if (pixmapSize.width() <= 0 || pixmapSize.height() <= 0) return; @@ -2342,7 +2342,7 @@ void QGraphicsWidget::paintWindowFrame(QPainter *painter, const QStyleOptionGrap frameOptions.midLineWidth = 1; style()->drawPrimitive(QStyle::PE_FrameWindow, &frameOptions, painter, widget); -#ifdef Q_WS_MAC +#ifdef Q_OS_MAC realPainter->drawPixmap(QPoint(), pm); delete painter; #endif diff --git a/src/widgets/itemviews/qlistview.cpp b/src/widgets/itemviews/qlistview.cpp index 8238e5f6d4..135f89d4ac 100644 --- a/src/widgets/itemviews/qlistview.cpp +++ b/src/widgets/itemviews/qlistview.cpp @@ -1842,18 +1842,18 @@ void QCommonListViewBase::paintDragDrop(QPainter *painter) } #endif -void QCommonListViewBase::updateHorizontalScrollBar(const QSize & /*step*/) +void QCommonListViewBase::updateHorizontalScrollBar(const QSize &step) { + horizontalScrollBar()->setSingleStep(step.width() + spacing()); horizontalScrollBar()->setPageStep(viewport()->width()); horizontalScrollBar()->setRange(0, contentsSize.width() - viewport()->width()); - // we do not want to overwrite (a possible user set) single step } -void QCommonListViewBase::updateVerticalScrollBar(const QSize & /*step*/) +void QCommonListViewBase::updateVerticalScrollBar(const QSize &step) { + verticalScrollBar()->setSingleStep(step.height() + spacing()); verticalScrollBar()->setPageStep(viewport()->height()); verticalScrollBar()->setRange(0, contentsSize.height() - viewport()->height()); - // we do not want to overwrite (a possible user set) single step } void QCommonListViewBase::scrollContentsBy(int dx, int dy, bool /*scrollElasticBand*/) diff --git a/src/widgets/itemviews/qtableview.cpp b/src/widgets/itemviews/qtableview.cpp index 08600b3ef7..a252428a81 100644 --- a/src/widgets/itemviews/qtableview.cpp +++ b/src/widgets/itemviews/qtableview.cpp @@ -2170,7 +2170,7 @@ void QTableView::updateGeometries() } else { // ScrollPerPixel horizontalScrollBar()->setPageStep(vsize.width()); horizontalScrollBar()->setRange(0, horizontalLength - vsize.width()); - // here we do not want to overwrite (a possible user set) single step + horizontalScrollBar()->setSingleStep(qMax(vsize.width() / (columnsInViewport + 1), 2)); } // vertical scroll bar @@ -2198,7 +2198,7 @@ void QTableView::updateGeometries() } else { // ScrollPerPixel verticalScrollBar()->setPageStep(vsize.height()); verticalScrollBar()->setRange(0, verticalLength - vsize.height()); - // here we do not want to overwrite (a possible user set) single step + verticalScrollBar()->setSingleStep(qMax(vsize.height() / (rowsInViewport + 1), 2)); } d->geometryRecursionBlock = false; diff --git a/src/widgets/itemviews/qtreeview.cpp b/src/widgets/itemviews/qtreeview.cpp index 4d0eb5c3ad..5d0e835b0e 100644 --- a/src/widgets/itemviews/qtreeview.cpp +++ b/src/widgets/itemviews/qtreeview.cpp @@ -3685,7 +3685,7 @@ void QTreeViewPrivate::updateScrollBars() } vbar->setRange(0, contentsHeight - viewportSize.height()); vbar->setPageStep(viewportSize.height()); - // here we do not want to overwrite (a possible user set) single step + vbar->setSingleStep(qMax(viewportSize.height() / (itemsInViewport + 1), 2)); } const int columnCount = header->count(); @@ -3711,7 +3711,7 @@ void QTreeViewPrivate::updateScrollBars() viewportSize = maxSize; hbar->setPageStep(viewportSize.width()); hbar->setRange(0, qMax(horizontalLength - viewportSize.width(), 0)); - // here we do not want to overwrite (a possible user set) single step + hbar->setSingleStep(qMax(viewportSize.width() / (columnsInViewport + 1), 2)); } } diff --git a/src/widgets/styles/qmacstyle_mac.mm b/src/widgets/styles/qmacstyle_mac.mm index d13339b555..fa49bcb884 100644 --- a/src/widgets/styles/qmacstyle_mac.mm +++ b/src/widgets/styles/qmacstyle_mac.mm @@ -2077,6 +2077,10 @@ int QMacStyle::pixelMetric(PixelMetric metric, const QStyleOption *opt, const QW ret = 0; break; + case PM_MenuBarPanelWidth: + ret = 0; + break; + case QStyle::PM_MenuDesktopFrameWidth: ret = 5; break; @@ -6259,6 +6263,10 @@ QSize QMacStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt, sz = QSize(w, h); } break; + case CT_MenuBarItem: + if (!sz.isEmpty()) + sz += QSize(12, 4); // Constants from QWindowsStyle + break; case CT_ToolButton: sz.rwidth() += 10; sz.rheight() += 10; diff --git a/src/widgets/styles/qstylesheetstyle.cpp b/src/widgets/styles/qstylesheetstyle.cpp index 2f36e0e53c..6bd0ba37c8 100644 --- a/src/widgets/styles/qstylesheetstyle.cpp +++ b/src/widgets/styles/qstylesheetstyle.cpp @@ -4710,7 +4710,9 @@ int QStyleSheetStyle::pixelMetric(PixelMetric m, const QStyleOption *opt, const break; case PM_TabBarBaseOverlap: { - const QWidget *tabWidget = qobject_cast<const QTabWidget *>(w) ? w : w->parentWidget(); + const QWidget *tabWidget = qobject_cast<const QTabWidget *>(w); + if (!tabWidget && w) + tabWidget = w->parentWidget(); if (hasStyleRule(tabWidget, PseudoElement_TabWidgetPane)) { return 0; } diff --git a/src/widgets/styles/qwindowsvistastyle.cpp b/src/widgets/styles/qwindowsvistastyle.cpp index 2f36944b5e..af379b756e 100644 --- a/src/widgets/styles/qwindowsvistastyle.cpp +++ b/src/widgets/styles/qwindowsvistastyle.cpp @@ -1879,7 +1879,11 @@ void QWindowsVistaStyle::drawComplexControl(ComplexControl control, const QStyle XPThemeData ftheme(widget, painter, QWindowsXPStylePrivate::EditTheme, partId, stateId, r); - ftheme.noContent = true; + // The spinbox in Windows QStyle is drawn with frameless QLineEdit inside it + // That however breaks with QtQuickControls where this results in transparent + // spinbox background, so if there's no "widget" passed (QtQuickControls case), + // let ftheme.noContent be false, which fixes the spinbox rendering in QQC + ftheme.noContent = (widget != NULL); d->drawBackground(ftheme); } if (sub & SC_SpinBoxUp) { diff --git a/src/widgets/widgets/qmainwindow.cpp b/src/widgets/widgets/qmainwindow.cpp index 0638981a9c..07db78c06c 100644 --- a/src/widgets/widgets/qmainwindow.cpp +++ b/src/widgets/widgets/qmainwindow.cpp @@ -60,6 +60,9 @@ #include <private/qwidget_p.h> #include "qtoolbar_p.h" #include "qwidgetanimator_p.h" +#ifdef Q_OS_OSX +#include <qpa/qplatformnativeinterface.h> +#endif #ifdef Q_WS_MAC #include <private/qt_mac_p.h> #include <private/qt_cocoa_helpers_mac_p.h> @@ -76,6 +79,9 @@ class QMainWindowPrivate : public QWidgetPrivate public: inline QMainWindowPrivate() : layout(0), explicitIconSize(false), toolButtonStyle(Qt::ToolButtonIconOnly) +#ifdef Q_OS_OSX + , useUnifiedToolBar(false) +#endif #ifdef Q_WS_MAC , useHIToolBar(false) , activateUnifiedToolbarAfterFullScreen(false) @@ -88,6 +94,9 @@ public: QSize iconSize; bool explicitIconSize; Qt::ToolButtonStyle toolButtonStyle; +#ifdef Q_OS_OSX + bool useUnifiedToolBar; +#endif #ifdef Q_WS_MAC bool useHIToolBar; bool activateUnifiedToolbarAfterFullScreen; @@ -1492,16 +1501,29 @@ bool QMainWindow::event(QEvent *event) /*! \property QMainWindow::unifiedTitleAndToolBarOnMac \brief whether the window uses the unified title and toolbar look on Mac OS X - \since 4.3 - \obsolete - - This property is not implemented in Qt 5. Setting it has no effect. - - A replacement API (QtMacUnifiedToolBar) is available in QtMacExtras at - http://qt.gitorious.org/qtplayground/qtmacextras + \since 5.2 */ void QMainWindow::setUnifiedTitleAndToolBarOnMac(bool set) { +#ifdef Q_OS_OSX + Q_D(QMainWindow); + if (isWindow()) { + QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface(); + QPlatformNativeInterface::NativeResourceForIntegrationFunction function = + nativeInterface->nativeResourceFunctionForIntegration("setContentBorderThickness"); + if (!function) + return; // Not Cocoa platform plugin. + + createWinId(); + + d->useUnifiedToolBar = set; + + const int toolBarHeight = 50; + typedef void (*SetContentBorderThicknessFunction)(QWindow *window, int topThickness, int bottomThickness); + (reinterpret_cast<SetContentBorderThicknessFunction>(function))(window()->windowHandle(), toolBarHeight, 0); + } +#endif + #ifdef Q_WS_MAC Q_D(QMainWindow); if (!isWindow() || d->useHIToolBar == set || QSysInfo::MacintoshVersion < QSysInfo::MV_10_3) @@ -1534,6 +1556,9 @@ void QMainWindow::setUnifiedTitleAndToolBarOnMac(bool set) bool QMainWindow::unifiedTitleAndToolBarOnMac() const { +#ifdef Q_OS_OSX + return d_func()->useUnifiedToolBar; +#endif #ifdef Q_WS_MAC return d_func()->useHIToolBar && !testAttribute(Qt::WA_MacBrushedMetal) && !(windowFlags() & Qt::FramelessWindowHint); #endif @@ -1655,9 +1680,7 @@ QMenu *QMainWindow::createPopupMenu() for (int i = 0; i < toolbars.size(); ++i) { QToolBar *toolBar = toolbars.at(i); if (toolBar->parentWidget() == this - && (!d->layout->layoutState.toolBarAreaLayout.indexOf(toolBar).isEmpty() - || (unifiedTitleAndToolBarOnMac() - && toolBarArea(toolBar) == Qt::TopToolBarArea))) { + && (!d->layout->layoutState.toolBarAreaLayout.indexOf(toolBar).isEmpty())) { menu->addAction(toolbars.at(i)->toggleViewAction()); } } diff --git a/src/widgets/widgets/qtextedit.cpp b/src/widgets/widgets/qtextedit.cpp index 49e05e8e14..e47abace4d 100644 --- a/src/widgets/widgets/qtextedit.cpp +++ b/src/widgets/widgets/qtextedit.cpp @@ -2042,7 +2042,7 @@ QList<QTextEdit::ExtraSelection> QTextEdit::extraSelections() const This function returns a new MIME data object to represent the contents of the text edit's current selection. It is called when the selection needs to be encapsulated into a new QMimeData object; for example, when a drag - and drop operation is started, or when data is copyied to the clipboard. + and drop operation is started, or when data is copied to the clipboard. If you reimplement this function, note that the ownership of the returned QMimeData object is passed to the caller. The selection can be retrieved diff --git a/src/widgets/widgets/qtoolbararealayout.cpp b/src/widgets/widgets/qtoolbararealayout.cpp index 04ef6a80be..5ec76569aa 100644 --- a/src/widgets/widgets/qtoolbararealayout.cpp +++ b/src/widgets/widgets/qtoolbararealayout.cpp @@ -655,9 +655,7 @@ QRect QToolBarAreaLayout::fitLayout() docks[QInternal::BottomDock].rect = QRect(rect.left(), center.bottom() + 1, rect.width(), bottom_hint.height()); - if (!mainWindow->unifiedTitleAndToolBarOnMac()) { - docks[QInternal::TopDock].fitLayout(); - } + docks[QInternal::TopDock].fitLayout(); docks[QInternal::LeftDock].fitLayout(); docks[QInternal::RightDock].fitLayout(); docks[QInternal::BottomDock].fitLayout(); @@ -1307,8 +1305,6 @@ bool QToolBarAreaLayout::restoreState(QDataStream &stream, const QList<QToolBar* QList<QToolBar*> toolBars = _toolBars; int lines; stream >> lines; - if (!testing) - testing = mainWindow->unifiedTitleAndToolBarOnMac(); for (int j = 0; j < lines; ++j) { int pos; @@ -1319,7 +1315,7 @@ bool QToolBarAreaLayout::restoreState(QDataStream &stream, const QList<QToolBar* stream >> cnt; QToolBarAreaLayoutInfo &dock = docks[pos]; - const bool applyingLayout = !testing && !(pos == QInternal::TopDock && mainWindow->unifiedTitleAndToolBarOnMac()); + const bool applyingLayout = !testing; QToolBarAreaLayoutLine line(dock.o); for (int k = 0; k < cnt; ++k) { diff --git a/tests/auto/corelib/animation/qpauseanimation/tst_qpauseanimation.cpp b/tests/auto/corelib/animation/qpauseanimation/tst_qpauseanimation.cpp index 529069552b..419fa1af20 100644 --- a/tests/auto/corelib/animation/qpauseanimation/tst_qpauseanimation.cpp +++ b/tests/auto/corelib/animation/qpauseanimation/tst_qpauseanimation.cpp @@ -262,7 +262,7 @@ void tst_QPauseAnimation::pauseResume() QTRY_COMPARE(animation.state(), QAbstractAnimation::Stopped); #ifdef Q_OS_WIN - if (animation.m_updateCurrentTimeCount != 3) + if (animation.m_updateCurrentTimeCount < 3) QEXPECT_FAIL("", winTimerError, Abort); #endif QVERIFY2(animation.m_updateCurrentTimeCount >= 3, qPrintable( diff --git a/tests/auto/corelib/io/qdir/tst_qdir.cpp b/tests/auto/corelib/io/qdir/tst_qdir.cpp index fbb21e4e9a..2bac6f5834 100644 --- a/tests/auto/corelib/io/qdir/tst_qdir.cpp +++ b/tests/auto/corelib/io/qdir/tst_qdir.cpp @@ -193,6 +193,8 @@ private slots: void isReadable(); + void cdNonreadable(); + void cdBelowRoot(); private: @@ -1096,6 +1098,10 @@ void tst_QDir::absoluteFilePath_data() QTest::newRow("2") << "/" << "passwd" << "/passwd"; QTest::newRow("3") << "relative" << "path" << QDir::currentPath() + "/relative/path"; QTest::newRow("4") << "" << "" << QDir::currentPath(); +#ifdef Q_OS_WIN + QTest::newRow("5") << "//machine" << "share" << "//machine/share"; +#endif + QTest::newRow("resource") << ":/prefix" << "foo.bar" << ":/prefix/foo.bar"; } @@ -1990,6 +1996,23 @@ void tst_QDir::isReadable() #endif } +void tst_QDir::cdNonreadable() +{ +#ifdef Q_OS_UNIX + if (::getuid() == 0) + QSKIP("Running this test as root doesn't make sense"); + + QDir dir; + QVERIFY(dir.mkdir("nonreadabledir2")); + QVERIFY(0 == ::chmod("nonreadabledir2", S_IWUSR | S_IXUSR)); + QVERIFY(dir.cd("nonreadabledir2")); + QVERIFY(!dir.isReadable()); + QVERIFY(dir.cd("..")); + QVERIFY(0 == ::chmod("nonreadabledir2", S_IRUSR | S_IWUSR | S_IXUSR)); + QVERIFY(dir.rmdir("nonreadabledir2")); +#endif +} + void tst_QDir::cdBelowRoot() { #if defined (Q_OS_UNIX) diff --git a/tests/auto/corelib/io/qstandardpaths/tst_qstandardpaths.cpp b/tests/auto/corelib/io/qstandardpaths/tst_qstandardpaths.cpp index 35a59401b7..21dfa5a962 100644 --- a/tests/auto/corelib/io/qstandardpaths/tst_qstandardpaths.cpp +++ b/tests/auto/corelib/io/qstandardpaths/tst_qstandardpaths.cpp @@ -52,7 +52,7 @@ #include <sys/types.h> #endif -#if defined(Q_OS_UNIX) && !defined(Q_OS_MAC) && !defined(Q_OS_BLACKBERRY) +#if defined(Q_OS_UNIX) && !defined(Q_OS_MAC) && !defined(Q_OS_BLACKBERRY) && !defined(Q_OS_ANDROID) #define Q_XDG_PLATFORM #endif @@ -289,9 +289,9 @@ void tst_qstandardpaths::testDataLocation() { // On all platforms, DataLocation should be GenericDataLocation / organization name / app name // This allows one app to access the data of another app. - // Blackberry OS is an exception to this case, owing to the fact that + // Blackberry OS and Android are exceptions to this case, owing to the fact that // applications are sandboxed. -#ifndef Q_OS_BLACKBERRY +#if !defined(Q_OS_BLACKBERRY) && !defined(Q_OS_ANDROID) const QString base = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation); QCOMPARE(QStandardPaths::writableLocation(QStandardPaths::DataLocation), base + "/tst_qstandardpaths"); QCoreApplication::instance()->setOrganizationName("Qt"); diff --git a/tests/auto/corelib/mimetypes/qmimedatabase/qmimedatabase.pro b/tests/auto/corelib/mimetypes/qmimedatabase/qmimedatabase.pro index 1ff5546e5c..536a6b64de 100644 --- a/tests/auto/corelib/mimetypes/qmimedatabase/qmimedatabase.pro +++ b/tests/auto/corelib/mimetypes/qmimedatabase/qmimedatabase.pro @@ -1,3 +1,3 @@ TEMPLATE = subdirs SUBDIRS = qmimedatabase-xml -unix:!mac: SUBDIRS += qmimedatabase-cache +unix:!mac:!qnx: SUBDIRS += qmimedatabase-cache diff --git a/tests/auto/corelib/tools/qstring/tst_qstring.cpp b/tests/auto/corelib/tools/qstring/tst_qstring.cpp index 48874781c0..12fe5259d9 100644 --- a/tests/auto/corelib/tools/qstring/tst_qstring.cpp +++ b/tests/auto/corelib/tools/qstring/tst_qstring.cpp @@ -4419,6 +4419,62 @@ void tst_QString::operator_smaller() // operator< is not locale-aware (or shouldn't be) QVERIFY( foo < QString("\xc3\xa9") ); QVERIFY( foo < "\xc3\xa9" ); + + QVERIFY(QString("a") < QString("b")); + QVERIFY(QString("a") <= QString("b")); + QVERIFY(QString("a") <= QString("a")); + QVERIFY(QString("a") == QString("a")); + QVERIFY(QString("a") >= QString("a")); + QVERIFY(QString("b") >= QString("a")); + QVERIFY(QString("b") > QString("a")); + + QVERIFY("a" < QString("b")); + QVERIFY("a" <= QString("b")); + QVERIFY("a" <= QString("a")); + QVERIFY("a" == QString("a")); + QVERIFY("a" >= QString("a")); + QVERIFY("b" >= QString("a")); + QVERIFY("b" > QString("a")); + + QVERIFY(QString("a") < "b"); + QVERIFY(QString("a") <= "b"); + QVERIFY(QString("a") <= "a"); + QVERIFY(QString("a") == "a"); + QVERIFY(QString("a") >= "a"); + QVERIFY(QString("b") >= "a"); + QVERIFY(QString("b") > "a"); + + QVERIFY(QLatin1String("a") < QString("b")); + QVERIFY(QLatin1String("a") <= QString("b")); + QVERIFY(QLatin1String("a") <= QString("a")); + QVERIFY(QLatin1String("a") == QString("a")); + QVERIFY(QLatin1String("a") >= QString("a")); + QVERIFY(QLatin1String("b") >= QString("a")); + QVERIFY(QLatin1String("b") > QString("a")); + + QVERIFY(QString("a") < QLatin1String("b")); + QVERIFY(QString("a") <= QLatin1String("b")); + QVERIFY(QString("a") <= QLatin1String("a")); + QVERIFY(QString("a") == QLatin1String("a")); + QVERIFY(QString("a") >= QLatin1String("a")); + QVERIFY(QString("b") >= QLatin1String("a")); + QVERIFY(QString("b") > QLatin1String("a")); + + QVERIFY("a" < QLatin1String("b")); + QVERIFY("a" <= QLatin1String("b")); + QVERIFY("a" <= QLatin1String("a")); + QVERIFY("a" == QLatin1String("a")); + QVERIFY("a" >= QLatin1String("a")); + QVERIFY("b" >= QLatin1String("a")); + QVERIFY("b" > QLatin1String("a")); + + QVERIFY(QLatin1String("a") < "b"); + QVERIFY(QLatin1String("a") <= "b"); + QVERIFY(QLatin1String("a") <= "a"); + QVERIFY(QLatin1String("a") == "a"); + QVERIFY(QLatin1String("a") >= "a"); + QVERIFY(QLatin1String("b") >= "a"); + QVERIFY(QLatin1String("b") > "a"); } void tst_QString::integer_conversion_data() diff --git a/tests/auto/corelib/tools/qvector/tst_qvector.cpp b/tests/auto/corelib/tools/qvector/tst_qvector.cpp index 53caec4a64..59956e33cf 100644 --- a/tests/auto/corelib/tools/qvector/tst_qvector.cpp +++ b/tests/auto/corelib/tools/qvector/tst_qvector.cpp @@ -2042,6 +2042,9 @@ void tst_QVector::initializeList() QVector<QVector<T>> v3; v3 << v1 << (QVector<T>() << val4) << QVector<T>() << v1; QCOMPARE(v3, v2); + + QVector<T> v4({}); + QCOMPARE(v4.size(), 0); #endif } diff --git a/tests/auto/gui/image/qicon/tst_qicon.cpp b/tests/auto/gui/image/qicon/tst_qicon.cpp index 2ce6fc5058..bfe2fbc9f7 100644 --- a/tests/auto/gui/image/qicon/tst_qicon.cpp +++ b/tests/auto/gui/image/qicon/tst_qicon.cpp @@ -594,7 +594,9 @@ void tst_QIcon::fromTheme() QCOMPARE(appointmentIcon.pixmap(22).size(), QSize(22, 22)); // exact QCOMPARE(appointmentIcon.pixmap(32).size(), QSize(32, 32)); // exact QCOMPARE(appointmentIcon.pixmap(48).size(), QSize(32, 32)); // smaller + QCOMPARE(appointmentIcon.pixmap(16).size(), QSize(16, 16)); // scaled down QCOMPARE(appointmentIcon.pixmap(8).size(), QSize(8, 8)); // scaled down + QCOMPARE(appointmentIcon.pixmap(16).size(), QSize(16, 16)); // scaled down QByteArray ba; // write to QByteArray diff --git a/tests/auto/gui/kernel/qguivariant/test/tst_qguivariant.cpp b/tests/auto/gui/kernel/qguivariant/test/tst_qguivariant.cpp index 42570751fc..7512829e09 100644 --- a/tests/auto/gui/kernel/qguivariant/test/tst_qguivariant.cpp +++ b/tests/auto/gui/kernel/qguivariant/test/tst_qguivariant.cpp @@ -640,7 +640,7 @@ void tst_QGuiVariant::writeToReadFromOldDataStream() dataFileStream.setVersion(QDataStream::Qt_4_9); QVariant readVariant; dataFileStream >> readVariant; - QVERIFY(readVariant.type() == QMetaType::QPolygonF); + QVERIFY(readVariant.userType() == QMetaType::QPolygonF); QCOMPARE(testVariant, readVariant); file.close(); } diff --git a/tests/auto/network/kernel/qhostinfo/qhostinfo.pro b/tests/auto/network/kernel/qhostinfo/qhostinfo.pro index c21e73ccee..b6f5c2badb 100644 --- a/tests/auto/network/kernel/qhostinfo/qhostinfo.pro +++ b/tests/auto/network/kernel/qhostinfo/qhostinfo.pro @@ -3,6 +3,7 @@ TARGET = tst_qhostinfo SOURCES += tst_qhostinfo.cpp +requires(contains(QT_CONFIG,private_tests)) QT = core-private network-private testlib wince*: { diff --git a/tests/auto/network/socket/qhttpsocketengine/qhttpsocketengine.pro b/tests/auto/network/socket/qhttpsocketengine/qhttpsocketengine.pro index 414486f82b..009d151e29 100644 --- a/tests/auto/network/socket/qhttpsocketengine/qhttpsocketengine.pro +++ b/tests/auto/network/socket/qhttpsocketengine/qhttpsocketengine.pro @@ -7,6 +7,7 @@ include(../platformsocketengine/platformsocketengine.pri) MOC_DIR=tmp +requires(contains(QT_CONFIG,private_tests)) QT = core-private network-private testlib DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp index a15daf660a..d19e08178a 100644 --- a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp +++ b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp @@ -1924,9 +1924,6 @@ void tst_QSslSocket::verifyMode() loop.exec(); QVERIFY(clientSocket.isEncrypted()); -#if (defined(UBUNTU_ONEIRIC) && defined(__x86_64__)) || defined(Q_OS_WIN) || defined(Q_OS_MAC) - QEXPECT_FAIL("", "QTBUG-24234", Abort); -#endif QVERIFY(server.socket->sslErrors().isEmpty()); } diff --git a/tests/auto/tools/moc/moc.pro b/tests/auto/tools/moc/moc.pro index 779e992881..9a3fee38f0 100644 --- a/tests/auto/tools/moc/moc.pro +++ b/tests/auto/tools/moc/moc.pro @@ -42,3 +42,6 @@ DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 # Ensure that plugin_metadata.h are moc-ed with some extra -M arguments: QMAKE_MOC_OPTIONS += -Muri=com.company.app -Muri=com.company.app.private +# Define macro on the command lines used in parse-defines.h +QMAKE_MOC_OPTIONS += "-DDEFINE_CMDLINE_EMPTY=" "\"-DDEFINE_CMDLINE_SIGNAL=void cmdlineSignal(const QMap<int, int> &i)\"" + diff --git a/tests/auto/tools/moc/parse-defines.h b/tests/auto/tools/moc/parse-defines.h index aaadcef601..35934853f0 100644 --- a/tests/auto/tools/moc/parse-defines.h +++ b/tests/auto/tools/moc/parse-defines.h @@ -79,9 +79,16 @@ #define PD_ADD_SUFFIX(x) PD_DEFINE1(x,_SUFFIX) #define PD_DEFINE_ITSELF PD_ADD_SUFFIX(PD_DEFINE_ITSELF) +#ifndef Q_MOC_RUN +// macro defined on the command line (in tst_moc.pro) +#define DEFINE_CMDLINE_EMPTY +#define DEFINE_CMDLINE_SIGNAL void cmdlineSignal(const QMap<int, int> &i) +#endif + PD_BEGIN_NAMESPACE -class PD_CLASSNAME : public QObject +class DEFINE_CMDLINE_EMPTY PD_CLASSNAME DEFINE_CMDLINE_EMPTY + : public DEFINE_CMDLINE_EMPTY QObject DEFINE_CMDLINE_EMPTY { Q_OBJECT Q_CLASSINFO("TestString", PD_STRINGIFY(PD_CLASSNAME)) @@ -140,6 +147,9 @@ public slots: void PD_DEFINE_ITSELF(int) {} +signals: + DEFINE_CMDLINE_SIGNAL; + }; #undef QString diff --git a/tests/auto/tools/moc/tst_moc.cpp b/tests/auto/tools/moc/tst_moc.cpp index 7fae29e5ca..8ce55cbdf5 100644 --- a/tests/auto/tools/moc/tst_moc.cpp +++ b/tests/auto/tools/moc/tst_moc.cpp @@ -3037,6 +3037,9 @@ void tst_Moc::parseDefines() index = mo->indexOfSlot("PD_DEFINE_ITSELF_SUFFIX(int)"); QVERIFY(index != -1); + + index = mo->indexOfSignal("cmdlineSignal(QMap<int,int>)"); + QVERIFY(index != -1); } void tst_Moc::preprocessorOnly() diff --git a/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp b/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp index 97ea7d7d32..d4aad98ae9 100644 --- a/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp +++ b/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp @@ -1286,6 +1286,7 @@ void tst_QAbstractItemView::task200665_itemEntered() QVERIFY(QTest::qWaitForWindowExposed(&view)); QRect rect = view.visualRect(model.index(0,0)); QCursor::setPos( view.viewport()->mapToGlobal(rect.center()) ); + QCoreApplication::processEvents(); QSignalSpy spy(&view, SIGNAL(entered(QModelIndex))); view.verticalScrollBar()->setValue(view.verticalScrollBar()->maximum()); diff --git a/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp b/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp index 76ac6bcf19..dfb780c8fa 100644 --- a/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp +++ b/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp @@ -3702,7 +3702,7 @@ void tst_QTableView::mouseWheel_data() << 10 + qApp->wheelScrollLines() << 10 + qApp->wheelScrollLines(); QTest::newRow("scroll down per pixel") << int(QAbstractItemView::ScrollPerPixel) << -120 - << 10 + qApp->wheelScrollLines() << 10 + qApp->wheelScrollLines(); + << 10 + qApp->wheelScrollLines() * 89 << 10 + qApp->wheelScrollLines() * 28; } void tst_QTableView::mouseWheel() diff --git a/tests/manual/qnetworkreply/main.cpp b/tests/manual/qnetworkreply/main.cpp index 2f47985261..fe667e92a0 100644 --- a/tests/manual/qnetworkreply/main.cpp +++ b/tests/manual/qnetworkreply/main.cpp @@ -47,6 +47,8 @@ #include <QtNetwork/qnetworkrequest.h> #include <QtNetwork/qnetworkaccessmanager.h> #include <QtNetwork/qsslconfiguration.h> +#include <QtNetwork/qhttpmultipart.h> +#include <QtCore/QJsonDocument> #include "../../auto/network-settings.h" #if defined(QT_BUILD_INTERNAL) && !defined(QT_NO_SSL) @@ -65,6 +67,9 @@ private slots: void limiting(); void setSslConfiguration_data(); void setSslConfiguration(); + void uploadToFacebook(); +private: + QHttpMultiPart *createFacebookMultiPart(const QByteArray &accessToken); }; QNetworkReply *reply; @@ -177,6 +182,108 @@ void tst_qnetworkreply::setSslConfiguration() #endif // QT_NO_SSL } +QHttpMultiPart *tst_qnetworkreply::createFacebookMultiPart(const QByteArray &accessToken) +{ + QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType); + QHttpPart accessTokenPart; + accessTokenPart.setHeader(QNetworkRequest::ContentDispositionHeader, + QVariant("form-data; name=\"access_token\"")); + accessTokenPart.setBody(accessToken); + multiPart->append(accessTokenPart); + + QHttpPart batchPart; + batchPart.setHeader(QNetworkRequest::ContentDispositionHeader, + QVariant("form-data; name=\"batch\"")); + batchPart.setBody("[" +" {" +" \"attached_files\" : \"image1\"," +" \"body\" : \"message=&published=0\"," +" \"method\" : \"POST\"," +" \"relative_url\" : \"me/photos\"" +" }," +" {" +" \"attached_files\" : \"image2\"," +" \"body\" : \"message=&published=0\"," +" \"method\" : \"POST\"," +" \"relative_url\" : \"me/photos\"" +" }," +" {" +" \"attached_files\" : \"image3\"," +" \"body\" : \"message=&published=0\"," +" \"method\" : \"POST\"," +" \"relative_url\" : \"me/photos\"" +" }" +"]"); + multiPart->append(batchPart); + + QHttpPart imagePart1; + imagePart1.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("image/jpg")); + imagePart1.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"image1\"; filename=\"image1.jpg\"")); + QFile *file1 = new QFile(QFINDTESTDATA("../../auto/network/access/qnetworkreply/image1.jpg")); + file1->open(QIODevice::ReadOnly); + imagePart1.setBodyDevice(file1); + file1->setParent(multiPart); + + multiPart->append(imagePart1); + + QHttpPart imagePart2; + imagePart2.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("image/jpg")); + imagePart2.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"image2\"; filename=\"image2.jpg\"")); + QFile *file2 = new QFile(QFINDTESTDATA("../../auto/network/access/qnetworkreply/image2.jpg")); + file2->open(QIODevice::ReadOnly); + imagePart2.setBodyDevice(file2); + file2->setParent(multiPart); + + multiPart->append(imagePart2); + + QHttpPart imagePart3; + imagePart3.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("image/jpg")); + imagePart3.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"image3\"; filename=\"image3.jpg\"")); + QFile *file3 = new QFile(QFINDTESTDATA("../../auto/network/access/qnetworkreply/image3.jpg")); + file3->open(QIODevice::ReadOnly); + imagePart3.setBodyDevice(file3); + file3->setParent(multiPart); + + multiPart->append(imagePart3); + return multiPart; +} + +void tst_qnetworkreply::uploadToFacebook() +{ + QByteArray accessToken = qgetenv("QT_FACEBOOK_ACCESS_TOKEN"); + if (accessToken.isEmpty()) + QSKIP("This test requires the QT_FACEBOOK_ACCESS_TOKEN environment variable to be set. " + "Do something like 'export QT_FACEBOOK_ACCESS_TOKEN=MyAccessToken'"); + + QElapsedTimer timer; + QNetworkAccessManager manager; + QNetworkRequest request(QUrl("https://graph.facebook.com/me/photos")); + QHttpMultiPart *multiPart = createFacebookMultiPart(accessToken); + timer.start(); + + QNetworkReply *reply = manager.post(request, multiPart); + multiPart->setParent(reply); + QObject::connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); + QTestEventLoop::instance().enterLoop(120); + qint64 elapsed = timer.elapsed(); + QVERIFY(!QTestEventLoop::instance().timeout()); + qDebug() << "reply finished after" << elapsed / 1000.0 << "seconds"; + QCOMPARE(reply->error(), QNetworkReply::NoError); + + QByteArray content = reply->readAll(); + QJsonDocument jsonDocument = QJsonDocument::fromJson(content); + QVERIFY(jsonDocument.isArray()); + QJsonArray uploadStatuses = jsonDocument.array(); + QVERIFY(uploadStatuses.size() > 0); + for (int a = 0; a < uploadStatuses.size(); a++) { + QJsonValue currentUploadStatus = uploadStatuses.at(a); + QVERIFY(currentUploadStatus.isObject()); + QJsonObject statusObject = currentUploadStatus.toObject(); + QJsonValue statusCode = statusObject.value(QLatin1String("code")); + QCOMPARE(statusCode.toVariant().toInt(), 200); // 200 OK + } +} + QTEST_MAIN(tst_qnetworkreply) #include "main.moc" |