Merge remote-tracking branch 'origin/stable' into dev

Change-Id: Ie56539b2e0be611a363b5f15ae5412a78d6945a2
bb10
Frederik Gladhorn 2013-10-24 12:48:39 +02:00
commit 840f6a40e6
293 changed files with 4369 additions and 1658 deletions

View File

@ -1,3 +0,0 @@
OBJECTIVE_SOURCES = coreservices.mm
LIBS += -framework CoreServices
CONFIG -= qt

View File

@ -1,2 +1,3 @@
SOURCES = ptrsizetest.cpp
CONFIG -= qt dylib
CONFIG += debug console

45
configure vendored
View File

@ -1609,8 +1609,8 @@ while [ "$#" -gt 0 ]; do
[ "$XPLATFORM" = "undefined" ] && exit 101
;;
device-option)
DEV_VAR=`echo $VAL | sed "s,^\(.*\)=.*,\1,"`
DEV_VAL=`echo $VAL | sed "s,^.*=\(.*\),\1,"`
DEV_VAR=`echo $VAL | cut -d '=' -f 1`
DEV_VAL=`echo $VAL | cut -d '=' -f 2-`
DeviceVar set $DEV_VAR "$DEV_VAL"
;;
qpa)
@ -2882,7 +2882,7 @@ if [ "$XPLATFORM_IOS" = "yes" ]; then
CFG_NOBUILD_PARTS="$CFG_NOBUILD_PARTS examples tests"
CFG_SHARED="no" # iOS builds should be static to be able to submit to the App Store
CFG_CXX11="no" # C++11 support disabled for now
CFG_SKIP_MODULES="$CFG_SKIP_MODULES qtconnectivity qtdoc qtgraphicaleffects qtlocation qtmultimedia qtquickcontrols qtserialport qttools qtwebkit qtwebkit-examples"
CFG_SKIP_MODULES="$CFG_SKIP_MODULES qtconnectivity qtdoc qtgraphicaleffects qtlocation qtmacextras qtmultimedia qtquickcontrols qtserialport qttools qtwebkit qtwebkit-examples"
fi
# disable GTK style support auto-detection on Mac
@ -3032,6 +3032,21 @@ unset tty
eval `LC_ALL=C $TEST_COMPILER $SYSROOT_FLAG $TEST_COMPILER_CXXFLAGS -xc++ -E -v - < /dev/null 2>&1 > /dev/null | $AWK '
BEGIN { ORS = ""; FS = "="; incs = 0; libs = 0; }
function normalize(dir)
{
do {
odir = dir
gsub(/\\/[^\\/]+\\/\\.\\./, "", dir)
} while (dir != odir);
do {
odir = dir
gsub(/\\/\\./, "", dir)
} while (dir != odir);
sub("/$", "", dir);
return dir;
}
function quote(s)
{
# We only handle spaces
@ -3047,14 +3062,19 @@ function quote(s)
/^\#include </ { yup=1; print "DEFAULT_INCDIRS=\""; next }
/^End of search/ { yup=0; print "\"\n" }
/ \(framework directory\)$/ { next }
yup { print quote(substr($0, 2)) " "; ++incs }
yup { print quote(normalize(substr($0, 2))) " "; ++incs }
# extract from one line like LIBRARY_PATH=/one/path:/another/path:...
$1 == "LIBRARY_PATH" {
libs = split($2, library_paths, ":");
print "DEFAULT_LIBDIRS=\"";
for (lib in library_paths)
print quote(library_paths[lib]) " ";
for (lib in library_paths) {
dir = normalize(library_paths[lib]);
if (!(dir in dirs)) {
print quote(dir) " ";
dirs[dir] = 1;
}
}
print "\"\n"
}
@ -4230,7 +4250,7 @@ fi
#-------------------------------------------------------------------------------
# Verify makespec
#-------------------------------------------------------------------------------
QMAKE_OUTPUT=`$outpath/bin/qmake -E -nocache -spec "$XQMAKESPEC" "QT=" $DEV_NULL 2>&1 >/dev/null`
QMAKE_OUTPUT=`$outpath/bin/qmake -E -nocache -spec "$XQMAKESPEC" "QT=" $DEV_NULL 2>&1`
if [ $? != "0" ]; then
echo "Failed to process makespec for platform '$XPLATFORM'"
if [ "$OPT_VERBOSE" = "yes" ]; then
@ -5501,6 +5521,7 @@ elif [ "$CFG_EGL" != "no" ]; then
QMAKE_CFLAGS_EGL=`$PKG_CONFIG --cflags egl 2>/dev/null`
QMakeVar set QMAKE_INCDIR_EGL "$QMAKE_INCDIR_EGL"
QMakeVar set QMAKE_LIBS_EGL "$QMAKE_LIBS_EGL"
QMakeVar set QMAKE_CFLAGS_EGL "`echo " $QMAKE_CFLAGS_EGL " | sed -e 's, -I[^ ]* , ,g;s,^ ,,;s, $,,'`"
fi # detect EGL support
if compileTest qpa/egl "EGL" $QMAKE_CFLAGS_EGL $QMAKE_LIBS_EGL; then
CFG_EGL=yes
@ -5582,14 +5603,6 @@ if [ "$CFG_KMS" = "yes" ]; then
QT_CONFIG="$QT_CONFIG kms"
fi
if [ "$BUILD_ON_MAC" = "yes" ]; then
if compileTest mac/coreservices "CoreServices"; then
QT_CONFIG="$QT_CONFIG coreservices"
else
QMakeVar add DEFINES QT_NO_CORESERVICES
fi
fi
if [ "$BUILD_ON_MAC" = "no" ] && [ "$XPLATFORM_MINGW" = "no" ] && [ "$XPLATFORM_QNX" = "no" ] && [ "$XPLATFORM_ANDROID" = "no" ]; then
if [ "$CFG_XCB" = "no" ] && [ "$CFG_EGLFS" = "no" ] && [ "$CFG_DIRECTFB" = "no" ] && [ "$CFG_LINUXFB" = "no" ] && [ "$CFG_KMS" = "no" ]; then
if [ "$QPA_PLATFORM_GUARD" = "yes" ] &&
@ -6898,7 +6911,7 @@ report_support " FreeType ..............." "$CFG_FREETYPE"
report_support " Iconv .................." "$CFG_ICONV"
report_support " ICU ...................." "$CFG_ICU"
report_support " Image formats:"
report_support_plugin " GIF .................." "$CFG_GIF" system QtGui
report_support_plugin " GIF .................." "$CFG_GIF" qt QtGui
report_support_plugin " JPEG ................." "$CFG_JPEG" "$CFG_LIBJPEG" QtGui
report_support_plugin " PNG .................." "$CFG_PNG" "$CFG_LIBPNG" QtGui
report_support " Glib ..................." "$CFG_GLIB"

19
dist/changes-5.2.0 vendored
View File

@ -84,3 +84,22 @@ QtGui
related to session management. For platform that don't support this
feature the default behavior has not changed.
Both X11 and Windows session management are supported.
QtNetwork
---------
- API was added to store and resume TLS session tickets.
- The minimum support openssl version has been increased to openssl 1.0. The
code to support older versions has not been removed, but is no longer
supported.
- An off-by-one error in NTLM proxy authentication has been fixed.
- Various improvements to reduce the memory used by qtnetwork have been made.
- Improved support for HTTP proxy authentication.
- Support for preconnecting to servers before making HTTP and HTTPS
connections. This allows for much reduced latency when the hosts to be
connected to are known.

View File

@ -1,3 +1,5 @@
requires(qtHaveModule(gui))
TEMPLATE = subdirs
CONFIG += no_docs_target

View File

@ -1,2 +1,4 @@
requires(qtHaveModule(gui))
TEMPLATE = subdirs
SUBDIRS = windows

View File

@ -45,8 +45,6 @@
#include <QGuiApplication>
#include <qtconcurrentmap.h>
#ifndef QT_NO_CONCURRENT
QImage scale(const QImage &image)
{
qDebug() << "Scaling image in thread" << QThread::currentThread();
@ -70,23 +68,3 @@ int main(int argc, char *argv[])
return 0;
}
#else
#include <QLabel>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QString text("Qt Concurrent is not yet supported on this platform");
QLabel *label = new QLabel(text);
label->setWordWrap(true);
label->show();
qDebug() << text;
app.exec();
}
#endif

View File

@ -10,6 +10,11 @@ SUBDIRS = imagescaling \
SUBDIRS += progressdialog
}
!qtHaveModule(gui) {
SUBDIRS -= \
map
}
!qtHaveModule(widgets) {
SUBDIRS -= \
imagescaling \

View File

@ -38,7 +38,7 @@
**
****************************************************************************/
#include <QtGui>
#include <QtCore>
#include <stdio.h>
#include <stdlib.h>

View File

@ -1,5 +1,5 @@
SOURCES += semaphores.cpp
QT = core gui
QT = core
CONFIG -= app_bundle
CONFIG += console

View File

@ -38,7 +38,7 @@
**
****************************************************************************/
#include <QtGui>
#include <QtCore>
#include <stdio.h>
#include <stdlib.h>

View File

@ -1,4 +1,4 @@
QT = core gui
QT = core
CONFIG -= moc app_bundle
CONFIG += console

View File

@ -178,7 +178,7 @@ QMAKE_LFLAGS_NOUNDEF = -Wl,--no-undefined
QMAKE_LFLAGS_RPATH = -Wl,-rpath=
QMAKE_LFLAGS_RPATHLINK = -Wl,-rpath-link=
QMAKE_LIBS = -lgnustl_shared -lsupc++ -llog -lz -lm -ldl -lc -lgcc
QMAKE_LIBS_PRIVATE = -lgnustl_shared -llog -lz -lm -ldl -lc -lgcc
QMAKE_LIBS_X11 =
QMAKE_LIBS_THREAD =
QMAKE_LIBS_EGL = -lEGL

View File

@ -0,0 +1,22 @@
#
# qmake configuration for blackberry armv7le systems
#
load(qt_config)
DEFINES += Q_OS_BLACKBERRY
CONFIG += blackberry
LIBS += -lbps
# Blackberry also has support for stack smashing protection in its libc
contains(QT_CONFIG, stack-protector-strong) {
QMAKE_CFLAGS += -fstack-protector-strong
} else {
QMAKE_CFLAGS += -fstack-protector -fstack-protector-all
}
QMAKE_CFLAGS += -mcpu=cortex-a9 -mtune=cortex-a9 -mthumb -D_FORTIFY_SOURCE=2
QMAKE_LFLAGS_SHLIB += -Wl,-z,relro -Wl,-z,now
include(../common/qcc-base-qnx-armv7le.conf)

View File

@ -1,9 +1,9 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Copyright (C) 2012 - 2013 BlackBerry Limited. All rights reserved.
** Contact: http://www.qt-project.org/legal
**
** This file is part of the config.tests of the Qt Toolkit.
** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
@ -39,10 +39,4 @@
**
****************************************************************************/
#include <CoreServices/CoreServices.h>
int main()
{
FSRef ref;
return 0;
}
#include "../qnx-armv7le-qcc/qplatformdefs.h"

View File

@ -1,22 +1,5 @@
#
# qmake configuration for blackberry armv7le systems
# deprecated, please use blackberry-armle-v7-qcc instead
#
load(qt_config)
DEFINES += Q_OS_BLACKBERRY
CONFIG += blackberry
LIBS += -lbps
# Blackberry also has support for stack smashing protection in its libc
contains(QT_CONFIG, stack-protector-strong) {
QMAKE_CFLAGS += -fstack-protector-strong
} else {
QMAKE_CFLAGS += -fstack-protector -fstack-protector-all
}
QMAKE_CFLAGS += -mcpu=cortex-a9 -mtune=cortex-a9 -mthumb -D_FORTIFY_SOURCE=2
QMAKE_LFLAGS_SHLIB += -Wl,-z,relro -Wl,-z,now
include(../common/qcc-base-qnx-armv7le.conf)
warning("You are using deprecated mkspecs. Please use blackberry-armle-v7-qcc instead.")
include(../blackberry-armle-v7-qcc/qmake.conf)

View File

@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2012 Research In Motion Limited. <blackberry-qt@qnx.com>
** Copyright (C) 2012 - 2013 BlackBerry Limited. All rights reserved.
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtCore module of the Qt Toolkit.
@ -39,4 +39,4 @@
**
****************************************************************************/
#include "../qnx-armv7le-qcc/qplatformdefs.h"
#include "../blackberry-armle-v7-qcc/qplatformdefs.h"

View File

@ -14,3 +14,4 @@ QMAKE_SYMBOLIC_LINK = $$QMAKE_COPY
QMAKE_LN_SHLIB = $$QMAKE_SYMBOLIC_LINK
# xcopy copies the contained files if source is a directory. Deal with it.
CONFIG += copy_dir_files
QMAKE_STREAM_EDITOR = $(QMAKE) -install sed

View File

@ -0,0 +1,8 @@
#
# qmake configuration for the Blackberry Playbook armv7le
#
include(../../blackberry-armle-v7-qcc/qmake.conf)
DEFINES += Q_OS_BLACKBERRY_TABLET
CONFIG += blackberry-playbook

View File

@ -0,0 +1,42 @@
/****************************************************************************
**
** Copyright (C) 2013 Klarälvdalens Datakonsult AB <info@kdab.com>
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "../../blackberry-armle-v7-qcc/qplatformdefs.h"

View File

@ -1,8 +1,5 @@
#
# qmake configuration for the Blackberry Playbook armv7le
# deprecated, please use blackberry-playbook-armle-v7-qcc instead
#
include(../../blackberry-armv7le-qcc/qmake.conf)
DEFINES += Q_OS_BLACKBERRY_TABLET
CONFIG += blackberry-playbook
warning("You are using deprecated mkspecs. Please use blackberry-playbook-armle-v7-qcc instead.")
include(../blackberry-playbook-armle-v7-qcc/qmake.conf)

View File

@ -39,4 +39,4 @@
**
****************************************************************************/
#include "../../blackberry-armv7le-qcc/qplatformdefs.h"
#include "../blackberry-playbook-armle-v7-qcc/qplatformdefs.h"

View File

@ -41,6 +41,7 @@
#include "qeglfshooks.h"
#include <EGL/eglvivante.h>
#include <QDebug>
QT_BEGIN_NAMESPACE
@ -62,6 +63,15 @@ private:
QEglFSImx6Hooks::QEglFSImx6Hooks()
{
int width, height;
bool multiBufferNotEnabledYet = qEnvironmentVariableIsEmpty("FB_MULTI_BUFFER");
bool multiBuffer = qEnvironmentVariableIsEmpty("QT_EGLFS_IMX6_NO_FB_MULTI_BUFFER");
if (multiBufferNotEnabledYet && multiBuffer) {
qWarning() << "QEglFSImx6Hooks will set environment variable FB_MULTI_BUFFER=2 to enable double buffering and vsync.\n"
<< "If this is not desired, you can override this via: export QT_EGLFS_IMX6_NO_FB_MULTI_BUFFER=1";
qputenv("FB_MULTI_BUFFER", "2");
}
mNativeDisplay = fbGetDisplayByIndex(0);
fbGetDisplayGeometry(mNativeDisplay, &width, &height);
mScreenSize.setHeight(height);

View File

@ -136,89 +136,6 @@ static void destroyDispmanxLayer(EGLNativeWindowType window)
delete eglWindow;
}
class QEglFSPiCursor : public QEglFSCursor
{
public:
QEglFSPiCursor(QEglFSScreen *screen) : QEglFSCursor(screen) {
QSurfaceFormat platformFormat;
platformFormat.setDepthBufferSize(24);
platformFormat.setStencilBufferSize(8);
platformFormat.setRedBufferSize(8);
platformFormat.setGreenBufferSize(8);
platformFormat.setBlueBufferSize(8);
platformFormat.setAlphaBufferSize(8);
m_config = q_configFromGLFormat(m_screen->display(), platformFormat);
createSurface();
createContext();
drawInLayer();
}
~QEglFSPiCursor() {
eglDestroySurface(m_screen->display(), m_surface);
destroyDispmanxLayer(m_window);
eglDestroyContext(m_screen->display(), m_context);
}
void createSurface() {
const QRect cr = cursorRect();
m_window = createDispmanxLayer(cr.topLeft(), cr.size(), 50, DISPMANX_FLAGS_ALPHA_FROM_SOURCE);
m_surface = eglCreateWindowSurface(m_screen->display(), m_config, m_window, NULL);
}
void createContext() {
eglBindAPI(EGL_OPENGL_ES_API);
QVector<EGLint> attrs;
attrs.append(EGL_CONTEXT_CLIENT_VERSION);
attrs.append(2);
attrs.append(EGL_NONE);
m_context = eglCreateContext(m_screen->display(), m_config, EGL_NO_CONTEXT, attrs.constData());
}
void drawInLayer() {
eglMakeCurrent(m_screen->display(), m_surface, m_surface, m_context);
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT);
draw(QRectF(QPointF(-1, 1), QPointF(1, -1)));
eglSwapBuffers(m_screen->display(), m_surface);
eglMakeCurrent(m_screen->display(), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
}
void changeCursor(QCursor *cursor, QWindow *window) Q_DECL_OVERRIDE {
if (!setCurrentCursor(cursor))
return;
EGL_DISPMANX_WINDOW_T *eglWindow = static_cast<EGL_DISPMANX_WINDOW_T *>(m_window);
if (QSize(eglWindow->width, eglWindow->height) != m_cursor.size) {
eglDestroySurface(m_screen->display(), m_surface);
destroyDispmanxLayer(m_window);
createSurface();
}
drawInLayer();
}
void setPos(const QPoint &pos) Q_DECL_OVERRIDE {
m_cursor.pos = pos;
moveDispmanxLayer(m_window, cursorRect().topLeft());
}
void pointerEvent(const QMouseEvent &event) Q_DECL_OVERRIDE {
if (event.type() != QEvent::MouseMove)
return;
m_cursor.pos = event.pos();
moveDispmanxLayer(m_window, cursorRect().topLeft());
}
void paintOnScreen() Q_DECL_OVERRIDE { }
private:
EGLConfig m_config;
EGLContext m_context;
EGLNativeWindowType m_window;
EGLSurface m_surface;
};
class QEglFSPiHooks : public QEglFSHooks
{
public:
@ -230,9 +147,6 @@ public:
virtual void destroyNativeWindow(EGLNativeWindowType window);
virtual bool hasCapability(QPlatformIntegration::Capability cap) const;
QEglFSCursor *createCursor(QEglFSScreen *screen) const {
return new QEglFSPiCursor(screen);
}
};
void QEglFSPiHooks::platformInit()

View File

@ -25,6 +25,7 @@ contains(TEMPLATE, ".*app"):!build_pass:!android-no-sdk {
else: NDK_TOOLCHAIN_PREFIX = arm-linux-androideabi
}
FILE_CONTENT += " \"toolchain-prefix\": $$emitString($$NDK_TOOLCHAIN_PREFIX),"
FILE_CONTENT += " \"tool-prefix\": $$emitString($$NDK_TOOLS_PREFIX),"
NDK_TOOLCHAIN_VERSION = $$(ANDROID_NDK_TOOLCHAIN_VERSION)
isEmpty(NDK_TOOLCHAIN_VERSION): NDK_TOOLCHAIN_VERSION = $$DEFAULT_ANDROID_NDK_TOOLCHAIN_VERSION
@ -61,9 +62,6 @@ contains(TEMPLATE, ".*app"):!build_pass:!android-no-sdk {
!isEmpty(ANDROID_EXTRA_LIBS): \
FILE_CONTENT += " \"android-extra-libs\": $$emitString($$join(ANDROID_EXTRA_LIBS, ",")),"
!isEmpty(QMAKE_SUPPORTED_ORIENTATIONS): \
FILE_CONTENT += " \"supported-orientations\": $$emitString($$join(QMAKE_SUPPORTED_ORIENTATIONS, ",")),"
FILE_CONTENT += " \"application-binary\": $$emitString($$absolute_path($$DESTDIR, $$OUT_PWD)/$$TARGET)"
FILE_CONTENT += "}"

View File

@ -30,11 +30,19 @@ split_incpath {
CMAKE_ADD_SOURCE_INCLUDE_DIRS = true
CMAKE_NO_PRIVATE_INCLUDES = true # Don't add private includes in the build dir which don't exist
CMAKE_SOURCE_INCLUDES = \
$$cmakeTargetPath($$QT_MODULE_INCLUDE_BASE) \
$$cmakeTargetPath($$QT_MODULE_INCLUDE_BASE/Qt$${CMAKE_MODULE_NAME})
$$cmakeTargetPaths($$QT_MODULE_INCLUDE_BASE $$QT_MODULE_INCLUDE_BASE/Qt$${CMAKE_MODULE_NAME})
CMAKE_SOURCE_PRIVATE_INCLUDES = \
$$cmakeTargetPath($$QT_MODULE_INCLUDE_BASE/Qt$${CMAKE_MODULE_NAME}/$$eval(QT.$${MODULE}.VERSION)) \
$$cmakeTargetPath($$QT_MODULE_INCLUDE_BASE/Qt$${CMAKE_MODULE_NAME}/$$eval(QT.$${MODULE}.VERSION)/Qt$${CMAKE_MODULE_NAME})
$$cmakeTargetPaths($$QT_MODULE_INCLUDE_BASE/Qt$${CMAKE_MODULE_NAME}/$$eval(QT.$${MODULE}.VERSION) \
$$QT_MODULE_INCLUDE_BASE/Qt$${CMAKE_MODULE_NAME}/$$eval(QT.$${MODULE}.VERSION)/Qt$${CMAKE_MODULE_NAME})
cmake_extra_source_includes.input = $$PWD/data/cmake/ExtraSourceIncludes.cmake.in
cmake_extra_source_includes.output = $$DESTDIR/cmake/Qt5$${CMAKE_MODULE_NAME}/ExtraSourceIncludes.cmake
!build_pass:QMAKE_SUBSTITUTES += \
cmake_extra_source_includes
cmake_qt5_module_files.files = \
$$cmake_extra_source_includes.output
}
CMAKE_INCLUDE_DIR = $$cmakeRelativePath($$[QT_INSTALL_HEADERS], $$[QT_INSTALL_PREFIX])
@ -68,7 +76,7 @@ contains(CMAKE_PLUGIN_DIR, "^\\.\\./.*") {
CMAKE_PLUGIN_DIR_IS_ABSOLUTE = True
}
!isEmpty(DLLDESTDIR):!static:!staticlib {
win32:!wince:!static:!staticlib {
CMAKE_DLL_DIR = $$cmakeRelativePath($$[QT_INSTALL_BINS], $$[QT_INSTALL_PREFIX])
contains(CMAKE_DLL_DIR, "^\\.\\./.*") {
CMAKE_DLL_DIR = $$[QT_INSTALL_BINS]/

View File

@ -0,0 +1,7 @@
list(APPEND _Qt5$${CMAKE_MODULE_NAME}_OWN_INCLUDE_DIRS
$$CMAKE_SOURCE_INCLUDES
)
set(Qt5$${CMAKE_MODULE_NAME}_PRIVATE_INCLUDE_DIRS
$$CMAKE_SOURCE_PRIVATE_INCLUDES
)

View File

@ -121,12 +121,7 @@ if (NOT TARGET Qt5::$${CMAKE_MODULE_NAME})
!!ENDIF
!!ENDIF
!!IF !isEmpty(CMAKE_ADD_SOURCE_INCLUDE_DIRS)
list(APPEND _Qt5$${CMAKE_MODULE_NAME}_OWN_INCLUDE_DIRS
$$CMAKE_SOURCE_INCLUDES
)
set(Qt5$${CMAKE_MODULE_NAME}_PRIVATE_INCLUDE_DIRS
$$CMAKE_SOURCE_PRIVATE_INCLUDES
)
include(\"${CMAKE_CURRENT_LIST_DIR}/ExtraSourceIncludes.cmake\" OPTIONAL)
!!ENDIF
!!ELSE
set(_Qt5$${CMAKE_MODULE_NAME}_OWN_INCLUDE_DIRS)

View File

@ -6,6 +6,18 @@ contains(TEMPLATE, ".*(lib|app)"):CONFIG += have_target
load(resolve_config)
# If the TARGET looks like a path, split it into DESTDIR and the resulting TARGET
target_dir_part = $$dirname(TARGET)
!isEmpty(target_dir_part) {
isEmpty(DESTDIR): \
DESTDIR = $$target_dir_part
else: \
DESTDIR = $$DESTDIR/$$target_dir_part
TARGET = $$basename(TARGET)
DESTDIR = $$clean_path($$DESTDIR)
}
QT_BREAKPAD_ROOT_PATH = $$(QT_BREAKPAD_ROOT_PATH)
!isEmpty(QT_BREAKPAD_ROOT_PATH): \ # quick test first whether requested ...
!static:release:have_target: \ # is it applicable?

View File

@ -14,6 +14,8 @@ wince*:contains(QT_CONFIG, opengles1) {
} else {
INCLUDEPATH += $$QMAKE_INCDIR_EGL
LIBS_PRIVATE += $$QMAKE_LIBS_EGL
QMAKE_CFLAGS += $$QMAKE_CFLAGS_EGL
QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_EGL
LIBS += $$QMAKE_LFLAGS_EGL
for(p, QMAKE_LIBDIR_EGL) {
exists($$p):LIBS_PRIVATE += -L$$p

View File

@ -1,9 +0,0 @@
load(default_pre)
# Check for supported Xcode versions
lessThan(QMAKE_XCODE_VERSION, "4.3"): \
error("This mkspec requires Xcode 4.3 or later")
!contains(QMAKE_XCODE_VERSION, ^(4\\.[3456]|5\\.[0])$): \
warning("The version of Xcode installed on this system ($$QMAKE_XCODE_VERSION)" \
"has not been tested fully - custom compiler settings may be necessary")

View File

@ -1,75 +0,0 @@
equals(TEMPLATE, app):contains(QT, gui(-private)?) {
!macx-xcode: \
error("Linking the iOS platform plugin requires bulding through Xcode")
LIBS *= -L$$[QT_INSTALL_PLUGINS/get]/platforms
lib_name = qios
lib_path_and_base = $$[QT_INSTALL_PLUGINS/get]/platforms/lib$${lib_name}$$qtPlatformTargetSuffix()
LIBS += -l$${lib_name}$$qtPlatformTargetSuffix() $$fromfile($${lib_path_and_base}.prl, QMAKE_PRL_LIBS)
# By marking qt_registerPlatformPlugin as undefined, we ensure that
# the plugin.o translation unit is considered for inclusion in
# the final binary, which in turn ensures that the plugin's
# static initializer is included and run.
QMAKE_LFLAGS += -u _qt_registerPlatformPlugin
# We do link and dependency resolution for the platform plugin
# manually, since we know we always need the plugin, so we don't
# need to generate an import for it.
CONFIG -= import_qpa_plugin
!no_main_wrapper {
# Instead of messing with the user's main function we go the other
# way and change the application entry point to call our main wrapper.
# This entry point is the 'start' symbol, provided by crt1.o, so we
# make a copy of the file and rename the '_main' unresolved symbol
# to our wrapper function, '_qtmn', injecting ourselves into the app
# startup. Once Apple starts shipping the LLVM linker (lld) we may
# get rid of this step completely and just pass -e _qtmn to the
# linker, taking advantage of the new LC_MAIN load command.
# We know that iOS 3.1 and up uses crt1.3.1.o (technically not
# true for simulator, but the SDK has a symlink to the correct file).
original_crt_path = "$(SDK_DIR)/usr/lib/crt1.3.1.o"
xcode_objects_path = "$(OBJECT_FILE_DIR_$(CURRENT_VARIANT))/$(CURRENT_ARCH)"
custom_crt_filename = "crt1_qt.o"
custom_crt_path = "$$xcode_objects_path/$$custom_crt_filename"
EOC = $$escape_expand(\\n\\t)
create_custom_crt.commands = \
# Copy original crt1 to build directory
"$$QMAKE_COPY_FILE $$original_crt_path $$custom_crt_path $$EOC" \
# And rename all occurrences of _main to _qtmn
"strings -t d - $${custom_crt_path}" \
"| sed -n 's/^\\([0-9]\\{1,\\}\\) _main\$\$/\1/p'" \
"| while read offset; do" \
"printf '_qtmn'" \
"| dd of=$${custom_crt_path} bs=1 seek=\$\$offset conv=notrunc >/dev/null 2>&1" \
"; done"
create_custom_crt.depends = $$original_crt_path
create_custom_crt.target = $$custom_crt_path
preprocess.depends = create_custom_crt
QMAKE_EXTRA_TARGETS += create_custom_crt preprocess
clean_custom_crt.commands = "$$QMAKE_DEL_FILE $$custom_crt_path"
preprocess_clean.depends += clean_custom_crt
QMAKE_EXTRA_TARGETS += clean_custom_crt preprocess_clean
# Prevent usage of new LC_MAIN load command, which skips start/crt1
# and calls main from the loader. We rely on injecting into start.
QMAKE_LFLAGS += -Wl,-no_new_main
# Explicitly link against our modified crt1 object
QMAKE_LFLAGS += -nostartfiles -l$${custom_crt_filename}
# Workaround for QMAKE_PBX_LIBPATHS mangling the Xcode variables
lib_search_path.name = LIBRARY_SEARCH_PATHS
lib_search_path.value = $$xcode_objects_path
QMAKE_MAC_XCODE_SETTINGS += lib_search_path
}
}
load(qt)

View File

@ -23,3 +23,9 @@ isEmpty(QMAKE_XCODE_VERSION) {
isEmpty(QMAKE_XCODE_VERSION): error("Could not resolve Xcode version.")
unset(xcode_version)
}
# These two variables are used by the xcode_dynamic_library_suffix
# feature, which allows Xcode to choose the Qt libraries to link to
# at build time, depending on the current Xcode SDK and configuration.
QMAKE_XCODE_LIBRARY_SUFFIX = $$qtPlatformTargetSuffix()
QMAKE_XCODE_LIBRARY_SUFFIX_SETTING = QT_LIBRARY_SUFFIX

View File

@ -25,6 +25,11 @@ if(win32|mac):!macx-xcode {
}
isEmpty(TARGETPATH): TARGETPATH = $$eval(QT.$${CXX_MODULE}.name)
# Insert the plugins URI into its meta data to enable usage
# of static plugins in QtDeclarative:
URI = $$replace(TARGETPATH, "/", ".")
QMAKE_MOC_OPTIONS += -Muri=$$URI
QMLTYPEFILE = $$_PRO_FILE_PWD_/plugins.qmltypes
exists($$QMLTYPEFILE): QML_FILES += $$QMLTYPEFILE

View File

@ -73,6 +73,88 @@ wince*:static:gui {
QTLIB += qmenu_wce.res
}
# static builds: link qml import plugins into the app.
if(contains(QT, qml)|contains(QT_PRIVATE, qml)): \
contains(QT_CONFIG, static):contains(TEMPLATE, .*app):!host_build:!no_import_scan {
# run qmlimportscanner
qtPrepareTool(QMLIMPORTSCANNER, qmlimportscanner)
for (MODULE, QT_MODULES) {
PATH = $$eval(QT.$${MODULE}.qml)
!isEmpty(PATH): QMLPATHS += $$PATH
}
QMLPATHS = $$unique(QMLPATHS)
for (QMLPATH, QMLPATHS): \
IMPORTPATHS += -importPath $$QMLPATH
#message(run $$QMLIMPORTSCANNER $$_PRO_FILE_PWD_ $$IMPORTPATHS)
JSON = $$system($$QMLIMPORTSCANNER $$_PRO_FILE_PWD_ $$IMPORTPATHS)
parseJson(JSON, IMPORTS)| error("Failed to parse qmlimportscanner output.")
!isEmpty(IMPORTS._KEYS_) {
# add import plugins to LIBS line
for (key, IMPORTS._KEYS_): {
PATH = $$eval(IMPORTS.$${key}.path)
PLUGIN = $$eval(IMPORTS.$${key}.plugin)
!isEmpty(PATH):!isEmpty(PLUGIN): LIBS *= -L$$PATH -l$$PLUGIN
}
# create qml_plugin_import.cpp
IMPORT_FILE_CONT = \
"// This file is autogenerated by qmake. It imports static plugin classes for" \
"// static plugins used by QML imports." \
"$${LITERAL_HASH}include <QtPlugin>"
for (key, IMPORTS._KEYS_) {
PLUGIN = $$eval(IMPORTS.$${key}.plugin)
CLASSNAME = $$eval(IMPORTS.$${key}.classname)
!isEmpty(PLUGIN) {
!isEmpty(CLASSNAME) {
!contains(ADDED_IMPORTS, $$PLUGIN) {
ADDED_IMPORTS += $$PLUGIN
IMPORT_FILE_CONT += "Q_IMPORT_PLUGIN($$CLASSNAME)"
}
} else {
error("Plugin $$PLUGIN is missing a classname entry, please add one to the qmldir file.")
}
}
}
QML_IMPORT_CPP = $$OUT_PWD/$$lower($$basename(TARGET))_qml_plugin_import.cpp
write_file($$QML_IMPORT_CPP, IMPORT_FILE_CONT)|error("Aborting.")
SOURCES += $$QML_IMPORT_CPP
QMAKE_CLEAN += $$QML_IMPORT_CPP
# copy qml files. this part is platform spesific.
macx {
# copy to Contents/Resources in the bundle.
QmlImports.path = Contents/Resources/
QmlImports.files *= $$QMLPATHS
QMAKE_BUNDLE_DATA += QmlImports
# place qt.conf in Contents/Resources in the app bundle
QT_CONF_CONTENTS = \
"[Paths]" \
"Imports = Resources/qml" \
"Qml2Imports = Resources/qml"
QT_CONF = "$$OUT_PWD/$${TARGET}.app/Contents/Resources/qt.conf"
write_file($$QT_CONF, QT_CONF_CONTENTS)|error("Aborting.")
} else: ios {
# flat bundle layout (no Contents/Resources)
QmlImports.files *= $$QMLPATHS
QMAKE_BUNDLE_DATA += QmlImports
# write qt.conf to OUT_PWD and make xcode copy it via QMAKE_BUNDLE_DATA
QT_CONF_CONTENTS = \
"[Paths]" \
"Imports = qml" \
"Qml2Imports = qml"
QT_CONF = "$$OUT_PWD/qt.conf"
write_file($$QT_CONF, QT_CONF_CONTENTS)|error("Aborting.")
QtConf.files = $$QT_CONF
QMAKE_BUNDLE_DATA += QtConf
}
}
}
QT_PLUGIN_VERIFY = DEPLOYMENT_PLUGIN
contains(QT_CONFIG, static) {
QT_PLUGIN_VERIFY += QTPLUGIN

View File

@ -29,6 +29,7 @@ QMAKE_QT_CONFIG = $$[QT_HOST_DATA/get]/mkspecs/qconfig.pri
include($$mod)
}
}
QT_MODULES = $$unique(QT_MODULES) # In case modules appear in multiple places
unset(QT_MODULE_INCLUDE_BASE)
unset(QT_MODULE_LIB_BASE)
unset(QT_MODULE_HOST_LIB_BASE)

View File

@ -23,13 +23,13 @@ defineReplace(qtLibraryTarget) {
}
defineTest(qtAddLibrary) {
warning("qtAddLibrary() is deprecated. Use qtAddModule() or QT+= instead.")
warning("qtAddLibrary() is deprecated. Use QT+= instead.")
# Reverse-engineer the module name from the library name.
for(var, QT_MODULES) {
isEqual(QT.$${var}.name, $$1) {
qtAddModule($$var, , LIBS)
return(true):break() # Yes, the break is insanity. But necessary.
return(true)
}
}
error("No module matching library '$$1' found.")

View File

@ -36,11 +36,34 @@ CONFIG(debug, debug|release): \
else: \
CONFIG -= debug
debug_and_release {
!macx-xcode: addExclusiveBuilds(debug, Debug, release, Release)
} else: fix_output_dirs {
debug: \
fixExclusiveOutputDirs(debug, release)
else: \
fixExclusiveOutputDirs(release, debug)
!macx-xcode {
debug_and_release {
addExclusiveBuilds(debug, Debug, release, Release)
} else: fix_output_dirs {
debug: \
fixExclusiveOutputDirs(debug, release)
else: \
fixExclusiveOutputDirs(release, debug)
}
} else {
# The Xcode generator always generates project files with
# debug and release configurations, regardless of whether
# or not debug_and_release is active.
for(build, $$list(debug release)) {
suffix =
contains(QT_CONFIG, debug_and_release) {
equals(build, debug): \
suffix = _debug
} else {
contains(QT_CONFIG, debug): \
suffix = _debug
}
library_suffix_$${build}.name = $$QMAKE_XCODE_LIBRARY_SUFFIX_SETTING
library_suffix_$${build}.value = $$suffix
library_suffix_$${build}.build = $$build
QMAKE_MAC_XCODE_SETTINGS += library_suffix_$${build}
CONFIG *= xcode_dynamic_library_suffix
}
}

View File

@ -10,34 +10,35 @@ check.files =
check.path = .
# If the test ends up in a different directory, we should cd to that directory.
# Note that qmake modifies DESTDIR after this file is processed,
# therefore, testing DESTDIR for emptiness is not sufficient.
# Also note that in debug-and-release mode we don't want to cd into the debug/release
# directory (e.g. if the test goes to foo/release/tst_thing.exe, we want to do
# cd foo && release/tst_thing.exe ).
MUNGED_DESTDIR=$$DESTDIR
MUNGED_TARGET=$$TARGET
win32:debug_and_release {
contains(DESTDIR,^release$)|contains(DESTDIR,^debug$):MUNGED_DESTDIR=
TESTRUN_CWD = $$DESTDIR
# In debug-and-release mode, the first ../ in TARGET breaks out of the debug/release
# subdirectory. However, since make's working directory is already outside of the
# debug/release subdirectory, this first ../ should be ignored when deciding if
# we have to change directory before running the test.
MUNGED_TARGET=$$replace(MUNGED_TARGET,^\\.\\./,)
debug_and_release:debug_and_release_target {
# But in debug-and-release-target mode we don't want to cd into the debug/release
# directory (e.g. if the test goes to foo/release/tst_thing.exe, we want to do
# 'cd foo && release/tst_thing.exe', not 'cd foo/release && tst_thing.exe').
TESTRUN_CWD ~= s/(release|debug)$//
TEST_TARGET_DIR = $$relative_path($$absolute_path($$DESTDIR, $$OUT_PWD), $$absolute_path($$TESTRUN_CWD, $$OUT_PWD))
}
!isEmpty(MUNGED_DESTDIR):!contains(MUNGED_DESTDIR,^\\./?):check.commands = cd $(DESTDIR) &&
contains(MUNGED_TARGET,.*/.*):check.commands = cd $(DESTDIR) &&
!isEmpty(TESTRUN_CWD):!contains(TESTRUN_CWD,^\\./?): \
check.commands = cd $$system_path($$TESTRUN_CWD) &&
# Allow for a custom test runner script
check.commands += $(TESTRUNNER)
mac {
app_bundle: check.commands += ./$(QMAKE_TARGET).app/Contents/MacOS/$(QMAKE_TARGET)
else: check.commands += ./$(QMAKE_TARGET)
unix {
isEmpty(TEST_TARGET_DIR): TEST_TARGET_DIR = .
mac:app_bundle: \
check.commands += $${TEST_TARGET_DIR}/$(QMAKE_TARGET).app/Contents/MacOS/$(QMAKE_TARGET)
else: \
check.commands += $${TEST_TARGET_DIR}/$(QMAKE_TARGET)
} else {
# Windows
!isEmpty(TEST_TARGET_DIR): TEST_TARGET_DIR = $${TEST_TARGET_DIR}$${QMAKE_DIR_SEP}
check.commands += $${TEST_TARGET_DIR}$(TARGET)
}
else:unix: check.commands += ./$(QMAKE_TARGET)
else: check.commands += $(DESTDIR_TARGET)
# Allow for custom arguments to tests
check.commands += $(TESTARGS)

View File

@ -1,4 +0,0 @@
linux*:CONFIG = wayland-scanner $$CONFIG
load(default_pre)

View File

@ -42,6 +42,7 @@ QMAKE_CXXFLAGS_SHLIB = $$QMAKE_CFLAGS_SHLIB
QMAKE_CXXFLAGS_STATIC_LIB = $$QMAKE_CFLAGS_STATIC_LIB
QMAKE_CXXFLAGS_YACC = $$QMAKE_CFLAGS_YACC
QMAKE_CXXFLAGS_THREAD = $$QMAKE_CFLAGS_THREAD
QMAKE_CXXFLAGS_EXCEPTIONS_OFF = -fno-exceptions
QMAKE_CXXFLAGS_CXX11 = -std=c++0x
QMAKE_INCDIR =

View File

@ -17,10 +17,13 @@ equals(TEMPLATE, app) {
# building by calling out to xcodebuild.
TEMPLATE = aux
CONFIG -= have_target qt staticlib dll
CONFIG =
SOURCES =
OBJECTIVE_SOURCES =
RESOURCES =
INSTALLS =
QMAKE_EXTRA_COMPILERS =
QMAKE_EXTRA_TARGETS =
TARGET_XCODE_PROJECT_DIR = $${TARGET}.xcodeproj
@ -41,6 +44,7 @@ equals(TEMPLATE, app) {
# And distclean
xcodebuild_distclean.commands = "$(DEL_FILE) -R $$TARGET_XCODE_PROJECT_DIR"
xcodebuild_distclean.depends = xcodebuild_clean
QMAKE_EXTRA_TARGETS += xcodebuild_distclean
distclean.depends = xcodebuild_distclean
QMAKE_EXTRA_TARGETS += distclean
@ -53,21 +57,11 @@ macx-xcode {
QMAKE_MAC_XCODE_SETTINGS += ios_device_family
}
isEmpty(QT_ARCH) {
# The iPhoneOS and iPhoneSimulator targets share the same toolchain,
# so when configure runs the arch tests it passes the correct sysroot,
# but we fail to pick up the architecture since we're not passing -arch
# yet. Xcode does not seem to have a way to run the shared toolchain
# in a way that will automatically do this (for example xcrun -sdk).
contains(QMAKE_MAC_SDK, iphoneos.*): QT_ARCH = arm
else: QT_ARCH = i386 # Simulator
}
# Be more specific about which architecture we're targeting
equals(QT_ARCH, arm): \
actual_archs = armv7
actual_archs = $$QMAKE_IOS_DEVICE_ARCHS
else: \
actual_archs = $$QT_ARCH
actual_archs = $$QMAKE_IOS_SIMULATOR_ARCHS
macx-xcode {
QMAKE_XCODE_ARCHS = $$actual_archs

View File

@ -0,0 +1,6 @@
load(default_pre)
# Check for supported Xcode versions
lessThan(QMAKE_XCODE_VERSION, "4.3"): \
error("This mkspec requires Xcode 4.3 or later")

View File

@ -0,0 +1,49 @@
equals(TEMPLATE, app):contains(QT, gui(-private)?) {
LIBS *= -L$$[QT_INSTALL_PLUGINS/get]/platforms
lib_name = qios
lib_path_and_base = $$[QT_INSTALL_PLUGINS/get]/platforms/lib$${lib_name}$$qtPlatformTargetSuffix()
LIBS += -l$${lib_name}$$qtPlatformTargetSuffix() $$fromfile($${lib_path_and_base}.prl, QMAKE_PRL_LIBS)
# By marking qt_registerPlatformPlugin as undefined, we ensure that
# the plugin.o translation unit is considered for inclusion in
# the final binary, which in turn ensures that the plugin's
# static initializer is included and run.
QMAKE_LFLAGS += -u _qt_registerPlatformPlugin
# We do link and dependency resolution for the platform plugin
# manually, since we know we always need the plugin, so we don't
# need to generate an import for it.
CONFIG -= import_qpa_plugin
!no_main_wrapper {
# We use ld to rename the _main symbol to _qt_main, so that we don't get a symbol clash
# with the _main we provide that calls UIApplicationMain. We need to make a copy of the
# original object file, as ld will not copy over DWARF debug information to the output
# file. Instead, it will inject a reference back to the original object file, so when
# Xcode runs dsymutil to make the final dSYM file it will still find the debug info
# for the object file that provided the original _main. This back-reference has the
# interesting side-effect of the debug information still referring to the original
# symbol name, so stack-traces will show both our wrapper main and the original
# user main as 'main', and adding a symbolic breakpoint for 'main' will break on
# both functions. Although a bit weird, it's a good thing, as the user will still be
# able to add symbolic breakpoints for 'main', not caring that the symbol is actually
# called 'qt_main' now.
isEmpty(OBJECTS_DIR): \
OBJECTS_DIR = .
!isEmpty(QMAKE_PRE_LINK): \
QMAKE_PRE_LINK += ";"
QMAKE_PRE_LINK += \
"for f in $(find $${OBJECTS_DIR} -name '*.o'); do" \
"(nm $f | grep -q 'T _main' && cp $f $f.original" \
"&& ld -r -alias _main _qt_main -unexported_symbol _main $f.original -o $f)" \
"|| true" \
"; done"
}
}
load(qt)

View File

@ -0,0 +1,12 @@
load(qt_config)
isEmpty(QT_ARCH) {
# The configure tests are run without QT_ARCH being resolved yet, which
# means we fail to pass -arch to the compiler, resulting in broke tests.
# As the Xcode toolchain doesn't seem to have a way to auto-detect the
# arch based on the SDK, we have to hard-code the arch for configure.
contains(QMAKE_MAC_SDK, iphoneos.*): \
QT_ARCH = arm
else: \ # Simulator
QT_ARCH = i386
}

View File

@ -10,11 +10,14 @@ QMAKE_MACOSX_DEPLOYMENT_TARGET =
QMAKE_IOS_DEPLOYMENT_TARGET = 5.0
INCLUDEPATH += $$PWD/ios
DEFINES += DARWIN_NO_CARBON QT_NO_CORESERVICES QT_NO_PRINTER QT_NO_PRINTDIALOG
DEFINES += DARWIN_NO_CARBON QT_NO_PRINTER QT_NO_PRINTDIALOG
# Universal target (iPhone and iPad)
QMAKE_IOS_TARGETED_DEVICE_FAMILY = 1,2
QMAKE_IOS_DEVICE_ARCHS = armv7
QMAKE_IOS_SIMULATOR_ARCHS = i386
include(../common/ios.conf)
include(../common/gcc-base-mac.conf)
include(../common/clang.conf)

View File

@ -1,7 +0,0 @@
isEmpty(QMAKE_INFO_PLIST) {
plist_template = $$absolute_path(../../$$[QMAKE_XSPEC]/Info.plist.$${TEMPLATE})
exists($$plist_template): QMAKE_INFO_PLIST = $$plist_template
}
load(default_post)

View File

@ -4,6 +4,12 @@
# OS X + Xcode
#
include(../$$[QMAKE_XSPEC]/qmake.conf)
QMAKESPEC = $$dirname(PWD)/$$[QMAKE_XSPEC]
include($$QMAKESPEC/qmake.conf)
MAKEFILE_GENERATOR = XCODE
# The active spec is now the original spec, but we still want
# Xcode specific blocks to be triggered.
CONFIG += macx-xcode

View File

@ -19,6 +19,7 @@ QOBJS=qtextcodec.o qutfcodec.o qstring.o qstringbuilder.o qtextstream.o qiodevic
qabstractfileengine.o qtemporaryfile.o qmap.o qmetatype.o qsettings.o qsystemerror.o qlibraryinfo.o \
qvariant.o qvsnprintf.o qlocale.o qlocale_tools.o qlinkedlist.o qnumeric.o \
qcryptographichash.o qxmlstream.o qxmlutils.o qlogging.o \
qjson.o qjsondocument.o qjsonparser.o qjsonarray.o qjsonobject.o qjsonvalue.o \
$(QTOBJS)
@ -80,6 +81,12 @@ DEPEND_SRC = \
$(SOURCE_PATH)/src/corelib/global/qlogging.cpp \
$(SOURCE_PATH)/src/corelib/plugin/qsystemlibrary.cpp \
$(SOURCE_PATH)/tools/shared/windows/registry.cpp \
$(SOURCE_PATH)/src/corelib/json/qjson.cpp \
$(SOURCE_PATH)/src/corelib/json/qjsondocument.cpp \
$(SOURCE_PATH)/src/corelib/json/qjsonparser.cpp \
$(SOURCE_PATH)/src/corelib/json/qjsonarray.cpp \
$(SOURCE_PATH)/src/corelib/json/qjsonobject.cpp \
$(SOURCE_PATH)/src/corelib/json/qjsonvalue.cpp \
$(QTSRCS)
CPPFLAGS = -g $(EXTRA_CPPFLAGS) \
@ -93,7 +100,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_CRYPTOGRAPHICHASH_ONLY_SHA1 -DQT_JSON_READONLY
CXXFLAGS = $(EXTRA_CXXFLAGS) $(CPPFLAGS)
@ -385,4 +392,22 @@ qsystemlibrary.o: $(SOURCE_PATH)/src/corelib/plugin/qsystemlibrary.cpp
registry.o: $(SOURCE_PATH)/tools/shared/windows/registry.cpp
$(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/tools/shared/windows/registry.cpp
qjson.o: $(SOURCE_PATH)/src/corelib/json/qjson.cpp
$(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/json/qjson.cpp
qjsondocument.o: $(SOURCE_PATH)/src/corelib/json/qjsondocument.cpp
$(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/json/qjsondocument.cpp
qjsonparser.o: $(SOURCE_PATH)/src/corelib/json/qjsonparser.cpp
$(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/json/qjsonparser.cpp
qjsonarray.o: $(SOURCE_PATH)/src/corelib/json/qjsonarray.cpp
$(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/json/qjsonarray.cpp
qjsonobject.o: $(SOURCE_PATH)/src/corelib/json/qjsonobject.cpp
$(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/json/qjsonobject.cpp
qjsonvalue.o: $(SOURCE_PATH)/src/corelib/json/qjsonvalue.cpp
$(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/json/qjsonvalue.cpp
# DO NOT DELETE THIS LINE -- make depend depends on it

View File

@ -41,7 +41,7 @@ CFLAGS_BARE = -c -Fo./ \
-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
-DUNICODE -DQT_CRYPTOGRAPHICHASH_ONLY_SHA1 -DQT_JSON_READONLY
CFLAGS = -Yuqmake_pch.h -FIqmake_pch.h -Fpqmake_pch.pch $(CFLAGS_BARE) $(CFLAGS) $(EXTRA_CPPFLAGS)
CXXFLAGS_BARE = $(CFLAGS_BARE)
@ -120,7 +120,13 @@ QTOBJS= \
qxmlstream.obj \
qxmlutils.obj \
qnumeric.obj \
qlogging.obj
qlogging.obj \
qjson.obj \
qjsondocument.obj \
qjsonparser.obj \
qjsonarray.obj \
qjsonobject.obj \
qjsonvalue.obj
first all: qmake.exe
@ -207,5 +213,8 @@ qmake_pch.obj:
{$(SOURCE_PATH)\src\corelib\xml}.cpp{}.obj::
$(CXX) $(CXXFLAGS) $<
{$(SOURCE_PATH)\src\corelib\json}.cpp{}.obj::
$(CXX) $(CXXFLAGS) $<
{$(SOURCE_PATH)\tools\shared\windows}.cpp{}.obj::
$(CXX) $(CXXFLAGS) $<

View File

@ -301,6 +301,8 @@ ProjectBuilderMakefileGenerator::writeSubDirs(QTextStream &t)
QString defaultConfig;
for(int as_release = 0; as_release < 2; as_release++)
{
QString configName = (as_release ? "Release" : "Debug");
QMap<QString, QString> settings;
settings.insert("COPY_PHASE_STRIP", (as_release ? "YES" : "NO"));
if(as_release)
@ -311,6 +313,12 @@ ProjectBuilderMakefileGenerator::writeSubDirs(QTextStream &t)
const ProStringList &l = project->values("QMAKE_MAC_XCODE_SETTINGS");
for(int i = 0; i < l.size(); ++i) {
ProString name = l.at(i);
const ProKey buildKey(name + ".build");
if (!project->isEmpty(buildKey)) {
const QString build = project->values(buildKey).first().toQString();
if (build.toLower() != configName.toLower())
continue;
}
const ProKey nkey(name + ".name");
if (!project->isEmpty(nkey))
name = project->first(nkey);
@ -319,10 +327,9 @@ ProjectBuilderMakefileGenerator::writeSubDirs(QTextStream &t)
}
}
QString name = (as_release ? "Release" : "Debug");
if (project->isActiveConfig("debug") != (bool)as_release)
defaultConfig = name;
QString key = keyFor("QMAKE_SUBDIR_PBX_BUILDCONFIG_" + name);
defaultConfig = configName;
QString key = keyFor("QMAKE_SUBDIR_PBX_BUILDCONFIG_" + configName);
project->values("QMAKE_SUBDIR_PBX_BUILDCONFIGS").append(key);
t << "\t\t" << key << " = {\n"
<< "\t\t\t" << writeSettings("isa", "XCBuildConfiguration", SettingsNoQuote) << ";\n"
@ -330,7 +337,7 @@ ProjectBuilderMakefileGenerator::writeSubDirs(QTextStream &t)
for (QMap<QString, QString>::Iterator set_it = settings.begin(); set_it != settings.end(); ++set_it)
t << "\t\t\t\t" << writeSettings(set_it.key(), set_it.value()) << ";\n";
t << "\t\t\t};\n"
<< "\t\t\t" << writeSettings("name", name) << ";\n"
<< "\t\t\t" << writeSettings("name", configName) << ";\n"
<< "\t\t};\n";
}
t << "\t\t" << keyFor("QMAKE_SUBDIR_PBX_BUILDCONFIG_LIST") << " = {\n"
@ -867,6 +874,20 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
debug_msg(1, "pbuilder: Found library (%s) via PRL %s (%s)",
opt.toLatin1().constData(), lib_file.toLatin1().constData(), library.toLatin1().constData());
remove = true;
if (project->isActiveConfig("xcode_dynamic_library_suffix")) {
QString suffixSetting = project->first("QMAKE_XCODE_LIBRARY_SUFFIX_SETTING").toQString();
if (!suffixSetting.isEmpty()) {
QString librarySuffix = project->first("QMAKE_XCODE_LIBRARY_SUFFIX").toQString();
suffixSetting = "$(" + suffixSetting + ")";
if (!librarySuffix.isEmpty()) {
library = library.replace(librarySuffix, suffixSetting);
name = name.remove(librarySuffix);
} else {
library = library.replace(name, name + suffixSetting);
}
}
}
}
}
}
@ -998,6 +1019,27 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
<< "\t\t\t" << writeSettings("shellScript", "make -C " + IoUtils::shellQuoteUnix(qmake_getpwd()) + " -f " + IoUtils::shellQuoteUnix(mkfile)) << ";\n"
<< "\t\t};\n";
}
if (!project->isEmpty("QMAKE_PRE_LINK")) {
QString phase_key = keyFor("QMAKE_PBX_PRELINK_BUILDPHASE");
project->values("QMAKE_PBX_BUILDPHASES").append(phase_key);
t << "\t\t" << phase_key << " = {\n"
<< "\t\t\t" << writeSettings("buildActionMask", "2147483647", SettingsNoQuote) << ";\n"
<< "\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"
<< "\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"
<< "\t\t\t" << writeSettings("name", "Qt Prelink") << ";\n"
<< "\t\t\t" << writeSettings("shellPath", "/bin/sh") << ";\n"
<< "\t\t\t" << writeSettings("shellScript", project->values("QMAKE_PRE_LINK")) << ";\n"
<< "\t\t};\n";
}
//LIBRARY BUILDPHASE
if(!project->isEmpty("QMAKE_PBX_LIBRARIES")) {
tmp = project->values("QMAKE_PBX_LIBRARIES");
@ -1023,6 +1065,24 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
<< "\t\t\t" << writeSettings("name", escapeFilePath(grp)) << ";\n"
<< "\t\t};\n";
}
if (!project->isEmpty("QMAKE_POST_LINK")) {
QString phase_key = keyFor("QMAKE_PBX_POSTLINK_BUILDPHASE");
project->values("QMAKE_PBX_BUILDPHASES").append(phase_key);
t << "\t\t" << phase_key << " = {\n"
<< "\t\t\t" << writeSettings("buildActionMask", "2147483647", SettingsNoQuote) << ";\n"
<< "\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 the phase is run after linking.
<< "\t\t\t" << writeSettings("inputPaths", ProStringList("$(TARGET_BUILD_DIR)/$(EXECUTABLE_PATH)"), SettingsAsList, 4) << ";\n"
<< "\t\t\t" << writeSettings("isa", "PBXShellScriptBuildPhase", SettingsNoQuote) << ";\n"
<< "\t\t\t" << writeSettings("runOnlyForDeploymentPostprocessing", "0", SettingsNoQuote) << ";\n"
<< "\t\t\t" << writeSettings("name", "Qt Postlink") << ";\n"
<< "\t\t\t" << writeSettings("shellPath", "/bin/sh") << ";\n"
<< "\t\t\t" << writeSettings("shellScript", project->values("QMAKE_POST_LINK")) << ";\n"
<< "\t\t};\n";
}
if (!project->isEmpty("DESTDIR")) {
QString phase_key = keyFor("QMAKE_PBX_TARGET_COPY_PHASE");
QString destDir = project->first("DESTDIR").toQString();
@ -1244,6 +1304,8 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
QString defaultConfig;
for(int as_release = 0; as_release < 2; as_release++)
{
QString configName = (as_release ? "Release" : "Debug");
QMap<QString, QString> settings;
settings.insert("COPY_PHASE_STRIP", (as_release ? "YES" : "NO"));
settings.insert("GCC_GENERATE_DEBUGGING_SYMBOLS", as_release ? "NO" : "YES");
@ -1255,6 +1317,12 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
const ProStringList &l = project->values("QMAKE_MAC_XCODE_SETTINGS");
for(int i = 0; i < l.size(); ++i) {
ProString name = l.at(i);
const ProKey buildKey(name + ".build");
if (!project->isEmpty(buildKey)) {
const QString build = project->values(buildKey).first().toQString();
if (build.toLower() != configName.toLower())
continue;
}
const QString value = project->values(ProKey(name + ".value")).join(QString(Option::field_sep));
const ProKey nkey(name + ".name");
if (!project->isEmpty(nkey))
@ -1271,11 +1339,10 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
settings.insert("PRODUCT_NAME", escapeFilePath(lib.toQString()));
}
QString name = (as_release ? "Release" : "Debug");
if (project->isActiveConfig("debug") != (bool)as_release)
defaultConfig = name;
defaultConfig = configName;
for (int i = 0; i < buildConfigGroups.size(); i++) {
QString key = keyFor("QMAKE_PBX_BUILDCONFIG_" + name + buildConfigGroups.at(i));
QString key = keyFor("QMAKE_PBX_BUILDCONFIG_" + configName + buildConfigGroups.at(i));
project->values(ProKey("QMAKE_PBX_BUILDCONFIGS_" + buildConfigGroups.at(i))).append(key);
t << "\t\t" << key << " = {\n"
<< "\t\t\t" << writeSettings("isa", "XCBuildConfiguration", SettingsNoQuote) << ";\n"
@ -1429,7 +1496,7 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
}
}
t << "\t\t\t};\n"
<< "\t\t\t" << writeSettings("name", name) << ";\n"
<< "\t\t\t" << writeSettings("name", configName) << ";\n"
<< "\t\t};\n";
}
}

View File

@ -3240,7 +3240,8 @@ MakefileGenerator::writePkgConfigFile()
}
}
}
t << var << "=" << val << endl;
if (!val.isEmpty())
t << var << "=" << val << endl;
}
t << endl;
@ -3331,8 +3332,7 @@ QString MakefileGenerator::installMetaFile(const ProKey &replace_rule, const QSt
{
QString ret;
if (project->isEmpty(replace_rule)
|| project->isActiveConfig("no_sed_meta_install")
|| project->isEmpty("QMAKE_STREAM_EDITOR")) {
|| project->isActiveConfig("no_sed_meta_install")) {
ret += "-$(INSTALL_FILE) \"" + src + "\" \"" + dst + "\"";
} else {
ret += "-$(SED)";

View File

@ -106,20 +106,8 @@ UnixMakefileGenerator::init()
return; /* subdirs is done */
}
//If the TARGET looks like a path split it into DESTDIR and the resulting TARGET
if(!project->isEmpty("TARGET")) {
if (!project->isEmpty("TARGET"))
project->values("TARGET") = escapeFilePaths(project->values("TARGET"));
ProString targ = unescapeFilePath(project->first("TARGET"));
int slsh = qMax(targ.lastIndexOf('/'), targ.lastIndexOf(Option::dir_sep));
if(slsh != -1) {
if(project->isEmpty("DESTDIR"))
project->values("DESTDIR").append("");
else if(project->first("DESTDIR").right(1) != Option::dir_sep)
project->values("DESTDIR") = ProStringList(project->first("DESTDIR") + Option::dir_sep);
project->values("DESTDIR") = ProStringList(project->first("DESTDIR") + targ.left(slsh+1));
project->values("TARGET") = ProStringList(targ.mid(slsh+1));
}
}
project->values("QMAKE_ORIG_TARGET") = project->values("TARGET");
project->values("QMAKE_ORIG_DESTDIR") = project->values("DESTDIR");

View File

@ -449,7 +449,7 @@ ProStringList VcprojGenerator::collectDependencies(QMakeProject *proj, QHash<QSt
if (!qmake_setpwd(dir))
fprintf(stderr, "Cannot find directory: %s", dir.toLatin1().constData());
}
Option::output_dir = Option::globals->shadowedPath(QDir::cleanPath(fi.absoluteFilePath()));
Option::output_dir = Option::globals->shadowedPath(QDir::cleanPath(dir));
if (tmp_proj.read(fn)) {
// Check if all requirements are fulfilled
if (!tmp_proj.isEmpty("QMAKE_FAILED_REQUIREMENTS")) {

View File

@ -274,20 +274,6 @@ Win32MakefileGenerator::processPrlFiles()
void Win32MakefileGenerator::processVars()
{
//If the TARGET looks like a path split it into DESTDIR and the resulting TARGET
if(!project->isEmpty("TARGET")) {
ProString targ = project->first("TARGET");
int slsh = qMax(targ.lastIndexOf('/'), targ.lastIndexOf(Option::dir_sep));
if(slsh != -1) {
if(project->isEmpty("DESTDIR"))
project->values("DESTDIR").append("");
else if(project->first("DESTDIR").right(1) != Option::dir_sep)
project->values("DESTDIR") = ProStringList(project->first("DESTDIR") + Option::dir_sep);
project->values("DESTDIR") = ProStringList(project->first("DESTDIR") + targ.left(slsh+1));
project->values("TARGET") = ProStringList(targ.mid(slsh+1));
}
}
project->values("QMAKE_ORIG_TARGET") = project->values("TARGET");
if (project->isEmpty("QMAKE_PROJECT_NAME"))
project->values("QMAKE_PROJECT_NAME") = project->values("QMAKE_ORIG_TARGET");
@ -315,6 +301,8 @@ void Win32MakefileGenerator::processVars()
project->values("QMAKE_COPY_FILE").append("$(COPY)");
if(project->isEmpty("QMAKE_COPY_DIR"))
project->values("QMAKE_COPY_DIR").append("xcopy /s /q /y /i");
if (project->isEmpty("QMAKE_STREAM_EDITOR"))
project->values("QMAKE_STREAM_EDITOR").append("$(QMAKE) -install sed");
if(project->isEmpty("QMAKE_INSTALL_FILE"))
project->values("QMAKE_INSTALL_FILE").append("$(COPY_FILE)");
if(project->isEmpty("QMAKE_INSTALL_PROGRAM"))

View File

@ -56,6 +56,11 @@
#include <qset.h>
#include <qstringlist.h>
#include <qtextstream.h>
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
# include <qjsondocument.h>
# include <qjsonobject.h>
# include <qjsonarray.h>
#endif
#ifdef PROEVALUATOR_THREAD_SAFE
# include <qthreadpool.h>
#endif
@ -101,7 +106,7 @@ enum TestFunc {
T_INVALID = 0, T_REQUIRES, T_GREATERTHAN, T_LESSTHAN, T_EQUALS,
T_EXISTS, T_EXPORT, T_CLEAR, T_UNSET, T_EVAL, T_CONFIG, T_SYSTEM,
T_DEFINED, T_CONTAINS, T_INFILE,
T_COUNT, T_ISEMPTY, T_INCLUDE, T_LOAD, T_DEBUG, T_LOG, T_MESSAGE, T_WARNING, T_ERROR, T_IF,
T_COUNT, T_ISEMPTY, T_PARSE_JSON, T_INCLUDE, T_LOAD, T_DEBUG, T_LOG, T_MESSAGE, T_WARNING, T_ERROR, T_IF,
T_MKPATH, T_WRITE_FILE, T_TOUCH, T_CACHE
};
@ -178,6 +183,9 @@ void QMakeEvaluator::initFunctionStatics()
{ "infile", T_INFILE },
{ "count", T_COUNT },
{ "isEmpty", T_ISEMPTY },
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
{ "parseJson", T_PARSE_JSON },
#endif
{ "load", T_LOAD },
{ "include", T_INCLUDE },
{ "debug", T_DEBUG },
@ -286,6 +294,75 @@ quoteValue(const ProString &val)
return ret;
}
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
static void addJsonValue(const QJsonValue &value, const QString &keyPrefix, ProValueMap *map);
static void insertJsonKeyValue(const QString &key, const QStringList &values, ProValueMap *map)
{
map->insert(ProKey(key), ProStringList(values));
}
static void addJsonArray(const QJsonArray &array, const QString &keyPrefix, ProValueMap *map)
{
QStringList keys;
for (int i = 0; i < array.count(); ++i) {
keys.append(QString::number(i));
addJsonValue(array.at(i), keyPrefix + QString::number(i), map);
}
insertJsonKeyValue(keyPrefix + QLatin1String("_KEYS_"), keys, map);
}
static void addJsonObject(const QJsonObject &object, const QString &keyPrefix, ProValueMap *map)
{
foreach (const QString &key, object.keys())
addJsonValue(object.value(key), keyPrefix + key, map);
insertJsonKeyValue(keyPrefix + QLatin1String("_KEYS_"), object.keys(), map);
}
static void addJsonValue(const QJsonValue &value, const QString &keyPrefix, ProValueMap *map)
{
switch (value.type()) {
case QJsonValue::Bool:
insertJsonKeyValue(keyPrefix, QStringList() << (value.toBool() ? QLatin1String("true") : QLatin1String("false")), map);
break;
case QJsonValue::Double:
insertJsonKeyValue(keyPrefix, QStringList() << QString::number(value.toDouble()), map);
break;
case QJsonValue::String:
insertJsonKeyValue(keyPrefix, QStringList() << value.toString(), map);
break;
case QJsonValue::Array:
addJsonArray(value.toArray(), keyPrefix + QLatin1Char('.'), map);
break;
case QJsonValue::Object:
addJsonObject(value.toObject(), keyPrefix + QLatin1Char('.'), map);
break;
default:
break;
}
}
static QMakeEvaluator::VisitReturn parseJsonInto(const QByteArray &json, const QString &into, ProValueMap *value)
{
QJsonDocument document = QJsonDocument::fromJson(json);
if (document.isNull())
return QMakeEvaluator::ReturnFalse;
QString currentKey = into + QLatin1Char('.');
// top-level item is either an array or object
if (document.isArray())
addJsonArray(document.array(), currentKey, value);
else if (document.isObject())
addJsonObject(document.object(), currentKey, value);
else
return QMakeEvaluator::ReturnFalse;
return QMakeEvaluator::ReturnTrue;
}
#endif
QMakeEvaluator::VisitReturn
QMakeEvaluator::writeFile(const QString &ctx, const QString &fn, QIODevice::OpenMode mode,
const QString &contents)
@ -1278,6 +1355,18 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
m_valuemapStack.top()[var] = statics.fakeValue;
return ReturnTrue;
}
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
case T_PARSE_JSON: {
if (args.count() != 2) {
evalError(fL1S("parseJson(variable, into) requires two arguments."));
return ReturnFalse;
}
QByteArray json = values(args.at(0).toKey()).join(QLatin1Char(' ')).toUtf8();
QString parseInto = args.at(1).toQString(m_tmp2);
return parseJsonInto(json, parseInto, &m_valuemapStack.top());
}
#endif
case T_INCLUDE: {
if (args.count() < 1 || args.count() > 3) {
evalError(fL1S("include(file, [into, [silent]]) requires one, two or three arguments."));

View File

@ -129,6 +129,7 @@ void QMakeEvaluator::initStatics()
statics.strhost_build = QLatin1String("host_build");
statics.strTEMPLATE = ProKey("TEMPLATE");
statics.strQMAKE_PLATFORM = ProKey("QMAKE_PLATFORM");
statics.strQMAKESPEC = ProKey("QMAKESPEC");
#ifdef PROEVALUATOR_FULL
statics.strREQUIRES = ProKey("REQUIRES");
#endif
@ -939,6 +940,12 @@ void QMakeEvaluator::visitProVariable(
setTemplate();
else if (varName == statics.strQMAKE_PLATFORM)
m_featureRoots = 0;
else if (varName == statics.strQMAKESPEC) {
if (!values(varName).isEmpty()) {
m_qmakespec = values(varName).first().toQString();
m_featureRoots = 0;
}
}
#ifdef PROEVALUATOR_FULL
else if (varName == statics.strREQUIRES)
checkRequirements(values(varName));
@ -1160,7 +1167,7 @@ bool QMakeEvaluator::loadSpecInternal()
m_qmakespec = orig_spec.toQString();
# endif
#endif
valuesRef(ProKey("QMAKESPEC")) << ProString(m_qmakespec);
valuesRef(ProKey("QMAKESPEC")) = ProString(m_qmakespec);
m_qmakespecName = IoUtils::fileName(m_qmakespec).toString();
// This also ensures that m_featureRoots is valid.
if (evaluateFeatureFile(QLatin1String("spec_post.prf")) != ReturnTrue)
@ -1271,6 +1278,14 @@ void QMakeEvaluator::evaluateCommand(const QString &cmds, const QString &where)
}
}
void QMakeEvaluator::applyExtraConfigs()
{
if (m_extraConfigs.isEmpty())
return;
evaluateCommand(fL1S("CONFIG += ") + m_extraConfigs.join(QLatin1Char(' ')), fL1S("(extra configs)"));
}
QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateConfigFeatures()
{
QSet<QString> processed;
@ -1365,10 +1380,6 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::visitProFile(
loadDefaults();
}
for (ProValueMap::ConstIterator it = m_extraVars.constBegin();
it != m_extraVars.constEnd(); ++it)
m_valuemapStack.first().insert(it.key(), it.value());
VisitReturn vr;
m_handler->aboutToEval(currentProFile(), pro, type);
@ -1377,14 +1388,23 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::visitProFile(
if (flags & LoadPreFiles) {
setupProject();
for (ProValueMap::ConstIterator it = m_extraVars.constBegin();
it != m_extraVars.constEnd(); ++it)
m_valuemapStack.first().insert(it.key(), it.value());
// In case default_pre needs to make decisions based on the current
// build pass configuration.
applyExtraConfigs();
if ((vr = evaluateFeatureFile(QLatin1String("default_pre.prf"))) == ReturnError)
goto failed;
evaluateCommand(m_option->precmds, fL1S("(command line)"));
if (!m_option->precmds.isEmpty()) {
evaluateCommand(m_option->precmds, fL1S("(command line)"));
// After user configs, to override them
if (!m_extraConfigs.isEmpty())
evaluateCommand(fL1S("CONFIG += ") + m_extraConfigs.join(QLatin1Char(' ')), fL1S("(extra configs)"));
// Again, after user configs, to override them
applyExtraConfigs();
}
}
debugMsg(1, "visiting file %s", qPrintable(pro->fileName()));
@ -1398,8 +1418,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::visitProFile(
// Again, to ensure the project does not mess with us.
// Specifically, do not allow a project to override debug/release within a
// debug_and_release build pass - it's too late for that at this point anyway.
if (!m_extraConfigs.isEmpty())
evaluateCommand(fL1S("CONFIG += ") + m_extraConfigs.join(QLatin1Char(' ')), fL1S("(extra configs)"));
applyExtraConfigs();
if ((vr = evaluateFeatureFile(QLatin1String("default_post.prf"))) == ReturnError)
goto failed;

View File

@ -170,6 +170,7 @@ public:
void initFrom(const QMakeEvaluator &other);
void setupProject();
void evaluateCommand(const QString &cmds, const QString &where);
void applyExtraConfigs();
VisitReturn visitProFile(ProFile *pro, QMakeHandler::EvalFileType type,
LoadFlags flags);
VisitReturn visitProBlock(ProFile *pro, const ushort *tokPtr);

View File

@ -91,6 +91,7 @@ struct QMakeStatics {
QString strhost_build;
ProKey strTEMPLATE;
ProKey strQMAKE_PLATFORM;
ProKey strQMAKESPEC;
#ifdef PROEVALUATOR_FULL
ProKey strREQUIRES;
#endif

View File

@ -57,6 +57,128 @@
QT_BEGIN_NAMESPACE
#ifdef Q_OS_WIN
struct SedSubst {
QRegExp from;
QString to;
};
Q_DECLARE_TYPEINFO(SedSubst, Q_MOVABLE_TYPE);
static int doSed(int argc, char **argv)
{
QVector<SedSubst> substs;
QList<const char *> inFiles;
for (int i = 0; i < argc; i++) {
if (!strcmp(argv[i], "-e")) {
if (++i == argc) {
fprintf(stderr, "Error: sed option -e requires an argument\n");
return 3;
}
QString cmd = QString::fromLocal8Bit(argv[i]);
for (int j = 0; j < cmd.length(); j++) {
QChar c = cmd.at(j);
if (c.isSpace())
continue;
if (c != QLatin1Char('s')) {
fprintf(stderr, "Error: unrecognized sed command '%c'\n", c.toLatin1());
return 3;
}
QChar sep = ++j < cmd.length() ? cmd.at(j) : QChar();
bool escaped = false;
int phase = 1;
QStringList phases;
QString curr;
while (++j < cmd.length()) {
c = cmd.at(j);
if (!escaped) {
if (c == QLatin1Char(';'))
break;
if (c == QLatin1Char('\\')) {
escaped = true;
continue;
}
if (c == sep) {
phase++;
phases << curr;
curr.clear();
continue;
}
}
if (phase == 1
&& (c == QLatin1Char('+') || c == QLatin1Char('?')
|| c == QLatin1Char('{') || c == QLatin1Char('}')
|| c == QLatin1Char('(') || c == QLatin1Char(')'))) {
// translate sed rx to QRegExp
escaped ^= 1;
}
if (escaped) {
escaped = false;
curr += QLatin1Char('\\');
}
curr += c;
}
if (escaped) {
fprintf(stderr, "Error: unterminated escape sequence in sed s command\n");
return 3;
}
if (phase != 3) {
fprintf(stderr, "Error: sed s command requires three arguments (%d, %c, %s)\n", phase, sep.toLatin1(), qPrintable(curr));
return 3;
}
if (curr != QLatin1String("g")) {
fprintf(stderr, "Error: sed s command must be used with the g option (only)\n");
return 3;
}
SedSubst subst;
subst.from = QRegExp(phases.at(0));
subst.to = phases.at(1);
substs << subst;
}
} else if (argv[i][0] == '-' && argv[i][1] != 0) {
fprintf(stderr, "Error: unrecognized sed option '%s'\n", argv[i]);
return 3;
} else {
inFiles << argv[i];
}
}
if (inFiles.isEmpty())
inFiles << "-";
foreach (const char *inFile, inFiles) {
FILE *f;
if (!strcmp(inFile, "-")) {
f = stdin;
} else if (!(f = fopen(inFile, "r"))) {
perror(inFile);
return 1;
}
QTextStream is(f);
while (!is.atEnd()) {
QString line = is.readLine();
for (int i = 0; i < substs.size(); i++)
line.replace(substs.at(i).from, substs.at(i).to);
puts(qPrintable(line));
}
if (f != stdin)
fclose(f);
}
return 0;
}
static int doInstall(int argc, char **argv)
{
if (!argc) {
fprintf(stderr, "Error: -install requires further arguments\n");
return 3;
}
if (!strcmp(argv[0], "sed"))
return doSed(argc - 1, argv + 1);
fprintf(stderr, "Error: unrecognized -install subcommand '%s'\n", argv[0]);
return 3;
}
#endif // Q_OS_WIN
/* This is to work around lame implementation on Darwin. It has been noted that the getpwd(3) function
is much too slow, and called much too often inside of Qt (every fileFixify). With this we use a locally
cached copy because I can control all the times it is set (because Qt never sets the pwd under me).
@ -85,6 +207,12 @@ int runQMake(int argc, char **argv)
// This is particularly important for things like QtCreator and scripted builds.
setvbuf(stdout, (char *)NULL, _IONBF, 0);
#ifdef Q_OS_WIN
// Workaround for inferior/missing command line tools on Windows: make our own!
if (argc >= 2 && !strcmp(argv[1], "-install"))
return doInstall(argc - 2, argv + 2);
#endif
QMakeVfs vfs;
Option::vfs = &vfs;
QMakeGlobals globals;

View File

@ -83,7 +83,13 @@ bootstrap { #Qt code
qvsnprintf.cpp \
qxmlstream.cpp \
qxmlutils.cpp \
qlogging.cpp
qlogging.cpp \
qjson.cpp \
qjsondocument.cpp \
qjsonparser.cpp \
qjsonarray.cpp \
qjsonobject.cpp \
qjsonvalue.cpp
HEADERS+= \
qbitarray.h \
@ -126,7 +132,14 @@ bootstrap { #Qt code
quuid.h \
qvector.h \
qxmlstream.h \
qxmlutils.h
qxmlutils.h \
qjson.h \
qjsondocument.h \
qjsonparser.h \
qjsonwriter.h \
qjsonarray.h \
qjsonobject.h \
qjsonvalue.h
unix {
SOURCES += qfilesystemengine_unix.cpp qfilesystemiterator_unix.cpp qfsfileengine_unix.cpp

View File

@ -20,6 +20,7 @@ VPATH += $$QT_SOURCE_TREE/src/corelib/global \
$$QT_SOURCE_TREE/src/corelib/plugin \
$$QT_SOURCE_TREE/src/corelib/xml \
$$QT_SOURCE_TREE/src/corelib/io \
$$QT_SOURCE_TREE/src/corelib/json \
$$QT_SOURCE_TREE/tools/shared/windows
INCLUDEPATH += . \

View File

@ -84,7 +84,7 @@ bool IndexRangeCache::IndexRange::operator<(const IndexRange& rhs) const
#if defined(_MSC_VER) && _MSC_VER < 1600
return std::tr1::make_tuple(type, offset, count) < std::tr1::make_tuple(rhs.type, rhs.offset, rhs.count);
#else
return std::make_tuple(type, offset, count) < std::tr1::make_tuple(rhs.type, rhs.offset, rhs.count);
return std::make_tuple(type, offset, count) < std::make_tuple(rhs.type, rhs.offset, rhs.count);
#endif
}

View File

@ -9,21 +9,21 @@
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<meta-data android:name="android.app.lib_name" android:value="-- %%INSERT_APP_LIB_NAME%% --"/>
<meta-data android:name="android.app.qt_sources_resource_id" android:resource="@array/qt_sources"/>
<meta-data android:value="@string/repository" android:name="android.app.repository"/>
<meta-data android:name="android.app.repository" android:value="default"/>
<meta-data android:name="android.app.qt_libs_resource_id" android:resource="@array/qt_libs"/>
<meta-data android:name="android.app.bundled_libs_resource_id" android:resource="@array/bundled_libs"/>
<meta-data android:value="@string/app_lib_name" android:name="android.app.lib_name"/>
<!-- Deploy Qt libs as part of package -->
<meta-data android:value="1" android:name="android.app.bundle_local_qt_libs"/>
<meta-data android:name="android.app.bundle_local_qt_libs" android:value="-- %%BUNDLE_LOCAL_QT_LIBS%% --"/>
<meta-data android:name="android.app.bundled_in_lib_resource_id" android:resource="@array/bundled_in_lib"/>
<meta-data android:name="android.app.bundled_in_assets_resource_id" android:resource="@array/bundled_in_assets"/>
<!-- Run with local libs -->
<meta-data android:value="1" android:name="android.app.use_local_qt_libs"/>
<meta-data android:value="/data/local/tmp/qt/" android:name="android.app.libs_prefix"/>
<meta-data android:value="@string/local_libs" android:name="android.app.load_local_libs"/>
<meta-data android:value="@string/local_jars" android:name="android.app.load_local_jars"/>
<meta-data android:value="@string/init_classes" android:name="android.app.static_init_classes"/>
<meta-data android:name="android.app.use_local_qt_libs" android:value="-- %%USE_LOCAL_QT_LIBS%% --"/>
<meta-data android:name="android.app.libs_prefix" android:value="/data/local/tmp/qt/"/>
<meta-data android:name="android.app.load_local_libs" android:value="-- %%INSERT_LOCAL_LIBS%% --"/>
<meta-data android:name="android.app.load_local_jars" android:value="-- %%INSERT_LOCAL_JARS%% --"/>
<meta-data android:name="android.app.static_init_classes" android:value="-- %%INSERT_INIT_CLASSES%% --"/>
<!-- Messages maps -->
<meta-data android:value="@string/ministro_not_found_msg" android:name="android.app.ministro_not_found_msg"/>
<meta-data android:value="@string/ministro_needed_msg" android:name="android.app.ministro_needed_msg"/>

View File

@ -3,7 +3,6 @@
<array name="qt_sources">
<item>https://download.qt-project.org/ministro/android/qt5/latest</item>
</array>
<string name="repository">default</string>
<!-- The following is handled automatically by the deployment tool. It should
not be edited manually. -->

View File

@ -1,10 +1,6 @@
<?xml version='1.0' encoding='utf-8'?>
<resources>
<string name="app_name"><!-- %%INSERT_APP_NAME%% --></string>
<string name="app_lib_name"><!-- %%INSERT_APP_LIB_NAME%% --></string>
<string name="local_libs"><!-- %%INSERT_LOCAL_LIBS%% --></string>
<string name="local_jars"><!-- %%INSERT_LOCAL_JARS%% --></string>
<string name="init_classes"><!-- %%INSERT_INIT_CLASSES%% --></string>
<string name="ministro_not_found_msg">Can\'t find Ministro service.\nThe application can\'t start.</string>
<string name="ministro_needed_msg">This application requires Ministro service. Would you like to install it?</string>

View File

@ -489,6 +489,14 @@ public class QtActivity extends Activity
+ "\tQML2_IMPORT_PATH=" + localPrefix + "/qml"
+ "\tQML_IMPORT_PATH=" + localPrefix + "/imports"
+ "\tQT_PLUGIN_PATH=" + localPrefix + "/plugins");
Intent intent = getIntent();
if (intent != null) {
String parameters = intent.getStringExtra("applicationArguments");
if (parameters != null)
loaderParams.putString(APPLICATION_PARAMETERS_KEY, parameters.replace(' ', '\t'));
}
loadApplication(loaderParams);
return;
}

View File

@ -22,7 +22,7 @@ index 610a5ef..95a6961 100644
+#if defined(_MSC_VER) && _MSC_VER < 1600
+ return std::tr1::make_tuple(type, offset, count) < std::tr1::make_tuple(rhs.type, rhs.offset, rhs.count);
+#else
+ return std::make_tuple(type, offset, count) < std::tr1::make_tuple(rhs.type, rhs.offset, rhs.count);
+ return std::make_tuple(type, offset, count) < std::make_tuple(rhs.type, rhs.offset, rhs.count);
+#endif
}

View File

@ -106,14 +106,6 @@ QByteArray QUtf8::convertFromUnicode(const QChar *uc, int len, QTextCodec::Conve
if (u < 0x0800) {
*cursor++ = 0xc0 | ((uchar) (u >> 6));
} else {
// is it one of the Unicode non-characters?
if (QChar::isNonCharacter(u)) {
*cursor++ = replacement;
++ch;
++invalid;
continue;
}
if (QChar::requiresSurrogates(u)) {
*cursor++ = 0xf0 | ((uchar) (u >> 18));
*cursor++ = 0x80 | (((uchar) (u >> 12)) & 0x3f);
@ -180,15 +172,14 @@ QString QUtf8::convertToUnicode(const char *chars, int len, QTextCodec::Converte
--need;
if (!need) {
// utf-8 bom composes into 0xfeff code point
bool nonCharacter;
if (!headerdone && uc == 0xfeff) {
// don't do anything, just skip the BOM
} else if (!(nonCharacter = QChar::isNonCharacter(uc)) && QChar::requiresSurrogates(uc) && uc <= QChar::LastValidCodePoint) {
} else if (QChar::requiresSurrogates(uc) && uc <= QChar::LastValidCodePoint) {
// surrogate pair
Q_ASSERT((qch - (ushort*)result.unicode()) + 2 < result.length());
*qch++ = QChar::highSurrogate(uc);
*qch++ = QChar::lowSurrogate(uc);
} else if ((uc < min_uc) || QChar::isSurrogate(uc) || nonCharacter || uc > QChar::LastValidCodePoint) {
} else if ((uc < min_uc) || QChar::isSurrogate(uc) || uc > QChar::LastValidCodePoint) {
// error: overlong sequence, UTF16 surrogate or non-character
*qch++ = replacement;
++invalid;

View File

@ -273,3 +273,33 @@ QString onlyLetters(const QString &in)
return out;
}
//! [23]
//! [24]
QVector<int> a, b;
a.resize(100000); // make a big vector filled with 0.
QVector<int>::iterator i = a.begin();
// WRONG way of using the iterator i:
b = a;
/*
Now we should be careful with iterator i since it will point to shared data
If we do *i = 4 then we would change the shared instance (both vectors)
The behavior differs from STL containers. Avoid doing such things in Qt.
*/
a[0] = 5;
/*
Container a is now detached from the shared data,
and even though i was an iterator from the container a, it now works as an iterator in b.
Here the situation is that (*i) == 0.
*/
b.clear(); // Now the iterator i is completely invalid.
int j = *i; // Undefined behavior!
/*
The data from b (which i pointed to) is gone.
This would be well-defined with STL containers (and (*i) == 5),
but with QVector this is likely to crash.
*/
//! [24]

View File

@ -67,24 +67,45 @@ QList<UsbEntry> usbEntries() {
return entries;
}
void main(int argc, char *argv[])
//![20]
void myCategoryFilter(QLoggingCategory *);
//![20]
//![21]
QLoggingCategory::CategoryFilter oldCategoryFilter;
void myCategoryFilter(QLoggingCategory *category)
{
// configure qt.driver.usb category here, otherwise forward to to default filter.
if (qstrcmp(category->categoryName(), "qt.driver.usb") == 0)
category->setEnabled(QtDebugMsg, true);
else
oldCategoryFilter(category);
}
//![21]
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
//![2]
// don't run the expensive code if the string won't print
if (QT_DRIVER_USB().isDebugEnabled()) {
QStringList items;
foreach (const UsbEntry &entry, usbEntries())
items << QString("%1 (%2)").arg(entry.id, entry.classtype);
qCDebug(QT_DRIVER_USB) << "devices: " << items;
}
QLoggingCategory::setFilterRules(QStringLiteral("qt.driver.usb.debug=true"));
//![2]
//![22]
// ...
oldCategoryFilter = QLoggingCategory::installFilter(myCategoryFilter);
//![22]
//![3]
qSetMessagePattern("%{category} %{message}");
//![3]
//![4]
// usbEntries() will only be called if QT_DRIVER_USB category is enabled
qCDebug(QT_DRIVER_USB) << "devices: " << usbEntries();
//![3]
//![4]
{
//![10]
@ -106,8 +127,7 @@ void main(int argc, char *argv[])
qCCritical(category) << "a critical message";
//![12]
}
return 0;
}
//![20]
void myCategoryFilter(QLoggingCategory *);
//![20]

View File

@ -533,10 +533,18 @@
This problem doesn't occur with functions that return a const or
non-const reference to a container.
\section3 Implicit sharing iterator problem
\l{Implicit sharing} has another consequence on STL-style
iterators: You must not take a copy of a container while
non-const iterators are active on that container. Java-style
iterators don't suffer from that limitation.
iterators: you should avoid copying a container while
iterators are active on that container. The iterators
point to an internal structure, and if you copy a container
you should be very careful with your iterators. E.g:
\snippet code/doc_src_containers.cpp 24
The above example only shows a problem with QVector, but
the problem exists for all the implicitly shared Qt containers.
\keyword foreach
\section1 The foreach Keyword

View File

@ -89,9 +89,12 @@
of data. Objects can easily be assigned, sent as function arguments,
and returned from functions.
Implicit sharing takes place behind the scenes; the programmer
does not need to worry about it. Even in multithreaded
applications, implicit sharing takes place, as explained in
Implicit sharing mostly takes place behind the scenes;
the programmer rarely needs to worry about it. However, Qt's
container iterators have different behavior than those from
the STL. Read \l{Implicit sharing iterator problem}.
In multithreaded applications, implicit sharing takes place, as explained in
\l{Thread-Support in Qt Modules#Threads and Implicitly Shared Classes}
{Threads and Implicitly Shared Classes}.
@ -105,9 +108,10 @@
greater than one. (This is often called \e {copy-on-write} or
\e {value semantics}.)
An implicitly shared class has total control of its internal data. In
An implicitly shared class has control of its internal data. In
any member functions that modify its data, it automatically detaches
before modifying the data.
before modifying the data. Notice, however, the special case with
container iterators; see \l{Implicit sharing iterator problem}.
The QPen class, which uses implicit sharing, detaches from the shared
data in all member functions that change the internal data.
@ -133,9 +137,9 @@
In this example, \c p1 and \c p2 share data until QPainter::begin()
is called for \c p2, because painting a pixmap will modify it.
\warning Do not copy an implicitly shared container (QMap,
QVector, etc.) while you are iterating over it using an non-const
\l{STL-style iterators}{STL-style iterator}.
\warning Be careful with copying an implicitly shared container
(QMap, QVector, etc.) while you use
\l{STL-style iterators}{STL-style iterator}. See \l{Implicit sharing iterator problem}.
\keyword implicitly shared classes
\annotatedlist shared

View File

@ -28,6 +28,7 @@
/*!
\page signalsandslots.html
\title Signals & Slots
\keyword Signals and Slots
\ingroup qt-basic-concepts
\brief An overview of Qt's signals and slots inter-object
communication mechanism.

View File

@ -199,31 +199,6 @@
still important.
On Linux, Valgrind and Helgrind can help detect threading errors.
The anatomy of QThread is quite interesting:
\list
\li QThread does not live in the new thread where \l{QThread::}{run()} is
executed. It lives in the old thread.
\li Most QThread methods are the thread's control interface and are meant to
be called from the old thread. Do not move this interface to the newly
created thread using \l{QObject::}{moveToThread()}; i.e., calling
\l{QObject::moveToThread()}{moveToThread(this)} is regarded as bad
practice.
\li \l{QThread::}{exec()} and the static methods
\l{QThread::}{usleep()}, \l{QThread::}{msleep()},
\l{QThread::}{sleep()} are meant to be called from the newly created
thread.
\li Additional members defined in the QThread subclass are
accessible by both threads. The developer is responsible for
coordinating access. A typical strategy is to set the members before
\l{QThread::}{start()} is called. Once the worker thread is running,
the main thread should not touch the additional members anymore. After
the worker has terminated, the main thread can access the additional
members again. This is a convenient strategy for passing parameters to a
thread before it is started as well as for collecting the result once it
has terminated.
\endlist
\section2 Protecting the Integrity of Data
When writing a multithread application, extra care must be taken to avoid

View File

@ -123,7 +123,7 @@
\nextpage Synchronizing Threads
Qt offers many classes and functions for working with threads. Below are
three different approaches that Qt programmers can use to implement
four different approaches that Qt programmers can use to implement
multithreaded applications.
@ -163,19 +163,47 @@
\section1 Qt Concurrent: Using a High-level API
The \l{Qt Concurrent} module provides high-level functions that deal with some
common parallel computation patterns: map, filter, and reduce. Unlike QThread
and QRunnable, these functions do not require the use of low-level threading
primitives such as mutexes or semaphores. \l {Qt Concurrent} will automatically
adjust the number of threads used according to the number of processor cores
available, so applications written today will continue to scale when deployed
later on a system with more cores.
common parallel computation patterns: map, filter, and reduce. Unlike using
QThread and QRunnable, these functions never require the use of \l{Synchronizing
Threads#Low-Level Synchronization Primitives}{low-level threading primitives}
such as mutexes or semaphores. Instead, they return a QFuture object which can
be used to retrieve the functions' results when they are ready. QFuture can
also be used to query computation progress and to pause/resume/cancel the
computation. For convenience, QFutureWatcher enables interactions with
\l{QFuture}s via signals and slots.
This module also provides the QtConcurrent::run() function, which can run
any function in a thread managed by the global QThreadPool.
\l{Qt Concurrent}'s map, filter and reduce algorithms automatically distribute
computation across all available processor cores, so applications written today
will continue to scale when deployed later on a system with more cores.
This module also provides the QtConcurrent::run() function, which can run any
function in another thread. However, QtConcurrent::run() only supports a subset
of features available to the map, filter and reduce functions. The QFuture
can be used to retrieve the function's return value and to check if the thread
is running. However, a call to QtConcurrent::run() uses one thread only, cannot
be paused/resumed/canceled, and cannot be queried for progress.
See the \l{Qt Concurrent} module documentation for details on the individual functions.
\section1 WorkerScript: Threading in QML
The WorkerScript QML type lets JavaScript code run in parallel with the GUI
thread.
Each WorkerScript instance can have one \c{.js} script attached to it. When
WorkerScript::sendMessage() is called, the script will run in a separate thread
(and a separate \l{QQmlContext}{QML context}). When the script finishes
running, it can send a reply back to the GUI thread which will invoke the
WorkerScript::onMessage() signal handler.
Using a WorkerScript is similar to using a worker QObject that has been moved
to another thread. Data is transferred between threads via signals.
See the WorkerScript documentation for details on how to implement the script,
and for a list of data types that can be passed between threads.
\section1 Choosing an Appropriate Approach
As demonstrated above, Qt provides different solutions for developing threaded
@ -187,52 +215,62 @@
\table
\header
\li Feature/Characteristic
\li Feature
\li QThread
\li QRunnable
\li Qt Concurrent\sup{*}
\li QRunnable and QThreadPool
\li QtConcurrent::run()
\li Qt Concurrent (Map, Filter, Reduce)
\li WorkerScript
\row
\li Supports different thread priorities
\li API
\li C++
\li C++
\li C++
\li C++
\li QML
\row
\li Thread priority can be specified
\li Yes
\li Yes
\li
\li
\li
\row
\li Supports an event loop
\li Thread can run an event loop
\li Yes
\li
\li
\li
\li
\row
\li Supports transferring data to the thread using signals
\li Thread can receive data updates through signals
\li Yes (received by a worker QObject)
\li
\li
\li
\li Yes (received by WorkerScript)
\row
\li Supports controlling the thread using signals
\li Thread can be controlled using signals
\li Yes (received by QThread)
\li
\li
\li Yes (received by QFutureWatcher)
\li
\row
\li Supports thread reuse
\li Thread can be monitored through a QFuture
\li
\li
\li Partially
\li Yes
\li Yes
\li
\row
\li Task-oriented
\li Built-in ability to pause/resume/cancel
\li
\li Yes
\li Yes
\row
\li High level API
\li
\li
\li Yes
\row
\li Supports pausing/resuming/canceling
\li
\li
\li Yes
\endtable
\sup{\e{*Except QtConcurrent::run(), which is like QRunnable}}
\section2 Example Use Cases
@ -244,7 +282,7 @@
\li Solution
\row
\li One call
\li Run a linear function within another thread, optionally with progress
\li Run a new linear function within another thread, optionally with progress
updates during the run.
\li Qt provides different solutions:
\list
@ -256,6 +294,13 @@
\li Run the function using QtConcurrent::run(). Write to a \l{Synchronizing
Threads}{thread-safe variable} to update progress.
\endlist
\row
\li One call
\li Run an existing function within another thread and get its return value.
\li Run the function using QtConcurrent::run(). Have a QFutureWatcher emit
the \l{QFutureWatcher::}{finished()} signal when the function has
returned, and call QFutureWatcher::result() to get the function's return
value.
\row
\li One call
\li Perform an operation on all items of a container, using all available
@ -263,8 +308,17 @@
\li Use Qt Concurrent's \l{QtConcurrent::}{filter()} function to select
container elements, and the \l{QtConcurrent::}{map()} function to apply
an operation to each element. To fold the output into a single result,
use \l{QtConcurrent::}{filterReduced()} and \l{QtConcurrent::}{mapReduced()}
instead.
use \l{QtConcurrent::}{filteredReduced()} and
\l{QtConcurrent::}{mappedReduced()} instead.
\row
\li One call/Permanent
\li Perfrom a long computation in a pure QML application, and update the GUI
when the results are ready.
\li Place the computation code in a \c{.js} script and attach it to a
WorkerScript instance. Call \l{WorkerScript::}{sendMessage()} to start the
computation in a new thread. Let the script call WorkerScript::sendMessage()
too, to pass the result back to the GUI thread. Handle the result in
\l{WorkerScript::}{onMessage} and update the GUI there.
\row
\li Permanent
\li Have an object living in another thread that can perform different

View File

@ -165,6 +165,13 @@
# /* Compatibility with older Clang versions */
# define __has_extension __has_feature
# endif
# if defined(__APPLE__)
/* Apple/clang specific features */
# define Q_DECL_CF_RETURNS_RETAINED __attribute__((cf_returns_retained))
# ifdef __OBJC__
# define Q_DECL_NS_RETURNS_AUTORELEASED __attribute__((ns_returns_autoreleased))
# endif
# endif
# else
/* Plain GCC */
# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 405
@ -628,14 +635,6 @@
# endif
#endif // Q_CC_CLANG
#if defined(Q_CC_CLANG) && defined(__APPLE__)
/* Apple/clang specific features */
# define Q_DECL_CF_RETURNS_RETAINED __attribute__((cf_returns_retained))
# ifdef __OBJC__
# define Q_DECL_NS_RETURNS_AUTORELEASED __attribute__((ns_returns_autoreleased))
# endif
#endif
#if defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && !defined(Q_CC_CLANG)
# if defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L
# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 403
@ -704,15 +703,20 @@
# if _MSC_VER >= 1400
/* C++11 features supported in VC8 = VC2005: */
# define Q_COMPILER_VARIADIC_MACROS
# ifndef __cplusplus_cli
/* 2005 supports the override and final contextual keywords, in
the same positions as the C++11 variants, but 'final' is
called 'sealed' instead:
http://msdn.microsoft.com/en-us/library/0w2w91tf%28v=vs.80%29.aspx
The behavior is slightly different in C++/CLI, which requires the
"virtual" keyword to be present too, so don't define for that.
So don't define Q_COMPILER_EXPLICIT_OVERRIDES (since it's not
the same as the C++11 version), but define the Q_DECL_* flags
accordingly: */
# define Q_DECL_OVERRIDE override
# define Q_DECL_FINAL sealed
# endif
# endif
# if _MSC_VER >= 1600
/* C++11 features supported in VC10 = VC2010: */

View File

@ -76,6 +76,10 @@
#include <CoreServices/CoreServices.h>
#endif
#if defined(Q_OS_ANDROID)
#include <private/qjni_p.h>
#endif
QT_BEGIN_NAMESPACE
#if !QT_DEPRECATED_SINCE(5, 0)
@ -2348,6 +2352,9 @@ typedef uint SeedStorageType;
typedef QThreadStorage<SeedStorageType *> SeedStorage;
Q_GLOBAL_STATIC(SeedStorage, randTLS) // Thread Local Storage for seed value
#elif defined(Q_OS_ANDROID)
typedef QThreadStorage<QJNIObjectPrivate> AndroidRandomStorage;
Q_GLOBAL_STATIC(AndroidRandomStorage, randomTLS)
#endif
/*!
@ -2381,6 +2388,16 @@ void qsrand(uint seed)
//global static object, fallback to srand(seed)
srand(seed);
}
#elif defined(Q_OS_ANDROID)
QJNIObjectPrivate random = QJNIObjectPrivate("java/util/Random",
"(J)V",
jlong(seed));
if (!random.isValid()) {
srand(seed);
return;
}
randomTLS->setLocalData(random);
#else
// On Windows srand() and rand() already use Thread-Local-Storage
// to store the seed between calls
@ -2422,6 +2439,25 @@ int qrand()
//global static object, fallback to rand()
return rand();
}
#elif defined(Q_OS_ANDROID)
AndroidRandomStorage *randomStorage = randomTLS();
if (!randomStorage)
return rand();
QJNIObjectPrivate random;
if (!randomStorage->hasLocalData()) {
random = QJNIObjectPrivate("java/util/Random",
"(J)V",
jlong(1));
if (!random.isValid())
return rand();
randomStorage->setLocalData(random);
} else {
random = randomStorage->localData();
}
return random.callMethod<jint>("nextInt", "(I)I", RAND_MAX);
#else
// On Windows srand() and rand() already use Thread-Local-Storage
// to store the seed between calls

View File

@ -1004,13 +1004,19 @@ template <bool B, typename T = void> struct QEnableIf;
template <typename T> struct QEnableIf<true, T> { typedef T Type; };
}
#ifdef __OBJC__
#define Q_FORWARD_DECLARE_OBJC_CLASS(classname) @class classname
#else
#define Q_FORWARD_DECLARE_OBJC_CLASS(classname) typedef struct objc_object classname
#ifndef Q_FORWARD_DECLARE_OBJC_CLASS
# ifdef __OBJC__
# define Q_FORWARD_DECLARE_OBJC_CLASS(classname) @class classname
# else
# define Q_FORWARD_DECLARE_OBJC_CLASS(classname) typedef struct objc_object classname
# endif
#endif
#ifndef Q_FORWARD_DECLARE_CF_TYPE
# define Q_FORWARD_DECLARE_CF_TYPE(type) typedef const struct __ ## type * type ## Ref
#endif
#ifndef Q_FORWARD_DECLARE_MUTABLE_CF_TYPE
# define Q_FORWARD_DECLARE_MUTABLE_CF_TYPE(type) typedef struct __ ## type * type ## Ref
#endif
#define Q_FORWARD_DECLARE_CF_TYPE(type) typedef const struct __ ## type * type ## Ref
#define Q_FORWARD_DECLARE_MUTABLE_CF_TYPE(type) typedef struct __ ## type * type ## Ref
QT_END_NAMESPACE
// Q_GLOBAL_STATIC

View File

@ -57,11 +57,16 @@ enum GuardValues {
};
}
#if defined(QT_NO_THREAD) || defined(Q_CC_GNU)
#if defined(QT_NO_THREAD) || (defined(Q_CC_GNU) && !defined(Q_OS_MAC))
// some compilers support thread-safe statics
// The IA-64 C++ ABI requires this, so we know that all GCC versions since 3.4
// support it. C++11 also requires this behavior.
// Clang and Intel CC masquerade as GCC when compiling on Linux and Mac OS X.
// Clang and Intel CC masquerade as GCC when compiling on Linux.
//
// Apple's libc++abi however uses a global lock for initializing local statics,
// which will block other threads also trying to initialize a local static
// until the constructor returns ...
// We better avoid these kind of problems by using our own locked implementation.
#define Q_GLOBAL_STATIC_INTERNAL(ARGS) \
Q_DECL_HIDDEN inline Type *innerFunction() \

View File

@ -446,7 +446,11 @@ QLibraryInfo::rawLocation(LibraryLocation loc, PathGroup group)
QCFType<CFURLRef> urlRef = CFBundleCopyBundleURL(bundleRef);
if (urlRef) {
QCFString path = CFURLCopyFileSystemPath(urlRef, kCFURLPOSIXPathStyle);
#ifdef Q_OS_MACX
return QDir::cleanPath(QString(path) + QLatin1String("/Contents/") + ret);
#else
return QDir::cleanPath(QString(path) + QLatin1Char('/') + ret); // iOS
#endif
}
}
#endif

View File

@ -549,6 +549,7 @@ static const char functionTokenC[] = "%{function}";
static const char pidTokenC[] = "%{pid}";
static const char appnameTokenC[] = "%{appname}";
static const char threadidTokenC[] = "%{threadid}";
static const char ifCategoryTokenC[] = "%{if-category}";
static const char ifDebugTokenC[] = "%{if-debug}";
static const char ifWarningTokenC[] = "%{if-warning}";
static const char ifCriticalTokenC[] = "%{if-critical}";
@ -556,7 +557,7 @@ static const char ifFatalTokenC[] = "%{if-fatal}";
static const char endifTokenC[] = "%{endif}";
static const char emptyTokenC[] = "";
static const char defaultPattern[] = "%{message}";
static const char defaultPattern[] = "%{if-category}%{category}: %{endif}%{message}";
struct QMessagePattern {
@ -675,6 +676,7 @@ void QMessagePattern::setPattern(const QString &pattern)
tokens[i] = LEVEL; \
inIf = true; \
}
IF_TOKEN(ifCategoryTokenC)
IF_TOKEN(ifDebugTokenC)
IF_TOKEN(ifWarningTokenC)
IF_TOKEN(ifCriticalTokenC)
@ -837,6 +839,9 @@ Q_CORE_EXPORT QString qMessageFormatString(QtMsgType type, const QMessageLogCont
message.append(QLatin1String("0x"));
message.append(QString::number(qlonglong(QThread::currentThread()->currentThread()), 16));
#endif
} else if (token == ifCategoryTokenC) {
if (!context.category || (strcmp(context.category, "default") == 0))
skip = true;
#define HANDLE_IF_TOKEN(LEVEL) \
} else if (token == if##LEVEL##TokenC) { \
skip = type != Qt##LEVEL##Msg;
@ -927,7 +932,7 @@ static void qt_message_print(QtMsgType msgType, const QMessageLogContext &contex
#ifndef QT_BOOTSTRAPPED
// qDebug, qWarning, ... macros do not check whether category is enabled
if (!context.category || (strcmp(context.category, "default") == 0)) {
if (QLoggingCategory *defaultCategory = &QLoggingCategory::defaultCategory()) {
if (QLoggingCategory *defaultCategory = QLoggingCategory::defaultCategory()) {
if (!defaultCategory->isEnabled(msgType))
return;
}
@ -1108,6 +1113,7 @@ void qErrnoWarning(int code, const char *msg, ...)
\table
\header \li Placeholder \li Description
\row \li \c %{appname} \li QCoreApplication::applicationName()
\row \li \c %{category} \li Logging category
\row \li \c %{file} \li Path to source file
\row \li \c %{function} \li Function
\row \li \c %{line} \li Line in source file

View File

@ -907,7 +907,7 @@ public:
Key_BrightnessAdjust = 0x010000c2,
Key_Finance = 0x010000c3,
Key_Community = 0x010000c4,
Key_AudioRewind = 0x010000c5,
Key_AudioRewind = 0x010000c5, // Media rewind
Key_BackForward = 0x010000c6,
Key_ApplicationLeft = 0x010000c7,
Key_ApplicationRight = 0x010000c8,
@ -919,7 +919,7 @@ public:
Key_Close = 0x010000ce,
Key_Copy = 0x010000cf,
Key_Cut = 0x010000d0,
Key_Display = 0x010000d1,
Key_Display = 0x010000d1, // Output switch key
Key_DOS = 0x010000d2,
Key_Documents = 0x010000d3,
Key_Excel = 0x010000d4,
@ -968,9 +968,9 @@ public:
Key_Bluetooth = 0x010000ff,
Key_WLAN = 0x01000100,
Key_UWB = 0x01000101,
Key_AudioForward = 0x01000102,
Key_AudioRepeat = 0x01000103,
Key_AudioRandomPlay = 0x01000104,
Key_AudioForward = 0x01000102, // Media fast-forward
Key_AudioRepeat = 0x01000103, // Toggle repeat mode
Key_AudioRandomPlay = 0x01000104, // Toggle shuffle mode
Key_Subtitle = 0x01000105,
Key_AudioCycleTrack = 0x01000106,
Key_Time = 0x01000107,
@ -1557,6 +1557,18 @@ public:
IgnoredGesturesPropagateToParent = 0x04
};
Q_DECLARE_FLAGS(GestureFlags, GestureFlag)
enum NativeGestureType
{
BeginNativeGesture,
EndNativeGesture,
PanNativeGesture,
ZoomNativeGesture,
SmartZoomNativeGesture,
RotateNativeGesture,
SwipeNativeGesture
};
#endif // QT_NO_GESTURES
enum NavigationMode

View File

@ -1735,6 +1735,8 @@
\value LeftEdge The left edge of the rectangle.
\value RightEdge The right edge of the rectangle.
\value BottomEdge The bottom edge of the rectangle.
\since 5.1
*/
/*!

View File

@ -675,6 +675,8 @@ bool QFileInfo::exists() const
}
/*!
\since 5.2
Returns \c true if the \a file exists; otherwise returns \c false.
\note If \a file is a symlink that points to a non-existing
@ -691,7 +693,8 @@ bool QFileInfo::exists(const QString &file)
QFileSystemEngine::resolveEntryAndCreateLegacyEngine(entry, data);
// Expensive fallback to non-QFileSystemEngine implementation
if (engine)
return QFileInfo(file).exists();
return QFileInfo(new QFileInfoPrivate(entry, data, engine)).exists();
QFileSystemEngine::fillMetaData(entry, data, QFileSystemMetaData::ExistsAttribute);
return data.exists();
}

View File

@ -120,6 +120,20 @@ public:
metaData = QFileSystemMetaData();
}
inline QFileInfoPrivate(const QFileSystemEntry &file, const QFileSystemMetaData &data, QAbstractFileEngine *engine)
: fileEntry(file),
metaData(data),
fileEngine(engine),
cachedFlags(0),
#ifndef QT_NO_FSFILEENGINE
isDefaultConstructed(false),
#else
isDefaultConstructed(!fileEngine),
#endif
cache_enabled(true), fileFlags(0), fileSize(0)
{
}
inline void clearFlags() const {
fileFlags = 0;
cachedFlags = 0;

View File

@ -1038,8 +1038,10 @@ bool QFileSystemEngine::fillMetaData(const QFileSystemEntry &entry, QFileSystemM
return data.hasFlags(what);
}
static inline bool mkDir(const QString &path)
static inline bool mkDir(const QString &path, DWORD *lastError = 0)
{
if (lastError)
*lastError = 0;
#if defined(Q_OS_WINCE)
// Unfortunately CreateDirectory returns true for paths longer than
// 256, but does not create a directory. It starts to fail, when
@ -1059,7 +1061,11 @@ static inline bool mkDir(const QString &path)
if (platformId == 1 && QFSFileEnginePrivate::longFileName(path).size() > 256)
return false;
#endif
return ::CreateDirectory((wchar_t*)QFSFileEnginePrivate::longFileName(path).utf16(), 0);
const QString longPath = QFSFileEnginePrivate::longFileName(path);
const bool result = ::CreateDirectory((wchar_t*)longPath.utf16(), 0);
if (lastError) // Capture lastError before any QString is freed since custom allocators might change it.
*lastError = GetLastError();
return result;
}
static inline bool rmDir(const QString &path)
@ -1131,9 +1137,9 @@ bool QFileSystemEngine::createDirectory(const QFileSystemEntry &entry, bool crea
slash = dirName.length();
}
if (slash) {
DWORD lastError;
QString chunk = dirName.left(slash);
if (!mkDir(chunk)) {
const DWORD lastError = GetLastError();
if (!mkDir(chunk, &lastError)) {
if (lastError == ERROR_ALREADY_EXISTS || lastError == ERROR_ACCESS_DENIED) {
bool existed = false;
if (isDirPath(chunk, &existed) && existed)

View File

@ -99,8 +99,10 @@ void debugBinaryString(const char *data, qint64 maxlen)
#define CHECK_WRITABLE(function, returnType) \
do { \
if ((d->openMode & WriteOnly) == 0) { \
if (d->openMode == NotOpen) \
if (d->openMode == NotOpen) { \
qWarning("QIODevice::"#function": device not open"); \
return returnType; \
} \
qWarning("QIODevice::"#function": ReadOnly device"); \
return returnType; \
} \
@ -109,8 +111,10 @@ void debugBinaryString(const char *data, qint64 maxlen)
#define CHECK_READABLE(function, returnType) \
do { \
if ((d->openMode & ReadOnly) == 0) { \
if (d->openMode == NotOpen) \
if (d->openMode == NotOpen) { \
qWarning("QIODevice::"#function": device not open"); \
return returnType; \
} \
qWarning("QIODevice::"#function": WriteOnly device"); \
return returnType; \
} \

View File

@ -140,6 +140,13 @@ static bool setNativeLocks(int fd)
QLockFile::LockError QLockFilePrivate::tryLock_sys()
{
// Assemble data, to write in a single call to write
// (otherwise we'd have to check every write call)
// Use operator% from the fast builder to avoid multiple memory allocations.
QByteArray fileData = QByteArray::number(QCoreApplication::applicationPid()) % '\n'
% qAppName().toUtf8() % '\n'
% localHostName().toUtf8() % '\n';
const QByteArray lockFileName = QFile::encodeName(fileName);
const int fd = qt_safe_open(lockFileName.constData(), O_WRONLY | O_CREAT | O_EXCL, 0644);
if (fd < 0) {
@ -160,16 +167,6 @@ QLockFile::LockError QLockFilePrivate::tryLock_sys()
// We hold the lock, continue.
fileHandle = fd;
// Assemble data, to write in a single call to write
// (otherwise we'd have to check every write call)
QByteArray fileData;
fileData += QByteArray::number(QCoreApplication::applicationPid());
fileData += '\n';
fileData += qAppName().toUtf8();
fileData += '\n';
fileData += localHostName().toUtf8();
fileData += '\n';
QLockFile::LockError error = QLockFile::NoError;
if (qt_write_loop(fd, fileData.constData(), fileData.size()) < fileData.size())
error = QLockFile::UnknownError; // partition full

View File

@ -71,30 +71,36 @@ Q_GLOBAL_STATIC_WITH_ARGS(QLoggingCategory, qtDefaultCategory,
\section1 Checking category configuration
QLoggingCategory provides a generic \l isEnabled() and message
type dependent \l isDebugEnabled(), \l isWarningEnabled(),
\l isCriticalEnabled() and \l isTraceEnabled()
methods for checking whether the current category is enabled.
QLoggingCategory provides \l isDebugEnabled(), \l isWarningEnabled(),
\l isCriticalEnabled(), \l isTraceEnabled(), as well as \l isEnabled()
to check whether messages for the given message type should be logged.
\note The qCDebug(), qCWarning(), qCCritical(), qCTrace() and
qCTraceGuard() macros prevent arguments from being evaluated if the
respective message types are not enabled for the category, so explicit
checking is not needed:
\snippet qloggingcategory/main.cpp 3
\snippet qloggingcategory/main.cpp 4
\section1 Default configuration
\section1 Default category configuration
In the default configuration \l isWarningEnabled() and \l isCriticalEnabled()
will return \c true. By default, \l isDebugEnabled() will return \c true only
will return \c true. \l isDebugEnabled() will return \c true only
for the \c "default" category.
\section1 Changing configuration
\section1 Changing the configuration of a category
The default configuration can be changed by calling \l setEnabled(). However,
this only affects the current category object, not e.g. another object for the
same category name. Use either \l setFilterRules() or \l installFilter() to
configure categories globally.
Use either \l setFilterRules() or \l installFilter() to
configure categories, for example
\snippet qloggingcategory/main.cpp 2
\section1 Printing the category
Use the \c %{category} place holder to print the category in the default
message handler:
\snippet qloggingcategory/main.cpp 3
*/
typedef QVector<QTracer *> Tracers;
@ -117,7 +123,10 @@ QLoggingCategory::QLoggingCategory(const char *category)
enabledDebug(false),
enabledWarning(true),
enabledCritical(true),
enabledTrace(false)
enabledTrace(false),
placeholder1(false),
placeholder2(false),
placeholder3(false)
{
bool isDefaultCategory
= (category == 0) || (strcmp(category, qtDefaultCategoryName) == 0);
@ -215,14 +224,12 @@ bool QLoggingCategory::isEnabled(QtMsgType msgtype) const
/*!
Changes the message type \a type for the category to \a enable.
Changes only affect the current QLoggingCategory object, and won't
change e.g. the settings of another objects for the same category name.
\note Changes only affect the current QLoggingCategory object, and won't
change the settings of other objects for the same category name.
Use either \l setFilterRules() or \l installFilter() to change the
configuration globally.
\note \c QtFatalMsg cannot be changed. It will always return \c true.
Example:
\snippet qtracer/ftracer.cpp 5
*/
void QLoggingCategory::setEnabled(QtMsgType type, bool enable)
{
@ -244,12 +251,19 @@ void QLoggingCategory::setEnabled(QtMsgType type, bool enable)
*/
/*!
Returns the category \c "default" that is used e.g. by qDebug(), qWarning(),
qCritical(), qFatal().
Returns a pointer to the global category \c "default" that
is used e.g. by qDebug(), qWarning(), qCritical(), qFatal().
\note The returned pointer may be null during destruction of
static objects.
\note Ownership of the category is not transferred, do not
\c delete the returned pointer.
*/
QLoggingCategory &QLoggingCategory::defaultCategory()
QLoggingCategory *QLoggingCategory::defaultCategory()
{
return *qtDefaultCategory();
return qtDefaultCategory();
}
/*!
@ -272,6 +286,12 @@ QLoggingCategory &QLoggingCategory::defaultCategory()
filter is free to change the respective category configuration with
\l setEnabled().
The filter might be called concurrently from different threads, and
therefore has to be reentrant.
Example:
\snippet qloggingcategory/main.cpp 21
An alternative way of configuring the default filter is via
\l setFilterRules().
*/
@ -281,7 +301,6 @@ QLoggingCategory::installFilter(QLoggingCategory::CategoryFilter filter)
return QLoggingRegistry::instance()->installFilter(filter);
}
/*!
Configures which categories and message types should be enabled through a
a set of \a rules.
@ -296,8 +315,13 @@ QLoggingCategory::installFilter(QLoggingCategory::CategoryFilter filter)
wildcard symbol at the start and/or the end. The optional \c <type> must
be either \c debug, \c warning, \c critical, or \c trace.
The rules might be ignored if a custom category filter is installed with
\l installFilter().
Example:
\snippet qloggingcategory/main.cpp 2
\note The rules might be ignored if a custom category filter is installed
with \l installFilter().
*/
void QLoggingCategory::setFilterRules(const QString &rules)
{
@ -380,7 +404,7 @@ void QLoggingCategory::setFilterRules(const QString &rules)
The macro expands to code that checks whether
\l QLoggingCategory::isTraceEnabled() evaluates to \c true.
If so, the stream arguments are processed and sent to the tracers
If so, the stream arguments are processed and sent to the \l QTracer objects
registered with the category.
\note Arguments are not processed if trace output for the category is not
@ -390,7 +414,7 @@ void QLoggingCategory::setFilterRules(const QString &rules)
\snippet qtracer/ftracer.cpp 6
\sa qCTraceGuard()
\sa qCTraceGuard() QTraceGuard
*/
/*!
@ -402,11 +426,12 @@ void QLoggingCategory::setFilterRules(const QString &rules)
storage. The guard constructor checks whether
\l QLoggingCategory::isTraceEnabled() evaluates to \c true.
If so, the stream arguments are processed and the \c{start()}
functions of the tracers registered with the \a category are called.
functions of the \l QTracer objects registered with the \a category are
called.
The guard destructor also checks whether the category is enabled for
tracing and if so, the \c{end()}
functions of the tracers registered with the \a category are called.
functions of the \l QTracer objects registered with the \a category are called.
\note Arguments are always processed, even if trace output for the
category is disabled. They will, however, in that case not be passed
@ -416,7 +441,7 @@ void QLoggingCategory::setFilterRules(const QString &rules)
\snippet qtracer/ftracer.cpp 4
\sa qCTrace()
\sa qCTrace() QTracer
*/
/*!

View File

@ -72,7 +72,7 @@ public:
// allows usage of both factory method and variable in qCX macros
QLoggingCategory &operator()() { return *this; }
static QLoggingCategory &defaultCategory();
static QLoggingCategory *defaultCategory();
typedef void (*CategoryFilter)(QLoggingCategory*);
static CategoryFilter installFilter(CategoryFilter);
@ -92,6 +92,10 @@ private:
bool enabledWarning;
bool enabledCritical;
bool enabledTrace;
// reserve space for future use
bool placeholder1;
bool placeholder2;
bool placeholder3;
};
class Q_CORE_EXPORT QTracer

View File

@ -1840,12 +1840,21 @@ void QUrl::setUrl(const QString &url, ParsingMode parsingMode)
input. It must also start with an ASCII letter.
The scheme describes the type (or protocol) of the URL. It's
represented by one or more ASCII characters at the start the URL,
and is followed by a ':'. The following example shows a URL where
the scheme is "ftp":
represented by one or more ASCII characters at the start the URL.
A scheme is strictly \l {http://www.ietf.org/rfc/rfc3986.txt} {RFC 3986}-compliant:
\tt {scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )}
The following example shows a URL where the scheme is "ftp":
\image qurl-authority2.png
To set the scheme, the following call is used:
\code
QUrl url;
url.setScheme("ftp");
\endcode
The scheme can also be empty, in which case the URL is interpreted
as relative.
@ -3327,7 +3336,7 @@ QString QUrl::fromPercentEncoding(const QByteArray &input)
them to \a include.
Unreserved is defined as:
ALPHA / DIGIT / "-" / "." / "_" / "~"
\tt {ALPHA / DIGIT / "-" / "." / "_" / "~"}
\snippet code/src_corelib_io_qurl.cpp 6
*/

View File

@ -304,7 +304,7 @@ static bool encodedUtf8ToUtf16(QString &result, ushort *&output, const ushort *b
// we've decoded something; safety-check it
if (uc < min_uc)
return false;
if (QChar::isSurrogate(uc) || QChar::isNonCharacter(uc) || uc > QChar::LastValidCodePoint)
if (QChar::isSurrogate(uc) || uc > QChar::LastValidCodePoint)
return false;
if (!QChar::requiresSurrogates(uc)) {
@ -410,10 +410,9 @@ static int recode(QString &result, const ushort *begin, const ushort *end, QUrl:
const ushort *input = begin;
ushort *output = 0;
EncodingAction action = EncodeCharacter;
for ( ; input != end; ++input) {
ushort c;
EncodingAction action;
// try a run where no change is necessary
for ( ; input != end; ++input) {
c = *input;

View File

@ -1089,7 +1089,7 @@ void QJsonArray::compact()
}
#ifndef QT_NO_DEBUG_STREAM
#if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY)
QDebug operator<<(QDebug dbg, const QJsonArray &a)
{
if (!a.a) {

View File

@ -211,7 +211,7 @@ private:
QJsonPrivate::Array *a;
};
#ifndef QT_NO_DEBUG_STREAM
#if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY)
Q_CORE_EXPORT QDebug operator<<(QDebug, const QJsonArray &);
#endif

View File

@ -303,10 +303,12 @@ QVariant QJsonDocument::toVariant() const
\sa fromJson()
*/
#ifndef QT_JSON_READONLY
QByteArray QJsonDocument::toJson() const
{
return toJson(Indented);
}
#endif
/*!
\enum QJsonDocument::JsonFormat
@ -338,6 +340,7 @@ QByteArray QJsonDocument::toJson() const
\sa fromJson(), JsonFormat
*/
#ifndef QT_JSON_READONLY
QByteArray QJsonDocument::toJson(JsonFormat format) const
{
if (!d)
@ -352,6 +355,7 @@ QByteArray QJsonDocument::toJson(JsonFormat format) const
return json;
}
#endif
/*!
Parses a UTF-8 encoded JSON document and creates a QJsonDocument
@ -562,7 +566,7 @@ bool QJsonDocument::isNull() const
return (d == 0);
}
#ifndef QT_NO_DEBUG_STREAM
#if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY)
QDebug operator<<(QDebug dbg, const QJsonDocument &o)
{
if (!o.d) {

View File

@ -117,7 +117,7 @@ public:
#ifdef Q_QDOC
QByteArray toJson(JsonFormat format = Indented) const;
#else
#elif !defined(QT_JSON_READONLY)
QByteArray toJson() const; //### Merge in Qt6
QByteArray toJson(JsonFormat format) const;
#endif
@ -148,7 +148,7 @@ private:
QJsonPrivate::Data *d;
};
#ifndef QT_NO_DEBUG_STREAM
#if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY)
Q_CORE_EXPORT QDebug operator<<(QDebug, const QJsonDocument &);
#endif

View File

@ -1036,7 +1036,7 @@ void QJsonObject::setValueAt(int i, const QJsonValue &val)
insert(e->key(), val);
}
#ifndef QT_NO_DEBUG_STREAM
#if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY)
QDebug operator<<(QDebug dbg, const QJsonObject &o)
{
if (!o.o) {

View File

@ -206,7 +206,7 @@ private:
QJsonPrivate::Object *o;
};
#ifndef QT_NO_DEBUG_STREAM
#if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY)
Q_CORE_EXPORT QDebug operator<<(QDebug, const QJsonObject &);
#endif

View File

@ -853,7 +853,7 @@ static inline bool scanUtf8Char(const char *&json, const char *end, uint *result
uc = (uc << 6) | (ch & 0x3f);
}
if (uc < min_uc || QChar::isNonCharacter(uc) ||
if (uc < min_uc ||
QChar::isSurrogate(uc) || uc > QChar::LastValidCodePoint) {
return false;
}

Some files were not shown because too many files have changed in this diff Show More