summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--config.tests/arch/arch.pro1
-rw-r--r--config.tests/common/avx/avx.pro1
-rw-r--r--config.tests/common/avx2/avx2.pro1
-rw-r--r--config.tests/common/c++11/c++11.pro2
-rw-r--r--config.tests/common/sse2/sse2.pro1
-rw-r--r--config.tests/common/sse3/sse3.pro1
-rw-r--r--config.tests/common/sse4_1/sse4_1.pro1
-rw-r--r--config.tests/common/sse4_2/sse4_2.pro1
-rw-r--r--config.tests/common/ssse3/ssse3.pro1
-rw-r--r--config.tests/mac/coreservices/coreservices.pro2
-rw-r--r--config.tests/mac/corewlan/corewlan.pro2
-rw-r--r--config.tests/qpa/directfb/directfb.pro1
-rw-r--r--config.tests/unix/alsa/alsa.pro1
-rwxr-xr-xconfig.tests/unix/arch.test2
-rw-r--r--config.tests/unix/clock-gettime/clock-gettime.pro1
-rw-r--r--config.tests/unix/clock-monotonic/clock-monotonic.pro1
-rwxr-xr-xconfig.tests/unix/compile.test2
-rw-r--r--config.tests/unix/cups/cups.pro1
-rw-r--r--config.tests/unix/db2/db2.pro1
-rw-r--r--config.tests/unix/dbus/dbus.pro1
-rw-r--r--config.tests/unix/eventfd/eventfd.pro1
-rw-r--r--config.tests/unix/fontconfig/fontconfig.pro2
-rw-r--r--config.tests/unix/getaddrinfo/getaddrinfo.pro1
-rw-r--r--config.tests/unix/getifaddrs/getifaddrs.pro1
-rw-r--r--config.tests/unix/glib/glib.pro2
-rw-r--r--config.tests/unix/gnu-libiconv/gnu-libiconv.pro1
-rw-r--r--config.tests/unix/ibase/ibase.pro1
-rw-r--r--config.tests/unix/iconv/iconv.pro2
-rw-r--r--config.tests/unix/icu/icu.pro2
-rw-r--r--config.tests/unix/inotify/inotify.pro1
-rw-r--r--config.tests/unix/iodbc/iodbc.pro1
-rw-r--r--config.tests/unix/ipv6ifname/ipv6ifname.pro1
-rw-r--r--config.tests/unix/libjpeg/libjpeg.pro1
-rw-r--r--config.tests/unix/libpng/libpng.pro1
-rw-r--r--config.tests/unix/mremap/mremap.pro1
-rw-r--r--config.tests/unix/mysql/mysql.pro1
-rw-r--r--config.tests/unix/mysql_r/mysql_r.pro1
-rw-r--r--config.tests/unix/nis/nis.pro1
-rw-r--r--config.tests/unix/oci/oci.pro1
-rw-r--r--config.tests/unix/odbc/odbc.pro1
-rw-r--r--config.tests/unix/opengldesktop/opengldesktop.pro1
-rw-r--r--config.tests/unix/opengles1/opengles1.pro1
-rw-r--r--config.tests/unix/opengles2/opengles2.pro1
-rw-r--r--config.tests/unix/openssl/openssl.pro1
-rw-r--r--config.tests/unix/pcre/pcre.pro2
-rw-r--r--config.tests/unix/psql/psql.pro1
-rwxr-xr-xconfig.tests/unix/ptrsize.test2
-rw-r--r--config.tests/unix/ptrsize/ptrsizetest.pro1
-rw-r--r--config.tests/unix/slog2/slog2.pro1
-rw-r--r--config.tests/unix/sqlite/sqlite.pro1
-rw-r--r--config.tests/unix/sqlite2/sqlite2.pro1
-rw-r--r--config.tests/unix/stdint/stdint.pro1
-rw-r--r--config.tests/unix/stl/stl.pro1
-rw-r--r--config.tests/unix/sun-libiconv/sun-libiconv.pro2
-rw-r--r--config.tests/unix/tds/tds.pro1
-rw-r--r--config.tests/unix/zlib/zlib.pro1
-rwxr-xr-xconfigure121
-rw-r--r--dist/changes-5.2.042
-rw-r--r--doc/global/config.qdocconf12
-rw-r--r--doc/global/fileextensions.qdocconf12
-rw-r--r--doc/global/html-config.qdocconf29
-rw-r--r--doc/global/html-footer.qdocconf30
-rw-r--r--doc/global/html-header-offline.qdocconf31
-rw-r--r--doc/global/html-header-online.qdocconf64
-rw-r--r--doc/global/qt-cpp-defines.qdocconf (renamed from doc/global/qt-cpp-ignore.qdocconf)30
-rw-r--r--doc/global/qt-defines.qdocconf17
-rw-r--r--doc/global/qt-html-templates-offline.qdocconf45
-rw-r--r--doc/global/qt-html-templates-online.qdocconf79
-rw-r--r--doc/global/qt-module-defaults-offline.qdocconf13
-rw-r--r--doc/global/qt-module-defaults-online.qdocconf40
-rw-r--r--doc/global/qt-module-defaults.qdocconf35
-rw-r--r--doc/global/template/images/Qt-dark_gradient.pngbin0 -> 1032 bytes
-rw-r--r--doc/global/template/images/Qt-footer-bg.jpgbin0 -> 3843 bytes
-rw-r--r--doc/global/template/images/Qt-footer_shadow.pngbin0 -> 3181 bytes
-rw-r--r--doc/global/template/images/Qt-gradient.pngbin0 -> 956 bytes
-rw-r--r--doc/global/template/images/Qt-header-bg.jpgbin0 -> 11264 bytes
-rw-r--r--doc/global/template/images/Qt-logo.pngbin0 -> 4344 bytes
-rw-r--r--doc/global/template/images/arrow_bc.pngbin0 -> 1071 bytes
-rw-r--r--doc/global/template/images/logo.pngbin0 -> 2205 bytes
-rw-r--r--doc/global/template/style/offline.css72
-rw-r--r--doc/global/template/style/online.css387
-rw-r--r--examples/widgets/dialogs/standarddialogs/dialog.cpp20
-rw-r--r--examples/widgets/dialogs/standarddialogs/dialog.h2
-rw-r--r--examples/widgets/itemviews/spreadsheet/main.cpp3
-rw-r--r--examples/widgets/itemviews/spreadsheet/spreadsheet.cpp1
-rw-r--r--examples/widgets/widgets/spinboxes/window.cpp10
-rw-r--r--mkspecs/blackberry-armv7le-qcc/qmake.conf1
-rw-r--r--mkspecs/common/clang.conf10
-rw-r--r--mkspecs/common/ios/qmake.conf3
-rw-r--r--mkspecs/common/mac.conf2
-rw-r--r--mkspecs/common/macx.conf2
-rw-r--r--mkspecs/darwin-g++/qmake.conf2
-rw-r--r--mkspecs/features/cmake_functions.prf5
-rw-r--r--mkspecs/features/create_cmake.prf11
-rw-r--r--mkspecs/features/ios/default_post.prf67
-rw-r--r--mkspecs/features/qt_docs.prf2
-rw-r--r--mkspecs/features/simd.prf3
-rw-r--r--mkspecs/features/spec_post.prf10
-rw-r--r--mkspecs/macx-clang-libc++-32/qmake.conf23
-rw-r--r--mkspecs/macx-clang-libc++/qmake.conf22
-rwxr-xr-xmkspecs/macx-xcode/Info.plist.app22
-rw-r--r--mkspecs/macx-xcode/Info.plist.lib18
-rw-r--r--mkspecs/macx-xcode/features/default_post.prf7
-rw-r--r--qmake/Makefile.unix2
-rw-r--r--qmake/Makefile.win322
-rw-r--r--qmake/generators/mac/pbuilder_pbx.cpp98
-rw-r--r--qmake/generators/mac/pbuilder_pbx.h1
-rw-r--r--qmake/generators/makefile.cpp3
-rw-r--r--qmake/library/ioutils.cpp5
-rw-r--r--qmake/library/ioutils.h1
-rw-r--r--qmake/library/qmake_global.h4
-rw-r--r--qmake/library/qmakebuiltins.cpp34
-rw-r--r--qmake/library/qmakeevaluator.cpp83
-rw-r--r--qmake/library/qmakeevaluator.h20
-rw-r--r--qmake/library/qmakeglobals.cpp52
-rw-r--r--qmake/property.cpp4
-rw-r--r--qmake/qmake.pro2
-rw-r--r--qtbase.pro2
-rw-r--r--src/concurrent/doc/qtconcurrent.qdocconf3
-rw-r--r--src/corelib/Qt5CoreConfigExtras.cmake.in7
-rw-r--r--src/corelib/Qt5CoreConfigExtrasMkspecDir.cmake.in6
-rw-r--r--src/corelib/Qt5CoreConfigExtrasMkspecDirForInstall.cmake.in6
-rw-r--r--src/corelib/corelib.pro24
-rw-r--r--src/corelib/doc/qtcore.qdocconf3
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_io_qurl.cpp6
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_kernel_qvariant.cpp58
-rw-r--r--src/corelib/global/qcompilerdetection.h22
-rw-r--r--src/corelib/global/qglobal.cpp10
-rw-r--r--src/corelib/global/qglobal.h9
-rw-r--r--src/corelib/global/qlibraryinfo.cpp23
-rw-r--r--src/corelib/global/qlibraryinfo.h2
-rw-r--r--src/corelib/global/qnamespace.h8
-rw-r--r--src/corelib/global/qnamespace.qdoc6
-rw-r--r--src/corelib/global/qsystemdetection.h11
-rw-r--r--src/corelib/io/qdatastream.cpp5
-rw-r--r--src/corelib/io/qdatastream.h5
-rw-r--r--src/corelib/io/qdir.cpp57
-rw-r--r--src/corelib/io/qipaddress.cpp60
-rw-r--r--src/corelib/io/qipaddress_p.h2
-rw-r--r--src/corelib/io/qurl.cpp270
-rw-r--r--src/corelib/io/qurl.h6
-rw-r--r--src/corelib/io/qurl_p.h3
-rw-r--r--src/corelib/io/qurlidna.cpp5
-rw-r--r--src/corelib/io/qurlrecode.cpp13
-rw-r--r--src/corelib/itemmodels/qabstractitemmodel.h5
-rw-r--r--src/corelib/json/qjson_p.h2
-rw-r--r--src/corelib/json/qjsonvalue.cpp12
-rw-r--r--src/corelib/json/qjsonvalue.h1
-rw-r--r--src/corelib/json/qjsonwriter.cpp9
-rw-r--r--src/corelib/kernel/qcore_mac_p.h6
-rw-r--r--src/corelib/kernel/qcoreapplication.cpp57
-rw-r--r--src/corelib/kernel/qeventdispatcher_blackberry.cpp82
-rw-r--r--src/corelib/kernel/qmetatype.cpp283
-rw-r--r--src/corelib/kernel/qmetatype.h1058
-rw-r--r--src/corelib/kernel/qobject.cpp60
-rw-r--r--src/corelib/kernel/qobject_p.h7
-rw-r--r--src/corelib/kernel/qobjectdefs.h1
-rw-r--r--src/corelib/kernel/qsocketnotifier.cpp9
-rw-r--r--src/corelib/kernel/qvariant.cpp589
-rw-r--r--src/corelib/kernel/qvariant.h295
-rw-r--r--src/corelib/plugin/plugin.pri6
-rw-r--r--src/corelib/plugin/qlibrary.cpp141
-rw-r--r--src/corelib/plugin/qmachparser.cpp218
-rw-r--r--src/corelib/plugin/qmachparser_p.h (renamed from src/plugins/platforms/kms/qkmsudevlistener.h)55
-rw-r--r--src/corelib/tools/qalgorithms.h67
-rw-r--r--src/corelib/tools/qalgorithms.qdoc31
-rw-r--r--src/corelib/tools/qbitarray.cpp11
-rw-r--r--src/corelib/tools/qbitarray.h1
-rw-r--r--src/corelib/tools/qbytearray.cpp1
-rw-r--r--src/corelib/tools/qdatetime.cpp55
-rw-r--r--src/corelib/tools/qdatetime.h3
-rw-r--r--src/corelib/tools/qharfbuzz_p.h14
-rw-r--r--src/corelib/tools/qhash.h21
-rw-r--r--src/corelib/tools/qlist.h17
-rw-r--r--src/corelib/tools/qlocale_p.h2
-rw-r--r--src/corelib/tools/qmap.h18
-rw-r--r--src/corelib/tools/qpair.h13
-rw-r--r--src/corelib/tools/qpair.qdoc20
-rw-r--r--src/corelib/tools/qset.h22
-rw-r--r--src/corelib/tools/qvarlengtharray.h10
-rw-r--r--src/corelib/tools/qvector.h10
-rw-r--r--src/dbus/doc/qtdbus.qdocconf5
-rw-r--r--src/dbus/qdbusabstractadaptor.cpp11
-rw-r--r--src/dbus/qdbusconnection_p.h4
-rw-r--r--src/dbus/qdbusintegrator.cpp6
-rw-r--r--src/dbus/qdbusmisc.cpp22
-rw-r--r--src/dbus/qdbusxmlgenerator.cpp16
-rw-r--r--src/gui/doc/qtgui.qdocconf3
-rw-r--r--src/gui/image/qicon.cpp1
-rw-r--r--src/gui/image/qicon.h4
-rw-r--r--src/gui/image/qiconloader.cpp12
-rw-r--r--src/gui/image/qimage.h5
-rw-r--r--src/gui/kernel/qguiapplication.cpp6
-rw-r--r--src/gui/kernel/qkeysequence.h4
-rw-r--r--src/gui/kernel/qplatformdialoghelper.cpp19
-rw-r--r--src/gui/kernel/qplatformdialoghelper.h48
-rw-r--r--src/gui/kernel/qplatformintegration.cpp2
-rw-r--r--src/gui/kernel/qplatformintegration.h3
-rw-r--r--src/gui/kernel/qplatformintegrationfactory.cpp20
-rw-r--r--src/gui/kernel/qplatformintegrationfactory_p.h2
-rw-r--r--src/gui/kernel/qplatformintegrationplugin.cpp14
-rw-r--r--src/gui/kernel/qplatformintegrationplugin.h3
-rw-r--r--src/gui/kernel/qplatformservices.cpp5
-rw-r--r--src/gui/kernel/qplatformtheme.cpp4
-rw-r--r--src/gui/kernel/qplatformtheme.h9
-rw-r--r--src/gui/kernel/qshortcutmap.cpp3
-rw-r--r--src/gui/kernel/qstylehints.cpp11
-rw-r--r--src/gui/kernel/qstylehints.h1
-rw-r--r--src/gui/kernel/qtouchdevice.cpp19
-rw-r--r--src/gui/kernel/qtouchdevice.h2
-rw-r--r--src/gui/kernel/qtouchdevice_p.h4
-rw-r--r--src/gui/opengl/qopenglfunctions.cpp12
-rw-r--r--src/gui/opengl/qopenglfunctions.h3
-rw-r--r--src/gui/painting/painting.pri9
-rw-r--r--src/gui/painting/qcolor.cpp43
-rw-r--r--src/gui/painting/qcolor.h3
-rw-r--r--src/gui/painting/qcolor_p.cpp12
-rw-r--r--src/gui/painting/qdrawhelper.cpp2
-rw-r--r--src/gui/text/qfontdatabase.cpp49
-rw-r--r--src/gui/text/qfontdatabase.h10
-rw-r--r--src/gui/text/qfontdatabase_qpa.cpp2
-rw-r--r--src/gui/text/qplatformfontdatabase.cpp13
-rw-r--r--src/gui/text/qplatformfontdatabase.h2
-rw-r--r--src/gui/text/qtextengine.cpp233
-rw-r--r--src/gui/text/qtextengine_p.h16
-rw-r--r--src/network/access/qhttpnetworkconnection.cpp36
-rw-r--r--src/network/access/qhttpnetworkconnection_p.h4
-rw-r--r--src/network/access/qhttpnetworkconnectionchannel.cpp14
-rw-r--r--src/network/access/qhttpnetworkreply.cpp5
-rw-r--r--src/network/access/qhttpnetworkrequest.cpp22
-rw-r--r--src/network/access/qhttpnetworkrequest_p.h4
-rw-r--r--src/network/access/qhttpthreaddelegate.cpp8
-rw-r--r--src/network/access/qnetworkaccessbackend.cpp17
-rw-r--r--src/network/access/qnetworkaccessbackend_p.h2
-rw-r--r--src/network/access/qnetworkaccessdebugpipebackend.cpp6
-rw-r--r--src/network/access/qnetworkaccessdebugpipebackend_p.h1
-rw-r--r--src/network/access/qnetworkaccessfilebackend.cpp11
-rw-r--r--src/network/access/qnetworkaccessfilebackend_p.h1
-rw-r--r--src/network/access/qnetworkaccessftpbackend.cpp6
-rw-r--r--src/network/access/qnetworkaccessftpbackend_p.h1
-rw-r--r--src/network/access/qnetworkaccessmanager.cpp171
-rw-r--r--src/network/access/qnetworkaccessmanager.h16
-rw-r--r--src/network/access/qnetworkaccessmanager_p.h16
-rw-r--r--src/network/access/qnetworkreplyhttpimpl.cpp7
-rw-r--r--src/network/bearer/qnetworkconfiguration.cpp183
-rw-r--r--src/network/bearer/qnetworkconfiguration.h7
-rw-r--r--src/network/doc/qtnetwork.qdocconf3
-rw-r--r--src/network/kernel/qhostaddress.cpp2
-rw-r--r--src/network/ssl/qssl.cpp10
-rw-r--r--src/network/ssl/qssl.h4
-rw-r--r--src/network/ssl/qsslconfiguration.cpp65
-rw-r--r--src/network/ssl/qsslconfiguration.h4
-rw-r--r--src/network/ssl/qsslconfiguration_p.h6
-rw-r--r--src/network/ssl/qsslcontext.cpp41
-rw-r--r--src/network/ssl/qsslcontext_p.h5
-rw-r--r--src/network/ssl/qsslsocket.cpp2
-rw-r--r--src/network/ssl/qsslsocket_openssl.cpp12
-rw-r--r--src/network/ssl/qsslsocket_openssl_symbols.cpp4
-rw-r--r--src/network/ssl/qsslsocket_openssl_symbols_p.h2
-rw-r--r--src/opengl/doc/qtopengl.qdocconf5
-rw-r--r--src/platformsupport/eglconvenience/qxlibeglintegration.cpp17
-rw-r--r--src/platformsupport/eventdispatchers/eventdispatchers.pri8
-rw-r--r--src/platformsupport/eventdispatchers/qioseventdispatcher.mm (renamed from src/plugins/platforms/ios/qioseventdispatcher.mm)49
-rw-r--r--src/platformsupport/eventdispatchers/qioseventdispatcher_p.h (renamed from src/plugins/platforms/ios/qioseventdispatcher.h)0
-rw-r--r--src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp4
-rw-r--r--src/platformsupport/services/genericunix/qgenericunixservices.cpp26
-rw-r--r--src/platformsupport/themes/genericunix/qgenericunixthemes.cpp52
-rw-r--r--src/plugins/bearer/blackberry/qbbengine.cpp7
-rw-r--r--src/plugins/platforms/android/src/androidjniinput.cpp18
-rw-r--r--src/plugins/platforms/android/src/qandroidplatformintegration.cpp4
-rw-r--r--src/plugins/platforms/android/src/qandroidplatformintegration.h2
-rw-r--r--src/plugins/platforms/android/src/qandroidsystemlocale.cpp179
-rw-r--r--src/plugins/platforms/android/src/qandroidsystemlocale.h (renamed from src/plugins/platforms/kms/qkmsudevdrmhandler.h)25
-rw-r--r--src/plugins/platforms/android/src/src.pri6
-rw-r--r--src/plugins/platforms/cocoa/qcocoaapplication.h4
-rw-r--r--src/plugins/platforms/cocoa/qcocoaapplication.mm10
-rw-r--r--src/plugins/platforms/cocoa/qcocoaapplicationdelegate.h3
-rw-r--r--src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm12
-rw-r--r--src/plugins/platforms/cocoa/qcocoacolordialoghelper.mm9
-rw-r--r--src/plugins/platforms/cocoa/qcocoafiledialoghelper.h8
-rw-r--r--src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm128
-rw-r--r--src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm24
-rw-r--r--src/plugins/platforms/cocoa/qcocoahelpers.mm26
-rw-r--r--src/plugins/platforms/cocoa/qcocoaintegration.mm8
-rw-r--r--src/plugins/platforms/cocoa/qcocoamenu.mm10
-rw-r--r--src/plugins/platforms/cocoa/qcocoamenubar.mm4
-rw-r--r--src/plugins/platforms/cocoa/qcocoamenuitem.mm8
-rw-r--r--src/plugins/platforms/cocoa/qcocoamenuloader.h4
-rw-r--r--src/plugins/platforms/cocoa/qcocoamenuloader.mm4
-rw-r--r--src/plugins/platforms/cocoa/qcocoaservices.mm4
-rw-r--r--src/plugins/platforms/cocoa/qcocoasystemsettings.mm4
-rwxr-xr-xsrc/plugins/platforms/cocoa/qcocoasystemtrayicon.mm18
-rw-r--r--src/plugins/platforms/cocoa/qcocoatheme.h4
-rw-r--r--src/plugins/platforms/cocoa/qcocoatheme.mm4
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.h2
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.mm3
-rw-r--r--src/plugins/platforms/cocoa/qnsview.mm7
-rw-r--r--src/plugins/platforms/cocoa/qpaintengine_mac.mm10
-rw-r--r--src/plugins/platforms/directfb/qdirectfbconvenience.cpp8
-rw-r--r--src/plugins/platforms/ios/ios.pro39
-rw-r--r--src/plugins/platforms/ios/plugin.mm4
-rw-r--r--src/plugins/platforms/ios/plugin.pro36
-rw-r--r--src/plugins/platforms/ios/qiosapplicationdelegate.h4
-rw-r--r--src/plugins/platforms/ios/qiosapplicationdelegate.mm59
-rw-r--r--src/plugins/platforms/ios/qiosapplicationstate.h (renamed from src/plugins/platforms/kms/qkmsudevhandler.cpp)19
-rw-r--r--src/plugins/platforms/ios/qiosapplicationstate.mm162
-rw-r--r--src/plugins/platforms/ios/qioscontext.mm2
-rw-r--r--src/plugins/platforms/ios/qiosinputcontext.h1
-rw-r--r--src/plugins/platforms/ios/qiosinputcontext.mm11
-rw-r--r--src/plugins/platforms/ios/qiosintegration.h3
-rw-r--r--src/plugins/platforms/ios/qiosintegration.mm10
-rw-r--r--src/plugins/platforms/ios/qiosmain_dummy.mm (renamed from src/plugins/platforms/kms/qkmsudevhandler.h)32
-rw-r--r--src/plugins/platforms/ios/qiosmain_wrapper.mm (renamed from src/plugins/platforms/kms/qkmsudevdrmhandler.cpp)34
-rw-r--r--src/plugins/platforms/ios/qioswindow.mm18
-rw-r--r--src/plugins/platforms/ios/qtmain.mm94
-rw-r--r--src/plugins/platforms/ios/qtmain.pro8
-rw-r--r--src/plugins/platforms/kms/kms.pro6
-rw-r--r--src/plugins/platforms/kms/qkmsintegration.cpp31
-rw-r--r--src/plugins/platforms/kms/qkmsintegration.h14
-rw-r--r--src/plugins/platforms/qnx/main.cpp3
-rw-r--r--src/plugins/platforms/qnx/qnx.pro31
-rw-r--r--src/plugins/platforms/qnx/qqnxbpseventfilter.cpp12
-rw-r--r--src/plugins/platforms/qnx/qqnxbpseventfilter.h2
-rw-r--r--src/plugins/platforms/qnx/qqnxfiledialoghelper.h28
-rw-r--r--src/plugins/platforms/qnx/qqnxfiledialoghelper_bb10.cpp217
-rw-r--r--src/plugins/platforms/qnx/qqnxfiledialoghelper_playbook.cpp (renamed from src/plugins/platforms/qnx/qqnxfiledialoghelper.cpp)36
-rw-r--r--src/plugins/platforms/qnx/qqnxfilepicker.cpp289
-rw-r--r--src/plugins/platforms/qnx/qqnxfilepicker.h (renamed from src/plugins/platforms/kms/qkmsudevlistener.cpp)113
-rw-r--r--src/plugins/platforms/qnx/qqnxintegration.cpp34
-rw-r--r--src/plugins/platforms/qnx/qqnxintegration.h15
-rw-r--r--src/plugins/platforms/qnx/qqnxrasterbackingstore.cpp27
-rw-r--r--src/plugins/platforms/qnx/qqnxscreen.cpp15
-rw-r--r--src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp6
-rw-r--r--src/plugins/platforms/qnx/qqnxtheme.cpp4
-rw-r--r--src/plugins/platforms/qnx/qqnxwindow.cpp19
-rw-r--r--src/plugins/platforms/qnx/qqnxwindow.h2
-rw-r--r--src/plugins/platforms/windows/main.cpp4
-rw-r--r--src/plugins/platforms/windows/qwindowscontext.cpp34
-rw-r--r--src/plugins/platforms/windows/qwindowscontext.h3
-rw-r--r--src/plugins/platforms/windows/qwindowsdialoghelpers.cpp211
-rw-r--r--src/plugins/platforms/windows/qwindowsfontdatabase.cpp4
-rw-r--r--src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp4
-rw-r--r--src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp141
-rw-r--r--src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h2
-rw-r--r--src/plugins/platforms/windows/qwindowstabletsupport.cpp473
-rw-r--r--src/plugins/platforms/windows/qwindowstabletsupport.h142
-rw-r--r--src/plugins/platforms/windows/qwindowstheme.cpp26
-rw-r--r--src/plugins/platforms/windows/qwindowstheme.h3
-rw-r--r--src/plugins/platforms/windows/windows.pro6
-rw-r--r--src/plugins/platforms/xcb/main.cpp6
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.cpp9
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.h7
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection_xi2.cpp288
-rw-r--r--src/plugins/platforms/xcb/qxcbintegration.cpp24
-rw-r--r--src/plugins/platforms/xcb/qxcbintegration.h2
-rw-r--r--src/plugins/platforms/xcb/qxcbkeyboard.cpp8
-rw-r--r--src/plugins/platformthemes/gtk2/qgtk2dialoghelpers.cpp28
-rw-r--r--src/plugins/platformthemes/gtk2/qgtk2dialoghelpers.h12
-rw-r--r--src/printsupport/doc/qtprintsupport.qdocconf3
-rw-r--r--src/sql/doc/qtsql.qdocconf3
-rw-r--r--src/src.pro6
-rw-r--r--src/testlib/doc/qttestlib.qdocconf3
-rw-r--r--src/testlib/doc/src/qttestlib-manual.qdoc3
-rw-r--r--src/testlib/qtestcase.cpp35
-rw-r--r--src/testlib/qtestresult.cpp8
-rw-r--r--src/tools/qdbuscpp2xml/qdbuscpp2xml.cpp12
-rw-r--r--src/tools/qdbusxml2cpp/qdbusxml2cpp.cpp4
-rw-r--r--src/tools/qdoc/codemarker.cpp2
-rw-r--r--src/tools/qdoc/codeparser.cpp46
-rw-r--r--src/tools/qdoc/codeparser.h2
-rw-r--r--src/tools/qdoc/config.h7
-rw-r--r--src/tools/qdoc/cppcodemarker.cpp59
-rw-r--r--src/tools/qdoc/cppcodeparser.cpp339
-rw-r--r--src/tools/qdoc/cppcodeparser.h13
-rw-r--r--src/tools/qdoc/ditaxmlgenerator.cpp66
-rw-r--r--src/tools/qdoc/doc.cpp10
-rw-r--r--src/tools/qdoc/doc.h8
-rw-r--r--src/tools/qdoc/doc/config/qdoc.qdocconf2
-rw-r--r--src/tools/qdoc/generator.cpp25
-rw-r--r--src/tools/qdoc/generator.h1
-rw-r--r--src/tools/qdoc/helpprojectwriter.cpp23
-rw-r--r--src/tools/qdoc/htmlgenerator.cpp278
-rw-r--r--src/tools/qdoc/htmlgenerator.h14
-rw-r--r--src/tools/qdoc/main.cpp7
-rw-r--r--src/tools/qdoc/node.cpp160
-rw-r--r--src/tools/qdoc/node.h52
-rw-r--r--src/tools/qdoc/puredocparser.cpp81
-rw-r--r--src/tools/qdoc/qdocdatabase.cpp2
-rw-r--r--src/tools/qdoc/qdocindexfiles.cpp52
-rw-r--r--src/tools/qdoc/qmlcodeparser.cpp67
-rw-r--r--src/tools/qdoc/qmlcodeparser.h4
-rw-r--r--src/tools/qdoc/qmlvisitor.cpp219
-rw-r--r--src/tools/qdoc/qmlvisitor.h11
-rw-r--r--src/tools/qdoc/tree.cpp2
-rw-r--r--src/widgets/dialogs/qcolordialog.cpp240
-rw-r--r--src/widgets/dialogs/qcolordialog.h4
-rw-r--r--src/widgets/dialogs/qcolordialog_p.h8
-rw-r--r--src/widgets/dialogs/qdialog_p.h2
-rw-r--r--src/widgets/dialogs/qfiledialog.cpp417
-rw-r--r--src/widgets/dialogs/qfiledialog.h64
-rw-r--r--src/widgets/dialogs/qfiledialog_p.h40
-rw-r--r--src/widgets/dialogs/qfileinfogatherer.cpp2
-rw-r--r--src/widgets/dialogs/qfileinfogatherer_p.h8
-rw-r--r--src/widgets/dialogs/qfilesystemmodel.cpp2
-rw-r--r--src/widgets/dialogs/qfilesystemmodel_p.h2
-rw-r--r--src/widgets/dialogs/qfontdialog.cpp28
-rw-r--r--src/widgets/dialogs/qfontdialog.h6
-rw-r--r--src/widgets/dialogs/qinputdialog.cpp112
-rw-r--r--src/widgets/dialogs/qinputdialog.h9
-rw-r--r--src/widgets/doc/qtwidgets.qdocconf3
-rw-r--r--src/widgets/graphicsview/qgridlayoutengine.cpp9
-rw-r--r--src/widgets/itemviews/itemviews.pri1
-rw-r--r--src/widgets/itemviews/qabstractitemview.cpp20
-rw-r--r--src/widgets/itemviews/qabstractitemview_p.h2
-rw-r--r--src/widgets/itemviews/qfileiconprovider.cpp93
-rw-r--r--src/widgets/itemviews/qfileiconprovider.h14
-rw-r--r--src/widgets/itemviews/qfileiconprovider_p.h87
-rw-r--r--src/widgets/itemviews/qheaderview.cpp96
-rw-r--r--src/widgets/itemviews/qheaderview.h5
-rw-r--r--src/widgets/itemviews/qheaderview_p.h5
-rw-r--r--src/widgets/itemviews/qlistwidget.cpp4
-rw-r--r--src/widgets/itemviews/qtableview.cpp219
-rw-r--r--src/widgets/itemviews/qtableview.h2
-rw-r--r--src/widgets/itemviews/qtableview_p.h2
-rw-r--r--src/widgets/itemviews/qtreeview.cpp144
-rw-r--r--src/widgets/itemviews/qtreeview.h2
-rw-r--r--src/widgets/itemviews/qtreeview_p.h3
-rw-r--r--src/widgets/itemviews/qtreewidget.cpp6
-rw-r--r--src/widgets/kernel/qapplication.cpp73
-rw-r--r--src/widgets/kernel/qapplication_p.h4
-rw-r--r--src/widgets/kernel/qapplication_qpa.cpp1
-rw-r--r--src/widgets/kernel/qlayout.cpp4
-rw-r--r--src/widgets/kernel/qlayoutitem.cpp2
-rw-r--r--src/widgets/kernel/qsizepolicy.h5
-rw-r--r--src/widgets/kernel/qsizepolicy.qdoc17
-rw-r--r--src/widgets/kernel/qtooltip.cpp36
-rw-r--r--src/widgets/kernel/qtooltip.h2
-rw-r--r--src/widgets/kernel/qwidget.cpp39
-rw-r--r--src/widgets/kernel/qwidget.h3
-rw-r--r--src/widgets/kernel/qwidget_p.h2
-rw-r--r--src/widgets/styles/images/cleartext-16.pngbin0 -> 760 bytes
-rw-r--r--src/widgets/styles/qcommonstyle.cpp21
-rw-r--r--src/widgets/styles/qgtkstyle_p.cpp3
-rw-r--r--src/widgets/styles/qstyle.cpp7
-rw-r--r--src/widgets/styles/qstyle.h3
-rw-r--r--src/widgets/styles/qstyle.qrc1
-rw-r--r--src/widgets/widgets/qabstractscrollarea.cpp96
-rw-r--r--src/widgets/widgets/qabstractscrollarea.h12
-rw-r--r--src/widgets/widgets/qabstractscrollarea_p.h4
-rw-r--r--src/widgets/widgets/qcombobox.cpp14
-rw-r--r--src/widgets/widgets/qcombobox.h3
-rw-r--r--src/widgets/widgets/qdialogbuttonbox.cpp15
-rw-r--r--src/widgets/widgets/qdialogbuttonbox.h3
-rw-r--r--src/widgets/widgets/qfontcombobox.cpp99
-rw-r--r--src/widgets/widgets/qlineedit.cpp2
-rw-r--r--src/widgets/widgets/qscrollarea.cpp12
-rw-r--r--src/widgets/widgets/qscrollarea.h2
-rw-r--r--src/widgets/widgets/qspinbox.cpp64
-rw-r--r--src/widgets/widgets/qspinbox.h3
-rw-r--r--src/widgets/widgets/qsplashscreen.cpp16
-rw-r--r--src/widgets/widgets/qsplashscreen.h1
-rw-r--r--src/widgets/widgets/qtextedit.cpp36
-rw-r--r--src/widgets/widgets/qtextedit.h4
-rw-r--r--src/widgets/widgets/qtextedit_p.h2
-rw-r--r--src/widgets/widgets/qwidgetlinecontrol.cpp4
-rw-r--r--src/xml/doc/qtxml.qdocconf3
-rwxr-xr-xtests/auto/android/runtests.pl1
-rw-r--r--tests/auto/android/src/org/qtproject/qt5/android/QtActivity.java2
-rw-r--r--tests/auto/android/src/org/qtproject/qt5/android/QtNative.java13
-rw-r--r--tests/auto/corelib/io/qipaddress/tst_qipaddress.cpp4
-rw-r--r--tests/auto/corelib/io/qurl/tst_qurl.cpp161
-rw-r--r--tests/auto/corelib/io/qurlinternal/tst_qurlinternal.cpp14
-rw-r--r--tests/auto/corelib/json/tst_qtjson.cpp86
-rw-r--r--tests/auto/corelib/kernel/qeventloop/tst_qeventloop.cpp30
-rw-r--r--tests/auto/corelib/kernel/qmetatype/qmetatype.pro1
-rw-r--r--tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp450
-rw-r--r--tests/auto/corelib/kernel/qobject/tst_qobject.cpp51
-rw-r--r--tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp314
-rw-r--r--tests/auto/corelib/plugin/qpluginloader/fakeplugin.cpp (renamed from mkspecs/macx-clang-libc++/qplatformdefs.h)12
-rwxr-xr-xtests/auto/corelib/plugin/qpluginloader/machtest/generate-bad.pl209
-rw-r--r--tests/auto/corelib/plugin/qpluginloader/machtest/machtest.pro56
-rwxr-xr-xtests/auto/corelib/plugin/qpluginloader/machtest/ppcconverter.pl112
-rw-r--r--tests/auto/corelib/plugin/qpluginloader/qpluginloader.pro1
-rw-r--r--tests/auto/corelib/plugin/qpluginloader/tst/tst.pro5
-rw-r--r--tests/auto/corelib/plugin/qpluginloader/tst_qpluginloader.cpp78
-rw-r--r--tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp32
-rw-r--r--tests/auto/corelib/tools/qalgorithms/tst_qalgorithms.cpp80
-rw-r--r--tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp15
-rw-r--r--tests/auto/corelib/tools/qtime/tst_qtime.cpp30
-rw-r--r--tests/auto/dbus/qdbusabstractinterface/interface.h3
-rw-r--r--tests/auto/dbus/qdbusabstractinterface/org.qtproject.QtDBus.Pinger.xml4
-rw-r--r--tests/auto/dbus/qdbusabstractinterface/pinger.h152
-rw-r--r--tests/auto/dbus/qdbusabstractinterface/test/test.pro8
-rw-r--r--tests/auto/dbus/qdbusabstractinterface/tst_qdbusabstractinterface.cpp34
-rw-r--r--tests/auto/gui/kernel/qbackingstore/qbackingstore.pro1
-rw-r--r--tests/auto/gui/kernel/qinputmethod/qinputmethod.pro1
-rw-r--r--tests/auto/gui/painting/qcolor/tst_qcolor.cpp81
-rw-r--r--tests/auto/gui/text/qcssparser/tst_qcssparser.cpp5
-rw-r--r--tests/auto/gui/text/qfontdatabase/qfontdatabase.pro3
-rw-r--r--tests/auto/gui/text/qfontdatabase/tst_qfontdatabase.cpp7
-rw-r--r--tests/auto/network/access/qnetworkaccessmanager/tst_qnetworkaccessmanager.cpp35
-rw-r--r--tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp61
-rw-r--r--tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp2
-rw-r--r--tests/auto/testlib/selftests/expected_cmptest.lightxml8
-rw-r--r--tests/auto/testlib/selftests/expected_cmptest.txt8
-rw-r--r--tests/auto/testlib/selftests/expected_cmptest.xml8
-rw-r--r--tests/auto/testlib/selftests/expected_cmptest.xunitxml8
-rw-r--r--tests/auto/testlib/selftests/expected_datetime.lightxml2
-rw-r--r--tests/auto/testlib/selftests/expected_datetime.txt2
-rw-r--r--tests/auto/testlib/selftests/expected_datetime.xml2
-rw-r--r--tests/auto/testlib/selftests/expected_datetime.xunitxml2
-rw-r--r--tests/auto/testlib/selftests/expected_float.txt6
-rw-r--r--tests/auto/testlib/selftests/expected_strcmp.lightxml4
-rw-r--r--tests/auto/testlib/selftests/expected_strcmp.txt4
-rw-r--r--tests/auto/testlib/selftests/expected_strcmp.xml4
-rw-r--r--tests/auto/testlib/selftests/expected_strcmp.xunitxml4
-rw-r--r--tests/auto/testlib/selftests/expected_subtest.lightxml4
-rw-r--r--tests/auto/testlib/selftests/expected_subtest.txt4
-rw-r--r--tests/auto/testlib/selftests/expected_subtest.xml4
-rw-r--r--tests/auto/testlib/selftests/expected_subtest.xunitxml4
-rw-r--r--tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp48
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsanchorlayout/qgraphicsanchorlayout.pro1
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicseffectsource/qgraphicseffectsource.pro1
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsgridlayout/qgraphicsgridlayout.pro1
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsgridlayout/tst_qgraphicsgridlayout.cpp38
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicslinearlayout/qgraphicslinearlayout.pro2
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicssceneindex/qgraphicssceneindex.pro1
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicswidget/qgraphicswidget.pro1
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicswidget/tst_qgraphicswidget.cpp3
-rw-r--r--tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp32
-rw-r--r--tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp2
-rw-r--r--tests/auto/widgets/kernel/qlayout/tst_qlayout.cpp43
-rw-r--r--tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp146
-rw-r--r--tests/auto/widgets/widgets/qdialogbuttonbox/tst_qdialogbuttonbox.cpp37
-rw-r--r--tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp6
-rw-r--r--tests/auto/widgets/widgets/qspinbox/tst_qspinbox.cpp58
-rw-r--r--tests/benchmarks/corelib/io/qfile/main.cpp4
-rw-r--r--tests/benchmarks/corelib/tools/qset/main.cpp141
-rw-r--r--tests/benchmarks/corelib/tools/qset/qset.pro4
-rw-r--r--tests/benchmarks/gui/itemviews/qtableview/tst_qtableview.cpp21
-rw-r--r--tests/benchmarks/network/access/qnetworkreply/qnetworkreply.pro2
-rw-r--r--tests/benchmarks/network/access/qnetworkreply/tst_qnetworkreply.cpp127
-rw-r--r--tests/manual/corelib/tools/qhash/main.cpp85
-rw-r--r--tests/manual/corelib/tools/qhash/main.pro1
-rw-r--r--tests/manual/corelib/tools/qlist/main.cpp71
-rw-r--r--tests/manual/corelib/tools/qlist/main.pro1
-rw-r--r--tests/manual/corelib/tools/qmap/main.cpp (renamed from tests/auto/dbus/qdbusabstractinterface/pinger.cpp)82
-rw-r--r--tests/manual/corelib/tools/qmap/qmaptest.pro2
-rw-r--r--tests/manual/corelib/tools/qset/main.cpp (renamed from mkspecs/macx-clang-libc++-32/qplatformdefs.h)26
-rw-r--r--tests/manual/corelib/tools/qset/main.pro1
-rw-r--r--tests/manual/corelib/tools/qvarlengtharray/main.cpp76
-rw-r--r--tests/manual/corelib/tools/qvarlengtharray/main.pro1
-rw-r--r--tests/manual/corelib/tools/qvector/main.cpp76
-rw-r--r--tests/manual/corelib/tools/qvector/main.pro1
-rw-r--r--tests/manual/dialogs/colordialogpanel.h2
-rw-r--r--tests/manual/dialogs/dialogs.pro4
-rw-r--r--tests/manual/dialogs/filedialogpanel.cpp75
-rw-r--r--tests/manual/dialogs/filedialogpanel.h9
-rw-r--r--tests/manual/dialogs/fontdialogpanel.cpp12
-rw-r--r--tests/manual/dialogs/fontdialogpanel.h6
-rw-r--r--tests/manual/dialogs/main.cpp2
-rw-r--r--tests/manual/dialogs/messageboxpanel.cpp175
-rw-r--r--tests/manual/dialogs/messageboxpanel.h83
-rw-r--r--tests/manual/dialogs/wizardpanel.h2
-rw-r--r--tests/manual/manual.pro1
-rw-r--r--tests/manual/qnetworkconfiguration/main.cpp139
-rw-r--r--tests/manual/qnetworkconfiguration/qnetworkconfiguration.pro7
-rw-r--r--tests/manual/qpainfo/main.cpp14
-rw-r--r--tests/manual/qtabletevent/regular_widgets/main.cpp83
-rw-r--r--tests/manual/widgets/itemviews/autoResizePrecision/tablehorz/testtable1.cpp115
-rw-r--r--tests/manual/widgets/itemviews/autoResizePrecision/tablehorz/testtable1.pro2
-rw-r--r--tests/manual/widgets/itemviews/autoResizePrecision/tablevert/testtable2.cpp125
-rw-r--r--tests/manual/widgets/itemviews/autoResizePrecision/tablevert/testtable2.pro2
-rw-r--r--tests/manual/widgets/itemviews/autoResizePrecision/treeview/testtree.cpp132
-rw-r--r--tests/manual/widgets/itemviews/autoResizePrecision/treeview/testtree.pro2
-rw-r--r--tests/manual/widgets/itemviews/qtreeview/main.cpp35
-rw-r--r--tests/manual/widgets/kernel/kernel.pro2
-rw-r--r--tests/manual/widgets/kernel/qtooltip/main.cpp161
-rw-r--r--tests/manual/widgets/kernel/qtooltip/main.pro2
-rw-r--r--tests/manual/widgets/kernel/sizeonhide/main.cpp134
-rw-r--r--tests/manual/widgets/kernel/sizeonhide/sizeonhide.pro3
-rw-r--r--tests/manual/widgets/qgraphicsview/rubberband/rubberbandtest.cpp4
-rw-r--r--tests/manual/widgets/widgets.pro3
-rw-r--r--tools/configure/configureapp.cpp38
585 files changed, 15249 insertions, 3916 deletions
diff --git a/.gitignore b/.gitignore
index 5f9854a674..936570e416 100644
--- a/.gitignore
+++ b/.gitignore
@@ -310,6 +310,7 @@ tests/auto/corelib/plugin/quuid/testProcessUniqueness/testProcessUniqueness
tests/auto/corelib/io/qlockfile/qlockfiletesthelper/qlockfile_test_helper
tests/auto/dbus/qdbusabstractadaptor/qmyserver/qmyserver
tests/auto/dbus/qdbusabstractinterface/qpinger/qpinger
+tests/auto/dbus/qdbusabstractinterface/test/pinger_interface.*
tests/auto/dbus/qdbusinterface/qmyserver/qmyserver
tests/auto/gui/kernel/qfileopenevent/qfileopeneventexternal/qfileopeneventexternal
tests/auto/network/bearer/qnetworksession/lackey/lackey
diff --git a/config.tests/arch/arch.pro b/config.tests/arch/arch.pro
index fda4acc601..d89d70b1ee 100644
--- a/config.tests/arch/arch.pro
+++ b/config.tests/arch/arch.pro
@@ -2,4 +2,3 @@ TARGET = arch
SOURCES = arch.cpp
CONFIG -= qt dylib release debug_and_release
CONFIG += debug console
-mac:CONFIG -= app_bundle
diff --git a/config.tests/common/avx/avx.pro b/config.tests/common/avx/avx.pro
index ba7fd96e43..8d1b9702bc 100644
--- a/config.tests/common/avx/avx.pro
+++ b/config.tests/common/avx/avx.pro
@@ -1,6 +1,5 @@
SOURCES = avx.cpp
CONFIG -= qt dylib release debug_and_release
CONFIG += debug console
-mac:CONFIG -= app_bundle
isEmpty(QMAKE_CFLAGS_AVX):error("This compiler does not support AVX")
else:QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_AVX
diff --git a/config.tests/common/avx2/avx2.pro b/config.tests/common/avx2/avx2.pro
index 5aa9429d68..927f64efc8 100644
--- a/config.tests/common/avx2/avx2.pro
+++ b/config.tests/common/avx2/avx2.pro
@@ -1,6 +1,5 @@
SOURCES = avx2.cpp
CONFIG -= qt dylib release debug_and_release
CONFIG += debug console
-mac:CONFIG -= app_bundle
isEmpty(QMAKE_CFLAGS_AVX2):error("This compiler does not support AVX2")
else:QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_AVX2
diff --git a/config.tests/common/c++11/c++11.pro b/config.tests/common/c++11/c++11.pro
index dd4042b8d6..dbe764ba84 100644
--- a/config.tests/common/c++11/c++11.pro
+++ b/config.tests/common/c++11/c++11.pro
@@ -1,3 +1,3 @@
SOURCES = c++11.cpp
CONFIG += c++11
-CONFIG -= qt app_bundle
+CONFIG -= qt
diff --git a/config.tests/common/sse2/sse2.pro b/config.tests/common/sse2/sse2.pro
index c8d0861170..b4031f13fa 100644
--- a/config.tests/common/sse2/sse2.pro
+++ b/config.tests/common/sse2/sse2.pro
@@ -1,6 +1,5 @@
SOURCES = sse2.cpp
CONFIG -= qt dylib release debug_and_release
CONFIG += debug console
-mac:CONFIG -= app_bundle
isEmpty(QMAKE_CFLAGS_SSE2):error("This compiler does not support SSE2")
else:QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_SSE2
diff --git a/config.tests/common/sse3/sse3.pro b/config.tests/common/sse3/sse3.pro
index 90f61d2065..f704c40c75 100644
--- a/config.tests/common/sse3/sse3.pro
+++ b/config.tests/common/sse3/sse3.pro
@@ -1,6 +1,5 @@
SOURCES = sse3.cpp
CONFIG -= qt dylib release debug_and_release
CONFIG += debug console
-mac:CONFIG -= app_bundle
isEmpty(QMAKE_CFLAGS_SSE3):error("This compiler does not support SSE3")
else:QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_SSE3
diff --git a/config.tests/common/sse4_1/sse4_1.pro b/config.tests/common/sse4_1/sse4_1.pro
index d92be9dc43..5cc04e7c5c 100644
--- a/config.tests/common/sse4_1/sse4_1.pro
+++ b/config.tests/common/sse4_1/sse4_1.pro
@@ -1,6 +1,5 @@
SOURCES = sse4_1.cpp
CONFIG -= qt dylib release debug_and_release
CONFIG += debug console
-mac:CONFIG -= app_bundle
isEmpty(QMAKE_CFLAGS_SSE4_1):error("This compiler does not support SSE4.1")
else:QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_SSE4_1
diff --git a/config.tests/common/sse4_2/sse4_2.pro b/config.tests/common/sse4_2/sse4_2.pro
index 744098dce8..6a04b1f9a5 100644
--- a/config.tests/common/sse4_2/sse4_2.pro
+++ b/config.tests/common/sse4_2/sse4_2.pro
@@ -1,6 +1,5 @@
SOURCES = sse4_2.cpp
CONFIG -= qt dylib release debug_and_release
CONFIG += debug console
-mac:CONFIG -= app_bundle
isEmpty(QMAKE_CFLAGS_SSE4_2):error("This compiler does not support SSE4.2")
else:QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_SSE4_2
diff --git a/config.tests/common/ssse3/ssse3.pro b/config.tests/common/ssse3/ssse3.pro
index e3984bd1cd..5b207e78ce 100644
--- a/config.tests/common/ssse3/ssse3.pro
+++ b/config.tests/common/ssse3/ssse3.pro
@@ -1,6 +1,5 @@
SOURCES = ssse3.cpp
CONFIG -= qt dylib release debug_and_release
CONFIG += debug console
-mac:CONFIG -= app_bundle
isEmpty(QMAKE_CFLAGS_SSSE3):error("This compiler does not support SSSE3")
else:QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_SSSE3
diff --git a/config.tests/mac/coreservices/coreservices.pro b/config.tests/mac/coreservices/coreservices.pro
index 6f7c07a487..64936eb974 100644
--- a/config.tests/mac/coreservices/coreservices.pro
+++ b/config.tests/mac/coreservices/coreservices.pro
@@ -1,3 +1,3 @@
OBJECTIVE_SOURCES = coreservices.mm
LIBS += -framework CoreServices
-CONFIG -= app_bundle qt
+CONFIG -= qt
diff --git a/config.tests/mac/corewlan/corewlan.pro b/config.tests/mac/corewlan/corewlan.pro
index a9c256043c..8db0c8c1e7 100644
--- a/config.tests/mac/corewlan/corewlan.pro
+++ b/config.tests/mac/corewlan/corewlan.pro
@@ -1,3 +1,3 @@
OBJECTIVE_SOURCES = corewlantest.mm
LIBS += -framework CoreWLAN -framework Foundation
-CONFIG -= app_bundle qt
+CONFIG -= qt
diff --git a/config.tests/qpa/directfb/directfb.pro b/config.tests/qpa/directfb/directfb.pro
index 958ced7bea..b138fd0109 100644
--- a/config.tests/qpa/directfb/directfb.pro
+++ b/config.tests/qpa/directfb/directfb.pro
@@ -1,3 +1,2 @@
SOURCES = directfb.cpp
CONFIG -= qt
-mac:CONFIG -= app_bundle
diff --git a/config.tests/unix/alsa/alsa.pro b/config.tests/unix/alsa/alsa.pro
index 4931d38ea8..6d5d55bcfd 100644
--- a/config.tests/unix/alsa/alsa.pro
+++ b/config.tests/unix/alsa/alsa.pro
@@ -1,4 +1,3 @@
SOURCES = alsatest.cpp
LIBS+=-lasound
CONFIG -= qt dylib
-mac:CONFIG -= app_bundle
diff --git a/config.tests/unix/arch.test b/config.tests/unix/arch.test
index 3efd6f4f25..529ed5e547 100755
--- a/config.tests/unix/arch.test
+++ b/config.tests/unix/arch.test
@@ -26,7 +26,7 @@ CXXFLAGS="$SYSROOT_FLAG"
test -d "$OUTDIR/config.tests/arch" || mkdir -p "$OUTDIR/config.tests/arch"
cd "$OUTDIR/config.tests/arch"
[ -f Makefile ] && $MAKE distclean >/dev/null 2>&1
-OUTDIR=$OUTDIR "$OUTDIR/bin/qmake" -nocache -spec "$QMKSPEC" "QT_BUILD_TREE=$OUTDIR" "LIBS+=$LFLAGS" "QMAKE_CXXFLAGS+=$CXXFLAGS" "$SRCDIR/config.tests/arch/arch$PROSUFFIX.pro" >/dev/null 2>&1 || echo "qmake is broken" >&2
+OUTDIR=$OUTDIR "$OUTDIR/bin/qmake" -nocache -spec "$QMKSPEC" "QT_BUILD_TREE=$OUTDIR" "LIBS+=$LFLAGS" "QMAKE_CXXFLAGS+=$CXXFLAGS" "CONFIG-=app_bundle" "$SRCDIR/config.tests/arch/arch$PROSUFFIX.pro" >/dev/null 2>&1 || echo "qmake is broken" >&2
ARCH=""
diff --git a/config.tests/unix/clock-gettime/clock-gettime.pro b/config.tests/unix/clock-gettime/clock-gettime.pro
index c527535183..bdbb1c2a82 100644
--- a/config.tests/unix/clock-gettime/clock-gettime.pro
+++ b/config.tests/unix/clock-gettime/clock-gettime.pro
@@ -1,4 +1,3 @@
SOURCES = clock-gettime.cpp
CONFIG -= qt dylib
-mac:CONFIG -= app_bundle
include(clock-gettime.pri)
diff --git a/config.tests/unix/clock-monotonic/clock-monotonic.pro b/config.tests/unix/clock-monotonic/clock-monotonic.pro
index 961e3a848d..253a9f7346 100644
--- a/config.tests/unix/clock-monotonic/clock-monotonic.pro
+++ b/config.tests/unix/clock-monotonic/clock-monotonic.pro
@@ -1,4 +1,3 @@
SOURCES = clock-monotonic.cpp
CONFIG -= qt dylib
-mac:CONFIG -= app_bundle
include(../clock-gettime/clock-gettime.pri)
diff --git a/config.tests/unix/compile.test b/config.tests/unix/compile.test
index 6b90044009..22064b85e9 100755
--- a/config.tests/unix/compile.test
+++ b/config.tests/unix/compile.test
@@ -67,7 +67,7 @@ test -r Makefile && $MAKE distclean >/dev/null 2>&1
# Make sure output from possible previous tests is gone
rm -f "$EXE" "${EXE}.exe"
-set -- "$OUTDIR/bin/qmake" -nocache -spec "$QMKSPEC" "CONFIG+=$QMAKE_CONFIG" "CONFIG+=android_app" "CONFIG-=debug_and_release" "LIBS*=$LFLAGS" "LIBS+=$MAC_ARCH_LFLAGS" "INCLUDEPATH*=$INCLUDEPATH" "QMAKE_CXXFLAGS*=$CXXFLAGS" "QMAKE_CXXFLAGS+=$MAC_ARCH_CXXFLAGS" "QT_BUILD_TREE=$OUTDIR" "$SRCDIR/$TEST/$EXE.pro" -o "$OUTDIR/$TEST/Makefile"
+set -- "$OUTDIR/bin/qmake" -nocache -spec "$QMKSPEC" "CONFIG+=$QMAKE_CONFIG" "CONFIG+=android_app" "CONFIG-=debug_and_release app_bundle lib_bundle" "LIBS*=$LFLAGS" "LIBS+=$MAC_ARCH_LFLAGS" "INCLUDEPATH*=$INCLUDEPATH" "QMAKE_CXXFLAGS*=$CXXFLAGS" "QMAKE_CXXFLAGS+=$MAC_ARCH_CXXFLAGS" "QT_BUILD_TREE=$OUTDIR" "$SRCDIR/$TEST/$EXE.pro" -o "$OUTDIR/$TEST/Makefile"
if [ "$VERBOSE" = "yes" ]; then
OUTDIR=$OUTDIR "$@"
$MAKE
diff --git a/config.tests/unix/cups/cups.pro b/config.tests/unix/cups/cups.pro
index d7b78c877f..3f8ca99d0f 100644
--- a/config.tests/unix/cups/cups.pro
+++ b/config.tests/unix/cups/cups.pro
@@ -1,4 +1,3 @@
SOURCES = cups.cpp
CONFIG -= qt dylib
-mac:CONFIG -= app_bundle
LIBS += -lcups
diff --git a/config.tests/unix/db2/db2.pro b/config.tests/unix/db2/db2.pro
index 0fa39a8242..b7316051f9 100644
--- a/config.tests/unix/db2/db2.pro
+++ b/config.tests/unix/db2/db2.pro
@@ -1,4 +1,3 @@
SOURCES = db2.cpp
CONFIG -= qt dylib
-mac:CONFIG -= app_bundle
LIBS += -ldb2
diff --git a/config.tests/unix/dbus/dbus.pro b/config.tests/unix/dbus/dbus.pro
index 1e4aea73e4..c2a01ea269 100644
--- a/config.tests/unix/dbus/dbus.pro
+++ b/config.tests/unix/dbus/dbus.pro
@@ -1,3 +1,2 @@
SOURCES = dbus.cpp
CONFIG -= qt
-mac:CONFIG -= app_bundle
diff --git a/config.tests/unix/eventfd/eventfd.pro b/config.tests/unix/eventfd/eventfd.pro
index c41204f49f..de99717750 100644
--- a/config.tests/unix/eventfd/eventfd.pro
+++ b/config.tests/unix/eventfd/eventfd.pro
@@ -1,3 +1,2 @@
SOURCES = main.cpp
CONFIG -= qt dylib
-mac:CONFIG -= app_bundle
diff --git a/config.tests/unix/fontconfig/fontconfig.pro b/config.tests/unix/fontconfig/fontconfig.pro
index 5989586751..8360774035 100644
--- a/config.tests/unix/fontconfig/fontconfig.pro
+++ b/config.tests/unix/fontconfig/fontconfig.pro
@@ -1,4 +1,4 @@
SOURCES = fontconfig.cpp
-CONFIG -= qt app_bundle
+CONFIG -= qt
LIBS += -lfreetype -lfontconfig
include(../../unix/freetype/freetype.pri)
diff --git a/config.tests/unix/getaddrinfo/getaddrinfo.pro b/config.tests/unix/getaddrinfo/getaddrinfo.pro
index c9121db9b4..cc739118fa 100644
--- a/config.tests/unix/getaddrinfo/getaddrinfo.pro
+++ b/config.tests/unix/getaddrinfo/getaddrinfo.pro
@@ -1,4 +1,3 @@
SOURCES = getaddrinfotest.cpp
CONFIG -= qt dylib
-mac:CONFIG -= app_bundle
LIBS += $$QMAKE_LIBS_NETWORK
diff --git a/config.tests/unix/getifaddrs/getifaddrs.pro b/config.tests/unix/getifaddrs/getifaddrs.pro
index c3fead6354..14a89f87b8 100644
--- a/config.tests/unix/getifaddrs/getifaddrs.pro
+++ b/config.tests/unix/getifaddrs/getifaddrs.pro
@@ -1,5 +1,4 @@
SOURCES = getifaddrs.cpp
CONFIG -= qt
-mac:CONFIG -= app_bundle
QT =
LIBS += $$QMAKE_LIBS_NETWORK
diff --git a/config.tests/unix/glib/glib.pro b/config.tests/unix/glib/glib.pro
index c7cd53d116..15d059df77 100644
--- a/config.tests/unix/glib/glib.pro
+++ b/config.tests/unix/glib/glib.pro
@@ -1,2 +1,2 @@
SOURCES = glib.cpp
-CONFIG -= qt app_bundle
+CONFIG -= qt
diff --git a/config.tests/unix/gnu-libiconv/gnu-libiconv.pro b/config.tests/unix/gnu-libiconv/gnu-libiconv.pro
index d879b205f1..1ecf94390a 100644
--- a/config.tests/unix/gnu-libiconv/gnu-libiconv.pro
+++ b/config.tests/unix/gnu-libiconv/gnu-libiconv.pro
@@ -1,4 +1,3 @@
SOURCES = gnu-libiconv.cpp
CONFIG -= qt dylib
-mac:CONFIG -= app_bundle
LIBS += -liconv
diff --git a/config.tests/unix/ibase/ibase.pro b/config.tests/unix/ibase/ibase.pro
index 01e7429733..58787851e1 100644
--- a/config.tests/unix/ibase/ibase.pro
+++ b/config.tests/unix/ibase/ibase.pro
@@ -1,4 +1,3 @@
SOURCES = ibase.cpp
CONFIG -= qt dylib
-mac:CONFIG -= app_bundle
LIBS += -lgds
diff --git a/config.tests/unix/iconv/iconv.pro b/config.tests/unix/iconv/iconv.pro
index 39375a5714..1ef6aa7207 100644
--- a/config.tests/unix/iconv/iconv.pro
+++ b/config.tests/unix/iconv/iconv.pro
@@ -1,3 +1,3 @@
SOURCES = iconv.cpp
-CONFIG -= qt dylib app_bundle
+CONFIG -= qt dylib
mac|win32-g++*|qnx:LIBS += -liconv
diff --git a/config.tests/unix/icu/icu.pro b/config.tests/unix/icu/icu.pro
index 8e583348bb..002c4840d5 100644
--- a/config.tests/unix/icu/icu.pro
+++ b/config.tests/unix/icu/icu.pro
@@ -1,4 +1,4 @@
SOURCES = icu.cpp
-CONFIG -= qt dylib app_bundle
+CONFIG -= qt dylib
unix:LIBS += -licuuc -licui18n
win32:LIBS += -licuin
diff --git a/config.tests/unix/inotify/inotify.pro b/config.tests/unix/inotify/inotify.pro
index e2e1560a47..35880de3c0 100644
--- a/config.tests/unix/inotify/inotify.pro
+++ b/config.tests/unix/inotify/inotify.pro
@@ -1,3 +1,2 @@
SOURCES = inotifytest.cpp
CONFIG -= qt dylib
-mac:CONFIG -= app_bundle
diff --git a/config.tests/unix/iodbc/iodbc.pro b/config.tests/unix/iodbc/iodbc.pro
index 465a9a7a1b..68a0bd0ef4 100644
--- a/config.tests/unix/iodbc/iodbc.pro
+++ b/config.tests/unix/iodbc/iodbc.pro
@@ -1,4 +1,3 @@
SOURCES = iodbc.cpp
CONFIG -= qt dylib
-mac:CONFIG -= app_bundle
LIBS += -liodbc
diff --git a/config.tests/unix/ipv6ifname/ipv6ifname.pro b/config.tests/unix/ipv6ifname/ipv6ifname.pro
index ed62869cb9..88203a782c 100644
--- a/config.tests/unix/ipv6ifname/ipv6ifname.pro
+++ b/config.tests/unix/ipv6ifname/ipv6ifname.pro
@@ -1,5 +1,4 @@
SOURCES = ipv6ifname.cpp
CONFIG -= qt
-mac:CONFIG -= app_bundle
QT =
LIBS += $$QMAKE_LIBS_NETWORK
diff --git a/config.tests/unix/libjpeg/libjpeg.pro b/config.tests/unix/libjpeg/libjpeg.pro
index d06888c57d..01329a11fe 100644
--- a/config.tests/unix/libjpeg/libjpeg.pro
+++ b/config.tests/unix/libjpeg/libjpeg.pro
@@ -1,4 +1,3 @@
SOURCES = libjpeg.cpp
CONFIG -= qt dylib
-mac:CONFIG -= app_bundle
LIBS += -ljpeg
diff --git a/config.tests/unix/libpng/libpng.pro b/config.tests/unix/libpng/libpng.pro
index f03838663e..4e50fe26e5 100644
--- a/config.tests/unix/libpng/libpng.pro
+++ b/config.tests/unix/libpng/libpng.pro
@@ -1,4 +1,3 @@
SOURCES = libpng.cpp
CONFIG -= qt dylib
-mac:CONFIG -= app_bundle
LIBS += -lpng
diff --git a/config.tests/unix/mremap/mremap.pro b/config.tests/unix/mremap/mremap.pro
index a36d756db3..1dbd3b7a7e 100644
--- a/config.tests/unix/mremap/mremap.pro
+++ b/config.tests/unix/mremap/mremap.pro
@@ -1,3 +1,2 @@
SOURCES = mremap.cpp
CONFIG -= qt dylib
-mac:CONFIG -= app_bundle
diff --git a/config.tests/unix/mysql/mysql.pro b/config.tests/unix/mysql/mysql.pro
index a22579e1bd..06d1880f08 100644
--- a/config.tests/unix/mysql/mysql.pro
+++ b/config.tests/unix/mysql/mysql.pro
@@ -1,4 +1,3 @@
SOURCES = mysql.cpp
CONFIG -= qt dylib
-mac:CONFIG -= app_bundle
LIBS += -lmysqlclient
diff --git a/config.tests/unix/mysql_r/mysql_r.pro b/config.tests/unix/mysql_r/mysql_r.pro
index 8c06067305..096da69487 100644
--- a/config.tests/unix/mysql_r/mysql_r.pro
+++ b/config.tests/unix/mysql_r/mysql_r.pro
@@ -1,4 +1,3 @@
SOURCES = ../mysql/mysql.cpp
CONFIG -= qt dylib
-mac:CONFIG -= app_bundle
LIBS += -lmysqlclient_r
diff --git a/config.tests/unix/nis/nis.pro b/config.tests/unix/nis/nis.pro
index 1f985b2049..b7f5693b60 100644
--- a/config.tests/unix/nis/nis.pro
+++ b/config.tests/unix/nis/nis.pro
@@ -1,5 +1,4 @@
SOURCES = nis.cpp
CONFIG -= qt dylib
-mac: CONFIG -= app_bundle
solaris-*:LIBS += -lnsl
else:LIBS += $$QMAKE_LIBS_NIS
diff --git a/config.tests/unix/oci/oci.pro b/config.tests/unix/oci/oci.pro
index 4add225f5d..3ffda1ddd7 100644
--- a/config.tests/unix/oci/oci.pro
+++ b/config.tests/unix/oci/oci.pro
@@ -1,4 +1,3 @@
SOURCES = oci.cpp
CONFIG -= qt dylib
-mac:CONFIG -= app_bundle
LIBS += -lclntsh
diff --git a/config.tests/unix/odbc/odbc.pro b/config.tests/unix/odbc/odbc.pro
index 06a548fd71..418a0e0d54 100644
--- a/config.tests/unix/odbc/odbc.pro
+++ b/config.tests/unix/odbc/odbc.pro
@@ -1,5 +1,4 @@
SOURCES = odbc.cpp
CONFIG -= qt dylib
-mac:CONFIG -= app_bundle
win32-g++*:LIBS += -lodbc32
else:LIBS += -lodbc
diff --git a/config.tests/unix/opengldesktop/opengldesktop.pro b/config.tests/unix/opengldesktop/opengldesktop.pro
index fbf36a0c67..c3e700c50a 100644
--- a/config.tests/unix/opengldesktop/opengldesktop.pro
+++ b/config.tests/unix/opengldesktop/opengldesktop.pro
@@ -9,4 +9,3 @@ CONFIG -= qt
LIBS += $$QMAKE_LIBS_OPENGL
mac:DEFINES += Q_OS_MAC
-CONFIG -= app_bundle
diff --git a/config.tests/unix/opengles1/opengles1.pro b/config.tests/unix/opengles1/opengles1.pro
index 9e6012474d..58817e6a6e 100644
--- a/config.tests/unix/opengles1/opengles1.pro
+++ b/config.tests/unix/opengles1/opengles1.pro
@@ -9,5 +9,4 @@ CONFIG -= qt
LIBS += $$QMAKE_LIBS_OPENGL_ES1
mac {
DEFINES += BUILD_ON_MAC
- CONFIG -= app_bundle
}
diff --git a/config.tests/unix/opengles2/opengles2.pro b/config.tests/unix/opengles2/opengles2.pro
index 34d77371b4..c4d76895a8 100644
--- a/config.tests/unix/opengles2/opengles2.pro
+++ b/config.tests/unix/opengles2/opengles2.pro
@@ -9,5 +9,4 @@ CONFIG -= qt
LIBS += $$QMAKE_LIBS_OPENGL_ES2
mac {
DEFINES += BUILD_ON_MAC
- CONFIG -= app_bundle
}
diff --git a/config.tests/unix/openssl/openssl.pro b/config.tests/unix/openssl/openssl.pro
index 1c537cb2b1..a023aee4aa 100644
--- a/config.tests/unix/openssl/openssl.pro
+++ b/config.tests/unix/openssl/openssl.pro
@@ -1,3 +1,2 @@
SOURCES = openssl.cpp
CONFIG -= x11 qt
-mac:CONFIG -= app_bundle
diff --git a/config.tests/unix/pcre/pcre.pro b/config.tests/unix/pcre/pcre.pro
index b29c55da47..7b8bfc6545 100644
--- a/config.tests/unix/pcre/pcre.pro
+++ b/config.tests/unix/pcre/pcre.pro
@@ -1,3 +1,3 @@
SOURCES = pcre.cpp
-CONFIG -= qt dylib app_bundle
+CONFIG -= qt dylib
LIBS += -lpcre16
diff --git a/config.tests/unix/psql/psql.pro b/config.tests/unix/psql/psql.pro
index 38bfb3ed70..d0f3761bfb 100644
--- a/config.tests/unix/psql/psql.pro
+++ b/config.tests/unix/psql/psql.pro
@@ -1,4 +1,3 @@
SOURCES = psql.cpp
CONFIG -= qt dylib
-mac:CONFIG -= app_bundle
LIBS *= -lpq
diff --git a/config.tests/unix/ptrsize.test b/config.tests/unix/ptrsize.test
index c78c73f7a2..3ad15dbd2b 100755
--- a/config.tests/unix/ptrsize.test
+++ b/config.tests/unix/ptrsize.test
@@ -10,7 +10,7 @@ OUTDIR=$4
# build and run a test program
test -d "$OUTDIR/config.tests/unix/ptrsize" || mkdir -p "$OUTDIR/config.tests/unix/ptrsize"
-"$OUTDIR/bin/qmake" -nocache -spec "$QMKSPEC" "QT_BUILD_TREE=$OUTDIR" "$SRCDIR/config.tests/unix/ptrsize/ptrsizetest.pro" -o "$OUTDIR/config.tests/unix/ptrsize/Makefile" >/dev/null 2>&1
+"$OUTDIR/bin/qmake" -nocache -spec "$QMKSPEC" "QT_BUILD_TREE=$OUTDIR" "CONFIG-=app_bundle" "$SRCDIR/config.tests/unix/ptrsize/ptrsizetest.pro" -o "$OUTDIR/config.tests/unix/ptrsize/Makefile" >/dev/null 2>&1
cd "$OUTDIR/config.tests/unix/ptrsize"
if [ "$VERBOSE" = "yes" ]; then
diff --git a/config.tests/unix/ptrsize/ptrsizetest.pro b/config.tests/unix/ptrsize/ptrsizetest.pro
index 41aba86dd9..045a759ec9 100644
--- a/config.tests/unix/ptrsize/ptrsizetest.pro
+++ b/config.tests/unix/ptrsize/ptrsizetest.pro
@@ -1,3 +1,2 @@
SOURCES = ptrsizetest.cpp
CONFIG -= qt dylib
-mac:CONFIG -= app_bundle
diff --git a/config.tests/unix/slog2/slog2.pro b/config.tests/unix/slog2/slog2.pro
index 9f5b34d664..e65460bb94 100644
--- a/config.tests/unix/slog2/slog2.pro
+++ b/config.tests/unix/slog2/slog2.pro
@@ -1,4 +1,3 @@
SOURCES = slog2.cpp
CONFIG -= qt
-mac:CONFIG -= app_bundle
LIBS += -lslog2
diff --git a/config.tests/unix/sqlite/sqlite.pro b/config.tests/unix/sqlite/sqlite.pro
index ba2cac1465..4b24e014ba 100644
--- a/config.tests/unix/sqlite/sqlite.pro
+++ b/config.tests/unix/sqlite/sqlite.pro
@@ -1,3 +1,2 @@
SOURCES = sqlite.cpp
CONFIG -= qt dylib
-mac:CONFIG -= app_bundle
diff --git a/config.tests/unix/sqlite2/sqlite2.pro b/config.tests/unix/sqlite2/sqlite2.pro
index 14a64d5db9..7e69fdf2f3 100644
--- a/config.tests/unix/sqlite2/sqlite2.pro
+++ b/config.tests/unix/sqlite2/sqlite2.pro
@@ -1,4 +1,3 @@
SOURCES = sqlite2.cpp
CONFIG -= qt dylib
-mac:CONFIG -= app_bundle
LIBS += -lsqlite
diff --git a/config.tests/unix/stdint/stdint.pro b/config.tests/unix/stdint/stdint.pro
index 79a0d9cd3a..9975484889 100644
--- a/config.tests/unix/stdint/stdint.pro
+++ b/config.tests/unix/stdint/stdint.pro
@@ -1,4 +1,3 @@
SOURCES = main.cpp
CONFIG -= x11 qt
-mac:CONFIG -= app_bundle
diff --git a/config.tests/unix/stl/stl.pro b/config.tests/unix/stl/stl.pro
index a2feab431c..7303e8d31c 100644
--- a/config.tests/unix/stl/stl.pro
+++ b/config.tests/unix/stl/stl.pro
@@ -1,3 +1,2 @@
SOURCES = stltest.cpp
CONFIG -= qt dylib
-mac:CONFIG -= app_bundle
diff --git a/config.tests/unix/sun-libiconv/sun-libiconv.pro b/config.tests/unix/sun-libiconv/sun-libiconv.pro
index 00df8653c8..923afc7dd2 100644
--- a/config.tests/unix/sun-libiconv/sun-libiconv.pro
+++ b/config.tests/unix/sun-libiconv/sun-libiconv.pro
@@ -1,2 +1,2 @@
SOURCES = ../gnu-libiconv/gnu-libiconv.cpp
-CONFIG -= qt dylib app_bundle
+CONFIG -= qt dylib
diff --git a/config.tests/unix/tds/tds.pro b/config.tests/unix/tds/tds.pro
index 5516a14c8f..6712779d58 100644
--- a/config.tests/unix/tds/tds.pro
+++ b/config.tests/unix/tds/tds.pro
@@ -1,4 +1,3 @@
SOURCES = tds.cpp
CONFIG -= qt dylib
-mac:CONFIG -= app_bundle
LIBS += -lsybdb
diff --git a/config.tests/unix/zlib/zlib.pro b/config.tests/unix/zlib/zlib.pro
index 67cc870516..d9bd03e5df 100644
--- a/config.tests/unix/zlib/zlib.pro
+++ b/config.tests/unix/zlib/zlib.pro
@@ -1,4 +1,3 @@
SOURCES = zlib.cpp
CONFIG -= qt dylib
-mac:CONFIG -= app_bundle
LIBS += -lz
diff --git a/configure b/configure
index 140c7b4131..c3994307e7 100755
--- a/configure
+++ b/configure
@@ -2449,47 +2449,7 @@ if [ "$OPT_SHADOW" = "yes" ]; then
[ -d "$outpath/bin" ] || mkdir -p "$outpath/bin"
- # save a pre-existing mkspecs/modules dir
- test -d "$outpath/mkspecs/modules" && \
- mv "$outpath/mkspecs/modules" "$outpath/mkspecs-modules"
- # ditto for mkspecs/modules-inst
- test -d "$outpath/mkspecs/modules-inst" && \
- mv "$outpath/mkspecs/modules-inst" "$outpath/mkspecs-modules-inst"
-
- # symlink the mkspecs directory
mkdir -p "$outpath/mkspecs"
- rm -rf "$outpath"/mkspecs/*
- ln -s "$relpath"/mkspecs/* "$outpath/mkspecs"
-
- ShadowMkspecs()
- {
- rm -rf "$outpath/mkspecs/$1"
- find "$relpath/mkspecs/$1" -type d | sed "s,^$relpath,$outpath," | xargs mkdir -p
- find "$relpath/mkspecs/$1" -type f | sed "s,^$relpath/,," | while read f; do ln -s "$relpath/$f" "$outpath/$f"; done
- }
-
- # Special case for mkspecs/features directory.
- # To be able to place .prf files into a shadow build directory,
- # we're creating links for files only. The directory structure is reproduced.
- ShadowMkspecs features
-
- # The modules dir is special, too.
- if test -d "$outpath/mkspecs-modules"; then
- rm -rf "$outpath/mkspecs/modules"
- mv "$outpath/mkspecs-modules" "$outpath/mkspecs/modules"
- else
- ShadowMkspecs modules
- fi
-
- # The modules-inst dir is not quite as special, but still.
- if test -d "$outpath/mkspecs-modules-inst"; then
- rm -rf "$outpath/mkspecs/modules-inst"
- mv "$outpath/mkspecs-modules-inst" "$outpath/mkspecs/modules-inst"
- fi
-
- # Prepare doc directory
- mkdir -p "$outpath/doc"
- ln -f -s "$relpath"/doc/global "$outpath/doc"
fi
# symlink fonts to be able to run application from build directory
@@ -3031,21 +2991,44 @@ else
fi
# auto-detect default include and library search paths
-gccout=`LC_ALL=C $TEST_COMPILER $SYSROOT_FLAG $TEST_COMPILER_CXXFLAGS -xc++ -E -v - < /dev/null 2>&1 > /dev/null`
-# extract from one line like 'LIBRARY_PATH=/one/path:/another/path:...'
-libdirs=`echo "$gccout" | sed -n -e 's/^LIBRARY_PATH=\(.*\)/\1/p'`
-DEFAULT_LIBDIRS=`IFS=${HOST_DIRLIST_SEP}; for i in $libdirs; do test -d "$i" && cd "$i" && pwd; done`
-# extract from indented lines between '#include <...> search starts here:' and 'End of search list.'
-DEFAULT_INCDIRS=`echo "$gccout" | $AWK '
-/^End of search/ { yup=0 }
+unset tty
+[ "$OPT_VERBOSE" = "yes" ] && tty=/dev/stderr
+
+eval `LC_ALL=C $TEST_COMPILER $SYSROOT_FLAG $TEST_COMPILER_CXXFLAGS -xc++ -E -v - < /dev/null 2>&1 > /dev/null | $AWK '
+BEGIN { ORS = ""; FS = "="; incs = 0; libs = 0; }
+function quote(s)
+{
+ # We only handle spaces
+ if (match(s, " ") != 0)
+ return "\\\\\"" s "\\\\\"";
+ return s;
+}
+
+# extract include paths from indented lines between
+# #include <...> search starts here:
+# and
+# End of search list.
+/^\#include </ { yup=1; print "DEFAULT_INCDIRS=\""; next }
+/^End of search/ { yup=0; print "\"\n" }
/ \(framework directory\)$/ { next }
-yup { print substr($0, 2) }
-/^\#include </ { yup=1 }
-'`
-test -z "$DEFAULT_LIBDIRS" && DEFAULT_LIBDIRS="/lib
-/usr/lib"
-test -z "$DEFAULT_INCDIRS" && DEFAULT_INCDIRS="/usr/include
-/usr/local/include"
+yup { print quote(substr($0, 2)) " "; ++incs }
+
+# extract from one line like LIBRARY_PATH=/one/path:/another/path:...
+$1 == "LIBRARY_PATH" {
+ libs = split($2, library_paths, ":");
+ print "DEFAULT_LIBDIRS=\"";
+ for (lib in library_paths)
+ print quote(library_paths[lib]) " ";
+ print "\"\n"
+}
+
+END {
+ if (incs == 0)
+ print "DEFAULT_INCDIRS=\"/usr/include /usr/local/include\"\n";
+ if (libs == 0)
+ print "DEFAULT_LIBDIRS=\"/lib /usr/lib\"\n";
+}' | tee $tty`
+unset tty
#setup the build parts
if [ -z "$CFG_BUILD_PARTS" ]; then
@@ -4116,6 +4099,12 @@ cat > "$QTCONFFILE" <<EOF
[EffectivePaths]
Prefix=..
EOF
+if [ x"$relpath" != x"$outpath" ]; then
+ cat >> "$QTCONFFILE" <<EOF
+[EffectiveSourcePaths]
+Prefix=$relpath
+EOF
+fi
#-------------------------------------------------------------------------------
# write out device config before we run the test.
@@ -4390,8 +4379,7 @@ fi
# detect neon support
if [ "$CFG_ARCH" = "arm" ] && [ "${CFG_NEON}" = "auto" ]; then
- # The iOS toolchain has trouble building the pixman NEON draw-helpers
- if [ "$XPLATFORM_IOS" != "yes" ] && compileTest unix/neon "neon"; then
+ if compileTest unix/neon "neon"; then
CFG_NEON=yes
else
CFG_NEON=no
@@ -6526,12 +6514,13 @@ fi
cat >>"$QTCONFIG.tmp" <<EOF
#configuration
CONFIG += $QTCONFIG_CONFIG
-QT_ARCH = $CFG_ARCH
-QT_HOST_ARCH = $CFG_HOST_ARCH
-QT_CPU_FEATURES = $CFG_CPUFEATURES
-QT_HOST_CPU_FEATURES = $CFG_HOST_CPUFEATURES
-QMAKE_DEFAULT_LIBDIRS = `echo "$DEFAULT_LIBDIRS" | sed 's,^,",;s,$,",' | tr '\n' ' '`
-QMAKE_DEFAULT_INCDIRS = `echo "$DEFAULT_INCDIRS" | sed 's,^,",;s,$,",' | tr '\n' ' '`
+host_build {
+ QT_ARCH = $CFG_HOST_ARCH
+} else {
+ QT_ARCH = $CFG_ARCH
+ QMAKE_DEFAULT_LIBDIRS = $DEFAULT_LIBDIRS
+ QMAKE_DEFAULT_INCDIRS = $DEFAULT_INCDIRS
+}
QT_EDITION = $Edition
QT_CONFIG += $QT_CONFIG
@@ -6613,6 +6602,14 @@ if [ -n "$CFG_SKIP_MODULES" ]; then
echo "QT_SKIP_MODULES += $CFG_SKIP_MODULES" >> "$QTMODULE.tmp"
fi
+cat >>"$QTMODULE.tmp" <<EOF
+host_build {
+ QT_CPU_FEATURES.$CFG_HOST_ARCH = $CFG_HOST_CPUFEATURES
+} else {
+ QT_CPU_FEATURES.$CFG_ARCH = $CFG_CPUFEATURES
+}
+EOF
+
if [ -n "$QT_CFLAGS_PSQL" ]; then
echo "QT_CFLAGS_PSQL = $QT_CFLAGS_PSQL" >> "$QTMODULE.tmp"
fi
diff --git a/dist/changes-5.2.0 b/dist/changes-5.2.0
new file mode 100644
index 0000000000..dab73b7a2e
--- /dev/null
+++ b/dist/changes-5.2.0
@@ -0,0 +1,42 @@
+Qt 5.2 introduces many new features and improvements as well as bugfixes
+over the 5.1.x series. 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.
+
+****************************************************************************
+* Library *
+****************************************************************************
+
+QtWidgets
+---------
+
+- QAbstractScrollArea now has a SizeAdjustPolicy. If it is set to AdjustToContents
+ it will make use of the new protected viewportSizeHint() (binary compatible since it
+ was reserved in Qt5). This function returns a suggested size based on contents.
+
+- [QTBUG-4206] QTableView resizeToContents will now adjust to actual contents
+ and not just visible area. QHeaderView::setAutoResizePrecision() has been
+ introduced to control how precise the autoResize should be.
+
+- QFileDialog::setDefaultSuffix() removes leading dot characters.
+
+- QSizePolicy got a retainSizeWhenHidden attribute.
+
+QtCore
+------
+- [QTBUG-30250] QTime, QDateTime:
+ When calling QTime::toString(Qt::TextDate) and QTime::toString(Qt::ISODate),
+ milliseconds are now included in the returned string. This also applies to
+ QDateTime::toString(Qt::TextDate) and QDateTime::toString(ISODate).
diff --git a/doc/global/config.qdocconf b/doc/global/config.qdocconf
new file mode 100644
index 0000000000..2b3ca1d6ba
--- /dev/null
+++ b/doc/global/config.qdocconf
@@ -0,0 +1,12 @@
+#Include this file to inherit configuration related to Qt Project based modules.
+
+dita.metadata.default.author = Qt Project
+dita.metadata.default.permissions = all
+dita.metadata.default.publisher = Qt Project
+dita.metadata.default.copyryear = 2013
+dita.metadata.default.copyrholder = Digia Plc
+dita.metadata.default.audience = programmer
+
+#Set the main Qt index.html
+navigation.homepage = "Qt $QT_VER"
+buildversion = "Qt $QT_VERSION Reference Documentation"
diff --git a/doc/global/fileextensions.qdocconf b/doc/global/fileextensions.qdocconf
new file mode 100644
index 0000000000..ec47dc9c7f
--- /dev/null
+++ b/doc/global/fileextensions.qdocconf
@@ -0,0 +1,12 @@
+naturallanguage = en_US
+outputencoding = UTF-8
+sourceencoding = UTF-8
+
+examples.fileextensions = "*.cpp *.h *.js *.xq *.svg *.xml *.ui *.qhp *.qhcp *.qml *.css"
+examples.imageextensions = "*.png *.jpg *.gif"
+
+headers.fileextensions = "*.ch *.h *.h++ *.hh *.hpp *.hxx"
+sources.fileextensions = "*.c++ *.cc *.cpp *.cxx *.mm *.qml *.qdoc"
+
+#include the external websites
+sourcedirs += externalsites
diff --git a/doc/global/html-config.qdocconf b/doc/global/html-config.qdocconf
new file mode 100644
index 0000000000..1560db8d98
--- /dev/null
+++ b/doc/global/html-config.qdocconf
@@ -0,0 +1,29 @@
+#Additional HTML settings
+
+HTML.nonavigationbar = "false"
+
+HTML.extraimages += template/images/arrow_bc.png \
+ template/images/home.png \
+ template/images/ico_out.png \
+ template/images/ico_note.png \
+ template/images/ico_note_attention.png \
+ template/images/btn_prev.png \
+ template/images/btn_next.png \
+ template/images/bullet_dn.png \
+ template/images/bullet_sq.png \
+ template/images/bgrContent.png \
+ template/images/logo.png
+
+#specify which files in the output directory should be packed into the qch file.
+#these files are assumed to be in each module's output directory."qtquick/images/ico_out.png" for example.
+qhp.extraFiles += images/arrow_bc.png \
+ images/home.png \
+ images/ico_out.png \
+ images/ico_note.png \
+ images/ico_note_attention.png \
+ images/btn_prev.png \
+ images/btn_next.png \
+ images/bullet_dn.png \
+ images/bullet_sq.png \
+ images/bgrContent.png \
+ images/logo.png
diff --git a/doc/global/html-footer.qdocconf b/doc/global/html-footer.qdocconf
new file mode 100644
index 0000000000..6c26dc7c29
--- /dev/null
+++ b/doc/global/html-footer.qdocconf
@@ -0,0 +1,30 @@
+#Default HTML footer for QDoc builds.
+
+HTML.footer = \
+ " </div>\n" \
+ " </div>\n" \
+ " </div>\n" \
+ " </div>\n" \
+ "</div>\n" \
+ "<div class=\"footer\">\n" \
+ " <div class=\"qt13a-copyright\" id=\"copyright\">\n" \
+ " <div class=\"qt13a-container\">\n" \
+ " <p>\n" \
+ " <acronym title=\"Copyright\">&copy;</acronym> 2013 Digia Plc and/or its\n" \
+ " subsidiaries. Documentation contributions included herein are the copyrights of\n" \
+ " their respective owners.</p>\n" \
+ " <p>\n" \
+ " The documentation provided herein is licensed under the terms of the\n" \
+ " <a href=\"http://www.gnu.org/licenses/fdl.html\">GNU Free Documentation\n" \
+ " License version 1.3</a> as published by the Free Software Foundation.</p>\n" \
+ " <p>\n" \
+ " Documentation sources may be obtained from <a href=\"http://www.qt-project.org\">\n" \
+ " www.qt-project.org</a>.</p>\n" \
+ " <p>\n" \
+ " Digia, Qt and their respective logos are trademarks of Digia Plc \n" \
+ " in Finland and/or other countries worldwide. All other trademarks are property\n" \
+ " of their respective owners. <a title=\"Privacy Policy\"\n" \
+ " href=\"http://en.gitorious.org/privacy_policy/\">Privacy Policy</a></p>\n" \
+ " </div>\n" \
+ " </div>\n" \
+ "</div>\n" \
diff --git a/doc/global/html-header-offline.qdocconf b/doc/global/html-header-offline.qdocconf
new file mode 100644
index 0000000000..d84f38fef8
--- /dev/null
+++ b/doc/global/html-header-offline.qdocconf
@@ -0,0 +1,31 @@
+#Default HTML header for QDoc builds.
+
+#specify the CSS file used by this template
+HTML.stylesheets = template/style/offline.css
+
+#for including files into the qch file
+qhp.extraFiles += style/offline.css
+
+HTML.headerstyles = \
+ " <link rel=\"stylesheet\" type=\"text/css\" href=\"style/offline.css\" />\n"
+
+HTML.endheader = \
+ "</head>\n"
+
+HTML.postheader = \
+ "<body>\n" \
+ "<div class=\"header\" id=\"qtdocheader\">\n"\
+ " <div class=\"main\">\n" \
+ " <div class=\"main-rounded\">\n" \
+ " <div class=\"navigationbar\">\n"\
+ " <ul>\n"\
+
+
+
+HTML.postpostheader = \
+ " </ul>\n"\
+ " </div>\n" \
+ "</div>\n" \
+ "<div class=\"content\">\n" \
+ "<div class=\"line\">\n" \
+ "<div class=\"content mainContent\">\n" \
diff --git a/doc/global/html-header-online.qdocconf b/doc/global/html-header-online.qdocconf
new file mode 100644
index 0000000000..5c21644a39
--- /dev/null
+++ b/doc/global/html-header-online.qdocconf
@@ -0,0 +1,64 @@
+#HTML Header with Qt Project branding and online links
+
+HTML.stylesheets = template/style/online.css
+
+#for including files into the qch file. Relative to the outputdir of a QDoc build.
+# $QT_INSTALL_DOCS/qtquick/style/online.css for example
+qhp.extraFiles += style/online.css
+
+HTML.headerstyles = \
+ " <link rel=\"stylesheet\" type=\"text/css\" href=\"style/online.css\" />\n"
+
+HTML.endheader = \
+ "</head>\n"
+
+HTML.postheader = \
+ "<body>\n" \
+ "<div class=\"header\" id=\"qtdocheader\"></div>\n" \
+ " <div class=\"nav\" id=\"qt13a-header\">\n" \
+ " <div class=\"qt13a-gradient\">\n" \
+ " <div class=\"qt13a-container qt13a-dynamicREMOVE\" >\n" \
+ " <div id=\"qt13a-register\">\n" \
+ " <a href=\"http://qt-project.org/\">Qt Home</a>\n" \
+ " <a href=\"https://bugreports.qt-project.org/\">Bug Tracker</a>\n" \
+ " <a href=\"https://codereview.qt-project.org/\">Code Review</a>\n" \
+ " </div>\n" \
+ " <div class=\"qt13a-sixCol\">\n" \
+ " <div id=\"qt13a-logo\">\n" \
+ " <a href=\"http://qt-project.org/\" class=\"qt13a-site-logo\">\n" \
+ " <img src=\"images/Qt-logo.png\" alt=\"Qt\"></img>\n" \
+ " </a>\n" \
+ " </div>\n" \
+ " <div id=\"qt13a-title_nav\">\n" \
+ " <div id=\"qt13a-title\">\n" \
+ " <p class=\"qt13a-title\">Qt Documentation Snapshots</p>\n" \
+ " </div>\n" \
+ " <div class=\"qt13a-nav\">\n" \
+ " <ul>\n" \
+ " <li>\n" \
+ " <a href=\"http://doc-snapshot.qt-project.org\">Snapshots</a>\n" \
+ " </li>\n" \
+ " <li>\n" \
+ " <a href=\"http://qt-project.org/doc\">Released</a>\n" \
+ " </li>\n" \
+ " <li>\n" \
+ " <a href=\"http://doc.qt.digia.com\">Archives</a>\n" \
+ " </li>\n" \
+ " </ul>\n" \
+ " </div>\n" \
+ " </div>\n" \
+ " </div>\n" \
+ " </div>\n" \
+ " </div>\n" \
+ " </div>\n" \
+ " <div class=\"main\">\n" \
+ " <div class=\"main-rounded\">\n" \
+ " <div class=\"navigationbar\">\n" \
+ " <ul>\n" \
+
+HTML.postpostheader = \
+ " </ul>\n" \
+ " </div>\n" \
+ "<div class=\"content\">\n" \
+ " <div class=\"line\">\n" \
+ " <div class=\"content mainContent\">\n" \
diff --git a/doc/global/qt-cpp-ignore.qdocconf b/doc/global/qt-cpp-defines.qdocconf
index 1f34f366cb..e65baf6c5f 100644
--- a/doc/global/qt-cpp-ignore.qdocconf
+++ b/doc/global/qt-cpp-defines.qdocconf
@@ -1,3 +1,21 @@
+versionsym = QT_VERSION_STR
+
+defines += Q_QDOC \
+ QT_.*_SUPPORT \
+ QT_.*_LIB \
+ QT_COMPAT \
+ QT_KEYPAD_NAVIGATION \
+ QT_NO_EGL \
+ QT3_SUPPORT \
+ Q_WS_.* \
+ Q_OS_.* \
+ Q_BYTE_ORDER \
+ QT_DEPRECATED \
+ QT_DEPRECATED_* \
+ Q_NO_USING_KEYWORD \
+ __cplusplus \
+ Q_COMPILER_INITIALIZER_LISTS
+
Cpp.ignoretokens += \
PHONON_EXPORT \
Q_AUTOTEST_EXPORT \
@@ -84,13 +102,15 @@ Cpp.ignoretokens += \
QT_END_NAMESPACE \
QT_FASTCALL \
QT_WIDGET_PLUGIN_EXPORT \
- QTBLUETOOTH_BEGIN_NAMESPACE \
- QTBLUETOOTH_END_NAMESAPCE \
- QTNFC_BEGIN_NAMESPACE \
- QTNFC_END_NAMESPACE \
+ 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 = \
+Cpp.ignoredirectives += \
__attribute__ \
K_DECLARE_PRIVATE \
PHONON_HEIR \
diff --git a/doc/global/qt-defines.qdocconf b/doc/global/qt-defines.qdocconf
deleted file mode 100644
index 79b13eee92..0000000000
--- a/doc/global/qt-defines.qdocconf
+++ /dev/null
@@ -1,17 +0,0 @@
-versionsym = QT_VERSION_STR
-
-defines += Q_QDOC \
- QT_.*_SUPPORT \
- QT_.*_LIB \
- QT_COMPAT \
- QT_KEYPAD_NAVIGATION \
- QT_NO_EGL \
- QT3_SUPPORT \
- Q_WS_.* \
- Q_OS_.* \
- Q_BYTE_ORDER \
- QT_DEPRECATED \
- QT_DEPRECATED_* \
- Q_NO_USING_KEYWORD \
- __cplusplus \
- Q_COMPILER_INITIALIZER_LISTS
diff --git a/doc/global/qt-html-templates-offline.qdocconf b/doc/global/qt-html-templates-offline.qdocconf
index e9b2c6a7a8..cd8315aa9a 100644
--- a/doc/global/qt-html-templates-offline.qdocconf
+++ b/doc/global/qt-html-templates-offline.qdocconf
@@ -1,4 +1,10 @@
-HTML.nobreadcrumbs = "true"
+#include standard set of HTML header and footer.
+include(html-config.qdocconf)
+include(html-header-offline.qdocconf)
+include(html-footer.qdocconf)
+
+#uncomment if navigation bar is not wanted
+#HTML.nonavigationbar = "true"
HTML.stylesheets = template/style/offline.css
HTML.extraimages += template/images/ico_out.png \
@@ -20,40 +26,3 @@ qhp.extraFiles += style/offline.css \
images/bullet_dn.png \
images/bullet_sq.png \
images/bgrContent.png
-
-
-HTML.headerstyles = \
- " <link rel=\"stylesheet\" type=\"text/css\" href=\"style/offline.css\" />\n"
-
-HTML.endheader = \
- "</head>\n" \
- "<body>\n" \
- "<div class=\"header\" id=\"qtdocheader\"></div>\n"\
- "<div class=\"content\">\n" \
- "<div class=\"line\">\n" \
- "<div class=\"content mainContent\">\n" \
-
-HTML.footer = \
- "</div>\n" \
- "</div>\n" \
- "</div>\n" \
- "<div class=\"footer\">\n" \
- " <p>\n" \
- " <acronym title=\"Copyright\">&copy;</acronym> 2013 Digia Plc and/or its\n" \
- " subsidiaries. Documentation contributions included herein are the copyrights of\n" \
- " their respective owners.</p>\n" \
- " <br />\n" \
- " <p>\n" \
- " The documentation provided herein is licensed under the terms of the\n" \
- " <a href=\"http://www.gnu.org/licenses/fdl.html\">GNU Free Documentation\n" \
- " License version 1.3</a> as published by the Free Software Foundation.</p>\n" \
- " <p>\n" \
- " Documentation sources may be obtained from <a href=\"http://www.qt-project.org\">\n" \
- " www.qt-project.org</a>.</p>\n" \
- " <br />\n" \
- " <p>\n" \
- " Digia, Qt and their respective logos are trademarks of Digia Plc \n" \
- " in Finland and/or other countries worldwide. All other trademarks are property\n" \
- " of their respective owners. <a title=\"Privacy Policy\"\n" \
- " href=\"http://en.gitorious.org/privacy_policy/\">Privacy Policy</a></p>\n" \
- "</div>\n" \
diff --git a/doc/global/qt-html-templates-online.qdocconf b/doc/global/qt-html-templates-online.qdocconf
index c794c47679..88abc3429b 100644
--- a/doc/global/qt-html-templates-online.qdocconf
+++ b/doc/global/qt-html-templates-online.qdocconf
@@ -1,4 +1,10 @@
-HTML.nobreadcrumbs = "true"
+#include standard set of HTML header and footer.
+include(html-config.qdocconf)
+include(html-header-online.qdocconf)
+include(html-footer.qdocconf)
+
+#uncomment if navigation bar is not wanted
+#HTML.nonavigationbar = "true"
HTML.stylesheets = template/style/online.css
HTML.extraimages += template/images/ico_out.png \
@@ -8,67 +14,10 @@ HTML.extraimages += template/images/ico_out.png \
template/images/btn_next.png \
template/images/bullet_dn.png \
template/images/bullet_sq.png \
- template/images/bgrContent.png
-
-HTML.headerstyles = \
- " <link rel=\"stylesheet\" type=\"text/css\" href=\"style/online.css\" />\n"
-
-HTML.endheader = \
- "</head>\n" \
- "<body>\n" \
- "<div class=\"header\" id=\"qtdocheader\"></div>\n" \
- " <header>\n" \
- " <div class=\"nav\">\n" \
- " <a href=\"http://qt-project.org/\">Qt Home</a>\n" \
- " <a href=\"https://bugreports.qt-project.org/\">Bug Tracker</a>\n" \
- " <a href=\"https://codereview.qt-project.org/\">Code Review</a>\n" \
- " </div>\n" \
- " <a href=\"http://qt-project.org/\">\n" \
- " <img src=\"http://doc-snapshot.qt-project.org/images/logo.png\" alt=\"Qt\"></img>\n" \
- " </a>\n" \
- " <div class=\"nav-title\">\n" \
- " <h1 >Qt Documentation Snapshots</h1>\n" \
- " <div class=\"nav-subtitle\">\n" \
- " --snapshots of unreleased Qt documentation\n" \
- " </div>\n" \
- " </div>\n" \
- " <div class=\"nav-main\">\n" \
- " <div class=\"nav-main-content\">\n" \
- " <a href=\"http://doc-snapshot.qt-project.org\">All Modules</a>\n" \
- " </div>\n" \
- " <div class=\"nav-main-content\">\n" \
- " <a href=\"http://qt-project.org/doc\">Qt Releases</a>\n" \
- " </div>\n" \
- " <div class=\"nav-main-content\">\n" \
- " <a href=\"http://doc.qt.digia.com\">Archives</a>\n" \
- " </div>\n" \
- " </div>\n" \
- "</header>\n" \
- "<div class=\"content\">\n" \
- " <div class=\"line\">\n" \
- " <div class=\"content mainContent\">\n" \
-
-HTML.footer = \
- " </div>\n" \
- " </div>\n" \
- "</div>\n" \
- "<div class=\"footer\">\n" \
- " <p>\n" \
- " <acronym title=\"Copyright\">&copy;</acronym> 2013 Digia Plc and/or its\n" \
- " subsidiaries. Documentation contributions included herein are the copyrights of\n" \
- " their respective owners.</p>\n" \
- " <br />\n" \
- " <p>\n" \
- " The documentation provided herein is licensed under the terms of the\n" \
- " <a href=\"http://www.gnu.org/licenses/fdl.html\">GNU Free Documentation\n" \
- " License version 1.3</a> as published by the Free Software Foundation.</p>\n" \
- " <p>\n" \
- " Documentation sources may be obtained from <a href=\"http://www.qt-project.org\">\n" \
- " www.qt-project.org</a>.</p>\n" \
- " <br />\n" \
- " <p>\n" \
- " Digia, Qt and their respective logos are trademarks of Digia Plc \n" \
- " in Finland and/or other countries worldwide. All other trademarks are property\n" \
- " of their respective owners. <a title=\"Privacy Policy\"\n" \
- " href=\"http://en.gitorious.org/privacy_policy/\">Privacy Policy</a></p>\n" \
- "</div>\n" \
+ template/images/bgrContent.png \
+ template/images/Qt-logo.png \
+ template/images/Qt-dark_gradient.png \
+ template/images/Qt-footer-bg.jpg \
+ template/images/Qt-footer_shadow.png \
+ template/images/Qt-gradient.png \
+ template/images/Qt-header-bg.jpg
diff --git a/doc/global/qt-module-defaults-offline.qdocconf b/doc/global/qt-module-defaults-offline.qdocconf
new file mode 100644
index 0000000000..bdca212960
--- /dev/null
+++ b/doc/global/qt-module-defaults-offline.qdocconf
@@ -0,0 +1,13 @@
+#The default configuration for a Qt 5 module, including Add-Ons and Tools.
+#Include this file for a standard Qt 5 module; builds with the offline style.
+
+#include standard set of macros and C++ defines and ignores
+include(macros.qdocconf)
+include(qt-cpp-defines.qdocconf)
+include(compat.qdocconf)
+include(manifest-meta.qdocconf)
+include(fileextensions.qdocconf)
+include(qt-html-templates-offline.qdocconf)
+
+#extra configuration data such as file extensions
+include(config.qdocconf)
diff --git a/doc/global/qt-module-defaults-online.qdocconf b/doc/global/qt-module-defaults-online.qdocconf
index 93ecae16fa..258295b4f9 100644
--- a/doc/global/qt-module-defaults-online.qdocconf
+++ b/doc/global/qt-module-defaults-online.qdocconf
@@ -1,32 +1,14 @@
+#The online onfiguration for a Qt 5 module, including Add-Ons and Tools.
+#Online version contains a different header.
+#Include this file for a standard Qt 5 module; builds with the online style.
+
+#include standard set of macros and C++ defines and ignores
include(macros.qdocconf)
-include(qt-cpp-ignore.qdocconf)
-include(qt-defines.qdocconf)
-include(qt-html-templates-online.qdocconf)
+include(qt-cpp-defines.qdocconf)
include(compat.qdocconf)
+include(manifest-meta.qdocconf)
+include(fileextensions.qdocconf)
+include(qt-html-templates-online.qdocconf)
-dita.metadata.default.author = Qt Project
-dita.metadata.default.permissions = all
-dita.metadata.default.publisher = Qt Project
-dita.metadata.default.copyryear = 2013
-dita.metadata.default.copyrholder = Digia Plc
-dita.metadata.default.audience = programmer
-
-naturallanguage = en_US
-outputencoding = UTF-8
-sourceencoding = UTF-8
-
-examples.fileextensions = "*.cpp *.h *.js *.xq *.svg *.xml *.ui *.qhp *.qhcp *.qml *.css"
-examples.imageextensions = "*.png *.jpg *.gif"
-
-headers.fileextensions = "*.ch *.h *.h++ *.hh *.hpp *.hxx"
-sources.fileextensions = "*.c++ *.cc *.cpp *.cxx *.mm *.qml *.qdoc"
-
-versionsym = QT_VERSION_STR
-
-macro.raisedaster.HTML = "<sup>*</sup>"
-
-#for including files into the qch file
-qhp.extraFiles += template/style/online.css
-
-#include the external websites
-sourcedirs += externalsites
+#extra configuration data DITA information
+include(config.qdocconf)
diff --git a/doc/global/qt-module-defaults.qdocconf b/doc/global/qt-module-defaults.qdocconf
index 0365d5a6cd..8d0665ef41 100644
--- a/doc/global/qt-module-defaults.qdocconf
+++ b/doc/global/qt-module-defaults.qdocconf
@@ -1,30 +1,7 @@
-include(macros.qdocconf)
-include(qt-cpp-ignore.qdocconf)
-include(qt-defines.qdocconf)
-include(qt-html-templates-offline.qdocconf)
-include(compat.qdocconf)
-include(manifest-meta.qdocconf)
+#The default configuration for a Qt 5 module, including Add-Ons and Tools.
+#Include this file for a standard Qt 5 module. This file is provided for
+#compatibility reasons.
-dita.metadata.default.author = Qt Project
-dita.metadata.default.permissions = all
-dita.metadata.default.publisher = Qt Project
-dita.metadata.default.copyryear = 2013
-dita.metadata.default.copyrholder = Digia Plc
-dita.metadata.default.audience = programmer
-
-naturallanguage = en_US
-outputencoding = UTF-8
-sourceencoding = UTF-8
-
-examples.fileextensions = "*.cpp *.h *.js *.xq *.svg *.xml *.ui *.qhp *.qhcp *.qml *.css"
-examples.imageextensions = "*.png *.jpg *.gif"
-
-headers.fileextensions = "*.ch *.h *.h++ *.hh *.hpp *.hxx"
-sources.fileextensions = "*.c++ *.cc *.cpp *.cxx *.mm *.qml *.qdoc"
-
-versionsym = QT_VERSION_STR
-
-macro.raisedaster.HTML = "<sup>*</sup>"
-
-#include the external websites
-sourcedirs += externalsites
+#The default is the offline style. The alternate style is in
+#qt-module-defaults-online.qdocconf
+include(qt-module-defaults-offline.qdocconf)
diff --git a/doc/global/template/images/Qt-dark_gradient.png b/doc/global/template/images/Qt-dark_gradient.png
new file mode 100644
index 0000000000..6ae10f37bf
--- /dev/null
+++ b/doc/global/template/images/Qt-dark_gradient.png
Binary files differ
diff --git a/doc/global/template/images/Qt-footer-bg.jpg b/doc/global/template/images/Qt-footer-bg.jpg
new file mode 100644
index 0000000000..c0ff209b7e
--- /dev/null
+++ b/doc/global/template/images/Qt-footer-bg.jpg
Binary files differ
diff --git a/doc/global/template/images/Qt-footer_shadow.png b/doc/global/template/images/Qt-footer_shadow.png
new file mode 100644
index 0000000000..5a7063dfee
--- /dev/null
+++ b/doc/global/template/images/Qt-footer_shadow.png
Binary files differ
diff --git a/doc/global/template/images/Qt-gradient.png b/doc/global/template/images/Qt-gradient.png
new file mode 100644
index 0000000000..aa38227cbb
--- /dev/null
+++ b/doc/global/template/images/Qt-gradient.png
Binary files differ
diff --git a/doc/global/template/images/Qt-header-bg.jpg b/doc/global/template/images/Qt-header-bg.jpg
new file mode 100644
index 0000000000..c9a6d96db4
--- /dev/null
+++ b/doc/global/template/images/Qt-header-bg.jpg
Binary files differ
diff --git a/doc/global/template/images/Qt-logo.png b/doc/global/template/images/Qt-logo.png
new file mode 100644
index 0000000000..64c1c4aaa3
--- /dev/null
+++ b/doc/global/template/images/Qt-logo.png
Binary files differ
diff --git a/doc/global/template/images/arrow_bc.png b/doc/global/template/images/arrow_bc.png
new file mode 100644
index 0000000000..f2a83a5740
--- /dev/null
+++ b/doc/global/template/images/arrow_bc.png
Binary files differ
diff --git a/doc/global/template/images/logo.png b/doc/global/template/images/logo.png
new file mode 100644
index 0000000000..1e7ed4cf21
--- /dev/null
+++ b/doc/global/template/images/logo.png
Binary files differ
diff --git a/doc/global/template/style/offline.css b/doc/global/template/style/offline.css
index 0e4dd5e9a4..5a036c7f07 100644
--- a/doc/global/template/style/offline.css
+++ b/doc/global/template/style/offline.css
@@ -181,6 +181,74 @@ footer and license
text-align:center
}
+.navigationbar{
+display: block;
+position: relative;
+top:-20px;
+/*border-top:2px solid #ffffff;*/
+border-bottom: 1px solid #cecece;
+background-color:#F2F2F2;
+z-index:1;
+height:20px;
+padding-left:7px;
+margin:0px;
+padding-top:2px;
+margin-left:-5px;
+margin-right:-5px;
+}
+
+.navigationbar ul{
+ margin:0px;
+ padding:0px;
+}
+
+.navigationbar ul li{
+list-style-type:none;
+padding-top:2px;
+padding-left: 4px;
+margin:0;
+height:20px;
+}
+
+.navigationbar li{
+float:left;
+}
+
+.navigationbar .first {
+background:url(../images/home.png);
+background-position:left;
+background-repeat:no-repeat;
+padding-left:20px;
+}
+
+
+.navigationbar li a{
+display:block;
+text-decoration:none;
+background:url(../images/arrow_bc.png);
+background-repeat:no-repeat;
+background-position:right;
+padding-right:17px;
+}
+
+
+/*
+-----------
+footer and license
+-----------
+*/
+.footer{
+text-align:center
+}
+
+#buildversion{
+font-style: italic;
+font-size: small;
+float: right;
+margin-right: 5px;
+}
+/*
+
/* table of content
no display
*/
@@ -441,7 +509,7 @@ padding: 3px 15px 3px 0;
.qml{
display: block;
-margin: 10;
+margin: 10px;
overflow: auto;
padding: 20px 20px 20px 20px;
}
@@ -493,7 +561,7 @@ vertical-align:top;
-moz-border-radius: 7px 7px 7px 7px;
-webkit-border-radius: 7px 7px 7px 7px;
border-radius: 7px 7px 7px 7px;
- background:#FFF url(../images/bgrContent.png);
+ background:#FFF url('../images/bgrContent.png');
background-position:top;
background-repeat:repeat-x;
border: 1px solid #E6E6E6;
diff --git a/doc/global/template/style/online.css b/doc/global/template/style/online.css
index 7809783fa7..09c863feff 100644
--- a/doc/global/template/style/online.css
+++ b/doc/global/template/style/online.css
@@ -1,14 +1,4 @@
-body{
-font: normal 400 14px/1.2 Arial;
-font-family: Arial, Helvetica;
-color:#313131;
-text-align:justify;
-margin-left:5px;
-margin-right:5px;
-background: none repeat scroll 0% 0% rgb(230,231,232);
-}
-
-p {
+{
line-height: 20px;
}
img{
@@ -21,7 +11,9 @@ max-width: 800px;
height: auto
}
-.content{}
+.content{
+ margin: 15px;
+}
.descr{
margin-top:35px;
@@ -85,7 +77,7 @@ font-weight:bold;
}
.note,.tip,.fastpath{
-background: #F2F2F2 url(../images/ico_note.png);
+background: #F2F2F2 url('../images/ico_note.png');
background-repeat: no-repeat;
background-position: top left;
padding:5px;
@@ -97,7 +89,7 @@ margin:5px;
}
.attention,.caution,.danger,.important,.remember,.restriction{
-background: #F2F2F2 url(../images/ico_note_attention.png);
+background: #F2F2F2 url('../images/ico_note_attention.png');
background-repeat:no-repeat;
background-position:top left;
padding:5px;
@@ -108,51 +100,6 @@ color:#666666;
margin:5px;
}
-/*
--------------------------------
-Top navigation
--------------------------------
-*/
-
-.nav{
-text-align:right;
-margin-right:9px;
-}
-.nav img{
- box-shadow: none;
-}
-.nav-main{
-margin-top:22px;
-margin-left: 20px;
-text-align:left
-}
-.nav-main-content{
-margin-right: 20px;
-display:inline-block;
-}
-.nav-subtitle{
-margin-left: 220px;
-}
-
-header{
-background: none repeat scroll 0% 0% rgb(255,255,255);
-border-radius: 10px 10px 10px 10px;
-padding: 10px;
-box-shadow: 0px 0px 10px rgba(0,0,0,0.1);
-}
-
-header h1{
-display:block;
-line-height: 70px;
-font-size: 30px;
-margin-left: 223px;
-}
-header img{
-box-shadow: none;
-border: 0;
-position: absolute;
-left: 30px;
-}
.qtref{
display: block;
top: -76px;
@@ -173,7 +120,7 @@ padding-top:4px;
.naviNextPrevious > a.prevPage {
-background-image:url(../images/btn_prev.png);
+background-image:url('../images/btn_prev.png');
background-repeat:no-repeat;
background-position:left;
padding-left:20px;
@@ -182,7 +129,7 @@ padding-left:20px;
}
.naviNextPrevious > a.nextPage {
-background-image:url(../images/btn_next.png);
+background-image:url('../images/btn_next.png');
background-repeat:no-repeat;
background-position:right;
padding-right:20px;
@@ -190,93 +137,47 @@ height:20px;
margin-left:30px;
}
-.breadcrumb{
-display: block;
-position: relative;
-z-index:1;
-height:20px;
-padding:0px;
-margin:0px;
-padding-left:10px;
-padding-top:12px;
-margin-left:-5px;
-margin-right:-5px;
-}
-
-.breadcrumb ul{
- margin:0px;
- padding:0px;
+.navigationbar {
+ background-repeat: no-repeat;
+ height: 33px;
+ margin: 0px !important;
+ padding: 0px !important;
+ border-bottom: 1px solid rgb(209, 209, 209);
+ background-image: -moz-linear-gradient(center top , rgb(246, 245, 245), rgb(239, 239, 239));
+background-image: -webkit-gradient( linear, left bottom, left top, color-stop(0.0, #efefef), color-stop(0.5, #f6f5f5) );
+ border-radius: 10px 10px 0px 0px;
}
-.breadcrumb ul li{
-list-style-type:none;
-padding:0;
-margin:0;
+.navigationbar ul{
+margin:0px;
+padding:8px 0px 15px 15px;
height:20px;
}
-.breadcrumb li{
+.navigationbar li{
+list-style-type:none;
float:left;
+font-size: 15px;
}
-.breadcrumb .first {
-background:url(../images/home.png);
-background-position:left;
-background-repeat:no-repeat;
-padding-left:20px;
-}
-
-
-.breadcrumb li a{
+.navigationbar li a{
display:block;
text-decoration:none;
-background:url(../images/arrow.png);
+background:url('../images/arrow_bc.png');
background-repeat:no-repeat;
background-position:right;
padding-right:25px;
-padding-left:10px;
+font-size: inherit;
}
-.breadcrumb li a:hover{
-color:#909090;
-display:block;
-text-decoration:none;
-background:url(../images/arrow.png);
-background-repeat:no-repeat;
-background-position:right;
-padding-right:20px;
-padding-left:10px;
-}
-/*
------------
-footer and license
------------
-*/
-.footer{
-text-align:center
-}
-/*
------------
-main content
------------
-*/
-.line{
-text-align: left;
-background: none repeat scroll 0% 0% rgb(255,255,255);
-border-radius: 10px 10px 10px 10px;
-padding-left: 14px;
-padding-right: 14px;
-box-shadow: 0px 0px 10px rgba(0,0,0,0.1);
-margin-top: 10px;
-padding-bottom: 35px;
+#buildversion{
+font-style: italic;
+font-size: small;
+float: right;
+margin-right: 5px;
}
-
-/* table of content
-no display
-*/
-
/*
-----------
headers
@@ -360,7 +261,6 @@ color:#808080;
@media print {
.title {
color:#0066CB;
-font-family:Arial, Helvetica;
font-size: 32px;
font-weight: normal;
left: 0;
@@ -509,14 +409,6 @@ overflow: auto;
padding: 20px 20px 20px 20px;
}
-.footer{
-margin-top: 50px;
-padding-left:5px;
-margin-bottom: 10px;
-font-size:10px;
-border-top: 1px solid #999;
-padding-top:11px;
-}
.footerNavi{
width:auto;
@@ -574,7 +466,7 @@ clear: right;
padding-bottom: 10px;
padding-top: 50px;
width: 100%;
-background-image:url(../images/bgrContent.png);
+background-image:url('../images/bgrContent.png');
background-position:top;
background-repeat:no-repeat;
}
@@ -591,7 +483,7 @@ vertical-align:top;
-moz-border-radius: 7px 7px 7px 7px;
-webkit-border-radius: 7px 7px 7px 7px;
border-radius: 7px 7px 7px 7px;
- background:#FFF url(../images/bgrContent.png);
+ background:#FFF url('../images/bgrContent.png');
background-position:top;
background-repeat:repeat-x;
border: 1px solid #E6E6E6;
@@ -625,7 +517,7 @@ padding-top:10px;
.toc ul li{
margin-left:15px;
-list-style-image:url(../images/blu_dot.png);
+list-style-image:url('../images/blu_dot.png');
list-style:outside;
marker-offset: 0px;
margin-bottom:8px;
@@ -765,3 +657,214 @@ Landing page
.sectionlist {
width: 100% !important;
}
+
+
+/*
+Additions from Qt Project
+*/
+
+body{
+background:#E8E8E8;
+margin: 0px;
+font-family:"Open Sans",sans-serif !important
+}
+
+.qt13a-twoCol{width:23.46939%;float:left;margin-right:2.04082%;display:inline}
+
+.qt13a-fourCol{width:48.97959%;float:left;margin-right:2.04082%;display:inline}
+
+.qt13a-sixCol{
+ width:70.4898%;
+ float:left;
+ margin-right:2.04082%;
+ display:inline
+}
+.qt13a-eightCol{
+ width:100%;
+ float:left;
+ margin-right:2.04082%;
+ display:inline
+}
+.qt13a-fiveCol{width:17.35537%;float:left;margin-right:3.30579%;display:inline}
+.qt13a-fiveCol:nth-child(2n){float:left;margin-right:3.30579%}
+.qt13a-omega{float:right;margin-right:0;*margin-left:-20px;display:inline}
+.qt13a-last{float:right;margin-right:0;*margin-left:-20px;display:inline}
+.qt13a-container{*zoom:1;padding-left:20px;padding-right:20px;margin-left:auto;margin-right:auto;max-width:1045px}
+.qt13a-container:after{content:"";display:table;clear:both}
+.qt13a-container.qt13a-dynamic{max-width:1295px}
+.qt13a-no-bg-img{background-image:none !important}
+.qt13a-wrapper{overflow:hidden}
+.content-view{position:relative;overflow:hidden;}
+
+#qt13a-header{background:url('../images/Qt-header-bg.jpg') repeat;min-height:126px;padding:0;margin:0;min-width:1045px;margin-bottom:18px}
+#qt13a-header .qt13a-gradient{background:url('../images/Qt-gradient.png') repeat-x;background-position:bottom;margin:0;min-height:126px;padding:0}
+#qt13a-header #qt13a-title_nav{padding-top:34px;width:87.37374%;float:left;margin-right:1.0101%;display:inline;float:right;margin-right:0;*margin-left:-20px;display:inline}
+#qt13a-header #qt13a-title{padding:0px 0 0 0px;padding-bottom:0px}
+#qt13a-header p.qt13a-title{
+ font-size:24px;
+ margin:0 0 0 0px;
+ letter-spacing:-1px;
+ color:#35322f;
+ font-weight: 600
+}
+#qt13a-header p.qt13a-title a{font-weight:600;color:#35322f}
+#qt13a-header p.qt13a-title a:hover{color:#35322f;text-decoration:none}
+#qt13a-header #qt13a-logo{float:left;width:11.61616%;float:left;margin-right:1.0101%;display:inline;margin:20px 0px 10px 0;min-width:50px}
+#qt13a-header #qt13a-logo img{
+ float:left;
+ border: 0;
+ -moz-box-shadow: none;
+ -webkit-box-shadow: none;
+ box-shadow: none;
+}
+#qt13a-header #qt13a-logo .qt13a-site-logo{
+ background: url('../images/Qt-logo.png') no-repeat;
+ text-indent:-100em;
+ overflow:hidden;
+ display:block;
+ height:90px;
+ -moz-box-shadow: none;
+ -webkit-box-shadow: none;
+ box-shadow: none;
+}
+
+#qt13a-header .qt13a-nav{
+ background:none
+}
+
+#qt13a-header .qt13a-nav ul{
+ margin:0 0 0 0px;
+ padding:11px 0 0;
+ background:none
+}
+#qt13a-header .qt13a-nav .qt13a-nav-small a{font-size:13px}
+#qt13a-header .qt13a-nav ul li{display:inline-block;width:auto;padding:0 2.88% 0 0;margin:0;border:0;*display:inline;zoom:1}
+#qt13a-header .qt13a-nav ul li.devnet-active a{color:#fff}
+
+#qt13a-header .qt13a-nav ul li a{
+ color:#35322f;
+ margin:0;
+ padding:0;
+ line-height:18px;
+ font-size:18px
+}
+#qt13a-header .qt13a-nav ul li a:hover,#qt13a-header .qt13a-nav ul li a:active,#qt13a-header .qt13a-nav ul li a.active{
+ color:#fff;
+ text-decoration:none
+}
+#qt13a-header .qt13a-nav .qt13a-nav-divider-left{
+ border-left:1px solid #35322f;
+ padding-left:20px
+}
+#qt13a-header .qt13a-nav-divider-left{
+ border-left:1px solid #35322f;
+ padding-left:10px;
+ margin-left:5px;
+ font-size: 13px
+}
+#qt13a-register_search{
+ display:block;
+ font-variant:400;
+ float:right
+}
+#qt13a-register{
+ padding:34px 0px 0;
+ float:right;
+ text-align:right;
+ color:#1e1b18;
+}
+#qt13a-register a{
+ color:#1e1b18;
+ font-weight:400;
+ font-size:13px;
+ padding-left:13px
+}
+#qt13a-register a:visited{color:#1e1b18}
+#qt13a-register a:hover{color:#fff;text-decoration:none}
+#qt13a-register .qt13a-link-divider{padding:0 5px}
+#search{margin-top:23px}
+#qt13a-footer{background: url('../images/Qt-header-bg.jpg') repeat;margin:0}
+#qt13a-footer .qt13a-last{float:right;margin-right:0;*margin-left:-20px;display:inline}
+#qt13a-footer .qt13a-container{padding:36px 0}
+#qt13a-footer .qt13a-gradient{background: url('../images/Qt-dark_gradient.png') repeat-x;background-position:bottom;margin:0;min-height:126px;padding:0}
+#qt13a-footer .qt13a-shadow{background:transparent url('../images/Qt-footer_shadow.png') repeat-x top center}
+#qt13a-footer .qt13a-title a,#qt13a-footer .qt13a-title{padding:18px 0 18px;font-weight:400;letter-spacing:-0.5pt;color:#35322f;font-size:18px;margin:0}
+#qt13a-footer ul{width:17.35537%;float:left;margin-right:3.30579%;display:inline;padding-left:0;list-style-type:none}
+#qt13a-footer ul li a{font-family:"Open Sans",sans-serif;font-size:13px;color:#35322f;padding:0;font-weight:400}
+#qt13a-footer ul li a:hover,#qt13a-footer ul li a:active{color:#35322f;text-decoration:underline}
+#qt13a-footer ul li a.qt13a-some-icon{width:32px;height:32px;background-repeat:none;text-indent:-300em;overflow:hidden;display:-moz-inline-stack;display:inline-block;vertical-align:middle;*vertical-align:auto;zoom:1;*display:inline}
+.qt13a-copyright{
+ border-top:1px solid #000;
+ background: url('../images/Qt-footer-bg.jpg') repeat;
+ margin:0;
+ padding:36px 0;
+ font-weight:400;
+ font-size:0.84615em;
+ line-height:1.63636em}
+.qt13a-copyright p{padding:0;color:#aeadac;font-size:11px}
+.qt13a-copyright a{color:#328930}
+.qt13a-copyright a:visited{color:#328930}
+
+
+.searchbox
+{
+ display: block;
+ overflow: hidden;
+ padding: 0px 35px 0 5px;
+}
+
+
+.content-view
+{
+ position:relative;
+ overflow:hidden;
+}
+
+
+p, li,
+p.forum-overview-title,
+p.forum-description,
+p.desc,
+p.forum-lastpost,
+div.navigationbars li,
+div.block-profile div
+{
+ font-size: 13px;
+}
+
+p.forum-description.desc
+{
+ font-size: 13px !important;
+}
+
+.steps li
+{
+ font-size: 16px;
+}
+
+div.license p,
+div.notes p
+{
+ font-size: 12px !important;
+}
+
+a {
+color: #44a51c;
+text-decoration: none;
+}
+.wrap{
+padding-left: 30px
+}
+
+.main {
+ padding: 0px 30px 30px 30px;
+}
+.main-rounded {
+ display: inline-block;
+ background: none repeat scroll 0% 0% rgb(255,255,255);
+ width: 100%;
+ border: 1px solid #DADADA;
+ border-radius: 10px 10px 10px 10px;
+ box-shadow: 0 0 3px #C4C4C4;
+ padding-bottom: 30px;
+}
diff --git a/examples/widgets/dialogs/standarddialogs/dialog.cpp b/examples/widgets/dialogs/standarddialogs/dialog.cpp
index c626b63b7d..fdd3633950 100644
--- a/examples/widgets/dialogs/standarddialogs/dialog.cpp
+++ b/examples/widgets/dialogs/standarddialogs/dialog.cpp
@@ -121,6 +121,10 @@ Dialog::Dialog(QWidget *parent)
textLabel->setFrameStyle(frameStyle);
QPushButton *textButton = new QPushButton(tr("QInputDialog::get&Text()"));
+ multiLineTextLabel = new QLabel;
+ multiLineTextLabel->setFrameStyle(frameStyle);
+ QPushButton *multiLineTextButton = new QPushButton(tr("QInputDialog::get&MultiLineText()"));
+
colorLabel = new QLabel;
colorLabel->setFrameStyle(frameStyle);
QPushButton *colorButton = new QPushButton(tr("QColorDialog::get&Color()"));
@@ -177,6 +181,7 @@ Dialog::Dialog(QWidget *parent)
connect(doubleButton, SIGNAL(clicked()), this, SLOT(setDouble()));
connect(itemButton, SIGNAL(clicked()), this, SLOT(setItem()));
connect(textButton, SIGNAL(clicked()), this, SLOT(setText()));
+ connect(multiLineTextButton, SIGNAL(clicked()), this, SLOT(setMultiLineText()));
connect(colorButton, SIGNAL(clicked()), this, SLOT(setColor()));
connect(fontButton, SIGNAL(clicked()), this, SLOT(setFont()));
connect(directoryButton, SIGNAL(clicked()),
@@ -206,7 +211,9 @@ Dialog::Dialog(QWidget *parent)
layout->addWidget(itemLabel, 2, 1);
layout->addWidget(textButton, 3, 0);
layout->addWidget(textLabel, 3, 1);
- layout->addItem(new QSpacerItem(0, 0, QSizePolicy::Ignored, QSizePolicy::MinimumExpanding), 4, 0);
+ layout->addWidget(multiLineTextButton, 4, 0);
+ layout->addWidget(multiLineTextLabel, 4, 1);
+ layout->addItem(new QSpacerItem(0, 0, QSizePolicy::Ignored, QSizePolicy::MinimumExpanding), 5, 0);
toolbox->addItem(page, tr("Input Dialogs"));
const QString doNotUseNativeDialog = tr("Do not use native dialog");
@@ -327,6 +334,17 @@ void Dialog::setText()
//! [3]
}
+void Dialog::setMultiLineText()
+{
+//! [4]
+ bool ok;
+ QString text = QInputDialog::getMultiLineText(this, tr("QInputDialog::getMultiLineText()"),
+ tr("Address:"), "John Doe\nFreedom Street", &ok);
+ if (ok && !text.isEmpty())
+ multiLineTextLabel->setText(text);
+//! [4]
+}
+
void Dialog::setColor()
{
const QColorDialog::ColorDialogOptions options = QFlag(colorDialogOptionsWidget->value());
diff --git a/examples/widgets/dialogs/standarddialogs/dialog.h b/examples/widgets/dialogs/standarddialogs/dialog.h
index 27b1de98cb..d6272c440e 100644
--- a/examples/widgets/dialogs/standarddialogs/dialog.h
+++ b/examples/widgets/dialogs/standarddialogs/dialog.h
@@ -63,6 +63,7 @@ private slots:
void setDouble();
void setItem();
void setText();
+ void setMultiLineText();
void setColor();
void setFont();
void setExistingDirectory();
@@ -80,6 +81,7 @@ private:
QLabel *doubleLabel;
QLabel *itemLabel;
QLabel *textLabel;
+ QLabel *multiLineTextLabel;
QLabel *colorLabel;
QLabel *fontLabel;
QLabel *directoryLabel;
diff --git a/examples/widgets/itemviews/spreadsheet/main.cpp b/examples/widgets/itemviews/spreadsheet/main.cpp
index 1cc9205d7e..f518986bc5 100644
--- a/examples/widgets/itemviews/spreadsheet/main.cpp
+++ b/examples/widgets/itemviews/spreadsheet/main.cpp
@@ -42,14 +42,15 @@
#include "spreadsheet.h"
#include <QApplication>
+#include <QLayout>
int main(int argc, char** argv) {
Q_INIT_RESOURCE(spreadsheet);
QApplication app(argc, argv);
SpreadSheet sheet(10, 6);
sheet.setWindowIcon(QPixmap(":/images/interview.png"));
- sheet.resize(640, 420);
sheet.show();
+ sheet.layout()->setSizeConstraint(QLayout::SetFixedSize);
return app.exec();
}
diff --git a/examples/widgets/itemviews/spreadsheet/spreadsheet.cpp b/examples/widgets/itemviews/spreadsheet/spreadsheet.cpp
index 59d29f0e61..6fab0c2aae 100644
--- a/examples/widgets/itemviews/spreadsheet/spreadsheet.cpp
+++ b/examples/widgets/itemviews/spreadsheet/spreadsheet.cpp
@@ -64,6 +64,7 @@ SpreadSheet::SpreadSheet(int rows, int cols, QWidget *parent)
toolBar->addWidget(formulaInput);
table = new QTableWidget(rows, cols, this);
+ table->setSizeAdjustPolicy(QTableWidget::AdjustToContents);
for (int c = 0; c < cols; ++c) {
QString character(QChar('A' + c));
table->setHorizontalHeaderItem(c, new QTableWidgetItem(character));
diff --git a/examples/widgets/widgets/spinboxes/window.cpp b/examples/widgets/widgets/spinboxes/window.cpp
index 8c35f93c56..acce642ec6 100644
--- a/examples/widgets/widgets/spinboxes/window.cpp
+++ b/examples/widgets/widgets/spinboxes/window.cpp
@@ -94,6 +94,14 @@ void Window::createSpinBoxes()
priceSpinBox->setValue(99);
//! [4] //! [5]
+ QLabel *hexLabel = new QLabel(tr("Enter a value between "
+ "%1 and %2:").arg('-' + QString::number(31, 16)).arg(QString::number(31, 16)));
+ QSpinBox *hexSpinBox = new QSpinBox;
+ hexSpinBox->setRange(-31, 31);
+ hexSpinBox->setSingleStep(1);
+ hexSpinBox->setValue(0);
+ hexSpinBox->setDisplayIntegerBase(16);
+
QVBoxLayout *spinBoxLayout = new QVBoxLayout;
spinBoxLayout->addWidget(integerLabel);
spinBoxLayout->addWidget(integerSpinBox);
@@ -101,6 +109,8 @@ void Window::createSpinBoxes()
spinBoxLayout->addWidget(zoomSpinBox);
spinBoxLayout->addWidget(priceLabel);
spinBoxLayout->addWidget(priceSpinBox);
+ spinBoxLayout->addWidget(hexLabel);
+ spinBoxLayout->addWidget(hexSpinBox);
spinBoxesGroup->setLayout(spinBoxLayout);
}
//! [5]
diff --git a/mkspecs/blackberry-armv7le-qcc/qmake.conf b/mkspecs/blackberry-armv7le-qcc/qmake.conf
index 2e24e4e0d3..cfcd2aecf0 100644
--- a/mkspecs/blackberry-armv7le-qcc/qmake.conf
+++ b/mkspecs/blackberry-armv7le-qcc/qmake.conf
@@ -16,6 +16,7 @@ contains(QT_CONFIG, stack-protector-strong) {
}
QMAKE_CFLAGS += -mcpu=cortex-a9 -mtune=cortex-a9 -mthumb -D_FORTIFY_SOURCE=2
+QMAKE_CXXFLAGS += -mcpu=cortex-a9 -mtune=cortex-a9 -mthumb -D_FORTIFY_SOURCE=2
QMAKE_LFLAGS_SHLIB += -Wl,-z,relro -Wl,-z,now
diff --git a/mkspecs/common/clang.conf b/mkspecs/common/clang.conf
index 4f141351c1..ace2496f10 100644
--- a/mkspecs/common/clang.conf
+++ b/mkspecs/common/clang.conf
@@ -20,13 +20,3 @@ QMAKE_CXXFLAGS_USE_PRECOMPILE = $$QMAKE_CFLAGS_USE_PRECOMPILE
QMAKE_CXXFLAGS_CXX11 = -std=c++11
QMAKE_LFLAGS_CXX11 =
-
-QMAKE_CFLAGS_SSE2 += -msse2
-QMAKE_CFLAGS_SSE3 += -msse3
-QMAKE_CFLAGS_SSSE3 += -mssse3
-QMAKE_CFLAGS_SSE4_1 += -msse4.1
-QMAKE_CFLAGS_SSE4_2 += -msse4.2
-QMAKE_CFLAGS_AVX += -mavx
-QMAKE_CFLAGS_AVX2 += -mavx2
-QMAKE_CFLAGS_IWMMXT += -mcpu=iwmmxt
-QMAKE_CFLAGS_NEON += -mfpu=neon
diff --git a/mkspecs/common/ios/qmake.conf b/mkspecs/common/ios/qmake.conf
index 39465aa765..3c477438a3 100644
--- a/mkspecs/common/ios/qmake.conf
+++ b/mkspecs/common/ios/qmake.conf
@@ -15,9 +15,6 @@ QMAKE_RANLIB = ranlib -s
QMAKE_LINK = $$QMAKE_CXX
QMAKE_LINK_SHLIB = $$QMAKE_CXX
-# Basic iOS frameworks needed for any GUI app
-QMAKE_LFLAGS += -framework Foundation -framework UIKit -framework QuartzCore -lz
-
# No OpenGL ES1
QMAKE_INCDIR_OPENGL_ES1 =
QMAKE_LIBDIR_OPENGL_ES1 =
diff --git a/mkspecs/common/mac.conf b/mkspecs/common/mac.conf
index 1b480aa267..4421665370 100644
--- a/mkspecs/common/mac.conf
+++ b/mkspecs/common/mac.conf
@@ -4,7 +4,7 @@
!load(device_config): error(Could not successfully load device configuration)
-QMAKE_PLATFORM += mac
+QMAKE_PLATFORM += mac darwin
QMAKE_RESOURCE = /Developer/Tools/Rez
QMAKE_EXTENSION_SHLIB = dylib
diff --git a/mkspecs/common/macx.conf b/mkspecs/common/macx.conf
index 48efae5d1e..ad54612f22 100644
--- a/mkspecs/common/macx.conf
+++ b/mkspecs/common/macx.conf
@@ -2,7 +2,7 @@
# qmake configuration for common OS X
#
-QMAKE_PLATFORM += macx
+QMAKE_PLATFORM += osx macx
QMAKE_MAC_SDK = macosx
include(mac.conf)
diff --git a/mkspecs/darwin-g++/qmake.conf b/mkspecs/darwin-g++/qmake.conf
index 24a6224b7c..ab333b1684 100644
--- a/mkspecs/darwin-g++/qmake.conf
+++ b/mkspecs/darwin-g++/qmake.conf
@@ -5,7 +5,7 @@
#
MAKEFILE_GENERATOR = UNIX
-QMAKE_PLATFORM = mac macx
+QMAKE_PLATFORM = osx macx mac darwin
CONFIG += native_precompiled_headers
DEFINES += __USE_WS_X11__
diff --git a/mkspecs/features/cmake_functions.prf b/mkspecs/features/cmake_functions.prf
index 2dc72a7a2f..3a9d0173fe 100644
--- a/mkspecs/features/cmake_functions.prf
+++ b/mkspecs/features/cmake_functions.prf
@@ -63,3 +63,8 @@ defineReplace(cmakeProcessLibs) {
}
return ($$join(out, ";"))
}
+
+defineReplace(cmakeRelativePath) {
+ path = $$relative_path($$1, $$2)
+ return($$replace(path, ([^/])$, \\1/))
+}
diff --git a/mkspecs/features/create_cmake.prf b/mkspecs/features/create_cmake.prf
index 7a200056ae..2dcb8da063 100644
--- a/mkspecs/features/create_cmake.prf
+++ b/mkspecs/features/create_cmake.prf
@@ -11,11 +11,6 @@
load(cmake_functions)
-defineReplace(cmakeRelativePath) {
- path = $$relative_path($$1, $$2)
- return($$replace(path, ([^/])$, \\1/))
-}
-
CMAKE_MODULE_NAME = $$cmakeModuleName($${MODULE})
CMAKE_MODULE_DEPS = $$cmakeModuleList($$sort_depends(QT.$${MODULE}.depends, QT.))
@@ -71,12 +66,6 @@ contains(CMAKE_BIN_DIR, "^\\.\\./.*") {
CMAKE_DLL_DIR_IS_ABSOLUTE = $$CMAKE_LIB_DIR_IS_ABSOLUTE
}
-CMAKE_HOST_DATA_DIR = $$cmakeRelativePath($$[QT_HOST_DATA], $$[QT_INSTALL_PREFIX])
-contains(CMAKE_HOST_DATA_DIR, "^\\.\\./.*") {
- CMAKE_HOST_DATA_DIR = $$[QT_HOST_DATA]/
- CMAKE_HOST_DATA_DIR_IS_ABSOLUTE = True
-}
-
static|staticlib:CMAKE_STATIC_TYPE = true
unix:contains(QT_CONFIG, reduce_relocations):CMAKE_ADD_FPIE_FLAGS = "true"
diff --git a/mkspecs/features/ios/default_post.prf b/mkspecs/features/ios/default_post.prf
index e9d2149351..fea5aea44d 100644
--- a/mkspecs/features/ios/default_post.prf
+++ b/mkspecs/features/ios/default_post.prf
@@ -11,27 +11,25 @@ isEmpty(MAKEFILE_GENERATOR) {
}
gui_app {
- # We have to do the link and dependency resolution for the platform plugin
- # manually, since QTPLUGIN and the prl lookup logic does not support
- # the -force_load link style. The -force_load option ensures that all
- # symbols from the static library are included, not just the ones the
- # linker have seen a use for so far. We need this because we load the platform
- # plugin from the platform plugin itself, using Q_IMPORT_PLUGIN.
- lib_path_and_base = $$[QT_INSTALL_PLUGINS/get]/platforms/libqios$$qtPlatformTargetSuffix()
- LIBS += "-force_load $${lib_path_and_base}.$${QMAKE_EXTENSION_STATICLIB}"
- LIBS += $$fromfile($${lib_path_and_base}.prl, QMAKE_PRL_LIBS)
+ LIBS *= -L$$[QT_INSTALL_PLUGINS/get]/platforms
- # Which means we don't want the auto-generated import for the platform plugin
+ lib_name = qios
+ lib_path_and_base = $$[QT_INSTALL_PLUGINS/get]/platforms/lib$${lib_name}$$qtPlatformTargetSuffix()
+ LIBS += -l$${lib_name}$$qtPlatformTargetSuffix() $$fromfile($${lib_path_and_base}.prl, QMAKE_PRL_LIBS)
+
+ # By marking qt_registerPlatformPlugin as undefined, we ensure that
+ # the plugin.o translation unit is considered for inclusion in
+ # the final binary, which in turn ensures that the plugin's
+ # static initializer is included and run.
+ QMAKE_LFLAGS += -u _qt_registerPlatformPlugin
+
+ # We do link and dependency resolution for the platform plugin
+ # manually, since we know we always need the plugin, so we don't
+ # need to generate an import for it.
CONFIG -= import_qpa_plugin
- !no_main_wrapper {
- # We link the iosmain library manually as well, since it's not really a plugin
- lib_name = qiosmain
- lib_path_and_base = $$[QT_INSTALL_PLUGINS/get]/platforms/lib$${lib_name}$$qtPlatformTargetSuffix()
- LIBS += -L$$[QT_INSTALL_PLUGINS/get]/platforms -l$${lib_name}$$qtPlatformTargetSuffix()
- LIBS += $$fromfile($${lib_path_and_base}.prl, QMAKE_PRL_LIBS)
- DEFINES += main=qt_main
- }
+ # FIXME: Solve using 'ld -r -alias -unexported_symbol' instead
+ !no_main_wrapper: DEFINES += main=qt_user_main
}
contains(MAKEFILE_GENERATOR, XCODE) {
@@ -46,24 +44,27 @@ isEmpty(QT_ARCH) {
# but we fail to pick up the architecture since we're not passing -arch
# yet. Xcode does not seem to have a way to run the shared toolchain
# in a way that will automatically do this (for example xcrun -sdk).
- contains(QMAKE_MAC_SDK, iphoneos.*): QT_ARCH = armv7
+ contains(QMAKE_MAC_SDK, iphoneos.*): QT_ARCH = arm
else: QT_ARCH = i386 # Simulator
-} else {
- # Fix up the QT_ARCH to be more specific
- equals(QT_ARCH, arm) {
- # Samsung S5PC100, Apple A4, A5, A5X
- QT_ARCH = armv7
-
- # FIXME: How do we support armv7s when Qt can't do universal builds?
- }
}
-!equals(MAKEFILE_GENERATOR, XCODE) {
- arch_flag = -arch $$QT_ARCH
- QMAKE_CFLAGS += $$arch_flag
- QMAKE_CXXFLAGS += $$arch_flag
- QMAKE_OBJECTIVE_CFLAGS += $$arch_flag
- QMAKE_LFLAGS += $$arch_flag
+# Be more specific about which architecture we're targeting
+equals(QT_ARCH, arm): \
+ actual_archs = armv7
+else: \
+ actual_archs = $$QT_ARCH
+
+equals(MAKEFILE_GENERATOR, XCODE) {
+ QMAKE_XCODE_ARCHS = $$actual_archs
+} else {
+ for(arch, actual_archs): \
+ arch_flags += -arch $$arch
+
+ QMAKE_CFLAGS += $$arch_flags
+ QMAKE_CXXFLAGS += $$arch_flags
+ QMAKE_OBJECTIVE_CFLAGS += $$arch_flags
+ QMAKE_LFLAGS += $$arch_flags
}
+unset(actual_archs)
load(default_post)
diff --git a/mkspecs/features/qt_docs.prf b/mkspecs/features/qt_docs.prf
index 85e2db25bc..be3cd5273c 100644
--- a/mkspecs/features/qt_docs.prf
+++ b/mkspecs/features/qt_docs.prf
@@ -34,7 +34,7 @@ qtmver.value = $$replace(qtver.value, ^(\\d+\\.\\d+).*$, \\1)
qtvertag.name = QT_VERSION_TAG
qtvertag.value = $$replace(qtver.value, \.,)
qtdocs.name = QT_INSTALL_DOCS
-qtdocs.value = $$[QT_INSTALL_DOCS/get]
+qtdocs.value = $$[QT_INSTALL_DOCS/src]
qtAddToolEnv(QDOC, qtver qtmver qtvertag qtdocs)
doc_command = $$QDOC $$QMAKE_DOCS
prepare_docs {
diff --git a/mkspecs/features/simd.prf b/mkspecs/features/simd.prf
index 14da926dc3..e0cd5a3a58 100644
--- a/mkspecs/features/simd.prf
+++ b/mkspecs/features/simd.prf
@@ -12,6 +12,9 @@
# Get the SIMD flags
load(qt_build_config)
+# Set QT_CPU_FEATURES for convenience
+QT_CPU_FEATURES = $$eval(QT_CPU_FEATURES.$$QT_ARCH)
+
#
# Set up compilers for SIMD (SSE/AVX, NEON etc)
#
diff --git a/mkspecs/features/spec_post.prf b/mkspecs/features/spec_post.prf
index c9e9f8b2f6..ad03c9c428 100644
--- a/mkspecs/features/spec_post.prf
+++ b/mkspecs/features/spec_post.prf
@@ -9,7 +9,7 @@ isEmpty(QMAKE_PLATFORM) {
isEmpty(TARGET_PLATFORM) {
equals(MAKEFILE_GENERATOR, UNIX) {
equals(QMAKE_HOST.os, Darwin): \
- TARGET_PLATFORM = macx
+ TARGET_PLATFORM = macx # backwards compatibility; cannot change
else: \
TARGET_PLATFORM = unix
} else:if(equals(MAKEFILE_GENERATOR, MSVC.NET) \
@@ -28,12 +28,18 @@ isEmpty(QMAKE_PLATFORM) {
equals(TARGET_PLATFORM, unix): \
QMAKE_PLATFORM = unix
else:equals(TARGET_PLATFORM, macx): \
- QMAKE_PLATFORM = mac macx unix
+ QMAKE_PLATFORM = osx macx mac darwin unix
else:equals(TARGET_PLATFORM, win32): \
QMAKE_PLATFORM = win32
else: \
error("Qmake spec sets an invalid TARGET_PLATFORM.")
}
+
+contains(QMAKE_PLATFORM, macx):!contains(QMAKE_PLATFORM, osx) {
+ warning("qmake spec specifies platform macx, but not osx.")
+ QMAKE_PLATFORM = osx $$QMAKE_PLATFORM
+}
+
CONFIG += $$QMAKE_PLATFORM
isEmpty(QMAKE_COMPILER) {
diff --git a/mkspecs/macx-clang-libc++-32/qmake.conf b/mkspecs/macx-clang-libc++-32/qmake.conf
deleted file mode 100644
index 3f7342da0b..0000000000
--- a/mkspecs/macx-clang-libc++-32/qmake.conf
+++ /dev/null
@@ -1,23 +0,0 @@
-#
-# qmake configuration for 32-bit Clang on OS X
-#
-
-warning("QMakespec macx-clang-libc++-32 is deprecated. Use macx-clang-32 instead.")
-
-MAKEFILE_GENERATOR = UNIX
-CONFIG += app_bundle incremental global_init_link_order lib_version_first plugin_no_soname
-QMAKE_INCREMENTAL_STYLE = sublib
-
-include(../common/macx.conf)
-include(../common/gcc-base-mac.conf)
-include(../common/clang.conf)
-include(../common/clang-mac.conf)
-
-QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.7
-
-QMAKE_CFLAGS += -arch i386
-QMAKE_OBJECTIVE_CFLAGS += -arch i386 -stdlib=libc++
-QMAKE_CXXFLAGS += -arch i386 -stdlib=libc++
-QMAKE_LFLAGS += -arch i386 -stdlib=libc++
-
-load(qt_config)
diff --git a/mkspecs/macx-clang-libc++/qmake.conf b/mkspecs/macx-clang-libc++/qmake.conf
deleted file mode 100644
index 7f4151e81b..0000000000
--- a/mkspecs/macx-clang-libc++/qmake.conf
+++ /dev/null
@@ -1,22 +0,0 @@
-#
-# qmake configuration for Clang on OS X
-#
-
-warning("QMakespec macx-clang-libc++ is deprecated. Use macx-clang instead.")
-
-MAKEFILE_GENERATOR = UNIX
-CONFIG += app_bundle incremental global_init_link_order lib_version_first plugin_no_soname
-QMAKE_INCREMENTAL_STYLE = sublib
-
-include(../common/macx.conf)
-include(../common/gcc-base-mac.conf)
-include(../common/clang.conf)
-include(../common/clang-mac.conf)
-
-QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.7
-
-QMAKE_OBJECTIVE_CFLAGS += -stdlib=libc++
-QMAKE_CXXFLAGS += -stdlib=libc++
-QMAKE_LFLAGS += -stdlib=libc++
-
-load(qt_config)
diff --git a/mkspecs/macx-xcode/Info.plist.app b/mkspecs/macx-xcode/Info.plist.app
deleted file mode 100755
index b822c2851f..0000000000
--- a/mkspecs/macx-xcode/Info.plist.app
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
-<plist version="0.9">
-<dict>
- <key>NSPrincipalClass</key>
- <string>NSApplication</string>
- <key>CFBundleIconFile</key>
- <string>@ICON@</string>
- <key>CFBundlePackageType</key>
- <string>APPL</string>
- <key>CFBundleGetInfoString</key>
- <string>Created by Qt/QMake</string>
- <key>CFBundleSignature</key>
- <string>@TYPEINFO@</string>
- <key>CFBundleExecutable</key>
- <string>@EXECUTABLE@</string>
- <key>CFBundleIdentifier</key>
- <string>com.yourcompany.@EXECUTABLE@</string>
- <key>NOTE</key>
- <string>This file was generated by Qt/QMake.</string>
-</dict>
-</plist>
diff --git a/mkspecs/macx-xcode/Info.plist.lib b/mkspecs/macx-xcode/Info.plist.lib
deleted file mode 100644
index 97609ed0ce..0000000000
--- a/mkspecs/macx-xcode/Info.plist.lib
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
-<plist version="0.9">
-<dict>
- <key>CFBundlePackageType</key>
- <string>FMWK</string>
- <key>CFBundleShortVersionString</key>
- <string>@SHORT_VERSION@</string>
- <key>CFBundleGetInfoString</key>
- <string>Created by Qt/QMake</string>
- <key>CFBundleSignature</key>
- <string>@TYPEINFO@</string>
- <key>CFBundleExecutable</key>
- <string>@LIBRARY@</string>
- <key>NOTE</key>
- <string>Please, do NOT change this file -- It was generated by Qt/QMake.</string>
-</dict>
-</plist>
diff --git a/mkspecs/macx-xcode/features/default_post.prf b/mkspecs/macx-xcode/features/default_post.prf
new file mode 100644
index 0000000000..4c4746bb2b
--- /dev/null
+++ b/mkspecs/macx-xcode/features/default_post.prf
@@ -0,0 +1,7 @@
+
+isEmpty(QMAKE_INFO_PLIST) {
+ plist_template = $$absolute_path(../../$$[QMAKE_XSPEC]/Info.plist.$${TEMPLATE})
+ exists($$plist_template): QMAKE_INFO_PLIST = $$plist_template
+}
+
+load(default_post)
diff --git a/qmake/Makefile.unix b/qmake/Makefile.unix
index 9b7bfa6f8b..f55dfe45e2 100644
--- a/qmake/Makefile.unix
+++ b/qmake/Makefile.unix
@@ -90,7 +90,7 @@ CPPFLAGS = -g $(EXTRA_CPPFLAGS) \
-I$(BUILD_PATH)/src/corelib/global -DHAVE_QCONFIG_CPP \
-I$(QMAKESPEC) \
-I$(SOURCE_PATH)/tools/shared \
- -DQT_BUILD_QMAKE -DQT_BOOTSTRAPPED -DPROEVALUATOR_FULL -DPROEVALUATOR_DEBUG \
+ -DQT_BUILD_QMAKE -DQT_BOOTSTRAPPED -DPROEVALUATOR_FULL \
-DQT_NO_TEXTCODEC -DQT_NO_UNICODETABLES -DQT_NO_COMPONENT -DQT_NO_COMPRESS \
-DQT_NO_THREAD -DQT_NO_QOBJECT -DQT_NO_GEOM_VARIANT -DQT_NO_DATASTREAM
diff --git a/qmake/Makefile.win32 b/qmake/Makefile.win32
index 85b5405b41..22375ef94a 100644
--- a/qmake/Makefile.win32
+++ b/qmake/Makefile.win32
@@ -38,7 +38,7 @@ CFLAGS_BARE = -c -Fo./ \
-I$(BUILD_PATH)\src\corelib\global -DHAVE_QCONFIG_CPP \
-I$(SOURCE_PATH)\mkspecs\$(QMAKESPEC) \
-I$(SOURCE_PATH)\tools\shared \
- -DQT_BUILD_QMAKE -DQT_BOOTSTRAPPED -DPROEVALUATOR_FULL -DPROEVALUATOR_DEBUG \
+ -DQT_BUILD_QMAKE -DQT_BOOTSTRAPPED -DPROEVALUATOR_FULL \
-DQT_NO_TEXTCODEC -DQT_NO_UNICODETABLES -DQT_NO_COMPONENT -DQT_NO_COMPRESS \
-DQT_NO_THREAD -DQT_NO_QOBJECT -DQT_NO_GEOM_VARIANT -DQT_NO_DATASTREAM \
-DUNICODE
diff --git a/qmake/generators/mac/pbuilder_pbx.cpp b/qmake/generators/mac/pbuilder_pbx.cpp
index 41e5754251..d1c70900fb 100644
--- a/qmake/generators/mac/pbuilder_pbx.cpp
+++ b/qmake/generators/mac/pbuilder_pbx.cpp
@@ -1381,24 +1381,24 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
!project->values("QMAKE_FRAMEWORKPATH").isEmpty() ? SettingsAsList : 0, 5) << ";\n";
{
- ProStringList cflags = fixListForOutput("QMAKE_CFLAGS");
+ ProStringList cflags = project->values("QMAKE_CFLAGS");
const ProStringList &prl_defines = project->values("PRL_EXPORT_DEFINES");
for (int i = 0; i < prl_defines.size(); ++i)
cflags += "-D" + prl_defines.at(i);
const ProStringList &defines = project->values("DEFINES");
for (int i = 0; i < defines.size(); ++i)
cflags += "-D" + defines.at(i);
- t << "\t\t\t\t" << writeSettings("OTHER_CFLAGS", cflags, SettingsAsList, 5) << ";\n";
+ t << "\t\t\t\t" << writeSettings("OTHER_CFLAGS", fixListForOutput(cflags), SettingsAsList, 5) << ";\n";
}
{
- ProStringList cxxflags = fixListForOutput("QMAKE_CXXFLAGS");
+ ProStringList cxxflags = project->values("QMAKE_CXXFLAGS");
const ProStringList &prl_defines = project->values("PRL_EXPORT_DEFINES");
for (int i = 0; i < prl_defines.size(); ++i)
cxxflags += "-D" + prl_defines.at(i);
const ProStringList &defines = project->values("DEFINES");
for (int i = 0; i < defines.size(); ++i)
cxxflags += "-D" + defines.at(i);
- t << "\t\t\t\t" << writeSettings("OTHER_CPLUSPLUSFLAGS", cxxflags, SettingsAsList, 5) << ";\n";
+ t << "\t\t\t\t" << writeSettings("OTHER_CPLUSPLUSFLAGS", fixListForOutput(cxxflags), SettingsAsList, 5) << ";\n";
}
if (!project->isActiveConfig("staticlib")) {
t << "\t\t\t\t" << writeSettings("OTHER_LDFLAGS",
@@ -1408,7 +1408,8 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
+ fixListForOutput("QMAKE_LIBS_PRIVATE"),
SettingsAsList, 6) << ";\n";
}
- const ProStringList &archs = project->values("QT_ARCH");
+ const ProStringList &archs = !project->values("QMAKE_XCODE_ARCHS").isEmpty() ?
+ project->values("QMAKE_XCODE_ARCHS") : project->values("QT_ARCH");
if (!archs.isEmpty())
t << "\t\t\t\t" << writeSettings("ARCHS", archs) << ";\n";
if (!project->isEmpty("OBJECTS_DIR"))
@@ -1518,19 +1519,20 @@ ProjectBuilderMakefileGenerator::fixForOutput(const QString &values)
project->values("QMAKE_PBX_VARS").append(reg_var.cap(1));
rep += reg_var.matchedLength();
}
- QString ret = values;
- ret = ret.replace(QRegExp("\\\\ "), " "); //unescape spaces
- ret = ret.replace(QRegExp("('|\\\\|\")"), "\\\\1"); //fix quotes
- ret = ret.replace("\t", " "); //fix tabs
- ret = ret.replace(QRegExp(" "), "\\ "); //escape spaces
- return ret;
+
+ return values;
}
ProStringList
ProjectBuilderMakefileGenerator::fixListForOutput(const char *where)
{
+ return fixListForOutput(project->values(where));
+}
+
+ProStringList
+ProjectBuilderMakefileGenerator::fixListForOutput(const ProStringList &l)
+{
ProStringList ret;
- const ProStringList &l = project->values(where);
for(int i = 0; i < l.count(); i++)
ret += fixForOutput(l[i].toQString());
return ret;
@@ -1747,37 +1749,81 @@ ProjectBuilderMakefileGenerator::escapeFilePath(const QString &path) const
#endif
}
+static QString quotedStringLiteral(const QString &value)
+{
+ QString result;
+ const int len = value.length();
+ result.reserve(int(len * 1.1) + 2);
+
+ result += QLatin1Char('"');
+
+ // Escape
+ for (int i = 0; i < len; ++i) {
+ QChar character = value.at(i);;
+ ushort code = character.unicode();
+ switch (code) {
+ case '\\':
+ result += QLatin1String("\\\\");
+ break;
+ case '"':
+ result += QLatin1String("\\\"");
+ break;
+ case '\b':
+ result += QLatin1String("\\b");
+ break;
+ case '\n':
+ result += QLatin1String("\\n");
+ break;
+ case '\r':
+ result += QLatin1String("\\r");
+ break;
+ case '\t':
+ result += QLatin1String("\\t");
+ break;
+ default:
+ if (code >= 32 && code <= 127)
+ result += character;
+ else
+ result += QLatin1String("\\u") + QString::number(code, 16).rightJustified(4, '0');
+ }
+ }
+
+ result += QLatin1Char('"');
+
+ result.squeeze();
+ return result;
+}
+
QString
ProjectBuilderMakefileGenerator::writeSettings(const QString &var, const ProStringList &vals, int flags, int indent_level)
{
QString ret;
- const QString quote = (flags & SettingsNoQuote) ? "" : "\"";
- const QString escape_quote = quote.isEmpty() ? "" : QString("\\" + quote);
+ bool shouldQuote = !((flags & SettingsNoQuote));
+
QString newline = "\n";
for(int i = 0; i < indent_level; ++i)
newline += "\t";
+
+ ret += var + " = ";
+
if(flags & SettingsAsList) {
- ret += var + " = (" + newline;
+ ret += "(" + newline;
for(int i = 0, count = 0; i < vals.size(); ++i) {
QString val = vals.at(i).toQString();
if(!val.isEmpty()) {
if(count++ > 0)
ret += "," + newline;
- ret += quote + val.replace(quote, escape_quote) + quote;
+ if (shouldQuote)
+ val = quotedStringLiteral(val);
+ ret += val;
}
}
ret += ")";
} else {
- ret += var + " = " + quote;
- for(int i = 0; i < vals.size(); ++i) {
- QString val = vals.at(i).toQString();
-// if(val.isEmpty())
-// val = quote + quote;
- if(i)
- ret += " ";
- ret += val;
- }
- ret += quote;
+ QString val = vals.join(QLatin1Char(' '));
+ if (shouldQuote)
+ val = quotedStringLiteral(val);
+ ret += val;
}
return ret;
}
diff --git a/qmake/generators/mac/pbuilder_pbx.h b/qmake/generators/mac/pbuilder_pbx.h
index 255dd43348..a08dc7c2bd 100644
--- a/qmake/generators/mac/pbuilder_pbx.h
+++ b/qmake/generators/mac/pbuilder_pbx.h
@@ -61,6 +61,7 @@ class ProjectBuilderMakefileGenerator : public UnixMakefileGenerator
QString findProgram(const ProString &prog);
QString fixForOutput(const QString &file);
ProStringList fixListForOutput(const char *where);
+ ProStringList fixListForOutput(const ProStringList &list);
int reftypeForFile(const QString &where);
QString sourceTreeForFile(const QString &where);
QString projectSuffix() const;
diff --git a/qmake/generators/makefile.cpp b/qmake/generators/makefile.cpp
index 98b5a328e4..a8ae84a4e2 100644
--- a/qmake/generators/makefile.cpp
+++ b/qmake/generators/makefile.cpp
@@ -2272,8 +2272,7 @@ MakefileGenerator::writeHeader(QTextStream &t)
{
t << "#############################################################################\n";
t << "# Makefile for building: " << escapeFilePath(var("TARGET")) << endl;
- t << "# Generated by qmake (" QMAKE_VERSION_STR ") (Qt " QT_VERSION_STR ") on: ";
- t << QDateTime::currentDateTime().toString() << endl;
+ t << "# Generated by qmake (" QMAKE_VERSION_STR ") (Qt " QT_VERSION_STR ")\n";
t << "# Project: " << fileFixify(project->projectFile()) << endl;
t << "# Template: " << var("TEMPLATE") << endl;
if(!project->isActiveConfig("build_pass"))
diff --git a/qmake/library/ioutils.cpp b/qmake/library/ioutils.cpp
index 3c2801594a..cc19aa5c42 100644
--- a/qmake/library/ioutils.cpp
+++ b/qmake/library/ioutils.cpp
@@ -88,6 +88,11 @@ bool IoUtils::isRelativePath(const QString &path)
return true;
}
+QStringRef IoUtils::pathName(const QString &fileName)
+{
+ return fileName.leftRef(fileName.lastIndexOf(QLatin1Char('/')) + 1);
+}
+
QStringRef IoUtils::fileName(const QString &fileName)
{
return fileName.midRef(fileName.lastIndexOf(QLatin1Char('/')) + 1);
diff --git a/qmake/library/ioutils.h b/qmake/library/ioutils.h
index 160e879fce..d69725fa27 100644
--- a/qmake/library/ioutils.h
+++ b/qmake/library/ioutils.h
@@ -64,6 +64,7 @@ public:
static bool exists(const QString &fileName) { return fileType(fileName) != FileNotFound; }
static bool isRelativePath(const QString &fileName);
static bool isAbsolutePath(const QString &fileName) { return !isRelativePath(fileName); }
+ static QStringRef pathName(const QString &fileName); // Requires normalized path
static QStringRef fileName(const QString &fileName); // Requires normalized path
static QString resolvePath(const QString &baseDir, const QString &fileName);
static QString shellQuoteUnix(const QString &arg);
diff --git a/qmake/library/qmake_global.h b/qmake/library/qmake_global.h
index 7e2247e8c6..acb95e7ab3 100644
--- a/qmake/library/qmake_global.h
+++ b/qmake/library/qmake_global.h
@@ -64,4 +64,8 @@
# define ALWAYS_INLINE inline
#endif
+#ifdef PROEVALUATOR_FULL
+# define PROEVALUATOR_DEBUG
+#endif
+
#endif
diff --git a/qmake/library/qmakebuiltins.cpp b/qmake/library/qmakebuiltins.cpp
index be0d8ea172..9b86048219 100644
--- a/qmake/library/qmakebuiltins.cpp
+++ b/qmake/library/qmakebuiltins.cpp
@@ -315,12 +315,12 @@ QMakeEvaluator::writeFile(const QString &ctx, const QString &fn, QIODevice::Open
return ReturnFalse;
}
QString errStr;
- if (!doWriteFile(qfi.filePath(), mode, contents, &errStr)) {
+ if (!doWriteFile(fn, mode, contents, &errStr)) {
evalError(fL1S("Cannot write %1file %2: %3.")
- .arg(ctx, QDir::toNativeSeparators(qfi.filePath()), errStr));
+ .arg(ctx, QDir::toNativeSeparators(fn), errStr));
return ReturnFalse;
}
- m_parser->discardFileFromCache(qfi.filePath());
+ m_parser->discardFileFromCache(fn);
return ReturnTrue;
}
@@ -1118,11 +1118,11 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
}
}
return ReturnFalse;
-#ifdef PROEVALUATOR_FULL
case T_REQUIRES:
+#ifdef PROEVALUATOR_FULL
checkRequirements(args);
- return ReturnFalse; // Another qmake breakage
#endif
+ return ReturnFalse; // Another qmake breakage
case T_EVAL: {
VisitReturn ret = ReturnFalse;
ProFile *pro = m_parser->parsedProBlock(args.join(statics.field_sep),
@@ -1389,14 +1389,14 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
}
return (func_t == T_ERROR && !m_cumulative) ? ReturnError : ReturnTrue;
}
-#ifdef PROEVALUATOR_FULL
case T_SYSTEM: {
- if (m_cumulative) // Anything else would be insanity
- return ReturnFalse;
if (args.count() != 1) {
evalError(fL1S("system(exec) requires one argument."));
return ReturnFalse;
}
+#ifdef PROEVALUATOR_FULL
+ if (m_cumulative) // Anything else would be insanity
+ return ReturnFalse;
#ifndef QT_BOOTSTRAPPED
QProcess proc;
proc.setProcessChannelMode(QProcess::ForwardedChannels);
@@ -1407,8 +1407,10 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
+ IoUtils::shellQuote(QDir::toNativeSeparators(currentDirectory()))
+ QLatin1String(" && ") + args.at(0)).toLocal8Bit().constData()) == 0);
#endif
- }
+#else
+ return ReturnTrue;
#endif
+ }
case T_ISEMPTY: {
if (args.count() != 1) {
evalError(fL1S("isEmpty(var) requires one argument."));
@@ -1435,17 +1437,18 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
return ReturnFalse;
}
-#ifdef PROEVALUATOR_FULL
case T_MKPATH: {
if (args.count() != 1) {
evalError(fL1S("mkpath(file) requires one argument."));
return ReturnFalse;
}
+#ifdef PROEVALUATOR_FULL
const QString &fn = resolvePath(args.at(0).toQString(m_tmp1));
if (!QDir::current().mkpath(fn)) {
evalError(fL1S("Cannot create directory %1.").arg(QDir::toNativeSeparators(fn)));
return ReturnFalse;
}
+#endif
return ReturnTrue;
}
case T_WRITE_FILE: {
@@ -1453,6 +1456,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
evalError(fL1S("write_file(name, [content var, [append]]) requires one to three arguments."));
return ReturnFalse;
}
+#ifdef PROEVALUATOR_FULL
QIODevice::OpenMode mode = QIODevice::Truncate;
QString contents;
if (args.count() >= 2) {
@@ -1464,12 +1468,16 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
mode = QIODevice::Append;
}
return writeFile(QString(), resolvePath(args.at(0).toQString(m_tmp1)), mode, contents);
+#else
+ return ReturnTrue;
+#endif
}
case T_TOUCH: {
if (args.count() != 2) {
evalError(fL1S("touch(file, reffile) requires two arguments."));
return ReturnFalse;
}
+#ifdef PROEVALUATOR_FULL
const QString &tfn = resolvePath(args.at(0).toQString(m_tmp1));
const QString &rfn = resolvePath(args.at(1).toQString(m_tmp2));
#ifdef Q_OS_UNIX
@@ -1506,6 +1514,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
SetFileTime(wHand, 0, 0, &ft);
CloseHandle(wHand);
#endif
+#endif
return ReturnTrue;
}
case T_CACHE: {
@@ -1513,6 +1522,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
evalError(fL1S("cache(var, [set|add|sub] [transient] [super], [srcvar]) requires one to three arguments."));
return ReturnFalse;
}
+#ifdef PROEVALUATOR_FULL
bool persist = true;
bool super = false;
enum { CacheSet, CacheAdd, CacheSub } mode = CacheSet;
@@ -1638,8 +1648,10 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
fn = m_cachefile;
}
return writeFile(fL1S("cache "), fn, QIODevice::Append, varstr);
- }
+#else
+ return ReturnTrue;
#endif
+ }
default:
evalError(fL1S("Function '%1' is not implemented.").arg(function.toQString(m_tmp1)));
return ReturnFalse;
diff --git a/qmake/library/qmakeevaluator.cpp b/qmake/library/qmakeevaluator.cpp
index 09ea231684..0cb053e566 100644
--- a/qmake/library/qmakeevaluator.cpp
+++ b/qmake/library/qmakeevaluator.cpp
@@ -936,7 +936,7 @@ void QMakeEvaluator::visitProVariable(
if (varName == statics.strTEMPLATE)
setTemplate();
else if (varName == statics.strQMAKE_PLATFORM)
- updateFeaturePaths();
+ m_featureRoots = 0;
#ifdef PROEVALUATOR_FULL
else if (varName == statics.strREQUIRES)
checkRequirements(values(varName));
@@ -1160,6 +1160,7 @@ bool QMakeEvaluator::loadSpecInternal()
#endif
valuesRef(ProKey("QMAKESPEC")) << ProString(m_qmakespec);
m_qmakespecName = IoUtils::fileName(m_qmakespec).toString();
+ // This also ensures that m_featureRoots is valid.
if (evaluateFeatureFile(QLatin1String("spec_post.prf")) != ReturnTrue)
return false;
// The MinGW and x-build specs may change the separator; $$shell_{path,quote}() need it
@@ -1174,6 +1175,8 @@ bool QMakeEvaluator::loadSpec()
{
QMakeEvaluator evaluator(m_option, m_parser, m_handler);
+ evaluator.m_sourceRoot = m_sourceRoot;
+ evaluator.m_buildRoot = m_buildRoot;
if (!m_superfile.isEmpty()) {
valuesRef(ProKey("_QMAKE_SUPER_CACHE_")) << ProString(m_superfile);
if (evaluator.evaluateFile(
@@ -1429,6 +1432,7 @@ void QMakeEvaluator::updateMkspecPaths()
ret << m_sourceRoot + concat;
ret << m_option->propertyValue(ProKey("QT_HOST_DATA/get")) + concat;
+ ret << m_option->propertyValue(ProKey("QT_HOST_DATA/src")) + concat;
ret.removeDuplicates();
m_mkspecPaths = ret;
@@ -1450,10 +1454,14 @@ void QMakeEvaluator::updateFeaturePaths()
m_option->dirlist_sep, QString::SkipEmptyParts);
QStringList feature_bases;
- if (!m_buildRoot.isEmpty())
+ if (!m_buildRoot.isEmpty()) {
+ feature_bases << m_buildRoot + mkspecs_concat;
feature_bases << m_buildRoot;
- if (!m_sourceRoot.isEmpty())
+ }
+ if (!m_sourceRoot.isEmpty()) {
+ feature_bases << m_sourceRoot + mkspecs_concat;
feature_bases << m_sourceRoot;
+ }
foreach (const QString &item, m_option->getPathListEnv(QLatin1String("QMAKEPATH")))
feature_bases << (item + mkspecs_concat);
@@ -1477,8 +1485,8 @@ void QMakeEvaluator::updateFeaturePaths()
}
}
- feature_bases << (m_option->propertyValue(ProKey("QT_HOST_DATA/get")).toQString(m_mtmp)
- + mkspecs_concat);
+ feature_bases << (m_option->propertyValue(ProKey("QT_HOST_DATA/get")) + mkspecs_concat);
+ feature_bases << (m_option->propertyValue(ProKey("QT_HOST_DATA/src")) + mkspecs_concat);
foreach (const QString &fb, feature_bases) {
foreach (const ProString &sfx, values(ProKey("QMAKE_PLATFORM")))
@@ -1496,7 +1504,7 @@ void QMakeEvaluator::updateFeaturePaths()
foreach (const QString &root, feature_roots)
if (IoUtils::exists(root))
ret << root;
- m_featureRoots = ret;
+ m_featureRoots = new QMakeFeatureRoots(ret);
}
ProString QMakeEvaluator::propertyValue(const ProKey &name) const
@@ -1854,34 +1862,55 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateFeatureFile(
if (!fn.endsWith(QLatin1String(".prf")))
fn += QLatin1String(".prf");
- if (m_featureRoots.isEmpty())
+ if (!m_featureRoots)
updateFeaturePaths();
- int start_root = 0;
+#ifdef PROEVALUATOR_THREAD_SAFE
+ m_featureRoots->mutex.lock();
+#endif
QString currFn = currentFileName();
- if (IoUtils::fileName(currFn) == IoUtils::fileName(fn)) {
- for (int root = 0; root < m_featureRoots.size(); ++root)
- if (currFn == m_featureRoots.at(root) + fn) {
- start_root = root + 1;
- break;
+ if (IoUtils::fileName(currFn) != IoUtils::fileName(fn))
+ currFn.clear();
+ // Null values cannot regularly exist in the hash, so they indicate that the value still
+ // needs to be determined. Failed lookups are represented via non-null empty strings.
+ QString *fnp = &m_featureRoots->cache[qMakePair(fn, currFn)];
+ if (fnp->isNull()) {
+ int start_root = 0;
+ const QStringList &paths = m_featureRoots->paths;
+ if (!currFn.isEmpty()) {
+ QStringRef currPath = IoUtils::pathName(currFn);
+ for (int root = 0; root < paths.size(); ++root)
+ if (currPath == paths.at(root)) {
+ start_root = root + 1;
+ break;
+ }
+ }
+ for (int root = start_root; root < paths.size(); ++root) {
+ QString fname = paths.at(root) + fn;
+ if (IoUtils::exists(fname)) {
+ fn = fname;
+ goto cool;
}
- }
- for (int root = start_root; root < m_featureRoots.size(); ++root) {
- QString fname = m_featureRoots.at(root) + fn;
- if (IoUtils::exists(fname)) {
- fn = fname;
- goto cool;
}
- }
#ifdef QMAKE_BUILTIN_PRFS
- fn.prepend(QLatin1String(":/qmake/features/"));
- if (QFileInfo(fn).exists())
- goto cool;
+ fn.prepend(QLatin1String(":/qmake/features/"));
+ if (QFileInfo(fn).exists())
+ goto cool;
#endif
- if (!silent)
- evalError(fL1S("Cannot find feature %1").arg(fileName));
- return ReturnFalse;
+ fn = QLatin1String(""); // Indicate failed lookup. See comment above.
- cool:
+ cool:
+ *fnp = fn;
+ } else {
+ fn = *fnp;
+ }
+#ifdef PROEVALUATOR_THREAD_SAFE
+ m_featureRoots->mutex.unlock();
+#endif
+ if (fn.isEmpty()) {
+ if (!silent)
+ evalError(fL1S("Cannot find feature %1").arg(fileName));
+ return ReturnFalse;
+ }
ProStringList &already = valuesRef(ProKey("QMAKE_INTERNAL_INCLUDED_FEATURES"));
ProString afn(fn);
if (already.contains(afn)) {
diff --git a/qmake/library/qmakeevaluator.h b/qmake/library/qmakeevaluator.h
index 09617ba019..91433302d0 100644
--- a/qmake/library/qmakeevaluator.h
+++ b/qmake/library/qmakeevaluator.h
@@ -55,9 +55,13 @@
#include <qstack.h>
#include <qstring.h>
#include <qstringlist.h>
+#include <qshareddata.h>
#ifndef QT_BOOTSTRAPPED
# include <qprocess.h>
#endif
+#ifdef PROEVALUATOR_THREAD_SAFE
+# include <qmutex.h>
+#endif
QT_BEGIN_NAMESPACE
@@ -83,6 +87,20 @@ public:
virtual void doneWithEval(ProFile *parent) = 0;
};
+typedef QPair<QString, QString> QMakeFeatureKey; // key, parent
+typedef QHash<QMakeFeatureKey, QString> QMakeFeatureHash;
+
+class QMAKE_EXPORT QMakeFeatureRoots : public QSharedData
+{
+public:
+ QMakeFeatureRoots(const QStringList &_paths) : paths(_paths) {}
+ const QStringList paths;
+ mutable QMakeFeatureHash cache;
+#ifdef PROEVALUATOR_THREAD_SAFE
+ mutable QMutex mutex;
+#endif
+};
+
// We use a QLinkedList based stack instead of a QVector based one (QStack), so that
// the addresses of value maps stay constant. The qmake generators rely on that.
class QMAKE_EXPORT ProValueMapStack : public QLinkedList<ProValueMap>
@@ -284,7 +302,7 @@ public:
QStringList m_qmakepath;
QStringList m_qmakefeatures;
QStringList m_mkspecPaths;
- QStringList m_featureRoots;
+ QExplicitlySharedDataPointer<QMakeFeatureRoots> m_featureRoots;
ProString m_dirSep;
ProFunctionDefs m_functionDefs;
ProStringList m_returnValue;
diff --git a/qmake/library/qmakeglobals.cpp b/qmake/library/qmakeglobals.cpp
index 3570aa70b7..bf37d51c40 100644
--- a/qmake/library/qmakeglobals.cpp
+++ b/qmake/library/qmakeglobals.cpp
@@ -324,34 +324,46 @@ bool QMakeGlobals::initProperties()
QT_PCLOSE(proc);
}
#endif
- foreach (QByteArray line, data.split('\n'))
- if (!line.startsWith("QMAKE_")) {
- int off = line.indexOf(':');
- if (off < 0) // huh?
- continue;
- if (line.endsWith('\r'))
- line.chop(1);
- QString name = QString::fromLatin1(line.left(off));
- ProString value = ProString(QDir::fromNativeSeparators(
- QString::fromLocal8Bit(line.mid(off + 1))));
- properties.insert(ProKey(name), value);
- if (name.startsWith(QLatin1String("QT_")) && !name.contains(QLatin1Char('/'))) {
- if (name.startsWith(QLatin1String("QT_INSTALL_"))) {
+ foreach (QByteArray line, data.split('\n')) {
+ int off = line.indexOf(':');
+ if (off < 0) // huh?
+ continue;
+ if (line.endsWith('\r'))
+ line.chop(1);
+ QString name = QString::fromLatin1(line.left(off));
+ ProString value = ProString(QDir::fromNativeSeparators(
+ QString::fromLocal8Bit(line.mid(off + 1))));
+ properties.insert(ProKey(name), value);
+ if (name.startsWith(QLatin1String("QT_"))) {
+ bool plain = !name.contains(QLatin1Char('/'));
+ if (!plain) {
+ if (!name.endsWith(QLatin1String("/get")))
+ continue;
+ name.chop(4);
+ }
+ if (name.startsWith(QLatin1String("QT_INSTALL_"))) {
+ if (plain) {
properties.insert(ProKey(name + QLatin1String("/raw")), value);
properties.insert(ProKey(name + QLatin1String("/get")), value);
- if (name == QLatin1String("QT_INSTALL_PREFIX")
- || name == QLatin1String("QT_INSTALL_DATA")
- || name == QLatin1String("QT_INSTALL_BINS")) {
- name.replace(3, 7, QLatin1String("HOST"));
+ }
+ properties.insert(ProKey(name + QLatin1String("/src")), value);
+ if (name == QLatin1String("QT_INSTALL_PREFIX")
+ || name == QLatin1String("QT_INSTALL_DATA")
+ || name == QLatin1String("QT_INSTALL_BINS")) {
+ name.replace(3, 7, QLatin1String("HOST"));
+ if (plain) {
properties.insert(ProKey(name), value);
properties.insert(ProKey(name + QLatin1String("/get")), value);
}
- } else if (name.startsWith(QLatin1String("QT_HOST_"))) {
- properties.insert(ProKey(name + QLatin1String("/get")), value);
+ properties.insert(ProKey(name + QLatin1String("/src")), value);
}
+ } else if (name.startsWith(QLatin1String("QT_HOST_"))) {
+ if (plain)
+ properties.insert(ProKey(name + QLatin1String("/get")), value);
+ properties.insert(ProKey(name + QLatin1String("/src")), value);
}
}
- properties.insert(ProKey("QMAKE_VERSION"), ProString("2.01a"));
+ }
return true;
}
#else
diff --git a/qmake/property.cpp b/qmake/property.cpp
index 4685440b48..38d454cb5d 100644
--- a/qmake/property.cpp
+++ b/qmake/property.cpp
@@ -83,6 +83,7 @@ QMakeProperty::QMakeProperty() : settings(0)
{
for (int i = 0; i < sizeof(propList)/sizeof(propList[0]); i++) {
QString name = QString::fromLatin1(propList[i].name);
+ m_values[ProKey(name + "/src")] = QLibraryInfo::rawLocation(propList[i].loc, QLibraryInfo::EffectiveSourcePaths);
m_values[ProKey(name + "/get")] = QLibraryInfo::rawLocation(propList[i].loc, QLibraryInfo::EffectivePaths);
QString val = QLibraryInfo::rawLocation(propList[i].loc, QLibraryInfo::FinalPaths);
if (!propList[i].raw) {
@@ -164,11 +165,14 @@ QMakeProperty::exec()
ProString val = value(ProKey(prop));
ProString pval = value(ProKey(prop + "/raw"));
ProString gval = value(ProKey(prop + "/get"));
+ ProString sval = value(ProKey(prop + "/src"));
fprintf(stdout, "%s:%s\n", prop.toLatin1().constData(), val.toLatin1().constData());
if (!pval.isEmpty() && pval != val)
fprintf(stdout, "%s/raw:%s\n", prop.toLatin1().constData(), pval.toLatin1().constData());
if (!gval.isEmpty() && gval != (pval.isEmpty() ? val : pval))
fprintf(stdout, "%s/get:%s\n", prop.toLatin1().constData(), gval.toLatin1().constData());
+ if (!sval.isEmpty() && sval != gval)
+ fprintf(stdout, "%s/src:%s\n", prop.toLatin1().constData(), sval.toLatin1().constData());
}
return true;
}
diff --git a/qmake/qmake.pro b/qmake/qmake.pro
index a81d0cdf77..568ad41ce1 100644
--- a/qmake/qmake.pro
+++ b/qmake/qmake.pro
@@ -6,7 +6,7 @@ option(host_build)
CONFIG += console bootstrap
CONFIG -= qt shared app_bundle uic
DEFINES += QT_BUILD_QMAKE QT_BOOTSTRAPPED \
- PROEVALUATOR_FULL PROEVALUATOR_DEBUG
+ PROEVALUATOR_FULL
DESTDIR = ../bin/
OBJECTS_DIR = .
diff --git a/qtbase.pro b/qtbase.pro
index d6726b5e93..d3b03d1fba 100644
--- a/qtbase.pro
+++ b/qtbase.pro
@@ -107,7 +107,7 @@ prefix_build|!equals(PWD, $$OUT_PWD) {
mkspecs.path = $$[QT_HOST_DATA]/mkspecs
mkspecs.files = \
$$OUT_PWD/mkspecs/qconfig.pri $$OUT_PWD/mkspecs/qmodule.pri $$OUT_PWD/mkspecs/qdevice.pri \
- $$files($$PWD/mkspecs/*) # $$OUT_PWD contains only symlinks under Unix
+ $$files($$PWD/mkspecs/*)
mkspecs.files -= $$PWD/mkspecs/modules
INSTALLS += mkspecs
diff --git a/src/concurrent/doc/qtconcurrent.qdocconf b/src/concurrent/doc/qtconcurrent.qdocconf
index 3d5e9de5e0..7fa437c17f 100644
--- a/src/concurrent/doc/qtconcurrent.qdocconf
+++ b/src/concurrent/doc/qtconcurrent.qdocconf
@@ -40,3 +40,6 @@ exampledirs += ../../../examples/qtconcurrent \
excludedirs += ../../../examples/widgets/doc
imagedirs += images
+
+navigation.landingpage = "Qt Concurrent"
+navigation.cppclassespage = "Qt Concurrent C++ Classes"
diff --git a/src/corelib/Qt5CoreConfigExtras.cmake.in b/src/corelib/Qt5CoreConfigExtras.cmake.in
index e01b448351..36a54787b3 100644
--- a/src/corelib/Qt5CoreConfigExtras.cmake.in
+++ b/src/corelib/Qt5CoreConfigExtras.cmake.in
@@ -55,11 +55,8 @@ set_property(TARGET Qt5::Core APPEND PROPERTY
COMPATIBLE_INTERFACE_STRING QT_MAJOR_VERSION
)
-!!IF isEmpty(CMAKE_HOST_DATA_DIR_IS_ABSOLUTE)
-set(_qt5_corelib_extra_includes \"${_qt5Core_install_prefix}/$${CMAKE_HOST_DATA_DIR}/mkspecs/$${CMAKE_MKSPEC}\")
-!!ELSE
-set(_qt5_corelib_extra_includes \"$${CMAKE_HOST_DATA_DIR}mkspecs/$${CMAKE_MKSPEC}\")
-!!ENDIF
+include(\"${CMAKE_CURRENT_LIST_DIR}/Qt5CoreConfigExtrasMkspecDir.cmake\")
+
foreach(_dir ${_qt5_corelib_extra_includes})
_qt5_Core_check_file_exists(${_dir})
endforeach()
diff --git a/src/corelib/Qt5CoreConfigExtrasMkspecDir.cmake.in b/src/corelib/Qt5CoreConfigExtrasMkspecDir.cmake.in
new file mode 100644
index 0000000000..c357237d0e
--- /dev/null
+++ b/src/corelib/Qt5CoreConfigExtrasMkspecDir.cmake.in
@@ -0,0 +1,6 @@
+
+!!IF isEmpty(CMAKE_HOST_DATA_DIR_IS_ABSOLUTE)
+set(_qt5_corelib_extra_includes \"${_qt5Core_install_prefix}/$${CMAKE_HOST_DATA_DIR}/mkspecs/$${CMAKE_MKSPEC}\")
+!!ELSE
+set(_qt5_corelib_extra_includes \"$${CMAKE_HOST_DATA_DIR}mkspecs/$${CMAKE_MKSPEC}\")
+!!ENDIF
diff --git a/src/corelib/Qt5CoreConfigExtrasMkspecDirForInstall.cmake.in b/src/corelib/Qt5CoreConfigExtrasMkspecDirForInstall.cmake.in
new file mode 100644
index 0000000000..706304cf34
--- /dev/null
+++ b/src/corelib/Qt5CoreConfigExtrasMkspecDirForInstall.cmake.in
@@ -0,0 +1,6 @@
+
+!!IF isEmpty(CMAKE_INSTALL_DATA_DIR_IS_ABSOLUTE)
+set(_qt5_corelib_extra_includes \"${_qt5Core_install_prefix}/$${CMAKE_INSTALL_DATA_DIR}/mkspecs/$${CMAKE_MKSPEC}\")
+!!ELSE
+set(_qt5_corelib_extra_includes \"$${CMAKE_INSTALL_DATA_DIR}mkspecs/$${CMAKE_MKSPEC}\")
+!!ENDIF
diff --git a/src/corelib/corelib.pro b/src/corelib/corelib.pro
index 44a3f06f50..766529c587 100644
--- a/src/corelib/corelib.pro
+++ b/src/corelib/corelib.pro
@@ -77,12 +77,32 @@ cmake_umbrella_config_file.output = $$DESTDIR/cmake/Qt5/Qt5Config.cmake
cmake_umbrella_config_version_file.input = $$PWD/../../mkspecs/features/data/cmake/Qt5ConfigVersion.cmake.in
cmake_umbrella_config_version_file.output = $$DESTDIR/cmake/Qt5/Qt5ConfigVersion.cmake
+load(cmake_functions)
+
+CMAKE_HOST_DATA_DIR = $$cmakeRelativePath($$[QT_HOST_DATA/src], $$[QT_INSTALL_PREFIX])
+contains(CMAKE_HOST_DATA_DIR, "^\\.\\./.*"):!isEmpty(CMAKE_HOST_DATA_DIR) {
+ CMAKE_HOST_DATA_DIR = $$[QT_HOST_DATA/src]/
+ CMAKE_HOST_DATA_DIR_IS_ABSOLUTE = True
+}
+
+cmake_extras_mkspec_dir.input = $$PWD/Qt5CoreConfigExtrasMkspecDir.cmake.in
+cmake_extras_mkspec_dir.output = $$DESTDIR/cmake/Qt5Core/Qt5CoreConfigExtrasMkspecDir.cmake
+
+CMAKE_INSTALL_DATA_DIR = $$cmakeRelativePath($$[QT_HOST_DATA], $$[QT_INSTALL_PREFIX])
+contains(CMAKE_INSTALL_DATA_DIR, "^\\.\\./.*"):!isEmpty(CMAKE_INSTALL_DATA_DIR) {
+ CMAKE_INSTALL_DATA_DIR = $$[QT_HOST_DATA]/
+ CMAKE_INSTALL_DATA_DIR_IS_ABSOLUTE = True
+}
+
+cmake_extras_mkspec_dir_for_install.input = $$PWD/Qt5CoreConfigExtrasMkspecDirForInstall.cmake.in
+cmake_extras_mkspec_dir_for_install.output = $$DESTDIR/cmake/install/Qt5Core/Qt5CoreConfigExtrasMkspecDir.cmake
+
cmake_qt5_umbrella_module_files.files = $$cmake_umbrella_config_file.output $$cmake_umbrella_config_version_file.output
cmake_qt5_umbrella_module_files.path = $$[QT_INSTALL_LIBS]/cmake/Qt5
-QMAKE_SUBSTITUTES += ctest_macros_file cmake_umbrella_config_file cmake_umbrella_config_version_file
+QMAKE_SUBSTITUTES += ctest_macros_file cmake_umbrella_config_file cmake_umbrella_config_version_file cmake_extras_mkspec_dir cmake_extras_mkspec_dir_for_install
-ctest_qt5_module_files.files += $$ctest_macros_file.output
+ctest_qt5_module_files.files += $$ctest_macros_file.output $$cmake_extras_mkspec_dir_for_install.output
ctest_qt5_module_files.path = $$[QT_INSTALL_LIBS]/cmake/Qt5Core
diff --git a/src/corelib/doc/qtcore.qdocconf b/src/corelib/doc/qtcore.qdocconf
index 0e275ee8d4..c74a2b4761 100644
--- a/src/corelib/doc/qtcore.qdocconf
+++ b/src/corelib/doc/qtcore.qdocconf
@@ -39,3 +39,6 @@ exampledirs += \
../../../examples/tools/
imagedirs += images
+
+navigation.landingpage = "Qt Core"
+navigation.cppclassespage = "Qt Core C++ Classes"
diff --git a/src/corelib/doc/snippets/code/src_corelib_io_qurl.cpp b/src/corelib/doc/snippets/code/src_corelib_io_qurl.cpp
index 532a0e1f59..91eaf298e1 100644
--- a/src/corelib/doc/snippets/code/src_corelib_io_qurl.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_io_qurl.cpp
@@ -85,3 +85,9 @@ QByteArray ba = QUrl::toPercentEncoding("{a fishy string?}", "{}", "s");
qDebug(ba.constData());
// prints "{a fi%73hy %73tring%3F}"
//! [6]
+
+//! [7]
+QUrl url("http://qt-project.org/support/file.html");
+// url.adjusted(RemoveFilename) == "http://qt-project.org/support/"
+// url.fileName() == "file.html"
+//! [7]
diff --git a/src/corelib/doc/snippets/code/src_corelib_kernel_qvariant.cpp b/src/corelib/doc/snippets/code/src_corelib_kernel_qvariant.cpp
index 25d24185ee..ab909e5065 100644
--- a/src/corelib/doc/snippets/code/src_corelib_kernel_qvariant.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_kernel_qvariant.cpp
@@ -134,3 +134,61 @@ return QVariant::fromValue(s);
QObject *object = getObjectFromSomewhere();
QVariant data = QVariant::fromValue(object);
//! [8]
+
+//! [9]
+
+QList<int> intList;
+intList.push_back(7);
+intList.push_back(11);
+intList.push_back(42);
+
+QVariant variant = QVariant::fromValue(intList);
+if (variant.canConvert<QVariantList>()) {
+ QSequentialIterable iterable = variant.value<QSequentialIterable>();
+ // Can use foreach:
+ foreach (const QVariant &v, iterable) {
+ qDebug() << v;
+ }
+ // Can use C++11 range-for:
+ for (const QVariant &v : iterable) {
+ qDebug() << v;
+ }
+ // Can use iterators:
+ QSequentialIterable::const_iterator it = iterable.begin();
+ const QSequentialIterable::const_iterator end = iterable.end();
+ for ( ; it != end; ++it) {
+ qDebug() << *it;
+ }
+}
+
+//! [9]
+
+//! [10]
+
+QHash<int, QString> mapping;
+mapping.insert(7, "Seven");
+mapping.insert(11, "Eleven");
+mapping.insert(42, "Forty-two");
+
+QVariant variant = QVariant::fromValue(mapping);
+if (variant.canConvert<QVariantHash>()) {
+ QAssociativeIterable iterable = variant.value<QAssociativeIterable>();
+ // Can use foreach over the values:
+ foreach (const QVariant &v, iterable) {
+ qDebug() << v;
+ }
+ // Can use C++11 range-for over the values:
+ for (const QVariant &v : iterable) {
+ qDebug() << v;
+ }
+ // Can use iterators:
+ QAssociativeIterable::const_iterator it = iterable.begin();
+ const QAssociativeIterable::const_iterator end = iterable.end();
+ for ( ; it != end; ++it) {
+ qDebug() << *it; // The current value
+ qDebug() << it.key();
+ qDebug() << it.value();
+ }
+}
+
+//! [10]
diff --git a/src/corelib/global/qcompilerdetection.h b/src/corelib/global/qcompilerdetection.h
index b685c1fe0d..27fc2d4038 100644
--- a/src/corelib/global/qcompilerdetection.h
+++ b/src/corelib/global/qcompilerdetection.h
@@ -881,4 +881,26 @@
Q_UNUSED(valueOfExpression); /* the value may not be used if Q_ASSERT_X and Q_ASSUME_IMPL are noop */\
} while (0)
+
+/*
+ Sanitize compiler feature availability
+*/
+#if !defined(Q_PROCESSOR_X86)
+# undef QT_COMPILER_SUPPORTS_SSE2
+# undef QT_COMPILER_SUPPORTS_SSE3
+# undef QT_COMPILER_SUPPORTS_SSSE3
+# undef QT_COMPILER_SUPPORTS_SSE4_1
+# undef QT_COMPILER_SUPPORTS_SSE4_2
+# undef QT_COMPILER_SUPPORTS_AVX
+# undef QT_COMPILER_SUPPORTS_AVX2
+#endif
+#if !defined(Q_PROCESSOR_ARM)
+# undef QT_COMPILER_SUPPORTS_IWMMXT
+# undef QT_COMPILER_SUPPORTS_NEON
+#endif
+#if !defined(Q_PROCESSOR_MIPS)
+# undef QT_COMPILER_SUPPORTS_MIPS_DSP
+# undef QT_COMPILER_SUPPORTS_MIPS_DSPR2
+#endif
+
#endif // QCOMPILERDETECTION_H
diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp
index bcd0d06777..ac347655bc 100644
--- a/src/corelib/global/qglobal.cpp
+++ b/src/corelib/global/qglobal.cpp
@@ -934,7 +934,7 @@ bool qSharedBuild() Q_DECL_NOTHROW
\endlist
Some constants are defined only on certain platforms. You can use
- the preprocessor symbols Q_OS_WIN and Q_OS_MACX to test that
+ the preprocessor symbols Q_OS_WIN and Q_OS_OSX to test that
the application is compiled under Windows or OS X.
\sa QLibraryInfo
@@ -1077,18 +1077,20 @@ bool qSharedBuild() Q_DECL_NOTHROW
\macro Q_OS_DARWIN
\relates <QtGlobal>
- Defined on Darwin OS (synonym for Q_OS_MAC).
+ Defined on Darwin-based operating systems such as OS X and iOS,
+ including any open source version(s) of Darwin.
*/
/*!
\macro Q_OS_MAC
\relates <QtGlobal>
- Defined on OS X and iOS (synonym for Q_OS_DARWIN).
+ Defined on Darwin-based operating systems distributed by Apple, which
+ currently includes OS X and iOS, but not the open source version.
*/
/*!
- \macro Q_OS_MACX
+ \macro Q_OS_OSX
\relates <QtGlobal>
Defined on OS X.
diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h
index 4e63e5d0ba..f9629ff430 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.1.1"
+#define QT_VERSION_STR "5.2.0"
/*
QT_VERSION is (major << 16) + (minor << 8) + patch.
*/
-#define QT_VERSION 0x050101
+#define QT_VERSION 0x050200
/*
can be used like #if (QT_VERSION >= QT_VERSION_CHECK(4, 4, 0))
*/
@@ -68,12 +68,15 @@
#define QT_STRINGIFY(x) QT_STRINGIFY2(x)
#include <QtCore/qsystemdetection.h>
-#include <QtCore/qcompilerdetection.h>
#include <QtCore/qprocessordetection.h>
+#include <QtCore/qcompilerdetection.h>
#if defined (__ELF__)
# define Q_OF_ELF
#endif
+#if defined (__MACH__) && defined (__APPLE__)
+# define Q_OF_MACH_O
+#endif
#ifdef __cplusplus
diff --git a/src/corelib/global/qlibraryinfo.cpp b/src/corelib/global/qlibraryinfo.cpp
index 53a3ebbc10..18f293bba5 100644
--- a/src/corelib/global/qlibraryinfo.cpp
+++ b/src/corelib/global/qlibraryinfo.cpp
@@ -78,6 +78,7 @@ struct QLibrarySettings
QLibrarySettings();
QScopedPointer<QSettings> settings;
#ifdef QT_BOOTSTRAPPED
+ bool haveEffectiveSourcePaths;
bool haveEffectivePaths;
bool havePaths;
#endif
@@ -99,8 +100,10 @@ public:
static bool haveGroup(QLibraryInfo::PathGroup group)
{
QLibrarySettings *ls = qt_library_settings();
- return ls ? (group == QLibraryInfo::EffectivePaths
- ? ls->haveEffectivePaths : ls->havePaths) : false;
+ return ls ? (group == QLibraryInfo::EffectiveSourcePaths
+ ? ls->haveEffectiveSourcePaths
+ : group == QLibraryInfo::EffectivePaths
+ ? ls->haveEffectivePaths : ls->havePaths) : false;
}
#endif
static QSettings *configuration()
@@ -122,7 +125,12 @@ QLibrarySettings::QLibrarySettings()
// This code needs to be in the regular library, as otherwise a qt.conf that
// works for qmake would break things for dynamically built Qt tools.
QStringList children = settings->childGroups();
+#ifdef QT_BOOTSTRAPPED
+ haveEffectiveSourcePaths = children.contains(QLatin1String("EffectiveSourcePaths"));
+ haveEffectivePaths = haveEffectiveSourcePaths || children.contains(QLatin1String("EffectivePaths"));
+#else
haveEffectivePaths = children.contains(QLatin1String("EffectivePaths"));
+#endif
// Backwards compat: an existing but empty file is claimed to contain the Paths section.
havePaths = !haveEffectivePaths || children.contains(QLatin1String("Paths"));
#ifndef QT_BOOTSTRAPPED
@@ -130,6 +138,9 @@ QLibrarySettings::QLibrarySettings()
settings.reset(0);
#else
} else {
+#ifdef QT_BOOTSTRAPPED
+ haveEffectiveSourcePaths = false;
+#endif
haveEffectivePaths = false;
havePaths = false;
#endif
@@ -334,9 +345,12 @@ QLibraryInfo::rawLocation(LibraryLocation loc, PathGroup group)
// and qt.conf with that section is present, use it, otherwise fall back to
// FinalPaths. For FinalPaths, use qt.conf if present and contains not only
// [EffectivePaths], otherwise fall back to builtins.
+ // EffectiveSourcePaths falls back to EffectivePaths.
if (!QLibraryInfoPrivate::haveGroup(group)
- && (group == FinalPaths
- || !(group = FinalPaths, QLibraryInfoPrivate::haveGroup(FinalPaths))))
+ && !(group == EffectiveSourcePaths
+ && (group = EffectivePaths, QLibraryInfoPrivate::haveGroup(group)))
+ && !(group == EffectivePaths
+ && (group = FinalPaths, QLibraryInfoPrivate::haveGroup(group))))
#elif !defined(QT_NO_SETTINGS)
if (!QLibraryInfoPrivate::configuration())
#endif
@@ -368,6 +382,7 @@ QLibraryInfo::rawLocation(LibraryLocation loc, PathGroup group)
QSettings *config = QLibraryInfoPrivate::configuration();
config->beginGroup(QLatin1String(
#ifdef QT_BOOTSTRAPPED
+ group == EffectiveSourcePaths ? "EffectiveSourcePaths" :
group == EffectivePaths ? "EffectivePaths" :
#endif
"Paths"));
diff --git a/src/corelib/global/qlibraryinfo.h b/src/corelib/global/qlibraryinfo.h
index b275e018a0..17864b555b 100644
--- a/src/corelib/global/qlibraryinfo.h
+++ b/src/corelib/global/qlibraryinfo.h
@@ -92,7 +92,7 @@ public:
};
static QString location(LibraryLocation); // ### Qt 6: consider renaming it to path()
#ifdef QT_BOOTSTRAPPED
- enum PathGroup { FinalPaths, EffectivePaths };
+ enum PathGroup { FinalPaths, EffectivePaths, EffectiveSourcePaths };
static QString rawLocation(LibraryLocation, PathGroup);
#endif
diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h
index 25c47d5d34..6f1a089670 100644
--- a/src/corelib/global/qnamespace.h
+++ b/src/corelib/global/qnamespace.h
@@ -982,6 +982,14 @@ public:
Key_MicMute = 0x01000113,
+ Key_Red = 0x01000114,
+ Key_Green = 0x01000115,
+ Key_Yellow = 0x01000116,
+ Key_Blue = 0x01000117,
+
+ Key_ChannelUp = 0x01000118,
+ Key_ChannelDown = 0x01000119,
+
Key_MediaLast = 0x0100ffff,
// Keypad navigation keys
diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc
index f9248eb68d..5cd1812b54 100644
--- a/src/corelib/global/qnamespace.qdoc
+++ b/src/corelib/global/qnamespace.qdoc
@@ -1622,6 +1622,12 @@
\value Key_TouchpadOn
\value Key_TouchpadOff
\value Key_MicMute
+ \value Key_Red
+ \value Key_Green
+ \value Key_Yellow
+ \value Key_Blue
+ \value Key_ChannelUp
+ \value Key_ChannelDown
\value Key_MediaLast
\value Key_unknown
diff --git a/src/corelib/global/qsystemdetection.h b/src/corelib/global/qsystemdetection.h
index cb55fa808b..5e68226b60 100644
--- a/src/corelib/global/qsystemdetection.h
+++ b/src/corelib/global/qsystemdetection.h
@@ -49,9 +49,9 @@
/*
The operating system, must be one of: (Q_OS_x)
- DARWIN - Darwin OS (synonym for Q_OS_MAC)
- MAC - OS X or iOS (synonym for Q_OS_DARWIN)
- MACX - OS X
+ DARWIN - Any Darwin system
+ MAC - OS X and iOS
+ OSX - OS X
IOS - iOS
MSDOS - MS-DOS and Windows
OS2 - OS/2
@@ -175,8 +175,9 @@
# include <TargetConditionals.h>
# if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
# define Q_OS_IOS
-# else
-# define Q_OS_MACX
+# elif defined(TARGET_OS_MAC) && TARGET_OS_MAC
+# define Q_OS_OSX
+# define Q_OS_MACX // compatibility synonym
# endif
#endif
diff --git a/src/corelib/io/qdatastream.cpp b/src/corelib/io/qdatastream.cpp
index b6926bc544..52b80badb8 100644
--- a/src/corelib/io/qdatastream.cpp
+++ b/src/corelib/io/qdatastream.cpp
@@ -251,7 +251,7 @@ QT_BEGIN_NAMESPACE
return retVal;
enum {
- DefaultStreamVersion = QDataStream::Qt_5_1
+ DefaultStreamVersion = QDataStream::Qt_5_2
};
/*!
@@ -539,7 +539,8 @@ void QDataStream::setByteOrder(ByteOrder bo)
\value Qt_4_8 Same as Qt_4_6.
\value Qt_4_9 Same as Qt_4_6.
\value Qt_5_0 Version 13 (Qt 5.0)
- \value Qt_5_1 Version 14 (Qt 5.1)
+ \value Qt_5_1 Version 14 (Qt 5.1, Qt 5.2)
+ \value Qt_5_2 Same as Qt_5_1.
\sa setVersion(), version()
*/
diff --git a/src/corelib/io/qdatastream.h b/src/corelib/io/qdatastream.h
index 969cdf4517..eb064b3fe2 100644
--- a/src/corelib/io/qdatastream.h
+++ b/src/corelib/io/qdatastream.h
@@ -86,8 +86,9 @@ public:
Qt_4_8 = Qt_4_7,
Qt_4_9 = Qt_4_8,
Qt_5_0 = 13,
- Qt_5_1 = 14
-#if QT_VERSION >= 0x050200
+ Qt_5_1 = 14,
+ Qt_5_2 = Qt_5_1
+#if QT_VERSION >= 0x050300
#error Add the datastream version for this Qt version
#endif
};
diff --git a/src/corelib/io/qdir.cpp b/src/corelib/io/qdir.cpp
index 9ca512e84f..9b3ea2fe2c 100644
--- a/src/corelib/io/qdir.cpp
+++ b/src/corelib/io/qdir.cpp
@@ -2005,25 +2005,14 @@ bool QDir::match(const QString &filter, const QString &fileName)
#endif // QT_NO_REGEXP
/*!
- Returns \a path with directory separators normalized (converted to "/") and
- redundant ones removed, and "."s and ".."s resolved (as far as possible).
-
- Symbolic links are kept. This function does not return the
- canonical path, but rather the simplest version of the input.
- For example, "./local" becomes "local", "local/../bin" becomes
- "bin" and "/local/usr/../bin" becomes "/local/bin".
+ Returns \a path with redundant directory separators removed,
+ and "."s and ".."s resolved (as far as possible).
- \sa absolutePath(), canonicalPath()
+ This method is shared with QUrl, so it doesn't deal with QDir::separator(),
+ nor does it remove the trailing slash, if any.
*/
-QString QDir::cleanPath(const QString &path)
+QString qt_normalizePathSegments(const QString &name, bool allowUncPaths)
{
- if (path.isEmpty())
- return path;
- QString name = path;
- QChar dir_separator = separator();
- if (dir_separator != QLatin1Char('/'))
- name.replace(dir_separator, QLatin1Char('/'));
-
int used = 0, levels = 0;
const int len = name.length();
QVarLengthArray<QChar> outVector(len);
@@ -2033,10 +2022,8 @@ QString QDir::cleanPath(const QString &path)
for (int i = 0, last = -1, iwrite = 0; i < len; ++i) {
if (p[i] == QLatin1Char('/')) {
while (i+1 < len && p[i+1] == QLatin1Char('/')) {
-#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) //allow unc paths
- if (!i)
+ if (allowUncPaths && i == 0)
break;
-#endif
i++;
}
bool eaten = false;
@@ -2099,8 +2086,6 @@ QString QDir::cleanPath(const QString &path)
eaten = true;
#endif
last = -1;
- } else if (last != -1 && i == len-1) {
- eaten = true;
} else {
levels++;
}
@@ -2126,6 +2111,36 @@ QString QDir::cleanPath(const QString &path)
}
QString ret = (used == len ? name : QString(out, used));
+ return ret;
+}
+
+/*!
+ Returns \a path with directory separators normalized (converted to "/") and
+ redundant ones removed, and "."s and ".."s resolved (as far as possible).
+
+ Symbolic links are kept. This function does not return the
+ canonical path, but rather the simplest version of the input.
+ For example, "./local" becomes "local", "local/../bin" becomes
+ "bin" and "/local/usr/../bin" becomes "/local/bin".
+
+ \sa absolutePath(), canonicalPath()
+*/
+QString QDir::cleanPath(const QString &path)
+{
+ if (path.isEmpty())
+ return path;
+ QString name = path;
+ QChar dir_separator = separator();
+ if (dir_separator != QLatin1Char('/'))
+ name.replace(dir_separator, QLatin1Char('/'));
+
+ bool allowUncPaths = false;
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) //allow unc paths
+ allowUncPaths = true;
+#endif
+
+ QString ret = qt_normalizePathSegments(name, allowUncPaths);
+
// Strip away last slash except for root directories
if (ret.length() > 1 && ret.endsWith(QLatin1Char('/'))) {
#if defined (Q_OS_WIN)
diff --git a/src/corelib/io/qipaddress.cpp b/src/corelib/io/qipaddress.cpp
index bd36d36ac1..334c239c91 100644
--- a/src/corelib/io/qipaddress.cpp
+++ b/src/corelib/io/qipaddress.cpp
@@ -53,7 +53,7 @@ static QString number(quint8 val, int base = 10)
}
typedef QVarLengthArray<char, 64> Buffer;
-static bool checkedToAscii(Buffer &buffer, const QChar *begin, const QChar *end)
+static const QChar *checkedToAscii(Buffer &buffer, const QChar *begin, const QChar *end)
{
const ushort *const ubegin = reinterpret_cast<const ushort *>(begin);
const ushort *const uend = reinterpret_cast<const ushort *>(end);
@@ -64,11 +64,11 @@ static bool checkedToAscii(Buffer &buffer, const QChar *begin, const QChar *end)
while (src != uend) {
if (*src >= 0x7f)
- return false;
+ return reinterpret_cast<const QChar *>(src);
*dst++ = *src++;
}
*dst = '\0';
- return true;
+ return 0;
}
static bool parseIp4Internal(IPv4Address &address, const char *ptr, bool acceptLeadingZero);
@@ -76,7 +76,7 @@ bool parseIp4(IPv4Address &address, const QChar *begin, const QChar *end)
{
Q_ASSERT(begin != end);
Buffer buffer;
- if (!checkedToAscii(buffer, begin, end))
+ if (checkedToAscii(buffer, begin, end))
return false;
const char *ptr = buffer.data();
@@ -137,12 +137,23 @@ void toString(QString &appendTo, IPv4Address address)
% number(address);
}
-bool parseIp6(IPv6Address &address, const QChar *begin, const QChar *end)
+/*!
+ \internal
+ \since 5.0
+
+ Parses one IPv6 address from \a begin to \a end and stores the
+ representation in \a address. Returns null if everything was parsed
+ correctly, or the pointer to the first bad character where parsing failed.
+ If the parsing failed for a reason not related to a particular character,
+ returns \a end.
+*/
+const QChar *parseIp6(IPv6Address &address, const QChar *begin, const QChar *end)
{
Q_ASSERT(begin != end);
Buffer buffer;
- if (!checkedToAscii(buffer, begin, end))
- return false;
+ const QChar *ret = checkedToAscii(buffer, begin, end);
+ if (ret)
+ return ret;
const char *ptr = buffer.data();
@@ -158,11 +169,11 @@ bool parseIp6(IPv6Address &address, const QChar *begin, const QChar *end)
}
// IPv4-in-IPv6 addresses are stricter in what they accept
if (dotCount != 0 && dotCount != 3)
- return false;
+ return end;
memset(address, 0, sizeof address);
if (colonCount == 2 && end - begin == 2) // "::"
- return true;
+ return 0;
// if there's a double colon ("::"), this is how many zeroes it means
int zeroWordsToFill;
@@ -174,7 +185,7 @@ bool parseIp6(IPv6Address &address, const QChar *begin, const QChar *end)
(ptr[end - begin - 2] == ':' && ptr[end - begin - 1] == ':')) {
zeroWordsToFill = 9 - colonCount;
} else if (colonCount < 2 || colonCount > 7) {
- return false;
+ return end;
} else {
zeroWordsToFill = 8 - colonCount;
}
@@ -183,18 +194,13 @@ bool parseIp6(IPv6Address &address, const QChar *begin, const QChar *end)
int pos = 0;
while (pos < 15) {
- const char *endptr;
- bool ok;
- quint64 ll = qstrtoull(ptr, &endptr, 16, &ok);
- quint16 x = ll;
-
- if (ptr == endptr) {
+ if (*ptr == ':') {
// empty field, we hope it's "::"
if (zeroWordsToFill < 1)
- return false;
+ return begin + (ptr - buffer.data());
if (pos == 0 || pos == colonCount * 2) {
if (ptr[0] == '\0' || ptr[1] != ':')
- return false;
+ return begin + (ptr - buffer.data());
++ptr;
}
pos += zeroWordsToFill * 2;
@@ -202,24 +208,30 @@ bool parseIp6(IPv6Address &address, const QChar *begin, const QChar *end)
++ptr;
continue;
}
+
+ const char *endptr;
+ bool ok;
+ quint64 ll = qstrtoull(ptr, &endptr, 16, &ok);
+ quint16 x = ll;
+
if (!ok || ll != x)
- return false;
+ return begin + (ptr - buffer.data());
if (*endptr == '.') {
// this could be an IPv4 address
// it's only valid in the last element
if (pos != 12)
- return false;
+ return begin + (ptr - buffer.data());
IPv4Address ip4;
if (!parseIp4Internal(ip4, ptr, false))
- return false;
+ return begin + (ptr - buffer.data());
address[12] = ip4 >> 24;
address[13] = ip4 >> 16;
address[14] = ip4 >> 8;
address[15] = ip4;
- return true;
+ return 0;
}
address[pos++] = x >> 8;
@@ -228,10 +240,10 @@ bool parseIp6(IPv6Address &address, const QChar *begin, const QChar *end)
if (*endptr == '\0')
break;
if (*endptr != ':')
- return false;
+ return begin + (endptr - buffer.data());
ptr = endptr + 1;
}
- return pos == 16;
+ return pos == 16 ? 0 : end;
}
static inline QChar toHex(uchar c)
diff --git a/src/corelib/io/qipaddress_p.h b/src/corelib/io/qipaddress_p.h
index d5c158d4d1..3059a1c205 100644
--- a/src/corelib/io/qipaddress_p.h
+++ b/src/corelib/io/qipaddress_p.h
@@ -63,7 +63,7 @@ typedef quint32 IPv4Address;
typedef quint8 IPv6Address[16];
Q_CORE_EXPORT bool parseIp4(IPv4Address &address, const QChar *begin, const QChar *end);
-Q_CORE_EXPORT bool parseIp6(IPv6Address &address, const QChar *begin, const QChar *end);
+Q_CORE_EXPORT const QChar *parseIp6(IPv6Address &address, const QChar *begin, const QChar *end);
Q_CORE_EXPORT void toString(QString &appendTo, IPv4Address address);
Q_CORE_EXPORT void toString(QString &appendTo, IPv6Address address);
diff --git a/src/corelib/io/qurl.cpp b/src/corelib/io/qurl.cpp
index f2e1f9bbc7..f8a8bd18e3 100644
--- a/src/corelib/io/qurl.cpp
+++ b/src/corelib/io/qurl.cpp
@@ -225,9 +225,14 @@
\value RemoveQuery The query part of the URL (following a '?' character)
is removed.
\value RemoveFragment
+ \value RemoveFilename The filename (i.e. everything after the last '/' in the path) is removed.
+ The trailing '/' is kept, unless StripTrailingSlash is set.
+ Only valid if RemovePath is not set.
\value PreferLocalFile If the URL is a local file according to isLocalFile()
and contains no query or fragment, a local file path is returned.
\value StripTrailingSlash The trailing slash is removed if one is present.
+ \value NormalizePathSegments Modifies the path to remove redundant directory separators,
+ and to resolve "."s and ".."s (as far as possible).
Note that the case folding rules in \l{RFC 3491}{Nameprep}, which QUrl
conforms to, require host names to always be converted to lower case,
@@ -321,6 +326,7 @@
#endif
QT_BEGIN_NAMESPACE
+extern QString qt_normalizePathSegments(const QString &name, bool allowUncPaths); // qdir.cpp
inline static bool isHex(char c)
{
@@ -368,6 +374,7 @@ public:
InvalidRegNameError = Host << 8,
InvalidIPv4AddressError,
InvalidIPv6AddressError,
+ InvalidCharacterInIPv6Error,
InvalidIPvFutureError,
HostMissingEndBracket,
@@ -418,7 +425,7 @@ public:
void appendHost(QString &appendTo, QUrl::FormattingOptions options) const;
void appendPath(QString &appendTo, QUrl::FormattingOptions options, Section appendingTo) const;
void appendQuery(QString &appendTo, QUrl::FormattingOptions options, Section appendingTo) const;
- void appendFragment(QString &appendTo, QUrl::FormattingOptions options) const;
+ void appendFragment(QString &appendTo, QUrl::FormattingOptions options, Section appendingTo) const;
// the "end" parameters are like STL iterators: they point to one past the last valid element
bool setScheme(const QString &value, int len, bool doSetError);
@@ -799,16 +806,32 @@ inline void QUrlPrivate::appendPassword(QString &appendTo, QUrl::FormattingOptio
inline void QUrlPrivate::appendPath(QString &appendTo, QUrl::FormattingOptions options, Section appendingTo) const
{
+ QString thePath = path;
+ if (options & QUrl::NormalizePathSegments) {
+ thePath = qt_normalizePathSegments(path, false);
+ }
+ if (options & QUrl::RemoveFilename) {
+ const int slash = path.lastIndexOf(QLatin1Char('/'));
+ if (slash == -1)
+ return;
+ thePath = path.left(slash+1);
+ }
+ // check if we need to remove trailing slashes
+ if (options & QUrl::StripTrailingSlash) {
+ while (thePath.length() > 1 && thePath.endsWith(QLatin1Char('/')))
+ thePath.chop(1);
+ }
+
if (appendingTo != Path && !(options & QUrl::EncodeDelimiters)) {
- if (!qt_urlRecode(appendTo, path.constData(), path.constEnd(), options, decodedPathInUrlActions))
- appendTo += path;
+ if (!qt_urlRecode(appendTo, thePath.constData(), thePath.constEnd(), options, decodedPathInUrlActions))
+ appendTo += thePath;
} else {
- appendToUser(appendTo, path, options, encodedPathActions, decodedPathInIsolationActions);
+ appendToUser(appendTo, thePath, options, encodedPathActions, decodedPathInIsolationActions);
}
}
-inline void QUrlPrivate::appendFragment(QString &appendTo, QUrl::FormattingOptions options) const
+inline void QUrlPrivate::appendFragment(QString &appendTo, QUrl::FormattingOptions options, Section appendingTo) const
{
appendToUser(appendTo, fragment, options, encodedFragmentActions, decodedFragmentInIsolationActions);
}
@@ -1059,7 +1082,7 @@ inline void QUrlPrivate::appendHost(QString &appendTo, QUrl::FormattingOptions o
// this is either an IPv4Address or a reg-name
// if it is a reg-name, it is already stored in Unicode form
if (options == QUrl::EncodeUnicode)
- appendTo += qt_ACE_do(host, ToAceOnly);
+ appendTo += qt_ACE_do(host, ToAceOnly, AllowLeadingDot);
else
appendTo += host;
}
@@ -1067,7 +1090,7 @@ inline void QUrlPrivate::appendHost(QString &appendTo, QUrl::FormattingOptions o
// the whole IPvFuture is passed and parsed here, including brackets;
// returns null if the parsing was successful, or the QChar of the first failure
-static const QChar *parseIpFuture(QString &host, const QChar *begin, const QChar *end)
+static const QChar *parseIpFuture(QString &host, const QChar *begin, const QChar *end, QUrl::ParsingMode mode)
{
// IPvFuture = "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" )
static const char acceptable[] =
@@ -1076,19 +1099,25 @@ static const QChar *parseIpFuture(QString &host, const QChar *begin, const QChar
"-._~"; // unreserved
// the brackets and the "v" have been checked
+ const QChar *const origBegin = begin;
if (begin[3].unicode() != '.')
return &begin[3];
- if ((begin[2].unicode() >= 'A' && begin[2].unicode() >= 'F') ||
+ if ((begin[2].unicode() >= 'A' && begin[2].unicode() <= 'F') ||
(begin[2].unicode() >= 'a' && begin[2].unicode() <= 'f') ||
(begin[2].unicode() >= '0' && begin[2].unicode() <= '9')) {
// this is so unlikely that we'll just go down the slow path
// decode the whole string, skipping the "[vH." and "]" which we already know to be there
host += QString::fromRawData(begin, 4);
+
+ // uppercase the version, if necessary
+ if (begin[2].unicode() >= 'a')
+ host[host.length() - 2] = begin[2].unicode() - 0x20;
+
begin += 4;
--end;
QString decoded;
- if (qt_urlRecode(decoded, begin, end, QUrl::FullyEncoded, 0)) {
+ if (mode == QUrl::TolerantMode && qt_urlRecode(decoded, begin, end, QUrl::FullyDecoded, 0)) {
begin = decoded.constBegin();
end = decoded.constEnd();
}
@@ -1103,37 +1132,44 @@ static const QChar *parseIpFuture(QString &host, const QChar *begin, const QChar
else if (begin->unicode() < 0x80 && strchr(acceptable, begin->unicode()) != 0)
host += *begin;
else
- return begin;
+ return decoded.isEmpty() ? begin : &origBegin[2];
}
host += QLatin1Char(']');
return 0;
}
- return &begin[2];
+ return &origBegin[2];
}
// ONLY the IPv6 address is parsed here, WITHOUT the brackets
-static bool parseIp6(QString &host, const QChar *begin, const QChar *end)
+static const QChar *parseIp6(QString &host, const QChar *begin, const QChar *end, QUrl::ParsingMode mode)
{
QIPAddressUtils::IPv6Address address;
- if (!QIPAddressUtils::parseIp6(address, begin, end)) {
+ const QChar *ret = QIPAddressUtils::parseIp6(address, begin, end);
+ if (ret) {
+ // this struct is kept in automatic storage because it's only 4 bytes
+ const ushort decodeColon[] = { decode(':'), 0 };
+
// IPv6 failed parsing, check if it was a percent-encoded character in
// the middle and try again
QString decoded;
- if (!qt_urlRecode(decoded, begin, end, QUrl::FullyEncoded, 0)) {
- // no transformation, nothing to re-parse
- return false;
+ if (mode == QUrl::TolerantMode && qt_urlRecode(decoded, begin, end, 0, decodeColon)) {
+ // recurse
+ // if the parsing fails again, the qt_urlRecode above will return 0
+ ret = parseIp6(host, decoded.constBegin(), decoded.constEnd(), mode);
+
+ // we can't return ret, otherwise it would be dangling
+ return ret ? end : 0;
}
- // recurse
- // if the parsing fails again, the qt_urlRecode above will return 0
- return parseIp6(host, decoded.constBegin(), decoded.constEnd());
+ // no transformation, nothing to re-parse
+ return ret;
}
host.reserve(host.size() + (end - begin));
host += QLatin1Char('[');
QIPAddressUtils::toString(host, address);
host += QLatin1Char(']');
- return true;
+ return 0;
}
inline bool QUrlPrivate::setHost(const QString &value, int from, int iend, QUrl::ParsingMode mode)
@@ -1157,17 +1193,22 @@ inline bool QUrlPrivate::setHost(const QString &value, int from, int iend, QUrl:
}
if (len > 5 && begin[1].unicode() == 'v') {
- const QChar *c = parseIpFuture(host, begin, end);
+ const QChar *c = parseIpFuture(host, begin, end, mode);
if (c)
setError(InvalidIPvFutureError, value, c - value.constData());
return !c;
+ } else if (begin[1].unicode() == 'v') {
+ setError(InvalidIPvFutureError, value, from);
}
- if (parseIp6(host, begin + 1, end - 1))
+ const QChar *c = parseIp6(host, begin + 1, end - 1, mode);
+ if (!c)
return true;
- setError(begin[1].unicode() == 'v' ? InvalidIPvFutureError : InvalidIPv6AddressError,
- value, from);
+ if (c == end - 1)
+ setError(InvalidIPv6AddressError, value, from);
+ else
+ setError(InvalidCharacterInIPv6Error, value, c - value.constData());
return false;
}
@@ -1194,7 +1235,7 @@ inline bool QUrlPrivate::setHost(const QString &value, int from, int iend, QUrl:
// check for percent-encoding first
QString s;
- if (mode == QUrl::TolerantMode && qt_urlRecode(s, begin, end, QUrl::DecodeReserved, 0)) {
+ if (mode == QUrl::TolerantMode && qt_urlRecode(s, begin, end, 0, 0)) {
// something was decoded
// anything encoded left?
int pos = s.indexOf(QChar(0x25)); // '%'
@@ -1207,7 +1248,7 @@ inline bool QUrlPrivate::setHost(const QString &value, int from, int iend, QUrl:
return setHost(s, 0, s.length(), QUrl::StrictMode);
}
- s = qt_ACE_do(QString::fromRawData(begin, len), NormalizeAce);
+ s = qt_ACE_do(QString::fromRawData(begin, len), NormalizeAce, ForbidLeadingDot);
if (s.isEmpty()) {
setError(InvalidRegNameError, value);
return false;
@@ -1583,87 +1624,6 @@ inline void QUrlPrivate::validate() const
}
}
}
-
-inline const QByteArray &QUrlPrivate::normalized() const
-{
- if (QURL_HASFLAG(stateFlags, QUrlPrivate::Normalized))
- return encodedNormalized;
-
- QUrlPrivate *that = const_cast<QUrlPrivate *>(this);
- QURL_SETFLAG(that->stateFlags, QUrlPrivate::Normalized);
-
- QUrlPrivate tmp = *this;
- tmp.scheme = tmp.scheme.toLower();
- tmp.host = tmp.canonicalHost();
-
- // ensure the encoded and normalized parts of the URL
- tmp.ensureEncodedParts();
- if (tmp.encodedUserName.contains('%'))
- q_normalizePercentEncoding(&tmp.encodedUserName, userNameExcludeChars);
- if (tmp.encodedPassword.contains('%'))
- q_normalizePercentEncoding(&tmp.encodedPassword, passwordExcludeChars);
- if (tmp.encodedFragment.contains('%'))
- q_normalizePercentEncoding(&tmp.encodedFragment, fragmentExcludeChars);
-
- if (tmp.encodedPath.contains('%')) {
- // the path is a bit special:
- // the slashes shouldn't be encoded or decoded.
- // They should remain exactly like they are right now
- //
- // treat the path as a slash-separated sequence of pchar
- QByteArray result;
- result.reserve(tmp.encodedPath.length());
- if (tmp.encodedPath.startsWith('/'))
- result.append('/');
-
- const char *data = tmp.encodedPath.constData();
- int lastSlash = 0;
- int nextSlash;
- do {
- ++lastSlash;
- nextSlash = tmp.encodedPath.indexOf('/', lastSlash);
- int len;
- if (nextSlash == -1)
- len = tmp.encodedPath.length() - lastSlash;
- else
- len = nextSlash - lastSlash;
-
- if (memchr(data + lastSlash, '%', len)) {
- // there's at least one percent before the next slash
- QByteArray block = QByteArray(data + lastSlash, len);
- q_normalizePercentEncoding(&block, pathExcludeChars);
- result.append(block);
- } else {
- // no percents in this path segment, append wholesale
- result.append(data + lastSlash, len);
- }
-
- // append the slash too, if it's there
- if (nextSlash != -1)
- result.append('/');
-
- lastSlash = nextSlash;
- } while (lastSlash != -1);
-
- tmp.encodedPath = result;
- }
-
- if (!tmp.scheme.isEmpty()) // relative test
- removeDotsFromPath(&tmp.encodedPath);
-
- int qLen = tmp.query.length();
- for (int i = 0; i < qLen; i++) {
- if (qLen - i > 2 && tmp.query.at(i) == '%') {
- ++i;
- tmp.query[i] = qToLower(tmp.query.at(i));
- ++i;
- tmp.query[i] = qToLower(tmp.query.at(i));
- }
- }
- encodedNormalized = tmp.toEncoded();
-
- return encodedNormalized;
-}
#endif
/*!
@@ -2458,6 +2418,36 @@ QString QUrl::path(ComponentFormattingOptions options) const
*/
/*!
+ \since 5.2
+
+ Returns the name of the file, excluding the directory path.
+
+ Note that, if this QUrl object is given a path ending in a slash, the name of the file is considered empty.
+
+ If the path doesn't contain any slash, it is fully returned as the fileName.
+
+ Example:
+
+ \snippet code/src_corelib_io_qurl.cpp 7
+
+ The \a options argument controls how to format the file name component. All
+ values produce an unambiguous result. With QUrl::FullyDecoded, all
+ percent-encoded sequences are decoded; otherwise, the returned value may
+ contain some percent-encoded sequences for some control sequences not
+ representable in decoded form in QString.
+
+ \sa path()
+*/
+QString QUrl::fileName(ComponentFormattingOptions options) const
+{
+ const QString ourPath = path(options);
+ const int slash = ourPath.lastIndexOf(QLatin1Char('/'));
+ if (slash == -1)
+ return ourPath;
+ return ourPath.mid(slash + 1);
+}
+
+/*!
\since 4.2
Returns true if this URL contains a Query (i.e., if ? was seen on it).
@@ -2903,7 +2893,7 @@ QString QUrl::fragment(ComponentFormattingOptions options) const
if (!d) return QString();
QString result;
- d->appendFragment(result, options);
+ d->appendFragment(result, options, QUrlPrivate::Fragment);
if (d->hasFragment() && result.isNull())
result.detach();
return result;
@@ -2976,7 +2966,7 @@ QString QUrl::topLevelDomain(ComponentFormattingOptions options) const
{
QString tld = qTopLevelDomain(host());
if (options & EncodeUnicode) {
- return qt_ACE_do(tld, ToAceOnly);
+ return qt_ACE_do(tld, ToAceOnly, AllowLeadingDot);
}
return tld;
}
@@ -3148,12 +3138,8 @@ QString QUrl::toString(FormattingOptions options) const
url += QLatin1String("//");
}
- if (!(options & QUrl::RemovePath)) {
+ if (!(options & QUrl::RemovePath))
d->appendPath(url, options, QUrlPrivate::FullUrl);
- // check if we need to remove trailing slashes
- if ((options & StripTrailingSlash) && !d->path.isEmpty() && d->path != QLatin1String("/") && url.endsWith(QLatin1Char('/')))
- url.chop(1);
- }
if (!(options & QUrl::RemoveQuery) && d->hasQuery()) {
url += QLatin1Char('?');
@@ -3161,7 +3147,7 @@ QString QUrl::toString(FormattingOptions options) const
}
if (!(options & QUrl::RemoveFragment) && d->hasFragment()) {
url += QLatin1Char('#');
- d->appendFragment(url, options);
+ d->appendFragment(url, options, QUrlPrivate::FullUrl);
}
return url;
@@ -3188,6 +3174,52 @@ QString QUrl::toDisplayString(FormattingOptions options) const
}
/*!
+ \since 5.2
+
+ Returns an adjusted version of the URL.
+ The output can be customized by passing flags with \a options.
+
+ The encoding options from QUrl::ComponentFormattingOption don't make
+ much sense for this method, nor does QUrl::PreferLocalFile.
+
+ This is always equivalent to QUrl(url.toString(options)).
+
+ \sa FormattingOptions, toEncoded(), toString()
+*/
+QUrl QUrl::adjusted(QUrl::FormattingOptions options) const
+{
+ if (!isValid()) {
+ // also catches isEmpty()
+ return QUrl();
+ }
+ QUrl that = *this;
+ if (options & RemoveScheme)
+ that.setScheme(QString());
+ if ((options & RemoveAuthority) == RemoveAuthority) {
+ that.setAuthority(QString());
+ } else {
+ if ((options & RemoveUserInfo) == RemoveUserInfo)
+ that.setUserInfo(QString());
+ else if (options & RemovePassword)
+ that.setPassword(QString());
+ if (options & RemovePort)
+ that.setPort(-1);
+ }
+ if (options & RemoveQuery)
+ that.setQuery(QString());
+ if (options & RemoveFragment)
+ that.setFragment(QString());
+ if (options & RemovePath) {
+ that.setPath(QString());
+ } else if (options & (StripTrailingSlash | RemoveFilename | NormalizePathSegments)) {
+ QString path;
+ d->appendPath(path, options, QUrlPrivate::Path);
+ that.setPath(path);
+ }
+ return that;
+}
+
+/*!
Returns the encoded representation of the URL if it's valid;
otherwise an empty QByteArray is returned. The output can be
customized by passing flags with \a options.
@@ -3296,7 +3328,7 @@ QString QUrl::fromEncodedComponent_helper(const QByteArray &ba)
*/
QString QUrl::fromAce(const QByteArray &domain)
{
- return qt_ACE_do(QString::fromLatin1(domain), NormalizeAce);
+ return qt_ACE_do(QString::fromLatin1(domain), NormalizeAce, ForbidLeadingDot /*FIXME: make configurable*/);
}
/*!
@@ -3317,7 +3349,7 @@ QString QUrl::fromAce(const QByteArray &domain)
*/
QByteArray QUrl::toAce(const QString &domain)
{
- QString result = qt_ACE_do(domain, ToAceOnly);
+ QString result = qt_ACE_do(domain, ToAceOnly, ForbidLeadingDot /*FIXME: make configurable*/);
return result.toLatin1();
}
@@ -3668,8 +3700,10 @@ static QString errorMessage(QUrlPrivate::ErrorCode errorCode, const QString &err
return QString(); // doesn't happen yet
case QUrlPrivate::InvalidIPv6AddressError:
return QStringLiteral("Invalid IPv6 address");
+ case QUrlPrivate::InvalidCharacterInIPv6Error:
+ return QStringLiteral("Invalid IPv6 address (character '%1' not permitted)").arg(c);
case QUrlPrivate::InvalidIPvFutureError:
- return QStringLiteral("Invalid IPvFuture address");
+ return QStringLiteral("Invalid IPvFuture address (character '%1' not permitted)").arg(c);
case QUrlPrivate::HostMissingEndBracket:
return QStringLiteral("Expected ']' to match '[' in hostname");
diff --git a/src/corelib/io/qurl.h b/src/corelib/io/qurl.h
index cf208bf71e..3018f6d0e4 100644
--- a/src/corelib/io/qurl.h
+++ b/src/corelib/io/qurl.h
@@ -140,7 +140,9 @@ public:
RemoveFragment = 0x80,
// 0x100 was a private code in Qt 4, keep unused for a while
PreferLocalFile = 0x200,
- StripTrailingSlash = 0x400
+ StripTrailingSlash = 0x400,
+ RemoveFilename = 0x800,
+ NormalizePathSegments = 0x1000
};
enum ComponentFormattingOption {
@@ -185,6 +187,7 @@ public:
QString url(FormattingOptions options = FormattingOptions(PrettyDecoded)) const;
QString toString(FormattingOptions options = FormattingOptions(PrettyDecoded)) const;
QString toDisplayString(FormattingOptions options = FormattingOptions(PrettyDecoded)) const;
+ QUrl adjusted(FormattingOptions options) const;
QByteArray toEncoded(FormattingOptions options = FullyEncoded) const;
static QUrl fromEncoded(const QByteArray &url, ParsingMode mode = TolerantMode);
@@ -221,6 +224,7 @@ public:
void setPath(const QString &path, ParsingMode mode = TolerantMode);
QString path(ComponentFormattingOptions options = PrettyDecoded) const;
+ QString fileName(ComponentFormattingOptions options = PrettyDecoded) const;
bool hasQuery() const;
void setQuery(const QString &query, ParsingMode mode = TolerantMode);
diff --git a/src/corelib/io/qurl_p.h b/src/corelib/io/qurl_p.h
index a0c1882162..9c8fe1cfc6 100644
--- a/src/corelib/io/qurl_p.h
+++ b/src/corelib/io/qurl_p.h
@@ -63,8 +63,9 @@ extern Q_AUTOTEST_EXPORT int qt_urlRecode(QString &appendTo, const QChar *begin,
QUrl::ComponentFormattingOptions encoding, const ushort *tableModifications = 0);
// in qurlidna.cpp
+enum AceLeadingDot { AllowLeadingDot, ForbidLeadingDot };
enum AceOperation { ToAceOnly, NormalizeAce };
-extern QString qt_ACE_do(const QString &domain, AceOperation op);
+extern QString qt_ACE_do(const QString &domain, AceOperation op, AceLeadingDot dot);
extern Q_AUTOTEST_EXPORT void qt_nameprep(QString *source, int from);
extern Q_AUTOTEST_EXPORT bool qt_check_std3rules(const QChar *uc, int len);
extern Q_AUTOTEST_EXPORT void qt_punycodeEncoder(const QChar *s, int ucLength, QString *output);
diff --git a/src/corelib/io/qurlidna.cpp b/src/corelib/io/qurlidna.cpp
index 70db9e09eb..e959faccd2 100644
--- a/src/corelib/io/qurlidna.cpp
+++ b/src/corelib/io/qurlidna.cpp
@@ -2461,7 +2461,7 @@ static int nextDotDelimiter(const QString &domain, int from = 0)
return ch - b;
}
-QString qt_ACE_do(const QString &domain, AceOperation op)
+QString qt_ACE_do(const QString &domain, AceOperation op, AceLeadingDot dot)
{
if (domain.isEmpty())
return domain;
@@ -2479,7 +2479,8 @@ QString qt_ACE_do(const QString &domain, AceOperation op)
if (labelLength == 0) {
if (idx == domain.length())
break;
- return QString(); // two delimiters in a row -- empty label not allowed
+ if (dot == ForbidLeadingDot || idx > 0)
+ return QString(); // two delimiters in a row -- empty label not allowed
}
// RFC 3490 says, about the ToASCII operation:
diff --git a/src/corelib/io/qurlrecode.cpp b/src/corelib/io/qurlrecode.cpp
index 5ff0c40a4f..509a92d2b0 100644
--- a/src/corelib/io/qurlrecode.cpp
+++ b/src/corelib/io/qurlrecode.cpp
@@ -573,6 +573,13 @@ static int decode(QString &appendTo, const ushort *begin, const ushort *end)
continue;
}
+ if (Q_UNLIKELY(end - input < 3 || !isHex(input[1]) || !isHex(input[2]))) {
+ // badly-encoded data
+ appendTo.resize(origSize + (end - begin));
+ memcpy(appendTo.begin() + origSize, begin, (end - begin) * sizeof(ushort));
+ return end - begin;
+ }
+
if (Q_UNLIKELY(!output)) {
// detach
appendTo.resize(origSize + (end - begin));
@@ -582,9 +589,6 @@ static int decode(QString &appendTo, const ushort *begin, const ushort *end)
}
++input;
- Q_ASSERT(input <= end - 2); // we need two characters
- Q_ASSERT(isHex(input[0]));
- Q_ASSERT(isHex(input[1]));
*output++ = decodeNibble(input[0]) << 4 | decodeNibble(input[1]);
input += 2;
}
@@ -635,6 +639,9 @@ static void maskTable(uchar (&table)[N], const uchar (&mask)[N])
handled. It consists of a sequence of 16-bit values, where the low 8 bits
indicate the character in question and the high 8 bits are either \c
EncodeCharacter, \c LeaveCharacter or \c DecodeCharacter.
+
+ This function corrects percent-encoded errors by interpreting every '%' as
+ meaning "%25" (all percents in the same content).
*/
Q_AUTOTEST_EXPORT int
diff --git a/src/corelib/itemmodels/qabstractitemmodel.h b/src/corelib/itemmodels/qabstractitemmodel.h
index f3bf2c1019..ac98476492 100644
--- a/src/corelib/itemmodels/qabstractitemmodel.h
+++ b/src/corelib/itemmodels/qabstractitemmodel.h
@@ -113,6 +113,11 @@ public:
inline bool operator!=(const QPersistentModelIndex &other) const
{ return !operator==(other); }
QPersistentModelIndex &operator=(const QPersistentModelIndex &other);
+#ifdef Q_COMPILER_RVALUE_REFS
+ inline QPersistentModelIndex(QPersistentModelIndex &&other) : d(other.d) { other.d = 0; }
+ inline QPersistentModelIndex &operator=(QPersistentModelIndex &&other)
+ { qSwap(d, other.d); return *this; }
+#endif
inline void swap(QPersistentModelIndex &other) { qSwap(d, other.d); }
bool operator==(const QModelIndex &other) const;
bool operator!=(const QModelIndex &other) const;
diff --git a/src/corelib/json/qjson_p.h b/src/corelib/json/qjson_p.h
index 06885ad972..7d0162938d 100644
--- a/src/corelib/json/qjson_p.h
+++ b/src/corelib/json/qjson_p.h
@@ -60,8 +60,10 @@
#include <qatomic.h>
#include <qstring.h>
#include <qendian.h>
+#include <qnumeric.h>
#include <limits.h>
+#include <limits>
QT_BEGIN_NAMESPACE
diff --git a/src/corelib/json/qjsonvalue.cpp b/src/corelib/json/qjsonvalue.cpp
index a540626579..d0b06c6924 100644
--- a/src/corelib/json/qjsonvalue.cpp
+++ b/src/corelib/json/qjsonvalue.cpp
@@ -156,6 +156,18 @@ QJsonValue::QJsonValue(int n)
}
/*!
+ \overload
+ Creates a value of type Double, with value \a n.
+ NOTE: the integer limits for IEEE 754 double precision data is 2^53 (-9007199254740992 to +9007199254740992).
+ If you pass in values outside this range expect a loss of precision to occur.
+ */
+QJsonValue::QJsonValue(qint64 n)
+ : d(0), t(Double)
+{
+ this->dbl = n;
+}
+
+/*!
Creates a value of type String, with value \a s.
*/
QJsonValue::QJsonValue(const QString &s)
diff --git a/src/corelib/json/qjsonvalue.h b/src/corelib/json/qjsonvalue.h
index b8bdf55aa3..c8efab5d5f 100644
--- a/src/corelib/json/qjsonvalue.h
+++ b/src/corelib/json/qjsonvalue.h
@@ -79,6 +79,7 @@ public:
QJsonValue(bool b);
QJsonValue(double n);
QJsonValue(int n);
+ QJsonValue(qint64 n);
QJsonValue(const QString &s);
QJsonValue(QLatin1String s);
QJsonValue(const QJsonArray &a);
diff --git a/src/corelib/json/qjsonwriter.cpp b/src/corelib/json/qjsonwriter.cpp
index 3ac16c6fd1..8426b351f6 100644
--- a/src/corelib/json/qjsonwriter.cpp
+++ b/src/corelib/json/qjsonwriter.cpp
@@ -169,9 +169,14 @@ static void valueToJson(const QJsonPrivate::Base *b, const QJsonPrivate::Value &
case QJsonValue::Bool:
json += v.toBoolean() ? "true" : "false";
break;
- case QJsonValue::Double:
- json += QByteArray::number(v.toDouble(b), 'g', 17);
+ case QJsonValue::Double: {
+ const double d = v.toDouble(b);
+ if (qIsFinite(d)) // +2 to format to ensure the expected precision
+ json += QByteArray::number(d, 'g', std::numeric_limits<double>::digits10 + 2); // ::digits10 is 15
+ else
+ json += "null"; // +INF || -INF || NaN (see RFC4627#section2.4)
break;
+ }
case QJsonValue::String:
json += '"';
json += escapedString(v.toString(b));
diff --git a/src/corelib/kernel/qcore_mac_p.h b/src/corelib/kernel/qcore_mac_p.h
index f0899c6dee..fa911fb967 100644
--- a/src/corelib/kernel/qcore_mac_p.h
+++ b/src/corelib/kernel/qcore_mac_p.h
@@ -75,6 +75,12 @@
#include "qstring.h"
+#if defined( __OBJC__) && defined(QT_NAMESPACE)
+#define QT_NAMESPACE_ALIAS_OBJC_CLASS(__KLASS__) @compatibility_alias __KLASS__ QT_MANGLE_NAMESPACE(__KLASS__)
+#else
+#define QT_NAMESPACE_ALIAS_OBJC_CLASS(__KLASS__)
+#endif
+
QT_BEGIN_NAMESPACE
/*
diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp
index efb1289a5c..4a46bb32f5 100644
--- a/src/corelib/kernel/qcoreapplication.cpp
+++ b/src/corelib/kernel/qcoreapplication.cpp
@@ -1950,7 +1950,6 @@ QString QCoreApplication::applicationFilePath()
char buff[maximum_path+1];
if (_cmdname(buff)) {
d->cachedApplicationFilePath = QDir::cleanPath(QString::fromLocal8Bit(buff));
- return d->cachedApplicationFilePath;
} else {
qWarning("QCoreApplication::applicationFilePath: _cmdname() failed");
// _cmdname() won't fail, but just in case, fallback to the old method
@@ -1959,11 +1958,11 @@ QString QCoreApplication::applicationFilePath()
if (!executables.empty()) {
//We assume that there is only one executable in the folder
d->cachedApplicationFilePath = dir.absoluteFilePath(executables.first());
- return d->cachedApplicationFilePath;
} else {
- return QString();
+ d->cachedApplicationFilePath = QString();
}
}
+ return d->cachedApplicationFilePath;
#elif defined(Q_OS_MAC)
QString qAppFileName_str = qAppFileName();
if(!qAppFileName_str.isEmpty()) {
@@ -1982,34 +1981,38 @@ QString QCoreApplication::applicationFilePath()
return d->cachedApplicationFilePath;
}
# endif
+ if (!arguments().isEmpty()) {
+ QString argv0 = QFile::decodeName(arguments().at(0).toLocal8Bit());
+ QString absPath;
+
+ if (!argv0.isEmpty() && argv0.at(0) == QLatin1Char('/')) {
+ /*
+ If argv0 starts with a slash, it is already an absolute
+ file path.
+ */
+ absPath = argv0;
+ } else if (argv0.contains(QLatin1Char('/'))) {
+ /*
+ If argv0 contains one or more slashes, it is a file path
+ relative to the current directory.
+ */
+ absPath = QDir::current().absoluteFilePath(argv0);
+ } else {
+ /*
+ Otherwise, the file path has to be determined using the
+ PATH environment variable.
+ */
+ absPath = QStandardPaths::findExecutable(argv0);
+ }
+
+ absPath = QDir::cleanPath(absPath);
- QString argv0 = QFile::decodeName(arguments().at(0).toLocal8Bit());
- QString absPath;
-
- if (!argv0.isEmpty() && argv0.at(0) == QLatin1Char('/')) {
- /*
- If argv0 starts with a slash, it is already an absolute
- file path.
- */
- absPath = argv0;
- } else if (argv0.contains(QLatin1Char('/'))) {
- /*
- If argv0 contains one or more slashes, it is a file path
- relative to the current directory.
- */
- absPath = QDir::current().absoluteFilePath(argv0);
+ QFileInfo fi(absPath);
+ d->cachedApplicationFilePath = fi.exists() ? fi.canonicalFilePath() : QString();
} else {
- /*
- Otherwise, the file path has to be determined using the
- PATH environment variable.
- */
- absPath = QStandardPaths::findExecutable(argv0);
+ d->cachedApplicationFilePath = QString();
}
- absPath = QDir::cleanPath(absPath);
-
- QFileInfo fi(absPath);
- d->cachedApplicationFilePath = fi.exists() ? fi.canonicalFilePath() : QString();
return d->cachedApplicationFilePath;
#endif
}
diff --git a/src/corelib/kernel/qeventdispatcher_blackberry.cpp b/src/corelib/kernel/qeventdispatcher_blackberry.cpp
index f90f2e3268..d9e38b68b2 100644
--- a/src/corelib/kernel/qeventdispatcher_blackberry.cpp
+++ b/src/corelib/kernel/qeventdispatcher_blackberry.cpp
@@ -128,16 +128,16 @@ static int bpsIOHandler(int fd, int io_events, void *data)
// create unblock event
bps_event_t *event;
int result = bps_event_create(&event, bpsUnblockDomain, 0, NULL, NULL);
- if (result != BPS_SUCCESS) {
- qWarning("QEventDispatcherBlackberryPrivate::QEventDispatcherBlackberry: bps_event_create() failed");
+ if (Q_UNLIKELY(result != BPS_SUCCESS)) {
+ qWarning("QEventDispatcherBlackberry: bps_event_create failed");
return BPS_FAILURE;
}
// post unblock event to our thread; in this callback the bps channel is
// guaranteed to be the same that was active when bps_add_fd was called
result = bps_push_event(event);
- if (result != BPS_SUCCESS) {
- qWarning("QEventDispatcherBlackberryPrivate::QEventDispatcherBlackberry: bps_push_event() failed");
+ if (Q_UNLIKELY(result != BPS_SUCCESS)) {
+ qWarning("QEventDispatcherBlackberry: bps_push_event failed");
bps_event_destroy(event);
return BPS_FAILURE;
}
@@ -151,16 +151,16 @@ QEventDispatcherBlackberryPrivate::QEventDispatcherBlackberryPrivate()
{
// prepare to use BPS
int result = bps_initialize();
- if (result != BPS_SUCCESS)
- qFatal("QEventDispatcherBlackberryPrivate::QEventDispatcherBlackberry: bps_initialize() failed");
+ if (Q_UNLIKELY(result != BPS_SUCCESS))
+ qFatal("QEventDispatcherBlackberry: bps_initialize failed");
bps_channel = bps_channel_get_active();
// get domain for IO ready and wake up events - ignoring race condition here for now
if (bpsUnblockDomain == -1) {
bpsUnblockDomain = bps_register_domain();
- if (bpsUnblockDomain == -1)
- qWarning("QEventDispatcherBlackberryPrivate::QEventDispatcherBlackberry: bps_register_domain() failed");
+ if (Q_UNLIKELY(bpsUnblockDomain == -1))
+ qWarning("QEventDispatcherBlackberry: bps_register_domain failed");
}
}
@@ -202,21 +202,26 @@ void QEventDispatcherBlackberry::registerSocketNotifier(QSocketNotifier *notifie
Q_ASSERT(notifier);
Q_D(QEventDispatcherBlackberry);
- BpsChannelScopeSwitcher channelSwitcher(d->bps_channel);
-
- // Register the fd with bps
int sockfd = notifier->socket();
int type = notifier->type();
- qEventDispatcherDebug << Q_FUNC_INFO << "fd =" << sockfd;
- int io_events = ioEvents(sockfd);
+ qEventDispatcherDebug << Q_FUNC_INFO << "fd =" << sockfd;
- if (io_events)
- bps_remove_fd(sockfd);
+ if (Q_UNLIKELY(sockfd >= FD_SETSIZE)) {
+ qWarning() << "QEventDispatcherBlackberry: cannot register QSocketNotifier (fd too high)"
+ << sockfd;
+ return;
+ }
// Call the base Unix implementation. Needed to allow select() to be called correctly
QEventDispatcherUNIX::registerSocketNotifier(notifier);
+ // Register the fd with bps
+ BpsChannelScopeSwitcher channelSwitcher(d->bps_channel);
+ int io_events = ioEvents(sockfd);
+ if (io_events)
+ bps_remove_fd(sockfd);
+
switch (type) {
case QSocketNotifier::Read:
qEventDispatcherDebug << "Registering" << sockfd << "for Reads";
@@ -233,44 +238,41 @@ void QEventDispatcherBlackberry::registerSocketNotifier(QSocketNotifier *notifie
break;
}
- errno = 0;
- int result = bps_add_fd(sockfd, io_events, &bpsIOHandler, d->ioData.data());
-
- if (result != BPS_SUCCESS)
- qWarning() << Q_FUNC_INFO << "bps_add_fd() failed" << strerror(errno) << "code:" << errno;
+ const int result = bps_add_fd(sockfd, io_events, &bpsIOHandler, d->ioData.data());
+ if (Q_UNLIKELY(result != BPS_SUCCESS))
+ qWarning() << "QEventDispatcherBlackberry: bps_add_fd failed";
}
void QEventDispatcherBlackberry::unregisterSocketNotifier(QSocketNotifier *notifier)
{
Q_D(QEventDispatcherBlackberry);
- BpsChannelScopeSwitcher channelSwitcher(d->bps_channel);
+ int sockfd = notifier->socket();
+
+ qEventDispatcherDebug << Q_FUNC_INFO << "fd =" << sockfd;
+
+ if (Q_UNLIKELY(sockfd >= FD_SETSIZE)) {
+ qWarning() << "QEventDispatcherBlackberry: cannot unregister QSocketNotifier" << sockfd;
+ return;
+ }
// Allow the base Unix implementation to unregister the fd too
QEventDispatcherUNIX::unregisterSocketNotifier(notifier);
// Unregister the fd with bps
- int sockfd = notifier->socket();
- qEventDispatcherDebug << Q_FUNC_INFO << "fd =" << sockfd;
-
+ BpsChannelScopeSwitcher channelSwitcher(d->bps_channel);
const int io_events = ioEvents(sockfd);
-
int result = bps_remove_fd(sockfd);
- if (result != BPS_SUCCESS)
- qWarning() << Q_FUNC_INFO << "bps_remove_fd() failed" << sockfd;
-
+ if (Q_UNLIKELY(result != BPS_SUCCESS))
+ qWarning() << "QEventDispatcherBlackberry: bps_remove_fd failed" << sockfd;
- /* if no other socket notifier is
- * watching sockfd, our job ends here
- */
+ // if no other socket notifier is watching sockfd, our job ends here
if (!io_events)
return;
- errno = 0;
result = bps_add_fd(sockfd, io_events, &bpsIOHandler, d->ioData.data());
- if (result != BPS_SUCCESS) {
- qWarning() << Q_FUNC_INFO << "bps_add_fd() failed" << strerror(errno) << "code:" << errno;
- }
+ if (Q_UNLIKELY(result != BPS_SUCCESS))
+ qWarning("QEventDispatcherBlackberry: bps_add_fd error");
}
static inline int timespecToMillisecs(const timespec &tv)
@@ -358,8 +360,8 @@ int QEventDispatcherBlackberry::select(int nfds, fd_set *readfds, fd_set *writef
// Wait for event or file to be ready
const int result = bps_get_event(&event, timeoutLeft);
- if (result != BPS_SUCCESS)
- qWarning("QEventDispatcherBlackberry::select: bps_get_event() failed");
+ if (Q_UNLIKELY(result != BPS_SUCCESS))
+ qWarning("QEventDispatcherBlackberry: bps_get_event failed");
}
if (!event) // In case of !event, we break out of the loop to let Qt process the timers
@@ -392,13 +394,13 @@ void QEventDispatcherBlackberry::wakeUp()
Q_D(QEventDispatcherBlackberry);
if (d->wakeUps.testAndSetAcquire(0, 1)) {
bps_event_t *event;
- if (bps_event_create(&event, bpsUnblockDomain, 0, 0, 0) == BPS_SUCCESS) {
- if (bps_channel_push_event(d->bps_channel, event) == BPS_SUCCESS)
+ if (Q_LIKELY(bps_event_create(&event, bpsUnblockDomain, 0, 0, 0) == BPS_SUCCESS)) {
+ if (Q_LIKELY(bps_channel_push_event(d->bps_channel, event) == BPS_SUCCESS))
return;
else
bps_event_destroy(event);
}
- qWarning("QEventDispatcherBlackberryPrivate::wakeUp failed");
+ qWarning("QEventDispatcherBlackberry: wakeUp failed");
}
}
diff --git a/src/corelib/kernel/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp
index 50f3a1814b..586d6cf29f 100644
--- a/src/corelib/kernel/qmetatype.cpp
+++ b/src/corelib/kernel/qmetatype.cpp
@@ -421,6 +421,56 @@ public:
int alias;
};
+template<typename T, typename Key>
+class QMetaTypeFunctionRegistry
+{
+public:
+ ~QMetaTypeFunctionRegistry()
+ {
+ const QWriteLocker locker(&lock);
+ map.clear();
+ }
+
+ bool contains(Key k) const
+ {
+ const QReadLocker locker(&lock);
+ return map.contains(k);
+ }
+
+ bool insertIfNotContains(Key k, const T *f)
+ {
+ const QWriteLocker locker(&lock);
+ const T* &fun = map[k];
+ if (fun != 0)
+ return false;
+ fun = f;
+ return true;
+ }
+
+ const T *function(Key k) const
+ {
+ const QReadLocker locker(&lock);
+ return map.value(k, 0);
+ }
+
+ void remove(int from, int to)
+ {
+ const Key k(from, to);
+ const QWriteLocker locker(&lock);
+ map.remove(k);
+ }
+private:
+ mutable QReadWriteLock lock;
+ QHash<Key, const T *> map;
+};
+
+typedef QMetaTypeFunctionRegistry<QtPrivate::AbstractConverterFunction,QPair<int,int> >
+QMetaTypeConverterRegistry;
+typedef QMetaTypeFunctionRegistry<QtPrivate::AbstractComparatorFunction,int>
+QMetaTypeComparatorRegistry;
+typedef QMetaTypeFunctionRegistry<QtPrivate::AbstractDebugStreamFunction,int>
+QMetaTypeDebugStreamRegistry;
+
namespace
{
union CheckThatItIsPod
@@ -432,6 +482,198 @@ union CheckThatItIsPod
Q_DECLARE_TYPEINFO(QCustomTypeInfo, Q_MOVABLE_TYPE);
Q_GLOBAL_STATIC(QVector<QCustomTypeInfo>, customTypes)
Q_GLOBAL_STATIC(QReadWriteLock, customTypesLock)
+Q_GLOBAL_STATIC(QMetaTypeConverterRegistry, customTypesConversionRegistry)
+Q_GLOBAL_STATIC(QMetaTypeComparatorRegistry, customTypesComparatorRegistry)
+Q_GLOBAL_STATIC(QMetaTypeDebugStreamRegistry, customTypesDebugStreamRegistry)
+
+/*!
+ \fn bool QMetaType::registerConverter()
+ \since 5.2
+ Registers the possibility of an implicit conversion from type From to type To in the meta
+ type system. Returns true if the registration succeeded, otherwise false.
+*/
+
+/*!
+ \fn bool QMetaType::registerConverter(MemberFunction function)
+ \since 5.2
+ \overload
+ Registers a method \a function like To From::function() const as converter from type From
+ to type To in the meta type system. Returns true if the registration succeeded, otherwise false.
+*/
+
+/*!
+ \fn bool QMetaType::registerConverter(MemberFunctionOk function)
+ \since 5.2
+ \overload
+ Registers a method \a function like To From::function(bool *ok) const as converter from type From
+ to type To in the meta type system. Returns true if the registration succeeded, otherwise false.
+*/
+
+/*!
+ \fn bool QMetaType::registerConverter(UnaryFunction function)
+ \since 5.2
+ \overload
+ Registers a unary function object \a function as converter from type From
+ to type To in the meta type system. Returns true if the registration succeeded, otherwise false.
+*/
+
+/*!
+ \fn bool QMetaType::registerComparators()
+ \since 5.2
+ Registers comparison operetarors for the user-registered type T. This requires T to have
+ both an operator== and an operator<.
+ Returns true if the registration succeeded, otherwise false.
+*/
+
+#ifndef QT_NO_DEBUG_STREAM
+/*!
+ \fn bool QMetaType::registerDebugStreamOperator()
+ Registers the debug stream operator for the user-registered type T. This requires T to have
+ an operator<<(QDebug dbg, T).
+ Returns true if the registration succeeded, otherwise false.
+*/
+#endif
+
+/*!
+ Registers function \a f as converter function from type id \a from to \a to.
+ If there's already a conversion registered, this does nothing but deleting \a f.
+ Returns true if the registration succeeded, otherwise false.
+ \since 5.2
+ \internal
+*/
+bool QMetaType::registerConverterFunction(const QtPrivate::AbstractConverterFunction *f, int from, int to)
+{
+ if (!customTypesConversionRegistry()->insertIfNotContains(qMakePair(from, to), f)) {
+ qWarning("Type conversion already registered from type %s to type %s",
+ QMetaType::typeName(from), QMetaType::typeName(to));
+ return false;
+ }
+ return true;
+}
+
+/*!
+ \internal
+
+ Invoked automatically when a converter function object is destroyed.
+ */
+void QMetaType::unregisterConverterFunction(int from, int to)
+{
+ customTypesConversionRegistry()->remove(from, to);
+}
+
+bool QMetaType::registerComparatorFunction(const QtPrivate::AbstractComparatorFunction *f, int type)
+{
+ if (!customTypesComparatorRegistry()->insertIfNotContains(type, f)) {
+ qWarning("Comparators already registered for type %s", QMetaType::typeName(type));
+ return false;
+ }
+ return true;
+}
+
+/*!
+ \fn bool QMetaType::hasRegisteredComparators()
+ Returns true, if the meta type system has registered comparators for type T.
+ \since 5.2
+ */
+
+/*!
+ Returns true, if the meta type system has registered comparators for type id \a typeId.
+ \since 5.2
+ */
+bool QMetaType::hasRegisteredComparators(int typeId)
+{
+ return customTypesComparatorRegistry()->contains(typeId);
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+bool QMetaType::registerDebugStreamOperatorFunction(const QtPrivate::AbstractDebugStreamFunction *f,
+ int type)
+{
+ if (!customTypesDebugStreamRegistry()->insertIfNotContains(type, f)) {
+ qWarning("Debug stream operator already registered for type %s", QMetaType::typeName(type));
+ return false;
+ }
+ return true;
+}
+
+/*!
+ \fn bool QMetaType::hasRegisteredDebugStreamOperator()
+ Returns true, if the meta type system has a registered debug stream operator for type T.
+ \since 5.2
+ */
+
+/*!
+ Returns true, if the meta type system has a registered debug stream operator for type
+ id \a typeId.
+ \since 5.2
+*/
+bool QMetaType::hasRegisteredDebugStreamOperator(int typeId)
+{
+ return customTypesDebugStreamRegistry()->contains(typeId);
+}
+#endif
+
+/*!
+ Converts the object at \a from from \a fromTypeId to the preallocated space at \a to
+ typed \a toTypeId. Returns true, if the conversion succeeded, otherwise false.
+ \since 5.2
+*/
+bool QMetaType::convert(const void *from, int fromTypeId, void *to, int toTypeId)
+{
+ const QtPrivate::AbstractConverterFunction * const f =
+ customTypesConversionRegistry()->function(qMakePair(fromTypeId, toTypeId));
+ return f && f->convert(f, from, to);
+}
+
+/*!
+ Compares the objects at \a lhs and \a rhs. Both objects need to be of type \a typeId.
+ \a result is set to less than, equal to or greater than zero, if \a lhs is less than, equal to
+ or greater than \a rhs. Returns true, if the comparison succeeded, otherwiess false.
+ \since 5.2
+*/
+bool QMetaType::compare(const void *lhs, const void *rhs, int typeId, int* result)
+{
+ const QtPrivate::AbstractComparatorFunction * const f =
+ customTypesComparatorRegistry()->function(typeId);
+ if (!f)
+ return false;
+ if (f->equals(f, lhs, rhs))
+ *result = 0;
+ else
+ *result = f->lessThan(f, lhs, rhs) ? -1 : 1;
+ return true;
+}
+
+/*!
+ Streams the object at \a rhs of type \a typeId to the debug stream \a dbg. Returns true
+ on success, otherwise false.
+ \since 5.2
+*/
+bool QMetaType::debugStream(QDebug& dbg, const void *rhs, int typeId)
+{
+ const QtPrivate::AbstractDebugStreamFunction * const f = customTypesDebugStreamRegistry()->function(typeId);
+ if (!f)
+ return false;
+ f->stream(f, dbg, rhs);
+ return true;
+}
+
+/*!
+ \fn bool QMetaType::hasRegisteredConverterFunction()
+ Returns true, if the meta type system has a registered conversion from type From to type To.
+ \since 5.2
+ \overload
+ */
+
+/*!
+ Returns true, if the meta type system has a registered conversion from meta type id \a fromTypeId
+ to \a toTypeId
+ \since 5.2
+*/
+bool QMetaType::hasRegisteredConverterFunction(int fromTypeId, int toTypeId)
+{
+ return customTypesConversionRegistry()->contains(qMakePair(fromTypeId, toTypeId));
+}
#ifndef QT_NO_DATASTREAM
/*!
@@ -723,11 +965,11 @@ int QMetaType::registerNormalizedTypedef(const NS(QByteArray) &normalizedTypeNam
}
if (idx != aliasId) {
- qFatal("QMetaType::registerTypedef: Binary compatibility break "
- "-- Type name '%s' previously registered as typedef of '%s' [%i], "
- "now registering as typedef of '%s' [%i].",
- normalizedTypeName.constData(), QMetaType::typeName(idx), idx,
- QMetaType::typeName(aliasId), aliasId);
+ qWarning("QMetaType::registerTypedef: "
+ "-- Type name '%s' previously registered as typedef of '%s' [%i], "
+ "now registering as typedef of '%s' [%i].",
+ normalizedTypeName.constData(), QMetaType::typeName(idx), idx,
+ QMetaType::typeName(aliasId), aliasId);
}
return idx;
}
@@ -1841,6 +2083,37 @@ const QMetaObject *QMetaType::metaObjectForType(int type)
\sa Q_DECLARE_METATYPE(), QMetaType::type()
*/
+/*!
+ \fn bool qRegisterSequentialConverter()
+ \relates QMetaType
+ \since 5.2
+
+ Registers a sequential container so that it can be converted to
+ a QVariantList. If compilation fails, then you probably forgot to
+ Q_DECLARE_METATYPE the value type.
+
+ Note that it is not necessary to call this method for Qt containers (QList,
+ QVector etc) or for std::vector or std::list. Such containers are automatically
+ registered by Qt.
+
+ \sa QVariant::canConvert()
+*/
+
+/*!
+ \fn bool qRegisterAssociativeConverter()
+ \relates QMetaType
+ \since 5.2
+
+ Registers an associative container so that it can be converted to
+ a QVariantHash or QVariantMap. If the key_type and mapped_type of the container
+ was not declared with Q_DECLARE_METATYPE(), compilation will fail.
+
+ Note that it is not necessary to call this method for Qt containers (QHash,
+ QMap etc) or for std::map. Such containers are automatically registered by Qt.
+
+ \sa QVariant::canConvert()
+*/
+
namespace {
class TypeInfo {
template<typename T, bool IsAcceptedType = DefinedTypesFilter::Acceptor<T>::IsAccepted>
diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h
index 5763bcc07b..005199080d 100644
--- a/src/corelib/kernel/qmetatype.h
+++ b/src/corelib/kernel/qmetatype.h
@@ -47,17 +47,27 @@
#include <QtCore/qbytearray.h>
#include <QtCore/qvarlengtharray.h>
#include <QtCore/qisenum.h>
+#include <QtCore/qtypetraits.h>
#ifndef QT_NO_QOBJECT
#include <QtCore/qobjectdefs.h>
#endif
#include <new>
+#include <vector>
+#include <list>
+#include <map>
+
#ifdef Bool
#error qmetatype.h must be included before any header file that defines Bool
#endif
QT_BEGIN_NAMESPACE
+template <typename T>
+struct QMetaTypeId2;
+
+template <typename T>
+inline Q_DECL_CONSTEXPR int qMetaTypeId();
// F is a tuple: (QMetaType::TypeName, QMetaType::TypeNameID, RealType)
#define QT_FOR_EACH_STATIC_PRIMITIVE_TYPE(F)\
@@ -183,10 +193,183 @@ QT_BEGIN_NAMESPACE
#define QT_DEFINE_METATYPE_ID(TypeName, Id, Name) \
TypeName = Id,
+#define QT_FOR_EACH_AUTOMATIC_TEMPLATE_1ARG(F) \
+ F(QList) \
+ F(QVector) \
+ F(QQueue) \
+ F(QStack) \
+ F(QSet) \
+ F(QLinkedList)
+
+#define QT_FOR_EACH_AUTOMATIC_TEMPLATE_2ARG(F) \
+ F(QHash, class) \
+ F(QMap, class) \
+ F(QPair, struct)
+
class QDataStream;
class QMetaTypeInterface;
struct QMetaObject;
+namespace QtPrivate
+{
+/*!
+ This template is used for implicit conversion from type From to type To.
+ \internal
+*/
+template<typename From, typename To>
+To convertImplicit(const From& from)
+{
+ return from;
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+struct AbstractDebugStreamFunction
+{
+ typedef void (*Stream)(const AbstractDebugStreamFunction *, QDebug&, const void *);
+ typedef void (*Destroy)(AbstractDebugStreamFunction *);
+ explicit AbstractDebugStreamFunction(Stream s = 0, Destroy d = 0)
+ : stream(s), destroy(d) {}
+ Q_DISABLE_COPY(AbstractDebugStreamFunction)
+ Stream stream;
+ Destroy destroy;
+};
+
+template<typename T>
+struct BuiltInDebugStreamFunction : public AbstractDebugStreamFunction
+{
+ BuiltInDebugStreamFunction()
+ : AbstractDebugStreamFunction(stream, destroy) {}
+ static void stream(const AbstractDebugStreamFunction *, QDebug& dbg, const void *r)
+ {
+ const T *rhs = static_cast<const T *>(r);
+ operator<<(dbg, *rhs);
+ }
+
+ static void destroy(AbstractDebugStreamFunction *_this)
+ {
+ delete static_cast<BuiltInDebugStreamFunction *>(_this);
+ }
+};
+#endif
+
+struct AbstractComparatorFunction
+{
+ typedef bool (*LessThan)(const AbstractComparatorFunction *, const void *, const void *);
+ typedef bool (*Equals)(const AbstractComparatorFunction *, const void *, const void *);
+ typedef void (*Destroy)(AbstractComparatorFunction *);
+ explicit AbstractComparatorFunction(LessThan lt = 0, Equals e = 0, Destroy d = 0)
+ : lessThan(lt), equals(e), destroy(d) {}
+ Q_DISABLE_COPY(AbstractComparatorFunction)
+ LessThan lessThan;
+ Equals equals;
+ Destroy destroy;
+};
+
+template<typename T>
+struct BuiltInComparatorFunction : public AbstractComparatorFunction
+{
+ BuiltInComparatorFunction()
+ : AbstractComparatorFunction(lessThan, equals, destroy) {}
+ static bool lessThan(const AbstractComparatorFunction *, const void *l, const void *r)
+ {
+ const T *lhs = static_cast<const T *>(l);
+ const T *rhs = static_cast<const T *>(r);
+ return *lhs < *rhs;
+ }
+
+ static bool equals(const AbstractComparatorFunction *, const void *l, const void *r)
+ {
+ const T *lhs = static_cast<const T *>(l);
+ const T *rhs = static_cast<const T *>(r);
+ return *lhs == *rhs;
+ }
+
+ static void destroy(AbstractComparatorFunction *_this)
+ {
+ delete static_cast<BuiltInComparatorFunction *>(_this);
+ }
+};
+
+struct AbstractConverterFunction
+{
+ typedef bool (*Converter)(const AbstractConverterFunction *, const void *, void*);
+ explicit AbstractConverterFunction(Converter c = 0)
+ : convert(c) {}
+ Q_DISABLE_COPY(AbstractConverterFunction)
+ Converter convert;
+};
+
+template<typename From, typename To>
+struct ConverterMemberFunction : public AbstractConverterFunction
+{
+ explicit ConverterMemberFunction(To(From::*function)() const)
+ : AbstractConverterFunction(convert),
+ m_function(function) {}
+ ~ConverterMemberFunction();
+ static bool convert(const AbstractConverterFunction *_this, const void *in, void *out)
+ {
+ const From *f = static_cast<const From *>(in);
+ To *t = static_cast<To *>(out);
+ const ConverterMemberFunction *_typedThis =
+ static_cast<const ConverterMemberFunction *>(_this);
+ *t = (f->*_typedThis->m_function)();
+ return true;
+ }
+
+ To(From::* const m_function)() const;
+};
+
+template<typename From, typename To>
+struct ConverterMemberFunctionOk : public AbstractConverterFunction
+{
+ explicit ConverterMemberFunctionOk(To(From::*function)(bool *) const)
+ : AbstractConverterFunction(convert),
+ m_function(function) {}
+ ~ConverterMemberFunctionOk();
+ static bool convert(const AbstractConverterFunction *_this, const void *in, void *out)
+ {
+ const From *f = static_cast<const From *>(in);
+ To *t = static_cast<To *>(out);
+ bool ok = false;
+ const ConverterMemberFunctionOk *_typedThis =
+ static_cast<const ConverterMemberFunctionOk *>(_this);
+ *t = (f->*_typedThis->m_function)(&ok);
+ if (!ok)
+ *t = To();
+ return ok;
+ }
+
+ To(From::* const m_function)(bool*) const;
+};
+
+template<typename From, typename To, typename UnaryFunction>
+struct ConverterFunctor : public AbstractConverterFunction
+{
+ explicit ConverterFunctor(UnaryFunction function)
+ : AbstractConverterFunction(convert),
+ m_function(function) {}
+ ~ConverterFunctor();
+ static bool convert(const AbstractConverterFunction *_this, const void *in, void *out)
+ {
+ const From *f = static_cast<const From *>(in);
+ To *t = static_cast<To *>(out);
+ const ConverterFunctor *_typedThis =
+ static_cast<const ConverterFunctor *>(_this);
+ *t = _typedThis->m_function(*f);
+ return true;
+ }
+
+ UnaryFunction m_function;
+};
+
+ template<typename T, bool>
+ struct ValueTypeIsMetaType;
+ template<typename T, bool>
+ struct AssociativeValueTypeIsMetaType;
+ template<typename T, bool>
+ struct IsMetaTypePair;
+}
+
class Q_CORE_EXPORT QMetaType {
enum ExtensionFlag { NoExtensionFlags,
CreateEx = 0x1, DestroyEx = 0x2,
@@ -320,6 +503,109 @@ public:
inline void destroy(void *data) const;
inline void *construct(void *where, const void *copy = 0) const;
inline void destruct(void *data) const;
+
+public:
+ template<typename T>
+ static bool registerComparators()
+ {
+ Q_STATIC_ASSERT_X((!QMetaTypeId2<T>::IsBuiltIn),
+ "QMetaType::registerComparators: The type must be a custom type.");
+
+ const int typeId = qMetaTypeId<T>();
+ static const QtPrivate::BuiltInComparatorFunction<T> f;
+ return registerComparatorFunction( &f, typeId);
+ }
+ template<typename T>
+ static bool hasRegisteredComparators()
+ {
+ return hasRegisteredComparators(qMetaTypeId<T>());
+ }
+ static bool hasRegisteredComparators(int typeId);
+
+
+#ifndef QT_NO_DEBUG_STREAM
+ template<typename T>
+ static bool registerDebugStreamOperator()
+ {
+ Q_STATIC_ASSERT_X((!QMetaTypeId2<T>::IsBuiltIn),
+ "QMetaType::registerDebugStreamOperator: The type must be a custom type.");
+
+ const int typeId = qMetaTypeId<T>();
+ static const QtPrivate::BuiltInDebugStreamFunction<T> f;
+ return registerDebugStreamOperatorFunction(&f, typeId);
+ }
+ template<typename T>
+ static bool hasRegisteredDebugStreamOperator()
+ {
+ return hasRegisteredDebugStreamOperator(qMetaTypeId<T>());
+ }
+ static bool hasRegisteredDebugStreamOperator(int typeId);
+#endif
+
+ // implicit conversion supported like double -> float
+ template<typename From, typename To>
+ static bool registerConverter()
+ {
+ return registerConverter<From, To>(QtPrivate::convertImplicit<From, To>);
+ }
+
+#ifdef Q_QDOC
+ static bool registerConverter(MemberFunction function);
+ static bool registerConverter(MemberFunctionOk function);
+ static bool registerConverter(UnaryFunction function);
+#else
+ // member function as in "QString QFont::toString() const"
+ template<typename From, typename To>
+ static bool registerConverter(To(From::*function)() const)
+ {
+ Q_STATIC_ASSERT_X((!QMetaTypeId2<To>::IsBuiltIn || !QMetaTypeId2<From>::IsBuiltIn),
+ "QMetaType::registerConverter: At least one of the types must be a custom type.");
+
+ const int fromTypeId = qMetaTypeId<From>();
+ const int toTypeId = qMetaTypeId<To>();
+ static const QtPrivate::ConverterMemberFunction<From, To> f(function);
+ return registerConverterFunction(&f, fromTypeId, toTypeId);
+ }
+
+ // member function as in "double QString::toDouble(bool *ok = 0) const"
+ template<typename From, typename To>
+ static bool registerConverter(To(From::*function)(bool*) const)
+ {
+ Q_STATIC_ASSERT_X((!QMetaTypeId2<To>::IsBuiltIn || !QMetaTypeId2<From>::IsBuiltIn),
+ "QMetaType::registerConverter: At least one of the types must be a custom type.");
+
+ const int fromTypeId = qMetaTypeId<From>();
+ const int toTypeId = qMetaTypeId<To>();
+ static const QtPrivate::ConverterMemberFunctionOk<From, To> f(function);
+ return registerConverterFunction(&f, fromTypeId, toTypeId);
+ }
+
+ // functor or function pointer
+ template<typename From, typename To, typename UnaryFunction>
+ static bool registerConverter(UnaryFunction function)
+ {
+ Q_STATIC_ASSERT_X((!QMetaTypeId2<To>::IsBuiltIn || !QMetaTypeId2<From>::IsBuiltIn),
+ "QMetaType::registerConverter: At least one of the types must be a custom type.");
+
+ const int fromTypeId = qMetaTypeId<From>();
+ const int toTypeId = qMetaTypeId<To>();
+ static const QtPrivate::ConverterFunctor<From, To, UnaryFunction> f(function);
+ return registerConverterFunction(&f, fromTypeId, toTypeId);
+ }
+#endif
+
+ static bool convert(const void *from, int fromTypeId, void *to, int toTypeId);
+ static bool compare(const void *lhs, const void *rhs, int typeId, int* result);
+ static bool debugStream(QDebug& dbg, const void *rhs, int typeId);
+
+ template<typename From, typename To>
+ static bool hasRegisteredConverterFunction()
+ {
+ return hasRegisteredConverterFunction(qMetaTypeId<From>(), qMetaTypeId<To>());
+ }
+
+ static bool hasRegisteredConverterFunction(int fromTypeId, int toTypeId);
+
private:
static QMetaType typeInfo(const int type);
inline QMetaType(const ExtensionFlag extensionFlags, const QMetaTypeInterface *info,
@@ -348,6 +634,31 @@ private:
void *constructExtended(void *where, const void *copy = 0) const;
void destructExtended(void *data) const;
+ static bool registerComparatorFunction(const QtPrivate::AbstractComparatorFunction *f, int type);
+#ifndef QT_NO_DEBUG_STREAM
+ static bool registerDebugStreamOperatorFunction(const QtPrivate::AbstractDebugStreamFunction *f, int type);
+#endif
+
+#ifndef Q_NO_TEMPLATE_FRIENDS
+#ifndef Q_QDOC
+ template<typename T>
+ friend bool qRegisterSequentialConverter();
+ template<typename, bool> friend struct QtPrivate::ValueTypeIsMetaType;
+ template<typename, typename> friend struct QtPrivate::ConverterMemberFunction;
+ template<typename, typename> friend struct QtPrivate::ConverterMemberFunctionOk;
+ template<typename, typename, typename> friend struct QtPrivate::ConverterFunctor;
+ template<typename T>
+ friend bool qRegisterAssociativeConverter();
+ template<typename, bool> friend struct QtPrivate::AssociativeValueTypeIsMetaType;
+ template<typename, bool> friend struct QtPrivate::IsMetaTypePair;
+#endif
+#else
+public:
+#endif
+ static bool registerConverterFunction(const QtPrivate::AbstractConverterFunction *f, int from, int to);
+ static void unregisterConverterFunction(int from, int to);
+private:
+
Creator m_creator;
Deleter m_deleter;
SaveOperator m_saveOp;
@@ -366,6 +677,26 @@ private:
Q_DECLARE_OPERATORS_FOR_FLAGS(QMetaType::TypeFlags)
+namespace QtPrivate {
+
+template<typename From, typename To>
+ConverterMemberFunction<From, To>::~ConverterMemberFunction()
+{
+ QMetaType::unregisterConverterFunction(qMetaTypeId<From>(), qMetaTypeId<To>());
+}
+template<typename From, typename To>
+ConverterMemberFunctionOk<From, To>::~ConverterMemberFunctionOk()
+{
+ QMetaType::unregisterConverterFunction(qMetaTypeId<From>(), qMetaTypeId<To>());
+}
+template<typename From, typename To, typename UnaryFunction>
+ConverterFunctor<From, To, UnaryFunction>::~ConverterFunctor()
+{
+ QMetaType::unregisterConverterFunction(qMetaTypeId<From>(), qMetaTypeId<To>());
+}
+
+}
+
namespace QtMetaTypePrivate {
template <typename T, bool Accepted = true>
struct QMetaTypeFunctionHelper {
@@ -421,6 +752,484 @@ template <>
struct QMetaTypeFunctionHelper<void, /* Accepted */ true>
: public QMetaTypeFunctionHelper<void, /* Accepted */ false>
{};
+
+struct VariantData
+{
+ VariantData(const int metaTypeId_,
+ const void *data_,
+ const uint flags_)
+ : metaTypeId(metaTypeId_)
+ , data(data_)
+ , flags(flags_)
+ {
+ }
+ const int metaTypeId;
+ const void *data;
+ const uint flags;
+};
+
+template<typename const_iterator>
+struct IteratorOwner
+{
+ static void assign(void **ptr, const_iterator iterator)
+ {
+ *ptr = new const_iterator(iterator);
+ }
+
+ static void advance(void **iterator, int step)
+ {
+ const_iterator &it = *static_cast<const_iterator*>(*iterator);
+ std::advance(it, step);
+ }
+
+ static void destroy(void **ptr)
+ {
+ delete static_cast<const_iterator*>(*ptr);
+ }
+
+ static const void *getData(void * const *iterator)
+ {
+ return &**static_cast<const_iterator*>(*iterator);
+ }
+
+ static const void *getData(const_iterator it)
+ {
+ return &*it;
+ }
+};
+template<typename const_iterator>
+struct IteratorOwner<const const_iterator*>
+{
+ static void assign(void **ptr, const const_iterator *iterator )
+ {
+ *ptr = const_cast<const_iterator*>(iterator);
+ }
+
+ static void advance(void **iterator, int step)
+ {
+ const_iterator *it = static_cast<const_iterator*>(*iterator);
+ std::advance(it, step);
+ *iterator = it;
+ }
+
+ static void destroy(void **)
+ {
+ }
+
+ static const void *getData(void * const *iterator)
+ {
+ return *iterator;
+ }
+
+ static const void *getData(const const_iterator *it)
+ {
+ return it;
+ }
+};
+
+enum IteratorCapability
+{
+ ForwardCapability = 1,
+ BiDirectionalCapability = 2,
+ RandomAccessCapability = 4
+};
+
+template<typename T, typename Category = typename std::iterator_traits<typename T::const_iterator>::iterator_category>
+struct CapabilitiesImpl;
+
+template<typename T>
+struct CapabilitiesImpl<T, std::forward_iterator_tag>
+{ enum { IteratorCapabilities = ForwardCapability }; };
+template<typename T>
+struct CapabilitiesImpl<T, std::bidirectional_iterator_tag>
+{ enum { IteratorCapabilities = BiDirectionalCapability | ForwardCapability }; };
+template<typename T>
+struct CapabilitiesImpl<T, std::random_access_iterator_tag>
+{ enum { IteratorCapabilities = RandomAccessCapability | BiDirectionalCapability | ForwardCapability }; };
+
+template<typename T>
+struct ContainerAPI : CapabilitiesImpl<T>
+{
+ static int size(const T *t) { return std::distance(t->begin(), t->end()); }
+};
+
+template<typename T>
+struct ContainerAPI<QList<T> > : CapabilitiesImpl<QList<T> >
+{ static int size(const QList<T> *t) { return t->size(); } };
+
+template<typename T>
+struct ContainerAPI<QVector<T> > : CapabilitiesImpl<QVector<T> >
+{ static int size(const QVector<T> *t) { return t->size(); } };
+
+template<typename T>
+struct ContainerAPI<std::vector<T> > : CapabilitiesImpl<std::vector<T> >
+{ static int size(const std::vector<T> *t) { return t->size(); } };
+
+template<typename T>
+struct ContainerAPI<std::list<T> > : CapabilitiesImpl<std::list<T> >
+{ static int size(const std::list<T> *t) { return t->size(); } };
+
+class QSequentialIterableImpl
+{
+public:
+ const void * _iterable;
+ void *_iterator;
+ int _metaType_id;
+ uint _metaType_flags;
+ uint _iteratorCapabilities;
+ typedef int(*sizeFunc)(const void *p);
+ typedef const void * (*atFunc)(const void *p, int);
+ typedef void (*moveIteratorFunc)(const void *p, void **);
+ typedef void (*advanceFunc)(void **p, int);
+ typedef VariantData (*getFunc)( void * const *p, int metaTypeId, uint flags);
+ typedef void (*destroyIterFunc)(void **p);
+ typedef bool (*equalIterFunc)(void * const *p, void * const *other);
+
+ sizeFunc _size;
+ atFunc _at;
+ moveIteratorFunc _moveToBegin;
+ moveIteratorFunc _moveToEnd;
+ advanceFunc _advance;
+ getFunc _get;
+ destroyIterFunc _destroyIter;
+ equalIterFunc _equalIter;
+
+ template<class T>
+ static int sizeImpl(const void *p)
+ { return ContainerAPI<T>::size(static_cast<const T*>(p)); }
+
+ template<class T>
+ static const void* atImpl(const void *p, int idx)
+ {
+ typename T::const_iterator i = static_cast<const T*>(p)->begin();
+ std::advance(i, idx);
+ return IteratorOwner<typename T::const_iterator>::getData(i);
+ }
+
+ template<class T>
+ static void advanceImpl(void **p, int step)
+ { IteratorOwner<typename T::const_iterator>::advance(p, step); }
+
+ template<class T>
+ static void moveToBeginImpl(const void *container, void **iterator)
+ { IteratorOwner<typename T::const_iterator>::assign(iterator, static_cast<const T*>(container)->begin()); }
+
+ template<class T>
+ static void moveToEndImpl(const void *container, void **iterator)
+ { IteratorOwner<typename T::const_iterator>::assign(iterator, static_cast<const T*>(container)->end()); }
+
+ template<class T>
+ static void destroyIterImpl(void **iterator)
+ { IteratorOwner<typename T::const_iterator>::destroy(iterator); }
+
+ template<class T>
+ static bool equalIterImpl(void * const *iterator, void * const *other)
+ { return *static_cast<typename T::const_iterator*>(*iterator) == *static_cast<typename T::const_iterator*>(*other); }
+
+ template<class T>
+ static VariantData getImpl(void * const *iterator, int metaTypeId, uint flags)
+ { return VariantData(metaTypeId, IteratorOwner<typename T::const_iterator>::getData(iterator), flags); }
+
+public:
+ template<class T> QSequentialIterableImpl(const T*p)
+ : _iterable(p)
+ , _iterator(0)
+ , _metaType_id(qMetaTypeId<typename T::value_type>())
+ , _metaType_flags(QTypeInfo<typename T::value_type>::isPointer)
+ , _iteratorCapabilities(ContainerAPI<T>::IteratorCapabilities)
+ , _size(sizeImpl<T>)
+ , _at(atImpl<T>)
+ , _moveToBegin(moveToBeginImpl<T>)
+ , _moveToEnd(moveToEndImpl<T>)
+ , _advance(advanceImpl<T>)
+ , _get(getImpl<T>)
+ , _destroyIter(destroyIterImpl<T>)
+ , _equalIter(equalIterImpl<T>)
+ {
+ }
+
+ QSequentialIterableImpl()
+ : _iterable(0)
+ , _iterator(0)
+ , _metaType_id(QMetaType::UnknownType)
+ , _metaType_flags(0)
+ , _iteratorCapabilities(0)
+ , _size(0)
+ , _at(0)
+ , _moveToBegin(0)
+ , _moveToEnd(0)
+ , _advance(0)
+ , _get(0)
+ , _destroyIter(0)
+ , _equalIter(0)
+ {
+ }
+
+ inline void moveToBegin() { _moveToBegin(_iterable, &_iterator); }
+ inline void moveToEnd() { _moveToEnd(_iterable, &_iterator); }
+ inline bool equal(const QSequentialIterableImpl&other) const { return _equalIter(&_iterator, &other._iterator); }
+ inline QSequentialIterableImpl &advance(int i) {
+ Q_ASSERT(i > 0 || _iteratorCapabilities & BiDirectionalCapability);
+ _advance(&_iterator, i);
+ return *this;
+ }
+
+ inline VariantData getCurrent() const { return _get(&_iterator, _metaType_id, _metaType_flags); }
+
+ VariantData at(int idx) const
+ { return VariantData(_metaType_id, _at(_iterable, idx), _metaType_flags); }
+
+ int size() const { Q_ASSERT(_iterable); return _size(_iterable); }
+
+ inline void destroyIter() { _destroyIter(&_iterator); }
+};
+
+template<typename From>
+struct QSequentialIterableConvertFunctor
+{
+ QSequentialIterableConvertFunctor() {}
+
+ QSequentialIterableImpl operator()(const From &f) const
+ {
+ return QSequentialIterableImpl(&f);
+ }
+};
+}
+
+namespace QtMetaTypePrivate {
+template<typename T, bool = QtPrivate::is_same<typename T::const_iterator::value_type, typename T::mapped_type>::value>
+struct AssociativeContainerAccessor
+{
+ static const typename T::key_type& getKey(const typename T::const_iterator &it)
+ {
+ return it.key();
+ }
+
+ static const typename T::mapped_type& getValue(const typename T::const_iterator &it)
+ {
+ return it.value();
+ }
+};
+
+template<typename T, bool = QtPrivate::is_same<typename T::const_iterator::value_type, std::pair<const typename T::key_type, typename T::mapped_type> >::value>
+struct StlStyleAssociativeContainerAccessor;
+
+template<typename T>
+struct StlStyleAssociativeContainerAccessor<T, true>
+{
+ static const typename T::key_type& getKey(const typename T::const_iterator &it)
+ {
+ return it->first;
+ }
+
+ static const typename T::mapped_type& getValue(const typename T::const_iterator &it)
+ {
+ return it->second;
+ }
+};
+
+template<typename T>
+struct AssociativeContainerAccessor<T, false> : public StlStyleAssociativeContainerAccessor<T>
+{
+};
+
+class QAssociativeIterableImpl
+{
+public:
+ const void *_iterable;
+ void *_iterator;
+ int _metaType_id_key;
+ uint _metaType_flags_key;
+ int _metaType_id_value;
+ uint _metaType_flags_value;
+ typedef int(*sizeFunc)(const void *p);
+ typedef void (*findFunc)(const void *container, const void *p, void **iterator);
+ typedef void (*beginFunc)(const void *p, void **);
+ typedef void (*advanceFunc)(void **p, int);
+ typedef VariantData (*getFunc)(void * const *p, int metaTypeId, uint flags);
+ typedef void (*destroyIterFunc)(void **p);
+ typedef bool (*equalIterFunc)(void * const *p, void * const *other);
+
+ sizeFunc _size;
+ findFunc _find;
+ beginFunc _begin;
+ beginFunc _end;
+ advanceFunc _advance;
+ getFunc _getKey;
+ getFunc _getValue;
+ destroyIterFunc _destroyIter;
+ equalIterFunc _equalIter;
+
+ template<class T>
+ static int sizeImpl(const void *p)
+ { return std::distance(static_cast<const T*>(p)->begin(),
+ static_cast<const T*>(p)->end()); }
+
+ template<class T>
+ static void findImpl(const void *container, const void *p, void **iterator)
+ { IteratorOwner<typename T::const_iterator>::assign(iterator,
+ static_cast<const T*>(container)->find(*static_cast<const typename T::key_type*>(p))); }
+
+ template<class T>
+ static void advanceImpl(void **p, int step)
+ { std::advance(*static_cast<typename T::const_iterator*>(*p), step); }
+
+ template<class T>
+ static void beginImpl(const void *container, void **iterator)
+ { IteratorOwner<typename T::const_iterator>::assign(iterator, static_cast<const T*>(container)->begin()); }
+
+ template<class T>
+ static void endImpl(const void *container, void **iterator)
+ { IteratorOwner<typename T::const_iterator>::assign(iterator, static_cast<const T*>(container)->end()); }
+
+ template<class T>
+ static VariantData getKeyImpl(void * const *iterator, int metaTypeId, uint flags)
+ { return VariantData(metaTypeId, &AssociativeContainerAccessor<T>::getKey(*static_cast<typename T::const_iterator*>(*iterator)), flags); }
+
+ template<class T>
+ static VariantData getValueImpl(void * const *iterator, int metaTypeId, uint flags)
+ { return VariantData(metaTypeId, &AssociativeContainerAccessor<T>::getValue(*static_cast<typename T::const_iterator*>(*iterator)), flags); }
+
+ template<class T>
+ static void destroyIterImpl(void **iterator)
+ { IteratorOwner<typename T::const_iterator>::destroy(iterator); }
+
+ template<class T>
+ static bool equalIterImpl(void * const *iterator, void * const *other)
+ { return *static_cast<typename T::const_iterator*>(*iterator) == *static_cast<typename T::const_iterator*>(*other); }
+
+public:
+ template<class T> QAssociativeIterableImpl(const T*p)
+ : _iterable(p)
+ , _metaType_id_key(qMetaTypeId<typename T::key_type>())
+ , _metaType_flags_key(QTypeInfo<typename T::key_type>::isPointer)
+ , _metaType_id_value(qMetaTypeId<typename T::mapped_type>())
+ , _metaType_flags_value(QTypeInfo<typename T::mapped_type>::isPointer)
+ , _size(sizeImpl<T>)
+ , _find(findImpl<T>)
+ , _begin(beginImpl<T>)
+ , _end(endImpl<T>)
+ , _advance(advanceImpl<T>)
+ , _getKey(getKeyImpl<T>)
+ , _getValue(getValueImpl<T>)
+ , _destroyIter(destroyIterImpl<T>)
+ , _equalIter(equalIterImpl<T>)
+ {
+ }
+
+ QAssociativeIterableImpl()
+ : _iterable(0)
+ , _metaType_id_key(QMetaType::UnknownType)
+ , _metaType_flags_key(0)
+ , _metaType_id_value(QMetaType::UnknownType)
+ , _metaType_flags_value(0)
+ , _size(0)
+ , _find(0)
+ , _begin(0)
+ , _end(0)
+ , _advance(0)
+ , _getKey(0)
+ , _getValue(0)
+ , _destroyIter(0)
+ , _equalIter(0)
+ {
+ }
+
+ inline void begin() { _begin(_iterable, &_iterator); }
+ inline void end() { _end(_iterable, &_iterator); }
+ inline bool equal(const QAssociativeIterableImpl&other) const { return _equalIter(&_iterator, &other._iterator); }
+ inline QAssociativeIterableImpl &advance(int i) { _advance(&_iterator, i); return *this; }
+
+ inline void destroyIter() { _destroyIter(&_iterator); }
+
+ inline VariantData getCurrentKey() const { return _getKey(&_iterator, _metaType_id_key, _metaType_flags_value); }
+ inline VariantData getCurrentValue() const { return _getValue(&_iterator, _metaType_id_value, _metaType_flags_value); }
+
+ inline void find(const VariantData &key)
+ { _find(_iterable, key.data, &_iterator); }
+
+ int size() const { Q_ASSERT(_iterable); return _size(_iterable); }
+};
+
+template<typename From>
+struct QAssociativeIterableConvertFunctor
+{
+ QAssociativeIterableConvertFunctor() {}
+
+ QAssociativeIterableImpl operator()(const From& f) const
+ {
+ return QAssociativeIterableImpl(&f);
+ }
+};
+
+class QPairVariantInterfaceImpl
+{
+ const void *_pair;
+ int _metaType_id_first;
+ uint _metaType_flags_first;
+ int _metaType_id_second;
+ uint _metaType_flags_second;
+
+ typedef VariantData (*getFunc)(const void * const *p, int metaTypeId, uint flags);
+
+ getFunc _getFirst;
+ getFunc _getSecond;
+
+ template<class T>
+ static VariantData getFirstImpl(const void * const *pair, int metaTypeId, uint flags)
+ { return VariantData(metaTypeId, &static_cast<const T*>(*pair)->first, flags); }
+ template<class T>
+ static VariantData getSecondImpl(const void * const *pair, int metaTypeId, uint flags)
+ { return VariantData(metaTypeId, &static_cast<const T*>(*pair)->second, flags); }
+
+public:
+ template<class T> QPairVariantInterfaceImpl(const T*p)
+ : _pair(p)
+ , _metaType_id_first(qMetaTypeId<typename T::first_type>())
+ , _metaType_flags_first(QTypeInfo<typename T::first_type>::isPointer)
+ , _metaType_id_second(qMetaTypeId<typename T::second_type>())
+ , _metaType_flags_second(QTypeInfo<typename T::second_type>::isPointer)
+ , _getFirst(getFirstImpl<T>)
+ , _getSecond(getSecondImpl<T>)
+ {
+ }
+
+ QPairVariantInterfaceImpl()
+ : _pair(0)
+ , _getFirst(0)
+ , _getSecond(0)
+ {
+ }
+
+ inline VariantData first() const { return _getFirst(&_pair, _metaType_id_first, _metaType_flags_first); }
+ inline VariantData second() const { return _getSecond(&_pair, _metaType_id_second, _metaType_flags_second); }
+};
+
+template<typename From>
+struct QPairVariantInterfaceConvertFunctor;
+
+template<typename T, typename U>
+struct QPairVariantInterfaceConvertFunctor<QPair<T, U> >
+{
+ QPairVariantInterfaceConvertFunctor() {}
+
+ QPairVariantInterfaceImpl operator()(const QPair<T, U>& f) const
+ {
+ return QPairVariantInterfaceImpl(&f);
+ }
+};
+
+template<typename T, typename U>
+struct QPairVariantInterfaceConvertFunctor<std::pair<T, U> >
+{
+ QPairVariantInterfaceConvertFunctor() {}
+
+ QPairVariantInterfaceImpl operator()(const std::pair<T, U>& f) const
+ {
+ return QPairVariantInterfaceImpl(&f);
+ }
+};
+
}
class QObject;
@@ -509,6 +1318,176 @@ namespace QtPrivate
enum { Value = true };
};
+ template<typename T>
+ struct IsSequentialContainer
+ {
+ enum { Value = false };
+ };
+
+#define QT_DEFINE_SEQUENTIAL_CONTAINER_TYPE(CONTAINER) \
+ template<typename T> \
+ struct IsSequentialContainer<CONTAINER<T> > \
+ { \
+ enum { Value = true }; \
+ };
+ QT_FOR_EACH_AUTOMATIC_TEMPLATE_1ARG(QT_DEFINE_SEQUENTIAL_CONTAINER_TYPE)
+ QT_DEFINE_SEQUENTIAL_CONTAINER_TYPE(std::vector)
+ QT_DEFINE_SEQUENTIAL_CONTAINER_TYPE(std::list)
+
+ template<typename T>
+ struct IsAssociativeContainer
+ {
+ enum { Value = false };
+ };
+
+#define QT_DEFINE_ASSOCIATIVE_CONTAINER_TYPE(CONTAINER) \
+ template<typename T, typename U> \
+ struct IsAssociativeContainer<CONTAINER<T, U> > \
+ { \
+ enum { Value = true }; \
+ };
+ QT_DEFINE_ASSOCIATIVE_CONTAINER_TYPE(QHash)
+ QT_DEFINE_ASSOCIATIVE_CONTAINER_TYPE(QMap)
+ QT_DEFINE_ASSOCIATIVE_CONTAINER_TYPE(std::map)
+
+
+ template<typename T, bool = QtPrivate::IsSequentialContainer<T>::Value>
+ struct SequentialContainerConverterHelper
+ {
+ static bool registerConverter(int)
+ {
+ return false;
+ }
+ };
+
+ template<typename T, bool = QMetaTypeId2<typename T::value_type>::Defined>
+ struct ValueTypeIsMetaType
+ {
+ static bool registerConverter(int)
+ {
+ return false;
+ }
+ };
+
+ template<typename T>
+ struct ValueTypeIsMetaType<T, true>
+ {
+ static bool registerConverter(int id)
+ {
+ const int toId = qMetaTypeId<QtMetaTypePrivate::QSequentialIterableImpl>();
+ if (!QMetaType::hasRegisteredConverterFunction(id, toId)) {
+ static const QtMetaTypePrivate::QSequentialIterableConvertFunctor<T> o;
+ static const QtPrivate::ConverterFunctor<T,
+ QtMetaTypePrivate::QSequentialIterableImpl,
+ QtMetaTypePrivate::QSequentialIterableConvertFunctor<T> > f(o);
+ return QMetaType::registerConverterFunction(&f, id, toId);
+ }
+ return true;
+ }
+ };
+
+ template<typename T>
+ struct SequentialContainerConverterHelper<T, true> : ValueTypeIsMetaType<T>
+ {
+ };
+
+ template<typename T, bool = QtPrivate::IsAssociativeContainer<T>::Value>
+ struct AssociativeContainerConverterHelper
+ {
+ static bool registerConverter(int)
+ {
+ return false;
+ }
+ };
+
+ template<typename T, bool = QMetaTypeId2<typename T::mapped_type>::Defined>
+ struct AssociativeValueTypeIsMetaType
+ {
+ static bool registerConverter(int)
+ {
+ return false;
+ }
+ };
+
+ template<typename T>
+ struct AssociativeValueTypeIsMetaType<T, true>
+ {
+ static bool registerConverter(int id)
+ {
+ const int toId = qMetaTypeId<QtMetaTypePrivate::QAssociativeIterableImpl>();
+ if (!QMetaType::hasRegisteredConverterFunction(id, toId)) {
+ static const QtMetaTypePrivate::QAssociativeIterableConvertFunctor<T> o;
+ static const QtPrivate::ConverterFunctor<T,
+ QtMetaTypePrivate::QAssociativeIterableImpl,
+ QtMetaTypePrivate::QAssociativeIterableConvertFunctor<T> > f(o);
+ return QMetaType::registerConverterFunction(&f, id, toId);
+ }
+ return true;
+ }
+ };
+
+ template<typename T, bool = QMetaTypeId2<typename T::key_type>::Defined>
+ struct KeyAndValueTypeIsMetaType
+ {
+ static bool registerConverter(int)
+ {
+ return false;
+ }
+ };
+
+ template<typename T>
+ struct KeyAndValueTypeIsMetaType<T, true> : AssociativeValueTypeIsMetaType<T>
+ {
+ };
+
+ template<typename T>
+ struct AssociativeContainerConverterHelper<T, true> : KeyAndValueTypeIsMetaType<T>
+ {
+ };
+
+ template<typename T, bool = QMetaTypeId2<typename T::first_type>::Defined
+ && QMetaTypeId2<typename T::second_type>::Defined>
+ struct IsMetaTypePair
+ {
+ static bool registerConverter(int)
+ {
+ return false;
+ }
+ };
+
+ template<typename T>
+ struct IsMetaTypePair<T, true>
+ {
+ static bool registerConverter(int id)
+ {
+ const int toId = qMetaTypeId<QtMetaTypePrivate::QPairVariantInterfaceImpl>();
+ if (!QMetaType::hasRegisteredConverterFunction(id, toId)) {
+ static const QtMetaTypePrivate::QPairVariantInterfaceConvertFunctor<T> o;
+ static const QtPrivate::ConverterFunctor<T,
+ QtMetaTypePrivate::QPairVariantInterfaceImpl,
+ QtMetaTypePrivate::QPairVariantInterfaceConvertFunctor<T> > f(o);
+ return QMetaType::registerConverterFunction(&f, id, toId);
+ }
+ return true;
+ }
+ };
+
+ template<typename T>
+ struct IsPair
+ {
+ static bool registerConverter(int)
+ {
+ return false;
+ }
+ };
+ template<typename T, typename U>
+ struct IsPair<QPair<T, U> > : IsMetaTypePair<QPair<T, U> > {};
+ template<typename T, typename U>
+ struct IsPair<std::pair<T, U> > : IsMetaTypePair<std::pair<T, U> > {};
+
+ template<typename T>
+ struct MetaTypePairHelper : IsPair<T> {};
+
Q_CORE_EXPORT bool isBuiltinType(const QByteArray &type);
} // namespace QtPrivate
@@ -546,11 +1525,16 @@ namespace QtPrivate {
{ return -1; }
};
+#ifndef Q_COMPILER_VARIADIC_TEMPLATES
// Function pointers don't derive from QObject
template <class Result> struct IsPointerToTypeDerivedFromQObject<Result(*)()> { enum { Value = false }; };
template <class Result, class Arg0> struct IsPointerToTypeDerivedFromQObject<Result(*)(Arg0)> { enum { Value = false }; };
template <class Result, class Arg0, class Arg1> struct IsPointerToTypeDerivedFromQObject<Result(*)(Arg0, Arg1)> { enum { Value = false }; };
template <class Result, class Arg0, class Arg1, class Arg2> struct IsPointerToTypeDerivedFromQObject<Result(*)(Arg0, Arg1, Arg2)> { enum { Value = false }; };
+#else
+ template <typename Result, typename... Args>
+ struct IsPointerToTypeDerivedFromQObject<Result(*)(Args...)> { enum { Value = false }; };
+#endif
template<typename T>
struct QMetaTypeTypeFlags
@@ -593,7 +1577,7 @@ int qRegisterNormalizedMetaType(const QT_PREPEND_NAMESPACE(QByteArray) &normaliz
if (defined)
flags |= QMetaType::WasDeclaredAsMetaType;
- return QMetaType::registerNormalizedType(normalizedTypeName,
+ const int id = QMetaType::registerNormalizedType(normalizedTypeName,
QtMetaTypePrivate::QMetaTypeFunctionHelper<T>::Delete,
QtMetaTypePrivate::QMetaTypeFunctionHelper<T>::Create,
QtMetaTypePrivate::QMetaTypeFunctionHelper<T>::Destruct,
@@ -601,6 +1585,14 @@ int qRegisterNormalizedMetaType(const QT_PREPEND_NAMESPACE(QByteArray) &normaliz
int(sizeof(T)),
flags,
QtPrivate::MetaObjectForType<T>::value());
+
+ if (id > 0) {
+ QtPrivate::SequentialContainerConverterHelper<T>::registerConverter(id);
+ QtPrivate::AssociativeContainerConverterHelper<T>::registerConverter(id);
+ QtPrivate::MetaTypePairHelper<T>::registerConverter(id);
+ }
+
+ return id;
}
template <typename T>
@@ -846,19 +1838,6 @@ struct QMetaTypeId< SMART_POINTER<T> > : public QMetaTypeId_ ## SMART_POINTER ##
{ \
};
-#define QT_FOR_EACH_AUTOMATIC_TEMPLATE_1ARG(F) \
- F(QList) \
- F(QVector) \
- F(QQueue) \
- F(QStack) \
- F(QSet) \
- F(QLinkedList)
-
-#define QT_FOR_EACH_AUTOMATIC_TEMPLATE_2ARG(F) \
- F(QHash, class) \
- F(QMap, class) \
- F(QPair, struct)
-
#define QT_FOR_EACH_AUTOMATIC_TEMPLATE_SMART_POINTER(F) \
F(QSharedPointer) \
F(QWeakPointer) \
@@ -872,6 +1851,9 @@ QT_FOR_EACH_AUTOMATIC_TEMPLATE_1ARG(Q_DECLARE_METATYPE_TEMPLATE_1ARG_ITER)
#undef Q_DECLARE_METATYPE_TEMPLATE_1ARG_ITER
+Q_DECLARE_METATYPE_TEMPLATE_1ARG(std::vector)
+Q_DECLARE_METATYPE_TEMPLATE_1ARG(std::list)
+
#define Q_DECLARE_METATYPE_TEMPLATE_2ARG_ITER(TEMPLATENAME, CPPTYPE) \
template <class T1, class T2> CPPTYPE TEMPLATENAME; \
Q_DECLARE_METATYPE_TEMPLATE_2ARG(TEMPLATENAME)
@@ -880,6 +1862,9 @@ QT_FOR_EACH_AUTOMATIC_TEMPLATE_2ARG(Q_DECLARE_METATYPE_TEMPLATE_2ARG_ITER)
#undef Q_DECLARE_METATYPE_TEMPLATE_2ARG_ITER
+Q_DECLARE_METATYPE_TEMPLATE_2ARG(std::pair)
+Q_DECLARE_METATYPE_TEMPLATE_2ARG(std::map)
+
#define Q_DECLARE_METATYPE_TEMPLATE_SMART_POINTER_ITER(TEMPLATENAME) \
Q_DECLARE_SMART_POINTER_METATYPE(TEMPLATENAME)
@@ -987,5 +1972,50 @@ QT_END_NAMESPACE
QT_FOR_EACH_STATIC_TYPE(Q_DECLARE_BUILTIN_METATYPE)
+Q_DECLARE_METATYPE(QtMetaTypePrivate::QSequentialIterableImpl)
+Q_DECLARE_METATYPE(QtMetaTypePrivate::QAssociativeIterableImpl)
+Q_DECLARE_METATYPE(QtMetaTypePrivate::QPairVariantInterfaceImpl)
+
+QT_BEGIN_NAMESPACE
+
+#ifndef Q_QDOC
+template<typename T>
+#endif
+bool qRegisterSequentialConverter()
+{
+ Q_STATIC_ASSERT_X(QMetaTypeId2<typename T::value_type>::Defined,
+ "The value_type of a sequential container must itself be a metatype.");
+ const int id = qMetaTypeId<T>();
+ const int toId = qMetaTypeId<QtMetaTypePrivate::QSequentialIterableImpl>();
+ if (QMetaType::hasRegisteredConverterFunction(id, toId))
+ return true;
+
+ static const QtMetaTypePrivate::QSequentialIterableConvertFunctor<T> o;
+ static const QtPrivate::ConverterFunctor<T,
+ QtMetaTypePrivate::QSequentialIterableImpl,
+ QtMetaTypePrivate::QSequentialIterableConvertFunctor<T> > f(o);
+ return QMetaType::registerConverterFunction(&f, id, toId);
+}
+
+template<typename T>
+bool qRegisterAssociativeConverter()
+{
+ Q_STATIC_ASSERT_X(QMetaTypeId2<typename T::key_type>::Defined
+ && QMetaTypeId2<typename T::mapped_type>::Defined,
+ "The key_type and mapped_type of an associative container must themselves be metatypes.");
+
+ const int id = qMetaTypeId<T>();
+ const int toId = qMetaTypeId<QtMetaTypePrivate::QAssociativeIterableImpl>();
+ if (QMetaType::hasRegisteredConverterFunction(id, toId))
+ return true;
+ static const QtMetaTypePrivate::QAssociativeIterableConvertFunctor<T> o;
+ static const QtPrivate::ConverterFunctor<T,
+ QtMetaTypePrivate::QAssociativeIterableImpl,
+ QtMetaTypePrivate::QAssociativeIterableConvertFunctor<T> > f(o);
+
+ return QMetaType::registerConverterFunction(&f, id, toId);
+}
+
+QT_END_NAMESPACE
#endif // QMETATYPE_H
diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp
index 02794e9fe3..997a65169d 100644
--- a/src/corelib/kernel/qobject.cpp
+++ b/src/corelib/kernel/qobject.cpp
@@ -4255,7 +4255,7 @@ void qDeleteInEventHandler(QObject *o)
must not have an overloaded or templated operator().
*/
-/**
+/*!
\internal
Implementation of the template version of connect
@@ -4280,12 +4280,13 @@ QMetaObject::Connection QObject::connectImpl(const QObject *sender, void **signa
QtPrivate::QSlotObjectBase *slotObj, Qt::ConnectionType type,
const int *types, const QMetaObject *senderMetaObject)
{
- if (!sender || !signal || !slotObj || !senderMetaObject) {
+ if (!signal) {
qWarning("QObject::connect: invalid null parameter");
if (slotObj)
slotObj->destroyIfLastRef();
return QMetaObject::Connection();
}
+
int signal_index = -1;
void *args[] = { &signal_index, signal };
for (; senderMetaObject && signal_index < 0; senderMetaObject = senderMetaObject->superClass()) {
@@ -4299,6 +4300,27 @@ QMetaObject::Connection QObject::connectImpl(const QObject *sender, void **signa
return QMetaObject::Connection(0);
}
signal_index += QMetaObjectPrivate::signalOffset(senderMetaObject);
+ return QObjectPrivate::connectImpl(sender, signal_index, receiver, slot, slotObj, type, types, senderMetaObject);
+}
+
+/*!
+ \internal
+
+ Internal version of connect used by the template version of QObject::connect (called via connectImpl) and
+ also used by the QObjectPrivate::connect version used by QML. The signal_index is expected to be relative
+ to the number of signals.
+ */
+QMetaObject::Connection QObjectPrivate::connectImpl(const QObject *sender, int signal_index,
+ const QObject *receiver, void **slot,
+ QtPrivate::QSlotObjectBase *slotObj, Qt::ConnectionType type,
+ const int *types, const QMetaObject *senderMetaObject)
+{
+ if (!sender || !slotObj || !senderMetaObject) {
+ qWarning("QObject::connect: invalid null parameter");
+ if (slotObj)
+ slotObj->destroyIfLastRef();
+ return QMetaObject::Connection();
+ }
QObject *s = const_cast<QObject *>(sender);
QObject *r = const_cast<QObject *>(receiver);
@@ -4469,6 +4491,40 @@ bool QObject::disconnectImpl(const QObject *sender, void **signal, const QObject
return QMetaObjectPrivate::disconnect(sender, signal_index, senderMetaObject, receiver, -1, slot);
}
+/*!
+ \internal
+ Used by QML to connect a signal by index to a slot implemented in JavaScript (wrapped in a custom QSlotOBjectBase subclass).
+
+ The signal_index is an index relative to the number of methods.
+ */
+QMetaObject::Connection QObjectPrivate::connect(const QObject *sender, int signal_index, QtPrivate::QSlotObjectBase *slotObj, Qt::ConnectionType type)
+{
+ if (!sender) {
+ qWarning("QObject::connect: invalid null parameter");
+ if (slotObj)
+ slotObj->destroyIfLastRef();
+ return QMetaObject::Connection();
+ }
+ const QMetaObject *senderMetaObject = sender->metaObject();
+ signal_index = methodIndexToSignalIndex(&senderMetaObject, signal_index);
+
+ return QObjectPrivate::connectImpl(sender, signal_index, sender, /*slot*/0, slotObj, type, /*types*/0, senderMetaObject);
+}
+
+/*!
+ \internal
+ Used by QML to disconnect a signal by index that's connected to a slot implemented in JavaScript (wrapped in a custom QSlotObjectBase subclass)
+ In the QML case the slot is not a pointer to a pointer to the function to disconnect, but instead it is a pointer to an array of internal values
+ required for the disconnect.
+ */
+bool QObjectPrivate::disconnect(const QObject *sender, int signal_index, void **slot)
+{
+ const QMetaObject *senderMetaObject = sender->metaObject();
+ signal_index = methodIndexToSignalIndex(&senderMetaObject, signal_index);
+
+ return QMetaObjectPrivate::disconnect(sender, signal_index, senderMetaObject, sender, -1, slot);
+}
+
/*! \class QMetaObject::Connection
\inmodule QtCore
Represents a handle to a signal-slot connection.
diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h
index e849ec1599..3c43972ac9 100644
--- a/src/corelib/kernel/qobject_p.h
+++ b/src/corelib/kernel/qobject_p.h
@@ -207,6 +207,13 @@ public:
template <typename Func1, typename Func2>
static inline bool disconnect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal,
const typename QtPrivate::FunctionPointer<Func2>::Object *receiverPrivate, Func2 slot);
+
+ static QMetaObject::Connection connectImpl(const QObject *sender, int signal_index,
+ const QObject *receiver, void **slot,
+ QtPrivate::QSlotObjectBase *slotObj, Qt::ConnectionType type,
+ const int *types, const QMetaObject *senderMetaObject);
+ static QMetaObject::Connection connect(const QObject *sender, int signal_index, QtPrivate::QSlotObjectBase *slotObj, Qt::ConnectionType type);
+ static bool disconnect(const QObject *sender, int signal_index, void **slot);
public:
ExtraData *extraData; // extra data set by the user
QThreadData *threadData; // id of the thread that owns the object
diff --git a/src/corelib/kernel/qobjectdefs.h b/src/corelib/kernel/qobjectdefs.h
index afbe1a5ece..c489344b10 100644
--- a/src/corelib/kernel/qobjectdefs.h
+++ b/src/corelib/kernel/qobjectdefs.h
@@ -456,6 +456,7 @@ class Q_CORE_EXPORT QMetaObject::Connection {
void *d_ptr; //QObjectPrivate::Connection*
explicit Connection(void *data) : d_ptr(data) { }
friend class QObject;
+ friend class QObjectPrivate;
friend struct QMetaObject;
public:
~Connection();
diff --git a/src/corelib/kernel/qsocketnotifier.cpp b/src/corelib/kernel/qsocketnotifier.cpp
index e0c7f171c3..6c88ed4531 100644
--- a/src/corelib/kernel/qsocketnotifier.cpp
+++ b/src/corelib/kernel/qsocketnotifier.cpp
@@ -181,17 +181,16 @@ QSocketNotifier::QSocketNotifier(qintptr socket, Type type, QObject *parent)
: QObject(*new QSocketNotifierPrivate, parent)
{
Q_D(QSocketNotifier);
- if (socket < 0)
- qWarning("QSocketNotifier: Invalid socket specified");
d->sockfd = socket;
d->sntype = type;
d->snenabled = true;
- if (!d->threadData->eventDispatcher.load()) {
+ if (socket < 0)
+ qWarning("QSocketNotifier: Invalid socket specified");
+ else if (!d->threadData->eventDispatcher.load())
qWarning("QSocketNotifier: Can only be used with threads started with QThread");
- } else {
+ else
d->threadData->eventDispatcher.load()->registerSocketNotifier(this);
- }
}
/*!
diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp
index 276257ddcf..24bf25baea 100644
--- a/src/corelib/kernel/qvariant.cpp
+++ b/src/corelib/kernel/qvariant.cpp
@@ -269,6 +269,16 @@ inline bool qt_convertToBool(const QVariant::Private *const d)
/*!
\internal
+ Returns the internal data pointer from \a d.
+ */
+
+static const void *constData(const QVariant::Private &d)
+{
+ return d.is_shared ? d.data.shared->ptr : reinterpret_cast<const void *>(&d.data.c);
+}
+
+/*!
+ \internal
Converts \a d to type \a t, which is placed in \a result.
*/
@@ -277,6 +287,14 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok)
Q_ASSERT(d->type != uint(t));
Q_ASSERT(result);
+ if (d->type >= QMetaType::User || t >= QMetaType::User) {
+ const bool isOk = QMetaType::convert(constData(*d), d->type, result, t);
+ if (ok)
+ *ok = isOk;
+ if (isOk)
+ return true;
+ }
+
bool dummy;
if (!ok)
ok = &dummy;
@@ -867,8 +885,15 @@ static bool customCompare(const QVariant::Private *a, const QVariant::Private *b
return !memcmp(a_ptr, b_ptr, QMetaType::sizeOf(a->type));
}
-static bool customConvert(const QVariant::Private *, int, void *, bool *ok)
+static bool customConvert(const QVariant::Private *d, int t, void *result, bool *ok)
{
+ if (d->type >= QMetaType::User || t >= QMetaType::User) {
+ const bool isOk = QMetaType::convert(constData(*d), d->type, result, t);
+ if (ok)
+ *ok = isOk;
+ return isOk;
+ }
+
if (ok)
*ok = false;
return false;
@@ -1958,6 +1983,12 @@ inline T qVariantToHelper(const QVariant::Private &d, const HandlersManager &han
return *v_cast<T>(&d);
T ret;
+ if (d.type >= QMetaType::User || targetType >= QMetaType::User) {
+ const void * const from = constData(d);
+ if (QMetaType::convert(from, d.type, &ret, targetType))
+ return ret;
+ }
+
handlerManager[d.type]->convert(&d, targetType, &ret, 0);
return ret;
}
@@ -2374,13 +2405,19 @@ template <typename T>
inline T qNumVariantToHelper(const QVariant::Private &d,
const HandlersManager &handlerManager, bool *ok, const T& val)
{
- uint t = qMetaTypeId<T>();
+ const uint t = qMetaTypeId<T>();
if (ok)
*ok = true;
+
if (d.type == t)
return val;
T ret = 0;
+ if ((d.type >= QMetaType::User || t >= QMetaType::User)
+ && QMetaType::convert(&val, d.type, &ret, t)) {
+ return ret;
+ }
+
if (!handlerManager[d.type]->convert(&d, t, &ret, ok) && ok)
*ok = false;
return ret;
@@ -2735,10 +2772,52 @@ static bool canConvertMetaObject(int fromId, int toId, QObject *fromObject)
function if a qobject_cast to the type described by \a targetTypeId would succeed. Note that
this only works for QObject subclasses which use the Q_OBJECT macro.
- \sa convert()
+ A QVariant containing a sequential container will also return true for this
+ function if the \a targetTypeId is QVariantList. It is possible to iterate over
+ the contents of the container without extracting it as a (copied) QVariantList:
+
+ \snippet code/src_corelib_kernel_qvariant.cpp 9
+
+ This requires that the value_type of the container is itself a metatype.
+
+ Similarly, a QVariant containing a sequential container will also return true for this
+ function the \a targetTypeId is QVariantHash or QVariantMap. It is possible to iterate over
+ the contents of the container without extracting it as a (copied) QVariantHash or QVariantMap:
+
+ \snippet code/src_corelib_kernel_qvariant.cpp 10
+
+ \sa convert(), QSequentialIterable, qRegisterSequentialConverter(), QAssociativeIterable,
+ qRegisterAssociativeConverter()
*/
bool QVariant::canConvert(int targetTypeId) const
{
+ if (targetTypeId == QMetaType::QVariantList
+ && (d.type == QMetaType::QVariantList
+ || d.type == QMetaType::QStringList
+ || QMetaType::hasRegisteredConverterFunction(d.type,
+ qMetaTypeId<QtMetaTypePrivate::QSequentialIterableImpl>()))) {
+ return true;
+ }
+
+ if ((targetTypeId == QMetaType::QVariantHash || targetTypeId == QMetaType::QVariantMap)
+ && (d.type == QMetaType::QVariantMap
+ || d.type == QMetaType::QVariantHash
+ || QMetaType::hasRegisteredConverterFunction(d.type,
+ qMetaTypeId<QtMetaTypePrivate::QAssociativeIterableImpl>()))) {
+ return true;
+ }
+
+ if (targetTypeId == qMetaTypeId<QPair<QVariant, QVariant> >() &&
+ QMetaType::hasRegisteredConverterFunction(d.type,
+ qMetaTypeId<QtMetaTypePrivate::QPairVariantInterfaceImpl>())) {
+ return true;
+ }
+
+ if ((d.type >= QMetaType::User || targetTypeId >= QMetaType::User)
+ && QMetaType::hasRegisteredConverterFunction(d.type, targetTypeId)) {
+ return true;
+ }
+
// TODO Reimplement this function, currently it works but it is a historical mess.
uint currentType = ((d.type == QMetaType::Float) ? QVariant::Double : d.type);
if (currentType == QMetaType::SChar || currentType == QMetaType::Char)
@@ -2886,7 +2965,6 @@ bool QVariant::convert(int targetTypeId)
*/
bool QVariant::convert(const int type, void *ptr) const
{
- Q_ASSERT(type < int(QMetaType::User));
return handlerManager[type]->convert(&d, type, ptr, 0);
}
@@ -2908,8 +2986,9 @@ bool QVariant::convert(const int type, void *ptr) const
which means that two values can be equal even if one of them is null and
another is not.
- \warning This function doesn't support custom types registered
- with qRegisterMetaType().
+ \warning To make this function work with a custom type registered with
+ qRegisterMetaType(), its comparison operator must be registered using
+ QMetaType::registerComparators().
*/
/*!
\fn bool operator!=(const QVariant &v1, const QVariant &v2)
@@ -2918,8 +2997,9 @@ bool QVariant::convert(const int type, void *ptr) const
Returns false if \a v1 and \a v2 are equal; otherwise returns true.
- \warning This function doesn't support custom types registered
- with qRegisterMetaType().
+ \warning To make this function work with a custom type registered with
+ qRegisterMetaType(), its comparison operator must be registered using
+ QMetaType::registerComparators().
*/
/*! \fn bool QVariant::operator==(const QVariant &v) const
@@ -2932,8 +3012,9 @@ bool QVariant::convert(const int type, void *ptr) const
type is not the same as this variant's type. See canConvert() for
a list of possible conversions.
- \warning This function doesn't support custom types registered
- with qRegisterMetaType().
+ \warning To make this function work with a custom type registered with
+ qRegisterMetaType(), its comparison operator must be registered using
+ QMetaType::registerComparators().
*/
/*!
@@ -2942,8 +3023,61 @@ bool QVariant::convert(const int type, void *ptr) const
Compares this QVariant with \a v and returns true if they are not
equal; otherwise returns false.
- \warning This function doesn't support custom types registered
- with qRegisterMetaType().
+ \warning To make this function work with a custom type registered with
+ qRegisterMetaType(), its comparison operator must be registered using
+ QMetaType::registerComparators().
+*/
+
+/*!
+ \fn bool QVariant::operator<(const QVariant &v) const
+
+ Compares this QVariant with \a v and returns true if this is less than \a v.
+
+ \note Comparability might not be availabe for the type stored in this QVariant
+ or in \a v.
+
+ \warning To make this function work with a custom type registered with
+ qRegisterMetaType(), its comparison operator must be registered using
+ QMetaType::registerComparators().
+*/
+
+/*!
+ \fn bool QVariant::operator<=(const QVariant &v) const
+
+ Compares this QVariant with \a v and returns true if this is less or equal than \a v.
+
+ \note Comparability might not be available for the type stored in this QVariant
+ or in \a v.
+
+ \warning To make this function work with a custom type registered with
+ qRegisterMetaType(), its comparison operator must be registered using
+ QMetaType::registerComparators().
+*/
+
+/*!
+ \fn bool QVariant::operator>(const QVariant &v) const
+
+ Compares this QVariant with \a v and returns true if this is larger than \a v.
+
+ \note Comparability might not be available for the type stored in this QVariant
+ or in \a v.
+
+ \warning To make this function work with a custom type registered with
+ qRegisterMetaType(), its comparison operator must be registered using
+ QMetaType::registerComparators().
+*/
+
+/*!
+ \fn bool QVariant::operator>=(const QVariant &v) const
+
+ Compares this QVariant with \a v and returns true if this is larger or equal than \a v.
+
+ \note Comparability might not be available for the type stored in this QVariant
+ or in \a v.
+
+ \warning To make this function work with a custom type registered with
+ qRegisterMetaType(), its comparison operator must be registered using
+ QMetaType::registerComparators().
*/
static bool qIsNumericType(uint tp)
@@ -2962,6 +3096,7 @@ static bool qIsFloatingPoint(uint tp)
*/
bool QVariant::cmp(const QVariant &v) const
{
+ QVariant v1 = *this;
QVariant v2 = v;
if (d.type != v2.d.type) {
if (qIsNumericType(d.type) && qIsNumericType(v.d.type)) {
@@ -2970,10 +3105,63 @@ bool QVariant::cmp(const QVariant &v) const
else
return toLongLong() == v.toLongLong();
}
- if (!v2.canConvert(d.type) || !v2.convert(d.type))
+ if (!v2.canConvert(v1.d.type) || !v2.convert(v1.d.type))
return false;
}
- return handlerManager[d.type]->compare(&d, &v2.d);
+ if (v1.d.type >= QMetaType::User) {
+ int result;
+ if (QMetaType::compare(QT_PREPEND_NAMESPACE(constData(v1.d)), QT_PREPEND_NAMESPACE(constData(v2.d)), v1.d.type, &result))
+ return result == 0;
+ }
+ return handlerManager[v1.d.type]->compare(&v1.d, &v2.d);
+}
+
+/*!
+ \internal
+ */
+int QVariant::compare(const QVariant &v) const
+{
+ if (cmp(v))
+ return 0;
+ QVariant v1 = *this;
+ QVariant v2 = v;
+ if (v1.d.type != v2.d.type) {
+ // if both types differ, try to convert
+ if (v2.canConvert(v1.d.type)) {
+ QVariant temp = v2;
+ if (temp.convert(v1.d.type))
+ v2 = temp;
+ }
+ if (v1.d.type != v2.d.type && v1.canConvert(v2.d.type)) {
+ QVariant temp = v1;
+ if (temp.convert(v2.d.type))
+ v1 = temp;
+ }
+ if (v1.d.type != v2.d.type) {
+ // if conversion fails, default to toString
+ return v1.toString().compare(v2.toString(), Qt::CaseInsensitive);
+ }
+ }
+ if (v1.d.type >= QMetaType::User) {
+ int result;
+ if (QMetaType::compare(QT_PREPEND_NAMESPACE(constData(d)), QT_PREPEND_NAMESPACE(constData(v2.d)), d.type, &result))
+ return result;
+ }
+ if (qIsNumericType(v1.d.type)) {
+ if (qIsFloatingPoint(v1.d.type))
+ return v1.toReal() < v2.toReal() ? -1 : 1;
+ else
+ return v1.toLongLong() < v2.toLongLong() ? -1 : 1;
+ }
+ switch (v1.d.type) {
+ case QVariant::Date:
+ return v1.toDate() < v2.toDate() ? -1 : 1;
+ case QVariant::Time:
+ return v1.toTime() < v2.toTime() ? -1 : 1;
+ case QVariant::DateTime:
+ return v1.toDateTime() < v2.toDateTime() ? -1 : 1;
+ }
+ return v1.toString().compare(v2.toString(), Qt::CaseInsensitive);
}
/*!
@@ -3022,7 +3210,16 @@ QDebug operator<<(QDebug dbg, const QVariant &v)
dbg.nospace() << "QVariant(";
if (typeId != QMetaType::UnknownType) {
dbg.nospace() << QMetaType::typeName(typeId) << ", ";
- handlerManager[typeId]->debugStream(dbg, v);
+ bool userStream = false;
+ bool canConvertToString = false;
+ if (typeId >= QMetaType::User) {
+ userStream = QMetaType::debugStream(dbg, constData(v.d), typeId);
+ canConvertToString = v.canConvert<QString>();
+ }
+ if (!userStream && canConvertToString)
+ dbg << v.toString();
+ else if (!userStream)
+ handlerManager[typeId]->debugStream(dbg, v);
} else {
dbg.nospace() << "Invalid";
}
@@ -3074,7 +3271,12 @@ QDebug operator<<(QDebug dbg, const QVariant::Type p)
returned. Note that this only works for QObject subclasses which use the
Q_OBJECT macro.
- \sa setValue(), fromValue(), canConvert()
+ If the QVariant contains a sequential container and \c{T} is QVariantList, the
+ elements of the container will be converted into QVariants and returned as a QVariantList.
+
+ \snippet code/src_corelib_kernel_qvariant.cpp 9
+
+ \sa setValue(), fromValue(), canConvert(), qRegisterSequentialConverter()
*/
/*! \fn bool QVariant::canConvert() const
@@ -3226,4 +3428,359 @@ QDebug operator<<(QDebug dbg, const QVariant::Type p)
\internal
*/
+/*!
+ \class QSequentialIterable
+
+ \inmodule QtCore
+ \brief The QSequentialIterable class is an iterable interface for a container in a QVariant.
+
+ This class allows several methods of accessing the elements of a container held within
+ a QVariant. An instance of QSequentialIterable can be extracted from a QVariant if it can
+ be converted to a QVariantList.
+
+ \snippet code/src_corelib_kernel_qvariant.cpp 9
+
+ The container itself is not copied before iterating over it.
+
+ \sa QVariant
+*/
+
+/*! \fn QSequentialIterable::QSequentialIterable(QtMetaTypePrivate::QSequentialIterableImpl)
+
+ \internal
+*/
+
+/*! \fn QSequentialIterable::const_iterator QSequentialIterable::begin() const
+
+ Returns a QSequentialIterable::const_iterator for the beginning of the container. This
+ can be used in stl-style iteration.
+
+ \sa end()
+*/
+
+/*! \fn QSequentialIterable::const_iterator QSequentialIterable::end() const
+
+ Returns a QSequentialIterable::const_iterator for the end of the container. This
+ can be used in stl-style iteration.
+
+ \sa begin()
+*/
+
+/*! \fn QVariant QSequentialIterable::at(int idx) const
+
+ Returns the element at position \a idx in the container.
+*/
+
+/*! \fn int QSequentialIterable::size() const
+
+ Returns the number of elements in the container.
+*/
+
+/*! \fn bool QSequentialIterable::canReverseIterate() const
+
+ Returns whether it is possible to iterate over the container in reverse. This
+ corresponds to the std::bidirectional_iterator_tag iterator trait of the
+ const_iterator of the container.
+*/
+
+/*!
+ \class QSequentialIterable::const_iterator
+
+ \inmodule QtCore
+ \brief The QSequentialIterable::const_iterator allows iteration over a container in a QVariant.
+
+ A QSequentialIterable::const_iterator can only be created by a QSequentialIterable instance,
+ and can be used in a way similar to other stl-style iterators.
+
+ \snippet code/src_corelib_kernel_qvariant.cpp 9
+
+ \sa QSequentialIterable
+*/
+
+
+/*! \fn QSequentialIterable::const_iterator::~const_iterator()
+
+ Destroys the QSequentialIterable::const_iterator.
+*/
+
+/*! \fn QSequentialIterable::const_iterator::const_iterator(const const_iterator &other)
+
+ Creates a copy of \a other.
+*/
+
+/*! \fn QVariant QSequentialIterable::const_iterator::operator*() const
+
+ Returns the current item, converted to a QVariant.
+*/
+
+/*! \fn bool QSequentialIterable::const_iterator::operator==(const const_iterator &other) const
+
+ Returns true if \a other points to the same item as this
+ iterator; otherwise returns false.
+
+ \sa operator!=()
+*/
+
+/*! \fn bool QSequentialIterable::const_iterator::operator!=(const const_iterator &other) const
+
+ Returns true if \a other points to a different item than this
+ iterator; otherwise returns false.
+
+ \sa operator==()
+*/
+
+/*! \fn QSequentialIterable::const_iterator &QSequentialIterable::const_iterator::operator++()
+
+ The prefix ++ operator (\c{++it}) advances the iterator to the
+ next item in the container and returns an iterator to the new current
+ item.
+
+ Calling this function on QSequentialIterable::end() leads to undefined results.
+
+ \sa operator--()
+*/
+
+/*! \fn QSequentialIterable::const_iterator QSequentialIterable::const_iterator::operator++(int)
+
+ \overload
+
+ The postfix ++ operator (\c{it++}) advances the iterator to the
+ next item in the container and returns an iterator to the previously
+ current item.
+*/
+
+/*! \fn QSequentialIterable::const_iterator &QSequentialIterable::const_iterator::operator--()
+
+ The prefix -- operator (\c{--it}) makes the preceding item
+ current and returns an iterator to the new current item.
+
+ Calling this function on QSequentialIterable::begin() leads to undefined results.
+
+ If the container in the QVariant does not support bi-directional iteration, calling this function
+ leads to undefined results.
+
+ \sa operator++(), canReverseIterate()
+*/
+
+/*! \fn QSequentialIterable::const_iterator QSequentialIterable::const_iterator::operator--(int)
+
+ \overload
+
+ The postfix -- operator (\c{it--}) makes the preceding item
+ current and returns an iterator to the previously current item.
+
+ If the container in the QVariant does not support bi-directional iteration, calling this function
+ leads to undefined results.
+
+ \sa canReverseIterate()
+*/
+
+/*! \fn QSequentialIterable::const_iterator &QSequentialIterable::const_iterator::operator+=(int j)
+
+ Advances the iterator by \a j items.
+
+ \sa operator-=(), operator+()
+*/
+
+/*! \fn QSequentialIterable::const_iterator &QSequentialIterable::const_iterator::operator-=(int j)
+
+ Makes the iterator go back by \a j items.
+
+ If the container in the QVariant does not support bi-directional iteration, calling this function
+ leads to undefined results.
+
+ \sa operator+=(), operator-(), canReverseIterate()
+*/
+
+/*! \fn QSequentialIterable::const_iterator QSequentialIterable::const_iterator::operator+(int j) const
+
+ Returns an iterator to the item at \a j positions forward from
+ this iterator.
+
+ \sa operator-(), operator+=()
+*/
+
+/*! \fn QSequentialIterable::const_iterator QSequentialIterable::const_iterator::operator-(int j) const
+
+ Returns an iterator to the item at \a j positions backward from
+ this iterator.
+
+ If the container in the QVariant does not support bi-directional iteration, calling this function
+ leads to undefined results.
+
+ \sa operator+(), operator-=(), canReverseIterate()
+*/
+
+/*!
+ \class QAssociativeIterable
+
+ \inmodule QtCore
+ \brief The QAssociativeIterable class is an iterable interface for an associative container in a QVariant.
+
+ This class allows several methods of accessing the elements of an associative container held within
+ a QVariant. An instance of QAssociativeIterable can be extracted from a QVariant if it can
+ be converted to a QVariantHash or QVariantMap.
+
+ \snippet code/src_corelib_kernel_qvariant.cpp 10
+
+ The container itself is not copied before iterating over it.
+
+ \sa QVariant
+*/
+
+/*! \fn QAssociativeIterable::QAssociativeIterable(QtMetaTypePrivate::QAssociativeIterableImpl)
+
+ \internal
+*/
+
+/*! \fn QAssociativeIterable::const_iterator QAssociativeIterable::begin() const
+
+ Returns a QAssociativeIterable::const_iterator for the beginning of the container. This
+ can be used in stl-style iteration.
+
+ \sa end()
+*/
+
+/*! \fn QAssociativeIterable::const_iterator QAssociativeIterable::end() const
+
+ Returns a QAssociativeIterable::const_iterator for the end of the container. This
+ can be used in stl-style iteration.
+
+ \sa begin()
+*/
+
+/*! \fn QVariant QAssociativeIterable::value(const QVariant &key) const
+
+ Returns the value for the given \a key in the container, if the types are convertible.
+*/
+
+/*! \fn int QAssociativeIterable::size() const
+
+ Returns the number of elements in the container.
+*/
+
+/*!
+ \class QAssociativeIterable::const_iterator
+
+ \inmodule QtCore
+ \brief The QAssociativeIterable::const_iterator allows iteration over a container in a QVariant.
+
+ A QAssociativeIterable::const_iterator can only be created by a QAssociativeIterable instance,
+ and can be used in a way similar to other stl-style iterators.
+
+ \snippet code/src_corelib_kernel_qvariant.cpp 10
+
+ \sa QAssociativeIterable
+*/
+
+
+/*! \fn QAssociativeIterable::const_iterator::~const_iterator()
+
+ Destroys the QAssociativeIterable::const_iterator.
+*/
+
+/*! \fn QAssociativeIterable::const_iterator::const_iterator(const const_iterator &other)
+
+ Creates a copy of \a other.
+*/
+
+/*! \fn QVariant QAssociativeIterable::const_iterator::operator*() const
+
+ Returns the current value, converted to a QVariant.
+*/
+
+/*! \fn QVariant QAssociativeIterable::const_iterator::key() const
+
+ Returns the current key, converted to a QVariant.
+*/
+
+/*! \fn QVariant QAssociativeIterable::const_iterator::value() const
+
+ Returns the current value, converted to a QVariant.
+*/
+
+/*! \fn bool QAssociativeIterable::const_iterator::operator==(const const_iterator &other) const
+
+ Returns true if \a other points to the same item as this
+ iterator; otherwise returns false.
+
+ \sa operator!=()
+*/
+
+/*! \fn bool QAssociativeIterable::const_iterator::operator!=(const const_iterator &other) const
+
+ Returns true if \a other points to a different item than this
+ iterator; otherwise returns false.
+
+ \sa operator==()
+*/
+
+/*! \fn QAssociativeIterable::const_iterator &QAssociativeIterable::const_iterator::operator++()
+
+ The prefix ++ operator (\c{++it}) advances the iterator to the
+ next item in the container and returns an iterator to the new current
+ item.
+
+ Calling this function on QAssociativeIterable::end() leads to undefined results.
+
+ \sa operator--()
+*/
+
+/*! \fn QAssociativeIterable::const_iterator QAssociativeIterable::const_iterator::operator++(int)
+
+ \overload
+
+ The postfix ++ operator (\c{it++}) advances the iterator to the
+ next item in the container and returns an iterator to the previously
+ current item.
+*/
+
+/*! \fn QAssociativeIterable::const_iterator &QAssociativeIterable::const_iterator::operator--()
+
+ The prefix -- operator (\c{--it}) makes the preceding item
+ current and returns an iterator to the new current item.
+
+ Calling this function on QAssociativeIterable::begin() leads to undefined results.
+
+ \sa operator++()
+*/
+
+/*! \fn QAssociativeIterable::const_iterator QAssociativeIterable::const_iterator::operator--(int)
+
+ \overload
+
+ The postfix -- operator (\c{it--}) makes the preceding item
+ current and returns an iterator to the previously current item.
+*/
+
+/*! \fn QAssociativeIterable::const_iterator &QAssociativeIterable::const_iterator::operator+=(int j)
+
+ Advances the iterator by \a j items.
+
+ \sa operator-=(), operator+()
+*/
+
+/*! \fn QAssociativeIterable::const_iterator &QAssociativeIterable::const_iterator::operator-=(int j)
+
+ Makes the iterator go back by \a j items.
+
+ \sa operator+=(), operator-()
+*/
+
+/*! \fn QAssociativeIterable::const_iterator QAssociativeIterable::const_iterator::operator+(int j) const
+
+ Returns an iterator to the item at \a j positions forward from
+ this iterator.
+
+ \sa operator-(), operator+=()
+*/
+
+/*! \fn QAssociativeIterable::const_iterator QAssociativeIterable::const_iterator::operator-(int j) const
+
+ Returns an iterator to the item at \a j positions backward from
+ this iterator.
+
+ \sa operator+(), operator-=()
+*/
+
QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h
index 6f212f5000..d5ea491288 100644
--- a/src/corelib/kernel/qvariant.h
+++ b/src/corelib/kernel/qvariant.h
@@ -49,6 +49,7 @@
#include <QtCore/qmap.h>
#include <QtCore/qhash.h>
#include <QtCore/qstring.h>
+#include <QtCore/qstringlist.h>
#include <QtCore/qobject.h>
QT_BEGIN_NAMESPACE
@@ -432,6 +433,14 @@ class Q_CORE_EXPORT QVariant
{ return cmp(v); }
inline bool operator!=(const QVariant &v) const
{ return !cmp(v); }
+ inline bool operator<(const QVariant &v) const
+ { return compare(v) < 0; }
+ inline bool operator<=(const QVariant &v) const
+ { return compare(v) <= 0; }
+ inline bool operator>(const QVariant &v) const
+ { return compare(v) > 0; }
+ inline bool operator>=(const QVariant &v) const
+ { return compare(v) >= 0; }
protected:
friend inline bool operator==(const QVariant &, const QVariantComparisonHelper &);
@@ -449,6 +458,7 @@ public:
Private d;
void create(int type, const void *copy);
bool cmp(const QVariant &other) const;
+ int compare(const QVariant &other) const;
bool convert(const int t, void *ptr) const;
private:
@@ -562,6 +572,173 @@ inline bool operator!=(const QVariant &v1, const QVariantComparisonHelper &v2)
}
#endif
+class QSequentialIterable
+{
+ QtMetaTypePrivate::QSequentialIterableImpl m_impl;
+public:
+ struct const_iterator
+ {
+ private:
+ QtMetaTypePrivate::QSequentialIterableImpl m_impl;
+ QAtomicInt *ref;
+ friend class QSequentialIterable;
+ inline explicit const_iterator(const QSequentialIterable &iter, QAtomicInt *ref_)
+ : m_impl(iter.m_impl), ref(ref_) { ref->ref(); }
+
+ inline explicit const_iterator(const QtMetaTypePrivate::QSequentialIterableImpl &impl, QAtomicInt *ref_)
+ : m_impl(impl), ref(ref_) { ref->ref(); }
+
+ inline void begin() { m_impl.moveToBegin(); }
+ inline void end() { m_impl.moveToEnd(); }
+ public:
+ inline ~const_iterator() {
+ if (!ref->deref()) {
+ m_impl.destroyIter();
+ }
+ }
+
+ inline const_iterator(const const_iterator &other) : m_impl(other.m_impl), ref(other.ref) {
+ ref->ref();
+ }
+
+ inline const QVariant operator*() const {
+ const QtMetaTypePrivate::VariantData d = m_impl.getCurrent();
+ if (d.metaTypeId == qMetaTypeId<QVariant>())
+ return *reinterpret_cast<const QVariant*>(d.data);
+ return QVariant(d.metaTypeId, d.data, d.flags);
+ }
+ inline bool operator==(const const_iterator &o) const { return m_impl.equal(o.m_impl); }
+ inline bool operator!=(const const_iterator &o) const { return !m_impl.equal(o.m_impl); }
+ inline const_iterator &operator++() { m_impl.advance(1); return *this; }
+ inline const_iterator operator++(int) { QtMetaTypePrivate::QSequentialIterableImpl impl = m_impl; m_impl.advance(1); return const_iterator(impl, this->ref); }
+ inline const_iterator &operator--() { m_impl.advance(-1); return *this; }
+ inline const_iterator operator--(int) { QtMetaTypePrivate::QSequentialIterableImpl impl = m_impl; m_impl.advance(-1); return const_iterator(impl, this->ref); }
+ inline const_iterator &operator+=(int j) { m_impl.advance(j); return *this; }
+ inline const_iterator &operator-=(int j) { m_impl.advance(-j); return *this; }
+ inline const_iterator operator+(int j) const { QtMetaTypePrivate::QSequentialIterableImpl impl = m_impl; impl.advance(j); return const_iterator(impl, this->ref); }
+ inline const_iterator operator-(int j) const { QtMetaTypePrivate::QSequentialIterableImpl impl = m_impl; impl.advance(-j); return const_iterator(impl, this->ref); }
+ };
+
+ friend struct const_iterator;
+
+ explicit QSequentialIterable(QtMetaTypePrivate::QSequentialIterableImpl impl)
+ : m_impl(impl)
+ {
+ }
+
+ const_iterator begin() const { const_iterator it(*this, new QAtomicInt(0)); it.begin(); return it; }
+ const_iterator end() const { const_iterator it(*this, new QAtomicInt(0)); it.end(); return it; }
+
+ QVariant at(int idx) const {
+ const QtMetaTypePrivate::VariantData d = m_impl.at(idx);
+ if (d.metaTypeId == qMetaTypeId<QVariant>())
+ return *reinterpret_cast<const QVariant*>(d.data);
+ return QVariant(d.metaTypeId, d.data, d.flags);
+ }
+ int size() const { return m_impl.size(); }
+
+ bool canReverseIterate() const
+ { return m_impl._iteratorCapabilities & QtMetaTypePrivate::BiDirectionalCapability; }
+};
+
+class QAssociativeIterable
+{
+ QtMetaTypePrivate::QAssociativeIterableImpl m_impl;
+public:
+ struct const_iterator
+ {
+ private:
+ QtMetaTypePrivate::QAssociativeIterableImpl m_impl;
+ QAtomicInt *ref;
+ friend class QAssociativeIterable;
+ inline explicit const_iterator(const QAssociativeIterable &iter, QAtomicInt *ref_)
+ : m_impl(iter.m_impl), ref(ref_) { ref->ref(); }
+
+ inline explicit const_iterator(const QtMetaTypePrivate::QAssociativeIterableImpl &impl, QAtomicInt *ref_)
+ : m_impl(impl), ref(ref_) { ref->ref(); }
+
+ inline void begin() { m_impl.begin(); }
+ inline void end() { m_impl.end(); }
+ public:
+ inline ~const_iterator() {
+ if (!ref->deref()) {
+ m_impl.destroyIter();
+ }
+ }
+ inline const_iterator(const const_iterator &other) : m_impl(other.m_impl), ref(other.ref) {
+ ref->ref();
+ }
+
+ inline const QVariant key() const {
+ const QtMetaTypePrivate::VariantData d = m_impl.getCurrentKey();
+ QVariant v(d.metaTypeId, d.data, d.flags);
+ if (d.metaTypeId == qMetaTypeId<QVariant>())
+ return *reinterpret_cast<const QVariant*>(d.data);
+ return v;
+ }
+
+ inline const QVariant value() const {
+ const QtMetaTypePrivate::VariantData d = m_impl.getCurrentValue();
+ QVariant v(d.metaTypeId, d.data, d.flags);
+ if (d.metaTypeId == qMetaTypeId<QVariant>())
+ return *reinterpret_cast<const QVariant*>(d.data);
+ return v;
+ }
+
+ inline const QVariant operator*() const {
+ const QtMetaTypePrivate::VariantData d = m_impl.getCurrentValue();
+ QVariant v(d.metaTypeId, d.data, d.flags);
+ if (d.metaTypeId == qMetaTypeId<QVariant>())
+ return *reinterpret_cast<const QVariant*>(d.data);
+ return v;
+ }
+ inline bool operator==(const const_iterator &o) const { return m_impl.equal(o.m_impl); }
+ inline bool operator!=(const const_iterator &o) const { return !m_impl.equal(o.m_impl); }
+ inline const_iterator &operator++() { m_impl.advance(1); return *this; }
+ inline const_iterator operator++(int) { QtMetaTypePrivate::QAssociativeIterableImpl impl = m_impl; m_impl.advance(1); return const_iterator(impl, this->ref); }
+ inline const_iterator &operator--() { m_impl.advance(-1); return *this; }
+ inline const_iterator operator--(int) { QtMetaTypePrivate::QAssociativeIterableImpl impl = m_impl; m_impl.advance(-1); return const_iterator(impl, this->ref); }
+ inline const_iterator &operator+=(int j) { m_impl.advance(j); return *this; }
+ inline const_iterator &operator-=(int j) { m_impl.advance(-j); return *this; }
+ inline const_iterator operator+(int j) const { QtMetaTypePrivate::QAssociativeIterableImpl impl = m_impl; impl.advance(j); return const_iterator(impl, this->ref); }
+ inline const_iterator operator-(int j) const { QtMetaTypePrivate::QAssociativeIterableImpl impl = m_impl; impl.advance(-j); return const_iterator(impl, this->ref); }
+ };
+
+ friend struct const_iterator;
+
+ explicit QAssociativeIterable(QtMetaTypePrivate::QAssociativeIterableImpl impl)
+ : m_impl(impl)
+ {
+ }
+
+ const_iterator begin() const { const_iterator it(*this, new QAtomicInt(0)); it.begin(); return it; }
+ const_iterator end() const { const_iterator it(*this, new QAtomicInt(0)); it.end(); return it; }
+
+ QVariant value(const QVariant &key) const
+ {
+ QVariant key_ = key;
+ if (!key_.canConvert(m_impl._metaType_id_key))
+ return QVariant();
+ if (!key_.convert(m_impl._metaType_id_key))
+ return QVariant();
+ const QtMetaTypePrivate::VariantData dkey(key_.userType(), key_.constData(), 0 /*key.flags()*/);
+ QtMetaTypePrivate::QAssociativeIterableImpl impl = m_impl;
+ impl.find(dkey);
+ QtMetaTypePrivate::QAssociativeIterableImpl endIt = m_impl;
+ endIt.end();
+ if (impl.equal(endIt))
+ return QVariant();
+ const QtMetaTypePrivate::VariantData d = impl.getCurrentValue();
+ QVariant v(d.metaTypeId, d.data, d.flags);
+ if (d.metaTypeId == qMetaTypeId<QVariant>())
+ return *reinterpret_cast<const QVariant*>(d.data);
+ return v;
+ }
+
+ int size() const { return m_impl.size(); }
+};
+
+#ifndef QT_MOC
namespace QtPrivate {
template<typename T>
struct QVariantValueHelper : TreatAsQObjectBeforeMetaType<QVariantValueHelper<T>, T, const QVariant &, T>
@@ -571,11 +748,9 @@ namespace QtPrivate {
const int vid = qMetaTypeId<T>();
if (vid == v.userType())
return *reinterpret_cast<const T *>(v.constData());
- if (vid < int(QMetaType::User)) {
- T t;
- if (v.convert(vid, &t))
- return t;
- }
+ T t;
+ if (v.convert(vid, &t))
+ return t;
return T();
}
#ifndef QT_NO_QOBJECT
@@ -585,12 +760,118 @@ namespace QtPrivate {
}
#endif
};
+
+ template<typename T>
+ struct QVariantValueHelperInterface : QVariantValueHelper<T>
+ {
+ };
+
+ template<>
+ struct QVariantValueHelperInterface<QSequentialIterable>
+ {
+ static QSequentialIterable invoke(const QVariant &v)
+ {
+ if (v.userType() == qMetaTypeId<QVariantList>()) {
+ return QSequentialIterable(QtMetaTypePrivate::QSequentialIterableImpl(reinterpret_cast<const QVariantList*>(v.constData())));
+ }
+ if (v.userType() == qMetaTypeId<QStringList>()) {
+ return QSequentialIterable(QtMetaTypePrivate::QSequentialIterableImpl(reinterpret_cast<const QStringList*>(v.constData())));
+ }
+ return QSequentialIterable(v.value<QtMetaTypePrivate::QSequentialIterableImpl>());
+ }
+ };
+ template<>
+ struct QVariantValueHelperInterface<QAssociativeIterable>
+ {
+ static QAssociativeIterable invoke(const QVariant &v)
+ {
+ if (v.userType() == qMetaTypeId<QVariantMap>()) {
+ return QAssociativeIterable(QtMetaTypePrivate::QAssociativeIterableImpl(reinterpret_cast<const QVariantMap*>(v.constData())));
+ }
+ if (v.userType() == qMetaTypeId<QVariantHash>()) {
+ return QAssociativeIterable(QtMetaTypePrivate::QAssociativeIterableImpl(reinterpret_cast<const QVariantHash*>(v.constData())));
+ }
+ return QAssociativeIterable(v.value<QtMetaTypePrivate::QAssociativeIterableImpl>());
+ }
+ };
+ template<>
+ struct QVariantValueHelperInterface<QVariantList>
+ {
+ static QVariantList invoke(const QVariant &v)
+ {
+ if (v.userType() == qMetaTypeId<QStringList>() || QMetaType::hasRegisteredConverterFunction(v.userType(), qMetaTypeId<QtMetaTypePrivate::QSequentialIterableImpl>())) {
+ QSequentialIterable iter = QVariantValueHelperInterface<QSequentialIterable>::invoke(v);
+ QVariantList l;
+ l.reserve(iter.size());
+ for (QSequentialIterable::const_iterator it = iter.begin(), end = iter.end(); it != end; ++it)
+ l << *it;
+ return l;
+ }
+ return QVariantValueHelper<QVariantList>::invoke(v);
+ }
+ };
+ template<>
+ struct QVariantValueHelperInterface<QVariantHash>
+ {
+ static QVariantHash invoke(const QVariant &v)
+ {
+ if (QMetaType::hasRegisteredConverterFunction(v.userType(), qMetaTypeId<QtMetaTypePrivate::QAssociativeIterableImpl>())) {
+ QAssociativeIterable iter = QVariantValueHelperInterface<QAssociativeIterable>::invoke(v);
+ QVariantHash l;
+ l.reserve(iter.size());
+ for (QAssociativeIterable::const_iterator it = iter.begin(), end = iter.end(); it != end; ++it)
+ l.insert(it.key().toString(), it.value());
+ return l;
+ }
+ return QVariantValueHelper<QVariantHash>::invoke(v);
+ }
+ };
+ template<>
+ struct QVariantValueHelperInterface<QVariantMap>
+ {
+ static QVariantMap invoke(const QVariant &v)
+ {
+ if (QMetaType::hasRegisteredConverterFunction(v.userType(), qMetaTypeId<QtMetaTypePrivate::QAssociativeIterableImpl>())) {
+ QAssociativeIterable iter = QVariantValueHelperInterface<QAssociativeIterable>::invoke(v);
+ QVariantMap l;
+ for (QAssociativeIterable::const_iterator it = iter.begin(), end = iter.end(); it != end; ++it)
+ l.insert(it.key().toString(), it.value());
+ return l;
+ }
+ return QVariantValueHelper<QVariantMap>::invoke(v);
+ }
+ };
+ template<>
+ struct QVariantValueHelperInterface<QPair<QVariant, QVariant> >
+ {
+ static QPair<QVariant, QVariant> invoke(const QVariant &v)
+ {
+ if (v.userType() == qMetaTypeId<QPair<QVariant, QVariant> >())
+ return QVariantValueHelper<QPair<QVariant, QVariant> >::invoke(v);
+
+ if (QMetaType::hasRegisteredConverterFunction(v.userType(), qMetaTypeId<QtMetaTypePrivate::QPairVariantInterfaceImpl>())) {
+ QtMetaTypePrivate::QPairVariantInterfaceImpl pi = v.value<QtMetaTypePrivate::QPairVariantInterfaceImpl>();
+
+ const QtMetaTypePrivate::VariantData d1 = pi.first();
+ QVariant v1(d1.metaTypeId, d1.data, d1.flags);
+ if (d1.metaTypeId == qMetaTypeId<QVariant>())
+ v1 = *reinterpret_cast<const QVariant*>(d1.data);
+
+ const QtMetaTypePrivate::VariantData d2 = pi.second();
+ QVariant v2(d2.metaTypeId, d2.data, d2.flags);
+ if (d2.metaTypeId == qMetaTypeId<QVariant>())
+ v2 = *reinterpret_cast<const QVariant*>(d2.data);
+
+ return QPair<QVariant, QVariant>(v1, v2);
+ }
+ return QVariantValueHelper<QPair<QVariant, QVariant> >::invoke(v);
+ }
+ };
}
-#ifndef QT_MOC
template<typename T> inline T qvariant_cast(const QVariant &v)
{
- return QtPrivate::QVariantValueHelper<T>::invoke(v);
+ return QtPrivate::QVariantValueHelperInterface<T>::invoke(v);
}
template<> inline QVariant qvariant_cast<QVariant>(const QVariant &v)
diff --git a/src/corelib/plugin/plugin.pri b/src/corelib/plugin/plugin.pri
index eb7a7f7fa8..338b3d0972 100644
--- a/src/corelib/plugin/plugin.pri
+++ b/src/corelib/plugin/plugin.pri
@@ -9,14 +9,16 @@ HEADERS += \
plugin/quuid.h \
plugin/qfactoryloader_p.h \
plugin/qsystemlibrary_p.h \
- plugin/qelfparser_p.h
+ plugin/qelfparser_p.h \
+ plugin/qmachparser_p.h
SOURCES += \
plugin/qpluginloader.cpp \
plugin/qfactoryloader.cpp \
plugin/quuid.cpp \
plugin/qlibrary.cpp \
- plugin/qelfparser_p.cpp
+ plugin/qelfparser_p.cpp \
+ plugin/qmachparser.cpp
win32 {
SOURCES += \
diff --git a/src/corelib/plugin/qlibrary.cpp b/src/corelib/plugin/qlibrary.cpp
index 3432f9619d..92e60c2216 100644
--- a/src/corelib/plugin/qlibrary.cpp
+++ b/src/corelib/plugin/qlibrary.cpp
@@ -1,7 +1,7 @@
-
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2013 Intel Corporation
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -64,6 +64,7 @@
#include <qjsondocument.h>
#include <qjsonvalue.h>
#include "qelfparser_p.h"
+#include "qmachparser_p.h"
QT_BEGIN_NAMESPACE
@@ -180,8 +181,6 @@ QT_BEGIN_NAMESPACE
*/
-#if defined(Q_OS_UNIX) && !defined(Q_OS_MAC)
-
static long qt_find_pattern(const char *s, ulong s_len,
const char *pattern, ulong p_len)
{
@@ -228,7 +227,7 @@ static long qt_find_pattern(const char *s, ulong s_len,
information could not be read.
Returns true if version information is present and successfully read.
*/
-static bool qt_unix_query(const QString &library, QLibraryPrivate *lib)
+static bool findPatternUnloaded(const QString &library, QLibraryPrivate *lib)
{
QFile file(library);
if (!file.open(QIODevice::ReadOnly)) {
@@ -253,7 +252,7 @@ static bool qt_unix_query(const QString &library, QLibraryPrivate *lib)
}
/*
- ELF binaries on GNU, have .qplugin sections.
+ ELF and Mach-O binaries with GCC have .qplugin sections.
*/
bool hasMetaData = false;
long pos = 0;
@@ -274,6 +273,26 @@ static bool qt_unix_query(const QString &library, QLibraryPrivate *lib)
pos += rel;
hasMetaData = true;
}
+#elif defined (Q_OF_MACH_O)
+ {
+ QString errorString;
+ int r = QMachOParser::parse(filedata, fdlen, library, &errorString, &pos, &fdlen);
+ if (r == QMachOParser::NotSuitable) {
+ if (qt_debug_component())
+ qWarning("QMachOParser: %s", qPrintable(errorString));
+ if (lib)
+ lib->errorString = errorString;
+ return false;
+ }
+ // even if the metadata section was not found, the Mach-O parser will
+ // at least return the boundaries of the right architecture
+ long rel = qt_find_pattern(filedata + pos, fdlen, pattern, plen);
+ if (rel < 0)
+ pos = -1;
+ else
+ pos += rel;
+ hasMetaData = true;
+ }
#else
pos = qt_find_pattern(filedata, fdlen, pattern, plen);
if (pos > 0)
@@ -300,8 +319,6 @@ static bool qt_unix_query(const QString &library, QLibraryPrivate *lib)
return ret;
}
-#endif // Q_OS_UNIX && !Q_OS_MAC
-
static void installCoverageTool(QLibraryPrivate *libPrivate)
{
#ifdef __COVERAGESCANNER__
@@ -618,41 +635,18 @@ bool QLibrary::isLibrary(const QString &fileName)
}
-#if defined (Q_OS_WIN) && defined(_MSC_VER) && _MSC_VER >= 1400 && !defined(Q_CC_INTEL)
-#define QT_USE_MS_STD_EXCEPTION 1
-const char* qt_try_versioninfo(void *pfn, bool *exceptionThrown)
-{
- *exceptionThrown = false;
- const char *szData = 0;
- typedef const char * (*VerificationFunction)();
- VerificationFunction func = reinterpret_cast<VerificationFunction>(pfn);
- __try {
- if(func)
- szData = func();
- } __except(EXCEPTION_EXECUTE_HANDLER) {
- *exceptionThrown = true;
- }
- return szData;
-}
-#endif
-
typedef const char * (*QtPluginQueryVerificationDataFunction)();
-bool qt_get_metadata(QtPluginQueryVerificationDataFunction pfn, QLibraryPrivate *priv, bool *exceptionThrown)
+static bool qt_get_metadata(QtPluginQueryVerificationDataFunction pfn, QLibraryPrivate *priv)
{
- *exceptionThrown = false;
const char *szData = 0;
if (!pfn)
return false;
-#ifdef QT_USE_MS_STD_EXCEPTION
- szData = qt_try_versioninfo((void *)pfn, exceptionThrown);
- if (*exceptionThrown)
- return false;
-#else
+
szData = pfn();
-#endif
if (!szData)
return false;
+
QJsonDocument doc = QLibraryPrivate::fromRawMetaData(szData);
if (doc.isNull())
return false;
@@ -690,80 +684,15 @@ void QLibraryPrivate::updatePluginState()
}
#endif
-#if defined(Q_OS_UNIX) && !defined(Q_OS_MAC)
if (!pHnd) {
- // use unix shortcut to avoid loading the library
- success = qt_unix_query(fileName, this);
- } else
-#endif
- {
- bool retryLoadLibrary = false; // Only used on Windows with MS compiler.(false in other cases)
- do {
- bool temporary_load = false;
-#ifdef Q_OS_WIN
- HMODULE hTempModule = 0;
-#endif
- if (!pHnd) {
-#ifdef Q_OS_WIN
- DWORD dwFlags = (retryLoadLibrary) ? 0: DONT_RESOLVE_DLL_REFERENCES;
- //avoid 'Bad Image' message box
- UINT oldmode = SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX);
- hTempModule = ::LoadLibraryEx((wchar_t*)QDir::toNativeSeparators(fileName).utf16(), 0, dwFlags);
- SetErrorMode(oldmode);
-#else
- temporary_load = load();
-#endif
- }
- QtPluginQueryVerificationDataFunction getMetaData = NULL;
-
- bool exceptionThrown = false;
- bool ret = false;
-#ifdef Q_OS_WIN
- if (hTempModule) {
- getMetaData = (QtPluginQueryVerificationDataFunction)
-#ifdef Q_OS_WINCE
- ::GetProcAddress(hTempModule, L"qt_plugin_query_metadata")
-#else
- ::GetProcAddress(hTempModule, "qt_plugin_query_metadata")
-#endif
- ;
- } else
-#endif
- {
- getMetaData = (QtPluginQueryVerificationDataFunction) resolve("qt_plugin_query_metadata");
- }
-
- if (getMetaData)
- ret = qt_get_metadata(getMetaData, this, &exceptionThrown);
-
- if (temporary_load)
- unload();
- if (!exceptionThrown) {
- if (ret) {
- success = true;
- }
- retryLoadLibrary = false;
- }
-#ifdef QT_USE_MS_STD_EXCEPTION
- else {
- // An exception was thrown when calling qt_plugin_query_verification_data().
- // This usually happens when plugin is compiled with the /clr compiler flag,
- // & will only work if the dependencies are loaded & DLLMain() is called.
- // LoadLibrary() will do this, try once with this & if it fails don't load.
- retryLoadLibrary = !retryLoadLibrary;
- }
-#endif
-#ifdef Q_OS_WIN
- if (hTempModule) {
- BOOL ok = ::FreeLibrary(hTempModule);
- if (ok) {
- hTempModule = 0;
- }
-
- }
-#endif
- } while (retryLoadLibrary); // Will be 'false' in all cases other than when an
- // exception is thrown(will happen only when using a MS compiler)
+ // scan for the plugin metadata without loading
+ success = findPatternUnloaded(fileName, this);
+ } else {
+ // library is already loaded (probably via QLibrary)
+ // simply get the target function and call it.
+ QtPluginQueryVerificationDataFunction getMetaData = NULL;
+ getMetaData = (QtPluginQueryVerificationDataFunction) resolve("qt_plugin_query_metadata");
+ success = qt_get_metadata(getMetaData, this);
}
if (!success) {
diff --git a/src/corelib/plugin/qmachparser.cpp b/src/corelib/plugin/qmachparser.cpp
new file mode 100644
index 0000000000..5152a92d1d
--- /dev/null
+++ b/src/corelib/plugin/qmachparser.cpp
@@ -0,0 +1,218 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Intel Corporation
+** 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 "qmachparser_p.h"
+
+#if defined(Q_OF_MACH_O) && !defined(QT_NO_LIBRARY)
+
+#include <qendian.h>
+#include "qlibrary_p.h"
+
+#include <mach-o/loader.h>
+#include <mach-o/fat.h>
+
+QT_BEGIN_NAMESPACE
+
+#if defined(Q_PROCESSOR_X86_64)
+# define MACHO64
+static const cpu_type_t my_cputype = CPU_TYPE_X86_64;
+#elif defined(Q_PROCESSOR_X86_32)
+static const cpu_type_t my_cputype = CPU_TYPE_X86;
+#elif defined(Q_PROCESSOR_POWER_64)
+# define MACHO64
+static const cpu_type_t my_cputype = CPU_TYPE_POWERPC64;
+#elif defined(Q_PROCESSOR_POWER_32)
+static const cpu_type_t my_cputype = CPU_TYPE_POWERPC;
+#elif defined(Q_PROCESSOR_ARM)
+static const cpu_type_t my_cputype = CPU_TYPE_ARM;
+#else
+# error "Unknown CPU type"
+#endif
+
+#ifdef MACHO64
+# undef MACHO64
+typedef mach_header_64 my_mach_header;
+typedef segment_command_64 my_segment_command;
+typedef section_64 my_section;
+static const uint32_t my_magic = MH_MAGIC_64;
+#else
+typedef mach_header my_mach_header;
+typedef segment_command my_segment_command;
+typedef section my_section;
+static const uint32_t my_magic = MH_MAGIC;
+#endif
+
+static int ns(const QString &reason, const QString &library, QString *errorString)
+{
+ if (errorString)
+ *errorString = QLibrary::tr("'%1' is not a valid Mach-O binary (%2)")
+ .arg(library, reason.isEmpty() ? QLibrary::tr("file is corrupt") : reason);
+ return QMachOParser::NotSuitable;
+}
+
+int QMachOParser::parse(const char *m_s, ulong fdlen, const QString &library, QString *errorString, long *pos, ulong *sectionlen)
+{
+ // The minimum size of a Mach-O binary we're interested in.
+ // It must have a full Mach header, at least one segment and at least one
+ // section. It's probably useless with just the "qtmetadata" section, but
+ // it's valid nonetheless.
+ // A fat binary must have this plus the fat header, of course.
+ static const size_t MinFileSize = sizeof(my_mach_header) + sizeof(my_segment_command) + sizeof(my_section);
+ static const size_t MinFatHeaderSize = sizeof(fat_header) + 2 * sizeof(fat_arch);
+
+ if (Q_UNLIKELY(fdlen < MinFileSize))
+ return ns(QLibrary::tr("file too small"), library, errorString);
+
+ // find out if this is a fat Mach-O binary first
+ const my_mach_header *header = 0;
+ const fat_header *fat = reinterpret_cast<const fat_header *>(m_s);
+ if (fat->magic == qToBigEndian(FAT_MAGIC)) {
+ // find our architecture in the binary
+ const fat_arch *arch = reinterpret_cast<const fat_arch *>(fat + 1);
+ if (Q_UNLIKELY(fdlen < MinFatHeaderSize)) {
+ return ns(QLibrary::tr("file too small"), library, errorString);
+ }
+
+ int count = qFromBigEndian(fat->nfat_arch);
+ if (Q_UNLIKELY(fdlen < sizeof(*fat) + sizeof(*arch) * count))
+ return ns(QString(), library, errorString);
+
+ for (int i = 0; i < count; ++i) {
+ if (arch[i].cputype == qToBigEndian(my_cputype)) {
+ // ### should we check the CPU subtype? Maybe on ARM?
+ uint32_t size = qFromBigEndian(arch[i].size);
+ uint32_t offset = qFromBigEndian(arch[i].offset);
+ if (Q_UNLIKELY(size > fdlen) || Q_UNLIKELY(offset > fdlen)
+ || Q_UNLIKELY(size + offset > fdlen) || Q_UNLIKELY(size < MinFileSize))
+ return ns(QString(), library, errorString);
+
+ header = reinterpret_cast<const my_mach_header *>(m_s + offset);
+ fdlen = size;
+ break;
+ }
+ }
+ if (!header)
+ return ns(QLibrary::tr("no suitable architecture in fat binary"), library, errorString);
+
+ // check the magic again
+ if (Q_UNLIKELY(header->magic != my_magic))
+ return ns(QString(), library, errorString);
+ } else {
+ header = reinterpret_cast<const my_mach_header *>(m_s);
+ fat = 0;
+
+ // check magic
+ if (header->magic != my_magic)
+ return ns(QLibrary::tr("invalid magic %1").arg(qFromBigEndian(header->magic), 8, 16, QLatin1Char('0')),
+ library, errorString);
+ }
+
+ // from this point on, fdlen is specific to this architecture
+ // from this point on, everything is in host byte order
+ *pos = reinterpret_cast<const char *>(header) - m_s;
+
+ // (re-)check the CPU type
+ // ### should we check the CPU subtype? Maybe on ARM?
+ if (header->cputype != my_cputype) {
+ if (fat)
+ return ns(QString(), library, errorString);
+ return ns(QLibrary::tr("wrong architecture"), library, errorString);
+ }
+
+ // check the file type
+ if (Q_UNLIKELY(header->filetype != MH_BUNDLE && header->filetype != MH_DYLIB))
+ return ns(QLibrary::tr("not a dynamic library"), library, errorString);
+
+ // find the __TEXT segment, "qtmetadata" section
+ const my_segment_command *seg = reinterpret_cast<const my_segment_command *>(header + 1);
+ ulong minsize = sizeof(*header);
+
+ for (uint i = 0; i < header->ncmds; ++i,
+ seg = reinterpret_cast<const my_segment_command *>(reinterpret_cast<const char *>(seg) + seg->cmdsize)) {
+ // We're sure that the file size includes at least one load command
+ // but we have to check anyway if we're past the first
+ if (Q_UNLIKELY(fdlen < minsize + sizeof(load_command)))
+ return ns(QString(), library, errorString);
+
+ // cmdsize can't be trusted until validated
+ // so check it against fdlen anyway
+ // (these are unsigned operations, with overflow behavior specified in the standard)
+ minsize += seg->cmdsize;
+ if (Q_UNLIKELY(fdlen < minsize) || Q_UNLIKELY(fdlen < seg->cmdsize))
+ return ns(QString(), library, errorString);
+
+ const uint32_t MyLoadCommand = sizeof(void *) > 4 ? LC_SEGMENT_64 : LC_SEGMENT;
+ if (seg->cmd != MyLoadCommand)
+ continue;
+
+ // is this the __TEXT segment?
+ if (strcmp(seg->segname, "__TEXT") == 0) {
+ const my_section *sect = reinterpret_cast<const my_section *>(seg + 1);
+ for (uint j = 0; j < seg->nsects; ++j) {
+ // is this the "qtmetadata" section?
+ if (strcmp(sect[j].sectname, "qtmetadata") != 0)
+ continue;
+
+ // found it!
+ if (Q_UNLIKELY(fdlen < sect[j].offset) || Q_UNLIKELY(fdlen < sect[j].size)
+ || Q_UNLIKELY(fdlen < sect[j].offset + sect[j].size))
+ return ns(QString(), library, errorString);
+
+ *pos += sect[j].offset;
+ *sectionlen = sect[j].size;
+ return QtMetaDataSection;
+ }
+ }
+
+ // other type of segment
+ seg = reinterpret_cast<const my_segment_command *>(reinterpret_cast<const char *>(seg) + seg->cmdsize);
+ }
+
+// // No Qt section was found, but at least we know that where the proper architecture's boundaries are
+// return NoQtSection;
+ if (errorString)
+ *errorString = QLibrary::tr("'%1' is not a Qt plugin").arg(library);
+ return NotSuitable;
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/platforms/kms/qkmsudevlistener.h b/src/corelib/plugin/qmachparser_p.h
index 7534f0bcd3..6b2774dab6 100644
--- a/src/plugins/platforms/kms/qkmsudevlistener.h
+++ b/src/corelib/plugin/qmachparser_p.h
@@ -1,9 +1,9 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2013 Intel Corporation
** Contact: http://www.qt-project.org/legal
**
-** This file is part of the plugins of the Qt Toolkit.
+** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
@@ -39,40 +39,41 @@
**
****************************************************************************/
-#ifndef QKMSUDEVLISTENER_H
-#define QKMSUDEVLISTENER_H
+#ifndef QMACHPARSER_P_H
+#define QMACHPARSER_P_H
-#include <QObject>
-#include <QMap>
-#include <QList>
-#include <QPointer>
-#include <QString>
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
-#include <qkmsudevhandler.h>
+#include <qendian.h>
+#include <qglobal.h>
-#include <libudev.h>
+#ifndef QT_NO_LIBRARY
+#if defined(Q_OF_MACH_O)
QT_BEGIN_NAMESPACE
-class QKmsUdevListener : public QObject
-{
- Q_OBJECT
+class QString;
+class QLibraryPrivate;
+class Q_AUTOTEST_EXPORT QMachOParser
+{
public:
- QKmsUdevListener(QObject *parent = 0);
- ~QKmsUdevListener();
-
- void addHandler(QKmsUdevHandler *);
-
-private:
- QList<QPointer<QKmsUdevHandler> > m_handlers;
- QMap<QString, QPointer<QObject> > m_devices;
- struct udev *m_udev;
-
- void scan();
- bool create(struct udev_device *);
+ enum { QtMetaDataSection, NoQtSection, NotSuitable };
+ static int parse(const char *m_s, ulong fdlen, const QString &library, QString *errorString, long *pos, ulong *sectionlen);
};
QT_END_NAMESPACE
-#endif // QKMSUDEVLISTENER_H
+#endif // defined(Q_OF_ELF) && defined(Q_CC_GNU)
+#endif // QT_NO_LIBRARY
+
+#endif // QMACHPARSER_P_H
diff --git a/src/corelib/tools/qalgorithms.h b/src/corelib/tools/qalgorithms.h
index e3b76886f1..8337afcb9d 100644
--- a/src/corelib/tools/qalgorithms.h
+++ b/src/corelib/tools/qalgorithms.h
@@ -516,6 +516,73 @@ Q_OUTOFLINE_TEMPLATE RandomAccessIterator qBinaryFindHelper(RandomAccessIterator
} //namespace QAlgorithmsPrivate
+
+// Use __builtin_popcount on gcc. Clang claims to be gcc
+// but has a bug where __builtin_popcount is not marked as
+// constexpr.
+#if defined(Q_CC_GNU) && !defined(Q_CC_CLANG)
+#define QALGORITHMS_USE_BUILTIN_POPCOUNT
+#endif
+
+Q_DECL_CONSTEXPR inline uint qPopulationCount(quint32 v)
+{
+#ifdef QALGORITHMS_USE_BUILTIN_POPCOUNT
+ return __builtin_popcount(v);
+#else
+ // See http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel
+ return
+ (((v ) & 0xfff) * Q_UINT64_C(0x1001001001001) & Q_UINT64_C(0x84210842108421)) % 0x1f +
+ (((v >> 12) & 0xfff) * Q_UINT64_C(0x1001001001001) & Q_UINT64_C(0x84210842108421)) % 0x1f +
+ (((v >> 24) & 0xfff) * Q_UINT64_C(0x1001001001001) & Q_UINT64_C(0x84210842108421)) % 0x1f;
+#endif
+}
+
+Q_DECL_CONSTEXPR inline uint qPopulationCount(quint8 v)
+{
+#ifdef QALGORITHMS_USE_BUILTIN_POPCOUNT
+ return __builtin_popcount(v);
+#else
+ return
+ (((v ) & 0xfff) * Q_UINT64_C(0x1001001001001) & Q_UINT64_C(0x84210842108421)) % 0x1f;
+#endif
+}
+
+Q_DECL_CONSTEXPR inline uint qPopulationCount(quint16 v)
+{
+#ifdef QALGORITHMS_USE_BUILTIN_POPCOUNT
+ return __builtin_popcount(v);
+#else
+ return
+ (((v ) & 0xfff) * Q_UINT64_C(0x1001001001001) & Q_UINT64_C(0x84210842108421)) % 0x1f +
+ (((v >> 12) & 0xfff) * Q_UINT64_C(0x1001001001001) & Q_UINT64_C(0x84210842108421)) % 0x1f;
+#endif
+}
+
+Q_DECL_CONSTEXPR inline uint qPopulationCount(quint64 v)
+{
+#ifdef QALGORITHMS_USE_BUILTIN_POPCOUNT
+ return __builtin_popcountll(v);
+#else
+ return
+ (((v ) & 0xfff) * Q_UINT64_C(0x1001001001001) & Q_UINT64_C(0x84210842108421)) % 0x1f +
+ (((v >> 12) & 0xfff) * Q_UINT64_C(0x1001001001001) & Q_UINT64_C(0x84210842108421)) % 0x1f +
+ (((v >> 24) & 0xfff) * Q_UINT64_C(0x1001001001001) & Q_UINT64_C(0x84210842108421)) % 0x1f +
+ (((v >> 36) & 0xfff) * Q_UINT64_C(0x1001001001001) & Q_UINT64_C(0x84210842108421)) % 0x1f +
+ (((v >> 48) & 0xfff) * Q_UINT64_C(0x1001001001001) & Q_UINT64_C(0x84210842108421)) % 0x1f +
+ (((v >> 60) & 0xfff) * Q_UINT64_C(0x1001001001001) & Q_UINT64_C(0x84210842108421)) % 0x1f;
+#endif
+}
+
+Q_DECL_CONSTEXPR inline uint qPopulationCount(long unsigned int v)
+{
+ return qPopulationCount(static_cast<quint64>(v));
+}
+
+#if defined(Q_CC_GNU) && !defined(Q_CC_CLANG)
+#undef QALGORITHMS_USE_BUILTIN_POPCOUNT
+#endif
+
+
QT_END_NAMESPACE
#endif // QALGORITHMS_H
diff --git a/src/corelib/tools/qalgorithms.qdoc b/src/corelib/tools/qalgorithms.qdoc
index ad6c3d913c..f3dfddec77 100644
--- a/src/corelib/tools/qalgorithms.qdoc
+++ b/src/corelib/tools/qalgorithms.qdoc
@@ -635,3 +635,34 @@ of \a value in the variable passed as a reference in argument \a n.
\sa {qLess()}{qLess<T>()}
*/
+
+
+/*!
+ \fn uint qPopulationCount(quint8 v)
+ \relates <QtAlgorithms>
+ \since 5.2
+
+ Returns the number of bits set in \a v. This number also called
+ the Hamming Weight of \a v.
+ */
+
+/*!
+ \fn uint qPopulationCount(quint16 v)
+ \relates <QtAlgorithms>
+ \since 5.2
+ \overload
+ */
+
+/*!
+ \fn uint qPopulationCount(quint32 v)
+ \relates <QtAlgorithms>
+ \since 5.2
+ \overload
+ */
+
+/*!
+ \fn uint qPopulationCount(quint64 v)
+ \relates <QtAlgorithms>
+ \since 5.2
+ \overload
+ */
diff --git a/src/corelib/tools/qbitarray.cpp b/src/corelib/tools/qbitarray.cpp
index b04c4f9c3d..54c1ff8843 100644
--- a/src/corelib/tools/qbitarray.cpp
+++ b/src/corelib/tools/qbitarray.cpp
@@ -40,6 +40,7 @@
****************************************************************************/
#include "qbitarray.h"
+#include <qalgorithms.h>
#include <qdatastream.h>
#include <qdebug.h>
#include <string.h>
@@ -160,24 +161,18 @@ int QBitArray::count(bool on) const
for (int i = 0; i < len; ++i)
numBits += testBit(i);
#else
- // See http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel
const quint8 *bits = reinterpret_cast<const quint8 *>(d.data()) + 1;
while (len >= 32) {
quint32 v = quint32(bits[0]) | (quint32(bits[1]) << 8) | (quint32(bits[2]) << 16) | (quint32(bits[3]) << 24);
- quint32 c = ((v & 0xfff) * Q_UINT64_C(0x1001001001001) & Q_UINT64_C(0x84210842108421)) % 0x1f;
- c += (((v & 0xfff000) >> 12) * Q_UINT64_C(0x1001001001001) & Q_UINT64_C(0x84210842108421)) % 0x1f;
- c += ((v >> 24) * Q_UINT64_C(0x1001001001001) & Q_UINT64_C(0x84210842108421)) % 0x1f;
len -= 32;
bits += 4;
- numBits += int(c);
+ numBits += int(qPopulationCount(v));
}
while (len >= 24) {
quint32 v = quint32(bits[0]) | (quint32(bits[1]) << 8) | (quint32(bits[2]) << 16);
- quint32 c = ((v & 0xfff) * Q_UINT64_C(0x1001001001001) & Q_UINT64_C(0x84210842108421)) % 0x1f;
- c += (((v & 0xfff000) >> 12) * Q_UINT64_C(0x1001001001001) & Q_UINT64_C(0x84210842108421)) % 0x1f;
len -= 24;
bits += 3;
- numBits += int(c);
+ numBits += int(qPopulationCount(v));
}
while (len >= 0) {
if (bits[len / 8] & (1 << ((len - 1) & 7)))
diff --git a/src/corelib/tools/qbitarray.h b/src/corelib/tools/qbitarray.h
index 1103712627..eaf9b2ff25 100644
--- a/src/corelib/tools/qbitarray.h
+++ b/src/corelib/tools/qbitarray.h
@@ -61,6 +61,7 @@ public:
QBitArray(const QBitArray &other) : d(other.d) {}
inline QBitArray &operator=(const QBitArray &other) { d = other.d; return *this; }
#ifdef Q_COMPILER_RVALUE_REFS
+ inline QBitArray(QBitArray &&other) : d(std::move(other.d)) {}
inline QBitArray &operator=(QBitArray &&other)
{ qSwap(d, other.d); return *this; }
#endif
diff --git a/src/corelib/tools/qbytearray.cpp b/src/corelib/tools/qbytearray.cpp
index 75900e9775..188deb4f94 100644
--- a/src/corelib/tools/qbytearray.cpp
+++ b/src/corelib/tools/qbytearray.cpp
@@ -556,6 +556,7 @@ QByteArray qUncompress(const uchar* data, int nbytes)
d.take(); // realloc was successful
d.reset(p);
d->offset = sizeof(QByteArrayData);
+ d->size = 0; // Shut up valgrind "uninitialized variable" warning
int res = ::uncompress((uchar*)d->data(), &len,
(uchar*)data+4, nbytes-4);
diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp
index d8e3a78cdf..0b4761d5b4 100644
--- a/src/corelib/tools/qdatetime.cpp
+++ b/src/corelib/tools/qdatetime.cpp
@@ -1474,15 +1474,15 @@ int QTime::msec() const
/*!
\overload
- Returns the time as a string. Milliseconds are not included. The
- \a format parameter determines the format of the string.
+ Returns the time as a string. The \a format parameter determines
+ the format of the string.
- If \a format is Qt::TextDate, the string format is HH:MM:SS; e.g. 1
- second before midnight would be "23:59:59".
+ If \a format is Qt::TextDate, the string format is HH:MM:SS.zzz;
+ e.g. 1 second before midnight would be "23:59:59.000".
If \a format is Qt::ISODate, the string format corresponds to the
- ISO 8601 extended specification for representations of dates,
- which is also HH:MM:SS.
+ ISO 8601 extended specification (with decimal fractions) for
+ representations of dates; also HH:MM:SS.zzz.
If the \a format is Qt::SystemLocaleShortDate or
Qt::SystemLocaleLongDate, the string format depends on the locale
@@ -1521,10 +1521,11 @@ QString QTime::toString(Qt::DateFormat format) const
default:
case Qt::ISODate:
case Qt::TextDate:
- return QString::fromLatin1("%1:%2:%3")
+ return QString::fromLatin1("%1:%2:%3.%4")
.arg(hour(), 2, 10, QLatin1Char('0'))
.arg(minute(), 2, 10, QLatin1Char('0'))
- .arg(second(), 2, 10, QLatin1Char('0'));
+ .arg(second(), 2, 10, QLatin1Char('0'))
+ .arg(msec(), 3, 10, QLatin1Char('0'));
}
}
@@ -2465,15 +2466,15 @@ void QDateTime::setTime_t(uint secsSince1Jan1970UTC)
the default way. QDate::shortDayName(), QDate::shortMonthName(),
and QTime::toString() are used to generate the string, so the
day and month names will be localized names. An example of this
- formatting is "Wed May 20 03:40:13 1998".
+ formatting is "Wed May 20 03:40:13.456 1998".
If the \a format is Qt::ISODate, the string format corresponds
- to the ISO 8601 extended specification for representations of
- dates and times, taking the form YYYY-MM-DDTHH:MM:SS[Z|[+|-]HH:MM],
- depending on the timeSpec() of the QDateTime. If the timeSpec()
- is Qt::UTC, Z will be appended to the string; if the timeSpec() is
- Qt::OffsetFromUTC, the offset in hours and minutes from UTC will
- be appended to the string.
+ to the ISO 8601 extended specification (with decimal fractions) for
+ representations of dates and times, taking the form
+ YYYY-MM-DDTHH:MM:SS.zzz[Z|[+|-]HH:MM], depending on the timeSpec()
+ of the QDateTime. If the timeSpec() is Qt::UTC, Z will be appended
+ to the string; if the timeSpec() is Qt::OffsetFromUTC, the offset
+ in hours and minutes from UTC will be appended to the string.
If the \a format is Qt::SystemLocaleShortDate or
Qt::SystemLocaleLongDate, the string format depends on the locale
@@ -3408,13 +3409,29 @@ QDateTime QDateTime::fromString(const QString& s, Qt::DateFormat f)
return QDateTime();
}
- int second = (timeParts.count() > 2) ? timeParts.at(2).toInt(&ok) : 0;
- if (!ok) {
- return QDateTime();
+ int second = 0;
+ int millisecond = 0;
+ if (timeParts.count() > 2) {
+ QStringList secondParts = timeParts.at(2).split(QLatin1Char('.'));
+ if (secondParts.size() > 2) {
+ return QDateTime();
+ }
+
+ second = secondParts.first().toInt(&ok);
+ if (!ok) {
+ return QDateTime();
+ }
+
+ if (secondParts.size() > 1) {
+ millisecond = secondParts.last().toInt(&ok);
+ if (!ok) {
+ return QDateTime();
+ }
+ }
}
QDate date(year, month, day);
- QTime time(hour, minute, second);
+ QTime time(hour, minute, second, millisecond);
if (parts.count() == 5)
return QDateTime(date, time, Qt::LocalTime);
diff --git a/src/corelib/tools/qdatetime.h b/src/corelib/tools/qdatetime.h
index 5c1668033c..e5c1e104a2 100644
--- a/src/corelib/tools/qdatetime.h
+++ b/src/corelib/tools/qdatetime.h
@@ -217,11 +217,13 @@ public:
QTime time() const;
Qt::TimeSpec timeSpec() const;
qint64 toMSecsSinceEpoch() const;
+ // ### Qt 6: use quint64 instead of uint
uint toTime_t() const;
void setDate(const QDate &date);
void setTime(const QTime &time);
void setTimeSpec(Qt::TimeSpec spec);
void setMSecsSinceEpoch(qint64 msecs);
+ // ### Qt 6: use quint64 instead of uint
void setTime_t(uint secsSince1Jan1970UTC);
#ifndef QT_NO_DATESTRING
QString toString(Qt::DateFormat f = Qt::TextDate) const;
@@ -255,6 +257,7 @@ public:
static QDateTime fromString(const QString &s, Qt::DateFormat f = Qt::TextDate);
static QDateTime fromString(const QString &s, const QString &format);
#endif
+ // ### Qt 6: use quint64 instead of uint
static QDateTime fromTime_t(uint secsSince1Jan1970UTC);
static QDateTime fromMSecsSinceEpoch(qint64 msecs);
static qint64 currentMSecsSinceEpoch() Q_DECL_NOTHROW;
diff --git a/src/corelib/tools/qharfbuzz_p.h b/src/corelib/tools/qharfbuzz_p.h
index 27ddb44e91..1471fd5712 100644
--- a/src/corelib/tools/qharfbuzz_p.h
+++ b/src/corelib/tools/qharfbuzz_p.h
@@ -140,20 +140,6 @@ typedef enum {
HB_ScriptCount = HB_Script_Inherited
} HB_Script;
-typedef enum {
- HB_NoJustification= 0, /* Justification can't be applied after this glyph */
- HB_Arabic_Space = 1, /* This glyph represents a space inside arabic text */
- HB_Character = 2, /* Inter-character justification point follows this glyph */
- HB_Space = 4, /* This glyph represents a blank outside an Arabic run */
- HB_Arabic_Normal = 7, /* Normal Middle-Of-Word glyph that connects to the right (begin) */
- HB_Arabic_Waw = 8, /* Next character is final form of Waw/Ain/Qaf/Fa */
- HB_Arabic_BaRa = 9, /* Next two chars are Ba + Ra/Ya/AlefMaksura */
- HB_Arabic_Alef = 10, /* Next character is final form of Alef/Tah/Lam/Kaf/Gaf */
- HB_Arabic_HaaDal = 11, /* Next character is final form of Haa/Dal/Taa Marbutah */
- HB_Arabic_Seen = 12, /* Initial or Medial form Of Seen/Sad */
- HB_Arabic_Kashida = 13 /* Kashida(U+640) in middle of word */
-} HB_JustificationClass;
-
#ifdef __xlC__
typedef unsigned hb_bitfield;
#else
diff --git a/src/corelib/tools/qhash.h b/src/corelib/tools/qhash.h
index e99a67d1e3..25029afe1f 100644
--- a/src/corelib/tools/qhash.h
+++ b/src/corelib/tools/qhash.h
@@ -509,6 +509,25 @@ private:
static void deleteNode2(QHashData::Node *node);
static void duplicateNode(QHashData::Node *originalNode, void *newNode);
+
+ bool isValidIterator(const iterator &it) const
+ {
+#if defined(QT_DEBUG) && !defined(Q_HASH_NO_ITERATOR_DEBUG)
+ union {
+ QHashData *iteratorHashData;
+ QHashData::Node *node;
+ };
+ node = it.i;
+ while (node->next)
+ node = node->next;
+
+ return (iteratorHashData == d);
+#else
+ Q_UNUSED(it);
+ return true;
+#endif
+ }
+ friend class QSet<Key>;
};
@@ -831,6 +850,8 @@ Q_OUTOFLINE_TEMPLATE T QHash<Key, T>::take(const Key &akey)
template <class Key, class T>
Q_OUTOFLINE_TEMPLATE typename QHash<Key, T>::iterator QHash<Key, T>::erase(iterator it)
{
+ Q_ASSERT_X(isValidIterator(it), "QHash::erase", "The specified const_iterator argument 'it' is invalid");
+
if (it == iterator(e))
return it;
diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h
index 0592c24e9f..8a9d364eac 100644
--- a/src/corelib/tools/qlist.h
+++ b/src/corelib/tools/qlist.h
@@ -346,6 +346,11 @@ private:
void node_destruct(Node *n);
void node_copy(Node *from, Node *to, Node *src);
void node_destruct(Node *from, Node *to);
+
+ bool isValidIterator(const iterator &i) const
+ {
+ return (constBegin().i <= i.i) && (i.i <= constEnd().i);
+ }
};
#if defined(Q_CC_BOR)
@@ -433,6 +438,8 @@ Q_INLINE_TEMPLATE QList<T> &QList<T>::operator=(const QList<T> &l)
template <typename T>
inline typename QList<T>::iterator QList<T>::insert(iterator before, const T &t)
{
+ Q_ASSERT_X(isValidIterator(before), "QList::insert", "The specified iterator argument 'before' is invalid");
+
int iBefore = int(before.i - reinterpret_cast<Node *>(p.begin()));
Node *n = reinterpret_cast<Node *>(p.insert(iBefore));
QT_TRY {
@@ -445,8 +452,11 @@ inline typename QList<T>::iterator QList<T>::insert(iterator before, const T &t)
}
template <typename T>
inline typename QList<T>::iterator QList<T>::erase(iterator it)
-{ node_destruct(it.i);
- return reinterpret_cast<Node *>(p.erase(reinterpret_cast<void**>(it.i))); }
+{
+ Q_ASSERT_X(isValidIterator(it), "QList::erase", "The specified iterator argument 'it' is invalid");
+ node_destruct(it.i);
+ return reinterpret_cast<Node *>(p.erase(reinterpret_cast<void**>(it.i)));
+}
template <typename T>
inline const T &QList<T>::at(int i) const
{ Q_ASSERT_X(i >= 0 && i < p.size(), "QList<T>::at", "index out of range");
@@ -811,6 +821,9 @@ template <typename T>
Q_OUTOFLINE_TEMPLATE typename QList<T>::iterator QList<T>::erase(typename QList<T>::iterator afirst,
typename QList<T>::iterator alast)
{
+ Q_ASSERT_X(isValidIterator(afirst), "QList::erase", "The specified iterator argument 'afirst' is invalid");
+ Q_ASSERT_X(isValidIterator(alast), "QList::erase", "The specified iterator argument 'alast' is invalid");
+
for (Node *n = afirst.i; n < alast.i; ++n)
node_destruct(n);
int idx = afirst - begin();
diff --git a/src/corelib/tools/qlocale_p.h b/src/corelib/tools/qlocale_p.h
index 56ed6c7534..34223d5af9 100644
--- a/src/corelib/tools/qlocale_p.h
+++ b/src/corelib/tools/qlocale_p.h
@@ -62,7 +62,7 @@
QT_BEGIN_NAMESPACE
#ifndef QT_NO_SYSTEMLOCALE
-class QSystemLocale
+class Q_CORE_EXPORT QSystemLocale
{
public:
QSystemLocale();
diff --git a/src/corelib/tools/qmap.h b/src/corelib/tools/qmap.h
index 449fcbca0a..8c15afd9f8 100644
--- a/src/corelib/tools/qmap.h
+++ b/src/corelib/tools/qmap.h
@@ -557,6 +557,18 @@ public:
private:
void detach_helper();
+ bool isValidIterator(const const_iterator &ci) const
+ {
+#if defined(QT_DEBUG) && !defined(Q_MAP_NO_ITERATOR_DEBUG)
+ const QMapNodeBase *n = ci.i;
+ while (n->parent())
+ n = n->parent();
+ return n->left == d->root();
+#else
+ Q_UNUSED(ci);
+ return true;
+#endif
+ }
};
template <class Key, class T>
@@ -670,6 +682,8 @@ typename QMap<Key, T>::iterator QMap<Key, T>::insert(const_iterator pos, const K
if (d->ref.isShared())
return this->insert(akey, avalue);
+ Q_ASSERT_X(isValidIterator(pos), "QMap::insert", "The specified const_iterator argument 'it' is invalid");
+
if (pos == constEnd()) {
// Hint is that the Node is larger than (or equal to) the largest value.
Node *n = static_cast<Node *>(pos.i->left);
@@ -753,6 +767,8 @@ typename QMap<Key, T>::iterator QMap<Key, T>::insertMulti(const_iterator pos, co
if (d->ref.isShared())
return this->insertMulti(akey, avalue);
+ Q_ASSERT_X(isValidIterator(pos), "QMap::insertMulti", "The specified const_iterator argument 'pos' is invalid");
+
if (pos == constEnd()) {
// Hint is that the Node is larger than (or equal to) the largest value.
Node *n = static_cast<Node *>(pos.i->left);
@@ -895,6 +911,8 @@ Q_OUTOFLINE_TEMPLATE typename QMap<Key, T>::iterator QMap<Key, T>::erase(iterato
if (it == iterator(d->end()))
return it;
+ Q_ASSERT_X(isValidIterator(const_iterator(it)), "QMap::erase", "The specified iterator argument 'it' is invalid");
+
Node *n = it.i;
++it;
d->deleteNode(n);
diff --git a/src/corelib/tools/qpair.h b/src/corelib/tools/qpair.h
index 96b1b65e33..9b8691a3d8 100644
--- a/src/corelib/tools/qpair.h
+++ b/src/corelib/tools/qpair.h
@@ -57,6 +57,19 @@ struct QPair
QPair(const T1 &t1, const T2 &t2) : first(t1), second(t2) {}
// compiler-generated copy/move ctor/assignment operators are fine!
+ template <typename TT1, typename TT2>
+ QPair(const QPair<TT1, TT2> &p) : first(p.first), second(p.second) {}
+ template <typename TT1, typename TT2>
+ QPair &operator=(const QPair<TT1, TT2> &p)
+ { first = p.first; second = p.second; return *this; }
+#ifdef Q_COMPILER_RVALUE_REFS
+ template <typename TT1, typename TT2>
+ QPair(QPair<TT1, TT2> &&p) : first(std::move(p.first)), second(std::move(p.second)) {}
+ template <typename TT1, typename TT2>
+ QPair &operator=(QPair<TT1, TT2> &&p)
+ { first = std::move(p.first); second = std::move(p.second); return *this; }
+#endif
+
T1 first;
T2 second;
};
diff --git a/src/corelib/tools/qpair.qdoc b/src/corelib/tools/qpair.qdoc
index b0caf1aaf0..dd3df8c464 100644
--- a/src/corelib/tools/qpair.qdoc
+++ b/src/corelib/tools/qpair.qdoc
@@ -96,6 +96,26 @@
\sa qMakePair()
*/
+/*!
+ \fn QPair::QPair(const QPair<TT1, TT2> &p)
+ \since 5.2
+
+ Constructs a pair from the other pair \a p, of types TT1 and TT2. This
+ constructor will fail if \c first cannot be initialized from \c p.first or
+ if \c second cannot be initialized from \c p.second.
+
+ \sa qMakePair()
+*/
+
+/*!
+ \fn QPair &QPair::operator=(const QPair<TT1, TT2> &p)
+ \since 5.2
+
+ Copies the pair \a p onto this pair.
+
+ \sa qMakePair()
+*/
+
/*! \fn bool operator==(const QPair<T1, T2> &p1, const QPair<T1, T2> &p2)
\relates QPair
diff --git a/src/corelib/tools/qset.h b/src/corelib/tools/qset.h
index d5c3637293..ad2f91b983 100644
--- a/src/corelib/tools/qset.h
+++ b/src/corelib/tools/qset.h
@@ -70,6 +70,7 @@ public:
inline QSet<T> &operator=(const QSet<T> &other)
{ q_hash = other.q_hash; return *this; }
#ifdef Q_COMPILER_RVALUE_REFS
+ inline QSet(QSet &&other) : q_hash(qMove(other.q_hash)) {}
inline QSet<T> &operator=(QSet<T> &&other)
{ qSwap(q_hash, other.q_hash); return *this; }
#endif
@@ -180,7 +181,10 @@ public:
inline const_iterator cend() const { return q_hash.end(); }
inline const_iterator constEnd() const { return q_hash.constEnd(); }
iterator erase(iterator i)
- { return q_hash.erase(reinterpret_cast<typename Hash::iterator &>(i)); }
+ {
+ Q_ASSERT_X(isValidIterator(i), "QSet::erase", "The specified const_iterator argument 'i' is invalid");
+ return q_hash.erase(reinterpret_cast<typename Hash::iterator &>(i));
+ }
// more Qt
typedef iterator Iterator;
@@ -233,6 +237,10 @@ public:
private:
Hash q_hash;
+ bool isValidIterator(const iterator &i) const
+ {
+ return q_hash.isValidIterator(reinterpret_cast<const typename Hash::iterator&>(i));
+ }
};
template <class T>
@@ -253,8 +261,16 @@ Q_INLINE_TEMPLATE QSet<T> &QSet<T>::unite(const QSet<T> &other)
template <class T>
Q_INLINE_TEMPLATE QSet<T> &QSet<T>::intersect(const QSet<T> &other)
{
- QSet<T> copy1(*this);
- QSet<T> copy2(other);
+ QSet<T> copy1;
+ QSet<T> copy2;
+ if (size() <= other.size()) {
+ copy1 = *this;
+ copy2 = other;
+ } else {
+ copy1 = other;
+ copy2 = *this;
+ *this = copy1;
+ }
typename QSet<T>::const_iterator i = copy1.constEnd();
while (i != copy1.constBegin()) {
--i;
diff --git a/src/corelib/tools/qvarlengtharray.h b/src/corelib/tools/qvarlengtharray.h
index 825e05ae1b..d9b85c4173 100644
--- a/src/corelib/tools/qvarlengtharray.h
+++ b/src/corelib/tools/qvarlengtharray.h
@@ -192,6 +192,11 @@ private:
qint64 q_for_alignment_1;
double q_for_alignment_2;
};
+
+ bool isValidIterator(const const_iterator &i) const
+ {
+ return (i <= constEnd()) && (constBegin() <= i);
+ }
};
template <class T, int Prealloc>
@@ -355,6 +360,8 @@ inline void QVarLengthArray<T, Prealloc>::replace(int i, const T &t)
template <class T, int Prealloc>
Q_OUTOFLINE_TEMPLATE typename QVarLengthArray<T, Prealloc>::iterator QVarLengthArray<T, Prealloc>::insert(const_iterator before, size_type n, const T &t)
{
+ Q_ASSERT_X(isValidIterator(before), "QVarLengthArray::insert", "The specified const_iterator argument 'before' is invalid");
+
int offset = int(before - ptr);
if (n != 0) {
resize(s + n);
@@ -382,6 +389,9 @@ Q_OUTOFLINE_TEMPLATE typename QVarLengthArray<T, Prealloc>::iterator QVarLengthA
template <class T, int Prealloc>
Q_OUTOFLINE_TEMPLATE typename QVarLengthArray<T, Prealloc>::iterator QVarLengthArray<T, Prealloc>::erase(const_iterator abegin, const_iterator aend)
{
+ Q_ASSERT_X(isValidIterator(abegin), "QVarLengthArray::insert", "The specified const_iterator argument 'abegin' is invalid");
+ Q_ASSERT_X(isValidIterator(aend), "QVarLengthArray::insert", "The specified const_iterator argument 'aend' is invalid");
+
int f = int(abegin - ptr);
int l = int(aend - ptr);
int n = l - f;
diff --git a/src/corelib/tools/qvector.h b/src/corelib/tools/qvector.h
index 489ee821b9..de64d7a670 100644
--- a/src/corelib/tools/qvector.h
+++ b/src/corelib/tools/qvector.h
@@ -238,7 +238,10 @@ private:
void defaultConstruct(T *from, T *to);
void copyConstruct(const T *srcFrom, const T *srcTo, T *dstFrom);
void destruct(T *from, T *to);
-
+ bool isValidIterator(const iterator &i) const
+ {
+ return (i <= d->end()) && (d->begin() <= i);
+ }
class AlignmentDummy { Data header; T array[1]; };
};
@@ -578,6 +581,8 @@ inline void QVector<T>::removeLast()
template <typename T>
typename QVector<T>::iterator QVector<T>::insert(iterator before, size_type n, const T &t)
{
+ Q_ASSERT_X(isValidIterator(before), "QVector::insert", "The specified iterator argument 'before' is invalid");
+
int offset = std::distance(d->begin(), before);
if (n != 0) {
const T copy(t);
@@ -611,6 +616,9 @@ typename QVector<T>::iterator QVector<T>::insert(iterator before, size_type n, c
template <typename T>
typename QVector<T>::iterator QVector<T>::erase(iterator abegin, iterator aend)
{
+ Q_ASSERT_X(isValidIterator(abegin), "QVector::erase", "The specified iterator argument 'abegin' is invalid");
+ Q_ASSERT_X(isValidIterator(aend), "QVector::erase", "The specified iterator argument 'aend' is invalid");
+
const int itemsToErase = aend - abegin;
if (!itemsToErase)
diff --git a/src/dbus/doc/qtdbus.qdocconf b/src/dbus/doc/qtdbus.qdocconf
index b47e02ff43..1233ae3d47 100644
--- a/src/dbus/doc/qtdbus.qdocconf
+++ b/src/dbus/doc/qtdbus.qdocconf
@@ -20,7 +20,7 @@ excludedirs += ../../../examples/widgets/doc
examplesinstallpath = dbus
-depends += qtcore
+depends += qtdoc qtcore
# The following parameters are for creating a qhp file, the qhelpgenerator
# program can convert the qhp file into a qch file which can be opened in
@@ -49,3 +49,6 @@ qhp.QtDBus.subprojects.classes.title = C++ Classes
qhp.QtDBus.subprojects.classes.indexTitle = Qt D-Bus C++ Classes
qhp.QtDBus.subprojects.classes.selectors = class fake:headerfile
qhp.QtDBus.subprojects.classes.sortPages = true
+
+navigation.landingpage = "Qt D-Bus"
+navigation.cppclassespage = "Qt D-Bus C++ Classes"
diff --git a/src/dbus/qdbusabstractadaptor.cpp b/src/dbus/qdbusabstractadaptor.cpp
index 02ff40068b..04accee037 100644
--- a/src/dbus/qdbusabstractadaptor.cpp
+++ b/src/dbus/qdbusabstractadaptor.cpp
@@ -307,15 +307,18 @@ void QDBusAdaptorConnector::relay(QObject *senderObj, int lastSignalIdx, void **
// break down the parameter list
QVector<int> types;
- int inputCount = qDBusParametersForMethod(mm, types);
- if (inputCount == -1)
+ QString errorMsg;
+ int inputCount = qDBusParametersForMethod(mm, types, errorMsg);
+ if (inputCount == -1) {
// invalid signal signature
- // qDBusParametersForMethod has already complained
+ qWarning("QDBusAbstractAdaptor: Cannot relay signal %s::%s: %s",
+ senderMetaObject->className(), mm.methodSignature().constData(),
+ qPrintable(errorMsg));
return;
+ }
if (inputCount + 1 != types.count() ||
types.at(inputCount) == QDBusMetaTypeId::message()) {
// invalid signal signature
- // qDBusParametersForMethod has not yet complained about this one
qWarning("QDBusAbstractAdaptor: Cannot relay signal %s::%s",
senderMetaObject->className(), mm.methodSignature().constData());
return;
diff --git a/src/dbus/qdbusconnection_p.h b/src/dbus/qdbusconnection_p.h
index 73c8dcf411..48026e15bd 100644
--- a/src/dbus/qdbusconnection_p.h
+++ b/src/dbus/qdbusconnection_p.h
@@ -342,9 +342,9 @@ public:
};
// in qdbusmisc.cpp
-extern int qDBusParametersForMethod(const QMetaMethod &mm, QVector<int> &metaTypes);
+extern int qDBusParametersForMethod(const QMetaMethod &mm, QVector<int> &metaTypes, QString &errorMsg);
#endif // QT_BOOTSTRAPPED
-extern Q_DBUS_EXPORT int qDBusParametersForMethod(const QList<QByteArray> &parameters, QVector<int>& metaTypes);
+extern Q_DBUS_EXPORT int qDBusParametersForMethod(const QList<QByteArray> &parameters, QVector<int>& metaTypes, QString &errorMsg);
extern Q_DBUS_EXPORT bool qDBusCheckAsyncTag(const char *tag);
#ifndef QT_BOOTSTRAPPED
extern bool qDBusInterfaceInObject(QObject *obj, const QString &interface_name);
diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp
index d5c359aea1..010c076b7f 100644
--- a/src/dbus/qdbusintegrator.cpp
+++ b/src/dbus/qdbusintegrator.cpp
@@ -721,7 +721,8 @@ static int findSlot(const QMetaObject *mo, const QByteArray &name, int flags,
if (isAsync && returnType != QMetaType::Void)
continue;
- int inputCount = qDBusParametersForMethod(mm, metaTypes);
+ QString errorMsg;
+ int inputCount = qDBusParametersForMethod(mm, metaTypes, errorMsg);
if (inputCount == -1)
continue; // problem parsing
@@ -1312,7 +1313,8 @@ int QDBusConnectionPrivate::findSlot(QObject* obj, const QByteArray &normalizedN
if (midx == -1)
return -1;
- int inputCount = qDBusParametersForMethod(obj->metaObject()->method(midx), params);
+ QString errorMsg;
+ int inputCount = qDBusParametersForMethod(obj->metaObject()->method(midx), params, errorMsg);
if ( inputCount == -1 || inputCount + 1 != params.count() )
return -1; // failed to parse or invalid arguments or output arguments
diff --git a/src/dbus/qdbusmisc.cpp b/src/dbus/qdbusmisc.cpp
index d28d5598c6..5d3512845a 100644
--- a/src/dbus/qdbusmisc.cpp
+++ b/src/dbus/qdbusmisc.cpp
@@ -131,14 +131,14 @@ bool qDBusInterfaceInObject(QObject *obj, const QString &interface_name)
// metaTypes.count() >= retval + 1 in all cases
//
// sig must be the normalised signature for the method
-int qDBusParametersForMethod(const QMetaMethod &mm, QVector<int> &metaTypes)
+int qDBusParametersForMethod(const QMetaMethod &mm, QVector<int> &metaTypes, QString &errorMsg)
{
- return qDBusParametersForMethod(mm.parameterTypes(), metaTypes);
+ return qDBusParametersForMethod(mm.parameterTypes(), metaTypes, errorMsg);
}
#endif // QT_BOOTSTRAPPED
-int qDBusParametersForMethod(const QList<QByteArray> &parameterTypes, QVector<int>& metaTypes)
+int qDBusParametersForMethod(const QList<QByteArray> &parameterTypes, QVector<int>& metaTypes, QString &errorMsg)
{
QDBusMetaTypeId::init();
metaTypes.clear();
@@ -151,8 +151,7 @@ int qDBusParametersForMethod(const QList<QByteArray> &parameterTypes, QVector<in
for ( ; it != end; ++it) {
const QByteArray &type = *it;
if (type.endsWith('*')) {
- //qWarning("Could not parse the method '%s'", mm.methodSignature().constData());
- // pointer?
+ errorMsg = QLatin1String("Pointers are not supported: ") + QLatin1String(type);
return -1;
}
@@ -162,8 +161,7 @@ int qDBusParametersForMethod(const QList<QByteArray> &parameterTypes, QVector<in
int id = QMetaType::type(basictype);
if (id == 0) {
- //qWarning("Could not parse the method '%s'", mm.methodSignature().constData());
- // invalid type in method parameter list
+ errorMsg = QLatin1String("Unregistered output type in parameter list: ") + QLatin1String(type);
return -1;
} else if (QDBusMetaType::typeToSignature(id) == 0)
return -1;
@@ -174,22 +172,22 @@ int qDBusParametersForMethod(const QList<QByteArray> &parameterTypes, QVector<in
}
if (seenMessage) { // && !type.endsWith('&')
- //qWarning("Could not parse the method '%s'", mm.methodSignature().constData());
- // non-output parameters after message or after output params
+ errorMsg = QLatin1String("Invalid method, non-output parameters after message or after output parameters: ") + QLatin1String(type);
return -1; // not allowed
}
int id = QMetaType::type(type);
if (id == QMetaType::UnknownType) {
- //qWarning("Could not parse the method '%s'", mm.methodSignature().constData());
- // invalid type in method parameter list
+ errorMsg = QLatin1String("Unregistered input type in parameter list: ") + QLatin1String(type);
return -1;
}
if (id == QDBusMetaTypeId::message())
seenMessage = true;
- else if (QDBusMetaType::typeToSignature(id) == 0)
+ else if (QDBusMetaType::typeToSignature(id) == 0) {
+ errorMsg = QLatin1String("Type not registered with QtDBus in parameter list: ") + QLatin1String(type);
return -1;
+ }
metaTypes.append(id);
++inputCount;
diff --git a/src/dbus/qdbusxmlgenerator.cpp b/src/dbus/qdbusxmlgenerator.cpp
index 8c822162e4..c724ac573a 100644
--- a/src/dbus/qdbusxmlgenerator.cpp
+++ b/src/dbus/qdbusxmlgenerator.cpp
@@ -41,6 +41,7 @@
#include <QtCore/qmetaobject.h>
#include <QtCore/qstringlist.h>
+#include <QtCore/qdebug.h>
#include "qdbusinterface_p.h" // for ANNOTATION_NO_WAIT
#include "qdbusabstractadaptor_p.h" // for QCLASSINFO_DBUS_*
@@ -159,17 +160,24 @@ static QString generateInterfaceXml(const QMetaObject *mo, int flags, int method
if (QDBusMetaType::signatureToType(typeName) == QVariant::Invalid)
xml += QString::fromLatin1(" <annotation name=\"org.qtproject.QtDBus.QtTypeName.Out0\" value=\"%1\"/>\n")
.arg(typeNameToXml(QMetaType::typeName(typeId)));
- } else
+ } else {
+ qWarning() << "Unsupported return type" << typeId << QMetaType::typeName(typeId) << "in method" << mm.name();
continue;
+ }
}
- else if (typeId == QMetaType::UnknownType)
+ else if (typeId == QMetaType::UnknownType) {
+ qWarning() << "Invalid return type in method" << mm.name();
continue; // wasn't a valid type
+ }
QList<QByteArray> names = mm.parameterNames();
QVector<int> types;
- int inputCount = qDBusParametersForMethod(mm, types);
- if (inputCount == -1)
+ QString errorMsg;
+ int inputCount = qDBusParametersForMethod(mm, types, errorMsg);
+ if (inputCount == -1) {
+ qWarning() << "Skipped method" << mm.name() << ":" << qPrintable(errorMsg);
continue; // invalid form
+ }
if (isSignal && inputCount + 1 != types.count())
continue; // signal with output arguments?
if (isSignal && types.at(inputCount) == QDBusMetaTypeId::message())
diff --git a/src/gui/doc/qtgui.qdocconf b/src/gui/doc/qtgui.qdocconf
index 5073dd7f0f..ed30172376 100644
--- a/src/gui/doc/qtgui.qdocconf
+++ b/src/gui/doc/qtgui.qdocconf
@@ -48,3 +48,6 @@ exampledirs += ../../../examples/gui \
imagedirs += images \
../../../examples/gui/doc/images \
../../../doc/src/images \
+
+navigation.landingpage = "Qt GUI"
+navigation.cppclassespage = "Qt GUI C++ Classes"
diff --git a/src/gui/image/qicon.cpp b/src/gui/image/qicon.cpp
index aef7324171..cb508ae6c7 100644
--- a/src/gui/image/qicon.cpp
+++ b/src/gui/image/qicon.cpp
@@ -1068,7 +1068,6 @@ void QIcon::setThemeName(const QString &name)
*/
QString QIcon::themeName()
{
- QIconLoader::instance()->ensureInitialized();
return QIconLoader::instance()->themeName();
}
diff --git a/src/gui/image/qicon.h b/src/gui/image/qicon.h
index e81bea69d6..f1a78b508c 100644
--- a/src/gui/image/qicon.h
+++ b/src/gui/image/qicon.h
@@ -62,6 +62,10 @@ public:
QIcon();
QIcon(const QPixmap &pixmap);
QIcon(const QIcon &other);
+#ifdef Q_COMPILER_RVALUE_REFS
+ QIcon(QIcon &&other)
+ :d(0) { qSwap(d, other.d); }
+#endif
explicit QIcon(const QString &fileName); // file or resource name
explicit QIcon(QIconEngine *engine);
~QIcon();
diff --git a/src/gui/image/qiconloader.cpp b/src/gui/image/qiconloader.cpp
index 105dc26c9b..d202d62957 100644
--- a/src/gui/image/qiconloader.cpp
+++ b/src/gui/image/qiconloader.cpp
@@ -128,6 +128,7 @@ void QIconLoader::ensureInitialized()
QIconLoader *QIconLoader::instance()
{
+ iconLoaderInstance()->ensureInitialized();
return iconLoaderInstance();
}
@@ -368,17 +369,14 @@ bool QIconLoaderEngine::hasIcon() const
// Lazily load the icon
void QIconLoaderEngine::ensureLoaded()
{
-
- iconLoaderInstance()->ensureInitialized();
-
- if (!(iconLoaderInstance()->themeKey() == m_key)) {
+ if (!(QIconLoader::instance()->themeKey() == m_key)) {
while (!m_entries.isEmpty())
delete m_entries.takeLast();
Q_ASSERT(m_entries.size() == 0);
- m_entries = iconLoaderInstance()->loadIcon(m_iconName);
- m_key = iconLoaderInstance()->themeKey();
+ m_entries = QIconLoader::instance()->loadIcon(m_iconName);
+ m_key = QIconLoader::instance()->themeKey();
}
}
@@ -565,7 +563,7 @@ void QIconLoaderEngine::virtual_hook(int id, void *data)
{
QIconEngine::AvailableSizesArgument &arg
= *reinterpret_cast<QIconEngine::AvailableSizesArgument*>(data);
- const QList<QIconDirInfo> directoryKey = iconLoaderInstance()->theme().keyList();
+ const QList<QIconDirInfo> directoryKey = QIconLoader::instance()->theme().keyList();
arg.sizes.clear();
// Gets all sizes from the DirectoryInfo entries
diff --git a/src/gui/image/qimage.h b/src/gui/image/qimage.h
index 50d4bc7666..a4aaf049f0 100644
--- a/src/gui/image/qimage.h
+++ b/src/gui/image/qimage.h
@@ -139,6 +139,11 @@ public:
explicit QImage(const QString &fileName, const char *format = 0);
QImage(const QImage &);
+#ifdef Q_COMPILER_RVALUE_REFS
+ inline QImage(QImage &&other)
+ : QPaintDevice(), d(0)
+ { qSwap(d, other.d); }
+#endif
~QImage();
QImage &operator=(const QImage &);
diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp
index bf8440cccf..e1d0b1c01f 100644
--- a/src/gui/kernel/qguiapplication.cpp
+++ b/src/gui/kernel/qguiapplication.cpp
@@ -785,14 +785,14 @@ QString QGuiApplication::platformName()
*QGuiApplicationPrivate::platform_name : QString();
}
-static void init_platform(const QString &pluginArgument, const QString &platformPluginPath)
+static void init_platform(const QString &pluginArgument, const QString &platformPluginPath, int &argc, char **argv)
{
// Split into platform name and arguments
QStringList arguments = pluginArgument.split(QLatin1Char(':'));
const QString name = arguments.takeFirst().toLower();
// Create the platform integration.
- QGuiApplicationPrivate::platform_integration = QPlatformIntegrationFactory::create(name, arguments, platformPluginPath);
+ QGuiApplicationPrivate::platform_integration = QPlatformIntegrationFactory::create(name, arguments, argc, argv, platformPluginPath);
if (QGuiApplicationPrivate::platform_integration) {
QGuiApplicationPrivate::platform_name = new QString(name);
} else {
@@ -920,7 +920,7 @@ void QGuiApplicationPrivate::createPlatformIntegration()
argc = j;
}
- init_platform(QLatin1String(platformName), platformPluginPath);
+ init_platform(QLatin1String(platformName), platformPluginPath, argc, argv);
}
diff --git a/src/gui/kernel/qkeysequence.h b/src/gui/kernel/qkeysequence.h
index 05460c6651..8a989682d8 100644
--- a/src/gui/kernel/qkeysequence.h
+++ b/src/gui/kernel/qkeysequence.h
@@ -44,6 +44,7 @@
#include <QtCore/qnamespace.h>
#include <QtCore/qstring.h>
+#include <QtCore/qobjectdefs.h>
QT_BEGIN_NAMESPACE
@@ -68,6 +69,9 @@ class QKeySequencePrivate;
class Q_GUI_EXPORT QKeySequence
{
+ Q_GADGET
+ Q_ENUMS(StandardKey)
+
public:
enum StandardKey {
UnknownKey,
diff --git a/src/gui/kernel/qplatformdialoghelper.cpp b/src/gui/kernel/qplatformdialoghelper.cpp
index 5f86b511f7..74442736c3 100644
--- a/src/gui/kernel/qplatformdialoghelper.cpp
+++ b/src/gui/kernel/qplatformdialoghelper.cpp
@@ -376,9 +376,9 @@ public:
QStringList nameFilters;
QString defaultSuffix;
QStringList history;
- QString initialDirectory;
+ QUrl initialDirectory;
QString initiallySelectedNameFilter;
- QStringList initiallySelectedFiles;
+ QList<QUrl> initiallySelectedFiles;
};
QFileDialogOptions::QFileDialogOptions() : d(new QFileDialogOptionsPrivate)
@@ -495,6 +495,8 @@ QStringList QFileDialogOptions::nameFilters() const
void QFileDialogOptions::setDefaultSuffix(const QString &suffix)
{
d->defaultSuffix = suffix;
+ if (d->defaultSuffix.size() > 1 && d->defaultSuffix.startsWith(QLatin1Char('.')))
+ d->defaultSuffix.remove(0, 1); // Silently change ".txt" -> "txt".
}
QString QFileDialogOptions::defaultSuffix() const
@@ -528,12 +530,12 @@ bool QFileDialogOptions::isLabelExplicitlySet(DialogLabel label)
return label >= 0 && label < DialogLabelCount && !d->labels[label].isEmpty();
}
-QString QFileDialogOptions::initialDirectory() const
+QUrl QFileDialogOptions::initialDirectory() const
{
return d->initialDirectory;
}
-void QFileDialogOptions::setInitialDirectory(const QString &directory)
+void QFileDialogOptions::setInitialDirectory(const QUrl &directory)
{
d->initialDirectory = directory;
}
@@ -548,16 +550,21 @@ void QFileDialogOptions::setInitiallySelectedNameFilter(const QString &filter)
d->initiallySelectedNameFilter = filter;
}
-QStringList QFileDialogOptions::initiallySelectedFiles() const
+QList<QUrl> QFileDialogOptions::initiallySelectedFiles() const
{
return d->initiallySelectedFiles;
}
-void QFileDialogOptions::setInitiallySelectedFiles(const QStringList &files)
+void QFileDialogOptions::setInitiallySelectedFiles(const QList<QUrl> &files)
{
d->initiallySelectedFiles = files;
}
+bool QPlatformFileDialogHelper::isSupportedUrl(const QUrl &url) const
+{
+ return url.isLocalFile();
+}
+
/*!
\class QPlatformFileDialogHelper
\since 5.0
diff --git a/src/gui/kernel/qplatformdialoghelper.h b/src/gui/kernel/qplatformdialoghelper.h
index ecc00ed8c6..092839aaed 100644
--- a/src/gui/kernel/qplatformdialoghelper.h
+++ b/src/gui/kernel/qplatformdialoghelper.h
@@ -57,6 +57,7 @@
#include <QtCore/QSharedDataPointer>
#include <QtCore/QSharedPointer>
#include <QtCore/QDir>
+#include <QtCore/QUrl>
#include <QtGui/QRgb>
QT_BEGIN_NAMESPACE
@@ -163,7 +164,11 @@ class Q_GUI_EXPORT QFontDialogOptions
public:
enum FontDialogOption {
NoButtons = 0x00000001,
- DontUseNativeDialog = 0x00000002
+ DontUseNativeDialog = 0x00000002,
+ ScalableFonts = 0x00000004,
+ NonScalableFonts = 0x00000008,
+ MonospacedFonts = 0x00000010,
+ ProportionalFonts = 0x00000020
};
Q_DECLARE_FLAGS(FontDialogOptions, FontDialogOption)
@@ -217,13 +222,14 @@ public:
enum FileDialogOption
{
- ShowDirsOnly = 0x00000001,
- DontResolveSymlinks = 0x00000002,
- DontConfirmOverwrite = 0x00000004,
- DontUseSheet = 0x00000008,
- DontUseNativeDialog = 0x00000010,
- ReadOnly = 0x00000020,
- HideNameFilterDetails = 0x00000040
+ ShowDirsOnly = 0x00000001,
+ DontResolveSymlinks = 0x00000002,
+ DontConfirmOverwrite = 0x00000004,
+ DontUseSheet = 0x00000008,
+ DontUseNativeDialog = 0x00000010,
+ ReadOnly = 0x00000020,
+ HideNameFilterDetails = 0x00000040,
+ DontUseCustomDirectoryIcons = 0x00000080
};
Q_DECLARE_FLAGS(FileDialogOptions, FileDialogOption)
@@ -270,14 +276,14 @@ public:
QString labelText(DialogLabel label) const;
bool isLabelExplicitlySet(DialogLabel label);
- QString initialDirectory() const;
- void setInitialDirectory(const QString &);
+ QUrl initialDirectory() const;
+ void setInitialDirectory(const QUrl &);
QString initiallySelectedNameFilter() const;
void setInitiallySelectedNameFilter(const QString &);
- QStringList initiallySelectedFiles() const;
- void setInitiallySelectedFiles(const QStringList &);
+ QList<QUrl> initiallySelectedFiles() const;
+ void setInitiallySelectedFiles(const QList<QUrl> &);
private:
QSharedDataPointer<QFileDialogOptionsPrivate> d;
@@ -290,14 +296,16 @@ class Q_GUI_EXPORT QPlatformFileDialogHelper : public QPlatformDialogHelper
Q_OBJECT
public:
virtual bool defaultNameFilterDisables() const = 0;
- virtual void setDirectory(const QString &directory) = 0;
- virtual QString directory() const = 0;
- virtual void selectFile(const QString &filename) = 0;
- virtual QStringList selectedFiles() const = 0;
+ virtual void setDirectory(const QUrl &directory) = 0;
+ virtual QUrl directory() const = 0;
+ virtual void selectFile(const QUrl &filename) = 0;
+ virtual QList<QUrl> selectedFiles() const = 0;
virtual void setFilter() = 0;
virtual void selectNameFilter(const QString &filter) = 0;
virtual QString selectedNameFilter() const = 0;
+ virtual bool isSupportedUrl(const QUrl &url) const;
+
const QSharedPointer<QFileDialogOptions> &options() const;
void setOptions(const QSharedPointer<QFileDialogOptions> &options);
@@ -305,10 +313,10 @@ public:
static const char *filterRegExp;
Q_SIGNALS:
- void fileSelected(const QString &file);
- void filesSelected(const QStringList &files);
- void currentChanged(const QString &path);
- void directoryEntered(const QString &directory);
+ void fileSelected(const QUrl &file);
+ void filesSelected(const QList<QUrl> &files);
+ void currentChanged(const QUrl &path);
+ void directoryEntered(const QUrl &directory);
void filterSelected(const QString &filter);
private:
diff --git a/src/gui/kernel/qplatformintegration.cpp b/src/gui/kernel/qplatformintegration.cpp
index e4f45ebb6e..2910bb9280 100644
--- a/src/gui/kernel/qplatformintegration.cpp
+++ b/src/gui/kernel/qplatformintegration.cpp
@@ -328,6 +328,8 @@ QVariant QPlatformIntegration::styleHint(StyleHint hint) const
return QVariant(false);
case SynthesizeMouseFromTouchEvents:
return true;
+ case SetFocusOnTouchRelease:
+ return QVariant(false);
}
return 0;
diff --git a/src/gui/kernel/qplatformintegration.h b/src/gui/kernel/qplatformintegration.h
index b7a44b13de..fcac211f72 100644
--- a/src/gui/kernel/qplatformintegration.h
+++ b/src/gui/kernel/qplatformintegration.h
@@ -141,7 +141,8 @@ public:
StartDragVelocity,
UseRtlExtensions,
SynthesizeMouseFromTouchEvents,
- PasswordMaskCharacter
+ PasswordMaskCharacter,
+ SetFocusOnTouchRelease
};
virtual QVariant styleHint(StyleHint hint) const;
diff --git a/src/gui/kernel/qplatformintegrationfactory.cpp b/src/gui/kernel/qplatformintegrationfactory.cpp
index 21f53d17de..365edd2010 100644
--- a/src/gui/kernel/qplatformintegrationfactory.cpp
+++ b/src/gui/kernel/qplatformintegrationfactory.cpp
@@ -55,18 +55,30 @@ Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
(QPlatformIntegrationFactoryInterface_iid, QLatin1String("/platforms"), Qt::CaseInsensitive))
Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, directLoader,
(QPlatformIntegrationFactoryInterface_iid, QLatin1String(""), Qt::CaseInsensitive))
-#endif
-QPlatformIntegration *QPlatformIntegrationFactory::create(const QString &platform, const QStringList &paramList, const QString &platformPluginPath)
+static inline QPlatformIntegration *loadIntegration(QFactoryLoader *loader, const QString &key, const QStringList &parameters, int &argc, char ** argv)
+{
+ const int index = loader->indexOf(key);
+ if (index != -1) {
+ if (QPlatformIntegrationPlugin *factory = qobject_cast<QPlatformIntegrationPlugin *>(loader->instance(index)))
+ if (QPlatformIntegration *result = factory->create(key, parameters, argc, argv))
+ return result;
+ }
+ return 0;
+}
+
+#endif // !QT_NO_LIBRARY
+
+QPlatformIntegration *QPlatformIntegrationFactory::create(const QString &platform, const QStringList &paramList, int &argc, char **argv, const QString &platformPluginPath)
{
#ifndef QT_NO_LIBRARY
// Try loading the plugin from platformPluginPath first:
if (!platformPluginPath.isEmpty()) {
QCoreApplication::addLibraryPath(platformPluginPath);
- if (QPlatformIntegration *ret = qLoadPlugin1<QPlatformIntegration, QPlatformIntegrationPlugin>(directLoader(), platform, paramList))
+ if (QPlatformIntegration *ret = loadIntegration(directLoader(), platform, paramList, argc, argv))
return ret;
}
- if (QPlatformIntegration *ret = qLoadPlugin1<QPlatformIntegration, QPlatformIntegrationPlugin>(loader(), platform, paramList))
+ if (QPlatformIntegration *ret = loadIntegration(loader(), platform, paramList, argc, argv))
return ret;
#endif
return 0;
diff --git a/src/gui/kernel/qplatformintegrationfactory_p.h b/src/gui/kernel/qplatformintegrationfactory_p.h
index fb3ba55316..bc8ce11609 100644
--- a/src/gui/kernel/qplatformintegrationfactory_p.h
+++ b/src/gui/kernel/qplatformintegrationfactory_p.h
@@ -64,7 +64,7 @@ class Q_GUI_EXPORT QPlatformIntegrationFactory
{
public:
static QStringList keys(const QString &platformPluginPath = QString());
- static QPlatformIntegration *create(const QString &name, const QStringList &args, const QString &platformPluginPath = QString());
+ static QPlatformIntegration *create(const QString &name, const QStringList &args, int &argc, char **argv, const QString &platformPluginPath = QString());
};
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qplatformintegrationplugin.cpp b/src/gui/kernel/qplatformintegrationplugin.cpp
index 0f7f365d2a..2a9a047141 100644
--- a/src/gui/kernel/qplatformintegrationplugin.cpp
+++ b/src/gui/kernel/qplatformintegrationplugin.cpp
@@ -52,4 +52,18 @@ QPlatformIntegrationPlugin::~QPlatformIntegrationPlugin()
{
}
+QPlatformIntegration *QPlatformIntegrationPlugin::create(const QString &key, const QStringList &paramList)
+{
+ Q_UNUSED(key)
+ Q_UNUSED(paramList);
+ return 0;
+}
+
+QPlatformIntegration *QPlatformIntegrationPlugin::create(const QString &key, const QStringList &paramList, int &argc, char **argv)
+{
+ Q_UNUSED(argc)
+ Q_UNUSED(argv)
+ return create(key, paramList); // Fallback for platform plugins that do not implement the argc/argv version.
+}
+
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qplatformintegrationplugin.h b/src/gui/kernel/qplatformintegrationplugin.h
index 434366f0b0..674622f84a 100644
--- a/src/gui/kernel/qplatformintegrationplugin.h
+++ b/src/gui/kernel/qplatformintegrationplugin.h
@@ -68,7 +68,8 @@ public:
explicit QPlatformIntegrationPlugin(QObject *parent = 0);
~QPlatformIntegrationPlugin();
- virtual QPlatformIntegration *create(const QString &key, const QStringList &paramList) = 0;
+ virtual QPlatformIntegration *create(const QString &key, const QStringList &paramList);
+ virtual QPlatformIntegration *create(const QString &key, const QStringList &paramList, int &argc, char **argv);
};
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qplatformservices.cpp b/src/gui/kernel/qplatformservices.cpp
index f2cade0a35..d09b74c6fe 100644
--- a/src/gui/kernel/qplatformservices.cpp
+++ b/src/gui/kernel/qplatformservices.cpp
@@ -74,7 +74,10 @@ bool QPlatformServices::openDocument(const QUrl &url)
/*!
* \brief QPlatformServices::desktopEnvironment returns the active desktop environment.
*
- * On Unix this function returns KDE, GNOME or UNKNOWN.
+ * On Unix this function returns the uppercase desktop environment name, such as
+ * KDE, GNOME, UNITY, XFCE, LXDE etc. or UNKNOWN if none was detected.
+ * The primary way to detect the desktop environment is the environment variable
+ * XDG_CURRENT_DESKTOP.
*/
QByteArray QPlatformServices::desktopEnvironment() const
{
diff --git a/src/gui/kernel/qplatformtheme.cpp b/src/gui/kernel/qplatformtheme.cpp
index 02b69bcb4d..098b8dad66 100644
--- a/src/gui/kernel/qplatformtheme.cpp
+++ b/src/gui/kernel/qplatformtheme.cpp
@@ -208,10 +208,12 @@ QPixmap QPlatformTheme::standardPixmap(StandardPixmap sp, const QSizeF &size) co
return QPixmap();
}
-QPixmap QPlatformTheme::fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &size) const
+QPixmap QPlatformTheme::fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &size,
+ QPlatformTheme::IconOptions iconOptions) const
{
Q_UNUSED(fileInfo);
Q_UNUSED(size);
+ Q_UNUSED(iconOptions);
// TODO Should return QCommonStyle pixmaps?
return QPixmap();
}
diff --git a/src/gui/kernel/qplatformtheme.h b/src/gui/kernel/qplatformtheme.h
index 80ba29a028..1d7a1ccffa 100644
--- a/src/gui/kernel/qplatformtheme.h
+++ b/src/gui/kernel/qplatformtheme.h
@@ -154,6 +154,7 @@ public:
ComboLineEditFont,
SmallFont,
MiniFont,
+ FixedFont,
NFonts
};
@@ -253,6 +254,11 @@ public:
AnimateToolBoxUiEffect = 0x40
};
+ enum IconOption {
+ DontUseCustomDirectoryIcons = 0x01
+ };
+ Q_DECLARE_FLAGS(IconOptions, IconOption)
+
explicit QPlatformTheme();
virtual ~QPlatformTheme();
@@ -274,7 +280,8 @@ public:
virtual QVariant themeHint(ThemeHint hint) const;
virtual QPixmap standardPixmap(StandardPixmap sp, const QSizeF &size) const;
- virtual QPixmap fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &size) const;
+ virtual QPixmap fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &size,
+ QPlatformTheme::IconOptions iconOptions = 0) const;
virtual QIconEngine *createIconEngine(const QString &iconName) const;
diff --git a/src/gui/kernel/qshortcutmap.cpp b/src/gui/kernel/qshortcutmap.cpp
index cd822090e2..513e21937e 100644
--- a/src/gui/kernel/qshortcutmap.cpp
+++ b/src/gui/kernel/qshortcutmap.cpp
@@ -324,6 +324,9 @@ bool QShortcutMap::tryShortcutEvent(QObject *o, QKeyEvent *e)
{
Q_D(QShortcutMap);
+ if (e->key() == Qt::Key_unknown)
+ return false;
+
bool wasAccepted = e->isAccepted();
bool wasSpontaneous = e->spont;
if (d->currentState == QKeySequence::NoMatch) {
diff --git a/src/gui/kernel/qstylehints.cpp b/src/gui/kernel/qstylehints.cpp
index 30b12835f7..a302f2186c 100644
--- a/src/gui/kernel/qstylehints.cpp
+++ b/src/gui/kernel/qstylehints.cpp
@@ -218,4 +218,15 @@ bool QStyleHints::useRtlExtensions() const
return hint(QPlatformIntegration::UseRtlExtensions).toBool();
}
+/*!
+ Returns \c true if focus objects (line edits etc) should receive
+ input focus after a touch/mouse release. This is normal behavior on
+ touch platforms. On desktop platforms, the standard is to set
+ focus already on touch/mouse press.
+*/
+bool QStyleHints::setFocusOnTouchRelease() const
+{
+ return hint(QPlatformIntegration::SetFocusOnTouchRelease).toBool();
+}
+
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qstylehints.h b/src/gui/kernel/qstylehints.h
index 64ef182aab..a0facd5f94 100644
--- a/src/gui/kernel/qstylehints.h
+++ b/src/gui/kernel/qstylehints.h
@@ -65,6 +65,7 @@ public:
QChar passwordMaskCharacter() const;
qreal fontSmoothingGamma() const;
bool useRtlExtensions() const;
+ bool setFocusOnTouchRelease() const;
private:
friend class QGuiApplication;
diff --git a/src/gui/kernel/qtouchdevice.cpp b/src/gui/kernel/qtouchdevice.cpp
index 02c6dd9efc..3ad4b4161e 100644
--- a/src/gui/kernel/qtouchdevice.cpp
+++ b/src/gui/kernel/qtouchdevice.cpp
@@ -140,6 +140,16 @@ QTouchDevice::Capabilities QTouchDevice::capabilities() const
}
/*!
+ Returns the maximum number of simultaneous touch points (fingers) that
+ can be detected.
+ \since 5.2
+ */
+int QTouchDevice::maximumTouchPoints() const
+{
+ return d->maxTouchPoints;
+}
+
+/*!
Returns the touch device name.
This string may often be empty. It is however useful for systems that have
@@ -169,6 +179,15 @@ void QTouchDevice::setCapabilities(Capabilities caps)
}
/*!
+ Sets the maximum number of simultaneous touchpoints \a max
+ supported by the device and its driver.
+ */
+void QTouchDevice::setMaximumTouchPoints(int max)
+{
+ d->maxTouchPoints = max;
+}
+
+/*!
Sets the \a name (a unique identifier) for the device. In most systems it is
enough to leave this unset and keep the default empty name. This identifier
becomes important when having multiple touch devices and a need to
diff --git a/src/gui/kernel/qtouchdevice.h b/src/gui/kernel/qtouchdevice.h
index 312bdce3e6..6aca93907c 100644
--- a/src/gui/kernel/qtouchdevice.h
+++ b/src/gui/kernel/qtouchdevice.h
@@ -75,10 +75,12 @@ public:
QString name() const;
DeviceType type() const;
Capabilities capabilities() const;
+ int maximumTouchPoints() const;
void setName(const QString &name);
void setType(DeviceType devType);
void setCapabilities(Capabilities caps);
+ void setMaximumTouchPoints(int max);
private:
QTouchDevicePrivate *d;
diff --git a/src/gui/kernel/qtouchdevice_p.h b/src/gui/kernel/qtouchdevice_p.h
index 435f8a5c37..fb87f49736 100644
--- a/src/gui/kernel/qtouchdevice_p.h
+++ b/src/gui/kernel/qtouchdevice_p.h
@@ -64,12 +64,14 @@ class QTouchDevicePrivate
public:
QTouchDevicePrivate()
: type(QTouchDevice::TouchScreen),
- caps(QTouchDevice::Position)
+ caps(QTouchDevice::Position),
+ maxTouchPoints(1)
{ }
QTouchDevice::DeviceType type;
QTouchDevice::Capabilities caps;
QString name;
+ int maxTouchPoints;
static void registerDevice(QTouchDevice *dev);
static bool isRegistered(QTouchDevice *dev);
diff --git a/src/gui/opengl/qopenglfunctions.cpp b/src/gui/opengl/qopenglfunctions.cpp
index 3737df7497..60591a34d2 100644
--- a/src/gui/opengl/qopenglfunctions.cpp
+++ b/src/gui/opengl/qopenglfunctions.cpp
@@ -141,8 +141,8 @@ QT_BEGIN_NAMESPACE
/*!
\enum QOpenGLFunctions::OpenGLFeature
- This enum defines OpenGL/ES 2.0 features that may be optional
- on other platforms.
+ This enum defines OpenGL and OpenGL ES features whose presence
+ may depend on the implementation.
\value Multitexture glActiveTexture() function is available.
\value Shaders Shader functions are available.
@@ -158,6 +158,7 @@ QT_BEGIN_NAMESPACE
\value StencilSeparate Separate stencil functions are available.
\value NPOTTextures Non power of two textures are available.
\value NPOTTextureRepeat Non power of two textures can use GL_REPEAT as wrap parameter.
+ \value FixedFunctionPipeline The fixed function pipeline is available.
*/
// Hidden private fields for additional extension data.
@@ -331,6 +332,13 @@ static int qt_gl_resolve_features()
if (format.majorVersion() >= 3)
features |= QOpenGLFunctions::Framebuffers;
+ const QPair<int, int> version = format.version();
+ if (version < qMakePair(3, 0)
+ || (version == qMakePair(3, 0) && format.testOption(QSurfaceFormat::DeprecatedFunctions))
+ || (version == qMakePair(3, 1) && extensions.match("GL_ARB_compatibility"))
+ || (version >= qMakePair(3, 2) && format.profile() == QSurfaceFormat::CompatibilityProfile)) {
+ features |= QOpenGLFunctions::FixedFunctionPipeline;
+ }
return features;
#endif
}
diff --git a/src/gui/opengl/qopenglfunctions.h b/src/gui/opengl/qopenglfunctions.h
index 1548ad4a24..9d8da209ad 100644
--- a/src/gui/opengl/qopenglfunctions.h
+++ b/src/gui/opengl/qopenglfunctions.h
@@ -199,7 +199,8 @@ public:
Multisample = 0x0400,
StencilSeparate = 0x0800,
NPOTTextures = 0x1000,
- NPOTTextureRepeat = 0x2000
+ NPOTTextureRepeat = 0x2000,
+ FixedFunctionPipeline = 0x4000
};
Q_DECLARE_FLAGS(OpenGLFeatures, OpenGLFeature)
diff --git a/src/gui/painting/painting.pri b/src/gui/painting/painting.pri
index 47ba27d72a..aadcc0f686 100644
--- a/src/gui/painting/painting.pri
+++ b/src/gui/painting/painting.pri
@@ -91,9 +91,12 @@ SSE2_SOURCES += painting/qdrawhelper_sse2.cpp
SSSE3_SOURCES += painting/qdrawhelper_ssse3.cpp
IWMMXT_SOURCES += painting/qdrawhelper_iwmmxt.cpp
AVX_SOURCES += painting/qdrawhelper_avx.cpp
-NEON_SOURCES += painting/qdrawhelper_neon.cpp
-NEON_HEADERS += painting/qdrawhelper_neon_p.h
-NEON_ASM += ../3rdparty/pixman/pixman-arm-neon-asm.S painting/qdrawhelper_neon_asm.S
+
+!ios {
+ NEON_SOURCES += painting/qdrawhelper_neon.cpp
+ NEON_HEADERS += painting/qdrawhelper_neon_p.h
+ NEON_ASM += ../3rdparty/pixman/pixman-arm-neon-asm.S painting/qdrawhelper_neon_asm.S
+}
MIPS_DSP_SOURCES += painting/qdrawhelper_mips_dsp.cpp
MIPS_DSP_HEADERS += painting/qdrawhelper_mips_dsp_p.h painting/qt_mips_asm_dsp_p.h
diff --git a/src/gui/painting/qcolor.cpp b/src/gui/painting/qcolor.cpp
index 12ca84d8d1..c93320c491 100644
--- a/src/gui/painting/qcolor.cpp
+++ b/src/gui/painting/qcolor.cpp
@@ -90,7 +90,8 @@ QT_BEGIN_NAMESPACE
specified.
A color can be set by passing an RGB string (such as "#112233"),
- or a color name (such as "blue"), to the setNamedColor() function.
+ or an ARGB string (such as "#ff112233") or a color name (such as "blue"),
+ to the setNamedColor() function.
The color names are taken from the SVG 1.0 color names. The name()
function returns the name of the color in the format
"#RRGGBB". Colors can also be set using setRgb(), setHsv() and
@@ -301,6 +302,17 @@ QT_BEGIN_NAMESPACE
*/
/*!
+ \enum QColor::NameFormat
+
+ How to format the output of the name() function
+
+ \value HexRgb #RRGGBB A "#" character followed by three two-digit hexadecimal numbers (i.e. \c{#RRGGBB}).
+ \value HexArgb #AARRGGBB A "#" character followed by four two-digit hexadecimal numbers (i.e. \c{#AARRGGBB}).
+
+ \sa name()
+*/
+
+/*!
\fn Spec QColor::spec() const
Returns how the color was specified.
@@ -489,8 +501,28 @@ QColor::QColor(Spec spec)
QString QColor::name() const
{
+ return name(HexRgb);
+}
+
+/*!
+ \since 5.2
+
+ Returns the name of the color in the specified \a format.
+
+ \sa setNamedColor(), NameFormat
+*/
+
+QString QColor::name(NameFormat format) const
+{
QString s;
- s.sprintf("#%02x%02x%02x", red(), green(), blue());
+ switch (format) {
+ case HexRgb:
+ s.sprintf("#%02x%02x%02x", red(), green(), blue());
+ break;
+ case HexArgb:
+ s.sprintf("#%02x%02x%02x%02x", alpha(), red(), green(), blue());
+ break;
+ }
return s;
}
@@ -501,6 +533,7 @@ QString QColor::name() const
\list
\li #RGB (each of R, G, and B is a single hex digit)
\li #RRGGBB
+ \li #AARRGGBB (Since 5.2)
\li #RRRGGGBBB
\li #RRRRGGGGBBBB
\li A name from the list of colors defined in the list of \l{http://www.w3.org/TR/SVG/types.html#ColorKeywords}{SVG color keyword names}
@@ -545,9 +578,9 @@ bool QColor::setColorFromString(const QString &name)
}
if (name.startsWith(QLatin1Char('#'))) {
- QRgb rgb;
- if (qt_get_hex_rgb(name.constData(), name.length(), &rgb)) {
- setRgb(rgb);
+ QRgb rgba;
+ if (qt_get_hex_rgb(name.constData(), name.length(), &rgba)) {
+ setRgba(rgba);
return true;
} else {
invalidate();
diff --git a/src/gui/painting/qcolor.h b/src/gui/painting/qcolor.h
index ef3503e8d8..1ede5a3682 100644
--- a/src/gui/painting/qcolor.h
+++ b/src/gui/painting/qcolor.h
@@ -65,6 +65,7 @@ class Q_GUI_EXPORT QColor
{
public:
enum Spec { Invalid, Rgb, Hsv, Cmyk, Hsl };
+ enum NameFormat { HexRgb, HexArgb };
QColor();
QColor(Qt::GlobalColor color);
@@ -77,7 +78,9 @@ public:
bool isValid() const;
+ // ### Qt 6: merge overloads
QString name() const;
+ QString name(NameFormat format) const;
void setNamedColor(const QString& name);
static QStringList colorNames();
diff --git a/src/gui/painting/qcolor_p.cpp b/src/gui/painting/qcolor_p.cpp
index 35e607ec54..b913f5338c 100644
--- a/src/gui/painting/qcolor_p.cpp
+++ b/src/gui/painting/qcolor_p.cpp
@@ -79,7 +79,8 @@ bool qt_get_hex_rgb(const char *name, QRgb *rgb)
return false;
name++;
int len = qstrlen(name);
- int r, g, b;
+ int a, r, g, b;
+ a = 255;
if (len == 12) {
r = hex2int(name);
g = hex2int(name + 4);
@@ -88,6 +89,11 @@ bool qt_get_hex_rgb(const char *name, QRgb *rgb)
r = hex2int(name);
g = hex2int(name + 3);
b = hex2int(name + 6);
+ } else if (len == 8) {
+ a = hex2int(name);
+ r = hex2int(name + 2);
+ g = hex2int(name + 4);
+ b = hex2int(name + 6);
} else if (len == 6) {
r = hex2int(name);
g = hex2int(name + 2);
@@ -99,11 +105,11 @@ bool qt_get_hex_rgb(const char *name, QRgb *rgb)
} else {
r = g = b = -1;
}
- if ((uint)r > 255 || (uint)g > 255 || (uint)b > 255) {
+ if ((uint)r > 255 || (uint)g > 255 || (uint)b > 255 || (uint)a > 255) {
*rgb = 0;
return false;
}
- *rgb = qRgb(r, g ,b);
+ *rgb = qRgba(r, g ,b, a);
return true;
}
diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp
index de0ab53c1b..c79e8babb6 100644
--- a/src/gui/painting/qdrawhelper.cpp
+++ b/src/gui/painting/qdrawhelper.cpp
@@ -6163,7 +6163,7 @@ void qInitDrawhelperAsm()
}
#endif // IWMMXT
-#if defined(QT_COMPILER_SUPPORTS_NEON)
+#if defined(QT_COMPILER_SUPPORTS_NEON) && !defined(Q_OS_IOS)
if (features & NEON) {
qBlendFunctions[QImage::Format_RGB32][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_neon;
qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_neon;
diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp
index 62379cd592..2e4f341e39 100644
--- a/src/gui/text/qfontdatabase.cpp
+++ b/src/gui/text/qfontdatabase.cpp
@@ -53,6 +53,7 @@
#include <QtGui/private/qguiapplication_p.h>
#include <qpa/qplatformfontdatabase.h>
+#include <qpa/qplatformtheme.h>
#include <stdlib.h>
#include <limits.h>
@@ -1103,6 +1104,17 @@ QFontDatabase::QFontDatabase()
*/
/*!
+ \enum QFontDatabase::SystemFont
+
+ \value GeneralFont The default system font.
+ \value FixedFont The fixed font that the system recommends.
+ \value TitleFont The system standard font for titles.
+ \value SmallestReadableFont The smallest readable system font.
+
+ \since 5.2
+*/
+
+/*!
Returns a sorted list of the available writing systems. This is
list generated from information about all installed fonts on the
system.
@@ -2114,6 +2126,43 @@ QStringList QFontDatabase::applicationFontFamilies(int id)
}
/*!
+ \since 5.2
+
+ Returns the most adequate font for a given \a type case for proper integration
+ with the system's look and feel.
+
+ \sa QGuiApplication::font()
+*/
+
+QFont QFontDatabase::systemFont(QFontDatabase::SystemFont type)
+{
+ const QFont *font = 0;
+ if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme()) {
+ switch (type) {
+ case GeneralFont:
+ font = theme->font(QPlatformTheme::SystemFont);
+ break;
+ case FixedFont:
+ font = theme->font(QPlatformTheme::FixedFont);
+ break;
+ case TitleFont:
+ font = theme->font(QPlatformTheme::TitleBarFont);
+ break;
+ case SmallestReadableFont:
+ font = theme->font(QPlatformTheme::MiniFont);
+ break;
+ }
+ }
+
+ if (font)
+ return *font;
+ else if (QPlatformIntegration *integration = QGuiApplicationPrivate::platformIntegration())
+ return integration->fontDatabase()->defaultFont();
+ else
+ return QFont();
+}
+
+/*!
\fn bool QFontDatabase::removeApplicationFont(int id)
\since 4.2
diff --git a/src/gui/text/qfontdatabase.h b/src/gui/text/qfontdatabase.h
index 05f1a85f24..bd603c3c4a 100644
--- a/src/gui/text/qfontdatabase.h
+++ b/src/gui/text/qfontdatabase.h
@@ -60,6 +60,7 @@ class Q_GUI_EXPORT QFontDatabase
{
Q_GADGET
Q_ENUMS(WritingSystem)
+ Q_ENUMS(SystemFont)
public:
// do not re-order or delete entries from this enum without updating the
// QPF2 format and makeqpf!!
@@ -106,6 +107,13 @@ public:
WritingSystemsCount
};
+ enum SystemFont {
+ GeneralFont,
+ FixedFont,
+ TitleFont,
+ SmallestReadableFont
+ };
+
static QList<int> standardSizes();
QFontDatabase();
@@ -144,6 +152,8 @@ public:
static bool supportsThreadedFontRendering();
+ static QFont systemFont(SystemFont type);
+
private:
static void createDatabase();
static void parseFontName(const QString &name, QString &foundry, QString &family);
diff --git a/src/gui/text/qfontdatabase_qpa.cpp b/src/gui/text/qfontdatabase_qpa.cpp
index 62b99968bc..8e6ad7cd97 100644
--- a/src/gui/text/qfontdatabase_qpa.cpp
+++ b/src/gui/text/qfontdatabase_qpa.cpp
@@ -85,7 +85,7 @@ Q_GUI_EXPORT void qt_registerFont(const QString &familyName, const QString &sty
size->handle = handle;
}
-Q_GUI_EXPORT void qt_registerAliasToFontFamily(const QString &familyName, const QString &alias)
+void qt_registerAliasToFontFamily(const QString &familyName, const QString &alias)
{
if (alias.isEmpty())
return;
diff --git a/src/gui/text/qplatformfontdatabase.cpp b/src/gui/text/qplatformfontdatabase.cpp
index 4399aff9da..293535a2e1 100644
--- a/src/gui/text/qplatformfontdatabase.cpp
+++ b/src/gui/text/qplatformfontdatabase.cpp
@@ -53,6 +53,8 @@ extern void qt_registerFont(const QString &familyname, const QString &stylename,
bool scalable, int pixelSize, bool fixedPitch,
const QSupportedWritingSystems &writingSystems, void *hanlde);
+void qt_registerAliasToFontFamily(const QString &familyName, const QString &alias);
+
/*!
\fn void QPlatformFontDatabase::registerQPF2Font(const QByteArray &dataArray, void *handle)
@@ -517,6 +519,17 @@ QSupportedWritingSystems QPlatformFontDatabase::writingSystemsFromTrueTypeBits(q
}
/*!
+ Helper function that register the \a alias for the \a familyName.
+
+ \since 5.2
+*/
+
+void QPlatformFontDatabase::registerAliasToFontFamily(const QString &familyName, const QString &alias)
+{
+ qt_registerAliasToFontFamily(familyName, alias);
+}
+
+/*!
\class QPlatformFontDatabase
\since 5.0
\internal
diff --git a/src/gui/text/qplatformfontdatabase.h b/src/gui/text/qplatformfontdatabase.h
index 6e53eba98b..6053f11051 100644
--- a/src/gui/text/qplatformfontdatabase.h
+++ b/src/gui/text/qplatformfontdatabase.h
@@ -122,6 +122,8 @@ public:
QFont::Style style, QFont::Stretch stretch, bool antialiased,
bool scalable, int pixelSize, bool fixedPitch,
const QSupportedWritingSystems &writingSystems, void *handle);
+
+ static void registerAliasToFontFamily(const QString &familyName, const QString &alias);
};
QT_END_NAMESPACE
diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp
index 2fa7f0232d..229db80186 100644
--- a/src/gui/text/qtextengine.cpp
+++ b/src/gui/text/qtextengine.cpp
@@ -59,9 +59,9 @@
#include <algorithm>
#include <stdlib.h>
+#ifndef QT_NO_RAWFONT
#include "qfontengine_qpa_p.h"
-
-#include <private/qharfbuzz_p.h>
+#endif
QT_BEGIN_NAMESPACE
@@ -838,21 +838,6 @@ void QTextEngine::bidiReorder(int numItems, const quint8 *levels, int *visualOrd
#endif
}
-// ask the font engine to find out which glyphs (as an index in the specific font) to use for the text in one item.
-static bool stringToGlyphs(HB_ShaperItem *item, QGlyphLayout *glyphs, QFontEngine *fontEngine)
-{
- int nGlyphs = item->num_glyphs;
-
- QFontEngine::ShaperFlags shaperFlags(QFontEngine::GlyphIndicesOnly);
- if (item->item.bidiLevel % 2)
- shaperFlags |= QFontEngine::RightToLeft;
-
- bool result = fontEngine->stringToCMap(reinterpret_cast<const QChar *>(item->string + item->item.pos), item->item.length, glyphs, &nGlyphs, shaperFlags);
- item->num_glyphs = nGlyphs;
- glyphs->numGlyphs = nGlyphs;
- return result;
-}
-
// shape all the items that intersect with the line, taking tab widths into account to find out what text actually fits in the line.
void QTextEngine::shapeLine(const QScriptLine &line)
{
@@ -892,19 +877,48 @@ void QTextEngine::shapeText(int item) const
if (si.num_glyphs)
return;
- shapeTextWithHarfbuzz(item);
-
si.width = 0;
+ si.glyph_data_offset = layoutData->used;
- if (!si.num_glyphs)
- return;
- QGlyphLayout glyphs = shapedGlyphs(&si);
+ const ushort *string = reinterpret_cast<const ushort *>(layoutData->string.constData()) + si.position;
+ const int itemLength = length(item);
+
+ if (!ensureSpace(itemLength))
+ return; // ### report OOM error somehow
+
+ QString casedString;
+ if (si.analysis.flags && si.analysis.flags <= QScriptAnalysis::SmallCaps) {
+ casedString.resize(itemLength);
+ ushort *uc = reinterpret_cast<ushort *>(casedString.data());
+ for (int i = 0; i < itemLength; ++i) {
+ uint ucs4 = string[i];
+ if (QChar::isHighSurrogate(ucs4) && i + 1 < itemLength) {
+ uint low = string[i + 1];
+ if (QChar::isLowSurrogate(low)) {
+ ++i;
+ ucs4 = QChar::surrogateToUcs4(ucs4, low);
+ ucs4 = si.analysis.flags == QScriptAnalysis::Lowercase ? QChar::toLower(ucs4)
+ : QChar::toUpper(ucs4);
+ // high part never changes in simple casing
+ uc[i] = QChar::lowSurrogate(ucs4);
+ }
+ } else {
+ uc[i] = si.analysis.flags == QScriptAnalysis::Lowercase ? QChar::toLower(ucs4)
+ : QChar::toUpper(ucs4);
+ }
+ }
+ string = reinterpret_cast<const ushort *>(casedString.constData());
+ }
+ QFontEngine *fontEngine = this->fontEngine(si, &si.ascent, &si.descent, &si.leading);
+
+ bool kerningEnabled;
bool letterSpacingIsAbsolute;
QFixed letterSpacing, wordSpacing;
#ifndef QT_NO_RAWFONT
if (useRawFont) {
QTextCharFormat f = format(&si);
+ kerningEnabled = f.fontKerning();
wordSpacing = QFixed::fromReal(f.fontWordSpacing());
letterSpacing = QFixed::fromReal(f.fontLetterSpacing());
letterSpacingIsAbsolute = true;
@@ -912,6 +926,7 @@ void QTextEngine::shapeText(int item) const
#endif
{
QFont font = this->font(si);
+ kerningEnabled = font.d->kerning;
letterSpacingIsAbsolute = font.d->letterSpacingIsAbsolute;
letterSpacing = font.d->letterSpacing;
wordSpacing = font.d->wordSpacing;
@@ -920,6 +935,13 @@ void QTextEngine::shapeText(int item) const
letterSpacing *= font.d->dpi / qt_defaultDpiY();
}
+ si.num_glyphs = shapeTextWithHarfbuzz(si, string, itemLength, fontEngine, kerningEnabled);
+ if (!si.num_glyphs)
+ return; // ### report shaping errors somehow
+ layoutData->used += si.num_glyphs;
+
+ QGlyphLayout glyphs = shapedGlyphs(&si);
+
if (letterSpacing != 0) {
for (int i = 1; i < si.num_glyphs; ++i) {
if (glyphs.attributes[i].clusterStart) {
@@ -940,12 +962,12 @@ void QTextEngine::shapeText(int item) const
}
if (wordSpacing != 0) {
for (int i = 0; i < si.num_glyphs; ++i) {
- if (glyphs.attributes[i].justification == HB_Space
- || glyphs.attributes[i].justification == HB_Arabic_Space) {
+ if (glyphs.attributes[i].justification == QGlyphAttributes::Space
+ || glyphs.attributes[i].justification == QGlyphAttributes::Arabic_Space) {
// word spacing only gets added once to a consecutive run of spaces (see CSS spec)
if (i + 1 == si.num_glyphs
- ||(glyphs.attributes[i+1].justification != HB_Space
- && glyphs.attributes[i+1].justification != HB_Arabic_Space))
+ ||(glyphs.attributes[i+1].justification != QGlyphAttributes::Space
+ && glyphs.attributes[i+1].justification != QGlyphAttributes::Arabic_Space))
glyphs.advances_x[i] += wordSpacing;
}
}
@@ -955,14 +977,6 @@ void QTextEngine::shapeText(int item) const
si.width += glyphs.advances_x[i] * !glyphs.attributes[i].dontPrint;
}
-static inline bool hasCaseChange(const QScriptItem &si)
-{
- return si.analysis.flags == QScriptAnalysis::SmallCaps ||
- si.analysis.flags == QScriptAnalysis::Uppercase ||
- si.analysis.flags == QScriptAnalysis::Lowercase;
-}
-
-
static inline void moveGlyphData(const QGlyphLayout &destination, const QGlyphLayout &source, int num)
{
if (num > 0 && destination.glyphs != source.glyphs) {
@@ -973,84 +987,60 @@ static inline void moveGlyphData(const QGlyphLayout &destination, const QGlyphLa
}
}
+QT_BEGIN_INCLUDE_NAMESPACE
+
+#include <private/qharfbuzz_p.h>
+
+QT_END_INCLUDE_NAMESPACE
+
Q_STATIC_ASSERT(sizeof(HB_Glyph) == sizeof(glyph_t));
Q_STATIC_ASSERT(sizeof(HB_GlyphAttributes) == sizeof(QGlyphAttributes));
Q_STATIC_ASSERT(sizeof(HB_Fixed) == sizeof(QFixed));
Q_STATIC_ASSERT(sizeof(HB_FixedPoint) == sizeof(QFixedPoint));
-/// take the item from layoutData->items and
-void QTextEngine::shapeTextWithHarfbuzz(int item) const
+// ask the font engine to find out which glyphs (as an index in the specific font) to use for the text in one item.
+static bool stringToGlyphs(HB_ShaperItem *item, QGlyphLayout *glyphs, QFontEngine *fontEngine)
{
- QScriptItem &si = layoutData->items[item];
-
- si.glyph_data_offset = layoutData->used;
+ int nGlyphs = item->num_glyphs;
- QFontEngine *font = fontEngine(si, &si.ascent, &si.descent, &si.leading);
+ QFontEngine::ShaperFlags shaperFlags(QFontEngine::GlyphIndicesOnly);
+ if (item->item.bidiLevel % 2)
+ shaperFlags |= QFontEngine::RightToLeft;
- bool kerningEnabled;
-#ifndef QT_NO_RAWFONT
- if (useRawFont) {
- QTextCharFormat f = format(&si);
- kerningEnabled = f.fontKerning();
- } else
-#endif
- kerningEnabled = this->font(si).d->kerning;
+ bool result = fontEngine->stringToCMap(reinterpret_cast<const QChar *>(item->string + item->item.pos), item->item.length, glyphs, &nGlyphs, shaperFlags);
+ item->num_glyphs = nGlyphs;
+ glyphs->numGlyphs = nGlyphs;
+ return result;
+}
+int QTextEngine::shapeTextWithHarfbuzz(QScriptItem &si, const ushort *string, int itemLength, QFontEngine *fontEngine, bool kerningEnabled) const
+{
HB_ShaperItem entire_shaper_item;
memset(&entire_shaper_item, 0, sizeof(entire_shaper_item));
- entire_shaper_item.string = reinterpret_cast<const HB_UChar16 *>(layoutData->string.constData());
- entire_shaper_item.stringLength = layoutData->string.length();
+ entire_shaper_item.string = reinterpret_cast<const HB_UChar16 *>(string);
+ entire_shaper_item.stringLength = itemLength;
entire_shaper_item.item.script = script_to_hbscript(si.analysis.script);
- entire_shaper_item.item.pos = si.position;
- entire_shaper_item.item.length = length(item);
+ entire_shaper_item.item.pos = 0;
+ entire_shaper_item.item.length = itemLength;
entire_shaper_item.item.bidiLevel = si.analysis.bidiLevel;
- QVarLengthArray<HB_UChar16, 256> casedString;
- if (hasCaseChange(si)) {
- if (casedString.size() < static_cast<int>(entire_shaper_item.item.length))
- casedString.resize(entire_shaper_item.item.length);
- HB_UChar16 *uc = casedString.data();
- for (uint i = 0; i < entire_shaper_item.item.length; ++i) {
- uint ucs4 = entire_shaper_item.string[si.position + i];
- if (QChar::isHighSurrogate(ucs4)) {
- uc[i] = ucs4; // high part never changes in simple casing
- if (i + 1 < entire_shaper_item.item.length) {
- ushort low = entire_shaper_item.string[si.position + i + 1];
- if (QChar::isLowSurrogate(low)) {
- ucs4 = QChar::surrogateToUcs4(ucs4, low);
- ucs4 = si.analysis.flags == QScriptAnalysis::Lowercase ? QChar::toLower(ucs4)
- : QChar::toUpper(ucs4);
- uc[++i] = QChar::lowSurrogate(ucs4);
- }
- }
- } else {
- uc[i] = si.analysis.flags == QScriptAnalysis::Lowercase ? QChar::toLower(ucs4)
- : QChar::toUpper(ucs4);
- }
- }
- entire_shaper_item.item.pos = 0;
- entire_shaper_item.string = uc;
- entire_shaper_item.stringLength = entire_shaper_item.item.length;
- }
-
entire_shaper_item.shaperFlags = 0;
if (!kerningEnabled)
entire_shaper_item.shaperFlags |= HB_ShaperFlag_NoKerning;
if (option.useDesignMetrics())
entire_shaper_item.shaperFlags |= HB_ShaperFlag_UseDesignMetrics;
- entire_shaper_item.num_glyphs = qMax(layoutData->glyphLayout.numGlyphs - layoutData->used, int(entire_shaper_item.item.length));
- if (!ensureSpace(entire_shaper_item.num_glyphs))
- return;
+ entire_shaper_item.num_glyphs = itemLength;
+
QGlyphLayout initialGlyphs = availableGlyphs(&si).mid(0, entire_shaper_item.num_glyphs);
- if (!stringToGlyphs(&entire_shaper_item, &initialGlyphs, font)) {
+ if (!stringToGlyphs(&entire_shaper_item, &initialGlyphs, fontEngine)) {
if (!ensureSpace(entire_shaper_item.num_glyphs))
- return;
+ return 0;
initialGlyphs = availableGlyphs(&si).mid(0, entire_shaper_item.num_glyphs);
- if (!stringToGlyphs(&entire_shaper_item, &initialGlyphs, font)) {
+ if (!stringToGlyphs(&entire_shaper_item, &initialGlyphs, fontEngine)) {
// ############ if this happens there's a bug in the fontengine
- return;
+ return 0;
}
}
@@ -1060,7 +1050,7 @@ void QTextEngine::shapeTextWithHarfbuzz(int item) const
itemBoundaries[0] = entire_shaper_item.item.pos;
itemBoundaries[1] = 0;
- if (font->type() == QFontEngine::Multi) {
+ if (fontEngine->type() == QFontEngine::Multi) {
uint lastEngine = 0;
int charIdx = entire_shaper_item.item.pos;
const int stringEnd = charIdx + entire_shaper_item.item.length;
@@ -1099,18 +1089,17 @@ void QTextEngine::shapeTextWithHarfbuzz(int item) const
if (shaper_item.num_glyphs < shaper_item.item.length)
shaper_item.num_glyphs = shaper_item.item.length;
- QFontEngine *actualFontEngine = font;
+ QFontEngine *actualFontEngine = fontEngine;
uint engineIdx = 0;
- if (font->type() == QFontEngine::Multi) {
+ if (fontEngine->type() == QFontEngine::Multi) {
engineIdx = uint(availableGlyphs(&si).glyphs[glyph_pos] >> 24);
- actualFontEngine = static_cast<QFontEngineMulti *>(font)->engine(engineIdx);
+ actualFontEngine = static_cast<QFontEngineMulti *>(fontEngine)->engine(engineIdx);
+ si.ascent = qMax(actualFontEngine->ascent(), si.ascent);
+ si.descent = qMax(actualFontEngine->descent(), si.descent);
+ si.leading = qMax(actualFontEngine->leading(), si.leading);
}
- si.ascent = qMax(actualFontEngine->ascent(), si.ascent);
- si.descent = qMax(actualFontEngine->descent(), si.descent);
- si.leading = qMax(actualFontEngine->leading(), si.leading);
-
shaper_item.font = (HB_Font)actualFontEngine->harfbuzzFont();
shaper_item.face = (HB_Face)actualFontEngine->harfbuzzFace();
@@ -1120,7 +1109,7 @@ void QTextEngine::shapeTextWithHarfbuzz(int item) const
do {
if (!ensureSpace(glyph_pos + shaper_item.num_glyphs + remaining_glyphs))
- return;
+ return 0;
const QGlyphLayout g = availableGlyphs(&si).mid(glyph_pos);
if (shaper_item.num_glyphs > shaper_item.item.length)
@@ -1137,8 +1126,6 @@ void QTextEngine::shapeTextWithHarfbuzz(int item) const
}
shaper_item.log_clusters = logClusters(&si) + shaper_item.item.pos - entire_shaper_item.item.pos;
-
-// qDebug(" .. num_glyphs=%d, used=%d, item.num_glyphs=%d", num_glyphs, used, shaper_item.num_glyphs);
} while (!qShapeItem(&shaper_item)); // this does the actual shaping via harfbuzz.
QGlyphLayout g = availableGlyphs(&si).mid(glyph_pos, shaper_item.num_glyphs);
@@ -1158,10 +1145,7 @@ void QTextEngine::shapeTextWithHarfbuzz(int item) const
glyph_pos += shaper_item.num_glyphs;
}
-// qDebug(" -> item: script=%d num_glyphs=%d", shaper_item.script, shaper_item.num_glyphs);
- si.num_glyphs = glyph_pos;
-
- layoutData->used += si.num_glyphs;
+ return glyph_pos;
}
void QTextEngine::init(QTextEngine *e)
@@ -1821,7 +1805,7 @@ static void set(QJustificationPoint *point, int type, const QGlyphLayout &glyph,
point->type = type;
point->glyph = glyph;
- if (type >= HB_Arabic_Normal) {
+ if (type >= QGlyphAttributes::Arabic_Normal) {
QChar ch(0x640); // Kashida character
QGlyphLayoutArray<8> glyphs;
int nglyphs = 7;
@@ -1829,7 +1813,7 @@ static void set(QJustificationPoint *point, int type, const QGlyphLayout &glyph,
if (glyphs.glyphs[0] && glyphs.advances_x[0] != 0) {
point->kashidaWidth = glyphs.advances_x[0];
} else {
- point->type = HB_NoJustification;
+ point->type = QGlyphAttributes::NoJustification;
point->kashidaWidth = 0;
}
}
@@ -1897,7 +1881,7 @@ void QTextEngine::justify(const QScriptLine &line)
for (int i = 0; i < nItems; ++i) {
QScriptItem &si = layoutData->items[firstItem + i];
- int kashida_type = HB_Arabic_Normal;
+ int kashida_type = QGlyphAttributes::Arabic_Normal;
int kashida_pos = -1;
int start = qMax(line.from - si.position, 0);
@@ -1921,11 +1905,11 @@ void QTextEngine::justify(const QScriptLine &line)
int justification = g.attributes[i].justification;
switch(justification) {
- case HB_NoJustification:
+ case QGlyphAttributes::NoJustification:
break;
- case HB_Space :
+ case QGlyphAttributes::Space :
// fall through
- case HB_Arabic_Space :
+ case QGlyphAttributes::Arabic_Space :
if (kashida_pos >= 0) {
// qDebug("kashida position at %d in word", kashida_pos);
set(&justificationPoints[nPoints], kashida_type, g.mid(kashida_pos), fontEngine(si));
@@ -1936,19 +1920,19 @@ void QTextEngine::justify(const QScriptLine &line)
}
}
kashida_pos = -1;
- kashida_type = HB_Arabic_Normal;
+ kashida_type = QGlyphAttributes::Arabic_Normal;
// fall through
- case HB_Character :
+ case QGlyphAttributes::Character :
set(&justificationPoints[nPoints++], justification, g.mid(i), fontEngine(si));
maxJustify = qMax(maxJustify, justification);
break;
- case HB_Arabic_Normal :
- case HB_Arabic_Waw :
- case HB_Arabic_BaRa :
- case HB_Arabic_Alef :
- case HB_Arabic_HaaDal :
- case HB_Arabic_Seen :
- case HB_Arabic_Kashida :
+ case QGlyphAttributes::Arabic_Normal :
+ case QGlyphAttributes::Arabic_Waw :
+ case QGlyphAttributes::Arabic_BaRa :
+ case QGlyphAttributes::Arabic_Alef :
+ case QGlyphAttributes::Arabic_HaaDal :
+ case QGlyphAttributes::Arabic_Seen :
+ case QGlyphAttributes::Arabic_Kashida :
if (justification >= kashida_type) {
kashida_pos = i;
kashida_type = justification;
@@ -1977,9 +1961,9 @@ void QTextEngine::justify(const QScriptLine &line)
// qDebug(" minKashida=%f, need=%f", minKashida.toReal(), need.toReal());
// distribute in priority order
- if (maxJustify >= HB_Arabic_Normal) {
+ if (maxJustify >= QGlyphAttributes::Arabic_Normal) {
while (need >= minKashida) {
- for (int type = maxJustify; need >= minKashida && type >= HB_Arabic_Normal; --type) {
+ for (int type = maxJustify; need >= minKashida && type >= QGlyphAttributes::Arabic_Normal; --type) {
for (int i = 0; need >= minKashida && i < nPoints; ++i) {
if (justificationPoints[i].type == type && justificationPoints[i].kashidaWidth <= need) {
justificationPoints[i].glyph.justifications->nKashidas++;
@@ -1996,7 +1980,7 @@ void QTextEngine::justify(const QScriptLine &line)
if (!need)
goto end;
- maxJustify = qMin(maxJustify, (int)HB_Space);
+ maxJustify = qMin(maxJustify, int(QGlyphAttributes::Space));
for (int type = maxJustify; need != 0 && type > 0; --type) {
int n = 0;
for (int i = 0; i < nPoints; ++i) {
@@ -2438,12 +2422,13 @@ QString QTextEngine::elidedText(Qt::TextElideMode mode, const QFixed &width, int
const int end = si.position + length(&si);
for (int i = si.position; i < end - 1; ++i) {
- if (layoutData->string.at(i) == QLatin1Char('&')) {
+ if (layoutData->string.at(i) == QLatin1Char('&')
+ && !attributes[i + 1].whiteSpace && attributes[i + 1].graphemeBoundary) {
const int gp = logClusters[i - si.position];
glyphs.attributes[gp].dontPrint = true;
- attributes[i + 1].graphemeBoundary = false;
- attributes[i + 1].lineBreak = false;
- attributes[i + 1].whiteSpace = false;
+ // emulate grapheme cluster
+ attributes[i] = attributes[i + 1];
+ memset(attributes + i + 1, 0, sizeof(QCharAttributes));
if (layoutData->string.at(i + 1) == QLatin1Char('&'))
++i;
}
diff --git a/src/gui/text/qtextengine_p.h b/src/gui/text/qtextengine_p.h
index ec7f7407b2..6d46231c67 100644
--- a/src/gui/text/qtextengine_p.h
+++ b/src/gui/text/qtextengine_p.h
@@ -96,6 +96,20 @@ typedef quint8 q_hb_bitfield;
#endif
typedef struct {
+ typedef enum {
+ NoJustification= 0, /* Justification can't be applied after this glyph */
+ Arabic_Space = 1, /* This glyph represents a space inside arabic text */
+ Character = 2, /* Inter-character justification point follows this glyph */
+ Space = 4, /* This glyph represents a blank outside an Arabic run */
+ Arabic_Normal = 7, /* Normal Middle-Of-Word glyph that connects to the right (begin) */
+ Arabic_Waw = 8, /* Next character is final form of Waw/Ain/Qaf/Fa */
+ Arabic_BaRa = 9, /* Next two chars are Ba + Ra/Ya/AlefMaksura */
+ Arabic_Alef = 10, /* Next character is final form of Alef/Tah/Lam/Kaf/Gaf */
+ Arabic_HaaDal = 11, /* Next character is final form of Haa/Dal/Taa Marbutah */
+ Arabic_Seen = 12, /* Initial or Medial form Of Seen/Sad */
+ Arabic_Kashida = 13 /* Kashida(U+640) in middle of word */
+ } JustificationClass;
+
q_hb_bitfield justification :4; /* Justification class */
q_hb_bitfield clusterStart :1; /* First glyph of representation of cluster */
q_hb_bitfield mark :1; /* needs to be positioned around base char */
@@ -685,7 +699,7 @@ private:
void setBoundary(int strPos) const;
void addRequiredBoundaries() const;
void shapeText(int item) const;
- void shapeTextWithHarfbuzz(int item) const;
+ int shapeTextWithHarfbuzz(QScriptItem &si, const ushort *string, int itemLength, QFontEngine *fontEngine, bool kerningEnabled) const;
void splitItem(int item, int pos) const;
int endOfLine(int lineNum);
diff --git a/src/network/access/qhttpnetworkconnection.cpp b/src/network/access/qhttpnetworkconnection.cpp
index a279990f4c..c3e3716b26 100644
--- a/src/network/access/qhttpnetworkconnection.cpp
+++ b/src/network/access/qhttpnetworkconnection.cpp
@@ -85,6 +85,7 @@ QHttpNetworkConnectionPrivate::QHttpNetworkConnectionPrivate(const QString &host
#ifndef QT_NO_NETWORKPROXY
, networkProxy(QNetworkProxy::NoProxy)
#endif
+ , preConnectRequests(0)
{
channels = new QHttpNetworkConnectionChannel[channelCount];
}
@@ -96,6 +97,7 @@ QHttpNetworkConnectionPrivate::QHttpNetworkConnectionPrivate(quint16 channelCoun
#ifndef QT_NO_NETWORKPROXY
, networkProxy(QNetworkProxy::NoProxy)
#endif
+ , preConnectRequests(0)
{
channels = new QHttpNetworkConnectionChannel[channelCount];
}
@@ -541,6 +543,9 @@ QHttpNetworkReply* QHttpNetworkConnectionPrivate::queueRequest(const QHttpNetwor
reply->d_func()->connectionChannel = &channels[0]; // will have the correct one set later
HttpMessagePair pair = qMakePair(request, reply);
+ if (request.isPreConnect())
+ preConnectRequests++;
+
switch (request.priority()) {
case QHttpNetworkRequest::HighPriority:
highPriorityQueue.prepend(pair);
@@ -925,13 +930,24 @@ void QHttpNetworkConnectionPrivate::_q_startNextRequest()
// If there is not already any connected channels we need to connect a new one.
// We do not pair the channel with the request until we know if it is
// connected or not. This is to reuse connected channels before we connect new once.
- int queuedRequest = highPriorityQueue.count() + lowPriorityQueue.count();
- for (int i = 0; i < channelCount; ++i) {
+ int queuedRequests = highPriorityQueue.count() + lowPriorityQueue.count();
+
+ // in case we have in-flight preconnect requests and normal requests,
+ // we only need one socket for each (preconnect, normal request) pair
+ int neededOpenChannels = queuedRequests;
+ if (preConnectRequests > 0) {
+ int normalRequests = queuedRequests - preConnectRequests;
+ neededOpenChannels = qMax(normalRequests, preConnectRequests);
+ }
+ for (int i = 0; i < channelCount && neededOpenChannels > 0; ++i) {
bool connectChannel = false;
if (channels[i].socket) {
- if ((channels[i].socket->state() == QAbstractSocket::ConnectingState) || (channels[i].socket->state() == QAbstractSocket::HostLookupState))
- queuedRequest--;
- if ( queuedRequest <=0 )
+ if ((channels[i].socket->state() == QAbstractSocket::ConnectingState)
+ || (channels[i].socket->state() == QAbstractSocket::HostLookupState)
+ || channels[i].pendingEncrypt) // pendingEncrypt == "EncryptingState"
+ neededOpenChannels--;
+
+ if (neededOpenChannels <= 0)
break;
if (!channels[i].reply && !channels[i].isSocketBusy() && (channels[i].socket->state() == QAbstractSocket::UnconnectedState))
connectChannel = true;
@@ -945,11 +961,8 @@ void QHttpNetworkConnectionPrivate::_q_startNextRequest()
else if (networkLayerState == IPv6)
channels[i].networkLayerPreference = QAbstractSocket::IPv6Protocol;
channels[i].ensureConnection();
- queuedRequest--;
+ neededOpenChannels--;
}
-
- if ( queuedRequest <=0 )
- break;
}
}
@@ -1270,6 +1283,11 @@ void QHttpNetworkConnection::ignoreSslErrors(const QList<QSslError> &errors, int
#endif //QT_NO_SSL
+void QHttpNetworkConnection::preConnectFinished()
+{
+ d_func()->preConnectRequests--;
+}
+
#ifndef QT_NO_NETWORKPROXY
// only called from QHttpNetworkConnectionChannel::_q_proxyAuthenticationRequired, not
// from QHttpNetworkConnectionChannel::handleAuthenticationChallenge
diff --git a/src/network/access/qhttpnetworkconnection_p.h b/src/network/access/qhttpnetworkconnection_p.h
index 956499ddab..c54250f6ed 100644
--- a/src/network/access/qhttpnetworkconnection_p.h
+++ b/src/network/access/qhttpnetworkconnection_p.h
@@ -131,6 +131,8 @@ public:
void setSslContext(QSharedPointer<QSslContext> context);
#endif
+ void preConnectFinished();
+
private:
Q_DECLARE_PRIVATE(QHttpNetworkConnection)
Q_DISABLE_COPY(QHttpNetworkConnection)
@@ -239,6 +241,8 @@ public:
QList<HttpMessagePair> highPriorityQueue;
QList<HttpMessagePair> lowPriorityQueue;
+ int preConnectRequests;
+
#ifndef QT_NO_SSL
QSharedPointer<QSslContext> sslContext;
#endif
diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp
index 5c537691e2..7aee9aa38a 100644
--- a/src/network/access/qhttpnetworkconnectionchannel.cpp
+++ b/src/network/access/qhttpnetworkconnectionchannel.cpp
@@ -183,6 +183,9 @@ void QHttpNetworkConnectionChannel::close()
else
state = QHttpNetworkConnectionChannel::ClosingState;
+ // pendingEncrypt must only be true in between connected and encrypted states
+ pendingEncrypt = false;
+
if (socket)
socket->close();
}
@@ -205,6 +208,17 @@ bool QHttpNetworkConnectionChannel::sendRequest()
// _q_connected or _q_encrypted
return false;
}
+ QString scheme = request.url().scheme();
+ if (scheme == QLatin1String("preconnect-http")
+ || scheme == QLatin1String("preconnect-https")) {
+ state = QHttpNetworkConnectionChannel::IdleState;
+ reply->d_func()->state = QHttpNetworkReplyPrivate::AllDoneState;
+ allDone();
+ connection->preConnectFinished(); // will only decrease the counter
+ reply = 0; // so we can reuse this channel
+ return true; // we have a working connection and are done
+ }
+
written = 0; // excluding the header
bytesTotal = 0;
diff --git a/src/network/access/qhttpnetworkreply.cpp b/src/network/access/qhttpnetworkreply.cpp
index eb8a8869cc..1b9e1f5a53 100644
--- a/src/network/access/qhttpnetworkreply.cpp
+++ b/src/network/access/qhttpnetworkreply.cpp
@@ -290,6 +290,11 @@ QHttpNetworkReplyPrivate::QHttpNetworkReplyPrivate(const QUrl &newUrl)
#endif
{
+ QString scheme = newUrl.scheme();
+ if (scheme == QLatin1String("preconnect-http")
+ || scheme == QLatin1String("preconnect-https"))
+ // make sure we do not close the socket after preconnecting
+ connectionCloseEnabled = false;
}
QHttpNetworkReplyPrivate::~QHttpNetworkReplyPrivate()
diff --git a/src/network/access/qhttpnetworkrequest.cpp b/src/network/access/qhttpnetworkrequest.cpp
index e5b2eced99..d9f9b555d7 100644
--- a/src/network/access/qhttpnetworkrequest.cpp
+++ b/src/network/access/qhttpnetworkrequest.cpp
@@ -49,7 +49,8 @@ QT_BEGIN_NAMESPACE
QHttpNetworkRequestPrivate::QHttpNetworkRequestPrivate(QHttpNetworkRequest::Operation op,
QHttpNetworkRequest::Priority pri, const QUrl &newUrl)
: QHttpNetworkHeaderPrivate(newUrl), operation(op), priority(pri), uploadByteDevice(0),
- autoDecompress(false), pipeliningAllowed(false), withCredentials(true)
+ autoDecompress(false), pipeliningAllowed(false), withCredentials(true),
+ preConnect(false)
{
}
@@ -64,6 +65,7 @@ QHttpNetworkRequestPrivate::QHttpNetworkRequestPrivate(const QHttpNetworkRequest
customVerb = other.customVerb;
withCredentials = other.withCredentials;
ssl = other.ssl;
+ preConnect = other.preConnect;
}
QHttpNetworkRequestPrivate::~QHttpNetworkRequestPrivate()
@@ -74,8 +76,15 @@ bool QHttpNetworkRequestPrivate::operator==(const QHttpNetworkRequestPrivate &ot
{
return QHttpNetworkHeaderPrivate::operator==(other)
&& (operation == other.operation)
+ && (priority == other.priority)
+ && (uploadByteDevice == other.uploadByteDevice)
+ && (autoDecompress == other.autoDecompress)
+ && (pipeliningAllowed == other.pipeliningAllowed)
+ // we do not clear the customVerb in setOperation
+ && (operation != QHttpNetworkRequest::Custom || (customVerb == other.customVerb))
+ && (withCredentials == other.withCredentials)
&& (ssl == other.ssl)
- && (uploadByteDevice == other.uploadByteDevice);
+ && (preConnect == other.preConnect);
}
QByteArray QHttpNetworkRequestPrivate::methodName() const
@@ -205,6 +214,15 @@ void QHttpNetworkRequest::setSsl(bool s)
d->ssl = s;
}
+bool QHttpNetworkRequest::isPreConnect() const
+{
+ return d->preConnect;
+}
+void QHttpNetworkRequest::setPreConnect(bool preConnect)
+{
+ d->preConnect = preConnect;
+}
+
qint64 QHttpNetworkRequest::contentLength() const
{
return d->contentLength();
diff --git a/src/network/access/qhttpnetworkrequest_p.h b/src/network/access/qhttpnetworkrequest_p.h
index fc4a6928c6..ce9fbb1509 100644
--- a/src/network/access/qhttpnetworkrequest_p.h
+++ b/src/network/access/qhttpnetworkrequest_p.h
@@ -120,6 +120,9 @@ public:
bool isSsl() const;
void setSsl(bool);
+ bool isPreConnect() const;
+ void setPreConnect(bool preConnect);
+
void setUploadByteDevice(QNonContiguousByteDevice *bd);
QNonContiguousByteDevice* uploadByteDevice() const;
@@ -151,6 +154,7 @@ public:
bool pipeliningAllowed;
bool withCredentials;
bool ssl;
+ bool preConnect;
};
diff --git a/src/network/access/qhttpthreaddelegate.cpp b/src/network/access/qhttpthreaddelegate.cpp
index a2cee48b22..ee3911c72c 100644
--- a/src/network/access/qhttpthreaddelegate.cpp
+++ b/src/network/access/qhttpthreaddelegate.cpp
@@ -107,8 +107,14 @@ static QByteArray makeCacheKey(QUrl &url, QNetworkProxy *proxy)
{
QString result;
QUrl copy = url;
- bool isEncrypted = copy.scheme().toLower() == QLatin1String("https");
+ QString scheme = copy.scheme().toLower();
+ bool isEncrypted = scheme == QLatin1String("https");
copy.setPort(copy.port(isEncrypted ? 443 : 80));
+ if (scheme == QLatin1String("preconnect-http")) {
+ copy.setScheme(QLatin1String("http"));
+ } else if (scheme == QLatin1String("preconnect-https")) {
+ copy.setScheme(QLatin1String("https"));
+ }
result = copy.toString(QUrl::RemoveUserInfo | QUrl::RemovePath |
QUrl::RemoveQuery | QUrl::RemoveFragment | QUrl::FullyEncoded);
diff --git a/src/network/access/qnetworkaccessbackend.cpp b/src/network/access/qnetworkaccessbackend.cpp
index a895864d76..47cd928541 100644
--- a/src/network/access/qnetworkaccessbackend.cpp
+++ b/src/network/access/qnetworkaccessbackend.cpp
@@ -47,6 +47,7 @@
#include "qnetworkreply_p.h"
#include "QtCore/qhash.h"
#include "QtCore/qmutex.h"
+#include "QtCore/qstringlist.h"
#include "QtNetwork/private/qnetworksession_p.h"
#include "qnetworkaccesscachebackend_p.h"
@@ -110,6 +111,22 @@ QNetworkAccessBackend *QNetworkAccessManagerPrivate::findBackend(QNetworkAccessM
return 0;
}
+QStringList QNetworkAccessManagerPrivate::backendSupportedSchemes() const
+{
+ if (QNetworkAccessBackendFactoryData::valid.load()) {
+ QMutexLocker locker(&factoryData()->mutex);
+ QNetworkAccessBackendFactoryData::ConstIterator it = factoryData()->constBegin();
+ QNetworkAccessBackendFactoryData::ConstIterator end = factoryData()->constEnd();
+ QStringList schemes;
+ while (it != end) {
+ schemes += (*it)->supportedSchemes();
+ ++it;
+ }
+ return schemes;
+ }
+ return QStringList();
+}
+
QNonContiguousByteDevice* QNetworkAccessBackend::createUploadByteDevice()
{
if (reply->outgoingDataBuffer)
diff --git a/src/network/access/qnetworkaccessbackend_p.h b/src/network/access/qnetworkaccessbackend_p.h
index bf284414e0..d9657cf750 100644
--- a/src/network/access/qnetworkaccessbackend_p.h
+++ b/src/network/access/qnetworkaccessbackend_p.h
@@ -62,6 +62,7 @@ class QAuthenticator;
class QNetworkProxy;
class QNetworkProxyQuery;
class QNetworkRequest;
+class QStringList;
class QUrl;
class QUrlInfo;
class QSslConfiguration;
@@ -219,6 +220,7 @@ class QNetworkAccessBackendFactory
public:
QNetworkAccessBackendFactory();
virtual ~QNetworkAccessBackendFactory();
+ virtual QStringList supportedSchemes() const = 0;
virtual QNetworkAccessBackend *create(QNetworkAccessManager::Operation op,
const QNetworkRequest &request) const = 0;
};
diff --git a/src/network/access/qnetworkaccessdebugpipebackend.cpp b/src/network/access/qnetworkaccessdebugpipebackend.cpp
index b6c04dddea..a91751523a 100644
--- a/src/network/access/qnetworkaccessdebugpipebackend.cpp
+++ b/src/network/access/qnetworkaccessdebugpipebackend.cpp
@@ -42,6 +42,7 @@
#include "qnetworkaccessdebugpipebackend_p.h"
#include "QtCore/qdatastream.h"
#include <QCoreApplication>
+#include <QStringList>
#include <QUrlQuery>
#include "private/qnoncontiguousbytedevice_p.h"
@@ -54,6 +55,11 @@ enum {
WriteBufferSize = ReadBufferSize
};
+QStringList QNetworkAccessDebugPipeBackendFactory::supportedSchemes() const
+{
+ return QStringList(QStringLiteral("debugpipe"));
+}
+
QNetworkAccessBackend *
QNetworkAccessDebugPipeBackendFactory::create(QNetworkAccessManager::Operation op,
const QNetworkRequest &request) const
diff --git a/src/network/access/qnetworkaccessdebugpipebackend_p.h b/src/network/access/qnetworkaccessdebugpipebackend_p.h
index 0ae49de132..7593dfa9b7 100644
--- a/src/network/access/qnetworkaccessdebugpipebackend_p.h
+++ b/src/network/access/qnetworkaccessdebugpipebackend_p.h
@@ -102,6 +102,7 @@ private:
class QNetworkAccessDebugPipeBackendFactory: public QNetworkAccessBackendFactory
{
public:
+ virtual QStringList supportedSchemes() const Q_DECL_OVERRIDE;
virtual QNetworkAccessBackend *create(QNetworkAccessManager::Operation op,
const QNetworkRequest &request) const;
};
diff --git a/src/network/access/qnetworkaccessfilebackend.cpp b/src/network/access/qnetworkaccessfilebackend.cpp
index 13428cc802..13e7394003 100644
--- a/src/network/access/qnetworkaccessfilebackend.cpp
+++ b/src/network/access/qnetworkaccessfilebackend.cpp
@@ -49,6 +49,17 @@
QT_BEGIN_NAMESPACE
+QStringList QNetworkAccessFileBackendFactory::supportedSchemes() const
+{
+ QStringList schemes;
+ schemes << QStringLiteral("file")
+ << QStringLiteral("qrc");
+#if defined(Q_OS_ANDROID)
+ schemes << QStringLiteral("assets");
+#endif
+ return schemes;
+}
+
QNetworkAccessBackend *
QNetworkAccessFileBackendFactory::create(QNetworkAccessManager::Operation op,
const QNetworkRequest &request) const
diff --git a/src/network/access/qnetworkaccessfilebackend_p.h b/src/network/access/qnetworkaccessfilebackend_p.h
index a52ecef165..157461fee7 100644
--- a/src/network/access/qnetworkaccessfilebackend_p.h
+++ b/src/network/access/qnetworkaccessfilebackend_p.h
@@ -88,6 +88,7 @@ private:
class QNetworkAccessFileBackendFactory: public QNetworkAccessBackendFactory
{
public:
+ virtual QStringList supportedSchemes() const Q_DECL_OVERRIDE;
virtual QNetworkAccessBackend *create(QNetworkAccessManager::Operation op,
const QNetworkRequest &request) const;
};
diff --git a/src/network/access/qnetworkaccessftpbackend.cpp b/src/network/access/qnetworkaccessftpbackend.cpp
index 737d7d0151..246eb41657 100644
--- a/src/network/access/qnetworkaccessftpbackend.cpp
+++ b/src/network/access/qnetworkaccessftpbackend.cpp
@@ -43,6 +43,7 @@
#include "qnetworkaccessmanager_p.h"
#include "QtNetwork/qauthenticator.h"
#include "private/qnoncontiguousbytedevice_p.h"
+#include <QStringList>
#ifndef QT_NO_FTP
@@ -61,6 +62,11 @@ static QByteArray makeCacheKey(const QUrl &url)
QUrl::RemoveFragment);
}
+QStringList QNetworkAccessFtpBackendFactory::supportedSchemes() const
+{
+ return QStringList(QStringLiteral("ftp"));
+}
+
QNetworkAccessBackend *
QNetworkAccessFtpBackendFactory::create(QNetworkAccessManager::Operation op,
const QNetworkRequest &request) const
diff --git a/src/network/access/qnetworkaccessftpbackend_p.h b/src/network/access/qnetworkaccessftpbackend_p.h
index 1bc377d80e..c006d450b8 100644
--- a/src/network/access/qnetworkaccessftpbackend_p.h
+++ b/src/network/access/qnetworkaccessftpbackend_p.h
@@ -111,6 +111,7 @@ private:
class QNetworkAccessFtpBackendFactory: public QNetworkAccessBackendFactory
{
public:
+ virtual QStringList supportedSchemes() const Q_DECL_OVERRIDE;
virtual QNetworkAccessBackend *create(QNetworkAccessManager::Operation op,
const QNetworkRequest &request) const;
};
diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp
index 10d19bb7aa..91655ef485 100644
--- a/src/network/access/qnetworkaccessmanager.cpp
+++ b/src/network/access/qnetworkaccessmanager.cpp
@@ -96,9 +96,11 @@ bool getProxyAuth(const QString& proxyHostname, const QString &scheme, QString&
SecProtocolType protocolType = kSecProtocolTypeAny;
if (scheme.compare(QLatin1String("ftp"),Qt::CaseInsensitive)==0) {
protocolType = kSecProtocolTypeFTP;
- } else if (scheme.compare(QLatin1String("http"),Qt::CaseInsensitive)==0) {
+ } else if (scheme.compare(QLatin1String("http"),Qt::CaseInsensitive)==0
+ || scheme.compare(QLatin1String("preconnect-http"),Qt::CaseInsensitive)==0) {
protocolType = kSecProtocolTypeHTTP;
- } else if (scheme.compare(QLatin1String("https"),Qt::CaseInsensitive)==0) {
+ } else if (scheme.compare(QLatin1String("https"),Qt::CaseInsensitive)==0
+ || scheme.compare(QLatin1String("preconnect-https"),Qt::CaseInsensitive)==0) {
protocolType = kSecProtocolTypeHTTPS;
}
QByteArray proxyHostnameUtf8(proxyHostname.toUtf8());
@@ -431,6 +433,7 @@ static void ensureInitialized()
QNetworkAccessManager::QNetworkAccessManager(QObject *parent)
: QObject(*new QNetworkAccessManagerPrivate, parent)
{
+ Q_D(QNetworkAccessManager);
ensureInitialized();
qRegisterMetaType<QNetworkReply::NetworkError>();
@@ -447,6 +450,19 @@ QNetworkAccessManager::QNetworkAccessManager(QObject *parent)
#endif
qRegisterMetaType<QNetworkReply::NetworkError>();
qRegisterMetaType<QSharedPointer<char> >();
+
+#ifndef QT_NO_BEARERMANAGEMENT
+ if (!d->networkSessionRequired) {
+ // if a session is required, we track online state through
+ // the QNetworkSession's signals
+ connect(&d->networkConfigurationManager, SIGNAL(onlineStateChanged(bool)),
+ SLOT(_q_onlineStateChanged(bool)));
+ // we would need all active configurations to check for
+ // d->networkConfigurationManager.isOnline(), which is asynchronous
+ // and potentially expensive. We can just check the configuration here
+ d->online = (d->networkConfiguration.state() & QNetworkConfiguration::Active);
+ }
+#endif
}
/*!
@@ -833,6 +849,11 @@ QNetworkReply *QNetworkAccessManager::deleteResource(const QNetworkRequest &requ
To restore the default network configuration set the network configuration to the value
returned from QNetworkConfigurationManager::defaultConfiguration().
+ Setting a network configuration means that the QNetworkAccessManager instance will only
+ be using the specified one. In particular, if the default network configuration changes
+ (upon e.g. Wifi being available), this new configuration needs to be enabled
+ manually if desired.
+
\snippet code/src_network_access_qnetworkaccessmanager.cpp 2
If an invalid network configuration is set, a network session will not be created. In this
@@ -844,7 +865,10 @@ QNetworkReply *QNetworkAccessManager::deleteResource(const QNetworkRequest &requ
*/
void QNetworkAccessManager::setConfiguration(const QNetworkConfiguration &config)
{
- d_func()->createSession(config);
+ Q_D(QNetworkAccessManager);
+ d->networkConfiguration = config;
+ d->customNetworkConfiguration = true;
+ d->createSession(config);
}
/*!
@@ -926,19 +950,73 @@ QNetworkAccessManager::NetworkAccessibility QNetworkAccessManager::networkAccess
{
Q_D(const QNetworkAccessManager);
- QSharedPointer<QNetworkSession> networkSession(d->getNetworkSession());
- if (networkSession) {
- // d->online holds online/offline state of this network session.
+ if (d->networkSessionRequired) {
+ QSharedPointer<QNetworkSession> networkSession(d->getNetworkSession());
+ if (networkSession) {
+ // d->online holds online/offline state of this network session.
+ if (d->online)
+ return d->networkAccessible;
+ else
+ return NotAccessible;
+ } else {
+ // Network accessibility is either disabled or unknown.
+ return (d->networkAccessible == NotAccessible) ? NotAccessible : UnknownAccessibility;
+ }
+ } else {
if (d->online)
return d->networkAccessible;
else
return NotAccessible;
- } else {
- // Network accessibility is either disabled or unknown.
- return (d->networkAccessible == NotAccessible) ? NotAccessible : UnknownAccessibility;
}
}
+#ifndef QT_NO_SSL
+/*!
+ \since 5.2
+
+ Initiates a connection to the host given by \a hostName at port \a port, using
+ \a sslConfiguration. This function is useful to complete the TCP and SSL handshake
+ to a host before the HTTPS request is made, resulting in a lower network latency.
+
+ \note This function has no possibility to report errors.
+
+ \sa connectToHost(), get(), post(), put(), deleteResource()
+*/
+void QNetworkAccessManager::connectToHostEncrypted(const QString &hostName, quint16 port,
+ const QSslConfiguration &sslConfiguration)
+{
+ QUrl url;
+ url.setHost(hostName);
+ url.setPort(port);
+ url.setScheme(QLatin1String("preconnect-https"));
+ QNetworkRequest request(url);
+ if (sslConfiguration != QSslConfiguration::defaultConfiguration())
+ request.setSslConfiguration(sslConfiguration);
+ get(request);
+}
+#endif
+
+/*!
+ \since 5.2
+
+ Initiates a connection to the host given by \a hostName at port \a port.
+ This function is useful to complete the TCP handshake
+ to a host before the HTTP request is made, resulting in a lower network latency.
+
+ \note This function has no possibility to report errors.
+
+ \sa connectToHostEncrypted(), get(), post(), put(), deleteResource()
+*/
+void QNetworkAccessManager::connectToHost(const QString &hostName, quint16 port)
+{
+ QUrl url;
+ url.setHost(hostName);
+ url.setPort(port);
+ url.setScheme(QLatin1String("preconnect-http"));
+ QNetworkRequest request(url);
+ get(request);
+}
+
/*!
\internal
@@ -1050,10 +1128,10 @@ QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Opera
return new QDisabledNetworkReply(this, req, op);
}
- if (!d->networkSessionStrongRef && (d->initializeSession || !d->networkConfiguration.isEmpty())) {
+ if (!d->networkSessionStrongRef && (d->initializeSession || !d->networkConfiguration.identifier().isEmpty())) {
QNetworkConfigurationManager manager;
- if (!d->networkConfiguration.isEmpty()) {
- d->createSession(manager.configurationFromIdentifier(d->networkConfiguration));
+ if (!d->networkConfiguration.identifier().isEmpty()) {
+ d->createSession(d->networkConfiguration);
} else {
if (manager.capabilities() & QNetworkConfigurationManager::NetworkSessionRequired)
d->createSession(manager.defaultConfiguration());
@@ -1083,9 +1161,9 @@ QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Opera
#ifndef QT_NO_HTTP
// Since Qt 5 we use the new QNetworkReplyHttpImpl
- if (scheme == QLatin1String("http")
+ if (scheme == QLatin1String("http") || scheme == QLatin1String("preconnect-http")
#ifndef QT_NO_SSL
- || scheme == QLatin1String("https")
+ || scheme == QLatin1String("https") || scheme == QLatin1String("preconnect-https")
#endif
) {
QNetworkReplyHttpImpl *reply = new QNetworkReplyHttpImpl(this, request, op, outgoingData);
@@ -1130,6 +1208,57 @@ QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Opera
return reply;
}
+/*!
+ \since 5.2
+
+ Lists all the URL schemes supported by the access manager.
+
+ \sa supportedSchemesImplementation()
+*/
+QStringList QNetworkAccessManager::supportedSchemes() const
+{
+ QStringList schemes;
+ QNetworkAccessManager *self = const_cast<QNetworkAccessManager *>(this); // We know we call a const slot
+ QMetaObject::invokeMethod(self, "supportedSchemesImplementation", Qt::DirectConnection,
+ Q_RETURN_ARG(QStringList, schemes));
+ schemes.removeDuplicates();
+ return schemes;
+}
+
+/*!
+ \since 5.2
+
+ Lists all the URL schemes supported by the access manager.
+
+ You should not call this function directly; use
+ QNetworkAccessManager::supportedSchemes() instead.
+
+ Reimplement this slot to provide your own supported schemes
+ in a QNetworkAccessManager subclass. It is for instance necessary
+ when your subclass provides support for new protocols.
+
+ Because of binary compatibility constraints, the supportedSchemes()
+ method (introduced in Qt 5.2) is not virtual. Instead, supportedSchemes()
+ will dynamically detect and call this slot.
+
+ \sa supportedSchemes()
+*/
+QStringList QNetworkAccessManager::supportedSchemesImplementation() const
+{
+ Q_D(const QNetworkAccessManager);
+
+ QStringList schemes = d->backendSupportedSchemes();
+ // Those ones don't exist in backends
+#ifndef QT_NO_HTTP
+ schemes << QStringLiteral("http");
+#ifndef QT_NO_SSL
+ if (QSslSocket::supportsSsl())
+ schemes << QStringLiteral("https");
+#endif
+#endif
+ schemes << QStringLiteral("data");
+ return schemes;
+}
/*!
\since 5.0
@@ -1403,7 +1532,7 @@ void QNetworkAccessManagerPrivate::_q_networkSessionClosed()
Q_Q(QNetworkAccessManager);
QSharedPointer<QNetworkSession> networkSession(getNetworkSession());
if (networkSession) {
- networkConfiguration = networkSession->configuration().identifier();
+ networkConfiguration = networkSession->configuration();
//disconnect from old session
QObject::disconnect(networkSession.data(), SIGNAL(opened()), q, SIGNAL(networkSessionConnected()));
@@ -1437,6 +1566,18 @@ void QNetworkAccessManagerPrivate::_q_networkSessionStateChanged(QNetworkSession
}
}
}
+
+void QNetworkAccessManagerPrivate::_q_onlineStateChanged(bool isOnline)
+{
+ // if the user set a config, we only care whether this one is active.
+ // Otherwise, this QNAM is online if there is an online config.
+ if (customNetworkConfiguration) {
+ online = (networkConfiguration.state() & QNetworkConfiguration::Active);
+ } else {
+ online = isOnline;
+ }
+}
+
#endif // QT_NO_BEARERMANAGEMENT
QNetworkRequest QNetworkAccessManagerPrivate::prepareMultipart(const QNetworkRequest &request, QHttpMultiPart *multiPart)
diff --git a/src/network/access/qnetworkaccessmanager.h b/src/network/access/qnetworkaccessmanager.h
index 826c8e47d7..67b9bbcb07 100644
--- a/src/network/access/qnetworkaccessmanager.h
+++ b/src/network/access/qnetworkaccessmanager.h
@@ -43,6 +43,9 @@
#define QNETWORKACCESSMANAGER_H
#include <QtCore/QObject>
+#ifndef QT_NO_SSL
+#include <QtNetwork/QSslConfiguration>
+#endif
QT_BEGIN_NAMESPACE
@@ -97,6 +100,9 @@ public:
explicit QNetworkAccessManager(QObject *parent = 0);
~QNetworkAccessManager();
+ // ### Qt 6: turn into virtual
+ QStringList supportedSchemes() const;
+
void clearAccessCache();
#ifndef QT_NO_NETWORKPROXY
@@ -132,6 +138,12 @@ public:
NetworkAccessibility networkAccessible() const;
#endif
+#ifndef QT_NO_SSL
+ void connectToHostEncrypted(const QString &hostName, quint16 port = 443,
+ const QSslConfiguration &sslConfiguration = QSslConfiguration::defaultConfiguration());
+#endif
+ void connectToHost(const QString &hostName, quint16 port = 80);
+
Q_SIGNALS:
#ifndef QT_NO_NETWORKPROXY
void proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *authenticator);
@@ -153,6 +165,9 @@ protected:
virtual QNetworkReply *createRequest(Operation op, const QNetworkRequest &request,
QIODevice *outgoingData = 0);
+protected Q_SLOTS:
+ QStringList supportedSchemesImplementation() const;
+
private:
friend class QNetworkReplyImplPrivate;
friend class QNetworkReplyHttpImpl;
@@ -165,6 +180,7 @@ private:
#ifndef QT_NO_BEARERMANAGEMENT
Q_PRIVATE_SLOT(d_func(), void _q_networkSessionClosed())
Q_PRIVATE_SLOT(d_func(), void _q_networkSessionStateChanged(QNetworkSession::State))
+ Q_PRIVATE_SLOT(d_func(), void _q_onlineStateChanged(bool))
#endif
};
diff --git a/src/network/access/qnetworkaccessmanager_p.h b/src/network/access/qnetworkaccessmanager_p.h
index cf756dad7b..292755e7eb 100644
--- a/src/network/access/qnetworkaccessmanager_p.h
+++ b/src/network/access/qnetworkaccessmanager_p.h
@@ -60,6 +60,9 @@
#include "QtNetwork/qnetworkproxy.h"
#include "QtNetwork/qnetworksession.h"
#include "qnetworkaccessauthenticationmanager_p.h"
+#ifndef QT_NO_BEARERMANAGEMENT
+#include "QtNetwork/qnetworkconfigmanager.h"
+#endif
QT_BEGIN_NAMESPACE
@@ -79,6 +82,10 @@ public:
#endif
#ifndef QT_NO_BEARERMANAGEMENT
lastSessionState(QNetworkSession::Invalid),
+ networkConfiguration(networkConfigurationManager.defaultConfiguration()),
+ customNetworkConfiguration(false),
+ networkSessionRequired(networkConfigurationManager.capabilities()
+ & QNetworkConfigurationManager::NetworkSessionRequired),
networkAccessible(QNetworkAccessManager::Accessible),
activeReplyCount(0),
online(false),
@@ -117,6 +124,7 @@ public:
#endif
QNetworkAccessBackend *findBackend(QNetworkAccessManager::Operation op, const QNetworkRequest &request);
+ QStringList backendSupportedSchemes() const;
#ifndef QT_NO_BEARERMANAGEMENT
void createSession(const QNetworkConfiguration &config);
@@ -127,6 +135,7 @@ public:
void _q_networkSessionPreferredConfigurationChanged(const QNetworkConfiguration &config,
bool isSeamless);
void _q_networkSessionStateChanged(QNetworkSession::State state);
+ void _q_onlineStateChanged(bool isOnline);
#endif
QNetworkRequest prepareMultipart(const QNetworkRequest &request, QHttpMultiPart *multiPart);
@@ -148,7 +157,12 @@ public:
QSharedPointer<QNetworkSession> networkSessionStrongRef;
QWeakPointer<QNetworkSession> networkSessionWeakRef;
QNetworkSession::State lastSessionState;
- QString networkConfiguration;
+ QNetworkConfigurationManager networkConfigurationManager;
+ QNetworkConfiguration networkConfiguration;
+ // we need to track whether the user set a config or not,
+ // because the default config might change
+ bool customNetworkConfiguration;
+ bool networkSessionRequired;
QNetworkAccessManager::NetworkAccessibility networkAccessible;
int activeReplyCount;
bool online;
diff --git a/src/network/access/qnetworkreplyhttpimpl.cpp b/src/network/access/qnetworkreplyhttpimpl.cpp
index c7d3846465..ddef970966 100644
--- a/src/network/access/qnetworkreplyhttpimpl.cpp
+++ b/src/network/access/qnetworkreplyhttpimpl.cpp
@@ -629,10 +629,15 @@ void QNetworkReplyHttpImplPrivate::postRequest()
QUrl url = request.url();
httpRequest.setUrl(url);
- bool ssl = url.scheme().toLower() == QLatin1String("https");
+ QString scheme = url.scheme().toLower();
+ bool ssl = (scheme == QLatin1String("https")
+ || scheme == QLatin1String("preconnect-https"));
q->setAttribute(QNetworkRequest::ConnectionEncryptedAttribute, ssl);
httpRequest.setSsl(ssl);
+ bool preConnect = (scheme == QLatin1String("preconnect-http")
+ || scheme == QLatin1String("preconnect-https"));
+ httpRequest.setPreConnect(preConnect);
#ifndef QT_NO_NETWORKPROXY
QNetworkProxy transparentProxy, cacheProxy;
diff --git a/src/network/bearer/qnetworkconfiguration.cpp b/src/network/bearer/qnetworkconfiguration.cpp
index 615ef21661..fae4aad76e 100644
--- a/src/network/bearer/qnetworkconfiguration.cpp
+++ b/src/network/bearer/qnetworkconfiguration.cpp
@@ -41,6 +41,12 @@
#include "qnetworkconfiguration.h"
#include "qnetworkconfiguration_p.h"
+#include <QDebug>
+
+#ifdef Q_OS_BLACKBERRY
+#include "private/qcore_unix_p.h" // qt_safe_open
+#include <sys/pps.h>
+#endif // Q_OS_BLACKBERRY
QT_BEGIN_NAMESPACE
@@ -193,13 +199,88 @@ QT_BEGIN_NAMESPACE
\value BearerEthernet The configuration is for an Ethernet interfaces.
\value BearerWLAN The configuration is for a Wireless LAN interface.
\value Bearer2G The configuration is for a CSD, GPRS, HSCSD, EDGE or cdmaOne interface.
+ \value Bearer3G The configuration is for a 3G interface.
+ \value Bearer4G The configuration is for a 4G interface.
\value BearerCDMA2000 The configuration is for CDMA interface.
\value BearerWCDMA The configuration is for W-CDMA/UMTS interface.
\value BearerHSPA The configuration is for High Speed Packet Access (HSPA) interface.
\value BearerBluetooth The configuration is for a Bluetooth interface.
\value BearerWiMAX The configuration is for a WiMAX interface.
+ \value BearerEVDO The configuration is for an EVDO (3G) interface.
+ \value BearerLTE The configuration is for a LTE (4G) interface.
*/
+#ifdef Q_OS_BLACKBERRY
+static const char cellularStatusFile[] = "/pps/services/radioctrl/modem0/status_public";
+
+static QNetworkConfiguration::BearerType cellularStatus()
+{
+ QNetworkConfiguration::BearerType ret = QNetworkConfiguration::BearerUnknown;
+
+ int cellularStatusFD;
+ if ((cellularStatusFD = qt_safe_open(cellularStatusFile, O_RDONLY)) == -1) {
+ qWarning() << Q_FUNC_INFO << "failed to open" << cellularStatusFile;
+ return ret;
+ }
+ char buf[2048];
+ if (qt_safe_read(cellularStatusFD, &buf, sizeof(buf)) == -1) {
+ qWarning() << Q_FUNC_INFO << "read from PPS file failed:" << strerror(errno);
+ qt_safe_close(cellularStatusFD);
+ return ret;
+ }
+ pps_decoder_t ppsDecoder;
+ if (pps_decoder_initialize(&ppsDecoder, buf) != PPS_DECODER_OK) {
+ qWarning() << Q_FUNC_INFO << "failed to initialize PPS decoder";
+ qt_safe_close(cellularStatusFD);
+ return ret;
+ }
+ pps_decoder_error_t err;
+ if ((err = pps_decoder_push(&ppsDecoder, 0)) != PPS_DECODER_OK) {
+ qWarning() << Q_FUNC_INFO << "pps_decoder_push failed" << err;
+ pps_decoder_cleanup(&ppsDecoder);
+ qt_safe_close(cellularStatusFD);
+ return ret;
+ }
+ if (!pps_decoder_is_integer(&ppsDecoder, "network_technology")) {
+ qWarning() << Q_FUNC_INFO << "field has not the expected data type";
+ pps_decoder_cleanup(&ppsDecoder);
+ qt_safe_close(cellularStatusFD);
+ return ret;
+ }
+ int type;
+ if (!pps_decoder_get_int(&ppsDecoder, "network_technology", &type)
+ == PPS_DECODER_OK) {
+ qWarning() << Q_FUNC_INFO << "could not read bearer type from PPS";
+ pps_decoder_cleanup(&ppsDecoder);
+ qt_safe_close(cellularStatusFD);
+ return ret;
+ }
+ switch (type) {
+ case 0: // 0 == NONE
+ break; // unhandled
+ case 1: // fallthrough, 1 == GSM
+ case 4: // 4 == CDMA_1X
+ ret = QNetworkConfiguration::Bearer2G;
+ break;
+ case 2: // 2 == UMTS
+ ret = QNetworkConfiguration::BearerWCDMA;
+ break;
+ case 8: // 8 == EVDO
+ ret = QNetworkConfiguration::BearerEVDO;
+ break;
+ case 16: // 16 == LTE
+ ret = QNetworkConfiguration::BearerLTE;
+ break;
+ default:
+ qWarning() << Q_FUNC_INFO << "unhandled bearer type" << type;
+ break;
+ }
+ pps_decoder_cleanup(&ppsDecoder);
+ qt_safe_close(cellularStatusFD);
+ return ret;
+}
+#endif // Q_OS_BLACKBERRY
+
/*!
Constructs an invalid configuration object.
@@ -412,6 +493,8 @@ QList<QNetworkConfiguration> QNetworkConfiguration::children() const
function can be used to retrieve a textural type name for the bearer.
An invalid network configuration always returns the BearerUnknown value.
+
+ \sa bearerTypeName(), bearerTypeFamily()
*/
QNetworkConfiguration::BearerType QNetworkConfiguration::bearerType() const
{
@@ -420,10 +503,74 @@ QNetworkConfiguration::BearerType QNetworkConfiguration::bearerType() const
QMutexLocker locker(&d->mutex);
+#ifdef Q_OS_BLACKBERRY
+ // for cellular configurations, we need to determine the exact
+ // type right now, because it might have changed after the last scan
+ if (d->bearerType == QNetworkConfiguration::Bearer2G) {
+ QNetworkConfiguration::BearerType type = cellularStatus();
+ // if reading the status failed for some reason, just
+ // fall back to 2G
+ return (type == QNetworkConfiguration::BearerUnknown)
+ ? QNetworkConfiguration::Bearer2G : type;
+ }
+#endif // Q_OS_BLACKBERRY
+
return d->bearerType;
}
/*!
+ \since 5.2
+
+ Returns the bearer type family used by this network configuration.
+ The following table lists how bearerType() values map to
+ bearerTypeFamily() values:
+
+ \table
+ \header
+ \li bearer type
+ \li bearer type family
+ \row
+ \li BearerUnknown, Bearer2G, BearerEthernet, BearerWLAN,
+ BearerBluetooth
+ \li (same type)
+ \row
+ \li BearerCDMA2000, BearerEVDO, BearerWCDMA, BearerHSPA, Bearer3G
+ \li Bearer3G
+ \row
+ \li BearerWiMAX, BearerLTE, Bearer4G
+ \li Bearer4G
+ \endtable
+
+ An invalid network configuration always returns the BearerUnknown value.
+
+ \sa bearerType(), bearerTypeName()
+*/
+QNetworkConfiguration::BearerType QNetworkConfiguration::bearerTypeFamily() const
+{
+ QNetworkConfiguration::BearerType type = bearerType();
+ switch (type) {
+ case QNetworkConfiguration::BearerUnknown: // fallthrough
+ case QNetworkConfiguration::Bearer2G: // fallthrough
+ case QNetworkConfiguration::BearerEthernet: // fallthrough
+ case QNetworkConfiguration::BearerWLAN: // fallthrough
+ case QNetworkConfiguration::BearerBluetooth:
+ return type;
+ case QNetworkConfiguration::BearerCDMA2000: // fallthrough
+ case QNetworkConfiguration::BearerEVDO: // fallthrough
+ case QNetworkConfiguration::BearerWCDMA: // fallthrough
+ case QNetworkConfiguration::BearerHSPA: // fallthrough
+ case QNetworkConfiguration::Bearer3G:
+ return QNetworkConfiguration::Bearer3G;
+ case QNetworkConfiguration::BearerWiMAX: // fallthrough
+ case QNetworkConfiguration::BearerLTE: // fallthrough
+ case QNetworkConfiguration::Bearer4G:
+ return QNetworkConfiguration::Bearer4G;
+ default:
+ qWarning() << "unknown bearer type" << type;
+ return QNetworkConfiguration::BearerUnknown;
+ }
+}
+/*!
Returns the type of bearer used by this network configuration as a string.
The string is not translated and therefore can not be shown to the user. The subsequent table
@@ -450,6 +597,12 @@ QNetworkConfiguration::BearerType QNetworkConfiguration::bearerType() const
\li Bearer2G
\li 2G
\row
+ \li Bearer3G
+ \li 3G
+ \row
+ \li Bearer4G
+ \li 4G
+ \row
\li BearerCDMA2000
\li CDMA2000
\row
@@ -464,13 +617,19 @@ QNetworkConfiguration::BearerType QNetworkConfiguration::bearerType() const
\row
\li BearerWiMAX
\li WiMAX
+ \row
+ \li BearerEVDO
+ \li EVDO
+ \row
+ \li BearerLTE
+ \li LTE
\endtable
This function returns an empty string if this is an invalid configuration, a network
configuration of type \l QNetworkConfiguration::ServiceNetwork or
\l QNetworkConfiguration::UserChoice.
- \sa bearerType()
+ \sa bearerType(), bearerTypeFamily()
*/
QString QNetworkConfiguration::bearerTypeName() const
{
@@ -489,7 +648,25 @@ QString QNetworkConfiguration::bearerTypeName() const
case BearerWLAN:
return QStringLiteral("WLAN");
case Bearer2G:
+#ifdef Q_OS_BLACKBERRY
+ {
+ // for cellular configurations, we need to determine the exact
+ // type right now, because it might have changed after the last scan
+ QNetworkConfiguration::BearerType type = cellularStatus();
+ if (type == QNetworkConfiguration::BearerWCDMA) {
+ return QStringLiteral("WCDMA");
+ } else if (type == QNetworkConfiguration::BearerEVDO) {
+ return QStringLiteral("EVDO");
+ }else if (type == QNetworkConfiguration::BearerLTE) {
+ return QStringLiteral("LTE");
+ }
+ }
+#endif // Q_OS_BLACKBERRY
return QStringLiteral("2G");
+ case Bearer3G:
+ return QStringLiteral("3G");
+ case Bearer4G:
+ return QStringLiteral("4G");
case BearerCDMA2000:
return QStringLiteral("CDMA2000");
case BearerWCDMA:
@@ -500,6 +677,10 @@ QString QNetworkConfiguration::bearerTypeName() const
return QStringLiteral("Bluetooth");
case BearerWiMAX:
return QStringLiteral("WiMAX");
+ case BearerEVDO:
+ return QStringLiteral("EVDO");
+ case BearerLTE:
+ return QStringLiteral("LTE");
case BearerUnknown:
break;
}
diff --git a/src/network/bearer/qnetworkconfiguration.h b/src/network/bearer/qnetworkconfiguration.h
index 25dafcb282..8887525a2f 100644
--- a/src/network/bearer/qnetworkconfiguration.h
+++ b/src/network/bearer/qnetworkconfiguration.h
@@ -97,7 +97,11 @@ public:
BearerWCDMA,
BearerHSPA,
BearerBluetooth,
- BearerWiMAX
+ BearerWiMAX,
+ BearerEVDO,
+ BearerLTE,
+ Bearer3G,
+ Bearer4G
};
StateFlags state() const;
@@ -105,6 +109,7 @@ public:
Purpose purpose() const;
BearerType bearerType() const;
+ BearerType bearerTypeFamily() const;
QString bearerTypeName() const;
QString identifier() const;
diff --git a/src/network/doc/qtnetwork.qdocconf b/src/network/doc/qtnetwork.qdocconf
index 048b3325b6..f4779ae8fe 100644
--- a/src/network/doc/qtnetwork.qdocconf
+++ b/src/network/doc/qtnetwork.qdocconf
@@ -40,3 +40,6 @@ exampledirs += ../../../examples/network \
imagedirs += images \
../../../examples/network/doc/images
+
+navigation.landingpage = "Qt Network"
+navigation.cppclassespage = "Qt Network C++ Classes"
diff --git a/src/network/kernel/qhostaddress.cpp b/src/network/kernel/qhostaddress.cpp
index dc67b0d835..5ef428305c 100644
--- a/src/network/kernel/qhostaddress.cpp
+++ b/src/network/kernel/qhostaddress.cpp
@@ -189,7 +189,7 @@ static bool parseIp6(const QString &address, QIPAddressUtils::IPv6Address &addr,
} else {
scopeId->clear();
}
- return QIPAddressUtils::parseIp6(addr, tmp.constBegin(), tmp.constEnd());
+ return QIPAddressUtils::parseIp6(addr, tmp.constBegin(), tmp.constEnd()) == 0;
}
bool QHostAddressPrivate::parse()
diff --git a/src/network/ssl/qssl.cpp b/src/network/ssl/qssl.cpp
index 4e33001d8d..ec771e1f49 100644
--- a/src/network/ssl/qssl.cpp
+++ b/src/network/ssl/qssl.cpp
@@ -161,12 +161,20 @@ QT_BEGIN_NAMESPACE
mechanism for renegotiating the connection parameters. When enabled, this
option can allow connections for legacy servers, but it introduces the
possibility that an attacker could inject plaintext into the SSL session.
+ \value SslOptionDisableSessionSharing Disables SSL session sharing via
+ the session ID handshake attribute.
+ \value SslOptionDisableSessionPersistence Disables storing the SSL session
+ in ASN.1 format as returned by QSslConfiguration::session(). Enabling
+ this feature adds memory overhead of approximately 1K per used session
+ ticket.
By default, SslOptionDisableEmptyFragments is turned on since this causes
problems with a large number of servers. SslOptionDisableLegacyRenegotiation
is also turned on, since it introduces a security risk.
SslOptionDisableCompression is turned on to prevent the attack publicised by
- CRIME. The other options are turned off.
+ CRIME.
+ SslOptionDisableSessionPersistence is turned on to optimize memory usage.
+ The other options are turned off.
Note: Availability of above options depends on the version of the SSL
backend in use.
diff --git a/src/network/ssl/qssl.h b/src/network/ssl/qssl.h
index 06d80965e2..21d03cb703 100644
--- a/src/network/ssl/qssl.h
+++ b/src/network/ssl/qssl.h
@@ -95,7 +95,9 @@ namespace QSsl {
SslOptionDisableSessionTickets = 0x02,
SslOptionDisableCompression = 0x04,
SslOptionDisableServerNameIndication = 0x08,
- SslOptionDisableLegacyRenegotiation = 0x10
+ SslOptionDisableLegacyRenegotiation = 0x10,
+ SslOptionDisableSessionSharing = 0x20,
+ SslOptionDisableSessionPersistence = 0x40
};
Q_DECLARE_FLAGS(SslOptions, SslOption)
}
diff --git a/src/network/ssl/qsslconfiguration.cpp b/src/network/ssl/qsslconfiguration.cpp
index afbd4fac77..6cc06dfbd2 100644
--- a/src/network/ssl/qsslconfiguration.cpp
+++ b/src/network/ssl/qsslconfiguration.cpp
@@ -49,7 +49,8 @@ QT_BEGIN_NAMESPACE
const QSsl::SslOptions QSslConfigurationPrivate::defaultSslOptions = QSsl::SslOptionDisableEmptyFragments
|QSsl::SslOptionDisableLegacyRenegotiation
- |QSsl::SslOptionDisableCompression;
+ |QSsl::SslOptionDisableCompression
+ |QSsl::SslOptionDisableSessionPersistence;
/*!
\class QSslConfiguration
@@ -182,7 +183,9 @@ bool QSslConfiguration::operator==(const QSslConfiguration &other) const
d->peerVerifyMode == other.d->peerVerifyMode &&
d->peerVerifyDepth == other.d->peerVerifyDepth &&
d->allowRootCertOnDemandLoading == other.d->allowRootCertOnDemandLoading &&
- d->sslOptions == other.d->sslOptions;
+ d->sslOptions == other.d->sslOptions &&
+ d->sslSession == other.d->sslSession &&
+ d->sslSessionTicketLifeTimeHint == other.d->sslSessionTicketLifeTimeHint;
}
/*!
@@ -216,7 +219,9 @@ bool QSslConfiguration::isNull() const
d->privateKey.isNull() &&
d->peerCertificate.isNull() &&
d->peerCertificateChain.count() == 0 &&
- d->sslOptions == QSslConfigurationPrivate::defaultSslOptions);
+ d->sslOptions == QSslConfigurationPrivate::defaultSslOptions &&
+ d->sslSession.isNull() &&
+ d->sslSessionTicketLifeTimeHint == -1);
}
/*!
@@ -594,6 +599,60 @@ bool QSslConfiguration::testSslOption(QSsl::SslOption option) const
}
/*!
+ \since 5.2
+
+ If QSsl::SslOptionDisableSessionPersistence was turned off, this
+ function returns the session used in the SSL handshake in ASN.1
+ format, suitable to e.g. be persisted to disk. If no session was
+ used or QSsl::SslOptionDisableSessionPersistence was not turned off,
+ this function returns an empty QByteArray.
+
+ \b{Note:} When persisting the session to disk or similar, be
+ careful not to expose the session to a potential attacker, as
+ knowledge of the session allows for eavesdropping on data
+ encrypted with the session parameters.
+
+ \sa setSession(), QSsl::SslOptionDisableSessionPersistence, setSslOption()
+ */
+QByteArray QSslConfiguration::session() const
+{
+ return d->sslSession;
+}
+
+/*!
+ \since 5.2
+
+ Sets the session to be used in an SSL handshake.
+ QSsl::SslOptionDisableSessionPersistence must be turned off
+ for this to work, and \a session must be in ASN.1 format
+ as returned by session().
+
+ \sa session(), QSsl::SslOptionDisableSessionPersistence, setSslOption()
+ */
+void QSslConfiguration::setSession(const QByteArray &session)
+{
+ d->sslSession = session;
+}
+
+/*!
+ \since 5.2
+
+ If QSsl::SslOptionDisableSessionPersistence was turned off, this
+ function returns the session ticket life time hint sent by the
+ server (which might be 0).
+ If the server did not send a session ticket (e.g. when
+ resuming a session or when the server does not support it) or
+ QSsl::SslOptionDisableSessionPersistence was not turned off,
+ this function returns -1.
+
+ \sa session(), QSsl::SslOptionDisableSessionPersistence, setSslOption()
+ */
+int QSslConfiguration::sessionTicketLifeTimeHint() const
+{
+ return d->sslSessionTicketLifeTimeHint;
+}
+
+/*!
Returns the default SSL configuration to be used in new SSL
connections.
diff --git a/src/network/ssl/qsslconfiguration.h b/src/network/ssl/qsslconfiguration.h
index 0000382ed5..949ce70d4c 100644
--- a/src/network/ssl/qsslconfiguration.h
+++ b/src/network/ssl/qsslconfiguration.h
@@ -124,6 +124,10 @@ public:
void setSslOption(QSsl::SslOption option, bool on);
bool testSslOption(QSsl::SslOption option) const;
+ QByteArray session() const;
+ void setSession(const QByteArray &session);
+ int sessionTicketLifeTimeHint() const;
+
static QSslConfiguration defaultConfiguration();
static void setDefaultConfiguration(const QSslConfiguration &configuration);
diff --git a/src/network/ssl/qsslconfiguration_p.h b/src/network/ssl/qsslconfiguration_p.h
index 54b7264d3d..71ee8d2bfe 100644
--- a/src/network/ssl/qsslconfiguration_p.h
+++ b/src/network/ssl/qsslconfiguration_p.h
@@ -85,7 +85,8 @@ public:
peerVerifyDepth(0),
allowRootCertOnDemandLoading(true),
peerSessionShared(false),
- sslOptions(QSslConfigurationPrivate::defaultSslOptions)
+ sslOptions(QSslConfigurationPrivate::defaultSslOptions),
+ sslSessionTicketLifeTimeHint(-1)
{ }
QSslCertificate peerCertificate;
@@ -110,6 +111,9 @@ public:
Q_AUTOTEST_EXPORT static const QSsl::SslOptions defaultSslOptions;
+ QByteArray sslSession;
+ int sslSessionTicketLifeTimeHint;
+
// in qsslsocket.cpp:
static QSslConfiguration defaultConfiguration();
static void setDefaultConfiguration(const QSslConfiguration &configuration);
diff --git a/src/network/ssl/qsslcontext.cpp b/src/network/ssl/qsslcontext.cpp
index 22ad42116b..6d281c390d 100644
--- a/src/network/ssl/qsslcontext.cpp
+++ b/src/network/ssl/qsslcontext.cpp
@@ -57,7 +57,8 @@ extern QString getErrorsFromOpenSsl();
QSslContext::QSslContext()
: ctx(0),
pkey(0),
- session(0)
+ session(0),
+ m_sessionTicketLifeTimeHint(-1)
{
}
@@ -258,6 +259,10 @@ init_context:
if (sslContext->sslConfiguration.peerVerifyDepth() != 0)
q_SSL_CTX_set_verify_depth(sslContext->ctx, sslContext->sslConfiguration.peerVerifyDepth());
+ // set persisted session if the user set it
+ if (!configuration.session().isEmpty())
+ sslContext->setSessionASN1(configuration.session());
+
return sslContext;
}
@@ -267,6 +272,12 @@ SSL* QSslContext::createSsl()
SSL* ssl = q_SSL_new(ctx);
q_SSL_clear(ssl);
+ if (!session && !sessionASN1().isEmpty()
+ && !sslConfiguration.testSslOption(QSsl::SslOptionDisableSessionPersistence)) {
+ const unsigned char *data = reinterpret_cast<const unsigned char *>(m_sessionASN1.constData());
+ session = q_d2i_SSL_SESSION(0, &data, m_sessionASN1.size()); // refcount is 1 already, set by function above
+ }
+
if (session) {
// Try to resume the last session we cached
if (!q_SSL_set_session(ssl, session)) {
@@ -292,8 +303,34 @@ bool QSslContext::cacheSession(SSL* ssl)
// cache the session the caller gave us and increase reference count
session = q_SSL_get1_session(ssl);
- return (session != NULL);
+ if (session && !sslConfiguration.testSslOption(QSsl::SslOptionDisableSessionPersistence)) {
+ int sessionSize = q_i2d_SSL_SESSION(session, 0);
+ if (sessionSize > 0) {
+ m_sessionASN1.resize(sessionSize);
+ unsigned char *data = reinterpret_cast<unsigned char *>(m_sessionASN1.data());
+ if (!q_i2d_SSL_SESSION(session, &data))
+ qWarning("could not store persistent version of SSL session");
+ m_sessionTicketLifeTimeHint = session->tlsext_tick_lifetime_hint;
+ }
+ }
+
+ return (session != 0);
+}
+
+QByteArray QSslContext::sessionASN1() const
+{
+ return m_sessionASN1;
+}
+
+void QSslContext::setSessionASN1(const QByteArray &session)
+{
+ m_sessionASN1 = session;
+}
+
+int QSslContext::sessionTicketLifeTimeHint() const
+{
+ return m_sessionTicketLifeTimeHint;
}
QSslError::SslError QSslContext::error() const
diff --git a/src/network/ssl/qsslcontext_p.h b/src/network/ssl/qsslcontext_p.h
index c8578d349e..2b596798a6 100644
--- a/src/network/ssl/qsslcontext_p.h
+++ b/src/network/ssl/qsslcontext_p.h
@@ -69,6 +69,9 @@ public:
SSL* createSsl();
bool cacheSession(SSL*); // should be called when handshake completed
+ QByteArray sessionASN1() const;
+ void setSessionASN1(const QByteArray &sessionASN1);
+ int sessionTicketLifeTimeHint() const;
protected:
QSslContext();
@@ -76,6 +79,8 @@ private:
SSL_CTX* ctx;
EVP_PKEY *pkey;
SSL_SESSION *session;
+ QByteArray m_sessionASN1;
+ int m_sessionTicketLifeTimeHint;
QSslError::SslError errorCode;
QString errorStr;
QSslConfiguration sslConfiguration;
diff --git a/src/network/ssl/qsslsocket.cpp b/src/network/ssl/qsslsocket.cpp
index f2310356df..0e7ac39d14 100644
--- a/src/network/ssl/qsslsocket.cpp
+++ b/src/network/ssl/qsslsocket.cpp
@@ -903,6 +903,8 @@ void QSslSocket::setSslConfiguration(const QSslConfiguration &configuration)
d->configuration.peerVerifyMode = configuration.peerVerifyMode();
d->configuration.protocol = configuration.protocol();
d->configuration.sslOptions = configuration.d->sslOptions;
+ d->configuration.sslSession = configuration.session();
+ d->configuration.sslSessionTicketLifeTimeHint = configuration.sessionTicketLifeTimeHint();
// if the CA certificates were set explicitly (either via
// QSslConfiguration::setCaCertificates() or QSslSocket::setCaCertificates(),
diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp
index 675bd7d9f7..e378faae68 100644
--- a/src/network/ssl/qsslsocket_openssl.cpp
+++ b/src/network/ssl/qsslsocket_openssl.cpp
@@ -1449,9 +1449,17 @@ void QSslSocketBackendPrivate::continueHandshake()
#endif
// Cache this SSL session inside the QSslContext
- if (!(configuration.sslOptions & QSsl::SslOptionDisableSessionTickets)) {
- if (!sslContextPointer->cacheSession(ssl))
+ if (!(configuration.sslOptions & QSsl::SslOptionDisableSessionSharing)) {
+ if (!sslContextPointer->cacheSession(ssl)) {
sslContextPointer.clear(); // we could not cache the session
+ } else {
+ // Cache the session for permanent usage as well
+ if (!(configuration.sslOptions & QSsl::SslOptionDisableSessionPersistence)) {
+ if (!sslContextPointer->sessionASN1().isEmpty())
+ configuration.sslSession = sslContextPointer->sessionASN1();
+ configuration.sslSessionTicketLifeTimeHint = sslContextPointer->sessionTicketLifeTimeHint();
+ }
+ }
}
connectionEncrypted = true;
diff --git a/src/network/ssl/qsslsocket_openssl_symbols.cpp b/src/network/ssl/qsslsocket_openssl_symbols.cpp
index d2a349455e..ec4730a022 100644
--- a/src/network/ssl/qsslsocket_openssl_symbols.cpp
+++ b/src/network/ssl/qsslsocket_openssl_symbols.cpp
@@ -332,6 +332,8 @@ DEFINEFUNC(void, OPENSSL_add_all_algorithms_conf, void, DUMMYARG, return, DUMMYA
DEFINEFUNC3(int, SSL_CTX_load_verify_locations, SSL_CTX *ctx, ctx, const char *CAfile, CAfile, const char *CApath, CApath, return 0, return)
DEFINEFUNC(long, SSLeay, void, DUMMYARG, return 0, return)
DEFINEFUNC(const char *, SSLeay_version, int a, a, return 0, return)
+DEFINEFUNC2(int, i2d_SSL_SESSION, SSL_SESSION *in, in, unsigned char **pp, pp, return 0, return)
+DEFINEFUNC3(SSL_SESSION *, d2i_SSL_SESSION, SSL_SESSION **a, a, const unsigned char **pp, pp, long length, length, return 0, return)
#define RESOLVEFUNC(func) \
if (!(_q_##func = _q_PTR_##func(libs.first->resolve(#func))) \
@@ -801,6 +803,8 @@ bool q_resolveOpenSslSymbols()
RESOLVEFUNC(SSL_CTX_load_verify_locations)
RESOLVEFUNC(SSLeay)
RESOLVEFUNC(SSLeay_version)
+ RESOLVEFUNC(i2d_SSL_SESSION)
+ RESOLVEFUNC(d2i_SSL_SESSION)
symbolsResolved = true;
delete libs.first;
diff --git a/src/network/ssl/qsslsocket_openssl_symbols_p.h b/src/network/ssl/qsslsocket_openssl_symbols_p.h
index 2e01ee4d31..1fd98cc7fb 100644
--- a/src/network/ssl/qsslsocket_openssl_symbols_p.h
+++ b/src/network/ssl/qsslsocket_openssl_symbols_p.h
@@ -469,6 +469,8 @@ void q_OPENSSL_add_all_algorithms_conf();
int q_SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile, const char *CApath);
long q_SSLeay();
const char *q_SSLeay_version(int type);
+int q_i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp);
+SSL_SESSION *q_d2i_SSL_SESSION(SSL_SESSION **a, const unsigned char **pp, long length);
// Helper function
class QDateTime;
diff --git a/src/opengl/doc/qtopengl.qdocconf b/src/opengl/doc/qtopengl.qdocconf
index e76a23844b..5b6d09dfcd 100644
--- a/src/opengl/doc/qtopengl.qdocconf
+++ b/src/opengl/doc/qtopengl.qdocconf
@@ -19,7 +19,7 @@ exampledirs += ../../../examples/opengl \
imagedirs += images \
../../../examples/opengl/doc/images
-depends += qtcore qtgui qtwidgets
+depends += qtdoc qtcore qtgui qtwidgets
examplesinstallpath = opengl
@@ -50,3 +50,6 @@ qhp.QtOpenGL.subprojects.classes.title = C++ Classes
qhp.QtOpenGL.subprojects.classes.indexTitle = Qt OpenGL C++ Classes
qhp.QtOpenGL.subprojects.classes.selectors = class fake:headerfile
qhp.QtOpenGL.subprojects.classes.sortPages = true
+
+navigation.landingpage = "Qt OpenGL"
+navigation.cppclassespage = "Qt OpenGL C++ Classes"
diff --git a/src/platformsupport/eglconvenience/qxlibeglintegration.cpp b/src/platformsupport/eglconvenience/qxlibeglintegration.cpp
index 58f24c0a04..80453816fc 100644
--- a/src/platformsupport/eglconvenience/qxlibeglintegration.cpp
+++ b/src/platformsupport/eglconvenience/qxlibeglintegration.cpp
@@ -41,17 +41,6 @@
#include "qxlibeglintegration_p.h"
-static int countBits(unsigned long mask)
-{
- int count = 0;
- while (mask != 0) {
- if (mask & 1)
- ++count;
- mask >>= 1;
- }
- return count;
-}
-
VisualID QXlibEglIntegration::getCompatibleVisualId(Display *display, EGLDisplay eglDisplay, EGLConfig config)
{
VisualID visualId = 0;
@@ -92,9 +81,9 @@ VisualID QXlibEglIntegration::getCompatibleVisualId(Display *display, EGLDisplay
return visualId;
}
- int visualRedSize = countBits(chosenVisualInfo->red_mask);
- int visualGreenSize = countBits(chosenVisualInfo->green_mask);
- int visualBlueSize = countBits(chosenVisualInfo->blue_mask);
+ int visualRedSize = qPopulationCount(chosenVisualInfo->red_mask);
+ int visualGreenSize = qPopulationCount(chosenVisualInfo->green_mask);
+ int visualBlueSize = qPopulationCount(chosenVisualInfo->blue_mask);
int visualAlphaSize = -1; // Need XRender to tell us the alpha channel size
bool visualMatchesConfig = false;
diff --git a/src/platformsupport/eventdispatchers/eventdispatchers.pri b/src/platformsupport/eventdispatchers/eventdispatchers.pri
index 6e16a46b34..ec556486b1 100644
--- a/src/platformsupport/eventdispatchers/eventdispatchers.pri
+++ b/src/platformsupport/eventdispatchers/eventdispatchers.pri
@@ -8,6 +8,14 @@ HEADERS +=\
$$PWD/qgenericunixeventdispatcher_p.h\
}
+ios {
+OBJECTIVE_SOURCES +=\
+ $$PWD/qioseventdispatcher.mm
+
+HEADERS +=\
+ $$PWD/qioseventdispatcher_p.h
+}
+
contains(QT_CONFIG, glib) {
SOURCES +=$$PWD/qeventdispatcher_glib.cpp
HEADERS +=$$PWD/qeventdispatcher_glib_p.h
diff --git a/src/plugins/platforms/ios/qioseventdispatcher.mm b/src/platformsupport/eventdispatchers/qioseventdispatcher.mm
index e9bf039047..ab3036143d 100644
--- a/src/plugins/platforms/ios/qioseventdispatcher.mm
+++ b/src/platformsupport/eventdispatchers/qioseventdispatcher.mm
@@ -39,8 +39,7 @@
**
****************************************************************************/
-#include "qioseventdispatcher.h"
-#import "qiosapplicationdelegate.h"
+#include "qioseventdispatcher_p.h"
#include <qdebug.h>
#include <qpa/qwindowsysteminterface.h>
#include <QtCore/QThread>
@@ -118,7 +117,9 @@ void QIOSEventDispatcher::maybeStartCFRunLoopTimer()
m_runLoopTimerRef = CFRunLoopTimerCreate(0, ttf, oneyear, 0, 0, QIOSEventDispatcher::nonBlockingTimerRunLoopCallback, &info);
Q_ASSERT(m_runLoopTimerRef != 0);
- CFRunLoopAddTimer(CFRunLoopGetMain(), m_runLoopTimerRef, kCFRunLoopCommonModes);
+ CFRunLoopRef mainRunLoop = CFRunLoopGetMain();
+ CFRunLoopAddTimer(mainRunLoop, m_runLoopTimerRef, kCFRunLoopCommonModes);
+ CFRunLoopAddTimer(mainRunLoop, m_runLoopTimerRef, (CFStringRef) UITrackingRunLoopMode);
} else {
struct timespec tv;
// Calculate when the next timer should fire:
@@ -168,6 +169,7 @@ QIOSEventDispatcher::QIOSEventDispatcher(QObject *parent)
m_blockingTimerRunLoopSource = CFRunLoopSourceCreate(kCFAllocatorDefault, 0, &context);
Q_ASSERT(m_blockingTimerRunLoopSource);
CFRunLoopAddSource(mainRunLoop, m_blockingTimerRunLoopSource, kCFRunLoopCommonModes);
+ CFRunLoopAddSource(mainRunLoop, m_blockingTimerRunLoopSource, (CFStringRef) UITrackingRunLoopMode);
// source used to handle posted events:
context.perform = QIOSEventDispatcher::postedEventsRunLoopCallback;
@@ -184,7 +186,9 @@ QIOSEventDispatcher::~QIOSEventDispatcher()
qDeleteAll(m_timerInfoList);
maybeStopCFRunLoopTimer();
- CFRunLoopRemoveSource(CFRunLoopGetMain(), m_blockingTimerRunLoopSource, kCFRunLoopCommonModes);
+
+ CFRunLoopRemoveSource(mainRunLoop, m_blockingTimerRunLoopSource, kCFRunLoopCommonModes);
+ CFRunLoopRemoveSource(mainRunLoop, m_blockingTimerRunLoopSource, (CFStringRef) UITrackingRunLoopMode);
CFRelease(m_blockingTimerRunLoopSource);
m_cfSocketNotifier.removeSocketNotifiers();
@@ -199,14 +203,42 @@ bool QIOSEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags)
bool execFlagSet = (flags & QEventLoop::DialogExec) || (flags & QEventLoop::EventLoopExec);
bool useExecMode = execFlagSet && !excludeUserEvents;
+ CFTimeInterval distantFuture = CFTimeInterval(3600. * 24. * 365. * 10.);
+ SInt32 result;
+
if (useExecMode) {
- NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
- while ([runLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]] && !m_interrupted);
+ while (!m_interrupted) {
+ // Run a single pass on the runloop to unblock it
+ result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, true);
+
+ // Run the default runloop until interrupted (by Qt or UIKit)
+ if (result != kCFRunLoopRunFinished)
+ result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, distantFuture, false);
+
+ // App has quit or Qt has interrupted?
+ if (result == kCFRunLoopRunFinished || m_interrupted)
+ break;
+
+ // Runloop was interrupted by UIKit?
+ if (result == kCFRunLoopRunStopped && !m_interrupted) {
+ // Run runloop in UI tracking mode
+ if (CFRunLoopRunInMode((CFStringRef) UITrackingRunLoopMode,
+ distantFuture, false) == kCFRunLoopRunFinished)
+ break;
+ }
+ }
eventsProcessed = true;
} else {
if (!(flags & QEventLoop::WaitForMoreEvents))
wakeUp();
- eventsProcessed = [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
+
+ // Run runloop in default mode
+ result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, distantFuture, true);
+ if (result != kCFRunLoopRunFinished) {
+ // Run runloop in UI tracking mode
+ CFRunLoopRunInMode((CFStringRef) UITrackingRunLoopMode, distantFuture, false);
+ }
+ eventsProcessed = (result == kCFRunLoopRunHandledSource);
}
return eventsProcessed;
}
@@ -309,8 +341,9 @@ void QIOSEventDispatcher::wakeUp()
void QIOSEventDispatcher::interrupt()
{
- wakeUp();
+ // Stop the runloop, which will cause processEvents() to exit
m_interrupted = true;
+ CFRunLoopStop(CFRunLoopGetMain());
}
void QIOSEventDispatcher::flush()
diff --git a/src/plugins/platforms/ios/qioseventdispatcher.h b/src/platformsupport/eventdispatchers/qioseventdispatcher_p.h
index 53a75618ce..53a75618ce 100644
--- a/src/plugins/platforms/ios/qioseventdispatcher.h
+++ b/src/platformsupport/eventdispatchers/qioseventdispatcher_p.h
diff --git a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp
index afe634dc4b..6b8a82352d 100644
--- a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp
+++ b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp
@@ -317,8 +317,6 @@ static const char *getFcFamilyForStyleHint(const QFont::StyleHint style)
return stylehint;
}
-Q_GUI_EXPORT void qt_registerAliasToFontFamily(const QString &familyName, const QString &alias);
-
void QFontconfigDatabase::populateFontDatabase()
{
FcFontSet *fonts;
@@ -453,7 +451,7 @@ void QFontconfigDatabase::populateFontDatabase()
// qDebug() << familyName << (const char *)foundry_value << weight << style << &writingSystems << scalable << true << pixel_size;
for (int k = 1; FcPatternGetString(fonts->fonts[i], FC_FAMILY, k, &value) == FcResultMatch; ++k)
- qt_registerAliasToFontFamily(familyName, QString::fromUtf8((const char *)value));
+ QPlatformFontDatabase::registerAliasToFontFamily(familyName, QString::fromUtf8((const char *)value));
}
FcFontSetDestroy (fonts);
diff --git a/src/platformsupport/services/genericunix/qgenericunixservices.cpp b/src/platformsupport/services/genericunix/qgenericunixservices.cpp
index fedaa3a655..77ea0f1db8 100644
--- a/src/platformsupport/services/genericunix/qgenericunixservices.cpp
+++ b/src/platformsupport/services/genericunix/qgenericunixservices.cpp
@@ -54,16 +54,24 @@ enum { debug = 0 };
static inline QByteArray detectDesktopEnvironment()
{
- if (!qEnvironmentVariableIsEmpty("KDE_FULL_SESSION"))
- return QByteArray("KDE");
- // Check Unity first, whose older versions also have "GNOME_DESKTOP_SESSION_ID" set.
const QByteArray xdgCurrentDesktop = qgetenv("XDG_CURRENT_DESKTOP");
- if (xdgCurrentDesktop == "Unity")
- return QByteArrayLiteral("UNITY");
- // GNOME_DESKTOP_SESSION_ID is deprecated for some reason, but still check it
- if (qgetenv("DESKTOP_SESSION") == "gnome" || !qEnvironmentVariableIsEmpty("GNOME_DESKTOP_SESSION_ID"))
- return QByteArray("GNOME");
- return QByteArray("UNKNOWN");
+ if (!xdgCurrentDesktop.isEmpty())
+ return xdgCurrentDesktop.toUpper(); // KDE, GNOME, UNITY, LXDE, MATE, XFCE...
+
+ // Classic fallbacks
+ if (!qEnvironmentVariableIsEmpty("KDE_FULL_SESSION"))
+ return QByteArrayLiteral("KDE");
+ if (!qEnvironmentVariableIsEmpty("GNOME_DESKTOP_SESSION_ID"))
+ return QByteArrayLiteral("GNOME");
+
+ // Fallback to checking $DESKTOP_SESSION (unreliable)
+ const QByteArray desktopSession = qgetenv("DESKTOP_SESSION");
+ if (desktopSession == "gnome")
+ return QByteArrayLiteral("GNOME");
+ if (desktopSession == "xfce")
+ return QByteArrayLiteral("XFCE");
+
+ return QByteArrayLiteral("UNKNOWN");
}
static inline bool checkExecutable(const QString &candidate, QString *result)
diff --git a/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp b/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp
index fdd45a49c5..fb50230382 100644
--- a/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp
+++ b/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp
@@ -95,9 +95,13 @@ public:
QGenericUnixThemePrivate()
: QPlatformThemePrivate()
, systemFont(QLatin1String(defaultSystemFontNameC), defaultSystemFontSize)
- { }
+ , fixedFont(QStringLiteral("monospace"), systemFont.pointSize())
+ {
+ fixedFont.setStyleHint(QFont::TypeWriter);
+ }
const QFont systemFont;
+ QFont fixedFont;
};
QGenericUnixTheme::QGenericUnixTheme()
@@ -108,9 +112,14 @@ QGenericUnixTheme::QGenericUnixTheme()
const QFont *QGenericUnixTheme::font(Font type) const
{
Q_D(const QGenericUnixTheme);
- if (type == QPlatformTheme::SystemFont)
+ switch (type) {
+ case QPlatformTheme::SystemFont:
return &d->systemFont;
- return 0;
+ case QPlatformTheme::FixedFont:
+ return &d->fixedFont;
+ default:
+ return 0;
+ }
}
// Helper to return the icon theme paths from XDG.
@@ -240,11 +249,18 @@ void QKdeThemePrivate::refresh()
toolButtonStyle = Qt::ToolButtonTextUnderIcon;
}
- // Read system font, ignore 'fixed' 'smallestReadableFont'
- if (QFont *systemFont = readKdeFontSetting(kdeSettings, QStringLiteral("font"))) {
+ // Read system font, ignore 'smallestReadableFont'
+ if (QFont *systemFont = readKdeFontSetting(kdeSettings, QStringLiteral("font")))
resources.fonts[QPlatformTheme::SystemFont] = systemFont;
- } else {
+ else
resources.fonts[QPlatformTheme::SystemFont] = new QFont(QLatin1String(defaultSystemFontNameC), defaultSystemFontSize);
+
+ if (QFont *fixedFont = readKdeFontSetting(kdeSettings, QStringLiteral("fixed"))) {
+ resources.fonts[QPlatformTheme::FixedFont] = fixedFont;
+ } else {
+ fixedFont = new QFont(QLatin1String(defaultSystemFontNameC), defaultSystemFontSize);
+ fixedFont->setStyleHint(QFont::TypeWriter);
+ resources.fonts[QPlatformTheme::FixedFont] = fixedFont;
}
}
@@ -461,9 +477,13 @@ class QGnomeThemePrivate : public QPlatformThemePrivate
public:
QGnomeThemePrivate()
: systemFont(QLatin1Literal(defaultSystemFontNameC), defaultSystemFontSize)
- {}
+ , fixedFont(QStringLiteral("monospace"), systemFont.pointSize())
+ {
+ fixedFont.setStyleHint(QFont::TypeWriter);
+ }
const QFont systemFont;
+ QFont fixedFont;
};
QGnomeTheme::QGnomeTheme()
@@ -501,10 +521,14 @@ QVariant QGnomeTheme::themeHint(QPlatformTheme::ThemeHint hint) const
const QFont *QGnomeTheme::font(Font type) const
{
Q_D(const QGnomeTheme);
- if (type == QPlatformTheme::SystemFont)
- return &d->systemFont;
-
- return 0;
+ switch (type) {
+ case QPlatformTheme::SystemFont:
+ return &d->systemFont;
+ case QPlatformTheme::FixedFont:
+ return &d->fixedFont;
+ default:
+ return 0;
+ }
}
/*!
@@ -534,7 +558,11 @@ QStringList QGenericUnixTheme::themeNames()
#ifndef QT_NO_SETTINGS
result.push_back(QLatin1String(QKdeTheme::name));
#endif
- } else { // Gnome, Unity, other Gtk-based desktops like XFCE.
+ } else if (desktopEnvironment == QByteArrayLiteral("GNOME") ||
+ desktopEnvironment == QByteArrayLiteral("UNITY") ||
+ desktopEnvironment == QByteArrayLiteral("MATE") ||
+ desktopEnvironment == QByteArrayLiteral("XFCE") ||
+ desktopEnvironment == QByteArrayLiteral("LXDE")) { // Gtk-based desktops
// prefer the GTK2 theme implementation with native dialogs etc.
result.push_back(QStringLiteral("gtk2"));
// fallback to the generic Gnome theme if loading the GTK2 theme fails
diff --git a/src/plugins/bearer/blackberry/qbbengine.cpp b/src/plugins/bearer/blackberry/qbbengine.cpp
index ab1ba9aa19..37093a09ec 100644
--- a/src/plugins/bearer/blackberry/qbbengine.cpp
+++ b/src/plugins/bearer/blackberry/qbbengine.cpp
@@ -98,10 +98,9 @@ interfaceType(netstatus_interface_type_t type)
return QNetworkConfiguration::BearerBluetooth;
case NETSTATUS_INTERFACE_TYPE_CELLULAR:
- //### TODO not sure which BearerType would be the best
- //to return here. We need to be able to get more
- //information on the bearer type in order to return
- //the exact match.
+ // The exact bearer type is determined in QNetworkConfiguration
+ // at the time this info is queried, because opposed to the
+ // information here the type might change quickly.
return QNetworkConfiguration::Bearer2G;
case NETSTATUS_INTERFACE_TYPE_VPN:
diff --git a/src/plugins/platforms/android/src/androidjniinput.cpp b/src/plugins/platforms/android/src/androidjniinput.cpp
index 75cb617ca8..b31e74bb52 100644
--- a/src/plugins/platforms/android/src/androidjniinput.cpp
+++ b/src/plugins/platforms/android/src/androidjniinput.cpp
@@ -411,6 +411,24 @@ namespace QtAndroidInput
case 0x00000018:
return Qt::Key_VolumeUp;
+ case 0x000000b7: // KEYCODE_PROG_RED
+ return Qt::Key_Red;
+
+ case 0x000000b8: // KEYCODE_PROG_GREEN
+ return Qt::Key_Green;
+
+ case 0x000000b9: // KEYCODE_PROG_YELLOW
+ return Qt::Key_Yellow;
+
+ case 0x000000ba: // KEYCODE_PROG_BLUE
+ return Qt::Key_Blue;
+
+ case 0x000000a6: // KEYCODE_CHANNEL_UP
+ return Qt::Key_ChannelUp;
+
+ case 0x000000a7: // KEYCODE_CHANNEL_DOWN
+ return Qt::Key_ChannelDown;
+
case 0x00000000: // KEYCODE_UNKNOWN
case 0x00000011: // KEYCODE_STAR ?!?!?
case 0x00000012: // KEYCODE_POUND ?!?!?
diff --git a/src/plugins/platforms/android/src/qandroidplatformintegration.cpp b/src/plugins/platforms/android/src/qandroidplatformintegration.cpp
index 91ad2b368f..8899d98795 100644
--- a/src/plugins/platforms/android/src/qandroidplatformintegration.cpp
+++ b/src/plugins/platforms/android/src/qandroidplatformintegration.cpp
@@ -66,6 +66,7 @@
#endif
#include "qandroidplatformtheme.h"
+#include "qandroidsystemlocale.h"
QT_BEGIN_NAMESPACE
@@ -108,6 +109,8 @@ QAndroidPlatformIntegration::QAndroidPlatformIntegration(const QStringList &para
m_androidFDB = new QAndroidPlatformFontDatabase();
m_androidPlatformServices = new QAndroidPlatformServices();
m_androidPlatformClipboard = new QAndroidPlatformClipboard();
+
+ m_androidSystemLocale = new QAndroidSystemLocale;
}
bool QAndroidPlatformIntegration::hasCapability(Capability cap) const
@@ -183,6 +186,7 @@ QAndroidPlatformIntegration::~QAndroidPlatformIntegration()
{
delete m_androidPlatformNativeInterface;
delete m_androidFDB;
+ delete m_androidSystemLocale;
QtAndroid::setAndroidPlatformIntegration(NULL);
}
QPlatformFontDatabase *QAndroidPlatformIntegration::fontDatabase() const
diff --git a/src/plugins/platforms/android/src/qandroidplatformintegration.h b/src/plugins/platforms/android/src/qandroidplatformintegration.h
index 6cc191701d..346d0c0953 100644
--- a/src/plugins/platforms/android/src/qandroidplatformintegration.h
+++ b/src/plugins/platforms/android/src/qandroidplatformintegration.h
@@ -60,6 +60,7 @@ QT_BEGIN_NAMESPACE
class QDesktopWidget;
class QAndroidPlatformServices;
+class QAndroidSystemLocale;
#ifdef ANDROID_PLUGIN_OPENGL
class QAndroidOpenGLPlatformWindow;
@@ -154,6 +155,7 @@ private:
QAndroidPlatformNativeInterface *m_androidPlatformNativeInterface;
QAndroidPlatformServices *m_androidPlatformServices;
QPlatformClipboard *m_androidPlatformClipboard;
+ QAndroidSystemLocale *m_androidSystemLocale;
mutable QAndroidInputContext m_platformInputContext;
};
diff --git a/src/plugins/platforms/android/src/qandroidsystemlocale.cpp b/src/plugins/platforms/android/src/qandroidsystemlocale.cpp
new file mode 100644
index 0000000000..24ae503335
--- /dev/null
+++ b/src/plugins/platforms/android/src/qandroidsystemlocale.cpp
@@ -0,0 +1,179 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins 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 "qandroidsystemlocale.h"
+#include "androidjnimain.h"
+#include "private/qjniobject_p.h"
+#include "private/qjnihelpers_p.h"
+#include "qdatetime.h"
+#include "qstringlist.h"
+#include "qvariant.h"
+
+QT_BEGIN_NAMESPACE
+
+QAndroidSystemLocale::QAndroidSystemLocale() : m_locale(QLocale::C)
+{
+}
+
+void QAndroidSystemLocale::getLocaleFromJava() const
+{
+ QWriteLocker locker(&m_lock);
+
+ QJNILocalRef<jobject> javaLocaleRef;
+ QJNIObject javaActivity(QtAndroid::activity());
+ if (javaActivity.isValid()) {
+ QJNIObject resources(javaActivity.callObjectMethod<jobject>("getResources", "()Landroid/content/res/Resources;").object());
+ QJNIObject configuration(resources.callObjectMethod<jobject>("getConfiguration", "()Landroid/content/res/Configuration;").object());
+
+ javaLocaleRef = configuration.getObjectField<jobject>("locale", "Ljava/util/Locale;");
+ } else {
+ javaLocaleRef = QJNIObject::callStaticObjectMethod<jobject>("java/util/Locale", "getDefault", "()Ljava/util/Locale;");
+ }
+
+ QJNIObject javaLocaleObject(javaLocaleRef.object());
+ QString languageCode = qt_convertJString(javaLocaleObject.callObjectMethod<jstring>("getLanguage", "()Ljava/lang/String;").object());
+ QString countryCode = qt_convertJString(javaLocaleObject.callObjectMethod<jstring>("getCountry", "()Ljava/lang/String;").object());
+
+ m_locale = QLocale(languageCode + QLatin1Char('_') + countryCode);
+}
+
+QVariant QAndroidSystemLocale::query(QueryType type, QVariant in) const
+{
+ if (type == LocaleChanged) {
+ getLocaleFromJava();
+ return QVariant();
+ }
+
+ QReadLocker locker(&m_lock);
+
+ switch (type) {
+ case DecimalPoint:
+ return m_locale.decimalPoint();
+ case GroupSeparator:
+ return m_locale.groupSeparator();
+ case ZeroDigit:
+ return m_locale.zeroDigit();
+ case NegativeSign:
+ return m_locale.negativeSign();
+ case DateFormatLong:
+ return m_locale.dateFormat(QLocale::LongFormat);
+ case DateFormatShort:
+ return m_locale.dateFormat(QLocale::ShortFormat);
+ case TimeFormatLong:
+ return m_locale.timeFormat(QLocale::LongFormat);
+ case TimeFormatShort:
+ return m_locale.timeFormat(QLocale::ShortFormat);
+ case DayNameLong:
+ return m_locale.dayName(in.toInt(), QLocale::LongFormat);
+ case DayNameShort:
+ return m_locale.dayName(in.toInt(), QLocale::ShortFormat);
+ case MonthNameLong:
+ return m_locale.monthName(in.toInt(), QLocale::LongFormat);
+ case MonthNameShort:
+ return m_locale.monthName(in.toInt(), QLocale::ShortFormat);
+ case StandaloneMonthNameLong:
+ return m_locale.standaloneMonthName(in.toInt(), QLocale::LongFormat);
+ case StandaloneMonthNameShort:
+ return m_locale.standaloneMonthName(in.toInt(), QLocale::ShortFormat);
+ case DateToStringLong:
+ return m_locale.toString(in.toDate(), QLocale::LongFormat);
+ case DateToStringShort:
+ return m_locale.toString(in.toDate(), QLocale::ShortFormat);
+ case TimeToStringLong:
+ return m_locale.toString(in.toTime(), QLocale::LongFormat);
+ case TimeToStringShort:
+ return m_locale.toString(in.toTime(), QLocale::ShortFormat);
+ case DateTimeFormatLong:
+ return m_locale.dateTimeFormat(QLocale::LongFormat);
+ case DateTimeFormatShort:
+ return m_locale.dateTimeFormat(QLocale::ShortFormat);
+ case DateTimeToStringLong:
+ return m_locale.toString(in.toDateTime(), QLocale::LongFormat);
+ case DateTimeToStringShort:
+ return m_locale.toString(in.toDateTime(), QLocale::ShortFormat);
+ case PositiveSign:
+ return m_locale.positiveSign();
+ case AMText:
+ return m_locale.amText();
+ case PMText:
+ return m_locale.pmText();
+ case FirstDayOfWeek:
+ return m_locale.firstDayOfWeek();
+ case CurrencySymbol:
+ return m_locale .currencySymbol(QLocale::CurrencySymbolFormat(in.toUInt()));
+ case CurrencyToString: {
+ switch (in.type()) {
+ case QVariant::Int:
+ return m_locale .toCurrencyString(in.toInt());
+ case QVariant::UInt:
+ return m_locale .toCurrencyString(in.toUInt());
+ case QVariant::Double:
+ return m_locale .toCurrencyString(in.toDouble());
+ case QVariant::LongLong:
+ return m_locale .toCurrencyString(in.toLongLong());
+ case QVariant::ULongLong:
+ return m_locale .toCurrencyString(in.toULongLong());
+ default:
+ break;
+ }
+ return QString();
+ }
+ case StringToStandardQuotation:
+ return m_locale.quoteString(in.value<QStringRef>());
+ case StringToAlternateQuotation:
+ return m_locale.quoteString(in.value<QStringRef>(), QLocale::AlternateQuotation);
+ case ListToSeparatedString:
+ return m_locale.createSeparatedList(in.value<QStringList>());
+ case LocaleChanged:
+ Q_ASSERT_X(false, Q_FUNC_INFO, "This can't happen.");
+ default:
+ break;
+ }
+ return QVariant();
+}
+
+QLocale QAndroidSystemLocale::fallbackUiLocale() const
+{
+ QReadLocker locker(&m_lock);
+ return m_locale;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/kms/qkmsudevdrmhandler.h b/src/plugins/platforms/android/src/qandroidsystemlocale.h
index 4ceecb11a8..fc2f6fad98 100644
--- a/src/plugins/platforms/kms/qkmsudevdrmhandler.h
+++ b/src/plugins/platforms/android/src/qandroidsystemlocale.h
@@ -39,28 +39,29 @@
**
****************************************************************************/
-#ifndef QKMSUDEVDRMHANDLER_H
-#define QKMSUDEVDRMHANDLER_H
+#ifndef QANDROIDSYSTEMLOCALE_H
+#define QANDROIDSYSTEMLOCALE_H
-#include <QObject>
-
-#include <qkmsudevhandler.h>
+#include "private/qlocale_p.h"
+#include <QtCore/qreadwritelock.h>
QT_BEGIN_NAMESPACE
-class QKmsIntegration;
-
-class QKmsUdevDRMHandler : public QKmsUdevHandler
+class QAndroidSystemLocale : public QSystemLocale
{
public:
- QKmsUdevDRMHandler(QKmsIntegration *integration);
+ QAndroidSystemLocale();
- QObject *create(struct udev_device *device);
+ virtual QVariant query(QueryType type, QVariant in) const;
+ virtual QLocale fallbackUiLocale() const;
private:
- QKmsIntegration *m_integration;
+ void getLocaleFromJava() const;
+
+ mutable QLocale m_locale;
+ mutable QReadWriteLock m_lock;
};
QT_END_NAMESPACE
-#endif // QKMSUDEVDRMHANDLER_H
+#endif // QANDROIDSYSTEMLOCALE_H
diff --git a/src/plugins/platforms/android/src/src.pri b/src/plugins/platforms/android/src/src.pri
index 76539b50ab..0fd9ace1fc 100644
--- a/src/plugins/platforms/android/src/src.pri
+++ b/src/plugins/platforms/android/src/src.pri
@@ -23,7 +23,8 @@ SOURCES += $$PWD/androidplatformplugin.cpp \
$$PWD/qandroidplatformtheme.cpp \
$$PWD/qandroidplatformmenubar.cpp \
$$PWD/qandroidplatformmenu.cpp \
- $$PWD/qandroidplatformmenuitem.cpp
+ $$PWD/qandroidplatformmenuitem.cpp \
+ $$PWD/qandroidsystemlocale.cpp
HEADERS += $$PWD/qandroidplatformintegration.h \
@@ -39,7 +40,8 @@ HEADERS += $$PWD/qandroidplatformintegration.h \
$$PWD/qandroidplatformtheme.h \
$$PWD/qandroidplatformmenubar.h \
$$PWD/qandroidplatformmenu.h \
- $$PWD/qandroidplatformmenuitem.h
+ $$PWD/qandroidplatformmenuitem.h \
+ $$PWD/qandroidsystemlocale.h
#Non-standard install directory, QTBUG-29859
diff --git a/src/plugins/platforms/cocoa/qcocoaapplication.h b/src/plugins/platforms/cocoa/qcocoaapplication.h
index 2376b35501..ffb12ea846 100644
--- a/src/plugins/platforms/cocoa/qcocoaapplication.h
+++ b/src/plugins/platforms/cocoa/qcocoaapplication.h
@@ -89,8 +89,10 @@
Cocoa Application Categories
*/
#include "qglobal.h"
+#include "private/qcore_mac_p.h"
#import <AppKit/AppKit.h>
+
@class QT_MANGLE_NAMESPACE(QCocoaMenuLoader);
@interface NSApplication (QT_MANGLE_NAMESPACE(QApplicationIntegration))
@@ -106,6 +108,8 @@
}
@end
+QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSApplication);
+
QT_BEGIN_NAMESPACE
void qt_redirectNSApplicationSendEvent();
diff --git a/src/plugins/platforms/cocoa/qcocoaapplication.mm b/src/plugins/platforms/cocoa/qcocoaapplication.mm
index d962ef8f75..c293f4cd52 100644
--- a/src/plugins/platforms/cocoa/qcocoaapplication.mm
+++ b/src/plugins/platforms/cocoa/qcocoaapplication.mm
@@ -87,12 +87,12 @@ QT_USE_NAMESPACE
- (void)QT_MANGLE_NAMESPACE(qt_setDockMenu):(NSMenu *)newMenu
{
- [[QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) sharedDelegate] setDockMenu:newMenu];
+ [[QCocoaApplicationDelegate sharedDelegate] setDockMenu:newMenu];
}
- (QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *)QT_MANGLE_NAMESPACE(qt_qcocoamenuLoader)
{
- return [[QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) sharedDelegate] menuLoader];
+ return [[QCocoaApplicationDelegate sharedDelegate] menuLoader];
}
- (int)QT_MANGLE_NAMESPACE(qt_validModesForFontPanel):(NSFontPanel *)fontPanel
@@ -155,7 +155,7 @@ static const QByteArray q_macLocalEventType = QByteArrayLiteral("mac_generic_NSE
@end
-@implementation QT_MANGLE_NAMESPACE(QNSApplication)
+@implementation QNSApplication
- (void)qt_sendEvent_original:(NSEvent *)event
{
@@ -189,7 +189,7 @@ QT_BEGIN_NAMESPACE
void qt_redirectNSApplicationSendEvent()
{
- if ([NSApp isMemberOfClass:[QT_MANGLE_NAMESPACE(QNSApplication) class]]) {
+ if ([NSApp isMemberOfClass:[QNSApplication class]]) {
// No need to change implementation since Qt
// already controls a subclass of NSApplication
return;
@@ -202,7 +202,7 @@ void qt_redirectNSApplicationSendEvent()
qt_cocoa_change_implementation(
[NSApplication class],
@selector(sendEvent:),
- [QT_MANGLE_NAMESPACE(QNSApplication) class],
+ [QNSApplication class],
@selector(qt_sendEvent_replacement:),
@selector(qt_sendEvent_original:));
}
diff --git a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.h b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.h
index e44b2d1b6d..7f6c4224df 100644
--- a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.h
+++ b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.h
@@ -90,6 +90,7 @@
#import <Cocoa/Cocoa.h>
#include <qglobal.h>
+#include <private/qcore_mac_p.h>
@class QT_MANGLE_NAMESPACE(QCocoaMenuLoader);
@@ -108,3 +109,5 @@
- (void)getUrl:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor *)replyEvent;
- (void) removeAppleEventHandlers;
@end
+
+QT_NAMESPACE_ALIAS_OBJC_CLASS(QCocoaApplicationDelegate);
diff --git a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm
index 3ec6ad7a20..423d552627 100644
--- a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm
+++ b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm
@@ -88,14 +88,14 @@
QT_USE_NAMESPACE
-static QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) *sharedCocoaApplicationDelegate = nil;
+static QCocoaApplicationDelegate *sharedCocoaApplicationDelegate = nil;
static void cleanupCocoaApplicationDelegate()
{
[sharedCocoaApplicationDelegate release];
}
-@implementation QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate)
+@implementation QCocoaApplicationDelegate
- (id)init
{
@@ -144,7 +144,7 @@ static void cleanupCocoaApplicationDelegate()
return nil;
}
-+ (QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate)*)sharedDelegate
++ (QCocoaApplicationDelegate *)sharedDelegate
{
@synchronized(self) {
if (sharedCocoaApplicationDelegate == nil)
@@ -166,14 +166,14 @@ static void cleanupCocoaApplicationDelegate()
return [[dockMenu retain] autorelease];
}
-- (void)setMenuLoader:(QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *)menuLoader
+- (void)setMenuLoader:(QCocoaMenuLoader *)menuLoader
{
[menuLoader retain];
[qtMenuLoader release];
qtMenuLoader = menuLoader;
}
-- (QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *)menuLoader
+- (QCocoaMenuLoader *)menuLoader
{
return [[qtMenuLoader retain] autorelease];
}
@@ -183,7 +183,7 @@ static void cleanupCocoaApplicationDelegate()
[[NSApp mainMenu] cancelTracking];
bool handle_quit = true;
- NSMenuItem *quitMenuItem = [[[QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) sharedDelegate] menuLoader] quitMenuItem];
+ NSMenuItem *quitMenuItem = [[[QCocoaApplicationDelegate sharedDelegate] menuLoader] quitMenuItem];
if (!QGuiApplicationPrivate::instance()->modalWindowList.isEmpty()
&& [quitMenuItem isEnabled]) {
int visible = 0;
diff --git a/src/plugins/platforms/cocoa/qcocoacolordialoghelper.mm b/src/plugins/platforms/cocoa/qcocoacolordialoghelper.mm
index 3379a26650..d90d77ec1d 100644
--- a/src/plugins/platforms/cocoa/qcocoacolordialoghelper.mm
+++ b/src/plugins/platforms/cocoa/qcocoacolordialoghelper.mm
@@ -87,7 +87,9 @@ static NSButton *macCreateButton(const char *text, NSView *superview)
- (void)finishOffWithCode:(NSInteger)code;
@end
-@implementation QT_MANGLE_NAMESPACE(QNSColorPanelDelegate)
+QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSColorPanelDelegate);
+
+@implementation QNSColorPanelDelegate
- (id)init
{
@@ -308,12 +310,13 @@ static NSButton *macCreateButton(const char *text, NSView *superview)
// close down during the cleanup.
qApp->processEvents(QEventLoop::ExcludeUserInputEvents | QEventLoop::ExcludeSocketNotifiers);
[NSApp runModalForWindow:mColorPanel];
+ mDialogIsExecuting = false;
return (mResultCode == NSOKButton);
}
-- (QT_PREPEND_NAMESPACE(QPlatformDialogHelper::DialogCode))dialogResultCode
+- (QPlatformDialogHelper::DialogCode)dialogResultCode
{
- return (mResultCode == NSOKButton) ? QT_PREPEND_NAMESPACE(QPlatformDialogHelper::Accepted) : QT_PREPEND_NAMESPACE(QPlatformDialogHelper::Rejected);
+ return (mResultCode == NSOKButton) ? QPlatformDialogHelper::Accepted : QPlatformDialogHelper::Rejected;
}
- (BOOL)windowShouldClose:(id)window
diff --git a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.h b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.h
index 701e8e2dbf..8a8b1d946c 100644
--- a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.h
+++ b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.h
@@ -62,10 +62,10 @@ public:
bool show(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow *parent);
void hide();
- void setDirectory(const QString &directory);
- QString directory() const;
- void selectFile(const QString &filename);
- QStringList selectedFiles() const;
+ void setDirectory(const QUrl &directory) Q_DECL_OVERRIDE;
+ QUrl directory() const Q_DECL_OVERRIDE;
+ void selectFile(const QUrl &filename) Q_DECL_OVERRIDE;
+ QList<QUrl> selectedFiles() const Q_DECL_OVERRIDE;
void setFilter();
void selectNameFilter(const QString &filter);
QString selectedNameFilter() const;
diff --git a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm
index 76cd235514..b3bc4a8ebf 100644
--- a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm
+++ b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm
@@ -139,7 +139,9 @@ typedef QSharedPointer<QFileDialogOptions> SharedPointerFileDialogOptions;
@end
-@implementation QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate)
+QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSOpenSavePanelDelegate);
+
+@implementation QNSOpenSavePanelDelegate
- (id)initWithAcceptMode:
(const QString &)selectFile
@@ -148,7 +150,7 @@ typedef QSharedPointer<QFileDialogOptions> SharedPointerFileDialogOptions;
{
self = [super init];
mOptions = options;
- if (mOptions->acceptMode() == QT_PREPEND_NAMESPACE(QFileDialogOptions::AcceptOpen)){
+ if (mOptions->acceptMode() == QFileDialogOptions::AcceptOpen){
mOpenPanel = [NSOpenPanel openPanel];
mSavePanel = mOpenPanel;
} else {
@@ -234,7 +236,7 @@ static QString strippedText(QString s)
- (void)closePanel
{
- *mCurrentSelection = QT_PREPEND_NAMESPACE(QCFString::toQString)([[mSavePanel URL] path]).normalized(QString::NormalizationForm_C);
+ *mCurrentSelection = QCFString::toQString([[mSavePanel URL] path]).normalized(QString::NormalizationForm_C);
if ([mSavePanel respondsToSelector:@selector(close)])
[mSavePanel close];
if ([mSavePanel isSheet])
@@ -245,7 +247,7 @@ static QString strippedText(QString s)
{
if (mOpenPanel){
QFileInfo info(*mCurrentSelection);
- NSString *filepath = QT_PREPEND_NAMESPACE(QCFString::toNSString)(info.filePath());
+ NSString *filepath = QCFString::toNSString(info.filePath());
bool selectable = (mOptions->acceptMode() == QFileDialogOptions::AcceptSave)
|| [self panel:nil shouldShowFilename:filepath];
@@ -264,12 +266,12 @@ static QString strippedText(QString s)
- (BOOL)runApplicationModalPanel
{
QFileInfo info(*mCurrentSelection);
- NSString *filepath = QT_PREPEND_NAMESPACE(QCFString::toNSString)(info.filePath());
+ NSString *filepath = QCFString::toNSString(info.filePath());
bool selectable = (mOptions->acceptMode() == QFileDialogOptions::AcceptSave)
|| [self panel:nil shouldShowFilename:filepath];
[mSavePanel setDirectoryURL: [NSURL fileURLWithPath:mCurrentDir]];
- [mSavePanel setNameFieldStringValue:selectable ? QT_PREPEND_NAMESPACE(QCFString::toNSString)(info.fileName()) : @""];
+ [mSavePanel setNameFieldStringValue:selectable ? QCFString::toNSString(info.fileName()) : @""];
// Call processEvents in case the event dispatcher has been interrupted, and needs to do
// cleanup of modal sessions. Do this before showing the native dialog, otherwise it will
@@ -281,22 +283,22 @@ static QString strippedText(QString s)
return (mReturnCode == NSOKButton);
}
-- (QT_PREPEND_NAMESPACE(QPlatformDialogHelper::DialogCode))dialogResultCode
+- (QPlatformDialogHelper::DialogCode)dialogResultCode
{
- return (mReturnCode == NSOKButton) ? QT_PREPEND_NAMESPACE(QPlatformDialogHelper::Accepted) : QT_PREPEND_NAMESPACE(QPlatformDialogHelper::Rejected);
+ return (mReturnCode == NSOKButton) ? QPlatformDialogHelper::Accepted : QPlatformDialogHelper::Rejected;
}
- (void)showWindowModalSheet:(QWindow *)parent
{
QFileInfo info(*mCurrentSelection);
- NSString *filepath = QT_PREPEND_NAMESPACE(QCFString::toNSString)(info.filePath());
+ NSString *filepath = QCFString::toNSString(info.filePath());
bool selectable = (mOptions->acceptMode() == QFileDialogOptions::AcceptSave)
|| [self panel:nil shouldShowFilename:filepath];
[self updateProperties];
[mSavePanel setDirectoryURL: [NSURL fileURLWithPath:mCurrentDir]];
- [mSavePanel setNameFieldStringValue:selectable ? QT_PREPEND_NAMESPACE(QCFString::toNSString)(info.fileName()) : @""];
+ [mSavePanel setNameFieldStringValue:selectable ? QCFString::toNSString(info.fileName()) : @""];
NSWindow *nsparent = static_cast<NSWindow *>(qGuiApp->platformNativeInterface()->nativeResourceForWindow("nswindow", parent));
[mSavePanel beginSheetModalForWindow:nsparent completionHandler:^(NSInteger result){
@@ -322,8 +324,8 @@ static QString strippedText(QString s)
}
}
- QString qtFileName = QT_PREPEND_NAMESPACE(QCFString::toQString)(filename);
- QFileInfo info(qtFileName.normalized(QT_PREPEND_NAMESPACE(QString::NormalizationForm_C)));
+ QString qtFileName = QCFString::toQString(filename);
+ QFileInfo info(qtFileName.normalized(QString::NormalizationForm_C));
QString path = info.absolutePath();
if (mCachedEntries->directory() != path) {
mCachedEntries->updateDirCache(path);
@@ -363,7 +365,7 @@ static QString strippedText(QString s)
if (filters.size() > 0){
for (int i=0; i<filters.size(); ++i) {
QString filter = hideDetails ? [self removeExtensions:filters.at(i)] : filters.at(i);
- [mPopUpButton addItemWithTitle:QT_PREPEND_NAMESPACE(QCFString::toNSString)(filter)];
+ [mPopUpButton addItemWithTitle:QCFString::toNSString(filter)];
}
[mPopUpButton selectItemAtIndex:0];
[mSavePanel setAccessoryView:mAccessoryView];
@@ -391,18 +393,20 @@ static QString strippedText(QString s)
return mNameFilterDropDownList->value([mPopUpButton indexOfSelectedItem]);
}
-- (QStringList)selectedFiles
+- (QList<QUrl>)selectedFiles
{
if (mOpenPanel) {
- QStringList result;
+ QList<QUrl> result;
NSArray* array = [mOpenPanel URLs];
- for (NSUInteger i=0; i<[array count]; ++i)
- result << QCFString::toQString([[array objectAtIndex:i] path]).normalized(QString::NormalizationForm_C);
+ for (NSUInteger i=0; i<[array count]; ++i) {
+ QString path = QCFString::toQString([[array objectAtIndex:i] path]).normalized(QString::NormalizationForm_C);
+ result << QUrl::fromLocalFile(path);
+ }
return result;
} else {
- QStringList result;
- QString filename = QT_PREPEND_NAMESPACE(QCFString::toQString)([[mSavePanel URL] path]).normalized(QString::NormalizationForm_C);
- result << filename.remove(QLatin1String("___qt_very_unlikely_prefix_"));
+ QList<QUrl> result;
+ QString filename = QCFString::toQString([[mSavePanel URL] path]).normalized(QString::NormalizationForm_C);
+ result << QUrl::fromLocalFile(filename.remove(QLatin1String("___qt_very_unlikely_prefix_")));
return result;
}
}
@@ -412,18 +416,18 @@ static QString strippedText(QString s)
// Call this functions if mFileMode, mFileOptions,
// mNameFilterDropDownList or mQDirFilter changes.
// The savepanel does not contain the neccessary functions for this.
- const QT_PREPEND_NAMESPACE(QFileDialogOptions::FileMode) fileMode = mOptions->fileMode();
- bool chooseFilesOnly = fileMode == QT_PREPEND_NAMESPACE(QFileDialogOptions::ExistingFile)
- || fileMode == QT_PREPEND_NAMESPACE(QFileDialogOptions::ExistingFiles);
- bool chooseDirsOnly = fileMode == QT_PREPEND_NAMESPACE(QFileDialogOptions::Directory)
- || fileMode == QT_PREPEND_NAMESPACE(QFileDialogOptions::DirectoryOnly)
- || mOptions->testOption(QT_PREPEND_NAMESPACE(QFileDialogOptions::ShowDirsOnly));
+ const QFileDialogOptions::FileMode fileMode = mOptions->fileMode();
+ bool chooseFilesOnly = fileMode == QFileDialogOptions::ExistingFile
+ || fileMode == QFileDialogOptions::ExistingFiles;
+ bool chooseDirsOnly = fileMode == QFileDialogOptions::Directory
+ || fileMode == QFileDialogOptions::DirectoryOnly
+ || mOptions->testOption(QFileDialogOptions::ShowDirsOnly);
[mOpenPanel setCanChooseFiles:!chooseDirsOnly];
[mOpenPanel setCanChooseDirectories:!chooseFilesOnly];
- [mSavePanel setCanCreateDirectories:!(mOptions->testOption(QT_PREPEND_NAMESPACE(QFileDialogOptions::ReadOnly)))];
- [mOpenPanel setAllowsMultipleSelection:(fileMode == QT_PREPEND_NAMESPACE(QFileDialogOptions::ExistingFiles))];
- [mOpenPanel setResolvesAliases:!(mOptions->testOption(QT_PREPEND_NAMESPACE(QFileDialogOptions::DontResolveSymlinks)))];
+ [mSavePanel setCanCreateDirectories:!(mOptions->testOption(QFileDialogOptions::ReadOnly))];
+ [mOpenPanel setAllowsMultipleSelection:(fileMode == QFileDialogOptions::ExistingFiles)];
+ [mOpenPanel setResolvesAliases:!(mOptions->testOption(QFileDialogOptions::DontResolveSymlinks))];
[mOpenPanel setTitle:QCFString::toNSString(mOptions->windowTitle())];
[mSavePanel setTitle:QCFString::toNSString(mOptions->windowTitle())];
[mPopUpButton setHidden:chooseDirsOnly]; // TODO hide the whole sunken pane instead?
@@ -432,7 +436,7 @@ static QString strippedText(QString s)
const QString defaultSuffix = mOptions->defaultSuffix();
if (!ext.isEmpty() && !defaultSuffix.isEmpty())
ext.prepend(defaultSuffix);
- [mSavePanel setAllowedFileTypes:ext.isEmpty() ? nil : QT_PREPEND_NAMESPACE(qt_mac_QStringListToNSMutableArray(ext))];
+ [mSavePanel setAllowedFileTypes:ext.isEmpty() ? nil : qt_mac_QStringListToNSMutableArray(ext)];
if ([mSavePanel respondsToSelector:@selector(isVisible)] && [mSavePanel isVisible]) {
if ([mSavePanel respondsToSelector:@selector(validateVisibleColumns)])
@@ -444,7 +448,7 @@ static QString strippedText(QString s)
{
Q_UNUSED(sender);
if (mHelper) {
- QString selection = QT_PREPEND_NAMESPACE(QCFString::toQString([[mSavePanel URL] path]));
+ QString selection = QCFString::toQString([[mSavePanel URL] path]);
if (selection != mCurrentSelection) {
*mCurrentSelection = selection;
mHelper->QNSOpenSavePanelDelegate_selectionChanged(selection);
@@ -462,7 +466,7 @@ static QString strippedText(QString s)
[mCurrentDir release];
mCurrentDir = [path retain];
- mHelper->QNSOpenSavePanelDelegate_directoryEntered(QT_PREPEND_NAMESPACE(QCFString::toQString(mCurrentDir)));
+ mHelper->QNSOpenSavePanelDelegate_directoryEntered(QCFString::toQString(mCurrentDir));
}
/*
@@ -489,7 +493,7 @@ static QString strippedText(QString s)
- (QString)removeExtensions:(const QString &)filter
{
- QRegExp regExp(QT_PREPEND_NAMESPACE(QString::fromLatin1)(QT_PREPEND_NAMESPACE(QPlatformFileDialogHelper::filterRegExp)));
+ QRegExp regExp(QString::fromLatin1(QPlatformFileDialogHelper::filterRegExp));
if (regExp.indexIn(filter) != -1)
return regExp.cap(1).trimmed();
return filter;
@@ -525,7 +529,7 @@ static QString strippedText(QString s)
(filterToUse == -1 && currentFilter.startsWith(selectedFilter)))
filterToUse = i;
QString filter = hideDetails ? [self removeExtensions:currentFilter] : currentFilter;
- [mPopUpButton addItemWithTitle:QT_PREPEND_NAMESPACE(QCFString::toNSString)(filter)];
+ [mPopUpButton addItemWithTitle:QCFString::toNSString(filter)];
}
if (filterToUse != -1)
[mPopUpButton selectItemAtIndex:filterToUse];
@@ -563,13 +567,13 @@ QCocoaFileDialogHelper::~QCocoaFileDialogHelper()
if (!mDelegate)
return;
QCocoaAutoReleasePool pool;
- [reinterpret_cast<QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *>(mDelegate) release];
+ [reinterpret_cast<QNSOpenSavePanelDelegate *>(mDelegate) release];
mDelegate = 0;
}
void QCocoaFileDialogHelper::QNSOpenSavePanelDelegate_selectionChanged(const QString &newPath)
{
- emit currentChanged(newPath);
+ emit currentChanged(QUrl::fromLocalFile(newPath));
}
void QCocoaFileDialogHelper::QNSOpenSavePanelDelegate_panelClosed(bool accepted)
@@ -584,7 +588,7 @@ void QCocoaFileDialogHelper::QNSOpenSavePanelDelegate_panelClosed(bool accepted)
void QCocoaFileDialogHelper::QNSOpenSavePanelDelegate_directoryEntered(const QString &newDir)
{
// ### fixme: priv->setLastVisitedDirectory(newDir);
- emit directoryEntered(newDir);
+ emit directoryEntered(QUrl::fromLocalFile(newDir));
}
void QCocoaFileDialogHelper::QNSOpenSavePanelDelegate_filterSelected(int menuIndex)
@@ -596,43 +600,45 @@ void QCocoaFileDialogHelper::QNSOpenSavePanelDelegate_filterSelected(int menuInd
extern OSErr qt_mac_create_fsref(const QString &, FSRef *); // qglobal.cpp
extern void qt_mac_to_pascal_string(QString s, Str255 str, TextEncoding encoding=0, int len=-1); // qglobal.cpp
-void QCocoaFileDialogHelper::setDirectory(const QString &directory)
+void QCocoaFileDialogHelper::setDirectory(const QUrl &directory)
{
- QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *>(mDelegate);
+ QNSOpenSavePanelDelegate *delegate = static_cast<QNSOpenSavePanelDelegate *>(mDelegate);
if (delegate)
- [delegate->mSavePanel setDirectoryURL:[NSURL fileURLWithPath:QCFString::toNSString(directory)]];
+ [delegate->mSavePanel setDirectoryURL:[NSURL fileURLWithPath:QCFString::toNSString(directory.toLocalFile())]];
}
-QString QCocoaFileDialogHelper::directory() const
+QUrl QCocoaFileDialogHelper::directory() const
{
- QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *>(mDelegate);
- if (delegate)
- return QCFString::toQString([[delegate->mSavePanel directoryURL] path]).normalized(QString::NormalizationForm_C);
- return QString();
+ QNSOpenSavePanelDelegate *delegate = static_cast<QNSOpenSavePanelDelegate *>(mDelegate);
+ if (delegate) {
+ QString path = QCFString::toQString([[delegate->mSavePanel directoryURL] path]).normalized(QString::NormalizationForm_C);
+ return QUrl::fromLocalFile(path);
+ }
+ return QUrl();
}
-void QCocoaFileDialogHelper::selectFile(const QString &filename)
+void QCocoaFileDialogHelper::selectFile(const QUrl &filename)
{
- QString filePath = filename;
+ QString filePath = filename.toLocalFile();
if (QDir::isRelativePath(filePath))
- filePath = QFileInfo(directory(), filePath).filePath();
+ filePath = QFileInfo(directory().toLocalFile(), filePath).filePath();
// There seems to no way to select a file once the dialog is running.
// So do the next best thing, set the file's directory:
setDirectory(QFileInfo(filePath).absolutePath());
}
-QStringList QCocoaFileDialogHelper::selectedFiles() const
+QList<QUrl> QCocoaFileDialogHelper::selectedFiles() const
{
- QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *>(mDelegate);
+ QNSOpenSavePanelDelegate *delegate = static_cast<QNSOpenSavePanelDelegate *>(mDelegate);
if (delegate)
return [delegate selectedFiles];
- return QStringList();
+ return QList<QUrl>();
}
void QCocoaFileDialogHelper::setFilter()
{
- QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *>(mDelegate);
+ QNSOpenSavePanelDelegate *delegate = static_cast<QNSOpenSavePanelDelegate *>(mDelegate);
if (!delegate)
return;
const SharedPointerFileDialogOptions &opts = options();
@@ -651,7 +657,7 @@ void QCocoaFileDialogHelper::selectNameFilter(const QString &filter)
return;
const int index = options()->nameFilters().indexOf(filter);
if (index != -1) {
- QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *>(mDelegate);
+ QNSOpenSavePanelDelegate *delegate = static_cast<QNSOpenSavePanelDelegate *>(mDelegate);
if (!delegate)
return;
[delegate->mPopUpButton selectItemAtIndex:index];
@@ -661,7 +667,7 @@ void QCocoaFileDialogHelper::selectNameFilter(const QString &filter)
QString QCocoaFileDialogHelper::selectedNameFilter() const
{
- QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *>(mDelegate);
+ QNSOpenSavePanelDelegate *delegate = static_cast<QNSOpenSavePanelDelegate *>(mDelegate);
if (!delegate)
return QString();
int index = [delegate->mPopUpButton indexOfSelectedItem];
@@ -695,11 +701,11 @@ void QCocoaFileDialogHelper::createNSOpenSavePanelDelegate()
return;
QCocoaAutoReleasePool pool;
const SharedPointerFileDialogOptions &opts = options();
- const QStringList selectedFiles = opts->initiallySelectedFiles();
- const QString directory = opts->initialDirectory();
+ const QList<QUrl> selectedFiles = opts->initiallySelectedFiles();
+ const QUrl directory = opts->initialDirectory();
const bool selectDir = selectedFiles.isEmpty();
- QString selection(selectDir ? directory : selectedFiles.front());
- QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *delegate = [[QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) alloc]
+ QString selection(selectDir ? directory.toLocalFile() : selectedFiles.front().toLocalFile());
+ QNSOpenSavePanelDelegate *delegate = [[QNSOpenSavePanelDelegate alloc]
initWithAcceptMode:
selection
options:opts
@@ -711,7 +717,7 @@ void QCocoaFileDialogHelper::createNSOpenSavePanelDelegate()
bool QCocoaFileDialogHelper::showCocoaFilePanel(Qt::WindowModality windowModality, QWindow *parent)
{
createNSOpenSavePanelDelegate();
- QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *>(mDelegate);
+ QNSOpenSavePanelDelegate *delegate = static_cast<QNSOpenSavePanelDelegate *>(mDelegate);
if (!delegate)
return false;
if (windowModality == Qt::NonModal)
@@ -729,7 +735,7 @@ bool QCocoaFileDialogHelper::hideCocoaFilePanel()
// open regarding whether or not to go native:
return false;
} else {
- QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *>(mDelegate);
+ QNSOpenSavePanelDelegate *delegate = static_cast<QNSOpenSavePanelDelegate *>(mDelegate);
[delegate closePanel];
// Even when we hide it, we are still using a
// native dialog, so return true:
@@ -744,7 +750,7 @@ void QCocoaFileDialogHelper::exec()
// yet been reactivated (regardless if [NSApp run] is still on the stack)),
// showing a native modal dialog will fail.
QCocoaAutoReleasePool pool;
- QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *>(mDelegate);
+ QNSOpenSavePanelDelegate *delegate = static_cast<QNSOpenSavePanelDelegate *>(mDelegate);
if ([delegate runApplicationModalPanel])
emit accept();
else
diff --git a/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm b/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm
index a70ba3749f..13b4085252 100644
--- a/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm
+++ b/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm
@@ -128,7 +128,9 @@ static QFont qfontForCocoaFont(NSFont *cocoaFont, const QFont &resolveFont)
- (void)finishOffWithCode:(NSInteger)code;
@end
-@implementation QT_MANGLE_NAMESPACE(QNSFontPanelDelegate)
+QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSFontPanelDelegate);
+
+@implementation QNSFontPanelDelegate
- (id)initWithDialogHelper:
(QCocoaFontDialogHelper *)helper
@@ -310,9 +312,9 @@ static QFont qfontForCocoaFont(NSFont *cocoaFont, const QFont &resolveFont)
return (mResultCode == NSOKButton);
}
-- (QT_PREPEND_NAMESPACE(QPlatformDialogHelper::DialogCode))dialogResultCode
+- (QPlatformDialogHelper::DialogCode)dialogResultCode
{
- return (mResultCode == NSOKButton) ? QT_PREPEND_NAMESPACE(QPlatformDialogHelper::Accepted) : QT_PREPEND_NAMESPACE(QPlatformDialogHelper::Rejected);
+ return (mResultCode == NSOKButton) ? QPlatformDialogHelper::Accepted : QPlatformDialogHelper::Rejected;
}
- (BOOL)windowShouldClose:(id)window
@@ -368,7 +370,7 @@ QCocoaFontDialogHelper::~QCocoaFontDialogHelper()
{
if (!mDelegate)
return;
- [reinterpret_cast<QT_MANGLE_NAMESPACE(QNSFontPanelDelegate) *>(mDelegate) release];
+ [reinterpret_cast<QNSFontPanelDelegate *>(mDelegate) release];
mDelegate = 0;
}
@@ -378,7 +380,7 @@ void QCocoaFontDialogHelper::exec()
// QEventLoop has been interrupted, and the second-most event loop has not
// yet been reactivated (regardless if [NSApp run] is still on the stack)),
// showing a native modal dialog will fail.
- QT_MANGLE_NAMESPACE(QNSFontPanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSFontPanelDelegate) *>(mDelegate);
+ QNSFontPanelDelegate *delegate = static_cast<QNSFontPanelDelegate *>(mDelegate);
if ([delegate runApplicationModalPanel])
emit accept();
else
@@ -398,7 +400,7 @@ void QCocoaFontDialogHelper::hide()
{
if (!mDelegate)
return;
- [reinterpret_cast<QT_MANGLE_NAMESPACE(QNSFontPanelDelegate) *>(mDelegate)->mFontPanel close];
+ [reinterpret_cast<QNSFontPanelDelegate *>(mDelegate)->mFontPanel close];
}
void QCocoaFontDialogHelper::setCurrentFont(const QFont &font)
@@ -426,14 +428,14 @@ void QCocoaFontDialogHelper::setCurrentFont(const QFont &font)
createNSFontPanelDelegate();
[mgr setSelectedFont:const_cast<NSFont *>(nsFont) isMultiple:NO];
- static_cast<QT_MANGLE_NAMESPACE(QNSFontPanelDelegate) *>(mDelegate)->mQtFont = font;
+ static_cast<QNSFontPanelDelegate *>(mDelegate)->mQtFont = font;
}
QFont QCocoaFontDialogHelper::currentFont() const
{
if (!mDelegate)
return QFont();
- return reinterpret_cast<QT_MANGLE_NAMESPACE(QNSFontPanelDelegate) *>(mDelegate)->mQtFont;
+ return reinterpret_cast<QNSFontPanelDelegate *>(mDelegate)->mQtFont;
}
void QCocoaFontDialogHelper::createNSFontPanelDelegate()
@@ -441,7 +443,7 @@ void QCocoaFontDialogHelper::createNSFontPanelDelegate()
if (mDelegate)
return;
- QT_MANGLE_NAMESPACE(QNSFontPanelDelegate) *delegate = [[QT_MANGLE_NAMESPACE(QNSFontPanelDelegate) alloc]
+ QNSFontPanelDelegate *delegate = [[QNSFontPanelDelegate alloc]
initWithDialogHelper:this];
mDelegate = delegate;
@@ -451,7 +453,7 @@ bool QCocoaFontDialogHelper::showCocoaFontPanel(Qt::WindowModality windowModalit
{
Q_UNUSED(parent);
createNSFontPanelDelegate();
- QT_MANGLE_NAMESPACE(QNSFontPanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSFontPanelDelegate) *>(mDelegate);
+ QNSFontPanelDelegate *delegate = static_cast<QNSFontPanelDelegate *>(mDelegate);
if (windowModality == Qt::NonModal)
[delegate showModelessPanel];
// no need to show a Qt::ApplicationModal dialog here, since it will be done in _q_platformRunNativeAppModalPanel()
@@ -463,7 +465,7 @@ bool QCocoaFontDialogHelper::hideCocoaFontPanel()
if (!mDelegate){
return false;
} else {
- QT_MANGLE_NAMESPACE(QNSFontPanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSFontPanelDelegate) *>(mDelegate);
+ QNSFontPanelDelegate *delegate = static_cast<QNSFontPanelDelegate *>(mDelegate);
[delegate closePanel];
return true;
}
diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.mm b/src/plugins/platforms/cocoa/qcocoahelpers.mm
index 3ade0a2a45..3be294de7e 100644
--- a/src/plugins/platforms/cocoa/qcocoahelpers.mm
+++ b/src/plugins/platforms/cocoa/qcocoahelpers.mm
@@ -508,7 +508,6 @@ CGColorSpaceRef qt_mac_displayColorSpace(const QWidget *widget)
CGColorSpaceRef colorSpace;
CGDirectDisplayID displayID;
- CMProfileRef displayProfile = 0;
if (widget == 0) {
displayID = CGMainDisplayID();
} else {
@@ -526,18 +525,11 @@ CGColorSpaceRef qt_mac_displayColorSpace(const QWidget *widget)
if ((colorSpace = m_displayColorSpaceHash.value(displayID)))
return colorSpace;
- CMError err = CMGetProfileByAVID((CMDisplayIDType)displayID, &displayProfile);
- if (err == noErr) {
- colorSpace = CGColorSpaceCreateWithPlatformColorSpace(displayProfile);
- } else if (widget) {
- return qt_mac_displayColorSpace(0); // fall back on main display
- }
-
+ colorSpace = CGDisplayCopyColorSpace(displayID);
if (colorSpace == 0)
colorSpace = CGColorSpaceCreateDeviceRGB();
m_displayColorSpaceHash.insert(displayID, colorSpace);
- CMCloseProfile(displayProfile);
if (!m_postRoutineRegistered) {
m_postRoutineRegistered = true;
void qt_mac_cleanUpMacColorSpaces();
@@ -810,20 +802,7 @@ CGImageRef qt_mac_toCGImage(const QImage &qImage, bool isMask, uchar **dataCopy)
NULL,
false);
} else {
- // Try get a device color space. Using the device color space means
- // that the CGImage can be drawn to screen without per-pixel color
- // space conversion, at the cost of less color accuracy.
- CGColorSpaceRef cgColourSpaceRef = 0;
- CMProfileRef sysProfile;
- if (CMGetSystemProfile(&sysProfile) == noErr)
- {
- cgColourSpaceRef = CGColorSpaceCreateWithPlatformColorSpace(sysProfile);
- CMCloseProfile(sysProfile);
- }
-
- // Fall back to Generic RGB if a profile was not found.
- if (!cgColourSpaceRef)
- cgColourSpaceRef = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
+ CGColorSpaceRef cgColourSpaceRef = qt_mac_displayColorSpace(0);
// Create a CGBitmapInfo contiaining the image format.
// Support the 8-bit per component (A)RGB formats.
@@ -857,7 +836,6 @@ CGImageRef qt_mac_toCGImage(const QImage &qImage, bool isMask, uchar **dataCopy)
NULL,
false,
kCGRenderingIntentDefault);
- CGColorSpaceRelease(cgColourSpaceRef);
}
CGDataProviderRelease(cgDataProviderRef);
return cgImage;
diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm
index fad743439e..6d1882f622 100644
--- a/src/plugins/platforms/cocoa/qcocoaintegration.mm
+++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm
@@ -232,7 +232,7 @@ QCocoaIntegration::QCocoaIntegration()
qApp->setAttribute(Qt::AA_DontUseNativeMenuBar, false);
- NSApplication *cocoaApplication = [QT_MANGLE_NAMESPACE(QNSApplication) sharedApplication];
+ NSApplication *cocoaApplication = [QNSApplication sharedApplication];
qt_redirectNSApplicationSendEvent();
if (qEnvironmentVariableIsEmpty("QT_MAC_DISABLE_FOREGROUND_APPLICATION_TRANSFORM")) {
@@ -256,12 +256,12 @@ QCocoaIntegration::QCocoaIntegration()
if (!QCoreApplication::testAttribute(Qt::AA_MacPluginApplication)) {
// Set app delegate, link to the current delegate (if any)
- QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) *newDelegate = [QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) sharedDelegate];
+ QCocoaApplicationDelegate *newDelegate = [QCocoaApplicationDelegate sharedDelegate];
[newDelegate setReflectionDelegate:[cocoaApplication delegate]];
[cocoaApplication setDelegate:newDelegate];
// Load the application menu. This menu contains Preferences, Hide, Quit.
- QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *qtMenuLoader = [[QT_MANGLE_NAMESPACE(QCocoaMenuLoader) alloc] init];
+ QCocoaMenuLoader *qtMenuLoader = [[QCocoaMenuLoader alloc] init];
qt_mac_loadMenuNib(qtMenuLoader);
[cocoaApplication setMenu:[qtMenuLoader menu]];
[newDelegate setMenuLoader:qtMenuLoader];
@@ -279,7 +279,7 @@ QCocoaIntegration::~QCocoaIntegration()
QCocoaAutoReleasePool pool;
if (!QCoreApplication::testAttribute(Qt::AA_MacPluginApplication)) {
// remove the apple event handlers installed by QCocoaApplicationDelegate
- QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) *delegate = [QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) sharedDelegate];
+ QCocoaApplicationDelegate *delegate = [QCocoaApplicationDelegate sharedDelegate];
[delegate removeAppleEventHandlers];
// reset the application delegate
[[NSApplication sharedApplication] setDelegate: 0];
diff --git a/src/plugins/platforms/cocoa/qcocoamenu.mm b/src/plugins/platforms/cocoa/qcocoamenu.mm
index bd406ee176..8c4325a775 100644
--- a/src/plugins/platforms/cocoa/qcocoamenu.mm
+++ b/src/plugins/platforms/cocoa/qcocoamenu.mm
@@ -74,7 +74,7 @@ NSString *qt_mac_removePrivateUnicode(NSString* string)
return string;
}
-static inline QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *getMenuLoader()
+static inline QCocoaMenuLoader *getMenuLoader()
{
return [NSApp QT_MANGLE_NAMESPACE(qt_qcocoamenuLoader)];
}
@@ -87,7 +87,9 @@ static inline QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *getMenuLoader()
@end
-@implementation QT_MANGLE_NAMESPACE(QCocoaMenuDelegate)
+QT_NAMESPACE_ALIAS_OBJC_CLASS(QCocoaMenuDelegate);
+
+@implementation QCocoaMenuDelegate
- (id) initWithMenu:(QCocoaMenu*) m
{
@@ -219,11 +221,11 @@ QCocoaMenu::QCocoaMenu() :
m_tag(0),
m_menuBar(0)
{
- m_delegate = [[QT_MANGLE_NAMESPACE(QCocoaMenuDelegate) alloc] initWithMenu:this];
+ m_delegate = [[QCocoaMenuDelegate alloc] initWithMenu:this];
m_nativeItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""];
m_nativeMenu = [[NSMenu alloc] initWithTitle:@"Untitled"];
[m_nativeMenu setAutoenablesItems:YES];
- m_nativeMenu.delegate = (QT_MANGLE_NAMESPACE(QCocoaMenuDelegate) *) m_delegate;
+ m_nativeMenu.delegate = (QCocoaMenuDelegate *) m_delegate;
[m_nativeItem setSubmenu:m_nativeMenu];
}
diff --git a/src/plugins/platforms/cocoa/qcocoamenubar.mm b/src/plugins/platforms/cocoa/qcocoamenubar.mm
index 8d1ca88b8e..da2704f19c 100644
--- a/src/plugins/platforms/cocoa/qcocoamenubar.mm
+++ b/src/plugins/platforms/cocoa/qcocoamenubar.mm
@@ -52,7 +52,7 @@
static QList<QCocoaMenuBar*> static_menubars;
-static inline QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *getMenuLoader()
+static inline QCocoaMenuLoader *getMenuLoader()
{
return [NSApp QT_MANGLE_NAMESPACE(qt_qcocoamenuLoader)];
}
@@ -238,7 +238,7 @@ void QCocoaMenuBar::updateMenuBarImmediately()
}
}
- QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *loader = getMenuLoader();
+ QCocoaMenuLoader *loader = getMenuLoader();
[loader ensureAppMenuInMenu:mb->nsMenu()];
NSMutableSet *mergedItems = [[NSMutableSet setWithCapacity:0] retain];
diff --git a/src/plugins/platforms/cocoa/qcocoamenuitem.mm b/src/plugins/platforms/cocoa/qcocoamenuitem.mm
index 6d8174c667..013f9931ff 100644
--- a/src/plugins/platforms/cocoa/qcocoamenuitem.mm
+++ b/src/plugins/platforms/cocoa/qcocoamenuitem.mm
@@ -52,7 +52,7 @@
#include <QtCore/QDebug>
-static inline QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *getMenuLoader()
+static inline QCocoaMenuLoader *getMenuLoader()
{
return [NSApp QT_MANGLE_NAMESPACE(qt_qcocoamenuLoader)];
}
@@ -199,7 +199,7 @@ NSMenuItem *QCocoaMenuItem::sync()
if ((m_role != NoRole && !m_textSynced) || m_merged) {
NSMenuItem *mergeItem = nil;
- QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *loader = getMenuLoader();
+ QCocoaMenuLoader *loader = getMenuLoader();
switch (m_role) {
case ApplicationSpecificRole:
mergeItem = [loader appSpecificMenuItem:reinterpret_cast<NSInteger>(this)];
@@ -326,7 +326,7 @@ QT_END_NAMESPACE
QString QCocoaMenuItem::mergeText()
{
- QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *loader = getMenuLoader();
+ QCocoaMenuLoader *loader = getMenuLoader();
if (m_native == [loader aboutMenuItem]) {
return qt_mac_applicationmenu_string(6).arg(qt_mac_applicationName());
} else if (m_native== [loader aboutQtMenuItem]) {
@@ -344,7 +344,7 @@ QString QCocoaMenuItem::mergeText()
QKeySequence QCocoaMenuItem::mergeAccel()
{
- QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *loader = getMenuLoader();
+ QCocoaMenuLoader *loader = getMenuLoader();
if (m_native == [loader preferencesMenuItem])
return QKeySequence(QKeySequence::Preferences);
else if (m_native == [loader quitMenuItem])
diff --git a/src/plugins/platforms/cocoa/qcocoamenuloader.h b/src/plugins/platforms/cocoa/qcocoamenuloader.h
index a45ec0fa89..e07da39995 100644
--- a/src/plugins/platforms/cocoa/qcocoamenuloader.h
+++ b/src/plugins/platforms/cocoa/qcocoamenuloader.h
@@ -92,9 +92,11 @@
- (NSArray *)mergeable;
@end
+QT_NAMESPACE_ALIAS_OBJC_CLASS(QCocoaMenuLoader);
+
QT_BEGIN_NAMESPACE
-void qt_mac_loadMenuNib(QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *qtMenuLoader);
+void qt_mac_loadMenuNib(QCocoaMenuLoader *qtMenuLoader);
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/cocoa/qcocoamenuloader.mm b/src/plugins/platforms/cocoa/qcocoamenuloader.mm
index 62b722d2d2..29fc0fb674 100644
--- a/src/plugins/platforms/cocoa/qcocoamenuloader.mm
+++ b/src/plugins/platforms/cocoa/qcocoamenuloader.mm
@@ -69,7 +69,7 @@ QT_BEGIN_NAMESPACE
and written to QDir::temp() before loading. (Earlier Qt versions used
to require having the nib file in the Qt GUI framework.)
*/
-void qt_mac_loadMenuNib(QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *qtMenuLoader)
+void qt_mac_loadMenuNib(QCocoaMenuLoader *qtMenuLoader)
{
// Create qt_menu.nib dir in temp.
QDir temp = QDir::temp();
@@ -106,7 +106,7 @@ void qt_mac_loadMenuNib(QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *qtMenuLoader)
QT_END_NAMESPACE
-@implementation QT_MANGLE_NAMESPACE(QCocoaMenuLoader)
+@implementation QCocoaMenuLoader
- (void)awakeFromNib
{
diff --git a/src/plugins/platforms/cocoa/qcocoaservices.mm b/src/plugins/platforms/cocoa/qcocoaservices.mm
index e4cec8c5f8..de4c688b71 100644
--- a/src/plugins/platforms/cocoa/qcocoaservices.mm
+++ b/src/plugins/platforms/cocoa/qcocoaservices.mm
@@ -55,7 +55,7 @@ bool QCocoaServices::openUrl(const QUrl &url)
const QString scheme = url.scheme();
if (scheme.isEmpty())
return openDocument(url);
- return [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:QT_PREPEND_NAMESPACE(QCFString::toNSString)(url.toString(QUrl::FullyEncoded))]];
+ return [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:QCFString::toNSString(url.toString(QUrl::FullyEncoded))]];
}
bool QCocoaServices::openDocument(const QUrl &url)
@@ -63,7 +63,7 @@ bool QCocoaServices::openDocument(const QUrl &url)
if (!url.isValid())
return false;
- return [[NSWorkspace sharedWorkspace] openFile:QT_PREPEND_NAMESPACE(QCFString::toNSString)(url.toLocalFile())];
+ return [[NSWorkspace sharedWorkspace] openFile:QCFString::toNSString(url.toLocalFile())];
}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/cocoa/qcocoasystemsettings.mm b/src/plugins/platforms/cocoa/qcocoasystemsettings.mm
index af817bd4c5..194394d11a 100644
--- a/src/plugins/platforms/cocoa/qcocoasystemsettings.mm
+++ b/src/plugins/platforms/cocoa/qcocoasystemsettings.mm
@@ -264,6 +264,10 @@ QHash<QPlatformTheme::Font, QFont *> qt_mac_createRoleFonts()
fonts.insert(QPlatformTheme::SmallFont, qt_mac_qfontForThemeFont(kThemeSmallSystemFont));
fonts.insert(QPlatformTheme::MiniFont, qt_mac_qfontForThemeFont(kThemeMiniSystemFont));
+ QFont* fixedFont = new QFont(QStringLiteral("Monaco"), fonts[QPlatformTheme::SystemFont]->pointSize());
+ fixedFont->setStyleHint(QFont::TypeWriter);
+ fonts.insert(QPlatformTheme::FixedFont, fixedFont);
+
return fonts;
}
diff --git a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm
index 99f533b33a..83c960d931 100755
--- a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm
+++ b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm
@@ -135,12 +135,16 @@ QT_USE_NAMESPACE
-(id)initWithQMenu:(QPlatformMenu*)qmenu;
@end
+QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSStatusItem);
+QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSImageView);
+QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSMenu);
+
QT_BEGIN_NAMESPACE
class QSystemTrayIconSys
{
public:
QSystemTrayIconSys(QCocoaSystemTrayIcon *sys) {
- item = [[QT_MANGLE_NAMESPACE(QNSStatusItem) alloc] initWithSysTray:sys];
+ item = [[QNSStatusItem alloc] initWithSysTray:sys];
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_8
if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_8) {
[[NSUserNotificationCenter defaultUserNotificationCenter] setDelegate:item];
@@ -156,7 +160,7 @@ public:
#endif
[item release];
}
- QT_MANGLE_NAMESPACE(QNSStatusItem) *item;
+ QNSStatusItem *item;
};
void QCocoaSystemTrayIcon::init()
@@ -310,8 +314,8 @@ QT_END_NAMESPACE
@implementation NSStatusItem (Qt)
@end
-@implementation QT_MANGLE_NAMESPACE(QNSImageView)
--(id)initWithParent:(QT_MANGLE_NAMESPACE(QNSStatusItem)*)myParent {
+@implementation QNSImageView
+-(id)initWithParent:(QNSStatusItem*)myParent {
self = [super init];
parent = myParent;
down = NO;
@@ -406,7 +410,7 @@ QT_END_NAMESPACE
}
@end
-@implementation QT_MANGLE_NAMESPACE(QNSStatusItem)
+@implementation QNSStatusItem
-(id)initWithSysTray:(QCocoaSystemTrayIcon *)sys
{
@@ -416,7 +420,7 @@ QT_END_NAMESPACE
menu = 0;
menuVisible = false;
systray = sys;
- imageCell = [[QT_MANGLE_NAMESPACE(QNSImageView) alloc] initWithParent:self];
+ imageCell = [[QNSImageView alloc] initWithParent:self];
[item setView: imageCell];
}
return self;
@@ -494,7 +498,7 @@ private:
QSystemTrayIconQMenu();
};
-@implementation QT_MANGLE_NAMESPACE(QNSMenu)
+@implementation QNSMenu
-(id)initWithQMenu:(QPlatformMenu*)qm {
self = [super init];
if (self) {
diff --git a/src/plugins/platforms/cocoa/qcocoatheme.h b/src/plugins/platforms/cocoa/qcocoatheme.h
index cac059763d..e4237c9b3e 100644
--- a/src/plugins/platforms/cocoa/qcocoatheme.h
+++ b/src/plugins/platforms/cocoa/qcocoatheme.h
@@ -68,7 +68,9 @@ public:
const QPalette *palette(Palette type = SystemPalette) const;
const QFont *font(Font type = SystemFont) const;
QPixmap standardPixmap(StandardPixmap sp, const QSizeF &size) const;
- QPixmap fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &size) const;
+ QPixmap fileIconPixmap(const QFileInfo &fileInfo,
+ const QSizeF &size,
+ QPlatformTheme::IconOptions options = 0) const;
QVariant themeHint(ThemeHint hint) const;
diff --git a/src/plugins/platforms/cocoa/qcocoatheme.mm b/src/plugins/platforms/cocoa/qcocoatheme.mm
index 13a387a0a3..1484ae2ba3 100644
--- a/src/plugins/platforms/cocoa/qcocoatheme.mm
+++ b/src/plugins/platforms/cocoa/qcocoatheme.mm
@@ -249,8 +249,10 @@ QPixmap QCocoaTheme::standardPixmap(StandardPixmap sp, const QSizeF &size) const
return QPlatformTheme::standardPixmap(sp, size);
}
-QPixmap QCocoaTheme::fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &size) const
+QPixmap QCocoaTheme::fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &size,
+ QPlatformTheme::IconOptions iconOptions) const
{
+ Q_UNUSED(iconOptions);
QCocoaAutoReleasePool pool;
NSImage *iconImage = [[NSWorkspace sharedWorkspace] iconForFile:QCFString::toNSString(fileInfo.canonicalFilePath())];
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h
index b82d096bb5..8967445f59 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.h
+++ b/src/plugins/platforms/cocoa/qcocoawindow.h
@@ -61,7 +61,7 @@ QT_FORWARD_DECLARE_CLASS(QCocoaWindow)
@end
@interface QNSPanel : NSPanel {
- @public QT_PREPEND_NAMESPACE(QCocoaWindow) *m_cocoaPlatformWindow;
+ @public QCocoaWindow *m_cocoaPlatformWindow;
}
- (void)clearPlatformWindow;
- (BOOL)canBecomeKeyWindow;
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm
index 057eb7e144..cc72f050d2 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.mm
+++ b/src/plugins/platforms/cocoa/qcocoawindow.mm
@@ -155,6 +155,9 @@ static bool isMouseEvent(NSEvent *ev)
- (BOOL)canBecomeKeyWindow
{
+ if (!m_cocoaPlatformWindow)
+ return NO;
+
// Only tool or dialog windows should become key:
if (m_cocoaPlatformWindow
&& (m_cocoaPlatformWindow->window()->type() == Qt::Tool || m_cocoaPlatformWindow->window()->type() == Qt::Dialog))
diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm
index 66a1b95ad8..288d4b4742 100644
--- a/src/plugins/platforms/cocoa/qnsview.mm
+++ b/src/plugins/platforms/cocoa/qnsview.mm
@@ -919,14 +919,11 @@ static QTouchDevice *touchDevice = 0;
NSString *charactersIgnoringModifiers = [nsevent charactersIgnoringModifiers];
NSString *characters = [nsevent characters];
- // [from Qt 4 impl] There is no way to get the scan code from carbon. But we cannot
+ // There is no way to get the scan code from carbon/cocoa. But we cannot
// use the value 0, since it indicates that the event originates from somewhere
// else than the keyboard.
quint32 nativeScanCode = 1;
-
- UInt32 nativeVirtualKey = 0;
- EventRef eventRef = EventRef([nsevent eventRef]);
- GetEventParameter(eventRef, kEventParamKeyCode, typeUInt32, 0, sizeof(nativeVirtualKey), 0, &nativeVirtualKey);
+ quint32 nativeVirtualKey = [nsevent keyCode];
QChar ch = QChar::ReplacementCharacter;
int keyCode = Qt::Key_unknown;
diff --git a/src/plugins/platforms/cocoa/qpaintengine_mac.mm b/src/plugins/platforms/cocoa/qpaintengine_mac.mm
index 301beb11c1..dc3757ce3c 100644
--- a/src/plugins/platforms/cocoa/qpaintengine_mac.mm
+++ b/src/plugins/platforms/cocoa/qpaintengine_mac.mm
@@ -362,7 +362,6 @@ CGColorSpaceRef QCoreGraphicsPaintEngine::macDisplayColorSpace(const QWidget *wi
CGColorSpaceRef colorSpace;
CGDirectDisplayID displayID;
- CMProfileRef displayProfile = 0;
if (widget == 0) {
displayID = CGMainDisplayID();
} else {
@@ -376,18 +375,11 @@ CGColorSpaceRef QCoreGraphicsPaintEngine::macDisplayColorSpace(const QWidget *wi
if ((colorSpace = m_displayColorSpaceHash.value(displayID)))
return colorSpace;
- CMError err = CMGetProfileByAVID((CMDisplayIDType)displayID, &displayProfile);
- if (err == noErr) {
- colorSpace = CGColorSpaceCreateWithPlatformColorSpace(displayProfile);
- } else if (widget) {
- return macDisplayColorSpace(0); // fall back on main display
- }
-
+ colorSpace = CGDisplayCopyColorSpace(displayID);
if (colorSpace == 0)
colorSpace = CGColorSpaceCreateDeviceRGB();
m_displayColorSpaceHash.insert(displayID, colorSpace);
- CMCloseProfile(displayProfile);
if (!m_postRoutineRegistered) {
m_postRoutineRegistered = true;
qAddPostRoutine(QCoreGraphicsPaintEngine::cleanUpMacColorSpaces);
diff --git a/src/plugins/platforms/directfb/qdirectfbconvenience.cpp b/src/plugins/platforms/directfb/qdirectfbconvenience.cpp
index 939d8c0686..5b4c958616 100644
--- a/src/plugins/platforms/directfb/qdirectfbconvenience.cpp
+++ b/src/plugins/platforms/directfb/qdirectfbconvenience.cpp
@@ -286,6 +286,14 @@ QDirectFbKeyMap::QDirectFbKeyMap()
insert(DIKS_MAIL , Qt::Key_LaunchMail);
insert(DIKS_FAVORITES , Qt::Key_Favorites);
+ insert(DIKS_RED , Qt::Key_Red);
+ insert(DIKS_GREEN , Qt::Key_Green);
+ insert(DIKS_YELLOW , Qt::Key_Yellow);
+ insert(DIKS_BLUE , Qt::Key_Blue);
+
+ insert(DIKS_CHANNEL_UP , Qt::Key_ChannelUp);
+ insert(DIKS_CHANNEL_DOWN , Qt::Key_ChannelDown);
+
insert(DIKS_BACK , Qt::Key_Back);
insert(DIKS_FORWARD , Qt::Key_Forward);
insert(DIKS_VOLUME_UP , Qt::Key_VolumeUp);
diff --git a/src/plugins/platforms/ios/ios.pro b/src/plugins/platforms/ios/ios.pro
index 842ff17f1c..9b957afd8c 100644
--- a/src/plugins/platforms/ios/ios.pro
+++ b/src/plugins/platforms/ios/ios.pro
@@ -1,3 +1,38 @@
-TEMPLATE = subdirs
+TARGET = qios
-SUBDIRS += plugin.pro qtmain.pro
+PLUGIN_TYPE = platforms
+load(qt_plugin)
+
+QT += core-private gui-private platformsupport-private
+LIBS += -framework Foundation -framework UIKit -framework QuartzCore
+
+OBJECTIVE_SOURCES = \
+ plugin.mm \
+ qiosmain_wrapper.mm \
+ qiosmain_dummy.mm \
+ qiosintegration.mm \
+ qioswindow.mm \
+ qiosscreen.mm \
+ qiosbackingstore.mm \
+ qiosapplicationdelegate.mm \
+ qiosapplicationstate.mm \
+ qiosviewcontroller.mm \
+ qioscontext.mm \
+ qiosinputcontext.mm \
+ qiostheme.mm \
+ qiosglobal.mm
+
+HEADERS = \
+ qiosintegration.h \
+ qioswindow.h \
+ qiosscreen.h \
+ qiosbackingstore.h \
+ qiosapplicationdelegate.h \
+ qiosapplicationstate.h \
+ qiosviewcontroller.h \
+ qioscontext.h \
+ qiosinputcontext.h \
+ qiostheme.h \
+ qiosglobal.h
+
+#HEADERS = qiossoftwareinputhandler.h
diff --git a/src/plugins/platforms/ios/plugin.mm b/src/plugins/platforms/ios/plugin.mm
index a93b6037ad..ca8ec936ae 100644
--- a/src/plugins/platforms/ios/plugin.mm
+++ b/src/plugins/platforms/ios/plugin.mm
@@ -66,4 +66,8 @@ QT_END_NAMESPACE
#include "plugin.moc"
+// Dummy function that we explicitly tell the linker to look for,
+// so that the plugin's static initializer is included and run.
+extern "C" void qt_registerPlatformPlugin() {}
+
Q_IMPORT_PLUGIN(QIOSIntegrationPlugin)
diff --git a/src/plugins/platforms/ios/plugin.pro b/src/plugins/platforms/ios/plugin.pro
deleted file mode 100644
index 591a0a67ed..0000000000
--- a/src/plugins/platforms/ios/plugin.pro
+++ /dev/null
@@ -1,36 +0,0 @@
-TARGET = qios
-
-PLUGIN_TYPE = platforms
-load(qt_plugin)
-
-QT += core-private gui-private platformsupport-private
-LIBS += -framework UIKit -framework QuartzCore
-
-OBJECTIVE_SOURCES = \
- plugin.mm \
- qiosintegration.mm \
- qioswindow.mm \
- qiosscreen.mm \
- qioseventdispatcher.mm \
- qiosbackingstore.mm \
- qiosapplicationdelegate.mm \
- qiosviewcontroller.mm \
- qioscontext.mm \
- qiosinputcontext.mm \
- qiostheme.mm \
- qiosglobal.mm
-
-HEADERS = \
- qiosintegration.h \
- qioswindow.h \
- qiosscreen.h \
- qioseventdispatcher.h \
- qiosbackingstore.h \
- qiosapplicationdelegate.h \
- qiosviewcontroller.h \
- qioscontext.h \
- qiosinputcontext.h \
- qiostheme.h \
- qiosglobal.h
-
-#HEADERS = qiossoftwareinputhandler.h
diff --git a/src/plugins/platforms/ios/qiosapplicationdelegate.h b/src/plugins/platforms/ios/qiosapplicationdelegate.h
index 3d3ba58049..bfe31af198 100644
--- a/src/plugins/platforms/ios/qiosapplicationdelegate.h
+++ b/src/plugins/platforms/ios/qiosapplicationdelegate.h
@@ -50,7 +50,3 @@
@property (strong, nonatomic) QIOSViewController *qiosViewController;
@end
-
-@interface QIOSMainWrapperApplicationDelegate : QIOSApplicationDelegate
-@end
-
diff --git a/src/plugins/platforms/ios/qiosapplicationdelegate.mm b/src/plugins/platforms/ios/qiosapplicationdelegate.mm
index 10cbe529c4..52d94f38fb 100644
--- a/src/plugins/platforms/ios/qiosapplicationdelegate.mm
+++ b/src/plugins/platforms/ios/qiosapplicationdelegate.mm
@@ -39,10 +39,15 @@
**
****************************************************************************/
-#import "qiosapplicationdelegate.h"
+#include "qiosapplicationdelegate.h"
+
+#include "qiosviewcontroller.h"
#include "qioswindow.h"
+
#include <QtCore/QtCore>
+extern int qt_user_main(int argc, char *argv[]);
+
@implementation QIOSApplicationDelegate
@synthesize window;
@@ -50,40 +55,43 @@
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
- Q_UNUSED(application)
- Q_UNUSED(launchOptions)
+ Q_UNUSED(application);
+ Q_UNUSED(launchOptions);
- return YES;
-}
+ self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
+ self.qiosViewController = [[[QIOSViewController alloc] init] autorelease];
+ self.window.rootViewController = self.qiosViewController;
-- (void)applicationWillResignActive:(UIApplication *)application
-{
- Q_UNUSED(application)
-}
+#ifdef QT_DEBUG
+ self.window.backgroundColor = [UIColor cyanColor];
+#endif
-- (void)applicationDidEnterBackground:(UIApplication *)application
-{
- Q_UNUSED(application)
-}
+ [self.window makeKeyAndVisible];
-- (void)applicationWillEnterForeground:(UIApplication *)application
-{
- Q_UNUSED(application)
- // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
-}
+ // We schedule the main-redirection for the next eventloop pass so that we
+ // can return from this function and let UIApplicationMain finish its job.
+ [NSTimer scheduledTimerWithTimeInterval:.01f target:self
+ selector:@selector(runUserMain) userInfo:nil repeats:NO];
-- (void)applicationDidBecomeActive:(UIApplication *)application
-{
- Q_UNUSED(application)
- // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
+ return YES;
}
-- (void)applicationWillTerminate:(UIApplication *)application
+- (void)runUserMain
{
- Q_UNUSED(application)
- // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
+ NSArray *arguments = [[NSProcessInfo processInfo] arguments];
+ int argc = arguments.count;
+ char **argv = new char*[argc];
+ for (int i = 0; i < argc; ++i) {
+ NSString *arg = [arguments objectAtIndex:i];
+ argv[i] = reinterpret_cast<char *>(malloc([arg lengthOfBytesUsingEncoding:[NSString defaultCStringEncoding]]));
+ strcpy(argv[i], [arg cStringUsingEncoding:[NSString defaultCStringEncoding]]);
+ }
+
+ qt_user_main(argc, argv);
+ delete[] argv;
}
+
- (void)dealloc
{
[qiosViewController release];
@@ -93,4 +101,3 @@
@end
-
diff --git a/src/plugins/platforms/kms/qkmsudevhandler.cpp b/src/plugins/platforms/ios/qiosapplicationstate.h
index e32723e78f..e726ad895e 100644
--- a/src/plugins/platforms/kms/qkmsudevhandler.cpp
+++ b/src/plugins/platforms/ios/qiosapplicationstate.h
@@ -39,17 +39,22 @@
**
****************************************************************************/
-#include <qkmsudevhandler.h>
+#ifndef QIOSAPPLICATIONSTATE_H
+#define QIOSAPPLICATIONSTATE_H
QT_BEGIN_NAMESPACE
-QKmsUdevHandler::QKmsUdevHandler(QObject *parent)
- : QObject(parent)
-{
-}
+@class QIOSApplicationStateListener;
-QKmsUdevHandler::~QKmsUdevHandler()
+class QIOSApplicationState
{
-}
+public:
+ QIOSApplicationState();
+ ~QIOSApplicationState();
+private:
+ QIOSApplicationStateListener *m_listener;
+};
QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/platforms/ios/qiosapplicationstate.mm b/src/plugins/platforms/ios/qiosapplicationstate.mm
new file mode 100644
index 0000000000..df64edf465
--- /dev/null
+++ b/src/plugins/platforms/ios/qiosapplicationstate.mm
@@ -0,0 +1,162 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins 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$
+**
+****************************************************************************/
+
+#import <UIKit/UIKit.h>
+
+#include <qpa/qwindowsysteminterface.h>
+#include "qiosapplicationstate.h"
+
+@interface QIOSApplicationStateListener : NSObject
+@end
+
+@implementation QIOSApplicationStateListener
+
+- (id) init
+{
+ self = [super init];
+ if (self) {
+ // Listen for application state changes.
+ // Note: We use notifications rather than application delegate callbacks to
+ // also support hybrid applications were QIOSApplicationDelegate is not in use.
+ [[NSNotificationCenter defaultCenter]
+ addObserver:self
+ selector:@selector(applicationDidBecomeActive)
+ name:UIApplicationDidBecomeActiveNotification
+ object:nil];
+ [[NSNotificationCenter defaultCenter]
+ addObserver:self
+ selector:@selector(applicationWillResignActive)
+ name:UIApplicationWillResignActiveNotification
+ object:nil];
+ [[NSNotificationCenter defaultCenter]
+ addObserver:self
+ selector:@selector(applicationDidEnterBackground)
+ name:UIApplicationDidEnterBackgroundNotification
+ object:nil];
+ }
+ return self;
+}
+
+- (void) dealloc
+{
+ [[NSNotificationCenter defaultCenter]
+ removeObserver:self
+ name:UIApplicationDidBecomeActiveNotification
+ object:nil];
+ [[NSNotificationCenter defaultCenter]
+ removeObserver:self
+ name:UIApplicationWillResignActiveNotification
+ object:nil];
+ [[NSNotificationCenter defaultCenter]
+ removeObserver:self
+ name:UIApplicationDidEnterBackgroundNotification
+ object:nil];
+ [super dealloc];
+}
+
+- (void) applicationDidBecomeActive
+{
+ [self handleApplicationStateChanged:UIApplicationStateActive];
+}
+
+- (void) applicationWillResignActive
+{
+ // Note that UIApplication is still UIApplicationStateActive at this
+ // point, but since there is no separate notification for the inactive
+ // state, we report UIApplicationStateInactive now:
+ [self handleApplicationStateChanged:UIApplicationStateInactive];
+}
+
+- (void) applicationDidEnterBackground
+{
+ [self handleApplicationStateChanged:UIApplicationStateBackground];
+}
+
+- (void) handleApplicationStateChanged:(UIApplicationState) uiApplicationState
+{
+ Qt::ApplicationState state;
+ switch (uiApplicationState) {
+ case UIApplicationStateActive:
+ // The application is visible in front, and receiving events:
+ state = Qt::ApplicationActive;
+ break;
+ case UIApplicationStateInactive:
+ // The app is running in the foreground but is not receiving events. This
+ // typically happens while transitioning to/from active/background, like
+ // upon app launch or when receiving incoming calls:
+ state = Qt::ApplicationInactive;
+ break;
+ case UIApplicationStateBackground:
+ // Normally the app would enter this state briefly before it gets
+ // suspeded (you have five seconds, according to Apple).
+ // You can request more time and start a background task, which would
+ // normally map closer to Qt::ApplicationHidden. But since we have no
+ // API for doing that yet, we handle this state as "about to be suspended".
+ // Note: A screen-shot for the SpringBoard will also be taken after this
+ // call returns.
+ state = Qt::ApplicationSuspended;
+ break;
+ }
+ QWindowSystemInterface::handleApplicationStateChanged(state);
+}
+
+@end
+
+QT_BEGIN_NAMESPACE
+
+QIOSApplicationState::QIOSApplicationState()
+ : m_listener([[QIOSApplicationStateListener alloc] init])
+{
+ // Update the current state now, since we have missed all the updates
+ // posted from AppKit so far. But let QPA finish initialization first:
+ dispatch_async(dispatch_get_main_queue(), ^{
+ UIApplicationState state = [UIApplication sharedApplication].applicationState;
+ [m_listener handleApplicationStateChanged:state];
+ });
+}
+
+QIOSApplicationState::~QIOSApplicationState()
+{
+ [m_listener release];
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/plugins/platforms/ios/qioscontext.mm b/src/plugins/platforms/ios/qioscontext.mm
index 87bcc01d04..85f560a722 100644
--- a/src/plugins/platforms/ios/qioscontext.mm
+++ b/src/plugins/platforms/ios/qioscontext.mm
@@ -200,7 +200,7 @@ void QIOSContext::windowDestroyed(QObject *object)
QFunctionPointer QIOSContext::getProcAddress(const QByteArray& functionName)
{
- return reinterpret_cast<QFunctionPointer>(dlsym(RTLD_NEXT, functionName.constData()));
+ return QFunctionPointer(dlsym(RTLD_DEFAULT, functionName.constData()));
}
#include "moc_qioscontext.cpp"
diff --git a/src/plugins/platforms/ios/qiosinputcontext.h b/src/plugins/platforms/ios/qiosinputcontext.h
index 176ad05733..78c1b260e6 100644
--- a/src/plugins/platforms/ios/qiosinputcontext.h
+++ b/src/plugins/platforms/ios/qiosinputcontext.h
@@ -66,6 +66,7 @@ public:
private:
QIOSKeyboardListener *m_keyboardListener;
UIView *m_focusView;
+ bool m_hasPendingHideRequest;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/ios/qiosinputcontext.mm b/src/plugins/platforms/ios/qiosinputcontext.mm
index 1d3ab12de9..d430589037 100644
--- a/src/plugins/platforms/ios/qiosinputcontext.mm
+++ b/src/plugins/platforms/ios/qiosinputcontext.mm
@@ -99,6 +99,7 @@ QIOSInputContext::QIOSInputContext()
: QPlatformInputContext()
, m_keyboardListener([[QIOSKeyboardListener alloc] initWithQIOSInputContext:this])
, m_focusView(0)
+ , m_hasPendingHideRequest(false)
{
}
@@ -120,12 +121,20 @@ void QIOSInputContext::showInputPanel()
// responder. Rather than searching for it from the top, we let the active QIOSWindow tell us which view to use.
// Note that Qt will forward keyevents to whichever QObject that needs it, regardless of which UIView the input
// actually came from. So in this respect, we're undermining iOS' responder chain.
+ m_hasPendingHideRequest = false;
[m_focusView becomeFirstResponder];
}
void QIOSInputContext::hideInputPanel()
{
- [m_focusView resignFirstResponder];
+ // Delay hiding the keyboard for cases where the user is transferring focus between
+ // 'line edits'. In that case the 'line edit' that lost focus will close the input
+ // panel, just to see that the new 'line edit' will open it again:
+ m_hasPendingHideRequest = true;
+ dispatch_async(dispatch_get_main_queue(), ^{
+ if (m_hasPendingHideRequest)
+ [m_focusView resignFirstResponder];
+ });
}
bool QIOSInputContext::isInputPanelVisible() const
diff --git a/src/plugins/platforms/ios/qiosintegration.h b/src/plugins/platforms/ios/qiosintegration.h
index c352e0f2d2..4aaf98f839 100644
--- a/src/plugins/platforms/ios/qiosintegration.h
+++ b/src/plugins/platforms/ios/qiosintegration.h
@@ -46,6 +46,8 @@
#include <qpa/qplatformnativeinterface.h>
#include <qpa/qwindowsysteminterface.h>
+#include "qiosapplicationstate.h"
+
QT_BEGIN_NAMESPACE
class QIOSIntegration : public QPlatformIntegration, public QPlatformNativeInterface
@@ -79,6 +81,7 @@ private:
QPlatformInputContext *m_inputContext;
QPlatformScreen *m_screen;
QTouchDevice *m_touchDevice;
+ QIOSApplicationState m_applicationState;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/ios/qiosintegration.mm b/src/plugins/platforms/ios/qiosintegration.mm
index 61fd1c3d60..e31804f428 100644
--- a/src/plugins/platforms/ios/qiosintegration.mm
+++ b/src/plugins/platforms/ios/qiosintegration.mm
@@ -43,12 +43,13 @@
#include "qioswindow.h"
#include "qiosbackingstore.h"
#include "qiosscreen.h"
-#include "qioseventdispatcher.h"
#include "qioscontext.h"
#include "qiosinputcontext.h"
#include "qiostheme.h"
+#include <QtPlatformSupport/private/qioseventdispatcher_p.h>
#include <QtPlatformSupport/private/qcoretextfontdatabase_p.h>
+#include <QDir>
#include <QtDebug>
@@ -71,6 +72,9 @@ QIOSIntegration::QIOSIntegration()
exit(-1);
}
+ // Set current directory to app bundle folder
+ QDir::setCurrent(QString::fromUtf8([[[NSBundle mainBundle] bundlePath] UTF8String]));
+
screenAdded(m_screen);
m_touchDevice = new QTouchDevice;
@@ -86,6 +90,8 @@ bool QIOSIntegration::hasCapability(Capability cap) const
return true;
case MultipleWindows:
return true;
+ case ApplicationState:
+ return true;
default:
return QPlatformIntegration::hasCapability(cap);
}
@@ -129,6 +135,8 @@ QVariant QIOSIntegration::styleHint(StyleHint hint) const
switch (hint) {
case ShowIsFullScreen:
return true;
+ case SetFocusOnTouchRelease:
+ return true;
default:
return QPlatformIntegration::styleHint(hint);
}
diff --git a/src/plugins/platforms/kms/qkmsudevhandler.h b/src/plugins/platforms/ios/qiosmain_dummy.mm
index e95960628a..28d7e59381 100644
--- a/src/plugins/platforms/kms/qkmsudevhandler.h
+++ b/src/plugins/platforms/ios/qiosmain_dummy.mm
@@ -39,26 +39,18 @@
**
****************************************************************************/
-#ifndef QKMSUDEVHANDLER_H
-#define QKMSUDEVHANDLER_H
+#include <QtCore/qglobal.h>
-#include <QObject>
+/*
+ This file provides a dummy implementation of qt_user_main, so that
+ we don't get an undefined symbol in the hybrid use-case, where we
+ don't rename main() to qt_user_main(). As long as the linker is not
+ passed -all_load, this translation unit is only picked up and used
+ if qt_user_main is not defined by the user's code.
+*/
-#include <libudev.h>
-
-QT_BEGIN_NAMESPACE
-
-class QKmsUdevHandler : public QObject
+int qt_user_main(int, char **)
{
- Q_OBJECT
-
-public:
- QKmsUdevHandler(QObject *parent = 0);
- virtual ~QKmsUdevHandler();
-
- virtual QObject *create(struct udev_device *) = 0;
-};
-
-QT_END_NAMESPACE
-
-#endif // QKMSUDEVHANDLER_H
+ qFatal("Hit dummy qt_user_main, this should never happen!");
+ return 0;
+}
diff --git a/src/plugins/platforms/kms/qkmsudevdrmhandler.cpp b/src/plugins/platforms/ios/qiosmain_wrapper.mm
index 68a4aaacdb..d9b8c7311e 100644
--- a/src/plugins/platforms/kms/qkmsudevdrmhandler.cpp
+++ b/src/plugins/platforms/ios/qiosmain_wrapper.mm
@@ -39,28 +39,22 @@
**
****************************************************************************/
-#include <QtCore/QRegExp>
+#include "qiosapplicationdelegate.h"
-#include <qkmsintegration.h>
-#include <qkmsudevdrmhandler.h>
+/*
+ This file provides a wrapper implementation of main() for the non-
+ hybrid use-case. The user's main is renamed to qt_user_main by the
+ build rules, and we'll call out to that main at the appropriate time.
-QT_BEGIN_NAMESPACE
+ This file purposly only exports a single symbol, _main, so that
+ when the linker considers the translation unit for inclusion it
+ will discard it when main has already been defined in the user's
+ application for the hybrid use-case.
+*/
-QKmsUdevDRMHandler::QKmsUdevDRMHandler(QKmsIntegration *integration)
- : m_integration(integration)
+int main(int argc, char *argv[])
{
+ @autoreleasepool {
+ return UIApplicationMain(argc, argv, nil, NSStringFromClass([QIOSApplicationDelegate class]));
+ }
}
-
-QObject *QKmsUdevDRMHandler::create(struct udev_device *device)
-{
- if (strcmp(udev_device_get_subsystem(device), "drm"))
- return 0;
-
- QRegExp regexp("^card\\d+$");
- if (!regexp.exactMatch(udev_device_get_sysname(device)))
- return 0;
-
- return m_integration->createDevice(udev_device_get_devnode(device));
-}
-
-QT_END_NAMESPACE
diff --git a/src/plugins/platforms/ios/qioswindow.mm b/src/plugins/platforms/ios/qioswindow.mm
index 0c3ae8e834..4c8a16b0bc 100644
--- a/src/plugins/platforms/ios/qioswindow.mm
+++ b/src/plugins/platforms/ios/qioswindow.mm
@@ -247,6 +247,23 @@
return YES;
}
+- (BOOL)becomeFirstResponder
+{
+ // On iOS, a QWindow should only have input focus when the input panel is
+ // open. This is to stop cursors and focus rects from being drawn when the
+ // user cannot type. And since the keyboard will open when a view becomes
+ // the first responder, it's now a good time to inform QPA that the QWindow
+ // this view backs became active:
+ QWindowSystemInterface::handleWindowActivated(m_qioswindow->window());
+ return [super becomeFirstResponder];
+}
+
+- (BOOL)resignFirstResponder
+{
+ QWindowSystemInterface::handleWindowActivated(0);
+ return [super resignFirstResponder];
+}
+
- (BOOL)hasText
{
return YES;
@@ -416,7 +433,6 @@ void QIOSWindow::requestActivateWindow()
raise();
QPlatformInputContext *context = QGuiApplicationPrivate::platformIntegration()->inputContext();
static_cast<QIOSInputContext *>(context)->focusViewChanged(m_view);
- QPlatformWindow::requestActivateWindow();
}
void QIOSWindow::raiseOrLower(bool raise)
diff --git a/src/plugins/platforms/ios/qtmain.mm b/src/plugins/platforms/ios/qtmain.mm
deleted file mode 100644
index 19c98f2c59..0000000000
--- a/src/plugins/platforms/ios/qtmain.mm
+++ /dev/null
@@ -1,94 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the plugins 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 "qiosapplicationdelegate.h"
-#include "qiosviewcontroller.h"
-
-int main(int argc, char *argv[])
-{
- @autoreleasepool {
- return UIApplicationMain(argc, argv, nil, NSStringFromClass([QIOSMainWrapperApplicationDelegate class]));
- }
-}
-
-extern int qt_main(int argc, char *argv[]);
-
-@implementation QIOSMainWrapperApplicationDelegate
-
-- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
-{
- self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
- self.qiosViewController = [[[QIOSViewController alloc] init] autorelease];
- self.window.rootViewController = self.qiosViewController;
-
-#ifdef QT_DEBUG
- self.window.backgroundColor = [UIColor cyanColor];
-#endif
-
- [self.window makeKeyAndVisible];
-
- // We schedule the main-redirection for the next eventloop pass so that we
- // can return from this function and let UIApplicationMain finish its job.
- [NSTimer scheduledTimerWithTimeInterval:.01f target:self
- selector:@selector(runUserMain) userInfo:nil repeats:NO];
-
- if ([QIOSApplicationDelegate instancesRespondToSelector:_cmd])
- return [super application:application didFinishLaunchingWithOptions:launchOptions];
- else
- return YES;
-}
-
-- (void)runUserMain
-{
- NSArray *arguments = [[NSProcessInfo processInfo] arguments];
- int argc = arguments.count;
- char **argv = new char*[argc];
- for (int i = 0; i < argc; ++i) {
- NSString *arg = [arguments objectAtIndex:i];
- argv[i] = reinterpret_cast<char *>(malloc([arg lengthOfBytesUsingEncoding:[NSString defaultCStringEncoding]]));
- strcpy(argv[i], [arg cStringUsingEncoding:[NSString defaultCStringEncoding]]);
- }
-
- qt_main(argc, argv);
- delete[] argv;
-}
-
-@end
diff --git a/src/plugins/platforms/ios/qtmain.pro b/src/plugins/platforms/ios/qtmain.pro
deleted file mode 100644
index cbcb272217..0000000000
--- a/src/plugins/platforms/ios/qtmain.pro
+++ /dev/null
@@ -1,8 +0,0 @@
-TARGET = qiosmain
-
-PLUGIN_TYPE = platforms
-load(qt_plugin)
-
-QT += gui-private
-
-OBJECTIVE_SOURCES = qtmain.mm
diff --git a/src/plugins/platforms/kms/kms.pro b/src/plugins/platforms/kms/kms.pro
index 711cf9e5c7..612a878736 100644
--- a/src/plugins/platforms/kms/kms.pro
+++ b/src/plugins/platforms/kms/kms.pro
@@ -22,9 +22,6 @@ SOURCES = main.cpp \
qkmsdevice.cpp \
qkmsbackingstore.cpp \
qkmsnativeinterface.cpp \
- qkmsudevlistener.cpp \
- qkmsudevhandler.cpp \
- qkmsudevdrmhandler.cpp \
qkmsvthandler.cpp
HEADERS = qkmsintegration.h \
qkmsscreen.h \
@@ -34,9 +31,6 @@ HEADERS = qkmsintegration.h \
qkmsdevice.h \
qkmsbackingstore.h \
qkmsnativeinterface.h \
- qkmsudevlistener.h \
- qkmsudevhandler.h \
- qkmsudevdrmhandler.h \
qkmsvthandler.h
OTHER_FILES += \
diff --git a/src/plugins/platforms/kms/qkmsintegration.cpp b/src/plugins/platforms/kms/qkmsintegration.cpp
index 8210b54535..e0cc33a606 100644
--- a/src/plugins/platforms/kms/qkmsintegration.cpp
+++ b/src/plugins/platforms/kms/qkmsintegration.cpp
@@ -46,8 +46,6 @@
#include "qkmsbackingstore.h"
#include "qkmscontext.h"
#include "qkmsnativeinterface.h"
-#include "qkmsudevlistener.h"
-#include "qkmsudevdrmhandler.h"
#include "qkmsvthandler.h"
#include <QtPlatformSupport/private/qgenericunixeventdispatcher_p.h>
@@ -62,18 +60,26 @@ QKmsIntegration::QKmsIntegration()
: QPlatformIntegration(),
m_fontDatabase(new QGenericUnixFontDatabase()),
m_eventDispatcher(createUnixEventDispatcher()),
- m_nativeInterface(new QKmsNativeInterface),
- m_udevListener(new QKmsUdevListener)
+ m_nativeInterface(new QKmsNativeInterface)
{
QGuiApplicationPrivate::instance()->setEventDispatcher(m_eventDispatcher);
setenv("EGL_PLATFORM", "drm",1);
m_vtHandler = new QKmsVTHandler;
- m_drmHandler = new QKmsUdevDRMHandler(this);
- m_udevListener->addHandler(m_drmHandler);
+
+ m_deviceDiscovery = QDeviceDiscovery::create(QDeviceDiscovery::Device_DRM, 0);
+ if (m_deviceDiscovery) {
+ QStringList devices = m_deviceDiscovery->scanConnectedDevices();
+ foreach (QString device, devices)
+ addDevice(device);
+
+ connect(m_deviceDiscovery, SIGNAL(deviceDetected(QString)), this, SLOT(addDevice(QString)));
+ connect(m_deviceDiscovery, SIGNAL(deviceRemoved(QString)), this, SLOT(removeDevice(QString)));
+ }
}
QKmsIntegration::~QKmsIntegration()
{
+ delete m_deviceDiscovery;
foreach (QKmsDevice *device, m_devices) {
delete device;
}
@@ -81,15 +87,18 @@ QKmsIntegration::~QKmsIntegration()
delete screen;
}
delete m_fontDatabase;
- delete m_udevListener;
delete m_vtHandler;
}
-QObject *QKmsIntegration::createDevice(const char *path)
+void QKmsIntegration::addDevice(const QString &deviceNode)
+{
+ m_devices.append(new QKmsDevice(deviceNode, this));
+}
+
+void QKmsIntegration::removeDevice(const QString &deviceNode)
{
- QKmsDevice *device = new QKmsDevice(path, this);
- m_devices.append(device);
- return device;
+ // TODO: support hot-plugging some day?
+ Q_UNUSED(deviceNode);
}
bool QKmsIntegration::hasCapability(QPlatformIntegration::Capability cap) const
diff --git a/src/plugins/platforms/kms/qkmsintegration.h b/src/plugins/platforms/kms/qkmsintegration.h
index c08396ba3f..5069753aa5 100644
--- a/src/plugins/platforms/kms/qkmsintegration.h
+++ b/src/plugins/platforms/kms/qkmsintegration.h
@@ -44,17 +44,18 @@
#include <qpa/qplatformintegration.h>
#include <qpa/qplatformnativeinterface.h>
+#include <QtPlatformSupport/private/qdevicediscovery_p.h>
QT_BEGIN_NAMESPACE
class QKmsScreen;
class QKmsDevice;
-class QKmsUdevListener;
-class QKmsUdevDRMHandler;
class QKmsVTHandler;
-class QKmsIntegration : public QPlatformIntegration
+class QKmsIntegration : public QObject, public QPlatformIntegration
{
+ Q_OBJECT
+
public:
QKmsIntegration();
~QKmsIntegration();
@@ -73,6 +74,10 @@ public:
void addScreen(QKmsScreen *screen);
QObject *createDevice(const char *);
+private slots:
+ void addDevice(const QString &deviceNode);
+ void removeDevice(const QString &deviceNode);
+
private:
QStringList findDrmDevices();
@@ -81,9 +86,8 @@ private:
QPlatformFontDatabase *m_fontDatabase;
QAbstractEventDispatcher *m_eventDispatcher;
QPlatformNativeInterface *m_nativeInterface;
- QKmsUdevListener *m_udevListener;
- QKmsUdevDRMHandler *m_drmHandler;
QKmsVTHandler *m_vtHandler;
+ QDeviceDiscovery *m_deviceDiscovery;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/qnx/main.cpp b/src/plugins/platforms/qnx/main.cpp
index ea50b12cb3..fb81928625 100644
--- a/src/plugins/platforms/qnx/main.cpp
+++ b/src/plugins/platforms/qnx/main.cpp
@@ -46,9 +46,8 @@ QT_BEGIN_NAMESPACE
QPlatformIntegration *QQnxIntegrationPlugin::create(const QString& system, const QStringList& paramList)
{
- Q_UNUSED(paramList);
if (system.toLower() == QLatin1String("qnx"))
- return new QQnxIntegration;
+ return new QQnxIntegration(paramList);
return 0;
}
diff --git a/src/plugins/platforms/qnx/qnx.pro b/src/plugins/platforms/qnx/qnx.pro
index 398b64640e..7c497b4434 100644
--- a/src/plugins/platforms/qnx/qnx.pro
+++ b/src/plugins/platforms/qnx/qnx.pro
@@ -11,11 +11,11 @@ QT += platformsupport-private core-private gui-private
CONFIG(blackberry) {
CONFIG += qqnx_pps
- # Unomment this to enable screen event handling
- # through a dedicated thread.
- # DEFINES += QQNX_SCREENEVENTTHREAD
+ # Uncomment following line to enable screen event
+ # handling through a dedicated thread.
+ # CONFIG += qqnx_screeneventthread
} else {
- DEFINES += QQNX_SCREENEVENTTHREAD
+ CONFIG += qqnx_screeneventthread
}
# Uncomment these to enable debugging output for various aspects of the plugin
@@ -40,11 +40,11 @@ CONFIG(blackberry) {
#DEFINES += QQNXVIRTUALKEYBOARD_DEBUG
#DEFINES += QQNXWINDOW_DEBUG
#DEFINES += QQNXCURSOR_DEBUG
+#DEFINES += QQNXFILEPICKER_DEBUG
SOURCES = main.cpp \
qqnxbuffer.cpp \
- qqnxscreeneventthread.cpp \
qqnxintegration.cpp \
qqnxscreen.cpp \
qqnxwindow.cpp \
@@ -60,7 +60,6 @@ SOURCES = main.cpp \
HEADERS = main.h \
qqnxbuffer.h \
- qqnxscreeneventthread.h \
qqnxkeytranslator.h \
qqnxintegration.h \
qqnxscreen.h \
@@ -75,6 +74,12 @@ HEADERS = main.h \
qqnxservices.h \
qqnxcursor.h
+CONFIG(qqnx_screeneventthread) {
+ DEFINES += QQNX_SCREENEVENTTHREAD
+ SOURCES += qqnxscreeneventthread.cpp
+ HEADERS += qqnxscreeneventthread.h
+}
+
LIBS += -lscreen
contains(QT_CONFIG, opengles2) {
@@ -91,8 +96,7 @@ CONFIG(blackberry) {
qqnxbpseventfilter.cpp \
qqnxvirtualkeyboardbps.cpp \
qqnxtheme.cpp \
- qqnxsystemsettings.cpp \
- qqnxfiledialoghelper.cpp
+ qqnxsystemsettings.cpp
HEADERS += qqnxnavigatorbps.h \
qqnxeventdispatcher_blackberry.h \
@@ -105,6 +109,17 @@ CONFIG(blackberry) {
LIBS += -lbps
}
+CONFIG(blackberry-playbook) {
+ SOURCES += qqnxfiledialoghelper_playbook.cpp
+} else {
+ CONFIG(blackberry) {
+ SOURCES += qqnxfiledialoghelper_bb10.cpp \
+ qqnxfilepicker.cpp
+
+ HEADERS += qqnxfilepicker.h
+ }
+}
+
CONFIG(qqnx_pps) {
DEFINES += QQNX_PPS
diff --git a/src/plugins/platforms/qnx/qqnxbpseventfilter.cpp b/src/plugins/platforms/qnx/qqnxbpseventfilter.cpp
index d94d3c092a..133bf02fee 100644
--- a/src/plugins/platforms/qnx/qqnxbpseventfilter.cpp
+++ b/src/plugins/platforms/qnx/qqnxbpseventfilter.cpp
@@ -41,11 +41,12 @@
#include "qqnxbpseventfilter.h"
#include "qqnxnavigatoreventhandler.h"
-#include "qqnxfiledialoghelper.h"
#include "qqnxscreen.h"
#include "qqnxscreeneventhandler.h"
#include "qqnxvirtualkeyboardbps.h"
+#include "qqnxfiledialoghelper.h"
+#include <QCoreApplication>
#include <QAbstractEventDispatcher>
#include <QDebug>
@@ -126,6 +127,7 @@ void QQnxBpsEventFilter::unregisterForScreenEvents(QQnxScreen *screen)
qWarning("QQNX: failed to unregister for screen events on screen %p", screen->nativeContext());
}
+#if defined(Q_OS_BLACKBERRY_TABLET)
void QQnxBpsEventFilter::registerForDialogEvents(QQnxFileDialogHelper *dialog)
{
if (dialog_request_events(0) != BPS_SUCCESS)
@@ -141,6 +143,7 @@ void QQnxBpsEventFilter::unregisterForDialogEvents(QQnxFileDialogHelper *dialog)
if (count == 0)
qWarning("QQNX: attempting to unregister dialog that was not registered");
}
+#endif // Q_OS_BLACKBERRY_TABLET
bool QQnxBpsEventFilter::nativeEventFilter(const QByteArray &eventType, void *message, long *result)
{
@@ -160,12 +163,14 @@ bool QQnxBpsEventFilter::nativeEventFilter(const QByteArray &eventType, void *me
return m_screenEventHandler->handleEvent(screenEvent);
}
+#if defined(Q_OS_BLACKBERRY_TABLET)
if (eventDomain == dialog_get_domain()) {
dialog_instance_t nativeDialog = dialog_event_get_dialog_instance(event);
QQnxFileDialogHelper *dialog = m_dialogMapper.value(nativeDialog, 0);
if (dialog)
return dialog->handleEvent(event);
}
+#endif
if (eventDomain == navigator_get_domain())
return handleNavigatorEvent(event);
@@ -244,6 +249,11 @@ bool QQnxBpsEventFilter::handleNavigatorEvent(bps_event_t *event)
break;
}
+ case NAVIGATOR_LOW_MEMORY:
+ qWarning() << "QGuiApplication based process" << QCoreApplication::applicationPid()
+ << "received \"NAVIGATOR_LOW_MEMORY\" event";
+ return false;
+
default:
qBpsEventFilterDebug() << Q_FUNC_INFO << "Unhandled navigator event. code=" << bps_event_get_code(event);
return false;
diff --git a/src/plugins/platforms/qnx/qqnxbpseventfilter.h b/src/plugins/platforms/qnx/qqnxbpseventfilter.h
index e897863efb..f8e36823d5 100644
--- a/src/plugins/platforms/qnx/qqnxbpseventfilter.h
+++ b/src/plugins/platforms/qnx/qqnxbpseventfilter.h
@@ -73,8 +73,10 @@ public:
void registerForScreenEvents(QQnxScreen *screen);
void unregisterForScreenEvents(QQnxScreen *screen);
+#ifdef Q_OS_BLACKBERRY_TABLET
void registerForDialogEvents(QQnxFileDialogHelper *dialog);
void unregisterForDialogEvents(QQnxFileDialogHelper *dialog);
+#endif
private:
bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) Q_DECL_OVERRIDE;
diff --git a/src/plugins/platforms/qnx/qqnxfiledialoghelper.h b/src/plugins/platforms/qnx/qqnxfiledialoghelper.h
index e17ea80501..e7c68f6ff5 100644
--- a/src/plugins/platforms/qnx/qqnxfiledialoghelper.h
+++ b/src/plugins/platforms/qnx/qqnxfiledialoghelper.h
@@ -44,12 +44,19 @@
#include <qpa/qplatformdialoghelper.h>
-#include <bps/dialog.h>
QT_BEGIN_NAMESPACE
class QQnxIntegration;
+#if defined(Q_OS_BLACKBERRY_TABLET)
+#include <bps/dialog.h>
+#define NativeDialogPtr dialog_instance_t
+#else
+class QQnxFilePicker;
+#define NativeDialogPtr QQnxFilePicker *
+#endif
+
class QQnxFileDialogHelper : public QPlatformFileDialogHelper
{
Q_OBJECT
@@ -57,7 +64,9 @@ public:
explicit QQnxFileDialogHelper(const QQnxIntegration *);
~QQnxFileDialogHelper();
+#if defined(Q_OS_BLACKBERRY_TABLET)
bool handleEvent(bps_event_t *event);
+#endif
void exec();
@@ -65,29 +74,32 @@ public:
void hide();
bool defaultNameFilterDisables() const;
- void setDirectory(const QString &directory);
- QString directory() const;
- void selectFile(const QString &fileName);
- QStringList selectedFiles() const;
+ void setDirectory(const QUrl &directory) Q_DECL_OVERRIDE;
+ QUrl directory() const Q_DECL_OVERRIDE;
+ void selectFile(const QUrl &fileName) Q_DECL_OVERRIDE;
+ QList<QUrl> selectedFiles() const Q_DECL_OVERRIDE;
void setFilter();
void selectNameFilter(const QString &filter);
QString selectedNameFilter() const;
- dialog_instance_t nativeDialog() const { return m_dialog; }
+ NativeDialogPtr nativeDialog() const { return m_dialog; }
Q_SIGNALS:
void dialogClosed();
private:
void setNameFilter(const QString &filter);
+ void setNameFilters(const QStringList &filters);
const QQnxIntegration *m_integration;
- dialog_instance_t m_dialog;
+ NativeDialogPtr m_dialog;
QFileDialogOptions::AcceptMode m_acceptMode;
QString m_selectedFilter;
QPlatformDialogHelper::DialogCode m_result;
- QStringList m_paths;
+#if defined(Q_OS_BLACKBERRY_TABLET)
+ QList<QUrl> m_paths;
+#endif
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/qnx/qqnxfiledialoghelper_bb10.cpp b/src/plugins/platforms/qnx/qqnxfiledialoghelper_bb10.cpp
new file mode 100644
index 0000000000..dc841eb1a9
--- /dev/null
+++ b/src/plugins/platforms/qnx/qqnxfiledialoghelper_bb10.cpp
@@ -0,0 +1,217 @@
+/***************************************************************************
+**
+** Copyright (C) 2013 Research In Motion
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins 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 "qqnxfiledialoghelper.h"
+
+#include "qqnxfilepicker.h"
+#include "qqnxbpseventfilter.h"
+#include "qqnxscreen.h"
+#include "qqnxintegration.h"
+
+#include <QDebug>
+#include <QEventLoop>
+#include <QScreen>
+#include <QTimer>
+#include <QWindow>
+
+#ifdef QQNXFILEDIALOGHELPER_DEBUG
+#define qFileDialogHelperDebug qDebug
+#else
+#define qFileDialogHelperDebug QT_NO_QDEBUG_MACRO
+#endif
+
+QT_BEGIN_NAMESPACE
+
+QQnxFileDialogHelper::QQnxFileDialogHelper(const QQnxIntegration *integration)
+ : QPlatformFileDialogHelper(),
+ m_integration(integration),
+ m_dialog(new QQnxFilePicker),
+ m_acceptMode(QFileDialogOptions::AcceptOpen),
+ m_selectedFilter(),
+ m_result(QPlatformDialogHelper::Rejected)
+{
+}
+
+QQnxFileDialogHelper::~QQnxFileDialogHelper()
+{
+ delete m_dialog;
+}
+
+void QQnxFileDialogHelper::exec()
+{
+ qFileDialogHelperDebug() << Q_FUNC_INFO;
+
+ // Clear any previous results
+ m_dialog->setDirectories(QStringList());
+
+ QEventLoop loop;
+ connect(m_dialog, SIGNAL(closed()), &loop, SLOT(quit()));
+ loop.exec();
+
+ if (m_dialog->selectedFiles().isEmpty())
+ Q_EMIT reject();
+ else
+ Q_EMIT accept();
+}
+
+bool QQnxFileDialogHelper::show(Qt::WindowFlags flags, Qt::WindowModality modality, QWindow *parent)
+{
+ Q_UNUSED(flags);
+ Q_UNUSED(parent);
+ Q_UNUSED(modality);
+
+ qFileDialogHelperDebug() << Q_FUNC_INFO;
+
+ // Create dialog
+ const QSharedPointer<QFileDialogOptions> &opts = options();
+ if (opts->acceptMode() == QFileDialogOptions::AcceptOpen) {
+ // Select one or many files?
+ const QQnxFilePicker::Mode mode = (opts->fileMode() == QFileDialogOptions::ExistingFiles)
+ ? QQnxFilePicker::PickerMultiple : QQnxFilePicker::Picker;
+
+ m_dialog->setMode(mode);
+
+ // Set the actual list of extensions
+ if (!opts->nameFilters().isEmpty())
+ setNameFilters(opts->nameFilters());
+ else
+ setNameFilter(tr("All files (*.*)"));
+ } else {
+ const QQnxFilePicker::Mode mode = (opts->initiallySelectedFiles().count() >= 2)
+ ? QQnxFilePicker::SaverMultiple : QQnxFilePicker::Saver;
+
+ m_dialog->setMode(mode);
+
+ if (!opts->initiallySelectedFiles().isEmpty()) {
+ QStringList files;
+ Q_FOREACH ( const QUrl &url, opts->initiallySelectedFiles() )
+ files.append(url.toLocalFile());
+ m_dialog->setDefaultSaveFileNames(files);
+ }
+ }
+
+ // Cache the accept mode so we know which functions to use to get the results back
+ m_acceptMode = opts->acceptMode();
+ m_dialog->setTitle(opts->windowTitle());
+ m_dialog->open();
+
+ return true;
+}
+
+void QQnxFileDialogHelper::hide()
+{
+ qFileDialogHelperDebug() << Q_FUNC_INFO;
+ m_dialog->close();
+}
+
+bool QQnxFileDialogHelper::defaultNameFilterDisables() const
+{
+ qFileDialogHelperDebug() << Q_FUNC_INFO;
+ return false;
+}
+
+void QQnxFileDialogHelper::setDirectory(const QUrl &directory)
+{
+ m_dialog->addDirectory(directory.toLocalFile());
+}
+
+QUrl QQnxFileDialogHelper::directory() const
+{
+ qFileDialogHelperDebug() << Q_FUNC_INFO;
+ if (!m_dialog->directories().isEmpty())
+ return QUrl::fromLocalFile(m_dialog->directories().first());
+
+ return QUrl();
+}
+
+void QQnxFileDialogHelper::selectFile(const QUrl &fileName)
+{
+ m_dialog->addDefaultSaveFileName(fileName.toLocalFile());
+}
+
+QList<QUrl> QQnxFileDialogHelper::selectedFiles() const
+{
+ qFileDialogHelperDebug() << Q_FUNC_INFO;
+ QList<QUrl> urls;
+ QStringList files = m_dialog->selectedFiles();
+ Q_FOREACH (const QString &file, files)
+ urls.append(QUrl::fromLocalFile(file));
+ return urls;
+}
+
+void QQnxFileDialogHelper::setFilter()
+{
+ // No native api to support setting a filter from QDir::Filters
+ qFileDialogHelperDebug() << Q_FUNC_INFO;
+}
+
+void QQnxFileDialogHelper::selectNameFilter(const QString &filter)
+{
+ qFileDialogHelperDebug() << Q_FUNC_INFO << "filter =" << filter;
+ setNameFilter(filter);
+}
+
+QString QQnxFileDialogHelper::selectedNameFilter() const
+{
+ // For now there is no way for the user to change the selected filter
+ // so this just reflects what the developer has set programmatically.
+ qFileDialogHelperDebug() << Q_FUNC_INFO;
+ return m_selectedFilter;
+}
+
+void QQnxFileDialogHelper::setNameFilter(const QString &filter)
+{
+ qFileDialogHelperDebug() << Q_FUNC_INFO << "filter =" << filter;
+
+ setNameFilters(QPlatformFileDialogHelper::cleanFilterList(filter));
+}
+
+void QQnxFileDialogHelper::setNameFilters(const QStringList &filters)
+{
+ qFileDialogHelperDebug() << Q_FUNC_INFO << "filters =" << filters;
+
+ Q_ASSERT(!filters.isEmpty());
+
+ m_dialog->setFilters(filters);
+ m_selectedFilter = filters.first();
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/qnx/qqnxfiledialoghelper.cpp b/src/plugins/platforms/qnx/qqnxfiledialoghelper_playbook.cpp
index 0325a33268..2a743d03f7 100644
--- a/src/plugins/platforms/qnx/qqnxfiledialoghelper.cpp
+++ b/src/plugins/platforms/qnx/qqnxfiledialoghelper_playbook.cpp
@@ -102,7 +102,7 @@ bool QQnxFileDialogHelper::handleEvent(bps_event_t *event)
for (int i = 0; i < pathCount; ++i) {
QString path = QFile::decodeName(filePaths[i]);
- m_paths.append(path);
+ m_paths.append(QUrl::fromLocalFile(path));
qFileDialogHelperDebug() << "path =" << path;
}
@@ -112,13 +112,13 @@ bool QQnxFileDialogHelper::handleEvent(bps_event_t *event)
const char *filePath = dialog_event_get_filesave_filepath(event);
QString path = QFile::decodeName(filePath);
qFileDialogHelperDebug() << "path =" << path;
- m_paths.append(path);
+ m_paths.append(QUrl::fromLocalFile(path));
}
} else { // Cancel
m_result = QPlatformDialogHelper::Rejected;
}
- emit dialogClosed();
+ Q_EMIT dialogClosed();
return true;
}
@@ -135,9 +135,9 @@ void QQnxFileDialogHelper::exec()
loop.exec();
if (m_result == QPlatformDialogHelper::Accepted)
- emit accept();
+ Q_EMIT accept();
else
- emit reject();
+ Q_EMIT reject();
}
bool QQnxFileDialogHelper::show(Qt::WindowFlags flags, Qt::WindowModality modality, QWindow *parent)
@@ -188,7 +188,7 @@ bool QQnxFileDialogHelper::show(Qt::WindowFlags flags, Qt::WindowModality modali
// Maybe pre-select a filename
if (!opts->initiallySelectedFiles().isEmpty()) {
- QString fileName = opts->initiallySelectedFiles().first();
+ QString fileName = opts->initiallySelectedFiles().first().toLocalFile();
dialog_set_filesave_filename(m_dialog, QFile::encodeName(fileName).constData());
}
@@ -240,29 +240,29 @@ bool QQnxFileDialogHelper::defaultNameFilterDisables() const
return false;
}
-void QQnxFileDialogHelper::setDirectory(const QString &directory)
+void QQnxFileDialogHelper::setDirectory(const QUrl &directory)
{
qFileDialogHelperDebug() << Q_FUNC_INFO << "directory =" << directory;
// No native API for setting the directory(!). The best we can do is to
// set it as the file name but even then only with a file save dialog.
if (m_dialog && m_acceptMode == QFileDialogOptions::AcceptSave)
- dialog_set_filesave_filename(m_dialog, QFile::encodeName(directory).constData());
+ dialog_set_filesave_filename(m_dialog, QFile::encodeName(directory.toLocalFile()).constData());
}
-QString QQnxFileDialogHelper::directory() const
+QUrl QQnxFileDialogHelper::directory() const
{
qFileDialogHelperDebug() << Q_FUNC_INFO;
return m_paths.first();
}
-void QQnxFileDialogHelper::selectFile(const QString &fileName)
+void QQnxFileDialogHelper::selectFile(const QUrl &fileName)
{
qFileDialogHelperDebug() << Q_FUNC_INFO << "filename =" << fileName;
if (m_dialog && m_acceptMode == QFileDialogOptions::AcceptSave)
- dialog_set_filesave_filename(m_dialog, QFile::encodeName(fileName).constData());
+ dialog_set_filesave_filename(m_dialog, QFile::encodeName(fileName.toLocalFile()).constData());
}
-QStringList QQnxFileDialogHelper::selectedFiles() const
+QList<QUrl> QQnxFileDialogHelper::selectedFiles() const
{
qFileDialogHelperDebug() << Q_FUNC_INFO;
return m_paths;
@@ -291,9 +291,15 @@ QString QQnxFileDialogHelper::selectedNameFilter() const
void QQnxFileDialogHelper::setNameFilter(const QString &filter)
{
qFileDialogHelperDebug() << Q_FUNC_INFO << "filter =" << filter;
+ setNameFilters(QPlatformFileDialogHelper::cleanFilterList(filter));
+}
+
+void QQnxFileDialogHelper::setNameFilters(const QStringList &filters)
+{
+ qFileDialogHelperDebug() << Q_FUNC_INFO << "filters =" << filters;
+
+ Q_ASSERT(!filters.isEmpty());
- // Extract the globbing expressions
- QStringList filters = QPlatformFileDialogHelper::cleanFilterList(filter);
char **globs = new char*[filters.size()];
for (int i = 0; i < filters.size(); ++i) {
QByteArray glob = filters.at(i).toLocal8Bit();
@@ -303,7 +309,7 @@ void QQnxFileDialogHelper::setNameFilter(const QString &filter)
// Set the filters
dialog_set_filebrowse_filter(m_dialog, const_cast<const char**>(globs), filters.size());
- m_selectedFilter = filter;
+ m_selectedFilter = filters.first();
// Cleanup
for (int i = 0; i < filters.size(); ++i)
diff --git a/src/plugins/platforms/qnx/qqnxfilepicker.cpp b/src/plugins/platforms/qnx/qqnxfilepicker.cpp
new file mode 100644
index 0000000000..5229d1f1f5
--- /dev/null
+++ b/src/plugins/platforms/qnx/qqnxfilepicker.cpp
@@ -0,0 +1,289 @@
+/***************************************************************************
+**
+** Copyright (C) 2013 Research In Motion
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins 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 "qqnxfilepicker.h"
+
+#include <QAbstractEventDispatcher>
+#include <QCoreApplication>
+#include <QDebug>
+#include <QJsonDocument>
+#include <QJsonObject>
+#include <QJsonArray>
+#include <QJsonParseError>
+#include <QUrl>
+
+#include <bps/navigator.h>
+#include <bps/navigator_invoke.h>
+
+#include <errno.h>
+
+#ifdef QQNXFILEPICKER_DEBUG
+#define qFilePickerDebug qDebug
+#else
+#define qFilePickerDebug QT_NO_QDEBUG_MACRO
+#endif
+
+static const char s_filePickerTarget[] = "sys.filepicker.target";
+
+QQnxFilePicker::QQnxFilePicker(QObject *parent)
+ : QObject(parent)
+ , m_invocationHandle(0)
+ , m_mode(QQnxFilePicker::Picker)
+ , m_title(tr("Pick a file"))
+{
+ QCoreApplication::eventDispatcher()->installNativeEventFilter(this);
+}
+
+QQnxFilePicker::~QQnxFilePicker()
+{
+ cleanup();
+
+ QCoreApplication::eventDispatcher()->removeNativeEventFilter(this);
+}
+
+void QQnxFilePicker::open()
+{
+ if (m_invocationHandle)
+ return;
+
+ int errorCode = BPS_SUCCESS;
+
+ errorCode = navigator_invoke_invocation_create(&m_invocationHandle);
+ if (errorCode != BPS_SUCCESS) {
+ qWarning() << "QQnxFilePicker: unable to create invocation:" << strerror(errno);
+ return;
+ }
+
+ errorCode = navigator_invoke_invocation_set_target(m_invocationHandle, s_filePickerTarget);
+
+ if (errorCode != BPS_SUCCESS) {
+ cleanup();
+ qWarning() << "QQnxFilePicker: unable to set target:" << strerror(errno);
+ return;
+ }
+
+ errorCode = navigator_invoke_invocation_set_action(m_invocationHandle, "bb.action.OPEN");
+ if (errorCode != BPS_SUCCESS) {
+ cleanup();
+ qWarning() << "QQnxFilePicker: unable to set action:" << strerror(errno);
+ return;
+ }
+
+ errorCode = navigator_invoke_invocation_set_type(m_invocationHandle, "application/vnd.blackberry.file_picker");
+ if (errorCode != BPS_SUCCESS) {
+ cleanup();
+ qWarning() << "QQnxFilePicker: unable to set mime type:" << strerror(errno);
+ return;
+ }
+
+ QVariantMap map;
+ map[QStringLiteral("Type")] = QStringLiteral("Other");
+ map[QStringLiteral("Mode")] = modeToString(m_mode);
+ map[QStringLiteral("Title")] = m_title;
+ map[QStringLiteral("ViewMode")] = QStringLiteral("Default");
+ map[QStringLiteral("SortBy")] = QStringLiteral("Default");
+ map[QStringLiteral("SortOrder")] = QStringLiteral("Default");
+ map[QStringLiteral("ImageCrop")] = false;
+ map[QStringLiteral("AllowOverwrite")] = false;
+
+ if (!m_defaultSaveFileNames.isEmpty())
+ map[QStringLiteral("DefaultFileNames")] = m_defaultSaveFileNames.join(",");
+ if (!m_filters.isEmpty())
+ map[QStringLiteral("Filter")] = m_filters.join(";");
+
+ QJsonDocument document;
+ document.setObject(QJsonObject::fromVariantMap(map));
+ const QByteArray jsonData = document.toJson(QJsonDocument::Compact);
+
+ errorCode = navigator_invoke_invocation_set_data(m_invocationHandle, jsonData.constData(), jsonData.size());
+ if (errorCode != BPS_SUCCESS) {
+ cleanup();
+ qWarning() << "QQnxFilePicker: unable to set data:" << strerror(errno);
+ return;
+ }
+
+ navigator_invoke_invocation_send(m_invocationHandle);
+}
+
+void QQnxFilePicker::close()
+{
+ navigator_card_close_child();
+ cleanup();
+}
+
+bool QQnxFilePicker::nativeEventFilter(const QByteArray&, void *message, long*)
+{
+ bps_event_t * const event = static_cast<bps_event_t*>(message);
+ if (!event)
+ return false;
+
+ if (bps_event_get_code(event) == NAVIGATOR_INVOKE_TARGET_RESULT) {
+ const char *id = navigator_event_get_id(event);
+ const char *err = navigator_event_get_err(event);
+ qFilePickerDebug("received invocation response: id=%s err=%s", id, err);
+ } else if (bps_event_get_code(event) == NAVIGATOR_CHILD_CARD_CLOSED) {
+ const char *data = navigator_event_get_card_closed_data(event);
+ qFilePickerDebug("received data: data='%s'", data);
+ handleFilePickerResponse(data);
+ }
+
+ return false; // do not drop the event
+}
+
+void QQnxFilePicker::setMode(QQnxFilePicker::Mode mode)
+{
+ m_mode = mode;
+}
+
+void QQnxFilePicker::setDefaultSaveFileNames(const QStringList &fileNames)
+{
+ m_defaultSaveFileNames = fileNames;
+}
+
+void QQnxFilePicker::addDefaultSaveFileName(const QString &fileName)
+{
+ m_defaultSaveFileNames.append(fileName);
+}
+
+void QQnxFilePicker::setDirectories(const QStringList &directories)
+{
+ m_directories = directories;
+}
+
+void QQnxFilePicker::addDirectory(const QString &directory)
+{
+ m_directories.append(directory);
+}
+
+void QQnxFilePicker::setFilters(const QStringList &filters)
+{
+ m_filters = filters;
+}
+
+void QQnxFilePicker::setTitle(const QString &title)
+{
+ m_title = title;
+}
+
+QQnxFilePicker::Mode QQnxFilePicker::mode() const
+{
+ return m_mode;
+}
+
+QStringList QQnxFilePicker::defaultSaveFileNames() const
+{
+ return m_defaultSaveFileNames;
+}
+
+QStringList QQnxFilePicker::directories() const
+{
+ return m_directories;
+}
+
+QStringList QQnxFilePicker::filters() const
+{
+ return m_filters;
+}
+
+QStringList QQnxFilePicker::selectedFiles() const
+{
+ return m_selectedFiles;
+}
+
+QString QQnxFilePicker::title() const
+{
+ return m_title;
+}
+
+void QQnxFilePicker::cleanup()
+{
+ if (m_invocationHandle) {
+ navigator_invoke_invocation_destroy(m_invocationHandle);
+ m_invocationHandle = 0;
+ }
+}
+
+void QQnxFilePicker::handleFilePickerResponse(const char *data)
+{
+ QJsonParseError jsonError;
+ QJsonDocument document = QJsonDocument::fromJson(data, &jsonError);
+
+ if (jsonError.error != QJsonParseError::NoError) {
+ qFilePickerDebug() << "Error parsing FilePicker response: "
+ << jsonError.errorString();
+ Q_EMIT closed();
+ cleanup();
+ return;
+ }
+
+ // The response is a list of Json objects.
+ const QVariantList array = document.array().toVariantList();
+
+ foreach (const QVariant &variant, array) {
+ const QJsonObject object = QJsonObject::fromVariantMap(variant.toMap());
+ const QUrl url(object.value(QStringLiteral("uri")).toString());
+ const QString localFile = url.toLocalFile(); // strip "file://"
+
+ if (!localFile.isEmpty())
+ m_selectedFiles << localFile;
+
+ qFilePickerDebug() << "FilePicker uri response:" << localFile;
+ }
+
+ Q_EMIT closed();
+ cleanup();
+}
+
+QString QQnxFilePicker::modeToString(QQnxFilePicker::Mode mode) const
+{
+ switch (mode) {
+ case Picker:
+ return QStringLiteral("Picker");
+ case Saver:
+ return QStringLiteral("Saver");
+ case PickerMultiple:
+ return QStringLiteral("PickerMultiple");
+ case SaverMultiple:
+ return QStringLiteral("SaverMultiple");
+ }
+
+ return QStringLiteral("Picker");
+}
diff --git a/src/plugins/platforms/kms/qkmsudevlistener.cpp b/src/plugins/platforms/qnx/qqnxfilepicker.h
index b2fb110479..5bb8f0969f 100644
--- a/src/plugins/platforms/kms/qkmsudevlistener.cpp
+++ b/src/plugins/platforms/qnx/qqnxfilepicker.h
@@ -1,6 +1,6 @@
-/****************************************************************************
+/***************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2013 Research In Motion
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
@@ -39,63 +39,72 @@
**
****************************************************************************/
-#include <qkmsudevlistener.h>
+#ifndef QQNXFILEPICKER_H
+#define QQNXFILEPICKER_H
-QT_BEGIN_NAMESPACE
+#include <QAbstractNativeEventFilter>
+#include <QObject>
+#include <QStringList>
-QKmsUdevListener::QKmsUdevListener(QObject *parent)
- : QObject(parent)
-{
- m_udev = udev_new();
-}
+struct navigator_invoke_invocation_t;
-QKmsUdevListener::~QKmsUdevListener()
+class QQnxFilePicker : public QObject, public QAbstractNativeEventFilter
{
- udev_unref(m_udev);
-}
+ Q_OBJECT
-void QKmsUdevListener::addHandler(QKmsUdevHandler *handler)
-{
- m_handlers.removeAll((QKmsUdevHandler *) 0);
- m_handlers.removeAll(handler);
- m_handlers.prepend(handler);
+public:
+ explicit QQnxFilePicker(QObject *parent = 0);
+ ~QQnxFilePicker();
- scan();
-}
+ enum Mode {
+ Picker,
+ Saver,
+ PickerMultiple,
+ SaverMultiple
+ };
-bool QKmsUdevListener::create(struct udev_device *device)
-{
- foreach (QKmsUdevHandler *handler, m_handlers) {
- if (!handler)
- continue;
+ bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) Q_DECL_OVERRIDE;
- QObject *obj = handler->create(device);
- if (obj) {
- m_devices[udev_device_get_syspath(device)] = obj;
- return true;
- }
- }
+ void setMode(Mode mode);
+ void setDefaultSaveFileNames(const QStringList &fileNames);
+ void addDefaultSaveFileName(const QString &fileName);
+ void setDirectories(const QStringList &directories);
+ void addDirectory(const QString &directory);
+ void setFilters(const QStringList &filters);
+ void setTitle(const QString &title);
- return false;
-}
+ Mode mode() const;
-void QKmsUdevListener::scan()
-{
- struct udev_enumerate *e;
- struct udev_list_entry *entry;
-
- e = udev_enumerate_new(m_udev);
- udev_enumerate_scan_devices(e);
- udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(e)) {
- const char *path = udev_list_entry_get_name(entry);
- if (m_devices.contains(path))
- continue;
-
- struct udev_device *device = udev_device_new_from_syspath(m_udev, path);
- create(device);
- udev_device_unref(device);
- }
- udev_enumerate_unref(e);
-}
-
-QT_END_NAMESPACE
+ QStringList defaultSaveFileNames() const;
+ QStringList directories() const;
+ QStringList filters() const;
+ QStringList selectedFiles() const;
+
+ QString title() const;
+
+Q_SIGNALS:
+ void closed();
+
+public Q_SLOTS:
+ void open();
+ void close();
+
+private:
+ void cleanup();
+ void handleFilePickerResponse(const char *data);
+
+ QString modeToString(Mode mode) const;
+
+ navigator_invoke_invocation_t *m_invocationHandle;
+
+ Mode m_mode;
+
+ QStringList m_defaultSaveFileNames;
+ QStringList m_directories;
+ QStringList m_filters;
+ QStringList m_selectedFiles;
+
+ QString m_title;
+};
+
+#endif // QQNXFILEPICKER_H
diff --git a/src/plugins/platforms/qnx/qqnxintegration.cpp b/src/plugins/platforms/qnx/qqnxintegration.cpp
index feb05e3093..fa9961ccce 100644
--- a/src/plugins/platforms/qnx/qqnxintegration.cpp
+++ b/src/plugins/platforms/qnx/qqnxintegration.cpp
@@ -40,7 +40,9 @@
****************************************************************************/
#include "qqnxintegration.h"
+#if defined(QQNX_SCREENEVENTTHREAD)
#include "qqnxscreeneventthread.h"
+#endif
#include "qqnxnativeinterface.h"
#include "qqnxrasterbackingstore.h"
#include "qqnxscreen.h"
@@ -84,6 +86,8 @@
#include <qpa/qplatformwindow.h>
#include <qpa/qwindowsysteminterface.h>
+#include <QtGui/private/qguiapplication_p.h>
+
#if !defined(QT_NO_OPENGL)
#include "qqnxglcontext.h"
#include <QtGui/QOpenGLContext>
@@ -107,9 +111,20 @@ QT_BEGIN_NAMESPACE
QQnxWindowMapper QQnxIntegration::ms_windowMapper;
QMutex QQnxIntegration::ms_windowMapperMutex;
-QQnxIntegration::QQnxIntegration()
+static inline QQnxIntegration::Options parseOptions(const QStringList &paramList)
+{
+ QQnxIntegration::Options options = QQnxIntegration::NoOptions;
+ if (!paramList.contains(QLatin1String("no-fullscreen"))) {
+ options |= QQnxIntegration::FullScreenApplication;
+ }
+ return options;
+}
+
+QQnxIntegration::QQnxIntegration(const QStringList &paramList)
: QPlatformIntegration()
+#if defined(QQNX_SCREENEVENTTHREAD)
, m_screenEventThread(0)
+#endif
, m_navigatorEventHandler(new QQnxNavigatorEventHandler())
, m_virtualKeyboard(0)
#if defined(QQNX_PPS)
@@ -134,6 +149,7 @@ QQnxIntegration::QQnxIntegration()
#if !defined(QT_NO_DRAGANDDROP)
, m_drag(new QSimpleDrag())
#endif
+ , m_options(parseOptions(paramList))
{
qIntegrationDebug() << Q_FUNC_INFO;
// Open connection to QNX composition manager
@@ -185,8 +201,13 @@ QQnxIntegration::QQnxIntegration()
#if defined(Q_OS_BLACKBERRY)
QQnxVirtualKeyboardBps* virtualKeyboardBps = new QQnxVirtualKeyboardBps;
- m_bpsEventFilter = new QQnxBpsEventFilter(m_navigatorEventHandler,
- (m_screenEventThread ? 0 : m_screenEventHandler), virtualKeyboardBps);
+
+#if defined(QQNX_SCREENEVENTTHREAD)
+ m_bpsEventFilter = new QQnxBpsEventFilter(m_navigatorEventHandler, 0, virtualKeyboardBps);
+#else
+ m_bpsEventFilter = new QQnxBpsEventFilter(m_navigatorEventHandler, m_screenEventHandler, virtualKeyboardBps);
+#endif
+
m_bpsEventFilter->installOnEventDispatcher(m_eventDispatcher);
m_virtualKeyboard = virtualKeyboardBps;
@@ -383,7 +404,7 @@ QPlatformDrag *QQnxIntegration::drag() const
QVariant QQnxIntegration::styleHint(QPlatformIntegration::StyleHint hint) const
{
qIntegrationDebug() << Q_FUNC_INFO;
- if (hint == ShowIsFullScreen)
+ if ((hint == ShowIsFullScreen) && (m_options & FullScreenApplication))
return true;
return QPlatformIntegration::styleHint(hint);
@@ -526,6 +547,11 @@ QQnxScreen *QQnxIntegration::primaryDisplay() const
return m_screens.first();
}
+QQnxIntegration::Options QQnxIntegration::options() const
+{
+ return m_options;
+}
+
bool QQnxIntegration::supportsNavigatorEvents() const
{
// If QQNX_PPS or Q_OS_BLACKBERRY is defined then we have navigator
diff --git a/src/plugins/platforms/qnx/qqnxintegration.h b/src/plugins/platforms/qnx/qqnxintegration.h
index e3eb9e06ba..dd8973b767 100644
--- a/src/plugins/platforms/qnx/qqnxintegration.h
+++ b/src/plugins/platforms/qnx/qqnxintegration.h
@@ -51,7 +51,9 @@
QT_BEGIN_NAMESPACE
class QQnxBpsEventFilter;
+#if defined(QQNX_SCREENEVENTTHREAD)
class QQnxScreenEventThread;
+#endif
class QQnxFileDialogHelper;
class QQnxNativeInterface;
class QQnxWindow;
@@ -80,7 +82,12 @@ typedef QHash<screen_window_t, QWindow *> QQnxWindowMapper;
class QQnxIntegration : public QPlatformIntegration
{
public:
- QQnxIntegration();
+ enum Option { // Options to be passed on command line.
+ NoOptions = 0x0,
+ FullScreenApplication = 0x1
+ };
+ Q_DECLARE_FLAGS(Options, Option)
+ explicit QQnxIntegration(const QStringList &paramList);
~QQnxIntegration();
bool hasCapability(QPlatformIntegration::Capability cap) const;
@@ -129,6 +136,8 @@ public:
void createDisplay(screen_display_t display, bool isPrimary);
void removeDisplay(QQnxScreen *screen);
QQnxScreen *primaryDisplay() const;
+ Options options() const;
+
private:
void createDisplays();
void destroyDisplays();
@@ -137,7 +146,9 @@ private:
static void removeWindow(screen_window_t qnxWindow);
screen_context_t m_screenContext;
+#if defined(QQNX_SCREENEVENTTHREAD)
QQnxScreenEventThread *m_screenEventThread;
+#endif
QQnxNavigatorEventHandler *m_navigatorEventHandler;
QQnxAbstractVirtualKeyboard *m_virtualKeyboard;
#if defined(QQNX_PPS)
@@ -164,6 +175,8 @@ private:
static QQnxWindowMapper ms_windowMapper;
static QMutex ms_windowMapperMutex;
+ const Options m_options;
+
friend class QQnxWindow;
};
diff --git a/src/plugins/platforms/qnx/qqnxrasterbackingstore.cpp b/src/plugins/platforms/qnx/qqnxrasterbackingstore.cpp
index 6a7a4d0944..1da3cd5446 100644
--- a/src/plugins/platforms/qnx/qqnxrasterbackingstore.cpp
+++ b/src/plugins/platforms/qnx/qqnxrasterbackingstore.cpp
@@ -91,6 +91,11 @@ void QQnxRasterBackingStore::flush(QWindow *window, const QRegion &region, const
if (window)
targetWindow = static_cast<QQnxWindow *>(window->handle());
+ // we only need to flush the platformWindow backing store, since this is
+ // the buffer where all drawing operations of all windows, including the
+ // child windows, are performed; conceptually ,child windows have no buffers
+ // (actually they do have a 1x1 placeholder buffer due to libscreen limitations),
+ // since Qt will only draw to the backing store of the top-level window.
QQnxWindow *platformWindow = this->platformWindow();
if (!targetWindow || targetWindow == platformWindow) {
@@ -108,28 +113,6 @@ void QQnxRasterBackingStore::flush(QWindow *window, const QRegion &region, const
// update the display with newly rendered content
platformWindow->post(region);
- } else if (targetWindow) {
-
- // The contents of the backing store should be flushed to a different window than the
- // window which owns the buffer.
- // This typically happens for child windows, since child windows share a backing store with
- // their top-level window (TLW).
- // Simply copy the buffer over to the child window, to emulate a painting operation, and
- // then post the window.
- //
- // ### Note that because of the design in the QNX QPA plugin, each window has its own buffers,
- // even though they might share a backing store. This is unneeded overhead, but I don't think
- // libscreen allows to have windows without buffers, or does it?
-
- // We assume that the TLW has been flushed previously and that no changes were made to the
- // backing store inbetween (### does Qt guarantee this?)
-
- targetWindow->adjustBufferSize();
- targetWindow->blitFrom(platformWindow, offset, region);
- targetWindow->post(region);
-
- } else {
- qWarning() << Q_FUNC_INFO << "flush() called without a valid window!";
}
m_hasUnflushedPaintOperations = false;
diff --git a/src/plugins/platforms/qnx/qqnxscreen.cpp b/src/plugins/platforms/qnx/qqnxscreen.cpp
index 84721c9c2a..5aa1257f38 100644
--- a/src/plugins/platforms/qnx/qqnxscreen.cpp
+++ b/src/plugins/platforms/qnx/qqnxscreen.cpp
@@ -85,7 +85,9 @@ static QSize determineScreenSize(screen_display_t display, bool primaryScreen) {
if (val[0] > 0 && val[1] > 0)
return QSize(val[0], val[1]);
- qWarning("QQnxScreen: screen_get_display_property_iv() reported an invalid physical screen size (%dx%d). Falling back to QQNX_PHYSICAL_SCREEN_SIZE environment variable.", val[0], val[1]);
+ qScreenDebug("QQnxScreen: screen_get_display_property_iv() reported an invalid "
+ "physical screen size (%dx%d). Falling back to QQNX_PHYSICAL_SCREEN_SIZE "
+ "environment variable.", val[0], val[1]);
const QString envPhySizeStr = qgetenv("QQNX_PHYSICAL_SCREEN_SIZE");
if (!envPhySizeStr.isEmpty()) {
@@ -94,7 +96,9 @@ static QSize determineScreenSize(screen_display_t display, bool primaryScreen) {
const int envHeight = envPhySizeStrList.size() == 2 ? envPhySizeStrList[1].toInt() : -1;
if (envWidth <= 0 || envHeight <= 0) {
- qFatal("QQnxScreen: The value of QQNX_PHYSICAL_SCREEN_SIZE must be in the format \"width,height\" in mm, with width, height > 0. Example: QQNX_PHYSICAL_SCREEN_SIZE=150,90");
+ qFatal("QQnxScreen: The value of QQNX_PHYSICAL_SCREEN_SIZE must be in the format "
+ "\"width,height\" in mm, with width, height > 0. "
+ "Example: QQNX_PHYSICAL_SCREEN_SIZE=150,90");
return QSize(150, 90);
}
@@ -103,11 +107,14 @@ static QSize determineScreenSize(screen_display_t display, bool primaryScreen) {
#if defined(QQNX_PHYSICAL_SCREEN_SIZE_DEFINED)
const QSize defSize(QQNX_PHYSICAL_SCREEN_WIDTH, QQNX_PHYSICAL_SCREEN_HEIGHT);
- qWarning("QQnxScreen: QQNX_PHYSICAL_SCREEN_SIZE variable not set. Falling back to defines QQNX_PHYSICAL_SCREEN_WIDTH/QQNX_PHYSICAL_SCREEN_HEIGHT (%dx%d)", defSize.width(), defSize.height());
+ qWarning("QQnxScreen: QQNX_PHYSICAL_SCREEN_SIZE variable not set. Falling back to defines "
+ "QQNX_PHYSICAL_SCREEN_WIDTH/QQNX_PHYSICAL_SCREEN_HEIGHT (%dx%d)",
+ defSize.width(), defSize.height());
return defSize;
#else
if (primaryScreen)
- qFatal("QQnxScreen: QQNX_PHYSICAL_SCREEN_SIZE variable not set. Could not determine physical screen size.");
+ qFatal("QQnxScreen: QQNX_PHYSICAL_SCREEN_SIZE variable not set. "
+ "Could not determine physical screen size.");
return QSize(150, 90);
#endif
}
diff --git a/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp b/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp
index c2d0e3e41c..c869d29c99 100644
--- a/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp
+++ b/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp
@@ -469,8 +469,14 @@ void QQnxScreenEventHandler::handleDisplayEvent(screen_event_t event)
qScreenEventDebug() << Q_FUNC_INFO << "display attachment is now:" << isAttached;
QQnxScreen *screen = m_qnxIntegration->screenForNative(nativeDisplay);
+
if (!screen) {
if (isAttached) {
+ int val[2];
+ screen_get_display_property_iv(nativeDisplay, SCREEN_PROPERTY_SIZE, val);
+ if (val[0] == 0 && val[1] == 0) //If screen size is invalid, wait for the next event
+ return;
+
qScreenEventDebug() << "creating new QQnxScreen for newly attached display";
m_qnxIntegration->createDisplay(nativeDisplay, false /* not primary, we assume */);
}
diff --git a/src/plugins/platforms/qnx/qqnxtheme.cpp b/src/plugins/platforms/qnx/qqnxtheme.cpp
index 733b7223b6..37c1079441 100644
--- a/src/plugins/platforms/qnx/qqnxtheme.cpp
+++ b/src/plugins/platforms/qnx/qqnxtheme.cpp
@@ -58,10 +58,8 @@ QQnxTheme::~QQnxTheme()
bool QQnxTheme::usePlatformNativeDialog(DialogType type) const
{
-#if defined(Q_OS_BLACKBERRY_TABLET)
if (type == QPlatformTheme::FileDialog)
return true;
-#endif
#if !defined(QT_NO_COLORDIALOG)
if (type == QPlatformTheme::ColorDialog)
return false;
@@ -76,10 +74,8 @@ bool QQnxTheme::usePlatformNativeDialog(DialogType type) const
QPlatformDialogHelper *QQnxTheme::createPlatformDialogHelper(DialogType type) const
{
switch (type) {
-#if defined(Q_OS_BLACKBERRY_TABLET)
case QPlatformTheme::FileDialog:
return new QQnxFileDialogHelper(m_integration);
-#endif
#if !defined(QT_NO_COLORDIALOG)
case QPlatformTheme::ColorDialog:
#endif
diff --git a/src/plugins/platforms/qnx/qqnxwindow.cpp b/src/plugins/platforms/qnx/qqnxwindow.cpp
index 5aa1c970fd..2bd5cfd801 100644
--- a/src/plugins/platforms/qnx/qqnxwindow.cpp
+++ b/src/plugins/platforms/qnx/qqnxwindow.cpp
@@ -336,6 +336,9 @@ QSize QQnxWindow::requestedBufferSize() const
void QQnxWindow::adjustBufferSize()
{
+ if (m_parentWindow)
+ return;
+
const QSize windowSize = window()->size();
if (windowSize != bufferSize())
setBufferSize(windowSize);
@@ -574,8 +577,18 @@ void QQnxWindow::setParent(const QPlatformWindow *window)
setScreen(m_parentWindow->m_screen);
m_parentWindow->m_childWindows.push_back(this);
+
+ // we don't need any buffers, since
+ // Qt will draw to the parent TLW
+ // backing store.
+ setBufferSize(QSize(1, 1));
} else {
m_screen->addWindow(this);
+
+ // recreate buffers, in case the
+ // window has been reparented and
+ // becomes a TLW
+ adjustBufferSize();
}
m_screen->updateHierarchy();
@@ -634,6 +647,12 @@ void QQnxWindow::setWindowState(Qt::WindowState state)
applyWindowState();
}
+void QQnxWindow::propagateSizeHints()
+{
+ // nothing to do; silence base class warning
+ qWindowDebug() << Q_FUNC_INFO << ": ignored";
+}
+
void QQnxWindow::gainedFocus()
{
qWindowDebug() << Q_FUNC_INFO << "window =" << window();
diff --git a/src/plugins/platforms/qnx/qqnxwindow.h b/src/plugins/platforms/qnx/qqnxwindow.h
index 63d5dc0979..e30a469be7 100644
--- a/src/plugins/platforms/qnx/qqnxwindow.h
+++ b/src/plugins/platforms/qnx/qqnxwindow.h
@@ -103,6 +103,8 @@ public:
void requestActivateWindow();
void setWindowState(Qt::WindowState state);
+ void propagateSizeHints();
+
void gainedFocus();
QQnxScreen *screen() const { return m_screen; }
diff --git a/src/plugins/platforms/windows/main.cpp b/src/plugins/platforms/windows/main.cpp
index e5c3269a6c..16cac9d547 100644
--- a/src/plugins/platforms/windows/main.cpp
+++ b/src/plugins/platforms/windows/main.cpp
@@ -107,10 +107,10 @@ class QWindowsIntegrationPlugin : public QPlatformIntegrationPlugin
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QPA.QPlatformIntegrationFactoryInterface.5.1" FILE "windows.json")
public:
- QPlatformIntegration *create(const QString&, const QStringList&);
+ QPlatformIntegration *create(const QString&, const QStringList&, int &, char **);
};
-QPlatformIntegration *QWindowsIntegrationPlugin::create(const QString& system, const QStringList& paramList)
+QPlatformIntegration *QWindowsIntegrationPlugin::create(const QString& system, const QStringList& paramList, int &, char **)
{
if (system.compare(system, QStringLiteral("windows"), Qt::CaseInsensitive) == 0)
return new QWindowsIntegration(paramList);
diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp
index 872fd07729..170160a901 100644
--- a/src/plugins/platforms/windows/qwindowscontext.cpp
+++ b/src/plugins/platforms/windows/qwindowscontext.cpp
@@ -47,6 +47,7 @@
#include "qtwindowsglobal.h"
#include "qwindowsmime.h"
#include "qwindowsinputcontext.h"
+#include "qwindowstabletsupport.h"
#ifndef QT_NO_ACCESSIBILITY
#include "accessible/qwindowsaccessibility.h"
#endif
@@ -83,6 +84,7 @@ int QWindowsContext::verboseOLE = 0;
int QWindowsContext::verboseInputMethods = 0;
int QWindowsContext::verboseDialogs = 0;
int QWindowsContext::verboseTheming = 0;
+int QWindowsContext::verboseTablet = 0;
// Get verbosity of components from "foo:2,bar:3"
static inline int componentVerbose(const char *v, const char *keyWord)
@@ -259,17 +261,20 @@ struct QWindowsContextPrivate {
QWindowsMimeConverter m_mimeConverter;
QWindowsScreenManager m_screenManager;
QSharedPointer<QWindowCreationContext> m_creationContext;
+#if !defined(QT_NO_TABLETEVENT) && !defined(Q_OS_WINCE)
+ QScopedPointer<QWindowsTabletSupport> m_tabletSupport;
+#endif
const HRESULT m_oleInitializeResult;
const QByteArray m_eventType;
QWindow *m_lastActiveWindow;
bool m_asyncExpose;
};
-QWindowsContextPrivate::QWindowsContextPrivate() :
- m_systemInfo(0),
- m_oleInitializeResult(OleInitialize(NULL)),
- m_eventType(QByteArrayLiteral("windows_generic_MSG")),
- m_lastActiveWindow(0), m_asyncExpose(0)
+QWindowsContextPrivate::QWindowsContextPrivate()
+ : m_systemInfo(0)
+ , m_oleInitializeResult(OleInitialize(NULL))
+ , m_eventType(QByteArrayLiteral("windows_generic_MSG"))
+ , m_lastActiveWindow(0), m_asyncExpose(0)
{
const QSysInfo::WinVersion ver = QSysInfo::windowsVersion();
#ifndef Q_OS_WINCE
@@ -310,7 +315,13 @@ QWindowsContext::QWindowsContext() :
QWindowsContext::verboseInputMethods = componentVerbose(v, "im");
QWindowsContext::verboseDialogs = componentVerbose(v, "dialogs");
QWindowsContext::verboseTheming = componentVerbose(v, "theming");
+ QWindowsContext::verboseTablet = componentVerbose(v, "tablet");
}
+#if !defined(QT_NO_TABLETEVENT) && !defined(Q_OS_WINCE)
+ d->m_tabletSupport.reset(QWindowsTabletSupport::create());
+ if (QWindowsContext::verboseTablet)
+ qDebug() << "Tablet support: " << (d->m_tabletSupport.isNull() ? QStringLiteral("None") : d->m_tabletSupport->description());
+#endif
}
QWindowsContext::~QWindowsContext()
@@ -626,6 +637,15 @@ QWindowsScreenManager &QWindowsContext::screenManager()
return d->m_screenManager;
}
+QWindowsTabletSupport *QWindowsContext::tabletSupport() const
+{
+#if !defined(QT_NO_TABLETEVENT) && !defined(Q_OS_WINCE)
+ return d->m_tabletSupport.data();
+#else
+ return 0;
+#endif
+}
+
/*!
\brief Convenience to create a non-visible, message-only dummy
window for example used as clipboard watcher or for GL.
@@ -854,6 +874,10 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
return true;
#ifndef Q_OS_WINCE
case QtWindows::ActivateWindowEvent:
+#ifndef QT_NO_TABLETEVENT
+ if (!d->m_tabletSupport.isNull())
+ d->m_tabletSupport->notifyActivate();
+#endif // !QT_NO_TABLETEVENT
if (platformWindow->testFlag(QWindowsWindow::BlockedByModal))
if (const QWindow *modalWindow = QGuiApplication::modalWindow())
QWindowsWindow::baseWindowOf(modalWindow)->alertWindow();
diff --git a/src/plugins/platforms/windows/qwindowscontext.h b/src/plugins/platforms/windows/qwindowscontext.h
index d60b632beb..b5c97cddc9 100644
--- a/src/plugins/platforms/windows/qwindowscontext.h
+++ b/src/plugins/platforms/windows/qwindowscontext.h
@@ -56,6 +56,7 @@ QT_BEGIN_NAMESPACE
class QWindow;
class QPlatformScreen;
class QWindowsScreenManager;
+class QWindowsTabletSupport;
class QWindowsWindow;
class QWindowsMimeConverter;
struct QWindowCreationContext;
@@ -135,6 +136,7 @@ public:
static int verboseInputMethods;
static int verboseDialogs;
static int verboseTheming;
+ static int verboseTablet;
explicit QWindowsContext();
~QWindowsContext();
@@ -184,6 +186,7 @@ public:
QWindowsMimeConverter &mimeConverter() const;
QWindowsScreenManager &screenManager();
+ QWindowsTabletSupport *tabletSupport() const;
#ifndef Q_OS_WINCE
static QWindowsUser32DLL user32dll;
static QWindowsShell32DLL shell32dll;
diff --git a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
index 33bed61398..17a6cd6579 100644
--- a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
+++ b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
@@ -39,6 +39,8 @@
**
****************************************************************************/
+#define QT_NO_URL_CAST_FROM_STRING 1
+
#include "qwindowsdialoghelpers.h"
#include "qwindowscontext.h"
@@ -651,34 +653,34 @@ public:
QWindowsFileDialogSharedData() : m_data(new Data) {}
void fromOptions(const QSharedPointer<QFileDialogOptions> &o);
- QString directory() const;
- void setDirectory(const QString &);
+ QUrl directory() const;
+ void setDirectory(const QUrl &);
QString selectedNameFilter() const;
void setSelectedNameFilter(const QString &);
- QStringList selectedFiles() const;
- void setSelectedFiles(const QStringList &);
+ QList<QUrl> selectedFiles() const;
+ void setSelectedFiles(const QList<QUrl> &);
QString selectedFile() const;
private:
class Data : public QSharedData {
public:
- QString directory;
+ QUrl directory;
QString selectedNameFilter;
- QStringList selectedFiles;
+ QList<QUrl> selectedFiles;
QMutex mutex;
};
QExplicitlySharedDataPointer<Data> m_data;
};
-inline QString QWindowsFileDialogSharedData::directory() const
+inline QUrl QWindowsFileDialogSharedData::directory() const
{
m_data->mutex.lock();
- const QString result = m_data->directory;
+ const QUrl result = m_data->directory;
m_data->mutex.unlock();
return result;
}
-inline void QWindowsFileDialogSharedData::setDirectory(const QString &d)
+inline void QWindowsFileDialogSharedData::setDirectory(const QUrl &d)
{
QMutexLocker (&m_data->mutex);
m_data->directory = d;
@@ -698,24 +700,24 @@ inline void QWindowsFileDialogSharedData::setSelectedNameFilter(const QString &f
m_data->selectedNameFilter = f;
}
-inline QStringList QWindowsFileDialogSharedData::selectedFiles() const
+inline QList<QUrl> QWindowsFileDialogSharedData::selectedFiles() const
{
m_data->mutex.lock();
- const QStringList result = m_data->selectedFiles;
+ const QList<QUrl> result = m_data->selectedFiles;
m_data->mutex.unlock();
return result;
}
inline QString QWindowsFileDialogSharedData::selectedFile() const
{
- const QStringList files = selectedFiles();
- return files.isEmpty() ? QString() : files.front();
+ const QList<QUrl> files = selectedFiles();
+ return files.isEmpty() ? QString() : files.front().toLocalFile();
}
-inline void QWindowsFileDialogSharedData::setSelectedFiles(const QStringList &f)
+inline void QWindowsFileDialogSharedData::setSelectedFiles(const QList<QUrl> &urls)
{
QMutexLocker (&m_data->mutex);
- m_data->selectedFiles = f;
+ m_data->selectedFiles = urls;
}
inline void QWindowsFileDialogSharedData::fromOptions(const QSharedPointer<QFileDialogOptions> &o)
@@ -822,7 +824,7 @@ public:
virtual void setWindowTitle(const QString &title);
inline void setMode(QFileDialogOptions::FileMode mode, QFileDialogOptions::FileDialogOptions options);
inline void setDirectory(const QString &directory);
- inline void updateDirectory() { setDirectory(m_data.directory()); }
+ inline void updateDirectory() { setDirectory(m_data.directory().toLocalFile()); }
inline QString directory() const;
virtual void exec(HWND owner = 0);
virtual void setNameFilters(const QStringList &f);
@@ -837,10 +839,10 @@ public:
inline void setLabelText(QFileDialogOptions::DialogLabel l, const QString &text);
// Return the selected files for tracking in OnSelectionChanged().
- virtual QStringList selectedFiles() const = 0;
+ virtual QList<QUrl> selectedFiles() const = 0;
// Return the result for tracking in OnFileOk(). Differs from selection for
// example by appended default suffixes, etc.
- virtual QStringList dialogResult() const = 0;
+ virtual QList<QUrl> dialogResult() const = 0;
inline void onFolderChange(IShellItem *);
inline void onSelectionChange();
@@ -848,8 +850,8 @@ public:
inline bool onFileOk();
signals:
- void directoryEntered(const QString& directory);
- void currentChanged(const QString& file);
+ void directoryEntered(const QUrl &directory);
+ void currentChanged(const QUrl &file);
void filterSelected(const QString & filter);
public slots:
@@ -861,9 +863,9 @@ protected:
void setDefaultSuffixSys(const QString &s);
inline IFileDialog * fileDialog() const { return m_fileDialog; }
static QString itemPath(IShellItem *item);
- static QStringList libraryItemFolders(IShellItem *item);
+ static QList<QUrl> libraryItemFolders(IShellItem *item);
static QString libraryItemDefaultSaveFolder(IShellItem *item);
- static int itemPaths(IShellItemArray *items, QStringList *fileResult = 0);
+ static int itemPaths(IShellItemArray *items, QList<QUrl> *fileResult = 0);
static IShellItem *shellItem(const QString &path);
const QWindowsFileDialogSharedData &data() const { return m_data; }
@@ -1031,9 +1033,9 @@ static IShellLibrary *sHLoadLibraryFromItem(IShellItem *libraryItem, DWORD mode)
}
// Return all folders of a library-type item.
-QStringList QWindowsNativeFileDialogBase::libraryItemFolders(IShellItem *item)
+QList<QUrl> QWindowsNativeFileDialogBase::libraryItemFolders(IShellItem *item)
{
- QStringList result;
+ QList<QUrl> result;
if (IShellLibrary *library = sHLoadLibraryFromItem(item, STGM_READ | STGM_SHARE_DENY_WRITE)) {
IShellItemArray *itemArray = 0;
if (SUCCEEDED(library->GetFolders(LFF_FORCEFILESYSTEM, IID_IShellItemArray, reinterpret_cast<void **>(&itemArray)))) {
@@ -1062,9 +1064,9 @@ QString QWindowsNativeFileDialogBase::libraryItemDefaultSaveFolder(IShellItem *i
#else // !Q_OS_WINCE && __IShellLibrary_INTERFACE_DEFINED__
-QStringList QWindowsNativeFileDialogBase::libraryItemFolders(IShellItem *)
+QList<QUrl> QWindowsNativeFileDialogBase::libraryItemFolders(IShellItem *)
{
- return QStringList();
+ return QList<QUrl>();
}
QString QWindowsNativeFileDialogBase::libraryItemDefaultSaveFolder(IShellItem *)
@@ -1096,7 +1098,7 @@ QString QWindowsNativeFileDialogBase::itemPath(IShellItem *item)
}
int QWindowsNativeFileDialogBase::itemPaths(IShellItemArray *items,
- QStringList *result /* = 0 */)
+ QList<QUrl> *result /* = 0 */)
{
DWORD itemCount = 0;
if (result)
@@ -1108,7 +1110,7 @@ int QWindowsNativeFileDialogBase::itemPaths(IShellItemArray *items,
for (DWORD i = 0; i < itemCount; ++i) {
IShellItem *item = 0;
if (SUCCEEDED(items->GetItemAt(i, &item)))
- result->push_back(QWindowsNativeFileDialogBase::itemPath(item));
+ result->push_back(QUrl::fromLocalFile(QWindowsNativeFileDialogBase::itemPath(item)));
}
}
return itemCount;
@@ -1270,7 +1272,7 @@ QString QWindowsNativeFileDialogBase::selectedNameFilter() const
void QWindowsNativeFileDialogBase::onFolderChange(IShellItem *item)
{
if (item) {
- const QString directory = QWindowsNativeFileDialogBase::itemPath(item);
+ const QUrl directory = QUrl::fromLocalFile(QWindowsNativeFileDialogBase::itemPath(item));
m_data.setDirectory(directory);
emit directoryEntered(directory);
}
@@ -1278,7 +1280,7 @@ void QWindowsNativeFileDialogBase::onFolderChange(IShellItem *item)
void QWindowsNativeFileDialogBase::onSelectionChange()
{
- const QStringList current = selectedFiles();
+ const QList<QUrl> current = selectedFiles();
m_data.setSelectedFiles(current);
if (current.size() == 1)
emit currentChanged(current.front());
@@ -1338,8 +1340,8 @@ public:
explicit QWindowsNativeSaveFileDialog(const QWindowsFileDialogSharedData &data)
: QWindowsNativeFileDialogBase(data) {}
virtual void setNameFilters(const QStringList &f);
- virtual QStringList selectedFiles() const;
- virtual QStringList dialogResult() const;
+ virtual QList<QUrl> selectedFiles() const;
+ virtual QList<QUrl> dialogResult() const;
};
// Return the first suffix from the name filter "Foo files (*.foo;*.bar)" -> "foo".
@@ -1374,22 +1376,22 @@ void QWindowsNativeSaveFileDialog::setNameFilters(const QStringList &f)
} // m_hasDefaultSuffix
}
-QStringList QWindowsNativeSaveFileDialog::dialogResult() const
+QList<QUrl> QWindowsNativeSaveFileDialog::dialogResult() const
{
- QStringList result;
+ QList<QUrl> result;
IShellItem *item = 0;
if (SUCCEEDED(fileDialog()->GetResult(&item)) && item)
- result.push_back(QWindowsNativeFileDialogBase::itemPath(item));
+ result.push_back(QUrl::fromLocalFile(QWindowsNativeFileDialogBase::itemPath(item)));
return result;
}
-QStringList QWindowsNativeSaveFileDialog::selectedFiles() const
+QList<QUrl> QWindowsNativeSaveFileDialog::selectedFiles() const
{
- QStringList result;
+ QList<QUrl> result;
IShellItem *item = 0;
const HRESULT hr = fileDialog()->GetCurrentSelection(&item);
if (SUCCEEDED(hr) && item)
- result.push_back(QWindowsNativeSaveFileDialog::itemPath(item));
+ result.push_back(QUrl::fromLocalFile(QWindowsNativeSaveFileDialog::itemPath(item)));
return result;
}
@@ -1408,26 +1410,26 @@ class QWindowsNativeOpenFileDialog : public QWindowsNativeFileDialogBase
public:
explicit QWindowsNativeOpenFileDialog(const QWindowsFileDialogSharedData &data) :
QWindowsNativeFileDialogBase(data) {}
- virtual QStringList selectedFiles() const;
- virtual QStringList dialogResult() const;
+ virtual QList<QUrl> selectedFiles() const;
+ virtual QList<QUrl> dialogResult() const;
private:
inline IFileOpenDialog *openFileDialog() const
{ return static_cast<IFileOpenDialog *>(fileDialog()); }
};
-QStringList QWindowsNativeOpenFileDialog::dialogResult() const
+QList<QUrl> QWindowsNativeOpenFileDialog::dialogResult() const
{
- QStringList result;
+ QList<QUrl> result;
IShellItemArray *items = 0;
if (SUCCEEDED(openFileDialog()->GetResults(&items)) && items)
QWindowsNativeFileDialogBase::itemPaths(items, &result);
return result;
}
-QStringList QWindowsNativeOpenFileDialog::selectedFiles() const
+QList<QUrl> QWindowsNativeOpenFileDialog::selectedFiles() const
{
- QStringList result;
+ QList<QUrl> result;
IShellItemArray *items = 0;
const HRESULT hr = openFileDialog()->GetSelectedItems(&items);
if (SUCCEEDED(hr) && items)
@@ -1484,14 +1486,13 @@ public:
virtual bool supportsNonModalDialog(const QWindow * /* parent */ = 0) const { return false; }
virtual bool defaultNameFilterDisables() const
{ return true; }
- virtual void setDirectory(const QString &directory);
- virtual QString directory() const;
- virtual void selectFile(const QString &filename);
- virtual QStringList selectedFiles() const;
- virtual void setFilter();
- virtual void setNameFilters(const QStringList &filters);
- virtual void selectNameFilter(const QString &filter);
- virtual QString selectedNameFilter() const;
+ virtual void setDirectory(const QUrl &directory) Q_DECL_OVERRIDE;
+ virtual QUrl directory() const Q_DECL_OVERRIDE;
+ virtual void selectFile(const QUrl &filename) Q_DECL_OVERRIDE;
+ virtual QList<QUrl> selectedFiles() const Q_DECL_OVERRIDE;
+ virtual void setFilter() Q_DECL_OVERRIDE;
+ virtual void selectNameFilter(const QString &filter) Q_DECL_OVERRIDE;
+ virtual QString selectedNameFilter() const Q_DECL_OVERRIDE;
private:
virtual QWindowsNativeDialogBase *createNativeDialog();
@@ -1509,10 +1510,10 @@ QWindowsNativeDialogBase *QWindowsFileDialogHelper::createNativeDialog()
return 0;
QObject::connect(result, SIGNAL(accepted()), this, SIGNAL(accept()));
QObject::connect(result, SIGNAL(rejected()), this, SIGNAL(reject()));
- QObject::connect(result, SIGNAL(directoryEntered(QString)),
- this, SIGNAL(directoryEntered(QString)));
- QObject::connect(result, SIGNAL(currentChanged(QString)),
- this, SIGNAL(currentChanged(QString)));
+ QObject::connect(result, SIGNAL(directoryEntered(QUrl)),
+ this, SIGNAL(directoryEntered(QUrl)));
+ QObject::connect(result, SIGNAL(currentChanged(QUrl)),
+ this, SIGNAL(currentChanged(QUrl)));
QObject::connect(result, SIGNAL(filterSelected(QString)),
this, SIGNAL(filterSelected(QString)));
@@ -1532,11 +1533,16 @@ QWindowsNativeDialogBase *QWindowsFileDialogHelper::createNativeDialog()
result->setLabelText(QFileDialogOptions::Accept, opts->labelText(QFileDialogOptions::Accept));
result->updateDirectory();
result->updateSelectedNameFilter();
- const QStringList initialSelection = opts->initiallySelectedFiles();
+ const QList<QUrl> initialSelection = opts->initiallySelectedFiles();
if (initialSelection.size() > 0) {
- QFileInfo info(initialSelection.front());
- if (!info.isDir())
- result->selectFile(info.fileName());
+ const QUrl url = initialSelection.front();
+ if (url.isLocalFile()) {
+ QFileInfo info(url.toLocalFile());
+ if (!info.isDir())
+ result->selectFile(info.fileName());
+ } else {
+ result->selectFile(url.path()); // TODO url.fileName() once it exists
+ }
}
// No need to select initialNameFilter if mode is Dir
if (mode != QFileDialogOptions::Directory && mode != QFileDialogOptions::DirectoryOnly) {
@@ -1550,31 +1556,31 @@ QWindowsNativeDialogBase *QWindowsFileDialogHelper::createNativeDialog()
return result;
}
-void QWindowsFileDialogHelper::setDirectory(const QString &directory)
+void QWindowsFileDialogHelper::setDirectory(const QUrl &directory)
{
if (QWindowsContext::verboseDialogs)
- qDebug("%s %s" , __FUNCTION__, qPrintable(directory));
+ qDebug("%s %s" , __FUNCTION__, qPrintable(directory.toString()));
m_data.setDirectory(directory);
if (hasNativeDialog())
nativeFileDialog()->updateDirectory();
}
-QString QWindowsFileDialogHelper::directory() const
+QUrl QWindowsFileDialogHelper::directory() const
{
return m_data.directory();
}
-void QWindowsFileDialogHelper::selectFile(const QString &fileName)
+void QWindowsFileDialogHelper::selectFile(const QUrl &fileName)
{
if (QWindowsContext::verboseDialogs)
- qDebug("%s %s" , __FUNCTION__, qPrintable(fileName));
+ qDebug("%s %s" , __FUNCTION__, qPrintable(fileName.toString()));
if (QWindowsNativeFileDialogBase *nfd = nativeFileDialog())
- nfd->selectFile(fileName);
+ nfd->selectFile(fileName.toLocalFile()); // ## should use QUrl::fileName() once it exists
}
-QStringList QWindowsFileDialogHelper::selectedFiles() const
+QList<QUrl> QWindowsFileDialogHelper::selectedFiles() const
{
return m_data.selectedFiles();
}
@@ -1585,14 +1591,6 @@ void QWindowsFileDialogHelper::setFilter()
qDebug("%s" , __FUNCTION__);
}
-void QWindowsFileDialogHelper::setNameFilters(const QStringList &filters)
-{
- if (QWindowsContext::verboseDialogs)
- qDebug("%s" , __FUNCTION__);
- if (QWindowsNativeFileDialogBase *nfd = nativeFileDialog())
- nfd->setNameFilters(filters);
-}
-
void QWindowsFileDialogHelper::selectNameFilter(const QString &filter)
{
m_data.setSelectedNameFilter(filter);
@@ -1643,8 +1641,8 @@ private:
explicit QWindowsXpNativeFileDialog(const OptionsPtr &options, const QWindowsFileDialogSharedData &data);
void populateOpenFileName(OPENFILENAME *ofn, HWND owner) const;
- QStringList execExistingDir(HWND owner);
- QStringList execFileNames(HWND owner, int *selectedFilterIndex) const;
+ QList<QUrl> execExistingDir(HWND owner);
+ QList<QUrl> execFileNames(HWND owner, int *selectedFilterIndex) const;
const OptionsPtr m_options;
QString m_title;
@@ -1683,7 +1681,7 @@ QWindowsXpNativeFileDialog::QWindowsXpNativeFileDialog(const OptionsPtr &options
void QWindowsXpNativeFileDialog::exec(HWND owner)
{
int selectedFilterIndex = -1;
- const QStringList selectedFiles =
+ const QList<QUrl> selectedFiles =
m_options->fileMode() == QFileDialogOptions::DirectoryOnly ?
execExistingDir(owner) : execFileNames(owner, &selectedFilterIndex);
m_data.setSelectedFiles(selectedFiles);
@@ -1695,7 +1693,8 @@ void QWindowsXpNativeFileDialog::exec(HWND owner)
const QStringList nameFilters = m_options->nameFilters();
if (selectedFilterIndex >= 0 && selectedFilterIndex < nameFilters.size())
m_data.setSelectedNameFilter(nameFilters.at(selectedFilterIndex));
- m_data.setDirectory(QFileInfo(selectedFiles.front()).absolutePath());
+ QUrl firstFile = selectedFiles.front();
+ m_data.setDirectory(firstFile.adjusted(QUrl::RemoveFilename));
m_result = QPlatformDialogHelper::Accepted;
emit accepted();
}
@@ -1722,7 +1721,7 @@ int QWindowsXpNativeFileDialog::existingDirCallback(HWND hwnd, UINT uMsg, LPARAM
case BFFM_INITIALIZED: {
if (!m_title.isEmpty())
SetWindowText(hwnd, (wchar_t *)m_title.utf16());
- const QString initialFile = QDir::toNativeSeparators(m_data.directory());
+ const QString initialFile = QDir::toNativeSeparators(m_data.directory().toLocalFile());
if (!initialFile.isEmpty())
SendMessage(hwnd, BFFM_SETSELECTION, TRUE, LPARAM(initialFile.utf16()));
}
@@ -1738,7 +1737,7 @@ int QWindowsXpNativeFileDialog::existingDirCallback(HWND hwnd, UINT uMsg, LPARAM
return 0;
}
-QStringList QWindowsXpNativeFileDialog::execExistingDir(HWND owner)
+QList<QUrl> QWindowsXpNativeFileDialog::execExistingDir(HWND owner)
{
BROWSEINFO bi;
wchar_t initPath[MAX_PATH];
@@ -1750,12 +1749,12 @@ QStringList QWindowsXpNativeFileDialog::execExistingDir(HWND owner)
bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_STATUSTEXT | BIF_NEWDIALOGSTYLE;
bi.lpfn = xpFileDialogGetExistingDirCallbackProc;
bi.lParam = LPARAM(this);
- QStringList selectedFiles;
+ QList<QUrl> selectedFiles;
if (qt_LpItemIdList pItemIDList = SHBrowseForFolder(&bi)) {
wchar_t path[MAX_PATH];
path[0] = 0;
if (SHGetPathFromIDList(pItemIDList, path) && path[0])
- selectedFiles.push_back(QDir::cleanPath(QString::fromWCharArray(path)));
+ selectedFiles.push_back(QUrl::fromLocalFile(QDir::cleanPath(QString::fromWCharArray(path))));
IMalloc *pMalloc;
if (SHGetMalloc(&pMalloc) == NOERROR) {
pMalloc->Free(pItemIDList);
@@ -1807,7 +1806,7 @@ void QWindowsXpNativeFileDialog::populateOpenFileName(OPENFILENAME *ofn, HWND ow
QDir::toNativeSeparators(m_data.selectedFile()).remove(QLatin1Char('<')).
remove(QLatin1Char('>')).remove(QLatin1Char('"')).remove(QLatin1Char('|'));
ofn->lpstrFile = qStringToWCharArray(initiallySelectedFile, ofn->nMaxFile);
- ofn->lpstrInitialDir = qStringToWCharArray(QDir::toNativeSeparators(m_data.directory()));
+ ofn->lpstrInitialDir = qStringToWCharArray(QDir::toNativeSeparators(m_data.directory().toLocalFile()));
ofn->lpstrTitle = (wchar_t*)m_title.utf16();
// Determine lpstrDefExt. Note that the current MSDN docs document this
// member wrong. It should rather be documented as "the default extension
@@ -1832,25 +1831,27 @@ void QWindowsXpNativeFileDialog::populateOpenFileName(OPENFILENAME *ofn, HWND ow
ofn->Flags |= OFN_OVERWRITEPROMPT;
}
-QStringList QWindowsXpNativeFileDialog::execFileNames(HWND owner, int *selectedFilterIndex) const
+QList<QUrl> QWindowsXpNativeFileDialog::execFileNames(HWND owner, int *selectedFilterIndex) const
{
*selectedFilterIndex = -1;
OPENFILENAME ofn;
populateOpenFileName(&ofn, owner);
- QStringList result;
+ QList<QUrl> result;
const bool isSave = m_options->acceptMode() == QFileDialogOptions::AcceptSave;
if (isSave ? m_getSaveFileNameW(&ofn) : m_getOpenFileNameW(&ofn)) {
*selectedFilterIndex = ofn.nFilterIndex - 1;
- result.push_back(QDir::cleanPath(QString::fromWCharArray(ofn.lpstrFile)));
+ const QString dir = QDir::cleanPath(QString::fromWCharArray(ofn.lpstrFile));
+ result.push_back(QUrl::fromLocalFile(dir));
// For multiselection, the first item is the path followed
// by "\0<file1>\0<file2>\0\0".
if (ofn.Flags & (OFN_ALLOWMULTISELECT)) {
- wchar_t *ptr = ofn.lpstrFile + result.front().size() + 1;
+ wchar_t *ptr = ofn.lpstrFile + dir.size() + 1;
if (*ptr) {
- const QString path = result.takeAt(0) + QLatin1Char('/');
+ result.pop_front();
+ const QString path = dir + QLatin1Char('/');
while (*ptr) {
const QString fileName = QString::fromWCharArray(ptr);
- result.push_back(path + fileName);
+ result.push_back(QUrl::fromLocalFile(path + fileName));
ptr += fileName.size() + 1;
} // extract multiple files
} // has multiple files
@@ -1879,14 +1880,13 @@ public:
virtual bool supportsNonModalDialog(const QWindow * /* parent */ = 0) const { return false; }
virtual bool defaultNameFilterDisables() const
{ return true; }
- virtual void setDirectory(const QString &directory);
- virtual QString directory() const;
- virtual void selectFile(const QString &filename);
- virtual QStringList selectedFiles() const;
- virtual void setFilter() {}
- virtual void setNameFilters(const QStringList &);
- virtual void selectNameFilter(const QString &);
- virtual QString selectedNameFilter() const;
+ virtual void setDirectory(const QUrl &directory) Q_DECL_OVERRIDE;
+ virtual QUrl directory() const Q_DECL_OVERRIDE;
+ virtual void selectFile(const QUrl &url) Q_DECL_OVERRIDE;
+ virtual QList<QUrl> selectedFiles() const Q_DECL_OVERRIDE;
+ virtual void setFilter() Q_DECL_OVERRIDE {}
+ virtual void selectNameFilter(const QString &) Q_DECL_OVERRIDE;
+ virtual QString selectedNameFilter() const Q_DECL_OVERRIDE;
private:
virtual QWindowsNativeDialogBase *createNativeDialog();
@@ -1907,31 +1907,26 @@ QWindowsNativeDialogBase *QWindowsXpFileDialogHelper::createNativeDialog()
return 0;
}
-void QWindowsXpFileDialogHelper::setDirectory(const QString &directory)
+void QWindowsXpFileDialogHelper::setDirectory(const QUrl &directory)
{
m_data.setDirectory(directory); // Dialog cannot be updated at run-time.
}
-QString QWindowsXpFileDialogHelper::directory() const
+QUrl QWindowsXpFileDialogHelper::directory() const
{
return m_data.directory();
}
-void QWindowsXpFileDialogHelper::selectFile(const QString &filename)
+void QWindowsXpFileDialogHelper::selectFile(const QUrl &url)
{
- m_data.setSelectedFiles(QStringList(filename)); // Dialog cannot be updated at run-time.
+ m_data.setSelectedFiles(QList<QUrl>() << url); // Dialog cannot be updated at run-time.
}
-QStringList QWindowsXpFileDialogHelper::selectedFiles() const
+QList<QUrl> QWindowsXpFileDialogHelper::selectedFiles() const
{
return m_data.selectedFiles();
}
-void QWindowsXpFileDialogHelper::setNameFilters(const QStringList &)
-{
- // Dialog cannot be updated at run-time.
-}
-
void QWindowsXpFileDialogHelper::selectNameFilter(const QString &f)
{
m_data.setSelectedNameFilter(f); // Dialog cannot be updated at run-time.
diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp
index b7ccb5767e..a6bce6502b 100644
--- a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp
+++ b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp
@@ -838,8 +838,6 @@ error:
return i18n_name;
}
-Q_GUI_EXPORT void qt_registerAliasToFontFamily(const QString &familyName, const QString &alias);
-
static bool addFontToDatabase(const QString &familyName, uchar charSet,
const TEXTMETRIC *textmetric,
const FONTSIGNATURE *signature,
@@ -932,7 +930,7 @@ static bool addFontToDatabase(const QString &familyName, uchar charSet,
QFont::StyleItalic, stretch, antialias, scalable, size, fixed, writingSystems, 0);
if (!englishName.isEmpty())
- qt_registerAliasToFontFamily(familyName, englishName);
+ QPlatformFontDatabase::registerAliasToFontFamily(familyName, englishName);
return true;
}
diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp
index 7f97d58be4..6037c201ac 100644
--- a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp
+++ b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp
@@ -122,8 +122,6 @@ static FontFile * createFontFile(const QString &fileName, int index)
extern bool localizedName(const QString &name);
extern QString getEnglishName(const QString &familyName);
-Q_GUI_EXPORT void qt_registerAliasToFontFamily(const QString &familyName, const QString &alias);
-
static bool addFontToDatabase(const QString &familyName, uchar charSet,
const TEXTMETRIC *textmetric,
const FONTSIGNATURE *signature,
@@ -304,7 +302,7 @@ static bool addFontToDatabase(const QString &familyName, uchar charSet,
antialias, scalable, size, fixed, writingSystems, createFontFile(value, index));
if (!englishName.isEmpty())
- qt_registerAliasToFontFamily(faceName, englishName);
+ QPlatformFontDatabase::registerAliasToFontFamily(faceName, englishName);
return true;
}
diff --git a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp
index c0f1b3a000..7407d88f8b 100644
--- a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp
+++ b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp
@@ -215,7 +215,9 @@ QWindowsFontEngineDirectWrite::QWindowsFontEngineDirectWrite(IDWriteFontFace *di
if (QWindowsContext::verboseFonts)
qDebug("%s %g", __FUNCTION__, pixelSize);
- d->directWriteFactory->AddRef();
+ Q_ASSERT(m_directWriteFontFace);
+
+ m_fontEngineData->directWriteFactory->AddRef();
m_directWriteFontFace->AddRef();
fontDef.pixelSize = pixelSize;
@@ -237,19 +239,17 @@ QWindowsFontEngineDirectWrite::~QWindowsFontEngineDirectWrite()
void QWindowsFontEngineDirectWrite::collectMetrics()
{
- if (m_directWriteFontFace != 0) {
- DWRITE_FONT_METRICS metrics;
-
- m_directWriteFontFace->GetMetrics(&metrics);
- m_unitsPerEm = metrics.designUnitsPerEm;
-
- m_lineThickness = DESIGN_TO_LOGICAL(metrics.underlineThickness);
- m_ascent = DESIGN_TO_LOGICAL(metrics.ascent);
- m_descent = DESIGN_TO_LOGICAL(metrics.descent);
- m_xHeight = DESIGN_TO_LOGICAL(metrics.xHeight);
- m_lineGap = DESIGN_TO_LOGICAL(metrics.lineGap);
- m_underlinePosition = DESIGN_TO_LOGICAL(metrics.underlinePosition);
- }
+ DWRITE_FONT_METRICS metrics;
+
+ m_directWriteFontFace->GetMetrics(&metrics);
+ m_unitsPerEm = metrics.designUnitsPerEm;
+
+ m_lineThickness = DESIGN_TO_LOGICAL(metrics.underlineThickness);
+ m_ascent = DESIGN_TO_LOGICAL(metrics.ascent);
+ m_descent = DESIGN_TO_LOGICAL(metrics.descent);
+ m_xHeight = DESIGN_TO_LOGICAL(metrics.xHeight);
+ m_lineGap = DESIGN_TO_LOGICAL(metrics.lineGap);
+ m_underlinePosition = DESIGN_TO_LOGICAL(metrics.underlinePosition);
}
QFixed QWindowsFontEngineDirectWrite::underlinePosition() const
@@ -272,31 +272,24 @@ bool QWindowsFontEngineDirectWrite::getSfntTableData(uint tag, uchar *buffer, ui
{
bool ret = false;
- if (m_directWriteFontFace) {
- DWORD t = qbswap<quint32>(tag);
-
- const void *tableData = 0;
- void *tableContext = 0;
- UINT32 tableSize;
- BOOL exists;
- HRESULT hr = m_directWriteFontFace->TryGetFontTable(
- t, &tableData, &tableSize, &tableContext, &exists
- );
-
- if (SUCCEEDED(hr)) {
- if (exists) {
- if (!buffer) {
- *length = tableSize;
- ret = true;
- } else if (*length >= tableSize) {
- memcpy(buffer, tableData, tableSize);
- ret = true;
- }
- }
- m_directWriteFontFace->ReleaseFontTable(tableContext);
- } else {
- qErrnoWarning("%s: TryGetFontTable failed", __FUNCTION__);
+ const void *tableData = 0;
+ UINT32 tableSize;
+ void *tableContext = 0;
+ BOOL exists;
+ HRESULT hr = m_directWriteFontFace->TryGetFontTable(qbswap<quint32>(tag)
+ &tableData, &tableSize,
+ &tableContext, &exists);
+ if (SUCCEEDED(hr)) {
+ if (exists) {
+ ret = true;
+ if (buffer && *length >= tableSize)
+ memcpy(buffer, tableData, tableSize);
+ else
+ *length = tableSize;
}
+ m_directWriteFontFace->ReleaseFontTable(tableContext);
+ } else {
+ qErrnoWarning("%s: TryGetFontTable failed", __FUNCTION__);
}
return ret;
@@ -327,43 +320,43 @@ inline unsigned int getChar(const QChar *str, int &i, const int len)
bool QWindowsFontEngineDirectWrite::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs,
int *nglyphs, QFontEngine::ShaperFlags flags) const
{
- if (m_directWriteFontFace != 0) {
- QVarLengthArray<UINT32> codePoints(len);
- for (int i=0; i<len; ++i) {
- codePoints[i] = getChar(str, i, len);
- if (flags & QFontEngine::RightToLeft)
- codePoints[i] = QChar::mirroredChar(codePoints[i]);
- }
+ if (*nglyphs < len) {
+ *nglyphs = len;
+ return false;
+ }
- QVarLengthArray<UINT16> glyphIndices(len);
- HRESULT hr = m_directWriteFontFace->GetGlyphIndicesW(codePoints.data(),
- len,
- glyphIndices.data());
+ QVarLengthArray<UINT32> codePoints(len);
+ int actualLength = 0;
+ if (flags & QFontEngine::RightToLeft) {
+ for (int i = 0; i < len; ++i)
+ codePoints[actualLength++] = QChar::mirroredChar(getChar(str, i, len));
+ } else {
+ for (int i = 0; i < len; ++i)
+ codePoints[actualLength++] = getChar(str, i, len);
+ }
- if (SUCCEEDED(hr)) {
- for (int i=0; i<len; ++i)
- glyphs->glyphs[i] = glyphIndices[i];
+ QVarLengthArray<UINT16> glyphIndices(actualLength);
+ HRESULT hr = m_directWriteFontFace->GetGlyphIndicesW(codePoints.data(), actualLength,
+ glyphIndices.data());
+ if (FAILED(hr)) {
+ qErrnoWarning("%s: GetGlyphIndicesW failed", __FUNCTION__);
+ return false;
+ }
- *nglyphs = len;
- glyphs->numGlyphs = len;
+ for (int i = 0; i < actualLength; ++i)
+ glyphs->glyphs[i] = glyphIndices.at(i);
- if (!(flags & GlyphIndicesOnly))
- recalcAdvances(glyphs, 0);
+ *nglyphs = actualLength;
+ glyphs->numGlyphs = actualLength;
- return true;
- } else {
- qErrnoWarning("%s: GetGlyphIndicesW failed", __FUNCTION__);
- }
- }
+ if (!(flags & GlyphIndicesOnly))
+ recalcAdvances(glyphs, 0);
- return false;
+ return true;
}
void QWindowsFontEngineDirectWrite::recalcAdvances(QGlyphLayout *glyphs, QFontEngine::ShaperFlags) const
{
- if (m_directWriteFontFace == 0)
- return;
-
QVarLengthArray<UINT16> glyphIndices(glyphs->numGlyphs);
// ### Caching?
@@ -391,9 +384,6 @@ void QWindowsFontEngineDirectWrite::recalcAdvances(QGlyphLayout *glyphs, QFontEn
void QWindowsFontEngineDirectWrite::addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int nglyphs,
QPainterPath *path, QTextItem::RenderFlags flags)
{
- if (m_directWriteFontFace == 0)
- return;
-
QVarLengthArray<UINT16> glyphIndices(nglyphs);
QVarLengthArray<DWRITE_GLYPH_OFFSET> glyphOffsets(nglyphs);
QVarLengthArray<FLOAT> glyphAdvances(nglyphs);
@@ -439,9 +429,6 @@ glyph_metrics_t QWindowsFontEngineDirectWrite::boundingBox(const QGlyphLayout &g
glyph_metrics_t QWindowsFontEngineDirectWrite::boundingBox(glyph_t g)
{
- if (m_directWriteFontFace == 0)
- return glyph_metrics_t();
-
UINT16 glyphIndex = g;
DWRITE_GLYPH_METRICS glyphMetrics;
@@ -668,14 +655,14 @@ bool QWindowsFontEngineDirectWrite::canRender(const QChar *string, int len)
if (FAILED(hr)) {
qErrnoWarning("%s: GetGlyphIndices failed", __FUNCTION__);
return false;
- } else {
- for (int i=0; i<glyphIndices.size(); ++i) {
- if (glyphIndices.at(i) == 0)
- return false;
- }
+ }
- return true;
+ for (int i = 0; i < actualLength; ++i) {
+ if (glyphIndices.at(i) == 0)
+ return false;
}
+
+ return true;
}
QFontEngine::Type QWindowsFontEngineDirectWrite::type() const
diff --git a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h
index 106087f757..ab14cb49eb 100644
--- a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h
+++ b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h
@@ -107,8 +107,6 @@ public:
static QString fontNameSubstitute(const QString &familyName);
private:
- friend class QRawFontPrivate;
-
QImage imageForGlyph(glyph_t t, QFixed subPixelPosition, int margin, const QTransform &xform);
void collectMetrics();
diff --git a/src/plugins/platforms/windows/qwindowstabletsupport.cpp b/src/plugins/platforms/windows/qwindowstabletsupport.cpp
new file mode 100644
index 0000000000..4a5d7b5a78
--- /dev/null
+++ b/src/plugins/platforms/windows/qwindowstabletsupport.cpp
@@ -0,0 +1,473 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins 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 "qwindowstabletsupport.h"
+
+#ifndef QT_NO_TABLETEVENT
+
+#include "qwindowscontext.h"
+#include "qwindowskeymapper.h"
+#include "qwindowswindow.h"
+
+#include <qpa/qwindowsysteminterface.h>
+
+#include <QtGui/QTabletEvent>
+#include <QtGui/QScreen>
+#include <QtGui/QGuiApplication>
+#include <QtGui/QWindow>
+#include <QtCore/QDebug>
+#include <QtCore/QScopedArrayPointer>
+#include <QtCore/QtMath>
+
+#include <private/qguiapplication_p.h>
+#include <QtCore/private/qsystemlibrary_p.h>
+
+// Note: The definition of the PACKET structure in pktdef.h depends on this define.
+#define PACKETDATA (PK_X | PK_Y | PK_BUTTONS | PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE | PK_ORIENTATION | PK_CURSOR | PK_Z)
+#include <pktdef.h>
+
+QT_BEGIN_NAMESPACE
+
+enum {
+ PacketMode = 0,
+ TabletPacketQSize = 128,
+ DeviceIdMask = 0xFF6, // device type mask && device color mask
+ CursorTypeBitMask = 0x0F06 // bitmask to find the specific cursor type (see Wacom FAQ)
+};
+
+extern "C" LRESULT QT_WIN_CALLBACK qWindowsTabletSupportWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ switch (message) {
+ case WT_PROXIMITY:
+ if (QWindowsContext::instance()->tabletSupport()->translateTabletProximityEvent(wParam, lParam))
+ return 0;
+ break;
+ case WT_PACKET:
+ if (QWindowsContext::instance()->tabletSupport()->translateTabletPacketEvent())
+ return 0;
+ break;
+ }
+ return DefWindowProc(hwnd, message, wParam, lParam);
+}
+
+
+// Scale tablet coordinates to screen coordinates.
+
+static inline int sign(int x)
+{
+ return x >= 0 ? 1 : -1;
+}
+
+inline QPointF QWindowsTabletDeviceData::scaleCoordinates(int coordX, int coordY, const QRect &targetArea) const
+{
+ const int targetX = targetArea.x();
+ const int targetY = targetArea.y();
+ const int targetWidth = targetArea.width();
+ const int targetHeight = targetArea.height();
+
+ const qreal x = sign(targetWidth) == sign(maxX) ?
+ ((coordX - minX) * qAbs(targetWidth) / qAbs(qreal(maxX - minX))) + targetX :
+ ((qAbs(maxX) - (coordX - minX)) * qAbs(targetWidth) / qAbs(qreal(maxX - minX))) + targetX;
+
+ const qreal y = sign(targetHeight) == sign(maxY) ?
+ ((coordY - minY) * qAbs(targetHeight) / qAbs(qreal(maxY - minY))) + targetY :
+ ((qAbs(maxY) - (coordY - minY)) * qAbs(targetHeight) / qAbs(qreal(maxY - minY))) + targetY;
+
+ return QPointF(x, y);
+}
+
+QWindowsWinTab32DLL QWindowsTabletSupport::m_winTab32DLL;
+
+/*!
+ \class QWindowsWinTab32DLL QWindowsTabletSupport
+ \brief Functions from wintabl32.dll shipped with WACOM tablets used by QWindowsTabletSupport.
+
+ \internal
+ \ingroup qt-lighthouse-win
+*/
+
+bool QWindowsWinTab32DLL::init()
+{
+ if (wTInfo)
+ return true;
+ QSystemLibrary library(QStringLiteral("wintab32"));
+ if (!library.load())
+ return false;
+ wTOpen = (PtrWTOpen)library.resolve("WTOpenW");
+ wTClose = (PtrWTClose)library.resolve("WTClose");
+ wTInfo = (PtrWTInfo)library.resolve("WTInfoW");
+ wTEnable = (PtrWTEnable)library.resolve("WTEnable");
+ wTOverlap = (PtrWTEnable)library.resolve("WTOverlap");
+ wTPacketsGet = (PtrWTPacketsGet)library.resolve("WTPacketsGet");
+ wTGet = (PtrWTGet)library.resolve("WTGetW");
+ wTQueueSizeGet = (PtrWTQueueSizeGet)library.resolve("WTQueueSizeGet");
+ wTQueueSizeSet = (PtrWTQueueSizeSet)library.resolve("WTQueueSizeSet");
+ return wTOpen && wTClose && wTInfo && wTEnable && wTOverlap && wTPacketsGet && wTQueueSizeGet && wTQueueSizeSet;
+}
+
+/*!
+ \class QWindowsTabletSupport
+ \brief Tablet support for Windows.
+
+ Support for WACOM tablets.
+
+ \sa http://www.wacomeng.com/windows/docs/Wintab_v140.htm
+
+ \internal
+ \since 5.2
+ \ingroup qt-lighthouse-win
+*/
+
+QWindowsTabletSupport::QWindowsTabletSupport(HWND window, HCTX context)
+ : m_window(window)
+ , m_context(context)
+ , m_tiltSupport(false)
+ , m_currentDevice(-1)
+{
+ AXIS orientation[3];
+ // Some tablets don't support tilt, check if it is possible,
+ if (QWindowsTabletSupport::m_winTab32DLL.wTInfo(WTI_DEVICES, DVC_ORIENTATION, &orientation))
+ m_tiltSupport = orientation[0].axResolution && orientation[1].axResolution;
+}
+
+QWindowsTabletSupport::~QWindowsTabletSupport()
+{
+ QWindowsTabletSupport::m_winTab32DLL.wTClose(m_context);
+ DestroyWindow(m_window);
+}
+
+QWindowsTabletSupport *QWindowsTabletSupport::create()
+{
+ if (!m_winTab32DLL.init())
+ return 0;
+ const HWND window = QWindowsContext::instance()->createDummyWindow(QStringLiteral("TabletDummyWindow"),
+ L"TabletDummyWindow",
+ qWindowsTabletSupportWndProc);
+ if (!window) {
+ if (QWindowsContext::verboseTablet)
+ qWarning() << __FUNCTION__ << "Unable to create window for tablet.";
+ return 0;
+ }
+ LOGCONTEXT lcMine;
+ // build our context from the default context
+ QWindowsTabletSupport::m_winTab32DLL.wTInfo(WTI_DEFSYSCTX, 0, &lcMine);
+ // Go for the raw coordinates, the tablet event will return good stuff
+ lcMine.lcOptions |= CXO_MESSAGES | CXO_CSRMESSAGES;
+ lcMine.lcPktData = lcMine.lcMoveMask = PACKETDATA;
+ lcMine.lcPktMode = PacketMode;
+ lcMine.lcOutOrgX = 0;
+ lcMine.lcOutExtX = lcMine.lcInExtX;
+ lcMine.lcOutOrgY = 0;
+ lcMine.lcOutExtY = -lcMine.lcInExtY;
+ const HCTX context = QWindowsTabletSupport::m_winTab32DLL.wTOpen(window, &lcMine, true);
+ if (!context) {
+ if (QWindowsContext::verboseTablet)
+ qWarning() << __FUNCTION__ << "Unable to open tablet.";
+ DestroyWindow(window);
+ return 0;
+
+ }
+ // Set the size of the Packet Queue to the correct size
+ const int currentQueueSize = QWindowsTabletSupport::m_winTab32DLL.wTQueueSizeGet(context);
+ if (currentQueueSize != TabletPacketQSize) {
+ if (!QWindowsTabletSupport::m_winTab32DLL.wTQueueSizeSet(context, TabletPacketQSize)) {
+ if (!QWindowsTabletSupport::m_winTab32DLL.wTQueueSizeSet(context, currentQueueSize)) {
+ qWarning() << "Unable to set queue size on tablet. The tablet will not work.";
+ QWindowsTabletSupport::m_winTab32DLL.wTClose(context);
+ DestroyWindow(window);
+ return 0;
+ } // cannot restore old size
+ } // cannot set
+ } // mismatch
+ if (QWindowsContext::verboseTablet)
+ qDebug("Opened tablet context %p on window %p, changed packet queue size %d -> %d",
+ context, window, currentQueueSize, TabletPacketQSize);
+ return new QWindowsTabletSupport(window, context);
+}
+
+unsigned QWindowsTabletSupport::options() const
+{
+ UINT result = 0;
+ m_winTab32DLL.wTInfo(WTI_INTERFACE, IFC_CTXOPTIONS, &result);
+ return result;
+}
+
+QString QWindowsTabletSupport::description() const
+{
+ const unsigned size = m_winTab32DLL.wTInfo(WTI_INTERFACE, IFC_WINTABID, 0);
+ if (!size)
+ return QString();
+ QScopedPointer<TCHAR> winTabId(new TCHAR[size + 1]);
+ m_winTab32DLL.wTInfo(WTI_INTERFACE, IFC_WINTABID, winTabId.data());
+ WORD implementationVersion = 0;
+ m_winTab32DLL.wTInfo(WTI_INTERFACE, IFC_IMPLVERSION, &implementationVersion);
+ WORD specificationVersion = 0;
+ m_winTab32DLL.wTInfo(WTI_INTERFACE, IFC_SPECVERSION, &specificationVersion);
+ const unsigned opts = options();
+ QString result = QString::fromLatin1("%1 specification: v%2.%3 implementation: v%4.%5 options: 0x%6")
+ .arg(QString::fromWCharArray(winTabId.data()))
+ .arg(specificationVersion >> 8).arg(specificationVersion & 0xFF)
+ .arg(implementationVersion >> 8).arg(implementationVersion & 0xFF)
+ .arg(opts, 0, 16);
+ if (opts & CXO_MESSAGES)
+ result += QStringLiteral(" CXO_MESSAGES");
+ if (opts & CXO_CSRMESSAGES)
+ result += QStringLiteral(" CXO_CSRMESSAGES");
+ if (m_tiltSupport)
+ result += QStringLiteral(" tilt");
+ return result;
+}
+
+void QWindowsTabletSupport::notifyActivate()
+{
+ // Cooperate with other tablet applications, but when we get focus, I want to use the tablet.
+ const bool result = QWindowsTabletSupport::m_winTab32DLL.wTEnable(m_context, true)
+ && QWindowsTabletSupport::m_winTab32DLL.wTOverlap(m_context, true);
+ if (QWindowsContext::verboseTablet)
+ qDebug() << __FUNCTION__ << result;
+}
+
+static inline int indexOfDevice(const QVector<QWindowsTabletDeviceData> &devices, qint64 uniqueId)
+{
+ for (int i = 0; i < devices.size(); ++i)
+ if (devices.at(i).uniqueId == uniqueId)
+ return i;
+ return -1;
+}
+
+static inline QTabletEvent::TabletDevice deviceType(const UINT cursorType)
+{
+ if (((cursorType & 0x0006) == 0x0002) && ((cursorType & CursorTypeBitMask) != 0x0902))
+ return QTabletEvent::Stylus;
+ switch (cursorType & CursorTypeBitMask) {
+ case 0x0802:
+ return QTabletEvent::Stylus;
+ case 0x0902:
+ return QTabletEvent::Airbrush;
+ case 0x0004:
+ return QTabletEvent::FourDMouse;
+ case 0x0006:
+ return QTabletEvent::Puck;
+ case 0x0804:
+ return QTabletEvent::RotationStylus;
+ default:
+ break;
+ }
+ return QTabletEvent::NoDevice;
+}
+
+static inline QTabletEvent::PointerType pointerType(unsigned currentCursor)
+{
+ switch (currentCursor % 3) { // %3 for dual track
+ case 0:
+ return QTabletEvent::Cursor;
+ case 1:
+ return QTabletEvent::Pen;
+ case 2:
+ return QTabletEvent::Eraser;
+ default:
+ break;
+ }
+ return QTabletEvent::UnknownPointer;
+}
+
+QDebug operator<<(QDebug d, const QWindowsTabletDeviceData &t)
+{
+ d << "TabletDevice id:" << t.uniqueId << " pressure: " << t.minPressure
+ << ".." << t.maxPressure << " tan pressure: " << t.minTanPressure << ".."
+ << t.maxTanPressure << " area:" << t.minX << t.minY <<t.minZ
+ << ".." << t.maxX << t.maxY << t.maxZ << " device " << t.currentDevice
+ << " pointer " << t.currentPointerType;
+ return d;
+}
+
+QWindowsTabletDeviceData QWindowsTabletSupport::tabletInit(const quint64 uniqueId, const UINT cursorType) const
+{
+ QWindowsTabletDeviceData result;
+ result.uniqueId = uniqueId;
+ /* browse WinTab's many info items to discover pressure handling. */
+ AXIS axis;
+ LOGCONTEXT lc;
+ /* get the current context for its device variable. */
+ QWindowsTabletSupport::m_winTab32DLL.wTGet(m_context, &lc);
+ /* get the size of the pressure axis. */
+ QWindowsTabletSupport::m_winTab32DLL.wTInfo(WTI_DEVICES + lc.lcDevice, DVC_NPRESSURE, &axis);
+ result.minPressure = int(axis.axMin);
+ result.maxPressure = int(axis.axMax);
+
+ QWindowsTabletSupport::m_winTab32DLL.wTInfo(WTI_DEVICES + lc.lcDevice, DVC_TPRESSURE, &axis);
+ result.minTanPressure = int(axis.axMin);
+ result.maxTanPressure = int(axis.axMax);
+
+ LOGCONTEXT defaultLc;
+ /* get default region */
+ QWindowsTabletSupport::m_winTab32DLL.wTInfo(WTI_DEFCONTEXT, 0, &defaultLc);
+ result.maxX = int(defaultLc.lcInExtX) - int(defaultLc.lcInOrgX);
+ result.maxY = int(defaultLc.lcInExtY) - int(defaultLc.lcInOrgY);
+ result.maxZ = int(defaultLc.lcInExtZ) - int(defaultLc.lcInOrgZ);
+ result.currentDevice = deviceType(cursorType);
+ return result;
+}
+
+bool QWindowsTabletSupport::translateTabletProximityEvent(WPARAM /* wParam */, LPARAM lParam)
+{
+ const bool enteredProximity = LOWORD(lParam) != 0;
+ PACKET proximityBuffer[1]; // we are only interested in the first packet in this case
+ const int totalPacks = QWindowsTabletSupport::m_winTab32DLL.wTPacketsGet(m_context, 1, proximityBuffer);
+ if (!totalPacks)
+ return false;
+ const UINT currentCursor = proximityBuffer[0].pkCursor;
+ UINT physicalCursorId;
+ QWindowsTabletSupport::m_winTab32DLL.wTInfo(WTI_CURSORS + currentCursor, CSR_PHYSID, &physicalCursorId);
+ UINT cursorType;
+ QWindowsTabletSupport::m_winTab32DLL.wTInfo(WTI_CURSORS + currentCursor, CSR_TYPE, &cursorType);
+ const qint64 uniqueId = (qint64(cursorType & DeviceIdMask) << 32L) | qint64(physicalCursorId);
+ // initializing and updating the cursor should be done in response to
+ // WT_CSRCHANGE. We do it in WT_PROXIMITY because some wintab never send
+ // the event WT_CSRCHANGE even if asked with CXO_CSRMESSAGES
+ m_currentDevice = indexOfDevice(m_devices, uniqueId);
+ if (m_currentDevice < 0) {
+ m_currentDevice = m_devices.size();
+ m_devices.push_back(tabletInit(uniqueId, cursorType));
+ }
+ m_devices[m_currentDevice].currentPointerType = pointerType(currentCursor);
+ if (QWindowsContext::verboseTablet)
+ qDebug() << __FUNCTION__ << (enteredProximity ? "enter" : "leave")
+ << " proximity for device #"
+ << m_currentDevice << m_devices.at(m_currentDevice);
+ if (enteredProximity) {
+ QWindowSystemInterface::handleTabletEnterProximityEvent(m_devices.at(m_currentDevice).currentDevice,
+ m_devices.at(m_currentDevice).currentPointerType,
+ m_devices.at(m_currentDevice).uniqueId);
+ } else {
+ QWindowSystemInterface::handleTabletLeaveProximityEvent(m_devices.at(m_currentDevice).currentDevice,
+ m_devices.at(m_currentDevice).currentPointerType,
+ m_devices.at(m_currentDevice).uniqueId);
+ }
+ return true;
+}
+
+bool QWindowsTabletSupport::translateTabletPacketEvent()
+{
+ static PACKET localPacketBuf[TabletPacketQSize]; // our own tablet packet queue.
+ const int packetCount = QWindowsTabletSupport::m_winTab32DLL.wTPacketsGet(m_context, TabletPacketQSize, &localPacketBuf);
+ if (!packetCount || m_currentDevice < 0)
+ return false;
+
+ const int currentDevice = m_devices.at(m_currentDevice).currentDevice;
+ const int currentPointer = m_devices.at(m_currentDevice).currentPointerType;
+
+ // When entering proximity, the tablet driver snaps the mouse pointer to the
+ // tablet position scaled to the virtual desktop and keeps it in sync.
+ const QRect virtualDesktopArea = QGuiApplication::primaryScreen()->virtualGeometry();
+
+ if (QWindowsContext::verboseTablet)
+ qDebug() << __FUNCTION__ << "processing " << packetCount
+ << "target:" << QGuiApplicationPrivate::tabletPressTarget;
+
+ const Qt::KeyboardModifiers keyboardModifiers = QWindowsKeyMapper::queryKeyboardModifiers();
+
+ for (int i = 0; i < packetCount ; ++i) {
+ const PACKET &packet = localPacketBuf[i];
+
+ const int z = currentDevice == QTabletEvent::FourDMouse ? int(packet.pkZ) : 0;
+ const QPointF globalPosF = m_devices.at(m_currentDevice).scaleCoordinates(packet.pkX, packet.pkY, virtualDesktopArea);
+
+ QWindow *target = QGuiApplicationPrivate::tabletPressTarget; // Pass to window that grabbed it.
+ const QPoint globalPos = globalPosF.toPoint();
+ if (!target)
+ if (QPlatformWindow *pw = QWindowsContext::instance()->findPlatformWindowAt(GetDesktopWindow(), globalPos, CWP_SKIPINVISIBLE | CWP_SKIPTRANSPARENT))
+ target = pw->window();
+ if (!target)
+ continue;
+
+ const QPoint localPos = target->mapFromGlobal(globalPos);
+
+ const qreal pressureNew = packet.pkButtons && (currentPointer == QTabletEvent::Pen || currentPointer == QTabletEvent::Eraser) ?
+ m_devices.at(m_currentDevice).scalePressure(packet.pkNormalPressure) :
+ qreal(0);
+ const qreal tangentialPressure = currentDevice == QTabletEvent::Airbrush ?
+ m_devices.at(m_currentDevice).scaleTangentialPressure(packet.pkTangentPressure) :
+ qreal(0);
+
+ int tiltX = 0;
+ int tiltY = 0;
+ qreal rotation = 0;
+ if (m_tiltSupport) {
+ // Convert from azimuth and altitude to x tilt and y tilt. What
+ // follows is the optimized version. Here are the equations used:
+ // X = sin(azimuth) * cos(altitude)
+ // Y = cos(azimuth) * cos(altitude)
+ // Z = sin(altitude)
+ // X Tilt = arctan(X / Z)
+ // Y Tilt = arctan(Y / Z)
+ const double radAzim = (packet.pkOrientation.orAzimuth / 10) * (M_PI / 180);
+ const double tanAlt = tan((abs(packet.pkOrientation.orAltitude / 10)) * (M_PI / 180));
+
+ const double degX = atan(sin(radAzim) / tanAlt);
+ const double degY = atan(cos(radAzim) / tanAlt);
+ tiltX = int(degX * (180 / M_PI));
+ tiltY = int(-degY * (180 / M_PI));
+ rotation = packet.pkOrientation.orTwist;
+ }
+
+ if (QWindowsContext::verboseTablet > 1) {
+ qDebug()
+ << "Packet #" << i << '/' << packetCount << "button:" << packet.pkButtons
+ << globalPosF << z << "to:" << target << localPos << "(packet" << packet.pkX
+ << packet.pkY << ") dev:" << currentDevice << "pointer:"
+ << currentPointer << "P:" << pressureNew << "tilt:" << tiltX << ','
+ << tiltY << "tanP:" << tangentialPressure << "rotation:" << rotation;
+ }
+
+ QWindowSystemInterface::handleTabletEvent(target, packet.pkButtons, localPos, globalPosF,
+ currentDevice, currentPointer,
+ pressureNew, tiltX, tiltY,
+ tangentialPressure, rotation, z,
+ m_devices.at(m_currentDevice).uniqueId,
+ keyboardModifiers);
+ }
+ return true;
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_TABLETEVENT
diff --git a/src/plugins/platforms/windows/qwindowstabletsupport.h b/src/plugins/platforms/windows/qwindowstabletsupport.h
new file mode 100644
index 0000000000..12f96b618d
--- /dev/null
+++ b/src/plugins/platforms/windows/qwindowstabletsupport.h
@@ -0,0 +1,142 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins 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$
+**
+****************************************************************************/
+
+#ifndef QWINDOWSTABLETSUPPORT_H
+#define QWINDOWSTABLETSUPPORT_H
+
+#include "qtwindowsglobal.h"
+
+#if !defined(QT_NO_TABLETEVENT) && !defined(Q_OS_WINCE)
+
+#include <QtCore/QVector>
+#include <QtCore/QPointF>
+
+#include <wintab.h>
+
+QT_BEGIN_NAMESPACE
+
+class QDebug;
+class QWindow;
+class QRect;
+
+struct QWindowsWinTab32DLL
+{
+ QWindowsWinTab32DLL() : wTOpen(0), wTClose(0), wTInfo(0), wTEnable(0), wTOverlap(0), wTPacketsGet(0), wTGet(0),
+ wTQueueSizeGet(0), wTQueueSizeSet(0) {}
+
+ bool init();
+
+ typedef HCTX (API *PtrWTOpen)(HWND, LPLOGCONTEXT, BOOL);
+ typedef BOOL (API *PtrWTClose)(HCTX);
+ typedef UINT (API *PtrWTInfo)(UINT, UINT, LPVOID);
+ typedef BOOL (API *PtrWTEnable)(HCTX, BOOL);
+ typedef BOOL (API *PtrWTOverlap)(HCTX, BOOL);
+ typedef int (API *PtrWTPacketsGet)(HCTX, int, LPVOID);
+ typedef BOOL (API *PtrWTGet)(HCTX, LPLOGCONTEXT);
+ typedef int (API *PtrWTQueueSizeGet)(HCTX);
+ typedef BOOL (API *PtrWTQueueSizeSet)(HCTX, int);
+
+ PtrWTOpen wTOpen;
+ PtrWTClose wTClose;
+ PtrWTInfo wTInfo;
+ PtrWTEnable wTEnable;
+ PtrWTOverlap wTOverlap;
+ PtrWTPacketsGet wTPacketsGet;
+ PtrWTGet wTGet;
+ PtrWTQueueSizeGet wTQueueSizeGet;
+ PtrWTQueueSizeSet wTQueueSizeSet;
+};
+
+struct QWindowsTabletDeviceData
+{
+ QWindowsTabletDeviceData() : minPressure(0), maxPressure(0), minTanPressure(0),
+ maxTanPressure(0), minX(0), maxX(0), minY(0), maxY(0), minZ(0), maxZ(0),
+ uniqueId(0), currentDevice(0), currentPointerType(0) {}
+
+ QPointF scaleCoordinates(int coordX, int coordY,const QRect &targetArea) const;
+ qreal scalePressure(qreal p) const { return p / qreal(maxPressure - minPressure); }
+ qreal scaleTangentialPressure(qreal p) const { return p / qreal(maxTanPressure - minTanPressure); }
+
+ int minPressure;
+ int maxPressure;
+ int minTanPressure;
+ int maxTanPressure;
+ int minX, maxX, minY, maxY, minZ, maxZ;
+ qint64 uniqueId;
+ int currentDevice;
+ int currentPointerType;
+};
+
+QDebug operator<<(QDebug d, const QWindowsTabletDeviceData &t);
+
+class QWindowsTabletSupport
+{
+ Q_DISABLE_COPY(QWindowsTabletSupport)
+
+ explicit QWindowsTabletSupport(HWND window, HCTX context);
+
+public:
+ ~QWindowsTabletSupport();
+
+ static QWindowsTabletSupport *create();
+
+ void notifyActivate();
+ QString description() const;
+
+ bool translateTabletProximityEvent(WPARAM wParam, LPARAM lParam);
+ bool translateTabletPacketEvent();
+
+private:
+ unsigned options() const;
+ QWindowsTabletDeviceData tabletInit(const quint64 uniqueId, const UINT cursorType) const;
+
+ static QWindowsWinTab32DLL m_winTab32DLL;
+ const HWND m_window;
+ const HCTX m_context;
+ bool m_tiltSupport;
+ QVector<QWindowsTabletDeviceData> m_devices;
+ int m_currentDevice;
+};
+
+QT_END_NAMESPACE
+
+#endif // !QT_NO_TABLETEVENT && !Q_OS_WINCE
+#endif // QWINDOWSTABLETSUPPORT_H
diff --git a/src/plugins/platforms/windows/qwindowstheme.cpp b/src/plugins/platforms/windows/qwindowstheme.cpp
index 844e46eec5..83d93b08bd 100644
--- a/src/plugins/platforms/windows/qwindowstheme.cpp
+++ b/src/plugins/platforms/windows/qwindowstheme.cpp
@@ -404,6 +404,8 @@ void QWindowsTheme::refreshFonts()
const QFont messageBoxFont = QWindowsFontDatabase::LOGFONT_to_QFont(ncm.lfMessageFont);
const QFont statusFont = QWindowsFontDatabase::LOGFONT_to_QFont(ncm.lfStatusFont);
const QFont titleFont = QWindowsFontDatabase::LOGFONT_to_QFont(ncm.lfCaptionFont);
+ QFont fixedFont(QStringLiteral("Courier New"), messageBoxFont.pointSize());
+ fixedFont.setStyleHint(QFont::TypeWriter);
LOGFONT lfIconTitleFont;
SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(lfIconTitleFont), &lfIconTitleFont, 0);
@@ -418,6 +420,7 @@ void QWindowsTheme::refreshFonts()
m_fonts[MdiSubWindowTitleFont] = new QFont(titleFont);
m_fonts[DockWidgetTitleFont] = new QFont(titleFont);
m_fonts[ItemViewFont] = new QFont(iconTitleFont);
+ m_fonts[FixedFont] = new QFont(fixedFont);
if (QWindowsContext::verboseTheming)
qDebug() << __FUNCTION__ << '\n'
@@ -595,7 +598,8 @@ public:
void operator delete (void *) {}
};
-QPixmap QWindowsTheme::fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &size) const
+QPixmap QWindowsTheme::fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &size,
+ QPlatformTheme::IconOptions iconOptions) const
{
/* We don't use the variable, but by storing it statically, we
* ensure CoInitialize is only called once. */
@@ -604,6 +608,8 @@ QPixmap QWindowsTheme::fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &s
static QCache<QString, FakePointer<int> > dirIconEntryCache(1000);
static QMutex mx;
+ static int defaultFolderIIcon = 0;
+ const bool useDefaultFolderIcon = iconOptions & QPlatformTheme::DontUseCustomDirectoryIcons;
QPixmap pixmap;
const QString filePath = QDir::toNativeSeparators(fileInfo.filePath());
@@ -612,7 +618,8 @@ QPixmap QWindowsTheme::fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &s
bool cacheableDirIcon = fileInfo.isDir() && !fileInfo.isRoot();
if (cacheableDirIcon) {
QMutexLocker locker(&mx);
- int iIcon = **dirIconEntryCache.object(filePath);
+ int iIcon = (useDefaultFolderIcon && defaultFolderIIcon) ? defaultFolderIIcon
+ : **dirIconEntryCache.object(filePath);
if (iIcon) {
QPixmapCache::find(dirIconPixmapCacheKey(iIcon, iconSize), pixmap);
if (pixmap.isNull()) // Let's keep both caches in sync
@@ -629,13 +636,24 @@ QPixmap QWindowsTheme::fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &s
#else
iconSize|SHGFI_SYSICONINDEX;
#endif // Q_OS_WINCE
- unsigned long val = SHGetFileInfo((const wchar_t *)filePath.utf16(), 0,
- &info, sizeof(SHFILEINFO), flags);
+ unsigned long val = 0;
+ if (cacheableDirIcon && useDefaultFolderIcon) {
+ flags |= SHGFI_USEFILEATTRIBUTES;
+ val = SHGetFileInfo(L"dummy",
+ FILE_ATTRIBUTE_DIRECTORY,
+ &info, sizeof(SHFILEINFO), flags);
+ } else {
+ val = SHGetFileInfo(reinterpret_cast<const wchar_t *>(filePath.utf16()), 0,
+ &info, sizeof(SHFILEINFO), flags);
+ }
// Even if GetFileInfo returns a valid result, hIcon can be empty in some cases
if (val && info.hIcon) {
QString key;
if (cacheableDirIcon) {
+ if (useDefaultFolderIcon && !defaultFolderIIcon)
+ defaultFolderIIcon = info.iIcon;
+
//using the unique icon index provided by windows save us from duplicate keys
key = dirIconPixmapCacheKey(info.iIcon, iconSize);
QPixmapCache::find(key, pixmap);
diff --git a/src/plugins/platforms/windows/qwindowstheme.h b/src/plugins/platforms/windows/qwindowstheme.h
index bbd7f4623f..9346621d59 100644
--- a/src/plugins/platforms/windows/qwindowstheme.h
+++ b/src/plugins/platforms/windows/qwindowstheme.h
@@ -68,7 +68,8 @@ public:
{ return m_fonts[type]; }
virtual QPixmap standardPixmap(StandardPixmap sp, const QSizeF &size) const;
- virtual QPixmap fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &size) const;
+ virtual QPixmap fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &size,
+ QPlatformTheme::IconOptions iconOptions = 0) const;
void windowsThemeChanged(QWindow *window);
diff --git a/src/plugins/platforms/windows/windows.pro b/src/plugins/platforms/windows/windows.pro
index 3aa9caaa0f..d4e6e558ed 100644
--- a/src/plugins/platforms/windows/windows.pro
+++ b/src/plugins/platforms/windows/windows.pro
@@ -102,6 +102,12 @@ contains(QT_CONFIG, opengles2) {
}
}
+!wince*:!contains( DEFINES, QT_NO_TABLETEVENT ) {
+ INCLUDEPATH += ../../../3rdparty/wintab
+ HEADERS += qwindowstabletsupport.h
+ SOURCES += qwindowstabletsupport.cpp
+}
+
contains(QT_CONFIG, freetype) {
DEFINES *= QT_NO_FONTCONFIG
QT_FREETYPE_DIR = $$QT_SOURCE_TREE/src/3rdparty/freetype
diff --git a/src/plugins/platforms/xcb/main.cpp b/src/plugins/platforms/xcb/main.cpp
index be5a0e3501..09e60f8d4c 100644
--- a/src/plugins/platforms/xcb/main.cpp
+++ b/src/plugins/platforms/xcb/main.cpp
@@ -49,13 +49,13 @@ class QXcbIntegrationPlugin : public QPlatformIntegrationPlugin
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QPA.QPlatformIntegrationFactoryInterface.5.1" FILE "xcb.json")
public:
- QPlatformIntegration *create(const QString&, const QStringList&);
+ QPlatformIntegration *create(const QString&, const QStringList&, int &, char **);
};
-QPlatformIntegration* QXcbIntegrationPlugin::create(const QString& system, const QStringList& parameters)
+QPlatformIntegration* QXcbIntegrationPlugin::create(const QString& system, const QStringList& parameters, int &argc, char **argv)
{
if (system.toLower() == "xcb")
- return new QXcbIntegration(parameters);
+ return new QXcbIntegration(parameters, argc, argv);
return 0;
}
diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp
index 01af23377e..c4dd58667d 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection.cpp
@@ -1385,6 +1385,8 @@ static const char * xcb_atomnames = {
"Abs MT Pressure\0"
"Abs MT Tracking ID\0"
"Max Contacts\0"
+ "Rel X\0"
+ "Rel Y\0"
// XInput2 tablet
"Abs X\0"
"Abs Y\0"
@@ -1401,11 +1403,16 @@ static const char * xcb_atomnames = {
"_XSETTINGS_SETTINGS\0" // \0\0 terminates loop.
};
-xcb_atom_t QXcbConnection::atom(QXcbAtom::Atom atom)
+xcb_atom_t QXcbConnection::atom(QXcbAtom::Atom atom) const
{
return m_allAtoms[atom];
}
+QXcbAtom::Atom QXcbConnection::qatom(xcb_atom_t xatom) const
+{
+ return static_cast<QXcbAtom::Atom>(qFind(m_allAtoms, m_allAtoms + QXcbAtom::NAtoms, xatom) - m_allAtoms);
+}
+
void QXcbConnection::initializeAllAtoms() {
const char *names[QXcbAtom::NAtoms];
const char *ptr = xcb_atomnames;
diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h
index 2a5ff0b1cb..8f568c6c25 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.h
+++ b/src/plugins/platforms/xcb/qxcbconnection.h
@@ -256,6 +256,8 @@ namespace QXcbAtom {
AbsMTPressure,
AbsMTTrackingID,
MaxContacts,
+ RelX,
+ RelY,
// XInput2 tablet
AbsX,
AbsY,
@@ -346,7 +348,8 @@ public:
const QList<QXcbScreen *> &screens() const { return m_screens; }
int primaryScreen() const { return m_primaryScreen; }
- xcb_atom_t atom(QXcbAtom::Atom atom);
+ xcb_atom_t atom(QXcbAtom::Atom atom) const;
+ QXcbAtom::Atom qatom(xcb_atom_t atom) const;
xcb_atom_t internAtom(const char *name);
QByteArray atomName(xcb_atom_t atom);
@@ -478,8 +481,6 @@ private:
};
QHash<int, ValuatorClassInfo> valuatorInfo;
};
- void xi2QueryTabletData(void *dev, TabletData *tabletData); // use no XI stuff in headers
- void xi2SetupTabletDevices();
bool xi2HandleTabletEvent(void *event, TabletData *tabletData);
void xi2ReportTabletEvent(const TabletData &tabletData, void *event);
QVector<TabletData> m_tabletData;
diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
index 991c82eaaa..466193b7a1 100644
--- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
@@ -44,8 +44,8 @@
#include "qxcbwindow.h"
#include "qtouchdevice.h"
#include <qpa/qwindowsysteminterface.h>
-//#define XI2_TOUCH_DEBUG
-#ifdef XI2_TOUCH_DEBUG
+//#define XI2_DEBUG
+#ifdef XI2_DEBUG
#include <QDebug>
#endif
@@ -63,20 +63,19 @@ struct XInput2DeviceData {
}
XIDeviceInfo *xiDeviceInfo;
QTouchDevice *qtTouchDevice;
-};
-#ifndef QT_NO_TABLETEVENT
-static inline bool q_xi2_is_tablet(XIDeviceInfo *dev)
-{
- QByteArray name(dev->name);
- name = name.toLower();
- // Cannot just check for "wacom" because that would also pick up the touch and tablet-button devices.
- return name.contains("stylus") || name.contains("eraser");
-}
-#endif // QT_NO_TABLETEVENT
+ // Stuff that is relevant only for touchpads
+ QHash<int, QPointF> pointPressedPosition; // in screen coordinates where each point was pressed
+ QPointF firstPressedPosition; // in screen coordinates where the first point was pressed
+ QPointF firstPressedNormalPosition; // device coordinates (0 to 1, 0 to 1) where the first point was pressed
+ QSizeF size; // device size in mm
+};
void QXcbConnection::initializeXInput2()
{
+#ifndef QT_NO_TABLETEVENT
+ m_tabletData.clear();
+#endif
Display *xDisplay = static_cast<Display *>(m_xlib_display);
if (XQueryExtension(xDisplay, "XInputExtension", &m_xiOpCode, &m_xiEventBase, &m_xiErrorBase)) {
int xiMajor = 2;
@@ -88,13 +87,76 @@ void QXcbConnection::initializeXInput2()
m_xi2Enabled = true;
}
if (m_xi2Enabled) {
+#ifdef XI2_DEBUG
+ qDebug("XInput version %d.%d is supported", xiMajor, m_xi2Minor);
+#endif
+ int deviceCount = 0;
+ XIDeviceInfo *devices = XIQueryDevice(xDisplay, XIAllDevices, &deviceCount);
+ for (int i = 0; i < deviceCount; ++i) {
+ // Only non-master pointing devices are relevant here.
+ if (devices[i].use != XISlavePointer)
+ continue;
+#ifdef XI2_DEBUG
+ qDebug() << "input device "<< devices[i].name;
+#endif
#ifndef QT_NO_TABLETEVENT
- // Tablet support: Find the stylus-related devices.
- xi2SetupTabletDevices();
+ TabletData tabletData;
+#endif
+ for (int c = 0; c < devices[i].num_classes; ++c) {
+ switch (devices[i].classes[c]->type) {
+ case XIValuatorClass: {
+ XIValuatorClassInfo *vci = reinterpret_cast<XIValuatorClassInfo *>(devices[i].classes[c]);
+ const int valuatorAtom = qatom(vci->label);
+#ifdef XI2_DEBUG
+ qDebug() << " has valuator" << atomName(vci->label) << "recognized?" << (valuatorAtom < QXcbAtom::NAtoms);
+#endif
+#ifndef QT_NO_TABLETEVENT
+ if (valuatorAtom < QXcbAtom::NAtoms) {
+ TabletData::ValuatorClassInfo info;
+ info.minVal = vci->min;
+ info.maxVal = vci->max;
+ info.number = vci->number;
+ tabletData.valuatorInfo[valuatorAtom] = info;
+ }
#endif // QT_NO_TABLETEVENT
-#ifdef XI2_TOUCH_DEBUG
- qDebug("XInput version %d.%d is supported", xiMajor, m_xi2Minor);
+ } break;
+ default:
+ break;
+ }
+ }
+ bool isTablet = false;
+#ifndef QT_NO_TABLETEVENT
+ // If we have found the valuators which we expect a tablet to have, assume it's a tablet.
+ if (tabletData.valuatorInfo.contains(QXcbAtom::AbsX) &&
+ tabletData.valuatorInfo.contains(QXcbAtom::AbsY) &&
+ tabletData.valuatorInfo.contains(QXcbAtom::AbsPressure)) {
+ tabletData.deviceId = devices[i].deviceid;
+ tabletData.pointerType = QTabletEvent::Pen;
+ if (QByteArray(devices[i].name).toLower().contains("eraser"))
+ tabletData.pointerType = QTabletEvent::Eraser;
+ m_tabletData.append(tabletData);
+ isTablet = true;
+#ifdef XI2_DEBUG
+ qDebug() << " it's a tablet with pointer type" << tabletData.pointerType;
#endif
+ }
+#endif // QT_NO_TABLETEVENT
+#ifdef XI2_DEBUG
+ if (!isTablet) {
+ XInput2DeviceData *dev = deviceForId(devices[i].deviceid);
+ if (dev && dev->qtTouchDevice->type() == QTouchDevice::TouchScreen)
+ qDebug(" it's a touchscreen with type %d capabilities 0x%X max touch points %d",
+ dev->qtTouchDevice->type(), (unsigned int)dev->qtTouchDevice->capabilities(),
+ dev->qtTouchDevice->maximumTouchPoints());
+ else if (dev && dev->qtTouchDevice->type() == QTouchDevice::TouchPad)
+ qDebug(" it's a touchpad with type %d capabilities 0x%X max touch points %d size %f x %f",
+ dev->qtTouchDevice->type(), (unsigned int)dev->qtTouchDevice->capabilities(),
+ dev->qtTouchDevice->maximumTouchPoints(),
+ dev->size.width(), dev->size.height());
+ }
+#endif // XI2_DEBUG
+ }
+ XIFreeDeviceInfo(devices);
}
}
}
@@ -113,25 +175,24 @@ void QXcbConnection::xi2Select(xcb_window_t window)
unsigned char *xiBitMask = reinterpret_cast<unsigned char *>(&bitMask);
#ifdef XCB_USE_XINPUT22
- // Select touch events on all master devices indiscriminately.
bitMask |= XI_TouchBeginMask;
bitMask |= XI_TouchUpdateMask;
bitMask |= XI_TouchEndMask;
XIEventMask mask;
- mask.deviceid = XIAllMasterDevices;
mask.mask_len = sizeof(bitMask);
mask.mask = xiBitMask;
- Status result = XISelectEvents(xDisplay, window, &mask, 1);
- // If we have XInput 2.2 and successfully enable touch on the master
- // devices, then evdev touchscreens will provide touch only. In most other
- // cases, there will be emulated mouse events, because true X11 touch
- // support is so new that for the older drivers, mouse emulation was the
- // only way; and it's still the fallback even with the modern evdev driver.
- // But if neither Qt nor X11 does mouse emulation, it will not be possible
- // to interact with mouse-oriented QWidgets; so we have to let Qt do it.
- if (m_xi2Minor >= 2 && result == Success)
- has_touch_without_mouse_emulation = true;
-#endif
+ // Enable each touchscreen
+ foreach (XInput2DeviceData *dev, m_touchDevices.values()) {
+ mask.deviceid = dev->xiDeviceInfo->deviceid;
+ Status result = XISelectEvents(xDisplay, window, &mask, 1);
+ // If we have XInput >= 2.2 and successfully enable a touchscreen, then
+ // it will provide touch only. In most other cases, there will be
+ // emulated mouse events from the driver. If not, then Qt must do its
+ // own mouse emulation to enable interaction with mouse-oriented QWidgets.
+ if (m_xi2Minor >= 2 && result == Success)
+ has_touch_without_mouse_emulation = true;
+ }
+#endif // XCB_USE_XINPUT22
#ifndef QT_NO_TABLETEVENT
// For each tablet, select some additional event types.
@@ -163,23 +224,29 @@ XInput2DeviceData *QXcbConnection::deviceForId(int id)
QTouchDevice::Capabilities caps = 0;
dev = new XInput2DeviceData;
dev->xiDeviceInfo = XIQueryDevice(static_cast<Display *>(m_xlib_display), id, &unused);
- dev->qtTouchDevice = new QTouchDevice;
+ int type = -1;
+ int maxTouchPoints = 1;
+ bool hasRelativeCoords = false;
for (int i = 0; i < dev->xiDeviceInfo->num_classes; ++i) {
XIAnyClassInfo *classinfo = dev->xiDeviceInfo->classes[i];
switch (classinfo->type) {
#ifdef XCB_USE_XINPUT22
case XITouchClass: {
XITouchClassInfo *tci = reinterpret_cast<XITouchClassInfo *>(classinfo);
+ maxTouchPoints = tci->num_touches;
+#ifdef XI2_DEBUG
+ qDebug(" has touch class with mode %d", tci->mode);
+#endif
switch (tci->mode) {
case XIModeRelative:
- dev->qtTouchDevice->setType(QTouchDevice::TouchPad);
+ type = QTouchDevice::TouchPad;
break;
case XIModeAbsolute:
- dev->qtTouchDevice->setType(QTouchDevice::TouchScreen);
+ type = QTouchDevice::TouchScreen;
break;
}
} break;
-#endif
+#endif // XCB_USE_XINPUT22
case XIValuatorClass: {
XIValuatorClassInfo *vci = reinterpret_cast<XIValuatorClassInfo *>(classinfo);
if (vci->label == atom(QXcbAtom::AbsMTPositionX))
@@ -188,18 +255,36 @@ XInput2DeviceData *QXcbConnection::deviceForId(int id)
caps |= QTouchDevice::Area;
else if (vci->label == atom(QXcbAtom::AbsMTPressure) || vci->label == atom(QXcbAtom::AbsPressure))
caps |= QTouchDevice::Pressure;
+ else if (vci->label == atom(QXcbAtom::RelX)) {
+ hasRelativeCoords = true;
+ dev->size.setWidth((vci->max - vci->min) * 1000.0 / vci->resolution);
+ } else if (vci->label == atom(QXcbAtom::RelY)) {
+ hasRelativeCoords = true;
+ dev->size.setHeight((vci->max - vci->min) * 1000.0 / vci->resolution);
+ }
} break;
}
}
- dev->qtTouchDevice->setCapabilities(caps);
- dev->qtTouchDevice->setName(dev->xiDeviceInfo->name);
- if (caps != 0)
- QWindowSystemInterface::registerTouchDevice(dev->qtTouchDevice);
-#ifdef XI2_TOUCH_DEBUG
- qDebug("registered new device %s with %d classes and %d max touch points",
- dev->xiDeviceInfo->name, dev->xiDeviceInfo->num_classes, dev->qtTouchDevice->maxTouchPoints());
-#endif
- m_touchDevices[id] = dev;
+ if (type < 0 && caps && hasRelativeCoords) {
+ type = QTouchDevice::TouchPad;
+ if (dev->size.width() < 10 || dev->size.height() < 10 ||
+ dev->size.width() > 10000 || dev->size.height() > 10000)
+ dev->size = QSizeF(130, 110);
+ }
+ if (type >= QTouchDevice::TouchScreen && type <= QTouchDevice::TouchPad) {
+ dev->qtTouchDevice = new QTouchDevice;
+ dev->qtTouchDevice->setName(dev->xiDeviceInfo->name);
+ dev->qtTouchDevice->setType((QTouchDevice::DeviceType)type);
+ dev->qtTouchDevice->setCapabilities(caps);
+ dev->qtTouchDevice->setMaximumTouchPoints(maxTouchPoints);
+ if (caps != 0)
+ QWindowSystemInterface::registerTouchDevice(dev->qtTouchDevice);
+ m_touchDevices[id] = dev;
+ } else {
+ m_touchDevices.remove(id);
+ delete dev;
+ dev = 0;
+ }
}
return dev;
}
@@ -218,7 +303,7 @@ static qreal valuatorNormalized(double value, XIValuatorClassInfo *vci)
value = vci->min;
return (value - vci->min) / (vci->max - vci->min);
}
-#endif
+#endif // XCB_USE_XINPUT22
void QXcbConnection::xi2HandleEvent(xcb_ge_event_t *event)
{
@@ -237,7 +322,7 @@ void QXcbConnection::xi2HandleEvent(xcb_ge_event_t *event)
#ifdef XCB_USE_XINPUT22
if (xiEvent->evtype == XI_TouchBegin || xiEvent->evtype == XI_TouchUpdate || xiEvent->evtype == XI_TouchEnd) {
xXIDeviceEvent* xiDeviceEvent = reinterpret_cast<xXIDeviceEvent *>(event);
-#ifdef XI2_TOUCH_DEBUG
+#ifdef XI2_DEBUG
qDebug("XI2 event type %d seq %d detail %d pos 0x%X,0x%X %f,%f root pos %f,%f",
event->event_type, xiEvent->sequenceNumber, xiDeviceEvent->detail,
xiDeviceEvent->event_x, xiDeviceEvent->event_y,
@@ -247,6 +332,8 @@ void QXcbConnection::xi2HandleEvent(xcb_ge_event_t *event)
if (QXcbWindow *platformWindow = platformWindowFromId(xiDeviceEvent->event)) {
XInput2DeviceData *dev = deviceForId(xiEvent->deviceid);
+ Q_ASSERT(dev);
+ const bool firstTouch = m_touchPoints.isEmpty();
if (xiEvent->evtype == XI_TouchBegin) {
QWindowSystemInterface::TouchPoint tp;
tp.id = xiDeviceEvent->detail % INT_MAX;
@@ -267,11 +354,15 @@ void QXcbConnection::xi2HandleEvent(xcb_ge_event_t *event)
double value;
if (!xi2GetValuatorValueIfSet(xiDeviceEvent, n, &value))
continue;
-#ifdef XI2_TOUCH_DEBUG
- qDebug(" valuator class label %d value %lf from range %lf -> %lf name %s",
- vci->label, value, vci->min, vci->max, XGetAtomName(static_cast<Display *>(m_xlib_display), vci->label) );
+#ifdef XI2_DEBUG
+ qDebug(" valuator %20s value %lf from range %lf -> %lf",
+ atomName(vci->label).constData(), value, vci->min, vci->max );
#endif
- if (vci->label == atom(QXcbAtom::AbsMTPositionX)) {
+ if (vci->label == atom(QXcbAtom::RelX)) {
+ nx = valuatorNormalized(value, vci);
+ } else if (vci->label == atom(QXcbAtom::RelY)) {
+ ny = valuatorNormalized(value, vci);
+ } else if (vci->label == atom(QXcbAtom::AbsMTPositionX)) {
nx = valuatorNormalized(value, vci);
} else if (vci->label == atom(QXcbAtom::AbsMTPositionY)) {
ny = valuatorNormalized(value, vci);
@@ -306,19 +397,45 @@ void QXcbConnection::xi2HandleEvent(xcb_ge_event_t *event)
}
switch (xiEvent->evtype) {
+ case XI_TouchBegin:
+ if (firstTouch) {
+ dev->firstPressedPosition = QPointF(x, y);
+ dev->firstPressedNormalPosition = QPointF(nx, ny);
+ }
+ dev->pointPressedPosition.insert(touchPoint.id, QPointF(x, y));
+ break;
case XI_TouchUpdate:
- if (touchPoint.area.center() != QPoint(x, y))
+ if (dev->qtTouchDevice->type() == QTouchDevice::TouchPad && dev->pointPressedPosition.value(touchPoint.id) == QPointF(x, y)) {
+ qreal dx = (nx - dev->firstPressedNormalPosition.x()) *
+ dev->size.width() * screen->geometry().width() / screen->physicalSize().width();
+ qreal dy = (ny - dev->firstPressedNormalPosition.y()) *
+ dev->size.height() * screen->geometry().height() / screen->physicalSize().height();
+ x = dev->firstPressedPosition.x() + dx;
+ y = dev->firstPressedPosition.y() + dy;
+ touchPoint.state = Qt::TouchPointMoved;
+ } else if (touchPoint.area.center() != QPoint(x, y)) {
touchPoint.state = Qt::TouchPointMoved;
+ dev->pointPressedPosition[touchPoint.id] = QPointF(x, y);
+ }
else
touchPoint.state = Qt::TouchPointStationary;
break;
case XI_TouchEnd:
touchPoint.state = Qt::TouchPointReleased;
+ if (dev->qtTouchDevice->type() == QTouchDevice::TouchPad && dev->pointPressedPosition.value(touchPoint.id) == QPointF(x, y)) {
+ qreal dx = (nx - dev->firstPressedNormalPosition.x()) *
+ dev->size.width() * screen->geometry().width() / screen->physicalSize().width();
+ qreal dy = (ny - dev->firstPressedNormalPosition.y()) *
+ dev->size.width() * screen->geometry().width() / screen->physicalSize().width();
+ x = dev->firstPressedPosition.x() + dx;
+ y = dev->firstPressedPosition.y() + dy;
+ }
+ dev->pointPressedPosition.remove(touchPoint.id);
}
touchPoint.area = QRectF(x - w/2, y - h/2, w, h);
touchPoint.normalPosition = QPointF(nx, ny);
-#ifdef XI2_TOUCH_DEBUG
+#ifdef XI2_DEBUG
qDebug() << " tp " << touchPoint.id << " state " << touchPoint.state << " pos norm " << touchPoint.normalPosition <<
" area " << touchPoint.area << " pressure " << touchPoint.pressure;
#endif
@@ -328,80 +445,11 @@ void QXcbConnection::xi2HandleEvent(xcb_ge_event_t *event)
m_touchPoints.remove(touchPoint.id);
}
}
-#endif
+#endif // XCB_USE_XINPUT22
}
}
#ifndef QT_NO_TABLETEVENT
-void QXcbConnection::xi2QueryTabletData(void *dev, TabletData *tabletData)
-{
- XIDeviceInfo *device = static_cast<XIDeviceInfo *>(dev);
- tabletData->deviceId = device->deviceid;
-
- tabletData->pointerType = QTabletEvent::Pen;
- if (QByteArray(device->name).toLower().contains("eraser"))
- tabletData->pointerType = QTabletEvent::Eraser;
-
- for (int i = 0; i < device->num_classes; ++i) {
- switch (device->classes[i]->type) {
- case XIValuatorClass: {
- XIValuatorClassInfo *vci = reinterpret_cast<XIValuatorClassInfo *>(device->classes[i]);
- int val = 0;
- if (vci->label == atom(QXcbAtom::AbsX))
- val = QXcbAtom::AbsX;
- else if (vci->label == atom(QXcbAtom::AbsY))
- val = QXcbAtom::AbsY;
- else if (vci->label == atom(QXcbAtom::AbsPressure))
- val = QXcbAtom::AbsPressure;
- else if (vci->label == atom(QXcbAtom::AbsTiltX))
- val = QXcbAtom::AbsTiltX;
- else if (vci->label == atom(QXcbAtom::AbsTiltY))
- val = QXcbAtom::AbsTiltY;
- else if (vci->label == atom(QXcbAtom::AbsWheel))
- val = QXcbAtom::AbsWheel;
- else if (vci->label == atom(QXcbAtom::AbsDistance))
- val = QXcbAtom::AbsDistance;
- if (val) {
- TabletData::ValuatorClassInfo info;
- info.minVal = vci->min;
- info.maxVal = vci->max;
- info.number = vci->number;
- tabletData->valuatorInfo[val] = info;
- }
- }
- break;
- default:
- break;
- }
- }
-}
-
-void QXcbConnection::xi2SetupTabletDevices()
-{
- Display *xDisplay = static_cast<Display *>(m_xlib_display);
- m_tabletData.clear();
- int deviceCount = 0;
- XIDeviceInfo *devices = XIQueryDevice(xDisplay, XIAllDevices, &deviceCount);
- if (devices) {
- for (int i = 0; i < deviceCount; ++i) {
- int unused = 0;
- XIDeviceInfo *dev = XIQueryDevice(xDisplay, devices[i].deviceid, &unused);
- if (dev) {
- if (q_xi2_is_tablet(dev)) {
- TabletData tabletData;
- xi2QueryTabletData(dev, &tabletData);
-#ifdef XI2_TOUCH_DEBUG
- qDebug() << "found tablet" << dev->name;
-#endif
- m_tabletData.append(tabletData);
- }
- XIFreeDeviceInfo(dev);
- }
- }
- XIFreeDeviceInfo(devices);
- }
-}
-
bool QXcbConnection::xi2HandleTabletEvent(void *event, TabletData *tabletData)
{
bool handled = true;
diff --git a/src/plugins/platforms/xcb/qxcbintegration.cpp b/src/plugins/platforms/xcb/qxcbintegration.cpp
index cf7e99023a..46077e2c3f 100644
--- a/src/plugins/platforms/xcb/qxcbintegration.cpp
+++ b/src/plugins/platforms/xcb/qxcbintegration.cpp
@@ -119,7 +119,7 @@ static bool runningUnderDebugger()
}
#endif
-QXcbIntegration::QXcbIntegration(const QStringList &parameters)
+QXcbIntegration::QXcbIntegration(const QStringList &parameters, int &argc, char **argv)
: m_eventDispatcher(createUnixEventDispatcher())
, m_services(new QGenericUnixServices)
{
@@ -138,7 +138,25 @@ QXcbIntegration::QXcbIntegration(const QStringList &parameters)
if (canNotGrabEnv)
canGrab = false;
- m_connections << new QXcbConnection(m_nativeInterface.data(), canGrab);
+ // Parse arguments
+ const char *displayName = 0;
+ if (argc) {
+ int j = 1;
+ for (int i = 1; i < argc; i++) {
+ char *arg = argv[i];
+ if (arg) {
+ if (!strcmp(arg, "-display") && i < argc - 1) {
+ displayName = argv[++i];
+ arg = 0;
+ }
+ }
+ if (arg)
+ argv[j++] = arg;
+ }
+ argc = j;
+ } // argc
+
+ m_connections << new QXcbConnection(m_nativeInterface.data(), canGrab, displayName);
for (int i = 0; i < parameters.size() - 1; i += 2) {
#ifdef Q_XCB_DEBUG
@@ -365,6 +383,8 @@ QVariant QXcbIntegration::styleHint(QPlatformIntegration::StyleHint hint) const
case QPlatformIntegration::SynthesizeMouseFromTouchEvents:
// We do not want Qt to synthesize mouse events if X11 already does it.
return m_connections.at(0)->hasTouchWithoutMouseEmulation();
+ default:
+ break;
}
return QPlatformIntegration::styleHint(hint);
}
diff --git a/src/plugins/platforms/xcb/qxcbintegration.h b/src/plugins/platforms/xcb/qxcbintegration.h
index 07b6b8d678..b884b3b7f2 100644
--- a/src/plugins/platforms/xcb/qxcbintegration.h
+++ b/src/plugins/platforms/xcb/qxcbintegration.h
@@ -55,7 +55,7 @@ class QXcbScreen;
class QXcbIntegration : public QPlatformIntegration
{
public:
- QXcbIntegration(const QStringList &parameters);
+ QXcbIntegration(const QStringList &parameters, int &argc, char **argv);
~QXcbIntegration();
QPlatformWindow *createPlatformWindow(QWindow *window) const;
diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.cpp b/src/plugins/platforms/xcb/qxcbkeyboard.cpp
index ae8bcb802b..5fbc23c049 100644
--- a/src/plugins/platforms/xcb/qxcbkeyboard.cpp
+++ b/src/plugins/platforms/xcb/qxcbkeyboard.cpp
@@ -243,6 +243,10 @@
#define XF86XK_Select 0x1008FFA0
#define XF86XK_View 0x1008FFA1
#define XF86XK_TopMenu 0x1008FFA2
+#define XF86XK_Red 0x1008FFA3
+#define XF86XK_Green 0x1008FFA4
+#define XF86XK_Yellow 0x1008FFA5
+#define XF86XK_Blue 0x1008FFA6
#define XF86XK_Suspend 0x1008FFA7
#define XF86XK_Hibernate 0x1008FFA8
#define XF86XK_TouchpadToggle 0x1008FFA9
@@ -538,6 +542,10 @@ static const unsigned int KeyTbl[] = {
XF86XK_Select, Qt::Key_Select,
XF86XK_View, Qt::Key_View,
XF86XK_TopMenu, Qt::Key_TopMenu,
+ XF86XK_Red, Qt::Key_Red,
+ XF86XK_Green, Qt::Key_Green,
+ XF86XK_Yellow, Qt::Key_Yellow,
+ XF86XK_Blue, Qt::Key_Blue,
XF86XK_Bluetooth, Qt::Key_Bluetooth,
XF86XK_Suspend, Qt::Key_Suspend,
XF86XK_Hibernate, Qt::Key_Hibernate,
diff --git a/src/plugins/platformthemes/gtk2/qgtk2dialoghelpers.cpp b/src/plugins/platformthemes/gtk2/qgtk2dialoghelpers.cpp
index 77a78d2140..4e9cc446b3 100644
--- a/src/plugins/platformthemes/gtk2/qgtk2dialoghelpers.cpp
+++ b/src/plugins/platformthemes/gtk2/qgtk2dialoghelpers.cpp
@@ -282,13 +282,13 @@ bool QGtk2FileDialogHelper::defaultNameFilterDisables() const
return false;
}
-void QGtk2FileDialogHelper::setDirectory(const QString &directory)
+void QGtk2FileDialogHelper::setDirectory(const QUrl &directory)
{
GtkDialog *gtkDialog = d->gtkDialog();
- gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(gtkDialog), directory.toUtf8());
+ gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(gtkDialog), directory.toLocalFile().toUtf8());
}
-QString QGtk2FileDialogHelper::directory() const
+QUrl QGtk2FileDialogHelper::directory() const
{
// While GtkFileChooserDialog is hidden, gtk_file_chooser_get_current_folder()
// returns a bogus value -> return the cached value before hiding
@@ -302,27 +302,27 @@ QString QGtk2FileDialogHelper::directory() const
ret = QString::fromUtf8(folder);
g_free(folder);
}
- return ret;
+ return QUrl::fromLocalFile(ret);
}
-void QGtk2FileDialogHelper::selectFile(const QString &filename)
+void QGtk2FileDialogHelper::selectFile(const QUrl &filename)
{
GtkDialog *gtkDialog = d->gtkDialog();
- gtk_file_chooser_select_filename(GTK_FILE_CHOOSER(gtkDialog), filename.toUtf8());
+ gtk_file_chooser_select_filename(GTK_FILE_CHOOSER(gtkDialog), filename.toLocalFile().toUtf8());
}
-QStringList QGtk2FileDialogHelper::selectedFiles() const
+QList<QUrl> QGtk2FileDialogHelper::selectedFiles() const
{
// While GtkFileChooserDialog is hidden, gtk_file_chooser_get_filenames()
// returns a bogus value -> return the cached value before hiding
if (!_selection.isEmpty())
return _selection;
- QStringList selection;
+ QList<QUrl> selection;
GtkDialog *gtkDialog = d->gtkDialog();
GSList *filenames = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(gtkDialog));
for (GSList *it = filenames; it; it = it->next)
- selection += QString::fromUtf8((const char*)it->data);
+ selection += QUrl::fromLocalFile(QString::fromUtf8((const char*)it->data));
g_slist_free(filenames);
return selection;
}
@@ -356,7 +356,7 @@ void QGtk2FileDialogHelper::onAccepted()
if (filter.isEmpty())
emit filterSelected(filter);
- QStringList files = selectedFiles();
+ QList<QUrl> files = selectedFiles();
emit filesSelected(files);
if (files.count() == 1)
emit fileSelected(files.first());
@@ -370,7 +370,7 @@ void QGtk2FileDialogHelper::onSelectionChanged(GtkDialog *gtkDialog, QGtk2FileDi
selection = QString::fromUtf8(filename);
g_free(filename);
}
- emit helper->currentChanged(selection);
+ emit helper->currentChanged(QUrl::fromLocalFile(selection));
}
void QGtk2FileDialogHelper::onCurrentFolderChanged(QGtk2FileDialogHelper *dialog)
@@ -419,12 +419,12 @@ void QGtk2FileDialogHelper::applyOptions()
if (!nameFilters.isEmpty())
setNameFilters(nameFilters);
- const QString initialDirectory = opts->initialDirectory();
+ const QString initialDirectory = opts->initialDirectory().toLocalFile();
if (!initialDirectory.isEmpty())
setDirectory(initialDirectory);
- foreach (const QString &filename, opts->initiallySelectedFiles())
- selectFile(filename);
+ foreach (const QUrl &filename, opts->initiallySelectedFiles())
+ selectFile(filename.toLocalFile());
const QString initialNameFilter = opts->initiallySelectedNameFilter();
if (!initialNameFilter.isEmpty())
diff --git a/src/plugins/platformthemes/gtk2/qgtk2dialoghelpers.h b/src/plugins/platformthemes/gtk2/qgtk2dialoghelpers.h
index c2d12625f5..47a6153fbc 100644
--- a/src/plugins/platformthemes/gtk2/qgtk2dialoghelpers.h
+++ b/src/plugins/platformthemes/gtk2/qgtk2dialoghelpers.h
@@ -90,10 +90,10 @@ public:
void hide();
bool defaultNameFilterDisables() const;
- void setDirectory(const QString &directory);
- QString directory() const;
- void selectFile(const QString &filename);
- QStringList selectedFiles() const;
+ void setDirectory(const QUrl &directory) Q_DECL_OVERRIDE;
+ QUrl directory() const Q_DECL_OVERRIDE;
+ void selectFile(const QUrl &filename) Q_DECL_OVERRIDE;
+ QList<QUrl> selectedFiles() const Q_DECL_OVERRIDE;
void setFilter();
void selectNameFilter(const QString &filter);
QString selectedNameFilter() const;
@@ -107,8 +107,8 @@ private:
void applyOptions();
void setNameFilters(const QStringList &filters);
- QString _dir;
- QStringList _selection;
+ QUrl _dir;
+ QList<QUrl> _selection;
QHash<QString, GtkFileFilter*> _filters;
QHash<GtkFileFilter*, QString> _filterNames;
QScopedPointer<QGtk2Dialog> d;
diff --git a/src/printsupport/doc/qtprintsupport.qdocconf b/src/printsupport/doc/qtprintsupport.qdocconf
index c7b14e16c1..d5015fa46a 100644
--- a/src/printsupport/doc/qtprintsupport.qdocconf
+++ b/src/printsupport/doc/qtprintsupport.qdocconf
@@ -40,3 +40,6 @@ excludedirs += ../../../examples/widgets/doc
imagedirs += images \
../../widgets/doc/images \
+
+navigation.landingpage = "Qt Print Support"
+navigation.cppclassespage = "Qt Print Support C++ Classes"
diff --git a/src/sql/doc/qtsql.qdocconf b/src/sql/doc/qtsql.qdocconf
index c2686079d5..a2a05d7c8a 100644
--- a/src/sql/doc/qtsql.qdocconf
+++ b/src/sql/doc/qtsql.qdocconf
@@ -39,3 +39,6 @@ exampledirs += ../../../examples/sql \
imagedirs += images \
../../../examples/sql/doc/images
+
+navigation.landingpage = "Qt SQL"
+navigation.cppclassespage = "Qt SQL C++ Classes"
diff --git a/src/src.pro b/src/src.pro
index b4c96025c1..6815fe4a75 100644
--- a/src/src.pro
+++ b/src/src.pro
@@ -102,12 +102,14 @@ src_android.subdir = $$PWD/android
# this order is important
SUBDIRS += src_tools_bootstrap src_tools_moc src_tools_rcc src_corelib
+TOOLS = src_tools_moc src_tools_rcc
win32:SUBDIRS += src_winmain
SUBDIRS += src_network src_sql src_xml src_testlib
contains(QT_CONFIG, dbus) {
SUBDIRS += src_dbus
force_bootstrap: SUBDIRS += src_tools_bootstrap_dbus
SUBDIRS += src_tools_qdbusxml2cpp src_tools_qdbuscpp2xml
+ TOOLS += src_tools_qdbusxml2cpp src_tools_qdbuscpp2xml
contains(QT_CONFIG, accessibility-atspi-bridge): \
src_platformsupport.depends += src_dbus src_tools_qdbusxml2cpp
src_plugins.depends += src_dbus src_tools_qdbusxml2cpp src_tools_qdbuscpp2xml
@@ -123,6 +125,7 @@ contains(QT_CONFIG, concurrent):SUBDIRS += src_concurrent
src_plugins.depends += src_gui src_platformsupport
!contains(QT_CONFIG, no-widgets) {
SUBDIRS += src_tools_uic src_widgets
+ TOOLS += src_tools_uic
src_plugins.depends += src_widgets
contains(QT_CONFIG, opengl(es1|es2)?) {
SUBDIRS += src_opengl
@@ -139,3 +142,6 @@ SUBDIRS += src_plugins src_tools_qdoc
nacl: SUBDIRS -= src_network src_testlib
android:!android-no-sdk: SUBDIRS += src_android
+
+sub-tools.depends = $$TOOLS
+QMAKE_EXTRA_TARGETS = sub-tools
diff --git a/src/testlib/doc/qttestlib.qdocconf b/src/testlib/doc/qttestlib.qdocconf
index 2eea4f246a..ab2bdc1948 100644
--- a/src/testlib/doc/qttestlib.qdocconf
+++ b/src/testlib/doc/qttestlib.qdocconf
@@ -40,3 +40,6 @@ exampledirs += ../../../examples/qtestlib \
excludedirs += ../../../examples/widgets/doc
imagedirs += images
+
+navigation.landingpage = "Qt Test"
+navigation.cppclassespage = "Qt Test C++ Classes"
diff --git a/src/testlib/doc/src/qttestlib-manual.qdoc b/src/testlib/doc/src/qttestlib-manual.qdoc
index c44bb49ae3..613d2c220c 100644
--- a/src/testlib/doc/src/qttestlib-manual.qdoc
+++ b/src/testlib/doc/src/qttestlib-manual.qdoc
@@ -247,6 +247,9 @@
2000.
\li \c -nocrashhandler \br
Disables the crash handler on Unix platforms.
+ On Windows, it re-enables the Windows Error Reporting dialog, which is
+ turned off by default.
+
\li \c -platform \e name \br
This command line argument applies to all Qt applications, but might be
especially useful in the context of auto-testing. By using the "offscreen"
diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp
index 77a59d0cf0..5d5a976201 100644
--- a/src/testlib/qtestcase.cpp
+++ b/src/testlib/qtestcase.cpp
@@ -1130,9 +1130,7 @@ namespace QTest
static int keyDelay = -1;
static int mouseDelay = -1;
static int eventDelay = -1;
-#if defined(Q_OS_UNIX)
static bool noCrashHandler = false;
-#endif
/*! \internal
Invoke a method of the object without generating warning if the method does not exist
@@ -1335,9 +1333,7 @@ Q_TESTLIB_EXPORT void qtest_qParseArgs(int argc, char *argv[], bool qml)
" -mousedelay ms : Set default delay for mouse simulation to ms milliseconds\n"
" -maxwarnings n : Sets the maximum amount of messages to output.\n"
" 0 means unlimited, default: 2000\n"
-#if defined(Q_OS_UNIX)
" -nocrashhandler : Disables the crash handler\n"
-#endif
"\n"
" Benchmarking options:\n"
#ifdef QTESTLIB_USE_VALGRIND
@@ -1468,10 +1464,8 @@ Q_TESTLIB_EXPORT void qtest_qParseArgs(int argc, char *argv[], bool qml)
} else {
QTestLog::setMaxWarnings(qToInt(argv[++i]));
}
-#if defined(Q_OS_UNIX)
} else if (strcmp(argv[i], "-nocrashhandler") == 0) {
QTest::noCrashHandler = true;
-#endif
#ifdef QTESTLIB_USE_VALGRIND
} else if (strcmp(argv[i], "-callgrind") == 0) {
if (QBenchmarkValgrindUtils::haveValgrind())
@@ -2083,6 +2077,18 @@ FatalSignalHandler::~FatalSignalHandler()
} // namespace
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
+static LONG WINAPI windowsFaultHandler(struct _EXCEPTION_POINTERS *exInfo)
+{
+ char appName[MAX_PATH];
+ if (!GetModuleFileNameA(NULL, appName, MAX_PATH))
+ appName[0] = 0;
+ fprintf(stderr, "A crash occurred in %s (exception code 0x%lx).",
+ appName, exInfo->ExceptionRecord->ExceptionCode);
+ return EXCEPTION_EXECUTE_HANDLER;
+}
+#endif // Q_OS_WIN) && !Q_OS_WINCE
+
/*!
Executes tests declared in \a testObject. In addition, the private slots
\c{initTestCase()}, \c{cleanupTestCase()}, \c{init()} and \c{cleanup()}
@@ -2138,13 +2144,6 @@ int QTest::qExec(QObject *testObject, int argc, char **argv)
try {
#endif
-#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
-# if !defined(Q_CC_MINGW)
- _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_DEBUG);
-# endif
- SetErrorMode(SetErrorMode(0) | SEM_NOGPFAULTERRORBOX);
-#endif
-
#if defined(Q_OS_MACX)
if (macNeedsActivate) {
CFStringRef reasonForActivity= CFSTR("No Display Sleep");
@@ -2170,6 +2169,16 @@ int QTest::qExec(QObject *testObject, int argc, char **argv)
qtest_qParseArgs(argc, argv, false);
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
+ if (!noCrashHandler) {
+# ifndef Q_CC_MINGW
+ _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_DEBUG);
+# endif
+ SetErrorMode(SetErrorMode(0) | SEM_NOGPFAULTERRORBOX);
+ SetUnhandledExceptionFilter(windowsFaultHandler);
+ } // !noCrashHandler
+#endif // Q_OS_WIN) && !Q_OS_WINCE
+
#ifdef QTESTLIB_USE_VALGRIND
if (QBenchmarkGlobalData::current->mode() == QBenchmarkGlobalData::CallgrindParentProcess) {
const QStringList origAppArgs(QCoreApplication::arguments());
diff --git a/src/testlib/qtestresult.cpp b/src/testlib/qtestresult.cpp
index a6a8ee0cc1..7ab317f209 100644
--- a/src/testlib/qtestresult.cpp
+++ b/src/testlib/qtestresult.cpp
@@ -268,10 +268,12 @@ 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) {
- qsnprintf(msg, 1024, "%s\n Actual (%s): %s\n Expected (%s): %s",
+ size_t len1 = strlen(actual);
+ size_t len2 = strlen(expected);
+ qsnprintf(msg, 1024, "%s\n Actual (%s)%*s %s\n Expected (%s)%*s %s",
failureMsg,
- actual, val1 ? val1 : "<null>",
- expected, val2 ? val2 : "<null>");
+ actual, qMax(len1, len2) - len1 + 1, ":", val1 ? val1 : "<null>",
+ expected, qMax(len1, len2) - len2 + 1, ":", val2 ? val2 : "<null>");
} else
qsnprintf(msg, 1024, "%s", failureMsg);
diff --git a/src/tools/qdbuscpp2xml/qdbuscpp2xml.cpp b/src/tools/qdbuscpp2xml/qdbuscpp2xml.cpp
index a66757907d..0e1fa59b90 100644
--- a/src/tools/qdbuscpp2xml/qdbuscpp2xml.cpp
+++ b/src/tools/qdbuscpp2xml/qdbuscpp2xml.cpp
@@ -47,6 +47,7 @@
#include <qbuffer.h>
#include <qregexp.h>
#include <qvector.h>
+#include <qdebug.h>
#include <stdio.h>
#include <stdlib.h>
@@ -95,14 +96,14 @@ static const char help[] =
"\n";
-int qDBusParametersForMethod(const FunctionDef &mm, QVector<int>& metaTypes)
+int qDBusParametersForMethod(const FunctionDef &mm, QVector<int>& metaTypes, QString &errorMsg)
{
QList<QByteArray> parameterTypes;
foreach (const ArgumentDef &arg, mm.arguments)
parameterTypes.append(arg.normalizedType);
- return qDBusParametersForMethod(parameterTypes, metaTypes);
+ return qDBusParametersForMethod(parameterTypes, metaTypes, errorMsg);
}
@@ -140,9 +141,12 @@ static QString addFunction(const FunctionDef &mm, bool isSignal = false) {
}
QList<ArgumentDef> names = mm.arguments;
QVector<int> types;
- int inputCount = qDBusParametersForMethod(mm, types);
- if (inputCount == -1)
+ QString errorMsg;
+ int inputCount = qDBusParametersForMethod(mm, types, errorMsg);
+ if (inputCount == -1) {
+ qWarning() << qPrintable(errorMsg);
return QString(); // invalid form
+ }
if (isSignal && inputCount + 1 != types.count())
return QString(); // signal with output arguments?
if (isSignal && types.at(inputCount) == QDBusMetaTypeId::message())
diff --git a/src/tools/qdbusxml2cpp/qdbusxml2cpp.cpp b/src/tools/qdbusxml2cpp/qdbusxml2cpp.cpp
index e6d77643de..f2b9441ea4 100644
--- a/src/tools/qdbusxml2cpp/qdbusxml2cpp.cpp
+++ b/src/tools/qdbusxml2cpp/qdbusxml2cpp.cpp
@@ -401,6 +401,8 @@ static QStringList makeArgNames(const QDBusIntrospection::Arguments &inputArgs,
QString name = arg.name;
if (name.isEmpty())
name = QString( QLatin1String("in%1") ).arg(i);
+ else
+ name.replace(QLatin1Char('-'), QLatin1Char('_'));
while (retval.contains(name))
name += QLatin1String("_");
retval << name;
@@ -410,6 +412,8 @@ static QStringList makeArgNames(const QDBusIntrospection::Arguments &inputArgs,
QString name = arg.name;
if (name.isEmpty())
name = QString( QLatin1String("out%1") ).arg(i);
+ else
+ name.replace(QLatin1Char('-'), QLatin1Char('_'));
while (retval.contains(name))
name += QLatin1String("_");
retval << name;
diff --git a/src/tools/qdoc/codemarker.cpp b/src/tools/qdoc/codemarker.cpp
index c7d9c5b339..8faac66b1b 100644
--- a/src/tools/qdoc/codemarker.cpp
+++ b/src/tools/qdoc/codemarker.cpp
@@ -398,7 +398,7 @@ void CodeMarker::insert(FastSection &fastSection,
bool inheritedMember = false;
if (!node->relates()) {
InnerNode* p = node->parent();
- if (p->subType() == Node::QmlPropertyGroup)
+ if (p->type() == Node::QmlPropertyGroup)
p = p->parent();
if (p != fastSection.parent_) { // && !node->parent()->isAbstract()) {
if (p->subType() != Node::QmlClass || !p->isAbstract()) {
diff --git a/src/tools/qdoc/codeparser.cpp b/src/tools/qdoc/codeparser.cpp
index 7b534a6c95..97a3d20263 100644
--- a/src/tools/qdoc/codeparser.cpp
+++ b/src/tools/qdoc/codeparser.cpp
@@ -199,29 +199,33 @@ CodeParser *CodeParser::parserForSourceFile(const QString &filePath)
return 0;
}
+static QSet<QString> commonMetaCommands_;
/*!
Returns the set of strings representing the common metacommands.
*/
-QSet<QString> CodeParser::commonMetaCommands()
+const QSet<QString>& CodeParser::commonMetaCommands()
{
- return QSet<QString>() << COMMAND_COMPAT
- << COMMAND_DEPRECATED
- << COMMAND_INGROUP
- << COMMAND_INMODULE
- << COMMAND_INQMLMODULE
- << COMMAND_INTERNAL
- << COMMAND_MAINCLASS
- << COMMAND_NONREENTRANT
- << COMMAND_OBSOLETE
- << COMMAND_PAGEKEYWORDS
- << COMMAND_PRELIMINARY
- << COMMAND_INPUBLICGROUP
- << COMMAND_REENTRANT
- << COMMAND_SINCE
- << COMMAND_SUBTITLE
- << COMMAND_THREADSAFE
- << COMMAND_TITLE
- << COMMAND_WRAPPER;
+ if (commonMetaCommands_.isEmpty()) {
+ commonMetaCommands_ << COMMAND_COMPAT
+ << COMMAND_DEPRECATED
+ << COMMAND_INGROUP
+ << COMMAND_INMODULE
+ << COMMAND_INQMLMODULE
+ << COMMAND_INTERNAL
+ << COMMAND_MAINCLASS
+ << COMMAND_NONREENTRANT
+ << COMMAND_OBSOLETE
+ << COMMAND_PAGEKEYWORDS
+ << COMMAND_PRELIMINARY
+ << COMMAND_INPUBLICGROUP
+ << COMMAND_REENTRANT
+ << COMMAND_SINCE
+ << COMMAND_SUBTITLE
+ << COMMAND_THREADSAFE
+ << COMMAND_TITLE
+ << COMMAND_WRAPPER;
+ }
+ return commonMetaCommands_;
}
/*!
@@ -269,8 +273,8 @@ void CodeParser::processCommonMetaCommand(const Location& location,
if (!showInternal) {
node->setAccess(Node::Private);
node->setStatus(Node::Internal);
- if (node->subType() == Node::QmlPropertyGroup) {
- const QmlPropGroupNode* qpgn = static_cast<const QmlPropGroupNode*>(node);
+ if (node->type() == Node::QmlPropertyGroup) {
+ const QmlPropertyGroupNode* qpgn = static_cast<const QmlPropertyGroupNode*>(node);
NodeList::ConstIterator p = qpgn->childNodes().constBegin();
while (p != qpgn->childNodes().constEnd()) {
if ((*p)->type() == Node::QmlProperty) {
diff --git a/src/tools/qdoc/codeparser.h b/src/tools/qdoc/codeparser.h
index 8c398aeb05..89f661abeb 100644
--- a/src/tools/qdoc/codeparser.h
+++ b/src/tools/qdoc/codeparser.h
@@ -86,7 +86,7 @@ public:
static const QString& currentOutputSubdirectory() { return currentSubDir_; }
protected:
- QSet<QString> commonMetaCommands();
+ const QSet<QString>& commonMetaCommands();
void processCommonMetaCommand(const Location& location,
const QString& command,
const ArgLocPair& arg,
diff --git a/src/tools/qdoc/config.h b/src/tools/qdoc/config.h
index 8787d27eb3..948f31c01a 100644
--- a/src/tools/qdoc/config.h
+++ b/src/tools/qdoc/config.h
@@ -165,7 +165,9 @@ private:
#define CONFIG_ALIAS "alias"
#define CONFIG_BASE "base"
#define CONFIG_BASEDIR "basedir"
+#define CONFIG_BUILDVERSION "buildversion"
#define CONFIG_CODEINDENT "codeindent"
+#define CONFIG_CPPCLASSESPAGE "cppclassespage"
#define CONFIG_DEFINES "defines"
#define CONFIG_DEPENDS "depends"
#define CONFIG_DESCRIPTION "description"
@@ -184,15 +186,18 @@ private:
#define CONFIG_HEADERS "headers"
#define CONFIG_HEADERSCRIPTS "headerscripts"
#define CONFIG_HEADERSTYLES "headerstyles"
+#define CONFIG_HOMEPAGE "homepage"
#define CONFIG_IGNOREDIRECTIVES "ignoredirectives"
#define CONFIG_IGNORETOKENS "ignoretokens"
#define CONFIG_IMAGEDIRS "imagedirs"
#define CONFIG_IMAGES "images"
#define CONFIG_INDEXES "indexes"
#define CONFIG_LANGUAGE "language"
+#define CONFIG_LANDINGPAGE "landingpage"
#define CONFIG_MACRO "macro"
#define CONFIG_MANIFESTMETA "manifestmeta"
#define CONFIG_NATURALLANGUAGE "naturallanguage"
+#define CONFIG_NAVIGATION "navigation"
#define CONFIG_NOLINKERRORS "nolinkerrors"
#define CONFIG_OBSOLETELINKS "obsoletelinks"
#define CONFIG_OUTPUTDIR "outputdir"
@@ -201,7 +206,9 @@ private:
#define CONFIG_OUTPUTFORMATS "outputformats"
#define CONFIG_OUTPUTPREFIXES "outputprefixes"
#define CONFIG_PROJECT "project"
+#define CONFIG_REDIRECTDOCUMENTATIONTODEVNULL "redirectdocumentationtodevnull"
#define CONFIG_QHP "qhp"
+#define CONFIG_QMLTYPESPAGE "qmltypespage"
#define CONFIG_QUOTINGINFORMATION "quotinginformation"
#define CONFIG_SCRIPTDIRS "scriptdirs"
#define CONFIG_SCRIPTS "scripts"
diff --git a/src/tools/qdoc/cppcodemarker.cpp b/src/tools/qdoc/cppcodemarker.cpp
index 75e49f288a..ad3c5cba47 100644
--- a/src/tools/qdoc/cppcodemarker.cpp
+++ b/src/tools/qdoc/cppcodemarker.cpp
@@ -1110,40 +1110,15 @@ QList<Section> CppCodeMarker::qmlSections(const QmlClassNode* qmlClassNode, Syno
while (qcn != 0) {
NodeList::ConstIterator c = qcn->childNodes().constBegin();
while (c != qcn->childNodes().constEnd()) {
- if ((*c)->subType() == Node::QmlPropertyGroup) {
- const QmlPropGroupNode* qpgn = static_cast<const QmlPropGroupNode*>(*c);
- NodeList::ConstIterator p = qpgn->childNodes().constBegin();
- while (p != qpgn->childNodes().constEnd()) {
- if ((*p)->type() == Node::QmlProperty) {
- const QmlPropertyNode* pn = static_cast<const QmlPropertyNode*>(*p);
- if (pn->isAttached())
- insert(qmlattachedproperties,*p,style,Okay);
- else
- insert(qmlproperties,*p,style,Okay);
- }
- ++p;
- }
+ if ((*c)->type() == Node::QmlPropertyGroup) {
+ insert(qmlproperties, *c, style, Okay);
}
else if ((*c)->type() == Node::QmlProperty) {
const QmlPropertyNode* pn = static_cast<const QmlPropertyNode*>(*c);
- if (pn->qmlPropNodes().isEmpty()) {
- if (pn->isAttached())
- insert(qmlattachedproperties,*c,style,Okay);
- else
- insert(qmlproperties,*c,style,Okay);
- }
+ if (pn->isAttached())
+ insert(qmlattachedproperties,*c,style,Okay);
else {
- NodeList::ConstIterator p = pn->qmlPropNodes().constBegin();
- while (p != pn->qmlPropNodes().constEnd()) {
- if ((*p)->type() == Node::QmlProperty) {
- const QmlPropertyNode* pn = static_cast<const QmlPropertyNode*>(*p);
- if (pn->isAttached())
- insert(qmlattachedproperties,*p,style,Okay);
- else
- insert(qmlproperties,*p,style,Okay);
- }
- ++p;
- }
+ insert(qmlproperties,*c,style,Okay);
}
}
else if ((*c)->type() == Node::QmlSignal) {
@@ -1196,24 +1171,8 @@ QList<Section> CppCodeMarker::qmlSections(const QmlClassNode* qmlClassNode, Syno
while (qcn != 0) {
NodeList::ConstIterator c = qcn->childNodes().constBegin();
while (c != qcn->childNodes().constEnd()) {
- if ((*c)->subType() == Node::QmlPropertyGroup) {
- bool attached = false;
- const QmlPropGroupNode* pgn = static_cast<const QmlPropGroupNode*>(*c);
- NodeList::ConstIterator C = pgn->childNodes().constBegin();
- while (C != pgn->childNodes().constEnd()) {
- if ((*C)->type() == Node::QmlProperty) {
- const QmlPropertyNode* pn = static_cast<const QmlPropertyNode*>(*C);
- if (pn->isAttached()) {
- attached = true;
- break;
- }
- }
- ++C;
- }
- if (attached)
- insert(qmlattachedproperties,*c,style,Okay);
- else
- insert(qmlproperties,*c,style,Okay);
+ if ((*c)->type() == Node::QmlPropertyGroup) {
+ insert(qmlproperties,*c,style,Okay);
}
else if ((*c)->type() == Node::QmlProperty) {
const QmlPropertyNode* pn = static_cast<const QmlPropertyNode*>(*c);
@@ -1278,8 +1237,8 @@ QList<Section> CppCodeMarker::qmlSections(const QmlClassNode* qmlClassNode, Syno
}
NodeList::ConstIterator c = current->childNodes().constBegin();
while (c != current->childNodes().constEnd()) {
- if ((*c)->subType() == Node::QmlPropertyGroup) {
- const QmlPropGroupNode* qpgn = static_cast<const QmlPropGroupNode*>(*c);
+ if ((*c)->type() == Node::QmlPropertyGroup) {
+ const QmlPropertyGroupNode* qpgn = static_cast<const QmlPropertyGroupNode*>(*c);
NodeList::ConstIterator p = qpgn->childNodes().constBegin();
while (p != qpgn->childNodes().constEnd()) {
if ((*p)->type() == Node::QmlProperty) {
diff --git a/src/tools/qdoc/cppcodeparser.cpp b/src/tools/qdoc/cppcodeparser.cpp
index 5c25eeedc4..30b26264f1 100644
--- a/src/tools/qdoc/cppcodeparser.cpp
+++ b/src/tools/qdoc/cppcodeparser.cpp
@@ -272,37 +272,42 @@ void CppCodeParser::doneParsingSourceFiles()
qdb_->treeRoot()->makeUndocumentedChildrenInternal();
}
+static QSet<QString> topicCommands_;
/*!
Returns the set of strings reopresenting the topic commands.
*/
-QSet<QString> CppCodeParser::topicCommands()
+const QSet<QString>& CppCodeParser::topicCommands()
{
- return QSet<QString>() << COMMAND_CLASS
- << COMMAND_DITAMAP
- << COMMAND_ENUM
- << COMMAND_EXAMPLE
- << COMMAND_EXTERNALPAGE
- << COMMAND_FILE
- << COMMAND_FN
- << COMMAND_GROUP
- << COMMAND_HEADERFILE
- << COMMAND_MACRO
- << COMMAND_MODULE
- << COMMAND_NAMESPACE
- << COMMAND_PAGE
- << COMMAND_PROPERTY
- << COMMAND_TYPEDEF
- << COMMAND_VARIABLE
- << COMMAND_QMLCLASS
- << COMMAND_QMLTYPE
- << COMMAND_QMLPROPERTY
- << COMMAND_QMLATTACHEDPROPERTY
- << COMMAND_QMLSIGNAL
- << COMMAND_QMLATTACHEDSIGNAL
- << COMMAND_QMLMETHOD
- << COMMAND_QMLATTACHEDMETHOD
- << COMMAND_QMLBASICTYPE
- << COMMAND_QMLMODULE;
+ if (topicCommands_.isEmpty()) {
+ topicCommands_ << COMMAND_CLASS
+ << COMMAND_DITAMAP
+ << COMMAND_ENUM
+ << COMMAND_EXAMPLE
+ << COMMAND_EXTERNALPAGE
+ << COMMAND_FILE
+ << COMMAND_FN
+ << COMMAND_GROUP
+ << COMMAND_HEADERFILE
+ << COMMAND_MACRO
+ << COMMAND_MODULE
+ << COMMAND_NAMESPACE
+ << COMMAND_PAGE
+ << COMMAND_PROPERTY
+ << COMMAND_TYPEDEF
+ << COMMAND_VARIABLE
+ << COMMAND_QMLCLASS
+ << COMMAND_QMLTYPE
+ << COMMAND_QMLPROPERTY
+ << COMMAND_QMLPROPERTYGROUP
+ << COMMAND_QMLATTACHEDPROPERTY
+ << COMMAND_QMLSIGNAL
+ << COMMAND_QMLATTACHEDSIGNAL
+ << COMMAND_QMLMETHOD
+ << COMMAND_QMLATTACHEDMETHOD
+ << COMMAND_QMLBASICTYPE
+ << COMMAND_QMLMODULE;
+ }
+ return topicCommands_;
}
/*!
@@ -643,6 +648,35 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc,
}
/*!
+ A QML property group argument has the form...
+
+ <QML-module>::<element>::<name>
+
+ This function splits the argument into those parts.
+ A <QML-module> is the QML equivalent of a C++ namespace.
+ So this function splits \a arg on "::" and stores the
+ parts in \a module, \a element, and \a name, and returns
+ true. If any part is not found, a qdoc warning is emitted
+ and false is returned.
+ */
+bool CppCodeParser::splitQmlPropertyGroupArg(const QString& arg,
+ QString& module,
+ QString& element,
+ QString& name)
+{
+ QStringList colonSplit = arg.split("::");
+ if (colonSplit.size() == 3) {
+ module = colonSplit[0];
+ element = colonSplit[1];
+ name = colonSplit[2];
+ return true;
+ }
+ QString msg = "Unrecognizable QML module/component qualifier for " + arg;
+ location().warning(tr(msg.toLatin1().data()));
+ return false;
+}
+
+/*!
A QML property argument has the form...
<type> <element>::<name>
@@ -750,79 +784,118 @@ bool CppCodeParser::splitQmlMethodArg(const QString& arg,
Currently, this function is called only for \e{qmlproperty}
and \e{qmlattachedproperty}.
*/
-Node* CppCodeParser::processTopicCommandGroup(const Doc& doc,
- const QString& command,
- const ArgList& args)
+void CppCodeParser::processQmlProperties(const Doc& doc, NodeList& nodes, DocList& docs)
{
- QmlPropGroupNode* qmlPropGroup = 0;
- if ((command == COMMAND_QMLPROPERTY) ||
- (command == COMMAND_QMLATTACHEDPROPERTY)) {
- QString arg;
- QString type;
- QString module;
- QString element;
- QString property;
- QmlClassNode* qmlClass = 0;
- bool attached = (command == COMMAND_QMLATTACHEDPROPERTY);
- ArgList::ConstIterator argsIter = args.constBegin();
- arg = argsIter->first;
- if (splitQmlPropertyArg(arg,type,module,element,property)) {
- qmlClass = qdb_->findQmlType(module,element);
- if (qmlClass) {
- qmlPropGroup = new QmlPropGroupNode(qmlClass,property); //,attached);
- qmlPropGroup->setLocation(doc.startLocation());
- }
+ QString arg;
+ QString type;
+ QString topic;
+ QString module;
+ QString element;
+ QString property;
+ QmlPropertyNode* qpn = 0;
+ QmlClassNode* qmlClass = 0;
+ QmlPropertyGroupNode* qpgn = 0;
+
+ Topic qmlPropertyGroupTopic;
+ const TopicList& topics = doc.topicsUsed();
+ for (int i=0; i<topics.size(); ++i) {
+ if (topics.at(i).topic == COMMAND_QMLPROPERTYGROUP) {
+ qmlPropertyGroupTopic = topics.at(i);
+ break;
}
- if (qmlPropGroup) {
- if (qmlClass->hasProperty(property)) {
- doc.startLocation().warning(tr("QML property documented multiple times: '%1'").arg(arg));
+ }
+ if (qmlPropertyGroupTopic.isEmpty() && topics.size() > 1) {
+ qmlPropertyGroupTopic = topics.at(0);
+ qmlPropertyGroupTopic.topic = COMMAND_QMLPROPERTYGROUP;
+ arg = qmlPropertyGroupTopic.args;
+ if (splitQmlPropertyArg(arg, type, module, element, property)) {
+ int i = property.indexOf('.');
+ if (i != -1) {
+ property = property.left(i);
+ qmlPropertyGroupTopic.args = module + "::" + element + "::" + property;
+ doc.location().warning(tr("No QML property group command found; using \\%1 %2")
+ .arg(COMMAND_QMLPROPERTYGROUP).arg(qmlPropertyGroupTopic.args));
}
else {
- QmlPropertyNode *qmlPropNode = new QmlPropertyNode(qmlPropGroup,property,type,attached);
- qmlPropNode->setLocation(doc.startLocation());
+ /*
+ Assumption: No '.' in the property name
+ means there is no property group.
+ */
+ qmlPropertyGroupTopic.clear();
+ }
+ }
+ }
+
+ if (!qmlPropertyGroupTopic.isEmpty()) {
+ arg = qmlPropertyGroupTopic.args;
+ if (splitQmlPropertyGroupArg(arg, module, element, property)) {
+ qmlClass = qdb_->findQmlType(module, element);
+ if (qmlClass) {
+ qpgn = new QmlPropertyGroupNode(qmlClass, property);
+ qpgn->setLocation(doc.startLocation());
}
- ++argsIter;
- while (argsIter != args.constEnd()) {
- arg = argsIter->first;
- if (splitQmlPropertyArg(arg,type,module,element,property)) {
- if (qmlClass->hasProperty(property)) {
- doc.startLocation().warning(tr("QML property documented multiple times: '%1'").arg(arg));
+ }
+ if (topics.size() == 1) {
+ nodes.append(qpgn);
+ docs.append(doc);
+ return;
+ }
+ }
+ for (int i=0; i<topics.size(); ++i) {
+ if (topics.at(i).topic == COMMAND_QMLPROPERTYGROUP)
+ continue;
+ topic = topics.at(i).topic;
+ arg = topics.at(i).args;
+ if ((topic == COMMAND_QMLPROPERTY) || (topic == COMMAND_QMLATTACHEDPROPERTY)) {
+ bool attached = (topic == COMMAND_QMLATTACHEDPROPERTY);
+ if (splitQmlPropertyArg(arg, type, module, element, property)) {
+ qmlClass = qdb_->findQmlType(module, element);
+ if (qmlClass) {
+ if (qmlClass->hasQmlProperty(property) != 0) {
+ QString msg = tr("QML property documented multiple times: '%1'").arg(arg);
+ doc.startLocation().warning(msg);
+ }
+ else if (qpgn) {
+ qpn = new QmlPropertyNode(qpgn, property, type, attached);
+ qpn->setLocation(doc.startLocation());
}
else {
- QmlPropertyNode* qmlPropNode = new QmlPropertyNode(qmlPropGroup,
- property,
- type,
- attached);
- qmlPropNode->setLocation(doc.startLocation());
+ qpn = new QmlPropertyNode(qmlClass, property, type, attached);
+ qpn->setLocation(doc.startLocation());
+ nodes.append(qpn);
+ docs.append(doc);
}
}
- ++argsIter;
}
}
}
- return qmlPropGroup;
}
+static QSet<QString> otherMetaCommands_;
/*!
Returns the set of strings representing the common metacommands
plus some other metacommands.
*/
-QSet<QString> CppCodeParser::otherMetaCommands()
+const QSet<QString>& CppCodeParser::otherMetaCommands()
{
- return commonMetaCommands() << COMMAND_INHEADERFILE
- << COMMAND_OVERLOAD
- << COMMAND_REIMP
- << COMMAND_RELATES
- << COMMAND_CONTENTSPAGE
- << COMMAND_NEXTPAGE
- << COMMAND_PREVIOUSPAGE
- << COMMAND_INDEXPAGE
- << COMMAND_STARTPAGE
- << COMMAND_QMLINHERITS
- << COMMAND_QMLINSTANTIATES
- << COMMAND_QMLDEFAULT
- << COMMAND_QMLREADONLY
- << COMMAND_QMLABSTRACT;
+ if (otherMetaCommands_.isEmpty()) {
+ otherMetaCommands_ = commonMetaCommands();
+ otherMetaCommands_ << COMMAND_INHEADERFILE
+ << COMMAND_OVERLOAD
+ << COMMAND_REIMP
+ << COMMAND_RELATES
+ << COMMAND_CONTENTSPAGE
+ << COMMAND_NEXTPAGE
+ << COMMAND_PREVIOUSPAGE
+ << COMMAND_INDEXPAGE
+ << COMMAND_STARTPAGE
+ << COMMAND_QMLINHERITS
+ << COMMAND_QMLINSTANTIATES
+ << COMMAND_QMLDEFAULT
+ << COMMAND_QMLREADONLY
+ << COMMAND_QMLABSTRACT;
+ }
+ return otherMetaCommands_;
}
/*!
@@ -855,8 +928,8 @@ void CppCodeParser::processOtherMetaCommand(const Doc& doc,
}
}
else if (command == COMMAND_REIMP) {
- if (node->parent() && !node->parent()->isInternal()) {
- if (node != 0 && node->type() == Node::Function) {
+ if (node != 0 && node->parent() && !node->parent()->isInternal()) {
+ if (node->type() == Node::Function) {
FunctionNode *func = (FunctionNode *) node;
const FunctionNode *from = func->reimplementedFrom();
if (from == 0) {
@@ -961,8 +1034,8 @@ void CppCodeParser::processOtherMetaCommand(const Doc& doc,
QmlPropertyNode* qpn = static_cast<QmlPropertyNode*>(node);
qpn->setDefault();
}
- else if (node->type() == Node::Document && node->subType() == Node::QmlPropertyGroup) {
- QmlPropGroupNode* qpgn = static_cast<QmlPropGroupNode*>(node);
+ else if (node->type() == Node::QmlPropertyGroup) {
+ QmlPropertyGroupNode* qpgn = static_cast<QmlPropertyGroupNode*>(node);
NodeList::ConstIterator p = qpgn->childNodes().constBegin();
while (p != qpgn->childNodes().constEnd()) {
if ((*p)->type() == Node::QmlProperty) {
@@ -978,8 +1051,8 @@ void CppCodeParser::processOtherMetaCommand(const Doc& doc,
QmlPropertyNode* qpn = static_cast<QmlPropertyNode*>(node);
qpn->setReadOnly(1);
}
- else if (node->type() == Node::Document && node->subType() == Node::QmlPropertyGroup) {
- QmlPropGroupNode* qpgn = static_cast<QmlPropGroupNode*>(node);
+ else if (node->type() == Node::QmlPropertyGroup) {
+ QmlPropertyGroupNode* qpgn = static_cast<QmlPropertyGroupNode*>(node);
NodeList::ConstIterator p = qpgn->childNodes().constBegin();
while (p != qpgn->childNodes().constEnd()) {
if ((*p)->type() == Node::QmlProperty) {
@@ -2067,10 +2140,9 @@ bool CppCodeParser::matchDeclList(InnerNode *parent)
bool CppCodeParser::matchDocsAndStuff()
{
ExtraFuncData extra;
- QSet<QString> topicCommandsAllowed = topicCommands();
- QSet<QString> otherMetacommandsAllowed = otherMetaCommands();
- QSet<QString> metacommandsAllowed = topicCommandsAllowed +
- otherMetacommandsAllowed;
+ const QSet<QString>& topicCommandsAllowed = topicCommands();
+ const QSet<QString>& otherMetacommandsAllowed = otherMetaCommands();
+ const QSet<QString>& metacommandsAllowed = topicCommandsAllowed + otherMetacommandsAllowed;
while (tok != Tok_Eoi) {
if (tok == Tok_Doc) {
@@ -2087,25 +2159,22 @@ bool CppCodeParser::matchDocsAndStuff()
/*
Doc parses the comment.
*/
- Doc doc(start_loc,end_loc,comment,metacommandsAllowed);
-
+ Doc doc(start_loc,end_loc,comment,metacommandsAllowed, topicCommandsAllowed);
QString topic;
- ArgList args;
-
- QSet<QString> topicCommandsUsed = topicCommandsAllowed & doc.metaCommandsUsed();
+ bool isQmlPropertyTopic = false;
- /*
- There should be one topic command in the set,
- or none. If the set is empty, then the comment
- should be a function description.
- */
- if (topicCommandsUsed.count() > 0) {
- topic = *topicCommandsUsed.constBegin();
- args = doc.metaCommandArgs(topic);
+ const TopicList& topics = doc.topicsUsed();
+ if (!topics.isEmpty()) {
+ topic = topics[0].topic;
+ if ((topic == COMMAND_QMLPROPERTY) ||
+ (topic == COMMAND_QMLPROPERTYGROUP) ||
+ (topic == COMMAND_QMLATTACHEDPROPERTY)) {
+ isQmlPropertyTopic = true;
+ }
}
-
+ // if (isQmlPropertyTopic && doc.location().fileName().endsWith("qquickitem.cpp")) {
NodeList nodes;
- QList<Doc> docs;
+ DocList docs;
if (topic.isEmpty()) {
QStringList parentPath;
@@ -2133,43 +2202,39 @@ bool CppCodeParser::matchDocsAndStuff()
.arg(COMMAND_FN).arg(COMMAND_PAGE));
}
}
+ else if (isQmlPropertyTopic) {
+ Doc nodeDoc = doc;
+ processQmlProperties(nodeDoc, nodes, docs);
+ }
else {
- /*
- There is a topic command. Process it.
- */
- if ((topic == COMMAND_QMLPROPERTY) ||
- (topic == COMMAND_QMLATTACHEDPROPERTY)) {
+ ArgList args;
+ const QSet<QString>& topicCommandsUsed = topicCommandsAllowed & doc.metaCommandsUsed();
+ if (topicCommandsUsed.count() > 0) {
+ topic = *topicCommandsUsed.constBegin();
+ args = doc.metaCommandArgs(topic);
+ }
+ if (topicCommandsUsed.count() > 1) {
+ QString topics;
+ QSet<QString>::ConstIterator t = topicCommandsUsed.constBegin();
+ while (t != topicCommandsUsed.constEnd()) {
+ topics += " \\" + *t + ",";
+ ++t;
+ }
+ topics[topics.lastIndexOf(',')] = '.';
+ int i = topics.lastIndexOf(',');
+ topics[i] = ' ';
+ topics.insert(i+1,"and");
+ doc.location().warning(tr("Multiple topic commands found in comment: %1").arg(topics));
+ }
+ ArgList::ConstIterator a = args.constBegin();
+ while (a != args.constEnd()) {
Doc nodeDoc = doc;
- Node *node = processTopicCommandGroup(nodeDoc, topic,args);
+ Node *node = processTopicCommand(nodeDoc,topic,*a);
if (node != 0) {
nodes.append(node);
docs.append(nodeDoc);
}
- }
- else {
- if (topicCommandsUsed.count() > 1) {
- QString topics;
- QSet<QString>::ConstIterator t = topicCommandsUsed.constBegin();
- while (t != topicCommandsUsed.constEnd()) {
- topics += " \\" + *t + ",";
- ++t;
- }
- topics[topics.lastIndexOf(',')] = '.';
- int i = topics.lastIndexOf(',');
- topics[i] = ' ';
- topics.insert(i+1,"and");
- doc.location().warning(tr("Multiple topic commands found in comment: %1").arg(topics));
- }
- ArgList::ConstIterator a = args.constBegin();
- while (a != args.constEnd()) {
- Doc nodeDoc = doc;
- Node *node = processTopicCommand(nodeDoc,topic,*a);
- if (node != 0) {
- nodes.append(node);
- docs.append(nodeDoc);
- }
- ++a;
- }
+ ++a;
}
}
diff --git a/src/tools/qdoc/cppcodeparser.h b/src/tools/qdoc/cppcodeparser.h
index 957142712b..d23cc25d33 100644
--- a/src/tools/qdoc/cppcodeparser.h
+++ b/src/tools/qdoc/cppcodeparser.h
@@ -84,13 +84,16 @@ public:
virtual void doneParsingSourceFiles();
protected:
- virtual QSet<QString> topicCommands();
+ const QSet<QString>& topicCommands();
+ const QSet<QString>& otherMetaCommands();
virtual Node* processTopicCommand(const Doc& doc,
const QString& command,
const ArgLocPair& arg);
- virtual Node *processTopicCommandGroup(const Doc& doc,
- const QString& command,
- const ArgList& args);
+ void processQmlProperties(const Doc& doc, NodeList& nodes, DocList& docs);
+ bool splitQmlPropertyGroupArg(const QString& arg,
+ QString& module,
+ QString& element,
+ QString& name);
bool splitQmlPropertyArg(const QString& arg,
QString& type,
QString& module,
@@ -100,7 +103,6 @@ protected:
QString& type,
QString& module,
QString& element);
- virtual QSet<QString> otherMetaCommands();
virtual void processOtherMetaCommand(const Doc& doc,
const QString& command,
const ArgLocPair& argLocPair,
@@ -212,6 +214,7 @@ protected:
#define COMMAND_QMLCLASS Doc::alias("qmlclass")
#define COMMAND_QMLTYPE Doc::alias("qmltype")
#define COMMAND_QMLPROPERTY Doc::alias("qmlproperty")
+#define COMMAND_QMLPROPERTYGROUP Doc::alias("qmlpropertygroup")
#define COMMAND_QMLATTACHEDPROPERTY Doc::alias("qmlattachedproperty")
#define COMMAND_QMLINHERITS Doc::alias("inherits")
#define COMMAND_QMLINSTANTIATES Doc::alias("instantiates")
diff --git a/src/tools/qdoc/ditaxmlgenerator.cpp b/src/tools/qdoc/ditaxmlgenerator.cpp
index 96f5519be4..56eb145485 100644
--- a/src/tools/qdoc/ditaxmlgenerator.cpp
+++ b/src/tools/qdoc/ditaxmlgenerator.cpp
@@ -3677,8 +3677,8 @@ QString DitaXmlGenerator::guidForNode(const Node* node)
return fn->guid();
}
case Node::Document:
- if (node->subType() != Node::QmlPropertyGroup)
- break;
+ break;
+ case Node::QmlPropertyGroup:
case Node::QmlProperty:
case Node::Property:
return node->guid();
@@ -3743,7 +3743,7 @@ QString DitaXmlGenerator::linkForNode(const Node* node, const Node* relative)
}
QString link = fn;
- if (!node->isInnerNode() || node->subType() == Node::QmlPropertyGroup) {
+ if (!node->isInnerNode() || node->type() == Node::QmlPropertyGroup) {
QString guid = guidForNode(node);
if (relative && fn == fileName(relative) && guid == guidForNode(relative)) {
return QString();
@@ -4079,8 +4079,8 @@ void DitaXmlGenerator::generateDetailedQmlMember(Node* node,
QString marked;
QmlPropertyNode* qpn = 0;
- if (node->subType() == Node::QmlPropertyGroup) {
- const QmlPropGroupNode* qpgn = static_cast<const QmlPropGroupNode*>(node);
+ if (node->type() == Node::QmlPropertyGroup) {
+ const QmlPropertyGroupNode* qpgn = static_cast<const QmlPropertyGroupNode*>(node);
NodeList::ConstIterator p = qpgn->childNodes().constBegin();
if (qpgn->childNodes().size() == 1) {
qpn = static_cast<QmlPropertyNode*>(*p);
@@ -4114,50 +4114,10 @@ void DitaXmlGenerator::generateDetailedQmlMember(Node* node,
}
else if (node->type() == Node::QmlProperty) {
qpn = static_cast<QmlPropertyNode*>(node);
- if (qpn->qmlPropNodes().isEmpty()) {
- startQmlProperty(qpn,relative,marker);
- writeApiDesc(node, marker, node->title());
- writeEndTag(); // </qmlPropertyDetail>
- writeEndTag(); // </qmlProperty>
- }
- else if (qpn->qmlPropNodes().size() == 1) {
- Node* n = qpn->qmlPropNodes().at(0);
- if (n->type() == Node::QmlProperty) {
- qpn = static_cast<QmlPropertyNode*>(n);
- startQmlProperty(qpn,relative,marker);
- writeApiDesc(node, marker, node->title());
- writeEndTag(); // </qmlPropertyDetail>
- writeEndTag(); // </qmlProperty>
- }
- }
- else {
- /*
- The QML property node has multiple override nodes.
- Process the whole list as we would for a QML property
- group.
- */
- writeStartTag(DT_qmlPropertyGroup);
- QString id = "id-qml-propertygroup-" + node->name();
- id.replace('.','-');
- xmlWriter().writeAttribute("id",id);
- writeStartTag(DT_apiName);
- //writeCharacters("...");
- writeEndTag(); // </apiName>
- writeStartTag(DT_qmlPropertyGroupDetail);
- writeApiDesc(node, marker, node->title());
- writeEndTag(); // </qmlPropertyGroupDetail>
- NodeList::ConstIterator p = qpn->qmlPropNodes().constBegin();
- while (p != qpn->qmlPropNodes().constEnd()) {
- if ((*p)->type() == Node::QmlProperty) {
- QmlPropertyNode* q = static_cast<QmlPropertyNode*>(*p);
- startQmlProperty(q,relative,marker);
- writeEndTag(); // </qmlPropertyDetail>
- writeEndTag(); // </qmlProperty>
- }
- ++p;
- }
- writeEndTag(); // </qmlPropertyGroup
- }
+ startQmlProperty(qpn,relative,marker);
+ writeApiDesc(node, marker, node->title());
+ writeEndTag(); // </qmlPropertyDetail>
+ writeEndTag(); // </qmlProperty>
}
else if (node->type() == Node::QmlSignal)
writeQmlRef(DT_qmlSignal,node,relative,marker);
@@ -5326,13 +5286,13 @@ DitaXmlGenerator::generateInnerNode(InnerNode* node)
return;
if (docNode->subType() == Node::Image)
return;
- if (docNode->subType() == Node::QmlPropertyGroup)
- return;
if (docNode->subType() == Node::Page) {
if (node->count() > 0)
qDebug("PAGE %s HAS CHILDREN", qPrintable(docNode->title()));
}
}
+ else if (node->type() == Node::QmlPropertyGroup)
+ return;
/*
Obtain a code marker for the source file.
@@ -5487,8 +5447,6 @@ Node* DitaXmlGenerator::collectNodesByTypeAndSubtype(const InnerNode* parent)
if (!isDuplicate(nodeSubtypeMaps[Node::QmlClass],child->title(),child))
nodeSubtypeMaps[Node::QmlClass]->insert(child->title(),child);
break;
- case Node::QmlPropertyGroup:
- break;
case Node::QmlBasicType:
if (!isDuplicate(nodeSubtypeMaps[Node::QmlBasicType],child->title(),child))
nodeSubtypeMaps[Node::QmlBasicType]->insert(child->title(),child);
@@ -5517,6 +5475,8 @@ Node* DitaXmlGenerator::collectNodesByTypeAndSubtype(const InnerNode* parent)
break;
case Node::QmlProperty:
break;
+ case Node::QmlPropertyGroup:
+ break;
case Node::QmlSignal:
break;
case Node::QmlSignalHandler:
diff --git a/src/tools/qdoc/doc.cpp b/src/tools/qdoc/doc.cpp
index 42b98502e0..04d673e748 100644
--- a/src/tools/qdoc/doc.cpp
+++ b/src/tools/qdoc/doc.cpp
@@ -376,7 +376,7 @@ public:
bool hasLegalese : 1;
bool hasSectioningUnits : 1;
DocPrivateExtra *extra;
- TopicList topics;
+ TopicList topics_;
DitaRefList ditamap_;
};
@@ -571,7 +571,7 @@ void DocParser::parse(const QString& source,
cachedPos = 0;
priv = docPrivate;
priv->text << Atom::Nop;
- priv->topics.clear();
+ priv->topics_.clear();
paraState = OutsideParagraph;
inTableHeader = false;
@@ -1404,7 +1404,7 @@ void DocParser::parse(const QString& source,
QString arg = getMetaCommandArgument(cmdStr);
priv->metaCommandMap[cmdStr].append(ArgLocPair(arg,location()));
if (possibleTopics.contains(cmdStr)) {
- priv->topics.append(Topic(cmdStr,arg));
+ priv->topics_.append(Topic(cmdStr,arg));
}
}
else if (macroHash()->contains(cmdStr)) {
@@ -2751,6 +2751,7 @@ QString DocParser::slashed(const QString& str)
#define COMMAND_BRIEF Doc::alias("brief")
#define COMMAND_QMLBRIEF Doc::alias("qmlbrief")
+#if 0
Doc::Doc(const Location& start_loc,
const Location& end_loc,
const QString& source,
@@ -2760,6 +2761,7 @@ Doc::Doc(const Location& start_loc,
DocParser parser;
parser.parse(source,priv,metaCommandSet,QSet<QString>());
}
+#endif
/*!
Parse the qdoc comment \a source. Build up a list of all the topic
@@ -3026,7 +3028,7 @@ const QSet<QString> &Doc::metaCommandsUsed() const
*/
const TopicList& Doc::topicsUsed() const
{
- return priv == 0 ? *nullTopicList() : priv->topics;
+ return priv == 0 ? *nullTopicList() : priv->topics_;
}
ArgList Doc::metaCommandArgs(const QString& metacommand) const
diff --git a/src/tools/qdoc/doc.h b/src/tools/qdoc/doc.h
index ca9787595f..23fc4c5b8b 100644
--- a/src/tools/qdoc/doc.h
+++ b/src/tools/qdoc/doc.h
@@ -71,7 +71,10 @@ struct Topic
{
QString topic;
QString args;
+ Topic() { }
Topic(QString& t, QString a) : topic(t), args(a) { }
+ bool isEmpty() const { return topic.isEmpty(); }
+ void clear() { topic.clear(); args.clear(); }
};
typedef QList<Topic> TopicList;
@@ -136,10 +139,6 @@ public:
};
Doc() : priv(0) {}
- Doc(const Location &start_loc,
- const Location &end_loc,
- const QString &source,
- const QSet<QString> &metaCommandSet);
Doc(const Location& start_loc,
const Location& end_loc,
const QString& source,
@@ -196,6 +195,7 @@ private:
void detach();
DocPrivate *priv;
};
+typedef QList<Doc> DocList;
QT_END_NAMESPACE
diff --git a/src/tools/qdoc/doc/config/qdoc.qdocconf b/src/tools/qdoc/doc/config/qdoc.qdocconf
index a7fbb38463..a6ae18a675 100644
--- a/src/tools/qdoc/doc/config/qdoc.qdocconf
+++ b/src/tools/qdoc/doc/config/qdoc.qdocconf
@@ -70,3 +70,5 @@ depends += \
qtwebkitexamples \
qtxml \
qtxmlpatterns
+
+navigation.landingpage = "QDoc Manual"
diff --git a/src/tools/qdoc/generator.cpp b/src/tools/qdoc/generator.cpp
index 889f0f55ca..8cc8e0050a 100644
--- a/src/tools/qdoc/generator.cpp
+++ b/src/tools/qdoc/generator.cpp
@@ -97,6 +97,7 @@ QStringList Generator::styleDirs;
QStringList Generator::styleFiles;
bool Generator::debugging_ = false;
bool Generator::noLinkErrors_ = false;
+bool Generator::redirectDocumentationToDevNull_ = false;
Generator::Passes Generator::qdocPass_ = Both;
void Generator::setDebugSegfaultFlag(bool b)
@@ -268,7 +269,8 @@ void Generator::beginSubPage(const InnerNode* node, const QString& fileName)
path += fileName;
Generator::debugSegfault("Writing: " + path);
outFileNames.insert(fileName,fileName);
- QFile* outFile = new QFile(path);
+
+ QFile* outFile = new QFile(redirectDocumentationToDevNull_ ? QStringLiteral("/dev/null") : path);
if (!outFile->open(QFile::WriteOnly))
node->location().fatal(tr("Cannot open output file '%1'").arg(outFile->fileName()));
QTextStream* out = new QTextStream(outFile);
@@ -299,7 +301,7 @@ QString Generator::fileBase(const Node *node) const
node = node->relates();
else if (!node->isInnerNode())
node = node->parent();
- if (node->subType() == Node::QmlPropertyGroup) {
+ if (node->type() == Node::QmlPropertyGroup) {
node = node->parent();
}
@@ -467,7 +469,7 @@ QString Generator::fullDocumentLocation(const Node *node, bool subdir)
parentName = fullDocumentLocation(node->relates());
}
else if ((parentNode = node->parent())) {
- if (parentNode->subType() == Node::QmlPropertyGroup) {
+ if (parentNode->type() == Node::QmlPropertyGroup) {
parentNode = parentNode->parent();
parentName = fullDocumentLocation(parentNode);
}
@@ -940,13 +942,13 @@ void Generator::generateInnerNode(InnerNode* node)
return;
if (docNode->subType() == Node::Image)
return;
- if (docNode->subType() == Node::QmlPropertyGroup)
- return;
if (docNode->subType() == Node::Page) {
if (node->count() > 0)
qDebug("PAGE %s HAS CHILDREN", qPrintable(docNode->title()));
}
}
+ else if (node->type() == Node::QmlPropertyGroup)
+ return;
/*
Obtain a code marker for the source file.
@@ -1475,6 +1477,7 @@ QString Generator::indent(int level, const QString& markedCode)
void Generator::initialize(const Config &config)
{
outputFormats = config.getOutputFormats();
+ redirectDocumentationToDevNull_ = config.getBool(CONFIG_REDIRECTDOCUMENTATIONTODEVNULL);
if (!outputFormats.isEmpty()) {
outDir_ = config.getOutputDir();
if (outDir_.isEmpty()) {
@@ -1907,8 +1910,6 @@ QString Generator::typeString(const Node *node)
switch (node->subType()) {
case Node::QmlClass:
return "type";
- case Node::QmlPropertyGroup:
- return "property group";
case Node::QmlBasicType:
return "type";
default:
@@ -1923,6 +1924,16 @@ QString Generator::typeString(const Node *node)
return "function";
case Node::Property:
return "property";
+ case Node::QmlPropertyGroup:
+ return "property group";
+ case Node::QmlProperty:
+ return "QML property";
+ case Node::QmlSignal:
+ return "QML signal";
+ case Node::QmlSignalHandler:
+ return "QML signal handler";
+ case Node::QmlMethod:
+ return "QML method";
default:
return "documentation";
}
diff --git a/src/tools/qdoc/generator.h b/src/tools/qdoc/generator.h
index 58e9073922..4657f71e1d 100644
--- a/src/tools/qdoc/generator.h
+++ b/src/tools/qdoc/generator.h
@@ -206,6 +206,7 @@ private:
static QStringList styleFiles;
static bool debugging_;
static bool noLinkErrors_;
+ static bool redirectDocumentationToDevNull_;
static Passes qdocPass_;
void appendFullName(Text& text,
diff --git a/src/tools/qdoc/helpprojectwriter.cpp b/src/tools/qdoc/helpprojectwriter.cpp
index 0cdb2de776..9e67007eba 100644
--- a/src/tools/qdoc/helpprojectwriter.cpp
+++ b/src/tools/qdoc/helpprojectwriter.cpp
@@ -135,6 +135,7 @@ void HelpProjectWriter::readSelectors(SubProject &subproject, const QStringList
typeHash["qmlsignal"] = Node::QmlSignal;
typeHash["qmlsignalhandler"] = Node::QmlSignalHandler;
typeHash["qmlmethod"] = Node::QmlMethod;
+ typeHash["qmlpropertygroup"] = Node::QmlPropertyGroup;
QHash<QString, Node::SubType> subTypeHash;
subTypeHash["example"] = Node::Example;
@@ -145,7 +146,6 @@ void HelpProjectWriter::readSelectors(SubProject &subproject, const QStringList
subTypeHash["page"] = Node::Page;
subTypeHash["externalpage"] = Node::ExternalPage;
subTypeHash["qmlclass"] = Node::QmlClass;
- subTypeHash["qmlpropertygroup"] = Node::QmlPropertyGroup;
subTypeHash["qmlbasictype"] = Node::QmlBasicType;
QSet<Node::SubType> allSubTypes = QSet<Node::SubType>::fromList(subTypeHash.values());
@@ -435,21 +435,24 @@ void HelpProjectWriter::generateSections(HelpProject &project,
continue;
if (childNode->type() == Node::Document) {
+ childMap[static_cast<const DocNode *>(childNode)->fullTitle()] = childNode;
+ }
+ else if (childNode->type() == Node::QmlPropertyGroup) {
/*
Don't visit QML property group nodes,
but visit their children, which are all
QML property nodes.
+
+ This is probably not correct anymore,
+ because The Qml Property Group is an
+ actual documented thing.
*/
- if (childNode->subType() == Node::QmlPropertyGroup) {
- const InnerNode* inner = static_cast<const InnerNode*>(childNode);
- foreach (const Node* n, inner->childNodes()) {
- if (n->access() == Node::Private)
- continue;
- childMap[n->fullDocumentName()] = n;
- }
+ const InnerNode* inner = static_cast<const InnerNode*>(childNode);
+ foreach (const Node* n, inner->childNodes()) {
+ if (n->access() == Node::Private)
+ continue;
+ childMap[n->fullDocumentName()] = n;
}
- else
- childMap[static_cast<const DocNode *>(childNode)->fullTitle()] = childNode;
}
else {
// Store member status of children
diff --git a/src/tools/qdoc/htmlgenerator.cpp b/src/tools/qdoc/htmlgenerator.cpp
index 7cb56974d5..4cd2206f9c 100644
--- a/src/tools/qdoc/htmlgenerator.cpp
+++ b/src/tools/qdoc/htmlgenerator.cpp
@@ -166,9 +166,9 @@ void HtmlGenerator::initializeGenerator(const Config &config)
pleaseGenerateMacRef = config.getBool(HtmlGenerator::format() +
Config::dot +
HTMLGENERATOR_GENERATEMACREFS);
- noBreadCrumbs = config.getBool(HtmlGenerator::format() +
+ noNavigationBar = config.getBool(HtmlGenerator::format() +
Config::dot +
- HTMLGENERATOR_NOBREADCRUMBS);
+ HTMLGENERATOR_NONAVIGATIONBAR);
project = config.getString(CONFIG_PROJECT);
@@ -229,6 +229,25 @@ void HtmlGenerator::initializeGenerator(const Config &config)
examplesPath = config.getString(CONFIG_EXAMPLESINSTALLPATH);
if (!examplesPath.isEmpty())
examplesPath += QLatin1Char('/');
+
+ //retrieve the config for the navigation bar
+ homepage = config.getString(CONFIG_NAVIGATION
+ + Config::dot
+ + CONFIG_HOMEPAGE);
+
+ landingpage = config.getString(CONFIG_NAVIGATION
+ + Config::dot
+ + CONFIG_LANDINGPAGE);
+
+ cppclassespage = config.getString(CONFIG_NAVIGATION
+ + Config::dot
+ + CONFIG_CPPCLASSESPAGE);
+
+ qmltypespage = config.getString(CONFIG_NAVIGATION
+ + Config::dot
+ + CONFIG_QMLTYPESPAGE);
+
+ buildversion = config.getString(CONFIG_BUILDVERSION);
}
/*!
@@ -1616,129 +1635,67 @@ QString HtmlGenerator::fileExtension() const
}
/*!
- Output breadcrumb list in the html file.
+ Output navigation list in the html file.
*/
-void HtmlGenerator::generateBreadCrumbs(const QString &title,
+void HtmlGenerator::generateNavigationBar(const QString &title,
const Node *node,
CodeMarker *marker)
{
- if (noBreadCrumbs)
+ if (noNavigationBar)
+ return;
+
+ Text navigationbar;
+
+ if (homepage == title)
return;
+ if (!homepage.isEmpty())
+ navigationbar << Atom(Atom::ListItemLeft)
+ << Atom(Atom::AutoLink, homepage)
+ << Atom(Atom::ListItemRight);
+ if (!landingpage.isEmpty() && landingpage != title)
+ navigationbar << Atom(Atom::ListItemLeft)
+ << Atom(Atom::AutoLink, landingpage)
+ << Atom(Atom::ListItemRight);
- Text breadcrumbs;
if (node->type() == Node::Class) {
const ClassNode *cn = static_cast<const ClassNode *>(node);
QString name = node->moduleName();
- breadcrumbs << Atom(Atom::ListItemLeft)
- << Atom(Atom::Link, QLatin1String("All Modules"))
- << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK)
- << Atom(Atom::String, QLatin1String("Modules"))
- << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK)
- << Atom(Atom::ListItemRight);
- if (!name.isEmpty())
- breadcrumbs << Atom(Atom::ListItemLeft)
- << Atom(Atom::AutoLink, name)
+
+ if (!cppclassespage.isEmpty())
+ navigationbar << Atom(Atom::ListItemLeft)
+ << Atom(Atom::Link, cppclassespage)
+ << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK)
+ << Atom(Atom::String, QLatin1String("C++ Classes"))
+ << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK)
<< Atom(Atom::ListItemRight);
+
if (!cn->name().isEmpty())
- breadcrumbs << Atom(Atom::ListItemLeft)
+ navigationbar << Atom(Atom::ListItemLeft)
<< Atom(Atom::String, protectEnc(cn->name()))
<< Atom(Atom::ListItemRight);
}
else if (node->type() == Node::Document) {
- const DocNode* fn = static_cast<const DocNode*>(node);
- if (node->subType() == Node::Module) {
- breadcrumbs << Atom(Atom::ListItemLeft)
- << Atom(Atom::Link, QLatin1String("All Modules"))
+ if (node->subType() == Node::QmlClass || node->subType() == Node::QmlBasicType) {
+ if (!qmltypespage.isEmpty())
+ navigationbar << Atom(Atom::ListItemLeft)
+ << Atom(Atom::Link, qmltypespage)
<< Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK)
- << Atom(Atom::String, QLatin1String("Modules"))
+ << Atom(Atom::String, QLatin1String("QML Types"))
<< Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK)
<< Atom(Atom::ListItemRight);
- QString name = node->name();
- if (!name.isEmpty())
- breadcrumbs << Atom(Atom::ListItemLeft)
- << Atom(Atom::String, protectEnc(name))
- << Atom(Atom::ListItemRight);
- }
- else if (node->subType() == Node::Group) {
- if (fn->name() == QString("modules"))
- breadcrumbs << Atom(Atom::String, QLatin1String("Modules"));
- else
- breadcrumbs << Atom(Atom::ListItemLeft)
- << Atom(Atom::String, protectEnc(title))
- << Atom(Atom::ListItemRight);
- }
- else if (node->subType() == Node::Page) {
- if (fn->name() == QString("qdeclarativeexamples.html")) {
- breadcrumbs << Atom(Atom::ListItemLeft)
- << Atom(Atom::Link, QLatin1String("Qt Examples"))
- << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK)
- << Atom(Atom::String, QLatin1String("Examples"))
- << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK)
- << Atom(Atom::ListItemRight);
- breadcrumbs << Atom(Atom::ListItemLeft)
- << Atom(Atom::AutoLink, QLatin1String("QML Examples & Demos"))
- << Atom(Atom::ListItemRight);
- }
- else if (fn->name().startsWith("examples-")) {
- breadcrumbs << Atom(Atom::ListItemLeft)
- << Atom(Atom::Link, QLatin1String("Qt Examples"))
- << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK)
- << Atom(Atom::String, QLatin1String("Examples"))
- << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK)
- << Atom(Atom::ListItemRight);
- breadcrumbs << Atom(Atom::ListItemLeft)
- << Atom(Atom::String, protectEnc(title))
- << Atom(Atom::ListItemRight);
- }
- else if (fn->name() == QString("namespaces.html"))
- breadcrumbs << Atom(Atom::String, QLatin1String("Namespaces"));
- else
- breadcrumbs << Atom(Atom::ListItemLeft)
- << Atom(Atom::String, protectEnc(title))
- << Atom(Atom::ListItemRight);
- }
- else if (node->subType() == Node::QmlClass) {
- breadcrumbs << Atom(Atom::ListItemLeft)
- << Atom(Atom::AutoLink, QLatin1String("Basic QML Types"))
- << Atom(Atom::ListItemRight);
- breadcrumbs << Atom(Atom::ListItemLeft)
+
+ navigationbar << Atom(Atom::ListItemLeft)
<< Atom(Atom::String, protectEnc(title))
<< Atom(Atom::ListItemRight);
}
- else if (node->subType() == Node::Example) {
- breadcrumbs << Atom(Atom::ListItemLeft)
- << Atom(Atom::Link, QLatin1String("Qt Examples"))
- << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK)
- << Atom(Atom::String, QLatin1String("Examples"))
- << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK)
- << Atom(Atom::ListItemRight);
- QStringList sl = fn->name().split('/');
- if (sl.contains("declarative"))
- breadcrumbs << Atom(Atom::ListItemLeft)
- << Atom(Atom::AutoLink, QLatin1String("QML Examples & Demos"))
- << Atom(Atom::ListItemRight);
- else {
- QString name = protectEnc("examples-" + sl.at(0) + ".html"); // this generates an empty link
- QString t = CodeParser::titleFromName(name);
- }
- breadcrumbs << Atom(Atom::ListItemLeft)
- << Atom(Atom::String, protectEnc(title))
- << Atom(Atom::ListItemRight);
+ else {
+ navigationbar << Atom(Atom::ListItemLeft)
+ << Atom(Atom::String, protectEnc(title))
+ << Atom(Atom::ListItemRight);
}
}
- else if (node->type() == Node::Namespace) {
- breadcrumbs << Atom(Atom::ListItemLeft)
- << Atom(Atom::Link, QLatin1String("All Namespaces"))
- << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK)
- << Atom(Atom::String, QLatin1String("Namespaces"))
- << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK)
- << Atom(Atom::ListItemRight);
- breadcrumbs << Atom(Atom::ListItemLeft)
- << Atom(Atom::String, protectEnc(title))
- << Atom(Atom::ListItemRight);
- }
- generateText(breadcrumbs, node, marker);
+ generateText(navigationbar, node, marker);
}
void HtmlGenerator::generateHeader(const QString& title,
@@ -1782,7 +1739,8 @@ void HtmlGenerator::generateHeader(const QString& title,
#endif
out() << QString(postHeader).replace("\\" + COMMAND_VERSION, qdb_->version());
- generateBreadCrumbs(title,node,marker);
+ generateNavigationBar(title,node,marker);
+ out() << "<li id=\"buildversion\">\n" << buildversion << "</li>\n";
out() << QString(postPostHeader).replace("\\" + COMMAND_VERSION, qdb_->version());
navigationLinks.clear();
@@ -3308,8 +3266,8 @@ QString HtmlGenerator::refForNode(const Node *node)
}
break;
case Node::Document:
- if (node->subType() != Node::QmlPropertyGroup)
- break;
+ break;
+ case Node::QmlPropertyGroup:
case Node::QmlProperty:
case Node::Property:
ref = node->name() + "-prop";
@@ -3372,7 +3330,7 @@ QString HtmlGenerator::linkForNode(const Node *node, const Node *relative)
}
QString link = fn;
- if (!node->isInnerNode() || node->subType() == Node::QmlPropertyGroup) {
+ if (!node->isInnerNode() || node->type() == Node::QmlPropertyGroup) {
QString ref = refForNode(node);
if (relative && fn == fileName(relative) && ref == refForNode(relative))
return QString();
@@ -3778,6 +3736,22 @@ void HtmlGenerator::generateQmlSummary(const Section& section,
while (m != section.members.constEnd()) {
out() << "<li class=\"fn\">";
generateQmlItem(*m,relative,marker,true);
+ if ((*m)->type() == Node::QmlPropertyGroup) {
+ const QmlPropertyGroupNode* qpgn = static_cast<const QmlPropertyGroupNode*>(*m);
+ if (!qpgn->childNodes().isEmpty()) {
+ NodeList::ConstIterator p = qpgn->childNodes().constBegin();
+ out() << "<ul>\n";
+ while (p != qpgn->childNodes().constEnd()) {
+ if ((*p)->type() == Node::QmlProperty) {
+ out() << "<li class=\"fn\">";
+ generateQmlItem(*p, relative, marker, true);
+ out() << "</li>\n";
+ }
+ ++p;
+ }
+ out() << "</ul>\n";
+ }
+ }
out() << "</li>\n";
++m;
}
@@ -3799,11 +3773,18 @@ void HtmlGenerator::generateDetailedQmlMember(Node *node,
#endif
generateExtractionMark(node, MemberMark);
out() << "<div class=\"qmlitem\">";
- if (node->subType() == Node::QmlPropertyGroup) {
- const QmlPropGroupNode* qpgn = static_cast<const QmlPropGroupNode*>(node);
+ if (node->type() == Node::QmlPropertyGroup) {
+ const QmlPropertyGroupNode* qpgn = static_cast<const QmlPropertyGroupNode*>(node);
NodeList::ConstIterator p = qpgn->childNodes().constBegin();
out() << "<div class=\"qmlproto\">";
out() << "<table class=\"qmlname\">";
+
+ QString heading = "Property Group: " + qpgn->name();
+ out() << "<tr valign=\"top\" class=\"even\">";
+ out() << "<th class=\"centerAlign\"><p>";
+ out() << "<a name=\"" + refForNode(qpgn) + "\"></a>";
+ out() << "<b>" << heading << "</b>";
+ out() << "</p></th></tr>";
while (p != qpgn->childNodes().constEnd()) {
if ((*p)->type() == Node::QmlProperty) {
qpn = static_cast<QmlPropertyNode*>(*p);
@@ -3825,68 +3806,23 @@ void HtmlGenerator::generateDetailedQmlMember(Node *node,
}
else if (node->type() == Node::QmlProperty) {
qpn = static_cast<QmlPropertyNode*>(node);
- /*
- If the QML property node has a single subproperty,
- override, replace qpn with that override node and
- proceed as normal.
- */
- if (qpn->qmlPropNodes().size() == 1) {
- Node* n = qpn->qmlPropNodes().at(0);
- if (n->type() == Node::QmlProperty)
- qpn = static_cast<QmlPropertyNode*>(n);
- }
- /*
- Now qpn either has no overrides, or it has more
- than 1. If it has none, proceed to output as nortmal.
- */
- if (qpn->qmlPropNodes().isEmpty()) {
- out() << "<div class=\"qmlproto\">";
- out() << "<table class=\"qmlname\">";
- out() << "<tr valign=\"top\" class=\"odd\">";
- out() << "<td class=\"tblQmlPropNode\"><p>";
- out() << "<a name=\"" + refForNode(qpn) + "\"></a>";
- if (!qpn->isReadOnlySet()) {
- if (qpn->declarativeCppNode())
- qpn->setReadOnly(!qpn->isWritable(qdb_));
- }
- if (qpn->isReadOnly())
- out() << "<span class=\"qmlreadonly\">read-only</span>";
- if (qpn->isDefault())
- out() << "<span class=\"qmldefault\">default</span>";
- generateQmlItem(qpn, relative, marker, false);
- out() << "</p></td></tr>";
- out() << "</table>";
- out() << "</div>";
- }
- else {
- /*
- The QML property node has multiple override nodes.
- Process the whole list as we would for a QML property
- group.
- */
- NodeList::ConstIterator p = qpn->qmlPropNodes().constBegin();
- out() << "<div class=\"qmlproto\">";
- out() << "<table class=\"qmlname\">";
- while (p != qpn->qmlPropNodes().constEnd()) {
- if ((*p)->type() == Node::QmlProperty) {
- QmlPropertyNode* q = static_cast<QmlPropertyNode*>(*p);
- out() << "<tr valign=\"top\" class=\"odd\">";
- out() << "<td class=\"tblQmlPropNode\"><p>";
- out() << "<a name=\"" + refForNode(q) + "\"></a>";
- if (!qpn->isReadOnlySet())
- qpn->setReadOnly(!qpn->isWritable(qdb_));
- if (qpn->isReadOnly())
- out() << "<span class=\"qmlreadonly\">read-only</span>";
- if (qpn->isDefault())
- out() << "<span class=\"qmldefault\">default</span>";
- generateQmlItem(q, relative, marker, false);
- out() << "</p></td></tr>";
- }
- ++p;
- }
- out() << "</table>";
- out() << "</div>";
- }
+ out() << "<div class=\"qmlproto\">";
+ out() << "<table class=\"qmlname\">";
+ out() << "<tr valign=\"top\" class=\"odd\">";
+ out() << "<td class=\"tblQmlPropNode\"><p>";
+ out() << "<a name=\"" + refForNode(qpn) + "\"></a>";
+ if (!qpn->isReadOnlySet()) {
+ if (qpn->declarativeCppNode())
+ qpn->setReadOnly(!qpn->isWritable(qdb_));
+ }
+ if (qpn->isReadOnly())
+ out() << "<span class=\"qmlreadonly\">read-only</span>";
+ if (qpn->isDefault())
+ out() << "<span class=\"qmldefault\">default</span>";
+ generateQmlItem(qpn, relative, marker, false);
+ out() << "</p></td></tr>";
+ out() << "</table>";
+ out() << "</div>";
}
else if (node->type() == Node::QmlSignal) {
const FunctionNode* qsn = static_cast<const FunctionNode*>(node);
@@ -4359,8 +4295,6 @@ void HtmlGenerator::reportOrphans(const InnerNode* parent)
break;
case Node::QmlClass:
break;
- case Node::QmlPropertyGroup:
- break;
case Node::QmlBasicType:
break;
case Node::QmlModule:
@@ -4394,6 +4328,8 @@ void HtmlGenerator::reportOrphans(const InnerNode* parent)
if (!related)
child->location().warning(tr("Global variable, %1, %2").arg(child->name()).arg(message));
break;
+ case Node::QmlPropertyGroup:
+ break;
case Node::QmlProperty:
if (!related)
child->location().warning(tr("Global QML property, %1, %2").arg(child->name()).arg(message));
diff --git a/src/tools/qdoc/htmlgenerator.h b/src/tools/qdoc/htmlgenerator.h
index 0a6717461e..54747cd6d6 100644
--- a/src/tools/qdoc/htmlgenerator.h
+++ b/src/tools/qdoc/htmlgenerator.h
@@ -127,7 +127,7 @@ private:
};
const QPair<QString,QString> anchorForNode(const Node *node);
- void generateBreadCrumbs(const QString& title,
+ void generateNavigationBar(const QString& title,
const Node *node,
CodeMarker *marker);
void generateHeader(const QString& title,
@@ -239,7 +239,7 @@ private:
QString footer;
QString address;
bool pleaseGenerateMacRef;
- bool noBreadCrumbs;
+ bool noNavigationBar;
QString project;
QString projectDescription;
QString projectUrl;
@@ -252,6 +252,12 @@ private:
QStack<QXmlStreamWriter*> xmlWriterStack;
static int id;
QList<ManifestMetaFilter> manifestMetaContent;
+ QString homepage;
+ QString landingpage;
+ QString cppclassespage;
+ QString qmltypespage;
+ QString buildversion;
+
public:
static bool debugging_on;
static QString divNavTop;
@@ -262,9 +268,9 @@ public:
#define HTMLGENERATOR_GENERATEMACREFS "generatemacrefs" // ### document me
#define HTMLGENERATOR_POSTHEADER "postheader"
#define HTMLGENERATOR_POSTPOSTHEADER "postpostheader"
-#define HTMLGENERATOR_NOBREADCRUMBS "nobreadcrumbs"
+#define HTMLGENERATOR_NONAVIGATIONBAR "nonavigationbar"
+
QT_END_NAMESPACE
#endif
-
diff --git a/src/tools/qdoc/main.cpp b/src/tools/qdoc/main.cpp
index 3ec121f795..ef8a6fd9c5 100644
--- a/src/tools/qdoc/main.cpp
+++ b/src/tools/qdoc/main.cpp
@@ -95,6 +95,7 @@ bool creationTimeBefore(const QFileInfo &fi1, const QFileInfo &fi2)
static bool highlighting = false;
static bool showInternal = false;
+static bool redirectDocumentationToDevNull = false;
static bool noLinkErrors = false;
static bool obsoleteLinks = false;
static QStringList defines;
@@ -139,6 +140,8 @@ static void printHelp()
"Run qdoc to read the index files and generate the docs\n"
" -showinternal "
"Include content marked internal\n"
+ " -redirect-documentation-to-dev-null "
+ "Save all documentation content to /dev/null. Useful if someone is interested in qdoc errors only.\n"
" -version "
"Display version of qdoc and exit\n") );
}
@@ -257,6 +260,7 @@ static void processQdocconfFile(const QString &fileName)
}
config.setStringList(CONFIG_SYNTAXHIGHLIGHTING, QStringList(highlighting ? "true" : "false"));
config.setStringList(CONFIG_SHOWINTERNAL, QStringList(showInternal ? "true" : "false"));
+ config.setStringList(CONFIG_REDIRECTDOCUMENTATIONTODEVNULL, QStringList(redirectDocumentationToDevNull ? "true" : "false"));
config.setStringList(CONFIG_NOLINKERRORS, QStringList(noLinkErrors ? "true" : "false"));
config.setStringList(CONFIG_OBSOLETELINKS, QStringList(obsoleteLinks ? "true" : "false"));
@@ -573,6 +577,9 @@ int main(int argc, char **argv)
else if (opt == "-showinternal") {
showInternal = true;
}
+ else if (opt == "-redirect-documentation-to-dev-null") {
+ redirectDocumentationToDevNull = true;
+ }
else if (opt == "-no-examples") {
Config::generateExamples = false;
}
diff --git a/src/tools/qdoc/node.cpp b/src/tools/qdoc/node.cpp
index 2184e302ae..fd56c77742 100644
--- a/src/tools/qdoc/node.cpp
+++ b/src/tools/qdoc/node.cpp
@@ -151,11 +151,11 @@ QString Node::fullName(const Node* relative) const
*/
void Node::setDoc(const Doc& doc, bool replace)
{
- if (!d.isEmpty() && !replace) {
+ if (!doc_.isEmpty() && !replace) {
doc.location().warning(tr("Overrides a previous doc"));
- d.location().warning(tr("(The previous doc is here)"));
+ doc_.location().warning(tr("(The previous doc is here)"));
}
- d = doc;
+ doc_ = doc;
}
/*!
@@ -311,6 +311,8 @@ QString Node::nodeTypeString(unsigned t)
return "variable";
case QmlProperty:
return "QML property";
+ case QmlPropertyGroup:
+ return "QML property group";
case QmlSignal:
return "QML signal";
case QmlSignalHandler:
@@ -359,8 +361,6 @@ QString Node::nodeSubtypeString(unsigned t)
return "external page";
case QmlClass:
return "QML type";
- case QmlPropertyGroup:
- return "QML property group";
case QmlBasicType:
return "QML basic type";
case QmlModule:
@@ -742,12 +742,12 @@ void InnerNode::getMemberClasses(NodeMap& out)
Node *InnerNode::findChildNodeByName(const QString& name)
{
Node *node = childMap.value(name);
- if (node && node->subType() != QmlPropertyGroup)
+ if (node && node->type() != QmlPropertyGroup)
return node;
if ((type() == Document) && (subType() == QmlClass)) {
for (int i=0; i<children_.size(); ++i) {
Node* n = children_.at(i);
- if (n->subType() == QmlPropertyGroup) {
+ if (n->type() == QmlPropertyGroup) {
node = static_cast<InnerNode*>(n)->findChildNodeByName(name);
if (node)
return node;
@@ -771,7 +771,7 @@ void InnerNode::findNodes(const QString& name, QList<Node*>& n)
if ((type() == Document) && (subType() == QmlClass)) {
for (int i=0; i<children_.size(); ++i) {
node = children_.at(i);
- if (node->subType() == QmlPropertyGroup) {
+ if (node->type() == QmlPropertyGroup) {
node = static_cast<InnerNode*>(node)->findChildNodeByName(name);
if (node) {
n.append(node);
@@ -793,7 +793,7 @@ void InnerNode::findNodes(const QString& name, QList<Node*>& n)
*/
for (int i=0; i<nodes.size(); ++i) {
node = nodes.at(i);
- if (node->subType() != QmlPropertyGroup)
+ if (node->type() != QmlPropertyGroup)
n.append(node);
else {
node = static_cast<InnerNode*>(node)->findChildNodeByName(name);
@@ -829,14 +829,14 @@ Node* InnerNode::findChildNodeByName(const QString& name, bool qml)
if (!node->isQmlNode())
return node;
}
- else if (node->isQmlNode() && (node->subType() != QmlPropertyGroup))
+ else if (node->isQmlNode() && (node->type() != QmlPropertyGroup))
return node;
}
}
if (qml && (type() == Document) && (subType() == QmlClass)) {
for (int i=0; i<children_.size(); ++i) {
Node* node = children_.at(i);
- if (node->subType() == QmlPropertyGroup) {
+ if (node->type() == QmlPropertyGroup) {
node = static_cast<InnerNode*>(node)->findChildNodeByName(name);
if (node)
return node;
@@ -1371,6 +1371,26 @@ void InnerNode::removeRelated(Node *pseudoChild)
}
/*!
+ If this node has a child that is a QML property named \a n,
+ return the pointer to that child.
+ */
+QmlPropertyNode* InnerNode::hasQmlProperty(const QString& n) const
+{
+ foreach (Node* child, childNodes()) {
+ if (child->type() == Node::QmlProperty) {
+ if (child->name() == n)
+ return static_cast<QmlPropertyNode*>(child);
+ }
+ else if (child->type() == Node::QmlPropertyGroup) {
+ QmlPropertyNode* t = child->hasQmlProperty(n);
+ if (t)
+ return t;
+ }
+ }
+ return 0;
+}
+
+/*!
\class LeafNode
*/
@@ -1673,25 +1693,6 @@ QString DocNode::subTitle() const
}
/*!
- Returns true if this QML type or property group contains a
- property named \a name.
- */
-bool DocNode::hasProperty(const QString& name) const
-{
- foreach (Node* child, childNodes()) {
- if (child->type() == Node::Document && child->subType() == Node::QmlPropertyGroup) {
- if (child->hasProperty(name))
- return true;
- }
- else if (child->type() == Node::QmlProperty) {
- if (child->hasProperty(name))
- return true;
- }
- }
- return false;
-}
-
-/*!
The constructor calls the DocNode constructor with
\a parent, \a name, and Node::Example.
*/
@@ -2273,8 +2274,8 @@ QmlBasicTypeNode::QmlBasicTypeNode(InnerNode *parent,
Constructor for the Qml property group node. \a parent is
always a QmlClassNode.
*/
-QmlPropGroupNode::QmlPropGroupNode(QmlClassNode* parent, const QString& name)
- : DocNode(parent, name, QmlPropertyGroup, Node::ApiPage)
+QmlPropertyGroupNode::QmlPropertyGroupNode(QmlClassNode* parent, const QString& name)
+ : InnerNode(QmlPropertyGroup, parent, name)
{
idNumber_ = -1;
}
@@ -2286,24 +2287,17 @@ QmlPropGroupNode::QmlPropGroupNode(QmlClassNode* parent, const QString& name)
property group count and set the id number to the new
value.
*/
-QString QmlPropGroupNode::idNumber()
+QString QmlPropertyGroupNode::idNumber()
{
if (idNumber_ == -1)
idNumber_ = incPropertyGroupCount();
return QString().setNum(idNumber_);
}
-
/*!
- Constructor for the QML property node, when the \a parent
- is QML property group node. This constructor is only used
- for creating QML property nodes for QML elements, i.e.
- not for creating QML property nodes for QML components.
- Hopefully, this constructor will become obsolete, so don't
- use it unless one of the other two constructors can't be
- used.
+ Constructor for the QML property node.
*/
-QmlPropertyNode::QmlPropertyNode(QmlPropGroupNode *parent,
+QmlPropertyNode::QmlPropertyNode(InnerNode* parent,
const QString& name,
const QString& type,
bool attached)
@@ -2311,56 +2305,14 @@ QmlPropertyNode::QmlPropertyNode(QmlPropGroupNode *parent,
type_(type),
stored_(FlagValueDefault),
designable_(FlagValueDefault),
+ isAlias_(false),
isdefault_(false),
attached_(attached),
readOnly_(FlagValueDefault)
{
setPageType(ApiPage);
-}
-
-/*!
- Constructor for the QML property node, when the \a parent
- is a QML class node.
- */
-QmlPropertyNode::QmlPropertyNode(QmlClassNode *parent,
- const QString& name,
- const QString& type,
- bool attached)
- : LeafNode(QmlProperty, parent, name),
- type_(type),
- stored_(FlagValueDefault),
- designable_(FlagValueDefault),
- isdefault_(false),
- attached_(attached),
- readOnly_(FlagValueDefault)
-{
- setPageType(ApiPage);
-}
-
-/*!
- Constructor for the QML property node, when the \a parent
- is a QML property node. Strictly speaking, this is not the
- way QML property nodes were originally meant to be built,
- because this constructor has another QML property node as
- its parent. But this constructor is useful for documenting
- QML properties in QML components, i.e., when you override
- the definition of a property with the \e{qmlproperty}
- command. It actually uses the parent of \a parent as the
- parent.
- */
-QmlPropertyNode::QmlPropertyNode(QmlPropertyNode* parent,
- const QString& name,
- const QString& type,
- bool attached)
- : LeafNode(parent->parent(), QmlProperty, name),
- type_(type),
- stored_(FlagValueDefault),
- designable_(FlagValueDefault),
- isdefault_(false),
- attached_(attached),
- readOnly_(FlagValueDefault)
-{
- setPageType(ApiPage);
+ if (type_ == QString("alias"))
+ isAlias_ = true;
}
/*!
@@ -2450,23 +2402,6 @@ PropertyNode* QmlPropertyNode::correspondingProperty(QDocDatabase* qdb)
return 0;
}
-/*!
- Returns true if this QML type or property group contains a
- property named \a name.
- */
-bool QmlPropertyNode::hasProperty(const QString& n) const
-{
- if (name() == n)
- return true;
- foreach (Node* child, qmlPropNodes()) {
- if (child->type() == Node::QmlProperty) {
- if (child->name() == n)
- return true;
- }
- }
- return false;
-}
-
/*! \class NameCollisionNode
An instance of this node is inserted in the tree
@@ -2586,11 +2521,10 @@ QString Node::fullDocumentName() const
const Node* n = this;
do {
- if (!n->name().isEmpty() &&
- ((n->type() != Node::Document) || (n->subType() != Node::QmlPropertyGroup)))
+ if (!n->name().isEmpty() && n->type() != Node::QmlPropertyGroup)
pieces.insert(0, n->name());
- if ((n->type() == Node::Document) && (n->subType() != Node::QmlPropertyGroup)) {
+ if (n->type() == Node::Document) {
if ((n->subType() == Node::QmlClass) && !n->qmlModuleName().isEmpty())
pieces.insert(0, n->qmlModuleIdentifier());
break;
@@ -2806,12 +2740,6 @@ QString Node::idForNode() const
case Node::QmlClass:
str = "qml-class-" + name();
break;
- case Node::QmlPropertyGroup:
- {
- Node* n = const_cast<Node*>(this);
- str = "qml-propertygroup-" + n->name();
- }
- break;
case Node::Page:
case Node::Group:
case Node::Module:
@@ -2852,6 +2780,12 @@ QString Node::idForNode() const
case Node::QmlProperty:
str = "qml-property-" + name();
break;
+ case Node::QmlPropertyGroup:
+ {
+ Node* n = const_cast<Node*>(this);
+ str = "qml-propertygroup-" + n->name();
+ }
+ break;
case Node::Property:
str = "property-" + name();
break;
diff --git a/src/tools/qdoc/node.h b/src/tools/qdoc/node.h
index bc75df2992..d5aa4a0cd4 100644
--- a/src/tools/qdoc/node.h
+++ b/src/tools/qdoc/node.h
@@ -60,6 +60,7 @@ class InnerNode;
class ExampleNode;
class QmlClassNode;
class QDocDatabase;
+class QmlPropertyNode;
typedef QList<Node*> NodeList;
typedef QMap<QString, Node*> NodeMap;
@@ -80,6 +81,7 @@ public:
Function,
Property,
Variable,
+ QmlPropertyGroup,
QmlProperty,
QmlSignal,
QmlSignalHandler,
@@ -98,7 +100,6 @@ public:
Page,
ExternalPage,
QmlClass,
- QmlPropertyGroup,
QmlBasicType,
QmlModule,
DitaMap,
@@ -200,8 +201,11 @@ public:
virtual bool isQmlPropertyGroup() const { return false; }
virtual bool isCollisionNode() const { return false; }
virtual bool isAttached() const { return false; }
+ virtual bool isAlias() const { return false; }
virtual bool isGroup() const { return false; }
virtual bool isWrapper() const;
+ virtual bool isReadOnly() const { return false; }
+ virtual bool isDefault() const { return false; }
virtual void addMember(Node* ) { }
virtual bool hasMembers() const { return false; }
virtual bool hasNamespaces() const { return false; }
@@ -209,10 +213,12 @@ public:
virtual void setAbstract(bool ) { }
virtual void setWrapper() { }
virtual QString title() const { return QString(); }
- virtual bool hasProperty(const QString& ) const { return false; }
+ virtual QmlPropertyNode* hasQmlProperty(const QString& ) const { return 0; }
virtual void getMemberNamespaces(NodeMap& ) { }
virtual void getMemberClasses(NodeMap& ) { }
virtual bool isInternal() const;
+ virtual void setDataType(const QString& ) { }
+ virtual void setReadOnly(bool ) { }
bool isIndexNode() const { return indexNodeFlag_; }
bool wasSeen() const { return seen_; }
Type type() const { return nodeType_; }
@@ -231,7 +237,7 @@ public:
Access access() const { return access_; }
QString accessString() const;
const Location& location() const { return loc; }
- const Doc& doc() const { return d; }
+ const Doc& doc() const { return doc_; }
Status status() const { return status_; }
Status inheritedStatus() const;
ThreadSafeness threadSafeness() const;
@@ -294,7 +300,7 @@ private:
InnerNode* relatesTo_;
QString name_;
Location loc;
- Doc d;
+ Doc doc_;
QMap<LinkType, QPair<QString, QString> > linkMap_;
QString moduleName_;
QString url_;
@@ -366,6 +372,7 @@ public:
virtual void setCurrentChild(InnerNode* ) { }
virtual void setOutputFileName(const QString& f) { outputFileName_ = f; }
virtual QString outputFileName() const { return outputFileName_; }
+ virtual QmlPropertyNode* hasQmlProperty(const QString& ) const;
void printChildren(const QString& title);
void printMembers(const QString& title);
@@ -497,8 +504,6 @@ public:
virtual QString nameForLists() const { return title(); }
virtual void setImageFileName(const QString& ) { }
virtual bool isGroup() const { return (subType() == Node::Group); }
- virtual bool isQmlPropertyGroup() const { return (nodeSubtype_ == QmlPropertyGroup); }
- virtual bool hasProperty(const QString& ) const;
protected:
SubType nodeSubtype_;
@@ -619,11 +624,11 @@ public:
virtual bool isQmlNode() const { return true; }
};
-class QmlPropGroupNode : public DocNode
+class QmlPropertyGroupNode : public InnerNode
{
public:
- QmlPropGroupNode(QmlClassNode* parent, const QString& name);
- virtual ~QmlPropGroupNode() { }
+ QmlPropertyGroupNode(QmlClassNode* parent, const QString& name);
+ virtual ~QmlPropertyGroupNode() { }
virtual bool isQmlNode() const { return true; }
virtual bool isQtQuickNode() const { return parent()->isQtQuickNode(); }
virtual QString qmlTypeName() const { return parent()->qmlTypeName(); }
@@ -631,6 +636,7 @@ public:
virtual QString qmlModuleVersion() const { return parent()->qmlModuleVersion(); }
virtual QString qmlModuleIdentifier() const { return parent()->qmlModuleIdentifier(); }
virtual QString idNumber();
+ virtual bool isQmlPropertyGroup() const { return true; }
const QString& element() const { return parent()->name(); }
@@ -645,34 +651,27 @@ class QmlPropertyNode : public LeafNode
Q_DECLARE_TR_FUNCTIONS(QDoc::QmlPropertyNode)
public:
- QmlPropertyNode(QmlClassNode *parent,
- const QString& name,
- const QString& type,
- bool attached);
- QmlPropertyNode(QmlPropGroupNode* parent,
- const QString& name,
- const QString& type,
- bool attached);
- QmlPropertyNode(QmlPropertyNode* parent,
+ QmlPropertyNode(InnerNode *parent,
const QString& name,
const QString& type,
bool attached);
virtual ~QmlPropertyNode() { }
- void setDataType(const QString& dataType) { type_ = dataType; }
+ virtual void setDataType(const QString& dataType) { type_ = dataType; }
void setStored(bool stored) { stored_ = toFlagValue(stored); }
void setDesignable(bool designable) { designable_ = toFlagValue(designable); }
- void setReadOnly(bool ro) { readOnly_ = toFlagValue(ro); }
+ virtual void setReadOnly(bool ro) { readOnly_ = toFlagValue(ro); }
void setDefault() { isdefault_ = true; }
const QString &dataType() const { return type_; }
QString qualifiedDataType() const { return type_; }
bool isReadOnlySet() const { return (readOnly_ != FlagValueDefault); }
- bool isDefault() const { return isdefault_; }
bool isStored() const { return fromFlagValue(stored_,true); }
bool isDesignable() const { return fromFlagValue(designable_,false); }
bool isWritable(QDocDatabase* qdb);
- bool isReadOnly() const { return fromFlagValue(readOnly_,false); }
+ virtual bool isDefault() const { return isdefault_; }
+ virtual bool isReadOnly() const { return fromFlagValue(readOnly_,false); }
+ virtual bool isAlias() const { return isAlias_; }
virtual bool isAttached() const { return attached_; }
virtual bool isQmlNode() const { return true; }
virtual bool isQtQuickNode() const { return parent()->isQtQuickNode(); }
@@ -680,22 +679,19 @@ public:
virtual QString qmlModuleName() const { return parent()->qmlModuleName(); }
virtual QString qmlModuleVersion() const { return parent()->qmlModuleVersion(); }
virtual QString qmlModuleIdentifier() const { return parent()->qmlModuleIdentifier(); }
- virtual bool hasProperty(const QString& name) const;
PropertyNode* correspondingProperty(QDocDatabase* qdb);
- const QString& element() const { return static_cast<QmlPropGroupNode*>(parent())->element(); }
- void appendQmlPropNode(QmlPropertyNode* p) { qmlPropNodes_.append(p); }
- const NodeList& qmlPropNodes() const { return qmlPropNodes_; }
+ const QString& element() const { return static_cast<QmlPropertyGroupNode*>(parent())->element(); }
private:
QString type_;
FlagValue stored_;
FlagValue designable_;
+ bool isAlias_;
bool isdefault_;
bool attached_;
FlagValue readOnly_;
- NodeList qmlPropNodes_;
};
class EnumItem
@@ -892,7 +888,7 @@ public:
PropertyNode(InnerNode* parent, const QString& name);
virtual ~PropertyNode() { }
- void setDataType(const QString& dataType) { type_ = dataType; }
+ virtual void setDataType(const QString& dataType) { type_ = dataType; }
void addFunction(FunctionNode* function, FunctionRole role);
void addSignal(FunctionNode* function, FunctionRole role);
void setStored(bool stored) { stored_ = toFlagValue(stored); }
diff --git a/src/tools/qdoc/puredocparser.cpp b/src/tools/qdoc/puredocparser.cpp
index d11ef3a3c7..644fe05438 100644
--- a/src/tools/qdoc/puredocparser.cpp
+++ b/src/tools/qdoc/puredocparser.cpp
@@ -118,9 +118,9 @@ void PureDocParser::parseSourceFile(const Location& location, const QString& fil
*/
bool PureDocParser::processQdocComments()
{
- QSet<QString> topicCommandsAllowed = topicCommands();
- QSet<QString> otherMetacommandsAllowed = otherMetaCommands();
- QSet<QString> metacommandsAllowed = topicCommandsAllowed + otherMetacommandsAllowed;
+ const QSet<QString>& topicCommandsAllowed = topicCommands();
+ const QSet<QString>& otherMetacommandsAllowed = otherMetaCommands();
+ const QSet<QString>& metacommandsAllowed = topicCommandsAllowed + otherMetacommandsAllowed;
while (tok != Tok_Eoi) {
if (tok == Tok_Doc) {
@@ -137,55 +137,68 @@ bool PureDocParser::processQdocComments()
/*
Doc parses the comment.
*/
- Doc doc(start_loc,end_loc,comment,metacommandsAllowed);
+ Doc doc(start_loc, end_loc, comment, metacommandsAllowed, topicCommandsAllowed);
QString topic;
- ArgList args;
+ bool isQmlPropertyTopic = false;
- QSet<QString> topicCommandsUsed = topicCommandsAllowed & doc.metaCommandsUsed();
-
- /*
- There should be one topic command in the set,
- or none. If the set is empty, then the comment
- should be a function description.
- */
- if (topicCommandsUsed.count() > 0) {
- topic = *topicCommandsUsed.begin();
- args = doc.metaCommandArgs(topic);
+ const TopicList& topics = doc.topicsUsed();
+ if (!topics.isEmpty()) {
+ topic = topics[0].topic;
+ if ((topic == COMMAND_QMLPROPERTY) ||
+ (topic == COMMAND_QMLPROPERTYGROUP) ||
+ (topic == COMMAND_QMLATTACHEDPROPERTY)) {
+ isQmlPropertyTopic = true;
+ }
+ }
+ if (isQmlPropertyTopic && topics.size() > 1) {
+ qDebug() << "MULTIPLE TOPICS:" << doc.location().fileName() << doc.location().lineNo();
+ for (int i=0; i<topics.size(); ++i) {
+ qDebug() << " " << topics[i].topic << topics[i].args;
+ }
}
NodeList nodes;
- QList<Doc> docs;
+ DocList docs;
if (topic.isEmpty()) {
doc.location().warning(tr("This qdoc comment contains no topic command "
"(e.g., '\\%1', '\\%2').")
.arg(COMMAND_MODULE).arg(COMMAND_PAGE));
}
+ else if (isQmlPropertyTopic) {
+ Doc nodeDoc = doc;
+ processQmlProperties(nodeDoc, nodes, docs);
+ }
else {
- /*
- There is a topic command. Process it.
- */
- if ((topic == COMMAND_QMLPROPERTY) ||
- (topic == COMMAND_QMLATTACHEDPROPERTY)) {
+ ArgList args;
+ QSet<QString> topicCommandsUsed = topicCommandsAllowed & doc.metaCommandsUsed();
+ if (topicCommandsUsed.count() > 0) {
+ topic = *topicCommandsUsed.begin();
+ args = doc.metaCommandArgs(topic);
+ }
+ if (topicCommandsUsed.count() > 1) {
+ QString topics;
+ QSet<QString>::ConstIterator t = topicCommandsUsed.constBegin();
+ while (t != topicCommandsUsed.constEnd()) {
+ topics += " \\" + *t + ",";
+ ++t;
+ }
+ topics[topics.lastIndexOf(',')] = '.';
+ int i = topics.lastIndexOf(',');
+ topics[i] = ' ';
+ topics.insert(i+1,"and");
+ doc.location().warning(tr("Multiple topic commands found in comment: %1").arg(topics));
+ }
+ ArgList::ConstIterator a = args.begin();
+ while (a != args.end()) {
Doc nodeDoc = doc;
- Node* node = processTopicCommandGroup(nodeDoc,topic,args);
+ Node* node = processTopicCommand(nodeDoc,topic,*a);
if (node != 0) {
nodes.append(node);
docs.append(nodeDoc);
}
- }
- else {
- ArgList::ConstIterator a = args.begin();
- while (a != args.end()) {
- Doc nodeDoc = doc;
- Node* node = processTopicCommand(nodeDoc,topic,*a);
- if (node != 0) {
- nodes.append(node);
- docs.append(nodeDoc);
- }
- ++a;
- }
+ ++a;
}
}
diff --git a/src/tools/qdoc/qdocdatabase.cpp b/src/tools/qdoc/qdocdatabase.cpp
index 7a3df4e4f2..a1e06c8020 100644
--- a/src/tools/qdoc/qdocdatabase.cpp
+++ b/src/tools/qdoc/qdocdatabase.cpp
@@ -612,7 +612,7 @@ void QDocDatabase::findAllObsoleteThings(const InnerNode* node)
case Node::QmlMethod:
if ((*c)->parent()) {
Node* parent = (*c)->parent();
- if (parent->subType() == Node::QmlPropertyGroup && parent->parent())
+ if (parent->type() == Node::QmlPropertyGroup && parent->parent())
parent = parent->parent();
if (parent && parent->subType() == Node::QmlClass && !parent->name().isEmpty())
name = parent->name() + "::" + name;
diff --git a/src/tools/qdoc/qdocindexfiles.cpp b/src/tools/qdoc/qdocindexfiles.cpp
index 5f2ebdfd07..4faa8ec8fc 100644
--- a/src/tools/qdoc/qdocindexfiles.cpp
+++ b/src/tools/qdoc/qdocindexfiles.cpp
@@ -217,8 +217,18 @@ void QDocIndexFiles::readIndexSection(const QDomElement& element,
location = Location(name);
node = qbtn;
}
- else if (element.nodeName() == "qmlproperty") {
+ else if (element.nodeName() == "qmlpropertygroup") {
QmlClassNode* qcn = static_cast<QmlClassNode*>(parent);
+ QmlPropertyGroupNode* qpgn = new QmlPropertyGroupNode(qcn, name);
+ if (element.hasAttribute("location"))
+ name = element.attribute("location", QString());
+ if (!indexUrl.isEmpty())
+ location = Location(indexUrl + QLatin1Char('/') + name);
+ else if (!indexUrl.isNull())
+ location = Location(name);
+ node = qpgn;
+ }
+ else if (element.nodeName() == "qmlproperty") {
QString type = element.attribute("type");
bool attached = false;
if (element.attribute("attached") == "true")
@@ -226,7 +236,15 @@ void QDocIndexFiles::readIndexSection(const QDomElement& element,
bool readonly = false;
if (element.attribute("writable") == "false")
readonly = true;
- QmlPropertyNode* qpn = new QmlPropertyNode(qcn, name, type, attached);
+ QmlPropertyNode* qpn = 0;
+ if (parent->type() == Node::Document) {
+ QmlClassNode* qcn = static_cast<QmlClassNode*>(parent);
+ qpn = new QmlPropertyNode(qcn, name, type, attached);
+ }
+ else if (parent->type() == Node::QmlPropertyGroup) {
+ QmlPropertyGroupNode* qpgn = static_cast<QmlPropertyGroupNode*>(parent);
+ qpn = new QmlPropertyNode(qpgn, name, type, attached);
+ }
qpn->setReadOnly(readonly);
node = qpn;
}
@@ -281,10 +299,6 @@ void QDocIndexFiles::readIndexSection(const QDomElement& element,
subtype = Node::QmlClass;
ptype = Node::ApiPage;
}
- else if (element.attribute("subtype") == "qmlpropertygroup") {
- subtype = Node::QmlPropertyGroup;
- ptype = Node::ApiPage;
- }
else if (element.attribute("subtype") == "qmlbasictype") {
subtype = Node::QmlBasicType;
ptype = Node::ApiPage;
@@ -501,7 +515,7 @@ void QDocIndexFiles::readIndexSection(const QDomElement& element,
// Create some content for the node.
QSet<QString> emptySet;
- Doc doc(location, location, " ", emptySet); // placeholder
+ Doc doc(location, location, " ", emptySet, emptySet); // placeholder
node->setDoc(doc);
node->setIndexNodeFlag();
node->setOutputSubdirectory(project_.toLower());
@@ -644,6 +658,9 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer,
case Node::QmlProperty:
nodeName = "qmlproperty";
break;
+ case Node::QmlPropertyGroup:
+ nodeName = "qmlpropertygroup";
+ break;
case Node::QmlSignal:
nodeName = "qmlsignal";
break;
@@ -927,6 +944,12 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer,
writer.writeAttribute("brief", brief);
}
break;
+ case Node::QmlPropertyGroup:
+ {
+ if (!brief.isEmpty())
+ writer.writeAttribute("brief", brief);
+ }
+ break;
case Node::Property:
{
const PropertyNode* propertyNode = static_cast<const PropertyNode*>(node);
@@ -1179,17 +1202,12 @@ void QDocIndexFiles::generateIndexSections(QXmlStreamWriter& writer,
foreach (Node* child, cnodes) {
/*
- Don't generate anything for a QML property group node.
- It is just a place holder for a collection of QML property
- nodes. Recurse to its children, which are the QML property
- nodes.
-
- Do the same thing for collision nodes - we want children
- of collision nodes in the index, but leaving out the
- parent collision page will make searching for nodes easier.
+ Don't generate anything for a collision node. We want
+ children of collision nodes in the index, but leaving
+ out the parent collision page will make searching for
+ nodes easier.
*/
- if (child->subType() == Node::QmlPropertyGroup ||
- child->subType() == Node::Collision) {
+ if (child->subType() == Node::Collision) {
const InnerNode* pgn = static_cast<const InnerNode*>(child);
foreach (Node* c, pgn->childNodes()) {
generateIndexSections(writer, c, generateInternalNodes);
diff --git a/src/tools/qdoc/qmlcodeparser.cpp b/src/tools/qdoc/qmlcodeparser.cpp
index b9c0ad9218..28b9c3ec9b 100644
--- a/src/tools/qdoc/qmlcodeparser.cpp
+++ b/src/tools/qdoc/qmlcodeparser.cpp
@@ -70,6 +70,7 @@ QT_BEGIN_NAMESPACE
#define COMMAND_QMLTYPE Doc::alias("qmltype")
#define COMMAND_QMLMODULE Doc::alias("qmlmodule")
#define COMMAND_QMLPROPERTY Doc::alias("qmlproperty")
+#define COMMAND_QMLPROPERTYGROUP Doc::alias("qmlpropertygroup")
#define COMMAND_QMLATTACHEDPROPERTY Doc::alias("qmlattachedproperty")
#define COMMAND_QMLINHERITS Doc::alias("inherits")
#define COMMAND_QMLINSTANTIATES Doc::alias("instantiates")
@@ -166,9 +167,9 @@ void QmlCodeParser::parseSourceFile(const Location& location, const QString& fil
extractPragmas(newCode);
lexer->setCode(newCode, 1);
- QSet<QString> topicCommandsAllowed = topicCommands();
- QSet<QString> otherMetacommandsAllowed = otherMetaCommands();
- QSet<QString> metacommandsAllowed = topicCommandsAllowed + otherMetacommandsAllowed;
+ const QSet<QString>& topicCommandsAllowed = topicCommands();
+ const QSet<QString>& otherMetacommandsAllowed = otherMetaCommands();
+ const QSet<QString>& metacommandsAllowed = topicCommandsAllowed + otherMetacommandsAllowed;
if (parser->parse()) {
QQmlJS::AST::UiProgram *ast = parser->ast();
@@ -195,42 +196,52 @@ void QmlCodeParser::doneParsingSourceFiles()
{
}
+static QSet<QString> topicCommands_;
/*!
Returns the set of strings representing the topic commands.
*/
-QSet<QString> QmlCodeParser::topicCommands()
+const QSet<QString>& QmlCodeParser::topicCommands()
{
- return QSet<QString>() << COMMAND_VARIABLE
- << COMMAND_QMLCLASS
- << COMMAND_QMLTYPE
- << COMMAND_QMLPROPERTY
- << COMMAND_QMLATTACHEDPROPERTY
- << COMMAND_QMLSIGNAL
- << COMMAND_QMLATTACHEDSIGNAL
- << COMMAND_QMLMETHOD
- << COMMAND_QMLATTACHEDMETHOD
- << COMMAND_QMLBASICTYPE;
+ if (topicCommands_.isEmpty()) {
+ topicCommands_ << COMMAND_VARIABLE
+ << COMMAND_QMLCLASS
+ << COMMAND_QMLTYPE
+ << COMMAND_QMLPROPERTY
+ << COMMAND_QMLPROPERTYGROUP
+ << COMMAND_QMLATTACHEDPROPERTY
+ << COMMAND_QMLSIGNAL
+ << COMMAND_QMLATTACHEDSIGNAL
+ << COMMAND_QMLMETHOD
+ << COMMAND_QMLATTACHEDMETHOD
+ << COMMAND_QMLBASICTYPE;
+ }
+ return topicCommands_;
}
+static QSet<QString> otherMetaCommands_;
/*!
Returns the set of strings representing the common metacommands
plus some other metacommands.
*/
-QSet<QString> QmlCodeParser::otherMetaCommands()
+const QSet<QString>& QmlCodeParser::otherMetaCommands()
{
- return commonMetaCommands() << COMMAND_STARTPAGE
- << COMMAND_QMLINHERITS
- << COMMAND_QMLDEFAULT
- << COMMAND_QMLREADONLY
- << COMMAND_DEPRECATED
- << COMMAND_INGROUP
- << COMMAND_INTERNAL
- << COMMAND_OBSOLETE
- << COMMAND_PRELIMINARY
- << COMMAND_SINCE
- << COMMAND_QMLABSTRACT
- << COMMAND_INQMLMODULE
- << COMMAND_WRAPPER;
+ if (otherMetaCommands_.isEmpty()) {
+ otherMetaCommands_ = commonMetaCommands();
+ otherMetaCommands_ << COMMAND_STARTPAGE
+ << COMMAND_QMLINHERITS
+ << COMMAND_QMLDEFAULT
+ << COMMAND_QMLREADONLY
+ << COMMAND_DEPRECATED
+ << COMMAND_INGROUP
+ << COMMAND_INTERNAL
+ << COMMAND_OBSOLETE
+ << COMMAND_PRELIMINARY
+ << COMMAND_SINCE
+ << COMMAND_QMLABSTRACT
+ << COMMAND_INQMLMODULE
+ << COMMAND_WRAPPER;
+ }
+ return otherMetaCommands_;
}
/*!
diff --git a/src/tools/qdoc/qmlcodeparser.h b/src/tools/qdoc/qmlcodeparser.h
index 5bdcfbfbbf..71b4660fe7 100644
--- a/src/tools/qdoc/qmlcodeparser.h
+++ b/src/tools/qdoc/qmlcodeparser.h
@@ -79,8 +79,8 @@ public:
void extractPragmas(QString &script);
protected:
- virtual QSet<QString> topicCommands();
- virtual QSet<QString> otherMetaCommands();
+ const QSet<QString>& topicCommands();
+ const QSet<QString>& otherMetaCommands();
private:
QQmlJS::Engine engine;
diff --git a/src/tools/qdoc/qmlvisitor.cpp b/src/tools/qdoc/qmlvisitor.cpp
index 86b86c8f34..c049857717 100644
--- a/src/tools/qdoc/qmlvisitor.cpp
+++ b/src/tools/qdoc/qmlvisitor.cpp
@@ -67,6 +67,7 @@ QT_BEGIN_NAMESPACE
#define COMMAND_QMLTYPE Doc::alias(QLatin1String("qmltype"))
#define COMMAND_QMLMODULE Doc::alias(QLatin1String("qmlmodule"))
#define COMMAND_QMLPROPERTY Doc::alias(QLatin1String("qmlproperty"))
+#define COMMAND_QMLPROPERTYGROUP Doc::alias(QLatin1String("qmlpropertygroup"))
#define COMMAND_QMLATTACHEDPROPERTY Doc::alias(QLatin1String("qmlattachedproperty"))
#define COMMAND_QMLINHERITS Doc::alias(QLatin1String("inherits"))
#define COMMAND_QMLINSTANTIATES Doc::alias(QLatin1String("instantiates"))
@@ -85,17 +86,17 @@ QT_BEGIN_NAMESPACE
QmlDocVisitor::QmlDocVisitor(const QString &filePath,
const QString &code,
QQmlJS::Engine *engine,
- QSet<QString> &commands,
- QSet<QString> &topics)
+ const QSet<QString> &commands,
+ const QSet<QString> &topics)
: nestingLevel(0)
{
lastEndOffset = 0;
- this->filePath = filePath;
+ this->filePath_ = filePath;
this->name = QFileInfo(filePath).baseName();
document = code;
this->engine = engine;
- this->commands = commands;
- this->topics = topics;
+ this->commands_ = commands;
+ this->topics_ = topics;
current = QDocDatabase::qdocDB()->treeRoot();
}
@@ -141,13 +142,89 @@ QQmlJS::AST::SourceLocation QmlDocVisitor::precedingComment(quint32 offset) cons
return QQmlJS::AST::SourceLocation();
}
+#if 0
+ ArgList args;
+ QSet<QString>::iterator i = metacommands.begin();
+ while (i != metacommands.end()) {
+ if (topics_.contains(*i)) {
+ topic = *i;
+ break;
+ }
+ ++i;
+ }
+ if (!topic.isEmpty()) {
+ args = doc.metaCommandArgs(topic);
+ if ((topic == COMMAND_QMLCLASS) || (topic == COMMAND_QMLTYPE)) {
+ // do nothing.
+ }
+ else if (topic == COMMAND_QMLPROPERTY) {
+ if (node->type() == Node::QmlProperty) {
+ QmlPropertyNode* qpn = static_cast<QmlPropertyNode*>(node);
+ qpn->setReadOnly(0);
+ if (qpn->dataType() == "alias") {
+ QStringList part = args[0].first.split(QLatin1Char(' '));
+ qpn->setDataType(part[0]);
+ }
+ }
+ }
+ else if (topic == COMMAND_QMLPROPERTYGROUP) {
+ // zzz ?
+ }
+ else if (topic == COMMAND_QMLMODULE) {
+ }
+ else if (topic == COMMAND_QMLATTACHEDPROPERTY) {
+ if (node->type() == Node::QmlProperty) {
+ QmlPropertyNode* qpn = static_cast<QmlPropertyNode*>(node);
+ qpn->setReadOnly(0);
+ }
+ }
+ else if (topic == COMMAND_QMLSIGNAL) {
+ }
+ else if (topic == COMMAND_QMLATTACHEDSIGNAL) {
+ }
+ else if (topic == COMMAND_QMLMETHOD) {
+ }
+ else if (topic == COMMAND_QMLATTACHEDMETHOD) {
+ }
+ else if (topic == COMMAND_QMLBASICTYPE) {
+ }
+ }
+
+ if (node->type() == Node::QmlProperty) {
+ QmlPropertyNode* qpn = static_cast<QmlPropertyNode*>(node);
+ for (int i=0; i<topicsUsed.size(); ++i) {
+ if (topicsUsed.at(i).topic == "qmlproperty") {
+ /*
+ A \qmlproperty command would be used in a QML file
+ to document the underlying property for a property
+ alias.
+ */
+ QmlPropArgs qpa;
+ if (splitQmlPropertyArg(doc, topicsUsed.at(i).args, qpa)) {
+ QmlPropertyNode* n = parent->hasQmlPropertyNode(qpa.name_);
+ if (n == 0)
+ n = new QmlPropertyNode(qpn, qpa.name_, qpa.type_, false);
+ n->setLocation(doc.location());
+ n->setReadOnly(qpn->isReadOnly());
+ if (qpn->isDefault())
+ n->setDefault();
+ }
+ else
+ qDebug() << " FAILED TO PARSE QML PROPERTY:"
+ << topicsUsed.at(i).topic << topicsUsed.at(i).args;
+ }
+ }
+ }
+
+#endif
+
/*!
Finds the nearest unused qdoc comment above the QML entity
represented by the \a node and processes the qdoc commands
- in that comment. The proceesed documentation is stored in
+ in that comment. The processed documentation is stored in
the \a node.
- If a qdoc comment is found about \a location, true is returned.
+ If a qdoc comment is found for \a location, true is returned.
If a comment is not found there, false is returned.
*/
bool QmlDocVisitor::applyDocumentation(QQmlJS::AST::SourceLocation location, Node* node)
@@ -156,23 +233,66 @@ bool QmlDocVisitor::applyDocumentation(QQmlJS::AST::SourceLocation location, Nod
if (loc.isValid()) {
QString source = document.mid(loc.offset, loc.length);
- Location start(filePath);
+ Location start(filePath_);
start.setLineNo(loc.startLine);
start.setColumnNo(loc.startColumn);
- Location finish(filePath);
+ Location finish(filePath_);
finish.setLineNo(loc.startLine);
finish.setColumnNo(loc.startColumn);
- Doc doc(start, finish, source.mid(1), commands, topics);
+ Doc doc(start, finish, source.mid(1), commands_, topics_);
+ const TopicList& topicsUsed = doc.topicsUsed();
+ NodeList nodes;
+ Node* nodePassedIn = node;
+ InnerNode* parent = nodePassedIn->parent();
node->setDoc(doc);
- applyMetacommands(loc, node, doc);
+ nodes.append(node);
+ if (topicsUsed.size() > 0) {
+ for (int i=0; i<topicsUsed.size(); ++i) {
+ if (topicsUsed.at(i).topic == QString("qmlpropertygroup")) {
+ qDebug() << "PROPERTY GROUP COMMAND SEEN:" << topicsUsed.at(i).args << filePath_;
+ break;
+ }
+ }
+ for (int i=0; i<topicsUsed.size(); ++i) {
+ QString topic = topicsUsed.at(i).topic;
+ QString args = topicsUsed.at(i).args;
+ if ((topic == COMMAND_QMLPROPERTY) || (topic == COMMAND_QMLATTACHEDPROPERTY)) {
+ QmlPropArgs qpa;
+ if (splitQmlPropertyArg(doc, args, qpa)) {
+ if (qpa.name_ == nodePassedIn->name()) {
+ if (nodePassedIn->isAlias())
+ nodePassedIn->setDataType(qpa.type_);
+ }
+ else {
+ bool isAttached = (topic == COMMAND_QMLATTACHEDPROPERTY);
+ QmlPropertyNode* n = parent->hasQmlProperty(qpa.name_);
+ if (n == 0)
+ n = new QmlPropertyNode(parent, qpa.name_, qpa.type_, isAttached);
+ n->setLocation(doc.location());
+ n->setDoc(doc);
+ n->setReadOnly(nodePassedIn->isReadOnly());
+ if (nodePassedIn->isDefault())
+ n->setDefault();
+ if (isAttached)
+ n->setReadOnly(0);
+ nodes.append(n);
+ }
+ }
+ else
+ qDebug() << " FAILED TO PARSE QML PROPERTY:" << topic << args;
+ }
+ }
+ }
+ for (int i=0; i<nodes.size(); ++i)
+ applyMetacommands(loc, nodes.at(i), doc);
usedComments.insert(loc.offset);
if (doc.isEmpty()) {
return false;
}
return true;
}
- Location codeLoc(filePath);
+ Location codeLoc(filePath_);
codeLoc.setLineNo(location.startLine);
node->setLocation(codeLoc);
return false;
@@ -237,80 +357,13 @@ void QmlDocVisitor::applyMetacommands(QQmlJS::AST::SourceLocation,
Doc& doc)
{
QDocDatabase* qdb = QDocDatabase::qdocDB();
-
- const TopicList& topicsUsed = doc.topicsUsed();
- if (topicsUsed.size() > 0) {
- if (node->type() == Node::QmlProperty) {
- QmlPropertyNode* qpn = static_cast<QmlPropertyNode*>(node);
- for (int i=0; i<topicsUsed.size(); ++i) {
- if (topicsUsed.at(i).topic == "qmlproperty") {
- QmlPropArgs qpa;
- if (splitQmlPropertyArg(doc, topicsUsed.at(i).args, qpa)) {
- QmlPropertyNode* n = new QmlPropertyNode(qpn, qpa.name_, qpa.type_, false);
- n->setLocation(doc.location());
- qpn->appendQmlPropNode(n);
- n->setReadOnly(qpn->isReadOnly());
- if (qpn->isDefault())
- n->setDefault();
- }
- else
- qDebug() << " FAILED TO PARSE QML PROPERTY:"
- << topicsUsed.at(i).topic << topicsUsed.at(i).args;
- }
- }
- }
- }
QSet<QString> metacommands = doc.metaCommandsUsed();
if (metacommands.count() > 0) {
- QString topic;
- ArgList args;
+ metacommands.subtract(topics_);
QSet<QString>::iterator i = metacommands.begin();
while (i != metacommands.end()) {
- if (topics.contains(*i)) {
- topic = *i;
- break;
- }
- ++i;
- }
- if (!topic.isEmpty()) {
- args = doc.metaCommandArgs(topic);
- if ((topic == COMMAND_QMLCLASS) || (topic == COMMAND_QMLTYPE)) {
- // do nothing.
- }
- else if (topic == COMMAND_QMLPROPERTY) {
- if (node->type() == Node::QmlProperty) {
- QmlPropertyNode* qpn = static_cast<QmlPropertyNode*>(node);
- qpn->setReadOnly(0);
- if (qpn->dataType() == "alias") {
- QStringList part = args[0].first.split(QLatin1Char(' '));
- qpn->setDataType(part[0]);
- }
- }
- }
- else if (topic == COMMAND_QMLMODULE) {
- }
- else if (topic == COMMAND_QMLATTACHEDPROPERTY) {
- if (node->type() == Node::QmlProperty) {
- QmlPropertyNode* qpn = static_cast<QmlPropertyNode*>(node);
- qpn->setReadOnly(0);
- }
- }
- else if (topic == COMMAND_QMLSIGNAL) {
- }
- else if (topic == COMMAND_QMLATTACHEDSIGNAL) {
- }
- else if (topic == COMMAND_QMLMETHOD) {
- }
- else if (topic == COMMAND_QMLATTACHEDMETHOD) {
- }
- else if (topic == COMMAND_QMLBASICTYPE) {
- }
- }
- metacommands.subtract(topics);
- i = metacommands.begin();
- while (i != metacommands.end()) {
QString command = *i;
- args = doc.metaCommandArgs(command);
+ ArgList args = doc.metaCommandArgs(command);
if (command == COMMAND_QMLABSTRACT) {
if ((node->type() == Node::Document) && (node->subType() == Node::QmlClass)) {
node->setAbstract(true);
@@ -528,7 +581,9 @@ bool QmlDocVisitor::visit(QQmlJS::AST::UiPublicMember *member)
QmlClassNode *qmlClass = static_cast<QmlClassNode *>(current);
if (qmlClass) {
QString name = member->name.toString();
- QmlPropertyNode *qmlPropNode = new QmlPropertyNode(qmlClass, name, type, false);
+ QmlPropertyNode* qmlPropNode = qmlClass->hasQmlProperty(name);
+ if (qmlPropNode == 0)
+ qmlPropNode = new QmlPropertyNode(qmlClass, name, type, false);
qmlPropNode->setReadOnly(member->isReadonlyMember);
if (member->isDefaultMember)
qmlPropNode->setDefault();
diff --git a/src/tools/qdoc/qmlvisitor.h b/src/tools/qdoc/qmlvisitor.h
index 2c3ff341d6..cdb7ae7391 100644
--- a/src/tools/qdoc/qmlvisitor.h
+++ b/src/tools/qdoc/qmlvisitor.h
@@ -45,7 +45,6 @@
#include <qstring.h>
#include "qqmljsastvisitor_p.h"
#include "node.h"
-#include "tree.h"
QT_BEGIN_NAMESPACE
@@ -72,8 +71,8 @@ public:
QmlDocVisitor(const QString &filePath,
const QString &code,
QQmlJS::Engine *engine,
- QSet<QString> &commands,
- QSet<QString> &topics);
+ const QSet<QString> &commands,
+ const QSet<QString> &topics);
virtual ~QmlDocVisitor();
bool visit(QQmlJS::AST::UiImportList *imports);
@@ -113,12 +112,12 @@ private:
QQmlJS::Engine *engine;
quint32 lastEndOffset;
quint32 nestingLevel;
- QString filePath;
+ QString filePath_;
QString name;
QString document;
ImportList importList;
- QSet<QString> commands;
- QSet<QString> topics;
+ QSet<QString> commands_;
+ QSet<QString> topics_;
QSet<quint32> usedComments;
InnerNode *current;
};
diff --git a/src/tools/qdoc/tree.cpp b/src/tools/qdoc/tree.cpp
index 553c569ae9..8c5ecdcfe9 100644
--- a/src/tools/qdoc/tree.cpp
+++ b/src/tools/qdoc/tree.cpp
@@ -169,7 +169,7 @@ const Node* Tree::findNode(const QStringList& path,
if (node && i == path.size()
&& (!(findFlags & NonFunction) || node->type() != Node::Function
|| ((FunctionNode*)node)->metaness() == FunctionNode::MacroWithoutParams)) {
- if ((node != self) && (node->subType() != Node::QmlPropertyGroup)) {
+ if ((node != self) && (node->type() != Node::QmlPropertyGroup)) {
if (node->subType() == Node::Collision) {
node = node->applyModuleIdentifier(start);
}
diff --git a/src/widgets/dialogs/qcolordialog.cpp b/src/widgets/dialogs/qcolordialog.cpp
index c08a034d9e..5da41aa0a5 100644
--- a/src/widgets/dialogs/qcolordialog.cpp
+++ b/src/widgets/dialogs/qcolordialog.cpp
@@ -63,6 +63,8 @@
#include "qmimedata.h"
#include "qspinbox.h"
#include "qdialogbuttonbox.h"
+#include "qscreen.h"
+#include "qcursor.h"
QT_BEGIN_NAMESPACE
@@ -920,6 +922,8 @@ signals:
private slots:
void rgbEd();
void hsvEd();
+ void htmlEd();
+
private:
void showCurrentColor();
int hue, sat, val;
@@ -931,6 +935,7 @@ private:
QLabel *lblRed;
QLabel *lblGreen;
QLabel *lblBlue;
+ QLabel *lblHtml;
QColSpinBox *hEd;
QColSpinBox *sEd;
QColSpinBox *vEd;
@@ -939,6 +944,7 @@ private:
QColSpinBox *bEd;
QColSpinBox *alphaEd;
QLabel *alphaLab;
+ QLineEdit *htEd;
QColorShowLabel *lab;
bool rgbOriginal;
QColorDialog *colorDialog;
@@ -1230,6 +1236,19 @@ QColorShower::QColorShower(QColorDialog *parent)
#endif
alphaEd->hide();
alphaLab->hide();
+ lblHtml = new QLabel(this);
+ htEd = new QLineEdit(this);
+#ifndef QT_NO_SHORTCUT
+ lblHtml->setBuddy(htEd);
+#endif
+
+ QRegularExpression regExp(QStringLiteral("#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})"));
+ QRegularExpressionValidator *validator = new QRegularExpressionValidator(regExp, this);
+ htEd->setValidator(validator);
+
+ lblHtml->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
+ gl->addWidget(lblHtml, 5, 1);
+ gl->addWidget(htEd, 5, 2);
connect(hEd, SIGNAL(valueChanged(int)), this, SLOT(hsvEd()));
connect(sEd, SIGNAL(valueChanged(int)), this, SLOT(hsvEd()));
@@ -1239,6 +1258,7 @@ QColorShower::QColorShower(QColorDialog *parent)
connect(gEd, SIGNAL(valueChanged(int)), this, SLOT(rgbEd()));
connect(bEd, SIGNAL(valueChanged(int)), this, SLOT(rgbEd()));
connect(alphaEd, SIGNAL(valueChanged(int)), this, SLOT(rgbEd()));
+ connect(htEd, SIGNAL(textEdited(QString)), this, SLOT(htmlEd()));
retranslateStrings();
}
@@ -1251,7 +1271,7 @@ inline bool QColorDialogPrivate::isAlphaVisible() const { return cs->isAlphaVisi
QColor QColorDialogPrivate::currentQColor() const
{
- if (!options->testOption(QColorDialogOptions::DontUseNativeDialog) && nativeDialogInUse)
+ if (nativeDialogInUse)
return platformColorDialogHelper()->currentColor();
return cs->currentQColor();
}
@@ -1273,6 +1293,8 @@ void QColorShower::rgbEd()
sEd->setValue(sat);
vEd->setValue(val);
+ htEd->setText(QColor(curCol).name());
+
showCurrentColor();
emit newCol(currentColor());
updateQColor();
@@ -1293,6 +1315,31 @@ void QColorShower::hsvEd()
gEd->setValue(qGreen(currentColor()));
bEd->setValue(qBlue(currentColor()));
+ htEd->setText(c.name());
+
+ showCurrentColor();
+ emit newCol(currentColor());
+ updateQColor();
+}
+
+void QColorShower::htmlEd()
+{
+ QColor c;
+ QString t = htEd->text();
+ c.setNamedColor(t);
+ if (!c.isValid())
+ return;
+ curCol = qRgba(c.red(), c.green(), c.blue(), currentAlpha());
+ rgb2hsv(curCol, hue, sat, val);
+
+ hEd->setValue(hue);
+ sEd->setValue(sat);
+ vEd->setValue(val);
+
+ rEd->setValue(qRed(currentColor()));
+ gEd->setValue(qGreen(currentColor()));
+ bEd->setValue(qBlue(currentColor()));
+
showCurrentColor();
emit newCol(currentColor());
updateQColor();
@@ -1313,6 +1360,8 @@ void QColorShower::setRgb(QRgb rgb)
gEd->setValue(qGreen(currentColor()));
bEd->setValue(qBlue(currentColor()));
+ htEd->setText(QColor(rgb).name());
+
showCurrentColor();
updateQColor();
}
@@ -1336,6 +1385,8 @@ void QColorShower::setHsv(int h, int s, int v)
gEd->setValue(qGreen(currentColor()));
bEd->setValue(qBlue(currentColor()));
+ htEd->setText(c.name());
+
showCurrentColor();
updateQColor();
}
@@ -1349,6 +1400,7 @@ void QColorShower::retranslateStrings()
lblGreen->setText(QColorDialog::tr("&Green:"));
lblBlue->setText(QColorDialog::tr("Bl&ue:"));
alphaLab->setText(QColorDialog::tr("A&lpha channel:"));
+ lblHtml->setText(QColorDialog::tr("&HTML:"));
}
void QColorShower::updateQColor()
@@ -1362,16 +1414,20 @@ void QColorShower::updateQColor()
//sets all widgets to display h,s,v
void QColorDialogPrivate::_q_newHsv(int h, int s, int v)
{
- cs->setHsv(h, s, v);
- cp->setCol(h, s);
- lp->setCol(h, s, v);
+ if (!nativeDialogInUse) {
+ cs->setHsv(h, s, v);
+ cp->setCol(h, s);
+ lp->setCol(h, s, v);
+ }
}
//sets all widgets to display rgb
void QColorDialogPrivate::setCurrentColor(QRgb rgb)
{
- cs->setRgb(rgb);
- _q_newColorTypedIn(rgb);
+ if (!nativeDialogInUse) {
+ cs->setRgb(rgb);
+ _q_newColorTypedIn(rgb);
+ }
}
// hack; doesn't keep curCol in sync, so use with care
@@ -1421,13 +1477,24 @@ bool QColorDialogPrivate::selectColor(const QColor &col)
return false;
}
+QColor QColorDialogPrivate::grabScreenColor(const QPoint &p)
+{
+ const QDesktopWidget *desktop = QApplication::desktop();
+ const QPixmap pixmap = QGuiApplication::screens().at(desktop->screenNumber())->grabWindow(desktop->winId(),
+ p.x(), p.y(), 1, 1);
+ QImage i = pixmap.toImage();
+ return i.pixel(0, 0);
+}
+
//sets all widgets except cs to display rgb
void QColorDialogPrivate::_q_newColorTypedIn(QRgb rgb)
{
- int h, s, v;
- rgb2hsv(rgb, h, s, v);
- cp->setCol(h, s);
- lp->setCol(h, s, v);
+ if (!nativeDialogInUse) {
+ int h, s, v;
+ rgb2hsv(rgb, h, s, v);
+ cp->setCol(h, s);
+ lp->setCol(h, s, v);
+ }
}
void QColorDialogPrivate::_q_nextCustom(int r, int c)
@@ -1450,6 +1517,48 @@ void QColorDialogPrivate::_q_newStandard(int r, int c)
custom->setSelected(-1,-1);
}
+void QColorDialogPrivate::_q_pickScreenColor()
+{
+ Q_Q(QColorDialog);
+ screenColorPicking = true;
+ // If user pushes Escape, the last color before picking will be restored.
+ beforeScreenColorPicking = cs->currentColor();
+ /*For some reason, q->grabMouse(Qt::CrossCursor) doesn't change
+ * the cursor, and therefore I have to change it manually.
+ */
+ q->grabMouse();
+ q->setCursor(Qt::CrossCursor);
+ q->grabKeyboard();
+ /* With setMouseTracking(true) the desired color can be more precisedly picked up,
+ * and continuously pushing the mouse button is not necessary.
+ */
+ q->setMouseTracking(true);
+
+ addCusBt->setDisabled(true);
+ buttons->setDisabled(true);
+ screenColorPickerButton->setDisabled(true);
+
+ q->setCurrentColor(grabScreenColor(QCursor::pos()));
+ lblScreenColorInfo->setText(QColorDialog::tr("Cursor at %1, %2, color: %3\nPress ESC to cancel")
+ .arg(QCursor::pos().x())
+ .arg(QCursor::pos().y())
+ .arg(q->currentColor().name()));
+}
+
+void QColorDialogPrivate::releaseColorPicking()
+{
+ Q_Q(QColorDialog);
+ screenColorPicking = false;
+ q->releaseMouse();
+ q->releaseKeyboard();
+ q->setCursor(Qt::ArrowCursor);
+ q->setMouseTracking(false);
+ lblScreenColorInfo->setText(QLatin1String("\n"));
+ addCusBt->setDisabled(false);
+ buttons->setDisabled(false);
+ screenColorPickerButton->setDisabled(false);
+}
+
void QColorDialogPrivate::init(const QColor &initial)
{
Q_Q(QColorDialog);
@@ -1457,9 +1566,24 @@ void QColorDialogPrivate::init(const QColor &initial)
q->setSizeGripEnabled(false);
q->setWindowTitle(QColorDialog::tr("Select Color"));
+ // default: use the native dialog if possible. Can be overridden in setOptions()
nativeDialogInUse = (platformColorDialogHelper() != 0);
-
+ screenColorPicking = false;
nextCust = 0;
+
+ if (!nativeDialogInUse)
+ initWidgets();
+
+#ifdef Q_WS_MAC
+ delegate = 0;
+#endif
+
+ q->setCurrentColor(initial);
+}
+
+void QColorDialogPrivate::initWidgets()
+{
+ Q_Q(QColorDialog);
QVBoxLayout *mainLay = new QVBoxLayout(q);
// there's nothing in this dialog that benefits from sizing up
mainLay->setSizeConstraint(QLayout::SetFixedSize);
@@ -1494,6 +1618,15 @@ void QColorDialogPrivate::init(const QColor &initial)
leftLay->addWidget(lblBasicColors);
leftLay->addWidget(standard);
+#if !defined(Q_OS_WINCE) && !defined(QT_SMALL_COLORDIALOG)
+ // The screen color picker button
+ screenColorPickerButton = new QPushButton(QColorDialog::tr("Pick Screen Color"));
+ leftLay->addWidget(screenColorPickerButton);
+ lblScreenColorInfo = new QLabel(QLatin1String("\n"));
+ leftLay->addWidget(lblScreenColorInfo);
+ q->connect(screenColorPickerButton, SIGNAL(clicked()), SLOT(_q_pickScreenColor()));
+#endif
+
#if !defined(Q_OS_WINCE)
leftLay->addStretch();
#endif
@@ -1597,12 +1730,6 @@ void QColorDialogPrivate::init(const QColor &initial)
QObject::connect(cancel, SIGNAL(clicked()), q, SLOT(reject()));
retranslateStrings();
-
-#ifdef Q_WS_MAC
- delegate = 0;
-#endif
-
- q->setCurrentColor(initial);
}
void QColorDialogPrivate::initHelper(QPlatformDialogHelper *h)
@@ -1667,6 +1794,11 @@ static const Qt::WindowFlags DefaultWindowFlags =
during the execution of the program. Use setCustomColor() to set
the custom colors, and use customColor() to get them.
+ When pressing the "Pick Screen Color" button, the cursor changes to a haircross
+ and the colors on the screen are scanned. The user can pick up one by clicking
+ the mouse or the Enter button. Pressing Escape restores the last color selected
+ before entering this mode.
+
The \l{dialogs/standarddialogs}{Standard Dialogs} example shows
how to use QColorDialog as well as other built-in Qt dialogs.
@@ -1708,12 +1840,13 @@ QColorDialog::QColorDialog(const QColor &initial, QWidget *parent)
void QColorDialog::setCurrentColor(const QColor &color)
{
Q_D(QColorDialog);
- d->setCurrentColor(color.rgb());
- d->selectColor(color);
- d->setCurrentAlpha(color.alpha());
-
- if (!testOption(QColorDialog::DontUseNativeDialog) && d->nativeDialogInUse)
+ if (d->nativeDialogInUse)
d->platformColorDialogHelper()->setCurrentColor(color);
+ else {
+ d->setCurrentColor(color.rgb());
+ d->selectColor(color);
+ d->setCurrentAlpha(color.alpha());
+ }
}
QColor QColorDialog::currentColor() const
@@ -1783,10 +1916,14 @@ void QColorDialog::setOptions(ColorDialogOptions options)
return;
d->options->setOptions(QColorDialogOptions::ColorDialogOptions(int(options)));
- d->buttons->setVisible(!(options & NoButtons));
- d->showAlpha(options & ShowAlphaChannel);
- if (options & DontUseNativeDialog)
+ if ((options & DontUseNativeDialog) && d->nativeDialogInUse) {
d->nativeDialogInUse = false;
+ d->initWidgets();
+ }
+ if (!d->nativeDialogInUse) {
+ d->buttons->setVisible(!(options & NoButtons));
+ d->showAlpha(options & ShowAlphaChannel);
+ }
}
QColorDialog::ColorDialogOptions QColorDialog::options() const
@@ -1868,7 +2005,7 @@ void QColorDialog::setVisible(bool visible)
}
#else
- if (!(options() & DontUseNativeDialog) && d->nativeDialogInUse) {
+ if (d->nativeDialogInUse) {
d->setNativeDialogVisible(visible);
// Set WA_DontShowOnScreen so that QDialog::setVisible(visible) below
// updates the state correctly, but skips showing the non-native version:
@@ -1983,6 +2120,57 @@ void QColorDialog::changeEvent(QEvent *e)
}
/*!
+ \reimp
+*/
+void QColorDialog::mouseMoveEvent(QMouseEvent *e)
+{
+ Q_D(QColorDialog);
+ if (d->screenColorPicking) {
+ setCurrentColor(d->grabScreenColor(e->globalPos()));
+ d->lblScreenColorInfo->setText(QColorDialog::tr("Cursor at %1, %2, color: %3\nPress ESC to cancel")
+ .arg(e->globalPos().x())
+ .arg(e->globalPos().y())
+ .arg(currentColor().name()));
+ return;
+ }
+ QDialog::mouseMoveEvent(e);
+}
+
+/*!
+ \reimp
+*/
+void QColorDialog::mouseReleaseEvent(QMouseEvent *e)
+{
+ Q_D(QColorDialog);
+ if (d->screenColorPicking) {
+ setCurrentColor(d->grabScreenColor(e->globalPos()));
+ d->releaseColorPicking();
+ return;
+ }
+ QDialog::mouseReleaseEvent(e);
+}
+
+/*!
+ \reimp
+*/
+void QColorDialog::keyPressEvent(QKeyEvent *e)
+{
+ Q_D(QColorDialog);
+ if (d->screenColorPicking) {
+ if (e->key() == Qt::Key_Escape) {
+ d->releaseColorPicking();
+ d->setCurrentColor(d->beforeScreenColorPicking);
+ } else if (e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter) {
+ setCurrentColor(d->grabScreenColor(QCursor::pos()));
+ d->releaseColorPicking();
+ }
+ e->accept();
+ return;
+ }
+ QDialog::keyPressEvent(e);
+}
+
+/*!
Closes the dialog and sets its result code to \a result. If this dialog
is shown with exec(), done() causes the local event loop to finish,
and exec() to return \a result.
diff --git a/src/widgets/dialogs/qcolordialog.h b/src/widgets/dialogs/qcolordialog.h
index f6dc627a05..c7a1d6f400 100644
--- a/src/widgets/dialogs/qcolordialog.h
+++ b/src/widgets/dialogs/qcolordialog.h
@@ -112,6 +112,9 @@ Q_SIGNALS:
protected:
void changeEvent(QEvent *event);
+ virtual void mouseMoveEvent(QMouseEvent *);
+ virtual void mouseReleaseEvent(QMouseEvent *);
+ virtual void keyPressEvent(QKeyEvent *);
void done(int result);
private:
@@ -123,6 +126,7 @@ private:
Q_PRIVATE_SLOT(d_func(), void _q_nextCustom(int, int))
Q_PRIVATE_SLOT(d_func(), void _q_newCustom(int, int))
Q_PRIVATE_SLOT(d_func(), void _q_newStandard(int, int))
+ Q_PRIVATE_SLOT(d_func(), void _q_pickScreenColor())
friend class QColorShower;
};
diff --git a/src/widgets/dialogs/qcolordialog_p.h b/src/widgets/dialogs/qcolordialog_p.h
index 695e95d26c..08199cc7c1 100644
--- a/src/widgets/dialogs/qcolordialog_p.h
+++ b/src/widgets/dialogs/qcolordialog_p.h
@@ -82,11 +82,13 @@ public:
{ return static_cast<QPlatformColorDialogHelper *>(platformHelper()); }
void init(const QColor &initial);
+ void initWidgets();
QRgb currentColor() const;
QColor currentQColor() const;
void setCurrentColor(QRgb rgb);
void setCurrentQColor(const QColor &color);
bool selectColor(const QColor &color);
+ QColor grabScreenColor(const QPoint &p);
int currentAlpha() const;
void setCurrentAlpha(int a);
@@ -101,6 +103,8 @@ public:
void _q_nextCustom(int, int);
void _q_newCustom(int, int);
void _q_newStandard(int, int);
+ void _q_pickScreenColor();
+ void releaseColorPicking();
QWellArray *custom;
QWellArray *standard;
@@ -112,12 +116,16 @@ public:
QColorShower *cs;
QLabel *lblBasicColors;
QLabel *lblCustomColors;
+ QLabel *lblScreenColorInfo;
QPushButton *ok;
QPushButton *cancel;
QPushButton *addCusBt;
+ QPushButton *screenColorPickerButton;
QColor selectedQColor;
int nextCust;
bool smallDisplay;
+ bool screenColorPicking;
+ QRgb beforeScreenColorPicking;
QSharedPointer<QColorDialogOptions> options;
QPointer<QObject> receiverToDisconnectOnClose;
diff --git a/src/widgets/dialogs/qdialog_p.h b/src/widgets/dialogs/qdialog_p.h
index eb0cb2372b..5064efa35d 100644
--- a/src/widgets/dialogs/qdialog_p.h
+++ b/src/widgets/dialogs/qdialog_p.h
@@ -111,7 +111,7 @@ public:
QPointer<QEventLoop> eventLoop;
- bool nativeDialogInUse; // Assigned in setVisible_sys() in derived classes.
+ bool nativeDialogInUse;
QPlatformDialogHelper *platformHelper() const;
private:
diff --git a/src/widgets/dialogs/qfiledialog.cpp b/src/widgets/dialogs/qfiledialog.cpp
index c42752311f..9c4b99253a 100644
--- a/src/widgets/dialogs/qfiledialog.cpp
+++ b/src/widgets/dialogs/qfiledialog.cpp
@@ -86,15 +86,27 @@ Q_GLOBAL_STATIC(QString, lastVisitedDir)
typedef QString (*_qt_filedialog_existing_directory_hook)(QWidget *parent, const QString &caption, const QString &dir, QFileDialog::Options options);
Q_WIDGETS_EXPORT _qt_filedialog_existing_directory_hook qt_filedialog_existing_directory_hook = 0;
+typedef QUrl (*_qt_filedialog_existing_directory_url_hook)(QWidget *parent, const QString &caption, const QUrl &dir, QFileDialog::Options options, const QStringList &supportedSchemes);
+Q_WIDGETS_EXPORT _qt_filedialog_existing_directory_url_hook qt_filedialog_existing_directory_url_hook = 0;
+
typedef QString (*_qt_filedialog_open_filename_hook)(QWidget * parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options);
Q_WIDGETS_EXPORT _qt_filedialog_open_filename_hook qt_filedialog_open_filename_hook = 0;
+typedef QUrl (*_qt_filedialog_open_file_url_hook)(QWidget * parent, const QString &caption, const QUrl &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options, const QStringList &supportedSchemes);
+Q_WIDGETS_EXPORT _qt_filedialog_open_file_url_hook qt_filedialog_open_file_url_hook = 0;
+
typedef QStringList (*_qt_filedialog_open_filenames_hook)(QWidget * parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options);
Q_WIDGETS_EXPORT _qt_filedialog_open_filenames_hook qt_filedialog_open_filenames_hook = 0;
+typedef QList<QUrl> (*_qt_filedialog_open_file_urls_hook)(QWidget * parent, const QString &caption, const QUrl &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options, const QStringList &supportedSchemes);
+Q_WIDGETS_EXPORT _qt_filedialog_open_file_urls_hook qt_filedialog_open_file_urls_hook = 0;
+
typedef QString (*_qt_filedialog_save_filename_hook)(QWidget * parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options);
Q_WIDGETS_EXPORT _qt_filedialog_save_filename_hook qt_filedialog_save_filename_hook = 0;
+typedef QUrl (*_qt_filedialog_save_file_url_hook)(QWidget * parent, const QString &caption, const QUrl &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options, const QStringList &supportedSchemes);
+Q_WIDGETS_EXPORT _qt_filedialog_save_file_url_hook qt_filedialog_save_file_url_hook = 0;
+
/*!
\class QFileDialog
\brief The QFileDialog class provides a dialog that allow users to select files or directories.
@@ -243,6 +255,11 @@ Q_WIDGETS_EXPORT _qt_filedialog_save_filename_hook qt_filedialog_save_filename_h
static functions will always be an application modal dialog. If
you want to use sheets, use QFileDialog::open() instead.
+ \value DontUseCustomDirectoryIcons Always use the default directory icon.
+ Some platforms allow the user to set a different icon. Custom icon lookup
+ cause a big performance impact over network or removable drives.
+ Setting this will enable the QFileIconProvider::DontUseCustomDirectoryIcons
+ option in the icon provider. This enum value was added in Qt 5.2.
*/
/*!
@@ -258,37 +275,76 @@ Q_WIDGETS_EXPORT _qt_filedialog_save_filename_hook qt_filedialog_save_filename_h
/*!
\fn void QFileDialog::filesSelected(const QStringList &selected)
- When the selection changes and the dialog is accepted, this signal is
- emitted with the (possibly empty) list of \a selected files.
+ When the selection changes for local operations and the dialog is
+ accepted, this signal is emitted with the (possibly empty) list
+ of \a selected files.
\sa currentChanged(), QDialog::Accepted
*/
+/*!
+ \fn void QFileDialog::urlsSelected(const QList<QUrl> &urls)
+
+ When the selection changes and the dialog is accepted, this signal is
+ emitted with the (possibly empty) list of selected \a urls.
+
+ \sa currentUrlChanged(), QDialog::Accepted
+ \since 5.2
+*/
/*!
\fn void QFileDialog::fileSelected(const QString &file)
- When the selection changes and the dialog is accepted, this signal is
- emitted with the (possibly empty) selected \a file.
+ When the selection changes for local operations and the dialog is
+ accepted, this signal is emitted with the (possibly empty)
+ selected \a file.
\sa currentChanged(), QDialog::Accepted
*/
+/*!
+ \fn void QFileDialog::urlSelected(const QUrl &url)
+
+ When the selection changes and the dialog is accepted, this signal is
+ emitted with the (possibly empty) selected \a url.
+
+ \sa currentUrlChanged(), QDialog::Accepted
+ \since 5.2
+*/
/*!
\fn void QFileDialog::currentChanged(const QString &path)
- When the current file changes, this signal is emitted with the
- new file name as the \a path parameter.
+ When the current file changes for local operations, this signal is
+ emitted with the new file name as the \a path parameter.
\sa filesSelected()
*/
/*!
+ \fn void QFileDialog::currentUrlChanged(const QUrl &url)
+
+ When the current file changes, this signal is emitted with the
+ new file URL as the \a url parameter.
+
+ \sa urlsSelected()
+ \since 5.2
+*/
+
+/*!
\fn void QFileDialog::directoryEntered(const QString &directory)
\since 4.3
+ This signal is emitted for local operations when the user enters
+ a \a directory.
+*/
+
+/*!
+ \fn void QFileDialog::directoryUrlEntered(const QUrl &directory)
+
This signal is emitted when the user enters a \a directory.
+
+ \since 5.2
*/
/*!
@@ -532,11 +588,10 @@ QFileDialogPrivate::~QFileDialogPrivate()
void QFileDialogPrivate::initHelper(QPlatformDialogHelper *h)
{
QFileDialog *d = q_func();
- QObject::connect(h, SIGNAL(fileSelected(QString)), d, SIGNAL(fileSelected(QString)));
- QObject::connect(h, SIGNAL(filesSelected(QStringList)), d, SIGNAL(filesSelected(QStringList)));
- QObject::connect(h, SIGNAL(currentChanged(QString)), d, SIGNAL(currentChanged(QString)));
- QObject::connect(h, SIGNAL(directoryEntered(QString)), d, SIGNAL(directoryEntered(QString)));
- QObject::connect(h, SIGNAL(directoryEntered(QString)), d, SLOT(_q_nativeEnterDirectory(QString)));
+ QObject::connect(h, SIGNAL(fileSelected(QUrl)), d, SLOT(_q_nativeFileSelected(QUrl)));
+ QObject::connect(h, SIGNAL(filesSelected(QList<QUrl>)), d, SLOT(_q_nativeFilesSelected(QList<QUrl>)));
+ QObject::connect(h, SIGNAL(currentChanged(QUrl)), d, SLOT(_q_nativeCurrentChanged(QUrl)));
+ QObject::connect(h, SIGNAL(directoryEntered(QUrl)), d, SLOT(_q_nativeEnterDirectory(QUrl)));
QObject::connect(h, SIGNAL(filterSelected(QString)), d, SIGNAL(filterSelected(QString)));
static_cast<QPlatformFileDialogHelper *>(h)->setOptions(options);
}
@@ -550,8 +605,8 @@ void QFileDialogPrivate::helperPrepareShow(QPlatformDialogHelper *)
options->setSidebarUrls(qFileDialogUi->sidebar->urls());
const QDir directory = q->directory();
options->setInitialDirectory(directory.exists() ?
- directory.absolutePath() :
- QString());
+ QUrl::fromLocalFile(directory.absolutePath()) :
+ QUrl());
options->setInitiallySelectedNameFilter(q->selectedNameFilter());
options->setInitiallySelectedFiles(userSelectedFiles());
}
@@ -742,6 +797,15 @@ void QFileDialog::setOptions(Options options)
if (changed & ShowDirsOnly)
setFilter((options & ShowDirsOnly) ? filter() & ~QDir::Files : filter() | QDir::Files);
+
+ if (changed & DontUseCustomDirectoryIcons) {
+ QFileIconProvider::Options providerOptions = iconProvider()->options();
+ if (options & DontUseCustomDirectoryIcons)
+ providerOptions |= QFileIconProvider::DontUseCustomDirectoryIcons;
+ else
+ providerOptions &= ~QFileIconProvider::DontUseCustomDirectoryIcons;
+ iconProvider()->setOptions(providerOptions);
+ }
}
QFileDialog::Options QFileDialog::options() const
@@ -850,7 +914,7 @@ void QFileDialog::setDirectory(const QString &directory)
d->setLastVisitedDirectory(newDirectory);
if (d->nativeDialogInUse){
- d->setDirectory_sys(newDirectory);
+ d->setDirectory_sys(QUrl::fromLocalFile(newDirectory));
return;
}
if (d->rootPath() == newDirectory)
@@ -875,7 +939,42 @@ void QFileDialog::setDirectory(const QString &directory)
QDir QFileDialog::directory() const
{
Q_D(const QFileDialog);
- return QDir(d->nativeDialogInUse ? d->directory_sys() : d->rootPath());
+ return QDir(d->nativeDialogInUse ? d->directory_sys().toLocalFile() : d->rootPath());
+}
+
+/*!
+ Sets the file dialog's current \a directory url.
+
+ \note The non-native QFileDialog supports only local files.
+
+ \since 5.2
+*/
+void QFileDialog::setDirectoryUrl(const QUrl &directory)
+{
+ Q_D(QFileDialog);
+ if (!directory.isValid())
+ return;
+
+ if (d->nativeDialogInUse)
+ d->setDirectory_sys(directory);
+ else if (directory.isLocalFile())
+ setDirectory(directory.toLocalFile());
+ else
+ qWarning() << "Non-native QFileDialog supports only local files";
+}
+
+/*!
+ Returns the url of the directory currently being displayed in the dialog.
+
+ \since 5.2
+*/
+QUrl QFileDialog::directoryUrl() const
+{
+ Q_D(const QFileDialog);
+ if (d->nativeDialogInUse)
+ return d->directory_sys();
+ else
+ return QUrl::fromLocalFile(directory().absolutePath());
}
/*!
@@ -890,7 +989,7 @@ void QFileDialog::selectFile(const QString &filename)
return;
if (d->nativeDialogInUse){
- d->selectFile_sys(filename);
+ d->selectFile_sys(QUrl::fromLocalFile(filename));
return;
}
@@ -927,6 +1026,28 @@ void QFileDialog::selectFile(const QString &filename)
d->lineEdit()->setText(file);
}
+/*!
+ Selects the given \a url in the file dialog.
+
+ \note The non-native QFileDialog supports only local files.
+
+ \sa selectedUrls()
+ \since 5.2
+*/
+void QFileDialog::selectUrl(const QUrl &url)
+{
+ Q_D(QFileDialog);
+ if (!url.isValid())
+ return;
+
+ if (d->nativeDialogInUse)
+ d->selectFile_sys(url);
+ else if (url.isLocalFile())
+ selectFile(url.toLocalFile());
+ else
+ qWarning() << "Non-native QFileDialog supports only local files";
+}
+
#ifdef Q_OS_UNIX
Q_AUTOTEST_EXPORT QString qt_tildeExpansion(const QString &path, bool *expanded = 0)
{
@@ -1015,17 +1136,19 @@ QStringList QFileDialogPrivate::typedFiles() const
// Return selected files without defaulting to the root of the file system model
// used for initializing QFileDialogOptions for native dialogs. The default is
// not suitable for native dialogs since it mostly equals directory().
-QStringList QFileDialogPrivate::userSelectedFiles() const
+QList<QUrl> QFileDialogPrivate::userSelectedFiles() const
{
+ QList<QUrl> files;
+
if (nativeDialogInUse)
- return addDefaultSuffixToFiles(selectedFiles_sys());
+ return addDefaultSuffixToUrls(selectedFiles_sys());
- QStringList files;
foreach (const QModelIndex &index, qFileDialogUi->listView->selectionModel()->selectedRows())
- files.append(index.data(QFileSystemModel::FilePathRole).toString());
+ files.append(QUrl::fromLocalFile(index.data(QFileSystemModel::FilePathRole).toString()));
if (files.isEmpty() && !lineEdit()->text().isEmpty())
- files = typedFiles();
+ foreach (const QString &path, typedFiles())
+ files.append(QUrl::fromLocalFile(path));
return files;
}
@@ -1056,6 +1179,20 @@ QStringList QFileDialogPrivate::addDefaultSuffixToFiles(const QStringList filesT
return files;
}
+QList<QUrl> QFileDialogPrivate::addDefaultSuffixToUrls(const QList<QUrl> &urlsToFix) const
+{
+ QList<QUrl> urls;
+ for (int i=0; i<urlsToFix.size(); ++i) {
+ QUrl url = urlsToFix.at(i);
+ // if the filename has no suffix, add the default suffix
+ const QString defaultSuffix = options->defaultSuffix();
+ if (!defaultSuffix.isEmpty() && !url.path().endsWith(QLatin1Char('/')) && url.path().lastIndexOf(QLatin1Char('.')) == -1)
+ url.setPath(url.path() + QLatin1Char('.') + defaultSuffix);
+ urls.append(url);
+ }
+ return urls;
+}
+
/*!
Returns a list of strings containing the absolute paths of the
@@ -1068,7 +1205,9 @@ QStringList QFileDialog::selectedFiles() const
{
Q_D(const QFileDialog);
- QStringList files = d->userSelectedFiles();
+ QStringList files;
+ foreach (const QUrl &file, d->userSelectedFiles())
+ files.append(file.toLocalFile());
if (files.isEmpty()) {
const FileMode fm = fileMode();
if (fm != ExistingFile && fm != ExistingFiles)
@@ -1077,6 +1216,27 @@ QStringList QFileDialog::selectedFiles() const
return files;
}
+/*!
+ Returns a list of urls containing the selected files in the dialog.
+ If no files are selected, or the mode is not ExistingFiles or
+ ExistingFile, selectedUrls() contains the current path in the viewport.
+
+ \sa selectedNameFilter(), selectUrl()
+ \since 5.2
+*/
+QList<QUrl> QFileDialog::selectedUrls() const
+{
+ Q_D(const QFileDialog);
+ if (d->nativeDialogInUse) {
+ return d->userSelectedFiles();
+ } else {
+ QList<QUrl> urls;
+ foreach (const QString &file, selectedFiles())
+ urls.append(QUrl::fromLocalFile(file));
+ return urls;
+ }
+}
+
/*
Makes a list of filters from ;;-separated text.
Used by the mac and windows implementations
@@ -1526,6 +1686,8 @@ bool QFileDialog::confirmOverwrite() const
filename if it has no suffix already. The suffix is typically
used to indicate the file type (e.g. "txt" indicates a text
file).
+
+ If the first character is a dot ('.'), it is removed.
*/
void QFileDialog::setDefaultSuffix(const QString &suffix)
{
@@ -1798,6 +1960,48 @@ QString QFileDialog::getOpenFileName(QWidget *parent,
}
/*!
+ This is a convenience static function that returns an existing file
+ selected by the user. If the user presses Cancel, it returns an
+ empty url.
+
+ The function is used similarly to QFileDialog::getOpenFileName(). In
+ particular \a parent, \a caption, \a dir, \a filter, \a selectedFilter
+ and \a options are used in the exact same way.
+
+ The main difference with QFileDialog::getOpenFileName() comes from
+ the ability offered to the user to select a remote file. That's why
+ the return type and the type of \a dir is QUrl.
+
+ The \a supportedSchemes argument allows to restrict the type of URLs the
+ user will be able to select. It is a way for the application to declare
+ the protocols it will support to fetch the file content. An empty list
+ means that no restriction is applied (the default).
+ Supported for local files ("file" scheme) is implicit and always enabled.
+ it is not necessary to include in the restriction.
+
+ When possible, this static function will use the native file dialog and
+ not a QFileDialog. On platforms which don't support selecting remote
+ files, Qt will allow to select only local files.
+
+ \sa getOpenFileName(), getOpenFileUrls(), getSaveFileUrl(), getExistingDirectoryUrl()
+ \since 5.2
+*/
+QUrl QFileDialog::getOpenFileUrl(QWidget *parent,
+ const QString &caption,
+ const QUrl &dir,
+ const QString &filter,
+ QString *selectedFilter,
+ Options options,
+ const QStringList &supportedSchemes)
+{
+ if (qt_filedialog_open_file_url_hook && !(options & DontUseNativeDialog))
+ return qt_filedialog_open_file_url_hook(parent, caption, dir, filter, selectedFilter, options, supportedSchemes);
+
+ // Falls back to local file
+ return QUrl::fromLocalFile(getOpenFileName(parent, caption, dir.toLocalFile(), filter, selectedFilter, options));
+}
+
+/*!
This is a convenience static function that will return one or more existing
files selected by the user.
@@ -1883,6 +2087,55 @@ QStringList QFileDialog::getOpenFileNames(QWidget *parent,
}
/*!
+ This is a convenience static function that will return or or more existing
+ files selected by the user. If the user presses Cancel, it returns an
+ empty list.
+
+ The function is used similarly to QFileDialog::getOpenFileNames(). In
+ particular \a parent, \a caption, \a dir, \a filter, \a selectedFilter
+ and \a options are used in the exact same way.
+
+ The main difference with QFileDialog::getOpenFileNames() comes from
+ the ability offered to the user to select remote files. That's why
+ the return type and the type of \a dir are respectively QList<QUrl>
+ and QUrl.
+
+ The \a supportedSchemes argument allows to restrict the type of URLs the
+ user will be able to select. It is a way for the application to declare
+ the protocols it will support to fetch the file content. An empty list
+ means that no restriction is applied (the default).
+ Supported for local files ("file" scheme) is implicit and always enabled.
+ it is not necessary to include in the restriction.
+
+ When possible, this static function will use the native file dialog and
+ not a QFileDialog. On platforms which don't support selecting remote
+ files, Qt will allow to select only local files.
+
+ \sa getOpenFileNames(), getOpenFileUrl(), getSaveFileUrl(), getExistingDirectoryUrl()
+ \since 5.2
+*/
+QList<QUrl> QFileDialog::getOpenFileUrls(QWidget *parent,
+ const QString &caption,
+ const QUrl &dir,
+ const QString &filter,
+ QString *selectedFilter,
+ Options options,
+ const QStringList &supportedSchemes)
+{
+ if (qt_filedialog_open_file_urls_hook && !(options & DontUseNativeDialog))
+ return qt_filedialog_open_file_urls_hook(parent, caption, dir, filter, selectedFilter, options, supportedSchemes);
+
+ // Falls back to local files
+ QList<QUrl> urls;
+
+ const QStringList fileNames = getOpenFileNames(parent, caption, dir.toLocalFile(), filter, selectedFilter, options);
+ foreach (const QString &fileName, fileNames)
+ urls << QUrl::fromLocalFile(fileName);
+
+ return urls;
+}
+
+/*!
This is a convenience static function that will return a file name selected
by the user. The file does not have to exist.
@@ -1971,6 +2224,48 @@ QString QFileDialog::getSaveFileName(QWidget *parent,
}
/*!
+ This is a convenience static function that returns a file selected by
+ the user. The file does not have to exist. If the user presses Cancel,
+ it returns an empty url.
+
+ The function is used similarly to QFileDialog::getSaveFileName(). In
+ particular \a parent, \a caption, \a dir, \a filter, \a selectedFilter
+ and \a options are used in the exact same way.
+
+ The main difference with QFileDialog::getSaveFileName() comes from
+ the ability offered to the user to select a remote file. That's why
+ the return type and the type of \a dir is QUrl.
+
+ The \a supportedSchemes argument allows to restrict the type of URLs the
+ user will be able to select. It is a way for the application to declare
+ the protocols it will support to save the file content. An empty list
+ means that no restriction is applied (the default).
+ Supported for local files ("file" scheme) is implicit and always enabled.
+ it is not necessary to include in the restriction.
+
+ When possible, this static function will use the native file dialog and
+ not a QFileDialog. On platforms which don't support selecting remote
+ files, Qt will allow to select only local files.
+
+ \sa getSaveFileName(), getOpenFileUrl(), getOpenFileUrls(), getExistingDirectoryUrl()
+ \since 5.2
+*/
+QUrl QFileDialog::getSaveFileUrl(QWidget *parent,
+ const QString &caption,
+ const QUrl &dir,
+ const QString &filter,
+ QString *selectedFilter,
+ Options options,
+ const QStringList &supportedSchemes)
+{
+ if (qt_filedialog_save_file_url_hook && !(options & DontUseNativeDialog))
+ return qt_filedialog_save_file_url_hook(parent, caption, dir, filter, selectedFilter, options, supportedSchemes);
+
+ // Falls back to local file
+ return QUrl::fromLocalFile(getSaveFileName(parent, caption, dir.toLocalFile(), filter, selectedFilter, options));
+}
+
+/*!
This is a convenience static function that will return an existing
directory selected by the user.
@@ -2041,6 +2336,46 @@ QString QFileDialog::getExistingDirectory(QWidget *parent,
return QString();
}
+/*!
+ This is a convenience static function that will return an existing
+ directory selected by the user. If the user presses Cancel, it
+ returns an empty url.
+
+ The function is used similarly to QFileDialog::getExistingDirectory().
+ In particular \a parent, \a caption, \a dir and \a options are used
+ in the exact same way.
+
+ The main difference with QFileDialog::getExistingDirectory() comes from
+ the ability offered to the user to select a remote directory. That's why
+ the return type and the type of \a dir is QUrl.
+
+ The \a supportedSchemes argument allows to restrict the type of URLs the
+ user will be able to select. It is a way for the application to declare
+ the protocols it will support to fetch the file content. An empty list
+ means that no restriction is applied (the default).
+ Supported for local files ("file" scheme) is implicit and always enabled.
+ it is not necessary to include in the restriction.
+
+ When possible, this static function will use the native file dialog and
+ not a QFileDialog. On platforms which don't support selecting remote
+ files, Qt will allow to select only local files.
+
+ \sa getExistingDirectory(), getOpenFileUrl(), getOpenFileUrls(), getSaveFileUrl()
+ \since 5.2
+*/
+QUrl QFileDialog::getExistingDirectoryUrl(QWidget *parent,
+ const QString &caption,
+ const QUrl &dir,
+ Options options,
+ const QStringList &supportedSchemes)
+{
+ if (qt_filedialog_existing_directory_url_hook && !(options & DontUseNativeDialog))
+ return qt_filedialog_existing_directory_url_hook(parent, caption, dir, options, supportedSchemes);
+
+ // Falls back to local file
+ return QUrl::fromLocalFile(getExistingDirectory(parent, caption, dir.toLocalFile(), options));
+}
+
inline static QString _qt_get_directory(const QString &path)
{
QFileInfo info = QFileInfo(QDir::current(), path);
@@ -3119,10 +3454,42 @@ void QFileDialogPrivate::_q_fileRenamed(const QString &path, const QString oldNa
}
}
-void QFileDialogPrivate::_q_nativeEnterDirectory(const QString &directory)
+void QFileDialogPrivate::_q_nativeFileSelected(const QUrl &file)
+{
+ Q_Q(QFileDialog);
+ emit q->urlSelected(file);
+ if (file.isLocalFile())
+ emit q->fileSelected(file.toLocalFile());
+}
+
+void QFileDialogPrivate::_q_nativeFilesSelected(const QList<QUrl> &files)
+{
+ Q_Q(QFileDialog);
+ emit q->urlsSelected(files);
+ QStringList localFiles;
+ foreach (const QUrl &file, files)
+ if (file.isLocalFile())
+ localFiles.append(file.toLocalFile());
+ if (!localFiles.isEmpty())
+ emit q->filesSelected(localFiles);
+}
+
+void QFileDialogPrivate::_q_nativeCurrentChanged(const QUrl &file)
{
- if (!directory.isEmpty()) // Windows native dialogs occasionally emit signals with empty strings.
- *lastVisitedDir() = directory;
+ Q_Q(QFileDialog);
+ emit q->currentUrlChanged(file);
+ if (file.isLocalFile())
+ emit q->currentChanged(file.toLocalFile());
+}
+
+void QFileDialogPrivate::_q_nativeEnterDirectory(const QUrl &directory)
+{
+ Q_Q(QFileDialog);
+ emit q->directoryUrlEntered(directory);
+ if (!directory.isEmpty() && directory.isLocalFile()) { // Windows native dialogs occasionally emit signals with empty strings.
+ *lastVisitedDir() = directory.toLocalFile();
+ emit q->directoryEntered(directory.toLocalFile());
+ }
}
/*!
diff --git a/src/widgets/dialogs/qfiledialog.h b/src/widgets/dialogs/qfiledialog.h
index 98d1fd5695..5413a42ea9 100644
--- a/src/widgets/dialogs/qfiledialog.h
+++ b/src/widgets/dialogs/qfiledialog.h
@@ -44,6 +44,7 @@
#include <QtCore/qdir.h>
#include <QtCore/qstring.h>
+#include <QtCore/qurl.h>
#include <QtWidgets/qdialog.h>
QT_BEGIN_NAMESPACE
@@ -58,7 +59,6 @@ class QFileIconProvider;
class QFileDialogPrivate;
class QAbstractItemDelegate;
class QAbstractProxyModel;
-class QUrl;
class Q_WIDGETS_EXPORT QFileDialog : public QDialog
{
@@ -84,13 +84,14 @@ public:
enum Option
{
- ShowDirsOnly = 0x00000001,
- DontResolveSymlinks = 0x00000002,
- DontConfirmOverwrite = 0x00000004,
- DontUseSheet = 0x00000008,
- DontUseNativeDialog = 0x00000010,
- ReadOnly = 0x00000020,
- HideNameFilterDetails = 0x00000040
+ ShowDirsOnly = 0x00000001,
+ DontResolveSymlinks = 0x00000002,
+ DontConfirmOverwrite = 0x00000004,
+ DontUseSheet = 0x00000008,
+ DontUseNativeDialog = 0x00000010,
+ ReadOnly = 0x00000020,
+ HideNameFilterDetails = 0x00000040,
+ DontUseCustomDirectoryIcons = 0x00000080
};
Q_DECLARE_FLAGS(Options, Option)
@@ -105,9 +106,15 @@ public:
inline void setDirectory(const QDir &directory);
QDir directory() const;
+ void setDirectoryUrl(const QUrl &directory);
+ QUrl directoryUrl() const;
+
void selectFile(const QString &filename);
QStringList selectedFiles() const;
+ void selectUrl(const QUrl &url);
+ QList<QUrl> selectedUrls() const;
+
void setNameFilterDetailsVisible(bool enabled);
bool isNameFilterDetailsVisible() const;
@@ -184,6 +191,12 @@ Q_SIGNALS:
void filesSelected(const QStringList &files);
void currentChanged(const QString &path);
void directoryEntered(const QString &directory);
+
+ void urlSelected(const QUrl &url);
+ void urlsSelected(const QList<QUrl> &urls);
+ void currentUrlChanged(const QUrl &url);
+ void directoryUrlEntered(const QUrl &directory);
+
void filterSelected(const QString &filter);
public:
@@ -195,6 +208,14 @@ public:
QString *selectedFilter = 0,
Options options = 0);
+ static QUrl getOpenFileUrl(QWidget *parent = 0,
+ const QString &caption = QString(),
+ const QUrl &dir = QUrl(),
+ const QString &filter = QString(),
+ QString *selectedFilter = 0,
+ Options options = 0,
+ const QStringList &supportedSchemes = QStringList());
+
static QString getSaveFileName(QWidget *parent = 0,
const QString &caption = QString(),
const QString &dir = QString(),
@@ -202,11 +223,25 @@ public:
QString *selectedFilter = 0,
Options options = 0);
+ static QUrl getSaveFileUrl(QWidget *parent = 0,
+ const QString &caption = QString(),
+ const QUrl &dir = QUrl(),
+ const QString &filter = QString(),
+ QString *selectedFilter = 0,
+ Options options = 0,
+ const QStringList &supportedSchemes = QStringList());
+
static QString getExistingDirectory(QWidget *parent = 0,
const QString &caption = QString(),
const QString &dir = QString(),
Options options = ShowDirsOnly);
+ static QUrl getExistingDirectoryUrl(QWidget *parent = 0,
+ const QString &caption = QString(),
+ const QUrl &dir = QUrl(),
+ Options options = ShowDirsOnly,
+ const QStringList &supportedSchemes = QStringList());
+
static QStringList getOpenFileNames(QWidget *parent = 0,
const QString &caption = QString(),
const QString &dir = QString(),
@@ -214,6 +249,14 @@ public:
QString *selectedFilter = 0,
Options options = 0);
+ static QList<QUrl> getOpenFileUrls(QWidget *parent = 0,
+ const QString &caption = QString(),
+ const QUrl &dir = QUrl(),
+ const QString &filter = QString(),
+ QString *selectedFilter = 0,
+ Options options = 0,
+ const QStringList &supportedSchemes = QStringList());
+
protected:
QFileDialog(const QFileDialogArgs &args);
@@ -240,7 +283,10 @@ private:
Q_PRIVATE_SLOT(d_func(), void _q_updateOkButton())
Q_PRIVATE_SLOT(d_func(), void _q_currentChanged(const QModelIndex &index))
Q_PRIVATE_SLOT(d_func(), void _q_enterDirectory(const QModelIndex &index))
- Q_PRIVATE_SLOT(d_func(), void _q_nativeEnterDirectory(const QString&))
+ Q_PRIVATE_SLOT(d_func(), void _q_nativeFileSelected(const QUrl &))
+ Q_PRIVATE_SLOT(d_func(), void _q_nativeFilesSelected(const QList<QUrl> &))
+ Q_PRIVATE_SLOT(d_func(), void _q_nativeCurrentChanged(const QUrl &))
+ Q_PRIVATE_SLOT(d_func(), void _q_nativeEnterDirectory(const QUrl&))
Q_PRIVATE_SLOT(d_func(), void _q_goToDirectory(const QString &path))
Q_PRIVATE_SLOT(d_func(), void _q_useNameFilter(int index))
Q_PRIVATE_SLOT(d_func(), void _q_selectionChanged())
diff --git a/src/widgets/dialogs/qfiledialog_p.h b/src/widgets/dialogs/qfiledialog_p.h
index f8f33eb18d..e5a558bb91 100644
--- a/src/widgets/dialogs/qfiledialog_p.h
+++ b/src/widgets/dialogs/qfiledialog_p.h
@@ -130,8 +130,9 @@ public:
static QString workingDirectory(const QString &path);
static QString initialSelection(const QString &path);
QStringList typedFiles() const;
- QStringList userSelectedFiles() const;
+ QList<QUrl> userSelectedFiles() const;
QStringList addDefaultSuffixToFiles(const QStringList filesToFix) const;
+ QList<QUrl> addDefaultSuffixToUrls(const QList<QUrl> &urlsToFix) const;
bool removeDirectory(const QString &path);
void setLabelTextControl(QFileDialog::DialogLabel label, const QString &text);
inline void updateFileNameLabel();
@@ -206,7 +207,10 @@ public:
void _q_updateOkButton();
void _q_currentChanged(const QModelIndex &index);
void _q_enterDirectory(const QModelIndex &index);
- void _q_nativeEnterDirectory(const QString &directory);
+ void _q_nativeFileSelected(const QUrl &file);
+ void _q_nativeFilesSelected(const QList<QUrl> &files);
+ void _q_nativeCurrentChanged(const QUrl &file);
+ void _q_nativeEnterDirectory(const QUrl &directory);
void _q_goToDirectory(const QString &);
void _q_useNameFilter(int index);
void _q_selectionChanged();
@@ -246,10 +250,10 @@ public:
// used instead.
bool canBeNativeDialog();
- void setDirectory_sys(const QString &directory);
- QString directory_sys() const;
- void selectFile_sys(const QString &filename);
- QStringList selectedFiles_sys() const;
+ void setDirectory_sys(const QUrl &directory);
+ QUrl directory_sys() const;
+ void selectFile_sys(const QUrl &filename);
+ QList<QUrl> selectedFiles_sys() const;
void setFilter_sys();
void selectNameFilter_sys(const QString &filter);
QString selectedNameFilter_sys() const;
@@ -346,30 +350,40 @@ inline QString QFileDialogPrivate::rootPath() const {
return model->rootPath();
}
-inline void QFileDialogPrivate::setDirectory_sys(const QString &directory)
+inline void QFileDialogPrivate::setDirectory_sys(const QUrl &directory)
{
- if (QPlatformFileDialogHelper *helper = platformFileDialogHelper())
+ QPlatformFileDialogHelper *helper = platformFileDialogHelper();
+
+ if (!helper)
+ return;
+
+ if (helper->isSupportedUrl(directory))
helper->setDirectory(directory);
}
-inline QString QFileDialogPrivate::directory_sys() const
+inline QUrl QFileDialogPrivate::directory_sys() const
{
if (QPlatformFileDialogHelper *helper = platformFileDialogHelper())
return helper->directory();
return QString();
}
-inline void QFileDialogPrivate::selectFile_sys(const QString &filename)
+inline void QFileDialogPrivate::selectFile_sys(const QUrl &filename)
{
- if (QPlatformFileDialogHelper *helper = platformFileDialogHelper())
+ QPlatformFileDialogHelper *helper = platformFileDialogHelper();
+
+ if (!helper)
+ return;
+
+ if (helper->isSupportedUrl(filename))
helper->selectFile(filename);
}
-inline QStringList QFileDialogPrivate::selectedFiles_sys() const
+inline QList<QUrl> QFileDialogPrivate::selectedFiles_sys() const
{
if (QPlatformFileDialogHelper *helper = platformFileDialogHelper())
return helper->selectedFiles();
- return QStringList();
+ return QList<QUrl>();
}
inline void QFileDialogPrivate::setFilter_sys()
diff --git a/src/widgets/dialogs/qfileinfogatherer.cpp b/src/widgets/dialogs/qfileinfogatherer.cpp
index 213aefe5f5..0f12c2b80e 100644
--- a/src/widgets/dialogs/qfileinfogatherer.cpp
+++ b/src/widgets/dialogs/qfileinfogatherer.cpp
@@ -238,7 +238,7 @@ QExtendedInformation QFileInfoGatherer::getInfo(const QFileInfo &fileInfo) const
#endif
#ifdef Q_OS_WIN
- if (m_resolveSymlinks && fileInfo.isSymLink()) {
+ if (m_resolveSymlinks && info.isSymLink(/* ignoreNtfsSymLinks = */ true)) {
QFileInfo resolvedInfo(fileInfo.symLinkTarget());
resolvedInfo = resolvedInfo.canonicalFilePath();
if (resolvedInfo.exists()) {
diff --git a/src/widgets/dialogs/qfileinfogatherer_p.h b/src/widgets/dialogs/qfileinfogatherer_p.h
index 0c4e644e40..447ee78edc 100644
--- a/src/widgets/dialogs/qfileinfogatherer_p.h
+++ b/src/widgets/dialogs/qfileinfogatherer_p.h
@@ -108,7 +108,13 @@ public:
return QExtendedInformation::System;
}
- bool isSymLink() const {
+ bool isSymLink(bool ignoreNtfsSymLinks = false) const
+ {
+ if (ignoreNtfsSymLinks) {
+#ifdef Q_OS_WIN
+ return !mFileInfo.suffix().compare(QLatin1String("lnk"), Qt::CaseInsensitive);
+#endif
+ }
return mFileInfo.isSymLink();
}
diff --git a/src/widgets/dialogs/qfilesystemmodel.cpp b/src/widgets/dialogs/qfilesystemmodel.cpp
index 8e3ecc3e0e..519c158f81 100644
--- a/src/widgets/dialogs/qfilesystemmodel.cpp
+++ b/src/widgets/dialogs/qfilesystemmodel.cpp
@@ -800,7 +800,7 @@ QString QFileSystemModelPrivate::name(const QModelIndex &index) const
if (!index.isValid())
return QString();
QFileSystemNode *dirNode = node(index);
- if (fileInfoGatherer.resolveSymlinks() && !resolvedSymLinks.isEmpty() && dirNode->isSymLink()) {
+ if (fileInfoGatherer.resolveSymlinks() && !resolvedSymLinks.isEmpty() && dirNode->isSymLink(/* ignoreNtfsSymLinks = */ true)) {
QString fullPath = QDir::fromNativeSeparators(filePath(index));
if (resolvedSymLinks.contains(fullPath))
return resolvedSymLinks[fullPath];
diff --git a/src/widgets/dialogs/qfilesystemmodel_p.h b/src/widgets/dialogs/qfilesystemmodel_p.h
index d61936d545..663be3d933 100644
--- a/src/widgets/dialogs/qfilesystemmodel_p.h
+++ b/src/widgets/dialogs/qfilesystemmodel_p.h
@@ -116,7 +116,7 @@ public:
inline bool isFile() const { if (info) return info->isFile(); return true; }
inline bool isSystem() const { if (info) return info->isSystem(); return true; }
inline bool isHidden() const { if (info) return info->isHidden(); return false; }
- inline bool isSymLink() const { if (info) return info->isSymLink(); return false; }
+ inline bool isSymLink(bool ignoreNtfsSymLinks = false) const { return info && info->isSymLink(ignoreNtfsSymLinks); }
inline bool caseSensitive() const { if (info) return info->isCaseSensitive(); return false; }
inline QIcon icon() const { if (info) return info->icon; return QIcon(); }
diff --git a/src/widgets/dialogs/qfontdialog.cpp b/src/widgets/dialogs/qfontdialog.cpp
index 313b475f1f..b989ea7c86 100644
--- a/src/widgets/dialogs/qfontdialog.cpp
+++ b/src/widgets/dialogs/qfontdialog.cpp
@@ -479,7 +479,22 @@ void QFontDialogPrivate::updateFamilies()
enum match_t { MATCH_NONE = 0, MATCH_LAST_RESORT = 1, MATCH_APP = 2, MATCH_FAMILY = 3 };
- QStringList familyNames = fdb.families(writingSystem);
+ const QFontDialog::FontDialogOptions scalableMask = (QFontDialog::ScalableFonts | QFontDialog::NonScalableFonts);
+ const QFontDialog::FontDialogOptions spacingMask = (QFontDialog::ProportionalFonts | QFontDialog::MonospacedFonts);
+ const QFontDialog::FontDialogOptions options = q->options();
+
+ QStringList familyNames;
+ foreach (const QString &family, fdb.families(writingSystem)) {
+ if ((options & scalableMask) && (options & scalableMask) != scalableMask) {
+ if (bool(options & QFontDialog::ScalableFonts) != fdb.isSmoothlyScalable(family))
+ continue;
+ }
+ if ((options & spacingMask) && (options & spacingMask) != spacingMask) {
+ if (bool(options & QFontDialog::MonospacedFonts) != fdb.isFixedPitch(family))
+ continue;
+ }
+ familyNames << family;
+ }
familyList->model()->setStringList(familyNames);
@@ -837,10 +852,21 @@ QFont QFontDialog::selectedFont() const
This enum specifies various options that affect the look and feel
of a font dialog.
+ For instance, it allows to specify which type of font should be
+ displayed. If none are specified all fonts available will be listed.
+
+ Note that the font filtering options might not be supported on some
+ platforms (e.g. Mac). They are always supported by the non native
+ dialog (used on Windows or Linux).
+
\value NoButtons Don't display \uicontrol{OK} and \uicontrol{Cancel} buttons. (Useful for "live dialogs".)
\value DontUseNativeDialog Use Qt's standard font dialog on the Mac instead of Apple's
native font panel. (Currently, the native dialog is never used,
but this is likely to change in future Qt releases.)
+ \value ScalableFonts Show scalable fonts
+ \value NonScalableFonts Show non scalable fonts
+ \value MonospacedFonts Show monospaced fonts
+ \value ProportionalFonts Show proportional fonts
\sa options, setOption(), testOption()
*/
diff --git a/src/widgets/dialogs/qfontdialog.h b/src/widgets/dialogs/qfontdialog.h
index c2d930bc1e..9956987cfe 100644
--- a/src/widgets/dialogs/qfontdialog.h
+++ b/src/widgets/dialogs/qfontdialog.h
@@ -64,7 +64,11 @@ class Q_WIDGETS_EXPORT QFontDialog : public QDialog
public:
enum FontDialogOption {
NoButtons = 0x00000001,
- DontUseNativeDialog = 0x00000002
+ DontUseNativeDialog = 0x00000002,
+ ScalableFonts = 0x00000004,
+ NonScalableFonts = 0x00000008,
+ MonospacedFonts = 0x00000010,
+ ProportionalFonts = 0x00000020
};
Q_DECLARE_FLAGS(FontDialogOptions, FontDialogOption)
diff --git a/src/widgets/dialogs/qinputdialog.cpp b/src/widgets/dialogs/qinputdialog.cpp
index 45aa49d552..c1f8deb4eb 100644
--- a/src/widgets/dialogs/qinputdialog.cpp
+++ b/src/widgets/dialogs/qinputdialog.cpp
@@ -49,6 +49,7 @@
#include "qlabel.h"
#include "qlayout.h"
#include "qlineedit.h"
+#include "qplaintextedit.h"
#include "qlistwidget.h"
#include "qpushbutton.h"
#include "qspinbox.h"
@@ -167,6 +168,7 @@ public:
void ensureLayout();
void ensureLineEdit();
+ void ensurePlainTextEdit();
void ensureComboBox();
void ensureListView();
void ensureIntSpinBox();
@@ -180,11 +182,13 @@ public:
void ensureLayout() const { const_cast<QInputDialogPrivate *>(this)->ensureLayout(); }
bool useComboBoxOrListView() const { return comboBox && comboBox->count() > 0; }
void _q_textChanged(const QString &text);
+ void _q_plainTextEditTextChanged();
void _q_currentRowChanged(const QModelIndex &newIndex, const QModelIndex &oldIndex);
mutable QLabel *label;
mutable QDialogButtonBox *buttonBox;
mutable QLineEdit *lineEdit;
+ mutable QPlainTextEdit *plainTextEdit;
mutable QSpinBox *intSpinBox;
mutable QDoubleSpinBox *doubleSpinBox;
mutable QComboBox *comboBox;
@@ -198,8 +202,8 @@ public:
};
QInputDialogPrivate::QInputDialogPrivate()
- : label(0), buttonBox(0), lineEdit(0), intSpinBox(0), doubleSpinBox(0), comboBox(0), listView(0),
- inputWidget(0), mainLayout(0)
+ : label(0), buttonBox(0), lineEdit(0), plainTextEdit(0), intSpinBox(0), doubleSpinBox(0),
+ comboBox(0), listView(0), inputWidget(0), mainLayout(0)
{
}
@@ -250,6 +254,21 @@ void QInputDialogPrivate::ensureLineEdit()
}
}
+void QInputDialogPrivate::ensurePlainTextEdit()
+{
+ Q_Q(QInputDialog);
+ if (!plainTextEdit) {
+ plainTextEdit = new QPlainTextEdit(q);
+ plainTextEdit->setLineWrapMode(QPlainTextEdit::NoWrap);
+#ifndef QT_NO_IM
+ qt_widget_private(plainTextEdit)->inheritsInputMethodHints = 1;
+#endif
+ plainTextEdit->hide();
+ QObject::connect(plainTextEdit, SIGNAL(textChanged()),
+ q, SLOT(_q_plainTextEditTextChanged()));
+ }
+}
+
void QInputDialogPrivate::ensureComboBox()
{
Q_Q(QInputDialog);
@@ -344,6 +363,8 @@ void QInputDialogPrivate::setInputWidget(QWidget *widget)
// textValue
if (widget == lineEdit) {
lineEdit->setText(textValue);
+ } else if (widget == plainTextEdit) {
+ plainTextEdit->setPlainText(textValue);
} else if (widget == comboBox) {
setComboBoxText(textValue);
} else if (widget == listView) {
@@ -364,6 +385,9 @@ void QInputDialogPrivate::chooseRightTextInputWidget()
} else {
widget = comboBox;
}
+ } else if (opts & QInputDialog::UsePlainTextEditForTextInput) {
+ ensurePlainTextEdit();
+ widget = plainTextEdit;
} else {
ensureLineEdit();
widget = lineEdit;
@@ -417,6 +441,16 @@ void QInputDialogPrivate::_q_textChanged(const QString &text)
}
}
+void QInputDialogPrivate::_q_plainTextEditTextChanged()
+{
+ Q_Q(QInputDialog);
+ QString text = plainTextEdit->toPlainText();
+ if (textValue != text) {
+ textValue = text;
+ emit q->textValueChanged(text);
+ }
+}
+
void QInputDialogPrivate::_q_currentRowChanged(const QModelIndex &newIndex,
const QModelIndex & /* oldIndex */)
{
@@ -434,8 +468,8 @@ void QInputDialogPrivate::_q_currentRowChanged(const QModelIndex &newIndex,
The input value can be a string, a number or an item from a list. A label
must be set to tell the user what they should enter.
- Four static convenience functions are provided: getText(), getInt(),
- getDouble(), and getItem(). All the functions can be used in a similar way,
+ Five static convenience functions are provided: getText(), getMultiLineText(),
+ getInt(), getDouble(), and getItem(). All the functions can be used in a similar way,
for example:
\snippet dialogs/standarddialogs/dialog.cpp 3
@@ -575,6 +609,8 @@ QString QInputDialog::labelText() const
\value NoButtons Don't display \uicontrol{OK} and \uicontrol{Cancel} buttons (useful for "live dialogs").
\value UseListViewForComboBoxItems Use a QListView rather than a non-editable QComboBox for
displaying the items set with setComboBoxItems().
+ \value UsePlainTextEditForTextInput Use a QPlainTextEdit for multiline text input. This value was
+ introduced in 5.2.
\sa options, setOption(), testOption()
*/
@@ -628,6 +664,8 @@ void QInputDialog::setOptions(InputDialogOptions options)
d->buttonBox->setVisible(!(options & NoButtons));
if ((changed & UseListViewForComboBoxItems) && inputMode() == TextInput)
d->chooseRightTextInputWidget();
+ if ((changed & UsePlainTextEditForTextInput) && inputMode() == TextInput)
+ d->chooseRightTextInputWidget();
}
QInputDialog::InputDialogOptions QInputDialog::options() const
@@ -653,6 +691,8 @@ void QInputDialog::setTextValue(const QString &text)
setInputMode(TextInput);
if (d->inputWidget == d->lineEdit) {
d->lineEdit->setText(text);
+ } else if (d->inputWidget == d->plainTextEdit) {
+ d->plainTextEdit->setPlainText(text);
} else if (d->inputWidget == d->comboBox) {
d->setComboBoxText(text);
} else {
@@ -1075,6 +1115,8 @@ void QInputDialog::setVisible(bool visible)
d->inputWidget->setFocus();
if (d->inputWidget == d->lineEdit) {
d->lineEdit->selectAll();
+ } else if (d->inputWidget == d->plainTextEdit) {
+ d->plainTextEdit->selectAll();
} else if (d->inputWidget == d->intSpinBox) {
d->intSpinBox->selectAll();
} else if (d->inputWidget == d->doubleSpinBox) {
@@ -1144,7 +1186,7 @@ void QInputDialog::done(int result)
want to do this, you should create the dialog yourself using one of the
QInputDialog constructors.
- \sa getInt(), getDouble(), getItem()
+ \sa getInt(), getDouble(), getItem(), getMultiLineText()
*/
QString QInputDialog::getText(QWidget *parent, const QString &title, const QString &label,
@@ -1169,6 +1211,58 @@ QString QInputDialog::getText(QWidget *parent, const QString &title, const QStri
}
/*!
+ \since 5.2
+
+ Static convenience function to get a multiline string from the user.
+
+ \a title is the text which is displayed in the title bar of the dialog.
+ \a label is the text which is shown to the user (it should say what should
+ be entered).
+ \a text is the default text which is placed in the plain text edit.
+ \a inputMethodHints is the input method hints that will be used in the
+ edit widget if an input method is active.
+
+ If \a ok is nonnull \e *\a ok will be set to true if the user pressed
+ \uicontrol OK and to false if the user pressed \uicontrol Cancel. The dialog's parent
+ is \a parent. The dialog will be modal and uses the specified widget
+ \a flags.
+
+ If the dialog is accepted, this function returns the text in the dialog's
+ plain text edit. If the dialog is rejected, a null QString is returned.
+
+ Use this static function like this:
+
+ \snippet dialogs/standarddialogs/dialog.cpp 4
+
+ \warning Do not delete \a parent during the execution of the dialog. If you
+ want to do this, you should create the dialog yourself using one of the
+ QInputDialog constructors.
+
+ \sa getInt(), getDouble(), getItem(), getText()
+*/
+
+QString QInputDialog::getMultiLineText(QWidget *parent, const QString &title, const QString &label,
+ const QString &text, bool *ok, Qt::WindowFlags flags,
+ Qt::InputMethodHints inputMethodHints)
+{
+ QInputDialog dialog(parent, flags);
+ dialog.setOptions(QInputDialog::UsePlainTextEditForTextInput);
+ dialog.setWindowTitle(title);
+ dialog.setLabelText(label);
+ dialog.setTextValue(text);
+ dialog.setInputMethodHints(inputMethodHints);
+
+ int ret = dialog.exec();
+ if (ok)
+ *ok = !!ret;
+ if (ret) {
+ return dialog.textValue();
+ } else {
+ return QString();
+ }
+}
+
+/*!
\since 4.5
Static convenience function to get an integer input from the user.
@@ -1196,7 +1290,7 @@ QString QInputDialog::getText(QWidget *parent, const QString &title, const QStri
want to do this, you should create the dialog yourself using one of the
QInputDialog constructors.
- \sa getText(), getDouble(), getItem()
+ \sa getText(), getDouble(), getItem(), getMultiLineText()
*/
int QInputDialog::getInt(QWidget *parent, const QString &title, const QString &label, int value,
@@ -1248,7 +1342,7 @@ int QInputDialog::getInt(QWidget *parent, const QString &title, const QString &l
want to do this, you should create the dialog yourself using one of the
QInputDialog constructors.
- \sa getText(), getDouble(), getItem()
+ \sa getText(), getDouble(), getItem(), getMultiLineText()
*/
/*!
@@ -1277,7 +1371,7 @@ int QInputDialog::getInt(QWidget *parent, const QString &title, const QString &l
want to do this, you should create the dialog yourself using one of the
QInputDialog constructors.
- \sa getText(), getInt(), getItem()
+ \sa getText(), getInt(), getItem(), getMultiLineText()
*/
double QInputDialog::getDouble(QWidget *parent, const QString &title, const QString &label,
@@ -1331,7 +1425,7 @@ double QInputDialog::getDouble(QWidget *parent, const QString &title, const QStr
want to do this, you should create the dialog yourself using one of the
QInputDialog constructors.
- \sa getText(), getInt(), getDouble()
+ \sa getText(), getInt(), getDouble(), getMultiLineText()
*/
QString QInputDialog::getItem(QWidget *parent, const QString &title, const QString &label,
diff --git a/src/widgets/dialogs/qinputdialog.h b/src/widgets/dialogs/qinputdialog.h
index 41dca1f94f..c2c85835c8 100644
--- a/src/widgets/dialogs/qinputdialog.h
+++ b/src/widgets/dialogs/qinputdialog.h
@@ -78,8 +78,9 @@ class Q_WIDGETS_EXPORT QInputDialog : public QDialog
public:
enum InputDialogOption {
- NoButtons = 0x00000001,
- UseListViewForComboBoxItems = 0x00000002
+ NoButtons = 0x00000001,
+ UseListViewForComboBoxItems = 0x00000002,
+ UsePlainTextEditForTextInput = 0x00000004
};
Q_DECLARE_FLAGS(InputDialogOptions, InputDialogOption)
@@ -168,6 +169,9 @@ public:
QLineEdit::EchoMode echo = QLineEdit::Normal,
const QString &text = QString(), bool *ok = 0, Qt::WindowFlags flags = 0,
Qt::InputMethodHints inputMethodHints = Qt::ImhNone);
+ static QString getMultiLineText(QWidget *parent, const QString &title, const QString &label,
+ const QString &text = QString(), bool *ok = 0, Qt::WindowFlags flags = 0,
+ Qt::InputMethodHints inputMethodHints = Qt::ImhNone);
static QString getItem(QWidget *parent, const QString &title, const QString &label,
const QStringList &items, int current = 0, bool editable = true,
bool *ok = 0, Qt::WindowFlags flags = 0,
@@ -204,6 +208,7 @@ public:
private:
Q_DISABLE_COPY(QInputDialog)
Q_PRIVATE_SLOT(d_func(), void _q_textChanged(const QString&))
+ Q_PRIVATE_SLOT(d_func(), void _q_plainTextEditTextChanged())
Q_PRIVATE_SLOT(d_func(), void _q_currentRowChanged(const QModelIndex&, const QModelIndex&))
};
diff --git a/src/widgets/doc/qtwidgets.qdocconf b/src/widgets/doc/qtwidgets.qdocconf
index a989ef9363..d3c7825bc0 100644
--- a/src/widgets/doc/qtwidgets.qdocconf
+++ b/src/widgets/doc/qtwidgets.qdocconf
@@ -54,3 +54,6 @@ imagedirs += images \
../../../doc/src/images \
../../../examples/widgets/doc/images \
../../../examples/widgets
+
+navigation.landingpage = "Qt Widgets"
+navigation.cppclassespage = "Qt Widgets C++ Classes"
diff --git a/src/widgets/graphicsview/qgridlayoutengine.cpp b/src/widgets/graphicsview/qgridlayoutengine.cpp
index 4f43a0a4ac..f741962264 100644
--- a/src/widgets/graphicsview/qgridlayoutengine.cpp
+++ b/src/widgets/graphicsview/qgridlayoutengine.cpp
@@ -432,6 +432,8 @@ QGridLayoutBox QGridLayoutRowData::totalBox(int start, int end) const
result.q_maximumSize = 0.0;
qreal nextSpacing = 0.0;
for (int i = start; i < end; ++i) {
+ if (ignore.testBit(i))
+ continue;
result.add(boxes.at(i), stretches.at(i), nextSpacing);
nextSpacing = spacings.at(i);
}
@@ -1475,7 +1477,7 @@ void QGridLayoutEngine::fillRowData(QGridLayoutRowData *rowData, const QLayoutSt
int effectiveRowSpan = 1;
for (int i = 1; i < itemRowSpan; ++i) {
- if (!rowData->ignore.testBit(i))
+ if (!rowData->ignore.testBit(i + itemRow))
++effectiveRowSpan;
}
@@ -1713,7 +1715,8 @@ void QGridLayoutEngine::ensureGeometries(const QLayoutStyleInfo &styleInfo,
q_descents.resize(rowCount());
if (constraintOrientation() != Qt::Horizontal) {
- //We might have items whose width depends on their height
+ // We might have items whose height depends on their width,
+ // or none of the items has a dynamic constraint.
ensureColumnAndRowData(&q_columnData, &q_totalBoxes[Hor], styleInfo, NULL, NULL, Qt::Horizontal);
//Calculate column widths and positions, and put results in q_xx.data() and q_widths.data() so that we can use this information as
//constraints to find the row heights
@@ -1724,7 +1727,7 @@ void QGridLayoutEngine::ensureGeometries(const QLayoutStyleInfo &styleInfo,
q_rowData.calculateGeometries(0, rowCount(), size.height(), q_yy.data(), q_heights.data(),
q_descents.data(), q_totalBoxes[Ver], q_infos[Ver]);
} else {
- //We have items whose height depends on their width
+ // We have items whose width depends on their height
ensureColumnAndRowData(&q_rowData, &q_totalBoxes[Ver], styleInfo, NULL, NULL, Qt::Vertical);
//Calculate row heights and positions, and put results in q_yy.data() and q_heights.data() so that we can use this information as
//constraints to find the column widths
diff --git a/src/widgets/itemviews/itemviews.pri b/src/widgets/itemviews/itemviews.pri
index 0bc0309271..4e152d18bb 100644
--- a/src/widgets/itemviews/itemviews.pri
+++ b/src/widgets/itemviews/itemviews.pri
@@ -26,6 +26,7 @@ HEADERS += \
itemviews/qtreewidgetitemiterator.h \
itemviews/qdatawidgetmapper.h \
itemviews/qfileiconprovider.h \
+ itemviews/qfileiconprovider_p.h \
itemviews/qcolumnviewgrip_p.h \
itemviews/qcolumnview.h \
itemviews/qcolumnview_p.h \
diff --git a/src/widgets/itemviews/qabstractitemview.cpp b/src/widgets/itemviews/qabstractitemview.cpp
index 70c8f44a73..b79525b9df 100644
--- a/src/widgets/itemviews/qabstractitemview.cpp
+++ b/src/widgets/itemviews/qabstractitemview.cpp
@@ -1108,6 +1108,7 @@ void QAbstractItemView::reset()
QAccessible::updateAccessibility(&accessibleEvent);
}
#endif
+ d->updateGeometry();
}
/*!
@@ -1124,6 +1125,7 @@ void QAbstractItemView::setRootIndex(const QModelIndex &index)
}
d->root = index;
d->doDelayedItemsLayout();
+ d->updateGeometry();
}
/*!
@@ -2668,8 +2670,10 @@ void QAbstractItemView::updateEditorGeometries()
*/
void QAbstractItemView::updateGeometries()
{
+ Q_D(QAbstractItemView);
updateEditorGeometries();
- d_func()->fetchMoreTimer.start(0, this); //fetch more later
+ d->fetchMoreTimer.start(0, this); //fetch more later
+ d->updateGeometry();
}
/*!
@@ -3231,6 +3235,7 @@ void QAbstractItemView::dataChanged(const QModelIndex &topLeft, const QModelInde
QAccessible::updateAccessibility(&accessibleEvent);
}
#endif
+ d->updateGeometry();
}
/*!
@@ -3332,6 +3337,7 @@ void QAbstractItemViewPrivate::_q_rowsRemoved(const QModelIndex &index, int star
QAccessible::updateAccessibility(&accessibleEvent);
}
#endif
+ updateGeometry();
}
/*!
@@ -3412,6 +3418,7 @@ void QAbstractItemViewPrivate::_q_columnsRemoved(const QModelIndex &index, int s
QAccessible::updateAccessibility(&accessibleEvent);
}
#endif
+ updateGeometry();
}
@@ -3435,6 +3442,7 @@ void QAbstractItemViewPrivate::_q_rowsInserted(const QModelIndex &index, int sta
QAccessible::updateAccessibility(&accessibleEvent);
}
#endif
+ updateGeometry();
}
/*!
@@ -3459,6 +3467,7 @@ void QAbstractItemViewPrivate::_q_columnsInserted(const QModelIndex &index, int
QAccessible::updateAccessibility(&accessibleEvent);
}
#endif
+ updateGeometry();
}
/*!
@@ -4084,7 +4093,14 @@ void QAbstractItemViewPrivate::interruptDelayedItemsLayout() const
delayedPendingLayout = false;
}
-
+void QAbstractItemViewPrivate::updateGeometry()
+{
+ Q_Q(QAbstractItemView);
+ if (sizeAdjustPolicy == QAbstractScrollArea::AdjustIgnored)
+ return;
+ if (sizeAdjustPolicy == QAbstractScrollArea::AdjustToContents || !shownOnce)
+ q->updateGeometry();
+}
QWidget *QAbstractItemViewPrivate::editor(const QModelIndex &index,
const QStyleOptionViewItem &options)
diff --git a/src/widgets/itemviews/qabstractitemview_p.h b/src/widgets/itemviews/qabstractitemview_p.h
index 86eab174ed..5da22615e2 100644
--- a/src/widgets/itemviews/qabstractitemview_p.h
+++ b/src/widgets/itemviews/qabstractitemview_p.h
@@ -127,6 +127,8 @@ public:
void doDelayedItemsLayout(int delay = 0);
void interruptDelayedItemsLayout() const;
+ void updateGeometry();
+
void startAutoScroll()
{ // ### it would be nice to make this into a style hint one day
int scrollInterval = (verticalScrollMode == QAbstractItemView::ScrollPerItem) ? 150 : 50;
diff --git a/src/widgets/itemviews/qfileiconprovider.cpp b/src/widgets/itemviews/qfileiconprovider.cpp
index 8a0736ec70..71697ddc40 100644
--- a/src/widgets/itemviews/qfileiconprovider.cpp
+++ b/src/widgets/itemviews/qfileiconprovider.cpp
@@ -40,9 +40,8 @@
****************************************************************************/
#include "qfileiconprovider.h"
+#include "qfileiconprovider_p.h"
-#ifndef QT_NO_FILEICONPROVIDER
-#include <qstyle.h>
#include <qapplication.h>
#include <qdir.h>
#include <qpixmapcache.h>
@@ -83,34 +82,15 @@ QT_BEGIN_NAMESPACE
\value File
*/
-class QFileIconProviderPrivate
-{
- Q_DECLARE_PUBLIC(QFileIconProvider)
-
-public:
- QFileIconProviderPrivate();
- QIcon getIcon(QStyle::StandardPixmap name) const;
- QIcon getIcon(const QFileInfo &fi) const;
-
- QFileIconProvider *q_ptr;
- const QString homePath;
-
-private:
- mutable QIcon file;
- mutable QIcon fileLink;
- mutable QIcon directory;
- mutable QIcon directoryLink;
- mutable QIcon harddisk;
- mutable QIcon floppy;
- mutable QIcon cdrom;
- mutable QIcon ram;
- mutable QIcon network;
- mutable QIcon computer;
- mutable QIcon desktop;
- mutable QIcon trashcan;
- mutable QIcon generic;
- mutable QIcon home;
-};
+
+/*!
+ \enum QFileIconProvider::Option
+ \since 5.2
+
+ \value DontUseCustomDirectoryIcons Always use the default directory icon.
+ Some platforms allow the user to set a different icon. Custom icon lookup
+ cause a big performance impact over network or removable drives.
+*/
QFileIconProviderPrivate::QFileIconProviderPrivate() :
homePath(QDir::home().absolutePath())
@@ -193,6 +173,31 @@ QFileIconProvider::~QFileIconProvider()
}
/*!
+ \since 5.2
+ Sets \a options that affect the icon provider.
+ \sa options()
+*/
+
+void QFileIconProvider::setOptions(QFileIconProvider::Options options)
+{
+ Q_D(QFileIconProvider);
+ d->options = options;
+}
+
+/*!
+ \since 5.2
+ Returns all the options that affect the icon provider.
+ By default, all options are disabled.
+ \sa setOptions()
+*/
+
+QFileIconProvider::Options QFileIconProvider::options() const
+{
+ Q_D(const QFileIconProvider);
+ return d->options;
+}
+
+/*!
Returns an icon set for the given \a type.
*/
@@ -220,6 +225,23 @@ QIcon QFileIconProvider::icon(IconType type) const
return QIcon();
}
+static bool isCacheable(const QFileInfo &fi)
+{
+ if (!fi.isFile())
+ return false;
+
+#ifdef Q_OS_WIN
+ // On windows it's faster to just look at the file extensions. QTBUG-13182
+ const QString fileExtension = fi.suffix();
+ // Will return false for .exe, .lnk and .ico extensions
+ return fileExtension.compare(QLatin1String("exe"), Qt::CaseInsensitive) &&
+ fileExtension.compare(QLatin1String("lnk"), Qt::CaseInsensitive) &&
+ fileExtension.compare(QLatin1String("ico"), Qt::CaseInsensitive);
+#else
+ return !fi.isExecutable() && !fi.isSymLink();
+#endif
+}
+
QIcon QFileIconProviderPrivate::getIcon(const QFileInfo &fi) const
{
QIcon retIcon;
@@ -231,10 +253,9 @@ QIcon QFileIconProviderPrivate::getIcon(const QFileInfo &fi) const
if (sizes.isEmpty())
return retIcon;
- const QString fileExtension = fi.suffix().toUpper();
const QString keyBase = QLatin1String("qt_.") + fi.suffix().toUpper();
- bool cacheable = fi.isFile() && !fi.isExecutable() && !fi.isSymLink() && fileExtension != QLatin1String("ICO");
+ bool cacheable = isCacheable(fi);
if (cacheable) {
QPixmap pixmap;
QPixmapCache::find(keyBase + QString::number(sizes.at(0)), pixmap);
@@ -253,8 +274,12 @@ QIcon QFileIconProviderPrivate::getIcon(const QFileInfo &fi) const
}
}
+ QPlatformTheme::IconOptions iconOptions;
+ if (options & QFileIconProvider::DontUseCustomDirectoryIcons)
+ iconOptions |= QPlatformTheme::DontUseCustomDirectoryIcons;
+
Q_FOREACH (int size, sizes) {
- QPixmap pixmap = theme->fileIconPixmap(fi, QSizeF(size, size));
+ QPixmap pixmap = theme->fileIconPixmap(fi, QSizeF(size, size), iconOptions);
if (!pixmap.isNull()) {
retIcon.addPixmap(pixmap);
if (cacheable)
@@ -372,5 +397,3 @@ QString QFileIconProvider::type(const QFileInfo &info) const
}
QT_END_NAMESPACE
-
-#endif
diff --git a/src/widgets/itemviews/qfileiconprovider.h b/src/widgets/itemviews/qfileiconprovider.h
index cac135fe71..6f7e28395b 100644
--- a/src/widgets/itemviews/qfileiconprovider.h
+++ b/src/widgets/itemviews/qfileiconprovider.h
@@ -49,8 +49,6 @@
QT_BEGIN_NAMESPACE
-#ifndef QT_NO_FILEICONPROVIDER
-
class QFileIconProviderPrivate;
class Q_WIDGETS_EXPORT QFileIconProvider
@@ -59,19 +57,27 @@ public:
QFileIconProvider();
virtual ~QFileIconProvider();
enum IconType { Computer, Desktop, Trashcan, Network, Drive, Folder, File };
+
+ enum Option {
+ DontUseCustomDirectoryIcons = 0x00000001
+ };
+ Q_DECLARE_FLAGS(Options, Option)
+
virtual QIcon icon(IconType type) const;
virtual QIcon icon(const QFileInfo &info) const;
virtual QString type(const QFileInfo &info) const;
+ void setOptions(Options options);
+ Options options() const;
+
private:
Q_DECLARE_PRIVATE(QFileIconProvider)
QScopedPointer<QFileIconProviderPrivate> d_ptr;
Q_DISABLE_COPY(QFileIconProvider)
};
-#endif // QT_NO_FILEICONPROVIDER
+Q_DECLARE_OPERATORS_FOR_FLAGS(QFileIconProvider::Options)
QT_END_NAMESPACE
#endif // QFILEICONPROVIDER_H
-
diff --git a/src/widgets/itemviews/qfileiconprovider_p.h b/src/widgets/itemviews/qfileiconprovider_p.h
new file mode 100644
index 0000000000..9b2d536258
--- /dev/null
+++ b/src/widgets/itemviews/qfileiconprovider_p.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtWidgets 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$
+**
+****************************************************************************/
+
+#ifndef QFILEICONPROVIDER_P_H
+#define QFILEICONPROVIDER_P_H
+
+#include "qfileiconprovider.h"
+
+#include <QtCore/qstring.h>
+#include <QtGui/qicon.h>
+#include <QtWidgets/qstyle.h>
+
+QT_BEGIN_NAMESPACE
+
+class QFileInfo;
+
+class QFileIconProviderPrivate
+{
+ Q_DECLARE_PUBLIC(QFileIconProvider)
+
+public:
+ QFileIconProviderPrivate();
+ QIcon getIcon(QStyle::StandardPixmap name) const;
+ QIcon getIcon(const QFileInfo &fi) const;
+
+ QFileIconProvider *q_ptr;
+ const QString homePath;
+ QFileIconProvider::Options options;
+
+private:
+ mutable QIcon file;
+ mutable QIcon fileLink;
+ mutable QIcon directory;
+ mutable QIcon directoryLink;
+ mutable QIcon harddisk;
+ mutable QIcon floppy;
+ mutable QIcon cdrom;
+ mutable QIcon ram;
+ mutable QIcon network;
+ mutable QIcon computer;
+ mutable QIcon desktop;
+ mutable QIcon trashcan;
+ mutable QIcon generic;
+ mutable QIcon home;
+};
+
+QT_END_NAMESPACE
+
+#endif // QFILEICONPROVIDER_P_H
diff --git a/src/widgets/itemviews/qheaderview.cpp b/src/widgets/itemviews/qheaderview.cpp
index edfbc5c8f1..c9a845fc7b 100644
--- a/src/widgets/itemviews/qheaderview.cpp
+++ b/src/widgets/itemviews/qheaderview.cpp
@@ -550,6 +550,22 @@ QSize QHeaderView::sizeHint() const
}
/*!
+ \reimp
+*/
+
+void QHeaderView::setVisible(bool v)
+{
+ bool actualChange = (v != isVisible());
+ QAbstractItemView::setVisible(v);
+ if (actualChange) {
+ QAbstractScrollArea *parent = qobject_cast<QAbstractScrollArea*>(parentWidget());
+ if (parent)
+ parent->updateGeometry();
+ }
+}
+
+
+/*!
Returns a suitable size hint for the section specified by \a logicalIndex.
\sa sizeHint(), defaultSectionSize(), minimumSectionSize(),
@@ -918,6 +934,18 @@ void QHeaderView::resizeSection(int logical, int size)
d->doDelayedResizeSections();
r = d->viewport->rect();
}
+
+ // If the parent is a QAbstractScrollArea with QAbstractScrollArea::AdjustToContents
+ // then we want to change the geometry on that widget. Not doing it at once can/will
+ // cause scrollbars flicker as they would be shown at first but then removed.
+ // In the same situation it will also allow shrinking the whole view when stretchLastSection is set
+ // (It is default on QTreeViews - and it wouldn't shrink since the last stretch was made before the
+ // viewport was resized)
+
+ QAbstractScrollArea *parent = qobject_cast<QAbstractScrollArea *>(parentWidget());
+ if (parent && parent->sizeAdjustPolicy() == QAbstractScrollArea::AdjustToContents)
+ parent->updateGeometry();
+
d->viewport->update(r.normalized());
emit sectionResized(logical, oldSize, size);
}
@@ -1225,7 +1253,7 @@ void QHeaderView::setSectionResizeMode(ResizeMode mode)
property is set to true. This is the default for the horizontal headers provided
by QTreeView.
- \sa setStretchLastSection()
+ \sa setStretchLastSection(), resizeContentsPrecision()
*/
void QHeaderView::setSectionResizeMode(int logicalIndex, ResizeMode mode)
@@ -1288,6 +1316,53 @@ QHeaderView::ResizeMode QHeaderView::sectionResizeMode(int logicalIndex) const
return d->headerSectionResizeMode(visual);
}
+/*!
+ \since 5.2
+ Sets how precise QHeaderView should calculate the size when ResizeToContents is used.
+ A low value will provide a less accurate but fast auto resize while a higher
+ value will provide a more accurate resize that however can be slow.
+
+ The number \a precision specifies how many sections that should be consider
+ when calculating the preferred size.
+
+ The default value is 1000 meaning that a horizontal column with auto-resize will look
+ at maximum 1000 rows on calculating when doing an auto resize.
+
+ Special value 0 means that it will look at only the visible area.
+ Special value -1 will imply looking at all elements.
+
+ This value is used in QTableView::sizeHintForColumn(), QTableView::sizeHintForRow()
+ and QTreeView::sizeHintForColumn(). Reimplementing these functions can make this
+ function not having an effect.
+
+ If \a resizeSectionsNow is set to true (default) it will do adjustment of sections by calling
+ resizeSections(). (regardless if the precision was changed).
+
+ \sa resizeContentsPrecision(), setSectionResizeMode(), resizeSections(), QTableView::sizeHintForColumn(), QTableView::sizeHintForRow(), QTreeView::sizeHintForColumn()
+*/
+
+void QHeaderView::setResizeContentsPrecision(int precision, bool resizeSectionsNow)
+{
+ Q_D(QHeaderView);
+ d->resizeContentsPrecision = precision;
+ if (resizeSectionsNow)
+ resizeSections();
+}
+
+/*!
+ \since 5.2
+ Returns how precise QHeaderView will calculate on ResizeToContents.
+
+ \sa setResizeContentsPrecision(), setSectionResizeMode()
+
+*/
+
+int QHeaderView::resizeContentsPrecision() const
+{
+ Q_D(const QHeaderView);
+ return d->resizeContentsPrecision;
+}
+
// ### Qt 6 - remove this obsolete function
/*!
\obsolete
@@ -3512,6 +3587,19 @@ int QHeaderViewPrivate::adjustedVisualIndex(int visualIndex) const
return visualIndex;
}
+void QHeaderViewPrivate::setScrollOffset(const QScrollBar *scrollBar, QAbstractItemView::ScrollMode scrollMode)
+{
+ Q_Q(QHeaderView);
+ if (scrollMode == QAbstractItemView::ScrollPerItem) {
+ if (scrollBar->maximum() > 0 && scrollBar->value() == scrollBar->maximum())
+ q->setOffsetToLastSection();
+ else
+ q->setOffsetToSectionPosition(scrollBar->value());
+ } else {
+ q->setOffset(scrollBar->value());
+ }
+}
+
#ifndef QT_NO_DATASTREAM
void QHeaderViewPrivate::write(QDataStream &out) const
{
@@ -3542,6 +3630,8 @@ void QHeaderViewPrivate::write(QDataStream &out) const
out << int(globalResizeMode);
out << sectionItems;
+ if (out.version() >= QDataStream::Qt_5_2)
+ out << resizeContentsPrecision;
}
bool QHeaderViewPrivate::read(QDataStream &in)
@@ -3593,6 +3683,10 @@ bool QHeaderViewPrivate::read(QDataStream &in)
}
sectionItems = newSectionItems;
recalcSectionStartPos();
+
+ if (in.version() >= QDataStream::Qt_5_2)
+ in >> resizeContentsPrecision;
+
return true;
}
diff --git a/src/widgets/itemviews/qheaderview.h b/src/widgets/itemviews/qheaderview.h
index 8fcd8d7a36..3de3d320bf 100644
--- a/src/widgets/itemviews/qheaderview.h
+++ b/src/widgets/itemviews/qheaderview.h
@@ -84,6 +84,7 @@ public:
int offset() const;
int length() const;
QSize sizeHint() const;
+ void setVisible(bool v);
int sectionSizeHint(int logicalIndex) const;
int visualIndexAt(int position) const;
@@ -132,6 +133,10 @@ public:
ResizeMode sectionResizeMode(int logicalIndex) const;
void setSectionResizeMode(ResizeMode mode);
void setSectionResizeMode(int logicalIndex, ResizeMode mode);
+
+ void setResizeContentsPrecision(int precision, bool resizeNow = true);
+ int resizeContentsPrecision() const;
+
#if QT_DEPRECATED_SINCE(5, 0)
inline QT_DEPRECATED void setResizeMode(ResizeMode mode)
{ setSectionResizeMode(mode); }
diff --git a/src/widgets/itemviews/qheaderview_p.h b/src/widgets/itemviews/qheaderview_p.h
index 7fda0c8873..c56e0d6196 100644
--- a/src/widgets/itemviews/qheaderview_p.h
+++ b/src/widgets/itemviews/qheaderview_p.h
@@ -99,7 +99,8 @@ public:
sectionIndicatorOffset(0),
sectionIndicator(0),
globalResizeMode(QHeaderView::Interactive),
- sectionStartposRecalc(true)
+ sectionStartposRecalc(true),
+ resizeContentsPrecision(1000)
{}
@@ -291,6 +292,7 @@ public:
QHeaderView::ResizeMode globalResizeMode;
QList<QPersistentModelIndex> persistentHiddenSections;
mutable bool sectionStartposRecalc;
+ int resizeContentsPrecision;
// header sections
struct SectionItem {
@@ -341,6 +343,7 @@ public:
// other
int viewSectionSizeHint(int logical) const;
int adjustedVisualIndex(int visualIndex) const;
+ void setScrollOffset(const QScrollBar *scrollBar, QAbstractItemView::ScrollMode scrollMode);
#ifndef QT_NO_DATASTREAM
void write(QDataStream &out) const;
diff --git a/src/widgets/itemviews/qlistwidget.cpp b/src/widgets/itemviews/qlistwidget.cpp
index 39d03124ce..1573e97981 100644
--- a/src/widgets/itemviews/qlistwidget.cpp
+++ b/src/widgets/itemviews/qlistwidget.cpp
@@ -347,7 +347,11 @@ void QListModel::ensureSorted(int column, Qt::SortOrder order, int start, int en
bool changed = false;
for (int i = 0; i < count; ++i) {
int oldRow = sorting.at(i).second;
+ int tmpitepos = lit - tmp.begin();
QListWidgetItem *item = tmp.takeAt(oldRow);
+ if (tmpitepos > tmp.size())
+ --tmpitepos;
+ lit = tmp.begin() + tmpitepos;
lit = sortedInsertionIterator(lit, tmp.end(), order, item);
int newRow = qMax(lit - tmp.begin(), 0);
lit = tmp.insert(lit, item);
diff --git a/src/widgets/itemviews/qtableview.cpp b/src/widgets/itemviews/qtableview.cpp
index a6623b9462..d282397c1b 100644
--- a/src/widgets/itemviews/qtableview.cpp
+++ b/src/widgets/itemviews/qtableview.cpp
@@ -931,6 +931,59 @@ void QTableViewPrivate::drawCell(QPainter *painter, const QStyleOptionViewItem &
}
/*!
+ \internal
+ Get sizeHint width for single Index (providing existing hint and style option)
+*/
+int QTableViewPrivate::widthHintForIndex(const QModelIndex &index, int hint, const QStyleOptionViewItem &option) const
+{
+ Q_Q(const QTableView);
+ QWidget *editor = editorForIndex(index).widget.data();
+ if (editor && persistent.contains(editor)) {
+ hint = qMax(hint, editor->sizeHint().width());
+ int min = editor->minimumSize().width();
+ int max = editor->maximumSize().width();
+ hint = qBound(min, hint, max);
+ }
+ hint = qMax(hint, q->itemDelegate(index)->sizeHint(option, index).width());
+ return hint;
+}
+
+/*!
+ \internal
+ Get sizeHint height for single Index (providing existing hint and style option)
+*/
+int QTableViewPrivate::heightHintForIndex(const QModelIndex &index, int hint, QStyleOptionViewItem &option) const
+{
+ Q_Q(const QTableView);
+ QWidget *editor = editorForIndex(index).widget.data();
+ if (editor && persistent.contains(editor)) {
+ hint = qMax(hint, editor->sizeHint().height());
+ int min = editor->minimumSize().height();
+ int max = editor->maximumSize().height();
+ hint = qBound(min, hint, max);
+ }
+
+ if (wrapItemText) {// for wrapping boundaries
+ option.rect.setY(q->rowViewportPosition(index.row()));
+ int height = q->rowHeight(index.row());
+ // if the option.height == 0 then q->itemDelegate(index)->sizeHint(option, index) will be wrong.
+ // The option.height == 0 is used to conclude that the text is not wrapped, and hence it will
+ // (exactly like widthHintForIndex) return a QSize with a long width (that we don't use) -
+ // and the height of the text if it was/is on one line.
+ // What we want is a height hint for the current width (and we know that this section is not hidden)
+ // Therefore we catch this special situation with:
+ if (height == 0)
+ height = 1;
+ option.rect.setHeight(height);
+ option.rect.setX(q->columnViewportPosition(index.column()));
+ option.rect.setWidth(q->columnWidth(index.column()));
+ }
+ hint = qMax(hint, q->itemDelegate(index)->sizeHint(option, index).height());
+ return hint;
+}
+
+
+/*!
\class QTableView
\brief The QTableView class provides a default model/view
@@ -1056,6 +1109,19 @@ QTableView::~QTableView()
/*!
\reimp
*/
+QSize QTableView::viewportSizeHint() const
+{
+ Q_D(const QTableView);
+ QSize result( (d->verticalHeader->isHidden() ? 0 : d->verticalHeader->width()) + d->horizontalHeader->length(),
+ (d->horizontalHeader->isHidden() ? 0 : d->horizontalHeader->height()) + d->verticalHeader->length());
+ result += QSize(verticalScrollBar()->isVisible() ? verticalScrollBar()->width() : 0,
+ horizontalScrollBar()->isVisible() ? horizontalScrollBar()->height() : 0);
+ return result;
+}
+
+/*!
+ \reimp
+*/
void QTableView::setModel(QAbstractItemModel *model)
{
Q_D(QTableView);
@@ -1113,15 +1179,7 @@ void QTableView::doItemsLayout()
{
Q_D(QTableView);
QAbstractItemView::doItemsLayout();
- if (verticalScrollMode() == QAbstractItemView::ScrollPerItem) {
- const int max = verticalScrollBar()->maximum();
- if (max > 0 && verticalScrollBar()->value() == max)
- d->verticalHeader->setOffsetToLastSection();
- else
- d->verticalHeader->setOffsetToSectionPosition(verticalScrollBar()->value());
- } else {
- d->verticalHeader->setOffset(verticalScrollBar()->value());
- }
+ d->verticalHeader->d_func()->setScrollOffset(verticalScrollBar(), verticalScrollMode());
if (!d->verticalHeader->updatesEnabled())
d->verticalHeader->setUpdatesEnabled(true);
}
@@ -1258,29 +1316,19 @@ void QTableView::scrollContentsBy(int dx, int dy)
dx = isRightToLeft() ? -dx : dx;
if (dx) {
+ int oldOffset = d->horizontalHeader->offset();
+ d->horizontalHeader->d_func()->setScrollOffset(horizontalScrollBar(), horizontalScrollMode());
if (horizontalScrollMode() == QAbstractItemView::ScrollPerItem) {
- int oldOffset = d->horizontalHeader->offset();
- if (horizontalScrollBar()->value() == horizontalScrollBar()->maximum())
- d->horizontalHeader->setOffsetToLastSection();
- else
- d->horizontalHeader->setOffsetToSectionPosition(horizontalScrollBar()->value());
int newOffset = d->horizontalHeader->offset();
dx = isRightToLeft() ? newOffset - oldOffset : oldOffset - newOffset;
- } else {
- d->horizontalHeader->setOffset(horizontalScrollBar()->value());
}
}
if (dy) {
+ int oldOffset = d->verticalHeader->offset();
+ d->verticalHeader->d_func()->setScrollOffset(verticalScrollBar(), verticalScrollMode());
if (verticalScrollMode() == QAbstractItemView::ScrollPerItem) {
- int oldOffset = d->verticalHeader->offset();
- if (verticalScrollBar()->value() == verticalScrollBar()->maximum())
- d->verticalHeader->setOffsetToLastSection();
- else
- d->verticalHeader->setOffsetToSectionPosition(verticalScrollBar()->value());
int newOffset = d->verticalHeader->offset();
dy = oldOffset - newOffset;
- } else {
- d->verticalHeader->setOffset(verticalScrollBar()->value());
}
}
d->scrollContentsBy(dx, dy);
@@ -1760,13 +1808,13 @@ QModelIndex QTableView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifi
visualRow = bottom;
break;
case MovePageUp: {
- int newRow = rowAt(visualRect(current).top() - d->viewport->height());
+ int newRow = rowAt(visualRect(current).bottom() - d->viewport->height());
if (newRow == -1)
newRow = d->logicalRow(0);
return d->model->index(newRow, current.column(), d->root);
}
case MovePageDown: {
- int newRow = rowAt(visualRect(current).bottom() + d->viewport->height());
+ int newRow = rowAt(visualRect(current).top() + d->viewport->height());
if (newRow == -1)
newRow = d->logicalRow(bottom);
return d->model->index(newRow, current.column(), d->root);
@@ -2175,7 +2223,7 @@ void QTableView::updateGeometries()
if a larger row height is required by either the vertical header or
the item delegate, that width will be used instead.
- \sa QWidget::sizeHint, verticalHeader()
+ \sa QWidget::sizeHint, verticalHeader(), QHeaderView::resizeContentsPrecision()
*/
int QTableView::sizeHintForRow(int row) const
{
@@ -2185,6 +2233,8 @@ int QTableView::sizeHintForRow(int row) const
return -1;
ensurePolished();
+ const int maximumProcessCols = d->verticalHeader->resizeContentsPrecision();
+
int left = qMax(0, d->horizontalHeader->visualIndexAt(0));
int right = d->horizontalHeader->visualIndexAt(d->viewport->width());
@@ -2195,27 +2245,55 @@ int QTableView::sizeHintForRow(int row) const
int hint = 0;
QModelIndex index;
- for (int column = left; column <= right; ++column) {
+ int columnsProcessed = 0;
+ int column = left;
+ for (; column <= right; ++column) {
int logicalColumn = d->horizontalHeader->logicalIndex(column);
if (d->horizontalHeader->isSectionHidden(logicalColumn))
continue;
index = d->model->index(row, logicalColumn, d->root);
- if (d->wrapItemText) {// for wrapping boundaries
- option.rect.setY(rowViewportPosition(index.row()));
- option.rect.setHeight(rowHeight(index.row()));
- option.rect.setX(columnViewportPosition(index.column()));
- option.rect.setWidth(columnWidth(index.column()));
- }
+ hint = d->heightHintForIndex(index, hint, option);
+
+ ++columnsProcessed;
+ if (columnsProcessed == maximumProcessCols)
+ break;
+ }
- QWidget *editor = d->editorForIndex(index).widget.data();
- if (editor && d->persistent.contains(editor)) {
- hint = qMax(hint, editor->sizeHint().height());
- int min = editor->minimumSize().height();
- int max = editor->maximumSize().height();
- hint = qBound(min, hint, max);
+ int actualRight = d->model->columnCount(d->root) - 1;
+ int idxLeft = left;
+ int idxRight = column - 1;
+
+ if (maximumProcessCols == 0)
+ columnsProcessed = 0; // skip the while loop
+
+ while (columnsProcessed != maximumProcessCols && (idxLeft > 0 || idxRight < actualRight)) {
+ int logicalIdx = -1;
+
+ if ((columnsProcessed % 2 && idxLeft > 0) || idxRight == actualRight) {
+ while (idxLeft > 0) {
+ --idxLeft;
+ int logcol = d->horizontalHeader->logicalIndex(idxLeft);
+ if (d->horizontalHeader->isSectionHidden(logcol))
+ continue;
+ logicalIdx = logcol;
+ break;
+ }
+ } else {
+ while (idxRight < actualRight) {
+ ++idxRight;
+ int logcol = d->horizontalHeader->logicalIndex(idxRight);
+ if (d->horizontalHeader->isSectionHidden(logcol))
+ continue;
+ logicalIdx = logcol;
+ break;
+ }
}
+ if (logicalIdx < 0)
+ continue;
- hint = qMax(hint, itemDelegate(index)->sizeHint(option, index).height());
+ index = d->model->index(row, logicalIdx, d->root);
+ hint = d->heightHintForIndex(index, hint, option);
+ ++columnsProcessed;
}
return d->showGrid ? hint + 1 : hint;
@@ -2234,7 +2312,7 @@ int QTableView::sizeHintForRow(int row) const
required by either the horizontal header or the item delegate, the larger
width will be used instead.
- \sa QWidget::sizeHint, horizontalHeader()
+ \sa QWidget::sizeHint, horizontalHeader(), QHeaderView::resizeContentsPrecision()
*/
int QTableView::sizeHintForColumn(int column) const
{
@@ -2244,6 +2322,7 @@ int QTableView::sizeHintForColumn(int column) const
return -1;
ensurePolished();
+ const int maximumProcessRows = d->horizontalHeader->resizeContentsPrecision();
int top = qMax(0, d->verticalHeader->visualIndexAt(0));
int bottom = d->verticalHeader->visualIndexAt(d->viewport->height());
@@ -2253,22 +2332,56 @@ int QTableView::sizeHintForColumn(int column) const
QStyleOptionViewItem option = d->viewOptions();
int hint = 0;
+ int rowsProcessed = 0;
QModelIndex index;
- for (int row = top; row <= bottom; ++row) {
+ int row = top;
+ for (; row <= bottom; ++row) {
int logicalRow = d->verticalHeader->logicalIndex(row);
if (d->verticalHeader->isSectionHidden(logicalRow))
continue;
index = d->model->index(logicalRow, column, d->root);
- QWidget *editor = d->editorForIndex(index).widget.data();
- if (editor && d->persistent.contains(editor)) {
- hint = qMax(hint, editor->sizeHint().width());
- int min = editor->minimumSize().width();
- int max = editor->maximumSize().width();
- hint = qBound(min, hint, max);
+ hint = d->widthHintForIndex(index, hint, option);
+ ++rowsProcessed;
+ if (rowsProcessed == maximumProcessRows)
+ break;
+ }
+
+ int actualBottom = d->model->rowCount(d->root) - 1;
+ int idxTop = top;
+ int idxBottom = row - 1;
+
+ if (maximumProcessRows == 0)
+ rowsProcessed = 0; // skip the while loop
+
+ while (rowsProcessed != maximumProcessRows && (idxTop > 0 || idxBottom < actualBottom)) {
+ int logicalIdx = -1;
+
+ if ((rowsProcessed % 2 && idxTop > 0) || idxBottom == actualBottom) {
+ while (idxTop > 0) {
+ --idxTop;
+ int logrow = d->verticalHeader->logicalIndex(idxTop);
+ if (d->verticalHeader->isSectionHidden(logrow))
+ continue;
+ logicalIdx = logrow;
+ break;
+ }
+ } else {
+ while (idxBottom < actualBottom) {
+ ++idxBottom;
+ int logrow = d->verticalHeader->logicalIndex(idxBottom);
+ if (d->verticalHeader->isSectionHidden(logrow))
+ continue;
+ logicalIdx = logrow;
+ break;
+ }
}
+ if (logicalIdx < 0)
+ continue;
- hint = qMax(hint, itemDelegate(index)->sizeHint(option, index).width());
+ index = d->model->index(logicalIdx, column, d->root);
+ hint = d->widthHintForIndex(index, hint, option);
+ ++rowsProcessed;
}
return d->showGrid ? hint + 1 : hint;
@@ -2934,6 +3047,8 @@ void QTableView::showColumn(int column)
/*!
Resizes the given \a row based on the size hints of the delegate
used to render each item in the row.
+
+ \sa resizeRowsToContents(), sizeHintForRow(), QHeaderView::resizeContentsPrecision()
*/
void QTableView::resizeRowToContents(int row)
{
@@ -2946,6 +3061,8 @@ void QTableView::resizeRowToContents(int row)
/*!
Resizes all rows based on the size hints of the delegate
used to render each item in the rows.
+
+ \sa resizeRowToContents(), sizeHintForRow(), QHeaderView::resizeContentsPrecision()
*/
void QTableView::resizeRowsToContents()
{
@@ -2959,6 +3076,8 @@ void QTableView::resizeRowsToContents()
\note Only visible columns will be resized. Reimplement sizeHintForColumn()
to resize hidden columns as well.
+
+ \sa resizeColumnsToContents(), sizeHintForColumn(), QHeaderView::resizeContentsPrecision()
*/
void QTableView::resizeColumnToContents(int column)
{
@@ -2971,6 +3090,8 @@ void QTableView::resizeColumnToContents(int column)
/*!
Resizes all columns based on the size hints of the delegate
used to render each item in the columns.
+
+ \sa resizeColumnToContents(), sizeHintForColumn(), QHeaderView::resizeContentsPrecision()
*/
void QTableView::resizeColumnsToContents()
{
diff --git a/src/widgets/itemviews/qtableview.h b/src/widgets/itemviews/qtableview.h
index 824348dbe8..db956480d6 100644
--- a/src/widgets/itemviews/qtableview.h
+++ b/src/widgets/itemviews/qtableview.h
@@ -118,6 +118,8 @@ public:
void sortByColumn(int column, Qt::SortOrder order);
+ QSize viewportSizeHint() const;
+
public Q_SLOTS:
void selectRow(int row);
void selectColumn(int column);
diff --git a/src/widgets/itemviews/qtableview_p.h b/src/widgets/itemviews/qtableview_p.h
index 923beec253..d36dcd2c3a 100644
--- a/src/widgets/itemviews/qtableview_p.h
+++ b/src/widgets/itemviews/qtableview_p.h
@@ -181,6 +181,8 @@ public:
const QStyleOptionViewItem &option, QBitArray *drawn,
int firstVisualRow, int lastVisualRow, int firstVisualColumn, int lastVisualColumn);
void drawCell(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index);
+ int widthHintForIndex(const QModelIndex &index, int hint, const QStyleOptionViewItem &option) const;
+ int heightHintForIndex(const QModelIndex &index, int hint, QStyleOptionViewItem &option) const;
bool showGrid;
Qt::PenStyle gridStyle;
diff --git a/src/widgets/itemviews/qtreeview.cpp b/src/widgets/itemviews/qtreeview.cpp
index 6aefbb5367..38f0aa6a9e 100644
--- a/src/widgets/itemviews/qtreeview.cpp
+++ b/src/widgets/itemviews/qtreeview.cpp
@@ -335,6 +335,7 @@ void QTreeView::setHeader(QHeaderView *header)
this, SLOT(updateGeometries()));
setSortingEnabled(d->sortingEnabled);
+ d->updateGeometry();
}
/*!
@@ -1526,6 +1527,23 @@ void QTreeViewPrivate::calcLogicalIndices(QVector<int> *logicalIndices, QVector<
}
}
+/*!
+ \internal
+ Get sizeHint width for single index (providing existing hint and style option) and index in viewIndex i.
+*/
+int QTreeViewPrivate::widthHintForIndex(const QModelIndex &index, int hint, const QStyleOptionViewItem &option, int i) const
+{
+ QWidget *editor = editorForIndex(index).widget.data();
+ if (editor && persistent.contains(editor)) {
+ hint = qMax(hint, editor->sizeHint().width());
+ int min = editor->minimumSize().width();
+ int max = editor->maximumSize().width();
+ hint = qBound(min, hint, max);
+ }
+ int xhint = delegateForIndex(index)->sizeHint(option, index).width();
+ hint = qMax(hint, xhint + (index.column() == 0 ? indentationForItem(i) : 0));
+ return hint;
+}
/*!
Draws the row in the tree view that contains the model item \a index,
@@ -2400,16 +2418,11 @@ void QTreeView::scrollContentsBy(int dx, int dy)
dx = isRightToLeft() ? -dx : dx;
if (dx) {
+ int oldOffset = d->header->offset();
+ d->header->d_func()->setScrollOffset(horizontalScrollBar(), horizontalScrollMode());
if (horizontalScrollMode() == QAbstractItemView::ScrollPerItem) {
- int oldOffset = d->header->offset();
- if (horizontalScrollBar()->value() == horizontalScrollBar()->maximum())
- d->header->setOffsetToLastSection();
- else
- d->header->setOffsetToSectionPosition(horizontalScrollBar()->value());
int newOffset = d->header->offset();
dx = isRightToLeft() ? newOffset - oldOffset : oldOffset - newOffset;
- } else {
- d->header->setOffset(horizontalScrollBar()->value());
}
}
@@ -2552,7 +2565,7 @@ void QTreeView::columnCountChanged(int oldCount, int newCount)
/*!
Resizes the \a column given to the size of its contents.
- \sa columnWidth(), setColumnWidth()
+ \sa columnWidth(), setColumnWidth(), sizeHintForColumn(), QHeaderView::resizeContentsPrecision()
*/
void QTreeView::resizeColumnToContents(int column)
{
@@ -2619,6 +2632,35 @@ void QTreeView::selectAll()
}
/*!
+ \reimp
+*/
+QSize QTreeView::viewportSizeHint() const
+{
+ Q_D(const QTreeView);
+ d->executePostedLayout(); // Make sure that viewItems are up to date.
+
+ if (d->viewItems.size() == 0)
+ return QAbstractItemView::viewportSizeHint();
+
+ // Get rect for last item
+ const QRect deepestRect = visualRect(d->viewItems.last().index);
+
+ if (!deepestRect.isValid())
+ return QAbstractItemView::viewportSizeHint();
+
+ QSize result = QSize(d->header->length(), deepestRect.bottom() + 1);
+
+ // add size for header
+ result += QSize(0, d->header->isVisible() ? d->header->height() : 0);
+
+ // add size for scrollbars
+ result += QSize(verticalScrollBar()->isVisible() ? verticalScrollBar()->width() : 0,
+ horizontalScrollBar()->isVisible() ? horizontalScrollBar()->height() : 0);
+
+ return result;
+}
+
+/*!
\since 4.2
Expands all expandable items.
@@ -2740,7 +2782,6 @@ void QTreeView::updateGeometries()
QRect vg = d->viewport->geometry();
QRect geometryRect(vg.left(), vg.top() - hint.height(), vg.width(), hint.height());
d->header->setGeometry(geometryRect);
- //d->header->setOffset(horizontalScrollBar()->value()); // ### bug ???
QMetaObject::invokeMethod(d->header, "updateGeometries");
d->updateScrollBars();
d->geometryRecursionBlock = false;
@@ -2760,7 +2801,7 @@ void QTreeView::updateGeometries()
if a larger column width is required by either the view's header or
the item delegate, that width will be used instead.
- \sa QWidget::sizeHint, header()
+ \sa QWidget::sizeHint, header(), QHeaderView::resizeContentsPrecision()
*/
int QTreeView::sizeHintForColumn(int column) const
{
@@ -2773,28 +2814,58 @@ int QTreeView::sizeHintForColumn(int column) const
QStyleOptionViewItem option = d->viewOptions();
const QVector<QTreeViewItem> viewItems = d->viewItems;
- int start = 0;
- int end = viewItems.count();
- if(end > 1000) { //if we have too many item this function would be too slow.
- //we get a good approximation by only iterate over 1000 items.
- start = qMax(0, d->firstVisibleItem() - 100);
- end = qMin(end, start + 900);
- }
+ const int maximumProcessRows = d->header->resizeContentsPrecision(); // To avoid this to take forever.
- for (int i = start; i < end; ++i) {
+ int offset = 0;
+ int start = d->firstVisibleItem(&offset);
+ int end = d->lastVisibleItem(start, offset);
+
+ int rowsProcessed = 0;
+
+ for (int i = start; i <= end; ++i) {
if (viewItems.at(i).spanning)
continue; // we have no good size hint
QModelIndex index = viewItems.at(i).index;
index = index.sibling(index.row(), column);
- QWidget *editor = d->editorForIndex(index).widget.data();
- if (editor && d->persistent.contains(editor)) {
- w = qMax(w, editor->sizeHint().width());
- int min = editor->minimumSize().width();
- int max = editor->maximumSize().width();
- w = qBound(min, w, max);
+ w = d->widthHintForIndex(index, w, option, i);
+ ++rowsProcessed;
+ if (rowsProcessed == maximumProcessRows)
+ break;
+ }
+
+ --end;
+ int actualBottom = viewItems.size() - 1;
+
+ if (maximumProcessRows == 0)
+ rowsProcessed = 0; // skip the while loop
+
+ while (rowsProcessed != maximumProcessRows && (start > 0 || end < actualBottom)) {
+ int idx = -1;
+
+ if ((rowsProcessed % 2 && start > 0) || end == actualBottom) {
+ while (start > 0) {
+ --start;
+ if (viewItems.at(start).spanning)
+ continue;
+ idx = start;
+ break;
+ }
+ } else {
+ while (end < actualBottom) {
+ ++end;
+ if (viewItems.at(end).spanning)
+ continue;
+ idx = end;
+ break;
+ }
}
- int hint = d->delegateForIndex(index)->sizeHint(option, index).width();
- w = qMax(w, hint + (column == 0 ? d->indentationForItem(i) : 0));
+ if (idx < 0)
+ continue;
+
+ QModelIndex index = viewItems.at(idx).index;
+ index = index.sibling(index.row(), column);
+ w = d->widthHintForIndex(index, w, option, idx);
+ ++rowsProcessed;
}
return w;
}
@@ -3314,7 +3385,7 @@ int QTreeViewPrivate::coordinateForItem(int item) const
if (verticalScrollMode == QAbstractItemView::ScrollPerPixel) {
if (uniformRowHeights)
return (item * defaultItemHeight) - vbar->value();
- // ### optimize (spans or caching)
+ // ### optimize (maybe do like QHeaderView by letting items have startposition)
int y = 0;
for (int i = 0; i < viewItems.count(); ++i) {
if (i == item)
@@ -3481,7 +3552,7 @@ int QTreeViewPrivate::firstVisibleItem(int *offset) const
*offset = -(value % defaultItemHeight);
return value / defaultItemHeight;
}
- int y = 0; // ### optimize (use spans ?)
+ int y = 0; // ### (maybe do like QHeaderView by letting items have startposition)
for (int i = 0; i < viewItems.count(); ++i) {
y += itemHeight(i); // the height value is cached
if (y > value) {
@@ -3493,6 +3564,21 @@ int QTreeViewPrivate::firstVisibleItem(int *offset) const
return -1;
}
+int QTreeViewPrivate::lastVisibleItem(int firstVisual, int offset) const
+{
+ if (firstVisual < 0 || offset < 0)
+ firstVisual = firstVisibleItem(&offset);
+ int y = - offset;
+ int value = viewport->height();
+
+ for (int i = firstVisual; i < viewItems.count(); ++i) {
+ y += itemHeight(i); // the height value is cached
+ if (y > value)
+ return i;
+ }
+ return viewItems.size() - 1;
+}
+
int QTreeViewPrivate::columnAt(int x) const
{
return header->logicalIndexAt(x);
@@ -3535,7 +3621,7 @@ void QTreeViewPrivate::updateScrollBars()
int contentsHeight = 0;
if (uniformRowHeights) {
contentsHeight = defaultItemHeight * viewItems.count();
- } else { // ### optimize (spans or caching)
+ } else { // ### (maybe do like QHeaderView by letting items have startposition)
for (int i = 0; i < viewItems.count(); ++i)
contentsHeight += itemHeight(i);
}
diff --git a/src/widgets/itemviews/qtreeview.h b/src/widgets/itemviews/qtreeview.h
index 73f11f1a48..fae814c6f6 100644
--- a/src/widgets/itemviews/qtreeview.h
+++ b/src/widgets/itemviews/qtreeview.h
@@ -144,6 +144,8 @@ public:
void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles = QVector<int>());
void selectAll();
+ QSize viewportSizeHint() const;
+
Q_SIGNALS:
void expanded(const QModelIndex &index);
void collapsed(const QModelIndex &index);
diff --git a/src/widgets/itemviews/qtreeview_p.h b/src/widgets/itemviews/qtreeview_p.h
index 90e83cb58c..8be9c568d3 100644
--- a/src/widgets/itemviews/qtreeview_p.h
+++ b/src/widgets/itemviews/qtreeview_p.h
@@ -148,6 +148,7 @@ public:
#endif
int firstVisibleItem(int *offset = 0) const;
+ int lastVisibleItem(int firstVisual = -1, int offset = -1) const;
int columnAt(int x) const;
bool hasVisibleChildren( const QModelIndex& parent) const;
@@ -171,7 +172,7 @@ public:
// logicalIndices: vector of currently visibly logical indices
// itemPositions: vector of view item positions (beginning/middle/end/onlyone)
void calcLogicalIndices(QVector<int> *logicalIndices, QVector<QStyleOptionViewItem::ViewItemPosition> *itemPositions, int left, int right) const;
-
+ int widthHintForIndex(const QModelIndex &index, int hint, const QStyleOptionViewItem &option, int i) const;
QHeaderView *header;
int indent;
diff --git a/src/widgets/itemviews/qtreewidget.cpp b/src/widgets/itemviews/qtreewidget.cpp
index f72abd20ab..2de7830c6a 100644
--- a/src/widgets/itemviews/qtreewidget.cpp
+++ b/src/widgets/itemviews/qtreewidget.cpp
@@ -623,7 +623,13 @@ void QTreeModel::ensureSorted(int column, Qt::SortOrder order,
for (int i = 0; i < count; ++i) {
int oldRow = sorting.at(i).second;
+
+ int tmpitepos = lit - lst.begin();
QTreeWidgetItem *item = lst.takeAt(oldRow);
+ if (tmpitepos > lst.size())
+ --tmpitepos;
+ lit = lst.begin() + tmpitepos;
+
lit = sortedInsertionIterator(lit, lst.end(), order, item);
int newRow = qMax(lit - lst.begin(), 0);
diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp
index 777342d7ae..27a152b706 100644
--- a/src/widgets/kernel/qapplication.cpp
+++ b/src/widgets/kernel/qapplication.cpp
@@ -1852,8 +1852,11 @@ bool QApplication::event(QEvent *e)
if (showToolTip) {
QHelpEvent e(QEvent::ToolTip, d->toolTipPos, d->toolTipGlobalPos);
QApplication::sendEvent(d->toolTipWidget, &e);
- if (e.isAccepted())
- d->toolTipFallAsleep.start(2000, this);
+ if (e.isAccepted()) {
+ QStyle *s = d->toolTipWidget->style();
+ int sleepDelay = s->styleHint(QStyle::SH_ToolTip_FallAsleepDelay, 0, d->toolTipWidget, 0);
+ d->toolTipFallAsleep.start(sleepDelay, this);
+ }
}
}
} else if (te->timerId() == d->toolTipFallAsleep.timerId()) {
@@ -2942,12 +2945,8 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
QPoint relpos = mouse->pos();
if (e->spontaneous()) {
-
- if (e->type() == QEvent::MouseButtonPress) {
- QApplicationPrivate::giveFocusAccordingToFocusPolicy(w,
- Qt::ClickFocus,
- Qt::MouseFocusReason);
- }
+ if (e->type() != QEvent::MouseMove)
+ QApplicationPrivate::giveFocusAccordingToFocusPolicy(w, e, relpos);
// ### Qt 5 These dynamic tool tips should be an OPT-IN feature. Some platforms
// like Mac OS X (probably others too), can optimize their views by not
@@ -2960,7 +2959,9 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
d->toolTipWidget = w;
d->toolTipPos = relpos;
d->toolTipGlobalPos = mouse->globalPos();
- d->toolTipWakeUp.start(d->toolTipFallAsleep.isActive()?20:700, this);
+ QStyle *s = d->toolTipWidget->style();
+ int wakeDelay = s->styleHint(QStyle::SH_ToolTip_WakeUpDelay, 0, d->toolTipWidget, 0);
+ d->toolTipWakeUp.start(d->toolTipFallAsleep.isActive() ? 20 : wakeDelay, this);
}
}
@@ -3035,11 +3036,8 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
QPoint relpos = wheel->pos();
bool eventAccepted = wheel->isAccepted();
- if (e->spontaneous()) {
- QApplicationPrivate::giveFocusAccordingToFocusPolicy(w,
- Qt::WheelFocus,
- Qt::MouseFocusReason);
- }
+ if (e->spontaneous())
+ QApplicationPrivate::giveFocusAccordingToFocusPolicy(w, e, relpos);
while (w) {
QWheelEvent we(relpos, wheel->globalPos(), wheel->pixelDelta(), wheel->angleDelta(), wheel->delta(), wheel->orientation(), wheel->buttons(),
@@ -3227,6 +3225,11 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
QTouchEvent *touchEvent = static_cast<QTouchEvent *>(e);
const bool acceptTouchEvents = widget->testAttribute(Qt::WA_AcceptTouchEvents);
+ if (e->type() != QEvent::TouchUpdate && acceptTouchEvents && e->spontaneous()) {
+ const QPoint localPos = touchEvent->touchPoints()[0].pos().toPoint();
+ QApplicationPrivate::giveFocusAccordingToFocusPolicy(widget, e, localPos);
+ }
+
touchEvent->setTarget(widget);
touchEvent->setAccepted(acceptTouchEvents);
@@ -3244,16 +3247,16 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
QWidget *widget = static_cast<QWidget *>(receiver);
QTouchEvent *touchEvent = static_cast<QTouchEvent *>(e);
bool eventAccepted = touchEvent->isAccepted();
- if (widget->testAttribute(Qt::WA_AcceptTouchEvents) && e->spontaneous()) {
- // give the widget focus if the focus policy allows it
- QApplicationPrivate::giveFocusAccordingToFocusPolicy(widget,
- Qt::ClickFocus,
- Qt::MouseFocusReason);
+ bool acceptTouchEvents = widget->testAttribute(Qt::WA_AcceptTouchEvents);
+
+ if (acceptTouchEvents && e->spontaneous()) {
+ const QPoint localPos = touchEvent->touchPoints()[0].pos().toPoint();
+ QApplicationPrivate::giveFocusAccordingToFocusPolicy(widget, e, localPos);
}
while (widget) {
// first, try to deliver the touch event
- bool acceptTouchEvents = widget->testAttribute(Qt::WA_AcceptTouchEvents);
+ acceptTouchEvents = widget->testAttribute(Qt::WA_AcceptTouchEvents);
touchEvent->setTarget(widget);
touchEvent->setAccepted(acceptTouchEvents);
QPointer<QWidget> p = widget;
@@ -3718,20 +3721,40 @@ bool qt_sendSpontaneousEvent(QObject *receiver, QEvent *event)
return QGuiApplication::sendSpontaneousEvent(receiver, event);
}
-
-void QApplicationPrivate::giveFocusAccordingToFocusPolicy(QWidget *widget,
- Qt::FocusPolicy focusPolicy,
- Qt::FocusReason focusReason)
+void QApplicationPrivate::giveFocusAccordingToFocusPolicy(QWidget *widget, QEvent *event, QPoint localPos)
{
+ const bool setFocusOnRelease = QGuiApplication::styleHints()->setFocusOnTouchRelease();
+ Qt::FocusPolicy focusPolicy = Qt::ClickFocus;
+
+ switch (event->type()) {
+ case QEvent::MouseButtonPress:
+ case QEvent::TouchBegin:
+ if (setFocusOnRelease)
+ return;
+ break;
+ case QEvent::MouseButtonRelease:
+ case QEvent::TouchEnd:
+ if (!setFocusOnRelease)
+ return;
+ break;
+ case QEvent::Wheel:
+ focusPolicy = Qt::WheelFocus;
+ break;
+ default:
+ return;
+ }
+
QWidget *focusWidget = widget;
while (focusWidget) {
if (focusWidget->isEnabled()
+ && focusWidget->rect().contains(localPos)
&& QApplicationPrivate::shouldSetFocus(focusWidget, focusPolicy)) {
- focusWidget->setFocus(focusReason);
+ focusWidget->setFocus(Qt::MouseFocusReason);
break;
}
if (focusWidget->isWindow())
break;
+ localPos += focusWidget->pos();
focusWidget = focusWidget->parentWidget();
}
}
diff --git a/src/widgets/kernel/qapplication_p.h b/src/widgets/kernel/qapplication_p.h
index 87cf259ba5..29c6902c78 100644
--- a/src/widgets/kernel/qapplication_p.h
+++ b/src/widgets/kernel/qapplication_p.h
@@ -294,9 +294,7 @@ public:
private:
static QApplicationPrivate *self;
- static void giveFocusAccordingToFocusPolicy(QWidget *w,
- Qt::FocusPolicy focusPolicy,
- Qt::FocusReason focusReason);
+ static void giveFocusAccordingToFocusPolicy(QWidget *w, QEvent *event, QPoint localPos);
static bool shouldSetFocus(QWidget *w, Qt::FocusPolicy policy);
diff --git a/src/widgets/kernel/qapplication_qpa.cpp b/src/widgets/kernel/qapplication_qpa.cpp
index 852b6b9697..0fc065e74b 100644
--- a/src/widgets/kernel/qapplication_qpa.cpp
+++ b/src/widgets/kernel/qapplication_qpa.cpp
@@ -198,7 +198,6 @@ void QApplicationPrivate::closePopup(QWidget *popup)
// mouse release event or inside
qt_replay_popup_mouse_event = false;
} else { // mouse press event
- QGuiApplicationPrivate::mousePressTime -= 10000; // avoid double click
qt_replay_popup_mouse_event = true;
}
diff --git a/src/widgets/kernel/qlayout.cpp b/src/widgets/kernel/qlayout.cpp
index a65c34adf5..8541dd984d 100644
--- a/src/widgets/kernel/qlayout.cpp
+++ b/src/widgets/kernel/qlayout.cpp
@@ -1443,7 +1443,7 @@ QDataStream &operator<<(QDataStream &stream, const QSizePolicy &policy)
policy.bits.hfw << 8 | // [8]
policy.bits.ctype << 9 | // [9, 13]
policy.bits.wfh << 14 | // [14]
- //policy.bits.padding << 15 | // [15]
+ policy.bits.retainSizeWhenHidden << 15 | // [15]
policy.bits.verStretch << 16 | // [16, 23]
policy.bits.horStretch << 24); // [24, 31]
return stream << data;
@@ -1468,7 +1468,7 @@ QDataStream &operator>>(QDataStream &stream, QSizePolicy &policy)
policy.bits.hfw = VALUE_OF_BITS(data, 8, 1);
policy.bits.ctype = VALUE_OF_BITS(data, 9, 5);
policy.bits.wfh = VALUE_OF_BITS(data, 14, 1);
- policy.bits.padding = 0;
+ policy.bits.retainSizeWhenHidden = VALUE_OF_BITS(data, 15, 1);
policy.bits.verStretch = VALUE_OF_BITS(data, 16, 8);
policy.bits.horStretch = VALUE_OF_BITS(data, 24, 8);
return stream;
diff --git a/src/widgets/kernel/qlayoutitem.cpp b/src/widgets/kernel/qlayoutitem.cpp
index 223bcf1d9b..a99ea77ce2 100644
--- a/src/widgets/kernel/qlayoutitem.cpp
+++ b/src/widgets/kernel/qlayoutitem.cpp
@@ -682,7 +682,7 @@ bool QSpacerItem::isEmpty() const
*/
bool QWidgetItem::isEmpty() const
{
- return wid->isHidden() || wid->isWindow();
+ return (wid->isHidden() && !wid->sizePolicy().retainSizeWhenHidden()) || wid->isWindow();
}
/*!
diff --git a/src/widgets/kernel/qsizepolicy.h b/src/widgets/kernel/qsizepolicy.h
index 2fe85cbe0c..9c6d67410a 100644
--- a/src/widgets/kernel/qsizepolicy.h
+++ b/src/widgets/kernel/qsizepolicy.h
@@ -131,6 +131,9 @@ public:
void setHorizontalStretch(int stretchFactor) { bits.horStretch = static_cast<quint32>(qBound(0, stretchFactor, 255)); }
void setVerticalStretch(int stretchFactor) { bits.verStretch = static_cast<quint32>(qBound(0, stretchFactor, 255)); }
+ bool retainSizeWhenHidden() const { return bits.retainSizeWhenHidden; }
+ void setRetainSizeWhenHidden(bool retainSize) { bits.retainSizeWhenHidden = retainSize; }
+
void transpose();
@@ -150,7 +153,7 @@ private:
quint32 ctype : 5;
quint32 hfw : 1;
quint32 wfh : 1;
- quint32 padding : 1; // feel free to use
+ quint32 retainSizeWhenHidden : 1;
} bits;
quint32 data;
};
diff --git a/src/widgets/kernel/qsizepolicy.qdoc b/src/widgets/kernel/qsizepolicy.qdoc
index 6af694d999..2c088113e1 100644
--- a/src/widgets/kernel/qsizepolicy.qdoc
+++ b/src/widgets/kernel/qsizepolicy.qdoc
@@ -341,6 +341,23 @@
*/
/*!
+ \fn void QSizePolicy::retainSizeWhenHidden() const
+
+ Returns if the layout should retain the widgets size when it is hidden. This is by default false.
+
+ \sa setRetainSizeWhenHidden()
+*/
+
+/*!
+ \fn void QSizePolicy::setRetainSizeWhenHidden(bool retainSize)
+
+ Set if a layout should retain the widgets size when it is hidden.
+ If \a retainSize is true the layout will not be changed by hiding the widget.
+
+ \sa retainSizeWhenHidden()
+*/
+
+/*!
\enum QSizePolicy::ControlType
\since 4.3
diff --git a/src/widgets/kernel/qtooltip.cpp b/src/widgets/kernel/qtooltip.cpp
index 864ed6a555..8399f94976 100644
--- a/src/widgets/kernel/qtooltip.cpp
+++ b/src/widgets/kernel/qtooltip.cpp
@@ -120,7 +120,7 @@ class QTipLabel : public QLabel
{
Q_OBJECT
public:
- QTipLabel(const QString &text, QWidget *w);
+ QTipLabel(const QString &text, QWidget *w, int msecDisplayTime);
~QTipLabel();
static QTipLabel *instance;
@@ -130,11 +130,11 @@ public:
bool fadingOut;
- void reuseTip(const QString &text);
+ void reuseTip(const QString &text, int msecDisplayTime);
void hideTip();
void hideTipImmediately();
void setTipRect(QWidget *w, const QRect &r);
- void restartExpireTimer();
+ void restartExpireTimer(int msecDisplayTime);
bool tipChanged(const QPoint &pos, const QString &text, QObject *o);
void placeTip(const QPoint &pos, QWidget *w);
@@ -166,7 +166,7 @@ private:
QTipLabel *QTipLabel::instance = 0;
-QTipLabel::QTipLabel(const QString &text, QWidget *w)
+QTipLabel::QTipLabel(const QString &text, QWidget *w, int msecDisplayTime)
#ifndef QT_NO_STYLE_STYLESHEET
: QLabel(w, Qt::ToolTip | Qt::BypassGraphicsProxyWidget), styleSheetParent(0), widget(0)
#else
@@ -187,17 +187,19 @@ QTipLabel::QTipLabel(const QString &text, QWidget *w)
setWindowOpacity(style()->styleHint(QStyle::SH_ToolTipLabel_Opacity, 0, this) / 255.0);
setMouseTracking(true);
fadingOut = false;
- reuseTip(text);
+ reuseTip(text, msecDisplayTime);
}
-void QTipLabel::restartExpireTimer()
+void QTipLabel::restartExpireTimer(int msecDisplayTime)
{
int time = 10000 + 40 * qMax(0, text().length()-100);
+ if (msecDisplayTime > 0)
+ time = msecDisplayTime;
expireTimer.start(time, this);
hideTimer.stop();
}
-void QTipLabel::reuseTip(const QString &text)
+void QTipLabel::reuseTip(const QString &text, int msecDisplayTime)
{
#ifndef QT_NO_STYLE_STYLESHEET
if (styleSheetParent){
@@ -215,7 +217,7 @@ void QTipLabel::reuseTip(const QString &text)
if (fm.descent() == 2 && fm.ascent() >= 11)
++extra.rheight();
resize(sizeHint() + extra);
- restartExpireTimer();
+ restartExpireTimer(msecDisplayTime);
}
void QTipLabel::paintEvent(QPaintEvent *ev)
@@ -440,6 +442,18 @@ bool QTipLabel::tipChanged(const QPoint &pos, const QString &text, QObject *o)
void QToolTip::showText(const QPoint &pos, const QString &text, QWidget *w, const QRect &rect)
{
+ showText(pos, text, w, rect, -1);
+}
+
+/*!
+ \since 5.2
+ \overload
+ This is similar to QToolTip::showText(\a pos, \a text, \a w, \a rect) but with an extra parameter \a msecDisplayTime
+ that specifies how long the tool tip will be displayed, in milliseconds.
+*/
+
+void QToolTip::showText(const QPoint &pos, const QString &text, QWidget *w, const QRect &rect, int msecDisplayTime)
+{
if (QTipLabel::instance && QTipLabel::instance->isVisible()){ // a tip does already exist
if (text.isEmpty()){ // empty text means hide current tip
QTipLabel::instance->hideTip();
@@ -452,7 +466,7 @@ void QToolTip::showText(const QPoint &pos, const QString &text, QWidget *w, cons
if (w)
localPos = w->mapFromGlobal(pos);
if (QTipLabel::instance->tipChanged(localPos, text, w)){
- QTipLabel::instance->reuseTip(text);
+ QTipLabel::instance->reuseTip(text, msecDisplayTime);
QTipLabel::instance->setTipRect(w, rect);
QTipLabel::instance->placeTip(pos, w);
}
@@ -462,11 +476,11 @@ void QToolTip::showText(const QPoint &pos, const QString &text, QWidget *w, cons
if (!text.isEmpty()){ // no tip can be reused, create new tip:
#ifndef Q_WS_WIN
- new QTipLabel(text, w); // sets QTipLabel::instance to itself
+ new QTipLabel(text, w, msecDisplayTime); // sets QTipLabel::instance to itself
#else
// On windows, we can't use the widget as parent otherwise the window will be
// raised when the tooltip will be shown
- new QTipLabel(text, QApplication::desktop()->screen(QTipLabel::getTipScreen(pos, w)));
+ new QTipLabel(text, QApplication::desktop()->screen(QTipLabel::getTipScreen(pos, w)), msecDisplayTime);
#endif
QTipLabel::instance->setTipRect(w, rect);
QTipLabel::instance->placeTip(pos, w);
diff --git a/src/widgets/kernel/qtooltip.h b/src/widgets/kernel/qtooltip.h
index 25b138b855..ccde405342 100644
--- a/src/widgets/kernel/qtooltip.h
+++ b/src/widgets/kernel/qtooltip.h
@@ -53,8 +53,10 @@ class Q_WIDGETS_EXPORT QToolTip
{
QToolTip() Q_DECL_EQ_DELETE;
public:
+ // ### Qt 6 - merge the three showText functions below
static void showText(const QPoint &pos, const QString &text, QWidget *w = 0);
static void showText(const QPoint &pos, const QString &text, QWidget *w, const QRect &rect);
+ static void showText(const QPoint &pos, const QString &text, QWidget *w, const QRect &rect, int msecShowTime);
static inline void hideText() { showText(QPoint(), QString()); }
static bool isVisible();
diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp
index 7cb0979c06..869362654c 100644
--- a/src/widgets/kernel/qwidget.cpp
+++ b/src/widgets/kernel/qwidget.cpp
@@ -245,6 +245,9 @@ QWidgetPrivate::QWidgetPrivate(int version)
#if !defined(QT_NO_IM)
, imHints(Qt::ImhNone)
#endif
+#ifndef QT_NO_TOOLTIP
+ , toolTipDuration(-1)
+#endif
, inheritedFontResolveMask(0)
, inheritedPaletteResolveMask(0)
, leftmargin(0)
@@ -261,6 +264,7 @@ QWidgetPrivate::QWidgetPrivate(int version)
, bg_role(QPalette::NoRole)
, dirtyOpaqueChildren(1)
, isOpaque(0)
+ , retainSizeWhenHiddenChanged(0)
, inDirtyList(0)
, isScrolled(0)
, isMoved(0)
@@ -8207,7 +8211,7 @@ bool QWidget::event(QEvent *event)
#ifndef QT_NO_TOOLTIP
case QEvent::ToolTip:
if (!d->toolTip.isEmpty())
- QToolTip::showText(static_cast<QHelpEvent*>(event)->globalPos(), d->toolTip, this);
+ QToolTip::showText(static_cast<QHelpEvent*>(event)->globalPos(), d->toolTip, this, QRect(), d->toolTipDuration);
else
event->ignore();
break;
@@ -9251,6 +9255,10 @@ void QWidget::setSizePolicy(QSizePolicy policy)
setAttribute(Qt::WA_WState_OwnSizePolicy);
if (policy == d->size_policy)
return;
+
+ if (d->size_policy.retainSizeWhenHidden() != policy.retainSizeWhenHidden())
+ d->retainSizeWhenHiddenChanged = 1;
+
d->size_policy = policy;
#ifndef QT_NO_GRAPHICSVIEW
@@ -9261,6 +9269,7 @@ void QWidget::setSizePolicy(QSizePolicy policy)
#endif
updateGeometry();
+ d->retainSizeWhenHiddenChanged = 0;
if (isWindow() && d->maybeTopData())
d->topData()->sizeAdjusted = false;
@@ -9389,7 +9398,9 @@ void QWidgetPrivate::updateGeometry_helper(bool forceUpdate)
widgetItem->invalidateSizeCache();
QWidget *parent;
if (forceUpdate || !extra || extra->minw != extra->maxw || extra->minh != extra->maxh) {
- if (!q->isWindow() && !q->isHidden() && (parent = q->parentWidget())) {
+ const int isHidden = q->isHidden() && !size_policy.retainSizeWhenHidden() && !retainSizeWhenHiddenChanged;
+
+ if (!q->isWindow() && !isHidden && (parent = q->parentWidget())) {
if (parent->d_func()->layout)
parent->d_func()->layout->invalidate();
else if (parent->isVisible())
@@ -10426,6 +10437,30 @@ QString QWidget::toolTip() const
Q_D(const QWidget);
return d->toolTip;
}
+
+/*!
+ \property QWidget::toolTipDuration
+ \brief the widget's tooltip duration
+ \since 5.2
+
+ Specifies how long time the tooltip will be displayed, in milliseconds.
+ If the value is -1 (default) the duration is calculated depending on the length of the tooltip.
+
+ \sa toolTip
+*/
+
+void QWidget::setToolTipDuration(int msec)
+{
+ Q_D(QWidget);
+ d->toolTipDuration = msec;
+}
+
+int QWidget::toolTipDuration() const
+{
+ Q_D(const QWidget);
+ return d->toolTipDuration;
+}
+
#endif // QT_NO_TOOLTIP
diff --git a/src/widgets/kernel/qwidget.h b/src/widgets/kernel/qwidget.h
index f90f2ee5f5..f579dbb9cd 100644
--- a/src/widgets/kernel/qwidget.h
+++ b/src/widgets/kernel/qwidget.h
@@ -178,6 +178,7 @@ class Q_WIDGETS_EXPORT QWidget : public QObject, public QPaintDevice
Q_PROPERTY(bool windowModified READ isWindowModified WRITE setWindowModified DESIGNABLE isWindow)
#ifndef QT_NO_TOOLTIP
Q_PROPERTY(QString toolTip READ toolTip WRITE setToolTip)
+ Q_PROPERTY(int toolTipDuration READ toolTipDuration WRITE setToolTipDuration)
#endif
#ifndef QT_NO_STATUSTIP
Q_PROPERTY(QString statusTip READ statusTip WRITE setStatusTip)
@@ -376,6 +377,8 @@ public:
#ifndef QT_NO_TOOLTIP
void setToolTip(const QString &);
QString toolTip() const;
+ void setToolTipDuration(int msec);
+ int toolTipDuration() const;
#endif
#ifndef QT_NO_STATUSTIP
void setStatusTip(const QString &);
diff --git a/src/widgets/kernel/qwidget_p.h b/src/widgets/kernel/qwidget_p.h
index 50f32af8b0..0580f72e11 100644
--- a/src/widgets/kernel/qwidget_p.h
+++ b/src/widgets/kernel/qwidget_p.h
@@ -644,6 +644,7 @@ public:
QRegion dirty;
#ifndef QT_NO_TOOLTIP
QString toolTip;
+ int toolTipDuration;
#endif
#ifndef QT_NO_STATUSTIP
QString statusTip;
@@ -687,6 +688,7 @@ public:
QPalette::ColorRole bg_role : 8;
uint dirtyOpaqueChildren : 1;
uint isOpaque : 1;
+ uint retainSizeWhenHiddenChanged : 1;
uint inDirtyList : 1;
uint isScrolled : 1;
uint isMoved : 1;
diff --git a/src/widgets/styles/images/cleartext-16.png b/src/widgets/styles/images/cleartext-16.png
new file mode 100644
index 0000000000..74133bafff
--- /dev/null
+++ b/src/widgets/styles/images/cleartext-16.png
Binary files differ
diff --git a/src/widgets/styles/qcommonstyle.cpp b/src/widgets/styles/qcommonstyle.cpp
index 936eb76dad..262275611c 100644
--- a/src/widgets/styles/qcommonstyle.cpp
+++ b/src/widgets/styles/qcommonstyle.cpp
@@ -5097,11 +5097,7 @@ int QCommonStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget
ret = theme->themeHint(QPlatformTheme::ToolButtonStyle).toInt();
break;
case SH_RequestSoftwareInputPanel:
-#ifdef Q_OS_ANDROID
ret = RSIP_OnMouseClick;
-#else
- ret = RSIP_OnMouseClickAndAlreadyFocused;
-#endif
break;
case SH_ScrollBar_Transient:
ret = false;
@@ -5109,6 +5105,14 @@ int QCommonStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget
case SH_Menu_SupportsSections:
ret = false;
break;
+#ifndef QT_NO_TOOLTIP
+ case SH_ToolTip_WakeUpDelay:
+ ret = 700;
+ break;
+ case SH_ToolTip_FallAsleepDelay:
+ ret = 2000;
+ break;
+#endif
default:
ret = 0;
break;
@@ -5289,6 +5293,13 @@ QPixmap QCommonStyle::standardPixmap(StandardPixmap sp, const QStyleOption *opti
}
}
break;
+ case SP_LineEditClearButton: {
+ QString themeName = rtl ? QStringLiteral("edit-clear-locationbar-ltr") : QStringLiteral("edit-clear-locationbar-rtl");
+ if (!QIcon::hasThemeIcon(themeName))
+ themeName = QStringLiteral("edit-clear");
+ pixmap = QIcon::fromTheme(themeName).pixmap(16);
+ }
+ break;
default:
break;
}
@@ -5417,6 +5428,8 @@ QPixmap QCommonStyle::standardPixmap(StandardPixmap sp, const QStyleOption *opti
return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/media-volume-16.png"));
case SP_MediaVolumeMuted:
return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/media-volume-muted-16.png"));
+ case SP_LineEditClearButton:
+ return QPixmap(QStringLiteral(":/qt-project.org/styles/commonstyle/images/cleartext-16.png"));
#endif // QT_NO_IMAGEFORMAT_PNG
default:
break;
diff --git a/src/widgets/styles/qgtkstyle_p.cpp b/src/widgets/styles/qgtkstyle_p.cpp
index 769d822108..c53a21e59a 100644
--- a/src/widgets/styles/qgtkstyle_p.cpp
+++ b/src/widgets/styles/qgtkstyle_p.cpp
@@ -756,8 +756,9 @@ void QGtkStylePrivate::removeWidgetFromMap(const QHashableLatin1Literal &path)
WidgetMap *map = gtkWidgetMap();
WidgetMap::iterator it = map->find(path);
if (it != map->end()) {
- free(const_cast<char *>(it.key().data()));
+ char* keyData = const_cast<char *>(it.key().data());
map->erase(it);
+ free(keyData);
}
}
diff --git a/src/widgets/styles/qstyle.cpp b/src/widgets/styles/qstyle.cpp
index dccc9ff3ce..826a05db51 100644
--- a/src/widgets/styles/qstyle.cpp
+++ b/src/widgets/styles/qstyle.cpp
@@ -1894,6 +1894,12 @@ void QStyle::drawItemPixmap(QPainter *painter, const QRect &rect, int alignment,
\value SH_Menu_SupportsSections Determines if the style displays sections in menus or treat them as
plain separators. Sections are separators with a text and icon hint.
+ \value SH_ToolTip_WakeUpDelay Determines the delay before a tooltip is shown, in milliseconds.
+
+ \value SH_ToolTip_FallAsleepDelay Determines the delay (in milliseconds) before a new wake time is needed when
+ a tooltip is shown (notice: shown, not hidden). When a new wake isn't needed, a user-requested tooltip
+ will be shown nearly instantly.
+
\sa styleHint()
*/
@@ -1986,6 +1992,7 @@ void QStyle::drawItemPixmap(QPainter *painter, const QRect &rect, int alignment,
\value SP_MediaSeekBackward Icon indicating that media should seek backward.
\value SP_MediaVolume Icon indicating a volume control.
\value SP_MediaVolumeMuted Icon indicating a muted volume control.
+ \value SP_LineEditClearButton Icon for a standard clear button in a QLineEdit. This enum value was added in Qt 5.2.
\value SP_CustomBase Base value for custom standard pixmaps;
custom values must be greater than this value.
diff --git a/src/widgets/styles/qstyle.h b/src/widgets/styles/qstyle.h
index beafad326e..d4e1be4787 100644
--- a/src/widgets/styles/qstyle.h
+++ b/src/widgets/styles/qstyle.h
@@ -698,6 +698,8 @@ public:
SH_RequestSoftwareInputPanel,
SH_ScrollBar_Transient,
SH_Menu_SupportsSections,
+ SH_ToolTip_WakeUpDelay,
+ SH_ToolTip_FallAsleepDelay,
// Add new style hint values here
SH_CustomBase = 0xf0000000
@@ -777,6 +779,7 @@ public:
SP_MediaSeekBackward,
SP_MediaVolume,
SP_MediaVolumeMuted,
+ SP_LineEditClearButton,
// do not add any values below/greater than this
SP_CustomBase = 0xf0000000
};
diff --git a/src/widgets/styles/qstyle.qrc b/src/widgets/styles/qstyle.qrc
index 28ad484032..c063ec5036 100644
--- a/src/widgets/styles/qstyle.qrc
+++ b/src/widgets/styles/qstyle.qrc
@@ -1,5 +1,6 @@
<RCC>
<qresource prefix="/qt-project.org/styles/commonstyle">
+ <file>images/cleartext-16.png</file>
<file>images/filelink-16.png</file>
<file>images/filelink-32.png</file>
<file>images/filelink-128.png</file>
diff --git a/src/widgets/widgets/qabstractscrollarea.cpp b/src/widgets/widgets/qabstractscrollarea.cpp
index 900e95f4da..e7827055fb 100644
--- a/src/widgets/widgets/qabstractscrollarea.cpp
+++ b/src/widgets/widgets/qabstractscrollarea.cpp
@@ -167,6 +167,7 @@ QT_BEGIN_NAMESPACE
QAbstractScrollAreaPrivate::QAbstractScrollAreaPrivate()
:hbar(0), vbar(0), vbarpolicy(Qt::ScrollBarAsNeeded), hbarpolicy(Qt::ScrollBarAsNeeded),
+ shownOnce(false), sizeAdjustPolicy(QAbstractScrollArea::AdjustIgnored),
viewport(0), cornerWidget(0), left(0), top(0), right(0), bottom(0),
xoffset(0), yoffset(0), viewportFilter(0)
#ifdef Q_WS_WIN
@@ -527,6 +528,19 @@ void QAbstractScrollAreaPrivate::layoutChildren()
}
/*!
+ \enum QAbstractScrollArea::SizeAdjustPolicy
+ \since 5.2
+
+ This enum specifies how the size hint of the QAbstractScrollArea should
+ adjust when the size of the viewport changes.
+
+ \value AdjustIgnored The scroll area will behave like before - and not do any adjust.
+ \value AdjustToContents The scroll area will always adjust to the viewport
+ \value AdjustToContentsOnFirstShow The scroll area will adjust to its viewport the first time it is shown.
+*/
+
+
+/*!
\internal
Creates a new QAbstractScrollAreaPrivate, \a dd with the given \a parent.
@@ -983,6 +997,13 @@ bool QAbstractScrollArea::event(QEvent *e)
case QEvent::Resize:
d->layoutChildren();
break;
+ case QEvent::Show:
+ if (!d->shownOnce && d->sizeAdjustPolicy == QAbstractScrollArea::AdjustToContentsOnFirstShow) {
+ d->sizeHint = QSize();
+ updateGeometry();
+ }
+ d->shownOnce = true;
+ return QFrame::event(e);
case QEvent::Paint: {
QStyleOption option;
option.initFrom(this);
@@ -1533,17 +1554,70 @@ QSize QAbstractScrollArea::minimumSizeHint() const
}
/*!
+ Returns the sizeHint property of the scroll area. The size is determined by using
+ viewportSizeHint() plus some extra space for scroll bars, if needed.
\reimp
*/
QSize QAbstractScrollArea::sizeHint() const
{
- return QSize(256, 192);
-#if 0
Q_D(const QAbstractScrollArea);
- int h = qMax(10, fontMetrics().height());
- int f = 2 * d->frameWidth;
- return QSize((6 * h) + f, (4 * h) + f);
-#endif
+ if (d->sizeAdjustPolicy == QAbstractScrollArea::AdjustIgnored)
+ return QSize(256, 192);
+
+ if (!d->sizeHint.isValid() || d->sizeAdjustPolicy == QAbstractScrollArea::AdjustToContents) {
+ const int f = 2 * d->frameWidth;
+ const QSize frame( f, f );
+ const QSize scrollbars(d->vbarpolicy == Qt::ScrollBarAlwaysOn ? d->vbar->sizeHint().width() : 0,
+ d->hbarpolicy == Qt::ScrollBarAlwaysOn ? d->hbar->sizeHint().height() : 0);
+ d->sizeHint = frame + scrollbars + viewportSizeHint();
+ }
+ return d->sizeHint;
+}
+
+/*!
+ \since 5.2
+ Returns the recommended size for the viewport.
+ The default implementation returns viewport()->sizeHint().
+ Note that the size is just the viewport's size, without any scroll bars visible.
+ */
+QSize QAbstractScrollArea::viewportSizeHint() const
+{
+ Q_D(const QAbstractScrollArea);
+ if (d->viewport) {
+ const QSize sh = d->viewport->sizeHint();
+ if (sh.isValid()) {
+ return sh;
+ }
+ }
+ const int h = qMax(10, fontMetrics().height());
+ return QSize(6 * h, 4 * h);
+}
+
+/*!
+ \since 5.2
+ \property QAbstractScrollArea::sizeAdjustPolicy
+ This property holds the policy describing how the size of the scroll area changes when the
+ size of the viewport changes.
+
+ The default policy is QAbstractScrollArea::AdjustIgnored.
+ Changing this property might actually resize the scrollarea.
+*/
+
+QAbstractScrollArea::SizeAdjustPolicy QAbstractScrollArea::sizeAdjustPolicy() const
+{
+ Q_D(const QAbstractScrollArea);
+ return d->sizeAdjustPolicy;
+}
+
+void QAbstractScrollArea::setSizeAdjustPolicy(SizeAdjustPolicy policy)
+{
+ Q_D(QAbstractScrollArea);
+ if (d->sizeAdjustPolicy == policy)
+ return;
+
+ d->sizeAdjustPolicy = policy;
+ d->sizeHint = QSize();
+ updateGeometry();
}
/*!
@@ -1559,16 +1633,6 @@ void QAbstractScrollArea::setupViewport(QWidget *viewport)
Q_UNUSED(viewport);
}
-/*!
- \internal
-
- This method is reserved for future use.
-*/
-QSize QAbstractScrollArea::viewportSizeHint() const
-{
- return QSize();
-}
-
QT_END_NAMESPACE
#include "moc_qabstractscrollarea.cpp"
diff --git a/src/widgets/widgets/qabstractscrollarea.h b/src/widgets/widgets/qabstractscrollarea.h
index ccf16b5e5c..fb9562db1b 100644
--- a/src/widgets/widgets/qabstractscrollarea.h
+++ b/src/widgets/widgets/qabstractscrollarea.h
@@ -56,13 +56,22 @@ class QAbstractScrollAreaPrivate;
class Q_WIDGETS_EXPORT QAbstractScrollArea : public QFrame
{
Q_OBJECT
+
+ Q_ENUMS(SizeAdjustPolicy)
Q_PROPERTY(Qt::ScrollBarPolicy verticalScrollBarPolicy READ verticalScrollBarPolicy WRITE setVerticalScrollBarPolicy)
Q_PROPERTY(Qt::ScrollBarPolicy horizontalScrollBarPolicy READ horizontalScrollBarPolicy WRITE setHorizontalScrollBarPolicy)
+ Q_PROPERTY(SizeAdjustPolicy sizeAdjustPolicy READ sizeAdjustPolicy WRITE setSizeAdjustPolicy)
public:
explicit QAbstractScrollArea(QWidget* parent=0);
~QAbstractScrollArea();
+ enum SizeAdjustPolicy {
+ AdjustIgnored,
+ AdjustToContentsOnFirstShow,
+ AdjustToContents
+ };
+
Qt::ScrollBarPolicy verticalScrollBarPolicy() const;
void setVerticalScrollBarPolicy(Qt::ScrollBarPolicy);
QScrollBar *verticalScrollBar() const;
@@ -89,6 +98,9 @@ public:
virtual void setupViewport(QWidget *viewport);
+ SizeAdjustPolicy sizeAdjustPolicy() const;
+ void setSizeAdjustPolicy(SizeAdjustPolicy policy);
+
protected:
QAbstractScrollArea(QAbstractScrollAreaPrivate &dd, QWidget *parent = 0);
void setViewportMargins(int left, int top, int right, int bottom);
diff --git a/src/widgets/widgets/qabstractscrollarea_p.h b/src/widgets/widgets/qabstractscrollarea_p.h
index 34d767fe29..3093c2f812 100644
--- a/src/widgets/widgets/qabstractscrollarea_p.h
+++ b/src/widgets/widgets/qabstractscrollarea_p.h
@@ -75,6 +75,10 @@ public:
QScrollBar *hbar, *vbar;
Qt::ScrollBarPolicy vbarpolicy, hbarpolicy;
+ bool shownOnce;
+ mutable QSize sizeHint;
+ QAbstractScrollArea::SizeAdjustPolicy sizeAdjustPolicy;
+
QWidget *viewport;
QWidget *cornerWidget;
QRect cornerPaintingRect;
diff --git a/src/widgets/widgets/qcombobox.cpp b/src/widgets/widgets/qcombobox.cpp
index c59edf295c..b89067155d 100644
--- a/src/widgets/widgets/qcombobox.cpp
+++ b/src/widgets/widgets/qcombobox.cpp
@@ -2065,6 +2065,20 @@ QString QComboBox::currentText() const
}
/*!
+ \property QComboBox::currentData
+ \brief the data for the current item
+ \since 5.2
+
+ By default, for an empty combo box or a combo box in which no current
+ item is set, this property contains an invalid QVariant.
+*/
+QVariant QComboBox::currentData(int role) const
+{
+ Q_D(const QComboBox);
+ return d->currentIndex.data(role);
+}
+
+/*!
Returns the text for the given \a index in the combobox.
*/
QString QComboBox::itemText(int index) const
diff --git a/src/widgets/widgets/qcombobox.h b/src/widgets/widgets/qcombobox.h
index d167ac7d11..d4aeeb9620 100644
--- a/src/widgets/widgets/qcombobox.h
+++ b/src/widgets/widgets/qcombobox.h
@@ -66,6 +66,7 @@ class Q_WIDGETS_EXPORT QComboBox : public QWidget
Q_PROPERTY(int count READ count)
Q_PROPERTY(QString currentText READ currentText WRITE setCurrentText NOTIFY currentTextChanged USER true)
Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged)
+ Q_PROPERTY(QVariant currentData READ currentData)
Q_PROPERTY(int maxVisibleItems READ maxVisibleItems WRITE setMaxVisibleItems)
Q_PROPERTY(int maxCount READ maxCount WRITE setMaxCount)
Q_PROPERTY(InsertPolicy insertPolicy READ insertPolicy WRITE setInsertPolicy)
@@ -167,8 +168,8 @@ public:
void setModelColumn(int visibleColumn);
int currentIndex() const;
-
QString currentText() const;
+ QVariant currentData(int role = Qt::UserRole) const;
QString itemText(int index) const;
QIcon itemIcon(int index) const;
diff --git a/src/widgets/widgets/qdialogbuttonbox.cpp b/src/widgets/widgets/qdialogbuttonbox.cpp
index bc5d84e259..226969cdd1 100644
--- a/src/widgets/widgets/qdialogbuttonbox.cpp
+++ b/src/widgets/widgets/qdialogbuttonbox.cpp
@@ -669,6 +669,21 @@ QDialogButtonBox::QDialogButtonBox(Qt::Orientation orientation, QWidget *parent)
}
/*!
+ \since 5.2
+
+ Constructs a horizontal button box with the given \a parent, containing
+ the standard buttons specified by \a buttons.
+
+ \sa orientation, addButton()
+*/
+QDialogButtonBox::QDialogButtonBox(StandardButtons buttons, QWidget *parent)
+ : QWidget(*new QDialogButtonBoxPrivate(Qt::Horizontal), parent, 0)
+{
+ d_func()->initLayout();
+ d_func()->createStandardButtons(buttons);
+}
+
+/*!
Constructs a button box with the given \a orientation and \a parent, containing
the standard buttons specified by \a buttons.
diff --git a/src/widgets/widgets/qdialogbuttonbox.h b/src/widgets/widgets/qdialogbuttonbox.h
index 6715c590e2..d8e1a997d4 100644
--- a/src/widgets/widgets/qdialogbuttonbox.h
+++ b/src/widgets/widgets/qdialogbuttonbox.h
@@ -115,7 +115,8 @@ public:
QDialogButtonBox(QWidget *parent = 0);
QDialogButtonBox(Qt::Orientation orientation, QWidget *parent = 0);
- QDialogButtonBox(StandardButtons buttons, Qt::Orientation orientation = Qt::Horizontal,
+ explicit QDialogButtonBox(StandardButtons buttons, QWidget *parent = 0);
+ QDialogButtonBox(StandardButtons buttons, Qt::Orientation orientation,
QWidget *parent = 0);
~QDialogButtonBox();
diff --git a/src/widgets/widgets/qfontcombobox.cpp b/src/widgets/widgets/qfontcombobox.cpp
index 5f929caf03..0b0efa2bdf 100644
--- a/src/widgets/widgets/qfontcombobox.cpp
+++ b/src/widgets/widgets/qfontcombobox.cpp
@@ -54,6 +54,88 @@
QT_BEGIN_NAMESPACE
+static QFontDatabase::WritingSystem writingSystemFromScript(QLocale::Script script)
+{
+ switch (script) {
+ case QLocale::ArabicScript:
+ return QFontDatabase::Arabic;
+ case QLocale::CyrillicScript:
+ return QFontDatabase::Cyrillic;
+ case QLocale::GurmukhiScript:
+ return QFontDatabase::Gurmukhi;
+ case QLocale::SimplifiedHanScript:
+ return QFontDatabase::SimplifiedChinese;
+ case QLocale::TraditionalHanScript:
+ return QFontDatabase::TraditionalChinese;
+ case QLocale::LatinScript:
+ return QFontDatabase::Latin;
+ case QLocale::ArmenianScript:
+ return QFontDatabase::Armenian;
+ case QLocale::BengaliScript:
+ return QFontDatabase::Bengali;
+ case QLocale::DevanagariScript:
+ return QFontDatabase::Devanagari;
+ case QLocale::GeorgianScript:
+ return QFontDatabase::Georgian;
+ case QLocale::GreekScript:
+ return QFontDatabase::Greek;
+ case QLocale::GujaratiScript:
+ return QFontDatabase::Gujarati;
+ case QLocale::HebrewScript:
+ return QFontDatabase::Hebrew;
+ case QLocale::JapaneseScript:
+ return QFontDatabase::Japanese;
+ case QLocale::KhmerScript:
+ return QFontDatabase::Khmer;
+ case QLocale::KannadaScript:
+ return QFontDatabase::Kannada;
+ case QLocale::KoreanScript:
+ return QFontDatabase::Korean;
+ case QLocale::LaoScript:
+ return QFontDatabase::Lao;
+ case QLocale::MalayalamScript:
+ return QFontDatabase::Malayalam;
+ case QLocale::MyanmarScript:
+ return QFontDatabase::Myanmar;
+ case QLocale::TamilScript:
+ return QFontDatabase::Tamil;
+ case QLocale::TeluguScript:
+ return QFontDatabase::Telugu;
+ case QLocale::ThaanaScript:
+ return QFontDatabase::Thaana;
+ case QLocale::ThaiScript:
+ return QFontDatabase::Thai;
+ case QLocale::TibetanScript:
+ return QFontDatabase::Tibetan;
+ case QLocale::SinhalaScript:
+ return QFontDatabase::Sinhala;
+ case QLocale::SyriacScript:
+ return QFontDatabase::Syriac;
+ case QLocale::OriyaScript:
+ return QFontDatabase::Oriya;
+ case QLocale::OghamScript:
+ return QFontDatabase::Ogham;
+ case QLocale::RunicScript:
+ return QFontDatabase::Runic;
+ case QLocale::NkoScript:
+ return QFontDatabase::Nko;
+ default:
+ return QFontDatabase::Any;
+ }
+}
+
+static QFontDatabase::WritingSystem writingSystemFromLocale()
+{
+ QStringList uiLanguages = QLocale::system().uiLanguages();
+ QLocale::Script script;
+ if (!uiLanguages.isEmpty())
+ script = QLocale(uiLanguages.at(0)).script();
+ else
+ script = QLocale::system().script();
+
+ return writingSystemFromScript(script);
+}
+
static QFontDatabase::WritingSystem writingSystemForFont(const QFont &font, bool *hasLatin)
{
QList<QFontDatabase::WritingSystem> writingSystems = QFontDatabase().writingSystems(font.family());
@@ -66,7 +148,22 @@ static QFontDatabase::WritingSystem writingSystemForFont(const QFont &font, bool
if (writingSystems.isEmpty())
return QFontDatabase::Any;
- QFontDatabase::WritingSystem system = writingSystems.last();
+ QFontDatabase::WritingSystem system = writingSystemFromLocale();
+
+ if (writingSystems.contains(system))
+ return system;
+
+ if (system == QFontDatabase::TraditionalChinese
+ && writingSystems.contains(QFontDatabase::SimplifiedChinese)) {
+ return QFontDatabase::SimplifiedChinese;
+ }
+
+ if (system == QFontDatabase::SimplifiedChinese
+ && writingSystems.contains(QFontDatabase::TraditionalChinese)) {
+ return QFontDatabase::TraditionalChinese;
+ }
+
+ system = writingSystems.last();
if (!*hasLatin) {
// we need to show something
diff --git a/src/widgets/widgets/qlineedit.cpp b/src/widgets/widgets/qlineedit.cpp
index 70083d7267..4254ef2b27 100644
--- a/src/widgets/widgets/qlineedit.cpp
+++ b/src/widgets/widgets/qlineedit.cpp
@@ -351,7 +351,7 @@ void QLineEdit::setPlaceholderText(const QString& placeholderText)
Q_D(QLineEdit);
if (d->placeholderText != placeholderText) {
d->placeholderText = placeholderText;
- if (!hasFocus())
+ if (d->control->text().isEmpty())
update();
}
}
diff --git a/src/widgets/widgets/qscrollarea.cpp b/src/widgets/widgets/qscrollarea.cpp
index 93c335c56b..2a6d4620d7 100644
--- a/src/widgets/widgets/qscrollarea.cpp
+++ b/src/widgets/widgets/qscrollarea.cpp
@@ -407,6 +407,18 @@ QSize QScrollArea::sizeHint() const
return sz.boundedTo(QSize(36 * h, 24 * h));
}
+/*!
+ \reimp
+ */
+QSize QScrollArea::viewportSizeHint() const
+{
+ Q_D(const QScrollArea);
+ if (d->widget) {
+ return d->resizable ? d->widget->sizeHint() : d->widget->size();
+ }
+ const int h = fontMetrics().height();
+ return QSize(6 * h, 4 * h);
+}
/*!
diff --git a/src/widgets/widgets/qscrollarea.h b/src/widgets/widgets/qscrollarea.h
index 576c9bc9e0..70af5fbbd7 100644
--- a/src/widgets/widgets/qscrollarea.h
+++ b/src/widgets/widgets/qscrollarea.h
@@ -69,6 +69,8 @@ public:
void setWidgetResizable(bool resizable);
QSize sizeHint() const;
+ QSize viewportSizeHint() const;
+
bool focusNextPrevChild(bool next);
Qt::Alignment alignment() const;
diff --git a/src/widgets/widgets/qspinbox.cpp b/src/widgets/widgets/qspinbox.cpp
index 0ce5473ad8..bf4e130d4e 100644
--- a/src/widgets/widgets/qspinbox.cpp
+++ b/src/widgets/widgets/qspinbox.cpp
@@ -78,6 +78,8 @@ public:
q->setInputMethodHints(Qt::ImhDigitsOnly);
setLayoutItemMargins(QStyle::SE_SpinBoxLayoutItem);
}
+
+ int displayIntegerBase;
};
class QDoubleSpinBoxPrivate : public QAbstractSpinBoxPrivate
@@ -425,6 +427,38 @@ void QSpinBox::setRange(int minimum, int maximum)
}
/*!
+ \property QSpinBox::displayIntegerBase
+
+ \brief the base used to display the value of the spin box
+
+ The default displayIntegerBase value is 10.
+
+ \sa textFromValue(), valueFromText()
+ \since 5.2
+*/
+
+int QSpinBox::displayIntegerBase() const
+{
+ Q_D(const QSpinBox);
+ return d->displayIntegerBase;
+}
+
+void QSpinBox::setDisplayIntegerBase(int base)
+{
+ Q_D(QSpinBox);
+ // Falls back to base 10 on invalid bases (like QString)
+ if (base < 2 || base > 36) {
+ qWarning("QSpinBox::setDisplayIntegerBase: Invalid base (%d)", base);
+ base = 10;
+ }
+
+ if (base != d->displayIntegerBase) {
+ d->displayIntegerBase = base;
+ d->updateEdit();
+ }
+}
+
+/*!
This virtual function is used by the spin box whenever it needs to
display the given \a value. The default implementation returns a
string containing \a value printed in the standard way using
@@ -444,9 +478,18 @@ void QSpinBox::setRange(int minimum, int maximum)
QString QSpinBox::textFromValue(int value) const
{
- QString str = locale().toString(value);
- if (qAbs(value) >= 1000 || value == INT_MIN) {
- str.remove(locale().groupSeparator());
+ Q_D(const QSpinBox);
+ QString str;
+
+ if (d->displayIntegerBase != 10) {
+ str = QString::number(qAbs(value), d->displayIntegerBase);
+ if (value < 0)
+ str.prepend('-');
+ } else {
+ str = locale().toString(value);
+ if (qAbs(value) >= 1000 || value == INT_MIN) {
+ str.remove(locale().groupSeparator());
+ }
}
return str;
@@ -926,6 +969,7 @@ QSpinBoxPrivate::QSpinBoxPrivate()
minimum = QVariant((int)0);
maximum = QVariant((int)99);
value = minimum;
+ displayIntegerBase = 10;
singleStep = QVariant((int)1);
type = QVariant::Int;
}
@@ -1003,11 +1047,15 @@ QVariant QSpinBoxPrivate::validateAndInterpret(QString &input, int &pos,
state = QValidator::Invalid; // special-case -0 will be interpreted as 0 and thus not be invalid with a range from 0-100
} else {
bool ok = false;
- num = locale.toInt(copy, &ok);
- if (!ok && copy.contains(locale.groupSeparator()) && (max >= 1000 || min <= -1000)) {
- QString copy2 = copy;
- copy2.remove(locale.groupSeparator());
- num = locale.toInt(copy2, &ok);
+ if (displayIntegerBase != 10) {
+ num = copy.toInt(&ok, displayIntegerBase);
+ } else {
+ num = locale.toInt(copy, &ok);
+ if (!ok && copy.contains(locale.groupSeparator()) && (max >= 1000 || min <= -1000)) {
+ QString copy2 = copy;
+ copy2.remove(locale.groupSeparator());
+ num = locale.toInt(copy2, &ok);
+ }
}
QSBDEBUG() << __FILE__ << __LINE__<< "num is set to" << num;
if (!ok) {
diff --git a/src/widgets/widgets/qspinbox.h b/src/widgets/widgets/qspinbox.h
index 4963f87a1a..98e809e141 100644
--- a/src/widgets/widgets/qspinbox.h
+++ b/src/widgets/widgets/qspinbox.h
@@ -61,6 +61,7 @@ class Q_WIDGETS_EXPORT QSpinBox : public QAbstractSpinBox
Q_PROPERTY(int maximum READ maximum WRITE setMaximum)
Q_PROPERTY(int singleStep READ singleStep WRITE setSingleStep)
Q_PROPERTY(int value READ value WRITE setValue NOTIFY valueChanged USER true)
+ Q_PROPERTY(int displayIntegerBase READ displayIntegerBase WRITE setDisplayIntegerBase)
public:
explicit QSpinBox(QWidget *parent = 0);
@@ -87,6 +88,8 @@ public:
void setRange(int min, int max);
+ int displayIntegerBase() const;
+ void setDisplayIntegerBase(int base);
protected:
bool event(QEvent *event);
diff --git a/src/widgets/widgets/qsplashscreen.cpp b/src/widgets/widgets/qsplashscreen.cpp
index 746c02e4e2..b2a0d3f8b8 100644
--- a/src/widgets/widgets/qsplashscreen.cpp
+++ b/src/widgets/widgets/qsplashscreen.cpp
@@ -200,7 +200,7 @@ void QSplashScreen::repaint()
is kept up to date with what your application is doing (e.g.,
loading files).
- \sa Qt::Alignment, clearMessage()
+ \sa Qt::Alignment, clearMessage(), message()
*/
void QSplashScreen::showMessage(const QString &message, int alignment,
const QColor &color)
@@ -214,6 +214,20 @@ void QSplashScreen::showMessage(const QString &message, int alignment,
}
/*!
+ \since 5.2
+
+ Returns the message that is currently displayed on the splash screen.
+
+ \sa showMessage(), clearMessage()
+*/
+
+QString QSplashScreen::message() const
+{
+ Q_D(const QSplashScreen);
+ return d->currStatus;
+}
+
+/*!
Removes the message being displayed on the splash screen
\sa showMessage()
diff --git a/src/widgets/widgets/qsplashscreen.h b/src/widgets/widgets/qsplashscreen.h
index a1af8e45ef..e675c2e7af 100644
--- a/src/widgets/widgets/qsplashscreen.h
+++ b/src/widgets/widgets/qsplashscreen.h
@@ -63,6 +63,7 @@ public:
const QPixmap pixmap() const;
void finish(QWidget *w);
void repaint();
+ QString message() const;
public Q_SLOTS:
void showMessage(const QString &message, int alignment = Qt::AlignLeft,
diff --git a/src/widgets/widgets/qtextedit.cpp b/src/widgets/widgets/qtextedit.cpp
index 4b3bf6de65..4e0c682493 100644
--- a/src/widgets/widgets/qtextedit.cpp
+++ b/src/widgets/widgets/qtextedit.cpp
@@ -773,6 +773,35 @@ QTextDocument *QTextEdit::document() const
}
/*!
+ \since 5.2
+
+ \property QTextEdit::placeholderText
+ \brief the editor placeholder text
+
+ Setting this property makes the editor display a grayed-out
+ placeholder text as long as the document() is empty.
+
+ By default, this property contains an empty string.
+
+ \sa document()
+*/
+QString QTextEdit::placeholderText() const
+{
+ Q_D(const QTextEdit);
+ return d->placeholderText;
+}
+
+void QTextEdit::setPlaceholderText(const QString &placeholderText)
+{
+ Q_D(QTextEdit);
+ if (d->placeholderText != placeholderText) {
+ d->placeholderText = placeholderText;
+ if (d->control->document()->isEmpty())
+ d->viewport->update();
+ }
+}
+
+/*!
Sets the visible \a cursor.
*/
void QTextEdit::setTextCursor(const QTextCursor &cursor)
@@ -1499,6 +1528,13 @@ void QTextEdit::paintEvent(QPaintEvent *e)
Q_D(QTextEdit);
QPainter p(d->viewport);
d->paint(&p, e);
+ if (!d->placeholderText.isEmpty() && d->control->document()->isEmpty()) {
+ QColor col = palette().text().color();
+ col.setAlpha(128);
+ p.setPen(col);
+ const int margin = int(document()->documentMargin());
+ p.drawText(d->viewport->rect().adjusted(margin, margin, -margin, -margin), Qt::AlignTop | Qt::TextWordWrap, d->placeholderText);
+ }
}
void QTextEditPrivate::_q_currentCharFormatChanged(const QTextCharFormat &fmt)
diff --git a/src/widgets/widgets/qtextedit.h b/src/widgets/widgets/qtextedit.h
index e1471848e7..06ec5fb889 100644
--- a/src/widgets/widgets/qtextedit.h
+++ b/src/widgets/widgets/qtextedit.h
@@ -85,6 +85,7 @@ class Q_WIDGETS_EXPORT QTextEdit : public QAbstractScrollArea
Q_PROPERTY(int cursorWidth READ cursorWidth WRITE setCursorWidth)
Q_PROPERTY(Qt::TextInteractionFlags textInteractionFlags READ textInteractionFlags WRITE setTextInteractionFlags)
Q_PROPERTY(QTextDocument *document READ document WRITE setDocument DESIGNABLE false)
+ Q_PROPERTY(QString placeholderText READ placeholderText WRITE setPlaceholderText)
public:
enum LineWrapMode {
NoWrap,
@@ -108,6 +109,9 @@ public:
void setDocument(QTextDocument *document);
QTextDocument *document() const;
+ void setPlaceholderText(const QString &placeholderText);
+ QString placeholderText() const;
+
void setTextCursor(const QTextCursor &cursor);
QTextCursor textCursor() const;
diff --git a/src/widgets/widgets/qtextedit_p.h b/src/widgets/widgets/qtextedit_p.h
index 1ce68dc23e..daa6eb5ed0 100644
--- a/src/widgets/widgets/qtextedit_p.h
+++ b/src/widgets/widgets/qtextedit_p.h
@@ -130,6 +130,8 @@ public:
QString anchorToScrollToWhenVisible;
+ QString placeholderText;
+
#ifdef QT_KEYPAD_NAVIGATION
QBasicTimer deleteAllTimer;
#endif
diff --git a/src/widgets/widgets/qwidgetlinecontrol.cpp b/src/widgets/widgets/qwidgetlinecontrol.cpp
index 9212f942c5..d10001a305 100644
--- a/src/widgets/widgets/qwidgetlinecontrol.cpp
+++ b/src/widgets/widgets/qwidgetlinecontrol.cpp
@@ -427,7 +427,7 @@ bool QWidgetLineControl::fixup() // this function assumes that validate currentl
m_validator->fixup(textCopy);
if (m_validator->validate(textCopy, cursorCopy) == QValidator::Acceptable) {
if (textCopy != m_text || cursorCopy != m_cursor)
- internalSetText(textCopy, cursorCopy);
+ internalSetText(textCopy, cursorCopy, false);
return true;
}
}
@@ -672,7 +672,7 @@ bool QWidgetLineControl::finishChange(int validateFromState, bool update, bool e
m_validInput = (m_validator->validate(textCopy, cursorCopy) != QValidator::Invalid);
if (m_validInput) {
if (m_text != textCopy) {
- internalSetText(textCopy, cursorCopy);
+ internalSetText(textCopy, cursorCopy, false);
return true;
}
m_cursor = cursorCopy;
diff --git a/src/xml/doc/qtxml.qdocconf b/src/xml/doc/qtxml.qdocconf
index 4e8cf34b0c..f9c847e022 100644
--- a/src/xml/doc/qtxml.qdocconf
+++ b/src/xml/doc/qtxml.qdocconf
@@ -40,3 +40,6 @@ exampledirs += ../../../examples/xml \
imagedirs += images \
../../../examples/xml/images
+
+navigation.landingpage = "Qt XML"
+navigation.cppclassespage = "Qt XML C++ Classes"
diff --git a/tests/auto/android/runtests.pl b/tests/auto/android/runtests.pl
index 7bb6833859..35cadda498 100755
--- a/tests/auto/android/runtests.pl
+++ b/tests/auto/android/runtests.pl
@@ -232,6 +232,7 @@ if ($deploy_qt)
print ("cp -L $_ $temp_dir/lib\n");
system("cp -L $_ $temp_dir/lib");
}
+ system("cp -L $android_ndk_dir/sources/cxx-stl/gnu-libstdc++/4.7/libs/armeabi-v7a/libgnustl_shared.so $temp_dir/lib");
system("cp -a plugins $temp_dir");
system("cp -a imports $temp_dir");
system("cp -a qml $temp_dir");
diff --git a/tests/auto/android/src/org/qtproject/qt5/android/QtActivity.java b/tests/auto/android/src/org/qtproject/qt5/android/QtActivity.java
index 6242f55488..cefca44ae5 100644
--- a/tests/auto/android/src/org/qtproject/qt5/android/QtActivity.java
+++ b/tests/auto/android/src/org/qtproject/qt5/android/QtActivity.java
@@ -102,6 +102,7 @@ public class QtActivity extends Activity {
}
if (getIntent().getExtras().containsKey("lib_name")) {
mainLib = getIntent().getExtras().getString("lib_name");
+ libraryList.add(mainLib);
int slash = mainLib.lastIndexOf("/");
if (slash >= 0) {
nativeLibDir = mainLib.substring(0, slash+1);
@@ -120,6 +121,7 @@ public class QtActivity extends Activity {
// TODO Auto-generated catch block
e.printStackTrace();
}
+ finish();
System.exit(0);
}
String[] libs = new String[libraryList.size()];
diff --git a/tests/auto/android/src/org/qtproject/qt5/android/QtNative.java b/tests/auto/android/src/org/qtproject/qt5/android/QtNative.java
index d9995e3178..a61543d31a 100644
--- a/tests/auto/android/src/org/qtproject/qt5/android/QtNative.java
+++ b/tests/auto/android/src/org/qtproject/qt5/android/QtNative.java
@@ -164,7 +164,8 @@ public class QtNative extends Application
m_displayMetricsDesktopWidthPixels,
m_displayMetricsDesktopHeightPixels,
m_displayMetricsXDpi,
- m_displayMetricsYDpi);
+ m_displayMetricsYDpi,
+ 1.0);
startQtApplication(f.getAbsolutePath()+"\t"+params, environment);
m_started = true;
}
@@ -183,7 +184,7 @@ public class QtNative extends Application
synchronized (m_mainActivityMutex) {
if (m_started) {
- setDisplayMetrics(screenWidthPixels, screenHeightPixels, desktopWidthPixels, desktopHeightPixels, XDpi, YDpi);
+ setDisplayMetrics(screenWidthPixels, screenHeightPixels, desktopWidthPixels, desktopHeightPixels, XDpi, YDpi, 1.0);
} else {
m_displayMetricsScreenWidthPixels = screenWidthPixels;
m_displayMetricsScreenHeightPixels = screenHeightPixels;
@@ -379,8 +380,12 @@ public class QtNative extends Application
// screen methods
public static native void setDisplayMetrics(int screenWidthPixels,
- int screenHeightPixels, int desktopWidthPixels,
- int desktopHeightPixels, double XDpi, double YDpi);
+ int screenHeightPixels,
+ int desktopWidthPixels,
+ int desktopHeightPixels,
+ double XDpi,
+ double YDpi,
+ double scaledDensity);
public static native void handleOrientationChanged(int newOrientation);
// screen methods
diff --git a/tests/auto/corelib/io/qipaddress/tst_qipaddress.cpp b/tests/auto/corelib/io/qipaddress/tst_qipaddress.cpp
index 1f57e38b44..4fcc46efab 100644
--- a/tests/auto/corelib/io/qipaddress/tst_qipaddress.cpp
+++ b/tests/auto/corelib/io/qipaddress/tst_qipaddress.cpp
@@ -361,7 +361,7 @@ void tst_QIpAddress::parseIp6()
#endif
Ip6 result;
- bool ok = QIPAddressUtils::parseIp6(result.u8, address.constBegin(), address.constEnd());
+ bool ok = QIPAddressUtils::parseIp6(result.u8, address.constBegin(), address.constEnd()) == 0;
QVERIFY(ok);
QCOMPARE(result, expected);
}
@@ -441,7 +441,7 @@ void tst_QIpAddress::invalidParseIp6()
#endif
Ip6 result;
- bool ok = QIPAddressUtils::parseIp6(result.u8, address.constBegin(), address.constEnd());
+ bool ok = QIPAddressUtils::parseIp6(result.u8, address.constBegin(), address.constEnd()) == 0;
QVERIFY(!ok);
}
diff --git a/tests/auto/corelib/io/qurl/tst_qurl.cpp b/tests/auto/corelib/io/qurl/tst_qurl.cpp
index 2a506ef8e2..bfd9c55c9e 100644
--- a/tests/auto/corelib/io/qurl/tst_qurl.cpp
+++ b/tests/auto/corelib/io/qurl/tst_qurl.cpp
@@ -111,6 +111,8 @@ private slots:
void percentEncoding();
void swap();
void symmetry();
+ void ipvfuture_data();
+ void ipvfuture();
void ipv6_data();
void ipv6();
void ipv6_2_data();
@@ -160,6 +162,8 @@ private slots:
void binaryData();
void fromUserInput_data();
void fromUserInput();
+ void fileName_data();
+ void fileName();
void isEmptyForEncodedUrl();
void toEncodedNotUsingUninitializedPath();
void emptyAuthorityRemovesExistingAuthority();
@@ -298,6 +302,17 @@ void tst_QUrl::comparison()
QEXPECT_FAIL("", "Normalization not implemented, will probably not be implemented like this", Continue);
QCOMPARE(url3, url4);
+ QUrl url3bis = QUrl::fromEncoded("example://a/b/c/%7Bfoo%7D/");
+ QUrl url3bisNoSlash = QUrl::fromEncoded("example://a/b/c/%7Bfoo%7D");
+ QUrl url4bis = QUrl::fromEncoded("example://a/.//b/../b/c//%7Bfoo%7D/");
+ QCOMPARE(url4bis.adjusted(QUrl::NormalizePathSegments), url3bis);
+ QCOMPARE(url4bis.adjusted(QUrl::NormalizePathSegments | QUrl::StripTrailingSlash), url3bisNoSlash);
+
+ QUrl url4EncodedDots = QUrl("example://a/.//b/%2E%2E%2F/b/c/");
+ QCOMPARE(QString::fromLatin1(url4EncodedDots.toEncoded()), QString::fromLatin1("example://a/.//b/..%2F/b/c/"));
+ QCOMPARE(url4EncodedDots.toString(), QString("example://a/.//b/..%2F/b/c/"));
+ QCOMPARE(url4EncodedDots.adjusted(QUrl::NormalizePathSegments).toString(), QString("example://a/b/..%2F/b/c/"));
+
// 6.2.2.1 Make sure hexdecimal characters in percent encoding are
// treated case-insensitively
QUrl url5;
@@ -946,8 +961,12 @@ void tst_QUrl::toString()
QFETCH(uint, options);
QFETCH(QString, string);
+ QUrl::FormattingOptions opt(options);
+
QUrl url(urlString);
- QCOMPARE(url.toString(QUrl::FormattingOptions(options)), string);
+ QCOMPARE(url.toString(opt), string);
+
+ QCOMPARE(url.adjusted(opt).toString(), string);
}
void tst_QUrl::toAndFromStringList_data()
@@ -1601,6 +1620,66 @@ void tst_QUrl::symmetry()
}
}
+void tst_QUrl::ipvfuture_data()
+{
+ QTest::addColumn<QString>("input");
+ QTest::addColumn<bool>("isValid");
+ QTest::addColumn<QString>("output");
+
+ // No one uses IPvFuture yet, so we have no clue what it might contain
+ // We're just testing that it can hold what the RFC says it should hold:
+ // IPvFuture = "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" )
+ QTest::newRow("missing-version-dot") << "x://[v]" << false;
+ QTest::newRow("missing-version") << "x://[v.]" << false;
+ QTest::newRow("missing-version-2") << "x://[v.1234]" << false;
+ QTest::newRow("missing-dot") << "x://[v7]" << false;
+ QTest::newRow("missing-dot-2") << "x://[v71234]" << false;
+ QTest::newRow("missing-data") << "x://[v7.]" << false;
+ QTest::newRow("non-hex-version") << "x://[vz.1234]" << false;
+
+ QTest::newRow("digit-ver") << "x://[v7.1]" << true << "x://[v7.1]";
+ QTest::newRow("lowercase-hex-ver") << "x://[va.1]" << true << "x://[vA.1]";
+ QTest::newRow("lowercase-hex-ver") << "x://[vA.1]" << true << "x://[vA.1]";
+
+ QTest::newRow("data-digits") << "x://[v7.1234]" << true << "x://[v7.1234]";
+ QTest::newRow("data-unreserved") << "x://[v7.hello~-WORLD_.com]" << true << "x://[v7.hello~-WORLD_.com]";
+ QTest::newRow("data-sub-delims-colon") << "x://[v7.!$&'()*+,;=:]" << true << "x://[v7.!$&'()*+,;=:]";
+
+ // we're using the tolerant parser
+ QTest::newRow("data-encoded-digits") << "x://[v7.%31%32%33%34]" << true << "x://[v7.1234]";
+ QTest::newRow("data-encoded-unreserved") << "x://[v7.%7E%2D%54%5f%2E]" << true << "x://[v7.~-T_.]";
+ QTest::newRow("data-encoded-sub-delims-colon") << "x://[v7.%21%24%26%27%28%29%2A%2B%2C%3B%3D%3A]" << true << "x://[v7.!$&'()*+,;=:]";
+
+ // should we test "[%76%37%2ex]" -> "[v7.x]" ?
+
+ QTest::newRow("data-invalid-space") << "x://[v7.%20]" << false;
+ QTest::newRow("data-invalid-control") << "x://[v7.\x7f]" << false;
+ QTest::newRow("data-invalid-other-1") << "x://[v7.{1234}]" << false;
+ QTest::newRow("data-invalid-other-2") << "x://[v7.<hello>]" << false;
+ QTest::newRow("data-invalid-unicode") << "x://[v7.æøå]" << false;
+ QTest::newRow("data-invalid-percent") << "x://[v7.%]" << false;
+ QTest::newRow("data-invalid-percent-percent") << "x://[v7.%25]" << false;
+}
+
+void tst_QUrl::ipvfuture()
+{
+ QFETCH(QString, input);
+ QFETCH(bool, isValid);
+
+ QUrl url(input);
+ if (isValid) {
+ QVERIFY2(url.isValid(), qPrintable(url.errorString()));
+
+ QFETCH(QString, output);
+ QCOMPARE(url.toString(), output);
+
+ QUrl url2(output);
+ QCOMPARE(url2, url);
+ } else {
+ QVERIFY(!url.isValid());
+ }
+}
+
void tst_QUrl::ipv6_data()
{
@@ -1641,6 +1720,9 @@ void tst_QUrl::ipv6_data()
QTest::newRow("case :,") << QString::fromLatin1("//[:,]") << false << "";
QTest::newRow("case ::bla") << QString::fromLatin1("//[::bla]") << false << "";
QTest::newRow("case v4-mapped") << "//[0:0:0:0:0:ffff:7f00:1]" << true << "//[::ffff:127.0.0.1]";
+
+ QTest::newRow("encoded-digit") << "//[::%31]" << true << "//[::1]";
+ QTest::newRow("encoded-colon") << "//[%3A%3A]" << true << "//[::]";
}
void tst_QUrl::ipv6()
@@ -1932,9 +2014,14 @@ void tst_QUrl::strictParser_data()
QTest::newRow("invalid-regname") << "http://bad<hostname>" << "Invalid hostname (contains invalid characters)";
QTest::newRow("invalid-regname-2") << "http://b%61d" << "Invalid hostname (contains invalid characters)";
QTest::newRow("invalid-ipv6") << "http://[:::]" << "Invalid IPv6 address";
+ QTest::newRow("invalid-ipv6-char1") << "http://[::g]" << "Invalid IPv6 address (character 'g' not permitted)";
+ QTest::newRow("invalid-ipv6-char2") << "http://[z::]" << "Invalid IPv6 address (character 'z' not permitted)";
QTest::newRow("invalid-ipvfuture-1") << "http://[v7]" << "Invalid IPvFuture address";
QTest::newRow("invalid-ipvfuture-2") << "http://[v7.]" << "Invalid IPvFuture address";
QTest::newRow("invalid-ipvfuture-3") << "http://[v789]" << "Invalid IPvFuture address";
+ QTest::newRow("invalid-ipvfuture-char1") << "http://[v7.^]" << "Invalid IPvFuture address";
+ QTest::newRow("invalid-encoded-ipv6") << "x://[%3a%3a%31]" << "Invalid IPv6 address";
+ QTest::newRow("invalid-encoded-ipvfuture") << "x://[v7.%7E%2D%54%5f%2E]" << "Invalid IPvFuture address";
QTest::newRow("unbalanced-brackets") << "http://[ff02::1" << "Expected ']' to match '[' in hostname";
// invalid hostnames happen in TolerantMode too
@@ -2427,23 +2514,37 @@ void tst_QUrl::fromEncoded()
void tst_QUrl::stripTrailingSlash_data()
{
QTest::addColumn<QString>("url");
- QTest::addColumn<QString>("expected");
+ QTest::addColumn<QString>("expectedStrip"); // toString(Strip)
+ QTest::addColumn<QString>("expectedDir"); // toString(RemoveFilename)
+ QTest::addColumn<QString>("expectedDirStrip"); // toString(RemoveFilename|Strip)
- QTest::newRow("ftp no slash") << "ftp://ftp.de.kde.org/dir" << "ftp://ftp.de.kde.org/dir";
- QTest::newRow("ftp slash") << "ftp://ftp.de.kde.org/dir/" << "ftp://ftp.de.kde.org/dir";
- QTest::newRow("file slash") << "file:///dir/" << "file:///dir";
- QTest::newRow("file no slash") << "file:///dir/" << "file:///dir";
- QTest::newRow("file root") << "file:///" << "file:///";
- QTest::newRow("no path") << "remote://" << "remote://";
+ QTest::newRow("subdir no slash") << "ftp://kde.org/dir/subdir" << "ftp://kde.org/dir/subdir" << "ftp://kde.org/dir/" << "ftp://kde.org/dir";
+ QTest::newRow("ftp no slash") << "ftp://kde.org/dir" << "ftp://kde.org/dir" << "ftp://kde.org/" << "ftp://kde.org/";
+ QTest::newRow("ftp slash") << "ftp://kde.org/dir/" << "ftp://kde.org/dir" << "ftp://kde.org/dir/" << "ftp://kde.org/dir";
+ QTest::newRow("ftp_two_slashes") << "ftp://kde.org/dir//" << "ftp://kde.org/dir" << "ftp://kde.org/dir//" << "ftp://kde.org/dir";
+ QTest::newRow("file slash") << "file:///dir/" << "file:///dir" << "file:///dir/" << "file:///dir";
+ QTest::newRow("file no slash") << "file:///dir" << "file:///dir" << "file:///" << "file:///";
+ QTest::newRow("file root") << "file:///" << "file:///" << "file:///" << "file:///";
+ QTest::newRow("file_root_manyslashes") << "file://///" << "file:///" << "file://///" << "file:///";
+ QTest::newRow("no path") << "remote://" << "remote://" << "remote://" << "remote://";
}
void tst_QUrl::stripTrailingSlash()
{
QFETCH(QString, url);
- QFETCH(QString, expected);
+ QFETCH(QString, expectedStrip);
+ QFETCH(QString, expectedDir);
+ QFETCH(QString, expectedDirStrip);
QUrl u(url);
- QCOMPARE(u.toString(QUrl::StripTrailingSlash), expected);
+ QCOMPARE(u.toString(QUrl::StripTrailingSlash), expectedStrip);
+ QCOMPARE(u.toString(QUrl::RemoveFilename), expectedDir);
+ QCOMPARE(u.toString(QUrl::RemoveFilename | QUrl::StripTrailingSlash), expectedDirStrip);
+
+ // Same thing, using QUrl::adjusted()
+ QCOMPARE(u.adjusted(QUrl::StripTrailingSlash).toString(), expectedStrip);
+ QCOMPARE(u.adjusted(QUrl::RemoveFilename).toString(), expectedDir);
+ QCOMPARE(u.adjusted(QUrl::RemoveFilename | QUrl::StripTrailingSlash).toString(), expectedDirStrip);
}
void tst_QUrl::hosts_data()
@@ -2729,6 +2830,43 @@ void tst_QUrl::fromUserInput()
QCOMPARE(url, guessUrlFromString);
}
+void tst_QUrl::fileName_data()
+{
+ QTest::addColumn<QString>("urlStr");
+ QTest::addColumn<QString>("expectedDirPath");
+ QTest::addColumn<QString>("expectedPrettyDecodedFileName");
+ QTest::addColumn<QString>("expectedFullyDecodedFileName");
+
+ QTest::newRow("fromDocu") << "http://qt-project.org/support/file.html"
+ << "/support/" << "file.html" << "file.html";
+ QTest::newRow("absoluteFile") << "file:///temp/tmp.txt"
+ << "/temp/" << "tmp.txt" << "tmp.txt";
+ QTest::newRow("absoluteDir") << "file:///temp/"
+ << "/temp/" << QString() << QString();
+ QTest::newRow("absoluteInRoot") << "file:///temp"
+ << "/" << "temp" << "temp";
+ QTest::newRow("relative") << "temp/tmp.txt"
+ << "temp/" << "tmp.txt" << "tmp.txt";
+ QTest::newRow("relativeNoSlash") << "tmp.txt"
+ << QString() << "tmp.txt" << "tmp.txt";
+ QTest::newRow("encoded") << "print:/specials/Print%20To%20File%20(PDF%252FAcrobat)"
+ << "/specials/" << "Print To File (PDF%252FAcrobat)" << "Print To File (PDF%2FAcrobat)";
+}
+
+void tst_QUrl::fileName()
+{
+ QFETCH(QString, urlStr);
+ QFETCH(QString, expectedDirPath);
+ QFETCH(QString, expectedPrettyDecodedFileName);
+ QFETCH(QString, expectedFullyDecodedFileName);
+
+ QUrl url(urlStr);
+ QVERIFY(url.isValid());
+ QCOMPARE(url.adjusted(QUrl::RemoveFilename).path(), expectedDirPath);
+ QCOMPARE(url.fileName(QUrl::PrettyDecoded), expectedPrettyDecodedFileName);
+ QCOMPARE(url.fileName(QUrl::FullyDecoded), expectedFullyDecodedFileName);
+}
+
// This is a regression test for a previously fixed bug where isEmpty didn't
// work for an encoded URL that was yet to be decoded. The test checks that
// isEmpty works for an encoded URL both after and before decoding.
@@ -2866,7 +3004,8 @@ void tst_QUrl::effectiveTLDs()
{
QFETCH(QUrl, domain);
QFETCH(QString, TLD);
- QCOMPARE(domain.topLevelDomain(), TLD);
+ QCOMPARE(domain.topLevelDomain(QUrl::PrettyDecoded), TLD);
+ QCOMPARE(domain.topLevelDomain(QUrl::FullyDecoded), TLD);
}
void tst_QUrl::lowercasesScheme()
diff --git a/tests/auto/corelib/io/qurlinternal/tst_qurlinternal.cpp b/tests/auto/corelib/io/qurlinternal/tst_qurlinternal.cpp
index 2014045171..b39b34e494 100644
--- a/tests/auto/corelib/io/qurlinternal/tst_qurlinternal.cpp
+++ b/tests/auto/corelib/io/qurlinternal/tst_qurlinternal.cpp
@@ -824,12 +824,20 @@ void tst_QUrlInternal::correctEncodedMistakes()
QFETCH(QString, expected);
// prepend some data to be sure that it remains there
- QString output = QTest::currentDataTag();
- expected.prepend(output);
+ QString dataTag = QTest::currentDataTag();
+ QString output = dataTag;
if (!qt_urlRecode(output, input.constData(), input.constData() + input.length(), 0))
output += input;
- QCOMPARE(output, expected);
+ QCOMPARE(output, dataTag + expected);
+
+ // now try the full decode mode
+ output = dataTag;
+ QString expected2 = QUrl::fromPercentEncoding(expected.toLatin1());
+
+ if (!qt_urlRecode(output, input.constData(), input.constData() + input.length(), QUrl::FullyDecoded))
+ output += input;
+ QCOMPARE(output, dataTag + expected2);
}
static void addUtf8Data(const char *name, const char *data)
diff --git a/tests/auto/corelib/json/tst_qtjson.cpp b/tests/auto/corelib/json/tst_qtjson.cpp
index bdf8c86442..78cb4277b2 100644
--- a/tests/auto/corelib/json/tst_qtjson.cpp
+++ b/tests/auto/corelib/json/tst_qtjson.cpp
@@ -45,6 +45,7 @@
#include "qjsonobject.h"
#include "qjsonvalue.h"
#include "qjsondocument.h"
+#include <limits>
#define INVALID_UNICODE "\357\277\277" // "\uffff"
#define UNICODE_DJE "\320\202" // Character from the Serbian Cyrillic alphabet
@@ -97,6 +98,8 @@ private Q_SLOTS:
void toVariantList();
void toJson();
+ void toJsonSillyNumericValues();
+ void toJsonLargeNumericValues();
void fromJson();
void fromJsonErrors();
void fromBinary();
@@ -1197,6 +1200,89 @@ void tst_QtJson::toJson()
}
}
+void tst_QtJson::toJsonSillyNumericValues()
+{
+ QJsonObject object;
+ QJsonArray array;
+ array.append(QJsonValue(std::numeric_limits<double>::infinity())); // encode to: null
+ array.append(QJsonValue(-std::numeric_limits<double>::infinity())); // encode to: null
+ array.append(QJsonValue(std::numeric_limits<double>::quiet_NaN())); // encode to: null
+ object.insert("Array", array);
+
+ QByteArray json = QJsonDocument(object).toJson();
+
+ QByteArray expected =
+ "{\n"
+ " \"Array\": [\n"
+ " null,\n"
+ " null,\n"
+ " null\n"
+ " ]\n"
+ "}\n";
+
+ QCOMPARE(json, expected);
+
+ QJsonDocument doc;
+ doc.setObject(object);
+ json = doc.toJson();
+ QCOMPARE(json, expected);
+}
+
+void tst_QtJson::toJsonLargeNumericValues()
+{
+ QJsonObject object;
+ QJsonArray array;
+ array.append(QJsonValue(1.234567)); // actual precision bug in Qt 5.0.0
+ array.append(QJsonValue(1.7976931348623157e+308)); // JS Number.MAX_VALUE
+ array.append(QJsonValue(5e-324)); // JS Number.MIN_VALUE
+ array.append(QJsonValue(std::numeric_limits<double>::min()));
+ array.append(QJsonValue(std::numeric_limits<double>::max()));
+ array.append(QJsonValue(std::numeric_limits<double>::epsilon()));
+ array.append(QJsonValue(std::numeric_limits<double>::denorm_min()));
+ array.append(QJsonValue(0.0));
+ array.append(QJsonValue(-std::numeric_limits<double>::min()));
+ array.append(QJsonValue(-std::numeric_limits<double>::max()));
+ array.append(QJsonValue(-std::numeric_limits<double>::epsilon()));
+ array.append(QJsonValue(-std::numeric_limits<double>::denorm_min()));
+ array.append(QJsonValue(-0.0));
+ array.append(QJsonValue(9007199254740992LL)); // JS Number max integer
+ array.append(QJsonValue(-9007199254740992LL)); // JS Number min integer
+ object.insert("Array", array);
+
+ QByteArray json = QJsonDocument(object).toJson();
+
+ QByteArray expected =
+ "{\n"
+ " \"Array\": [\n"
+ " 1.234567,\n"
+ " 1.7976931348623157e+308,\n"
+ // ((4.9406564584124654e-324 == 5e-324) == true)
+ // I can only think JavaScript has a special formatter to
+ // emit this value for this IEEE754 bit pattern.
+ " 4.9406564584124654e-324,\n"
+ " 2.2250738585072014e-308,\n"
+ " 1.7976931348623157e+308,\n"
+ " 2.2204460492503131e-16,\n"
+ " 4.9406564584124654e-324,\n"
+ " 0,\n"
+ " -2.2250738585072014e-308,\n"
+ " -1.7976931348623157e+308,\n"
+ " -2.2204460492503131e-16,\n"
+ " -4.9406564584124654e-324,\n"
+ " 0,\n"
+ " 9007199254740992,\n"
+ " -9007199254740992\n"
+ " ]\n"
+ "}\n";
+
+ QCOMPARE(json, expected);
+
+ QJsonDocument doc;
+ doc.setObject(object);
+ json = doc.toJson();
+ QCOMPARE(json, expected);
+}
+
void tst_QtJson::fromJson()
{
{
diff --git a/tests/auto/corelib/kernel/qeventloop/tst_qeventloop.cpp b/tests/auto/corelib/kernel/qeventloop/tst_qeventloop.cpp
index 25e5f03566..73f8365ce5 100644
--- a/tests/auto/corelib/kernel/qeventloop/tst_qeventloop.cpp
+++ b/tests/auto/corelib/kernel/qeventloop/tst_qeventloop.cpp
@@ -185,11 +185,11 @@ protected:
void tst_QEventLoop::processEvents()
{
- QSignalSpy spy1(QAbstractEventDispatcher::instance(), SIGNAL(aboutToBlock()));
- QSignalSpy spy2(QAbstractEventDispatcher::instance(), SIGNAL(awake()));
+ QSignalSpy aboutToBlockSpy(QAbstractEventDispatcher::instance(), SIGNAL(aboutToBlock()));
+ QSignalSpy awakeSpy(QAbstractEventDispatcher::instance(), SIGNAL(awake()));
- QVERIFY(spy1.isValid());
- QVERIFY(spy2.isValid());
+ QVERIFY(aboutToBlockSpy.isValid());
+ QVERIFY(awakeSpy.isValid());
QEventLoop eventLoop;
@@ -198,8 +198,8 @@ void tst_QEventLoop::processEvents()
// process posted events, QEventLoop::processEvents() should return
// true
QVERIFY(eventLoop.processEvents());
- QCOMPARE(spy1.count(), 0);
- QCOMPARE(spy2.count(), 1);
+ QCOMPARE(aboutToBlockSpy.count(), 0);
+ QCOMPARE(awakeSpy.count(), 1);
// allow any session manager to complete its handshake, so that
// there are no pending events left.
@@ -212,28 +212,28 @@ void tst_QEventLoop::processEvents()
// no events to process, QEventLoop::processEvents() should return
// false
- spy1.clear();
- spy2.clear();
+ aboutToBlockSpy.clear();
+ awakeSpy.clear();
QVERIFY(!eventLoop.processEvents());
- QCOMPARE(spy1.count(), 0);
- QCOMPARE(spy2.count(), 1);
+ QCOMPARE(aboutToBlockSpy.count(), 0);
+ QCOMPARE(awakeSpy.count(), 1);
// make sure the test doesn't block forever
int timerId = startTimer(100);
// wait for more events to process, QEventLoop::processEvents()
// should return true
- spy1.clear();
- spy2.clear();
+ aboutToBlockSpy.clear();
+ awakeSpy.clear();
QVERIFY(eventLoop.processEvents(QEventLoop::WaitForMoreEvents));
// Verify that the eventloop has blocked and woken up. Some eventloops
// may block and wake up multiple times.
- QVERIFY(spy1.count() > 0);
- QVERIFY(spy2.count() > 0);
+ QVERIFY(aboutToBlockSpy.count() > 0);
+ QVERIFY(awakeSpy.count() > 0);
// We should get one awake for each aboutToBlock, plus one awake when
// processEvents is entered.
- QVERIFY(spy2.count() >= spy1.count());
+ QVERIFY(awakeSpy.count() >= aboutToBlockSpy.count());
killTimer(timerId);
}
diff --git a/tests/auto/corelib/kernel/qmetatype/qmetatype.pro b/tests/auto/corelib/kernel/qmetatype/qmetatype.pro
index 5009fedc4f..23a8e6d23a 100644
--- a/tests/auto/corelib/kernel/qmetatype/qmetatype.pro
+++ b/tests/auto/corelib/kernel/qmetatype/qmetatype.pro
@@ -1,6 +1,7 @@
CONFIG += testcase parallel_test
TARGET = tst_qmetatype
QT = core testlib
+INCLUDEPATH += $$PWD/../../../other/qvariant_common
SOURCES = tst_qmetatype.cpp
TESTDATA=./typeFlags.bin
DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
diff --git a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp
index 77ea39da53..47900204e7 100644
--- a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp
+++ b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp
@@ -43,6 +43,8 @@
#include <QtCore>
#include <QtTest/QtTest>
+#include "tst_qvariant_common.h"
+
#ifdef Q_OS_LINUX
# include <pthread.h>
#endif
@@ -111,6 +113,11 @@ private slots:
void metaObject();
void constexprMetaTypeIds();
void constRefs();
+ void convertCustomType_data();
+ void convertCustomType();
+ void compareCustomType_data();
+ void compareCustomType();
+ void customDebugStream();
};
struct Foo { int i; };
@@ -1302,15 +1309,20 @@ Q_DECLARE_METATYPE(MyObjectPtr)
void tst_QMetaType::automaticTemplateRegistration()
{
- {
- QList<int> intList;
- intList << 42;
- QVERIFY(QVariant::fromValue(intList).value<QList<int> >().first() == 42);
- QVector<QList<int> > vectorList;
- vectorList << intList;
- QVERIFY(QVariant::fromValue(vectorList).value<QVector<QList<int> > >().first().first() == 42);
+#define TEST_SEQUENTIAL_CONTAINER(CONTAINER, VALUE_TYPE) \
+ { \
+ CONTAINER<VALUE_TYPE> innerContainer; \
+ innerContainer.push_back(42); \
+ QVERIFY(*QVariant::fromValue(innerContainer).value<CONTAINER<VALUE_TYPE> >().begin() == 42); \
+ QVector<CONTAINER<VALUE_TYPE> > outerContainer; \
+ outerContainer << innerContainer; \
+ QVERIFY(*QVariant::fromValue(outerContainer).value<QVector<CONTAINER<VALUE_TYPE> > >().first().begin() == 42); \
}
+ TEST_SEQUENTIAL_CONTAINER(QList, int)
+ TEST_SEQUENTIAL_CONTAINER(std::vector, int)
+ TEST_SEQUENTIAL_CONTAINER(std::list, int)
+
{
QList<QByteArray> bytearrayList;
bytearrayList << QByteArray("foo");
@@ -1323,14 +1335,9 @@ void tst_QMetaType::automaticTemplateRegistration()
QCOMPARE(::qMetaTypeId<QVariantList>(), (int)QMetaType::QVariantList);
QCOMPARE(::qMetaTypeId<QList<QVariant> >(), (int)QMetaType::QVariantList);
- {
- QList<QVariant> variantList;
- variantList << 42;
- QVERIFY(QVariant::fromValue(variantList).value<QList<QVariant> >().first() == 42);
- QVector<QList<QVariant> > vectorList;
- vectorList << variantList;
- QVERIFY(QVariant::fromValue(vectorList).value<QVector<QList<QVariant> > >().first().first() == 42);
- }
+ TEST_SEQUENTIAL_CONTAINER(QList, QVariant)
+ TEST_SEQUENTIAL_CONTAINER(std::vector, QVariant)
+ TEST_SEQUENTIAL_CONTAINER(std::list, QVariant)
{
QList<QSharedPointer<QObject> > sharedPointerList;
@@ -1395,6 +1402,31 @@ void tst_QMetaType::automaticTemplateRegistration()
QCOMPARE(QVariant::fromValue(variantMap).value<QVariantMap>().value(QStringLiteral("4")), QVariant(2));
}
{
+ typedef std::map<int, int> IntIntMap;
+ IntIntMap intIntMap;
+ intIntMap[4] = 2;
+ QCOMPARE(QVariant::fromValue(intIntMap).value<IntIntMap>()[4], 2);
+ }
+ {
+ typedef std::map<int, uint> StdIntUIntMap;
+ StdIntUIntMap intUIntMap;
+ intUIntMap[4] = 2;
+ QCOMPARE(QVariant::fromValue(intUIntMap).value<StdIntUIntMap>()[4], (uint)2);
+ }
+ {
+ typedef std::map<int, CustomObject*> StdMapIntCustomObject ;
+ StdMapIntCustomObject intComparableMap;
+ CustomObject *o = 0;
+ intComparableMap[4] = o;
+ QCOMPARE(QVariant::fromValue(intComparableMap).value<StdMapIntCustomObject >()[4], o);
+ }
+ {
+ typedef std::map<QString, QVariant> StdMapStringVariant;
+ StdMapStringVariant variantMap;
+ variantMap[QStringLiteral("4")] = 2;
+ QCOMPARE(QVariant::fromValue(variantMap).value<StdMapStringVariant>()[QStringLiteral("4")], QVariant(2));
+ }
+ {
typedef QPair<int, int> IntIntPair;
IntIntPair intIntPair = qMakePair(4, 2);
QCOMPARE(QVariant::fromValue(intIntPair).value<IntIntPair>().first, 4);
@@ -1412,6 +1444,25 @@ void tst_QMetaType::automaticTemplateRegistration()
QCOMPARE(QVariant::fromValue(intComparablePair).value<IntComparablePair>().second, m);
}
{
+ typedef std::pair<int, int> IntIntPair;
+ IntIntPair intIntPair = std::make_pair(4, 2);
+ QCOMPARE(QVariant::fromValue(intIntPair).value<IntIntPair>().first, 4);
+ QCOMPARE(QVariant::fromValue(intIntPair).value<IntIntPair>().second, 2);
+ }
+ {
+ typedef std::pair<int, uint> StdIntUIntPair;
+ StdIntUIntPair intUIntPair = std::make_pair<int, uint>(4, 2);
+ QCOMPARE(QVariant::fromValue(intUIntPair).value<StdIntUIntPair>().first, 4);
+ QCOMPARE(QVariant::fromValue(intUIntPair).value<StdIntUIntPair>().second, (uint)2);
+ }
+ {
+ typedef std::pair<int, CustomQObject*> StdIntComparablePair;
+ CustomQObject* o = 0;
+ StdIntComparablePair intComparablePair = std::make_pair(4, o);
+ QCOMPARE(QVariant::fromValue(intComparablePair).value<StdIntComparablePair>().first, 4);
+ QCOMPARE(QVariant::fromValue(intComparablePair).value<StdIntComparablePair>().second, o);
+ }
+ {
typedef QHash<int, UnregisteredType> IntUnregisteredTypeHash;
QVERIFY(qRegisterMetaType<IntUnregisteredTypeHash>("IntUnregisteredTypeHash") > 0);
}
@@ -1446,17 +1497,14 @@ void tst_QMetaType::automaticTemplateRegistration()
F(uint, __VA_ARGS__) \
F(qlonglong, __VA_ARGS__) \
F(qulonglong, __VA_ARGS__) \
- F(double, __VA_ARGS__) \
F(long, __VA_ARGS__) \
F(short, __VA_ARGS__) \
F(char, __VA_ARGS__) \
F(ulong, __VA_ARGS__) \
F(ushort, __VA_ARGS__) \
F(uchar, __VA_ARGS__) \
- F(float, __VA_ARGS__) \
F(QObject*, __VA_ARGS__) \
- F(QString, __VA_ARGS__) \
- F(CustomMovable, __VA_ARGS__)
+ F(QString, __VA_ARGS__)
#define CREATE_AND_VERIFY_CONTAINER(CONTAINER, ...) \
@@ -1774,6 +1822,366 @@ void tst_QMetaType::constRefs()
#endif
}
+struct CustomConvertibleType
+{
+ explicit CustomConvertibleType(const QVariant &foo = QVariant()) : m_foo(foo) {}
+ virtual ~CustomConvertibleType() {}
+ QString toString() const { return m_foo.toString(); }
+ operator QPoint() const { return QPoint(12, 34); }
+ template<typename To>
+ To convert() const { return s_value.value<To>();}
+ template<typename To>
+ To convertOk(bool *ok) const { *ok = s_ok; return s_value.value<To>();}
+
+ QVariant m_foo;
+ static QVariant s_value;
+ static bool s_ok;
+};
+
+bool operator<(const CustomConvertibleType &lhs, const CustomConvertibleType &rhs)
+{ return lhs.m_foo < rhs.m_foo; }
+bool operator==(const CustomConvertibleType &lhs, const CustomConvertibleType &rhs)
+{ return lhs.m_foo == rhs.m_foo; }
+bool operator!=(const CustomConvertibleType &lhs, const CustomConvertibleType &rhs)
+{ return !operator==(lhs, rhs); }
+
+QVariant CustomConvertibleType::s_value;
+bool CustomConvertibleType::s_ok = true;
+
+struct CustomConvertibleType2
+{
+ // implicit
+ CustomConvertibleType2(const CustomConvertibleType &t = CustomConvertibleType())
+ : m_foo(t.m_foo) {}
+ virtual ~CustomConvertibleType2() {}
+
+ QVariant m_foo;
+};
+
+struct CustomDebugStreamableType
+{
+ QString toString() const { return "test"; }
+};
+
+QDebug operator<<(QDebug dbg, const CustomDebugStreamableType&)
+{
+ return dbg << "string-content";
+}
+
+bool operator==(const CustomConvertibleType2 &lhs, const CustomConvertibleType2 &rhs)
+{ return lhs.m_foo == rhs.m_foo; }
+bool operator!=(const CustomConvertibleType2 &lhs, const CustomConvertibleType2 &rhs)
+{ return !operator==(lhs, rhs); }
+
+Q_DECLARE_METATYPE(CustomConvertibleType);
+Q_DECLARE_METATYPE(CustomConvertibleType2);
+Q_DECLARE_METATYPE(CustomDebugStreamableType);
+
+template<typename T, typename U>
+U convert(const T &t)
+{
+ return t;
+}
+
+template<typename From>
+struct ConvertFunctor
+{
+ CustomConvertibleType operator()(const From& f) const
+ {
+ return CustomConvertibleType(QVariant::fromValue(f));
+ }
+};
+
+template<typename From, typename To>
+bool hasRegisteredConverterFunction()
+{
+ return QMetaType::hasRegisteredConverterFunction<From, To>();
+}
+
+template<typename From, typename To>
+void testCustomTypeNotYetConvertible()
+{
+ QVERIFY((!hasRegisteredConverterFunction<From, To>()));
+ QVERIFY((!QVariant::fromValue<From>(From()).canConvert(qMetaTypeId<To>())));
+}
+
+template<typename From, typename To>
+void testCustomTypeConvertible()
+{
+ QVERIFY((hasRegisteredConverterFunction<From, To>()));
+ QVERIFY((QVariant::fromValue<From>(From()).canConvert(qMetaTypeId<To>())));
+}
+
+void customTypeNotYetConvertible()
+{
+ testCustomTypeNotYetConvertible<CustomConvertibleType, QString>();
+ testCustomTypeNotYetConvertible<CustomConvertibleType, bool>();
+ testCustomTypeNotYetConvertible<CustomConvertibleType, int>();
+ testCustomTypeNotYetConvertible<CustomConvertibleType, double>();
+ testCustomTypeNotYetConvertible<CustomConvertibleType, float>();
+ testCustomTypeNotYetConvertible<CustomConvertibleType, QRect>();
+ testCustomTypeNotYetConvertible<CustomConvertibleType, QRectF>();
+ testCustomTypeNotYetConvertible<CustomConvertibleType, QPoint>();
+ testCustomTypeNotYetConvertible<CustomConvertibleType, QPointF>();
+ testCustomTypeNotYetConvertible<CustomConvertibleType, QSize>();
+ testCustomTypeNotYetConvertible<CustomConvertibleType, QSizeF>();
+ testCustomTypeNotYetConvertible<CustomConvertibleType, QLine>();
+ testCustomTypeNotYetConvertible<CustomConvertibleType, QLineF>();
+ testCustomTypeNotYetConvertible<CustomConvertibleType, QChar>();
+ testCustomTypeNotYetConvertible<QString, CustomConvertibleType>();
+ testCustomTypeNotYetConvertible<bool, CustomConvertibleType>();
+ testCustomTypeNotYetConvertible<int, CustomConvertibleType>();
+ testCustomTypeNotYetConvertible<double, CustomConvertibleType>();
+ testCustomTypeNotYetConvertible<float, CustomConvertibleType>();
+ testCustomTypeNotYetConvertible<QRect, CustomConvertibleType>();
+ testCustomTypeNotYetConvertible<QRectF, CustomConvertibleType>();
+ testCustomTypeNotYetConvertible<QPoint, CustomConvertibleType>();
+ testCustomTypeNotYetConvertible<QPointF, CustomConvertibleType>();
+ testCustomTypeNotYetConvertible<QSize, CustomConvertibleType>();
+ testCustomTypeNotYetConvertible<QSizeF, CustomConvertibleType>();
+ testCustomTypeNotYetConvertible<QLine, CustomConvertibleType>();
+ testCustomTypeNotYetConvertible<QLineF, CustomConvertibleType>();
+ testCustomTypeNotYetConvertible<QChar, CustomConvertibleType>();
+ testCustomTypeNotYetConvertible<CustomConvertibleType, CustomConvertibleType2>();
+}
+
+void registerCustomTypeConversions()
+{
+ QVERIFY((QMetaType::registerConverter<CustomConvertibleType, QString>(&CustomConvertibleType::convertOk<QString>)));
+ QVERIFY((QMetaType::registerConverter<CustomConvertibleType, bool>(&CustomConvertibleType::convert<bool>)));
+ QVERIFY((QMetaType::registerConverter<CustomConvertibleType, int>(&CustomConvertibleType::convertOk<int>)));
+ QVERIFY((QMetaType::registerConverter<CustomConvertibleType, double>(&CustomConvertibleType::convert<double>)));
+ QVERIFY((QMetaType::registerConverter<CustomConvertibleType, float>(&CustomConvertibleType::convertOk<float>)));
+ QVERIFY((QMetaType::registerConverter<CustomConvertibleType, QRect>(&CustomConvertibleType::convert<QRect>)));
+ QVERIFY((QMetaType::registerConverter<CustomConvertibleType, QRectF>(&CustomConvertibleType::convertOk<QRectF>)));
+ QVERIFY((QMetaType::registerConverter<CustomConvertibleType, QPoint>(convert<CustomConvertibleType,QPoint>)));
+ QVERIFY((QMetaType::registerConverter<CustomConvertibleType, QPointF>(&CustomConvertibleType::convertOk<QPointF>)));
+ QVERIFY((QMetaType::registerConverter<CustomConvertibleType, QSize>(&CustomConvertibleType::convert<QSize>)));
+ QVERIFY((QMetaType::registerConverter<CustomConvertibleType, QSizeF>(&CustomConvertibleType::convertOk<QSizeF>)));
+ QVERIFY((QMetaType::registerConverter<CustomConvertibleType, QLine>(&CustomConvertibleType::convert<QLine>)));
+ QVERIFY((QMetaType::registerConverter<CustomConvertibleType, QLineF>(&CustomConvertibleType::convertOk<QLineF>)));
+ QVERIFY((QMetaType::registerConverter<CustomConvertibleType, QChar>(&CustomConvertibleType::convert<QChar>)));
+ QVERIFY((QMetaType::registerConverter<QString, CustomConvertibleType>(ConvertFunctor<QString>())));
+ QVERIFY((QMetaType::registerConverter<bool, CustomConvertibleType>(ConvertFunctor<bool>())));
+ QVERIFY((QMetaType::registerConverter<int, CustomConvertibleType>(ConvertFunctor<int>())));
+ QVERIFY((QMetaType::registerConverter<double, CustomConvertibleType>(ConvertFunctor<double>())));
+ QVERIFY((QMetaType::registerConverter<float, CustomConvertibleType>(ConvertFunctor<float>())));
+ QVERIFY((QMetaType::registerConverter<QRect, CustomConvertibleType>(ConvertFunctor<QRect>())));
+ QVERIFY((QMetaType::registerConverter<QRectF, CustomConvertibleType>(ConvertFunctor<QRectF>())));
+ QVERIFY((QMetaType::registerConverter<QPoint, CustomConvertibleType>(ConvertFunctor<QPoint>())));
+ QVERIFY((QMetaType::registerConverter<QPointF, CustomConvertibleType>(ConvertFunctor<QPointF>())));
+ QVERIFY((QMetaType::registerConverter<QSize, CustomConvertibleType>(ConvertFunctor<QSize>())));
+ QVERIFY((QMetaType::registerConverter<QSizeF, CustomConvertibleType>(ConvertFunctor<QSizeF>())));
+ QVERIFY((QMetaType::registerConverter<QLine, CustomConvertibleType>(ConvertFunctor<QLine>())));
+ QVERIFY((QMetaType::registerConverter<QLineF, CustomConvertibleType>(ConvertFunctor<QLineF>())));
+ QVERIFY((QMetaType::registerConverter<QChar, CustomConvertibleType>(ConvertFunctor<QChar>())));
+ QVERIFY((QMetaType::registerConverter<CustomConvertibleType, CustomConvertibleType2>()));
+ QTest::ignoreMessage(QtWarningMsg, "Type conversion already registered from type CustomConvertibleType to type CustomConvertibleType2");
+ QVERIFY((!QMetaType::registerConverter<CustomConvertibleType, CustomConvertibleType2>()));
+}
+
+void tst_QMetaType::convertCustomType_data()
+{
+ customTypeNotYetConvertible();
+ registerCustomTypeConversions();
+
+ QTest::addColumn<bool>("ok");
+ QTest::addColumn<QString>("testQString");
+ QTest::addColumn<bool>("testBool");
+ QTest::addColumn<int>("testInt");
+ QTest::addColumn<double>("testDouble");
+ QTest::addColumn<float>("testFloat");
+ QTest::addColumn<QRect>("testQRect");
+ QTest::addColumn<QRectF>("testQRectF");
+ QTest::addColumn<QPoint>("testQPoint");
+ QTest::addColumn<QPointF>("testQPointF");
+ QTest::addColumn<QSize>("testQSize");
+ QTest::addColumn<QSizeF>("testQSizeF");
+ QTest::addColumn<QLine>("testQLine");
+ QTest::addColumn<QLineF>("testQLineF");
+ QTest::addColumn<QChar>("testQChar");
+ QTest::addColumn<CustomConvertibleType>("testCustom");
+
+ QTest::newRow("default") << true
+ << QString::fromLatin1("string") << true << 15
+ << double(3.14) << float(3.6) << QRect(1, 2, 3, 4)
+ << QRectF(1.4, 1.9, 10.9, 40.2) << QPoint(12, 34)
+ << QPointF(9.2, 2.7) << QSize(4, 9) << QSizeF(3.3, 9.8)
+ << QLine(3, 9, 29, 4) << QLineF(38.9, 28.9, 102.3, 0.0)
+ << QChar('Q') << CustomConvertibleType(QString::fromLatin1("test"));
+ QTest::newRow("not ok") << false
+ << QString::fromLatin1("string") << true << 15
+ << double(3.14) << float(3.6) << QRect(1, 2, 3, 4)
+ << QRectF(1.4, 1.9, 10.9, 40.2) << QPoint(12, 34)
+ << QPointF(9.2, 2.7) << QSize(4, 9) << QSizeF(3.3, 9.8)
+ << QLine(3, 9, 29, 4) << QLineF()
+ << QChar('Q') << CustomConvertibleType(42);
+}
+
+void tst_QMetaType::convertCustomType()
+{
+ QFETCH(bool, ok);
+ CustomConvertibleType::s_ok = ok;
+
+ CustomConvertibleType t;
+ QVariant v = QVariant::fromValue(t);
+ QFETCH(QString, testQString);
+ CustomConvertibleType::s_value = testQString;
+ QCOMPARE(v.toString(), ok ? testQString : QString());
+ QCOMPARE(v.value<QString>(), ok ? testQString : QString());
+ QVERIFY(CustomConvertibleType::s_value.canConvert<CustomConvertibleType>());
+ QCOMPARE((CustomConvertibleType::s_value.value<CustomConvertibleType>().m_foo.toString()), testQString);
+
+ QFETCH(bool, testBool);
+ CustomConvertibleType::s_value = testBool;
+ QCOMPARE(v.toBool(), testBool);
+ QCOMPARE(v.value<bool>(), testBool);
+ QCOMPARE((CustomConvertibleType::s_value.value<CustomConvertibleType>().m_foo.toBool()), testBool);
+
+ QFETCH(int, testInt);
+ CustomConvertibleType::s_value = testInt;
+ QCOMPARE(v.toInt(), ok ? testInt : 0);
+ QCOMPARE(v.value<int>(), ok ? testInt : 0);
+ QCOMPARE((CustomConvertibleType::s_value.value<CustomConvertibleType>().m_foo.toInt()), testInt);
+
+ QFETCH(double, testDouble);
+ CustomConvertibleType::s_value = testDouble;
+ QCOMPARE(v.toDouble(), testDouble);
+ QCOMPARE(v.value<double>(), testDouble);
+ QCOMPARE((CustomConvertibleType::s_value.value<CustomConvertibleType>().m_foo.toDouble()), testDouble);
+
+ QFETCH(float, testFloat);
+ CustomConvertibleType::s_value = testFloat;
+ QCOMPARE(v.toFloat(), ok ? testFloat : 0.0);
+ QCOMPARE(v.value<float>(), ok ? testFloat : 0.0);
+ QCOMPARE((CustomConvertibleType::s_value.value<CustomConvertibleType>().m_foo.toFloat()), testFloat);
+
+ QFETCH(QRect, testQRect);
+ CustomConvertibleType::s_value = testQRect;
+ QCOMPARE(v.toRect(), testQRect);
+ QCOMPARE(v.value<QRect>(), testQRect);
+ QCOMPARE((CustomConvertibleType::s_value.value<CustomConvertibleType>().m_foo.toRect()), testQRect);
+
+ QFETCH(QRectF, testQRectF);
+ CustomConvertibleType::s_value = testQRectF;
+ QCOMPARE(v.toRectF(), ok ? testQRectF : QRectF());
+ QCOMPARE(v.value<QRectF>(), ok ? testQRectF : QRectF());
+ QCOMPARE((CustomConvertibleType::s_value.value<CustomConvertibleType>().m_foo.toRectF()), testQRectF);
+
+ QFETCH(QPoint, testQPoint);
+ CustomConvertibleType::s_value = testQPoint;
+ QCOMPARE(v.toPoint(), testQPoint);
+ QCOMPARE(v.value<QPoint>(), testQPoint);
+ QCOMPARE((CustomConvertibleType::s_value.value<CustomConvertibleType>().m_foo.toPoint()), testQPoint);
+
+ QFETCH(QPointF, testQPointF);
+ CustomConvertibleType::s_value = testQPointF;
+ QCOMPARE(v.toPointF(), ok ? testQPointF : QPointF());
+ QCOMPARE(v.value<QPointF>(), ok ? testQPointF : QPointF());
+ QCOMPARE((CustomConvertibleType::s_value.value<CustomConvertibleType>().m_foo.toPointF()), testQPointF);
+
+ QFETCH(QSize, testQSize);
+ CustomConvertibleType::s_value = testQSize;
+ QCOMPARE(v.toSize(), testQSize);
+ QCOMPARE(v.value<QSize>(), testQSize);
+ QCOMPARE((CustomConvertibleType::s_value.value<CustomConvertibleType>().m_foo.toSize()), testQSize);
+
+ QFETCH(QSizeF, testQSizeF);
+ CustomConvertibleType::s_value = testQSizeF;
+ QCOMPARE(v.toSizeF(), ok ? testQSizeF : QSizeF());
+ QCOMPARE(v.value<QSizeF>(), ok ? testQSizeF : QSizeF());
+ QCOMPARE((CustomConvertibleType::s_value.value<CustomConvertibleType>().m_foo.toSizeF()), testQSizeF);
+
+ QFETCH(QLine, testQLine);
+ CustomConvertibleType::s_value = testQLine;
+ QCOMPARE(v.toLine(), testQLine);
+ QCOMPARE(v.value<QLine>(), testQLine);
+ QCOMPARE((CustomConvertibleType::s_value.value<CustomConvertibleType>().m_foo.toLine()), testQLine);
+
+ QFETCH(QLineF, testQLineF);
+ CustomConvertibleType::s_value = testQLineF;
+ QCOMPARE(v.toLineF(), ok ? testQLineF : QLineF());
+ QCOMPARE(v.value<QLineF>(), ok ? testQLineF : QLineF());
+ QCOMPARE((CustomConvertibleType::s_value.value<CustomConvertibleType>().m_foo.toLineF()), testQLineF);
+
+ QFETCH(QChar, testQChar);
+ CustomConvertibleType::s_value = testQChar;
+ QCOMPARE(v.toChar(), testQChar);
+ QCOMPARE((CustomConvertibleType::s_value.value<CustomConvertibleType>().m_foo.toChar()), testQChar);
+
+ QFETCH(CustomConvertibleType, testCustom);
+ v = QVariant::fromValue(testCustom);
+ QVERIFY(v.canConvert(::qMetaTypeId<CustomConvertibleType2>()));
+ QCOMPARE(v.value<CustomConvertibleType2>().m_foo, testCustom.m_foo);
+}
+
+void tst_QMetaType::compareCustomType_data()
+{
+ QMetaType::registerComparators<CustomConvertibleType>();
+
+ QTest::addColumn<QVariantList>("unsorted");
+ QTest::addColumn<QVariantList>("sorted");
+
+ QTest::newRow("int") << (QVariantList() << 37 << 458 << 1 << 243 << -4 << 383)
+ << (QVariantList() << -4 << 1 << 37 << 243 << 383 << 458);
+
+ QTest::newRow("dobule") << (QVariantList() << 4934.93 << 0.0 << 302.39 << -39.0)
+ << (QVariantList() << -39.0 << 0.0 << 302.39 << 4934.93);
+
+ QTest::newRow("QString") << (QVariantList() << "Hello" << "World" << "this" << "is" << "a" << "test")
+ << (QVariantList() << "a" << "Hello" << "is" << "test" << "this" << "World");
+
+ QTest::newRow("QTime") << (QVariantList() << QTime(14, 39) << QTime(0, 0) << QTime(18, 18) << QTime(9, 27))
+ << (QVariantList() << QTime(0, 0) << QTime(9, 27) << QTime(14, 39) << QTime(18, 18));
+
+ QTest::newRow("QDate") << (QVariantList() << QDate(2013, 3, 23) << QDate(1900, 12, 1) << QDate(2001, 2, 2) << QDate(1982, 12, 16))
+ << (QVariantList() << QDate(1900, 12, 1) << QDate(1982, 12, 16) << QDate(2001, 2, 2) << QDate(2013, 3, 23));
+
+ QTest::newRow("mixed") << (QVariantList() << "Hello" << "World" << QChar('a') << 38 << QChar('z') << -39 << 4.6)
+ << (QVariantList() << -39 << 4.6 << 38 << QChar('a') << "Hello" << "World" << QChar('z'));
+
+ QTest::newRow("custom") << (QVariantList() << QVariant::fromValue(CustomConvertibleType(1)) << QVariant::fromValue(CustomConvertibleType(100)) << QVariant::fromValue(CustomConvertibleType(50)))
+ << (QVariantList() << QVariant::fromValue(CustomConvertibleType(1)) << QVariant::fromValue(CustomConvertibleType(50)) << QVariant::fromValue(CustomConvertibleType(100)));
+}
+
+void tst_QMetaType::compareCustomType()
+{
+ QFETCH(QVariantList, unsorted);
+ QFETCH(QVariantList, sorted);
+ qSort(unsorted);
+ QCOMPARE(unsorted, sorted);
+}
+
+struct MessageHandlerCustom : public MessageHandler
+{
+ MessageHandlerCustom(const int typeId)
+ : MessageHandler(typeId, handler)
+ {}
+ static void handler(QtMsgType, const QMessageLogContext &, const QString &msg)
+ {
+ QCOMPARE(msg.trimmed(), expectedMessage.trimmed());
+ }
+ static QString expectedMessage;
+};
+
+QString MessageHandlerCustom::expectedMessage;
+
+void tst_QMetaType::customDebugStream()
+{
+ MessageHandlerCustom handler(::qMetaTypeId<CustomDebugStreamableType>());
+ QVariant v1 = QVariant::fromValue(CustomDebugStreamableType());
+ handler.expectedMessage = "QVariant(CustomDebugStreamableType, )";
+ qDebug() << v1;
+
+ QMetaType::registerConverter<CustomDebugStreamableType, QString>(&CustomDebugStreamableType::toString);
+ handler.expectedMessage = "QVariant(CustomDebugStreamableType, \"test\")";
+ qDebug() << v1;
+
+ QMetaType::registerDebugStreamOperator<CustomDebugStreamableType>();
+ handler.expectedMessage = "QVariant(CustomDebugStreamableType, string-content)";
+ qDebug() << v1;
+}
+
// Compile-time test, it should be possible to register function pointer types
class Undefined;
@@ -1781,11 +2189,15 @@ typedef Undefined (*UndefinedFunction0)();
typedef Undefined (*UndefinedFunction1)(Undefined);
typedef Undefined (*UndefinedFunction2)(Undefined, Undefined);
typedef Undefined (*UndefinedFunction3)(Undefined, Undefined, Undefined);
+typedef Undefined (*UndefinedFunction4)(Undefined, Undefined, Undefined, Undefined, Undefined, Undefined, Undefined, Undefined);
Q_DECLARE_METATYPE(UndefinedFunction0);
Q_DECLARE_METATYPE(UndefinedFunction1);
Q_DECLARE_METATYPE(UndefinedFunction2);
Q_DECLARE_METATYPE(UndefinedFunction3);
+#ifdef Q_COMPILER_VARIADIC_TEMPLATES
+Q_DECLARE_METATYPE(UndefinedFunction4);
+#endif
QTEST_MAIN(tst_QMetaType)
#include "tst_qmetatype.moc"
diff --git a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp
index d16369de02..9bf28430b0 100644
--- a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp
+++ b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp
@@ -146,6 +146,7 @@ private slots:
void connectFunctorOverloads();
void disconnectDoesNotLeakFunctor();
void connectBase();
+ void qmlConnect();
};
struct QObjectCreatedOnShutdown
@@ -5835,6 +5836,56 @@ void tst_QObject::connectBase()
QCOMPARE( r1.count_slot3, 1 );
}
+struct QmlReceiver : public QtPrivate::QSlotObjectBase
+{
+ int callCount;
+ void *magic;
+
+ QmlReceiver()
+ : QtPrivate::QSlotObjectBase(&impl)
+ , callCount(0)
+ , magic(0)
+ {}
+
+ static void impl(int which, QSlotObjectBase *this_, QObject *, void **metaArgs, bool *ret)
+ {
+ switch (which) {
+ case Destroy: delete static_cast<QmlReceiver*>(this_); return;
+ case Call: static_cast<QmlReceiver*>(this_)->callCount++; return;
+ case Compare: *ret = static_cast<QmlReceiver*>(this_)->magic == metaArgs[0]; return;
+ case NumOperations: break;
+ }
+ }
+};
+
+void tst_QObject::qmlConnect()
+{
+#ifdef QT_BUILD_INTERNAL
+ SenderObject sender;
+ QmlReceiver *receiver = new QmlReceiver;
+ receiver->magic = receiver;
+ receiver->ref();
+
+ QVERIFY(QObjectPrivate::connect(&sender, sender.metaObject()->indexOfSignal("signal1()"),
+ receiver, Qt::AutoConnection));
+
+ QCOMPARE(receiver->callCount, 0);
+ sender.emitSignal1();
+ QCOMPARE(receiver->callCount, 1);
+
+ void *a[] = {
+ receiver
+ };
+ QVERIFY(QObjectPrivate::disconnect(&sender, sender.metaObject()->indexOfSignal("signal1()"), reinterpret_cast<void**>(&a)));
+
+ sender.emitSignal1();
+ QCOMPARE(receiver->callCount, 1);
+
+ receiver->destroyIfLastRef();
+#else
+ QSKIP("Needs QT_BUILD_INTERNAL");
+#endif
+}
QTEST_MAIN(tst_QObject)
#include "tst_qobject.moc"
diff --git a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp
index 4d862f4fc5..dab40db0ec 100644
--- a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp
+++ b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp
@@ -242,6 +242,9 @@ private slots:
void saveNewBuiltinWithOldStream();
void implicitConstruction();
+
+ void iterateContainerElements();
+ void pairElements();
private:
void dataStream_data(QDataStream::Version version);
void loadQVariantFromDataStream(QDataStream::Version version);
@@ -990,8 +993,8 @@ void tst_QVariant::toString_data()
QTest::newRow( "float" ) << QVariant( 123.456f ) << QString( "123.456" );
QTest::newRow( "bool" ) << QVariant( true ) << QString( "true" );
QTest::newRow( "qdate" ) << QVariant( QDate( 2002, 1, 1 ) ) << QString( "2002-01-01" );
- QTest::newRow( "qtime" ) << QVariant( QTime( 12, 34, 56 ) ) << QString( "12:34:56" );
- QTest::newRow( "qdatetime" ) << QVariant( QDateTime( QDate( 2002, 1, 1 ), QTime( 12, 34, 56 ) ) ) << QString( "2002-01-01T12:34:56" );
+ QTest::newRow( "qtime" ) << QVariant( QTime( 12, 34, 56 ) ) << QString( "12:34:56.000" );
+ QTest::newRow( "qdatetime" ) << QVariant( QDateTime( QDate( 2002, 1, 1 ), QTime( 12, 34, 56 ) ) ) << QString( "2002-01-01T12:34:56.000" );
QTest::newRow( "llong" ) << QVariant( (qlonglong)Q_INT64_C(123456789012) ) <<
QString( "123456789012" );
QTest::newRow("QJsonValue") << QVariant(QJsonValue(QString("hello"))) << QString("hello");
@@ -3392,5 +3395,312 @@ void tst_QVariant::saveNewBuiltinWithOldStream()
QCOMPARE(int(data.constData()[3]), 0);
}
+template<typename Container, typename Value_Type = typename Container::value_type>
+struct ContainerAPI
+{
+ static void insert(Container &container, typename Container::value_type value)
+ {
+ container.push_back(value);
+ }
+
+ static bool compare(const QVariant &variant, typename Container::value_type value)
+ {
+ return variant.value<typename Container::value_type>() == value;
+ }
+ static bool compare(QVariant variant, const QVariant &value)
+ {
+ return variant == value;
+ }
+};
+
+template<typename Container>
+struct ContainerAPI<Container, QVariant>
+{
+ static void insert(Container &container, int value)
+ {
+ container.push_back(QVariant::fromValue(value));
+ }
+
+ static bool compare(QVariant variant, const QVariant &value)
+ {
+ return variant == value;
+ }
+};
+
+template<typename Container>
+struct ContainerAPI<Container, QString>
+{
+ static void insert(Container &container, int value)
+ {
+ container.push_back(QString::number(value));
+ }
+
+ static bool compare(const QVariant &variant, QString value)
+ {
+ return variant.value<QString>() == value;
+ }
+ static bool compare(QVariant variant, const QVariant &value)
+ {
+ return variant == value;
+ }
+};
+
+// We have no built-in defines to check the stdlib features.
+// #define TEST_FORWARD_LIST
+
+#ifdef TEST_FORWARD_LIST
+#include <forward_list>
+Q_DECLARE_METATYPE(std::forward_list<int>)
+Q_DECLARE_METATYPE(std::forward_list<QVariant>)
+Q_DECLARE_METATYPE(std::forward_list<QString>)
+
+template<typename Value_Type>
+struct ContainerAPI<std::forward_list<Value_Type> >
+{
+ static void insert(std::forward_list<Value_Type> &container, Value_Type value)
+ {
+ container.push_front(value);
+ }
+ static bool compare(const QVariant &variant, Value_Type value)
+ {
+ return variant.value<Value_Type>() == value;
+ }
+ static bool compare(QVariant variant, const QVariant &value)
+ {
+ return variant == value;
+ }
+};
+
+template<>
+struct ContainerAPI<std::forward_list<QVariant> >
+{
+ static void insert(std::forward_list<QVariant> &container, int value)
+ {
+ container.push_front(QVariant::fromValue(value));
+ }
+
+ static bool compare(QVariant variant, const QVariant &value)
+ {
+ return variant == value;
+ }
+};
+
+template<>
+struct ContainerAPI<std::forward_list<QString> >
+{
+ static void insert(std::forward_list<QString> &container, int value)
+ {
+ container.push_front(QString::number(value));
+ }
+ static bool compare(const QVariant &variant, QString value)
+ {
+ return variant.value<QString>() == value;
+ }
+ static bool compare(QVariant variant, const QVariant &value)
+ {
+ return variant == value;
+ }
+};
+#endif
+
+template<typename Container>
+struct KeyGetter
+{
+ static const typename Container::key_type & get(const typename Container::const_iterator &it)
+ {
+ return it.key();
+ }
+ static const typename Container::mapped_type & value(const typename Container::const_iterator &it)
+ {
+ return it.value();
+ }
+};
+
+template<typename T, typename U>
+struct KeyGetter<std::map<T, U> >
+{
+ static const T & get(const typename std::map<T, U>::const_iterator &it)
+ {
+ return it->first;
+ }
+ static const U & value(const typename std::map<T, U>::const_iterator &it)
+ {
+ return it->second;
+ }
+};
+
+
+// We have no built-in defines to check the stdlib features.
+// #define TEST_UNORDERED_MAP
+
+#ifdef TEST_UNORDERED_MAP
+#include <unordered_map>
+typedef std::unordered_map<int, bool> StdUnorderedMap_int_bool;
+Q_DECLARE_METATYPE(StdUnorderedMap_int_bool)
+
+template<typename T, typename U>
+struct KeyGetter<std::unordered_map<T, U> >
+{
+ static const T & get(const typename std::unordered_map<T, U>::const_iterator &it)
+ {
+ return it->first;
+ }
+ static const U & value(const typename std::unordered_map<T, U>::const_iterator &it)
+ {
+ return it->second;
+ }
+};
+#endif
+
+void tst_QVariant::iterateContainerElements()
+{
+#ifdef Q_COMPILER_RANGE_FOR
+
+#define TEST_RANGE_FOR(CONTAINER, VALUE_TYPE) \
+ numSeen = 0; \
+ containerIter = intList.begin(); \
+ for (QVariant v : listIter) { \
+ QVERIFY(ContainerAPI<CONTAINER<VALUE_TYPE > >::compare(v, *containerIter)); \
+ QVERIFY(ContainerAPI<CONTAINER<VALUE_TYPE > >::compare(v, varList.at(numSeen))); \
+ ++containerIter; \
+ ++numSeen; \
+ } \
+ QCOMPARE(numSeen, (int)std::distance(intList.begin(), intList.end()));
+
+#else
+
+#define TEST_RANGE_FOR(CONTAINER, VALUE_TYPE)
+
+#endif
+
+#define TEST_SEQUENTIAL_ITERATION(CONTAINER, VALUE_TYPE) \
+ { \
+ int numSeen = 0; \
+ CONTAINER<VALUE_TYPE > intList; \
+ ContainerAPI<CONTAINER<VALUE_TYPE > >::insert(intList, 1); \
+ ContainerAPI<CONTAINER<VALUE_TYPE > >::insert(intList, 2); \
+ ContainerAPI<CONTAINER<VALUE_TYPE > >::insert(intList, 3); \
+ \
+ QVariant listVariant = QVariant::fromValue(intList); \
+ QVERIFY(listVariant.canConvert<QVariantList>()); \
+ QVariantList varList = listVariant.value<QVariantList>(); \
+ QCOMPARE(varList.size(), (int)std::distance(intList.begin(), intList.end())); \
+ QSequentialIterable listIter = listVariant.value<QSequentialIterable>(); \
+ QCOMPARE(varList.size(), listIter.size()); \
+ \
+ CONTAINER<VALUE_TYPE >::iterator containerIter = intList.begin(); \
+ const CONTAINER<VALUE_TYPE >::iterator containerEnd = intList.end(); \
+ for (int i = 0; i < listIter.size(); ++i, ++containerIter, ++numSeen) \
+ { \
+ QVERIFY(ContainerAPI<CONTAINER<VALUE_TYPE > >::compare(listIter.at(i), *containerIter)); \
+ QVERIFY(ContainerAPI<CONTAINER<VALUE_TYPE > >::compare(listIter.at(i), varList.at(i))); \
+ } \
+ QCOMPARE(numSeen, (int)std::distance(intList.begin(), intList.end())); \
+ QCOMPARE(containerIter, containerEnd); \
+ \
+ containerIter = intList.begin(); \
+ numSeen = 0; \
+ Q_FOREACH (const QVariant &v, listIter) { \
+ QVERIFY(ContainerAPI<CONTAINER<VALUE_TYPE > >::compare(v, *containerIter)); \
+ QVERIFY(ContainerAPI<CONTAINER<VALUE_TYPE > >::compare(v, varList.at(numSeen))); \
+ ++containerIter; \
+ ++numSeen; \
+ } \
+ QCOMPARE(numSeen, (int)std::distance(intList.begin(), intList.end())); \
+ TEST_RANGE_FOR(CONTAINER, VALUE_TYPE) \
+ }
+
+ TEST_SEQUENTIAL_ITERATION(QVector, int)
+ TEST_SEQUENTIAL_ITERATION(QVector, QVariant)
+ TEST_SEQUENTIAL_ITERATION(QVector, QString)
+ TEST_SEQUENTIAL_ITERATION(QQueue, int)
+ TEST_SEQUENTIAL_ITERATION(QQueue, QVariant)
+ TEST_SEQUENTIAL_ITERATION(QQueue, QString)
+ TEST_SEQUENTIAL_ITERATION(QList, int)
+ TEST_SEQUENTIAL_ITERATION(QList, QVariant)
+ TEST_SEQUENTIAL_ITERATION(QList, QString)
+ TEST_SEQUENTIAL_ITERATION(QStack, int)
+ TEST_SEQUENTIAL_ITERATION(QStack, QVariant)
+ TEST_SEQUENTIAL_ITERATION(QStack, QString)
+ TEST_SEQUENTIAL_ITERATION(std::vector, int)
+ TEST_SEQUENTIAL_ITERATION(std::vector, QVariant)
+ TEST_SEQUENTIAL_ITERATION(std::vector, QString)
+ TEST_SEQUENTIAL_ITERATION(std::list, int)
+ TEST_SEQUENTIAL_ITERATION(std::list, QVariant)
+ TEST_SEQUENTIAL_ITERATION(std::list, QString)
+
+#ifdef TEST_FORWARD_LIST
+ qRegisterSequentialConverter<std::forward_list<int> >();
+ qRegisterSequentialConverter<std::forward_list<QVariant> >();
+ qRegisterSequentialConverter<std::forward_list<QString> >();
+ TEST_SEQUENTIAL_ITERATION(std::forward_list, int)
+ TEST_SEQUENTIAL_ITERATION(std::forward_list, QVariant)
+ TEST_SEQUENTIAL_ITERATION(std::forward_list, QString)
+#endif
+
+#define TEST_ASSOCIATIVE_ITERATION(CONTAINER, KEY_TYPE, MAPPED_TYPE) \
+ { \
+ int numSeen = 0; \
+ CONTAINER<KEY_TYPE, MAPPED_TYPE> mapping; \
+ mapping[5] = true; \
+ mapping[15] = false; \
+ \
+ QVariant mappingVariant = QVariant::fromValue(mapping); \
+ QVariantMap varMap = mappingVariant.value<QVariantMap>(); \
+ QVariantMap varHash = mappingVariant.value<QVariantMap>(); \
+ QAssociativeIterable mappingIter = mappingVariant.value<QAssociativeIterable>(); \
+ \
+ CONTAINER<KEY_TYPE, MAPPED_TYPE>::const_iterator containerIter = mapping.begin(); \
+ const CONTAINER<KEY_TYPE, MAPPED_TYPE>::const_iterator containerEnd = mapping.end(); \
+ for ( ; containerIter != containerEnd; ++containerIter, ++numSeen) \
+ { \
+ MAPPED_TYPE expected = KeyGetter<CONTAINER<KEY_TYPE, MAPPED_TYPE> >::value(containerIter); \
+ KEY_TYPE key = KeyGetter<CONTAINER<KEY_TYPE, MAPPED_TYPE> >::get(containerIter); \
+ MAPPED_TYPE actual = mappingIter.value(key).value<MAPPED_TYPE >(); \
+ QCOMPARE(varMap.value(QString::number(key)).value<MAPPED_TYPE>(), expected); \
+ QCOMPARE(varHash.value(QString::number(key)).value<MAPPED_TYPE>(), expected); \
+ QCOMPARE(actual, expected); \
+ } \
+ QCOMPARE(numSeen, (int)std::distance(mapping.begin(), mapping.end())); \
+ QCOMPARE(containerIter, containerEnd); \
+ \
+ }
+
+ TEST_ASSOCIATIVE_ITERATION(QHash, int, bool)
+ TEST_ASSOCIATIVE_ITERATION(QMap, int, bool)
+ TEST_ASSOCIATIVE_ITERATION(std::map, int, bool)
+#ifdef TEST_UNORDERED_MAP
+ qRegisterAssociativeConverter<StdUnorderedMap_int_bool>();
+ TEST_ASSOCIATIVE_ITERATION(std::unordered_map, int, bool)
+#endif
+}
+
+void tst_QVariant::pairElements()
+{
+ typedef QPair<QVariant, QVariant> QVariantPair;
+
+#define TEST_PAIR_ELEMENT_ACCESS(PAIR, T1, T2, VALUE1, VALUE2) \
+ { \
+ PAIR<T1, T2> p(VALUE1, VALUE2); \
+ QVariant v = QVariant::fromValue(p); \
+ \
+ QVERIFY(v.canConvert<QVariantPair>()); \
+ QVariantPair pi = v.value<QVariantPair>(); \
+ QCOMPARE(pi.first, QVariant::fromValue(VALUE1)); \
+ QCOMPARE(pi.second, QVariant::fromValue(VALUE2)); \
+ }
+
+ TEST_PAIR_ELEMENT_ACCESS(QPair, int, int, 4, 5)
+ TEST_PAIR_ELEMENT_ACCESS(std::pair, int, int, 4, 5)
+ TEST_PAIR_ELEMENT_ACCESS(QPair, QString, QString, QStringLiteral("one"), QStringLiteral("two"))
+ TEST_PAIR_ELEMENT_ACCESS(std::pair, QString, QString, QStringLiteral("one"), QStringLiteral("two"))
+ TEST_PAIR_ELEMENT_ACCESS(QPair, QVariant, QVariant, 4, 5)
+ TEST_PAIR_ELEMENT_ACCESS(std::pair, QVariant, QVariant, 4, 5)
+ TEST_PAIR_ELEMENT_ACCESS(QPair, QVariant, int, 41, 15)
+ TEST_PAIR_ELEMENT_ACCESS(std::pair, QVariant, int, 34, 65)
+ TEST_PAIR_ELEMENT_ACCESS(QPair, int, QVariant, 24, 25)
+ TEST_PAIR_ELEMENT_ACCESS(std::pair, int, QVariant, 44, 15)
+}
+
QTEST_MAIN(tst_QVariant)
#include "tst_qvariant.moc"
diff --git a/mkspecs/macx-clang-libc++/qplatformdefs.h b/tests/auto/corelib/plugin/qpluginloader/fakeplugin.cpp
index 2c3a8b1c09..d5c933e3af 100644
--- a/mkspecs/macx-clang-libc++/qplatformdefs.h
+++ b/tests/auto/corelib/plugin/qpluginloader/fakeplugin.cpp
@@ -1,9 +1,9 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2013 Intel Corporation
** Contact: http://www.qt-project.org/legal
**
-** This file is part of the qmake spec of the Qt Toolkit.
+** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
@@ -39,5 +39,11 @@
**
****************************************************************************/
-#include "../common/mac/qplatformdefs.h"
+#include <QtCore/qplugin.h>
+#if QT_POINTER_SIZE == 8
+QT_PLUGIN_METADATA_SECTION void *const pluginSection = (void*)(0xc0ffeec0ffeeL);
+#else
+QT_PLUGIN_METADATA_SECTION void *const pluginSection = (void*)0xc0ffee;
+#endif
+QT_PLUGIN_METADATA_SECTION const char message[] = "QTMETADATA";
diff --git a/tests/auto/corelib/plugin/qpluginloader/machtest/generate-bad.pl b/tests/auto/corelib/plugin/qpluginloader/machtest/generate-bad.pl
new file mode 100755
index 0000000000..ec0dd980a9
--- /dev/null
+++ b/tests/auto/corelib/plugin/qpluginloader/machtest/generate-bad.pl
@@ -0,0 +1,209 @@
+#!/usr/bin/perl
+#############################################################################
+##
+## Copyright (C) 2013 Intel Corporation.
+## Contact: http://www.qt-project.org/legal
+##
+## This file is the build configuration utility 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$
+##
+#############################################################################
+
+use strict;
+use constant FAT_MAGIC => 0xcafebabe;
+use constant MH_MAGIC => 0xfeedface;
+use constant MH_MAGIC_64 => 0xfeedfacf;
+use constant CPU_TYPE_X86 => 7;
+use constant CPU_TYPE_X86_64 => CPU_TYPE_X86 | 0x01000000;
+use constant CPU_SUBTYPE_I386_ALL => 3;
+use constant MH_DYLIB => 6;
+use constant LC_SEGMENT => 1;
+use constant LC_SEGMENT_64 => 0x19;
+
+my $good = pack("(L7 L2 Z16 L8 Z16 Z16 L9 . L)>",
+ MH_MAGIC, CPU_TYPE_X86, CPU_SUBTYPE_I386_ALL, MH_DYLIB, # 0-3
+ 1, # 4: ncmds
+ 4 * (37 - 6), # 5: sizeofcmds
+ 0, # 6: flags
+
+ LC_SEGMENT, # 7: cmd
+ 4 * (37 - 6), # 8: cmdsize
+ '__TEXT', # 9-12: segname
+ 0, # 13: vmaddr
+ 0x1000, # 14: vmsize
+ 0, # 15: fileoff
+ 0x204, # 16: filesize
+ 7, # 17: maxprot (rwx)
+ 5, # 18: initprot (r-x)
+ 1, # 19: nsects
+ 0, # 20: flags
+
+ 'qtmetadata', # 21-24: sectname
+ '__TEXT', # 25-28: segname
+ 0x200, # 29: addr
+ 4, # 30: size
+ 0x200, # 31: offset
+ 2, # 32: align (2^2)
+ 0, # 33: reloff
+ 0, # 34: nreloc
+ 0, # 35: flags
+ 0, # 36: reserved1
+ 0, # 37: reserved2
+
+ 0x200,
+ 0xc0ffee # data
+);
+
+my $good64 = pack("(L8 L2 Z16 Q4 L4 Z16 Z16 Q2 L8 . Q)>",
+ MH_MAGIC_64, CPU_TYPE_X86_64, CPU_SUBTYPE_I386_ALL, MH_DYLIB, # 0-3
+ 1, # 4: ncmds
+ 4 * (45 - 7), # 5: sizeofcmds
+ 0, # 6: flags
+ 0, # 7: reserved
+
+ LC_SEGMENT_64, # 8: cmd
+ 4 * (45 - 7), # 9: cmdsize
+ '__TEXT', # 10-13: segname
+ 0, # 14-15: vmaddr
+ 0x1000, # 16-17: vmsize
+ 0, # 18-19: fileoff
+ 0x208, # 20-21: filesize
+ 7, # 22: maxprot (rwx)
+ 5, # 23: initprot (r-x)
+ 1, # 24: nsects
+ 0, # 25: flags
+
+ 'qtmetadata', # 26-29: sectname
+ '__TEXT', # 30-33: segname
+ 0x200, # 34-35: addr
+ 4, # 36-37: size
+ 0x200, # 38: offset
+ 3, # 39: align (2^3)
+ 0, # 40: reloff
+ 0, # 41: nreloc
+ 0, # 42: flags
+ 0, # 43: reserved1
+ 0, # 44: reserved2
+ 0, # 45: reserved3
+
+ 0x200,
+ 0xc0ffeec0ffee # data
+);
+
+my $fat = pack("L>*",
+ FAT_MAGIC, # 1: magic
+ 2, # 2: nfat_arch
+
+ CPU_TYPE_X86, # 3: cputype
+ CPU_SUBTYPE_I386_ALL, # 4: cpusubtype
+ 0x1000, # 5: offset
+ 0x1000, # 6: size
+ 12, # 7: align (2^12)
+
+ CPU_TYPE_X86_64, # 8: cputype
+ CPU_SUBTYPE_I386_ALL, # 9: cpusubtype
+ 0x2000, # 10: offset
+ 0x1000, # 11: size
+ 12, # 12: align (2^12)
+);
+
+my $buffer;
+
+our $badcount = 1;
+sub generate($) {
+ open OUT, ">", "bad$badcount.dylib" or die("Could not open file bad$badcount.dylib: $!\n");
+ binmode OUT;
+ print OUT $_[0];
+ close OUT;
+ ++$badcount;
+}
+
+# Bad file 1-2
+# Except that the cmdsize fields are null
+$buffer = $good;
+vec($buffer, 5, 32) = 0;
+generate $buffer;
+
+$buffer = $good;
+vec($buffer, 8, 32) = 0;
+generate $buffer;
+
+# Bad file 3-4: same as above but 64-bit
+$buffer = $good64;
+vec($buffer, 5, 32) = 0;
+generate $buffer;
+
+$buffer = $good64;
+vec($buffer, 9, 32) = 0;
+generate $buffer;
+
+# Bad file 5-8: same as 1-4, but set cmdsize to bigger than file
+$buffer = $good;
+vec($buffer, 5, 32) = 0x1000;
+generate $buffer;
+
+$buffer = $good;
+vec($buffer, 8, 32) = 0x1000;
+generate $buffer;
+
+$buffer = $good64;
+vec($buffer, 5, 32) = 0x1000;
+generate $buffer;
+
+$buffer = $good64;
+vec($buffer, 9, 32) = 0x1000;
+generate $buffer;
+
+# Bad file 9-10: overflow size+offset
+$buffer = $good;
+vec($buffer, 30, 32) = 0xffffffe0;
+generate $buffer;
+
+$buffer = $good64;
+vec($buffer, 36, 32) = 0xffffffff;
+vec($buffer, 37, 32) = 0xffffffe0;
+generate $buffer;
+
+# Bad file 11: FAT binary with just the header
+generate $fat;
+
+# Bad file 12: FAT binary where the Mach contents don't match the FAT directory
+$buffer = pack("a4096 a4096 a4096", $fat, $good64, $good);
+generate $buffer;
+
+# Bad file 13: FAT binary with overflowing size
+$buffer = pack("a4096 a4096 a4096", $fat, $good, $good64);
+vec($buffer, 5, 32) = 0xfffffffe0;
+vec($buffer, 10, 32) = 0xfffffffe0;
+generate $buffer;
diff --git a/tests/auto/corelib/plugin/qpluginloader/machtest/machtest.pro b/tests/auto/corelib/plugin/qpluginloader/machtest/machtest.pro
new file mode 100644
index 0000000000..b1183da84d
--- /dev/null
+++ b/tests/auto/corelib/plugin/qpluginloader/machtest/machtest.pro
@@ -0,0 +1,56 @@
+TEMPLATE = aux
+OTHER_FILES += \
+ ppcconverter.pl \
+ generate-bad.pl
+
+i386.target = good.i386.dylib
+i386.commands = $(CXX) -shared -arch i386 -o $@ -I$$[QT_INSTALL_HEADERS/get] $<
+i386.depends += $$PWD/../fakeplugin.cpp
+x86_64.target = good.x86_64.dylib
+x86_64.commands = $(CXX) -shared -arch x86_64 -o $@ -I$$[QT_INSTALL_HEADERS/get] $<
+x86_64.depends += $$PWD/../fakeplugin.cpp
+
+# Current Mac OS X toolchains have no compiler for PPC anymore
+# So we fake it by converting an x86-64 binary to (little-endian!) PPC64
+ppc64.target = good.ppc64.dylib
+ppc64.commands = $$PWD/ppcconverter.pl $< $@
+ppc64.depends = x86_64 $$PWD/ppcconverter.pl
+
+# Generate a fat binary with three architectures
+fat_all.target = good.fat.all.dylib
+fat_all.commands = lipo -create -output $@ \
+ -arch ppc64 $$ppc64.target \
+ -arch i386 $$i386.target \
+ -arch x86_64 $$x86_64.target
+fat_all.depends += i386 x86_64 ppc64
+
+fat_no_i386.target = good.fat.no-i386.dylib
+fat_no_i386.commands = lipo -create -output $@ -arch x86_64 $$x86_64.target -arch ppc64 $$ppc64.target
+fat_no_i386.depends += x86_64 ppc64
+
+fat_no_x86_64.target = good.fat.no-x86_64.dylib
+fat_no_x86_64.commands = lipo -create -output $@ -arch i386 $$i386.target -arch ppc64 $$ppc64.target
+fat_no_x86_64.depends += i386 ppc64
+
+fat_stub_i386.target = good.fat.stub-i386.dylib
+fat_stub_i386.commands = lipo -create -output $@ -arch ppc64 $$ppc64.target -arch_blank i386
+fat_stub_i386.depends += x86_64 ppc64
+
+fat_stub_x86_64.target = good.fat.stub-x86_64.dylib
+fat_stub_x86_64.commands = lipo -create -output $@ -arch ppc64 $$ppc64.target -arch_blank x86_64
+fat_stub_x86_64.depends += i386 ppc64
+
+bad.commands = $$PWD/generate-bad.pl
+bad.depends += $$PWD/generate-bad.pl
+
+MYTARGETS = $$fat_all.depends fat_all fat_no_x86_64 fat_no_i386 \
+ fat_stub_i386 fat_stub_x86_64 bad
+all.depends += $$MYTARGETS
+QMAKE_EXTRA_TARGETS += $$MYTARGETS all
+
+QMAKE_CLEAN += $$i386.target $$x86_64.target $$ppc64.target $$fat_all.target \
+ $$fat_no_i386.target $$fat_no_x86_64.target \
+ $$fat_stub_i386.target $$fat_stub_x86_64.target \
+ "bad*.dylib"
+
+
diff --git a/tests/auto/corelib/plugin/qpluginloader/machtest/ppcconverter.pl b/tests/auto/corelib/plugin/qpluginloader/machtest/ppcconverter.pl
new file mode 100755
index 0000000000..86943161b7
--- /dev/null
+++ b/tests/auto/corelib/plugin/qpluginloader/machtest/ppcconverter.pl
@@ -0,0 +1,112 @@
+#!/usr/bin/perl
+#############################################################################
+##
+## Copyright (C) 2013 Intel Corporation.
+## Contact: http://www.qt-project.org/legal
+##
+## This file is the build configuration utility 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$
+##
+#############################################################################
+
+# Changes the Mach-O file type header to PowerPC.
+#
+# The header is (from mach-o/loader.h):
+# struct mach_header {
+# uint32_t magic; /* mach magic number identifier */
+# cpu_type_t cputype; /* cpu specifier */
+# cpu_subtype_t cpusubtype; /* machine specifier */
+# uint32_t filetype; /* type of file */
+# uint32_t ncmds; /* number of load commands */
+# uint32_t sizeofcmds; /* the size of all the load commands */
+# uint32_t flags; /* flags */
+# };
+#
+# The 64-bit header is identical in the first three fields, except for a different
+# magic number. We will not touch the magic number, we'll just reset the cputype
+# field to the PowerPC type and the subtype field to zero.
+#
+# We will not change the file's endianness. That means we might create a little-endian
+# PowerPC binary, which could not be run in real life.
+#
+# We will also not change the 64-bit ABI flag, which is found in the cputype's high
+# byte. That means we'll create a PPC64 binary if fed a 64-bit input.
+#
+use strict;
+use constant MH_MAGIC => 0xfeedface;
+use constant MH_CIGAM => 0xcefaedfe;
+use constant MH_MAGIC_64 => 0xfeedfacf;
+use constant MH_CIGAM_64 => 0xcffaedfe;
+use constant CPU_TYPE_POWERPC => 18;
+use constant CPU_SUBTYPE_POWERPC_ALL => 0;
+
+my $infile = shift @ARGV or die("Missing input filename");
+my $outfile = shift @ARGV or die("Missing output filename");
+
+open IN, "<$infile" or die("Can't open $infile for reading: $!\n");
+open OUT, ">$outfile" or die("Can't open $outfile for writing: $!\n");
+
+binmode IN;
+binmode OUT;
+
+# Read the first 12 bytes, which includes the interesting fields of the header
+my $buffer;
+read(IN, $buffer, 12);
+
+my $magic = vec($buffer, 0, 32);
+if ($magic == MH_MAGIC || $magic == MH_MAGIC_64) {
+ # Big endian
+ # The low byte of cputype is at offset 7
+ vec($buffer, 7, 8) = CPU_TYPE_POWERPC;
+} elsif ($magic == MH_CIGAM || $magic == MH_CIGAM_64) {
+ # Little endian
+ # The low byte of cpytype is at offset 4
+ vec($buffer, 4, 8) = CPU_TYPE_POWERPC;
+} else {
+ $magic = '';
+ $magic .= sprintf("%02X ", $_) for unpack("CCCC", $buffer);
+ die("Invalid input. Unknown magic $magic\n");
+}
+vec($buffer, 2, 32) = CPU_SUBTYPE_POWERPC_ALL;
+
+print OUT $buffer;
+
+# Copy the rest
+while (!eof(IN)) {
+ read(IN, $buffer, 4096) and
+ print OUT $buffer or
+ die("Problem copying: $!\n");
+}
+close(IN);
+close(OUT);
diff --git a/tests/auto/corelib/plugin/qpluginloader/qpluginloader.pro b/tests/auto/corelib/plugin/qpluginloader/qpluginloader.pro
index 0cba19887e..8d117793bf 100644
--- a/tests/auto/corelib/plugin/qpluginloader/qpluginloader.pro
+++ b/tests/auto/corelib/plugin/qpluginloader/qpluginloader.pro
@@ -5,6 +5,7 @@ SUBDIRS = lib \
theplugin \
tst
!win32: !mac: SUBDIRS += almostplugin
+macx-*: SUBDIRS += machtest
TARGET = tst_qpluginloader
# no special install rule for subdir
diff --git a/tests/auto/corelib/plugin/qpluginloader/tst/tst.pro b/tests/auto/corelib/plugin/qpluginloader/tst/tst.pro
index a7a9661a54..3894c90ae3 100644
--- a/tests/auto/corelib/plugin/qpluginloader/tst/tst.pro
+++ b/tests/auto/corelib/plugin/qpluginloader/tst/tst.pro
@@ -2,7 +2,8 @@ CONFIG += testcase
CONFIG += parallel_test
TARGET = ../tst_qpluginloader
QT = core testlib
-SOURCES = ../tst_qpluginloader.cpp
+contains(QT_CONFIG, private_tests): QT += core-private
+SOURCES = ../tst_qpluginloader.cpp ../fakeplugin.cpp
HEADERS = ../theplugin/plugininterface.h
CONFIG -= app_bundle
@@ -14,5 +15,5 @@ win32 {
}
}
-TESTDATA += ../elftest
+TESTDATA += ../elftest ../machtest
DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
diff --git a/tests/auto/corelib/plugin/qpluginloader/tst_qpluginloader.cpp b/tests/auto/corelib/plugin/qpluginloader/tst_qpluginloader.cpp
index cef4f53101..351e3a23e0 100644
--- a/tests/auto/corelib/plugin/qpluginloader/tst_qpluginloader.cpp
+++ b/tests/auto/corelib/plugin/qpluginloader/tst_qpluginloader.cpp
@@ -44,6 +44,10 @@
#include <qpluginloader.h>
#include "theplugin/plugininterface.h"
+#if defined(QT_BUILD_INTERNAL) && defined(Q_OF_MACH_O)
+# include <QtCore/private/qmachparser_p.h>
+#endif
+
// Helper macros to let us know if some suffixes are valid
#define bundle_VALID false
#define dylib_VALID false
@@ -118,6 +122,8 @@ private slots:
void deleteinstanceOnUnload();
void loadDebugObj();
void loadCorruptElf();
+ void loadMachO_data();
+ void loadMachO();
#if defined (Q_OS_UNIX)
void loadGarbage();
#endif
@@ -311,6 +317,78 @@ void tst_QPluginLoader::loadCorruptElf()
#endif
}
+void tst_QPluginLoader::loadMachO_data()
+{
+#ifdef Q_OF_MACH_O
+ QTest::addColumn<int>("parseResult");
+
+ QTest::newRow("/dev/null") << int(QMachOParser::NotSuitable);
+ QTest::newRow("elftest/debugobj.so") << int(QMachOParser::NotSuitable);
+ QTest::newRow("tst_qpluginloader.cpp") << int(QMachOParser::NotSuitable);
+ QTest::newRow("tst_qpluginloader") << int(QMachOParser::NotSuitable);
+
+# ifdef Q_PROCESSOR_X86_64
+ QTest::newRow("machtest/good.x86_64.dylib") << int(QMachOParser::QtMetaDataSection);
+ QTest::newRow("machtest/good.i386.dylib") << int(QMachOParser::NotSuitable);
+ QTest::newRow("machtest/good.fat.no-x86_64.dylib") << int(QMachOParser::NotSuitable);
+ QTest::newRow("machtest/good.fat.no-i386.dylib") << int(QMachOParser::QtMetaDataSection);
+# elif defined(Q_PROCESSOR_X86_32)
+ QTest::newRow("machtest/good.i386.dylib") << int(QMachOParser::QtMetaDataSection);
+ QTest::newRow("machtest/good.x86_64.dylib") << int(QMachOParser::NotSuitable);
+ QTest::newRow("machtest/good.fat.no-i386.dylib") << int(QMachOParser::NotSuitable);
+ QTest::newRow("machtest/good.fat.no-x86_64.dylib") << int(QMachOParser::QtMetaDataSection);
+# endif
+# ifndef Q_PROCESSOR_POWER_64
+ QTest::newRow("machtest/good.ppc64.dylib") << int(QMachOParser::NotSuitable);
+# endif
+
+ QTest::newRow("machtest/good.fat.all.dylib") << int(QMachOParser::QtMetaDataSection);
+ QTest::newRow("machtest/good.fat.stub-x86_64.dylib") << int(QMachOParser::NotSuitable);
+ QTest::newRow("machtest/good.fat.stub-i386.dylib") << int(QMachOParser::NotSuitable);
+
+ QDir d(QFINDTESTDATA("machtest"));
+ QStringList badlist = d.entryList(QStringList() << "bad*.dylib");
+ foreach (const QString &bad, badlist)
+ QTest::newRow(qPrintable("machtest/" + bad)) << int(QMachOParser::NotSuitable);
+#endif
+}
+
+void tst_QPluginLoader::loadMachO()
+{
+#ifdef Q_OF_MACH_O
+ QFile f(QFINDTESTDATA(QTest::currentDataTag()));
+ QVERIFY(f.open(QIODevice::ReadOnly));
+ QByteArray data = f.readAll();
+
+ long pos;
+ ulong len;
+ QString errorString;
+ int r = QMachOParser::parse(data.constData(), data.size(), f.fileName(), &errorString, &pos, &len);
+
+ QFETCH(int, parseResult);
+ QCOMPARE(r, parseResult);
+
+ if (r == QMachOParser::NotSuitable)
+ return;
+
+ QVERIFY(pos > 0);
+ QVERIFY(len >= sizeof(void*));
+ QVERIFY(pos + long(len) < data.size());
+ QCOMPARE(pos & (sizeof(void*) - 1), 0UL);
+
+ void *value = *(void**)(data.constData() + pos);
+ QCOMPARE(value, sizeof(void*) > 4 ? (void*)(0xc0ffeec0ffeeL) : (void*)0xc0ffee);
+
+ // now that we know it's valid, let's try to make it invalid
+ ulong offeredlen = pos;
+ do {
+ --offeredlen;
+ r = QMachOParser::parse(data.constData(), offeredlen, f.fileName(), &errorString, &pos, &len);
+ QVERIFY2(r == QMachOParser::NotSuitable, qPrintable(QString("Failed at size 0x%1").arg(offeredlen, 0, 16)));
+ } while (offeredlen);
+#endif
+}
+
#if defined (Q_OS_UNIX)
void tst_QPluginLoader::loadGarbage()
{
diff --git a/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp b/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp
index 3c0e132a0a..fb34afb880 100644
--- a/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp
+++ b/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp
@@ -214,22 +214,22 @@ void tst_QThreadPool::waitcomplete()
QCOMPARE(testFunctionCount, runs);
}
-volatile bool ran;
+QAtomicInt ran; // bool
class TestTask : public QRunnable
{
public:
void run()
{
- ran = true;
+ ran.store(true);
}
};
void tst_QThreadPool::runTask()
{
QThreadPool manager;
- ran = false;
+ ran.store(false);
manager.start(new TestTask());
- QTRY_VERIFY(ran);
+ QTRY_VERIFY(ran.load());
}
/*
@@ -237,19 +237,19 @@ void tst_QThreadPool::runTask()
*/
void tst_QThreadPool::singleton()
{
- ran = false;
+ ran.store(false);
QThreadPool::globalInstance()->start(new TestTask());
- QTRY_VERIFY(ran);
+ QTRY_VERIFY(ran.load());
}
-int *value = 0;
+QAtomicInt *value = 0;
class IntAccessor : public QRunnable
{
public:
void run()
{
for (int i = 0; i < 100; ++i) {
- ++(*value);
+ value->ref();
QTest::qSleep(1);
}
}
@@ -261,7 +261,7 @@ public:
*/
void tst_QThreadPool::destruction()
{
- value = new int;
+ value = new QAtomicInt;
QThreadPool *threadManager = new QThreadPool();
threadManager->start(new IntAccessor());
threadManager->start(new IntAccessor());
@@ -681,8 +681,8 @@ void tst_QThreadPool::tryStart()
}
QMutex mutex;
-int activeThreads = 0;
-int peakActiveThreads = 0;
+QAtomicInt activeThreads;
+QAtomicInt peakActiveThreads;
void tst_QThreadPool::tryStartPeakThreadCount()
{
class CounterTask : public QRunnable
@@ -694,14 +694,14 @@ void tst_QThreadPool::tryStartPeakThreadCount()
{
{
QMutexLocker lock(&mutex);
- ++activeThreads;
- peakActiveThreads = qMax(peakActiveThreads, activeThreads);
+ activeThreads.ref();
+ peakActiveThreads.store(qMax(peakActiveThreads.load(), activeThreads.load()));
}
QTest::qWait(100);
{
QMutexLocker lock(&mutex);
- --activeThreads;
+ activeThreads.deref();
}
}
};
@@ -713,13 +713,13 @@ void tst_QThreadPool::tryStartPeakThreadCount()
if (threadPool.tryStart(&task) == false)
QTest::qWait(10);
}
- QCOMPARE(peakActiveThreads, QThread::idealThreadCount());
+ QCOMPARE(peakActiveThreads.load(), QThread::idealThreadCount());
for (int i = 0; i < 20; ++i) {
if (threadPool.tryStart(&task) == false)
QTest::qWait(10);
}
- QCOMPARE(peakActiveThreads, QThread::idealThreadCount());
+ QCOMPARE(peakActiveThreads.load(), QThread::idealThreadCount());
}
void tst_QThreadPool::tryStartCount()
diff --git a/tests/auto/corelib/tools/qalgorithms/tst_qalgorithms.cpp b/tests/auto/corelib/tools/qalgorithms/tst_qalgorithms.cpp
index 72bf5c58ca..c18ba4d05c 100644
--- a/tests/auto/corelib/tools/qalgorithms/tst_qalgorithms.cpp
+++ b/tests/auto/corelib/tools/qalgorithms/tst_qalgorithms.cpp
@@ -78,10 +78,22 @@ private slots:
void qCountContainer() const;
void binaryFindOnLargeContainer() const;
-#if Q_TEST_PERFORMANCE
+ void popCount08_data() { popCount_data_impl(sizeof(quint8 )); }
+ void popCount16_data() { popCount_data_impl(sizeof(quint16)); }
+ void popCount32_data() { popCount_data_impl(sizeof(quint32)); }
+ void popCount64_data() { popCount_data_impl(sizeof(quint64)); }
+ void popCount08() { popCount_impl<quint8 >(); }
+ void popCount16() { popCount_impl<quint16>(); }
+ void popCount32() { popCount_impl<quint32>(); }
+ void popCount64() { popCount_impl<quint64>(); }
+
private:
+#if Q_TEST_PERFORMANCE
void performance();
#endif
+ void popCount_data_impl(size_t sizeof_T_Int);
+ template <typename T_Int>
+ void popCount_impl();
};
class TestInt
@@ -1007,6 +1019,72 @@ void tst_QAlgorithms::binaryFindOnLargeContainer() const
QCOMPARE(foundIt.pos(), 1073987655);
}
+// alternative implementation of qPopulationCount for comparison:
+static const uint bitsSetInNibble[] = {
+ 0, 1, 1, 2, 1, 2, 2, 3,
+ 1, 2, 2, 3, 2, 3, 3, 4,
+};
+Q_STATIC_ASSERT(sizeof bitsSetInNibble / sizeof *bitsSetInNibble == 16);
+
+static Q_DECL_CONSTEXPR uint bitsSetInByte(quint8 byte)
+{
+ return bitsSetInNibble[byte & 0xF] + bitsSetInNibble[byte >> 4];
+}
+static Q_DECL_CONSTEXPR uint bitsSetInShort(quint16 word)
+{
+ return bitsSetInByte(word & 0xFF) + bitsSetInByte(word >> 8);
+}
+static Q_DECL_CONSTEXPR uint bitsSetInInt(quint32 word)
+{
+ return bitsSetInShort(word & 0xFFFF) + bitsSetInShort(word >> 16);
+}
+static Q_DECL_CONSTEXPR uint bitsSetInInt64(quint64 word)
+{
+ return bitsSetInInt(word & 0xFFFFFFFF) + bitsSetInInt(word >> 32);
+}
+
+
+void tst_QAlgorithms::popCount_data_impl(size_t sizeof_T_Int)
+{
+ using namespace QTest;
+ addColumn<quint64>("input");
+ addColumn<uint>("expected");
+
+ for (uint i = 0; i < UCHAR_MAX; ++i) {
+ const uchar byte = static_cast<uchar>(i);
+ const uint bits = bitsSetInByte(byte);
+ const quint64 value = static_cast<quint64>(byte);
+ const quint64 input = value << ((i % sizeof_T_Int) * 8U);
+ newRow(qPrintable(QString().sprintf("0x%016llx", input))) << input << bits;
+ }
+
+ // and some random ones:
+ if (sizeof_T_Int >= 8)
+ for (size_t i = 0; i < 1000; ++i) {
+ const quint64 input = quint64(qrand()) << 32 | quint32(qrand());
+ newRow(qPrintable(QString().sprintf("0x%016llx", input))) << input << bitsSetInInt64(input);
+ }
+ else if (sizeof_T_Int >= 2)
+ for (size_t i = 0; i < 1000 ; ++i) {
+ const quint32 input = qrand();
+ if (sizeof_T_Int >= 4)
+ newRow(qPrintable(QString().sprintf("0x%08x", input))) << quint64(input) << bitsSetInInt(input);
+ else
+ newRow(qPrintable(QString().sprintf("0x%04x", quint16(input & 0xFFFF)))) << quint64(input & 0xFFFF) << bitsSetInShort(input & 0xFFFF);
+ }
+}
+
+template <typename T_Int>
+void tst_QAlgorithms::popCount_impl()
+{
+ QFETCH(quint64, input);
+ QFETCH(uint, expected);
+
+ const T_Int value = static_cast<T_Int>(input);
+
+ QCOMPARE(qPopulationCount(value), expected);
+}
+
QTEST_APPLESS_MAIN(tst_QAlgorithms)
#include "tst_qalgorithms.moc"
diff --git a/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp b/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp
index 0ec3f64020..23c4eb33f6 100644
--- a/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp
+++ b/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp
@@ -556,22 +556,25 @@ void tst_QDateTime::toString_isoDate_data()
QTest::newRow("localtime")
<< QDateTime(QDate(1978, 11, 9), QTime(13, 28, 34))
- << QString("1978-11-09T13:28:34");
+ << QString("1978-11-09T13:28:34.000");
QTest::newRow("UTC")
<< QDateTime(QDate(1978, 11, 9), QTime(13, 28, 34), Qt::UTC)
- << QString("1978-11-09T13:28:34Z");
+ << QString("1978-11-09T13:28:34.000Z");
QDateTime dt(QDate(1978, 11, 9), QTime(13, 28, 34));
dt.setUtcOffset(19800);
QTest::newRow("positive OffsetFromUTC")
<< dt
- << QString("1978-11-09T13:28:34+05:30");
+ << QString("1978-11-09T13:28:34.000+05:30");
dt.setUtcOffset(-7200);
QTest::newRow("negative OffsetFromUTC")
<< dt
- << QString("1978-11-09T13:28:34-02:00");
+ << QString("1978-11-09T13:28:34.000-02:00");
QTest::newRow("invalid")
<< QDateTime(QDate(-1, 11, 9), QTime(13, 28, 34), Qt::UTC)
<< QString();
+ QTest::newRow("999 milliseconds UTC")
+ << QDateTime(QDate(2000, 1, 1), QTime(13, 28, 34, 999), Qt::UTC)
+ << QString("2000-01-01T13:28:34.999Z");
}
void tst_QDateTime::toString_isoDate()
@@ -591,7 +594,7 @@ void tst_QDateTime::toString_enumformat()
QVERIFY(!str1.isEmpty()); // It's locale dependent everywhere
QString str2 = dt1.toString(Qt::ISODate);
- QCOMPARE(str2, QString("1995-05-20T12:34:56"));
+ QCOMPARE(str2, QString("1995-05-20T12:34:56.000"));
QString str3 = dt1.toString(Qt::LocalDate);
QVERIFY(!str3.isEmpty());
@@ -1611,6 +1614,8 @@ void tst_QDateTime::fromStringDateFormat_data()
<< Qt::TextDate << invalidDateTime();
QTest::newRow("text invalid gmt minute") << QString::fromLatin1("Thu 1. Jan 1970 00:00:00 GMT+000X")
<< Qt::TextDate << invalidDateTime();
+ QTest::newRow("text second fraction") << QString::fromLatin1("Mon 6. May 2013 01:02:03.456")
+ << Qt::TextDate << QDateTime(QDate(2013, 5, 6), QTime(1, 2, 3, 456));
// Test Qt::ISODate format.
QTest::newRow("ISO +01:00") << QString::fromLatin1("1987-02-13T13:24:51+01:00")
diff --git a/tests/auto/corelib/tools/qtime/tst_qtime.cpp b/tests/auto/corelib/tools/qtime/tst_qtime.cpp
index 97645ea7f6..95aed05e7c 100644
--- a/tests/auto/corelib/tools/qtime/tst_qtime.cpp
+++ b/tests/auto/corelib/tools/qtime/tst_qtime.cpp
@@ -614,25 +614,27 @@ void tst_QTime::fromStringDateFormat()
void tst_QTime::toStringDateFormat_data()
{
- // Since we can't define an element of Qt::DateFormat, str1 will be the string
- // in TextDate format, and str2 will be the time in ISODate format.
-
- QTest::addColumn<QTime>("t");
- QTest::addColumn<QString>("str1");
- QTest::addColumn<QString>("str2");
-
- QTest::newRow( "data0" ) << QTime(0,0,0,0) << QString("00:00:00") << QString("00:00:00");
- QTest::newRow( "data1" ) << QTime(10,12,34,0) << QString("10:12:34") << QString("10:12:34");
+ QTest::addColumn<QTime>("time");
+ QTest::addColumn<Qt::DateFormat>("format");
+ QTest::addColumn<QString>("expected");
+
+ QTest::newRow("00:00:00.000") << QTime(0, 0, 0, 0) << Qt::TextDate << QString("00:00:00.000");
+ QTest::newRow("ISO 00:00:00.000") << QTime(0, 0, 0, 0) << Qt::ISODate << QString("00:00:00.000");
+ QTest::newRow("Text 10:12:34.000") << QTime(10, 12, 34, 0) << Qt::TextDate << QString("10:12:34.000");
+ QTest::newRow("ISO 10:12:34.000") << QTime(10, 12, 34, 0) << Qt::ISODate << QString("10:12:34.000");
+ QTest::newRow("Text 10:12:34.001") << QTime(10, 12, 34, 001) << Qt::TextDate << QString("10:12:34.001");
+ QTest::newRow("ISO 10:12:34.001") << QTime(10, 12, 34, 001) << Qt::ISODate << QString("10:12:34.001");
+ QTest::newRow("Text 10:12:34.999") << QTime(10, 12, 34, 999) << Qt::TextDate << QString("10:12:34.999");
+ QTest::newRow("ISO 10:12:34.999") << QTime(10, 12, 34, 999) << Qt::ISODate << QString("10:12:34.999");
}
void tst_QTime::toStringDateFormat()
{
- QFETCH( QTime, t );
- QFETCH( QString, str1 );
- QFETCH( QString, str2 );
+ QFETCH(QTime, time);
+ QFETCH(Qt::DateFormat, format);
+ QFETCH(QString, expected);
- QCOMPARE( str1, t.toString( Qt::TextDate ) );
- QCOMPARE( str2, t.toString( Qt::ISODate ) );
+ QCOMPARE(time.toString(format), expected);
}
void tst_QTime::toStringFormat_data()
diff --git a/tests/auto/dbus/qdbusabstractinterface/interface.h b/tests/auto/dbus/qdbusabstractinterface/interface.h
index 5db59b19eb..ecf732ce2d 100644
--- a/tests/auto/dbus/qdbusabstractinterface/interface.h
+++ b/tests/auto/dbus/qdbusabstractinterface/interface.h
@@ -43,6 +43,7 @@
#define INTERFACE_H
#include <QtCore/QObject>
+#include <QtCore/QHash>
#include <QtDBus/QDBusArgument>
struct RegisteredType
@@ -103,7 +104,7 @@ public slots:
Q_SCRIPTABLE void voidMethod() {}
Q_SCRIPTABLE int sleepMethod(int);
Q_SCRIPTABLE QString stringMethod() { return "Hello, world"; }
- Q_SCRIPTABLE RegisteredType complexMethod() { return RegisteredType("Hello, world"); }
+ Q_SCRIPTABLE RegisteredType complexMethod(const QVariantHash &vars) { return RegisteredType(vars.value("arg1").toString()); }
Q_SCRIPTABLE QString multiOutMethod(int &value) { value = 42; return "Hello, world"; }
signals:
diff --git a/tests/auto/dbus/qdbusabstractinterface/org.qtproject.QtDBus.Pinger.xml b/tests/auto/dbus/qdbusabstractinterface/org.qtproject.QtDBus.Pinger.xml
index 845e7be5b4..ad61351cb2 100644
--- a/tests/auto/dbus/qdbusabstractinterface/org.qtproject.QtDBus.Pinger.xml
+++ b/tests/auto/dbus/qdbusabstractinterface/org.qtproject.QtDBus.Pinger.xml
@@ -8,7 +8,7 @@
</property>
<signal name="voidSignal"/>
<signal name="stringSignal">
- <arg type="s"/>
+ <arg type="s" name="string-data"/>
</signal>
<signal name="complexSignal">
<arg name="" type="(s)"/>
@@ -23,6 +23,8 @@
<arg type="s" direction="out"/>
</method>
<method name="complexMethod">
+ <annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="QHash&lt;QString,QVariant&gt;"/>
+ <arg type='a{sv}' name='platform_data' direction='in'/>
<arg type="(s)" direction="out"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="RegisteredType"/>
</method>
diff --git a/tests/auto/dbus/qdbusabstractinterface/pinger.h b/tests/auto/dbus/qdbusabstractinterface/pinger.h
deleted file mode 100644
index 6bed72c203..0000000000
--- a/tests/auto/dbus/qdbusabstractinterface/pinger.h
+++ /dev/null
@@ -1,152 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtDBus 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$
-**
-****************************************************************************/
-
-/*
- * This file was generated by qdbusxml2cpp version 0.7
- * Command line was: qdbusxml2cpp -i interface.h -p pinger org.qtproject.QtDBus.Pinger.xml
- *
- * qdbusxml2cpp is Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
- *
- * This is an auto-generated file.
- * Do not edit! All changes made to it will be lost.
- */
-
-#ifndef PINGER_H_1246463415
-#define PINGER_H_1246463415
-
-#include <QtCore/QObject>
-#include <QtCore/QByteArray>
-#include <QtCore/QList>
-#include <QtCore/QMap>
-#include <QtCore/QString>
-#include <QtCore/QStringList>
-#include <QtCore/QVariant>
-#include <QtDBus/QtDBus>
-#include "interface.h"
-
-/*
- * Proxy class for interface org.qtproject.QtDBus.Pinger
- */
-class ComTrolltechQtDBusPingerInterface: public QDBusAbstractInterface
-{
- Q_OBJECT
-public:
- static inline const char *staticInterfaceName()
- { return "org.qtproject.QtDBus.Pinger"; }
-
-public:
- ComTrolltechQtDBusPingerInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0);
-
- ~ComTrolltechQtDBusPingerInterface();
-
- Q_PROPERTY(RegisteredType complexProp READ complexProp WRITE setComplexProp)
- inline RegisteredType complexProp() const
- { return qvariant_cast< RegisteredType >(property("complexProp")); }
- inline void setComplexProp(RegisteredType value)
- { setProperty("complexProp", QVariant::fromValue(value)); }
-
- Q_PROPERTY(QString stringProp READ stringProp WRITE setStringProp)
- inline QString stringProp() const
- { return qvariant_cast< QString >(property("stringProp")); }
- inline void setStringProp(const QString &value)
- { setProperty("stringProp", QVariant::fromValue(value)); }
-
- Q_PROPERTY(QDBusVariant variantProp READ variantProp WRITE setVariantProp)
- inline QDBusVariant variantProp() const
- { return qvariant_cast< QDBusVariant >(property("variantProp")); }
- inline void setVariantProp(const QDBusVariant &value)
- { setProperty("variantProp", QVariant::fromValue(value)); }
-
-public Q_SLOTS: // METHODS
- inline QDBusPendingReply<RegisteredType> complexMethod()
- {
- QList<QVariant> argumentList;
- return asyncCallWithArgumentList(QLatin1String("complexMethod"), argumentList);
- }
-
- inline QDBusPendingReply<QString, int> multiOutMethod()
- {
- QList<QVariant> argumentList;
- return asyncCallWithArgumentList(QLatin1String("multiOutMethod"), argumentList);
- }
- inline QDBusReply<QString> multiOutMethod(int &out1)
- {
- QList<QVariant> argumentList;
- QDBusMessage reply = callWithArgumentList(QDBus::Block, QLatin1String("multiOutMethod"), argumentList);
- if (reply.type() == QDBusMessage::ReplyMessage && reply.arguments().count() == 2) {
- out1 = qdbus_cast<int>(reply.arguments().at(1));
- }
- return reply;
- }
-
- inline QDBusPendingReply<int> sleepMethod(int in0)
- {
- QList<QVariant> argumentList;
- argumentList << QVariant::fromValue(in0);
- return asyncCallWithArgumentList(QLatin1String("sleepMethod"), argumentList);
- }
-
- inline QDBusPendingReply<QString> stringMethod()
- {
- QList<QVariant> argumentList;
- return asyncCallWithArgumentList(QLatin1String("stringMethod"), argumentList);
- }
-
- inline QDBusPendingReply<> voidMethod()
- {
- QList<QVariant> argumentList;
- return asyncCallWithArgumentList(QLatin1String("voidMethod"), argumentList);
- }
-
-Q_SIGNALS: // SIGNALS
- void complexSignal(RegisteredType in0);
- void stringSignal(const QString &in0);
- void voidSignal();
-};
-
-namespace com {
- namespace trolltech {
- namespace QtDBus {
- typedef ::ComTrolltechQtDBusPingerInterface Pinger;
- }
- }
-}
-#endif
diff --git a/tests/auto/dbus/qdbusabstractinterface/test/test.pro b/tests/auto/dbus/qdbusabstractinterface/test/test.pro
index 363d5fdf9c..66744b9252 100644
--- a/tests/auto/dbus/qdbusabstractinterface/test/test.pro
+++ b/tests/auto/dbus/qdbusabstractinterface/test/test.pro
@@ -2,13 +2,11 @@ CONFIG += testcase
SOURCES += ../tst_qdbusabstractinterface.cpp ../interface.cpp
HEADERS += ../interface.h
-# These are generated sources
-# To regenerate, see the command-line at the top of the files
-SOURCES += ../pinger.cpp
-HEADERS += ../pinger.h
-
TARGET = ../tst_qdbusabstractinterface
QT = core testlib
QT += dbus
DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
+
+DBUS_INTERFACES = ../org.qtproject.QtDBus.Pinger.xml
+QDBUSXML2CPP_INTERFACE_HEADER_FLAGS += -i ../interface.h
diff --git a/tests/auto/dbus/qdbusabstractinterface/tst_qdbusabstractinterface.cpp b/tests/auto/dbus/qdbusabstractinterface/tst_qdbusabstractinterface.cpp
index 5f3cf539e9..91e69fcdb7 100644
--- a/tests/auto/dbus/qdbusabstractinterface/tst_qdbusabstractinterface.cpp
+++ b/tests/auto/dbus/qdbusabstractinterface/tst_qdbusabstractinterface.cpp
@@ -47,13 +47,13 @@
#include <QtDBus>
#include "interface.h"
-#include "pinger.h"
+#include "pinger_interface.h"
static const char serviceName[] = "org.qtproject.autotests.qpinger";
static const char objectPath[] = "/org/qtproject/qpinger";
static const char *interfaceName = serviceName;
-typedef QSharedPointer<com::trolltech::QtDBus::Pinger> Pinger;
+typedef QSharedPointer<org::qtproject::QtDBus::Pinger> Pinger;
class tst_QDBusAbstractInterface: public QObject
{
@@ -67,7 +67,7 @@ class tst_QDBusAbstractInterface: public QObject
return Pinger();
if (service.isEmpty() && !service.isNull())
service = con.baseService();
- return Pinger(new com::trolltech::QtDBus::Pinger(service, path, con));
+ return Pinger(new org::qtproject::QtDBus::Pinger(service, path, con));
}
Pinger getPingerPeer(const QString &path = "/", const QString &service = "")
@@ -75,7 +75,7 @@ class tst_QDBusAbstractInterface: public QObject
QDBusConnection con = QDBusConnection("peer");
if (!con.isConnected())
return Pinger();
- return Pinger(new com::trolltech::QtDBus::Pinger(service, path, con));
+ return Pinger(new org::qtproject::QtDBus::Pinger(service, path, con));
}
void resetServer()
@@ -308,14 +308,22 @@ void tst_QDBusAbstractInterface::makeStringCall()
QCOMPARE(r.value(), targetObj.stringMethod());
}
+static QHash<QString, QVariant> complexMethodArgs()
+{
+ QHash<QString, QVariant> args;
+ args.insert("arg1", "Hello world");
+ args.insert("arg2", 12345);
+ return args;
+}
+
void tst_QDBusAbstractInterface::makeComplexCall()
{
Pinger p = getPinger();
QVERIFY2(p, "Not connected to D-Bus");
- QDBusReply<RegisteredType> r = p->complexMethod();
+ QDBusReply<RegisteredType> r = p->complexMethod(complexMethodArgs());
QVERIFY(r.isValid());
- QCOMPARE(r.value(), targetObj.complexMethod());
+ QCOMPARE(r.value(), targetObj.complexMethod(complexMethodArgs()));
}
void tst_QDBusAbstractInterface::makeMultiOutCall()
@@ -356,9 +364,9 @@ void tst_QDBusAbstractInterface::makeComplexCallPeer()
Pinger p = getPingerPeer();
QVERIFY2(p, "Not connected to D-Bus");
- QDBusReply<RegisteredType> r = p->complexMethod();
+ QDBusReply<RegisteredType> r = p->complexMethod(complexMethodArgs());
QVERIFY(r.isValid());
- QCOMPARE(r.value(), targetObj.complexMethod());
+ QCOMPARE(r.value(), targetObj.complexMethod(complexMethodArgs()));
}
void tst_QDBusAbstractInterface::makeMultiOutCallPeer()
@@ -401,10 +409,10 @@ void tst_QDBusAbstractInterface::makeAsyncComplexCall()
Pinger p = getPinger();
QVERIFY2(p, "Not connected to D-Bus");
- QDBusPendingReply<RegisteredType> r = p->complexMethod();
+ QDBusPendingReply<RegisteredType> r = p->complexMethod(complexMethodArgs());
r.waitForFinished();
QVERIFY(r.isValid());
- QCOMPARE(r.value(), targetObj.complexMethod());
+ QCOMPARE(r.value(), targetObj.complexMethod(complexMethodArgs()));
}
void tst_QDBusAbstractInterface::makeAsyncMultiOutCall()
@@ -449,10 +457,10 @@ void tst_QDBusAbstractInterface::makeAsyncComplexCallPeer()
Pinger p = getPingerPeer();
QVERIFY2(p, "Not connected to D-Bus");
- QDBusPendingReply<RegisteredType> r = p->complexMethod();
+ QDBusPendingReply<RegisteredType> r = p->complexMethod(complexMethodArgs());
r.waitForFinished();
QVERIFY(r.isValid());
- QCOMPARE(r.value(), targetObj.complexMethod());
+ QCOMPARE(r.value(), targetObj.complexMethod(complexMethodArgs()));
}
void tst_QDBusAbstractInterface::makeAsyncMultiOutCallPeer()
@@ -551,7 +559,7 @@ void tst_QDBusAbstractInterface::callWithTimeout()
}
// Now using generated code
- com::trolltech::QtDBus::Pinger p(server_serviceName, server_objectPath, QDBusConnection::sessionBus());
+ org::qtproject::QtDBus::Pinger p(server_serviceName, server_objectPath, QDBusConnection::sessionBus());
{
// Call with no timeout
QDBusReply<int> reply = p.sleepMethod(100);
diff --git a/tests/auto/gui/kernel/qbackingstore/qbackingstore.pro b/tests/auto/gui/kernel/qbackingstore/qbackingstore.pro
index c3113ed4b1..211be4c1c0 100644
--- a/tests/auto/gui/kernel/qbackingstore/qbackingstore.pro
+++ b/tests/auto/gui/kernel/qbackingstore/qbackingstore.pro
@@ -1,5 +1,4 @@
CONFIG += testcase
-CONFIG += parallel_test
TARGET = tst_qbackingstore
QT += core-private gui-private testlib
diff --git a/tests/auto/gui/kernel/qinputmethod/qinputmethod.pro b/tests/auto/gui/kernel/qinputmethod/qinputmethod.pro
index ff491c1e25..015cc782eb 100644
--- a/tests/auto/gui/kernel/qinputmethod/qinputmethod.pro
+++ b/tests/auto/gui/kernel/qinputmethod/qinputmethod.pro
@@ -1,5 +1,4 @@
CONFIG += testcase
-CONFIG += parallel_test
TARGET = tst_qinputmethod
SOURCES += tst_qinputmethod.cpp
QT += core-private gui-private testlib
diff --git a/tests/auto/gui/painting/qcolor/tst_qcolor.cpp b/tests/auto/gui/painting/qcolor/tst_qcolor.cpp
index 6fe7961545..1b1f5575b1 100644
--- a/tests/auto/gui/painting/qcolor/tst_qcolor.cpp
+++ b/tests/auto/gui/painting/qcolor/tst_qcolor.cpp
@@ -61,6 +61,8 @@ private slots:
void name_data();
void name();
+ void namehex_data();
+ void namehex();
void setNamedColor();
void constructNamedColorWithSpace();
@@ -254,36 +256,75 @@ void tst_QColor::isValid()
QVERIFY(color.isValid() == isValid);
}
+Q_DECLARE_METATYPE(QColor::NameFormat);
+
void tst_QColor::name_data()
{
QTest::addColumn<QColor>("color");
QTest::addColumn<QString>("name");
-
- QTest::newRow("invalid") << QColor() << "#000000";
- QTest::newRow("global color black") << QColor(Qt::black) << "#000000";
- QTest::newRow("global color white") << QColor(Qt::white) << "#ffffff";
- QTest::newRow("global color darkGray") << QColor(Qt::darkGray) << "#808080";
- QTest::newRow("global color gray") << QColor(Qt::gray) << "#a0a0a4";
- QTest::newRow("global color lightGray") << QColor(Qt::lightGray) << "#c0c0c0";
- QTest::newRow("global color red") << QColor(Qt::red) << "#ff0000";
- QTest::newRow("global color green") << QColor(Qt::green) << "#00ff00";
- QTest::newRow("global color blue") << QColor(Qt::blue) << "#0000ff";
- QTest::newRow("global color cyan") << QColor(Qt::cyan) << "#00ffff";
- QTest::newRow("global color magenta") << QColor(Qt::magenta) << "#ff00ff";
- QTest::newRow("global color yellow") << QColor(Qt::yellow) << "#ffff00";
- QTest::newRow("global color darkRed") << QColor(Qt::darkRed) << "#800000";
- QTest::newRow("global color darkGreen") << QColor(Qt::darkGreen) << "#008000";
- QTest::newRow("global color darkBlue") << QColor(Qt::darkBlue) << "#000080";
- QTest::newRow("global color darkCyan") << QColor(Qt::darkCyan) << "#008080";
- QTest::newRow("global color darkMagenta") << QColor(Qt::darkMagenta) << "#800080";
- QTest::newRow("global color darkYellow") << QColor(Qt::darkYellow) << "#808000";
+ QTest::addColumn<QColor::NameFormat>("nameFormat");
+
+ QTest::newRow("invalid") << QColor() << "#000000" << QColor::HexRgb;
+ QTest::newRow("global color black") << QColor(Qt::black) << "#000000" << QColor::HexRgb;
+ QTest::newRow("global color white") << QColor(Qt::white) << "#ffffff" << QColor::HexRgb;
+ QTest::newRow("global color darkGray") << QColor(Qt::darkGray) << "#808080" << QColor::HexRgb;
+ QTest::newRow("global color gray") << QColor(Qt::gray) << "#a0a0a4" << QColor::HexRgb;
+ QTest::newRow("global color lightGray") << QColor(Qt::lightGray) << "#c0c0c0" << QColor::HexRgb;
+ QTest::newRow("global color red") << QColor(Qt::red) << "#ff0000" << QColor::HexRgb;
+ QTest::newRow("global color green") << QColor(Qt::green) << "#00ff00" << QColor::HexRgb;
+ QTest::newRow("global color blue") << QColor(Qt::blue) << "#0000ff" << QColor::HexRgb;
+ QTest::newRow("global color cyan") << QColor(Qt::cyan) << "#00ffff" << QColor::HexRgb;
+ QTest::newRow("global color magenta") << QColor(Qt::magenta) << "#ff00ff" << QColor::HexRgb;
+ QTest::newRow("global color yellow") << QColor(Qt::yellow) << "#ffff00" << QColor::HexRgb;
+ QTest::newRow("global color darkRed") << QColor(Qt::darkRed) << "#800000" << QColor::HexRgb;
+ QTest::newRow("global color darkGreen") << QColor(Qt::darkGreen) << "#008000" << QColor::HexRgb;
+ QTest::newRow("global color darkBlue") << QColor(Qt::darkBlue) << "#000080" << QColor::HexRgb;
+ QTest::newRow("global color darkCyan") << QColor(Qt::darkCyan) << "#008080" << QColor::HexRgb;
+ QTest::newRow("global color darkMagenta") << QColor(Qt::darkMagenta) << "#800080" << QColor::HexRgb;
+ QTest::newRow("global color darkYellow") << QColor(Qt::darkYellow) << "#808000" << QColor::HexRgb;
+ QTest::newRow("transparent red") << QColor(255, 0, 0, 102) << "#66ff0000" << QColor::HexArgb;
}
void tst_QColor::name()
{
QFETCH(QColor, color);
QFETCH(QString, name);
- QCOMPARE(color.name(), name);
+ QFETCH(QColor::NameFormat, nameFormat);
+ QCOMPARE(color.name(nameFormat), name);
+}
+
+void tst_QColor::namehex_data()
+{
+ QTest::addColumn<QString>("hexcolor");
+ QTest::addColumn<QColor>("color");
+
+ QTest::newRow("global color black") << "#000000" << QColor(Qt::black);
+ QTest::newRow("global color white") << "#ffffff" << QColor(Qt::white);
+ QTest::newRow("global color darkGray") << "#808080" << QColor(Qt::darkGray);
+ QTest::newRow("global color gray") << "#a0a0a4" << QColor(Qt::gray);
+ QTest::newRow("global color lightGray") << "#c0c0c0" << QColor(Qt::lightGray);
+ QTest::newRow("global color red") << "#ff0000" << QColor(Qt::red);
+ QTest::newRow("global color green") << "#00ff00" << QColor(Qt::green);
+ QTest::newRow("global color blue") << "#0000ff" << QColor(Qt::blue);
+ QTest::newRow("global color cyan") << "#00ffff" << QColor(Qt::cyan);
+ QTest::newRow("global color magenta") << "#ff00ff" << QColor(Qt::magenta);
+ QTest::newRow("global color yellow") << "#ffff00" << QColor(Qt::yellow);
+ QTest::newRow("global color darkRed") << "#800000" << QColor(Qt::darkRed);
+ QTest::newRow("global color darkGreen") << "#008000" << QColor(Qt::darkGreen);
+ QTest::newRow("global color darkBlue") << "#000080" << QColor(Qt::darkBlue);
+ QTest::newRow("global color darkCyan") << "#008080" << QColor(Qt::darkCyan);
+ QTest::newRow("global color darkMagenta") << "#800080" << QColor(Qt::darkMagenta);
+ QTest::newRow("global color darkYellow") << "#808000" << QColor(Qt::darkYellow);
+ QTest::newRow("transparent red") << "#66ff0000" << QColor(255, 0, 0, 102);
+ QTest::newRow("invalid red") << "#gg0000" << QColor();
+ QTest::newRow("invalid transparent") << "#gg00ff00" << QColor();
+}
+
+void tst_QColor::namehex()
+{
+ QFETCH(QString, hexcolor);
+ QFETCH(QColor, color);
+ QCOMPARE(QColor(hexcolor), color);
}
void tst_QColor::globalColors_data()
diff --git a/tests/auto/gui/text/qcssparser/tst_qcssparser.cpp b/tests/auto/gui/text/qcssparser/tst_qcssparser.cpp
index ca6c42c9bd..86e282fad2 100644
--- a/tests/auto/gui/text/qcssparser/tst_qcssparser.cpp
+++ b/tests/auto/gui/text/qcssparser/tst_qcssparser.cpp
@@ -344,8 +344,6 @@ void tst_QCssParser::term_data()
val.variant = QVariant(QColor("#ffbb00"));
QTest::newRow("hexcolor2") << true << "#fb0" << val;
- QTest::newRow("hexcolor_failure") << false << "#cafebabe" << val;
-
val.type = QCss::Value::Uri;
val.variant = QString("www.kde.org");
QTest::newRow("uri1") << true << "url(\"www.kde.org\")" << val;
@@ -367,9 +365,6 @@ void tst_QCssParser::term()
QFETCH(QString, css);
QFETCH(QCss::Value, expectedValue);
- if (strcmp(QTest::currentDataTag(), "hexcolor_failure") == 0)
- QTest::ignoreMessage(QtWarningMsg, "QCssParser::parseHexColor: Unknown color name '#cafebabe'");
-
QCss::Parser parser(css);
QCss::Value val;
QVERIFY(parser.testTerm());
diff --git a/tests/auto/gui/text/qfontdatabase/qfontdatabase.pro b/tests/auto/gui/text/qfontdatabase/qfontdatabase.pro
index 37868dcfde..6975c4088b 100644
--- a/tests/auto/gui/text/qfontdatabase/qfontdatabase.pro
+++ b/tests/auto/gui/text/qfontdatabase/qfontdatabase.pro
@@ -2,8 +2,7 @@ CONFIG += testcase
CONFIG += parallel_test
TARGET = tst_qfontdatabase
SOURCES += tst_qfontdatabase.cpp
-QT += testlib
-!mac: QT += core-private gui-private
+QT += testlib core-private gui-private
wince* {
additionalFiles.files = FreeMono.ttf
diff --git a/tests/auto/gui/text/qfontdatabase/tst_qfontdatabase.cpp b/tests/auto/gui/text/qfontdatabase/tst_qfontdatabase.cpp
index 9cf4082287..63da383596 100644
--- a/tests/auto/gui/text/qfontdatabase/tst_qfontdatabase.cpp
+++ b/tests/auto/gui/text/qfontdatabase/tst_qfontdatabase.cpp
@@ -44,6 +44,7 @@
#include <qfontdatabase.h>
#include <qfontinfo.h>
#include <qfontmetrics.h>
+#include <qpa/qplatformfontdatabase.h>
class tst_QFontDatabase : public QObject
{
@@ -277,10 +278,6 @@ void tst_QFontDatabase::addAppFont()
QCOMPARE(db.families(), oldFamilies);
}
-QT_BEGIN_NAMESPACE
-Q_GUI_EXPORT void qt_registerAliasToFontFamily(const QString &familyName, const QString &alias);
-QT_END_NAMESPACE
-
void tst_QFontDatabase::aliases()
{
QFontDatabase db;
@@ -290,7 +287,7 @@ void tst_QFontDatabase::aliases()
QVERIFY(db.hasFamily(firstFont));
const QString alias = QStringLiteral("AliasToFirstFont") + firstFont;
QVERIFY(!db.hasFamily(alias));
- qt_registerAliasToFontFamily(firstFont, alias);
+ QPlatformFontDatabase::registerAliasToFontFamily(firstFont, alias);
QVERIFY(db.hasFamily(alias));
}
diff --git a/tests/auto/network/access/qnetworkaccessmanager/tst_qnetworkaccessmanager.cpp b/tests/auto/network/access/qnetworkaccessmanager/tst_qnetworkaccessmanager.cpp
index 25301feee4..125eab2f8c 100644
--- a/tests/auto/network/access/qnetworkaccessmanager/tst_qnetworkaccessmanager.cpp
+++ b/tests/auto/network/access/qnetworkaccessmanager/tst_qnetworkaccessmanager.cpp
@@ -77,30 +77,43 @@ void tst_QNetworkAccessManager::networkAccessible()
QSignalSpy spy(&manager,
SIGNAL(networkAccessibleChanged(QNetworkAccessManager::NetworkAccessibility)));
- QCOMPARE(manager.networkAccessible(), QNetworkAccessManager::UnknownAccessibility);
+ // if there is no session, we cannot know in which state we are in
+ QNetworkAccessManager::NetworkAccessibility initialAccessibility =
+ manager.networkAccessible();
+ QCOMPARE(manager.networkAccessible(), initialAccessibility);
manager.setNetworkAccessible(QNetworkAccessManager::NotAccessible);
- QCOMPARE(spy.count(), 1);
- QCOMPARE(spy.takeFirst().at(0).value<QNetworkAccessManager::NetworkAccessibility>(),
- QNetworkAccessManager::NotAccessible);
+ int expectedCount = (initialAccessibility == QNetworkAccessManager::Accessible) ? 1 : 0;
+ QCOMPARE(spy.count(), expectedCount);
+ if (expectedCount > 0)
+ QCOMPARE(spy.takeFirst().at(0).value<QNetworkAccessManager::NetworkAccessibility>(),
+ QNetworkAccessManager::NotAccessible);
QCOMPARE(manager.networkAccessible(), QNetworkAccessManager::NotAccessible);
manager.setNetworkAccessible(QNetworkAccessManager::Accessible);
- QCOMPARE(spy.count(), 1);
- QCOMPARE(spy.takeFirst().at(0).value<QNetworkAccessManager::NetworkAccessibility>(),
- QNetworkAccessManager::UnknownAccessibility);
- QCOMPARE(manager.networkAccessible(), QNetworkAccessManager::UnknownAccessibility);
+ QCOMPARE(spy.count(), expectedCount);
+ if (expectedCount > 0)
+ QCOMPARE(spy.takeFirst().at(0).value<QNetworkAccessManager::NetworkAccessibility>(),
+ initialAccessibility);
+ QCOMPARE(manager.networkAccessible(), initialAccessibility);
QNetworkConfigurationManager configManager;
+ bool sessionRequired = (configManager.capabilities()
+ & QNetworkConfigurationManager::NetworkSessionRequired);
QNetworkConfiguration defaultConfig = configManager.defaultConfiguration();
if (defaultConfig.isValid()) {
manager.setConfiguration(defaultConfig);
- QCOMPARE(spy.count(), 1);
- QCOMPARE(spy.takeFirst().at(0).value<QNetworkAccessManager::NetworkAccessibility>(),
- QNetworkAccessManager::Accessible);
+ // the accessibility has not changed if no session is required
+ if (sessionRequired) {
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.takeFirst().at(0).value<QNetworkAccessManager::NetworkAccessibility>(),
+ QNetworkAccessManager::Accessible);
+ } else {
+ QCOMPARE(spy.count(), 0);
+ }
QCOMPARE(manager.networkAccessible(), QNetworkAccessManager::Accessible);
manager.setNetworkAccessible(QNetworkAccessManager::NotAccessible);
diff --git a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp
index 5c04ac8a01..2bf8f71d31 100644
--- a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp
+++ b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp
@@ -367,6 +367,8 @@ private Q_SLOTS:
#ifdef QT_BUILD_INTERNAL
void sslSessionSharing_data();
void sslSessionSharing();
+ void sslSessionSharingFromPersistentSession_data();
+ void sslSessionSharingFromPersistentSession();
#endif
#endif
@@ -5920,7 +5922,7 @@ void tst_QNetworkReply::sslSessionSharing()
warmupRequest.setAttribute(QNetworkRequest::User, sessionSharingEnabled); // so we can read it from the slot
if (! sessionSharingEnabled) {
QSslConfiguration configuration(QSslConfiguration::defaultConfiguration());
- configuration.setSslOption(QSsl::SslOptionDisableSessionTickets, true);
+ configuration.setSslOption(QSsl::SslOptionDisableSessionSharing, true);
warmupRequest.setSslConfiguration(configuration);
}
QNetworkReply *reply = manager.get(warmupRequest);
@@ -5966,6 +5968,63 @@ void tst_QNetworkReply::sslSessionSharingHelperSlot()
}
}
+void tst_QNetworkReply::sslSessionSharingFromPersistentSession_data()
+{
+ QTest::addColumn<bool>("sessionPersistenceEnabled");
+ QTest::newRow("enabled") << true;
+ QTest::newRow("disabled") << false;
+}
+
+void tst_QNetworkReply::sslSessionSharingFromPersistentSession()
+{
+ QString urlString("https://" + QtNetworkSettings::serverName());
+
+ // warm up SSL session cache to get a working session
+ QNetworkRequest warmupRequest(urlString);
+ QFETCH(bool, sessionPersistenceEnabled);
+ if (sessionPersistenceEnabled) {
+ QSslConfiguration warmupConfiguration(QSslConfiguration::defaultConfiguration());
+ warmupConfiguration.setSslOption(QSsl::SslOptionDisableSessionPersistence, false);
+ warmupRequest.setSslConfiguration(warmupConfiguration);
+ }
+ QNetworkReply *warmupReply = manager.get(warmupRequest);
+ warmupReply->ignoreSslErrors();
+ connect(warmupReply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()));
+ QTestEventLoop::instance().enterLoop(20);
+ QVERIFY(!QTestEventLoop::instance().timeout());
+ QCOMPARE(warmupReply->error(), QNetworkReply::NoError);
+ QByteArray sslSession = warmupReply->sslConfiguration().session();
+ QCOMPARE(!sslSession.isEmpty(), sessionPersistenceEnabled);
+
+ // test server sends a life time hint of 0, which is not common
+ // practice; however it is good enough because the default is -1
+ int expectedSessionTicketLifeTimeHint = sessionPersistenceEnabled ? 0 : -1;
+ QCOMPARE(warmupReply->sslConfiguration().sessionTicketLifeTimeHint(),
+ expectedSessionTicketLifeTimeHint);
+
+ warmupReply->deleteLater();
+
+ // now send another request with a new QNAM and the persisted session,
+ // to verify it can be resumed without any internal state
+ QNetworkRequest request(warmupRequest);
+ if (sessionPersistenceEnabled) {
+ QSslConfiguration configuration = request.sslConfiguration();
+ configuration.setSession(sslSession);
+ request.setSslConfiguration(configuration);
+ }
+ QNetworkAccessManager newManager;
+ QNetworkReply *reply = newManager.get(request);
+ reply->ignoreSslErrors();
+ connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()));
+ QTestEventLoop::instance().enterLoop(20);
+ QVERIFY(!QTestEventLoop::instance().timeout());
+ QCOMPARE(reply->error(), QNetworkReply::NoError);
+
+ bool sslSessionSharingWasUsedInReply = QSslConfigurationPrivate::peerSessionWasShared(
+ reply->sslConfiguration());
+ QCOMPARE(sessionPersistenceEnabled, sslSessionSharingWasUsedInReply);
+}
+
#endif // QT_BUILD_INTERNAL
#endif // QT_NO_SSL
diff --git a/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp b/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp
index 2b9dfc5081..ee5c7e42d8 100644
--- a/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp
+++ b/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp
@@ -513,7 +513,7 @@ void tst_QTcpSocket::bind()
{
QFETCH_GLOBAL(bool, setProxy);
if (setProxy)
- QSKIP("QTBUG-22964");
+ return; // QTBUG-22964 for proxies, QTBUG-29972 for QSKIP
QFETCH(QString, stringAddr);
QFETCH(bool, successExpected);
QFETCH(QString, stringExpectedLocalAddress);
diff --git a/tests/auto/testlib/selftests/expected_cmptest.lightxml b/tests/auto/testlib/selftests/expected_cmptest.lightxml
index 54c5bb85f0..99e2e825c0 100644
--- a/tests/auto/testlib/selftests/expected_cmptest.lightxml
+++ b/tests/auto/testlib/selftests/expected_cmptest.lightxml
@@ -15,7 +15,7 @@
<Incident type="fail" file="/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp" line="214">
<DataTag><![CDATA[int, string]]></DataTag>
<Description><![CDATA[Compared values are not the same
- Actual (actual): QVariant(int,123)
+ Actual (actual) : QVariant(int,123)
Expected (expected): QVariant(QString,hi)]]></Description>
</Incident>
<Incident type="pass" file="" line="0">
@@ -24,19 +24,19 @@
<Incident type="fail" file="/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp" line="214">
<DataTag><![CDATA[null hash, invalid]]></DataTag>
<Description><![CDATA[Compared values are not the same
- Actual (actual): QVariant(QVariantHash)
+ Actual (actual) : QVariant(QVariantHash)
Expected (expected): QVariant()]]></Description>
</Incident>
<Incident type="fail" file="/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp" line="214">
<DataTag><![CDATA[string, null user type]]></DataTag>
<Description><![CDATA[Compared values are not the same
- Actual (actual): QVariant(QString,A simple string)
+ Actual (actual) : QVariant(QString,A simple string)
Expected (expected): QVariant(PhonyClass)]]></Description>
</Incident>
<Incident type="fail" file="/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp" line="214">
<DataTag><![CDATA[both non-null user type]]></DataTag>
<Description><![CDATA[Compared values are not the same
- Actual (actual): QVariant(PhonyClass,<value not representable as string>)
+ Actual (actual) : QVariant(PhonyClass,<value not representable as string>)
Expected (expected): QVariant(PhonyClass,<value not representable as string>)]]></Description>
</Incident>
</TestFunction>
diff --git a/tests/auto/testlib/selftests/expected_cmptest.txt b/tests/auto/testlib/selftests/expected_cmptest.txt
index 9d03a8e3da..504507f032 100644
--- a/tests/auto/testlib/selftests/expected_cmptest.txt
+++ b/tests/auto/testlib/selftests/expected_cmptest.txt
@@ -4,20 +4,20 @@ PASS : tst_Cmptest::initTestCase()
PASS : tst_Cmptest::compare_boolfuncs()
PASS : tst_Cmptest::compare_pointerfuncs()
FAIL! : tst_Cmptest::compare_tostring(int, string) Compared values are not the same
- Actual (actual): QVariant(int,123)
+ Actual (actual) : QVariant(int,123)
Expected (expected): QVariant(QString,hi)
Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp(214)]
PASS : tst_Cmptest::compare_tostring(both invalid)
FAIL! : tst_Cmptest::compare_tostring(null hash, invalid) Compared values are not the same
- Actual (actual): QVariant(QVariantHash)
+ Actual (actual) : QVariant(QVariantHash)
Expected (expected): QVariant()
Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp(214)]
FAIL! : tst_Cmptest::compare_tostring(string, null user type) Compared values are not the same
- Actual (actual): QVariant(QString,A simple string)
+ Actual (actual) : QVariant(QString,A simple string)
Expected (expected): QVariant(PhonyClass)
Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp(214)]
FAIL! : tst_Cmptest::compare_tostring(both non-null user type) Compared values are not the same
- Actual (actual): QVariant(PhonyClass,<value not representable as string>)
+ Actual (actual) : QVariant(PhonyClass,<value not representable as string>)
Expected (expected): QVariant(PhonyClass,<value not representable as string>)
Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp(214)]
PASS : tst_Cmptest::compareQStringLists(empty lists)
diff --git a/tests/auto/testlib/selftests/expected_cmptest.xml b/tests/auto/testlib/selftests/expected_cmptest.xml
index ccab93d7c0..df35058acc 100644
--- a/tests/auto/testlib/selftests/expected_cmptest.xml
+++ b/tests/auto/testlib/selftests/expected_cmptest.xml
@@ -17,7 +17,7 @@
<Incident type="fail" file="/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp" line="214">
<DataTag><![CDATA[int, string]]></DataTag>
<Description><![CDATA[Compared values are not the same
- Actual (actual): QVariant(int,123)
+ Actual (actual) : QVariant(int,123)
Expected (expected): QVariant(QString,hi)]]></Description>
</Incident>
<Incident type="pass" file="" line="0">
@@ -26,19 +26,19 @@
<Incident type="fail" file="/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp" line="214">
<DataTag><![CDATA[null hash, invalid]]></DataTag>
<Description><![CDATA[Compared values are not the same
- Actual (actual): QVariant(QVariantHash)
+ Actual (actual) : QVariant(QVariantHash)
Expected (expected): QVariant()]]></Description>
</Incident>
<Incident type="fail" file="/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp" line="214">
<DataTag><![CDATA[string, null user type]]></DataTag>
<Description><![CDATA[Compared values are not the same
- Actual (actual): QVariant(QString,A simple string)
+ Actual (actual) : QVariant(QString,A simple string)
Expected (expected): QVariant(PhonyClass)]]></Description>
</Incident>
<Incident type="fail" file="/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp" line="214">
<DataTag><![CDATA[both non-null user type]]></DataTag>
<Description><![CDATA[Compared values are not the same
- Actual (actual): QVariant(PhonyClass,<value not representable as string>)
+ Actual (actual) : QVariant(PhonyClass,<value not representable as string>)
Expected (expected): QVariant(PhonyClass,<value not representable as string>)]]></Description>
</Incident>
</TestFunction>
diff --git a/tests/auto/testlib/selftests/expected_cmptest.xunitxml b/tests/auto/testlib/selftests/expected_cmptest.xunitxml
index 0cb88147b0..e7d76ac839 100644
--- a/tests/auto/testlib/selftests/expected_cmptest.xunitxml
+++ b/tests/auto/testlib/selftests/expected_cmptest.xunitxml
@@ -9,16 +9,16 @@
<testcase result="pass" name="compare_pointerfuncs"/>
<testcase result="fail" name="compare_tostring">
<failure tag="int, string" message="Compared values are not the same
- Actual (actual): QVariant(int,123)
+ Actual (actual) : QVariant(int,123)
Expected (expected): QVariant(QString,hi)" result="fail"/>
<failure tag="null hash, invalid" message="Compared values are not the same
- Actual (actual): QVariant(QVariantHash)
+ Actual (actual) : QVariant(QVariantHash)
Expected (expected): QVariant()" result="fail"/>
<failure tag="string, null user type" message="Compared values are not the same
- Actual (actual): QVariant(QString,A simple string)
+ Actual (actual) : QVariant(QString,A simple string)
Expected (expected): QVariant(PhonyClass)" result="fail"/>
<failure tag="both non&#x002D;null user type" message="Compared values are not the same
- Actual (actual): QVariant(PhonyClass,&lt;value not representable as string&gt;)
+ Actual (actual) : QVariant(PhonyClass,&lt;value not representable as string&gt;)
Expected (expected): QVariant(PhonyClass,&lt;value not representable as string&gt;)" result="fail"/>
</testcase>
<testcase result="fail" name="compareQStringLists">
diff --git a/tests/auto/testlib/selftests/expected_datetime.lightxml b/tests/auto/testlib/selftests/expected_datetime.lightxml
index d8acae9c26..183744b2e2 100644
--- a/tests/auto/testlib/selftests/expected_datetime.lightxml
+++ b/tests/auto/testlib/selftests/expected_datetime.lightxml
@@ -9,7 +9,7 @@
<Incident type="fail" file="/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/datetime/tst_datetime.cpp" line="66">
<Description><![CDATA[Compared values are not the same
Actual (local): 2000/05/03 04:03:04.000[local time]
- Expected (utc): 2000/05/03 04:03:04.000[UTC]]]></Description>
+ Expected (utc) : 2000/05/03 04:03:04.000[UTC]]]></Description>
</Incident>
</TestFunction>
<TestFunction name="qurl">
diff --git a/tests/auto/testlib/selftests/expected_datetime.txt b/tests/auto/testlib/selftests/expected_datetime.txt
index ce9e1f36b4..0cbc6506d5 100644
--- a/tests/auto/testlib/selftests/expected_datetime.txt
+++ b/tests/auto/testlib/selftests/expected_datetime.txt
@@ -3,7 +3,7 @@ Config: Using QtTest library @INSERT_QT_VERSION_HERE@, Qt @INSERT_QT_VERSION_HER
PASS : tst_DateTime::initTestCase()
FAIL! : tst_DateTime::dateTime() Compared values are not the same
Actual (local): 2000/05/03 04:03:04.000[local time]
- Expected (utc): 2000/05/03 04:03:04.000[UTC]
+ Expected (utc) : 2000/05/03 04:03:04.000[UTC]
Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/datetime/tst_datetime.cpp(33)]
PASS : tst_DateTime::qurl(empty urls)
FAIL! : tst_DateTime::qurl(empty rhs) Compared values are not the same
diff --git a/tests/auto/testlib/selftests/expected_datetime.xml b/tests/auto/testlib/selftests/expected_datetime.xml
index d7c9afabee..42b566c074 100644
--- a/tests/auto/testlib/selftests/expected_datetime.xml
+++ b/tests/auto/testlib/selftests/expected_datetime.xml
@@ -11,7 +11,7 @@
<Incident type="fail" file="/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/datetime/tst_datetime.cpp" line="66">
<Description><![CDATA[Compared values are not the same
Actual (local): 2000/05/03 04:03:04.000[local time]
- Expected (utc): 2000/05/03 04:03:04.000[UTC]]]></Description>
+ Expected (utc) : 2000/05/03 04:03:04.000[UTC]]]></Description>
</Incident>
</TestFunction>
<TestFunction name="qurl">
diff --git a/tests/auto/testlib/selftests/expected_datetime.xunitxml b/tests/auto/testlib/selftests/expected_datetime.xunitxml
index af0e4db7e8..00bd43f904 100644
--- a/tests/auto/testlib/selftests/expected_datetime.xunitxml
+++ b/tests/auto/testlib/selftests/expected_datetime.xunitxml
@@ -8,7 +8,7 @@
<testcase result="fail" name="dateTime">
<failure message="Compared values are not the same
Actual (local): 2000/05/03 04:03:04.000[local time]
- Expected (utc): 2000/05/03 04:03:04.000[UTC]" result="fail"/>
+ Expected (utc) : 2000/05/03 04:03:04.000[UTC]" result="fail"/>
</testcase>
<testcase result="fail" name="qurl">
<failure tag="empty rhs" message="Compared values are not the same
diff --git a/tests/auto/testlib/selftests/expected_float.txt b/tests/auto/testlib/selftests/expected_float.txt
index dc32fd76f1..da98f9c19d 100644
--- a/tests/auto/testlib/selftests/expected_float.txt
+++ b/tests/auto/testlib/selftests/expected_float.txt
@@ -3,15 +3,15 @@ Config: Using QtTest library @INSERT_QT_VERSION_HERE@, Qt @INSERT_QT_VERSION_HER
PASS : tst_float::initTestCase()
PASS : tst_float::floatComparisons(should SUCCEED 1)
FAIL! : tst_float::floatComparisons(should FAIL 1) Compared floats are not the same (fuzzy compare)
- Actual (operandLeft): 1
+ Actual (operandLeft) : 1
Expected (operandRight): 3
Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(61)]
FAIL! : tst_float::floatComparisons(should FAIL 2) Compared floats are not the same (fuzzy compare)
- Actual (operandLeft): 1e-07
+ Actual (operandLeft) : 1e-07
Expected (operandRight): 3e-07
Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(61)]
FAIL! : tst_float::floatComparisons(should FAIL 3) Compared floats are not the same (fuzzy compare)
- Actual (operandLeft): 99998
+ Actual (operandLeft) : 99998
Expected (operandRight): 99999
Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(61)]
PASS : tst_float::floatComparisons(should SUCCEED 2)
diff --git a/tests/auto/testlib/selftests/expected_strcmp.lightxml b/tests/auto/testlib/selftests/expected_strcmp.lightxml
index d5135fd7df..4c30c9f801 100644
--- a/tests/auto/testlib/selftests/expected_strcmp.lightxml
+++ b/tests/auto/testlib/selftests/expected_strcmp.lightxml
@@ -35,13 +35,13 @@
<Incident type="fail" file="/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/strcmp/tst_strcmp.cpp" line="121">
<Description><![CDATA[Compared values are not the same
Actual (QByteArray("foo")): 66 6F 6F
- Expected (QByteArray()): ]]></Description>
+ Expected (QByteArray()) : ]]></Description>
</Incident>
</TestFunction>
<TestFunction name="failByteArrayEmpty">
<Incident type="fail" file="/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/strcmp/tst_strcmp.cpp" line="126">
<Description><![CDATA[Compared values are not the same
- Actual (QByteArray("")):
+ Actual (QByteArray("")) :
Expected (QByteArray("foo")): 66 6F 6F]]></Description>
</Incident>
</TestFunction>
diff --git a/tests/auto/testlib/selftests/expected_strcmp.txt b/tests/auto/testlib/selftests/expected_strcmp.txt
index 797aefa82f..f3ad169fb7 100644
--- a/tests/auto/testlib/selftests/expected_strcmp.txt
+++ b/tests/auto/testlib/selftests/expected_strcmp.txt
@@ -18,10 +18,10 @@ FAIL! : tst_StrCmp::failByteArray() Compared values are not the same
Loc: [./tst_strcmp.cpp(82)]
FAIL! : tst_StrCmp::failByteArrayNull() Compared values are not the same
Actual (QByteArray("foo")): 66 6F 6F
- Expected (QByteArray()):
+ Expected (QByteArray()) :
Loc: [./tst_strcmp.cpp(88)]
FAIL! : tst_StrCmp::failByteArrayEmpty() Compared values are not the same
- Actual (QByteArray("")):
+ Actual (QByteArray("")) :
Expected (QByteArray("foo")): 66 6F 6F
Loc: [./tst_strcmp.cpp(93)]
FAIL! : tst_StrCmp::failByteArraySingleChars() Compared values are not the same
diff --git a/tests/auto/testlib/selftests/expected_strcmp.xml b/tests/auto/testlib/selftests/expected_strcmp.xml
index 0c5a73918d..db9ed34bb8 100644
--- a/tests/auto/testlib/selftests/expected_strcmp.xml
+++ b/tests/auto/testlib/selftests/expected_strcmp.xml
@@ -37,13 +37,13 @@
<Incident type="fail" file="/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/strcmp/tst_strcmp.cpp" line="121">
<Description><![CDATA[Compared values are not the same
Actual (QByteArray("foo")): 66 6F 6F
- Expected (QByteArray()): ]]></Description>
+ Expected (QByteArray()) : ]]></Description>
</Incident>
</TestFunction>
<TestFunction name="failByteArrayEmpty">
<Incident type="fail" file="/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/strcmp/tst_strcmp.cpp" line="126">
<Description><![CDATA[Compared values are not the same
- Actual (QByteArray("")):
+ Actual (QByteArray("")) :
Expected (QByteArray("foo")): 66 6F 6F]]></Description>
</Incident>
</TestFunction>
diff --git a/tests/auto/testlib/selftests/expected_strcmp.xunitxml b/tests/auto/testlib/selftests/expected_strcmp.xunitxml
index a900e2f17a..dde9ff5299 100644
--- a/tests/auto/testlib/selftests/expected_strcmp.xunitxml
+++ b/tests/auto/testlib/selftests/expected_strcmp.xunitxml
@@ -22,11 +22,11 @@
<testcase result="fail" name="failByteArrayNull">
<failure message="Compared values are not the same
Actual (QByteArray(&quot;foo&quot;)): 66 6F 6F
- Expected (QByteArray()): " result="fail"/>
+ Expected (QByteArray()) : " result="fail"/>
</testcase>
<testcase result="fail" name="failByteArrayEmpty">
<failure message="Compared values are not the same
- Actual (QByteArray(&quot;&quot;)):
+ Actual (QByteArray(&quot;&quot;)) :
Expected (QByteArray(&quot;foo&quot;)): 66 6F 6F" result="fail"/>
</testcase>
<testcase result="fail" name="failByteArraySingleChars">
diff --git a/tests/auto/testlib/selftests/expected_subtest.lightxml b/tests/auto/testlib/selftests/expected_subtest.lightxml
index b156dc3991..5adbb771af 100644
--- a/tests/auto/testlib/selftests/expected_subtest.lightxml
+++ b/tests/auto/testlib/selftests/expected_subtest.lightxml
@@ -122,7 +122,7 @@
<Incident type="fail" file="/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/subtest/tst_subtest.cpp" line="154">
<DataTag><![CDATA[data1]]></DataTag>
<Description><![CDATA[Compared values are not the same
- Actual (str): hello1
+ Actual (str) : hello1
Expected (QString("hello0")): hello0]]></Description>
</Incident>
<Message type="qdebug" file="" line="0">
@@ -140,7 +140,7 @@
<Incident type="fail" file="/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/subtest/tst_subtest.cpp" line="154">
<DataTag><![CDATA[data2]]></DataTag>
<Description><![CDATA[Compared values are not the same
- Actual (str): hello2
+ Actual (str) : hello2
Expected (QString("hello0")): hello0]]></Description>
</Incident>
<Message type="qdebug" file="" line="0">
diff --git a/tests/auto/testlib/selftests/expected_subtest.txt b/tests/auto/testlib/selftests/expected_subtest.txt
index 4537f983e5..bb88f189ec 100644
--- a/tests/auto/testlib/selftests/expected_subtest.txt
+++ b/tests/auto/testlib/selftests/expected_subtest.txt
@@ -33,14 +33,14 @@ PASS : tst_Subtest::test3(data0)
QDEBUG : tst_Subtest::test3(data1) init test3 data1
QDEBUG : tst_Subtest::test3(data1) test2 test3 data1
FAIL! : tst_Subtest::test3(data1) Compared values are not the same
- Actual (str): hello1
+ Actual (str) : hello1
Expected (QString("hello0")): hello0
Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/subtest/tst_subtest.cpp(154)]
QDEBUG : tst_Subtest::test3(data1) cleanup test3 data1
QDEBUG : tst_Subtest::test3(data2) init test3 data2
QDEBUG : tst_Subtest::test3(data2) test2 test3 data2
FAIL! : tst_Subtest::test3(data2) Compared values are not the same
- Actual (str): hello2
+ Actual (str) : hello2
Expected (QString("hello0")): hello0
Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/subtest/tst_subtest.cpp(154)]
QDEBUG : tst_Subtest::test3(data2) cleanup test3 data2
diff --git a/tests/auto/testlib/selftests/expected_subtest.xml b/tests/auto/testlib/selftests/expected_subtest.xml
index 365df51e23..094e22383d 100644
--- a/tests/auto/testlib/selftests/expected_subtest.xml
+++ b/tests/auto/testlib/selftests/expected_subtest.xml
@@ -124,7 +124,7 @@
<Incident type="fail" file="/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/subtest/tst_subtest.cpp" line="154">
<DataTag><![CDATA[data1]]></DataTag>
<Description><![CDATA[Compared values are not the same
- Actual (str): hello1
+ Actual (str) : hello1
Expected (QString("hello0")): hello0]]></Description>
</Incident>
<Message type="qdebug" file="" line="0">
@@ -142,7 +142,7 @@
<Incident type="fail" file="/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/subtest/tst_subtest.cpp" line="154">
<DataTag><![CDATA[data2]]></DataTag>
<Description><![CDATA[Compared values are not the same
- Actual (str): hello2
+ Actual (str) : hello2
Expected (QString("hello0")): hello0]]></Description>
</Incident>
<Message type="qdebug" file="" line="0">
diff --git a/tests/auto/testlib/selftests/expected_subtest.xunitxml b/tests/auto/testlib/selftests/expected_subtest.xunitxml
index 6097000e7f..6f8fc3db45 100644
--- a/tests/auto/testlib/selftests/expected_subtest.xunitxml
+++ b/tests/auto/testlib/selftests/expected_subtest.xunitxml
@@ -38,13 +38,13 @@
<!-- tag="data1" message="init test3 data1 " type="qdebug" -->
<!-- tag="data1" message="test2 test3 data1 " type="qdebug" -->
<failure tag="data1" message="Compared values are not the same
- Actual (str): hello1
+ Actual (str) : hello1
Expected (QString(&quot;hello0&quot;)): hello0" result="fail"/>
<!-- tag="data1" message="cleanup test3 data1 " type="qdebug" -->
<!-- tag="data2" message="init test3 data2 " type="qdebug" -->
<!-- tag="data2" message="test2 test3 data2 " type="qdebug" -->
<failure tag="data2" message="Compared values are not the same
- Actual (str): hello2
+ Actual (str) : hello2
Expected (QString(&quot;hello0&quot;)): hello0" result="fail"/>
<!-- tag="data2" message="cleanup test3 data2 " type="qdebug" -->
</testcase>
diff --git a/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp b/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp
index 65d36247f6..81b69f6b89 100644
--- a/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp
+++ b/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp
@@ -612,6 +612,8 @@ void tst_QFiledialog::defaultSuffix()
QCOMPARE(fd.defaultSuffix(), QString());
fd.setDefaultSuffix("txt");
QCOMPARE(fd.defaultSuffix(), QString("txt"));
+ fd.setDefaultSuffix(".txt");
+ QCOMPARE(fd.defaultSuffix(), QString("txt"));
fd.setDefaultSuffix(QString());
QCOMPARE(fd.defaultSuffix(), QString());
}
@@ -1334,6 +1336,38 @@ QString saveName(QWidget *, const QString &, const QString &, const QString &, Q
return "saveName";
}
+QT_BEGIN_NAMESPACE
+typedef QUrl (*_qt_filedialog_existing_directory_url_hook)(QWidget *parent, const QString &caption, const QUrl &dir, QFileDialog::Options options, const QStringList &supportedSchemes);
+extern Q_WIDGETS_EXPORT _qt_filedialog_existing_directory_url_hook qt_filedialog_existing_directory_url_hook;
+QT_END_NAMESPACE
+QUrl existingUrl(QWidget *, const QString &, const QUrl &, QFileDialog::Options, const QStringList &) {
+ return QUrl("http://dirUrl");
+}
+
+QT_BEGIN_NAMESPACE
+typedef QUrl (*_qt_filedialog_open_file_url_hook)(QWidget * parent, const QString &caption, const QUrl &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options, const QStringList &supportedSchemes);
+extern Q_WIDGETS_EXPORT _qt_filedialog_open_file_url_hook qt_filedialog_open_file_url_hook;
+QT_END_NAMESPACE
+QUrl openUrl(QWidget *, const QString &, const QUrl &, const QString &, QString *, QFileDialog::Options, const QStringList &) {
+ return QUrl("http://openUrl");
+}
+
+QT_BEGIN_NAMESPACE
+typedef QList<QUrl> (*_qt_filedialog_open_file_urls_hook)(QWidget * parent, const QString &caption, const QUrl &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options, const QStringList &supportedSchemes);
+extern Q_WIDGETS_EXPORT _qt_filedialog_open_file_urls_hook qt_filedialog_open_file_urls_hook;
+QT_END_NAMESPACE
+QList<QUrl> openUrls(QWidget *, const QString &, const QUrl &, const QString &, QString *, QFileDialog::Options, const QStringList &) {
+ return QList<QUrl>() << QUrl("http://openUrls");
+}
+
+QT_BEGIN_NAMESPACE
+typedef QUrl (*_qt_filedialog_save_file_url_hook)(QWidget * parent, const QString &caption, const QUrl &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options, const QStringList &supportedSchemes);
+extern Q_WIDGETS_EXPORT _qt_filedialog_save_file_url_hook qt_filedialog_save_file_url_hook;
+QT_END_NAMESPACE
+QUrl saveUrl(QWidget *, const QString &, const QUrl &, const QString &, QString *, QFileDialog::Options, const QStringList &) {
+ return QUrl("http://saveUrl");
+}
+
void tst_QFiledialog::hooks()
{
@@ -1346,6 +1380,20 @@ void tst_QFiledialog::hooks()
QCOMPARE(QFileDialog::getOpenFileName(), QString("openName"));
QCOMPARE(QFileDialog::getOpenFileNames(), QStringList("openNames"));
QCOMPARE(QFileDialog::getSaveFileName(), QString("saveName"));
+ QCOMPARE(QFileDialog::getExistingDirectoryUrl(), QUrl::fromLocalFile("dir"));
+ QCOMPARE(QFileDialog::getOpenFileUrl(), QUrl::fromLocalFile("openName"));
+ QCOMPARE(QFileDialog::getOpenFileUrls(), QList<QUrl>() << QUrl::fromLocalFile("openNames"));
+ QCOMPARE(QFileDialog::getSaveFileUrl(), QUrl::fromLocalFile("saveName"));
+
+ qt_filedialog_existing_directory_url_hook = &existingUrl;
+ qt_filedialog_save_file_url_hook = &saveUrl;
+ qt_filedialog_open_file_url_hook = &openUrl;
+ qt_filedialog_open_file_urls_hook = &openUrls;
+
+ QCOMPARE(QFileDialog::getExistingDirectoryUrl(), QUrl("http://dirUrl"));
+ QCOMPARE(QFileDialog::getOpenFileUrl(), QUrl("http://openUrl"));
+ QCOMPARE(QFileDialog::getOpenFileUrls(), QList<QUrl>() << QUrl("http://openUrls"));
+ QCOMPARE(QFileDialog::getSaveFileUrl(), QUrl("http://saveUrl"));
}
#ifdef Q_OS_UNIX
diff --git a/tests/auto/widgets/graphicsview/qgraphicsanchorlayout/qgraphicsanchorlayout.pro b/tests/auto/widgets/graphicsview/qgraphicsanchorlayout/qgraphicsanchorlayout.pro
index 3eb18e61eb..8e8c0708a3 100644
--- a/tests/auto/widgets/graphicsview/qgraphicsanchorlayout/qgraphicsanchorlayout.pro
+++ b/tests/auto/widgets/graphicsview/qgraphicsanchorlayout/qgraphicsanchorlayout.pro
@@ -3,4 +3,3 @@ TARGET = tst_qgraphicsanchorlayout
QT += widgets widgets-private testlib
QT += core-private gui-private
SOURCES += tst_qgraphicsanchorlayout.cpp
-CONFIG += parallel_test
diff --git a/tests/auto/widgets/graphicsview/qgraphicseffectsource/qgraphicseffectsource.pro b/tests/auto/widgets/graphicsview/qgraphicseffectsource/qgraphicseffectsource.pro
index 4fe3405d11..550d3debf7 100644
--- a/tests/auto/widgets/graphicsview/qgraphicseffectsource/qgraphicseffectsource.pro
+++ b/tests/auto/widgets/graphicsview/qgraphicseffectsource/qgraphicseffectsource.pro
@@ -5,4 +5,3 @@ QT += widgets widgets-private testlib
QT += core-private gui-private
SOURCES += tst_qgraphicseffectsource.cpp
-CONFIG += parallel_test
diff --git a/tests/auto/widgets/graphicsview/qgraphicsgridlayout/qgraphicsgridlayout.pro b/tests/auto/widgets/graphicsview/qgraphicsgridlayout/qgraphicsgridlayout.pro
index 5796cbfd73..e49139a8ad 100644
--- a/tests/auto/widgets/graphicsview/qgraphicsgridlayout/qgraphicsgridlayout.pro
+++ b/tests/auto/widgets/graphicsview/qgraphicsgridlayout/qgraphicsgridlayout.pro
@@ -3,4 +3,3 @@ TARGET = tst_qgraphicsgridlayout
QT += widgets testlib
SOURCES += tst_qgraphicsgridlayout.cpp
-CONFIG += parallel_test
diff --git a/tests/auto/widgets/graphicsview/qgraphicsgridlayout/tst_qgraphicsgridlayout.cpp b/tests/auto/widgets/graphicsview/qgraphicsgridlayout/tst_qgraphicsgridlayout.cpp
index 8c8f27d635..1ffb5c3b5c 100644
--- a/tests/auto/widgets/graphicsview/qgraphicsgridlayout/tst_qgraphicsgridlayout.cpp
+++ b/tests/auto/widgets/graphicsview/qgraphicsgridlayout/tst_qgraphicsgridlayout.cpp
@@ -126,6 +126,7 @@ private slots:
void spanningItem2x3_data();
void spanningItem2x3();
void spanningItem();
+ void spanAcrossEmptyRow();
void heightForWidth();
void widthForHeight();
void heightForWidthWithSpanning();
@@ -3192,23 +3193,19 @@ void tst_QGraphicsGridLayout::heightForWidthWithSpanning()
QCOMPARE(layout->effectiveSizeHint(Qt::MinimumSize, QSizeF(-1, -1)), QSizeF(1, 1));
QCOMPARE(layout->effectiveSizeHint(Qt::PreferredSize, QSizeF(-1, -1)), QSizeF(200, 100));
- QEXPECT_FAIL("", "Due to an old bug this wrongly returns QWIDGETSIZE_MAX", Continue);
QCOMPARE(layout->effectiveSizeHint(Qt::MaximumSize, QSizeF(-1, -1)), QSizeF(30000, 30000));
QCOMPARE(layout->effectiveSizeHint(Qt::MinimumSize, QSizeF(200, -1)), QSizeF(200, 100));
QCOMPARE(layout->effectiveSizeHint(Qt::PreferredSize, QSizeF(200, -1)), QSizeF(200, 100));
- QEXPECT_FAIL("", "Due to an old bug this wrongly returns QWIDGETSIZE_MAX", Continue);
QCOMPARE(layout->effectiveSizeHint(Qt::MaximumSize, QSizeF(200, -1)), QSizeF(200, 100));
QCOMPARE(layout->effectiveSizeHint(Qt::MinimumSize, QSizeF(2, -1)), QSizeF(2, 10000));
QCOMPARE(layout->effectiveSizeHint(Qt::PreferredSize, QSizeF(2, -1)), QSizeF(2, 10000));
- QEXPECT_FAIL("", "Due to an old bug this wrongly returns QWIDGETSIZE_MAX", Continue);
QCOMPARE(layout->effectiveSizeHint(Qt::MaximumSize, QSizeF(2, -1)), QSizeF(2, 10000));
QCOMPARE(layout->effectiveSizeHint(Qt::MinimumSize, QSizeF(200, -1)), QSizeF(200, 100));
QCOMPARE(layout->effectiveSizeHint(Qt::PreferredSize, QSizeF(200, -1)), QSizeF(200, 100));
- QEXPECT_FAIL("", "Due to an old bug this wrongly returns QWIDGETSIZE_MAX", Continue);
- QCOMPARE(layout->effectiveSizeHint(Qt::MaximumSize, QSizeF(200, -1)), QSizeF(200, 10000));
+ QCOMPARE(layout->effectiveSizeHint(Qt::MaximumSize, QSizeF(200, -1)), QSizeF(200, 100));
}
Q_DECLARE_METATYPE(QSizePolicy::Policy)
@@ -3364,6 +3361,37 @@ void tst_QGraphicsGridLayout::spanningItem()
QCOMPARE(layout->maximumSize(), QSizeF(160,80));
}
+void tst_QGraphicsGridLayout::spanAcrossEmptyRow()
+{
+ QGraphicsWidget *form = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout(form);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0);
+ RectWidget *w1 = new RectWidget;
+ RectWidget *w2 = new RectWidget;
+ RectWidget *w3 = new RectWidget;
+
+ QSizeF size(10, 10);
+ for (int i = 0; i < 3; ++i) {
+ w1->setSizeHint((Qt::SizeHint)i, size);
+ w2->setSizeHint((Qt::SizeHint)i, size);
+ w3->setSizeHint((Qt::SizeHint)i, size);
+ size+=size; //[(10,10), (20,20), (40,40)]
+ }
+ layout->addItem(w1, 0, 0, 1, 1);
+ layout->addItem(w2, 0, 1, 1, 2);
+ layout->addItem(w3, 0, 99, 1, 1);
+
+ form->resize(60,20);
+ QCOMPARE(w1->geometry(), QRectF( 0, 0, 20, 20));
+ QCOMPARE(w2->geometry(), QRectF(20, 0, 20, 20));
+ QCOMPARE(w3->geometry(), QRectF(40, 0, 20, 20));
+
+ QCOMPARE(layout->effectiveSizeHint(Qt::MinimumSize), QSizeF(30, 10));
+ QCOMPARE(layout->effectiveSizeHint(Qt::PreferredSize), QSizeF(60, 20));
+ QCOMPARE(layout->effectiveSizeHint(Qt::MaximumSize), QSizeF(120, 40));
+}
+
void tst_QGraphicsGridLayout::stretchAndHeightForWidth()
{
QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
diff --git a/tests/auto/widgets/graphicsview/qgraphicslinearlayout/qgraphicslinearlayout.pro b/tests/auto/widgets/graphicsview/qgraphicslinearlayout/qgraphicslinearlayout.pro
index 50a886cece..2bf1a1d676 100644
--- a/tests/auto/widgets/graphicsview/qgraphicslinearlayout/qgraphicslinearlayout.pro
+++ b/tests/auto/widgets/graphicsview/qgraphicslinearlayout/qgraphicslinearlayout.pro
@@ -2,5 +2,3 @@ CONFIG += testcase
TARGET = tst_qgraphicslinearlayout
QT += widgets testlib
SOURCES += tst_qgraphicslinearlayout.cpp
-CONFIG += parallel_test
-
diff --git a/tests/auto/widgets/graphicsview/qgraphicssceneindex/qgraphicssceneindex.pro b/tests/auto/widgets/graphicsview/qgraphicssceneindex/qgraphicssceneindex.pro
index 5fd3bdf8d6..3d0d73566e 100644
--- a/tests/auto/widgets/graphicsview/qgraphicssceneindex/qgraphicssceneindex.pro
+++ b/tests/auto/widgets/graphicsview/qgraphicssceneindex/qgraphicssceneindex.pro
@@ -4,5 +4,4 @@ requires(contains(QT_CONFIG,private_tests))
QT += widgets widgets-private testlib
QT += core-private gui-private
SOURCES += tst_qgraphicssceneindex.cpp
-CONFIG += parallel_test
DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
diff --git a/tests/auto/widgets/graphicsview/qgraphicswidget/qgraphicswidget.pro b/tests/auto/widgets/graphicsview/qgraphicswidget/qgraphicswidget.pro
index 4e119cbcb3..481bc96d96 100644
--- a/tests/auto/widgets/graphicsview/qgraphicswidget/qgraphicswidget.pro
+++ b/tests/auto/widgets/graphicsview/qgraphicswidget/qgraphicswidget.pro
@@ -6,5 +6,4 @@ QT += core-private gui-private
SOURCES += tst_qgraphicswidget.cpp
-linux-*:system(". /etc/lsb-release && [ $DISTRIB_CODENAME = lucid ]"):DEFINES+=UBUNTU_LUCID # QTBUG-20778
DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
diff --git a/tests/auto/widgets/graphicsview/qgraphicswidget/tst_qgraphicswidget.cpp b/tests/auto/widgets/graphicsview/qgraphicswidget/tst_qgraphicswidget.cpp
index 31439e203c..2dd2089f81 100644
--- a/tests/auto/widgets/graphicsview/qgraphicswidget/tst_qgraphicswidget.cpp
+++ b/tests/auto/widgets/graphicsview/qgraphicswidget/tst_qgraphicswidget.cpp
@@ -3194,9 +3194,6 @@ void tst_QGraphicsWidget::initialShow2()
qApp->setActiveWindow(&view);
QVERIFY(QTest::qWaitForWindowActive(&view));
-#ifdef UBUNTU_LUCID
- QEXPECT_FAIL("", "QTBUG-20778", Abort);
-#endif
QTRY_COMPARE(widget->repaints, expectedRepaintCount);
}
diff --git a/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp b/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp
index 8e888f06ee..dfb780c8fa 100644
--- a/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp
+++ b/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp
@@ -106,6 +106,8 @@ private slots:
void moveCursorStrikesBack_data();
void moveCursorStrikesBack();
+ void moveCursorBiggerJump();
+
void hideRows_data();
void hideRows();
@@ -1354,6 +1356,34 @@ void tst_QTableView::moveCursorStrikesBack()
QCOMPARE(newColumn, expectedColumn);
}
+void tst_QTableView::moveCursorBiggerJump()
+{
+ QtTestTableModel model(50, 7);
+ QTableView view;
+ view.setModel(&model);
+ view.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
+
+ int height = view.horizontalHeader()->height();
+ for (int i=0;i<8;i++)
+ height += view.verticalHeader()->sectionSize(i);
+ view.resize(view.width(), height);
+ view.setCurrentIndex(model.index(0,0));
+
+ QTest::keyClick(&view, Qt::Key_PageDown);
+ QCOMPARE(view.indexAt(QPoint(0,0)), model.index(1,0));
+ QTest::keyClick(&view, Qt::Key_PageDown);
+ QCOMPARE(view.indexAt(QPoint(0,0)), model.index(8,0));
+ QTest::keyClick(&view, Qt::Key_PageDown);
+ QCOMPARE(view.indexAt(QPoint(0,0)), model.index(15,0));
+ QTest::keyClick(&view, Qt::Key_PageUp);
+ QCOMPARE(view.indexAt(QPoint(0,0)), model.index(14,0));
+ QTest::keyClick(&view, Qt::Key_PageUp);
+ QCOMPARE(view.indexAt(QPoint(0,0)), model.index(7,0));
+ QTest::keyClick(&view, Qt::Key_PageUp);
+ QCOMPARE(view.indexAt(QPoint(0,0)), model.index(0,0));
+}
+
void tst_QTableView::hideRows_data()
{
QTest::addColumn<int>("rowCount");
@@ -3762,8 +3792,6 @@ void tst_QTableView::task259308_scrollVerticalHeaderSwappedSections()
QTRY_COMPARE(tv.rowAt(0), tv.verticalHeader()->logicalIndex(0));
int newRow = tv.rowAt(tv.viewport()->height());
- if (newRow == tv.rowAt(tv.viewport()->height() - 1)) // Overlapping row
- newRow++;
QTest::keyClick(&tv, Qt::Key_PageDown); // Scroll down and check current
QTRY_COMPARE(tv.currentIndex().row(), newRow);
diff --git a/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp b/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp
index 9a7b7956d8..dcda9f7fd7 100644
--- a/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp
+++ b/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp
@@ -2017,6 +2017,8 @@ void tst_QTreeView::clicked()
view.setModel(&model);
view.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
+
QModelIndex firstIndex = model.index(0, 0, QModelIndex());
QVERIFY(firstIndex.isValid());
int itemHeight = view.visualRect(firstIndex).height();
diff --git a/tests/auto/widgets/kernel/qlayout/tst_qlayout.cpp b/tests/auto/widgets/kernel/qlayout/tst_qlayout.cpp
index 2b9b4fd761..ab2df2e250 100644
--- a/tests/auto/widgets/kernel/qlayout/tst_qlayout.cpp
+++ b/tests/auto/widgets/kernel/qlayout/tst_qlayout.cpp
@@ -84,6 +84,7 @@ private slots:
void controlTypes();
void controlTypes2();
void adjustSizeShouldMakeSureLayoutIsActivated();
+ void testRetainSizeWhenHidden();
};
tst_QLayout::tst_QLayout()
@@ -350,5 +351,47 @@ void tst_QLayout::adjustSizeShouldMakeSureLayoutIsActivated()
QCOMPARE(main.size(), QSize(200, 10));
}
+void tst_QLayout::testRetainSizeWhenHidden()
+{
+ QWidget widget;
+ QBoxLayout layout(QBoxLayout::TopToBottom, &widget);
+
+ QLabel *label1 = new QLabel("label1 text", &widget);
+ layout.addWidget(label1);
+ QLabel *label2 = new QLabel("label2 text", &widget);
+ layout.addWidget(label2);
+
+ widget.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&widget));
+ int normalHeight = widget.height();
+
+ // a. Verify that a removed visible will mean lesser size after adjust
+ label1->hide();
+ widget.adjustSize();
+ int heightWithoutLabel1 = widget.height();
+ QVERIFY(heightWithoutLabel1 < normalHeight);
+
+ // b restore with verify that the size is the same
+ label1->show();
+ QCOMPARE(widget.sizeHint().height(), normalHeight);
+
+ // c verify that a policy with retainSizeWhenHidden is respected
+ QSizePolicy sp_remove = label1->sizePolicy();
+ QSizePolicy sp_retain = label1->sizePolicy();
+ sp_retain.setRetainSizeWhenHidden(true);
+
+ label1->setSizePolicy(sp_retain);
+ label1->hide();
+ QCOMPARE(widget.sizeHint().height(), normalHeight);
+
+ // d check that changing the policy to not wanting size will result in lesser size
+ label1->setSizePolicy(sp_remove);
+ QCOMPARE(widget.sizeHint().height(), heightWithoutLabel1);
+
+ // e verify that changing back the hidden widget to want the hidden size will ensure that it gets more size
+ label1->setSizePolicy(sp_retain);
+ QCOMPARE(widget.sizeHint().height(), normalHeight);
+}
+
QTEST_MAIN(tst_QLayout)
#include "tst_qlayout.moc"
diff --git a/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp b/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp
index 0bfd4baa0c..f26af0e1f4 100644
--- a/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp
+++ b/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp
@@ -160,6 +160,7 @@ private slots:
void maxVisibleItems();
void task_QTBUG_10491_currentIndexAndModelColumn();
void highlightedSignal();
+ void itemData();
};
class MyAbstractItemDelegate : public QAbstractItemDelegate
@@ -2755,5 +2756,150 @@ void tst_QComboBox::highlightedSignal()
QCOMPARE(spy.size(), 1);
}
+void tst_QComboBox::itemData()
+{
+ QComboBox comboBox;
+ const int itemCount = 10;
+
+ // ensure that the currentText(), the DisplayRole and the EditRole
+ // stay in sync when using QComboBox's default model
+ for (int i = 0; i < itemCount; ++i) {
+ QString itemText = QString("item text %1").arg(i);
+ comboBox.addItem(itemText);
+ }
+
+ for (int i = 0; i < itemCount; ++i) {
+ QString itemText = QString("item text %1").arg(i);
+ QCOMPARE(comboBox.itemText(i), itemText);
+ QCOMPARE(comboBox.itemData(i, Qt::DisplayRole).toString(), itemText);
+ QCOMPARE(comboBox.itemData(i, Qt::EditRole).toString(), itemText);
+
+ comboBox.setCurrentIndex(i);
+ QCOMPARE(comboBox.currentIndex(), i);
+ QCOMPARE(comboBox.currentText(), itemText);
+ QCOMPARE(comboBox.currentData(Qt::DisplayRole).toString(), itemText);
+ QCOMPARE(comboBox.currentData(Qt::EditRole).toString(), itemText);
+ }
+
+ for (int i = 0; i < itemCount; ++i) {
+ // now change by using setItemText
+ QString itemText = QString("setItemText %1").arg(i);
+ comboBox.setItemText(i, itemText);
+ }
+
+ for (int i = 0; i < itemCount; ++i) {
+ QString itemText = QString("setItemText %1").arg(i);
+ QCOMPARE(comboBox.itemText(i), itemText);
+ QCOMPARE(comboBox.itemData(i, Qt::DisplayRole).toString(), itemText);
+ QCOMPARE(comboBox.itemData(i, Qt::EditRole).toString(), itemText);
+
+ comboBox.setCurrentIndex(i);
+ QCOMPARE(comboBox.currentIndex(), i);
+ QCOMPARE(comboBox.currentText(), itemText);
+ QCOMPARE(comboBox.currentData(Qt::DisplayRole).toString(), itemText);
+ QCOMPARE(comboBox.currentData(Qt::EditRole).toString(), itemText);
+ }
+
+ for (int i = 0; i < itemCount; ++i) {
+ // now change by changing the DisplayRole's data
+ QString itemText = QString("setItemData(DisplayRole) %1").arg(i);
+ comboBox.setItemData(i, QVariant(itemText), Qt::DisplayRole);
+ }
+
+ for (int i = 0; i < itemCount; ++i) {
+ QString itemText = QString("setItemData(DisplayRole) %1").arg(i);
+ QCOMPARE(comboBox.itemText(i), itemText);
+ QCOMPARE(comboBox.itemData(i, Qt::DisplayRole).toString(), itemText);
+ QCOMPARE(comboBox.itemData(i, Qt::EditRole).toString(), itemText);
+
+ comboBox.setCurrentIndex(i);
+ QCOMPARE(comboBox.currentIndex(), i);
+ QCOMPARE(comboBox.currentText(), itemText);
+ QCOMPARE(comboBox.currentData(Qt::DisplayRole).toString(), itemText);
+ QCOMPARE(comboBox.currentData(Qt::EditRole).toString(), itemText);
+ }
+
+ for (int i = 0; i < itemCount; ++i) {
+ // now change by changing the EditRole's data
+ QString itemText = QString("setItemData(EditRole) %1").arg(i);
+ comboBox.setItemData(i, QVariant(itemText), Qt::EditRole);
+ }
+
+ for (int i = 0; i < itemCount; ++i) {
+ QString itemText = QString("setItemData(EditRole) %1").arg(i);
+ QCOMPARE(comboBox.itemText(i), itemText);
+ QCOMPARE(comboBox.itemData(i, Qt::DisplayRole).toString(), itemText);
+ QCOMPARE(comboBox.itemData(i, Qt::EditRole).toString(), itemText);
+
+ comboBox.setCurrentIndex(i);
+ QCOMPARE(comboBox.currentIndex(), i);
+ QCOMPARE(comboBox.currentText(), itemText);
+ QCOMPARE(comboBox.currentData(Qt::DisplayRole).toString(), itemText);
+ QCOMPARE(comboBox.currentData(Qt::EditRole).toString(), itemText);
+ }
+
+ comboBox.clear();
+
+
+ // set additional user data in the addItem call
+ for (int i = 0; i < itemCount; ++i) {
+ QString itemText = QString("item text %1").arg(i);
+ QString itemDataText = QString("item data %1").arg(i);
+ comboBox.addItem(itemText, QVariant(itemDataText));
+ }
+
+ for (int i = 0; i < itemCount; ++i) {
+ QString itemText = QString("item text %1").arg(i);
+ QString itemDataText = QString("item data %1").arg(i);
+ QCOMPARE(comboBox.itemData(i, Qt::DisplayRole).toString(), itemText);
+ QCOMPARE(comboBox.itemData(i, Qt::EditRole).toString(), itemText);
+ QCOMPARE(comboBox.itemData(i).toString(), itemDataText);
+
+ comboBox.setCurrentIndex(i);
+ QCOMPARE(comboBox.currentIndex(), i);
+ QCOMPARE(comboBox.currentData(Qt::DisplayRole).toString(), itemText);
+ QCOMPARE(comboBox.currentData(Qt::EditRole).toString(), itemText);
+ QCOMPARE(comboBox.currentData().toString(), itemDataText);
+
+ }
+
+ comboBox.clear();
+
+
+ // additional roles, setItemData
+ // UserRole + 0 -> string
+ // UserRole + 1 -> double
+ // UserRole + 2 -> icon
+ QString qtlogoPath = QFINDTESTDATA("qtlogo.png");
+ QIcon icon = QIcon(QPixmap(qtlogoPath));
+ for (int i = 0; i < itemCount; ++i) {
+ QString itemText = QString("item text %1").arg(i);
+ QString itemDataText = QString("item data %1").arg(i);
+ double d = i;
+ comboBox.addItem(itemText);
+ comboBox.setItemData(i, QVariant(itemDataText), Qt::UserRole);
+ comboBox.setItemData(i, QVariant(d), Qt::UserRole + 1);
+ comboBox.setItemData(i, QVariant::fromValue(icon), Qt::UserRole + 2);
+ }
+
+ for (int i = 0; i < itemCount; ++i) {
+ QString itemText = QString("item text %1").arg(i);
+ QString itemDataText = QString("item data %1").arg(i);
+ double d = i;
+ QCOMPARE(comboBox.itemData(i, Qt::DisplayRole).toString(), itemText);
+ QCOMPARE(comboBox.itemData(i, Qt::EditRole).toString(), itemText);
+ QCOMPARE(comboBox.itemData(i, Qt::UserRole).toString(), itemDataText);
+ QCOMPARE(comboBox.itemData(i, Qt::UserRole + 1).toDouble(), d);
+ QCOMPARE(comboBox.itemData(i, Qt::UserRole + 2).value<QIcon>(), icon);
+
+ comboBox.setCurrentIndex(i);
+ QCOMPARE(comboBox.currentData(Qt::DisplayRole).toString(), itemText);
+ QCOMPARE(comboBox.currentData(Qt::EditRole).toString(), itemText);
+ QCOMPARE(comboBox.currentData(Qt::UserRole).toString(), itemDataText);
+ QCOMPARE(comboBox.currentData(Qt::UserRole + 1).toDouble(), d);
+ QCOMPARE(comboBox.currentData(Qt::UserRole + 2).value<QIcon>(), icon);
+ }
+}
+
QTEST_MAIN(tst_QComboBox)
#include "tst_qcombobox.moc"
diff --git a/tests/auto/widgets/widgets/qdialogbuttonbox/tst_qdialogbuttonbox.cpp b/tests/auto/widgets/widgets/qdialogbuttonbox/tst_qdialogbuttonbox.cpp
index b0e454b643..db5b89f396 100644
--- a/tests/auto/widgets/widgets/qdialogbuttonbox/tst_qdialogbuttonbox.cpp
+++ b/tests/auto/widgets/widgets/qdialogbuttonbox/tst_qdialogbuttonbox.cpp
@@ -72,6 +72,8 @@ private slots:
void testConstructor2_data();
void testConstructor3();
void testConstructor3_data();
+ void testConstructor4();
+ void testConstructor4_data();
void setOrientation_data();
void setOrientation();
void addButton1_data();
@@ -201,6 +203,41 @@ void tst_QDialogButtonBox::testConstructor3()
QTEST(buttonBox.buttons().count(), "buttonCount");
}
+void tst_QDialogButtonBox::testConstructor4_data()
+{
+ QTest::addColumn<QDialogButtonBox::StandardButtons>("buttons");
+ QTest::addColumn<int>("buttonCount");
+
+ QTest::newRow("nothing") << (QDialogButtonBox::StandardButtons)0 << 0;
+ QTest::newRow("only 1") << QDialogButtonBox::StandardButtons(QDialogButtonBox::Ok) << 1;
+ QTest::newRow("only 1.. twice")
+ << (QDialogButtonBox::Ok | QDialogButtonBox::Ok)
+ << 1;
+ QTest::newRow("only 2")
+ << (QDialogButtonBox::Ok | QDialogButtonBox::Cancel)
+ << 2;
+ QTest::newRow("two different things")
+ << (QDialogButtonBox::Save | QDialogButtonBox::Close)
+ << 2;
+ QTest::newRow("three")
+ << (QDialogButtonBox::Ok
+ | QDialogButtonBox::Cancel
+ | QDialogButtonBox::Help)
+ << 3;
+ QTest::newRow("everything")
+ << (QDialogButtonBox::StandardButtons)UINT_MAX
+ << 18;
+}
+
+void tst_QDialogButtonBox::testConstructor4()
+{
+ QFETCH(QDialogButtonBox::StandardButtons, buttons);
+
+ QDialogButtonBox buttonBox(buttons);
+ QCOMPARE(buttonBox.orientation(), Qt::Horizontal);
+ QTEST(buttonBox.buttons().count(), "buttonCount");
+}
+
void tst_QDialogButtonBox::setOrientation_data()
{
QTest::addColumn<int>("orientation");
diff --git a/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp b/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp
index d428e2705d..ae3fefc45a 100644
--- a/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp
+++ b/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp
@@ -866,12 +866,18 @@ public:
void tst_QLineEdit::hasAcceptableInputValidator()
{
+ QSignalSpy spyChanged(testWidget, SIGNAL(textChanged(QString)));
+ QSignalSpy spyEdited(testWidget, SIGNAL(textEdited(QString)));
+
QFocusEvent lostFocus(QEvent::FocusOut);
ValidatorWithFixup val;
testWidget->setValidator(&val);
testWidget->setText("foobar");
qApp->sendEvent(testWidget, &lostFocus);
QVERIFY(testWidget->hasAcceptableInput());
+
+ QCOMPARE(spyChanged.count(), 2);
+ QCOMPARE(spyEdited.count(), 0);
}
diff --git a/tests/auto/widgets/widgets/qspinbox/tst_qspinbox.cpp b/tests/auto/widgets/widgets/qspinbox/tst_qspinbox.cpp
index a64b34c56a..004fdda5ef 100644
--- a/tests/auto/widgets/widgets/qspinbox/tst_qspinbox.cpp
+++ b/tests/auto/widgets/widgets/qspinbox/tst_qspinbox.cpp
@@ -98,6 +98,9 @@ private slots:
void setValue_data();
void setValue();
+ void setDisplayIntegerBase_data();
+ void setDisplayIntegerBase();
+
void setPrefixSuffix_data();
void setPrefixSuffix();
@@ -274,6 +277,61 @@ void tst_QSpinBox::setValue()
QCOMPARE(spin.value(), expected);
}
+void tst_QSpinBox::setDisplayIntegerBase_data()
+{
+ QTest::addColumn<int>("value");
+ QTest::addColumn<int>("base");
+ QTest::addColumn<QString>("string");
+
+ QTest::newRow("base 10") << 42 << 10 << "42";
+ QTest::newRow("base 2") << 42 << 2 << "101010";
+ QTest::newRow("base 8") << 42 << 8 << "52";
+ QTest::newRow("base 16") << 42 << 16 << "2a";
+ QTest::newRow("base 0") << 42 << 0 << "42";
+ QTest::newRow("base -4") << 42 << -4 << "42";
+ QTest::newRow("base 40") << 42 << 40 << "42";
+
+ QTest::newRow("negative base 10") << -42 << 10 << "-42";
+ QTest::newRow("negative base 2") << -42 << 2 << "-101010";
+ QTest::newRow("negative base 8") << -42 << 8 << "-52";
+ QTest::newRow("negative base 16") << -42 << 16 << "-2a";
+ QTest::newRow("negative base 0") << -42 << 0 << "-42";
+ QTest::newRow("negative base -4") << -42 << -4 << "-42";
+ QTest::newRow("negative base 40") << -42 << 40 << "-42";
+
+ QTest::newRow("0 base 10") << 0 << 10 << "0";
+ QTest::newRow("0 base 2") << 0 << 2 << "0";
+ QTest::newRow("0 base 8") << 0 << 8 << "0";
+ QTest::newRow("0 base 16") << 0 << 16 << "0";
+ QTest::newRow("0 base 0") << 0 << 0 << "0";
+ QTest::newRow("0 base -4") << 0 << -4 << "0";
+ QTest::newRow("0 base 40") << 0 << 40 << "0";
+}
+
+void tst_QSpinBox::setDisplayIntegerBase()
+{
+ QFETCH(int, value);
+ QFETCH(int, base);
+ QFETCH(QString, string);
+
+ SpinBox spin;
+ spin.setRange(INT_MIN, INT_MAX);
+
+ spin.setValue(value);
+ QCOMPARE(spin.lineEdit()->text(), QString::number(value));
+
+ spin.setDisplayIntegerBase(base);
+ QCOMPARE(spin.lineEdit()->text(), string);
+
+ spin.setValue(0);
+ QCOMPARE(spin.value(), 0);
+ QCOMPARE(spin.lineEdit()->text(), QString::number(0, base));
+
+ spin.lineEdit()->clear();
+ QTest::keyClicks(spin.lineEdit(), string);
+ QCOMPARE(spin.value(), value);
+}
+
void tst_QSpinBox::setPrefixSuffix_data()
{
QTest::addColumn<QString>("prefix");
diff --git a/tests/benchmarks/corelib/io/qfile/main.cpp b/tests/benchmarks/corelib/io/qfile/main.cpp
index ef5fd36254..0beffebfb7 100644
--- a/tests/benchmarks/corelib/io/qfile/main.cpp
+++ b/tests/benchmarks/corelib/io/qfile/main.cpp
@@ -54,6 +54,10 @@
# include <windows.h>
#endif
+#if defined(Q_OS_QNX) && defined(open)
+#undef open
+#endif
+
#define BUFSIZE 1024*512
#define FACTOR 1024*512
#define TF_SIZE FACTOR*81
diff --git a/tests/benchmarks/corelib/tools/qset/main.cpp b/tests/benchmarks/corelib/tools/qset/main.cpp
new file mode 100644
index 0000000000..744cc745d3
--- /dev/null
+++ b/tests/benchmarks/corelib/tools/qset/main.cpp
@@ -0,0 +1,141 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite 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 <QSet>
+#include <QTest>
+
+class tst_QSet : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void intersect_int_data();
+ void intersect_int();
+ void intersect_complexType_data();
+ void intersect_complexType();
+};
+
+void tst_QSet::intersect_int_data()
+{
+ QTest::addColumn<int>("lhsSize");
+ QTest::addColumn<int>("rhsSize");
+ QTest::addColumn<int>("intersectSize");
+
+ QTest::newRow("1000000.intersect(1000) = empty") << 1000000 << 1000 << 0;
+ QTest::newRow("1000.intersect(1000000) = empty") << 1000 << 1000000 << 0;
+ QTest::newRow("1000000.intersect(1000) = 500") << 1000000 << 1000 << 500;
+ QTest::newRow("1000.intersect(1000000) = 500") << 1000 << 1000000 << 500;
+ QTest::newRow("1000000.intersect(1000) = 1000") << 1000000 << 1000 << 1000;
+ QTest::newRow("1000.intersect(1000000) = 1000") << 1000 << 1000000 << 1000;
+}
+
+void tst_QSet::intersect_int()
+{
+ QFETCH(int, lhsSize);
+ QFETCH(int, rhsSize);
+ QFETCH(int, intersectSize);
+
+ // E.g. when lhsSize = 1000, rhsSize = 1000000 and intersectSize = 500:
+ // lhsSize = { 0, 1, ... 1000 }
+ // rhsSize = { 500, 501, ... 1000500 }
+
+ QSet<int> lhs;
+ for (int i = 0; i < lhsSize; ++i)
+ lhs.insert(i);
+
+ QSet<int> rhs;
+ const int start = lhsSize - intersectSize;
+ for (int i = start; i < start + rhsSize; ++i)
+ rhs.insert(i);
+
+ QBENCHMARK {
+ lhs.intersect(rhs);
+ }
+
+ QVERIFY(lhs.size() == intersectSize);
+}
+
+struct ComplexType
+{
+ ComplexType(int a) : a(a) {}
+ int a;
+ int b;
+ int c;
+};
+
+inline uint qHash(const ComplexType &key, uint seed = 0)
+{
+ return uint(key.a) ^ seed;
+}
+
+inline bool operator==(const ComplexType &lhs, const ComplexType &rhs)
+{
+ return lhs.a == rhs.a;
+}
+
+void tst_QSet::intersect_complexType_data()
+{
+ intersect_int_data();
+}
+
+void tst_QSet::intersect_complexType()
+{
+ QFETCH(int, lhsSize);
+ QFETCH(int, rhsSize);
+ QFETCH(int, intersectSize);
+
+ QSet<ComplexType> lhs;
+ for (int i = 0; i < lhsSize; ++i)
+ lhs.insert(ComplexType(i));
+
+ QSet<ComplexType> rhs;
+ const int start = lhsSize - intersectSize;
+ for (int i = start; i < start + rhsSize; ++i)
+ rhs.insert(ComplexType(i));
+
+ QBENCHMARK {
+ lhs.intersect(rhs);
+ }
+}
+
+QTEST_MAIN(tst_QSet)
+
+#include "main.moc"
diff --git a/tests/benchmarks/corelib/tools/qset/qset.pro b/tests/benchmarks/corelib/tools/qset/qset.pro
new file mode 100644
index 0000000000..8fb8bcfa0b
--- /dev/null
+++ b/tests/benchmarks/corelib/tools/qset/qset.pro
@@ -0,0 +1,4 @@
+TARGET = tst_qset
+QT = core testlib
+SOURCES += main.cpp
+CONFIG += release
diff --git a/tests/benchmarks/gui/itemviews/qtableview/tst_qtableview.cpp b/tests/benchmarks/gui/itemviews/qtableview/tst_qtableview.cpp
index c32ff0d099..b590269b70 100644
--- a/tests/benchmarks/gui/itemviews/qtableview/tst_qtableview.cpp
+++ b/tests/benchmarks/gui/itemviews/qtableview/tst_qtableview.cpp
@@ -44,6 +44,8 @@
#include <QTableView>
#include <QImage>
#include <QPainter>
+#include <QHeaderView>
+#include <QStandardItemModel>
class QtTestTableModel: public QAbstractTableModel
{
@@ -149,6 +151,7 @@ private slots:
void columnInsertion();
void columnRemoval_data();
void columnRemoval();
+ void sizeHintForColumnWhenHidden();
private:
static inline void spanInit_helper(QTableView *);
};
@@ -361,5 +364,23 @@ void tst_QTableView::columnRemoval()
}
}
+void tst_QTableView::sizeHintForColumnWhenHidden()
+{
+ QTableView view;
+ QStandardItemModel model(12500, 6);
+ for (int r = 0; r < model.rowCount(); ++r)
+ for (int c = 0; c < model.columnCount(); ++c) {
+ QStandardItem *item = new QStandardItem(QString("row %0, column %1").arg(r).arg(c));
+ model.setItem(r, c, item);
+ }
+
+ view.horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
+ view.setModel(&model);
+ QBENCHMARK_ONCE {
+ view.horizontalHeader()->resizeSection(0, 10); // this force resizeSections - on a hidden view.
+ }
+
+}
+
QTEST_MAIN(tst_QTableView)
#include "tst_qtableview.moc"
diff --git a/tests/benchmarks/network/access/qnetworkreply/qnetworkreply.pro b/tests/benchmarks/network/access/qnetworkreply/qnetworkreply.pro
index 7031b83210..92d20f50d0 100644
--- a/tests/benchmarks/network/access/qnetworkreply/qnetworkreply.pro
+++ b/tests/benchmarks/network/access/qnetworkreply/qnetworkreply.pro
@@ -2,7 +2,7 @@ TEMPLATE = app
TARGET = tst_bench_qnetworkreply
QT -= gui
-QT += network testlib
+QT += core-private network network-private testlib
CONFIG += release
diff --git a/tests/benchmarks/network/access/qnetworkreply/tst_qnetworkreply.cpp b/tests/benchmarks/network/access/qnetworkreply/tst_qnetworkreply.cpp
index 58cb65e1c7..55376d5a79 100644
--- a/tests/benchmarks/network/access/qnetworkreply/tst_qnetworkreply.cpp
+++ b/tests/benchmarks/network/access/qnetworkreply/tst_qnetworkreply.cpp
@@ -50,6 +50,9 @@
#include <QtNetwork/qtcpserver.h>
#include "../../../../auto/network-settings.h"
+#ifdef QT_BUILD_INTERNAL
+#include <QtNetwork/private/qhostinfo_p.h>
+#endif
Q_DECLARE_METATYPE(QSharedPointer<char>)
@@ -460,7 +463,9 @@ private slots:
#ifndef QT_NO_SSL
void echoPerformance_data();
void echoPerformance();
-#endif
+ void preConnectEncrypted();
+#endif // !QT_NO_SSL
+ void preConnectEncrypted_data();
void downloadPerformance();
void uploadPerformance();
@@ -472,9 +477,13 @@ private slots:
void httpDownloadPerformanceDownloadBuffer();
void httpsRequestChain();
void httpsUpload();
+ void preConnect_data();
+ void preConnect();
private:
void runHttpsUploadRequest(const QByteArray &data, const QNetworkRequest &request);
+ QPair<QNetworkReply *, qint64> runGetRequest(QNetworkAccessManager *manager,
+ const QNetworkRequest &request);
};
void tst_qnetworkreply::initTestCase()
@@ -495,6 +504,19 @@ void tst_qnetworkreply::httpLatency()
}
}
+QPair<QNetworkReply *, qint64> tst_qnetworkreply::runGetRequest(
+ QNetworkAccessManager *manager, const QNetworkRequest &request)
+{
+ QElapsedTimer timer;
+ timer.start();
+ QNetworkReply *reply = manager->get(request);
+ connect(reply, SIGNAL(sslErrors(QList<QSslError>)), reply, SLOT(ignoreSslErrors()));
+ connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()), Qt::QueuedConnection);
+ QTestEventLoop::instance().enterLoop(20);
+ qint64 elapsed = timer.elapsed();
+ return qMakePair(reply, elapsed);
+}
+
#ifndef QT_NO_SSL
void tst_qnetworkreply::echoPerformance_data()
{
@@ -527,7 +549,60 @@ void tst_qnetworkreply::echoPerformance()
delete reply;
}
}
+
+void tst_qnetworkreply::preConnectEncrypted()
+{
+ QString hostName = QLatin1String("www.google.com");
+
+ QNetworkAccessManager manager;
+ QNetworkRequest request(QUrl("https://" + hostName));
+
+ // make sure we have a full request including
+ // DNS lookup, TCP and SSL handshakes
+#ifdef QT_BUILD_INTERNAL
+ qt_qhostinfo_clear_cache();
+#else
+ qWarning("no internal build, could not clear DNS cache. Results may not be representative.");
+#endif
+
+ // first, benchmark a normal request
+ QPair<QNetworkReply *, qint64> normalResult = runGetRequest(&manager, request);
+ QNetworkReply *normalReply = normalResult.first;
+ QVERIFY(!QTestEventLoop::instance().timeout());
+ QVERIFY(normalReply->error() == QNetworkReply::NoError);
+ qint64 normalElapsed = normalResult.second;
+
+ // clear all caches again
+#ifdef QT_BUILD_INTERNAL
+ qt_qhostinfo_clear_cache();
+#else
+ qWarning("no internal build, could not clear DNS cache. Results may not be representative.");
#endif
+ manager.clearAccessCache();
+
+ // now try to make the connection beforehand
+ QFETCH(int, sleepTime);
+ manager.connectToHostEncrypted(hostName);
+ QTestEventLoop::instance().enterLoopMSecs(sleepTime);
+
+ // now make another request and hopefully use the existing connection
+ QPair<QNetworkReply *, qint64> preConnectResult = runGetRequest(&manager, request);
+ QNetworkReply *preConnectReply = normalResult.first;
+ QVERIFY(!QTestEventLoop::instance().timeout());
+ QVERIFY(preConnectReply->error() == QNetworkReply::NoError);
+ qint64 preConnectElapsed = preConnectResult.second;
+ qDebug() << request.url().toString() << "full request:" << normalElapsed
+ << "ms, pre-connect request:" << preConnectElapsed << "ms, difference:"
+ << (normalElapsed - preConnectElapsed) << "ms";
+}
+#endif // !QT_NO_SSL
+
+void tst_qnetworkreply::preConnectEncrypted_data()
+{
+ QTest::addColumn<int>("sleepTime");
+ QTest::newRow("2secs") << 2000; // to start a new request after preconnecting is done
+ QTest::newRow("100ms") << 100; // to start a new request while preconnecting is in-flight
+}
void tst_qnetworkreply::downloadPerformance()
{
@@ -850,6 +925,56 @@ void tst_qnetworkreply::httpsUpload()
}
}
+void tst_qnetworkreply::preConnect_data()
+{
+ preConnectEncrypted_data();
+}
+
+void tst_qnetworkreply::preConnect()
+{
+ QString hostName = QLatin1String("www.google.com");
+
+ QNetworkAccessManager manager;
+ QNetworkRequest request(QUrl("http://" + hostName));
+
+ // make sure we have a full request including
+ // DNS lookup and TCP handshake
+#ifdef QT_BUILD_INTERNAL
+ qt_qhostinfo_clear_cache();
+#else
+ qWarning("no internal build, could not clear DNS cache. Results may not be representative.");
+#endif
+
+ // first, benchmark a normal request
+ QPair<QNetworkReply *, qint64> normalResult = runGetRequest(&manager, request);
+ QNetworkReply *normalReply = normalResult.first;
+ QVERIFY(!QTestEventLoop::instance().timeout());
+ QVERIFY(normalReply->error() == QNetworkReply::NoError);
+ qint64 normalElapsed = normalResult.second;
+
+ // clear all caches again
+#ifdef QT_BUILD_INTERNAL
+ qt_qhostinfo_clear_cache();
+#else
+ qWarning("no internal build, could not clear DNS cache. Results may not be representative.");
+#endif
+ manager.clearAccessCache();
+
+ // now try to make the connection beforehand
+ QFETCH(int, sleepTime);
+ manager.connectToHost(hostName);
+ QTestEventLoop::instance().enterLoopMSecs(sleepTime);
+
+ // now make another request and hopefully use the existing connection
+ QPair<QNetworkReply *, qint64> preConnectResult = runGetRequest(&manager, request);
+ QNetworkReply *preConnectReply = normalResult.first;
+ QVERIFY(!QTestEventLoop::instance().timeout());
+ QVERIFY(preConnectReply->error() == QNetworkReply::NoError);
+ qint64 preConnectElapsed = preConnectResult.second;
+ qDebug() << request.url().toString() << "full request:" << normalElapsed
+ << "ms, pre-connect request:" << preConnectElapsed << "ms, difference:"
+ << (normalElapsed - preConnectElapsed) << "ms";
+}
QTEST_MAIN(tst_qnetworkreply)
diff --git a/tests/manual/corelib/tools/qhash/main.cpp b/tests/manual/corelib/tools/qhash/main.cpp
new file mode 100644
index 0000000000..fd38350c88
--- /dev/null
+++ b/tests/manual/corelib/tools/qhash/main.cpp
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Thorbjørn Lund Martsum - tmartsum[at]gmail.com
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite 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 <QDebug>
+//#define QT_STRICT_ITERATORS
+#include <QHash>
+
+void testEraseNoError()
+{
+ QHash<int, int> a;
+
+ a.insert(100, 100);
+ a.insert(101, 200);
+ a.insert(5, 50);
+ a.insertMulti(5, 60);
+ a.insertMulti(5, 70);
+ a.insertMulti(5, 80);
+
+ QHash<int, int>::iterator i = a.begin();
+ while (i.key() != 5)
+ ++i;
+ ++i;
+ a.erase(i);
+
+ qDebug() << "Erase - got no errors on iterator check";
+}
+
+void testErase()
+{
+ QHash<int, int> a, b;
+ a.insert(5, 50);
+ a.insert(6, 60);
+ a.insert(7, 70);
+ b = a;
+ a.erase(a.begin());
+ b.erase(b.end() - 1);
+ qDebug() << "Erase - Executing line with error now.";
+ a.erase(b.begin());
+}
+
+
+int main()
+{
+ testEraseNoError();
+ testErase();
+ return 0;
+}
diff --git a/tests/manual/corelib/tools/qhash/main.pro b/tests/manual/corelib/tools/qhash/main.pro
new file mode 100644
index 0000000000..bba41b9c12
--- /dev/null
+++ b/tests/manual/corelib/tools/qhash/main.pro
@@ -0,0 +1 @@
+SOURCES = main.cpp
diff --git a/tests/manual/corelib/tools/qlist/main.cpp b/tests/manual/corelib/tools/qlist/main.cpp
new file mode 100644
index 0000000000..8c1ee2890c
--- /dev/null
+++ b/tests/manual/corelib/tools/qlist/main.cpp
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Thorbjørn Lund Martsum - tmartsum[at]gmail.com
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite 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 <QDebug>
+//#define QT_STRICT_ITERATORS
+#include <QVector>
+void testErase()
+{
+ QList<int> a, b;
+ a.append(5);
+ a.append(6);
+ a.append(7);
+ b = a;
+ a.erase(a.begin());
+ qDebug() << "erase - Executing line with error now.";
+ // a.erase(a.end());
+ a.erase(b.begin());
+}
+void testInsert()
+{
+ QList<int> a, b;
+ a.insert(a.begin(), 1);
+ a.insert(a.begin(), 2);
+ a.insert(a.end(), 3);
+ b = a;
+ qDebug() << "insert - Executing line with error now.";
+ a.insert(b.begin(), 4);
+}
+int main()
+{
+ // testErase();
+ testInsert();
+ return 0;
+} \ No newline at end of file
diff --git a/tests/manual/corelib/tools/qlist/main.pro b/tests/manual/corelib/tools/qlist/main.pro
new file mode 100644
index 0000000000..bba41b9c12
--- /dev/null
+++ b/tests/manual/corelib/tools/qlist/main.pro
@@ -0,0 +1 @@
+SOURCES = main.cpp
diff --git a/tests/auto/dbus/qdbusabstractinterface/pinger.cpp b/tests/manual/corelib/tools/qmap/main.cpp
index be4fc30409..0d88e3f170 100644
--- a/tests/auto/dbus/qdbusabstractinterface/pinger.cpp
+++ b/tests/manual/corelib/tools/qmap/main.cpp
@@ -1,9 +1,9 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2012 Thorbjørn Lund Martsum - tmartsum[at]gmail.com
** Contact: http://www.qt-project.org/legal
**
-** This file is part of the QtDBus module of the Qt Toolkit.
+** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
@@ -39,29 +39,73 @@
**
****************************************************************************/
-/*
- * This file was generated by qdbusxml2cpp version 0.7
- * Command line was: qdbusxml2cpp -i interface.h -p pinger org.qtproject.QtDBus.Pinger.xml
- *
- * qdbusxml2cpp is Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
- *
- * This is an auto-generated file.
- * This file may have been hand-edited. Look for HAND-EDIT comments
- * before re-generating it.
- */
+//#define Q_NO_DEBUGMAP_PARENT_TEST
+// Comment in line above to skip the parent test.
+#include <QtCore/QMap>
+#include <QDebug>
-#include "pinger.h"
+void noBugErase()
+{
+ QMap<int, int> a, b;
+ a[10] = 11;
+ a[11] = 12;
+ b = a;
+ b.erase(b.begin());
+}
-/*
- * Implementation of interface class ComTrolltechQtDBusPingerInterface
- */
+void noBugInsertWithHints()
+{
+ QMap<int, int> a;
+ QMap<int, int> b;
+ for (int u = 100; u < 10000; u += 20)
+ a.insert(u, u);
+ b = a;
+ QMap<int, int>::const_iterator b_ite(b.begin()); // b.begin() ensures correct detach()
+ ++b_ite;
+ b.insert(b_ite, 501, 501);
+ b.insert(b_ite, 115, 115);
+ QMap<int, int> c;
+ c = b;
+ c.setSharable(false);
+}
-ComTrolltechQtDBusPingerInterface::ComTrolltechQtDBusPingerInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent)
- : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent)
+void testInsertWithHintCorruption()
{
+ qDebug() << "Starting testInsertWithHintCorruption";
+
+ QMap<int, int> a;
+ QMap<int, int> b;
+ for (int u = 100; u < 10000; u += 20)
+ a.insert(u, u);
+ b = a;
+ QMap<int, int>::const_iterator b_ite = b.constBegin();
+ ++b_ite;
+ b.insert(b_ite, 501, 501);
+ b.insert(b_ite, 115, 115); // insert with wrong hint.
+ QMap<int, int> c;
+ c = b;
+ c.setSharable(false);
+ qDebug() << "End of testInsertWithHintCorruption - failed silently";
}
-ComTrolltechQtDBusPingerInterface::~ComTrolltechQtDBusPingerInterface()
+void testEraseCorruption()
{
+ qDebug() << "Starting testEraseCorruption";
+
+ QMap<int, int> a, b;
+ a[10] = 11;
+ a[11] = 12;
+ b = a;
+ b.erase(a.begin());
+ qDebug() << "End of testEraseCorruption - failed silently";
}
+int main()
+{
+ noBugErase();
+ noBugInsertWithHints();
+
+ // testEraseCorruption();
+ testInsertWithHintCorruption();
+ return 0;
+}
diff --git a/tests/manual/corelib/tools/qmap/qmaptest.pro b/tests/manual/corelib/tools/qmap/qmaptest.pro
new file mode 100644
index 0000000000..fbe7013144
--- /dev/null
+++ b/tests/manual/corelib/tools/qmap/qmaptest.pro
@@ -0,0 +1,2 @@
+TEMPLATE = app
+SOURCES = main.cpp
diff --git a/mkspecs/macx-clang-libc++-32/qplatformdefs.h b/tests/manual/corelib/tools/qset/main.cpp
index 2c3a8b1c09..34a6c58c63 100644
--- a/mkspecs/macx-clang-libc++-32/qplatformdefs.h
+++ b/tests/manual/corelib/tools/qset/main.cpp
@@ -1,9 +1,9 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2013 Thorbjørn Lund Martsum - tmartsum[at]gmail.com
** Contact: http://www.qt-project.org/legal
**
-** This file is part of the qmake spec of the Qt Toolkit.
+** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
@@ -39,5 +39,25 @@
**
****************************************************************************/
-#include "../common/mac/qplatformdefs.h"
+#include <QDebug>
+//#define QT_STRICT_ITERATORS
+#include <QSet>
+void testErase()
+{
+ QSet<int> a, b;
+ a.insert(5);
+ a.insert(6);
+ a.insert(7);
+ b = a;
+ a.erase(a.begin());
+ b.erase(b.end() - 1);
+ qDebug() << "erase - no errors until now";
+ a.erase(b.begin());
+}
+
+int main()
+{
+ testErase();
+ return 0;
+}
diff --git a/tests/manual/corelib/tools/qset/main.pro b/tests/manual/corelib/tools/qset/main.pro
new file mode 100644
index 0000000000..bba41b9c12
--- /dev/null
+++ b/tests/manual/corelib/tools/qset/main.pro
@@ -0,0 +1 @@
+SOURCES = main.cpp
diff --git a/tests/manual/corelib/tools/qvarlengtharray/main.cpp b/tests/manual/corelib/tools/qvarlengtharray/main.cpp
new file mode 100644
index 0000000000..759f4b3905
--- /dev/null
+++ b/tests/manual/corelib/tools/qvarlengtharray/main.cpp
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Thorbjørn Lund Martsum - tmartsum[at]gmail.com
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite 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 <QDebug>
+//#define QT_STRICT_ITERATORS
+#include <QVarLengthArray>
+
+void testErase()
+{
+ QVarLengthArray<int> a, b;
+ a.append(5);
+ a.append(6);
+ a.append(7);
+ b = a;
+ a.erase(a.begin());
+ a.erase(a.end() - 1);
+ qDebug() << "erase - no errors until now";
+ // a.erase(a.end());
+ a.erase(b.begin());
+}
+
+void testInsert()
+{
+ QVarLengthArray<int> a, b;
+ a.insert(a.begin(), 1);
+ a.insert(a.begin(), 2);
+ a.insert(a.end(), 3);
+ b = a;
+ qDebug() << "insert - no errors until now";
+ a.insert(b.begin(), 1, 4);
+}
+
+int main()
+{
+ // testErase();
+ testInsert();
+ return 0;
+}
diff --git a/tests/manual/corelib/tools/qvarlengtharray/main.pro b/tests/manual/corelib/tools/qvarlengtharray/main.pro
new file mode 100644
index 0000000000..4ce070ab75
--- /dev/null
+++ b/tests/manual/corelib/tools/qvarlengtharray/main.pro
@@ -0,0 +1 @@
+SOURCES=main.cpp
diff --git a/tests/manual/corelib/tools/qvector/main.cpp b/tests/manual/corelib/tools/qvector/main.cpp
new file mode 100644
index 0000000000..2dce4a9264
--- /dev/null
+++ b/tests/manual/corelib/tools/qvector/main.cpp
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Thorbjørn Lund Martsum - tmartsum[at]gmail.com
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite 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 <QDebug>
+//#define QT_STRICT_ITERATORS
+#include <QVector>
+
+void testErase()
+{
+ QVector<int> a, b;
+ a.append(5);
+ a.append(6);
+ a.append(7);
+ b = a;
+ a.erase(a.begin());
+ a.erase(a.end() - 1);
+ qDebug() << "erase - no errors until now";
+ // a.erase(a.end());
+ a.erase(b.begin());
+}
+
+void testInsert()
+{
+ QVector<int> a, b;
+ a.insert(a.begin(), 1, 1);
+ a.insert(a.begin(), 1, 2);
+ a.insert(a.begin(), 1, 3);
+ b = a;
+ qDebug() << "insert - no errors until now";
+ a.insert(b.begin(), 1, 4);
+}
+
+int main()
+{
+ testErase();
+ // testInsert();
+ return 0;
+}
diff --git a/tests/manual/corelib/tools/qvector/main.pro b/tests/manual/corelib/tools/qvector/main.pro
new file mode 100644
index 0000000000..bba41b9c12
--- /dev/null
+++ b/tests/manual/corelib/tools/qvector/main.pro
@@ -0,0 +1 @@
+SOURCES = main.cpp
diff --git a/tests/manual/dialogs/colordialogpanel.h b/tests/manual/dialogs/colordialogpanel.h
index 05ca336a23..7f2898cea0 100644
--- a/tests/manual/dialogs/colordialogpanel.h
+++ b/tests/manual/dialogs/colordialogpanel.h
@@ -45,9 +45,11 @@
#include <QPointer>
#include <QColorDialog>
+QT_BEGIN_NAMESPACE
class QComboBox;
class QCheckBox;
class QPushButton;
+QT_END_NAMESPACE
class ColorDialogPanel : public QWidget
{
diff --git a/tests/manual/dialogs/dialogs.pro b/tests/manual/dialogs/dialogs.pro
index 4ed200ab7f..d19c3026d0 100644
--- a/tests/manual/dialogs/dialogs.pro
+++ b/tests/manual/dialogs/dialogs.pro
@@ -5,6 +5,6 @@ TARGET = dialogs
TEMPLATE = app
SOURCES += main.cpp filedialogpanel.cpp colordialogpanel.cpp fontdialogpanel.cpp \
- wizardpanel.cpp
+ wizardpanel.cpp messageboxpanel.cpp
HEADERS += filedialogpanel.h colordialogpanel.h fontdialogpanel.h \
- wizardpanel.h
+ wizardpanel.h messageboxpanel.h
diff --git a/tests/manual/dialogs/filedialogpanel.cpp b/tests/manual/dialogs/filedialogpanel.cpp
index a342122570..000d755cef 100644
--- a/tests/manual/dialogs/filedialogpanel.cpp
+++ b/tests/manual/dialogs/filedialogpanel.cpp
@@ -154,9 +154,11 @@ FileDialogPanel::FileDialogPanel(QWidget *parent)
, m_nameFilterDetailsVisible(new QCheckBox(tr("Name filter details visible")))
, m_resolveSymLinks(new QCheckBox(tr("Resolve symlinks")))
, m_native(new QCheckBox(tr("Use native dialog")))
+ , m_customDirIcons(new QCheckBox(tr("Don't use custom directory icons")))
, m_acceptMode(createCombo(this, acceptModeComboData, sizeof(acceptModeComboData)/sizeof(ComboData)))
, m_fileMode(createCombo(this, fileModeComboData, sizeof(fileModeComboData)/sizeof(ComboData)))
, m_viewMode(createCombo(this, viewModeComboData, sizeof(viewModeComboData)/sizeof(ComboData)))
+ , m_allowedSchemes(new QLineEdit(this))
, m_defaultSuffix(new QLineEdit(this))
, m_directory(new QLineEdit(this))
, m_selectedFileName(new QLineEdit(this))
@@ -171,11 +173,13 @@ FileDialogPanel::FileDialogPanel(QWidget *parent)
optionsLayout->addRow(tr("AcceptMode:"), m_acceptMode);
optionsLayout->addRow(tr("FileMode:"), m_fileMode);
optionsLayout->addRow(tr("ViewMode:"), m_viewMode);
+ optionsLayout->addRow(tr("Allowed Schemes:"), m_allowedSchemes);
optionsLayout->addRow(m_native);
optionsLayout->addRow(m_confirmOverWrite);
optionsLayout->addRow(m_nameFilterDetailsVisible);
optionsLayout->addRow(m_resolveSymLinks);
optionsLayout->addRow(m_readOnly);
+ optionsLayout->addRow(m_customDirIcons);
// Files
QGroupBox *filesGroupBox = new QGroupBox(tr("Files / Filters"));
@@ -216,9 +220,13 @@ FileDialogPanel::FileDialogPanel(QWidget *parent)
row = 0;
column++;
addButton(tr("getOpenFileName"), buttonLayout, row, column, this, SLOT(getOpenFileName()));
+ addButton(tr("getOpenFileUrl"), buttonLayout, row, column, this, SLOT(getOpenFileUrl()));
addButton(tr("getOpenFileNames"), buttonLayout, row, column, this, SLOT(getOpenFileNames()));
+ addButton(tr("getOpenFileUrls"), buttonLayout, row, column, this, SLOT(getOpenFileUrls()));
addButton(tr("getSaveFileName"), buttonLayout, row, column, this, SLOT(getSaveFileName()));
+ addButton(tr("getSaveFileUrl"), buttonLayout, row, column, this, SLOT(getSaveFileUrl()));
addButton(tr("getExistingDirectory"), buttonLayout, row, column, this, SLOT(getExistingDirectory()));
+ addButton(tr("getExistingDirectoryUrl"), buttonLayout, row, column, this, SLOT(getExistingDirectoryUrl()));
addButton(tr("Restore defaults"), buttonLayout, row, column, this, SLOT(restoreDefaults()));
// Main layout
@@ -316,9 +324,16 @@ QFileDialog::Options FileDialogPanel::options() const
result |= QFileDialog::DontConfirmOverwrite;
if (!m_native->isChecked())
result |= QFileDialog::DontUseNativeDialog;
+ if (!m_customDirIcons->isChecked())
+ result |= QFileDialog::DontUseCustomDirectoryIcons;
return result;
}
+QStringList FileDialogPanel::allowedSchemes() const
+{
+ return m_allowedSchemes->text().simplified().split(' ', QString::SkipEmptyParts);
+}
+
void FileDialogPanel::getOpenFileNames()
{
QString selectedFilter = m_selectedNameFilter->text().trimmed();
@@ -334,6 +349,22 @@ void FileDialogPanel::getOpenFileNames()
}
}
+void FileDialogPanel::getOpenFileUrls()
+{
+ QString selectedFilter = m_selectedNameFilter->text().trimmed();
+ const QList<QUrl> files =
+ QFileDialog::getOpenFileUrls(this, tr("getOpenFileNames Qt %1").arg(QLatin1String(QT_VERSION_STR)),
+ QUrl(m_directory->text()), filterString(), &selectedFilter, options(),
+ allowedSchemes());
+ if (!files.isEmpty()) {
+ QString result;
+ QDebug(&result).nospace()
+ << "Files: " << QUrl::toStringList(files)
+ << "\nName filter: " << selectedFilter;
+ QMessageBox::information(this, tr("getOpenFileNames"), result, QMessageBox::Ok);
+ }
+}
+
void FileDialogPanel::getOpenFileName()
{
QString selectedFilter = m_selectedNameFilter->text().trimmed();
@@ -349,6 +380,22 @@ void FileDialogPanel::getOpenFileName()
}
}
+void FileDialogPanel::getOpenFileUrl()
+{
+ QString selectedFilter = m_selectedNameFilter->text().trimmed();
+ const QUrl file =
+ QFileDialog::getOpenFileUrl(this, tr("getOpenFileUrl Qt %1").arg(QLatin1String(QT_VERSION_STR)),
+ QUrl(m_directory->text()), filterString(), &selectedFilter, options(),
+ allowedSchemes());
+ if (file.isValid()) {
+ QString result;
+ QDebug(&result).nospace()
+ << "File: " << file.toString()
+ << "\nName filter: " << selectedFilter;
+ QMessageBox::information(this, tr("getOpenFileName"), result, QMessageBox::Ok);
+ }
+}
+
void FileDialogPanel::getSaveFileName()
{
QString selectedFilter = m_selectedNameFilter->text().trimmed();
@@ -364,6 +411,22 @@ void FileDialogPanel::getSaveFileName()
}
}
+void FileDialogPanel::getSaveFileUrl()
+{
+ QString selectedFilter = m_selectedNameFilter->text().trimmed();
+ const QUrl file =
+ QFileDialog::getSaveFileUrl(this, tr("getSaveFileName Qt %1").arg(QLatin1String(QT_VERSION_STR)),
+ QUrl(m_directory->text()), filterString(), &selectedFilter, options(),
+ allowedSchemes());
+ if (file.isValid()) {
+ QString result;
+ QDebug(&result).nospace()
+ << "File: " << file.toString()
+ << "\nName filter: " << selectedFilter;
+ QMessageBox::information(this, tr("getSaveFileNames"), result, QMessageBox::Ok);
+ }
+}
+
void FileDialogPanel::getExistingDirectory()
{
const QString dir =
@@ -373,17 +436,29 @@ void FileDialogPanel::getExistingDirectory()
QMessageBox::information(this, tr("getExistingDirectory"), QLatin1String("Directory: ") + dir, QMessageBox::Ok);
}
+void FileDialogPanel::getExistingDirectoryUrl()
+{
+ const QUrl dir =
+ QFileDialog::getExistingDirectoryUrl(this, tr("getExistingDirectory Qt %1").arg(QLatin1String(QT_VERSION_STR)),
+ QUrl(m_directory->text()), options() | QFileDialog::ShowDirsOnly,
+ allowedSchemes());
+ if (!dir.isEmpty())
+ QMessageBox::information(this, tr("getExistingDirectory"), QLatin1String("Directory: ") + dir.toString(), QMessageBox::Ok);
+}
+
void FileDialogPanel::restoreDefaults()
{
QFileDialog d;
setComboBoxValue(m_acceptMode, d.acceptMode());
setComboBoxValue(m_fileMode, d.fileMode());
setComboBoxValue(m_viewMode, d.viewMode());
+ m_allowedSchemes->setText(QString());
m_confirmOverWrite->setChecked(d.confirmOverwrite());
m_nameFilterDetailsVisible->setChecked(d.isNameFilterDetailsVisible());
m_resolveSymLinks->setChecked(d.resolveSymlinks());
m_readOnly->setChecked(d.isReadOnly());
m_native->setChecked(true);
+ m_customDirIcons->setChecked(d.testOption(QFileDialog::DontUseCustomDirectoryIcons));
m_directory->setText(QDir::homePath());
m_defaultSuffix->setText(QLatin1String("txt"));
m_nameFilters->setPlainText(QLatin1String("Any files (*)\nImage files (*.png *.xpm *.jpg)\nText files (*.txt)"));
diff --git a/tests/manual/dialogs/filedialogpanel.h b/tests/manual/dialogs/filedialogpanel.h
index 2977de4164..2e1d5d4de9 100644
--- a/tests/manual/dialogs/filedialogpanel.h
+++ b/tests/manual/dialogs/filedialogpanel.h
@@ -46,11 +46,13 @@
#include <QFileDialog>
#include <QPointer>
+QT_BEGIN_NAMESPACE
class QPushButton;
class QCheckBox;
class QComboBox;
class QLineEdit;
class QPlainTextEdit;
+QT_END_NAMESPACE
class LabelLineEdit;
class FileDialogPanel : public QWidget
@@ -66,9 +68,13 @@ public slots:
void deleteNonModalDialog();
void deleteModalDialog();
void getOpenFileNames();
+ void getOpenFileUrls();
void getOpenFileName();
+ void getOpenFileUrl();
void getSaveFileName();
+ void getSaveFileUrl();
void getExistingDirectory();
+ void getExistingDirectoryUrl();
void accepted();
void showAcceptedResult();
void restoreDefaults();
@@ -80,6 +86,7 @@ private slots:
private:
QString filterString() const;
QFileDialog::Options options() const;
+ QStringList allowedSchemes() const;
void applySettings(QFileDialog *d) const;
QCheckBox *m_readOnly;
@@ -87,9 +94,11 @@ private:
QCheckBox *m_nameFilterDetailsVisible;
QCheckBox *m_resolveSymLinks;
QCheckBox *m_native;
+ QCheckBox *m_customDirIcons;
QComboBox *m_acceptMode;
QComboBox *m_fileMode;
QComboBox *m_viewMode;
+ QLineEdit *m_allowedSchemes;
QLineEdit *m_defaultSuffix;
QLineEdit *m_directory;
QLineEdit *m_selectedFileName;
diff --git a/tests/manual/dialogs/fontdialogpanel.cpp b/tests/manual/dialogs/fontdialogpanel.cpp
index 02f05f9580..c72bf77351 100644
--- a/tests/manual/dialogs/fontdialogpanel.cpp
+++ b/tests/manual/dialogs/fontdialogpanel.cpp
@@ -67,12 +67,20 @@ FontDialogPanel::FontDialogPanel(QWidget *parent)
, m_fontSizeBox(new QDoubleSpinBox)
, m_noButtons(new QCheckBox(tr("Don't display OK/Cancel buttons")))
, m_dontUseNativeDialog(new QCheckBox(tr("Don't use native dialog")))
+ , m_scalableFilter(new QCheckBox(tr("Filter scalable fonts")))
+ , m_nonScalableFilter(new QCheckBox(tr("Filter non scalable fonts")))
+ , m_monospacedFilter(new QCheckBox(tr("Filter monospaced fonts")))
+ , m_proportionalFilter(new QCheckBox(tr("Filter proportional fonts")))
{
// Options
QGroupBox *optionsGroupBox = new QGroupBox(tr("Options"), this);
QVBoxLayout *optionsLayout = new QVBoxLayout(optionsGroupBox);
optionsLayout->addWidget(m_noButtons);
optionsLayout->addWidget(m_dontUseNativeDialog);
+ optionsLayout->addWidget(m_scalableFilter);
+ optionsLayout->addWidget(m_nonScalableFilter);
+ optionsLayout->addWidget(m_monospacedFilter);
+ optionsLayout->addWidget(m_proportionalFilter);
// Font
QGroupBox *fontGroupBox = new QGroupBox(tr("Font"), this);
@@ -201,6 +209,10 @@ void FontDialogPanel::applySettings(QFontDialog *d) const
{
d->setOption(QFontDialog::NoButtons, m_noButtons->isChecked());
d->setOption(QFontDialog::DontUseNativeDialog, m_dontUseNativeDialog->isChecked());
+ d->setOption(QFontDialog::ScalableFonts, m_scalableFilter->isChecked());
+ d->setOption(QFontDialog::NonScalableFonts, m_nonScalableFilter->isChecked());
+ d->setOption(QFontDialog::MonospacedFonts, m_monospacedFilter->isChecked());
+ d->setOption(QFontDialog::ProportionalFonts, m_proportionalFilter->isChecked());
QFont font = m_fontFamilyBox->currentFont();
font.setPointSizeF(m_fontSizeBox->value());
diff --git a/tests/manual/dialogs/fontdialogpanel.h b/tests/manual/dialogs/fontdialogpanel.h
index f3bbbb3939..4592c2ec6e 100644
--- a/tests/manual/dialogs/fontdialogpanel.h
+++ b/tests/manual/dialogs/fontdialogpanel.h
@@ -45,10 +45,12 @@
#include <QPointer>
#include <QFontDialog>
+QT_BEGIN_NAMESPACE
class QCheckBox;
class QPushButton;
class QFontComboBox;
class QDoubleSpinBox;
+QT_END_NAMESPACE
class FontDialogPanel : public QWidget
{
@@ -77,6 +79,10 @@ private:
QDoubleSpinBox *m_fontSizeBox;
QCheckBox *m_noButtons;
QCheckBox *m_dontUseNativeDialog;
+ QCheckBox *m_scalableFilter;
+ QCheckBox *m_nonScalableFilter;
+ QCheckBox *m_monospacedFilter;
+ QCheckBox *m_proportionalFilter;
QPushButton *m_deleteNonModalDialogButton;
QPushButton *m_deleteModalDialogButton;
QString m_result;
diff --git a/tests/manual/dialogs/main.cpp b/tests/manual/dialogs/main.cpp
index 4ad2842e44..c5f14cabef 100644
--- a/tests/manual/dialogs/main.cpp
+++ b/tests/manual/dialogs/main.cpp
@@ -43,6 +43,7 @@
#include "colordialogpanel.h"
#include "fontdialogpanel.h"
#include "wizardpanel.h"
+#include "messageboxpanel.h"
#include <QMainWindow>
#include <QApplication>
@@ -73,6 +74,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
tabWidget->addTab(new ColorDialogPanel, tr("QColorDialog"));
tabWidget->addTab(new FontDialogPanel, tr("QFontDialog"));
tabWidget->addTab(new WizardPanel, tr("QWizard"));
+ tabWidget->addTab(new MessageBoxPanel, tr("QMessageBox"));
setCentralWidget(tabWidget);
}
diff --git a/tests/manual/dialogs/messageboxpanel.cpp b/tests/manual/dialogs/messageboxpanel.cpp
new file mode 100644
index 0000000000..6af6b8502f
--- /dev/null
+++ b/tests/manual/dialogs/messageboxpanel.cpp
@@ -0,0 +1,175 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Thorbjørn Lund Martsum - tmartsum[at]gmail.com
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite 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 "messageboxpanel.h"
+
+#include <QGroupBox>
+#include <QPushButton>
+#include <QVBoxLayout>
+#include <QHBoxLayout>
+#include <QMessageBox>
+#include <QPushButton>
+#include <QDebug>
+#include <QComboBox>
+#include <QLineEdit>
+#include <QLabel>
+#include <QCheckBox>
+
+MessageBoxPanel::MessageBoxPanel(QWidget *parent) : QWidget(parent)
+,m_iconComboBox(new QComboBox)
+,m_textInMsgBox(new QLineEdit)
+,m_informativeText(new QLineEdit)
+,m_buttonsMask(new QLineEdit)
+,m_btnExec(new QPushButton)
+,m_btnShowApply(new QPushButton)
+,m_resultLabel(new QLabel)
+,m_chkReallocMsgBox(new QCheckBox(QString::fromLatin1("Reallocate Message Box")))
+,m_msgbox(new QMessageBox)
+{
+ // --- Options ---
+ QGroupBox *optionsGroupBox = new QGroupBox(tr("Options"), this);
+ QVBoxLayout *optionsLayout = new QVBoxLayout(optionsGroupBox);
+
+ // text
+ optionsLayout->addWidget(new QLabel(QString::fromLatin1("Message box text")));
+ m_textInMsgBox->setText(QString::fromLatin1("This is a simple test with a text that is not long"));
+ optionsLayout->addWidget(m_textInMsgBox);
+
+ // informative text
+ optionsLayout->addWidget(new QLabel(QString::fromLatin1("Informative Text")));
+ optionsLayout->addWidget(m_informativeText);
+
+ // icon
+ QStringList items;
+ items << "NoIcon" << "Information" << "Warning" << "Critical" << "Question";
+ m_iconComboBox->addItems(items);
+ optionsLayout->addWidget(new QLabel(QString::fromLatin1("Message box icon")));
+ optionsLayout->addWidget(m_iconComboBox);
+
+ // buttons mask
+ optionsLayout->addWidget(new QLabel(QString::fromLatin1("Message box button mask (in hex)")));
+ m_validator = new QRegExpValidator(QRegExp("0[xX]?[0-9a-fA-F]+"), this);
+ m_buttonsMask->setMaxLength(10);
+ m_buttonsMask->setValidator(m_validator);
+ m_buttonsMask->setText(QString::fromLatin1("0x00300400"));
+ optionsLayout->addWidget(m_buttonsMask);
+
+ // reallocate
+ optionsLayout->addWidget(m_chkReallocMsgBox);
+ optionsLayout->addItem(new QSpacerItem(10, 10, QSizePolicy::Expanding, QSizePolicy::Expanding));
+
+ // Exec/Show
+ QGroupBox *execGroupBox = new QGroupBox(tr("Exec"));
+ QVBoxLayout *execLayout = new QVBoxLayout(execGroupBox);
+ m_btnExec->setText(QString::fromLatin1("Exec message box"));
+ connect(m_btnExec, SIGNAL(clicked()), this, SLOT(doExec()));
+ execLayout->addWidget(m_btnExec);
+
+ m_btnShowApply->setText(QString::fromLatin1("Show / apply"));
+ connect(m_btnShowApply, SIGNAL(clicked()), this, SLOT(doShowApply()));
+ execLayout->addWidget(m_btnShowApply);
+
+ // result label
+ execLayout->addWidget(m_resultLabel);
+
+ execLayout->addItem(new QSpacerItem(10, 10, QSizePolicy::Expanding, QSizePolicy::Expanding));
+ execGroupBox->setLayout(execLayout);
+
+ // Main layout
+ QHBoxLayout *mainLayout = new QHBoxLayout();
+ mainLayout->addWidget(optionsGroupBox);
+ mainLayout->addWidget(execGroupBox);
+
+ setLayout(mainLayout);
+}
+
+void MessageBoxPanel::setupMessageBox(QMessageBox &box)
+{
+ m_resultLabel->setText(QString());
+ box.setText(m_textInMsgBox->text());
+ box.setInformativeText(m_informativeText->text());
+
+ QString btnHexText = m_buttonsMask->text();
+ btnHexText = btnHexText.replace(QString::fromLatin1("0x"), QString(), Qt::CaseInsensitive);
+ bool ok;
+ QMessageBox::StandardButtons btns = (QMessageBox::StandardButtons) btnHexText.toUInt(&ok, 16);
+ box.setStandardButtons((QMessageBox::StandardButtons) btns);
+ if (box.standardButtons() == (QMessageBox::StandardButtons) 0)
+ box.setStandardButtons(QMessageBox::Ok); // just to have something.
+
+ box.setIcon((QMessageBox::Icon) m_iconComboBox->currentIndex());
+}
+
+MessageBoxPanel::~MessageBoxPanel()
+{
+ if (m_msgbox)
+ m_msgbox->deleteLater();
+}
+
+void MessageBoxPanel::doExec()
+{
+ if (!m_msgbox || m_chkReallocMsgBox->isChecked()) {
+ if (m_msgbox)
+ m_msgbox->deleteLater();
+ m_msgbox = new QMessageBox;
+ }
+ setupMessageBox(*m_msgbox);
+ m_msgbox->setWindowModality(Qt::NonModal);
+
+ int res = m_msgbox->exec();
+ QString sres;
+ sres.setNum(res, 16);
+ m_resultLabel->setText(QString::fromLatin1("Return value (hex): %1").arg(sres));
+}
+
+void MessageBoxPanel::doShowApply()
+{
+ if (!m_msgbox || m_chkReallocMsgBox->isChecked()) {
+ if (m_msgbox)
+ m_msgbox->deleteLater();
+ m_msgbox = new QMessageBox;
+ }
+ setupMessageBox(*m_msgbox);
+ if (!m_msgbox->isVisible()) {
+ m_msgbox->setWindowModality(Qt::NonModal);
+ m_msgbox->show();
+ }
+}
diff --git a/tests/manual/dialogs/messageboxpanel.h b/tests/manual/dialogs/messageboxpanel.h
new file mode 100644
index 0000000000..37093b3ff5
--- /dev/null
+++ b/tests/manual/dialogs/messageboxpanel.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 2013 Thorbjørn Lund Martsum - tmartsum[at]gmail.com
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite 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$
+**
+****************************************************************************/
+
+#ifndef MESSAGEBOXPANEL_H
+#define MESSAGEBOXPANEL_H
+
+#include <QWidget>
+
+QT_BEGIN_NAMESPACE
+class QComboBox;
+class QCheckBox;
+class QPushButton;
+class QLineEdit;
+class QValidator;
+class QLabel;
+class QMessageBox;
+class QCheckBox;
+QT_END_NAMESPACE
+
+class MessageBoxPanel : public QWidget
+{
+ Q_OBJECT
+public:
+ explicit MessageBoxPanel(QWidget *parent = 0);
+ ~MessageBoxPanel();
+
+public slots:
+ void doExec();
+ void doShowApply();
+
+private:
+ QComboBox *m_iconComboBox;
+ QLineEdit *m_textInMsgBox;
+ QLineEdit *m_informativeText;
+ QLineEdit *m_buttonsMask;
+ QPushButton *m_btnExec;
+ QPushButton *m_btnShowApply;
+ QValidator *m_validator;
+ QLabel *m_resultLabel;
+ QCheckBox *m_chkReallocMsgBox;
+ QMessageBox *m_msgbox;
+ void setupMessageBox(QMessageBox &box);
+};
+
+#endif
diff --git a/tests/manual/dialogs/wizardpanel.h b/tests/manual/dialogs/wizardpanel.h
index 6a2268e94c..10e0c5071e 100644
--- a/tests/manual/dialogs/wizardpanel.h
+++ b/tests/manual/dialogs/wizardpanel.h
@@ -46,7 +46,9 @@
class WizardStyleControl;
class WizardOptionsControl;
+QT_BEGIN_NAMESPACE
class QWizard;
+QT_END_NAMESPACE
class WizardPanel : public QWidget
{
diff --git a/tests/manual/manual.pro b/tests/manual/manual.pro
index 2fa05f65e0..c04f22b53b 100644
--- a/tests/manual/manual.pro
+++ b/tests/manual/manual.pro
@@ -20,6 +20,7 @@ qlayout \
qlocale \
qnetworkaccessmanager/qget \
qnetworkconfigurationmanager \
+qnetworkconfiguration \
qnetworkreply \
qpainfo \
qscreen \
diff --git a/tests/manual/qnetworkconfiguration/main.cpp b/tests/manual/qnetworkconfiguration/main.cpp
new file mode 100644
index 0000000000..c611cfc9e2
--- /dev/null
+++ b/tests/manual/qnetworkconfiguration/main.cpp
@@ -0,0 +1,139 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Research in Motion.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite 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 <QDebug>
+#include <qtest.h>
+#include <QtTest/QtTest>
+#include <QtNetwork/qnetworkconfiguration.h>
+#include <QtNetwork/qnetworkconfigmanager.h>
+
+class tst_qnetworkconfiguration : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void bearerType();
+ void bearerTypeFamily();
+};
+
+void tst_qnetworkconfiguration::bearerType()
+{
+ QNetworkConfigurationManager m;
+ QList<QNetworkConfiguration> allConfs = m.allConfigurations();
+ QElapsedTimer timer;
+ for (int a = 0; a < allConfs.count(); a++) {
+ timer.start();
+ QNetworkConfiguration::BearerType type = allConfs.at(a).bearerType();
+ qint64 elapsed = timer.elapsed();
+ QString typeString;
+ switch (type) {
+ case QNetworkConfiguration::BearerUnknown:
+ typeString = QLatin1String("Unknown");
+ break;
+ case QNetworkConfiguration::BearerEthernet:
+ typeString = QLatin1String("Ethernet");
+ break;
+ case QNetworkConfiguration::BearerWLAN:
+ typeString = QLatin1String("WLAN");
+ break;
+ case QNetworkConfiguration::Bearer2G:
+ typeString = QLatin1String("2G");
+ break;
+ case QNetworkConfiguration::BearerCDMA2000:
+ typeString = QLatin1String("CDMA2000");
+ break;
+ case QNetworkConfiguration::BearerWCDMA:
+ typeString = QLatin1String("WCDMA");
+ break;
+ case QNetworkConfiguration::BearerHSPA:
+ typeString = QLatin1String("HSPA");
+ break;
+ case QNetworkConfiguration::BearerBluetooth:
+ typeString = QLatin1String("Bluetooth");
+ break;
+ case QNetworkConfiguration::BearerWiMAX:
+ typeString = QLatin1String("WiMAX");
+ break;
+ case QNetworkConfiguration::BearerEVDO:
+ typeString = QLatin1String("EVDO");
+ break;
+ case QNetworkConfiguration::BearerLTE:
+ typeString = QLatin1String("LTE");
+ break;
+ default:
+ typeString = "unknown bearer (?)";
+ }
+
+ const char *isDefault = (allConfs.at(a) == m.defaultConfiguration())
+ ? "*DEFAULT*" : "";
+ qDebug() << isDefault << "identifier:" << allConfs.at(a).identifier()
+ << "bearer type name:" << allConfs.at(a).bearerTypeName()
+ << "bearer type:" << type << "(" << typeString << ")"
+ << "elapsed:" << elapsed;
+ QCOMPARE(allConfs.at(a).bearerTypeName(), typeString);
+ }
+}
+
+void tst_qnetworkconfiguration::bearerTypeFamily()
+{
+ QNetworkConfigurationManager m;
+ foreach (const QNetworkConfiguration &config,
+ m.allConfigurations(QNetworkConfiguration::Active)) {
+ QString family;
+ switch (config.bearerTypeFamily()) {
+ case QNetworkConfiguration::Bearer3G:
+ family = QLatin1String("Bearer3G");
+ break;
+ case QNetworkConfiguration::Bearer4G:
+ family = QLatin1String("Bearer4G");
+ break;
+ default:
+ family = config.bearerTypeName();
+ }
+ qDebug() << config.name() << "has bearer type"
+ << config.bearerTypeName() << "of bearer type family"
+ << family;
+ }
+}
+
+QTEST_MAIN(tst_qnetworkconfiguration)
+
+#include "main.moc"
diff --git a/tests/manual/qnetworkconfiguration/qnetworkconfiguration.pro b/tests/manual/qnetworkconfiguration/qnetworkconfiguration.pro
new file mode 100644
index 0000000000..25ef41b92a
--- /dev/null
+++ b/tests/manual/qnetworkconfiguration/qnetworkconfiguration.pro
@@ -0,0 +1,7 @@
+TEMPLATE = app
+TARGET = tst_qnetworkconfiguration
+
+QT -= gui
+QT += network testlib
+
+SOURCES += main.cpp
diff --git a/tests/manual/qpainfo/main.cpp b/tests/manual/qpainfo/main.cpp
index 6b712304a0..0f5119bab3 100644
--- a/tests/manual/qpainfo/main.cpp
+++ b/tests/manual/qpainfo/main.cpp
@@ -49,6 +49,7 @@
#include <QStringList>
#include <QVariant>
#include <QFont>
+#include <QFontDatabase>
#include <QSysInfo>
#include <QLibraryInfo>
#include <QStandardPaths>
@@ -85,6 +86,12 @@ std::ostream &operator<<(std::ostream &str, const QStringList &l)
return str;
}
+std::ostream &operator<<(std::ostream &str, const QFont &f)
+{
+ std::cout << '"' << f.family().toStdString() << "\" " << f.pointSize();
+ return str;
+}
+
static QStringList toNativeSeparators(QStringList in)
{
for (int i = 0; i < in.size(); ++i)
@@ -184,7 +191,12 @@ int main(int argc, char **argv)
<< " from " << platformTheme->themeHint(QPlatformTheme::IconThemeSearchPaths).toStringList() << '\n';
}
if (const QFont *systemFont = platformTheme->font())
- std::cout << " System font: \"" << systemFont->family().toStdString() << "\" " << systemFont->pointSize() << '\n';
+ std::cout << " System font: " << *systemFont<< '\n';
+ std::cout << " General font : " << QFontDatabase::systemFont(QFontDatabase::GeneralFont) << '\n'
+ << " Fixed font : " << QFontDatabase::systemFont(QFontDatabase::FixedFont) << '\n'
+ << " Title font : " << QFontDatabase::systemFont(QFontDatabase::TitleFont) << '\n'
+ << " Smallest font: " << QFontDatabase::systemFont(QFontDatabase::SmallestReadableFont) << "\n\n";
+
if (platformTheme->usePlatformNativeDialog(QPlatformTheme::FileDialog))
std::cout << " Native file dialog\n";
if (platformTheme->usePlatformNativeDialog(QPlatformTheme::ColorDialog))
diff --git a/tests/manual/qtabletevent/regular_widgets/main.cpp b/tests/manual/qtabletevent/regular_widgets/main.cpp
index 1e2f5c00da..ce77cf8cff 100644
--- a/tests/manual/qtabletevent/regular_widgets/main.cpp
+++ b/tests/manual/qtabletevent/regular_widgets/main.cpp
@@ -43,12 +43,38 @@
#include <QDebug>
#include <QMouseEvent>
#include <QTabletEvent>
-#include <QWidget>
+#include <QMainWindow>
+#include <QMenuBar>
+#include <QMenu>
+#include <QAction>
+#include <QVector>
+#include <QPainter>
+#include <QCursor>
+
+enum TabletPointType {
+ TabletButtonPress,
+ TabletButtonRelease,
+ TabletMove,
+ TabletDraw
+};
+
+struct TabletPoint
+{
+ TabletPoint(const QPoint &p = QPoint(), TabletPointType t = TabletMove) : pos(p), type(t) {}
+
+ QPoint pos;
+ TabletPointType type;
+};
class EventReportWidget : public QWidget
{
+ Q_OBJECT
public:
EventReportWidget();
+
+public slots:
+ void clearPoints() { m_points.clear(); update(); }
+
protected:
void mouseDoubleClickEvent(QMouseEvent *event) { outputMouseEvent(event); }
void mouseMoveEvent(QMouseEvent *event) { outputMouseEvent(event); }
@@ -57,11 +83,14 @@ protected:
void tabletEvent(QTabletEvent *);
+ void paintEvent(QPaintEvent *);
+
private:
void outputMouseEvent(QMouseEvent *event);
bool m_lastIsMouseMove;
bool m_lastIsTabletMove;
+ QVector<TabletPoint> m_points;
};
EventReportWidget::EventReportWidget()
@@ -69,6 +98,34 @@ EventReportWidget::EventReportWidget()
, m_lastIsTabletMove(false)
{ }
+void EventReportWidget::paintEvent(QPaintEvent *)
+{
+ QPainter p(this);
+ const QRect geom = QRect(QPoint(0, 0), size());
+ p.fillRect(geom, Qt::white);
+ p.drawRect(QRect(geom.topLeft(), geom.bottomRight() - QPoint(1,1)));
+ foreach (const TabletPoint &t, m_points) {
+ if (geom.contains(t.pos)) {
+ QPainterPath pp;
+ pp.addEllipse(t.pos, 5, 5);
+ switch (t.type) {
+ case TabletButtonPress:
+ p.fillPath(pp, Qt::black);
+ break;
+ case TabletButtonRelease:
+ p.fillPath(pp, Qt::red);
+ break;
+ case TabletMove:
+ p.drawPath(pp);
+ break;
+ case TabletDraw:
+ p.fillPath(pp, Qt::blue);
+ break;
+ }
+ }
+ }
+}
+
void EventReportWidget::tabletEvent(QTabletEvent *event)
{
QWidget::tabletEvent(event);
@@ -89,14 +146,20 @@ void EventReportWidget::tabletEvent(QTabletEvent *event)
m_lastIsTabletMove = true;
type = QString::fromLatin1("TabletMove");
+ m_points.push_back(TabletPoint(event->pos(), event->pressure() ? TabletDraw : TabletMove));
+ update();
break;
case QEvent::TabletPress:
m_lastIsTabletMove = false;
type = QString::fromLatin1("TabletPress");
+ m_points.push_back(TabletPoint(event->pos(), TabletButtonPress));
+ update();
break;
case QEvent::TabletRelease:
m_lastIsTabletMove = false;
type = QString::fromLatin1("TabletRelease");
+ m_points.push_back(TabletPoint(event->pos(), TabletButtonRelease));
+ update();
break;
default:
Q_ASSERT(false);
@@ -105,7 +168,8 @@ void EventReportWidget::tabletEvent(QTabletEvent *event)
qDebug() << "Tablet event, type = " << type
<< " position = " << event->pos()
- << " global position = " << event->globalPos();
+ << " global position = " << event->globalPos()
+ << " cursor at " << QCursor::pos();
}
void EventReportWidget::outputMouseEvent(QMouseEvent *event)
@@ -144,7 +208,18 @@ void EventReportWidget::outputMouseEvent(QMouseEvent *event)
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
- EventReportWidget widget;
- widget.show();
+ QMainWindow mainWindow;
+ mainWindow.setWindowTitle(QString::fromLatin1("Tablet Test %1").arg(QT_VERSION_STR));
+ EventReportWidget *widget = new EventReportWidget;
+ widget->setMinimumSize(640, 480);
+ QMenu *fileMenu = mainWindow.menuBar()->addMenu("File");
+ QObject::connect(fileMenu->addAction("Clear"), SIGNAL(triggered()), widget, SLOT(clearPoints()));
+ QAction *quitAction = fileMenu->addAction("Quit");
+ QObject::connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
+ quitAction->setShortcut(Qt::CTRL + Qt::Key_Q);
+ mainWindow.setCentralWidget(widget);
+ mainWindow.show();
return app.exec();
}
+
+#include "main.moc"
diff --git a/tests/manual/widgets/itemviews/autoResizePrecision/tablehorz/testtable1.cpp b/tests/manual/widgets/itemviews/autoResizePrecision/tablehorz/testtable1.cpp
new file mode 100644
index 0000000000..463366433c
--- /dev/null
+++ b/tests/manual/widgets/itemviews/autoResizePrecision/tablehorz/testtable1.cpp
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Thorbjørn Lund Martsum - tmartsum[at]gmail.com
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite 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 <QtWidgets/QtWidgets>
+
+const int rowCount = 2000;
+
+class TableDialog : public QDialog
+{
+ Q_OBJECT
+public:
+ TableDialog() : model(rowCount, 3) { create(); }
+ void create()
+ {
+ resize(1000, 233);
+ gridLayout = new QGridLayout(this);
+ tableView = new QTableView(this);
+
+ gridLayout->addWidget(tableView, 0, 0, 2, 1);
+ spinPrecision = new QSpinBox(this);
+ gridLayout->addWidget(spinPrecision, 0, 1, 1, 1);
+ verticalSpacer = new QSpacerItem(20, 20, QSizePolicy::Minimum, QSizePolicy::Expanding);
+ gridLayout->addItem(verticalSpacer, 1, 1, 1, 1);
+
+ QString ii = QString::fromLatin1("ii");
+ QStringList is;
+ spinPrecision->setMinimum(-1);
+ spinPrecision->setMaximum(rowCount + 2);
+ for (int u = 0; u < rowCount; ++u) {
+ if (u % 25 == 0)
+ ii += QString::fromLatin1("i");
+ else
+ ii[ii.length() - 1] = QChar::fromLatin1('a' + (u % 25));
+ ii[ii.length() - 2] = QChar::fromLatin1('i');
+ is.append(ii);
+ }
+
+ for (int u = 0; u < rowCount; ++u) {
+ QString col1;
+ col1 = QString::fromLatin1("Row: %1").arg(u);
+ model.setData(model.index(u, 0), col1);
+ model.setData(model.index(u, 1), is[u]);
+ model.setData(model.index(u, 2), is[rowCount - u -1]);
+ }
+ tableView->setModel(&model);
+
+ tableView->horizontalHeader()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
+ tableView->horizontalHeader()->setSectionResizeMode(1, QHeaderView::ResizeToContents);
+ tableView->horizontalHeader()->setSectionResizeMode(2, QHeaderView::ResizeToContents);
+ spinPrecision->setValue(tableView->horizontalHeader()->resizeContentsPrecision());
+ connect(spinPrecision, SIGNAL(valueChanged(int)), this, SLOT(slotValueChanged(int)));
+ } // setupUi
+protected slots:
+ void slotValueChanged(int newval);
+protected:
+ QGridLayout *gridLayout;
+ QTableView *tableView;
+ QSpinBox *spinPrecision;
+ QSpacerItem *verticalSpacer;
+ QStandardItemModel model;
+};
+
+void TableDialog::slotValueChanged(int newval)
+{
+ tableView->horizontalHeader()->setResizeContentsPrecision(newval, true);
+}
+
+
+int main(int argc, char *argv[])
+{
+ QApplication app(argc, argv);
+ TableDialog d1;
+ d1.show();
+ app.exec();
+}
+
+#include "testtable1.moc"
diff --git a/tests/manual/widgets/itemviews/autoResizePrecision/tablehorz/testtable1.pro b/tests/manual/widgets/itemviews/autoResizePrecision/tablehorz/testtable1.pro
new file mode 100644
index 0000000000..e07f40bc2f
--- /dev/null
+++ b/tests/manual/widgets/itemviews/autoResizePrecision/tablehorz/testtable1.pro
@@ -0,0 +1,2 @@
+SOURCES = testtable1.cpp
+QT += widgets
diff --git a/tests/manual/widgets/itemviews/autoResizePrecision/tablevert/testtable2.cpp b/tests/manual/widgets/itemviews/autoResizePrecision/tablevert/testtable2.cpp
new file mode 100644
index 0000000000..027801d528
--- /dev/null
+++ b/tests/manual/widgets/itemviews/autoResizePrecision/tablevert/testtable2.cpp
@@ -0,0 +1,125 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Thorbjørn Lund Martsum - tmartsum[at]gmail.com
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite 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 <QtWidgets/QtWidgets>
+
+const int columnCount = 1500;
+
+class TableDialog : public QDialog
+{
+ Q_OBJECT
+public:
+ TableDialog() : model(2, columnCount) { create(); }
+ void create()
+ {
+ resize(1200, 400);
+ gridLayout = new QGridLayout(this);
+ tableView = new QTableView(this);
+
+ gridLayout->addWidget(tableView, 0, 0, 2, 1);
+ spinPrecision = new QSpinBox(this);
+ gridLayout->addWidget(spinPrecision, 0, 1, 1, 1);
+ verticalSpacer = new QSpacerItem(20, 20, QSizePolicy::Minimum, QSizePolicy::Expanding);
+ gridLayout->addItem(verticalSpacer, 1, 1, 1, 1);
+
+ QString ii = QString::fromLatin1("ii");
+ QStringList is;
+ spinPrecision->setMinimum(-1);
+ spinPrecision->setMaximum(columnCount + 2);
+
+ QFont f = QApplication::font();
+ for (int u = 0; u < columnCount; ++u) {
+ int size = 10 + (u % 63);
+ f.setPixelSize(size);
+ QString col;
+ if (u % 50 < 25)
+ col = QChar::fromLatin1('a' + (u % 25));
+ else
+ col = QChar::fromLatin1('A' + (u % 25));
+
+ int v = columnCount - u - 1;
+ model.setData(model.index(0, u), col);
+ model.setData(model.index(1, v), col);
+
+ model.setData(model.index(0, u), f, Qt::FontRole);
+ model.setData(model.index(1, v), f, Qt::FontRole);
+ }
+ tableView->setModel(&model);
+
+ for (int u = 0; u < columnCount; ++ u)
+ tableView->horizontalHeader()->resizeSection(u, 60);
+
+ // Make last index in first row a bit special
+ f.setPixelSize(96);
+ model.setData(model.index(0, columnCount - 1), f, Qt::FontRole);
+ model.setData(model.index(0, columnCount - 1), QString::fromLatin1("qI"));
+ tableView->horizontalHeader()->resizeSection(columnCount - 1, 140);
+
+ tableView->verticalHeader()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
+ tableView->verticalHeader()->setSectionResizeMode(1, QHeaderView::ResizeToContents);
+ spinPrecision->setValue(tableView->verticalHeader()->resizeContentsPrecision());
+ connect(spinPrecision, SIGNAL(valueChanged(int)), this, SLOT(slotValueChanged(int)));
+ } // setupUi
+protected slots:
+ void slotValueChanged(int newval);
+protected:
+ QGridLayout *gridLayout;
+ QTableView *tableView;
+ QSpinBox *spinPrecision;
+ QSpacerItem *verticalSpacer;
+ QStandardItemModel model;
+};
+
+void TableDialog::slotValueChanged(int newval)
+{
+ tableView->verticalHeader()->setResizeContentsPrecision(newval, true);
+}
+
+
+int main(int argc, char *argv[])
+{
+ QApplication app(argc, argv);
+ TableDialog d1;
+ d1.show();
+ app.exec();
+}
+
+#include "testtable2.moc"
diff --git a/tests/manual/widgets/itemviews/autoResizePrecision/tablevert/testtable2.pro b/tests/manual/widgets/itemviews/autoResizePrecision/tablevert/testtable2.pro
new file mode 100644
index 0000000000..b887fcb14b
--- /dev/null
+++ b/tests/manual/widgets/itemviews/autoResizePrecision/tablevert/testtable2.pro
@@ -0,0 +1,2 @@
+SOURCES = testtable2.cpp
+QT += widgets
diff --git a/tests/manual/widgets/itemviews/autoResizePrecision/treeview/testtree.cpp b/tests/manual/widgets/itemviews/autoResizePrecision/treeview/testtree.cpp
new file mode 100644
index 0000000000..c48d933fcd
--- /dev/null
+++ b/tests/manual/widgets/itemviews/autoResizePrecision/treeview/testtree.cpp
@@ -0,0 +1,132 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Thorbjørn Lund Martsum - tmartsum[at]gmail.com
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite 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 <QtWidgets/QtWidgets>
+
+class TreeDialog : public QDialog
+{
+ Q_OBJECT
+public:
+ TreeDialog() { create(); }
+protected:
+ void create()
+ {
+ resize(1000, 233);
+ gridLayout = new QGridLayout(this);
+ treeWidget = new QTreeWidget(this);
+
+ gridLayout->addWidget(treeWidget, 0, 0, 2, 1);
+ spinPrecision = new QSpinBox(this);
+ gridLayout->addWidget(spinPrecision, 0, 1, 1, 1);
+ verticalSpacer = new QSpacerItem(20, 20, QSizePolicy::Minimum, QSizePolicy::Expanding);
+ gridLayout->addItem(verticalSpacer, 1, 1, 1, 1);
+
+ QStringList itemInfo("Col1");
+ itemInfo.append("Col2");
+ itemInfo.append("Col3");
+ itemInfo.append("Dummy");
+ // Developer no. could also have been social security number og some other id.
+ treeWidget->setHeaderLabels(itemInfo);
+
+ QStringList sl1("This is Root Item");
+ sl1.append("i");
+ QTreeWidgetItem *rootitem = new QTreeWidgetItem(treeWidget, sl1);
+
+ QStringList sl2("This is Child1 Item");
+ sl2.append("WW");
+ QTreeWidgetItem *child1 = new QTreeWidgetItem(rootitem, sl2);
+
+ QString ii = QString::fromLatin1("ii");
+ QStringList is;
+ const int rowCount = 3000;
+ spinPrecision->setMinimum(-1);
+ spinPrecision->setMaximum(rowCount + 5);
+ for (int u = 0; u < rowCount; ++u) {
+ if (u % 25 == 0)
+ ii += QString::fromLatin1("i");
+ else
+ ii[ii.length() - 1] = QChar::fromLatin1('a' + (u % 25));
+ ii[ii.length() - 2] = QChar::fromLatin1('i');
+ is.append(ii);
+ }
+
+ for (int u = 0; u < rowCount - 2; ++u) { // -2 since we have rootitem and child1
+ QString col1;
+ col1 = QString::fromLatin1("This is child item %1").arg(u + 2);
+
+ QStringList sl(col1);
+ sl.append(is[u]);
+ sl.append(is[rowCount - u - 1]);
+
+ if (u > 500)
+ new QTreeWidgetItem(rootitem, sl);
+ else
+ new QTreeWidgetItem(child1, sl);
+ }
+ treeWidget->header()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
+ treeWidget->header()->setSectionResizeMode(1, QHeaderView::ResizeToContents);
+ treeWidget->header()->setSectionResizeMode(2, QHeaderView::ResizeToContents);
+ spinPrecision->setValue(treeWidget->header()->resizeContentsPrecision());
+ connect(spinPrecision, SIGNAL(valueChanged(int)), this, SLOT(slotValueChanged(int)));
+ } // setupUi
+protected slots:
+ void slotValueChanged(int newval);
+protected:
+ QGridLayout *gridLayout;
+ QTreeWidget *treeWidget;
+ QSpinBox *spinPrecision;
+ QSpacerItem *verticalSpacer;
+};
+
+void TreeDialog::slotValueChanged(int newval)
+{
+ treeWidget->header()->setResizeContentsPrecision(newval, true);
+}
+
+int main(int argc, char *argv[])
+{
+ QApplication app(argc, argv);
+ TreeDialog d1;
+ d1.show();
+ app.exec();
+}
+
+#include "testtree.moc"
diff --git a/tests/manual/widgets/itemviews/autoResizePrecision/treeview/testtree.pro b/tests/manual/widgets/itemviews/autoResizePrecision/treeview/testtree.pro
new file mode 100644
index 0000000000..c062586eac
--- /dev/null
+++ b/tests/manual/widgets/itemviews/autoResizePrecision/treeview/testtree.pro
@@ -0,0 +1,2 @@
+SOURCES = testtree.cpp
+QT += widgets
diff --git a/tests/manual/widgets/itemviews/qtreeview/main.cpp b/tests/manual/widgets/itemviews/qtreeview/main.cpp
index 296ba6bcbf..22b4e07f75 100644
--- a/tests/manual/widgets/itemviews/qtreeview/main.cpp
+++ b/tests/manual/widgets/itemviews/qtreeview/main.cpp
@@ -39,17 +39,34 @@
**
****************************************************************************/
-
-#include <QtWidgets/QFileSystemModel>
-#include <QtWidgets/QtWidgets>
+#include <QtWidgets>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
- QFileSystemModel *model = new QFileSystemModel;
- model->setRootPath(QDir::currentPath());
- QTreeView *tree = new QTreeView();
- tree->setModel(model);
- tree->show();
- app.exec();
+ QFileSystemModel model;
+ QWidget window;
+ QTreeView *tree = new QTreeView(&window);
+ tree->setMaximumSize(1000, 600);
+
+ QHBoxLayout *layout = new QHBoxLayout;
+ layout->setSizeConstraint(QLayout::SetFixedSize);
+ layout->addWidget(tree);
+
+ window.setLayout(layout);
+ model.setRootPath("");
+ tree->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents);
+ tree->setModel(&model);
+
+ tree->setAnimated(false);
+ tree->setIndentation(20);
+ tree->setSortingEnabled(true);
+ tree->header()->setStretchLastSection(false);
+
+ window.setWindowTitle(QObject::tr("Dir View"));
+ tree->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
+
+ window.show();
+
+ return app.exec();
}
diff --git a/tests/manual/widgets/kernel/kernel.pro b/tests/manual/widgets/kernel/kernel.pro
new file mode 100644
index 0000000000..968d71724f
--- /dev/null
+++ b/tests/manual/widgets/kernel/kernel.pro
@@ -0,0 +1,2 @@
+TEMPLATE = subdirs
+SUBDIRS = qtooltip sizeonhide
diff --git a/tests/manual/widgets/kernel/qtooltip/main.cpp b/tests/manual/widgets/kernel/qtooltip/main.cpp
new file mode 100644
index 0000000000..a7a2b9915c
--- /dev/null
+++ b/tests/manual/widgets/kernel/qtooltip/main.cpp
@@ -0,0 +1,161 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Thorbjørn Lund Martsum - tmartsum[at]gmail.com
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite 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 <QTest>
+#include <QDialog>
+#include <QToolTip>
+#include <QLabel>
+#include <QPushButton>
+#include <QVBoxLayout>
+#include <QProxyStyle>
+#include <QSpinBox>
+
+class QToolTipTest : public QProxyStyle
+{
+ Q_OBJECT
+public:
+ QToolTipTest() : QProxyStyle()
+ {
+ wakeTime = QApplication::style()->styleHint(SH_ToolTip_WakeUpDelay);
+ sleepTime = QApplication::style()->styleHint(SH_ToolTip_FallAsleepDelay);
+ }
+
+ int styleHint(StyleHint hint, const QStyleOption *option = 0, const QWidget *widget = 0,
+ QStyleHintReturn *returnData = 0) const
+ {
+ switch (hint) {
+ case SH_ToolTip_WakeUpDelay:
+ return wakeTime;
+ case SH_ToolTip_FallAsleepDelay:
+ return sleepTime;
+ default:
+ return QProxyStyle::styleHint(hint, option, widget, returnData);
+ }
+ }
+
+public slots:
+ void setWakeTime(int wake) { wakeTime = wake; }
+ void setSleepTime(int sleep) { sleepTime = sleep; }
+protected:
+ int wakeTime;
+ int sleepTime;
+};
+
+class TestDialog : public QDialog
+{
+ Q_OBJECT
+public:
+ TestDialog(QToolTipTest *s);
+ QToolTipTest *style;
+protected slots:
+ void showSomeToolTips();
+};
+
+void TestDialog::showSomeToolTips()
+{
+ QPoint p(100 + 20, 100 + 20);
+
+ for (int u = 1; u < 20; u += 5) {
+ QString s = tr("Seconds: ") + QString::number(u);
+ QToolTip::showText(p, s, 0, QRect(), 1000 * u);
+ QTest::qWait((u + 1) * 1000);
+ }
+
+ QToolTip::showText(p, tr("Seconds: 2"), 0, QRect(), 2000);
+ QTest::qWait(3000);
+
+ QToolTip::showText(p, tr("Standard label"), 0, QRect());
+ QTest::qWait(12000);
+}
+
+TestDialog::TestDialog(QToolTipTest *s) : style(s)
+{
+ // Notice that these tool tips will disappear if another tool tip is shown.
+ QLabel *label1 = new QLabel(tr("Tooltip - Only two seconds display"));
+ label1->setToolTip(tr("2 seconds display"));
+ label1->setToolTipDuration(2000);
+ Q_ASSERT(label1->toolTipDuration() == 2000);
+
+ QLabel *label2 = new QLabel(tr("Tooltip - 30 seconds display time"));
+ label2->setToolTip(tr("30 seconds display"));
+ label2->setToolTipDuration(30000);
+
+ QPushButton *pb = new QPushButton(tr("&Test"));
+ pb->setToolTip(tr("Show some tool tips."));
+ Q_ASSERT(pb->toolTipDuration() == -1);
+ connect(pb, SIGNAL(clicked()), this, SLOT(showSomeToolTips()));
+
+ QLabel *wakeLabel = new QLabel(tr("Wake Delay:"));
+ QSpinBox *wakeSpinBox = new QSpinBox();
+ wakeSpinBox->setRange(0, 100000);
+ wakeSpinBox->setValue(style->styleHint(QStyle::SH_ToolTip_WakeUpDelay));
+ connect(wakeSpinBox, SIGNAL(valueChanged(int)), style, SLOT(setWakeTime(int)));
+
+ QLabel *sleepLabel = new QLabel(tr("Sleep Delay:"));
+ QSpinBox *sleepSpinBox = new QSpinBox();
+ sleepSpinBox->setRange(0, 100000);
+ sleepSpinBox->setValue(style->styleHint(QStyle::SH_ToolTip_FallAsleepDelay));
+ connect(sleepSpinBox, SIGNAL(valueChanged(int)), style, SLOT(setSleepTime(int)));
+
+ QVBoxLayout *layout = new QVBoxLayout;
+ layout->addWidget(label1);
+ layout->addWidget(label2);
+ layout->addWidget(pb);
+ layout->addWidget(wakeLabel);
+ layout->addWidget(wakeSpinBox);
+ layout->addWidget(wakeLabel);
+ layout->addWidget(sleepLabel);
+ layout->addWidget(sleepSpinBox);
+
+ setLayout(layout);
+}
+
+int main(int argc, char *argv[])
+{
+ QApplication app(argc, argv);
+ QToolTipTest *style = new QToolTipTest();
+ QApplication::setStyle(style);
+ TestDialog dlg(style);
+ dlg.show();
+ return app.exec();
+}
+
+#include "main.moc"
diff --git a/tests/manual/widgets/kernel/qtooltip/main.pro b/tests/manual/widgets/kernel/qtooltip/main.pro
new file mode 100644
index 0000000000..dac880a10e
--- /dev/null
+++ b/tests/manual/widgets/kernel/qtooltip/main.pro
@@ -0,0 +1,2 @@
+SOURCES = main.cpp
+QT += widgets testlib
diff --git a/tests/manual/widgets/kernel/sizeonhide/main.cpp b/tests/manual/widgets/kernel/sizeonhide/main.cpp
new file mode 100644
index 0000000000..e8b95dfe28
--- /dev/null
+++ b/tests/manual/widgets/kernel/sizeonhide/main.cpp
@@ -0,0 +1,134 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Thorbjørn Martsum - tmartsum[at]gmail.com
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtWidgets 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 <QtWidgets>
+
+class KeepSizeExampleDlg : public QDialog
+{
+ Q_OBJECT
+public:
+ QGridLayout *gridLayout;
+ QHBoxLayout *horizontalLayout;
+ QVBoxLayout *verticalLayout;
+ QCheckBox *checkBox;
+ QCheckBox *checkBox2;
+ QCheckBox *checkBox3;
+ QCheckBox *checkBox4;
+ QGroupBox *groupBox;
+ QVBoxLayout *verticalLayout2;
+ QRadioButton *radioButton;
+ QRadioButton *radioButton2;
+ QRadioButton *radioButton3;
+ QTableView *tableView;
+ QPushButton *pushButton;
+ QSpacerItem *horizontalSpacer;
+
+ KeepSizeExampleDlg()
+ {
+ QWidget *form = this;
+ form->resize(408, 295);
+ gridLayout = new QGridLayout(form);
+ horizontalLayout = new QHBoxLayout();
+ verticalLayout = new QVBoxLayout();
+ checkBox = new QCheckBox(form);
+ verticalLayout->addWidget(checkBox);
+ checkBox2 = new QCheckBox(form);
+ verticalLayout->addWidget(checkBox2);
+ checkBox3 = new QCheckBox(form);
+ verticalLayout->addWidget(checkBox3);
+ checkBox4 = new QCheckBox(form);
+ verticalLayout->addWidget(checkBox4);
+ horizontalLayout->addLayout(verticalLayout);
+ groupBox = new QGroupBox(form);
+ verticalLayout2 = new QVBoxLayout(groupBox);
+ radioButton = new QRadioButton(groupBox);
+ verticalLayout2->addWidget(radioButton);
+ radioButton2 = new QRadioButton(groupBox);
+ verticalLayout2->addWidget(radioButton2);
+ radioButton3 = new QRadioButton(groupBox);
+ verticalLayout2->addWidget(radioButton3);
+ horizontalLayout->addWidget(groupBox);
+ gridLayout->addLayout(horizontalLayout, 0, 0, 1, 2);
+ tableView = new QTableView(form);
+ gridLayout->addWidget(tableView, 1, 0, 1, 2);
+ pushButton = new QPushButton(form);
+ gridLayout->addWidget(pushButton, 2, 0, 1, 1);
+ horizontalSpacer = new QSpacerItem(340, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
+ gridLayout->addItem(horizontalSpacer, 2, 1, 1, 1);
+ checkBox->setText(QString::fromUtf8("CheckBox1"));
+ checkBox2->setText(QString::fromUtf8("CheckBox2"));
+ checkBox3->setText(QString::fromUtf8("CheckBox - for client A only"));
+ checkBox4->setText(QString::fromUtf8("CheckBox - also for client A"));
+ groupBox->setTitle(QString::fromUtf8("Mode"));
+ radioButton->setText(QString::fromUtf8("Mode 1"));
+ radioButton2->setText(QString::fromUtf8("Mode 2"));
+ radioButton3->setText(QString::fromUtf8("Mode 3"));
+ pushButton->setText(QString::fromUtf8("&Hide/Show"));
+
+ QObject::connect(pushButton, SIGNAL(clicked()), this, SLOT(showOrHide()));
+ }
+
+ protected slots:
+ void showOrHide()
+ {
+ if (checkBox3->isVisible()) {
+ checkBox3->hide();
+ checkBox4->hide();
+ } else {
+ checkBox3->show();
+ checkBox4->show();
+ }
+ }
+};
+
+int main(int argc, char *argv[])
+{
+ QApplication app(argc, argv);
+ KeepSizeExampleDlg d;
+ QSizePolicy policyKeepSpace = d.checkBox3->sizePolicy();
+ policyKeepSpace.setRetainSizeWhenHidden(true);
+ d.checkBox3->setSizePolicy(policyKeepSpace);
+ d.checkBox4->setSizePolicy(policyKeepSpace);
+ d.show();
+ app.exec();
+}
+
+#include "main.moc"
diff --git a/tests/manual/widgets/kernel/sizeonhide/sizeonhide.pro b/tests/manual/widgets/kernel/sizeonhide/sizeonhide.pro
new file mode 100644
index 0000000000..1969392ab3
--- /dev/null
+++ b/tests/manual/widgets/kernel/sizeonhide/sizeonhide.pro
@@ -0,0 +1,3 @@
+TEMPLATE = app
+SOURCES = main.cpp
+QT += widgets core-private
diff --git a/tests/manual/widgets/qgraphicsview/rubberband/rubberbandtest.cpp b/tests/manual/widgets/qgraphicsview/rubberband/rubberbandtest.cpp
index aec2479239..bb05570f18 100644
--- a/tests/manual/widgets/qgraphicsview/rubberband/rubberbandtest.cpp
+++ b/tests/manual/widgets/qgraphicsview/rubberband/rubberbandtest.cpp
@@ -49,7 +49,7 @@ public:
setFlags(QGraphicsItem::ItemIsSelectable);
}
- void paint(QPainter *painter, const QStyleOptionGraphicsItem * /* option*/, QWidget * /*widget*/)
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem * /* option*/, QWidget * /*widget*/) Q_DECL_OVERRIDE
{
if (isSelected())
painter->fillRect(rect(), QColor(255, 0, 0));
@@ -68,7 +68,7 @@ public:
connect(this, SIGNAL(rubberBandChanged(QRect, QPointF, QPointF)), this, SLOT(updateRubberbandInfo(QRect, QPointF, QPointF)));
}
protected:
- void mouseMoveEvent(QMouseEvent *event)
+ void mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE
{
QGraphicsView::mouseMoveEvent(event);
diff --git a/tests/manual/widgets/widgets.pro b/tests/manual/widgets/widgets.pro
index 4e2e4c7cee..e9dcdf39e7 100644
--- a/tests/manual/widgets/widgets.pro
+++ b/tests/manual/widgets/widgets.pro
@@ -1,2 +1,3 @@
TEMPLATE = subdirs
-SUBDIRS = itemviews qgraphicsview
+SUBDIRS = itemviews qgraphicsview kernel
+
diff --git a/tools/configure/configureapp.cpp b/tools/configure/configureapp.cpp
index a6376bbb7d..4443122595 100644
--- a/tools/configure/configureapp.cpp
+++ b/tools/configure/configureapp.cpp
@@ -135,23 +135,9 @@ Configure::Configure(int& argc, char** argv)
const QString installPath = buildPath;
#endif
if (sourceDir != buildDir) { //shadow builds!
- cout << "Preparing build tree..." << endl;
QDir(buildPath).mkpath("bin");
- //copy the mkspecs
buildDir.mkpath("mkspecs");
- if (!Environment::cpdir(sourcePath + "/mkspecs", buildPath + "/mkspecs")){
- cout << "Couldn't copy mkspecs!" << sourcePath << " " << buildPath << endl;
- dictionary["DONE"] = "error";
- return;
- }
-
- buildDir.mkpath("doc");
- if (!Environment::cpdir(sourcePath + "/doc/global", buildPath + "/doc/global")) {
- cout << "Couldn't copy global documentation!" << sourcePath << " " << buildPath << endl;
- dictionary["DONE"] = "error";
- return;
- }
}
defaultBuildParts << QStringLiteral("libs") << QStringLiteral("tools") << QStringLiteral("examples");
@@ -2818,6 +2804,14 @@ void Configure::generateCachefile()
moduleStream << "QT_SKIP_MODULES += " << skipModules.join(' ') << endl;
moduleStream << endl;
+ moduleStream << "host_build {" << endl;
+ moduleStream << " QT_CPU_FEATURES." << dictionary["QT_HOST_ARCH"] <<
+ " = " << dictionary["QT_HOST_CPU_FEATURES"] << endl;
+ moduleStream << "} else {" << endl;
+ moduleStream << " QT_CPU_FEATURES." << dictionary["QT_ARCH"] <<
+ " = " << dictionary["QT_CPU_FEATURES"] << endl;
+ moduleStream << "}" << endl;
+
if (dictionary["QT_EDITION"] != "QT_EDITION_OPENSOURCE")
moduleStream << "DEFINES *= QT_EDITION=QT_EDITION_DESKTOP" << endl;
@@ -3098,15 +3092,16 @@ void Configure::generateQConfigPri()
configStream << " qpa";
configStream << endl;
- configStream << "QT_ARCH = " << dictionary["QT_ARCH"] << endl;
- configStream << "QT_HOST_ARCH = " << dictionary["QT_HOST_ARCH"] << endl;
- configStream << "QT_CPU_FEATURES = " << dictionary["QT_CPU_FEATURES"] << endl;
- configStream << "QT_HOST_CPU_FEATURES = " << dictionary["QT_HOST_CPU_FEATURES"] << endl;
+ configStream << "host_build {" << endl;
+ configStream << " QT_ARCH = " << dictionary["QT_HOST_ARCH"] << endl;
+ configStream << "} else {" << endl;
+ configStream << " QT_ARCH = " << dictionary["QT_ARCH"] << endl;
if (dictionary.contains("XQMAKESPEC") && !dictionary["XQMAKESPEC"].startsWith("wince")) {
// FIXME: add detection
- configStream << "QMAKE_DEFAULT_LIBDIRS = /lib /usr/lib" << endl;
- configStream << "QMAKE_DEFAULT_INCDIRS = /usr/include /usr/local/include" << endl;
+ configStream << " QMAKE_DEFAULT_LIBDIRS = /lib /usr/lib" << endl;
+ configStream << " QMAKE_DEFAULT_INCDIRS = /usr/include /usr/local/include" << endl;
}
+ configStream << "}" << endl;
if (dictionary["QT_EDITION"].contains("OPENSOURCE"))
configStream << "QT_EDITION = " << QLatin1String("OpenSource") << endl;
else
@@ -3866,6 +3861,9 @@ void Configure::buildQmake()
QTextStream confStream(&confFile);
confStream << "[EffectivePaths]" << endl
<< "Prefix=.." << endl;
+ if (sourcePath != buildPath)
+ confStream << "[EffectiveSourcePaths]" << endl
+ << "Prefix=" << sourcePath << endl;
confStream.flush();
confFile.close();