diff options
83 files changed, 1349 insertions, 786 deletions
@@ -698,6 +698,7 @@ CFG_INOTIFY=auto CFG_EVENTFD=auto CFG_RPATH=yes CFG_FRAMEWORK=auto +CFG_USE_GOLD_LINKER=auto DEFINES= INCLUDES= D_FLAGS= @@ -1592,6 +1593,13 @@ while [ "$#" -gt 0 ]; do UNKNOWN_OPT=yes fi ;; + use-gold-linker) + if [ "$VAL" = "yes" ] || [ "$VAL" = "no" ]; then + CFG_USE_GOLD_LINKER="$VAL" + else + UNKNOWN_OPT=yes + fi + ;; zlib) [ "$VAL" = "qt" ] && VAL=yes if [ "$VAL" = "yes" ] || [ "$VAL" = "no" ] || [ "$VAL" = "system" ]; then @@ -2465,6 +2473,9 @@ Additional options: linker optimizations (Qt/X11 and Qt for Embedded Linux only; experimental; needs GNU ld >= 2.18). + -no-use-gold-linker ..... Do not link using the GNU gold linker. + + -use-gold-linker ........ Link using the GNU gold linker if available. + -force-asserts ........ Force Q_ASSERT to be enabled even in release builds. -device <name> ............... Cross-compile for device <name> (experimental) @@ -3230,6 +3241,19 @@ if [ "$CFG_REDUCE_EXPORTS" != "no" ]; then fi fi +# auto-detect -fuse-ld=gold support +if [ "$CFG_USE_GOLD_LINKER" != "no" ]; then + if linkerSupportsFlag $TEST_COMPILER -fuse-ld=gold; then + CFG_USE_GOLD_LINKER=yes + else + if [ "$CFG_USE_GOLD_LINKER" = "yes" ]; then + echo "-use-gold-linker was requested but this compiler does not support it" + exit 1 + fi + CFG_USE_GOLD_LINKER=no + fi +fi + # auto-detect -fstack-protector-strong support (for QNX only currently) if [ "$XPLATFORM_QNX" = "yes" ]; then if compilerSupportsFlag $TEST_COMPILER -fstack-protector-strong; then @@ -5598,6 +5622,7 @@ fi [ "$CFG_REDUCE_RELOCATIONS" = "yes" ] && QT_CONFIG="$QT_CONFIG reduce_relocations" [ "$CFG_STRIP" = "no" ] && QMAKE_CONFIG="$QMAKE_CONFIG nostrip" [ "$CFG_PRECOMPILE" = "yes" ] && QMAKE_CONFIG="$QMAKE_CONFIG precompile_header" +[ "$CFG_USE_GOLD_LINKER" = "yes" ] && QMAKE_CONFIG="$QMAKE_CONFIG use_gold_linker" if [ "$CFG_SEPARATE_DEBUG_INFO" = "yes" ]; then QT_CONFIG="$QT_CONFIG separate_debug_info" fi @@ -6472,6 +6497,7 @@ else fi unset build_mode release echo " Using C++11 ............ $CFG_CXX11" +echo " Using gold linker....... $CFG_USE_GOLD_LINKER" echo " Using PCH .............. $CFG_PRECOMPILE" echo " Target compiler supports:" if [ "$CFG_ARCH" = "i386" -o "$CFG_ARCH" = "x86_64" ]; then diff --git a/mkspecs/common/clang.conf b/mkspecs/common/clang.conf index d58b44b295..6235296ef3 100644 --- a/mkspecs/common/clang.conf +++ b/mkspecs/common/clang.conf @@ -16,8 +16,12 @@ QMAKE_PCH_OUTPUT_EXT = .pch QMAKE_CFLAGS_ISYSTEM = -isystem QMAKE_CFLAGS_PRECOMPILE = -x c-header -c ${QMAKE_PCH_INPUT} -o ${QMAKE_PCH_OUTPUT} QMAKE_CFLAGS_USE_PRECOMPILE = -Xclang -include-pch -Xclang ${QMAKE_PCH_OUTPUT} +QMAKE_CFLAGS_LTCG = -flto + QMAKE_CXXFLAGS_PRECOMPILE = -x c++-header -c ${QMAKE_PCH_INPUT} -o ${QMAKE_PCH_OUTPUT} QMAKE_CXXFLAGS_USE_PRECOMPILE = $$QMAKE_CFLAGS_USE_PRECOMPILE +QMAKE_CXXFLAGS_LTCG = $$QMAKE_CFLAGS_LTCG +QMAKE_CXXFLAGS_CXX11 = -std=c++11 -QMAKE_CXXFLAGS_CXX11 = -std=c++11 QMAKE_LFLAGS_CXX11 = +QMAKE_LFLAGS_LTCG = $$QMAKE_CFLAGS_LTCG diff --git a/mkspecs/common/gcc-base-unix.conf b/mkspecs/common/gcc-base-unix.conf index 84ef88aa4f..29e0521927 100644 --- a/mkspecs/common/gcc-base-unix.conf +++ b/mkspecs/common/gcc-base-unix.conf @@ -16,6 +16,7 @@ QMAKE_LFLAGS_SONAME += -Wl,-soname, QMAKE_LFLAGS_THREAD += QMAKE_LFLAGS_RPATH = -Wl,-rpath, QMAKE_LFLAGS_RPATHLINK = -Wl,-rpath-link, +QMAKE_LFLAGS_USE_GOLD = -fuse-ld=gold # -Bsymbolic-functions (ld) support QMAKE_LFLAGS_BSYMBOLIC_FUNC = -Wl,-Bsymbolic-functions diff --git a/mkspecs/common/gcc-base.conf b/mkspecs/common/gcc-base.conf index fcff502af6..06d87d7b36 100644 --- a/mkspecs/common/gcc-base.conf +++ b/mkspecs/common/gcc-base.conf @@ -48,6 +48,7 @@ QMAKE_CFLAGS_YACC += -Wno-unused -Wno-parentheses QMAKE_CFLAGS_HIDESYMS += -fvisibility=hidden QMAKE_CFLAGS_EXCEPTIONS_OFF += -fno-exceptions QMAKE_CFLAGS_SPLIT_SECTIONS += -ffunction-sections +QMAKE_CFLAGS_LTCG = -flto QMAKE_CXXFLAGS += $$QMAKE_CFLAGS QMAKE_CXXFLAGS_DEPS += $$QMAKE_CFLAGS_DEPS @@ -62,12 +63,14 @@ QMAKE_CXXFLAGS_YACC += $$QMAKE_CFLAGS_YACC QMAKE_CXXFLAGS_HIDESYMS += $$QMAKE_CFLAGS_HIDESYMS -fvisibility-inlines-hidden QMAKE_CXXFLAGS_EXCEPTIONS_OFF += $$QMAKE_CFLAGS_EXCEPTIONS_OFF QMAKE_CXXFLAGS_SPLIT_SECTIONS += $$QMAKE_CFLAGS_SPLIT_SECTIONS +QMAKE_CXXFLAGS_LTCG = $$QMAKE_CFLAGS_LTCG QMAKE_LFLAGS += QMAKE_LFLAGS_DEBUG += QMAKE_LFLAGS_APP += QMAKE_LFLAGS_RELEASE += QMAKE_LFLAGS_EXCEPTIONS_OFF += +QMAKE_LFLAGS_LTCG = $$QMAKE_CFLAGS_LTCG -fuse-linker-plugin QMAKE_CFLAGS_SSE2 += -msse2 QMAKE_CFLAGS_SSE3 += -msse3 diff --git a/mkspecs/features/default_post.prf b/mkspecs/features/default_post.prf index 6fb140b252..085527f28d 100644 --- a/mkspecs/features/default_post.prf +++ b/mkspecs/features/default_post.prf @@ -61,6 +61,8 @@ debug { QMAKE_LIBFLAGS += $$QMAKE_LIBFLAGS_RELEASE } +use_gold_linker: QMAKE_LFLAGS += $$QMAKE_LFLAGS_USE_GOLD + dll:win32: QMAKE_LFLAGS += $$QMAKE_LFLAGS_DLL static:mac: QMAKE_LFLAGS += $$QMAKE_LFLAGS_STATIC_LIB staticlib:unix { diff --git a/mkspecs/features/ltcg.prf b/mkspecs/features/ltcg.prf new file mode 100644 index 0000000000..b418135014 --- /dev/null +++ b/mkspecs/features/ltcg.prf @@ -0,0 +1,54 @@ +CONFIG(release, debug|release) { + # We need fat object files when creating static libraries on some platforms + # so the linker will know to load a particular object from the library + # in the first place. With GCC, we have -ffat-lto-objects. MSVC + # seems to work just fine. For other compilers, we disable LTCG + # for static libraries. + msvc { + # Nothing to do + } else: gcc { + !clang:!intel_icc { + static|fat-lto { + QMAKE_CFLAGS_LTCG += -ffat-lto-objects + QMAKE_CXXFLAGS_LTCG += -ffat-lto-objects + } else { + QMAKE_CFLAGS_LTCG += -fno-fat-lto-objects + QMAKE_CXXFLAGS_LTCG += -fno-fat-lto-objects + } + linux { + # Get the number of online processors, like _SC_NPROCESSORS_ONLN + isEmpty(QMAKE_NPROCESSORS_ONLN) { + QMAKE_NPROCESSORS_ONLN = $$system("grep -c '^processor' /proc/cpuinfo 2>/dev/null || echo 1") + cache(QMAKE_NPROCESSORS_ONLN, set stash) + } + + # Override LTO number of jobs + QMAKE_LFLAGS_LTCG -= -flto + QMAKE_LFLAGS_LTCG += -flto=$$QMAKE_NPROCESSORS_ONLN + } + } else: static { + QMAKE_CFLAGS_LTCG = + QMAKE_CXXFLAGS_LTCG = + QMAKE_LFLAGS_LTCG = + } + + # When doing link-time code generation, we need to pass the compiler + # flags during linking stage too. This file is processed after + # default_post.prf, so the QMAKE_CXXFLAGS already contains + # QMAKE_CXXFLAGS_DEBUG or _RELEASE. + use_c_linker { + # use_c_linker.prf is in effect, use the C flags + QMAKE_LFLAGS_LTCG += $$QMAKE_CFLAGS $$QMAKE_CFLAGS_LTCG + QMAKE_LFLAGS_APP += $$QMAKE_CFLAGS_APP + QMAKE_LFLAGS_SHLIB += $$QMAKE_CFLAGS_SHLIB + } else { + QMAKE_LFLAGS_LTCG = $$QMAKE_CXXFLAGS $$QMAKE_LFLAGS_LTCG + QMAKE_LFLAGS_APP += $$QMAKE_CXXFLAGS_APP + QMAKE_LFLAGS_SHLIB += $$QMAKE_CXXFLAGS_SHLIB + } + } + + QMAKE_CFLAGS *= $$QMAKE_CFLAGS_LTCG + QMAKE_CXXFLAGS *= $$QMAKE_CXXFLAGS_LTCG + QMAKE_LFLAGS *= $$QMAKE_LFLAGS_LTCG +} diff --git a/mkspecs/features/win32/ltcg.prf b/mkspecs/features/win32/ltcg.prf deleted file mode 100644 index f6f1299f47..0000000000 --- a/mkspecs/features/win32/ltcg.prf +++ /dev/null @@ -1,5 +0,0 @@ -CONFIG(release, debug|release) { - QMAKE_CFLAGS *= $$QMAKE_CFLAGS_LTCG - QMAKE_CXXFLAGS *= $$QMAKE_CXXFLAGS_LTCG - QMAKE_LFLAGS *= $$QMAKE_LFLAGS_LTCG -} diff --git a/mkspecs/linux-icc/qmake.conf b/mkspecs/linux-icc/qmake.conf index c0caca09fa..8119c8aa09 100644 --- a/mkspecs/linux-icc/qmake.conf +++ b/mkspecs/linux-icc/qmake.conf @@ -24,6 +24,7 @@ QMAKE_CFLAGS_YACC = QMAKE_CFLAGS_ISYSTEM = -isystem QMAKE_CFLAGS_THREAD = -D_REENTRANT QMAKE_CFLAGS_SPLIT_SECTIONS = -ffunction-sections +QMAKE_CFLAGS_LTCG = -ipo QMAKE_CFLAGS_SSE2 += -xSSE2 QMAKE_CFLAGS_SSE3 += -xSSE3 @@ -49,6 +50,7 @@ QMAKE_CXXFLAGS_SPLIT_SECTIONS = $$QMAKE_CFLAGS_SPLIT_SECTIONS # Disabling exceptions disabled - workaround for QTBUG-36577 #QMAKE_CXXFLAGS_EXCEPTIONS_OFF = -fno-exceptions QMAKE_CXXFLAGS_CXX11 = -std=c++0x +QMAKE_CXXFLAGS_LTCG = $$QMAKE_CFLAGS_LTCG QMAKE_INCDIR = QMAKE_LIBDIR = @@ -70,6 +72,7 @@ QMAKE_LFLAGS_NOUNDEF = -Wl,-z,defs QMAKE_LFLAGS_RPATH = -Wl,-rpath, QMAKE_LFLAGS_RPATHLINK = -Wl,-rpath-link, QMAKE_LFLAGS_CXX11 = +QMAKE_LFLAGS_LTCG = $$QMAKE_CFLAGS_LTCG QMAKE_LIBS = QMAKE_LIBS_DYNLOAD = -ldl diff --git a/mkspecs/macx-icc/qmake.conf b/mkspecs/macx-icc/qmake.conf index 370a738c6a..88b04976f2 100644 --- a/mkspecs/macx-icc/qmake.conf +++ b/mkspecs/macx-icc/qmake.conf @@ -23,6 +23,7 @@ QMAKE_CFLAGS_STATIC_LIB = $$QMAKE_CFLAGS_SHLIB QMAKE_CFLAGS_YACC = -Wno-unused -Wno-parentheses QMAKE_CFLAGS_THREAD = QMAKE_CFLAGS_SPLIT_SECTIONS = -ffunction-sections +QMAKE_CFLAGS_LTCG = -ipo QMAKE_CFLAGS_SSE2 += -msse2 QMAKE_CFLAGS_SSE3 += -msse3 @@ -54,6 +55,7 @@ QMAKE_CXXFLAGS_THREAD = $$QMAKE_CFLAGS_THREAD # Disabled, due to invalid C++11 code on Apple headers #QMAKE_CXXFLAGS_CXX11 = -std=c++11 QMAKE_CXXFLAGS_SPLIT_SECTIONS = $$QMAKE_CFLAGS_SPLIT_SECTIONS +QMAKE_CXXFLAGS_LTCG = $$QMAKE_CFLAGS_LTCG QMAKE_LINK = icpc QMAKE_LINK_SHLIB = icpc @@ -66,6 +68,7 @@ QMAKE_LFLAGS_PLUGIN = $$QMAKE_LFLAGS_SHLIB QMAKE_LFLAGS_SONAME = -install_name$${LITERAL_WHITESPACE} QMAKE_LFLAGS_THREAD = QMAKE_LFLAGS_RPATH = +QMAKE_LFLAGS_LTCG = $$QMAKE_CFLAGS_LTCG QMAKE_LFLAGS_VERSION = -current_version$${LITERAL_WHITESPACE} QMAKE_LFLAGS_COMPAT_VERSION = -compatibility_version$${LITERAL_WHITESPACE} diff --git a/mkspecs/macx-ios-clang/rename_main.sh b/mkspecs/macx-ios-clang/rename_main.sh index b30eb160d0..b1321e855e 100755 --- a/mkspecs/macx-ios-clang/rename_main.sh +++ b/mkspecs/macx-ios-clang/rename_main.sh @@ -46,9 +46,26 @@ if [ $# -eq 0 ]; then else for f in $(find $1 -name '*.o'); do # Skip object files without the _main symbol - nm $f | grep -q 'T _main$' || continue + nm $f 2>/dev/null | grep -q 'T _main$' || continue - echo "Found main() in ${f#$1/}" + fname=${f#$1/} + + file -b $f | grep -qi 'llvm bit-code' && \ + (cat \ +<<EOF >&2 +$f:: error: The file '$fname' contains LLVM bitcode, not object code. Automatic main() redirection could not be applied. +note: This is most likely due to the use of link-time optimization (-flto). Please disable LTO, or work around the \ +issue by manually renaming your main() function to qtmn(): + +#ifdef Q_OS_IOS +extern "C" int qtmn(int argc, char *argv[]) +#else +int main(int argc, char *argv[]) +#endif +EOF + ) && exit 1 + + echo "Found main() in $fname" strings -t d - $f | grep '_main\(\.eh\)\?$' | while read match; do offset=$(echo $match | cut -d ' ' -f 1) diff --git a/mkspecs/win32-g++/qmake.conf b/mkspecs/win32-g++/qmake.conf index d26ffb4e21..01c8ab9bc3 100644 --- a/mkspecs/win32-g++/qmake.conf +++ b/mkspecs/win32-g++/qmake.conf @@ -78,6 +78,7 @@ QMAKE_LFLAGS_WINDOWS = -Wl,-subsystem,windows QMAKE_LFLAGS_DLL = -shared QMAKE_LFLAGS_CXX11 = QMAKE_LFLAGS_GCSECTIONS = -Wl,--gc-sections +QMAKE_LFLAGS_USE_GOLD = -fuse-ld=gold QMAKE_LINK_OBJECT_MAX = 10 QMAKE_LINK_OBJECT_SCRIPT = object_script QMAKE_PREFIX_STATICLIB = lib diff --git a/mkspecs/win32-icc/qmake.conf b/mkspecs/win32-icc/qmake.conf index a60d846e2f..d326cdeee3 100644 --- a/mkspecs/win32-icc/qmake.conf +++ b/mkspecs/win32-icc/qmake.conf @@ -23,6 +23,7 @@ QMAKE_CFLAGS_WARN_OFF = -W0 /Qwd673 QMAKE_CFLAGS_RELEASE = -O2 -MD QMAKE_CFLAGS_DEBUG = -Zi -MDd -Od QMAKE_CFLAGS_YACC = +QMAKE_CFLAGS_LTCG = -Qipo QMAKE_CFLAGS_SSE2 = -QxSSE2 QMAKE_CFLAGS_SSE3 = -QxSSE3 QMAKE_CFLAGS_SSSE3 = -QxSSSE3 @@ -45,6 +46,7 @@ QMAKE_CXXFLAGS_RTTI_OFF = QMAKE_CXXFLAGS_EXCEPTIONS_ON = -EHsc QMAKE_CXXFLAGS_EXCEPTIONS_OFF = QMAKE_CXXFLAGS_CXX11 = -Qstd=c++11 +QMAKE_CXXFLAGS_LTCG = $$QMAKE_CFLAGS_LTCG QMAKE_INCDIR = @@ -62,6 +64,7 @@ QMAKE_LFLAGS_DEBUG = /DEBUG QMAKE_LFLAGS_CONSOLE = /SUBSYSTEM:console QMAKE_LFLAGS_WINDOWS = /SUBSYSTEM:windows QMAKE_LFLAGS_DLL = /DLL +QMAKE_LFLAGS_LTCG = $$QMAKE_CFLAGS_LTCG QMAKE_EXTENSION_STATICLIB = lib QMAKE_LIBS = diff --git a/qmake/Makefile.unix b/qmake/Makefile.unix index 52873203a0..10c72bf28f 100644 --- a/qmake/Makefile.unix +++ b/qmake/Makefile.unix @@ -103,7 +103,7 @@ CPPFLAGS = -g $(EXTRA_CPPFLAGS) \ -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 \ - -DQT_CRYPTOGRAPHICHASH_ONLY_SHA1 -DQT_JSON_READONLY + -DQT_CRYPTOGRAPHICHASH_ONLY_SHA1 -DQT_JSON_READONLY -DQT_NO_STANDARDPATHS CXXFLAGS = $(EXTRA_CXXFLAGS) $(CPPFLAGS) diff --git a/qmake/Makefile.win32 b/qmake/Makefile.win32 index 62dc7bcdf8..44102474b8 100644 --- a/qmake/Makefile.win32 +++ b/qmake/Makefile.win32 @@ -27,7 +27,7 @@ LINKER = link !if "$(QMAKESPEC)" == "win32-msvc2005" CFLAGS_EXTRA = /Zc:wchar_t- !elseif "$(QMAKESPEC)" == "win32-msvc2008" || "$(QMAKESPEC)" == "win32-msvc2010" || "$(QMAKESPEC)" == "win32-msvc2012" || "$(QMAKESPEC)" == "win32-msvc2013" -CFLAGS_EXTRA = /MP +CFLAGS_EXTRA = /MP /D_CRT_SECURE_NO_WARNINGS !endif CFLAGS_BARE = -c -Fo./ -Fdqmake.pdb \ @@ -41,7 +41,7 @@ CFLAGS_BARE = -c -Fo./ -Fdqmake.pdb \ -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 -DQT_CRYPTOGRAPHICHASH_ONLY_SHA1 -DQT_JSON_READONLY + -DUNICODE -DQT_CRYPTOGRAPHICHASH_ONLY_SHA1 -DQT_JSON_READONLY -DQT_NO_STANDARDPATHS CFLAGS = -Yuqmake_pch.h -FIqmake_pch.h -Fpqmake_pch.pch $(CFLAGS_BARE) $(CFLAGS) $(EXTRA_CPPFLAGS) CXXFLAGS_BARE = $(CFLAGS_BARE) @@ -141,7 +141,6 @@ clean:: -del $(OBJS) -del qmake_pch.obj -del qmake_pch.pch - -del qsystemlibrary.obj -del qmake.pdb -del qmake.ilk -del qmake.tds diff --git a/qmake/generators/mac/pbuilder_pbx.cpp b/qmake/generators/mac/pbuilder_pbx.cpp index 042e21ab5a..835676d9fe 100644 --- a/qmake/generators/mac/pbuilder_pbx.cpp +++ b/qmake/generators/mac/pbuilder_pbx.cpp @@ -1029,9 +1029,9 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t) << "\t\t\t" << writeSettings("files", ProStringList(), SettingsAsList, 4) << ";\n" // The build phases are not executed in the order they are defined, but by their // resolved dependenices, so we have to ensure that this phase is run after the - // compilation phase, and before the link phase. Making the phase depend on all the - // object files, and "write" to the list of files to link achieves that. - << "\t\t\t" << writeSettings("inputPaths", ProStringList("$(OBJECT_FILE_DIR_$(CURRENT_VARIANT))/$(CURRENT_ARCH)/*" + Option::obj_ext), SettingsAsList, 4) << ";\n" + // compilation phase, and before the link phase. Making the phase depend on the + // object file directory, and "write" to the list of files to link achieves that. + << "\t\t\t" << writeSettings("inputPaths", ProStringList("$(OBJECT_FILE_DIR_$(CURRENT_VARIANT))/$(CURRENT_ARCH)/"), SettingsAsList, 4) << ";\n" << "\t\t\t" << writeSettings("outputPaths", ProStringList("$(LINK_FILE_LIST_$(CURRENT_VARIANT)_$(CURRENT_ARCH))"), SettingsAsList, 4) << ";\n" << "\t\t\t" << writeSettings("isa", "PBXShellScriptBuildPhase", SettingsNoQuote) << ";\n" << "\t\t\t" << writeSettings("runOnlyForDeploymentPostprocessing", "0", SettingsNoQuote) << ";\n" diff --git a/qmake/generators/win32/msvc_objectmodel.cpp b/qmake/generators/win32/msvc_objectmodel.cpp index b2663e51c9..3d203c2ad0 100644 --- a/qmake/generators/win32/msvc_objectmodel.cpp +++ b/qmake/generators/win32/msvc_objectmodel.cpp @@ -916,6 +916,8 @@ bool VCCLCompilerTool::parseOption(const char* option) ForceConformanceInForLoopScope = ((*c) == '-' ? _False : _True); else if(fourth == 'w') TreatWChar_tAsBuiltInType = ((*c) == '-' ? _False : _True); + else if (config->CompilerVersion >= NET2013 && strncmp(option + 4, "strictStrings", 13) == 0) + AdditionalOptions += option; else found = false; } else { diff --git a/qmake/qmake.pri b/qmake/qmake.pri index 4457b2643b..4de41d63e6 100644 --- a/qmake/qmake.pri +++ b/qmake/qmake.pri @@ -159,7 +159,7 @@ bootstrap { #Qt code QT_BOOTSTRAPPED \ QT_NO_TEXTCODEC QT_NO_UNICODETABLES QT_NO_COMPONENT QT_NO_COMPRESS \ QT_NO_THREAD QT_NO_QOBJECT QT_NO_GEOM_VARIANT QT_NO_DATASTREAM \ - QT_CRYPTOGRAPHICHASH_ONLY_SHA1 QT_JSON_READONLY + QT_CRYPTOGRAPHICHASH_ONLY_SHA1 QT_JSON_READONLY QT_NO_STANDARDPATHS INCLUDEPATH += \ $$QT.core.includes $$QT.core_private.includes \ diff --git a/src/android/jar/src/org/qtproject/qt5/android/ExtractStyle.java b/src/android/jar/src/org/qtproject/qt5/android/ExtractStyle.java index 2f79f44d80..ef6d20fc9a 100644 --- a/src/android/jar/src/org/qtproject/qt5/android/ExtractStyle.java +++ b/src/android/jar/src/org/qtproject/qt5/android/ExtractStyle.java @@ -1027,12 +1027,43 @@ public class ExtractStyle { } } - public JSONObject extractTextAppearanceInformations(String styleName, String qtClass, AttributeSet attribSet, int textAppearance ) + public JSONObject extractTextAppearance(int styleId) { - return extractTextAppearanceInformations(styleName, qtClass, attribSet, textAppearance, -1); + JSONObject json = new JSONObject(); + try + { + TypedArray a = m_theme.obtainStyledAttributes(styleId, (int[]) styleableClass.getDeclaredField("TextAppearance").get(null)); + int n = a.getIndexCount(); + for (int i = 0; i < n; i++) + { + int attr = a.getIndex(i); + if (attr == TextAppearance_textColorHighlight) + json.put("TextAppearance_textColorHighlight", a.getColor(attr, 0)); + else if (attr == TextAppearance_textColor) + json.put("TextAppearance_textColor", getColorStateList(a.getColorStateList(attr))); + else if (attr == TextAppearance_textColorHint) + json.put("TextAppearance_textColorHint", getColorStateList(a.getColorStateList(attr))); + else if (attr == TextAppearance_textColorLink) + json.put("TextAppearance_textColorLink", getColorStateList(a.getColorStateList(attr))); + else if (attr == TextAppearance_textSize) + json.put("TextAppearance_textSize", a.getDimensionPixelSize(attr, 15)); + else if (attr == TextAppearance_typeface) + json.put("TextAppearance_typeface", a.getInt(attr, -1)); + else if (attr == TextAppearance_textStyle) + json.put("TextAppearance_textStyle", a.getInt(attr, -1)); + else if (attr == TextAppearance_textAllCaps) + json.put("TextAppearance_textAllCaps", a.getBoolean(attr, false)); + } + a.recycle(); + } + catch (Exception e) + { + e.printStackTrace(); + } + return json; } - public JSONObject extractTextAppearanceInformations(String styleName, String qtClass, AttributeSet attribSet, int textAppearance, int styleId) + public JSONObject extractTextAppearanceInformations(String styleName, String qtClass, AttributeSet attribSet, int textAppearance) { JSONObject json = new JSONObject(); try @@ -1046,10 +1077,8 @@ public class ExtractStyle { int styleIndex = -1; boolean allCaps = false; - if (-1==styleId) { - Class<?> attrClass= Class.forName("android.R$attr"); - styleId = attrClass.getDeclaredField(styleName).getInt(null); - } + Class<?> attrClass= Class.forName("android.R$attr"); + int styleId = attrClass.getDeclaredField(styleName).getInt(null); extractViewInformations(styleName, styleId, json, qtClass, attribSet); @@ -1425,7 +1454,7 @@ public class ExtractStyle { json.put("Switch_track", getDrawable(track, styleName + "_Switch_track")); int textAppearance = a.getResourceId(styleableClass.getDeclaredField("Switch_switchTextAppearance").getInt(null), -1); - json.put("Switch_switchTextAppearance", extractTextAppearanceInformations(styleName, null, null, textAppearance, styleId)); + json.put("Switch_switchTextAppearance", extractTextAppearance(textAppearance)); json.put("Switch_textOn", a.getText(getField(styleableClass, "Switch_textOn"))); json.put("Switch_textOff", a.getText(getField(styleableClass, "Switch_textOff"))); @@ -1517,10 +1546,10 @@ public class ExtractStyle { json.put("CalendarView_selectedDateVerticalBar", getDrawable(d, styleName + "_CalendarView_selectedDateVerticalBar")); int dateTextAppearance = a.getResourceId(styleableClass.getDeclaredField("CalendarView_dateTextAppearance").getInt(null), -1); - json.put("CalendarView_dateTextAppearance", extractTextAppearanceInformations(styleName, null, null, dateTextAppearance, styleId)); + json.put("CalendarView_dateTextAppearance", extractTextAppearance(dateTextAppearance)); int weekDayTextAppearance = a.getResourceId(styleableClass.getDeclaredField("CalendarView_weekDayTextAppearance").getInt(null), -1); - json.put("CalendarView_weekDayTextAppearance", extractTextAppearanceInformations(styleName, null, null, weekDayTextAppearance, styleId)); + json.put("CalendarView_weekDayTextAppearance", extractTextAppearance(weekDayTextAppearance)); json.put("CalendarView_firstDayOfWeek", a.getInt(getField(styleableClass, "CalendarView_firstDayOfWeek"), 0)); json.put("CalendarView_focusedMonthDateColor", a.getColor(getField(styleableClass, "CalendarView_focusedMonthDateColor"), 0)); diff --git a/src/corelib/doc/snippets/qloggingcategory/main.cpp b/src/corelib/doc/snippets/qloggingcategory/main.cpp index efbf9c55d3..3c6424921e 100644 --- a/src/corelib/doc/snippets/qloggingcategory/main.cpp +++ b/src/corelib/doc/snippets/qloggingcategory/main.cpp @@ -49,6 +49,9 @@ Q_DECLARE_LOGGING_CATEGORY(driverUsb) Q_LOGGING_CATEGORY(driverUsb, "driver.usb") //![1] +//![5] +Q_LOGGING_CATEGORY(driverUsbEvents, "driver.usb.events", QtWarningMsg) +//![5] // Completely made up example, inspired by en.wikipedia.org/wiki/USB :) struct UsbEntry { diff --git a/src/corelib/global/qcompilerdetection.h b/src/corelib/global/qcompilerdetection.h index 24c5bfa741..693d7e5c75 100644 --- a/src/corelib/global/qcompilerdetection.h +++ b/src/corelib/global/qcompilerdetection.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Copyright (C) 2012 Intel Corporation ** Contact: http://www.qt-project.org/legal ** @@ -705,6 +705,13 @@ # define Q_COMPILER_VLA # endif # endif + +# if defined(__has_warning) +# if __has_warning("-Wunused-private-field") +# define Q_DECL_UNUSED_MEMBER Q_DECL_UNUSED +# endif +# endif + #endif // Q_CC_CLANG #if defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && !defined(Q_CC_CLANG) @@ -996,6 +1003,9 @@ #ifndef Q_DECL_UNUSED # define Q_DECL_UNUSED #endif +#ifndef Q_DECL_UNUSED_MEMBER +# define Q_DECL_UNUSED_MEMBER +#endif #ifndef Q_FUNC_INFO # if defined(Q_OS_SOLARIS) || defined(Q_CC_XLC) # define Q_FUNC_INFO __FILE__ "(line number unavailable)" diff --git a/src/corelib/io/qdebug.cpp b/src/corelib/io/qdebug.cpp index ef9c654266..b0411f9dd9 100644 --- a/src/corelib/io/qdebug.cpp +++ b/src/corelib/io/qdebug.cpp @@ -79,6 +79,18 @@ QT_BEGIN_NAMESPACE used to write debugging information to files and other devices. The constructor that accepts a QString is used to write to a string for display or serialization. + \section1 Formatting Options + + QDebug formats output so that it's easily readable. It automatically adds spaces + between arguments, and adds quotes around QString, QByteArray, QChar arguments. + + You can tweak these options through the space(), nospace() and quote(), noquote() + methods. Furthermore, \l{QTextStream manipulators} can be piped into a QDebug + stream. + + QDebugStateSaver limits changes to the formatting to the current scope. + resetFormat() resets the options to the default ones. + \section1 Writing Custom Types to a Stream Many standard types can be written to QDebug objects, and Qt provides support for @@ -426,10 +438,18 @@ public: } void restoreState() { + const bool currentSpaces = m_dbg.autoInsertSpaces(); + if (currentSpaces && !m_spaces) + if (m_dbg.stream->buffer.endsWith(QLatin1Char(' '))) + m_dbg.stream->buffer.chop(1); + m_dbg.setAutoInsertSpaces(m_spaces); m_dbg.stream->ts.d_ptr->params = m_streamParams; if (m_dbg.stream->context.version > 1) m_dbg.stream->flags = m_flags; + + if (!currentSpaces && m_spaces) + m_dbg.stream->ts << ' '; } QDebug &m_dbg; @@ -463,7 +483,6 @@ QDebugStateSaver::QDebugStateSaver(QDebug &dbg) QDebugStateSaver::~QDebugStateSaver() { d->restoreState(); - d->m_dbg.maybeSpace(); } QT_END_NAMESPACE diff --git a/src/corelib/io/qfiledevice.cpp b/src/corelib/io/qfiledevice.cpp index f7e58a7bed..33cb6037f5 100644 --- a/src/corelib/io/qfiledevice.cpp +++ b/src/corelib/io/qfiledevice.cpp @@ -680,6 +680,13 @@ bool QFileDevice::setPermissions(Permissions permissions) function. \value NoOptions No options. + \value MapPrivateOption The mapped memory will be private, so any + modifications will not be visible to other processes and will not + be written to disk. Any such modifications will be lost when the + memory is unmapped. It is unspecified whether modifications made + to the file made after the mapping is created will be visible through + the mapped memory. This flag is not supported on Windows CE. + This enum value was introduced in Qt 5.4. */ /*! @@ -689,6 +696,10 @@ bool QFileDevice::setPermissions(Permissions permissions) or a new file is opened with this object, any maps that have not been unmapped will automatically be unmapped. + The mapping will have the same open mode as the file (read and/or write), + except when using MapPrivateOption, in which case it is always possible + to write to the mapped memory. + Any mapping options can be passed through \a flags. Returns a pointer to the memory or 0 if there is an error. diff --git a/src/corelib/io/qfiledevice.h b/src/corelib/io/qfiledevice.h index fc2779086a..4b13ffe589 100644 --- a/src/corelib/io/qfiledevice.h +++ b/src/corelib/io/qfiledevice.h @@ -112,8 +112,10 @@ public: virtual Permissions permissions() const; virtual bool setPermissions(Permissions permissionSpec); + // ### Qt 6: rename to MemoryMapFlag & make it a QFlags enum MemoryMapFlags { - NoOptions = 0 + NoOptions = 0, + MapPrivateOption = 0x0001 }; uchar *map(qint64 offset, qint64 size, MemoryMapFlags flags = NoOptions); diff --git a/src/corelib/io/qfsfileengine_unix.cpp b/src/corelib/io/qfsfileengine_unix.cpp index 064a1a511f..f9c6c8ab98 100644 --- a/src/corelib/io/qfsfileengine_unix.cpp +++ b/src/corelib/io/qfsfileengine_unix.cpp @@ -713,6 +713,12 @@ uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size, QFile::MemoryMapFla if (openMode & QIODevice::ReadOnly) access |= PROT_READ; if (openMode & QIODevice::WriteOnly) access |= PROT_WRITE; + int sharemode = MAP_SHARED; + if (flags & QFileDevice::MapPrivateOption) { + sharemode = MAP_PRIVATE; + access |= PROT_WRITE; + } + #if defined(Q_OS_INTEGRITY) int pageSize = sysconf(_SC_PAGESIZE); #else @@ -730,7 +736,7 @@ uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size, QFile::MemoryMapFla realOffset &= ~(QT_OFF_T(pageSize - 1)); void *mapAddress = QT_MMAP((void*)0, realSize, - access, MAP_SHARED, nativeHandle(), realOffset); + access, sharemode, nativeHandle(), realOffset); if (MAP_FAILED != mapAddress) { uchar *address = extra + static_cast<uchar*>(mapAddress); maps[address] = QPair<int,size_t>(extra, realSize); diff --git a/src/corelib/io/qfsfileengine_win.cpp b/src/corelib/io/qfsfileengine_win.cpp index fb4107b95d..81aed5f7b4 100644 --- a/src/corelib/io/qfsfileengine_win.cpp +++ b/src/corelib/io/qfsfileengine_win.cpp @@ -965,6 +965,21 @@ uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size, return 0; } + // check/setup args to map + DWORD access = 0; + if (flags & QFileDevice::MapPrivateOption) { +#ifdef FILE_MAP_COPY + access = FILE_MAP_COPY; +#else + q->setError(QFile::UnspecifiedError, "MapPrivateOption unsupported"); + return 0; +#endif + } else if (openMode & QIODevice::WriteOnly) { + access = FILE_MAP_WRITE; + } else if (openMode & QIODevice::ReadOnly) { + access = FILE_MAP_READ; + } + if (mapHandle == NULL) { // get handle to the file HANDLE handle = fileHandle; @@ -1011,11 +1026,6 @@ uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size, } } - // setup args to map - DWORD access = 0; - if (openMode & QIODevice::ReadOnly) access = FILE_MAP_READ; - if (openMode & QIODevice::WriteOnly) access = FILE_MAP_WRITE; - DWORD offsetHi = offset >> 32; DWORD offsetLo = offset & Q_UINT64_C(0xffffffff); SYSTEM_INFO sysinfo; diff --git a/src/corelib/io/qlockfile_win.cpp b/src/corelib/io/qlockfile_win.cpp index 28f6b02a64..00c8a85bcc 100644 --- a/src/corelib/io/qlockfile_win.cpp +++ b/src/corelib/io/qlockfile_win.cpp @@ -50,6 +50,11 @@ QT_BEGIN_NAMESPACE +static inline QByteArray localHostName() +{ + return qgetenv("COMPUTERNAME"); +} + QLockFile::LockError QLockFilePrivate::tryLock_sys() { const QFileSystemEntry fileEntry(fileName); @@ -98,7 +103,7 @@ QLockFile::LockError QLockFilePrivate::tryLock_sys() fileData += '\n'; fileData += qAppName().toUtf8(); fileData += '\n'; - //fileData += localHostname(); // gethostname requires winsock init, see QHostInfo... + fileData += localHostName(); fileData += '\n'; DWORD bytesWritten = 0; QLockFile::LockError error = QLockFile::NoError; @@ -123,14 +128,16 @@ bool QLockFilePrivate::isApparentlyStale() const // On WinRT there seems to be no way of obtaining information about other // processes due to sandboxing #ifndef Q_OS_WINRT - HANDLE procHandle = ::OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid); - if (!procHandle) - return true; - // We got a handle but check if process is still alive - DWORD dwR = ::WaitForSingleObject(procHandle, 0); - ::CloseHandle(procHandle); - if (dwR == WAIT_TIMEOUT) - return true; + if (hostname == QString::fromLocal8Bit(localHostName())) { + HANDLE procHandle = ::OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid); + if (!procHandle) + return true; + // We got a handle but check if process is still alive + DWORD dwR = ::WaitForSingleObject(procHandle, 0); + ::CloseHandle(procHandle); + if (dwR == WAIT_TIMEOUT) + return true; + } #endif // !Q_OS_WINRT const qint64 age = QFileInfo(fileName).lastModified().msecsTo(QDateTime::currentDateTime()); return staleLockTime > 0 && age > staleLockTime; diff --git a/src/corelib/io/qloggingcategory.cpp b/src/corelib/io/qloggingcategory.cpp index 92ac9d925f..63241f6698 100644 --- a/src/corelib/io/qloggingcategory.cpp +++ b/src/corelib/io/qloggingcategory.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -101,13 +101,21 @@ static void setBoolLane(QBasicAtomicInt *atomic, bool enable, int shift) \section1 Default category configuration - In the default configuration \l isWarningEnabled() , \l isDebugEnabled() and - \l isCriticalEnabled() will return \c true. + Both the QLoggingCategory constructor and the Q_LOGGING_CATEGORY() macro + accept an optional QtMsgType argument, which disables all message types with + a lower severity. That is, a category declared with + + \snippet qloggingcategory/main.cpp 5 + + will log messages of type \c QtWarningMsg, \c QtCriticalMsg, \c QtFatalMsg, but will + ignore messages of type \c QtDebugMsg. + + If no argument is passed, all messages will be logged. \section1 Configuring Categories - Categories can be centrally configured by either setting logging rules, - or by installing a custom filter. + The default configuration of categories can be overridden either by setting logging + rules, or by installing a custom filter. \section2 Logging Rules @@ -183,7 +191,7 @@ static void setBoolLane(QBasicAtomicInt *atomic, bool enable, int shift) /*! Constructs a QLoggingCategory object with the provided \a category name. - The object becomes the local identifier for the category. + All message types for this category are enabled by default. If \a category is \c{0}, the category name is changed to \c "default". */ @@ -191,8 +199,26 @@ QLoggingCategory::QLoggingCategory(const char *category) : d(0), name(0) { - Q_UNUSED(d); - Q_UNUSED(placeholder); + init(category, QtDebugMsg); +} + +/*! + Constructs a QLoggingCategory object with the provided \a category name, + and enables all messages with types more severe or equal than \a enableForLevel. + + If \a category is \c{0}, the category name is changed to \c "default". + + \since 5.4 +*/ +QLoggingCategory::QLoggingCategory(const char *category, QtMsgType enableForLevel) + : d(0), + name(0) +{ + init(category, enableForLevel); +} + +void QLoggingCategory::init(const char *category, QtMsgType severityLevel) +{ enabled.store(0x01010101); // enabledDebug = enabledWarning = enabledCritical = true; const bool isDefaultCategory @@ -200,14 +226,13 @@ QLoggingCategory::QLoggingCategory(const char *category) // normalize "default" category name, so that we can just do // pointer comparison in QLoggingRegistry::updateCategory - if (isDefaultCategory) { + if (isDefaultCategory) name = qtDefaultCategoryName; - } else { + else name = category; - } if (QLoggingRegistry *reg = QLoggingRegistry::instance()) - reg->registerCategory(this); + reg->registerCategory(this, severityLevel); } /*! @@ -524,7 +549,7 @@ void QLoggingCategory::setFilterRules(const QString &rules) \since 5.2 Defines a logging category \a name, and makes it configurable under the - \a string identifier. + \a string identifier. By default, all message types are enabled. Only one translation unit in a library or executable can define a category with a specific name. @@ -532,4 +557,21 @@ void QLoggingCategory::setFilterRules(const QString &rules) This macro must be used outside of a class or method. */ +/*! + \macro Q_LOGGING_CATEGORY(name, string, msgType) + \sa Q_DECLARE_LOGGING_CATEGORY() + \relates QLoggingCategory + \since 5.4 + + Defines a logging category \a name, and makes it configurable under the + \a string identifier. By default, messages of QtMsgType \a msgType + and more severe are enabled, types with a lower severity are disabled. + + Only one translation unit in a library or executable can define a category + with a specific name. + + This macro must be used outside of a class or method. It is only defined + if variadic macros are supported. +*/ + QT_END_NAMESPACE diff --git a/src/corelib/io/qloggingcategory.h b/src/corelib/io/qloggingcategory.h index 573af2105c..cca2031108 100644 --- a/src/corelib/io/qloggingcategory.h +++ b/src/corelib/io/qloggingcategory.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -51,7 +51,9 @@ class Q_CORE_EXPORT QLoggingCategory { Q_DISABLE_COPY(QLoggingCategory) public: + // ### Qt 6: Merge constructors explicit QLoggingCategory(const char *category); + QLoggingCategory(const char *category, QtMsgType severityLevel); ~QLoggingCategory(); bool isEnabled(QtMsgType type) const; @@ -80,7 +82,9 @@ public: static void setFilterRules(const QString &rules); private: - void *d; // reserved for future use + void init(const char *category, QtMsgType severityLevel); + + Q_DECL_UNUSED_MEMBER void *d; // reserved for future use const char *name; #ifdef Q_BIG_ENDIAN @@ -100,22 +104,20 @@ private: AtomicBools bools; QBasicAtomicInt enabled; }; - bool placeholder[4]; // reserve for future use + Q_DECL_UNUSED_MEMBER bool placeholder[4]; // reserved for future use }; #define Q_DECLARE_LOGGING_CATEGORY(name) \ extern const QLoggingCategory &name(); -// relies on QLoggingCategory(QString) being thread safe! -#define Q_LOGGING_CATEGORY(name, string) \ +#if defined(Q_COMPILER_VARIADIC_MACROS) || defined(Q_MOC_RUN) + +#define Q_LOGGING_CATEGORY(name, ...) \ const QLoggingCategory &name() \ { \ - static const QLoggingCategory category(string); \ + static const QLoggingCategory category(__VA_ARGS__); \ return category; \ } - -#ifdef Q_COMPILER_VARIADIC_MACROS - #define qCDebug(category, ...) \ for (bool qt_category_enabled = category().isDebugEnabled(); qt_category_enabled; qt_category_enabled = false) \ QMessageLogger(__FILE__, __LINE__, Q_FUNC_INFO, category().categoryName()).debug(__VA_ARGS__) @@ -126,14 +128,22 @@ private: for (bool qt_category_enabled = category().isCriticalEnabled(); qt_category_enabled; qt_category_enabled = false) \ QMessageLogger(__FILE__, __LINE__, Q_FUNC_INFO, category().categoryName()).critical(__VA_ARGS__) -#else +#else // defined(Q_COMPILER_VARIADIC_MACROS) || defined(Q_MOC_RUN) + +// Optional msgType argument not supported +#define Q_LOGGING_CATEGORY(name, string) \ + const QLoggingCategory &name() \ + { \ + static const QLoggingCategory category(string); \ + return category; \ + } // check for enabled category inside QMessageLogger. #define qCDebug qDebug #define qCWarning qWarning #define qCCritical qCritical -#endif // Q_COMPILER_VARIADIC_MACROS +#endif // Q_COMPILER_VARIADIC_MACROS || defined(Q_MOC_RUN) #if defined(QT_NO_DEBUG_OUTPUT) # undef qCDebug diff --git a/src/corelib/io/qloggingregistry.cpp b/src/corelib/io/qloggingregistry.cpp index 31a54d2d2d..dd1612c6b4 100644 --- a/src/corelib/io/qloggingregistry.cpp +++ b/src/corelib/io/qloggingregistry.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -131,15 +131,15 @@ void QLoggingRule::parse(const QStringRef &pattern) // strip trailing ".messagetype" if (pattern.endsWith(QLatin1String(".debug"))) { p = QStringRef(pattern.string(), pattern.position(), - pattern.length() - strlen(".debug")); + pattern.length() - 6); // strlen(".debug") messageType = QtDebugMsg; } else if (pattern.endsWith(QLatin1String(".warning"))) { p = QStringRef(pattern.string(), pattern.position(), - pattern.length() - strlen(".warning")); + pattern.length() - 8); // strlen(".warning") messageType = QtWarningMsg; } else if (pattern.endsWith(QLatin1String(".critical"))) { p = QStringRef(pattern.string(), pattern.position(), - pattern.length() - strlen(".critical")); + pattern.length() - 9); // strlen(".critical") messageType = QtCriticalMsg; } else { p = pattern; @@ -307,12 +307,12 @@ void QLoggingRegistry::init() This method might be called concurrently for the same category object. */ -void QLoggingRegistry::registerCategory(QLoggingCategory *cat) +void QLoggingRegistry::registerCategory(QLoggingCategory *cat, QtMsgType enableForLevel) { QMutexLocker locker(®istryMutex); if (!categories.contains(cat)) { - categories.append(cat); + categories.insert(cat, enableForLevel); (*categoryFilter)(cat); } } @@ -324,8 +324,7 @@ void QLoggingRegistry::registerCategory(QLoggingCategory *cat) void QLoggingRegistry::unregisterCategory(QLoggingCategory *cat) { QMutexLocker locker(®istryMutex); - - categories.removeOne(cat); + categories.remove(cat); } /*! @@ -341,7 +340,7 @@ void QLoggingRegistry::setApiRules(const QString &content) QMutexLocker locker(®istryMutex); if (qtLoggingDebug()) - debugMsg("Loading logging rules set by Qt API ..."); + debugMsg("Loading logging rules set by QLoggingCategory::setFilterRules ..."); apiRules = parser.rules(); @@ -361,7 +360,7 @@ void QLoggingRegistry::updateRules() rules = configRules + apiRules + envRules; - foreach (QLoggingCategory *cat, categories) + foreach (QLoggingCategory *cat, categories.keys()) (*categoryFilter)(cat); } @@ -380,7 +379,7 @@ QLoggingRegistry::installFilter(QLoggingCategory::CategoryFilter filter) QLoggingCategory::CategoryFilter old = categoryFilter; categoryFilter = filter; - foreach (QLoggingCategory *cat, categories) + foreach (QLoggingCategory *cat, categories.keys()) (*categoryFilter)(cat); return old; @@ -397,18 +396,22 @@ QLoggingRegistry *QLoggingRegistry::instance() */ void QLoggingRegistry::defaultCategoryFilter(QLoggingCategory *cat) { - // QLoggingCategory() normalizes "default" strings - // to qtDefaultCategoryName - bool debug = true; + QLoggingRegistry *reg = QLoggingRegistry::instance(); + Q_ASSERT(reg->categories.contains(cat)); + QtMsgType enableForLevel = reg->categories.value(cat); + + bool debug = (enableForLevel == QtDebugMsg) ? true : false; + bool warning = (enableForLevel <= QtWarningMsg) ? true : false; + bool critical = (enableForLevel <= QtCriticalMsg) ? true : false; + + // hard-wired implementation of + // qt.*.debug=false + // qt.debug=false char c; if (!memcmp(cat->categoryName(), "qt", 2) && (!(c = cat->categoryName()[2]) || c == '.')) debug = false; - bool warning = true; - bool critical = true; - QString categoryName = QLatin1String(cat->categoryName()); - QLoggingRegistry *reg = QLoggingRegistry::instance(); foreach (const QLoggingRule &item, reg->rules) { int filterpass = item.pass(categoryName, QtDebugMsg); if (filterpass != 0) diff --git a/src/corelib/io/qloggingregistry_p.h b/src/corelib/io/qloggingregistry_p.h index 48804cfc2b..ce2503b32c 100644 --- a/src/corelib/io/qloggingregistry_p.h +++ b/src/corelib/io/qloggingregistry_p.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -113,7 +113,7 @@ public: void init(); - void registerCategory(QLoggingCategory *category); + void registerCategory(QLoggingCategory *category, QtMsgType enableForLevel); void unregisterCategory(QLoggingCategory *category); void setApiRules(const QString &content); @@ -134,7 +134,7 @@ private: QVector<QLoggingRule> envRules; QVector<QLoggingRule> apiRules; QVector<QLoggingRule> rules; - QList<QLoggingCategory*> categories; + QHash<QLoggingCategory*,QtMsgType> categories; QLoggingCategory::CategoryFilter categoryFilter; friend class ::tst_QLoggingRegistry; diff --git a/src/corelib/io/qsettings.cpp b/src/corelib/io/qsettings.cpp index 1748170324..663ad3cc1b 100644 --- a/src/corelib/io/qsettings.cpp +++ b/src/corelib/io/qsettings.cpp @@ -53,6 +53,7 @@ #include "qmutex.h" #include "qlibraryinfo.h" #include "qtemporaryfile.h" +#include "qstandardpaths.h" #ifndef QT_NO_TEXTCODEC # include "qtextcodec.h" @@ -68,6 +69,11 @@ #include "qcoreapplication.h" #endif +#ifndef QT_BOOTSTRAPPED +#include "qsavefile.h" +#include "qlockfile.h" +#endif + #ifdef Q_OS_VXWORKS # include <ioLib.h> #endif @@ -101,12 +107,6 @@ using namespace ABI::Windows::Storage; #define CSIDL_APPDATA 0x001a // <username>\Application Data #endif -#ifdef Q_AUTOTEST_EXPORT -# define Q_AUTOTEST_EXPORT_HELPER Q_AUTOTEST_EXPORT -#else -# define Q_AUTOTEST_EXPORT_HELPER static -#endif - // ************************************************************************ // QConfFile @@ -141,101 +141,6 @@ static QBasicMutex settingsGlobalMutex; static QSettings::Format globalDefaultFormat = QSettings::NativeFormat; -#ifndef Q_OS_WIN -inline bool qt_isEvilFsTypeName(const char *name) -{ - return (qstrncmp(name, "nfs", 3) == 0 - || qstrncmp(name, "autofs", 6) == 0 - || qstrncmp(name, "cachefs", 7) == 0); -} - -#if defined(Q_OS_BSD4) && !defined(Q_OS_NETBSD) -QT_BEGIN_INCLUDE_NAMESPACE -# include <sys/param.h> -# include <sys/mount.h> -QT_END_INCLUDE_NAMESPACE - -Q_AUTOTEST_EXPORT_HELPER bool qIsLikelyToBeNfs(int handle) -{ - struct statfs buf; - if (fstatfs(handle, &buf) != 0) - return false; - return qt_isEvilFsTypeName(buf.f_fstypename); -} - -#elif defined(Q_OS_LINUX) || defined(Q_OS_HURD) -QT_BEGIN_INCLUDE_NAMESPACE -# include <sys/vfs.h> -# ifdef QT_LINUXBASE - // LSB 3.2 has fstatfs in sys/statfs.h, sys/vfs.h is just an empty dummy header -# include <sys/statfs.h> -# endif -QT_END_INCLUDE_NAMESPACE -# ifndef NFS_SUPER_MAGIC -# define NFS_SUPER_MAGIC 0x00006969 -# endif -# ifndef AUTOFS_SUPER_MAGIC -# define AUTOFS_SUPER_MAGIC 0x00000187 -# endif -# ifndef AUTOFSNG_SUPER_MAGIC -# define AUTOFSNG_SUPER_MAGIC 0x7d92b1a0 -# endif - -Q_AUTOTEST_EXPORT_HELPER bool qIsLikelyToBeNfs(int handle) -{ - struct statfs buf; - if (fstatfs(handle, &buf) != 0) - return false; - return buf.f_type == NFS_SUPER_MAGIC - || buf.f_type == AUTOFS_SUPER_MAGIC - || buf.f_type == AUTOFSNG_SUPER_MAGIC; -} - -#elif defined(Q_OS_SOLARIS) || defined(Q_OS_IRIX) || defined(Q_OS_AIX) || defined(Q_OS_HPUX) \ - || defined(Q_OS_OSF) || defined(Q_OS_QNX) || defined(Q_OS_SCO) \ - || defined(Q_OS_UNIXWARE) || defined(Q_OS_RELIANT) || defined(Q_OS_NETBSD) -QT_BEGIN_INCLUDE_NAMESPACE -# include <sys/statvfs.h> -QT_END_INCLUDE_NAMESPACE - -Q_AUTOTEST_EXPORT_HELPER bool qIsLikelyToBeNfs(int handle) -{ - struct statvfs buf; - if (fstatvfs(handle, &buf) != 0) - return false; -#if defined(Q_OS_NETBSD) - return qt_isEvilFsTypeName(buf.f_fstypename); -#else - return qt_isEvilFsTypeName(buf.f_basetype); -#endif -} -#else -Q_AUTOTEST_EXPORT_HELPER inline bool qIsLikelyToBeNfs(int /* handle */) -{ - return true; -} -#endif - -static bool unixLock(int handle, int lockType) -{ - /* - NFS hangs on the fcntl() call below when statd or lockd isn't - running. There's no way to detect this. Our work-around for - now is to disable locking when we detect NFS (or AutoFS or - CacheFS, which are probably wrapping NFS). - */ - if (qIsLikelyToBeNfs(handle)) - return false; - - struct flock fl; - fl.l_whence = SEEK_SET; - fl.l_start = 0; - fl.l_len = 0; - fl.l_type = lockType; - return fcntl(handle, F_SETLKW, &fl) == 0; -} -#endif - QConfFile::QConfFile(const QString &fileName, bool _userPerms) : name(fileName), size(0), ref(1), userPerms(_userPerms) { @@ -1140,6 +1045,8 @@ static void initDefaultPaths(QMutexLocker *locker) pathHash->insert(pathHashKey(QSettings::IniFormat, QSettings::SystemScope), windowsConfigPath(CSIDL_COMMON_APPDATA) + QDir::separator()); #else + +#ifdef QT_NO_STANDARDPATHS QString userPath; char *env = getenv("XDG_CONFIG_HOME"); if (env == 0) { @@ -1153,6 +1060,9 @@ static void initDefaultPaths(QMutexLocker *locker) userPath += QLatin1Char('/'); userPath += QFile::decodeName(env); } +#else + QString userPath = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation); +#endif userPath += QLatin1Char('/'); pathHash->insert(pathHashKey(QSettings::IniFormat, QSettings::UserScope), userPath); @@ -1457,105 +1367,30 @@ void QConfFileSettingsPrivate::syncConfFile(int confFileNo) return; } +#ifndef QT_BOOTSTRAPPED /* - Open the configuration file and try to use it using a named - semaphore on Windows and an advisory lock on Unix-based - systems. This protect us against other QSettings instances - trying to access the same file from other threads or - processes. - - As it stands now, the locking mechanism doesn't work for - .plist files. - */ - QFile file(confFile->name); - bool createFile = !file.exists(); - if (!readOnly && confFile->isWritable()) - file.open(QFile::ReadWrite); - if (!file.isOpen()) - file.open(QFile::ReadOnly); - - if (!createFile && !file.isOpen()) - setStatus(QSettings::AccessError); - -#ifdef Q_OS_WIN - HANDLE readSemaphore = 0; - HANDLE writeSemaphore = 0; - static const int FileLockSemMax = 50; - int numReadLocks = readOnly ? 1 : FileLockSemMax; - - if (file.isOpen()) { - // Acquire the write lock if we will be writing - if (!readOnly) { - QString writeSemName = QLatin1String("QSettingsWriteSem "); - writeSemName.append(file.fileName()); - -#ifndef Q_OS_WINRT - writeSemaphore = CreateSemaphore(0, 1, 1, reinterpret_cast<const wchar_t *>(writeSemName.utf16())); -#else - writeSemaphore = CreateSemaphoreEx(0, 1, 1, reinterpret_cast<const wchar_t *>(writeSemName.utf16()), 0, SEMAPHORE_ALL_ACCESS); -#endif + Use a lockfile in order to protect us against other QSettings instances + trying to write the same settings at the same time. - if (writeSemaphore) { -#ifndef Q_OS_WINRT - WaitForSingleObject(writeSemaphore, INFINITE); -#else - WaitForSingleObjectEx(writeSemaphore, INFINITE, FALSE); -#endif - } else { - setStatus(QSettings::AccessError); - return; - } - } - - // Acquire all the read locks if we will be writing, to make sure nobody - // reads while we're writing. If we are only reading, acquire a single - // read lock. - QString readSemName(QLatin1String("QSettingsReadSem ")); - readSemName.append(file.fileName()); - -#ifndef Q_OS_WINRT - readSemaphore = CreateSemaphore(0, FileLockSemMax, FileLockSemMax, reinterpret_cast<const wchar_t *>(readSemName.utf16())); -#else - readSemaphore = CreateSemaphoreEx(0, FileLockSemMax, FileLockSemMax, reinterpret_cast<const wchar_t *>(readSemName.utf16()), 0, SEMAPHORE_ALL_ACCESS); -#endif - - if (readSemaphore) { - for (int i = 0; i < numReadLocks; ++i) -#ifndef Q_OS_WINRT - WaitForSingleObject(readSemaphore, INFINITE); -#else - WaitForSingleObjectEx(readSemaphore, INFINITE, FALSE); -#endif - } else { + We only need to lock if we are actually writing as only concurrent writes are a problem. + Concurrent read and write are not a problem because the writing operation is atomic. + */ + QLockFile lockFile(confFile->name + QLatin1String(".lock")); + if (!readOnly) { + if (!confFile->isWritable() || !lockFile.lock() ) { setStatus(QSettings::AccessError); - if (writeSemaphore != 0) { - ReleaseSemaphore(writeSemaphore, 1, 0); - CloseHandle(writeSemaphore); - } return; } } -#else - if (file.isOpen()) - unixLock(file.handle(), readOnly ? F_RDLCK : F_WRLCK); #endif - // If we have created the file, apply the file perms - if (file.isOpen()) { - if (createFile) { - QFile::Permissions perms = file.permissions() | QFile::ReadOwner | QFile::WriteOwner; - if (!confFile->userPerms) - perms |= QFile::ReadGroup | QFile::ReadOther; - file.setPermissions(perms); - } - } - /* We hold the lock. Let's reread the file if it has changed since last time we read it. */ QFileInfo fileInfo(confFile->name); bool mustReadFile = true; + bool createFile = !fileInfo.exists(); if (!readOnly) mustReadFile = (confFile->size != fileInfo.size() @@ -1565,6 +1400,12 @@ void QConfFileSettingsPrivate::syncConfFile(int confFileNo) confFile->unparsedIniSections.clear(); confFile->originalKeys.clear(); + QFile file(confFile->name); + if (!createFile && !file.open(QFile::ReadOnly)) { + setStatus(QSettings::AccessError); + return; + } + /* Files that we can't read (because of permissions or because they don't exist) are treated as empty files. @@ -1615,42 +1456,40 @@ void QConfFileSettingsPrivate::syncConfFile(int confFileNo) ensureAllSectionsParsed(confFile); ParsedSettingsMap mergedKeys = confFile->mergedKeyMap(); - if (file.isWritable()) { #ifdef Q_OS_MAC - if (format == QSettings::NativeFormat) { - ok = writePlistFile(confFile->name, mergedKeys); - } else + if (format == QSettings::NativeFormat) { + ok = writePlistFile(confFile->name, mergedKeys); + } else #endif - { - file.seek(0); - file.resize(0); + { +#ifndef QT_BOOTSTRAPPED + QSaveFile sf(confFile->name); +#else + QFile sf(confFile->name); +#endif + if (!sf.open(QIODevice::WriteOnly)) { + setStatus(QSettings::AccessError); + ok = false; + } else if (format <= QSettings::IniFormat) { + ok = writeIniFile(sf, mergedKeys); + } else { + if (writeFunc) { + QSettings::SettingsMap tempOriginalKeys; - if (format <= QSettings::IniFormat) { - ok = writeIniFile(file, mergedKeys); - if (!ok) { - // try to restore old data; might work if the disk was full and the new data - // was larger than the old data - file.seek(0); - file.resize(0); - writeIniFile(file, confFile->originalKeys); + ParsedSettingsMap::const_iterator i = mergedKeys.constBegin(); + while (i != mergedKeys.constEnd()) { + tempOriginalKeys.insert(i.key(), i.value()); + ++i; } + ok = writeFunc(sf, tempOriginalKeys); } else { - if (writeFunc) { - QSettings::SettingsMap tempOriginalKeys; - - ParsedSettingsMap::const_iterator i = mergedKeys.constBegin(); - while (i != mergedKeys.constEnd()) { - tempOriginalKeys.insert(i.key(), i.value()); - ++i; - } - ok = writeFunc(file, tempOriginalKeys); - } else { - ok = false; - } + ok = false; } } - } else { - ok = false; +#ifndef QT_BOOTSTRAPPED + if (ok) + ok = sf.commit(); +#endif } if (ok) { @@ -1662,24 +1501,18 @@ void QConfFileSettingsPrivate::syncConfFile(int confFileNo) QFileInfo fileInfo(confFile->name); confFile->size = fileInfo.size(); confFile->timeStamp = fileInfo.lastModified(); + + // If we have created the file, apply the file perms + if (createFile) { + QFile::Permissions perms = fileInfo.permissions() | QFile::ReadOwner | QFile::WriteOwner; + if (!confFile->userPerms) + perms |= QFile::ReadGroup | QFile::ReadOther; + QFile(confFile->name).setPermissions(perms); + } } else { setStatus(QSettings::AccessError); } } - - /* - Release the file lock. - */ -#ifdef Q_OS_WIN - if (readSemaphore != 0) { - ReleaseSemaphore(readSemaphore, numReadLocks, 0); - CloseHandle(readSemaphore); - } - if (writeSemaphore != 0) { - ReleaseSemaphore(writeSemaphore, 1, 0); - CloseHandle(writeSemaphore); - } -#endif } enum { Space = 0x1, Special = 0x2 }; @@ -2505,12 +2338,6 @@ void QConfFileSettingsPrivate::ensureSectionParsed(QConfFile *confFile, 10.8 (Mountain Lion), only root can. However, 10.9 (Mavericks) changes that rule again but only for the native format (plist files). - \li On Unix and Mac OS X systems, the advisory file locking is disabled - if NFS (or AutoFS or CacheFS) is detected to work around a bug in the - NFS fcntl() implementation, which hangs forever if statd or lockd aren't - running. Also, the locking isn't performed when accessing \c .plist - files. - \li On the BlackBerry platform, applications run in a sandbox. They are not allowed to read or write outside of this sandbox. This involves the following limitations: diff --git a/src/corelib/io/qtextstream.cpp b/src/corelib/io/qtextstream.cpp index 24c22117fa..4002ce8694 100644 --- a/src/corelib/io/qtextstream.cpp +++ b/src/corelib/io/qtextstream.cpp @@ -2203,7 +2203,7 @@ void QTextStreamPrivate::putNumber(qulonglong number, bool negative) // add thousands group separators. For backward compatibility we // don't add a group separator for C locale. - if (locale != QLocale::c()) + if (locale != QLocale::c() && !locale.numberOptions().testFlag(QLocale::OmitGroupSeparator)) flags |= QLocaleData::ThousandsGroup; const QLocaleData *dd = locale.d->m_data; diff --git a/src/corelib/plugin/qlibrary.cpp b/src/corelib/plugin/qlibrary.cpp index 50281b632a..8af38acf51 100644 --- a/src/corelib/plugin/qlibrary.cpp +++ b/src/corelib/plugin/qlibrary.cpp @@ -455,7 +455,7 @@ inline QLibraryPrivate *QLibraryStore::findOrCreate(const QString &fileName, con lib = new QLibraryPrivate(fileName, version, loadHints); // track this library - if (Q_LIKELY(data)) + if (Q_LIKELY(data) && !fileName.isEmpty()) data->libraryMap.insert(fileName, lib); lib->libraryRefCount.ref(); @@ -475,7 +475,7 @@ inline void QLibraryStore::releaseLibrary(QLibraryPrivate *lib) // no one else is using Q_ASSERT(lib->libraryUnloadCount.load() == 0); - if (Q_LIKELY(data)) { + if (Q_LIKELY(data) && !lib->fileName.isEmpty()) { QLibraryPrivate *that = data->libraryMap.take(lib->fileName); Q_ASSERT(lib == that); Q_UNUSED(that); @@ -485,9 +485,9 @@ inline void QLibraryStore::releaseLibrary(QLibraryPrivate *lib) QLibraryPrivate::QLibraryPrivate(const QString &canonicalFileName, const QString &version, QLibrary::LoadHints loadHints) : pHnd(0), fileName(canonicalFileName), fullVersion(version), instance(0), - loadHints(loadHints), libraryRefCount(0), libraryUnloadCount(0), pluginState(MightBeAPlugin) { + loadHintsInt.store(loadHints); if (canonicalFileName.isEmpty()) errorString = QLibrary::tr("The shared library was not found."); } @@ -508,7 +508,7 @@ void QLibraryPrivate::mergeLoadHints(QLibrary::LoadHints lh) if (pHnd) return; - loadHints = lh; + loadHintsInt.store(lh); } QFunctionPointer QLibraryPrivate::resolve(const char *symbol) @@ -518,6 +518,12 @@ QFunctionPointer QLibraryPrivate::resolve(const char *symbol) return resolve_sys(symbol); } +void QLibraryPrivate::setLoadHints(QLibrary::LoadHints lh) +{ + // this locks a global mutex + QMutexLocker lock(&qt_library_mutex); + mergeLoadHints(lh); +} bool QLibraryPrivate::load() { @@ -914,13 +920,12 @@ void QLibrary::setFileName(const QString &fileName) { QLibrary::LoadHints lh; if (d) { - lh = d->loadHints; + lh = d->loadHints(); d->release(); d = 0; did_load = false; } - d = QLibraryPrivate::findOrCreate(fileName); - d->loadHints = lh; + d = QLibraryPrivate::findOrCreate(fileName, QString(), lh); } QString QLibrary::fileName() const @@ -943,13 +948,12 @@ void QLibrary::setFileNameAndVersion(const QString &fileName, int verNum) { QLibrary::LoadHints lh; if (d) { - lh = d->loadHints; + lh = d->loadHints(); d->release(); d = 0; did_load = false; } - d = QLibraryPrivate::findOrCreate(fileName, verNum >= 0 ? QString::number(verNum) : QString()); - d->loadHints = lh; + d = QLibraryPrivate::findOrCreate(fileName, verNum >= 0 ? QString::number(verNum) : QString(), lh); } /*! @@ -965,13 +969,12 @@ void QLibrary::setFileNameAndVersion(const QString &fileName, const QString &ver { QLibrary::LoadHints lh; if (d) { - lh = d->loadHints; + lh = d->loadHints(); d->release(); d = 0; did_load = false; } - d = QLibraryPrivate::findOrCreate(fileName, version); - d->loadHints = lh; + d = QLibraryPrivate::findOrCreate(fileName, version, lh); } /*! @@ -1102,6 +1105,12 @@ QString QLibrary::errorString() const By default, none of these flags are set, so libraries will be loaded with lazy symbol resolution, and will not export external symbols for resolution in other dynamically-loaded libraries. + + \note Setting this property after the library has been loaded has no effect + and loadHints() will not reflect those changes. + + \note This property is shared among all QLibrary instances that refer to + the same library. */ void QLibrary::setLoadHints(LoadHints hints) { @@ -1109,12 +1118,12 @@ void QLibrary::setLoadHints(LoadHints hints) d = QLibraryPrivate::findOrCreate(QString()); // ugly, but we need a d-ptr d->errorString.clear(); } - d->loadHints = hints; + d->setLoadHints(hints); } QLibrary::LoadHints QLibrary::loadHints() const { - return d ? d->loadHints : (QLibrary::LoadHints)0; + return d ? d->loadHints() : QLibrary::LoadHints(); } /* Internal, for debugging */ diff --git a/src/corelib/plugin/qlibrary_p.h b/src/corelib/plugin/qlibrary_p.h index e58d18e87b..df95d1342d 100644 --- a/src/corelib/plugin/qlibrary_p.h +++ b/src/corelib/plugin/qlibrary_p.h @@ -94,6 +94,10 @@ public: void release(); QFunctionPointer resolve(const char *); + QLibrary::LoadHints loadHints() const + { return QLibrary::LoadHints(loadHintsInt.load()); } + void setLoadHints(QLibrary::LoadHints lh); + static QLibraryPrivate *findOrCreate(const QString &fileName, const QString &version = QString(), QLibrary::LoadHints loadHints = 0); static QStringList suffixes_sys(const QString &fullVersion); @@ -104,7 +108,6 @@ public: QJsonObject metaData; QString errorString; - QLibrary::LoadHints loadHints; void updatePluginState(); bool isPlugin(); @@ -126,6 +129,8 @@ private: bool unload_sys(); QFunctionPointer resolve_sys(const char *); + QAtomicInt loadHintsInt; + /// counts how many QLibrary or QPluginLoader are attached to us, plus 1 if it's loaded QAtomicInt libraryRefCount; /// counts how many times load() or loadPlugin() were called diff --git a/src/corelib/plugin/qlibrary_unix.cpp b/src/corelib/plugin/qlibrary_unix.cpp index 43e2b5c15b..b9af143f35 100644 --- a/src/corelib/plugin/qlibrary_unix.cpp +++ b/src/corelib/plugin/qlibrary_unix.cpp @@ -162,6 +162,7 @@ bool QLibraryPrivate::load_sys() dlFlags |= BIND_DEFERRED; } #else + int loadHints = this->loadHints(); if (loadHints & QLibrary::ResolveAllSymbolsHint) { dlFlags |= RTLD_NOW; } else { diff --git a/src/corelib/plugin/qpluginloader.cpp b/src/corelib/plugin/qpluginloader.cpp index 2c139669e6..f34c019823 100644 --- a/src/corelib/plugin/qpluginloader.cpp +++ b/src/corelib/plugin/qpluginloader.cpp @@ -339,7 +339,7 @@ void QPluginLoader::setFileName(const QString &fileName) #if defined(QT_SHARED) QLibrary::LoadHints lh; if (d) { - lh = d->loadHints; + lh = d->loadHints(); d->release(); d = 0; did_load = false; @@ -405,17 +405,12 @@ void QPluginLoader::setLoadHints(QLibrary::LoadHints loadHints) d = QLibraryPrivate::findOrCreate(QString()); // ugly, but we need a d-ptr d->errorString.clear(); } - d->loadHints = loadHints; + d->setLoadHints(loadHints); } QLibrary::LoadHints QPluginLoader::loadHints() const { - if (!d) { - QPluginLoader *that = const_cast<QPluginLoader *>(this); - that->d = QLibraryPrivate::findOrCreate(QString()); // ugly, but we need a d-ptr - that->d->errorString.clear(); - } - return d->loadHints; + return d ? d->loadHints() : QLibrary::LoadHints(); } /*! diff --git a/src/corelib/tools/qhash.cpp b/src/corelib/tools/qhash.cpp index 8e4f0f6407..c9271848ec 100644 --- a/src/corelib/tools/qhash.cpp +++ b/src/corelib/tools/qhash.cpp @@ -986,8 +986,8 @@ uint qHash(long double key, uint seed) Q_DECL_NOTHROW A QHash's key type has additional requirements other than being an assignable data type: it must provide operator==(), and there must also be - a global qHash() function that returns a hash value for an argument of the - key's type. + a qHash() function in the type's namespace that returns a hash value for an + argument of the key's type. The qHash() function computes a numeric value based on a key. It can use any algorithm imaginable, as long as it always returns @@ -2152,8 +2152,8 @@ uint qHash(long double key, uint seed) Q_DECL_NOTHROW QMultiHash's key and value data types must be \l{assignable data types}. You cannot, for example, store a QWidget as a value; instead, store a QWidget *. In addition, QMultiHash's key type - must provide operator==(), and there must also be a global - qHash() function that returns a hash value for an argument of the + must provide operator==(), and there must also be a qHash() function + in the type's namespace that returns a hash value for an argument of the key's type. See the QHash documentation for details. \sa QHash, QHashIterator, QMutableHashIterator, QMultiMap diff --git a/src/corelib/tools/qringbuffer_p.h b/src/corelib/tools/qringbuffer_p.h index 2f208d21e3..5aa1f165be 100644 --- a/src/corelib/tools/qringbuffer_p.h +++ b/src/corelib/tools/qringbuffer_p.h @@ -61,9 +61,9 @@ QT_BEGIN_NAMESPACE class QRingBuffer { public: - explicit inline QRingBuffer(int growth = 4096) : basicBlockSize(growth) { - buffers << QByteArray(); - clear(); + explicit inline QRingBuffer(int growth = 4096) : + head(0), tail(0), tailBuffer(0), basicBlockSize(growth), bufferSize(0) { + buffers.append(QByteArray()); } inline int nextDataBlockSize() const { @@ -78,115 +78,65 @@ public: // the out-variable length will contain the amount of bytes readable // from there, e.g. the amount still the same QByteArray inline const char *readPointerAtPosition(qint64 pos, qint64 &length) const { - if (buffers.isEmpty()) { - length = 0; - return 0; - } - - if (pos >= bufferSize) { - length = 0; - return 0; - } - - // special case: it is in the first buffer - int nextDataBlockSizeValue = nextDataBlockSize(); - if (pos < nextDataBlockSizeValue) { - length = nextDataBlockSizeValue - pos; - return buffers.at(0).constData() + head + pos; - } - - // special case: we only had one buffer and tried to read over it - if (buffers.length() == 1) { - length = 0; - return 0; - } - - // skip the first - pos -= nextDataBlockSizeValue; - - // normal case: it is somewhere in the second to the-one-before-the-tailBuffer - for (int i = 1; i < tailBuffer; i++) { - if (pos >= buffers[i].size()) { - pos -= buffers[i].size(); - continue; + if (pos >= 0) { + pos += head; + for (int i = 0; i < buffers.size(); ++i) { + length = (i == tailBuffer ? tail : buffers[i].size()); + if (length > pos) { + length -= pos; + return buffers[i].constData() + pos; + } + pos -= length; } - - length = buffers[i].length() - pos; - return buffers[i].constData() + pos; } - // it is in the tail buffer - length = tail - pos; - return buffers[tailBuffer].constData() + pos; + length = 0; + return 0; } inline void free(int bytes) { - bufferSize -= bytes; - if (bufferSize < 0) - bufferSize = 0; - - for (;;) { - int nextBlockSize = nextDataBlockSize(); - if (bytes < nextBlockSize) { - head += bytes; - if (head == tail && tailBuffer == 0) - head = tail = 0; - break; - } - - bytes -= nextBlockSize; - if (buffers.count() == 1) { - if (buffers.at(0).size() != basicBlockSize) - buffers[0].resize(basicBlockSize); - head = tail = 0; - tailBuffer = 0; - break; + while (bytes > 0) { + int blockSize = buffers.first().size() - head; + + if (tailBuffer == 0 || blockSize > bytes) { + bufferSize -= bytes; + if (bufferSize <= 0) + clear(); // try to minify/squeeze us + else + head += bytes; + return; } - buffers.removeAt(0); + bufferSize -= blockSize; + bytes -= blockSize; + buffers.removeFirst(); --tailBuffer; head = 0; } - - if (isEmpty()) - clear(); // try to minify/squeeze us } inline char *reserve(int bytes) { - // if this is a fresh empty QRingBuffer - if (bufferSize == 0) { - buffers[0].resize(qMax(basicBlockSize, bytes)); - bufferSize += bytes; - tail = bytes; - return buffers[tailBuffer].data(); - } - - bufferSize += bytes; + if (bytes <= 0) + return 0; - // if there is already enough space, simply return. - if (tail + bytes <= buffers.at(tailBuffer).size()) { - char *writePtr = buffers[tailBuffer].data() + tail; - tail += bytes; - return writePtr; - } + // if need buffer reallocation + if (tail + bytes > buffers.last().size()) { + if (tail >= basicBlockSize) { + // shrink this buffer to its current size + buffers.last().resize(tail); - // if our buffer isn't half full yet, simply resize it. - if (tail < buffers.at(tailBuffer).size() / 2) { - buffers[tailBuffer].resize(tail + bytes); - char *writePtr = buffers[tailBuffer].data() + tail; - tail += bytes; - return writePtr; + // create a new QByteArray + buffers.append(QByteArray()); + ++tailBuffer; + tail = 0; + } + buffers.last().resize(qMax(basicBlockSize, tail + bytes)); } - // shrink this buffer to its current size - buffers[tailBuffer].resize(tail); - - // create a new QByteArray with the right size - buffers << QByteArray(); - ++tailBuffer; - buffers[tailBuffer].resize(qMax(basicBlockSize, bytes)); - tail = bytes; - return buffers[tailBuffer].data(); + char *writePtr = buffers.last().data() + tail; + bufferSize += bytes; + tail += bytes; + return writePtr; } inline void truncate(int pos) { @@ -195,33 +145,22 @@ public: } inline void chop(int bytes) { - bufferSize -= bytes; - if (bufferSize < 0) - bufferSize = 0; - - for (;;) { - // special case: head and tail are in the same buffer - if (tailBuffer == 0) { - tail -= bytes; - if (tail <= head) - tail = head = 0; - return; - } - - if (bytes <= tail) { - tail -= bytes; + while (bytes > 0) { + if (tailBuffer == 0 || tail > bytes) { + bufferSize -= bytes; + if (bufferSize <= 0) + clear(); // try to minify/squeeze us + else + tail -= bytes; return; } + bufferSize -= tail; bytes -= tail; - buffers.removeAt(tailBuffer); - + buffers.removeLast(); --tailBuffer; - tail = buffers.at(tailBuffer).size(); + tail = buffers.last().size(); } - - if (isEmpty()) - clear(); // try to minify/squeeze us } inline bool isEmpty() const { @@ -245,11 +184,11 @@ public: --head; if (head < 0) { buffers.prepend(QByteArray()); - buffers[0].resize(basicBlockSize); + buffers.first().resize(basicBlockSize); head = basicBlockSize - 1; ++tailBuffer; } - buffers[0][head] = c; + buffers.first()[head] = c; ++bufferSize; } @@ -259,8 +198,7 @@ public: inline void clear() { buffers.erase(buffers.begin() + 1, buffers.end()); - buffers[0].resize(0); - buffers[0].squeeze(); + buffers.first().clear(); head = tail = 0; tailBuffer = 0; @@ -269,47 +207,34 @@ public: inline int indexOf(char c) const { int index = 0; + int j = head; for (int i = 0; i < buffers.size(); ++i) { - int start = 0; - int end = buffers.at(i).size(); - - if (i == 0) - start = head; - if (i == tailBuffer) - end = tail; - const char *ptr = buffers.at(i).data() + start; - for (int j = start; j < end; ++j) { + const char *ptr = buffers[i].constData() + j; + j = index + (i == tailBuffer ? tail : buffers[i].size()) - j; + + while (index < j) { if (*ptr++ == c) return index; ++index; } + j = 0; } return -1; } inline int indexOf(char c, int maxLength) const { int index = 0; - int remain = qMin(size(), maxLength); - for (int i = 0; remain && i < buffers.size(); ++i) { - int start = 0; - int end = buffers.at(i).size(); - - if (i == 0) - start = head; - if (i == tailBuffer) - end = tail; - if (remain < end - start) { - end = start + remain; - remain = 0; - } else { - remain -= end - start; - } - const char *ptr = buffers.at(i).data() + start; - for (int j = start; j < end; ++j) { + int j = head; + for (int i = 0; index < maxLength && i < buffers.size(); ++i) { + const char *ptr = buffers[i].constData() + j; + j = qMin(index + (i == tailBuffer ? tail : buffers[i].size()) - j, maxLength); + + while (index < j) { if (*ptr++ == c) return index; ++index; } + j = 0; } return -1; } @@ -318,10 +243,9 @@ public: int bytesToRead = qMin(size(), maxLength); int readSoFar = 0; while (readSoFar < bytesToRead) { - const char *ptr = readPointer(); int bytesToReadFromThisBlock = qMin(bytesToRead - readSoFar, nextDataBlockSize()); if (data) - memcpy(data + readSoFar, ptr, bytesToReadFromThisBlock); + memcpy(data + readSoFar, readPointer(), bytesToReadFromThisBlock); readSoFar += bytesToReadFromThisBlock; free(bytesToReadFromThisBlock); } @@ -333,47 +257,33 @@ public: if (bufferSize == 0) return QByteArray(); - // multiple buffers, just take the first one - if (head == 0 && tailBuffer != 0) { - QByteArray qba = buffers.takeFirst(); - --tailBuffer; - bufferSize -= qba.length(); - return qba; - } + QByteArray qba(buffers.takeFirst()); - // one buffer with good value for head. Just take it. - if (head == 0 && tailBuffer == 0) { - QByteArray qba = buffers.takeFirst(); - qba.resize(tail); - buffers << QByteArray(); - bufferSize = 0; - tail = 0; - return qba; - } - - // Bad case: We have to memcpy. - // We can avoid by initializing the QRingBuffer with basicBlockSize of 0 - // and only using this read() function. - QByteArray qba(readPointer(), nextDataBlockSize()); - buffers.removeFirst(); - head = 0; + qba.reserve(0); // avoid that resizing needlessly reallocates if (tailBuffer == 0) { - buffers << QByteArray(); + qba.resize(tail); tail = 0; + buffers.append(QByteArray()); } else { --tailBuffer; } - bufferSize -= qba.length(); + qba.remove(0, head); // does nothing if head is 0 + head = 0; + bufferSize -= qba.size(); return qba; } // append a new buffer to the end inline void append(const QByteArray &qba) { - buffers[tailBuffer].resize(tail); - buffers << qba; - ++tailBuffer; - tail = qba.length(); - bufferSize += qba.length(); + if (tail == 0) { + buffers.last() = qba; + } else { + buffers.last().resize(tail); + buffers.append(qba); + ++tailBuffer; + } + tail = qba.size(); + bufferSize += tail; } inline int skip(int length) { @@ -381,35 +291,26 @@ public: } inline int readLine(char *data, int maxLength) { - int index = indexOf('\n'); - if (index == -1) - return read(data, maxLength); - if (maxLength <= 0) + if (!data || --maxLength <= 0) return -1; - int readSoFar = 0; - while (readSoFar < index + 1 && readSoFar < maxLength - 1) { - int bytesToRead = qMin((index + 1) - readSoFar, nextDataBlockSize()); - bytesToRead = qMin(bytesToRead, (maxLength - 1) - readSoFar); - memcpy(data + readSoFar, readPointer(), bytesToRead); - readSoFar += bytesToRead; - free(bytesToRead); - } + int i = indexOf('\n', maxLength); + i = read(data, i >= 0 ? (i + 1) : maxLength); // Terminate it. - data[readSoFar] = '\0'; - return readSoFar; + data[i] = '\0'; + return i; } inline bool canReadLine() const { - return indexOf('\n') != -1; + return indexOf('\n') >= 0; } private: QList<QByteArray> buffers; int head, tail; int tailBuffer; // always buffers.size() - 1 - int basicBlockSize; + const int basicBlockSize; int bufferSize; }; diff --git a/src/gui/accessible/qaccessible.cpp b/src/gui/accessible/qaccessible.cpp index 790563ad1a..3398fa0cb8 100644 --- a/src/gui/accessible/qaccessible.cpp +++ b/src/gui/accessible/qaccessible.cpp @@ -326,8 +326,8 @@ QT_BEGIN_NAMESPACE \value Desktop The object represents the desktop or workspace. \value Dial An object that represents a dial or knob. \value Dialog A dialog box. - \value Document A document window, usually in an MDI environment. - \value EditableText Editable text + \value Document A document, for example in an office application. + \value EditableText Editable text such as a line or text edit. \value Equation An object that represents a mathematical equation. \value Graphic A graphic or picture, e.g. an icon. \value Grip A grip that the user can drag to change the size of widgets. @@ -344,6 +344,7 @@ QT_BEGIN_NAMESPACE \value NoRole The object has no role. This usually indicates an invalid object. \value PageTab A page tab that the user can select to switch to a different page in a dialog. \value PageTabList A list of page tabs. + \value Paragraph A paragraph of text (usually found in documents). \value Pane A generic container. \value PopupMenu A menu which lists options that the user can select to perform an action. \value ProgressBar The object displays the progress of an operation in progress. @@ -353,6 +354,7 @@ QT_BEGIN_NAMESPACE \value Row A row of cells, usually within a table. \value RowHeader A header for a row of data. \value ScrollBar A scroll bar, which allows the user to scroll the visible area. + \value Section A section (in a document). \value Separator A separator that divides space into logical areas. \value Slider A slider that allows the user to select a value within a given range. \value Sound An object that represents a sound. @@ -368,6 +370,7 @@ QT_BEGIN_NAMESPACE \value Tree A list of items in a tree structure. \value TreeItem An item in a tree structure. \value UserRole The first value to be used for user defined roles. + \value WebDocument HTML document, usually in a browser. \value Whitespace Blank space between other objects. \value Window A top level window. */ diff --git a/src/gui/accessible/qaccessible.h b/src/gui/accessible/qaccessible.h index eced928069..2da7cf62bf 100644 --- a/src/gui/accessible/qaccessible.h +++ b/src/gui/accessible/qaccessible.h @@ -296,6 +296,9 @@ public: LayeredPane = 0x00000080, Terminal = 0x00000081, Desktop = 0x00000082, + Paragraph = 0x00000083, + WebDocument = 0x00000084, + Section = 0x00000085, UserRole = 0x0000ffff }; diff --git a/src/gui/image/qicon.cpp b/src/gui/image/qicon.cpp index 4f5e9c3d1f..ac95222c99 100644 --- a/src/gui/image/qicon.cpp +++ b/src/gui/image/qicon.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtGui module of the Qt Toolkit. @@ -1321,18 +1321,20 @@ QDataStream &operator>>(QDataStream &s, QIcon &icon) #ifndef QT_NO_DEBUG_STREAM QDebug operator<<(QDebug dbg, const QIcon &i) { - QDebug nospace = dbg.nospace(); - nospace << "QIcon("; + QDebugStateSaver saver(dbg); + dbg.resetFormat(); + dbg.nospace(); + dbg << "QIcon("; if (i.isNull()) { - nospace << "null"; + dbg << "null"; } else { if (!i.name().isEmpty()) - nospace << i.name() << ','; - nospace << "availableSizes[normal,Off]=" << i.availableSizes() + dbg << i.name() << ','; + dbg << "availableSizes[normal,Off]=" << i.availableSizes() << ",cacheKey=" << showbase << hex << i.cacheKey() << dec << noshowbase; } - nospace << ')'; - return dbg.space(); + dbg << ')'; + return dbg; } #endif diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp index 40f8b9e4d8..8c7c446e96 100644 --- a/src/gui/image/qimage.cpp +++ b/src/gui/image/qimage.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtGui module of the Qt Toolkit. @@ -4550,19 +4550,21 @@ bool QImageData::convertInPlace(QImage::Format newFormat, Qt::ImageConversionFla #ifndef QT_NO_DEBUG_STREAM QDebug operator<<(QDebug dbg, const QImage &i) { - QDebug nospace = dbg.nospace(); - nospace << "QImage("; + QDebugStateSaver saver(dbg); + dbg.resetFormat(); + dbg.nospace(); + dbg << "QImage("; if (i.isNull()) { - nospace << "null"; + dbg << "null"; } else { - nospace << i.size() << ",format=" << i.format() << ",depth=" << i.depth(); + dbg << i.size() << ",format=" << i.format() << ",depth=" << i.depth(); if (i.colorCount()) - nospace << ",colorCount=" << i.colorCount(); - nospace << ",devicePixelRatio=" << i.devicePixelRatio() + dbg << ",colorCount=" << i.colorCount(); + dbg << ",devicePixelRatio=" << i.devicePixelRatio() << ",bytesPerLine=" << i.bytesPerLine() << ",byteCount=" << i.byteCount(); } - nospace << ')'; - return dbg.space(); + dbg << ')'; + return dbg; } #endif diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp index 0ed840e0c0..2d41ca7e24 100644 --- a/src/gui/image/qpixmap.cpp +++ b/src/gui/image/qpixmap.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtGui module of the Qt Toolkit. @@ -1724,17 +1724,19 @@ QPlatformPixmap* QPixmap::handle() const #ifndef QT_NO_DEBUG_STREAM QDebug operator<<(QDebug dbg, const QPixmap &r) { - QDebug nospace = dbg.nospace(); - nospace << "QPixmap("; + QDebugStateSaver saver(dbg); + dbg.resetFormat(); + dbg.nospace(); + dbg << "QPixmap("; if (r.isNull()) { - nospace << "null"; + dbg << "null"; } else { - nospace << r.size() << ",depth=" << r.depth() + dbg << r.size() << ",depth=" << r.depth() << ",devicePixelRatio=" << r.devicePixelRatio() << ",cacheKey=" << showbase << hex << r.cacheKey() << dec << noshowbase; } - nospace << ')'; - return dbg.space(); + dbg << ')'; + return dbg; } #endif diff --git a/src/gui/opengl/qopengltexture.cpp b/src/gui/opengl/qopengltexture.cpp index 0b9732d278..811505cecb 100644 --- a/src/gui/opengl/qopengltexture.cpp +++ b/src/gui/opengl/qopengltexture.cpp @@ -1613,6 +1613,8 @@ QOpenGLTexture *QOpenGLTexturePrivate::createTextureView(QOpenGLTexture::Target \value UInt16_R5G6B5_Rev Equivalent to GL_UNSIGNED_SHORT_5_6_5_REV \value UInt16_RGBA4 Equivalent to GL_UNSIGNED_SHORT_4_4_4_4 \value UInt16_RGBA4_Rev Equivalent to GL_UNSIGNED_SHORT_4_4_4_4_REV + \value UInt32_RGBA8 Equivalent to GL_UNSIGNED_INT_8_8_8_8 + \value UInt32_RGBA8_Rev Equivalent to GL_UNSIGNED_INT_8_8_8_8_REV \value UInt32_RGB10A2 Equivalent to GL_UNSIGNED_INT_10_10_10_2 \value UInt32_RGB10A2_Rev Equivalent to GL_UNSIGNED_INT_2_10_10_10_REV \value UInt32_D24S8 Equivalent to GL_UNSIGNED_INT_24_8. Introduced in Qt 5.4 diff --git a/src/gui/opengl/qopengltexture.h b/src/gui/opengl/qopengltexture.h index ea81f1f8a4..1f4e0c048f 100644 --- a/src/gui/opengl/qopengltexture.h +++ b/src/gui/opengl/qopengltexture.h @@ -340,6 +340,8 @@ public: UInt16_R5G6B5_Rev = 0x8364, // GL_UNSIGNED_SHORT_5_6_5_REV UInt16_RGBA4 = 0x8033, // GL_UNSIGNED_SHORT_4_4_4_4 UInt16_RGBA4_Rev = 0x8365, // GL_UNSIGNED_SHORT_4_4_4_4_REV + UInt32_RGBA8 = 0x8035, // GL_UNSIGNED_INT_8_8_8_8 + UInt32_RGBA8_Rev = 0x8367, // GL_UNSIGNED_INT_8_8_8_8_REV UInt32_RGB10A2 = 0x8036, // GL_UNSIGNED_INT_10_10_10_2 UInt32_RGB10A2_Rev = 0x8368, // GL_UNSIGNED_INT_2_10_10_10_REV UInt32_D24S8 = 0x84FA, // GL_UNSIGNED_INT_24_8 diff --git a/src/platformsupport/linuxaccessibility/atspiadaptor.cpp b/src/platformsupport/linuxaccessibility/atspiadaptor.cpp index f9d2f21b0c..48cd01413f 100644 --- a/src/platformsupport/linuxaccessibility/atspiadaptor.cpp +++ b/src/platformsupport/linuxaccessibility/atspiadaptor.cpp @@ -910,6 +910,11 @@ void AtSpiAdaptor::notify(QAccessibleEvent *event) notifyAboutDestruction(event->accessibleInterface()); break; } + case QAccessible::ObjectReorder: { + if (sendObject || sendObject_children_changed) + childrenChanged(event->accessibleInterface()); + break; + } case QAccessible::NameChanged: { if (sendObject || sendObject_property_change || sendObject_property_change_accessible_name) { QString path = pathForInterface(event->accessibleInterface()); @@ -1148,7 +1153,6 @@ void AtSpiAdaptor::notify(QAccessibleEvent *event) case QAccessible::TextAttributeChanged: case QAccessible::TextColumnChanged: case QAccessible::VisibleDataChanged: - case QAccessible::ObjectReorder: case QAccessible::SelectionAdd: case QAccessible::SelectionWithin: case QAccessible::LocationChanged: @@ -1184,6 +1188,17 @@ void AtSpiAdaptor::sendFocusChanged(QAccessibleInterface *interface) const } } +void AtSpiAdaptor::childrenChanged(QAccessibleInterface *interface) const +{ + QString parentPath = pathForInterface(interface); + int childCount = interface->childCount(); + for (int i = 0; i < interface->childCount(); ++i) { + QString childPath = pathForInterface(interface->child(i)); + QVariantList args = packDBusSignalArguments(QLatin1String("add"), childCount, 0, childPath); + sendDBusSignal(parentPath, QLatin1String(ATSPI_DBUS_INTERFACE_EVENT_OBJECT), QLatin1String("ChildrenChanged"), args); + } +} + void AtSpiAdaptor::notifyAboutCreation(QAccessibleInterface *interface) const { // // say hello to d-bus diff --git a/src/platformsupport/linuxaccessibility/atspiadaptor_p.h b/src/platformsupport/linuxaccessibility/atspiadaptor_p.h index 244d3d7594..e1e2f2b149 100644 --- a/src/platformsupport/linuxaccessibility/atspiadaptor_p.h +++ b/src/platformsupport/linuxaccessibility/atspiadaptor_p.h @@ -91,6 +91,7 @@ private: void sendFocusChanged(QAccessibleInterface *interface) const; void notifyAboutCreation(QAccessibleInterface *interface) const; void notifyAboutDestruction(QAccessibleInterface *interface) const; + void childrenChanged(QAccessibleInterface *interface) const; // handlers for the different accessible interfaces bool applicationInterface(QAccessibleInterface *interface, const QString &function, const QDBusMessage &message, const QDBusConnection &connection); diff --git a/src/platformsupport/linuxaccessibility/bridge.cpp b/src/platformsupport/linuxaccessibility/bridge.cpp index 612fce501b..3a1e3e0ce0 100644 --- a/src/platformsupport/linuxaccessibility/bridge.cpp +++ b/src/platformsupport/linuxaccessibility/bridge.cpp @@ -244,6 +244,12 @@ static RoleMapping map[] = { //: Role of an accessible object { QAccessible::LayeredPane, ATSPI_ROLE_LAYERED_PANE, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "layered pane") }, //: Role of an accessible object + { QAccessible::WebDocument, ATSPI_ROLE_DOCUMENT_WEB, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "web document") }, + //: Role of an accessible object + { QAccessible::Paragraph, ATSPI_ROLE_PARAGRAPH, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "paragraph") }, + //: Role of an accessible object + { QAccessible::Section, ATSPI_ROLE_SECTION, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "section") }, + //: Role of an accessible object { QAccessible::UserRole, ATSPI_ROLE_UNKNOWN, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "unknown") } }; diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibility.mm b/src/plugins/platforms/cocoa/qcocoaaccessibility.mm index ca5044fad7..8f83b0fe30 100644 --- a/src/plugins/platforms/cocoa/qcocoaaccessibility.mm +++ b/src/plugins/platforms/cocoa/qcocoaaccessibility.mm @@ -149,6 +149,9 @@ static void populateRoleMap() roleMap[QAccessible::ListItem] = NSAccessibilityStaticTextRole; roleMap[QAccessible::Cell] = NSAccessibilityStaticTextRole; roleMap[QAccessible::Client] = NSAccessibilityGroupRole; + roleMap[QAccessible::Paragraph] = NSAccessibilityGroupRole; + roleMap[QAccessible::Section] = NSAccessibilityGroupRole; + roleMap[QAccessible::WebDocument] = NSAccessibilityGroupRole; } /* diff --git a/src/plugins/platforms/ios/qiosapplicationdelegate.h b/src/plugins/platforms/ios/qiosapplicationdelegate.h index 617b740d6e..f3c5c14502 100644 --- a/src/plugins/platforms/ios/qiosapplicationdelegate.h +++ b/src/plugins/platforms/ios/qiosapplicationdelegate.h @@ -45,7 +45,4 @@ #import "qiosviewcontroller.h" @interface QIOSApplicationDelegate : UIResponder <UIApplicationDelegate> - -@property (strong, nonatomic) UIWindow *window; - @end diff --git a/src/plugins/platforms/ios/qiosapplicationdelegate.mm b/src/plugins/platforms/ios/qiosapplicationdelegate.mm index b41b1e711f..ef9f924384 100644 --- a/src/plugins/platforms/ios/qiosapplicationdelegate.mm +++ b/src/plugins/platforms/ios/qiosapplicationdelegate.mm @@ -52,40 +52,6 @@ @implementation QIOSApplicationDelegate -@synthesize window; - -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions -{ - Q_UNUSED(application); - Q_UNUSED(launchOptions); - - self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease]; - self.window.rootViewController = [[[QIOSViewController alloc] init] autorelease]; - -#if QT_IOS_DEPLOYMENT_TARGET_BELOW(__IPHONE_7_0) - QSysInfo::MacVersion iosVersion = QSysInfo::MacintoshVersion; - - // We prefer to keep the root viewcontroller in fullscreen layout, so that - // we don't have to compensate for the viewcontroller position. This also - // gives us the same behavior on iOS 5/6 as on iOS 7, where full screen layout - // is the only way. - if (iosVersion < QSysInfo::MV_IOS_7_0) - self.window.rootViewController.wantsFullScreenLayout = YES; - - // Use translucent statusbar by default on iOS6 iPhones (unless the user changed - // the default in the Info.plist), so that windows placed under the stausbar are - // still visible, just like on iOS7. - if (iosVersion >= QSysInfo::MV_IOS_6_0 && iosVersion < QSysInfo::MV_IOS_7_0 - && [UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone - && [UIApplication sharedApplication].statusBarStyle == UIStatusBarStyleDefault) - [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleBlackTranslucent]; -#endif - - self.window.hidden = NO; - - return YES; -} - - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation { Q_UNUSED(application); @@ -103,11 +69,5 @@ return iosServices->handleUrl(QUrl::fromNSURL(url)); } -- (void)dealloc -{ - [window release]; - [super dealloc]; -} - @end diff --git a/src/plugins/platforms/ios/qiosintegration.mm b/src/plugins/platforms/ios/qiosintegration.mm index 5ed37c3525..9a722ead37 100644 --- a/src/plugins/platforms/ios/qiosintegration.mm +++ b/src/plugins/platforms/ios/qiosintegration.mm @@ -72,7 +72,7 @@ QIOSIntegration *QIOSIntegration::instance() QIOSIntegration::QIOSIntegration() : m_fontDatabase(new QCoreTextFontDatabase) , m_clipboard(new QIOSClipboard) - , m_inputContext(new QIOSInputContext) + , m_inputContext(0) , m_platformServices(new QIOSServices) , m_accessibility(0) { @@ -91,6 +91,9 @@ QIOSIntegration::QIOSIntegration() for (UIScreen *screen in [UIScreen screens]) addScreen(new QIOSScreen(screen)); + // Depends on a primary screen being present + m_inputContext = new QIOSInputContext; + m_touchDevice = new QTouchDevice; m_touchDevice->setType(QTouchDevice::TouchScreen); m_touchDevice->setCapabilities(QTouchDevice::Position | QTouchDevice::NormalizedPosition); diff --git a/src/plugins/platforms/ios/qiosscreen.h b/src/plugins/platforms/ios/qiosscreen.h index a6ef7a2593..9c7d53dcd6 100644 --- a/src/plugins/platforms/ios/qiosscreen.h +++ b/src/plugins/platforms/ios/qiosscreen.h @@ -80,6 +80,7 @@ public slots: private: UIScreen *m_uiScreen; + UIWindow *m_uiWindow; QRect m_geometry; QRect m_availableGeometry; int m_depth; diff --git a/src/plugins/platforms/ios/qiosscreen.mm b/src/plugins/platforms/ios/qiosscreen.mm index a53e42ce50..e876665431 100644 --- a/src/plugins/platforms/ios/qiosscreen.mm +++ b/src/plugins/platforms/ios/qiosscreen.mm @@ -181,8 +181,28 @@ static QString deviceModelIdentifier() QIOSScreen::QIOSScreen(UIScreen *screen) : QPlatformScreen() , m_uiScreen(screen) + , m_uiWindow(0) , m_orientationListener(0) { + for (UIWindow *existingWindow in [[UIApplication sharedApplication] windows]) { + if (existingWindow.screen == m_uiScreen) { + m_uiWindow = [m_uiWindow retain]; + break; + } + } + + if (!m_uiWindow) { + // Create a window and associated view-controller that we can use + m_uiWindow = [[UIWindow alloc] initWithFrame:[m_uiScreen bounds]]; + m_uiWindow.rootViewController = [[[QIOSViewController alloc] initWithQIOSScreen:this] autorelease]; + + // FIXME: Only do once windows are added to the screen, and for any screen + if (screen == [UIScreen mainScreen]) { + m_uiWindow.screen = m_uiScreen; + m_uiWindow.hidden = NO; + } + } + if (screen == [UIScreen mainScreen]) { QString deviceIdentifier = deviceModelIdentifier(); @@ -213,17 +233,12 @@ QIOSScreen::QIOSScreen(UIScreen *screen) QIOSScreen::~QIOSScreen() { [m_orientationListener release]; + [m_uiWindow release]; } void QIOSScreen::updateProperties() { - UIWindow *uiWindow = 0; - for (uiWindow in [[UIApplication sharedApplication] windows]) { - if (uiWindow.screen == m_uiScreen) - break; - } - - bool inPortrait = UIInterfaceOrientationIsPortrait(uiWindow.rootViewController.interfaceOrientation); + bool inPortrait = UIInterfaceOrientationIsPortrait(m_uiWindow.rootViewController.interfaceOrientation); QRect geometry = inPortrait ? fromCGRect(m_uiScreen.bounds).toRect() : QRect(m_uiScreen.bounds.origin.x, m_uiScreen.bounds.origin.y, m_uiScreen.bounds.size.height, m_uiScreen.bounds.size.width); diff --git a/src/plugins/platforms/ios/qiosviewcontroller.h b/src/plugins/platforms/ios/qiosviewcontroller.h index a0017808d3..5e95cdd3ee 100644 --- a/src/plugins/platforms/ios/qiosviewcontroller.h +++ b/src/plugins/platforms/ios/qiosviewcontroller.h @@ -41,7 +41,13 @@ #import <UIKit/UIKit.h> -@interface QIOSViewController : UIViewController +class QIOSScreen; + +@interface QIOSViewController : UIViewController { + QIOSScreen *m_screen; +} + +- (id)initWithQIOSScreen:(QIOSScreen *)screen; - (BOOL)prefersStatusBarHidden; @end diff --git a/src/plugins/platforms/ios/qiosviewcontroller.mm b/src/plugins/platforms/ios/qiosviewcontroller.mm index 2fe679fc20..73f1b51b83 100644 --- a/src/plugins/platforms/ios/qiosviewcontroller.mm +++ b/src/plugins/platforms/ios/qiosviewcontroller.mm @@ -53,6 +53,35 @@ @implementation QIOSViewController +- (id)initWithQIOSScreen:(QIOSScreen *)screen +{ + if (self = [self init]) { + m_screen = screen; + +#if QT_IOS_DEPLOYMENT_TARGET_BELOW(__IPHONE_7_0) + QSysInfo::MacVersion iosVersion = QSysInfo::MacintoshVersion; + + // We prefer to keep the root viewcontroller in fullscreen layout, so that + // we don't have to compensate for the viewcontroller position. This also + // gives us the same behavior on iOS 5/6 as on iOS 7, where full screen layout + // is the only way. + if (iosVersion < QSysInfo::MV_IOS_7_0) + self.wantsFullScreenLayout = YES; + + // Use translucent statusbar by default on iOS6 iPhones (unless the user changed + // the default in the Info.plist), so that windows placed under the stausbar are + // still visible, just like on iOS7. + if (screen->uiScreen() == [UIScreen mainScreen] + && iosVersion >= QSysInfo::MV_IOS_6_0 && iosVersion < QSysInfo::MV_IOS_7_0 + && [UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone + && [UIApplication sharedApplication].statusBarStyle == UIStatusBarStyleDefault) + [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleBlackTranslucent]; +#endif + } + + return self; +} + -(BOOL)shouldAutorotate { // Until a proper orientation and rotation API is in place, we always auto rotate. @@ -85,8 +114,7 @@ if (!QCoreApplication::instance()) return; // FIXME: Store orientation for later (?) - QIOSScreen *qiosScreen = static_cast<QIOSScreen *>(QGuiApplication::primaryScreen()->handle()); - qiosScreen->updateProperties(); + m_screen->updateProperties(); } #if QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_7_0) diff --git a/src/plugins/platforms/windows/accessible/iaccessible2.cpp b/src/plugins/platforms/windows/accessible/iaccessible2.cpp index 64a2891e49..20658f9cad 100644 --- a/src/plugins/platforms/windows/accessible/iaccessible2.cpp +++ b/src/plugins/platforms/windows/accessible/iaccessible2.cpp @@ -358,6 +358,8 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::role(long *ia2role) case QAccessible::LayeredPane: r = IA2_ROLE_LAYERED_PANE; break; case QAccessible::Terminal: r = IA2_ROLE_TERMINAL; break; case QAccessible::Desktop: r = IA2_ROLE_DESKTOP_PANE; break; + case QAccessible::Paragraph: r = IA2_ROLE_PARAGRAPH; break; + case QAccessible::Section: r = IA2_ROLE_SECTION; break; default: break; } diff --git a/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp index 70445f1e27..d606ecb6a5 100644 --- a/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp +++ b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp @@ -935,6 +935,8 @@ HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accRole(VARIANT varID, VAR // does not support IAccessible2, since it should prefer IA2::role() then. if (role == QAccessible::LayeredPane) role = QAccessible::Pane; + else if (role == QAccessible::WebDocument) + role = QAccessible::Document; else role = QAccessible::Client; } diff --git a/src/sql/kernel/qsqlquery.cpp b/src/sql/kernel/qsqlquery.cpp index 6b13eb02ed..2b1bd5feb1 100644 --- a/src/sql/kernel/qsqlquery.cpp +++ b/src/sql/kernel/qsqlquery.cpp @@ -43,6 +43,8 @@ //#define QT_DEBUG_SQL +#include "qdebug.h" +#include "qelapsedtimer.h" #include "qatomic.h" #include "qsqlrecord.h" #include "qsqlresult.h" @@ -370,6 +372,10 @@ bool QSqlQuery::isNull(const QString &name) const bool QSqlQuery::exec(const QString& query) { +#ifdef QT_DEBUG_SQL + QElapsedTimer t; + t.start(); +#endif if (d->ref.load() != 1) { bool fo = isForwardOnly(); *this = QSqlQuery(driver()->createResult()); @@ -391,10 +397,14 @@ bool QSqlQuery::exec(const QString& query) qWarning("QSqlQuery::exec: empty query"); return false; } + + bool retval = d->sqlResult->reset(query); #ifdef QT_DEBUG_SQL - qDebug("\n QSqlQuery: %s", query.toLocal8Bit().constData()); + qDebug().nospace() << "Executed query (" << t.elapsed() << "ms, " << d->sqlResult->size() + << " results, " << d->sqlResult->numRowsAffected() + << " affected): " << d->sqlResult->lastQuery(); #endif - return d->sqlResult->reset(query); + return retval; } /*! @@ -989,12 +999,22 @@ bool QSqlQuery::prepare(const QString& query) */ bool QSqlQuery::exec() { +#ifdef QT_DEBUG_SQL + QElapsedTimer t; + t.start(); +#endif d->sqlResult->resetBindCount(); if (d->sqlResult->lastError().isValid()) d->sqlResult->setLastError(QSqlError()); - return d->sqlResult->exec(); + bool retval = d->sqlResult->exec(); +#ifdef QT_DEBUG_SQL + qDebug().nospace() << "Executed prepared query (" << t.elapsed() << "ms, " + << d->sqlResult->size() << " results, " << d->sqlResult->numRowsAffected() + << " affected): " << d->sqlResult->lastQuery(); +#endif + return retval; } /*! \enum QSqlQuery::BatchExecutionMode diff --git a/src/testlib/qtestaccessible.h b/src/testlib/qtestaccessible.h index ef6f61bd82..65fbd4c818 100644 --- a/src/testlib/qtestaccessible.h +++ b/src/testlib/qtestaccessible.h @@ -194,42 +194,75 @@ private: { QAccessibleEvent *ev; if (event->type() == QAccessible::StateChanged) { - ev = new QAccessibleStateChangeEvent(event->object(), + if (event->object()) + ev = new QAccessibleStateChangeEvent(event->object(), + static_cast<QAccessibleStateChangeEvent*>(event)->changedStates()); + else + ev = new QAccessibleStateChangeEvent(event->accessibleInterface(), static_cast<QAccessibleStateChangeEvent*>(event)->changedStates()); } else if (event->type() == QAccessible::TextCaretMoved) { - ev = new QAccessibleTextCursorEvent(event->object(), static_cast<QAccessibleTextCursorEvent*>(event)->cursorPosition()); + if (event->object()) + ev = new QAccessibleTextCursorEvent(event->object(), static_cast<QAccessibleTextCursorEvent*>(event)->cursorPosition()); + else + ev = new QAccessibleTextCursorEvent(event->accessibleInterface(), static_cast<QAccessibleTextCursorEvent*>(event)->cursorPosition()); } else if (event->type() == QAccessible::TextSelectionChanged) { const QAccessibleTextSelectionEvent *original = static_cast<QAccessibleTextSelectionEvent*>(event); - QAccessibleTextSelectionEvent *sel = new QAccessibleTextSelectionEvent(event->object(), original->selectionStart(), original->selectionEnd()); + QAccessibleTextSelectionEvent *sel; + if (event->object()) + sel = new QAccessibleTextSelectionEvent(event->object(), original->selectionStart(), original->selectionEnd()); + else + sel = new QAccessibleTextSelectionEvent(event->accessibleInterface(), original->selectionStart(), original->selectionEnd()); sel->setCursorPosition(original->cursorPosition()); ev = sel; } else if (event->type() == QAccessible::TextInserted) { const QAccessibleTextInsertEvent *original = static_cast<QAccessibleTextInsertEvent*>(event); - QAccessibleTextInsertEvent *ins = new QAccessibleTextInsertEvent(event->object(), original->changePosition(), original->textInserted()); + QAccessibleTextInsertEvent *ins; + if (original->object()) + ins = new QAccessibleTextInsertEvent(event->object(), original->changePosition(), original->textInserted()); + else + ins = new QAccessibleTextInsertEvent(event->accessibleInterface(), original->changePosition(), original->textInserted()); ins->setCursorPosition(original->cursorPosition()); ev = ins; } else if (event->type() == QAccessible::TextRemoved) { const QAccessibleTextRemoveEvent *original = static_cast<QAccessibleTextRemoveEvent*>(event); - QAccessibleTextRemoveEvent *rem = new QAccessibleTextRemoveEvent(event->object(), original->changePosition(), original->textRemoved()); + QAccessibleTextRemoveEvent *rem; + if (event->object()) + rem = new QAccessibleTextRemoveEvent(event->object(), original->changePosition(), original->textRemoved()); + else + rem = new QAccessibleTextRemoveEvent(event->accessibleInterface(), original->changePosition(), original->textRemoved()); rem->setCursorPosition(original->cursorPosition()); ev = rem; } else if (event->type() == QAccessible::TextUpdated) { const QAccessibleTextUpdateEvent *original = static_cast<QAccessibleTextUpdateEvent*>(event); - QAccessibleTextUpdateEvent *upd = new QAccessibleTextUpdateEvent(event->object(), original->changePosition(), original->textRemoved(), original->textInserted()); + QAccessibleTextUpdateEvent *upd; + if (event->object()) + upd = new QAccessibleTextUpdateEvent(event->object(), original->changePosition(), original->textRemoved(), original->textInserted()); + else + upd = new QAccessibleTextUpdateEvent(event->accessibleInterface(), original->changePosition(), original->textRemoved(), original->textInserted()); upd->setCursorPosition(original->cursorPosition()); ev = upd; } else if (event->type() == QAccessible::ValueChanged) { - ev = new QAccessibleValueChangeEvent(event->object(), static_cast<QAccessibleValueChangeEvent*>(event)->value()); + if (event->object()) + ev = new QAccessibleValueChangeEvent(event->object(), static_cast<QAccessibleValueChangeEvent*>(event)->value()); + else + ev = new QAccessibleValueChangeEvent(event->accessibleInterface(), static_cast<QAccessibleValueChangeEvent*>(event)->value()); } else if (event->type() == QAccessible::TableModelChanged) { QAccessibleTableModelChangeEvent *oldEvent = static_cast<QAccessibleTableModelChangeEvent*>(event); - QAccessibleTableModelChangeEvent *newEvent = new QAccessibleTableModelChangeEvent(event->object(), oldEvent->modelChangeType()); + QAccessibleTableModelChangeEvent *newEvent; + if (event->object()) + newEvent = new QAccessibleTableModelChangeEvent(event->object(), oldEvent->modelChangeType()); + else + newEvent = new QAccessibleTableModelChangeEvent(event->accessibleInterface(), oldEvent->modelChangeType()); newEvent->setFirstRow(oldEvent->firstRow()); newEvent->setFirstColumn(oldEvent->firstColumn()); newEvent->setLastRow(oldEvent->lastRow()); newEvent->setLastColumn(oldEvent->lastColumn()); ev = newEvent; } else { - ev = new QAccessibleEvent(event->object(), event->type()); + if (event->object()) + ev = new QAccessibleEvent(event->object(), event->type()); + else + ev = new QAccessibleEvent(event->accessibleInterface(), event->type()); } ev->setChild(event->child()); return ev; diff --git a/src/tools/qdoc/htmlgenerator.cpp b/src/tools/qdoc/htmlgenerator.cpp index 7a19e3c027..3a4ef31a2a 100644 --- a/src/tools/qdoc/htmlgenerator.cpp +++ b/src/tools/qdoc/htmlgenerator.cpp @@ -1406,6 +1406,8 @@ void HtmlGenerator::generateQmlBasicTypePage(QmlBasicTypeNode* qbtn, CodeMarker* marker = CodeMarker::markerForLanguage(QLatin1String("QML")); generateHeader(htmlTitle, qbtn, marker); + QList<Section> sections = marker->sections(qbtn, CodeMarker::Summary, CodeMarker::Okay); + generateTableOfContents(qbtn,marker,§ions); generateTitle(htmlTitle, Text() << qbtn->subTitle(), subTitleSize, @@ -3920,6 +3922,7 @@ int HtmlGenerator::hOffset(const Node *node) case Node::Namespace: case Node::Class: return 2; + case Node::QmlBasicType: case Node::QmlType: case Node::Document: return 1; diff --git a/src/tools/rcc/main.cpp b/src/tools/rcc/main.cpp index 0dcbcafb11..81beff8363 100644 --- a/src/tools/rcc/main.cpp +++ b/src/tools/rcc/main.cpp @@ -112,13 +112,13 @@ int createProject(const QString &outFileName) int runRcc(int argc, char *argv[]) { QCoreApplication app(argc, argv); - QCoreApplication::setApplicationVersion(QString::fromLatin1(QT_VERSION_STR)); + QCoreApplication::setApplicationVersion(QStringLiteral(QT_VERSION_STR)); // Note that rcc isn't translated. // If you use this code as an example for a translated app, make sure to translate the strings. QCommandLineParser parser; parser.setSingleDashWordOptionMode(QCommandLineParser::ParseAsLongOptions); - parser.setApplicationDescription(QStringLiteral("Qt Resource Compiler version %1").arg(QString::fromLatin1(QT_VERSION_STR))); + parser.setApplicationDescription(QLatin1String("Qt Resource Compiler version " QT_VERSION_STR)); parser.addHelpOption(); parser.addVersionOption(); @@ -266,7 +266,7 @@ int runRcc(int argc, char *argv[]) } else { out.setFileName(outFilename); if (!out.open(mode)) { - const QString msg = QString::fromUtf8("Unable to open %1 for writing: %2\n").arg(outFilename).arg(out.errorString()); + const QString msg = QString::fromLatin1("Unable to open %1 for writing: %2\n").arg(outFilename).arg(out.errorString()); errorDevice.write(msg.toUtf8()); return 1; } diff --git a/src/tools/rcc/rcc.cpp b/src/tools/rcc/rcc.cpp index 3896f6c0e3..813ca518b7 100644 --- a/src/tools/rcc/rcc.cpp +++ b/src/tools/rcc/rcc.cpp @@ -86,7 +86,7 @@ void RCCResourceLibrary::writeByteArray(const QByteArray &other) static inline QString msgOpenReadFailed(const QString &fname, const QString &why) { - return QString::fromUtf8("Unable to open %1 for reading: %2\n").arg(fname).arg(why); + return QString::fromLatin1("Unable to open %1 for reading: %2\n").arg(fname).arg(why); } @@ -576,7 +576,7 @@ bool RCCResourceLibrary::interpretResourceFile(QIODevice *inputDevice, } if (m_root == 0) { - const QString msg = QString::fromUtf8("RCC: Warning: No resources in '%1'.\n").arg(fname); + const QString msg = QString::fromLatin1("RCC: Warning: No resources in '%1'.\n").arg(fname); m_errorDevice->write(msg.toUtf8()); if (!ignoreErrors && m_format == Binary) { // create dummy entry, otherwise loading with QResource will crash @@ -592,7 +592,7 @@ bool RCCResourceLibrary::addFile(const QString &alias, const RCCFileInfo &file) { Q_ASSERT(m_errorDevice); if (file.m_fileInfo.size() > 0xffffffff) { - const QString msg = QString::fromUtf8("File too big: %1\n").arg(file.m_fileInfo.absoluteFilePath()); + const QString msg = QString::fromLatin1("File too big: %1\n").arg(file.m_fileInfo.absoluteFilePath()); m_errorDevice->write(msg.toUtf8()); return false; } @@ -644,7 +644,7 @@ bool RCCResourceLibrary::readFiles(bool ignoreErrors, QIODevice &errorDevice) m_errorDevice = &errorDevice; //read in data if (m_verbose) { - const QString msg = QString::fromUtf8("Processing %1 files [%2]\n") + const QString msg = QString::fromLatin1("Processing %1 files [%2]\n") .arg(m_fileNames.size()).arg(static_cast<int>(ignoreErrors)); m_errorDevice->write(msg.toUtf8()); } @@ -669,7 +669,7 @@ bool RCCResourceLibrary::readFiles(bool ignoreErrors, QIODevice &errorDevice) } } if (m_verbose) { - const QString msg = QString::fromUtf8("Interpreting %1\n").arg(fname); + const QString msg = QString::fromLatin1("Interpreting %1\n").arg(fname); m_errorDevice->write(msg.toUtf8()); } diff --git a/src/widgets/dialogs/qfiledialog.cpp b/src/widgets/dialogs/qfiledialog.cpp index e3e4a58333..257f8b25e3 100644 --- a/src/widgets/dialogs/qfiledialog.cpp +++ b/src/widgets/dialogs/qfiledialog.cpp @@ -581,8 +581,8 @@ QFileDialogPrivate::~QFileDialogPrivate() void QFileDialogPrivate::initHelper(QPlatformDialogHelper *h) { QFileDialog *d = q_func(); - 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(fileSelected(QUrl)), d, SLOT(_q_emitUrlSelected(QUrl))); + QObject::connect(h, SIGNAL(filesSelected(QList<QUrl>)), d, SLOT(_q_emitUrlsSelected(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))); @@ -2560,15 +2560,20 @@ void QFileDialog::done(int result) void QFileDialog::accept() { Q_D(QFileDialog); - QStringList files = selectedFiles(); - if (files.isEmpty()) - return; if (!d->usingWidgets()) { - d->emitFilesSelected(files); + const QList<QUrl> urls = selectedUrls(); + if (urls.isEmpty()) + return; + d->_q_emitUrlsSelected(urls); + if (urls.count() == 1) + d->_q_emitUrlSelected(urls.first()); QDialog::accept(); return; } + QStringList files = selectedFiles(); + if (files.isEmpty()) + return; QString lineEditText = d->lineEdit()->text(); // "hidden feature" type .. and then enter, and it will move up a dir // special case for ".." @@ -3599,7 +3604,7 @@ void QFileDialogPrivate::_q_fileRenamed(const QString &path, const QString oldNa } } -void QFileDialogPrivate::_q_nativeFileSelected(const QUrl &file) +void QFileDialogPrivate::_q_emitUrlSelected(const QUrl &file) { Q_Q(QFileDialog); emit q->urlSelected(file); @@ -3607,7 +3612,7 @@ void QFileDialogPrivate::_q_nativeFileSelected(const QUrl &file) emit q->fileSelected(file.toLocalFile()); } -void QFileDialogPrivate::_q_nativeFilesSelected(const QList<QUrl> &files) +void QFileDialogPrivate::_q_emitUrlsSelected(const QList<QUrl> &files) { Q_Q(QFileDialog); emit q->urlsSelected(files); diff --git a/src/widgets/dialogs/qfiledialog.h b/src/widgets/dialogs/qfiledialog.h index 404e16cde1..184e07261a 100644 --- a/src/widgets/dialogs/qfiledialog.h +++ b/src/widgets/dialogs/qfiledialog.h @@ -287,8 +287,8 @@ 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_nativeFileSelected(const QUrl &)) - Q_PRIVATE_SLOT(d_func(), void _q_nativeFilesSelected(const QList<QUrl> &)) + Q_PRIVATE_SLOT(d_func(), void _q_emitUrlSelected(const QUrl &)) + Q_PRIVATE_SLOT(d_func(), void _q_emitUrlsSelected(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)) diff --git a/src/widgets/dialogs/qfiledialog_p.h b/src/widgets/dialogs/qfiledialog_p.h index c20dd36953..24969b1179 100644 --- a/src/widgets/dialogs/qfiledialog_p.h +++ b/src/widgets/dialogs/qfiledialog_p.h @@ -210,8 +210,8 @@ public: void _q_updateOkButton(); void _q_currentChanged(const QModelIndex &index); void _q_enterDirectory(const QModelIndex &index); - void _q_nativeFileSelected(const QUrl &file); - void _q_nativeFilesSelected(const QList<QUrl> &files); + void _q_emitUrlSelected(const QUrl &file); + void _q_emitUrlsSelected(const QList<QUrl> &files); void _q_nativeCurrentChanged(const QUrl &file); void _q_nativeEnterDirectory(const QUrl &directory); void _q_goToDirectory(const QString &); diff --git a/src/widgets/dialogs/qinputdialog.cpp b/src/widgets/dialogs/qinputdialog.cpp index 10d693b4a3..99344b3dd8 100644 --- a/src/widgets/dialogs/qinputdialog.cpp +++ b/src/widgets/dialogs/qinputdialog.cpp @@ -60,25 +60,37 @@ QT_USE_NAMESPACE -static const char *signalForMember(const char *member) +enum CandidateSignal { + TextValueSelectedSignal, + IntValueSelectedSignal, + DoubleValueSelectedSignal, + + NumCandidateSignals +}; + +static const char *candidateSignal(int which) { - static const int NumCandidates = 4; - static const char * const candidateSignals[NumCandidates] = { - SIGNAL(textValueSelected(QString)), - SIGNAL(intValueSelected(int)), - SIGNAL(doubleValueSelected(double)), - SIGNAL(accepted()) + switch (CandidateSignal(which)) { + case TextValueSelectedSignal: return SIGNAL(textValueSelected(QString)); + case IntValueSelectedSignal: return SIGNAL(intValueSelected(int)); + case DoubleValueSelectedSignal: return SIGNAL(doubleValueSelected(double)); + + case NumCandidateSignals: ; // fall through }; + Q_UNREACHABLE(); + return Q_NULLPTR; +} +static const char *signalForMember(const char *member) +{ QByteArray normalizedMember(QMetaObject::normalizedSignature(member)); - int i = 0; - while (i < NumCandidates - 1) { // sic - if (QMetaObject::checkConnectArgs(candidateSignals[i], normalizedMember)) - break; - ++i; - } - return candidateSignals[i]; + for (int i = 0; i < NumCandidateSignals; ++i) + if (QMetaObject::checkConnectArgs(candidateSignal(i), normalizedMember)) + return candidateSignal(i); + + // otherwise, use fit-all accepted signal: + return SIGNAL(accepted()); } QT_BEGIN_NAMESPACE diff --git a/src/widgets/widgets/qdockarealayout.cpp b/src/widgets/widgets/qdockarealayout.cpp index 066b3c7a86..5a40ceb2f7 100644 --- a/src/widgets/widgets/qdockarealayout.cpp +++ b/src/widgets/widgets/qdockarealayout.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 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. @@ -44,6 +44,7 @@ #include "QtWidgets/qtabbar.h" #include "QtWidgets/qstyle.h" #include "QtWidgets/qdesktopwidget.h" +#include "QtWidgets/qapplication.h" #include "QtCore/qvariant.h" #include "qdockarealayout_p.h" #include "qdockwidget.h" @@ -2978,8 +2979,9 @@ bool QDockAreaLayout::restoreDockWidget(QDockWidget *dockWidget) item.widgetItem = new QDockWidgetItem(dockWidget); if (placeHolder->window) { - QDesktopWidget desktop; - QRect r = constrainedRect(placeHolder->topLevelRect, desktop.screenGeometry(dockWidget)); + const QRect screenGeometry = + QApplication::desktop()->screenGeometry(placeHolder->topLevelRect.center()); + const QRect r = constrainedRect(placeHolder->topLevelRect, screenGeometry); dockWidget->d_func()->setWindowState(true, true, r); } dockWidget->setVisible(!placeHolder->hidden); diff --git a/tests/auto/corelib/io/qdebug/tst_qdebug.cpp b/tests/auto/corelib/io/qdebug/tst_qdebug.cpp index 2143a8874c..767fde7f6c 100644 --- a/tests/auto/corelib/io/qdebug/tst_qdebug.cpp +++ b/tests/auto/corelib/io/qdebug/tst_qdebug.cpp @@ -254,6 +254,17 @@ void tst_QDebug::stateSaver() const MessageHandlerSetter mhs(myMessageHandler); { QDebug d = qDebug(); + d << 42; + { + QDebugStateSaver saver(d); + d << 43; + } + d << 44; + } + QCOMPARE(s_msg, QString::fromLatin1("42 43 44")); + + { + QDebug d = qDebug(); { QDebugStateSaver saver(d); d.nospace() << hex << right << qSetFieldWidth(3) << qSetPadChar('0') << 42; @@ -271,6 +282,18 @@ void tst_QDebug::stateSaver() const d << QStringLiteral("World"); } QCOMPARE(s_msg, QString::fromLatin1("Hello \"World\"")); + + { + QDebug d = qDebug(); + d.noquote().nospace() << QStringLiteral("Hello") << hex << 42; + { + QDebugStateSaver saver(d); + d.resetFormat(); + d << QStringLiteral("World") << 42; + } + d << QStringLiteral("!") << 42; + } + QCOMPARE(s_msg, QString::fromLatin1("Hello2a\"World\" 42!2a")); } void tst_QDebug::veryLongWarningMessage() const diff --git a/tests/auto/corelib/io/qfile/tst_qfile.cpp b/tests/auto/corelib/io/qfile/tst_qfile.cpp index 60d1517ed3..9ce931d78a 100644 --- a/tests/auto/corelib/io/qfile/tst_qfile.cpp +++ b/tests/auto/corelib/io/qfile/tst_qfile.cpp @@ -3028,17 +3028,21 @@ void tst_QFile::mapResource() void tst_QFile::mapOpenMode_data() { QTest::addColumn<int>("openMode"); + QTest::addColumn<int>("flags"); - QTest::newRow("ReadOnly") << int(QIODevice::ReadOnly); + QTest::newRow("ReadOnly") << int(QIODevice::ReadOnly) << int(QFileDevice::NoOptions); //QTest::newRow("WriteOnly") << int(QIODevice::WriteOnly); // this doesn't make sense - QTest::newRow("ReadWrite") << int(QIODevice::ReadWrite); - QTest::newRow("ReadOnly,Unbuffered") << int(QIODevice::ReadOnly | QIODevice::Unbuffered); - QTest::newRow("ReadWrite,Unbuffered") << int(QIODevice::ReadWrite | QIODevice::Unbuffered); + QTest::newRow("ReadWrite") << int(QIODevice::ReadWrite) << int(QFileDevice::NoOptions); + QTest::newRow("ReadOnly,Unbuffered") << int(QIODevice::ReadOnly | QIODevice::Unbuffered) << int(QFileDevice::NoOptions); + QTest::newRow("ReadWrite,Unbuffered") << int(QIODevice::ReadWrite | QIODevice::Unbuffered) << int(QFileDevice::NoOptions); + QTest::newRow("ReadOnly + MapPrivate") << int(QIODevice::ReadOnly) << int(QFileDevice::MapPrivateOption); + QTest::newRow("ReadWrite + MapPrivate") << int(QIODevice::ReadWrite) << int(QFileDevice::MapPrivateOption); } void tst_QFile::mapOpenMode() { QFETCH(int, openMode); + QFETCH(int, flags); static const qint64 fileSize = 4096; QByteArray pattern(fileSize, 'A'); @@ -3060,11 +3064,15 @@ void tst_QFile::mapOpenMode() // open according to our mode QVERIFY(file.open(QIODevice::OpenMode(openMode))); - uchar *memory = file.map(0, fileSize); + uchar *memory = file.map(0, fileSize, QFileDevice::MemoryMapFlags(flags)); +#if defined(Q_OS_WINCE) + QEXPECT_FAIL("ReadOnly + MapPrivate" , "Windows CE does not support MapPrivateOption.", Abort); + QEXPECT_FAIL("ReadWrite + MapPrivate", "Windows CE does not support MapPrivateOption.", Abort); +#endif QVERIFY(memory); QVERIFY(memcmp(memory, pattern, fileSize) == 0); - if (openMode & QIODevice::WriteOnly) { + if ((openMode & QIODevice::WriteOnly) || (flags & QFileDevice::MapPrivateOption)) { // try to write to the file *memory = 'a'; file.unmap(memory); @@ -3073,7 +3081,7 @@ void tst_QFile::mapOpenMode() file.seek(0); char c; QVERIFY(file.getChar(&c)); - QCOMPARE(c, 'a'); + QCOMPARE(c, (flags & QFileDevice::MapPrivateOption) ? 'A' : 'a'); } file.close(); diff --git a/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp b/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp index 8174cd942f..37cb296ebb 100644 --- a/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp +++ b/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp @@ -78,9 +78,79 @@ #define Q_NO_SYMLINKS #endif -QT_BEGIN_NAMESPACE -extern Q_AUTOTEST_EXPORT bool qIsLikelyToBeNfs(int /* handle */); -QT_END_NAMESPACE + +#if defined(Q_OS_UNIX) && !defined(Q_OS_VXWORKS) +inline bool qt_isEvilFsTypeName(const char *name) +{ + return (qstrncmp(name, "nfs", 3) == 0 + || qstrncmp(name, "autofs", 6) == 0 + || qstrncmp(name, "cachefs", 7) == 0); +} + +#if defined(Q_OS_BSD4) && !defined(Q_OS_NETBSD) +# include <sys/param.h> +# include <sys/mount.h> + +bool qIsLikelyToBeNfs(int handle) +{ + struct statfs buf; + if (fstatfs(handle, &buf) != 0) + return false; + return qt_isEvilFsTypeName(buf.f_fstypename); +} + +#elif defined(Q_OS_LINUX) || defined(Q_OS_HURD) + +# include <sys/vfs.h> +# ifdef QT_LINUXBASE + // LSB 3.2 has fstatfs in sys/statfs.h, sys/vfs.h is just an empty dummy header +# include <sys/statfs.h> +# endif + +# ifndef NFS_SUPER_MAGIC +# define NFS_SUPER_MAGIC 0x00006969 +# endif +# ifndef AUTOFS_SUPER_MAGIC +# define AUTOFS_SUPER_MAGIC 0x00000187 +# endif +# ifndef AUTOFSNG_SUPER_MAGIC +# define AUTOFSNG_SUPER_MAGIC 0x7d92b1a0 +# endif + +bool qIsLikelyToBeNfs(int handle) +{ + struct statfs buf; + if (fstatfs(handle, &buf) != 0) + return false; + return buf.f_type == NFS_SUPER_MAGIC + || buf.f_type == AUTOFS_SUPER_MAGIC + || buf.f_type == AUTOFSNG_SUPER_MAGIC; +} + +#elif defined(Q_OS_SOLARIS) || defined(Q_OS_IRIX) || defined(Q_OS_AIX) || defined(Q_OS_HPUX) \ + || defined(Q_OS_OSF) || defined(Q_OS_QNX) || defined(Q_OS_SCO) \ + || defined(Q_OS_UNIXWARE) || defined(Q_OS_RELIANT) || defined(Q_OS_NETBSD) + +# include <sys/statvfs.h> + +bool qIsLikelyToBeNfs(int handle) +{ + struct statvfs buf; + if (fstatvfs(handle, &buf) != 0) + return false; +#if defined(Q_OS_NETBSD) + return qt_isEvilFsTypeName(buf.f_fstypename); +#else + return qt_isEvilFsTypeName(buf.f_basetype); +#endif +} +#else +inline bool qIsLikelyToBeNfs(int /* handle */) +{ + return false; +} +#endif +#endif class tst_QFileInfo : public QObject { diff --git a/tests/auto/corelib/io/qloggingcategory/tst_qloggingcategory.cpp b/tests/auto/corelib/io/qloggingcategory/tst_qloggingcategory.cpp index b0d7a76f0f..6d49238e51 100644 --- a/tests/auto/corelib/io/qloggingcategory/tst_qloggingcategory.cpp +++ b/tests/auto/corelib/io/qloggingcategory/tst_qloggingcategory.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 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. @@ -44,7 +44,6 @@ #include <QLoggingCategory> Q_LOGGING_CATEGORY(TST_LOG, "tst.log") -Q_LOGGING_CATEGORY(TST_LOG1, "tst.log1") Q_LOGGING_CATEGORY(Digia_Oslo_Office_com, "Digia.Oslo.Office.com") Q_LOGGING_CATEGORY(Digia_Oulu_Office_com, "Digia.Oulu.Office.com") Q_LOGGING_CATEGORY(Digia_Berlin_Office_com, "Digia.Berlin.Office.com") @@ -278,6 +277,14 @@ private slots: QCOMPARE(customCategory.isCriticalEnabled(), true); QCOMPARE(customCategory.isEnabled(QtCriticalMsg), true); + QLoggingCategory onlyWarningsCategory("withType", QtWarningMsg); + QCOMPARE(onlyWarningsCategory.isDebugEnabled(), false); + QCOMPARE(onlyWarningsCategory.isEnabled(QtDebugMsg), false); + QCOMPARE(onlyWarningsCategory.isWarningEnabled(), true); + QCOMPARE(onlyWarningsCategory.isEnabled(QtWarningMsg), true); + QCOMPARE(onlyWarningsCategory.isCriticalEnabled(), true); + QCOMPARE(onlyWarningsCategory.isEnabled(QtCriticalMsg), true); + // make sure nothing has printed warnings QVERIFY(logMessage.isEmpty()); } @@ -367,6 +374,35 @@ private slots: QCOMPARE(logMessage, buf); } + Q_LOGGING_CATEGORY(TST_MACRO_1, "tst.macro.1") +#ifdef Q_COMPILER_VARIADIC_MACROS + Q_LOGGING_CATEGORY(TST_MACRO_2, "tst.macro.2", QtDebugMsg) + Q_LOGGING_CATEGORY(TST_MACRO_3, "tst.macro.3", QtFatalMsg) +#endif + + void QLoggingCategoryMacro() + { + const QLoggingCategory &cat1 = TST_MACRO_1(); + QCOMPARE(cat1.categoryName(), "tst.macro.1"); + QCOMPARE(cat1.isDebugEnabled(), true); + QCOMPARE(cat1.isWarningEnabled(), true); + QCOMPARE(cat1.isCriticalEnabled(), true); + +#ifdef Q_COMPILER_VARIADIC_MACROS + const QLoggingCategory &cat2 = TST_MACRO_2(); + QCOMPARE(cat2.categoryName(), "tst.macro.2"); + QCOMPARE(cat2.isDebugEnabled(), true); + QCOMPARE(cat2.isWarningEnabled(), true); + QCOMPARE(cat2.isCriticalEnabled(), true); + + const QLoggingCategory &cat3 = TST_MACRO_3(); + QCOMPARE(cat3.categoryName(), "tst.macro.3"); + QCOMPARE(cat3.isDebugEnabled(), false); + QCOMPARE(cat3.isWarningEnabled(), false); + QCOMPARE(cat3.isCriticalEnabled(), false); +#endif + } + void qCDebugMacros() { QString buf; diff --git a/tests/auto/corelib/io/qtextstream/tst_qtextstream.cpp b/tests/auto/corelib/io/qtextstream/tst_qtextstream.cpp index 15fd235048..f402421165 100644 --- a/tests/auto/corelib/io/qtextstream/tst_qtextstream.cpp +++ b/tests/auto/corelib/io/qtextstream/tst_qtextstream.cpp @@ -2147,14 +2147,36 @@ void tst_QTextStream::byteArray_read_operator_FromDevice() { \ QFETCH(qulonglong, number); \ QFETCH(QByteArray, data); \ + QFETCH(QByteArray, dataWithSeparators); \ \ QBuffer buffer; \ buffer.open(QBuffer::WriteOnly); \ QTextStream stream(&buffer); \ + stream.setLocale(QLocale::c()); \ stream << (type)number; \ stream.flush(); \ + QCOMPARE(buffer.data().constData(), data.constData()); \ \ + QLocale locale("en-US"); \ + buffer.reset(); buffer.buffer().clear(); \ + stream.setLocale(locale); \ + stream << (type)number; \ + stream.flush(); \ + QCOMPARE(buffer.data(), dataWithSeparators); \ + \ + locale.setNumberOptions(QLocale::OmitGroupSeparator); \ + buffer.reset(); buffer.buffer().clear(); \ + stream.setLocale(locale); \ + stream << (type)number; \ + stream.flush(); \ QCOMPARE(buffer.data().constData(), data.constData()); \ + \ + locale = QLocale("de-DE"); \ + buffer.reset(); buffer.buffer().clear(); \ + stream.setLocale(locale); \ + stream << (type)number; \ + stream.flush(); \ + QCOMPARE(buffer.data(), dataWithSeparators.replace(',', '.')); \ } // ------------------------------------------------------------------------------ @@ -2162,16 +2184,17 @@ void tst_QTextStream::signedShort_write_operator_ToDevice_data() { QTest::addColumn<qulonglong>("number"); QTest::addColumn<QByteArray>("data"); + QTest::addColumn<QByteArray>("dataWithSeparators"); - QTest::newRow("0") << Q_UINT64_C(0) << QByteArray("0"); - QTest::newRow("1") << Q_UINT64_C(1) << QByteArray("1"); - QTest::newRow("-1") << Q_UINT64_C(-1) << QByteArray("-1"); - QTest::newRow("32767") << Q_UINT64_C(32767) << QByteArray("32767"); - QTest::newRow("32768") << Q_UINT64_C(32768) << QByteArray("-32768"); - QTest::newRow("32769") << Q_UINT64_C(32769) << QByteArray("-32767"); - QTest::newRow("65535") << Q_UINT64_C(65535) << QByteArray("-1"); - QTest::newRow("65536") << Q_UINT64_C(65536) << QByteArray("0"); - QTest::newRow("65537") << Q_UINT64_C(65537) << QByteArray("1"); + QTest::newRow("0") << Q_UINT64_C(0) << QByteArray("0") << QByteArray("0"); + QTest::newRow("1") << Q_UINT64_C(1) << QByteArray("1") << QByteArray("1"); + QTest::newRow("-1") << Q_UINT64_C(-1) << QByteArray("-1") << QByteArray("-1"); + QTest::newRow("32767") << Q_UINT64_C(32767) << QByteArray("32767") << QByteArray("32,767"); + QTest::newRow("32768") << Q_UINT64_C(32768) << QByteArray("-32768") << QByteArray("-32,768"); + QTest::newRow("32769") << Q_UINT64_C(32769) << QByteArray("-32767") << QByteArray("-32,767"); + QTest::newRow("65535") << Q_UINT64_C(65535) << QByteArray("-1") << QByteArray("-1"); + QTest::newRow("65536") << Q_UINT64_C(65536) << QByteArray("0") << QByteArray("0"); + QTest::newRow("65537") << Q_UINT64_C(65537) << QByteArray("1") << QByteArray("1"); } IMPLEMENT_STREAM_LEFT_INT_OPERATOR_TEST(signedShort, signed short) ; @@ -2181,16 +2204,17 @@ void tst_QTextStream::unsignedShort_write_operator_ToDevice_data() { QTest::addColumn<qulonglong>("number"); QTest::addColumn<QByteArray>("data"); + QTest::addColumn<QByteArray>("dataWithSeparators"); - QTest::newRow("0") << Q_UINT64_C(0) << QByteArray("0"); - QTest::newRow("1") << Q_UINT64_C(1) << QByteArray("1"); - QTest::newRow("-1") << Q_UINT64_C(-1) << QByteArray("65535"); - QTest::newRow("32767") << Q_UINT64_C(32767) << QByteArray("32767"); - QTest::newRow("32768") << Q_UINT64_C(32768) << QByteArray("32768"); - QTest::newRow("32769") << Q_UINT64_C(32769) << QByteArray("32769"); - QTest::newRow("65535") << Q_UINT64_C(65535) << QByteArray("65535"); - QTest::newRow("65536") << Q_UINT64_C(65536) << QByteArray("0"); - QTest::newRow("65537") << Q_UINT64_C(65537) << QByteArray("1"); + QTest::newRow("0") << Q_UINT64_C(0) << QByteArray("0") << QByteArray("0"); + QTest::newRow("1") << Q_UINT64_C(1) << QByteArray("1") << QByteArray("1"); + QTest::newRow("-1") << Q_UINT64_C(-1) << QByteArray("65535") << QByteArray("65,535"); + QTest::newRow("32767") << Q_UINT64_C(32767) << QByteArray("32767") << QByteArray("32,767"); + QTest::newRow("32768") << Q_UINT64_C(32768) << QByteArray("32768") << QByteArray("32,768"); + QTest::newRow("32769") << Q_UINT64_C(32769) << QByteArray("32769") << QByteArray("32,769"); + QTest::newRow("65535") << Q_UINT64_C(65535) << QByteArray("65535") << QByteArray("65,535"); + QTest::newRow("65536") << Q_UINT64_C(65536) << QByteArray("0") << QByteArray("0"); + QTest::newRow("65537") << Q_UINT64_C(65537) << QByteArray("1") << QByteArray("1"); } IMPLEMENT_STREAM_LEFT_INT_OPERATOR_TEST(unsignedShort, unsigned short) ; @@ -2200,22 +2224,23 @@ void tst_QTextStream::signedInt_write_operator_ToDevice_data() { QTest::addColumn<qulonglong>("number"); QTest::addColumn<QByteArray>("data"); + QTest::addColumn<QByteArray>("dataWithSeparators"); - QTest::newRow("0") << Q_UINT64_C(0) << QByteArray("0"); - QTest::newRow("1") << Q_UINT64_C(1) << QByteArray("1"); - QTest::newRow("-1") << Q_UINT64_C(-1) << QByteArray("-1"); - QTest::newRow("32767") << Q_UINT64_C(32767) << QByteArray("32767"); - QTest::newRow("32768") << Q_UINT64_C(32768) << QByteArray("32768"); - QTest::newRow("32769") << Q_UINT64_C(32769) << QByteArray("32769"); - QTest::newRow("65535") << Q_UINT64_C(65535) << QByteArray("65535"); - QTest::newRow("65536") << Q_UINT64_C(65536) << QByteArray("65536"); - QTest::newRow("65537") << Q_UINT64_C(65537) << QByteArray("65537"); - QTest::newRow("2147483647") << Q_UINT64_C(2147483647) << QByteArray("2147483647"); - QTest::newRow("2147483648") << Q_UINT64_C(2147483648) << QByteArray("-2147483648"); - QTest::newRow("2147483649") << Q_UINT64_C(2147483649) << QByteArray("-2147483647"); - QTest::newRow("4294967295") << Q_UINT64_C(4294967295) << QByteArray("-1"); - QTest::newRow("4294967296") << Q_UINT64_C(4294967296) << QByteArray("0"); - QTest::newRow("4294967297") << Q_UINT64_C(4294967297) << QByteArray("1"); + QTest::newRow("0") << Q_UINT64_C(0) << QByteArray("0") << QByteArray("0"); + QTest::newRow("1") << Q_UINT64_C(1) << QByteArray("1") << QByteArray("1"); + QTest::newRow("-1") << Q_UINT64_C(-1) << QByteArray("-1") << QByteArray("-1"); + QTest::newRow("32767") << Q_UINT64_C(32767) << QByteArray("32767") << QByteArray("32,767"); + QTest::newRow("32768") << Q_UINT64_C(32768) << QByteArray("32768") << QByteArray("32,768"); + QTest::newRow("32769") << Q_UINT64_C(32769) << QByteArray("32769") << QByteArray("32,769"); + QTest::newRow("65535") << Q_UINT64_C(65535) << QByteArray("65535") << QByteArray("65,535"); + QTest::newRow("65536") << Q_UINT64_C(65536) << QByteArray("65536") << QByteArray("65,536"); + QTest::newRow("65537") << Q_UINT64_C(65537) << QByteArray("65537") << QByteArray("65,537"); + QTest::newRow("2147483647") << Q_UINT64_C(2147483647) << QByteArray("2147483647") << QByteArray("2,147,483,647"); + QTest::newRow("2147483648") << Q_UINT64_C(2147483648) << QByteArray("-2147483648") << QByteArray("-2,147,483,648"); + QTest::newRow("2147483649") << Q_UINT64_C(2147483649) << QByteArray("-2147483647") << QByteArray("-2,147,483,647"); + QTest::newRow("4294967295") << Q_UINT64_C(4294967295) << QByteArray("-1") << QByteArray("-1"); + QTest::newRow("4294967296") << Q_UINT64_C(4294967296) << QByteArray("0") << QByteArray("0"); + QTest::newRow("4294967297") << Q_UINT64_C(4294967297) << QByteArray("1") << QByteArray("1"); } IMPLEMENT_STREAM_LEFT_INT_OPERATOR_TEST(signedInt, signed int) ; @@ -2225,22 +2250,23 @@ void tst_QTextStream::unsignedInt_write_operator_ToDevice_data() { QTest::addColumn<qulonglong>("number"); QTest::addColumn<QByteArray>("data"); + QTest::addColumn<QByteArray>("dataWithSeparators"); - QTest::newRow("0") << Q_UINT64_C(0) << QByteArray("0"); - QTest::newRow("1") << Q_UINT64_C(1) << QByteArray("1"); - QTest::newRow("-1") << Q_UINT64_C(-1) << QByteArray("4294967295"); - QTest::newRow("32767") << Q_UINT64_C(32767) << QByteArray("32767"); - QTest::newRow("32768") << Q_UINT64_C(32768) << QByteArray("32768"); - QTest::newRow("32769") << Q_UINT64_C(32769) << QByteArray("32769"); - QTest::newRow("65535") << Q_UINT64_C(65535) << QByteArray("65535"); - QTest::newRow("65536") << Q_UINT64_C(65536) << QByteArray("65536"); - QTest::newRow("65537") << Q_UINT64_C(65537) << QByteArray("65537"); - QTest::newRow("2147483647") << Q_UINT64_C(2147483647) << QByteArray("2147483647"); - QTest::newRow("2147483648") << Q_UINT64_C(2147483648) << QByteArray("2147483648"); - QTest::newRow("2147483649") << Q_UINT64_C(2147483649) << QByteArray("2147483649"); - QTest::newRow("4294967295") << Q_UINT64_C(4294967295) << QByteArray("4294967295"); - QTest::newRow("4294967296") << Q_UINT64_C(4294967296) << QByteArray("0"); - QTest::newRow("4294967297") << Q_UINT64_C(4294967297) << QByteArray("1"); + QTest::newRow("0") << Q_UINT64_C(0) << QByteArray("0") << QByteArray("0"); + QTest::newRow("1") << Q_UINT64_C(1) << QByteArray("1") << QByteArray("1"); + QTest::newRow("-1") << Q_UINT64_C(-1) << QByteArray("4294967295") << QByteArray("4,294,967,295"); + QTest::newRow("32767") << Q_UINT64_C(32767) << QByteArray("32767") << QByteArray("32,767"); + QTest::newRow("32768") << Q_UINT64_C(32768) << QByteArray("32768") << QByteArray("32,768"); + QTest::newRow("32769") << Q_UINT64_C(32769) << QByteArray("32769") << QByteArray("32,769"); + QTest::newRow("65535") << Q_UINT64_C(65535) << QByteArray("65535") << QByteArray("65,535"); + QTest::newRow("65536") << Q_UINT64_C(65536) << QByteArray("65536") << QByteArray("65,536"); + QTest::newRow("65537") << Q_UINT64_C(65537) << QByteArray("65537") << QByteArray("65,537"); + QTest::newRow("2147483647") << Q_UINT64_C(2147483647) << QByteArray("2147483647") << QByteArray("2,147,483,647"); + QTest::newRow("2147483648") << Q_UINT64_C(2147483648) << QByteArray("2147483648") << QByteArray("2,147,483,648"); + QTest::newRow("2147483649") << Q_UINT64_C(2147483649) << QByteArray("2147483649") << QByteArray("2,147,483,649"); + QTest::newRow("4294967295") << Q_UINT64_C(4294967295) << QByteArray("4294967295") << QByteArray("4,294,967,295"); + QTest::newRow("4294967296") << Q_UINT64_C(4294967296) << QByteArray("0") << QByteArray("0"); + QTest::newRow("4294967297") << Q_UINT64_C(4294967297) << QByteArray("1") << QByteArray("1"); } IMPLEMENT_STREAM_LEFT_INT_OPERATOR_TEST(unsignedInt, unsigned int) ; @@ -2250,26 +2276,27 @@ void tst_QTextStream::qlonglong_write_operator_ToDevice_data() { QTest::addColumn<qulonglong>("number"); QTest::addColumn<QByteArray>("data"); + QTest::addColumn<QByteArray>("dataWithSeparators"); - QTest::newRow("0") << Q_UINT64_C(0) << QByteArray("0"); - QTest::newRow("1") << Q_UINT64_C(1) << QByteArray("1"); - QTest::newRow("-1") << Q_UINT64_C(-1) << QByteArray("-1"); - QTest::newRow("32767") << Q_UINT64_C(32767) << QByteArray("32767"); - QTest::newRow("32768") << Q_UINT64_C(32768) << QByteArray("32768"); - QTest::newRow("32769") << Q_UINT64_C(32769) << QByteArray("32769"); - QTest::newRow("65535") << Q_UINT64_C(65535) << QByteArray("65535"); - QTest::newRow("65536") << Q_UINT64_C(65536) << QByteArray("65536"); - QTest::newRow("65537") << Q_UINT64_C(65537) << QByteArray("65537"); - QTest::newRow("2147483647") << Q_UINT64_C(2147483647) << QByteArray("2147483647"); - QTest::newRow("2147483648") << Q_UINT64_C(2147483648) << QByteArray("2147483648"); - QTest::newRow("2147483649") << Q_UINT64_C(2147483649) << QByteArray("2147483649"); - QTest::newRow("4294967295") << Q_UINT64_C(4294967295) << QByteArray("4294967295"); - QTest::newRow("4294967296") << Q_UINT64_C(4294967296) << QByteArray("4294967296"); - QTest::newRow("4294967297") << Q_UINT64_C(4294967297) << QByteArray("4294967297"); - QTest::newRow("9223372036854775807") << Q_UINT64_C(9223372036854775807) << QByteArray("9223372036854775807"); - QTest::newRow("9223372036854775808") << Q_UINT64_C(9223372036854775808) << QByteArray("-9223372036854775808"); - QTest::newRow("9223372036854775809") << Q_UINT64_C(9223372036854775809) << QByteArray("-9223372036854775807"); - QTest::newRow("18446744073709551615") << Q_UINT64_C(18446744073709551615) << QByteArray("-1"); + QTest::newRow("0") << Q_UINT64_C(0) << QByteArray("0") << QByteArray("0"); + QTest::newRow("1") << Q_UINT64_C(1) << QByteArray("1") << QByteArray("1"); + QTest::newRow("-1") << Q_UINT64_C(-1) << QByteArray("-1") << QByteArray("-1"); + QTest::newRow("32767") << Q_UINT64_C(32767) << QByteArray("32767") << QByteArray("32,767"); + QTest::newRow("32768") << Q_UINT64_C(32768) << QByteArray("32768") << QByteArray("32,768"); + QTest::newRow("32769") << Q_UINT64_C(32769) << QByteArray("32769") << QByteArray("32,769"); + QTest::newRow("65535") << Q_UINT64_C(65535) << QByteArray("65535") << QByteArray("65,535"); + QTest::newRow("65536") << Q_UINT64_C(65536) << QByteArray("65536") << QByteArray("65,536"); + QTest::newRow("65537") << Q_UINT64_C(65537) << QByteArray("65537") << QByteArray("65,537"); + QTest::newRow("2147483647") << Q_UINT64_C(2147483647) << QByteArray("2147483647") << QByteArray("2,147,483,647"); + QTest::newRow("2147483648") << Q_UINT64_C(2147483648) << QByteArray("2147483648") << QByteArray("2,147,483,648"); + QTest::newRow("2147483649") << Q_UINT64_C(2147483649) << QByteArray("2147483649") << QByteArray("2,147,483,649"); + QTest::newRow("4294967295") << Q_UINT64_C(4294967295) << QByteArray("4294967295") << QByteArray("4,294,967,295"); + QTest::newRow("4294967296") << Q_UINT64_C(4294967296) << QByteArray("4294967296") << QByteArray("4,294,967,296"); + QTest::newRow("4294967297") << Q_UINT64_C(4294967297) << QByteArray("4294967297") << QByteArray("4,294,967,297"); + QTest::newRow("9223372036854775807") << Q_UINT64_C(9223372036854775807) << QByteArray("9223372036854775807") << QByteArray("9,223,372,036,854,775,807"); + QTest::newRow("9223372036854775808") << Q_UINT64_C(9223372036854775808) << QByteArray("-9223372036854775808") << QByteArray("-9,223,372,036,854,775,808"); + QTest::newRow("9223372036854775809") << Q_UINT64_C(9223372036854775809) << QByteArray("-9223372036854775807") << QByteArray("-9,223,372,036,854,775,807"); + QTest::newRow("18446744073709551615") << Q_UINT64_C(18446744073709551615) << QByteArray("-1") << QByteArray("-1"); } IMPLEMENT_STREAM_LEFT_INT_OPERATOR_TEST(qlonglong, qlonglong) ; @@ -2279,26 +2306,27 @@ void tst_QTextStream::qulonglong_write_operator_ToDevice_data() { QTest::addColumn<qulonglong>("number"); QTest::addColumn<QByteArray>("data"); + QTest::addColumn<QByteArray>("dataWithSeparators"); - QTest::newRow("0") << Q_UINT64_C(0) << QByteArray("0"); - QTest::newRow("1") << Q_UINT64_C(1) << QByteArray("1"); - QTest::newRow("-1") << Q_UINT64_C(-1) << QByteArray("18446744073709551615"); - QTest::newRow("32767") << Q_UINT64_C(32767) << QByteArray("32767"); - QTest::newRow("32768") << Q_UINT64_C(32768) << QByteArray("32768"); - QTest::newRow("32769") << Q_UINT64_C(32769) << QByteArray("32769"); - QTest::newRow("65535") << Q_UINT64_C(65535) << QByteArray("65535"); - QTest::newRow("65536") << Q_UINT64_C(65536) << QByteArray("65536"); - QTest::newRow("65537") << Q_UINT64_C(65537) << QByteArray("65537"); - QTest::newRow("2147483647") << Q_UINT64_C(2147483647) << QByteArray("2147483647"); - QTest::newRow("2147483648") << Q_UINT64_C(2147483648) << QByteArray("2147483648"); - QTest::newRow("2147483649") << Q_UINT64_C(2147483649) << QByteArray("2147483649"); - QTest::newRow("4294967295") << Q_UINT64_C(4294967295) << QByteArray("4294967295"); - QTest::newRow("4294967296") << Q_UINT64_C(4294967296) << QByteArray("4294967296"); - QTest::newRow("4294967297") << Q_UINT64_C(4294967297) << QByteArray("4294967297"); - QTest::newRow("9223372036854775807") << Q_UINT64_C(9223372036854775807) << QByteArray("9223372036854775807"); - QTest::newRow("9223372036854775808") << Q_UINT64_C(9223372036854775808) << QByteArray("9223372036854775808"); - QTest::newRow("9223372036854775809") << Q_UINT64_C(9223372036854775809) << QByteArray("9223372036854775809"); - QTest::newRow("18446744073709551615") << Q_UINT64_C(18446744073709551615) << QByteArray("18446744073709551615"); + QTest::newRow("0") << Q_UINT64_C(0) << QByteArray("0") << QByteArray("0"); + QTest::newRow("1") << Q_UINT64_C(1) << QByteArray("1") << QByteArray("1"); + QTest::newRow("-1") << Q_UINT64_C(-1) << QByteArray("18446744073709551615") << QByteArray("18,446,744,073,709,551,615"); + QTest::newRow("32767") << Q_UINT64_C(32767) << QByteArray("32767") << QByteArray("32,767"); + QTest::newRow("32768") << Q_UINT64_C(32768) << QByteArray("32768") << QByteArray("32,768"); + QTest::newRow("32769") << Q_UINT64_C(32769) << QByteArray("32769") << QByteArray("32,769"); + QTest::newRow("65535") << Q_UINT64_C(65535) << QByteArray("65535") << QByteArray("65,535"); + QTest::newRow("65536") << Q_UINT64_C(65536) << QByteArray("65536") << QByteArray("65,536"); + QTest::newRow("65537") << Q_UINT64_C(65537) << QByteArray("65537") << QByteArray("65,537"); + QTest::newRow("2147483647") << Q_UINT64_C(2147483647) << QByteArray("2147483647") << QByteArray("2,147,483,647"); + QTest::newRow("2147483648") << Q_UINT64_C(2147483648) << QByteArray("2147483648") << QByteArray("2,147,483,648"); + QTest::newRow("2147483649") << Q_UINT64_C(2147483649) << QByteArray("2147483649") << QByteArray("2,147,483,649"); + QTest::newRow("4294967295") << Q_UINT64_C(4294967295) << QByteArray("4294967295") << QByteArray("4,294,967,295"); + QTest::newRow("4294967296") << Q_UINT64_C(4294967296) << QByteArray("4294967296") << QByteArray("4,294,967,296"); + QTest::newRow("4294967297") << Q_UINT64_C(4294967297) << QByteArray("4294967297") << QByteArray("4,294,967,297"); + QTest::newRow("9223372036854775807") << Q_UINT64_C(9223372036854775807) << QByteArray("9223372036854775807") << QByteArray("9,223,372,036,854,775,807"); + QTest::newRow("9223372036854775808") << Q_UINT64_C(9223372036854775808) << QByteArray("9223372036854775808") << QByteArray("9,223,372,036,854,775,808"); + QTest::newRow("9223372036854775809") << Q_UINT64_C(9223372036854775809) << QByteArray("9223372036854775809") << QByteArray("9,223,372,036,854,775,809"); + QTest::newRow("18446744073709551615") << Q_UINT64_C(18446744073709551615) << QByteArray("18446744073709551615") << QByteArray("18,446,744,073,709,551,615"); } IMPLEMENT_STREAM_LEFT_INT_OPERATOR_TEST(qulonglong, qulonglong) ; diff --git a/tests/auto/corelib/plugin/qlibrary/tst_qlibrary.cpp b/tests/auto/corelib/plugin/qlibrary/tst_qlibrary.cpp index d60e1514b9..2244f3e041 100644 --- a/tests/auto/corelib/plugin/qlibrary/tst_qlibrary.cpp +++ b/tests/auto/corelib/plugin/qlibrary/tst_qlibrary.cpp @@ -456,10 +456,21 @@ void tst_QLibrary::loadHints() if (int(loadHints) != 0) { lh |= library.loadHints(); library.setLoadHints(lh); + + // confirm that another QLibrary doesn't get affected - QTBUG-39642 + QCOMPARE(QLibrary().loadHints(), QLibrary::LoadHints()); } library.setFileName(lib); QCOMPARE(library.loadHints(), lh); bool ok = library.load(); + + // we can't change the hints anymore + library.setLoadHints(QLibrary::LoadHints()); + QCOMPARE(library.loadHints(), lh); + + // confirm that a new QLibrary inherits the hints too + QCOMPARE(QLibrary(lib).loadHints(), lh); + if ( result ) { QVERIFY( ok ); QVERIFY(library.unload()); diff --git a/tests/auto/corelib/tools/qringbuffer/tst_qringbuffer.cpp b/tests/auto/corelib/tools/qringbuffer/tst_qringbuffer.cpp index 285cc3042a..579d6cfe95 100644 --- a/tests/auto/corelib/tools/qringbuffer/tst_qringbuffer.cpp +++ b/tests/auto/corelib/tools/qringbuffer/tst_qringbuffer.cpp @@ -54,6 +54,13 @@ private slots: void sizeWhenEmpty(); void sizeWhenReservedAndChopped(); void sizeWhenReserved(); + void free(); + void reserveAndRead(); + void chop(); + void ungetChar(); + void indexOf(); + void appendAndRead(); + void readLine(); }; void tst_QRingBuffer::sizeWhenReserved() @@ -179,6 +186,134 @@ void tst_QRingBuffer::readPointerAtPositionWriteRead() QVERIFY(outData.buffer().startsWith(inData.buffer())); } +void tst_QRingBuffer::free() +{ + QRingBuffer ringBuffer; + // make three byte arrays with different sizes + ringBuffer.reserve(4096); + ringBuffer.reserve(2048); + ringBuffer.append(QByteArray("01234", 5)); + + ringBuffer.free(1); + QCOMPARE(ringBuffer.size(), 4095 + 2048 + 5); + ringBuffer.free(4096); + QCOMPARE(ringBuffer.size(), 2047 + 5); + ringBuffer.free(48); + ringBuffer.free(2000); + QCOMPARE(ringBuffer.size(), 4); + QVERIFY(memcmp(ringBuffer.readPointer(), "1234", 4) == 0); +} + +void tst_QRingBuffer::reserveAndRead() +{ + QRingBuffer ringBuffer; + // fill buffer with an arithmetic progression + for (int i = 1; i < 256; ++i) { + QByteArray ba(i, char(i)); + char *ringPos = ringBuffer.reserve(i); + QVERIFY(ringPos); + memcpy(ringPos, ba.constData(), i); + } + + // readback and check stored data + for (int i = 1; i < 256; ++i) { + QByteArray ba; + ba.resize(i); + int thisRead = ringBuffer.read(ba.data(), i); + QCOMPARE(thisRead, i); + QVERIFY(ba.count(char(i)) == i); + } + QVERIFY(ringBuffer.size() == 0); +} + +void tst_QRingBuffer::chop() +{ + QRingBuffer ringBuffer; + // make three byte arrays with different sizes + ringBuffer.append(QByteArray("01234", 5)); + ringBuffer.reserve(2048); + ringBuffer.reserve(4096); + + ringBuffer.chop(1); + QCOMPARE(ringBuffer.size(), 5 + 2048 + 4095); + ringBuffer.chop(4096); + QCOMPARE(ringBuffer.size(), 5 + 2047); + ringBuffer.chop(48); + ringBuffer.chop(2000); + QCOMPARE(ringBuffer.size(), 4); + QVERIFY(memcmp(ringBuffer.readPointer(), "0123", 4) == 0); +} + +void tst_QRingBuffer::ungetChar() +{ + QRingBuffer ringBuffer(16); + for (int i = 1; i < 32; ++i) + ringBuffer.putChar(char(i)); + + for (int i = 1; i < 31; ++i) { + int c = ringBuffer.getChar(); + QVERIFY(c == 1); + ringBuffer.getChar(); + ringBuffer.ungetChar(char(c)); // unget first char + } + QCOMPARE(ringBuffer.size(), 1); +} + +void tst_QRingBuffer::indexOf() +{ + QRingBuffer ringBuffer(16); + for (int i = 1; i < 256; ++i) + ringBuffer.putChar(char(i)); + + for (int i = 1; i < 256; ++i) { + int index = ringBuffer.indexOf(char(i)); + QCOMPARE(i - 1, index); + QCOMPARE(index, ringBuffer.indexOf(char(i), i)); + QVERIFY(ringBuffer.indexOf(char(i), i - 1) == -1); // test for absent char + } +} + +void tst_QRingBuffer::appendAndRead() +{ + QRingBuffer ringBuffer; + QByteArray ba1("Hello world!"); + QByteArray ba2("Test string."); + QByteArray ba3("0123456789"); + ringBuffer.append(ba1); + ringBuffer.append(ba2); + ringBuffer.append(ba3); + + QVERIFY(ringBuffer.read() == ba1); + QVERIFY(ringBuffer.read() == ba2); + QVERIFY(ringBuffer.read() == ba3); +} + +void tst_QRingBuffer::readLine() +{ + QRingBuffer ringBuffer; + QByteArray ba1("Hello world!\n", 13); + QByteArray ba2("\n", 1); + QByteArray ba3("Test string.", 12); + QByteArray ba4("0123456789", 10); + ringBuffer.append(ba1); + ringBuffer.append(ba2); + ringBuffer.append(ba3 + ba4 + ba2); + + char stringBuf[102]; + stringBuf[101] = 0; // non-crash terminator + QVERIFY(ringBuffer.readLine(stringBuf, sizeof(stringBuf) - 2) == ba1.size()); + QVERIFY(QByteArray(stringBuf, strlen(stringBuf)) == ba1); + + // check first empty string reading + stringBuf[0] = 0xFF; + QCOMPARE(ringBuffer.readLine(stringBuf, sizeof(stringBuf) - 2), ba2.size()); + QVERIFY(stringBuf[0] == ba2[0]); + + QVERIFY(ringBuffer.readLine(stringBuf, sizeof(stringBuf) - 2) == (ba3.size() + ba4.size() + + ba2.size())); + QVERIFY(QByteArray(stringBuf, strlen(stringBuf)) == (ba3 + ba4 + ba2)); + QVERIFY(ringBuffer.size() == 0); +} QTEST_APPLESS_MAIN(tst_QRingBuffer) #include "tst_qringbuffer.moc" diff --git a/tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.cpp b/tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.cpp index 9a6b9f488b..232231b005 100644 --- a/tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.cpp +++ b/tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.cpp @@ -64,6 +64,7 @@ class tst_QGuiApplication: public tst_QCoreApplication Q_OBJECT private slots: + void cleanup(); void displayName(); void firstWindowTitle(); void windowIcon(); @@ -80,6 +81,11 @@ private slots: void layoutDirection(); }; +void tst_QGuiApplication::cleanup() +{ + QVERIFY(QGuiApplication::allWindows().isEmpty()); +} + void tst_QGuiApplication::displayName() { int argc = 1; diff --git a/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp b/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp index 9517264e55..3fa02ebaa3 100644 --- a/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp +++ b/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp @@ -101,11 +101,17 @@ private slots: touchDevice->setType(QTouchDevice::TouchScreen); QWindowSystemInterface::registerTouchDevice(touchDevice); } + void cleanup(); private: QTouchDevice *touchDevice; }; +void tst_QWindow::cleanup() +{ + QVERIFY(QGuiApplication::allWindows().isEmpty()); +} + void tst_QWindow::mapGlobal() { QWindow a; diff --git a/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp b/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp index d46d3501f1..b9ca831e0c 100644 --- a/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp +++ b/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp @@ -114,8 +114,8 @@ public: virtual ~tst_QFiledialog(); public slots: + void initTestCase(); void init(); - void cleanup(); private slots: void currentChangedSignal(); @@ -185,28 +185,25 @@ tst_QFiledialog::~tst_QFiledialog() { } +void tst_QFiledialog::initTestCase() +{ + QStandardPaths::setTestModeEnabled(true); +} + void tst_QFiledialog::init() { - // Save the developers settings so they don't get mad when their sidebar folders are gone. + // clean up the sidebar between each test QSettings settings(QSettings::UserScope, QLatin1String("QtProject")); settings.beginGroup(QLatin1String("Qt")); - userSettings = settings.value(QLatin1String("filedialog")).toByteArray(); settings.remove(QLatin1String("filedialog")); - // populate it with some default settings + // populate the sidebar with some default settings QNonNativeFileDialog fd; #if defined(Q_OS_WINCE) QTest::qWait(1000); #endif } -void tst_QFiledialog::cleanup() -{ - QSettings settings(QSettings::UserScope, QLatin1String("QtProject")); - settings.beginGroup(QLatin1String("Qt")); - settings.setValue(QLatin1String("filedialog"), userSettings); -} - class MyAbstractItemDelegate : public QAbstractItemDelegate { public: diff --git a/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp b/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp index a170430ef6..6c1e67a049 100644 --- a/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp +++ b/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp @@ -260,6 +260,7 @@ void tst_QApplication::cleanup() { // TODO: Add cleanup code here. // This will be executed immediately after each test is run. + QVERIFY(QApplication::topLevelWidgets().isEmpty()); } void tst_QApplication::staticSetup() diff --git a/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp b/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp index 1809cdc16a..8084d50fbe 100644 --- a/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp +++ b/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp @@ -61,7 +61,7 @@ static inline void setFrameless(QWidget *w) w->setWindowFlags(flags); } -class tst_QWidget_window : public QWidget +class tst_QWidget_window : public QObject { Q_OBJECT @@ -71,6 +71,7 @@ public: public slots: void initTestCase(); void cleanupTestCase(); + void cleanup(); private slots: void tst_min_max_size(); @@ -106,6 +107,11 @@ void tst_QWidget_window::cleanupTestCase() { } +void tst_QWidget_window::cleanup() +{ + QVERIFY(QApplication::topLevelWidgets().isEmpty()); +} + /* Test if the maximum/minimum size constraints * are propagated from the widget to the QWidgetWindow * independently of whether they were set before or after diff --git a/tests/benchmarks/corelib/tools/qringbuffer/main.cpp b/tests/benchmarks/corelib/tools/qringbuffer/main.cpp new file mode 100644 index 0000000000..ebc87aa0cb --- /dev/null +++ b/tests/benchmarks/corelib/tools/qringbuffer/main.cpp @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 2014 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 <private/qringbuffer_p.h> +#include <QByteArray> + +#include <qtest.h> + +class tst_qringbuffer : public QObject +{ + Q_OBJECT +private slots: + void reserveAndRead(); + void free(); +}; + +void tst_qringbuffer::reserveAndRead() +{ + QRingBuffer ringBuffer; + QBENCHMARK { + for (int i = 1; i < 256; ++i) + ringBuffer.reserve(i); + + for (int i = 1; i < 256; ++i) + ringBuffer.read(0, i); + } +} + +void tst_qringbuffer::free() +{ + QRingBuffer ringBuffer; + QBENCHMARK { + ringBuffer.reserve(4096); + ringBuffer.reserve(2048); + ringBuffer.append(QByteArray("01234", 5)); + + ringBuffer.free(1); + ringBuffer.free(4096); + ringBuffer.free(48); + ringBuffer.free(2000); + } +} + +QTEST_MAIN(tst_qringbuffer) + +#include "main.moc" diff --git a/tests/benchmarks/corelib/tools/qringbuffer/qringbuffer.pro b/tests/benchmarks/corelib/tools/qringbuffer/qringbuffer.pro new file mode 100644 index 0000000000..21b50e10e5 --- /dev/null +++ b/tests/benchmarks/corelib/tools/qringbuffer/qringbuffer.pro @@ -0,0 +1,7 @@ +TEMPLATE = app +TARGET = tst_bench_qringbuffer + +QT = core-private testlib +CONFIG += release + +SOURCES += main.cpp diff --git a/tools/configure/configureapp.cpp b/tools/configure/configureapp.cpp index f1010aea34..6c49b2dc79 100644 --- a/tools/configure/configureapp.cpp +++ b/tools/configure/configureapp.cpp @@ -250,6 +250,8 @@ Configure::Configure(int& argc, char** argv) dictionary[ "C++11" ] = "auto"; + dictionary[ "USE_GOLD_LINKER" ] = "no"; + dictionary[ "SHARED" ] = "yes"; dictionary[ "ZLIB" ] = "auto"; @@ -461,6 +463,10 @@ void Configure::parseCmdLine() dictionary[ "C++11" ] = "yes"; else if (configCmdLine.at(i) == "-no-c++11") dictionary[ "C++11" ] = "no"; + else if (configCmdLine.at(i) == "-use-gold-linker") + dictionary[ "USE_GOLD_LINKER" ] = "yes"; + else if (configCmdLine.at(i) == "-no-use-gold-linker") + dictionary[ "USE_GOLD_LINKER" ] = "no"; else if (configCmdLine.at(i) == "-shared") dictionary[ "SHARED" ] = "yes"; else if (configCmdLine.at(i) == "-static") @@ -1762,6 +1768,9 @@ bool Configure::displayHelp() desc("C++11", "yes", "-c++11", "Compile Qt with C++11 support enabled."); desc("C++11", "no", "-no-c++11", "Do not compile Qt with C++11 support enabled.\n"); + desc("USE_GOLD_LINKER", "yes", "-use-gold-linker", "Link using the GNU gold linker (gcc only)."); + desc("USE_GOLD_LINKER", "no", "-no-use-gold-linker", "Do not link using the GNU gold linker.\n"); + desc("SHARED", "yes", "-shared", "Create and use shared Qt libraries."); desc("SHARED", "no", "-static", "Create and use static Qt libraries.\n"); @@ -2609,6 +2618,9 @@ void Configure::generateOutputVars() if (dictionary[ "C++11" ] == "yes") qtConfig += "c++11"; + if (dictionary[ "USE_GOLD_LINKER" ] == "yes") + qmakeConfig += "use_gold_linker"; + if (dictionary[ "SHARED" ] == "no") qtConfig += "static"; else |